<s> import os <EOL> import time <EOL> import datetime <EOL> import errno <EOL> from supervisor . options import readFile <EOL> from supervisor . options import tailFile <EOL> from supervisor . options import NotExecutable <EOL> from supervisor . options import NotFound <EOL> from supervisor . options import NoPermission <EOL> from supervisor . options import make_namespec <EOL> from supervisor . options import split_namespec <EOL> from supervisor . options import VERSION <EOL> from supervisor . events import notify <EOL> from supervisor . events import RemoteCommunicationEvent <EOL> from supervisor . http import NOT_DONE_YET <EOL> from supervisor . xmlrpc import Faults <EOL> from supervisor . xmlrpc import RPCError <EOL> from supervisor . states import SupervisorStates <EOL> from supervisor . states import getSupervisorStateDescription <EOL> from supervisor . states import ProcessStates <EOL> from supervisor . states import getProcessStateDescription <EOL> from supervisor . states import RUNNING_STATES <EOL> API_VERSION = '<STR_LIT>' <EOL> class SupervisorNamespaceRPCInterface : <EOL> def __init__ ( self , supervisord ) : <EOL> self . supervisord = supervisord <EOL> def _update ( self , text ) : <EOL> self . update_text = text <EOL> if self . supervisord . options . mood < SupervisorStates . RUNNING : <EOL> raise RPCError ( Faults . SHUTDOWN_STATE ) <EOL> def getAPIVersion ( self ) : <EOL> """<STR_LIT>""" <EOL> self . _update ( '<STR_LIT>' ) <EOL> return API_VERSION <EOL> getVersion = getAPIVersion <EOL> def getSupervisorVersion ( self ) : <EOL> """<STR_LIT>""" <EOL> self . _update ( '<STR_LIT>' ) <EOL> return VERSION <EOL> def getIdentification ( self ) : <EOL> """<STR_LIT>""" <EOL> self . _update ( '<STR_LIT>' ) <EOL> return self . supervisord . options . identifier <EOL> def getState ( self ) : <EOL> """<STR_LIT>""" <EOL> self . _update ( '<STR_LIT>' ) <EOL> state = self . supervisord . options . mood <EOL> statename = getSupervisorStateDescription ( state ) <EOL> data = { <EOL> '<STR_LIT>' : state , <EOL> '<STR_LIT>' : statename , <EOL> } <EOL> return data <EOL> def getPID ( self ) : <EOL> """<STR_LIT>""" <EOL> self . _update ( '<STR_LIT>' ) <EOL> return self . supervisord . options . get_pid ( ) <EOL> def readLog ( self , offset , length ) : <EOL> """<STR_LIT>""" <EOL> self . _update ( '<STR_LIT>' ) <EOL> logfile = self . supervisord . options . logfile <EOL> if logfile is None or not os . path . exists ( logfile ) : <EOL> raise RPCError ( Faults . NO_FILE , logfile ) <EOL> try : <EOL> return readFile ( logfile , int ( offset ) , int ( length ) ) <EOL> except ValueError , inst : <EOL> why = inst . args [ <NUM_LIT:0> ] <EOL> raise RPCError ( getattr ( Faults , why ) ) <EOL> readMainLog = readLog <EOL> def clearLog ( self ) : <EOL> """<STR_LIT>""" <EOL> self . _update ( '<STR_LIT>' ) <EOL> logfile = self . supervisord . options . logfile <EOL> if logfile is None or not self . supervisord . options . exists ( logfile ) : <EOL> raise RPCError ( Faults . NO_FILE ) <EOL> try : <EOL> self . supervisord . options . remove ( logfile ) <EOL> except ( OSError , IOError ) : <EOL> raise RPCError ( Faults . FAILED ) <EOL> for handler in self . supervisord . options . logger . handlers : <EOL> if hasattr ( handler , '<STR_LIT>' ) : <EOL> self . supervisord . options . logger . info ( '<STR_LIT>' ) <EOL> handler . reopen ( ) <EOL> return True <EOL> def shutdown ( self ) : <EOL> """<STR_LIT>""" <EOL> self . _update ( '<STR_LIT>' ) <EOL> self . supervisord . options . mood = SupervisorStates . SHUTDOWN <EOL> return True <EOL> def restart ( self ) : <EOL> """<STR_LIT>""" <EOL> self . _update ( '<STR_LIT>' ) <EOL> self . supervisord . options . mood = SupervisorStates . RESTARTING <EOL> return True <EOL> def reloadConfig ( self ) : <EOL> """<STR_LIT>""" <EOL> self . _update ( '<STR_LIT>' ) <EOL> try : <EOL> self . supervisord . options . process_config_file ( do_usage = False ) <EOL> except ValueError , msg : <EOL> raise RPCError ( Faults . CANT_REREAD , msg ) <EOL> added , changed , removed = self . supervisord . diff_to_active ( ) <EOL> added = [ group . name for group in added ] <EOL> changed = [ group . name for group in changed ] <EOL> removed = [ group . name for group in removed ] <EOL> return [ [ added , changed , removed ] ] <EOL> def addProcessGroup ( self , name ) : <EOL> """<STR_LIT>""" <EOL> self . _update ( '<STR_LIT>' ) <EOL> for config in self . supervisord . options . process_group_configs : <EOL> if config . name == name : <EOL> result = self . supervisord . add_process_group ( config ) <EOL> if not result : <EOL> raise RPCError ( Faults . ALREADY_ADDED , name ) <EOL> return True <EOL> raise RPCError ( Faults . BAD_NAME , name ) <EOL> def removeProcessGroup ( self , name ) : <EOL> """<STR_LIT>""" <EOL> self . _update ( '<STR_LIT>' ) <EOL> if name not in self . supervisord . process_groups : <EOL> raise RPCError ( Faults . BAD_NAME , name ) <EOL> result = self . supervisord . remove_process_group ( name ) <EOL> if not result : <EOL> raise RPCError ( Faults . STILL_RUNNING ) <EOL> return True <EOL> def _getAllProcesses ( self , lexical = False ) : <EOL> all_processes = [ ] <EOL> if lexical : <EOL> group_names = self . supervisord . process_groups . keys ( ) <EOL> group_names . sort ( ) <EOL> for group_name in group_names : <EOL> group = self . supervisord . process_groups [ group_name ] <EOL> process_names = group . processes . keys ( ) <EOL> process_names . sort ( ) <EOL> for process_name in process_names : <EOL> process = group . processes [ process_name ] <EOL> all_processes . append ( ( group , process ) ) <EOL> else : <EOL> groups = self . supervisord . process_groups . values ( ) <EOL> groups . sort ( ) <EOL> for group in groups : <EOL> processes = group . processes . values ( ) <EOL> processes . sort ( ) <EOL> for process in processes : <EOL> all_processes . append ( ( group , process ) ) <EOL> return all_processes <EOL> def _getGroupAndProcess ( self , name ) : <EOL> group_name , process_name = split_namespec ( name ) <EOL> group = self . supervisord . process_groups . get ( group_name ) <EOL> if group is None : <EOL> raise RPCError ( Faults . BAD_NAME , name ) <EOL> if process_name is None : <EOL> return group , None <EOL> process = group . processes . get ( process_name ) <EOL> if process is None : <EOL> raise RPCError ( Faults . BAD_NAME , name ) <EOL> return group , process <EOL> def startProcess ( self , name , wait = True ) : <EOL> """<STR_LIT>""" <EOL> self . _update ( '<STR_LIT>' ) <EOL> group , process = self . _getGroupAndProcess ( name ) <EOL> if process is None : <EOL> group_name , process_name = split_namespec ( name ) <EOL> return self . startProcessGroup ( group_name , wait ) <EOL> try : <EOL> filename , argv = process . get_execv_args ( ) <EOL> except NotFound , why : <EOL> raise RPCError ( Faults . NO_FILE , why . args [ <NUM_LIT:0> ] ) <EOL> except ( NotExecutable , NoPermission ) , why : <EOL> raise RPCError ( Faults . NOT_EXECUTABLE , why . args [ <NUM_LIT:0> ] ) <EOL> started = [ ] <EOL> startsecs = process . config . startsecs <EOL> def startit ( ) : <EOL> if not started : <EOL> if process . get_state ( ) in RUNNING_STATES : <EOL> raise RPCError ( Faults . ALREADY_STARTED , name ) <EOL> process . spawn ( ) <EOL> if process . spawnerr : <EOL> raise RPCError ( Faults . SPAWN_ERROR , name ) <EOL> started . append ( time . time ( ) ) <EOL> if not wait or not startsecs : <EOL> return True <EOL> t = time . time ( ) <EOL> runtime = ( t - started [ <NUM_LIT:0> ] ) <EOL> state = process . get_state ( ) <EOL> if state not in ( ProcessStates . STARTING , ProcessStates . RUNNING ) : <EOL> raise RPCError ( Faults . ABNORMAL_TERMINATION , name ) <EOL> if runtime < startsecs : <EOL> return NOT_DONE_YET <EOL> if state == ProcessStates . RUNNING : <EOL> return True <EOL> raise RPCError ( Faults . ABNORMAL_TERMINATION , name ) <EOL> startit . delay = <NUM_LIT> <EOL> startit . rpcinterface = self <EOL> return startit <EOL> def startProcessGroup ( self , name , wait = True ) : <EOL> """<STR_LIT>""" <EOL> self . _update ( '<STR_LIT>' ) <EOL> group = self . supervisord . process_groups . get ( name ) <EOL> if group is None : <EOL> raise RPCError ( Faults . BAD_NAME , name ) <EOL> processes = group . processes . values ( ) <EOL> processes . sort ( ) <EOL> processes = [ ( group , process ) for process in processes ] <EOL> startall = make_allfunc ( processes , isNotRunning , self . startProcess , <EOL> wait = wait ) <EOL> startall . delay = <NUM_LIT> <EOL> startall . rpcinterface = self <EOL> return startall <EOL> def startAllProcesses ( self , wait = True ) : <EOL> """<STR_LIT>""" <EOL> self . _update ( '<STR_LIT>' ) <EOL> processes = self . _getAllProcesses ( ) <EOL> startall = make_allfunc ( processes , isNotRunning , self . startProcess , <EOL> wait = wait ) <EOL> startall . delay = <NUM_LIT> <EOL> startall . rpcinterface = self <EOL> return startall <EOL> def stopProcess ( self , name , wait = True ) : <EOL> """<STR_LIT>""" <EOL> self . _update ( '<STR_LIT>' ) <EOL> group , process = self . _getGroupAndProcess ( name ) <EOL> if process is None : <EOL> group_name , process_name = split_namespec ( name ) <EOL> return self . stopProcessGroup ( group_name , wait ) <EOL> stopped = [ ] <EOL> called = [ ] <EOL> def killit ( ) : <EOL> if not called : <EOL> if process . get_state ( ) not in RUNNING_STATES : <EOL> raise RPCError ( Faults . NOT_RUNNING ) <EOL> called . append ( <NUM_LIT:1> ) <EOL> if not stopped : <EOL> msg = process . stop ( ) <EOL> if msg is not None : <EOL> raise RPCError ( Faults . FAILED , msg ) <EOL> stopped . append ( <NUM_LIT:1> ) <EOL> if wait : <EOL> return NOT_DONE_YET <EOL> else : <EOL> return True <EOL> if process . get_state ( ) not in ( ProcessStates . STOPPED , <EOL> ProcessStates . EXITED ) : <EOL> return NOT_DONE_YET <EOL> else : <EOL> return True <EOL> killit . delay = <NUM_LIT> <EOL> killit . rpcinterface = self <EOL> return killit <EOL> def stopProcessGroup ( self , name , wait = True ) : <EOL> """<STR_LIT>""" <EOL> self . _update ( '<STR_LIT>' ) <EOL> group = self . supervisord . process_groups . get ( name ) <EOL> if group is None : <EOL> raise RPCError ( Faults . BAD_NAME , name ) <EOL> processes = group . processes . values ( ) <EOL> processes . sort ( ) <EOL> processes = [ ( group , process ) for process in processes ] <EOL> killall = make_allfunc ( processes , isRunning , self . stopProcess , <EOL> wait = wait ) <EOL> killall . delay = <NUM_LIT> <EOL> killall . rpcinterface = self <EOL> return killall <EOL> def stopAllProcesses ( self , wait = True ) : <EOL> """<STR_LIT>""" <EOL> self . _update ( '<STR_LIT>' ) <EOL> processes = self . _getAllProcesses ( ) <EOL> killall = make_allfunc ( processes , isRunning , self . stopProcess , <EOL> wait = wait ) <EOL> killall . delay = <NUM_LIT> <EOL> killall . rpcinterface = self <EOL> return killall <EOL> def getAllConfigInfo ( self ) : <EOL> """<STR_LIT>""" <EOL> self . _update ( '<STR_LIT>' ) <EOL> configinfo = [ ] <EOL> for gconfig in self . supervisord . options . process_group_configs : <EOL> inuse = gconfig . name in self . supervisord . process_groups <EOL> for pconfig in gconfig . process_configs : <EOL> configinfo . append ( <EOL> { '<STR_LIT:name>' : pconfig . name , <EOL> '<STR_LIT>' : gconfig . name , <EOL> '<STR_LIT>' : inuse , <EOL> '<STR_LIT>' : pconfig . autostart , <EOL> '<STR_LIT>' : gconfig . priority , <EOL> '<STR_LIT>' : pconfig . priority } ) <EOL> configinfo . sort ( ) <EOL> return configinfo <EOL> def _interpretProcessInfo ( self , info ) : <EOL> state = info [ '<STR_LIT:state>' ] <EOL> if state == ProcessStates . RUNNING : <EOL> start = info [ '<STR_LIT:start>' ] <EOL> now = info [ '<STR_LIT>' ] <EOL> start_dt = datetime . datetime ( * time . gmtime ( start ) [ : <NUM_LIT:6> ] ) <EOL> now_dt = datetime . datetime ( * time . gmtime ( now ) [ : <NUM_LIT:6> ] ) <EOL> uptime = now_dt - start_dt <EOL> desc = '<STR_LIT>' % ( info [ '<STR_LIT>' ] , uptime ) <EOL> if info [ '<STR_LIT>' ] : <EOL> desc += '<STR_LIT>' <EOL> elif state in ( ProcessStates . FATAL , ProcessStates . BACKOFF ) : <EOL> desc = info [ '<STR_LIT>' ] <EOL> if not desc : <EOL> desc = '<STR_LIT>' % info [ '<STR_LIT:name>' ] <EOL> elif state in ( ProcessStates . STOPPED , ProcessStates . EXITED ) : <EOL> if info [ '<STR_LIT:start>' ] : <EOL> stop = info [ '<STR_LIT>' ] <EOL> stop_dt = datetime . datetime ( * time . localtime ( stop ) [ : <NUM_LIT:7> ] ) <EOL> desc = stop_dt . strftime ( '<STR_LIT>' ) <EOL> else : <EOL> desc = '<STR_LIT>' <EOL> else : <EOL> desc = '<STR_LIT>' <EOL> return desc <EOL> def getProcessInfo ( self , name ) : <EOL> """<STR_LIT>""" <EOL> self . _update ( '<STR_LIT>' ) <EOL> group , process = self . _getGroupAndProcess ( name ) <EOL> start = int ( process . laststart ) <EOL> stop = int ( process . laststop ) <EOL> now = int ( time . time ( ) ) <EOL> state = process . get_state ( ) <EOL> spawnerr = process . spawnerr or '<STR_LIT>' <EOL> exitstatus = process . exitstatus or <NUM_LIT:0> <EOL> stdout_logfile = process . config . stdout_logfile or '<STR_LIT>' <EOL> stderr_logfile = process . config . stderr_logfile or '<STR_LIT>' <EOL> info = { <EOL> '<STR_LIT:name>' : process . config . name , <EOL> '<STR_LIT>' : group . config . name , <EOL> '<STR_LIT:start>' : start , <EOL> '<STR_LIT>' : stop , <EOL> '<STR_LIT>' : now , <EOL> '<STR_LIT:state>' : state , <EOL> '<STR_LIT>' : getProcessStateDescription ( state ) , <EOL> '<STR_LIT>' : spawnerr , <EOL> '<STR_LIT>' : exitstatus , <EOL> '<STR_LIT>' : stdout_logfile , <EOL> '<STR_LIT>' : stdout_logfile , <EOL> '<STR_LIT>' : stderr_logfile , <EOL> '<STR_LIT>' : process . pid , <EOL> '<STR_LIT>' : process . resumed , <EOL> } <EOL> description = self . _interpretProcessInfo ( info ) <EOL> info [ '<STR_LIT:description>' ] = description <EOL> return info <EOL> def getAllProcessInfo ( self ) : <EOL> """<STR_LIT>""" <EOL> self . _update ( '<STR_LIT>' ) <EOL> all_processes = self . _getAllProcesses ( lexical = True ) <EOL> output = [ ] <EOL> for group , process in all_processes : <EOL> name = make_namespec ( group . config . name , process . config . name ) <EOL> output . append ( self . getProcessInfo ( name ) ) <EOL> return output <EOL> def _readProcessLog ( self , name , offset , length , channel ) : <EOL> group , process = self . _getGroupAndProcess ( name ) <EOL> logfile = getattr ( process . config , '<STR_LIT>' % channel ) <EOL> if logfile is None or not os . path . exists ( logfile ) : <EOL> raise RPCError ( Faults . NO_FILE , logfile ) <EOL> try : <EOL> return readFile ( logfile , int ( offset ) , int ( length ) ) <EOL> except ValueError , inst : <EOL> why = inst . args [ <NUM_LIT:0> ] <EOL> raise RPCError ( getattr ( Faults , why ) ) <EOL> def readProcessStdoutLog ( self , name , offset , length ) : <EOL> """<STR_LIT>""" <EOL> self . _update ( '<STR_LIT>' ) <EOL> return self . _readProcessLog ( name , offset , length , '<STR_LIT>' ) <EOL> readProcessLog = readProcessStdoutLog <EOL> def readProcessStderrLog ( self , name , offset , length ) : <EOL> """<STR_LIT>""" <EOL> self . _update ( '<STR_LIT>' ) <EOL> return self . _readProcessLog ( name , offset , length , '<STR_LIT>' ) <EOL> def _tailProcessLog ( self , name , offset , length , channel ) : <EOL> group , process = self . _getGroupAndProcess ( name ) <EOL> logfile = getattr ( process . config , '<STR_LIT>' % channel ) <EOL> if logfile is None or not os . path . exists ( logfile ) : <EOL> return [ '<STR_LIT>' , <NUM_LIT:0> , False ] <EOL> return tailFile ( logfile , int ( offset ) , int ( length ) ) <EOL> def tailProcessStdoutLog ( self , name , offset , length ) : <EOL> """<STR_LIT>""" <EOL> self . _update ( '<STR_LIT>' ) <EOL> return self . _tailProcessLog ( name , offset , length , '<STR_LIT>' ) <EOL> tailProcessLog = tailProcessStdoutLog <EOL> def tailProcessStderrLog ( self , name , offset , length ) : <EOL> """<STR_LIT>""" <EOL> self . _update ( '<STR_LIT>' ) <EOL> return self . _tailProcessLog ( name , offset , length , '<STR_LIT>' ) <EOL> def clearProcessLogs ( self , name ) : <EOL> """<STR_LIT>""" <EOL> self . _update ( '<STR_LIT>' ) <EOL> group , process = self . _getGroupAndProcess ( name ) <EOL> try : <EOL> process . removelogs ( ) <EOL> except ( IOError , OSError ) : <EOL> raise RPCError ( Faults . FAILED , name ) <EOL> return True <EOL> clearProcessLog = clearProcessLogs <EOL> def clearAllProcessLogs ( self ) : <EOL> """<STR_LIT>""" <EOL> self . _update ( '<STR_LIT>' ) <EOL> results = [ ] <EOL> callbacks = [ ] <EOL> all_processes = self . _getAllProcesses ( ) <EOL> for group , process in all_processes : <EOL> callbacks . append ( ( group , process , self . clearProcessLog ) ) <EOL> def clearall ( ) : <EOL> if not callbacks : <EOL> return results <EOL> group , process , callback = callbacks . pop ( <NUM_LIT:0> ) <EOL> name = make_namespec ( group . config . name , process . config . name ) <EOL> try : <EOL> callback ( name ) <EOL> except RPCError , e : <EOL> results . append ( <EOL> { '<STR_LIT:name>' : process . config . name , <EOL> '<STR_LIT>' : group . config . name , <EOL> '<STR_LIT:status>' : e . code , <EOL> '<STR_LIT:description>' : e . text } ) <EOL> else : <EOL> results . append ( <EOL> { '<STR_LIT:name>' : process . config . name , <EOL> '<STR_LIT>' : group . config . name , <EOL> '<STR_LIT:status>' : Faults . SUCCESS , <EOL> '<STR_LIT:description>' : '<STR_LIT:OK>' } <EOL> ) <EOL> if callbacks : <EOL> return NOT_DONE_YET <EOL> return results <EOL> clearall . delay = <NUM_LIT> <EOL> clearall . rpcinterface = self <EOL> return clearall <EOL> def sendProcessStdin ( self , name , chars ) : <EOL> """<STR_LIT>""" <EOL> self . _update ( '<STR_LIT>' ) <EOL> if isinstance ( chars , unicode ) : <EOL> chars = chars . encode ( '<STR_LIT:utf-8>' ) <EOL> if not isinstance ( chars , basestring ) : <EOL> raise RPCError ( Faults . INCORRECT_PARAMETERS , chars ) <EOL> group , process = self . _getGroupAndProcess ( name ) <EOL> if process is None : <EOL> raise RPCError ( Faults . BAD_NAME , name ) <EOL> if not process . pid or process . killing : <EOL> raise RPCError ( Faults . NOT_RUNNING , name ) <EOL> try : <EOL> process . write ( chars ) <EOL> except OSError , why : <EOL> if why [ <NUM_LIT:0> ] == errno . EPIPE : <EOL> raise RPCError ( Faults . NO_FILE , name ) <EOL> else : <EOL> raise <EOL> return True <EOL> def sendRemoteCommEvent ( self , type , data ) : <EOL> """<STR_LIT>""" <EOL> if isinstance ( type , unicode ) : <EOL> type = type . encode ( '<STR_LIT:utf-8>' ) <EOL> if isinstance ( data , unicode ) : <EOL> data = data . encode ( '<STR_LIT:utf-8>' ) <EOL> notify ( <EOL> RemoteCommunicationEvent ( type , data ) <EOL> ) <EOL> return True <EOL> def make_allfunc ( processes , predicate , func , ** extra_kwargs ) : <EOL> """<STR_LIT>""" <EOL> callbacks = [ ] <EOL> results = [ ] <EOL> def allfunc ( processes = processes , predicate = predicate , func = func , <EOL> extra_kwargs = extra_kwargs , callbacks = callbacks , <EOL> results = results ) : <EOL> if not callbacks : <EOL> for group , process in processes : <EOL> name = make_namespec ( group . config . name , process . config . name ) <EOL> if predicate ( process ) : <EOL> try : <EOL> callback = func ( name , ** extra_kwargs ) <EOL> callbacks . append ( ( group , process , callback ) ) <EOL> except RPCError , e : <EOL> results . append ( { '<STR_LIT:name>' : process . config . name , <EOL> '<STR_LIT>' : group . config . name , <EOL> '<STR_LIT:status>' : e . code , <EOL> '<STR_LIT:description>' : e . text } ) <EOL> continue <EOL> if not callbacks : <EOL> return results <EOL> group , process , callback = callbacks . pop ( <NUM_LIT:0> ) <EOL> try : <EOL> value = callback ( ) <EOL> except RPCError , e : <EOL> results . append ( <EOL> { '<STR_LIT:name>' : process . config . name , <EOL> '<STR_LIT>' : group . config . name , <EOL> '<STR_LIT:status>' : e . code , <EOL> '<STR_LIT:description>' : e . text } ) <EOL> return NOT_DONE_YET <EOL> if value is NOT_DONE_YET : <EOL> callbacks . append ( ( group , process , callback ) ) <EOL> else : <EOL> results . append ( <EOL> { '<STR_LIT:name>' : process . config . name , <EOL> '<STR_LIT>' : group . config . name , <EOL> '<STR_LIT:status>' : Faults . SUCCESS , <EOL> '<STR_LIT:description>' : '<STR_LIT:OK>' } <EOL> ) <EOL> if callbacks : <EOL> return NOT_DONE_YET <EOL> return results <EOL> return allfunc <EOL> def isRunning ( process ) : <EOL> if process . get_state ( ) in RUNNING_STATES : <EOL> return True <EOL> def isNotRunning ( process ) : <EOL> return not isRunning ( process ) <EOL> def make_main_rpcinterface ( supervisord ) : <EOL> return SupervisorNamespaceRPCInterface ( supervisord ) </s>
