LP1874510 libopensrf recv timeout cal repair
[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 import dns.resolver
29
30 def do_help():
31     '''
32     Print help for the OpenSRF Python application process manager
33     '''
34
35     print '''
36     Manage OpenSRF application processes
37
38     Options:
39         -a <action>
40             list_all -- List all services
41             start   -- Start a service
42             stop    -- stop a service
43             restart -- restart a service
44             start_all -- Start all services
45             stop_all -- Stop all services
46             restart_all -- Restart all services
47
48         -s <service>
49             The service name
50
51         -f <config file>
52             The OpenSRF config file
53
54         -c <config context>
55             The OpenSRF config file context
56
57         -p <PID dir>
58             The location of application PID files.  Default is @PID_DIR@/run/opensrf
59
60         -d 
61             If set, run in daemon (background) mode.  This creates a PID 
62             file for managing the process.
63
64         -l
65             If set, run in 'localhost' mode
66
67         -h
68             Prints help message
69     '''
70     sys.exit(0)
71
72 def get_pid_file(service):
73     '''
74     Return the PID file for the named service
75     '''
76
77     return "%s/%s.pid" % (pid_dir, service)
78
79 def do_init():
80     '''
81     Initialize the Python service environment
82     '''
83
84     global domain
85     global settings
86
87     try:
88         # connect to the OpenSRF network
89         osrf.system.System.net_connect(
90             config_file = config_file, config_context = config_ctx)
91     except dns.resolver.NXDOMAIN:
92         dnsfail = """
93 ERROR: Could not initialize the OpenSRF Python environment. A DNS query
94 failed to resolve the network address of the XMPP server.
95 """
96         sys.exit(dnsfail)
97
98     if as_localhost:
99         domain = 'localhost'
100     else:
101         domain = osrf.conf.get('domain')
102
103     try:
104         osrf.set.load(domain)
105     except osrf.net.XMPPNoRecipient:
106         print "* Unable to communicate with opensrf.settings.  Giving up..."
107         return
108
109     settings = osrf.set.get('apps')
110     activeapps = osrf.set.get('activeapps')
111
112     for key in (set(settings.keys()) & set(activeapps['appname'])):
113         svc = settings[key]
114         if isinstance(svc, dict) and 'language' in svc and svc['language'] == 'python':
115             services[key] = svc
116
117 def do_start(service):
118     '''
119     Start the named Python service
120     '''
121
122     pidfile = get_pid_file(service)
123
124     if service not in services:
125         print "* service %s is not a 'python' application" % service
126         return
127
128     if os.path.exists(pidfile):
129         try:
130             pid_fd = open(pidfile, 'r')
131             alive = os.getsid(int(pid_fd.read()))
132             print "* service %s already running" % service
133             return
134         except OSError:
135             os.remove(pidfile)
136
137     print "* starting %s" % service
138
139     if as_daemon:
140
141         if osrf.system.System.daemonize(False):
142             return # parent process returns
143
144         # write PID file
145         pid_fd = open(pidfile, 'w')
146         pid_fd.write(str(os.getpid()))
147         pid_fd.close()
148
149     svc_settings = services[service]
150
151     osrf.app.Application.load(service, svc_settings['implementation'])
152     osrf.app.Application.register_sysmethods()
153     osrf.app.Application.application.global_init()
154
155     controller = osrf.server.Controller(service)
156     controller.max_requests = svc_settings['unix_config']['max_requests']
157     controller.max_children = svc_settings['unix_config']['max_children']
158     controller.min_children = svc_settings['unix_config']['min_children']
159     controller.keepalive = svc_settings['keepalive']
160
161     controller.run()
162     os._exit(0)
163
164 def do_list_all():
165     '''
166     List all Python services listed in the OpenSRF configuration file
167     '''
168     for service in services.keys():
169         print service
170
171 def do_start_all():
172     '''
173     Start all Python services listed in the OpenSRF configuration file
174     '''
175
176     # You can't start more than one service without daemonizing
177     global as_daemon
178     as_daemon = True
179
180     print "* starting all services for %s " % domain
181     for service in services.keys():
182         do_start(service)
183
184 def do_stop_all():
185     '''
186     Stop all Python services listed in the OpenSRF configuration file
187     '''
188
189     print "* stopping all services for %s " % domain
190     for service in services.keys():
191         do_stop(service)
192
193 def do_stop(service):
194     '''
195     Stop the named Python service
196     '''
197
198     pidfile = get_pid_file(service)
199
200     if not os.path.exists(pidfile):
201         print "* %s is not running" % service
202         return
203
204     print "* stopping %s" % service
205
206     pid_fd = open(pidfile)
207     pid = pid_fd.read()
208     pid_fd.close()
209     try:
210         os.kill(int(pid), signal.SIGTERM)
211     except:
212         pass
213     os.remove(pidfile)
214
215 # -----------------------------------------------------
216
217 # Parse the command line options
218 ops, args = None, None
219 try:
220     ops, args = getopt.getopt(sys.argv[1:], 'a:s:f:c:p:dhl')
221 except getopt.GetoptError, e:
222     print '* %s' % str(e)
223     do_help()
224
225 options = dict(ops)
226
227 if '-a' not in options:
228     do_help()
229
230 action = options['-a']
231
232 config_file = options.get('-f', '@CONF_DIR@/opensrf_core.xml')
233 pid_dir = options.get('-p', '@PID_DIR@/run/opensrf')
234
235 service_name = options.get('-s')
236 config_ctx = options.get('-c', 'config.opensrf')
237 as_localhost = '-l' in options
238 as_daemon = '-d' in options
239
240 domain = None
241 settings = None
242 services = {}
243
244 do_init()
245
246 if action == 'start':
247     do_start(service_name)
248
249 elif action == 'stop':
250     do_stop(service_name)
251
252 elif action == 'restart':
253     do_stop(service_name)
254     do_start(service_name)
255
256 elif action == 'list_all':
257     do_list_all()
258
259 elif action == 'start_all':
260     do_start_all()
261
262 elif action == 'stop_all':
263     do_stop_all()
264
265 elif action == 'restart_all':
266     do_stop_all()
267     do_start_all()
268
269 elif action == 'help':
270     do_help()