Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Newer
Older
100644 501 lines (393 sloc) 12.659 kB
8bcefee @alobbs Initial import
alobbs authored
1 #!/usr/bin/env python
2
3 # -*- coding: utf-8 -*-
4 #
5 # Cherokee-admin
6 #
7 # Authors:
8 # Alvaro Lopez Ortega <alvaro@alobbs.com>
9 #
10 # Copyright (C) 2001-2011 Alvaro Lopez Ortega
11 #
12 # This program is free software; you can redistribute it and/or
13 # modify it under the terms of version 2 of the GNU General Public
14 # License as published by the Free Software Foundation.
15 #
16 # This program is distributed in the hope that it will be useful,
17 # but WITHOUT ANY WARRANTY; without even the implied warranty of
18 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 # GNU General Public License for more details.
20 #
21 # You should have received a copy of the GNU General Public License
22 # along with this program; if not, write to the Free Software
23 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
24 # 02110-1301, USA.
25 #
26
27 import re
28 import os
29 import sys
3fbee9c @alobbs Adds support for --from-<something> parameter. It also adds initial
alobbs authored
30 import glob
8bcefee @alobbs Initial import
alobbs authored
31 import subprocess
32
33 BUILD_DIR = "/var/tmp/cherokee-build"
34 URL_LATEST_RELEASE = "http://www.cherokee-project.com/cherokee-latest-tarball"
35 PREFIX = "/opt/cherokee"
36
3fbee9c @alobbs Adds support for --from-<something> parameter. It also adds initial
alobbs authored
37 PHASE_DOWNLOAD = 1
38 PHASE_UNPACK = 2
39 PHASE_COMPILE = 3
ffe9d1e @alobbs WIP: New 'Install' phase, better Launchd script, etc.
alobbs authored
40 PHASE_INSTALL = 4
41 PHASE_INITD = 5
42 PHASE_REPORT = 6
3fbee9c @alobbs Adds support for --from-<something> parameter. It also adds initial
alobbs authored
43
44
45 # Texts
46 #
47 LAUNCHD_PLIST = """\
48 <?xml version="1.0" encoding="UTF-8"?>
49 <!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
50 <plist version="1.0">
51 <dict>
ffe9d1e @alobbs WIP: New 'Install' phase, better Launchd script, etc.
alobbs authored
52 <key>Label</key><string>org.cherokee.webserver</string>
3fbee9c @alobbs Adds support for --from-<something> parameter. It also adds initial
alobbs authored
53 <key>RunAtLoad</key><true/>
54 <key>ProgramArguments</key><array>
ffe9d1e @alobbs WIP: New 'Install' phase, better Launchd script, etc.
alobbs authored
55 <string>%(PREFIX)s/sbin/cherokee</string>
3fbee9c @alobbs Adds support for --from-<something> parameter. It also adds initial
alobbs authored
56 </array>
ffe9d1e @alobbs WIP: New 'Install' phase, better Launchd script, etc.
alobbs authored
57 <key>UserName</key>
58 <string>root</string>
3fbee9c @alobbs Adds support for --from-<something> parameter. It also adds initial
alobbs authored
59 </dict>
60 </plist>
61 """
62
7551a16 @alobbs Implements support for init.d scripts.
alobbs authored
63 INITD_SH = """\
64 #!/bin/sh -e
65
66 PATH=/sbin:/bin:/usr/sbin:/usr/bin:%(PREFIX)s/sbin:%(PREFIX)s/bin
67
68 DAEMON=%(PREFIX)s/sbin/cherokee
69 NAME=cherokee
70 PIDFILE=%(PREFIX)s/var/run/cherokee.pid
71
72 set -e
73 test -x $DAEMON || exit 0
74
75 case "$1" in
76 start)
77 %(PREFIX)s/sbin/cherokee -d
78 ;;
79
80 stop)
81 if [ -f $PIDFILE ]; then
82 PID=$(cat $PIDFILE)
83 kill $PID
84 fi
85 ;;
86
87 restart)
88 $0 stop
89 sleep 1
90 $0 start
91 ;;
92
93 reload|force-reload)
94 printf "Reloading web server: %%s\t" "$NAME"
95 if [ -f $PIDFILE ]; then
96 PID=$(cat $PIDFILE)
97 if ps p $PID | grep $NAME >/dev/null 2>&1; then
98 kill -HUP $PID
99 else
100 echo "PID present, but $NAME not found at PID $PID - Cannot reload"
101 exit 1
102 fi
103 else
104 echo "No PID file present for $NAME - Cannot reload"
105 exit 1
106 fi
107 ;;
108
109 status)
110 printf "%%s web server status:\t" "$NAME"
111 if [ -e $PIDFILE ] ; then
112 PROCNAME=$(ps -p $(cat $PIDFILE) -o comm=)
113 if [ "x$PROCNAME" = "x" ]; then
114 printf "Not running, but PID file present \t"
115 else
116 if [ "$PROCNAME" = "$NAME" ]; then
117 printf "Running\t"
118 else
119 printf "PID file points to process '%%s', not '%%s'\t" "$PROCNAME" "$NAME"
120 fi
121 fi
122 else
123 if PID=$(pidofproc cherokee); then
124 printf "Running (PID %%s), but PIDFILE not present\t" "$PID"
125 else
126 printf "Not running\t"
127 fi
128 fi
129 ;;
130
131 *)
132 N=/etc/init.d/$NAME
133 echo "Usage: $N {start|stop|restart|reload|force-reload|status}" >&2
134 exit 1
135 ;;
136 esac
137
138 if [ $? = 0 ]; then
139 echo .
140 exit 0
141 else
142 echo failed
143 exit 1
144 fi
145 exit 0
146 """
147
148
3fbee9c @alobbs Adds support for --from-<something> parameter. It also adds initial
alobbs authored
149 # Globals
150 #
151 start_at = PHASE_DOWNLOAD
8bcefee @alobbs Initial import
alobbs authored
152
153
154 # ANSI Colors
155 #
156 ESC = chr(27) + '['
157 RESET = '%s0m' %(ESC)
158
159 def green (s): return ESC + '0;32m' + s + RESET
160 def red (s): return ESC + '0;31m' + s + RESET
161 def yellow (s): return ESC + '1;33m' + s + RESET
162 def blue (s): return ESC + '0;34m' + s + RESET
163
164
165 # Utilities
166 #
ffe9d1e @alobbs WIP: New 'Install' phase, better Launchd script, etc.
alobbs authored
167 def exe (cmd, colorer=lambda x: x, cd=None, stdin=None, return_fatal=True):
8bcefee @alobbs Initial import
alobbs authored
168 print (yellow(cmd))
169
170 stdout = ''
171
ffe9d1e @alobbs WIP: New 'Install' phase, better Launchd script, etc.
alobbs authored
172 kwargs = {'shell': True, 'stdout': subprocess.PIPE, 'cwd': cd}
173 if stdin:
174 kwargs['stdin'] = subprocess.PIPE
175
176 p = subprocess.Popen (cmd, **kwargs)
177
178 if stdin:
179 p.stdin.write (stdin)
180
8bcefee @alobbs Initial import
alobbs authored
181 while True:
182 line = p.stdout.readline()
183 if not line:
184 break
185
186 line = line.decode('utf-8')
187 stdout += line
188 print (colorer (line.rstrip('\n\r')))
189
190 p.wait()
191
192 # Return
193 if p.returncode != 0 and return_fatal:
7551a16 @alobbs Implements support for init.d scripts.
alobbs authored
194 print ('\n%s: Could not execute: %s' %(red('ERROR'), cmd))
8bcefee @alobbs Initial import
alobbs authored
195
196 return {'stdout': stdout,
197 'retcode': p.returncode}
198
ffe9d1e @alobbs WIP: New 'Install' phase, better Launchd script, etc.
alobbs authored
199 def exe_sudo (cmd, **kwargs):
200 command = "sudo -S " + cmd
201 return exe (command, **kwargs)
202
203
8bcefee @alobbs Initial import
alobbs authored
204 def which (program):
205 def is_exe(fpath):
206 return os.path.exists(fpath) and os.access(fpath, os.X_OK)
207
208 fpath, fname = os.path.split(program)
209 if fpath:
210 if is_exe(program):
211 return program
212 else:
213 for path in os.environ["PATH"].split(os.pathsep):
214 exe_file = os.path.join(path, program)
215 if is_exe(exe_file):
216 return exe_file
217
218 return None
219
220 def rm (path):
221 return exe ("rm -rf '%s'" %(path), red)
222
223 def mkdir (path):
224 return exe ("mkdir -p '%s'" %(path), blue)
225
226 def download (url, target_file):
227 # Wget
228 wget_bin = which ('wget')
229 if wget_bin:
230 ret = exe ("wget '%(url)s' --output-document='%(target_file)s'" %(locals()))
231 if ret['retcode'] == 0:
232 return
233
234 # Curl
235 curl_bin = which ('curl')
236 if curl_bin:
237 ret = exe ("curl '%(url)s' --output '%(target_file)s'" %(locals()))
238 if ret['retcode'] == 0:
239 return
240
241 # Python
242 import urllib2
243 print ("Downloading %s" %(url))
244 i = urllib2.urlopen (url)
245 o = open (target_file, 'w+')
246 o.write (i.read())
247
3fbee9c @alobbs Adds support for --from-<something> parameter. It also adds initial
alobbs authored
248 def read_input (prompt):
249 try:
250 # Python 2.x
251 return raw_input (prompt)
252 except NameError:
253 # Python 3.x
254 return input (prompt)
255
256 def read_yes_no (prompt, empty_is=None):
257 while True:
258 ret = read_input (prompt).lower()
259 if ret in ('y','yes'):
260 return True
261 if ret in ('n','no'):
ffe9d1e @alobbs WIP: New 'Install' phase, better Launchd script, etc.
alobbs authored
262 return False
3fbee9c @alobbs Adds support for --from-<something> parameter. It also adds initial
alobbs authored
263 if not ret and empty_is != None:
264 return empty_is
265
ffe9d1e @alobbs WIP: New 'Install' phase, better Launchd script, etc.
alobbs authored
266 _root_password = None
267 def get_root_password():
268 global _root_password
269
7551a16 @alobbs Implements support for init.d scripts.
alobbs authored
270 while not _root_password:
271 _root_password = read_input ("root's password: ")
ffe9d1e @alobbs WIP: New 'Install' phase, better Launchd script, etc.
alobbs authored
272
273 return _root_password
274
8bcefee @alobbs Initial import
alobbs authored
275
7551a16 @alobbs Implements support for init.d scripts.
alobbs authored
276 def figure_initd_app_level (directory, app, not_found=99):
277 files = [x.lower() for x in os.listdir(directory)]
278 for filename in files:
279 tmp = re.findall (r's(\d+)(.+)', filename)
280 if not tmp: continue
281
282 if tmp[0][1] == app:
283 return tmp[0][0]
284
285 return not_found
286
287
8bcefee @alobbs Initial import
alobbs authored
288 # Cherokee
289 #
3fbee9c @alobbs Adds support for --from-<something> parameter. It also adds initial
alobbs authored
290 def cherokee_download (tar_file):
8bcefee @alobbs Initial import
alobbs authored
291 latest_local = os.path.join (BUILD_DIR, "cherokee-latest.tar.gz")
292
293 rm (BUILD_DIR)
3fbee9c @alobbs Adds support for --from-<something> parameter. It also adds initial
alobbs authored
294 rm (tar_file)
8bcefee @alobbs Initial import
alobbs authored
295 mkdir (BUILD_DIR)
296
3fbee9c @alobbs Adds support for --from-<something> parameter. It also adds initial
alobbs authored
297 download (URL_LATEST_RELEASE, tar_file)
8bcefee @alobbs Initial import
alobbs authored
298
299
3fbee9c @alobbs Adds support for --from-<something> parameter. It also adds initial
alobbs authored
300 def cherokee_find_unpacked():
8bcefee @alobbs Initial import
alobbs authored
301 for f in os.listdir (BUILD_DIR):
302 fp = os.path.join (BUILD_DIR, f)
303 tmp = re.findall (r'cherokee-(\d+\.\d+\.\d+)', f)
304 if tmp and os.path.isdir (fp):
305 return fp
306
307
3fbee9c @alobbs Adds support for --from-<something> parameter. It also adds initial
alobbs authored
308 def cherokee_unpack (latest_local):
309 # Unpack
ebd2a17 @alobbs Better error handling
alobbs authored
310 ret = exe ("gzip -dc '%s' | tar xfv -" %(latest_local), cd=BUILD_DIR)
311 if ret['retcode'] != 0:
312 return None
3fbee9c @alobbs Adds support for --from-<something> parameter. It also adds initial
alobbs authored
313
314 # Look for the src directory
315 return cherokee_find_unpacked()
316
317
8bcefee @alobbs Initial import
alobbs authored
318 def cherokee_compile (src_dir):
91ba3f2 @alobbs Workaround for OSes/distros where gettext is not installed. It is
alobbs authored
319 params="--prefix='%s'" %(PREFIX)
320
321 # Look for gettext
322 if not which ("msgfmt"):
323 params += " --enable-nls=no"
324
325 # Configure
326 ret = exe ("./configure " + params, cd=src_dir)
ebd2a17 @alobbs Better error handling
alobbs authored
327 if ret['retcode'] != 0:
328 return True
329
91ba3f2 @alobbs Workaround for OSes/distros where gettext is not installed. It is
alobbs authored
330 # Build
ebd2a17 @alobbs Better error handling
alobbs authored
331 ret = exe ("make", cd=src_dir)
332 if ret['retcode'] != 0:
333 return True
8bcefee @alobbs Initial import
alobbs authored
334
ffe9d1e @alobbs WIP: New 'Install' phase, better Launchd script, etc.
alobbs authored
335
336 def cherokee_install (src_dir):
8bcefee @alobbs Initial import
alobbs authored
337 if os.access (PREFIX, os.W_OK):
ebd2a17 @alobbs Better error handling
alobbs authored
338 ret = exe ("make install", cd=src_dir)
8bcefee @alobbs Initial import
alobbs authored
339 else:
ebd2a17 @alobbs Better error handling
alobbs authored
340 ret = exe_sudo ("make install", cd=src_dir)
341
342 if ret['retcode'] != 0:
343 return True
8bcefee @alobbs Initial import
alobbs authored
344
345
3fbee9c @alobbs Adds support for --from-<something> parameter. It also adds initial
alobbs authored
346 def cherokee_set_initd():
347 print('')
348
349 proceed = read_yes_no ("Do you want Cherokee to be started at boot time? [Y/n] ", True)
350 if not proceed:
351 return
352
353 vars = globals()
354 vars.update (locals())
355
7551a16 @alobbs Implements support for init.d scripts.
alobbs authored
356 # MacOS X
3fbee9c @alobbs Adds support for --from-<something> parameter. It also adds initial
alobbs authored
357 if sys.platform == 'darwin':
ffe9d1e @alobbs WIP: New 'Install' phase, better Launchd script, etc.
alobbs authored
358 tmp_fp = os.path.join (BUILD_DIR, "launchd-cherokee.plist")
359 plist_fp = os.path.join (PREFIX, "launchd-cherokee.plist")
3fbee9c @alobbs Adds support for --from-<something> parameter. It also adds initial
alobbs authored
360
361 # Write the plist file
362 txt = LAUNCHD_PLIST %(vars)
ffe9d1e @alobbs WIP: New 'Install' phase, better Launchd script, etc.
alobbs authored
363 f = open (tmp_fp, 'w+')
3fbee9c @alobbs Adds support for --from-<something> parameter. It also adds initial
alobbs authored
364 f.write (txt)
365 f.close()
366
ffe9d1e @alobbs WIP: New 'Install' phase, better Launchd script, etc.
alobbs authored
367 # Permissions
368 exe_sudo ("cp '%s' '%s'" %(tmp_fp, plist_fp))
369 exe_sudo ("chown root '%s'" %(plist_fp))
370 exe_sudo ("chgrp admin '%s'" %(plist_fp))
371
3fbee9c @alobbs Adds support for --from-<something> parameter. It also adds initial
alobbs authored
372 # Let launchd know about it
ffe9d1e @alobbs WIP: New 'Install' phase, better Launchd script, etc.
alobbs authored
373 exe_sudo ("launchctl load -w '%s'" %(plist_fp))
374 exe_sudo ("launchctl start org.cherokee.webserver")
7551a16 @alobbs Implements support for init.d scripts.
alobbs authored
375 return
376
377 # Init.d
378 if (os.path.isdir ("/etc/init.d") and
379 (os.path.isdir ("/etc/rc2.d") or os.path.isdir ("/etc/init.d/rc2.d"))):
380
381 # Figure rc2.d directory
382 if os.path.isdir ("/etc/rc2.d"):
383 rc2_dir = "/etc/rc2.d"
384 elif os.path.isdir ("/etc/init.d/rc2.d"):
385 rc2_dir = "/etc/init.d/rc2.d"
386 else:
387 assert False, "Unknow layout"
388
389 # Build paths
390 tmp_fp = os.path.join (BUILD_DIR, "cherokee.initd")
391 sh_fp = os.path.join (PREFIX, "cherokee.initd")
392 initd_fp = "/etc/init.d/cherokee-opt"
393
394 # Figure rc2.d file level
395 level = 99
396 for k in ('apache', 'apache2', 'httpd', 'lighttpd', 'nginx'):
397 level = min (level, figure_initd_app_level (rc2_dir, k))
398
399 rc2S_fp = os.path.join (rc2_dir, "S%02dcherkee-opt"%(level-1))
400 rc2K_fp = os.path.join (rc2_dir, "K%02dcherkee-opt"%(level-1))
401
402 # Preliminary clean up
403 exe_sudo ("rm -f '%s' '%s' '%s' '%s' '%s'" %(tmp_fp, sh_fp, initd_fp, rc2S_fp, rc2K_fp))
404
405 # Write the init.d file
406 txt = INITD_SH %(vars)
407 f = open (tmp_fp, 'w+')
408 f.write (txt)
409 f.close()
410
411 # Permissions
412 exe_sudo ("cp '%s' '%s'" %(tmp_fp, sh_fp))
413 exe_sudo ("chown root '%s'" %(sh_fp))
414 exe_sudo ("chmod 755 '%s'" %(sh_fp))
415
416 # Add it
5d35805 @alobbs Adds an extra message that clarifies where the binaries were installed.
alobbs authored
417 exe_sudo ("ln -s '%s' '%s'" %(sh_fp, initd_fp)) # /etc/init.d/cherokee -> /opt/..
418 exe_sudo ("ln -s '%s' '%s'" %(initd_fp, rc2S_fp)) # /etc/rc2.d/S99cherokee -> /etc/init.d/..
419 exe_sudo ("ln -s '%s' '%s'" %(initd_fp, rc2K_fp)) # /etc/rc2.d/K99cherokee -> /etc/init.d/..
3fbee9c @alobbs Adds support for --from-<something> parameter. It also adds initial
alobbs authored
420
421
8bcefee @alobbs Initial import
alobbs authored
422 def cherokee_report():
423 cherokee_fp = os.path.join (PREFIX, "sbin", "cherokee")
5d35805 @alobbs Adds an extra message that clarifies where the binaries were installed.
alobbs authored
424
425 print (blue ("Technical details:"))
426 exe ("%s -i" %(cherokee_fp))
427
428 print (blue ("How to:"))
429 print (" - Launch manually the server: %s/sbin/cherokee -d" %(PREFIX))
430 print (" - Launch the administration GUI: %s/bin/cherokee-admin-launcher" %(PREFIX))
8bcefee @alobbs Initial import
alobbs authored
431
432
3fbee9c @alobbs Adds support for --from-<something> parameter. It also adds initial
alobbs authored
433
8bcefee @alobbs Initial import
alobbs authored
434 # Main
435 #
436 def main():
3fbee9c @alobbs Adds support for --from-<something> parameter. It also adds initial
alobbs authored
437 tar_file = os.path.join (BUILD_DIR, "cherokee-latest.tar.gz")
438
439 if start_at <= PHASE_DOWNLOAD:
440 cherokee_download (tar_file)
441
442 if start_at <= PHASE_UNPACK:
443 src_dir = cherokee_unpack (tar_file)
ebd2a17 @alobbs Better error handling
alobbs authored
444 if not src_dir: return
3fbee9c @alobbs Adds support for --from-<something> parameter. It also adds initial
alobbs authored
445 else:
446 src_dir = cherokee_find_unpacked()
ebd2a17 @alobbs Better error handling
alobbs authored
447 if not src_dir: return
3fbee9c @alobbs Adds support for --from-<something> parameter. It also adds initial
alobbs authored
448
449 if start_at <= PHASE_COMPILE:
ebd2a17 @alobbs Better error handling
alobbs authored
450 error = cherokee_compile (src_dir)
451 if error: return
3fbee9c @alobbs Adds support for --from-<something> parameter. It also adds initial
alobbs authored
452
ffe9d1e @alobbs WIP: New 'Install' phase, better Launchd script, etc.
alobbs authored
453 if start_at <= PHASE_INSTALL:
ebd2a17 @alobbs Better error handling
alobbs authored
454 error = cherokee_install (src_dir)
455 if error: return
ffe9d1e @alobbs WIP: New 'Install' phase, better Launchd script, etc.
alobbs authored
456
3fbee9c @alobbs Adds support for --from-<something> parameter. It also adds initial
alobbs authored
457 if start_at <= PHASE_INITD:
458 cherokee_set_initd()
459
460 if start_at <= PHASE_REPORT:
461 cherokee_report ()
8bcefee @alobbs Initial import
alobbs authored
462
463
464 def check_prerequisites():
465 assert which ("make"), "Make is required for the compilation"
466
467
3fbee9c @alobbs Adds support for --from-<something> parameter. It also adds initial
alobbs authored
468 def process_parameters():
469 global start_at
470
b3a3422 @alobbs Implements --help
alobbs authored
471 if '--help' in sys.argv:
472 print ("Cherokee's assisted deployment script:")
473 print (" USAGE: python install.py [params]")
474 print ("")
475 print (" Development:")
476 print (" --from-unpack Start at the 'unpack' phase")
477 print (" --from-compile Start at the 'compilation' phase")
478 print (" --from-install Start at the 'install' phase")
479 print (" --from-initd Start at the 'initd' phase")
480 print (" --from-report Start at the 'report' phase")
481 print ("")
482 print ("Report bugs to: http://bugs.cherokee-project.com/")
483 raise SystemExit
484
3fbee9c @alobbs Adds support for --from-<something> parameter. It also adds initial
alobbs authored
485 if '--from-unpack' in sys.argv:
486 start_at = PHASE_UNPACK
487 if '--from-compile' in sys.argv:
488 start_at = PHASE_COMPILE
ffe9d1e @alobbs WIP: New 'Install' phase, better Launchd script, etc.
alobbs authored
489 if '--from-install' in sys.argv:
490 start_at = PHASE_INSTALL
3fbee9c @alobbs Adds support for --from-<something> parameter. It also adds initial
alobbs authored
491 if '--from-initd' in sys.argv:
492 start_at = PHASE_INITD
493 if '--from-report' in sys.argv:
494 start_at = PHASE_REPORT
495
496
8bcefee @alobbs Initial import
alobbs authored
497 if __name__ == '__main__':
3fbee9c @alobbs Adds support for --from-<something> parameter. It also adds initial
alobbs authored
498 process_parameters()
8bcefee @alobbs Initial import
alobbs authored
499 check_prerequisites()
500 main()
Something went wrong with that request. Please try again.