durusmail: quixote-users: start-twistedweb.py script for Dulcinea
start-twistedweb.py script for Dulcinea
2004-07-31
start-twistedweb.py script for Dulcinea
Matt Campbell
2004-07-31
I've written a script called start-twistedweb.py which uses the twscgi
module I posted earlier to run an SCGI-enabled Twisted Web server.  It's
intended to be a drop-in replacement for Dulcinea's start-apache.py
script (in fact, I used start-apache.py as a starting point).  The
script is attached.  The changes to the site script are fairly
straightforward, so I won't include my copy of that script.  The
simplest way to do it is to replace all instances of "apache" in the
site script with "twistedweb".  It would be cool if the choice of web
server was configurable, but I'll leave that as an exercise for someone
else.  Twisted Web is good enough for me.

--
Matt Campbell
Lead Programmer
Serotek Corporation
www.freedombox.info

#!/www/python/bin/python

"""$URL: svn+ssh://svn.mems-exchange.org/repos/trunk/dulcinea/bin/start-
apache.py $
$Id: start-apache.py 24724 2004-07-19 20:44:05Z dbinger $

Script invoked by site command to start Twisted Web.
"""

import os
from dulcinea import site_util
from scgi import twscgi
from twisted.internet import reactor, ssl
from twisted.python import log
from twisted.web import server, static

config = site_util.get_config()
sites_directory = config.defaults().get('sites-directory')

def common (site, root):
    scgi_address = config.get(site, 'scgi-address')
    if scgi_address:
        scgi_host, scgi_port = site_util.parse_address(scgi_address)
        scgi_port = int(scgi_port)
        scgi_res = twscgi.SCGIResource(scgi_host, scgi_port)
        exports = list(site_util.get_root_exports(site))
        if '_q_index' in exports: # dynamic root
            exports.append('')
        for export in exports:
            root.putChild(export, scgi_res)


is_live = site_util.any_live_sites()
is_staging = site_util.any_staging_sites()
assert not (is_live and is_staging)

for site in site_util.list_sites():
    if not config.has_option(site, 'http-address'):
        continue
    if (is_live and not site_util.is_live(site)):
        # In live mode, skip sections that aren't live
        continue
    if (is_staging and not site_util.is_staging(site)):
        # In staging mode, skip sections that aren't staging
        continue

    docroot = '%s/%s/docroot' % (sites_directory, site)
    if not os.path.exists(docroot):
        raise SystemExit, 'docroot directory %r does not exist' % docroot
    root = static.File(docroot)
    common(site, root)
    factory = server.Site(root)
    addr = config.get(site, 'http-address')
    addr_ssl = config.get(site, 'https-address')
    host, port = site_util.parse_address(addr)
    port = int(port)
    reactor.listenTCP(port, factory, interface=host)

    if addr_ssl:
        host_ssl, port_ssl = site_util.parse_address(addr_ssl)
        port_ssl = int(port_ssl)
        ssl_cert = config.get(site, 'ssl-certificate')
        ssl_cert_key = ssl_cert.replace('.crt', '.key')
        ctx_factory = ssl.DefaultOpenSSLContextFactory(ssl_cert_key, ssl_cert)
        reactor.listenSSL(port_ssl, factory, ctx_factory, interface=host_ssl)

site_util.ensure_uid_gid_not_root()
pid_file_name = site_util.get_pid_file_name('twistedweb')
log_directory = config.defaults().get("log-directory")
log_file_name = os.path.join(log_directory, "twistedweb.log")
log.startLogging(open(log_file_name, "a")) # TODO: log rotation?
pid = os.fork()
if pid == 0:
    os.setsid()
    try:
        reactor.run()
    finally:
        try:
            os.remove(pid_file_name)
        except OSError:
            pass
else:
    pidfile = open(pid_file_name, "w")
    pidfile.write(str(pid))
    pidfile.close()
reply