Enhanced do_start() implementation in Python management script
[OpenSRF.git] / src / python / opensrf.py.in
1 #!/usr/bin/python
2 # -----------------------------------------------------------------------
3 # Copyright (C) 2008  Equinox Software, Inc.
4 # Bill Erickson <erickson@esilibrary.com>
5 #
6 # This program is free software; you can redistribute it and/or
7 # modify it under the terms of the GNU General Public License
8 # as published by the Free Software Foundation; either version 2
9 # of the License, or (at your option) any later version.
10 #
11 # This program is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 # GNU General Public License for more details.
15 #
16 # You should have received a copy of the GNU General Public License
17 # along with this program; if not, write to the Free Software
18 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 # 02110-1301, USA
20 # -----------------------------------------------------------------------
21
22 '''
23 Provides an environment for managing OpenSRF services written in Python
24 '''
25
26 import sys, getopt, os, signal
27 import osrf.system, osrf.server, osrf.app, osrf.set, osrf.json
28
29 def do_help():
30     '''
31     Print help for the OpenSRF Python application process manager
32     '''
33
34     print '''
35     Manage OpenSRF application processes
36
37     Options:
38         -a <action>
39             start   -- Start a service
40             stop    -- stop a service
41             restart -- restart a service
42             start_all -- Start all services
43             stop_all -- Stop all services
44             restart_all -- Restart all services
45
46         -s <service>
47             The service name
48
49         -f <config file>
50             The OpenSRF config file
51
52         -c <config context>
53             The OpenSRF config file context
54
55         -p <PID dir>
56             The location of application PID files.  Default is /tmp
57
58         -d 
59             If set, run in daemon (background) mode.  This creates a PID 
60             file for managing the process.
61
62         -l
63             If set, run in 'localhost' mode
64
65         -h
66             Prints help message
67     '''
68     sys.exit(0)
69
70 def get_pid_file(service):
71     '''
72     Return the PID file for the named service
73     '''
74
75     return "%s/%s.pid" % (pid_dir, service)
76
77 def do_init():
78     '''
79     Initialize the Python service environment
80     '''
81
82     global domain
83     global settings
84
85     # connect to the OpenSRF network
86     osrf.system.System.net_connect(
87         config_file = config_file, config_context = config_ctx)
88
89     if as_localhost:
90         domain = 'localhost'
91     else:
92         domain = osrf.conf.get('domain')
93
94     osrf.set.load(domain)
95
96     settings = osrf.set.get('apps')
97
98     for key in settings.keys():
99         svc = settings[key]
100         if isinstance(svc, dict) and 'language' in svc and svc['language'] == 'python':
101             services[key] = svc
102
103
104 def do_start(service):
105     '''
106     Start the named Python service
107     '''
108
109     pidfile = get_pid_file(service)
110
111     if service not in services:
112         print "* service %s is not a 'python' application" % service
113         return
114
115     if os.path.exists(pidfile):
116         try:
117             pid_fd = open(pidfile, 'r')
118             alive = os.getsid(int(pid_fd.read()))
119             print "* service %s already running" % service
120             return
121         except OSError:
122             os.remove(pidfile)
123
124     print "* starting %s" % service
125
126     if as_daemon:
127
128         if osrf.system.System.daemonize(False):
129             return # parent process returns
130
131         # write PID file
132         pid_fd = open(pidfile, 'w')
133         pid_fd.write(str(os.getpid()))
134         pid_fd.close()
135
136     svc_settings = services[service]
137
138     osrf.app.Application.load(service, svc_settings['implementation'])
139     osrf.app.Application.register_sysmethods()
140     osrf.app.Application.application.global_init()
141
142     controller = osrf.server.Controller(service)
143     controller.max_requests = svc_settings['unix_config']['max_requests']
144     controller.max_children = svc_settings['unix_config']['max_children']
145     controller.min_children = svc_settings['unix_config']['min_children']
146     controller.keepalive = svc_settings['keepalive']
147
148     controller.run()
149     os._exit(0)
150
151 def do_start_all():
152     '''
153     Start all Python services listed in the OpenSRF configuration file
154     '''
155
156     # You can't start more than one service without daemonizing
157     global as_daemon
158     as_daemon = True
159
160     print "* starting all services for %s " % domain
161     for service in services.keys():
162         do_start(service)
163
164 def do_stop_all():
165     '''
166     Stop all Python services listed in the OpenSRF configuration file
167     '''
168
169     print "* stopping all services for %s " % domain
170     for service in services.keys():
171         do_stop(service)
172
173 def do_stop(service):
174     '''
175     Stop the named Python service
176     '''
177
178     pidfile = get_pid_file(service)
179
180     if not os.path.exists(pidfile):
181         print "* %s is not running" % service
182         return
183
184     print "* stopping %s" % service
185
186     pid_fd = open(pidfile)
187     pid = pid_fd.read()
188     pid_fd.close()
189     try:
190         os.kill(int(pid), signal.SIGTERM)
191     except:
192         pass
193     os.remove(pidfile)
194
195 # -----------------------------------------------------
196
197 # Parse the command line options
198 ops, args = None, None
199 try:
200     ops, args = getopt.getopt(sys.argv[1:], 'a:s:f:c:p:dhl')
201 except getopt.GetoptError, e:
202     print '* %s' % str(e)
203     do_help()
204
205 options = dict(ops)
206
207 if '-a' not in options:
208     do_help()
209
210 action = options['-a']
211
212 config_file = options.get('-f', '@CONF_DIR@/opensrf_core.xml')
213 pid_dir = options.get('-p', '@PID_DIR@/run/opensrf')
214
215 service_name = options.get('-s')
216 config_ctx = options.get('-c', 'config.opensrf')
217 as_localhost = '-l' in options
218 as_daemon = '-d' in options
219
220 domain = None
221 settings = None
222 services = {}
223
224 do_init()
225
226 if action == 'start':
227     do_start(service_name)
228
229 elif action == 'stop':
230     do_stop(service_name)
231
232 elif action == 'restart':
233     do_stop(service_name)
234     do_start(service_name)
235
236 elif action == 'start_all':
237     do_start_all()
238
239 elif action == 'stop_all':
240     do_stop_all()
241
242 elif action == 'restart_all':
243     do_stop_all()
244     do_start_all()
245
246 elif action == 'help':
247     do_help()