From 0964810f9acb0f569f491dbaaa1d21be3bbd06b8 Mon Sep 17 00:00:00 2001 From: erickson Date: Fri, 22 May 2009 22:54:52 +0000 Subject: [PATCH] opensrf.py can now read the opensrf.settings file for managing apps. added start/stop_all actions. support for service name syslog ident git-svn-id: svn://svn.open-ils.org/OpenSRF/trunk@1705 9efc2488-bf62-4759-914b-345cdb29e865 --- src/python/opensrf.py | 132 ++++++++++++++++++++++++++++++++++++---------- src/python/osrf/log.py | 18 ++++--- src/python/osrf/server.py | 12 +++-- src/python/osrf/system.py | 12 +++-- 4 files changed, 133 insertions(+), 41 deletions(-) diff --git a/src/python/opensrf.py b/src/python/opensrf.py index bb1b17e..63d9866 100755 --- a/src/python/opensrf.py +++ b/src/python/opensrf.py @@ -31,6 +31,9 @@ def do_help(): start -- Start a service stop -- stop a service restart -- restart a service + start_all -- Start all services + stop_all -- Stop all services + restart_all -- Restart all services -s The service name @@ -48,6 +51,9 @@ def do_help(): If set, run in daemon (background) mode. This creates a PID file for managing the process. + -l + If set, run in 'localhost' mode + -h Prints help message ''' @@ -57,74 +63,146 @@ def do_help(): # Parse the command line options ops, args = None, None try: - ops, args = getopt.getopt(sys.argv[1:], 'a:s:f:c:p:dh') + ops, args = getopt.getopt(sys.argv[1:], 'a:s:f:c:p:dhl') except getopt.GetoptError, e: print '* %s' % str(e) do_help() options = dict(ops) -if '-a' not in options or '-s' not in options or '-f' not in options: +if '-a' not in options or '-f' not in options: do_help() action = options['-a'] -service = options['-s'] config_file = options['-f'] +pid_dir = options['-p'] + +service = options.get('-s') config_ctx = options.get('-c', 'config.opensrf') -pid_dir = options.get('-p', '/tmp') +as_localhost = '-l' in options as_daemon = '-d' in options -pidfile = "%s/osrf_py_%s.pid" % (pid_dir, service) +domain = None +settings = None +services = {} + + +def get_pid_file(service): + return "%s/%s.pid" % (pid_dir, service) -def do_start(): +def do_init(): + global domain + global settings # connect to the OpenSRF network osrf.system.System.net_connect( config_file = config_file, config_context = config_ctx) -# osrf.set.load(osrf.conf.get('domain')) -# settings = osrf.json.to_json(osrf.set.get('apps/%s' % service)) + if as_localhost: + domain = 'localhost' + else: + domain = osrf.conf.get('domain') -# if settings['language'].lower() != 'python': -# print '%s is not a Python application' % service -# return + osrf.set.load(domain) - # XXX load the settings configs... - osrf.app.Application.load(service, 'osrf.apps.example') # XXX example only for now - osrf.app.Application.register_sysmethods() - osrf.app.Application.application.global_init() + settings = osrf.set.get('apps') + + for key in settings.keys(): + svc = settings[key] + if isinstance(svc, dict) and svc['language'] == 'python': + services[key] = svc - controller = osrf.server.Controller(service) - controller.max_requests = 100 - controller.max_children = 6 - controller.min_children = 3 - controller.keepalive = 5 + +def do_start(service): + + pidfile = get_pid_file(service) + + if service not in services: + print "* service %s is not a 'python' application" % service + return + + if os.path.exists(pidfile): + print "* service %s already running" % service + return + + print "* starting %s" % service if as_daemon: - osrf.system.System.daemonize() + + if osrf.system.System.daemonize(False): + return # parent process returns + + # write PID file file = open(pidfile, 'w') file.write(str(os.getpid())) file.close() + settings = services[service]; + + osrf.app.Application.load(service, settings['implementation']) + osrf.app.Application.register_sysmethods() + osrf.app.Application.application.global_init() + + controller = osrf.server.Controller(service) + controller.max_requests = settings['unix_config']['max_requests'] + controller.max_children = settings['unix_config']['max_children'] + controller.min_children = settings['unix_config']['min_children'] + controller.keepalive = settings['keepalive'] + controller.run() + os._exit(0) + +def do_start_all(): + print "* starting all services for %s " % domain + for service in services.keys(): + do_start(service) + +def do_stop_all(): + print "* stopping all services for %s " % domain + for service in services.keys(): + do_stop(service) + +def do_stop(service): + pidfile = get_pid_file(service) + + if not os.path.exists(pidfile): + print "* %s is not running" % service + return + + print "* stopping %s" % service -def do_stop(): file = open(pidfile) pid = file.read() file.close() - os.kill(int(pid), signal.SIGTERM) + try: + os.kill(int(pid), signal.SIGTERM) + except: + pass os.remove(pidfile) +# ----------------------------------------------------- + +do_init() if action == 'start': - do_start() + do_start(service) elif action == 'stop': - do_stop() + do_stop(service) elif action == 'restart': - do_stop() - do_start() + do_stop(service) + do_start(service) + +elif action == 'start_all': + do_start_all() + +elif action == 'stop_all': + do_stop_all() + +elif action == 'restart_all': + do_stop_all() + do_start_all() elif action == 'help': do_help() diff --git a/src/python/osrf/log.py b/src/python/osrf/log.py index a64d8a4..906fd54 100644 --- a/src/python/osrf/log.py +++ b/src/python/osrf/log.py @@ -1,6 +1,6 @@ # ----------------------------------------------------------------------- # Copyright (C) 2007 Georgia Public Library Service -# Bill Erickson +# Bill Erickson # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License @@ -31,9 +31,9 @@ _xid_ctr = 0 _xid_is_client = False # true if we are the request origin -def initialize(level, facility=None, logfile=None, is_client=False): +def initialize(level, facility=None, logfile=None, is_client=False, syslog_ident=None): """Initialize the logging subsystem.""" - global LOG_LEVEL, LOG_TYPE, LOG_FILE, _xid_is_client + global LOG_LEVEL, LOG_TYPE, LOG_FILE, _xid_is_client _xid_is_client = is_client LOG_LEVEL = level @@ -46,7 +46,7 @@ def initialize(level, facility=None, logfile=None, is_client=False): return LOG_TYPE = OSRF_LOG_TYPE_SYSLOG - initialize_syslog(facility, level) + initialize_syslog(facility, syslog_ident) return if logfile: @@ -171,11 +171,12 @@ def __log_file(msg): logfile.close() -def initialize_syslog(facility, level): +def initialize_syslog(facility, ident=None): """Connect to syslog and set the logmask based on the level provided.""" import syslog - level = int(level) + if not ident: + ident = sys.argv[0] if facility == 'local0': facility = syslog.LOG_LOCAL0 @@ -191,7 +192,8 @@ def initialize_syslog(facility, level): facility = syslog.LOG_LOCAL5 if facility == 'local6': facility = syslog.LOG_LOCAL6 - # add other facility maps if necessary... + if facility == 'local7': + facility = syslog.LOG_LOCAL7 - syslog.openlog(sys.argv[0], 0, facility) + syslog.openlog(str(ident), 0, facility) diff --git a/src/python/osrf/server.py b/src/python/osrf/server.py index 6f2307d..4b5d014 100644 --- a/src/python/osrf/server.py +++ b/src/python/osrf/server.py @@ -18,7 +18,7 @@ # 02110-1301, USA # ----------------------------------------------------------------------- -import os, sys, threading, logging, fcntl, socket, errno, signal, time +import os, sys, threading, fcntl, socket, errno, signal, time import osrf.log, osrf.conf, osrf.net, osrf.system, osrf.stack, osrf.app, osrf.const @@ -90,7 +90,10 @@ class Controller(object): self.handle_signals() time.sleep(.5) # give children a chance to connect before we start taking data - self.osrf_handle = osrf.system.System.net_connect(resource = '%s_listener' % self.service) + self.osrf_handle = osrf.system.System.net_connect( + resource = '%s_listener' % self.service, + service = self.service + ) # clear the recv callback so inbound messages do not filter through the opensrf stack self.osrf_handle.receive_callback = None @@ -348,6 +351,9 @@ class Child(object): def init(self): ''' Connects the opensrf xmpp handle ''' osrf.net.clear_network_handle() - osrf.system.System.net_connect(resource = '%s_drone' % self.controller.service) + osrf.system.System.net_connect( + resource = '%s_drone' % self.controller.service, + service = self.controller.service + ) osrf.app.Application.application.child_init() diff --git a/src/python/osrf/system.py b/src/python/osrf/system.py index accf45c..0df4d73 100644 --- a/src/python/osrf/system.py +++ b/src/python/osrf/system.py @@ -45,7 +45,8 @@ class System(object): osrf.conf.get('loglevel'), osrf.conf.get_no_ex('syslog'), osrf.conf.get_no_ex('logfile'), - osrf.conf.get_no_ex('client') == 'true') + osrf.conf.get_no_ex('client') == 'true', + kwargs.get('service')) # connect to the opensrf network network = Network( @@ -93,8 +94,11 @@ class System(object): if not osrf.cache.CacheClient.get_client(): osrf.cache.CacheClient.connect(cache_servers) + ''' + @return 0 if child, pid if parent + ''' @staticmethod - def daemonize(): + def daemonize(parentExit=True): pid = os.fork() if pid == 0: os.chdir('/') @@ -102,7 +106,9 @@ class System(object): sys.stdin.close() sys.stdout.close() sys.stderr.close() - else: + elif parentExit: os._exit(0) + return pid + -- 2.11.0