[Supervisor-checkins] r826 - in supervisor/branches/chrism-30-merge: . src/supervisor src/supervisor/tests
Chris McDonough
chrism at agendaless.com
Sun Nov 23 13:07:19 EST 2008
Author: Chris McDonough <chrism at agendaless.com>
Date: Sun Nov 23 13:07:19 2008
New Revision: 826
Log:
- Made sure we got the gsoc branch merged correctly.
- Add ``reread``, ``update``, and ``avail`` commands based on Anders
Quist's ``online_config_reload.diff`` patch. This patch extends
the "add" and "drop" commands with automagical behavior::
In supervisorctl:
supervisor> status
bar RUNNING pid 14864, uptime 18:03:42
baz RUNNING pid 23260, uptime 0:10:16
foo RUNNING pid 14866, uptime 18:03:42
gazonk RUNNING pid 23261, uptime 0:10:16
supervisor> avail
bar in use auto 999:999
baz in use auto 999:999
foo in use auto 999:999
gazonk in use auto 999:999
quux avail auto 999:999
Now we add this to our conf:
[group:zegroup]
programs=baz,gazonk
Then we reread conf:
supervisor> reread
baz: disappeared
gazonk: disappeared
quux: available
zegroup: available
supervisor> avail
bar in use auto 999:999
foo in use auto 999:999
quux avail auto 999:999
zegroup:baz avail auto 999:999
zegroup:gazonk avail auto 999:999
supervisor> status
bar RUNNING pid 14864, uptime 18:04:18
baz RUNNING pid 23260, uptime 0:10:52
foo RUNNING pid 14866, uptime 18:04:18
gazonk RUNNING pid 23261, uptime 0:10:52
The magic make-it-so command:
supervisor> update
baz: stopped
baz: removed process group
gazonk: stopped
gazonk: removed process group
zegroup: added process group
quux: added process group
supervisor> status
bar RUNNING pid 14864, uptime 18:04:43
foo RUNNING pid 14866, uptime 18:04:43
quux RUNNING pid 23561, uptime 0:00:02
zegroup:baz RUNNING pid 23559, uptime 0:00:02
zegroup:gazonk RUNNING pid 23560, uptime 0:00:02
supervisor> avail
bar in use auto 999:999
foo in use auto 999:999
quux in use auto 999:999
zegroup:baz in use auto 999:999
zegroup:gazonk in use auto 999:999
Modified:
supervisor/branches/chrism-30-merge/CHANGES.txt
supervisor/branches/chrism-30-merge/src/supervisor/options.py
supervisor/branches/chrism-30-merge/src/supervisor/rpcinterface.py
supervisor/branches/chrism-30-merge/src/supervisor/supervisorctl.py
supervisor/branches/chrism-30-merge/src/supervisor/supervisord.py
supervisor/branches/chrism-30-merge/src/supervisor/tests/base.py
supervisor/branches/chrism-30-merge/src/supervisor/tests/test_options.py
supervisor/branches/chrism-30-merge/src/supervisor/tests/test_rpcinterfaces.py
supervisor/branches/chrism-30-merge/src/supervisor/tests/test_supervisorctl.py
supervisor/branches/chrism-30-merge/src/supervisor/tests/test_supervisord.py
Modified: supervisor/branches/chrism-30-merge/CHANGES.txt
==============================================================================
--- supervisor/branches/chrism-30-merge/CHANGES.txt (original)
+++ supervisor/branches/chrism-30-merge/CHANGES.txt Sun Nov 23 13:07:19 2008
@@ -1,5 +1,69 @@
Next Release
+ - Add ``reread``, ``update``, and ``avail`` commands based on Anders
+ Quist's ``online_config_reload.diff`` patch. This patch extends
+ the "add" and "drop" commands with automagical behavior::
+
+ In supervisorctl:
+
+ supervisor> status
+ bar RUNNING pid 14864, uptime 18:03:42
+ baz RUNNING pid 23260, uptime 0:10:16
+ foo RUNNING pid 14866, uptime 18:03:42
+ gazonk RUNNING pid 23261, uptime 0:10:16
+ supervisor> avail
+ bar in use auto 999:999
+ baz in use auto 999:999
+ foo in use auto 999:999
+ gazonk in use auto 999:999
+ quux avail auto 999:999
+
+ Now we add this to our conf:
+
+ [group:zegroup]
+ programs=baz,gazonk
+
+ Then we reread conf:
+
+ supervisor> reread
+ baz: disappeared
+ gazonk: disappeared
+ quux: available
+ zegroup: available
+ supervisor> avail
+ bar in use auto 999:999
+ foo in use auto 999:999
+ quux avail auto 999:999
+ zegroup:baz avail auto 999:999
+ zegroup:gazonk avail auto 999:999
+ supervisor> status
+ bar RUNNING pid 14864, uptime 18:04:18
+ baz RUNNING pid 23260, uptime 0:10:52
+ foo RUNNING pid 14866, uptime 18:04:18
+ gazonk RUNNING pid 23261, uptime 0:10:52
+
+ The magic make-it-so command:
+
+ supervisor> update
+ baz: stopped
+ baz: removed process group
+ gazonk: stopped
+ gazonk: removed process group
+ zegroup: added process group
+ quux: added process group
+ supervisor> status
+ bar RUNNING pid 14864, uptime 18:04:43
+ foo RUNNING pid 14866, uptime 18:04:43
+ quux RUNNING pid 23561, uptime 0:00:02
+ zegroup:baz RUNNING pid 23559, uptime 0:00:02
+ zegroup:gazonk RUNNING pid 23560, uptime 0:00:02
+ supervisor> avail
+ bar in use auto 999:999
+ foo in use auto 999:999
+ quux in use auto 999:999
+ zegroup:baz in use auto 999:999
+ zegroup:gazonk in use auto 999:999
+
- Fix bug with symptom "KeyError: 'process_name'" when using a logfile name
including documented 'process_name' Python string expansions.
Modified: supervisor/branches/chrism-30-merge/src/supervisor/options.py
==============================================================================
--- supervisor/branches/chrism-30-merge/src/supervisor/options.py (original)
+++ supervisor/branches/chrism-30-merge/src/supervisor/options.py Sun Nov 23 13:07:19 2008
@@ -471,27 +471,11 @@
self.identifier = section.identifier
- def diff_process_groups(self, new):
- cur = self.process_group_configs
-
- curdict = dict(zip([cfg.name for cfg in cur], cur))
- newdict = dict(zip([cfg.name for cfg in new], new))
-
- added = [cand for cand in new if cand.name not in curdict]
- removed = [cand for cand in cur if cand.name not in newdict]
-
- changed = [cand for cand in new
- if cand != curdict.get(cand.name, cand)]
-
- return added, changed, removed
-
def process_config_file(self):
Options.process_config_file(self)
new = self.configroot.supervisord.process_group_configs
- changes = self.diff_process_groups(new)
self.process_group_configs = new
- return changes
def read_config(self, fp):
section = self.configroot.supervisord
Modified: supervisor/branches/chrism-30-merge/src/supervisor/rpcinterface.py
==============================================================================
--- supervisor/branches/chrism-30-merge/src/supervisor/rpcinterface.py (original)
+++ supervisor/branches/chrism-30-merge/src/supervisor/rpcinterface.py Sun Nov 23 13:07:19 2008
@@ -162,6 +162,21 @@
self.supervisord.options.mood = SupervisorStates.RESTARTING
return True
+ def reloadConfig(self):
+ """
+ Reload configuration
+
+ @return boolean result always return True unless error
+ """
+ self._update('reloadConfig')
+ self.supervisord.options.process_config_file()
+ added, changed, removed = self.supervisord.diff_to_active()
+
+ added = [group.name for group in added]
+ changed = [group.name for group in changed]
+ removed = [group.name for group in removed]
+ return [[added, changed, removed]] # cannot return len > 1, apparently
+
def addProcessGroup(self, name):
""" Update the config for a running process from config file.
@@ -433,6 +448,29 @@
killall.rpcinterface = self
return killall # deferred
+ def getAllConfigInfo(self):
+ """ Get info about all availible process configurations. Each record
+ represents a single process (i.e. groups get flattened).
+
+ @return array result An array of process config info records
+ """
+ self._update('getAllConfigInfo')
+
+ configinfo = []
+ for gconfig in self.supervisord.options.process_group_configs:
+ inuse = gconfig.name in self.supervisord.process_groups
+ for pconfig in gconfig.process_configs:
+ configinfo.append(
+ { 'name': pconfig.name,
+ 'group': gconfig.name,
+ 'inuse': inuse,
+ 'autostart': pconfig.autostart,
+ 'group_prio': gconfig.priority,
+ 'process_prio': pconfig.priority })
+
+ configinfo.sort()
+ return configinfo
+
def _interpretProcessInfo(self, info):
state = info['state']
Modified: supervisor/branches/chrism-30-merge/src/supervisor/supervisorctl.py
==============================================================================
--- supervisor/branches/chrism-30-merge/src/supervisor/supervisorctl.py (original)
+++ supervisor/branches/chrism-30-merge/src/supervisor/supervisorctl.py Sun Nov 23 13:07:19 2008
@@ -778,6 +778,66 @@
def help_reload(self):
self.ctl.output("reload \t\tRestart the remote supervisord.")
+ def _formatChanges(self, (added, changed, dropped)):
+ changedict = {}
+ for n, t in [(added, 'available'),
+ (changed, 'changed'),
+ (dropped, 'disappeared')]:
+ changedict.update(dict(zip(n, [t] * len(n))))
+
+ if changedict:
+ for name in sorted(changedict):
+ self.ctl.output("%s: %s" % (name, changedict[name]))
+ else:
+ self.ctl.output("No config updates to proccesses")
+
+ def _formatConfigInfo(self, configinfo):
+ if configinfo['group'] == configinfo['name']:
+ name = configinfo['group']
+ else:
+ name = "%s:%s" % (configinfo['group'], configinfo['name'])
+ formatted = { 'name': name }
+ if configinfo['inuse']:
+ formatted['inuse'] = 'in use'
+ else:
+ formatted['inuse'] = 'avail'
+ if configinfo['autostart']:
+ formatted['autostart'] = 'auto'
+ else:
+ formatted['autostart'] = 'manual'
+ formatted['priority'] = "%s:%s" % (configinfo['group_prio'],
+ configinfo['process_prio'])
+
+ template = '%(name)-32s %(inuse)-9s %(autostart)-9s %(priority)s'
+ return template % formatted
+
+ def do_avail(self, arg):
+ supervisor = self.ctl.get_supervisor()
+ try:
+ configinfo = supervisor.getAllConfigInfo()
+ except xmlrpclib.Fault, e:
+ if e.faultCode == xmlrpc.Faults.SHUTDOWN_STATE:
+ self.ctl.output('ERROR: supervisor shutting down')
+ else:
+ for pinfo in configinfo:
+ self.ctl.output(self._formatConfigInfo(pinfo))
+
+ def help_avail(self):
+ self.ctl.output("avail\t\t\tDisplay all configured processes")
+
+ def do_reread(self, arg):
+ supervisor = self.ctl.get_supervisor()
+ try:
+ result = supervisor.reloadConfig()
+ except xmlrpclib.Fault, e:
+ if e.faultCode == xmlrpc.Faults.SHUTDOWN_STATE:
+ self.ctl.output('ERROR: already shutting down')
+ else:
+ self._formatChanges(result[0])
+
+ def help_reread(self):
+ self.ctl.output("reread \t\t\tReload the daemon's configuration files")
+
def do_add(self, arg):
names = arg.strip().split()
@@ -819,12 +879,55 @@
else:
raise
else:
- self.ctl.output("%s: removed" % name)
+ self.ctl.output("%s: removed process group" % name)
def help_remove(self):
self.ctl.output("remove <name> [...]\tRemoves process/group from "
"active config")
+ def do_update(self, arg):
+ def log(name, message):
+ self.ctl.output("%s: %s" % (name, message))
+
+ supervisor = self.ctl.get_supervisor()
+ try:
+ result = supervisor.reloadConfig()
+ except xmlrpclib.Fault, e:
+ if e.faultCode == xmlrpc.Faults.SHUTDOWN_STATE:
+ self.ctl.output('ERROR: already shutting down')
+ return
+ else:
+ raise e
+
+ added, changed, removed = result[0]
+
+ for gname in removed:
+ results = supervisor.stopProcessGroup(gname)
+ log(gname, "stopped")
+
+ fails = [res for res in results
+ if res['status'] == xmlrpc.Faults.FAILED]
+ if fails:
+ log(gname, "has problems; not removing")
+ continue
+ supervisor.removeProcessGroup(gname)
+ log(gname, "removed process group")
+
+ for gname in changed:
+ results = supervisor.stopProcessGroup(gname)
+ log(gname, "stopped")
+
+ supervisor.removeProcessGroup(gname)
+ supervisor.addProcessGroup(gname)
+ log(gname, "updated process group")
+
+ for gname in added:
+ supervisor.addProcessGroup(gname)
+ log(gname, "added process group")
+
+ def help_update(self):
+ self.ctl.output("update\t\tReload config and add/remove as necessary")
+
def _clearresult(self, result):
name = result['name']
code = result['status']
Modified: supervisor/branches/chrism-30-merge/src/supervisor/supervisord.py
==============================================================================
--- supervisor/branches/chrism-30-merge/src/supervisor/supervisord.py (original)
+++ supervisor/branches/chrism-30-merge/src/supervisor/supervisord.py Sun Nov 23 13:07:19 2008
@@ -108,6 +108,22 @@
finally:
self.options.cleanup()
+ def diff_to_active(self, new=None):
+ if not new:
+ new = self.options.process_group_configs
+ cur = [group.config for group in self.process_groups.values()]
+
+ curdict = dict(zip([cfg.name for cfg in cur], cur))
+ newdict = dict(zip([cfg.name for cfg in new], new))
+
+ added = [cand for cand in new if cand.name not in curdict]
+ removed = [cand for cand in cur if cand.name not in newdict]
+
+ changed = [cand for cand in new
+ if cand != curdict.get(cand.name, cand)]
+
+ return added, changed, removed
+
def add_process_group(self, config):
name = config.name
if name not in self.process_groups:
Modified: supervisor/branches/chrism-30-merge/src/supervisor/tests/base.py
==============================================================================
--- supervisor/branches/chrism-30-merge/src/supervisor/tests/base.py (original)
+++ supervisor/branches/chrism-30-merge/src/supervisor/tests/base.py Sun Nov 23 13:07:19 2008
@@ -79,6 +79,9 @@
self.realizeargs = args
self.realizekw = kw
+ def process_config_file(self):
+ pass
+
def cleanup_fds(self):
self.fds_cleaned_up = True
@@ -767,7 +770,7 @@
raise Fault(xmlrpc.Faults.SHUTDOWN_STATE, '')
def reloadConfig(self):
- return [[['added'], ['changed'], ['dropped']]]
+ return [[['added'], ['changed'], ['removed']]]
def addProcessGroup(self, name):
from xmlrpclib import Fault
Modified: supervisor/branches/chrism-30-merge/src/supervisor/tests/test_options.py
==============================================================================
--- supervisor/branches/chrism-30-merge/src/supervisor/tests/test_options.py (original)
+++ supervisor/branches/chrism-30-merge/src/supervisor/tests/test_options.py Sun Nov 23 13:07:19 2008
@@ -405,94 +405,6 @@
self.assertTrue(section.process_group_configs is
instance.process_group_configs)
- def test_diff_add_remove(self):
- options = self._makeOne()
-
- pconfig = DummyPConfig(options, 'process1', 'process1')
- group1 = DummyPGroupConfig(options, 'group1', pconfigs=[pconfig])
-
- pconfig = DummyPConfig(options, 'process2', 'process2')
- group2 = DummyPGroupConfig(options, 'group2', pconfigs=[pconfig])
-
- new = [group1, group2]
-
- added, changed, removed = options.diff_process_groups([])
- self.assertEqual(added, options.process_group_configs)
- self.assertEqual(removed, [])
-
- options.process_group_configs = list(new)
- added, changed, removed = options.diff_process_groups(new)
- self.assertEqual(added, [])
- self.assertEqual(changed, [])
- self.assertEqual(removed, [])
-
- pconfig = DummyPConfig(options, 'process3', 'process3')
- new_group1 = DummyPGroupConfig(options, pconfigs=[pconfig])
-
- pconfig = DummyPConfig(options, 'process4', 'process4')
- new_group2 = DummyPGroupConfig(options, pconfigs=[pconfig])
-
- new = [group2, new_group1, new_group2]
-
- added, changed, removed = options.diff_process_groups(new)
- self.assertEqual(added, [new_group1, new_group2])
- self.assertEqual(changed, [])
- self.assertEqual(removed, [group1])
-
- def test_diff_changed(self):
- from supervisor.options import ProcessConfig, ProcessGroupConfig
-
- options = self._makeOne()
-
- def make_pconfig(name, command, **params):
- result = {
- 'name': name, 'command': command,
- 'directory': None, 'umask': None, 'priority': 999, 'autostart': True,
- 'autorestart': True, 'startsecs': 10, 'startretries': 999,
- 'uid': None, 'stdout_logfile': None, 'stdout_capture_maxbytes': 0,
- 'stdout_logfile_backups': 0, 'stdout_logfile_maxbytes': 0,
- 'stderr_logfile': None, 'stderr_capture_maxbytes': 0,
- 'stderr_logfile_backups': 0, 'stderr_logfile_maxbytes': 0,
- 'redirect_stderr': False,
- 'stopsignal': None, 'stopwaitsecs': 10,
- 'exitcodes': (0,2), 'environment': None, 'serverurl': None }
- result.update(params)
- return ProcessConfig(options, **result)
-
- def make_gconfig(name, pconfigs):
- return ProcessGroupConfig(options, name, 25, pconfigs)
-
- pconfig = make_pconfig('process1', 'process1', uid='new')
- group1 = make_gconfig('group1', [pconfig])
-
- pconfig = make_pconfig('process2', 'process2')
- group2 = make_gconfig('group2', [pconfig])
- new = [group1, group2]
-
- pconfig = make_pconfig('process1', 'process1', uid='old')
- group3 = make_gconfig('group1', [pconfig])
-
- pconfig = make_pconfig('process2', 'process2')
- group4 = make_gconfig('group2', [pconfig])
- options.process_group_configs = [group4, group3]
-
- added, changed, removed = options.diff_process_groups(new)
-
- self.assertEqual([added, removed], [[], []])
- self.assertEqual(changed, [group1])
-
- options = self._makeOne()
- pconfig1 = make_pconfig('process1', 'process1')
- pconfig2 = make_pconfig('process2', 'process2')
- group1 = make_gconfig('group1', [pconfig1, pconfig2])
- new = [group1]
-
- options.process_group_configs = [make_gconfig('group1', [pconfig1])]
-
- added, changed, removed = options.diff_process_groups(new)
- self.assertEqual([added, removed], [[], []])
- self.assertEqual(changed, [group1])
-
def test_readFile_failed(self):
from supervisor.options import readFile
try:
Modified: supervisor/branches/chrism-30-merge/src/supervisor/tests/test_rpcinterfaces.py
==============================================================================
--- supervisor/branches/chrism-30-merge/src/supervisor/tests/test_rpcinterfaces.py (original)
+++ supervisor/branches/chrism-30-merge/src/supervisor/tests/test_rpcinterfaces.py Sun Nov 23 13:07:19 2008
@@ -218,6 +218,20 @@
self.assertEqual(value, True)
self.assertEqual(supervisord.options.mood, 0)
+ def test_reloadConfig(self):
+ options = DummyOptions()
+ supervisord = DummySupervisor(options)
+ interface = self._makeOne(supervisord)
+
+ changes = [ [DummyPGroupConfig(options, 'added')],
+ [DummyPGroupConfig(options, 'changed')],
+ [DummyPGroupConfig(options, 'dropped')] ]
+
+ supervisord.diff_to_active = lambda : changes
+
+ value = interface.reloadConfig()
+ self.assertEqual(value, [[['added'], ['changed'], ['dropped']]])
+
def test_addProcessGroup(self):
from supervisor.supervisord import Supervisor
from supervisor import xmlrpc
@@ -821,6 +835,31 @@
self.assertEqual(result[1]['status'], Faults.SUCCESS)
self.assertEqual(result[1]['description'], 'OK')
+ def test_getAllConfigInfo(self):
+ options = DummyOptions()
+ supervisord = DummySupervisor(options, 'foo')
+
+ pconfig1 = DummyPConfig(options, 'process1', __file__)
+ pconfig2 = DummyPConfig(options, 'process2', __file__)
+ gconfig = DummyPGroupConfig(options, 'group1', pconfigs=[pconfig1, pconfig2])
+ supervisord.process_groups = {'group1': DummyProcessGroup(gconfig)}
+ supervisord.options.process_group_configs = [gconfig]
+
+ interface = self._makeOne(supervisord)
+ configs = interface.getAllConfigInfo()
+ self.assertEqual(configs, [{ 'group': 'group1',
+ 'name': 'process1',
+ 'inuse': True,
+ 'autostart': True,
+ 'process_prio': 999,
+ 'group_prio': 999 },
+ { 'group': 'group1',
+ 'name': 'process2',
+ 'inuse': True,
+ 'autostart': True,
+ 'process_prio': 999,
+ 'group_prio': 999 }])
+
def test__interpretProcessInfo(self):
supervisord = DummySupervisor()
interface = self._makeOne(supervisord)
Modified: supervisor/branches/chrism-30-merge/src/supervisor/tests/test_supervisorctl.py
==============================================================================
--- supervisor/branches/chrism-30-merge/src/supervisor/tests/test_supervisorctl.py (original)
+++ supervisor/branches/chrism-30-merge/src/supervisor/tests/test_supervisorctl.py Sun Nov 23 13:07:19 2008
@@ -472,6 +472,54 @@
self.assertEqual(result, None)
self.assertEqual(options._server.supervisor._shutdown, True)
+ def test__formatChanges(self):
+ plugin = self._makeOne()
+ # Don't explode, plz
+ plugin._formatChanges([['added'], ['changed'], ['removed']])
+ plugin._formatChanges([[], [], []])
+
+ def test_reread(self):
+ plugin = self._makeOne()
+ calls = []
+ plugin._formatChanges = lambda x: calls.append(x)
+ result = plugin.do_reread(None)
+ self.assertEqual(result, None)
+ self.assertEqual(calls[0], [['added'], ['changed'], ['removed']])
+
+ def test__formatConfigInfo(self):
+ info = { 'group': 'group1',
+ 'name': 'process1',
+ 'inuse': True,
+ 'autostart': True,
+ 'process_prio': 999,
+ 'group_prio': 999 }
+ plugin = self._makeOne()
+ result = plugin._formatConfigInfo(info)
+ self.assertTrue('in use' in result)
+ info = { 'group': 'group1',
+ 'name': 'process1',
+ 'inuse': False,
+ 'autostart': False,
+ 'process_prio': 999,
+ 'group_prio': 999 }
+ result = plugin._formatConfigInfo(info)
+ self.assertTrue('avail' in result)
+
+ def test_avail(self):
+ calls = []
+ plugin = self._makeOne()
+
+ class FakeSupervisor(object):
+ def getAllConfigInfo(self):
+ return [{ 'group': 'group1', 'name': 'process1',
+ 'inuse': False, 'autostart': False,
+ 'process_prio': 999, 'group_prio': 999 }]
+
+ plugin.ctl.get_supervisor = lambda : FakeSupervisor()
+ plugin.ctl.output = calls.append
+ result = plugin.do_avail('')
+ self.assertEqual(result, None)
+
def test_add(self):
plugin = self._makeOne()
result = plugin.do_add('foo')
@@ -521,6 +569,126 @@
self.assertEqual(plugin.ctl.stdout.getvalue(),
'ERROR: process/group still running: STILL_RUNNING\n')
+ def test_update_not_on_shutdown(self):
+ plugin = self._makeOne()
+ supervisor = plugin.ctl.options._server.supervisor
+ def reloadConfig():
+ from supervisor import xmlrpc
+ import xmlrpclib
+ raise xmlrpclib.Fault(xmlrpc.Faults.SHUTDOWN_STATE, 'blah')
+ supervisor.reloadConfig = reloadConfig
+ supervisor.processes = ['removed']
+ plugin.do_update('')
+ self.assertEqual(supervisor.processes, ['removed'])
+
+ def test_update_added_procs(self):
+ plugin = self._makeOne()
+ supervisor = plugin.ctl.options._server.supervisor
+
+ calls = []
+ def reloadConfig():
+ return [[['new_proc'], [], []]]
+ supervisor.reloadConfig = reloadConfig
+
+ plugin.do_update('')
+ self.assertEqual(supervisor.processes, ['new_proc'])
+
+ def test_update_changed_procs(self):
+ from supervisor import xmlrpc
+ import xmlrpclib
+
+ plugin = self._makeOne()
+ supervisor = plugin.ctl.options._server.supervisor
+
+ calls = []
+ def reloadConfig():
+ return [[[], ['changed_group'], []]]
+ supervisor.reloadConfig = reloadConfig
+ supervisor.startProcess = lambda x: calls.append(('start', x))
+
+ supervisor.addProcessGroup('changed_group') # fake existence
+ results = [{'name': 'changed_process',
+ 'group': 'changed_group',
+ 'status': xmlrpc.Faults.SUCCESS,
+ 'description': 'blah'}]
+ def stopProcessGroup(name):
+ calls.append(('stop', name))
+ return results
+ supervisor.stopProcessGroup = stopProcessGroup
+
+ plugin.do_update('')
+ self.assertEqual(calls, [('stop', 'changed_group')])
+
+ supervisor.addProcessGroup('changed_group') # fake existence
+ calls[:] = []
+ results[:] = [{'name': 'changed_process1',
+ 'group': 'changed_group',
+ 'status': xmlrpc.Faults.NOT_RUNNING,
+ 'description': 'blah'},
+ {'name': 'changed_process2',
+ 'group': 'changed_group',
+ 'status': xmlrpc.Faults.FAILED,
+ 'description': 'blah'}]
+
+ plugin.do_update('')
+ self.assertEqual(calls, [('stop', 'changed_group')])
+
+ supervisor.addProcessGroup('changed_group') # fake existence
+ calls[:] = []
+ results[:] = [{'name': 'changed_process1',
+ 'group': 'changed_group',
+ 'status': xmlrpc.Faults.FAILED,
+ 'description': 'blah'},
+ {'name': 'changed_process2',
+ 'group': 'changed_group',
+ 'status': xmlrpc.Faults.SUCCESS,
+ 'description': 'blah'}]
+
+ plugin.do_update('')
+ self.assertEqual(calls, [('stop', 'changed_group')])
+
+ def test_update_removed_procs(self):
+ from supervisor import xmlrpc
+ import xmlrpclib
+
+ plugin = self._makeOne()
+ supervisor = plugin.ctl.options._server.supervisor
+
+ def reloadConfig():
+ return [[[], [], ['removed_group']]]
+ supervisor.reloadConfig = reloadConfig
+
+ results = [{'name': 'removed_process',
+ 'group': 'removed_group',
+ 'status': xmlrpc.Faults.SUCCESS,
+ 'description': 'blah'}]
+ supervisor.processes = ['removed_group']
+
+ def stopProcessGroup(name):
+ return results
+ supervisor.stopProcessGroup = stopProcessGroup
+
+ plugin.do_update('')
+ self.assertEqual(supervisor.processes, [])
+
+ results[:] = [{'name': 'removed_process',
+ 'group': 'removed_group',
+ 'status': xmlrpc.Faults.NOT_RUNNING,
+ 'description': 'blah'}]
+ supervisor.processes = ['removed_group']
+
+ plugin.do_update('')
+ self.assertEqual(supervisor.processes, [])
+
+ results[:] = [{'name': 'removed_process',
+ 'group': 'removed_group',
+ 'status': xmlrpc.Faults.FAILED,
+ 'description': 'blah'}]
+ supervisor.processes = ['removed_group']
+
+ plugin.do_update('')
+ self.assertEqual(supervisor.processes, ['removed_group'])
+
def test_pid(self):
plugin = self._makeOne()
result = plugin.do_pid('')
Modified: supervisor/branches/chrism-30-merge/src/supervisor/tests/test_supervisord.py
==============================================================================
--- supervisor/branches/chrism-30-merge/src/supervisor/tests/test_supervisord.py (original)
+++ supervisor/branches/chrism-30-merge/src/supervisor/tests/test_supervisord.py Sun Nov 23 13:07:19 2008
@@ -173,6 +173,106 @@
self.assertEqual(options.logger.data[0],
'received SIGUSR1 indicating nothing')
+ def test_diff_add_remove(self):
+ options = DummyOptions()
+ supervisord = self._makeOne(options)
+
+ pconfig = DummyPConfig(options, 'process1', 'process1')
+ group1 = DummyPGroupConfig(options, 'group1', pconfigs=[pconfig])
+
+ pconfig = DummyPConfig(options, 'process2', 'process2')
+ group2 = DummyPGroupConfig(options, 'group2', pconfigs=[pconfig])
+
+ new = [group1, group2]
+
+ added, changed, removed = supervisord.diff_to_active()
+ self.assertEqual(added, [])
+ self.assertEqual(changed, [])
+ self.assertEqual(removed, [])
+
+ added, changed, removed = supervisord.diff_to_active(new)
+ self.assertEqual(added, new)
+ self.assertEqual(changed, [])
+ self.assertEqual(removed, [])
+
+ supervisord.options.process_group_configs = new
+ added, changed, removed = supervisord.diff_to_active()
+ self.assertEqual(added, new)
+
+ supervisord.add_process_group(group1)
+ supervisord.add_process_group(group2)
+
+ pconfig = DummyPConfig(options, 'process3', 'process3')
+ new_group1 = DummyPGroupConfig(options, pconfigs=[pconfig])
+
+ pconfig = DummyPConfig(options, 'process4', 'process4')
+ new_group2 = DummyPGroupConfig(options, pconfigs=[pconfig])
+
+ new = [group2, new_group1, new_group2]
+
+ added, changed, removed = supervisord.diff_to_active(new)
+ self.assertEqual(added, [new_group1, new_group2])
+ self.assertEqual(changed, [])
+ self.assertEqual(removed, [group1])
+
+ def test_diff_changed(self):
+ from supervisor.options import ProcessConfig, ProcessGroupConfig
+
+ options = DummyOptions()
+ supervisord = self._makeOne(options)
+
+ def make_pconfig(name, command, **params):
+ result = {
+ 'name': name, 'command': command,
+ 'directory': None, 'umask': None, 'priority': 999, 'autostart': True,
+ 'autorestart': True, 'startsecs': 10, 'startretries': 999,
+ 'uid': None, 'stdout_logfile': None, 'stdout_capture_maxbytes': 0,
+ 'stdout_logfile_backups': 0, 'stdout_logfile_maxbytes': 0,
+ 'stderr_logfile': None, 'stderr_capture_maxbytes': 0,
+ 'stderr_logfile_backups': 0, 'stderr_logfile_maxbytes': 0,
+ 'redirect_stderr': False,
+ 'stopsignal': None, 'stopwaitsecs': 10,
+ 'exitcodes': (0,2), 'environment': None, 'serverurl': None }
+ result.update(params)
+ return ProcessConfig(options, **result)
+
+ def make_gconfig(name, pconfigs):
+ return ProcessGroupConfig(options, name, 25, pconfigs)
+
+ pconfig = make_pconfig('process1', 'process1', uid='new')
+ group1 = make_gconfig('group1', [pconfig])
+
+ pconfig = make_pconfig('process2', 'process2')
+ group2 = make_gconfig('group2', [pconfig])
+ new = [group1, group2]
+
+ pconfig = make_pconfig('process1', 'process1', uid='old')
+ group3 = make_gconfig('group1', [pconfig])
+
+ pconfig = make_pconfig('process2', 'process2')
+ group4 = make_gconfig('group2', [pconfig])
+ supervisord.add_process_group(group3)
+ supervisord.add_process_group(group4)
+
+ added, changed, removed = supervisord.diff_to_active(new)
+
+ self.assertEqual([added, removed], [[], []])
+ self.assertEqual(changed, [group1])
+
+ options = DummyOptions()
+ supervisord = self._makeOne(options)
+
+ pconfig1 = make_pconfig('process1', 'process1')
+ pconfig2 = make_pconfig('process2', 'process2')
+ group1 = make_gconfig('group1', [pconfig1, pconfig2])
+ new = [group1]
+
+ supervisord.add_process_group(make_gconfig('group1', [pconfig1]))
+
+ added, changed, removed = supervisord.diff_to_active(new)
+ self.assertEqual([added, removed], [[], []])
+ self.assertEqual(changed, [group1])
+
def test_add_process_group(self):
options = DummyOptions()
pconfig = DummyPConfig(options, 'foo', 'foo', '/bin/foo')
More information about the Supervisor-checkins
mailing list