root/cherokee/trunk/admin/CherokeeManagement.py

Revision 2170, 6.4 kB (checked in by alo, 2 months ago)

--

Line 
1 import os
2 import sys
3 import time
4 import signal
5 from select import select
6 from subprocess import *
7
8 from consts import *
9 from configured import *
10
11 DEFAULT_DELAY = 2
12 DEFAULT_PID_LOCATIONS = [
13     '/var/run/cherokee.pid',
14     os.path.join (PREFIX, 'var/run/cherokee.pid')
15 ]
16
17 CHEROKEE_MIN_DEFAULT_CONFIG = """# Default configuration
18 server!pid_file = %s
19 vserver!1!nick = default
20 vserver!1!document_root = /tmp
21 vserver!1!rule!1!match = default
22 vserver!1!rule!1!handler = common
23 """ % (DEFAULT_PID_LOCATIONS[0])
24
25
26 # Cherokee Management 'factory':
27 #
28
29 cherokee_management = None
30
31 def cherokee_management_get (cfg):
32     global cherokee_management
33
34     # Fast path
35     if cherokee_management:
36         return cherokee_management
37
38     # Needs to create a new object
39     cherokee_management = CherokeeManagement(cfg)
40     return cherokee_management
41
42 def cherokee_management_reset ():
43     global cherokee_management
44     cherokee_management = None
45
46 # Cherokee Management class
47 #
48
49 class CherokeeManagement:
50     def __init__ (self, cfg):
51         self._cfg = cfg
52         self._pid = self._get_pid (worker=False)
53
54     # Public
55     #
56
57     def save (self, restart=None):
58         self._cfg.save()
59
60         if not restart or restart.lower() == 'no':
61             return
62         if restart.lower() == 'graceful':
63             self._restart (graceful=True)
64         else:
65             self._restart()
66
67     def is_alive (self):
68         if not self._pid:
69             return False
70         return is_PID_alive (self._pid)
71
72     def launch (self):
73         def daemonize():
74             os.setsid()
75
76         p = Popen ([CHEROKEE_SERVER, '-C', self._cfg.file],
77                    stdout=PIPE, stderr=PIPE,
78                    preexec_fn=daemonize, close_fds=True)
79
80         stdout_f,  stderr_f  = (p.stdout, p.stderr)
81         stdout_fd, stderr_fd = stdout_f.fileno(), stderr_f.fileno()
82         stdout,    stderr    = '', ''
83
84         while True:
85             r,w,e = select([stdout_fd, stderr_fd], [], [stdout_fd, stderr_fd], 1)
86
87             if e:
88                 self._pid = None
89                 return "Could access file descriptors: " + str(e)
90
91             if stdout_fd in r:
92                 stdout += stdout_f.read(1)
93             if stderr_fd in r:
94                 stderr += stderr_f.read(1)
95
96             if stderr.count('\n'):
97                 self.__stop_process (p.pid)
98                 self._pid = None
99                 return stderr
100
101             if stdout.count('\n') > 1:
102                 break
103
104         self._pid = p.pid
105         time.sleep (DEFAULT_DELAY)
106         return None
107        
108     def stop (self):
109         # Stop Cherokee Guardian
110         self.__stop_process (self._pid)
111         self._pid = None
112        
113         # Get the PID
114         pid = self._get_pid (worker=True)
115         if not pid: return
116
117         # Stop Cherokee
118         self.__stop_process (pid)
119         time.sleep (DEFAULT_DELAY)
120
121     def create_config (self, file):
122         if os.path.exists (file):
123             return
124
125         dirname = os.path.dirname(file)
126         if not os.path.exists (dirname):
127             os.mkdir (dirname)
128
129         conf_sample = os.path.join(CHEROKEE_ADMINDIR, "cherokee.conf.sample")
130         if os.path.exists (conf_sample):
131             content = open(conf_sample, 'r').read()
132         else:
133             content = CHEROKEE_MIN_DEFAULT_CONFIG
134
135         f = open(file, 'w+')
136         f.write (content)
137         f.close()
138
139     # Protected
140     #
141     def _get_pid_path (self, worker):
142         pid_file = self._cfg.get_val("server!pid_file")
143         if not pid_file:
144             pid_file = os.path.join (CHEROKEE_VAR_RUN, "cherokee.pid")
145         if worker:
146             pid_file += ".worker"           
147         return pid_file
148
149     def _get_pid (self, worker=False):
150         pid_file = self._get_pid_path(worker)
151         return self.__read_pid_file (pid_file)
152
153     def _restart (self, graceful=False):
154         if not self._pid:
155             return
156         try:
157             if graceful:
158                 os.kill (self._pid, signal.SIGHUP)
159             else:
160                 os.kill (self._pid, signal.SIGUSR1)
161         except:
162             pass
163
164     # Private
165     #
166
167     def __read_pid_file (self, file):
168         if not os.access (file, os.R_OK):
169             return
170         f = open (file, "r")
171         try:
172             pid = int(f.readline())
173         except:
174             return None
175         try: f.close()
176         except: pass
177         return pid
178
179     def __stop_process (self, pid):
180         if not pid:
181             return
182
183         try: os.kill (pid, signal.SIGQUIT)
184         except: pass
185
186         try: os.waitpid (pid, 0)
187         except: pass
188
189
190 def is_PID_alive (pid):
191     if sys.platform.startswith('linux') or \
192        sys.platform.startswith('sunos') or \
193        sys.platform.startswith('irix'):
194         return os.path.exists('/proc/%s'%(pid))
195
196     elif sys.platform == 'darwin' or \
197          "bsd" in sys.platform.lower():
198         f = os.popen('/bin/ps -p %s'%(pid))
199         alive = len(f.readlines()) >= 2
200         try:
201             f.close()
202         except: pass
203         return alive
204
205     elif sys.platform == 'win32':
206         None
207
208     raise 'TODO'
209
210
211 #
212 # Plug-in checking
213 #
214
215 _server_info = None
216
217 def cherokee_get_server_info ():
218     global _server_info
219
220     if _server_info == None:
221         try:
222             f = os.popen ("%s -i" % (CHEROKEE_WORKER))
223         except:
224             print ("ERROR: Couldn't execute '%s -i'"  % (CHEROKEE_WORKER))
225
226         _server_info = f.read()
227
228         try:
229             f.close()
230         except: pass
231
232     return _server_info
233
234
235 _built_in_lists = {}
236
237 def cherokee_build_info_has (filter, module):
238     # Let's see whether it's built-in
239     global _built_in_lists
240
241     if not _built_in_lists.has_key(filter):
242         _built_in_lists[filter] = {}
243
244         cont = cherokee_get_server_info()
245
246         try:
247             filter_string = " %s: " % (filter)
248             for l in cont.split("\n"):
249                 if l.startswith(filter_string):
250                     line = l.replace (filter_string, "")
251                     _built_in_lists[filter] = line.split(" ")
252                     break
253         except:
254             pass
255
256     return module in _built_in_lists[filter]
257
258 def cherokee_has_plugin (module):
259     # Check for the dynamic plug-in
260     try:
261         mods = filter(lambda x: module in x, os.listdir(CHEROKEE_PLUGINDIR))
262         if len(mods) >= 1:
263             return True
264     except:
265         pass
266
267     return cherokee_build_info_has ("Built-in", module)
268
269 def cherokee_has_polling_method (module):
270     return cherokee_build_info_has ("Polling methods", module)
Note: See TracBrowser for help on using the browser.