[Supervisor-checkins] r880 - in supervisor/trunk: . src/supervisor src/supervisor/skel src/supervisor/tests
Mike Naberezny
mike at maintainable.com
Thu Jul 23 17:42:31 EDT 2009
Author: Mike Naberezny <mike at maintainable.com>
Date: Thu Jul 23 17:42:30 2009
New Revision: 880
Log:
Revert r879.
Modified:
supervisor/trunk/CHANGES.txt
supervisor/trunk/src/supervisor/rpcinterface.py
supervisor/trunk/src/supervisor/skel/sample.conf
supervisor/trunk/src/supervisor/supervisorctl.py
supervisor/trunk/src/supervisor/tests/base.py
supervisor/trunk/src/supervisor/tests/test_rpcinterfaces.py
supervisor/trunk/src/supervisor/tests/test_supervisorctl.py
Modified: supervisor/trunk/CHANGES.txt
==============================================================================
--- supervisor/trunk/CHANGES.txt (original)
+++ supervisor/trunk/CHANGES.txt Thu Jul 23 17:42:30 2009
@@ -8,24 +8,6 @@
- Added release dates to CHANGES.txt.
- - The configuration rereading functionality introduced in 3.0a7 has been
- moved into its own RPC interface and supervisorctl plugin. These will
- continue to be bundled with the main Supervisor package.
-
- Users who upgraded to 3.0a7 and wish to continue using the reread
- functionality must add these lines to their existing supervisord.conf:
-
- [rpcinterface:supervisor_reread]
- supervisor.rpcinterface_factory = supervisor.rpcinterface:make_reread_rpcinterface
- [ctlplugin:supervisor_reread]
- supervisor.ctl_factory = supervisor.supervisorctl:make_reread_controllerplugin
-
- The lines above are now included in the sample configuration file
- output by the ``echo_supervisord_conf`` console script.
-
- Please note that due to this change, supervisorctl from 3.0a7 cannot
- control the reread functions of 3.0a8 (and later).
-
3.0a7 (2009-05-24)
- We now bundle our own patched version of Medusa contributed by Jason
Modified: supervisor/trunk/src/supervisor/rpcinterface.py
==============================================================================
--- supervisor/trunk/src/supervisor/rpcinterface.py (original)
+++ supervisor/trunk/src/supervisor/rpcinterface.py Thu Jul 23 17:42:30 2009
@@ -165,6 +165,56 @@
self.supervisord.options.mood = SupervisorStates.RESTARTING
return True
+ def reloadConfig(self):
+ """
+ Reload configuration
+
+ @return boolean result always return True unless error
+ """
+ self._update('reloadConfig')
+ try:
+ self.supervisord.options.process_config_file(do_usage=False)
+ except ValueError, msg:
+ raise RPCError(Faults.CANT_REREAD, msg)
+
+ 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.
+
+ @param string name name of process group to add
+ @return boolean result true if successful
+ """
+ self._update('addProcessGroup')
+
+ for config in self.supervisord.options.process_group_configs:
+ if config.name == name:
+ result = self.supervisord.add_process_group(config)
+ if not result:
+ raise RPCError(Faults.ALREADY_ADDED, name)
+ return True
+ raise RPCError(Faults.BAD_NAME, name)
+
+ def removeProcessGroup(self, name):
+ """ Remove a stopped process from the active configuration.
+
+ @param string name name of process group to remove
+ @return boolean result Indicates wether the removal was successful
+ """
+ self._update('removeProcessGroup')
+ if name not in self.supervisord.process_groups:
+ raise RPCError(Faults.BAD_NAME, name)
+
+ result = self.supervisord.remove_process_group(name)
+ if not result:
+ raise RPCError(Faults.STILL_RUNNING)
+ return True
+
def _getAllProcesses(self, lexical=False):
# if lexical is true, return processes sorted in lexical order,
# otherwise, sort in priority order
@@ -405,6 +455,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']
@@ -790,94 +863,7 @@
def isNotRunning(process):
return not isRunning(process)
-
-class RereadNamespaceRPCInterface:
- def __init__(self, supervisord):
- self.supervisord = supervisord
-
- def _update(self, text):
- self.update_text = text # for unit tests, mainly
- if self.supervisord.options.mood < SupervisorStates.RUNNING:
- raise RPCError(Faults.SHUTDOWN_STATE)
-
- 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 reloadConfig(self):
- """
- Reload configuration
-
- @return boolean result always return True unless error
- """
- self._update('reloadConfig')
- try:
- self.supervisord.options.process_config_file(do_usage=False)
- except ValueError, msg:
- raise RPCError(Faults.CANT_REREAD, msg)
-
- 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.
-
- @param string name name of process group to add
- @return boolean result true if successful
- """
- self._update('addProcessGroup')
-
- for config in self.supervisord.options.process_group_configs:
- if config.name == name:
- result = self.supervisord.add_process_group(config)
- if not result:
- raise RPCError(Faults.ALREADY_ADDED, name)
- return True
- raise RPCError(Faults.BAD_NAME, name)
-
- def removeProcessGroup(self, name):
- """ Remove a stopped process from the active configuration.
-
- @param string name name of process group to remove
- @return boolean result Indicates wether the removal was successful
- """
- self._update('removeProcessGroup')
- if name not in self.supervisord.process_groups:
- raise RPCError(Faults.BAD_NAME, name)
-
- result = self.supervisord.remove_process_group(name)
- if not result:
- raise RPCError(Faults.STILL_RUNNING)
- return True
-
-
# this is not used in code but referenced via an entry point in the conf file
def make_main_rpcinterface(supervisord):
return SupervisorNamespaceRPCInterface(supervisord)
-# this is not used in code but referenced via an entry point in the conf file
-def make_reread_rpcinterface(supervisord):
- return RereadNamespaceRPCInterface(supervisord)
Modified: supervisor/trunk/src/supervisor/skel/sample.conf
==============================================================================
--- supervisor/trunk/src/supervisor/skel/sample.conf (original)
+++ supervisor/trunk/src/supervisor/skel/sample.conf Thu Jul 23 17:42:30 2009
@@ -30,20 +30,12 @@
;environment=KEY=value ; (key value pairs to add to environment)
;strip_ansi=false ; (strip ansi escape codes in logs; def. false)
-; the section [rpcinterface:supervisor] must remain in the config file
-; for RPC (supervisorctl/web interface) to work, additional interfaces may be
+; the below section must remain in the config file for RPC
+; (supervisorctl/web interface) to work, additional interfaces may be
; added by defining them in separate rpcinterface: sections
[rpcinterface:supervisor]
supervisor.rpcinterface_factory = supervisor.rpcinterface:make_main_rpcinterface
-; the sections [rpcinterface:supervisor_reread] and [ctlplugin:supervisor_reread]
-; enable supervisor's ability to reread its configuration after it has started.
-; remove these two sections if you want to disable this functionality.
-[rpcinterface:supervisor_reread]
-supervisor.rpcinterface_factory = supervisor.rpcinterface:make_reread_rpcinterface
-[ctlplugin:supervisor_reread]
-supervisor.ctl_factory = supervisor.supervisorctl:make_reread_controllerplugin
-
[supervisorctl]
serverurl=unix:///tmp/supervisor.sock ; use a unix:// URL for a unix socket
;serverurl=http://127.0.0.1:9001 ; use an http:// url to specify an inet socket
Modified: supervisor/trunk/src/supervisor/supervisorctl.py
==============================================================================
--- supervisor/trunk/src/supervisor/supervisorctl.py (original)
+++ supervisor/trunk/src/supervisor/supervisorctl.py Thu Jul 23 17:42:30 2009
@@ -790,142 +790,6 @@
def help_reload(self):
self.ctl.output("reload \t\tRestart the remote supervisord.")
- def _clearresult(self, result):
- name = result['name']
- code = result['status']
- template = '%s: ERROR (%s)'
- if code == xmlrpc.Faults.BAD_NAME:
- return template % (name, 'no such process')
- elif code == xmlrpc.Faults.FAILED:
- return template % (name, 'failed')
- elif code == xmlrpc.Faults.SUCCESS:
- return '%s: cleared' % name
- raise ValueError('Unknown result code %s for %s' % (code, name))
-
- def do_clear(self, arg):
- if not self.ctl.upcheck():
- return
-
- names = arg.strip().split()
-
- if not names:
- self.ctl.output('Error: clear requires a process name')
- self.help_clear()
- return
-
- supervisor = self.ctl.get_supervisor()
-
- if 'all' in names:
- results = supervisor.clearAllProcessLogs()
- for result in results:
- result = self._clearresult(result)
- self.ctl.output(result)
-
- else:
-
- for name in names:
- try:
- result = supervisor.clearProcessLogs(name)
- except xmlrpclib.Fault, e:
- error = self._clearresult({'status':e.faultCode,
- 'name':name,
- 'description':e.faultString})
- self.ctl.output(error)
- else:
- self.ctl.output('%s: cleared' % name)
-
- def help_clear(self):
- self.ctl.output("clear <name>\t\tClear a process' log files.")
- self.ctl.output(
- "clear <name> <name>\tClear multiple process' log files")
- self.ctl.output("clear all\t\tClear all process' log files")
-
- def do_open(self, arg):
- url = arg.strip()
- parts = urlparse.urlparse(url)
- if parts[0] not in ('unix', 'http'):
- self.ctl.output('ERROR: url must be http:// or unix://')
- return
- self.ctl.options.serverurl = url
- self.do_status('')
-
- def help_open(self):
- self.ctl.output("open <url>\tConnect to a remote supervisord process.")
- self.ctl.output("\t\t(for UNIX domain socket, use unix:///socket/path)")
-
- def do_version(self, arg):
- if not self.ctl.upcheck():
- return
- supervisor = self.ctl.get_supervisor()
- self.ctl.output(supervisor.getSupervisorVersion())
-
- def help_version(self):
- self.ctl.output(
- "version\t\t\tShow the version of the remote supervisord "
- "process")
-
- def do_fg(self,args=None):
- if not self.ctl.upcheck():
- return
- if not args:
- self.ctl.output('Error: no process name supplied')
- self.help_fg()
- return
- args = args.split()
- if len(args) > 1:
- self.ctl.output('Error: too many process names supplied')
- return
- program = args[0]
- supervisor = self.ctl.get_supervisor()
- try:
- info = supervisor.getProcessInfo(program)
- except xmlrpclib.Fault, msg:
- if msg.faultCode == xmlrpc.Faults.BAD_NAME:
- self.ctl.output('Error: bad process name supplied')
- return
- # for any other fault
- self.ctl.output(str(msg))
- return
- if not info['state'] == states.ProcessStates.RUNNING:
- self.ctl.output('Error: process not running')
- return
- # everything good; continue
- try:
- a = fgthread(program,self.ctl)
- # this thread takes care of
- # the output/error messages
- a.start()
- while True:
- # this takes care of the user input
- inp = raw_input() + '\n'
- try:
- supervisor.sendProcessStdin(program, inp)
- except xmlrpclib.Fault, msg:
- if msg.faultCode == xmlrpc.Faults.NOT_RUNNING:
- self.ctl.output('Process got killed')
- self.ctl.output('Exiting foreground')
- a.kill()
- return
- info = supervisor.getProcessInfo(program)
- if not info['state'] == states.ProcessStates.RUNNING:
- self.ctl.output('Process got killed')
- self.ctl.output('Exiting foreground')
- a.kill()
- return
- continue
- except (KeyboardInterrupt, EOFError):
- a.kill()
- self.ctl.output('Exiting foreground')
- return
-
- def help_fg(self,args=None):
- self.ctl.output('fg <process>\tConnect to a process in foreground mode')
- self.ctl.output('Press Ctrl+C to exit foreground')
-
-class RereadControllerPlugin(ControllerPluginBase):
- name = 'reread'
- listener = None # for unit tests
-
def _formatChanges(self, (added, changed, dropped)):
changedict = {}
for n, t in [(added, 'available'),
@@ -960,9 +824,9 @@
return template % formatted
def do_avail(self, arg):
- supervisor_reread = self.ctl.get_server_proxy('supervisor_reread')
+ supervisor = self.ctl.get_supervisor()
try:
- configinfo = supervisor_reread.getAllConfigInfo()
+ configinfo = supervisor.getAllConfigInfo()
except xmlrpclib.Fault, e:
if e.faultCode == xmlrpc.Faults.SHUTDOWN_STATE:
self.ctl.output('ERROR: supervisor shutting down')
@@ -974,9 +838,9 @@
self.ctl.output("avail\t\t\tDisplay all configured processes")
def do_reread(self, arg):
- supervisor_reread = self.ctl.get_server_proxy('supervisor_reread')
+ supervisor = self.ctl.get_supervisor()
try:
- result = supervisor_reread.reloadConfig()
+ result = supervisor.reloadConfig()
except xmlrpclib.Fault, e:
if e.faultCode == xmlrpc.Faults.SHUTDOWN_STATE:
self.ctl.output('ERROR: supervisor shutting down')
@@ -993,15 +857,10 @@
def do_add(self, arg):
names = arg.strip().split()
- if not names:
- self.ctl.output("ERROR: add requires a process group name")
- self.help_add()
- return
-
- supervisor_reread = self.ctl.get_server_proxy('supervisor_reread')
+ supervisor = self.ctl.get_supervisor()
for name in names:
try:
- supervisor_reread.addProcessGroup(name)
+ supervisor.addProcessGroup(name)
except xmlrpclib.Fault, e:
if e.faultCode == xmlrpc.Faults.SHUTDOWN_STATE:
self.ctl.output('ERROR: shutting down')
@@ -1022,19 +881,12 @@
def do_remove(self, arg):
names = arg.strip().split()
- if not names:
- self.ctl.output("ERROR: remove requires a process group name")
- self.help_add()
- return
-
- supervisor_reread = self.ctl.get_server_proxy('supervisor_reread')
+ supervisor = self.ctl.get_supervisor()
for name in names:
try:
- result = supervisor_reread.removeProcessGroup(name)
+ result = supervisor.removeProcessGroup(name)
except xmlrpclib.Fault, e:
- if e.faultCode == xmlrpc.Faults.SHUTDOWN_STATE:
- self.ctl.output('ERROR: shutting down')
- elif e.faultCode == xmlrpc.Faults.STILL_RUNNING:
+ if e.faultCode == xmlrpc.Faults.STILL_RUNNING:
self.ctl.output('ERROR: process/group still running: %s'
% name)
elif e.faultCode == xmlrpc.Faults.BAD_NAME:
@@ -1054,13 +906,11 @@
self.ctl.output("%s: %s" % (name, message))
supervisor = self.ctl.get_supervisor()
- supervisor_reread = self.ctl.get_server_proxy('supervisor_reread')
-
try:
- result = supervisor_reread.reloadConfig()
+ result = supervisor.reloadConfig()
except xmlrpclib.Fault, e:
if e.faultCode == xmlrpc.Faults.SHUTDOWN_STATE:
- self.ctl.output('ERROR: shutting down')
+ self.ctl.output('ERROR: already shutting down')
return
else:
raise e
@@ -1083,20 +933,148 @@
results = supervisor.stopProcessGroup(gname)
log(gname, "stopped")
- supervisor_reread.removeProcessGroup(gname)
- supervisor_reread.addProcessGroup(gname)
+ supervisor.removeProcessGroup(gname)
+ supervisor.addProcessGroup(gname)
log(gname, "updated process group")
for gname in added:
- supervisor_reread.addProcessGroup(gname)
+ 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 make_reread_controllerplugin(controller, **config):
- return RereadControllerPlugin(controller)
+ def _clearresult(self, result):
+ name = result['name']
+ code = result['status']
+ template = '%s: ERROR (%s)'
+ if code == xmlrpc.Faults.BAD_NAME:
+ return template % (name, 'no such process')
+ elif code == xmlrpc.Faults.FAILED:
+ return template % (name, 'failed')
+ elif code == xmlrpc.Faults.SUCCESS:
+ return '%s: cleared' % name
+ raise ValueError('Unknown result code %s for %s' % (code, name))
+
+ def do_clear(self, arg):
+ if not self.ctl.upcheck():
+ return
+
+ names = arg.strip().split()
+
+ if not names:
+ self.ctl.output('Error: clear requires a process name')
+ self.help_clear()
+ return
+
+ supervisor = self.ctl.get_supervisor()
+
+ if 'all' in names:
+ results = supervisor.clearAllProcessLogs()
+ for result in results:
+ result = self._clearresult(result)
+ self.ctl.output(result)
+
+ else:
+
+ for name in names:
+ try:
+ result = supervisor.clearProcessLogs(name)
+ except xmlrpclib.Fault, e:
+ error = self._clearresult({'status':e.faultCode,
+ 'name':name,
+ 'description':e.faultString})
+ self.ctl.output(error)
+ else:
+ self.ctl.output('%s: cleared' % name)
+
+ def help_clear(self):
+ self.ctl.output("clear <name>\t\tClear a process' log files.")
+ self.ctl.output(
+ "clear <name> <name>\tClear multiple process' log files")
+ self.ctl.output("clear all\t\tClear all process' log files")
+
+ def do_open(self, arg):
+ url = arg.strip()
+ parts = urlparse.urlparse(url)
+ if parts[0] not in ('unix', 'http'):
+ self.ctl.output('ERROR: url must be http:// or unix://')
+ return
+ self.ctl.options.serverurl = url
+ self.do_status('')
+
+ def help_open(self):
+ self.ctl.output("open <url>\tConnect to a remote supervisord process.")
+ self.ctl.output("\t\t(for UNIX domain socket, use unix:///socket/path)")
+
+ def do_version(self, arg):
+ if not self.ctl.upcheck():
+ return
+ supervisor = self.ctl.get_supervisor()
+ self.ctl.output(supervisor.getSupervisorVersion())
+
+ def help_version(self):
+ self.ctl.output(
+ "version\t\t\tShow the version of the remote supervisord "
+ "process")
+ def do_fg(self,args=None):
+ if not self.ctl.upcheck():
+ return
+ if not args:
+ self.ctl.output('Error: no process name supplied')
+ self.help_fg()
+ return
+ args = args.split()
+ if len(args) > 1:
+ self.ctl.output('Error: too many process names supplied')
+ return
+ program = args[0]
+ supervisor = self.ctl.get_supervisor()
+ try:
+ info = supervisor.getProcessInfo(program)
+ except xmlrpclib.Fault, msg:
+ if msg.faultCode == xmlrpc.Faults.BAD_NAME:
+ self.ctl.output('Error: bad process name supplied')
+ return
+ # for any other fault
+ self.ctl.output(str(msg))
+ return
+ if not info['state'] == states.ProcessStates.RUNNING:
+ self.ctl.output('Error: process not running')
+ return
+ # everything good; continue
+ try:
+ a = fgthread(program,self.ctl)
+ # this thread takes care of
+ # the output/error messages
+ a.start()
+ while True:
+ # this takes care of the user input
+ inp = raw_input() + '\n'
+ try:
+ supervisor.sendProcessStdin(program, inp)
+ except xmlrpclib.Fault, msg:
+ if msg.faultCode == xmlrpc.Faults.NOT_RUNNING:
+ self.ctl.output('Process got killed')
+ self.ctl.output('Exiting foreground')
+ a.kill()
+ return
+ info = supervisor.getProcessInfo(program)
+ if not info['state'] == states.ProcessStates.RUNNING:
+ self.ctl.output('Process got killed')
+ self.ctl.output('Exiting foreground')
+ a.kill()
+ return
+ continue
+ except (KeyboardInterrupt, EOFError):
+ a.kill()
+ self.ctl.output('Exiting foreground')
+ return
+
+ def help_fg(self,args=None):
+ self.ctl.output('fg <process>\tConnect to a process in foreground mode')
+ self.ctl.output('Press Ctrl+C to exit foreground')
def main(args=None, options=None):
if options is None:
Modified: supervisor/trunk/src/supervisor/tests/base.py
==============================================================================
--- supervisor/trunk/src/supervisor/tests/base.py (original)
+++ supervisor/trunk/src/supervisor/tests/base.py Thu Jul 23 17:42:30 2009
@@ -588,20 +588,18 @@
class DummyRPCServer:
def __init__(self):
self.supervisor = DummySupervisorRPCNamespace()
- self.supervisor_reread = DummyRereadRPCNamespace()
self.system = DummySystemRPCNamespace()
class DummySystemRPCNamespace:
pass
class DummySupervisorRPCNamespace:
- processes = []
-
_restartable = True
_restarted = False
_shutdown = False
_readlog_error = False
+
from supervisor.process import ProcessStates
all_process_info = [
{
@@ -840,43 +838,6 @@
raise Fault(self._readlog_error, '')
return 'mainlogdata'
-class DummyRereadRPCNamespace:
- def __init__(self):
- self.added_process_groups = []
- self.removed_process_groups = []
- self.processes = [] # xxx hack
-
- def addProcessGroup(self, name):
- from xmlrpclib import Fault
- from supervisor import xmlrpc
- if name == 'SHUTDOWN_STATE':
- raise Fault(xmlrpc.Faults.SHUTDOWN_STATE, '')
- elif name == 'ALREADY_ADDED':
- raise Fault(xmlrpc.Faults.ALREADY_ADDED, '')
- elif name == 'BAD_NAME':
- raise Fault(xmlrpc.Faults.BAD_NAME, '')
- else:
- self.processes.append(name) # xxx hack
- self.added_process_groups.append(name)
- return True
-
- def removeProcessGroup(self, name):
- from xmlrpclib import Fault
- from supervisor import xmlrpc
- if name == 'SHUTDOWN_STATE':
- raise Fault(xmlrpc.Faults.SHUTDOWN_STATE, '')
- elif name == 'STILL_RUNNING':
- raise Fault(xmlrpc.Faults.STILL_RUNNING, '')
- elif name == 'BAD_NAME':
- raise Fault(xmlrpc.Faults.BAD_NAME, '')
- else:
- self.removed_process_groups.append(name)
- return True
-
- def reloadConfig(self):
- return [[['added'], ['changed'], ['removed']]]
-
-
class DummyPGroupConfig:
def __init__(self, options, name='whatever', priority=999, pconfigs=None):
self.options = options
Modified: supervisor/trunk/src/supervisor/tests/test_rpcinterfaces.py
==============================================================================
--- supervisor/trunk/src/supervisor/tests/test_rpcinterfaces.py (original)
+++ supervisor/trunk/src/supervisor/tests/test_rpcinterfaces.py Thu Jul 23 17:42:30 2009
@@ -30,24 +30,8 @@
else:
raise AssertionError("Didnt raise")
-class TopLevelFunctionTests(TestBase):
- def test_factory_for_main_rpc_interface(self):
- from supervisor import rpcinterface
- supervisor = DummySupervisor()
- interface = rpcinterface.make_main_rpcinterface(supervisor)
-
- expected = rpcinterface.SupervisorNamespaceRPCInterface
- self.assertTrue(isinstance(interface, expected))
-
- def test_factory_for_reread_rpc_interface(self):
- from supervisor import rpcinterface
- supervisor = DummySupervisor()
- interface = rpcinterface.make_reread_rpcinterface(supervisor)
-
- expected = rpcinterface.RereadNamespaceRPCInterface
- self.assertTrue(isinstance(interface, expected))
-
class MainXMLRPCInterfaceTests(TestBase):
+
def _getTargetClass(self):
from supervisor import xmlrpc
return xmlrpc.RootRPCInterface
@@ -233,6 +217,99 @@
value = interface.restart()
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_reloadConfig_process_config_file_raises_ValueError(self):
+ from supervisor import xmlrpc
+ options = DummyOptions()
+ def raise_exc(*arg, **kw):
+ raise ValueError('foo')
+ options.process_config_file = raise_exc
+ supervisord = DummySupervisor(options)
+ interface = self._makeOne(supervisord)
+ self._assertRPCError(xmlrpc.Faults.CANT_REREAD, interface.reloadConfig)
+
+ def test_addProcessGroup(self):
+ from supervisor.supervisord import Supervisor
+ from supervisor import xmlrpc
+ options = DummyOptions()
+ supervisord = Supervisor(options)
+ pconfig = DummyPConfig(options, 'foo', __file__, autostart=False)
+ gconfig = DummyPGroupConfig(options, 'group1', pconfigs=[pconfig])
+ supervisord.options.process_group_configs = [gconfig]
+
+ interface = self._makeOne(supervisord)
+
+ result = interface.addProcessGroup('group1')
+ self.assertTrue(result)
+ self.assertEqual(supervisord.process_groups.keys(), ['group1'])
+
+ self._assertRPCError(xmlrpc.Faults.ALREADY_ADDED,
+ interface.addProcessGroup, 'group1')
+ self.assertEqual(supervisord.process_groups.keys(), ['group1'])
+
+ self._assertRPCError(xmlrpc.Faults.BAD_NAME,
+ interface.addProcessGroup, 'asdf')
+ self.assertEqual(supervisord.process_groups.keys(), ['group1'])
+
+ def test_removeProcessGroup(self):
+ from supervisor.supervisord import Supervisor
+ options = DummyOptions()
+ supervisord = Supervisor(options)
+ pconfig = DummyPConfig(options, 'foo', __file__, autostart=False)
+ gconfig = DummyPGroupConfig(options, 'group1', pconfigs=[pconfig])
+ supervisord.options.process_group_configs = [gconfig]
+
+ interface = self._makeOne(supervisord)
+
+ interface.addProcessGroup('group1')
+ result = interface.removeProcessGroup('group1')
+ self.assertTrue(result)
+ self.assertEqual(supervisord.process_groups.keys(), [])
+
+ def test_removeProcessGroup_bad_name(self):
+ from supervisor.supervisord import Supervisor
+ from supervisor import xmlrpc
+ options = DummyOptions()
+ supervisord = Supervisor(options)
+ pconfig = DummyPConfig(options, 'foo', __file__, autostart=False)
+ gconfig = DummyPGroupConfig(options, 'group1', pconfigs=[pconfig])
+ supervisord.options.process_group_configs = [gconfig]
+
+ interface = self._makeOne(supervisord)
+
+ self._assertRPCError(xmlrpc.Faults.BAD_NAME,
+ interface.removeProcessGroup, 'asdf')
+
+ def test_removeProcessGroup_still_running(self):
+ from supervisor.supervisord import Supervisor
+ from supervisor import xmlrpc
+ options = DummyOptions()
+ supervisord = Supervisor(options)
+ pconfig = DummyPConfig(options, 'foo', __file__, autostart=False)
+ gconfig = DummyPGroupConfig(options, 'group1', pconfigs=[pconfig])
+ supervisord.options.process_group_configs = [gconfig]
+ process = DummyProcessGroup(gconfig)
+ process.unstopped_processes = [123]
+ supervisord.process_groups = {'group1':process}
+ interface = self._makeOne(supervisord)
+ self._assertRPCError(xmlrpc.Faults.STILL_RUNNING,
+ interface.removeProcessGroup, 'group1')
+
+
def test_startProcess_already_started(self):
from supervisor import xmlrpc
options = DummyOptions()
@@ -768,6 +845,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)
@@ -1487,10 +1589,13 @@
L = []
def callback(event):
L.append(event)
-
- events.subscribe(events.RemoteCommunicationEvent, callback)
- result = interface.sendRemoteCommEvent('foo', 'bar')
- events.clear()
+
+ try:
+ events.callbacks[:] = [(events.RemoteCommunicationEvent, callback)]
+ result = interface.sendRemoteCommEvent('foo', 'bar')
+ finally:
+ events.callbacks[:] = []
+ events.clear()
self.assertTrue(result)
self.assertEqual(len(L), 1)
@@ -1507,142 +1612,20 @@
L = []
def callback(event):
L.append(event)
-
- events.subscribe(events.RemoteCommunicationEvent, callback)
- result = interface.sendRemoteCommEvent(u'fi\xed 1', u'fi\xed 2')
- events.clear()
+
+ try:
+ events.callbacks[:] = [(events.RemoteCommunicationEvent, callback)]
+ result = interface.sendRemoteCommEvent(u'fi\xed once', u'fi\xed twice')
+ finally:
+ events.callbacks[:] = []
+ events.clear()
self.assertTrue(result)
self.assertEqual(len(L), 1)
event = L[0]
- self.assertEqual(event.type, 'fi\xc3\xad 1')
- self.assertEqual(event.data, 'fi\xc3\xad 2')
-
+ self.assertEqual(event.type, 'fi\xc3\xad once')
+ self.assertEqual(event.data, 'fi\xc3\xad twice')
-class RereadNamespaceXMLRPCInterfaceTests(TestBase):
- def _getTargetClass(self):
- from supervisor import rpcinterface
- return rpcinterface.RereadNamespaceRPCInterface
-
- def _makeOne(self, *args, **kw):
- return self._getTargetClass()(*args, **kw)
-
- 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_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_reloadConfig_process_config_file_raises_ValueError(self):
- from supervisor import xmlrpc
- options = DummyOptions()
- def raise_exc(*arg, **kw):
- raise ValueError('foo')
- options.process_config_file = raise_exc
- supervisord = DummySupervisor(options)
- interface = self._makeOne(supervisord)
- self._assertRPCError(xmlrpc.Faults.CANT_REREAD, interface.reloadConfig)
-
- def test_addProcessGroup(self):
- from supervisor.supervisord import Supervisor
- from supervisor import xmlrpc
- options = DummyOptions()
- supervisord = Supervisor(options)
- pconfig = DummyPConfig(options, 'foo', __file__, autostart=False)
- gconfig = DummyPGroupConfig(options, 'group1', pconfigs=[pconfig])
- supervisord.options.process_group_configs = [gconfig]
-
- interface = self._makeOne(supervisord)
-
- result = interface.addProcessGroup('group1')
- self.assertTrue(result)
- self.assertEqual(supervisord.process_groups.keys(), ['group1'])
-
- self._assertRPCError(xmlrpc.Faults.ALREADY_ADDED,
- interface.addProcessGroup, 'group1')
- self.assertEqual(supervisord.process_groups.keys(), ['group1'])
-
- self._assertRPCError(xmlrpc.Faults.BAD_NAME,
- interface.addProcessGroup, 'asdf')
- self.assertEqual(supervisord.process_groups.keys(), ['group1'])
-
- def test_removeProcessGroup(self):
- from supervisor.supervisord import Supervisor
- options = DummyOptions()
- supervisord = Supervisor(options)
- pconfig = DummyPConfig(options, 'foo', __file__, autostart=False)
- gconfig = DummyPGroupConfig(options, 'group1', pconfigs=[pconfig])
- supervisord.options.process_group_configs = [gconfig]
-
- interface = self._makeOne(supervisord)
-
- interface.addProcessGroup('group1')
- result = interface.removeProcessGroup('group1')
- self.assertTrue(result)
- self.assertEqual(supervisord.process_groups.keys(), [])
-
- def test_removeProcessGroup_bad_name(self):
- from supervisor.supervisord import Supervisor
- from supervisor import xmlrpc
- options = DummyOptions()
- supervisord = Supervisor(options)
- pconfig = DummyPConfig(options, 'foo', __file__, autostart=False)
- gconfig = DummyPGroupConfig(options, 'group1', pconfigs=[pconfig])
- supervisord.options.process_group_configs = [gconfig]
-
- interface = self._makeOne(supervisord)
-
- self._assertRPCError(xmlrpc.Faults.BAD_NAME,
- interface.removeProcessGroup, 'asdf')
-
- def test_removeProcessGroup_still_running(self):
- from supervisor.supervisord import Supervisor
- from supervisor import xmlrpc
- options = DummyOptions()
- supervisord = Supervisor(options)
- pconfig = DummyPConfig(options, 'foo', __file__, autostart=False)
- gconfig = DummyPGroupConfig(options, 'group1', pconfigs=[pconfig])
- supervisord.options.process_group_configs = [gconfig]
- process = DummyProcessGroup(gconfig)
- process.unstopped_processes = [123]
- supervisord.process_groups = {'group1':process}
- interface = self._makeOne(supervisord)
- self._assertRPCError(xmlrpc.Faults.STILL_RUNNING,
- interface.removeProcessGroup, 'group1')
-
class SystemNamespaceXMLRPCInterfaceTests(TestBase):
def _getTargetClass(self):
Modified: supervisor/trunk/src/supervisor/tests/test_supervisorctl.py
==============================================================================
--- supervisor/trunk/src/supervisor/tests/test_supervisorctl.py (original)
+++ supervisor/trunk/src/supervisor/tests/test_supervisorctl.py Thu Jul 23 17:42:30 2009
@@ -511,310 +511,137 @@
self.assertEqual(result, None)
self.assertEqual(options._server.supervisor._shutdown, True)
- def test_pid(self):
- plugin = self._makeOne()
- result = plugin.do_pid('')
- options = plugin.ctl.options
- self.assertEqual(result, None)
- lines = plugin.ctl.stdout.getvalue().split('\n')
- self.assertEqual(len(lines), 2)
- self.assertEqual(lines[0], str(options._server.supervisor.getPID()))
-
- def test_maintail_toomanyargs(self):
- plugin = self._makeOne()
- result = plugin.do_maintail('foo bar')
- val = plugin.ctl.stdout.getvalue()
- self.failUnless(val.startswith('Error: too many'), val)
-
- def test_maintail_minus_string_fails(self):
- plugin = self._makeOne()
- result = plugin.do_maintail('-wrong')
- val = plugin.ctl.stdout.getvalue()
- self.failUnless(val.startswith('Error: bad argument -wrong'), val)
-
- def test_maintail_wrong(self):
- plugin = self._makeOne()
- result = plugin.do_maintail('wrong')
- val = plugin.ctl.stdout.getvalue()
- self.failUnless(val.startswith('Error: bad argument wrong'), val)
-
- def test_maintail_dashf(self):
- plugin = self._makeOne()
- plugin.listener = DummyListener()
- result = plugin.do_maintail('-f')
- errors = plugin.listener.errors
- self.assertEqual(len(errors), 1)
- error = errors[0]
- self.assertEqual(plugin.listener.closed,
- 'http://localhost:92491/mainlogtail')
- self.assertEqual(error[0],
- 'http://localhost:92491/mainlogtail')
- for msg in ('Cannot connect', 'socket.error', '32', 'Broken pipe'):
- self.assertTrue(msg in error[1])
-
- def test_maintail_nobytes(self):
- plugin = self._makeOne()
- result = plugin.do_maintail('')
- self.assertEqual(plugin.ctl.stdout.getvalue(), 'mainlogdata\n')
-
- def test_maintail_dashbytes(self):
+ def test__formatChanges(self):
plugin = self._makeOne()
- result = plugin.do_maintail('-100')
- self.assertEqual(plugin.ctl.stdout.getvalue(), 'mainlogdata\n')
+ # Don't explode, plz
+ plugin._formatChanges([['added'], ['changed'], ['removed']])
+ plugin._formatChanges([[], [], []])
- def test_maintail_readlog_error_nofile(self):
+ def test_reread(self):
plugin = self._makeOne()
- supervisor_rpc = plugin.ctl.get_supervisor()
- from supervisor import xmlrpc
- supervisor_rpc._readlog_error = xmlrpc.Faults.NO_FILE
- result = plugin.do_maintail('-100')
- self.assertEqual(plugin.ctl.stdout.getvalue(),
- 'supervisord: ERROR (no log file)\n')
+ 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_maintail_readlog_error_failed(self):
+ def test_reread_Fault(self):
plugin = self._makeOne()
- supervisor_rpc = plugin.ctl.get_supervisor()
from supervisor import xmlrpc
- supervisor_rpc._readlog_error = xmlrpc.Faults.FAILED
- result = plugin.do_maintail('-100')
+ import xmlrpclib
+ def raise_fault(*arg, **kw):
+ raise xmlrpclib.Fault(xmlrpc.Faults.CANT_REREAD, 'cant')
+ plugin.ctl.options._server.supervisor.reloadConfig = raise_fault
+ plugin.do_reread(None)
self.assertEqual(plugin.ctl.stdout.getvalue(),
- 'supervisord: ERROR (unknown error reading log)\n')
-
- def test_fg_too_few_args(self):
- plugin = self._makeOne()
- result = plugin.do_fg('')
- lines = plugin.ctl.stdout.getvalue().split('\n')
- self.assertEqual(result, None)
- self.assertEqual(lines[0], 'Error: no process name supplied')
+ 'ERROR: cant\n')
- def test_fg_too_many_args(self):
+ def test__formatConfigInfo(self):
+ info = { 'group': 'group1',
+ 'name': 'process1',
+ 'inuse': True,
+ 'autostart': True,
+ 'process_prio': 999,
+ 'group_prio': 999 }
plugin = self._makeOne()
- result = plugin.do_fg('foo bar')
- line = plugin.ctl.stdout.getvalue()
- self.assertEqual(result, None)
- self.assertEqual(line, 'Error: too many process names supplied\n')
+ 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_fg_badprocname(self):
+ def test_avail(self):
+ calls = []
plugin = self._makeOne()
- result = plugin.do_fg('BAD_NAME')
- line = plugin.ctl.stdout.getvalue()
- self.assertEqual(result, None)
- self.assertEqual(line, 'Error: bad process name supplied\n')
- def test_fg_procnotrunning(self):
- plugin = self._makeOne()
- result = plugin.do_fg('bar')
- line = plugin.ctl.stdout.getvalue()
- self.assertEqual(result, None)
- self.assertEqual(line, 'Error: process not running\n')
- result = plugin.do_fg('baz_01')
- lines = plugin.ctl.stdout.getvalue().split('\n')
- self.assertEqual(result, None)
- self.assertEqual(lines[-2], 'Error: process not running')
-
-class TestRereadControllerPlugin(unittest.TestCase):
- def _getTargetClass(self):
- from supervisor.supervisorctl import RereadControllerPlugin
- return RereadControllerPlugin
-
- def _makeOne(self, *arg, **kw):
- klass = self._getTargetClass()
- options = DummyClientOptions()
- ctl = DummyController(options)
- plugin = klass(ctl, *arg, **kw)
- return plugin
-
- def test_avail_handles_shutdown_state_fault(self):
- plugin = self._makeOne()
-
- class DummyRereadInterface:
+ class FakeSupervisor(object):
def getAllConfigInfo(self):
- import xmlrpclib
- from supervisor.xmlrpc import Faults
- raise xmlrpclib.Fault(Faults.SHUTDOWN_STATE, 'bye')
-
- server = plugin.ctl.options._server
- server.supervisor_reread = DummyRereadInterface()
-
- result = plugin.do_avail('')
- self.assertEqual(result, None)
-
- self.assertEqual(plugin.ctl.stdout.getvalue(),
- 'ERROR: supervisor shutting down\n')
-
- def test_avail_displays_formatted_config_info(self):
- plugin = self._makeOne()
-
- class DummyRereadInterface:
- def __init__(self):
- first = {'group': 'group1', 'name': 'process1',
- 'inuse': False, 'autostart': False,
- 'process_prio': 999, 'group_prio': 999}
- second = {'group': 'group2', 'name': 'process2',
+ return [{ 'group': 'group1', 'name': 'process1',
'inuse': False, 'autostart': False,
- 'process_prio': 999, 'group_prio': 999}
- self.info = [first, second]
-
- def getAllConfigInfo(self):
- return self.info
-
- server = plugin.ctl.options._server
- interface = DummyRereadInterface()
- server.supervisor_reread = interface
+ '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)
- expected = plugin._formatConfigInfo(interface.info[0]) + "\n" + \
- plugin._formatConfigInfo(interface.info[1]) + "\n"
- self.assertEqual(plugin.ctl.stdout.getvalue(), expected)
-
- def test_add_displays_error_and_help_when_given_no_args(self):
- plugin = self._makeOne()
-
- result = plugin.do_add(' ') # extra whitespace intentional
- self.assertEqual(result, None)
-
- output = plugin.ctl.stdout.getvalue()
- self.assertTrue('ERROR: add requires a process group name' in output)
- self.assertTrue('add <name>' in output)
-
- def test_add_will_add_a_single_process_group(self):
- plugin = self._makeOne()
-
- result = plugin.do_add(' foo') # extra whitespace intentional
- self.assertEqual(result, None)
-
- expected = 'foo: added process group\n'
- self.assertEqual(plugin.ctl.stdout.getvalue(), expected)
-
- interface = plugin.ctl.options._server.supervisor_reread
- self.assertEqual(interface.added_process_groups, ['foo'])
-
- def test_add_will_adds_multiple_process_groups(self):
- plugin = self._makeOne()
-
- result = plugin.do_add(' foo bar ') # extra whitespace intentional
- self.assertEqual(result, None)
-
- expected = "foo: added process group\n" \
- "bar: added process group\n"
- self.assertEqual(plugin.ctl.stdout.getvalue(), expected)
-
- interface = plugin.ctl.options._server.supervisor_reread
- self.assertEqual(interface.added_process_groups, ['foo', 'bar'])
-
- def test_add_handles_shutdown_state_fault(self):
+ def test_add(self):
plugin = self._makeOne()
-
- result = plugin.do_add('SHUTDOWN_STATE')
+ result = plugin.do_add('foo')
self.assertEqual(result, None)
+ supervisor = plugin.ctl.options._server.supervisor
+ self.assertEqual(supervisor.processes, ['foo'])
- expected = "ERROR: shutting down\n"
- self.assertEqual(plugin.ctl.stdout.getvalue(), expected)
-
- def test_add_handles_already_added_fault(self):
+ def test_add_already_added(self):
plugin = self._makeOne()
-
result = plugin.do_add('ALREADY_ADDED')
self.assertEqual(result, None)
+ supervisor = plugin.ctl.options._server.supervisor
+ self.assertEqual(plugin.ctl.stdout.getvalue(),
+ 'ERROR: process group already active\n')
- expected = "ERROR: process group already active\n"
- self.assertEqual(plugin.ctl.stdout.getvalue(), expected)
-
- def test_add_handles_bad_name_fault(self):
+ def test_add_bad_name(self):
plugin = self._makeOne()
-
result = plugin.do_add('BAD_NAME')
self.assertEqual(result, None)
+ supervisor = plugin.ctl.options._server.supervisor
+ self.assertEqual(plugin.ctl.stdout.getvalue(),
+ 'ERROR: no such process/group: BAD_NAME\n')
- expected = "ERROR: no such process/group: BAD_NAME\n"
- self.assertEqual(plugin.ctl.stdout.getvalue(), expected)
-
- def test_remove_will_remove_a_single_process_group(self):
- plugin = self._makeOne()
-
- result = plugin.do_remove(' foo') # extra whitespace intentional
- self.assertEqual(result, None)
-
- expected = "foo: removed process group\n"
- self.assertEqual(plugin.ctl.stdout.getvalue(), expected)
-
- interface = plugin.ctl.options._server.supervisor_reread
- self.assertEqual(interface.removed_process_groups, ['foo'])
-
- def test_remove_will_remove_multiple_process_groups(self):
+ def test_remove(self):
plugin = self._makeOne()
-
- result = plugin.do_remove(' foo bar ') # extra whitespace intentional
+ supervisor = plugin.ctl.options._server.supervisor
+ supervisor.processes = ['foo']
+ result = plugin.do_remove('foo')
self.assertEqual(result, None)
+ self.assertEqual(supervisor.processes, [])
- expected = "foo: removed process group\n" \
- "bar: removed process group\n"
- self.assertEqual(plugin.ctl.stdout.getvalue(), expected)
-
- interface = plugin.ctl.options._server.supervisor_reread
- self.assertEqual(interface.removed_process_groups, ['foo', 'bar'])
-
- def test_remove_handles_shutdown_state_fault(self):
+ def test_remove_bad_name(self):
plugin = self._makeOne()
-
- result = plugin.do_remove('SHUTDOWN_STATE')
+ supervisor = plugin.ctl.options._server.supervisor
+ supervisor.processes = ['foo']
+ result = plugin.do_remove('BAD_NAME')
self.assertEqual(result, None)
-
self.assertEqual(plugin.ctl.stdout.getvalue(),
- 'ERROR: shutting down\n')
+ 'ERROR: no such process/group: BAD_NAME\n')
- def test_remove_handles_still_running_fault(self):
+ def test_remove_still_running(self):
plugin = self._makeOne()
-
+ supervisor = plugin.ctl.options._server.supervisor
+ supervisor.processes = ['foo']
result = plugin.do_remove('STILL_RUNNING')
self.assertEqual(result, None)
-
self.assertEqual(plugin.ctl.stdout.getvalue(),
'ERROR: process/group still running: STILL_RUNNING\n')
- def test_remove_handles_bad_name_fault(self):
- plugin = self._makeOne()
-
- result = plugin.do_remove('BAD_NAME')
- self.assertEqual(result, None)
-
- self.assertEqual(plugin.ctl.stdout.getvalue(),
- 'ERROR: no such process/group: BAD_NAME\n')
-
- def test_update_handles_shutdown_state_fault(self):
+ def test_update_not_on_shutdown(self):
plugin = self._makeOne()
-
- class DummyRereadInterface:
- def reloadConfig(self):
- from supervisor import xmlrpc
- import xmlrpclib
- raise xmlrpclib.Fault(xmlrpc.Faults.SHUTDOWN_STATE, 'bye')
-
- server = plugin.ctl.options._server
- interface = DummyRereadInterface()
- server.supervisor_reread = interface
-
- result = plugin.do_update('')
- self.assertEqual(result, None)
-
- self.assertEquals(plugin.ctl.stdout.getvalue(),
- 'ERROR: shutting down\n')
+ 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_reread = plugin.ctl.options._server.supervisor_reread
supervisor = plugin.ctl.options._server.supervisor
- supervisor_reread.processes = supervisor.processes
calls = []
def reloadConfig():
return [[['new_proc'], [], []]]
- supervisor_reread.reloadConfig = reloadConfig
+ supervisor.reloadConfig = reloadConfig
plugin.do_update('')
- self.assertEqual(supervisor_reread.processes, ['new_proc'])
+ self.assertEqual(supervisor.processes, ['new_proc'])
def test_update_changed_procs(self):
from supervisor import xmlrpc
@@ -822,16 +649,14 @@
plugin = self._makeOne()
supervisor = plugin.ctl.options._server.supervisor
- supervisor_reread = plugin.ctl.options._server.supervisor_reread
- supervisor.processes = supervisor_reread.processes = []
calls = []
def reloadConfig():
return [[[], ['changed_group'], []]]
- supervisor_reread.reloadConfig = reloadConfig
+ supervisor.reloadConfig = reloadConfig
supervisor.startProcess = lambda x: calls.append(('start', x))
- supervisor_reread.addProcessGroup('changed_group') # fake existence
+ supervisor.addProcessGroup('changed_group') # fake existence
results = [{'name': 'changed_process',
'group': 'changed_group',
'status': xmlrpc.Faults.SUCCESS,
@@ -844,7 +669,7 @@
plugin.do_update('')
self.assertEqual(calls, [('stop', 'changed_group')])
- supervisor_reread.addProcessGroup('changed_group') # fake existence
+ supervisor.addProcessGroup('changed_group') # fake existence
calls[:] = []
results[:] = [{'name': 'changed_process1',
'group': 'changed_group',
@@ -858,7 +683,7 @@
plugin.do_update('')
self.assertEqual(calls, [('stop', 'changed_group')])
- supervisor_reread.addProcessGroup('changed_group') # fake existence
+ supervisor.addProcessGroup('changed_group') # fake existence
calls[:] = []
results[:] = [{'name': 'changed_process1',
'group': 'changed_group',
@@ -877,17 +702,16 @@
plugin = self._makeOne()
supervisor = plugin.ctl.options._server.supervisor
- supervisor_reread = plugin.ctl.options._server.supervisor_reread
def reloadConfig():
return [[[], [], ['removed_group']]]
- supervisor_reread.reloadConfig = reloadConfig
+ supervisor.reloadConfig = reloadConfig
results = [{'name': 'removed_process',
'group': 'removed_group',
'status': xmlrpc.Faults.SUCCESS,
'description': 'blah'}]
- supervisor.processes = supervisor_reread.processes = ['removed_group']
+ supervisor.processes = ['removed_group']
def stopProcessGroup(name):
return results
@@ -900,7 +724,7 @@
'group': 'removed_group',
'status': xmlrpc.Faults.NOT_RUNNING,
'description': 'blah'}]
- supervisor.processes = supervisor_reread.processes = ['removed_group']
+ supervisor.processes = ['removed_group']
plugin.do_update('')
self.assertEqual(supervisor.processes, [])
@@ -909,55 +733,111 @@
'group': 'removed_group',
'status': xmlrpc.Faults.FAILED,
'description': 'blah'}]
- supervisor.processes = supervisor_reread.processes = ['removed_group']
+ supervisor.processes = ['removed_group']
plugin.do_update('')
self.assertEqual(supervisor.processes, ['removed_group'])
- def test__formatChanges(self):
+ def test_pid(self):
plugin = self._makeOne()
- # Don't explode, plz
- plugin._formatChanges([['added'], ['changed'], ['removed']])
- plugin._formatChanges([[], [], []])
+ result = plugin.do_pid('')
+ options = plugin.ctl.options
+ self.assertEqual(result, None)
+ lines = plugin.ctl.stdout.getvalue().split('\n')
+ self.assertEqual(len(lines), 2)
+ self.assertEqual(lines[0], str(options._server.supervisor.getPID()))
- def test_reread(self):
+ def test_maintail_toomanyargs(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']])
+ result = plugin.do_maintail('foo bar')
+ val = plugin.ctl.stdout.getvalue()
+ self.failUnless(val.startswith('Error: too many'), val)
- def test_reread_Fault(self):
+ def test_maintail_minus_string_fails(self):
plugin = self._makeOne()
+ result = plugin.do_maintail('-wrong')
+ val = plugin.ctl.stdout.getvalue()
+ self.failUnless(val.startswith('Error: bad argument -wrong'), val)
+
+ def test_maintail_wrong(self):
+ plugin = self._makeOne()
+ result = plugin.do_maintail('wrong')
+ val = plugin.ctl.stdout.getvalue()
+ self.failUnless(val.startswith('Error: bad argument wrong'), val)
+
+ def test_maintail_dashf(self):
+ plugin = self._makeOne()
+ plugin.listener = DummyListener()
+ result = plugin.do_maintail('-f')
+ errors = plugin.listener.errors
+ self.assertEqual(len(errors), 1)
+ error = errors[0]
+ self.assertEqual(plugin.listener.closed,
+ 'http://localhost:92491/mainlogtail')
+ self.assertEqual(error[0],
+ 'http://localhost:92491/mainlogtail')
+ for msg in ('Cannot connect', 'socket.error', '32', 'Broken pipe'):
+ self.assertTrue(msg in error[1])
+
+ def test_maintail_nobytes(self):
+ plugin = self._makeOne()
+ result = plugin.do_maintail('')
+ self.assertEqual(plugin.ctl.stdout.getvalue(), 'mainlogdata\n')
+
+ def test_maintail_dashbytes(self):
+ plugin = self._makeOne()
+ result = plugin.do_maintail('-100')
+ self.assertEqual(plugin.ctl.stdout.getvalue(), 'mainlogdata\n')
+
+ def test_maintail_readlog_error_nofile(self):
+ plugin = self._makeOne()
+ supervisor_rpc = plugin.ctl.get_supervisor()
from supervisor import xmlrpc
- import xmlrpclib
- def raise_fault(*arg, **kw):
- raise xmlrpclib.Fault(xmlrpc.Faults.CANT_REREAD, 'cant')
- plugin.ctl.options._server.supervisor_reread.reloadConfig = raise_fault
- plugin.do_reread(None)
+ supervisor_rpc._readlog_error = xmlrpc.Faults.NO_FILE
+ result = plugin.do_maintail('-100')
self.assertEqual(plugin.ctl.stdout.getvalue(),
- 'ERROR: cant\n')
+ 'supervisord: ERROR (no log file)\n')
- def test__formatConfigInfo(self):
- info = { 'group': 'group1',
- 'name': 'process1',
- 'inuse': True,
- 'autostart': True,
- 'process_prio': 999,
- 'group_prio': 999 }
+ def test_maintail_readlog_error_failed(self):
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)
+ supervisor_rpc = plugin.ctl.get_supervisor()
+ from supervisor import xmlrpc
+ supervisor_rpc._readlog_error = xmlrpc.Faults.FAILED
+ result = plugin.do_maintail('-100')
+ self.assertEqual(plugin.ctl.stdout.getvalue(),
+ 'supervisord: ERROR (unknown error reading log)\n')
+
+ def test_fg_too_few_args(self):
+ plugin = self._makeOne()
+ result = plugin.do_fg('')
+ lines = plugin.ctl.stdout.getvalue().split('\n')
+ self.assertEqual(result, None)
+ self.assertEqual(lines[0], 'Error: no process name supplied')
+
+ def test_fg_too_many_args(self):
+ plugin = self._makeOne()
+ result = plugin.do_fg('foo bar')
+ line = plugin.ctl.stdout.getvalue()
+ self.assertEqual(result, None)
+ self.assertEqual(line, 'Error: too many process names supplied\n')
+
+ def test_fg_badprocname(self):
+ plugin = self._makeOne()
+ result = plugin.do_fg('BAD_NAME')
+ line = plugin.ctl.stdout.getvalue()
+ self.assertEqual(result, None)
+ self.assertEqual(line, 'Error: bad process name supplied\n')
+ def test_fg_procnotrunning(self):
+ plugin = self._makeOne()
+ result = plugin.do_fg('bar')
+ line = plugin.ctl.stdout.getvalue()
+ self.assertEqual(result, None)
+ self.assertEqual(line, 'Error: process not running\n')
+ result = plugin.do_fg('baz_01')
+ lines = plugin.ctl.stdout.getvalue().split('\n')
+ self.assertEqual(result, None)
+ self.assertEqual(lines[-2], 'Error: process not running')
class DummyListener:
def __init__(self):
More information about the Supervisor-checkins
mailing list