Refactor the CollectionHTTPServer around a wsgi-style request handler.
[jelmer/calypso.git] / calypso.py
1 #!/usr/bin/python
2 # -*- coding: utf-8 -*-
3 #
4 # This file is part of Calypso - CalDAV/CardDAV/WebDAV Server
5 # Copyright © 2011 Keith Packard
6 # Copyright © 2008-2011 Guillaume Ayoub
7 # Copyright © 2008 Nicolas Kandel
8 # Copyright © 2008 Pascal Halter
9 #
10 # This library is free software: you can redistribute it and/or modify
11 # it under the terms of the GNU General Public License as published by
12 # the Free Software Foundation, either version 3 of the License, or
13 # (at your option) any later version.
14 #
15 # This library is distributed in the hope that it will be useful,
16 # but WITHOUT ANY WARRANTY; without even the implied warranty of
17 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18 # GNU General Public License for more details.
19 #
20 # You should have received a copy of the GNU General Public License
21 # along with Calypso.  If not, see <http://www.gnu.org/licenses/>.
22
23 # This file is just a script, allow [a-z0-9]* variable names
24 # pylint: disable-msg=C0103
25
26 # ``import calypso`` refers to the ``calypso`` module, not ``calypso.py`` 
27 # pylint: disable-msg=W0406
28
29 """
30 Calypso Server entry point.
31
32 Launch the Calypso Server according to configuration and command-line
33 arguments.
34
35 """
36
37 # TODO: Manage smart and configurable logs
38
39 import daemon
40 import lockfile
41 import logging
42 import optparse
43 import os
44 import sys
45
46 import calypso
47 import calypso.webdav as webdav
48
49 # Get command-line options
50 parser = optparse.OptionParser(version=calypso.VERSION)
51 parser.add_option(
52     "-d", "--daemon", action="store_true",
53     default=calypso.config.getboolean("server", "daemon"),
54     help="launch as daemon")
55 parser.add_option(
56     "-f", "--foreground", action="store_false", dest="daemon",
57     help="launch in foreground (opposite of --daemon)")
58 parser.add_option(
59     "-H", "--host",
60     default=calypso.config.get("server", "host"),
61     help="set server hostname")
62 parser.add_option(
63     "-p", "--port", type="int",
64     default=calypso.config.getint("server", "port"),
65     help="set server port")
66 parser.add_option(
67     "-s", "--ssl", action="store_true",
68     default=calypso.config.getboolean("server", "ssl"),
69     help="use SSL connection")
70 parser.add_option(
71     "-S", "--no-ssl", action="store_false", dest="ssl",
72     help="do not use SSL connection (opposite of --ssl)")
73 parser.add_option(
74     "-k", "--key",
75     default=calypso.config.get("server", "key"),
76     help="private key file ")
77 parser.add_option(
78     "-c", "--certificate",
79     default=calypso.config.get("server", "certificate"),
80     help="certificate file ")
81 parser.add_option(
82     "-i", "--import", dest="import_dest")
83 parser.add_option(
84     "-g", "--debug", action="store_true",
85     default=False,
86     help="enable debug logging")
87 parser.add_option(
88     "-P", "--pid-file", dest="pidfile",
89     default=calypso.config.get("server", "pidfile"),
90     help="set location of process-id file")
91     
92 (options, args) = parser.parse_args()
93
94 # Update Calypso configuration according to options
95 for option in parser.option_list:
96     key = option.dest
97     if key:
98         value = getattr(options, key)
99         calypso.config.set("server", key, value)
100
101 log = logging.getLogger()
102 ch = logging.StreamHandler()
103
104 # Handle debugging option and log levels
105 if options.debug:
106     log.setLevel(logging.DEBUG)
107     ch.setLevel(logging.DEBUG)
108     logging.basicConfig(level=logging.DEBUG)
109     log.debug("enable debugging")
110 else:
111     log.setLevel(logging.WARN)
112     ch.setLevel(logging.WARN)
113     logging.basicConfig(level=logging.WARN)
114     
115
116 # Run import if requested
117 if options.import_dest:
118     try:
119         collection = webdav.Collection(options.import_dest)
120     except Exception:
121         print "Cannot open collection %s" % options.import_dest
122         sys.exit(1)
123     success = True
124     for arg in args:
125         if not collection.import_file(arg):
126             success = False
127     if success:
128         sys.exit(0)
129     else:
130         sys.exit(1)
131
132 def run_server():
133     try:
134         # Launch server
135         log.debug("Starting HTTP%s server on %s:%d" % ("S" if options.ssl else "",
136                                                        options.host if options.host else "*",
137                                                        options.port))
138         server_class = calypso.HTTPSServer if options.ssl else calypso.HTTPServer
139         server = server_class(
140             (options.host, options.port), calypso.CollectionHTTPHandler)
141         server.serve_forever(poll_interval=10)
142     except KeyboardInterrupt:
143         server.socket.close()
144
145 # If foreground execution is requested, just run the server
146 if not options.daemon:
147     run_server()
148     sys.exit(0)
149
150 # Otherwise, daemonize Calypso
151 context = daemon.DaemonContext()
152 context.umask = 0o002
153 if options.pidfile:
154     from lockfile import pidlockfile
155     # Generate a pidfile where requested
156     context.pidfile = pidlockfile.PIDLockFile(options.pidfile)
157 with context:
158     run_server()
159
160 # vim: set ts=4 sw=4 et si :