~loggerhead-team/loggerhead/trunk-rich

« back to all changes in this revision

Viewing changes to loggerhead/main.py

  • Committer: Jelmer Vernooij
  • Date: 2011-09-08 00:33:28 UTC
  • mfrom: (422.5.2 1.18)
  • mto: This revision was merged to the branch mainline in revision 457.
  • Revision ID: jelmer@samba.org-20110908003328-vu1ps5w21gohws2f
mergeĀ lp:loggerhead/1.18.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
#!/usr/bin/env python
 
1
#
 
2
# Copyright (C) 2008, 2009 Canonical Ltd
 
3
#
2
4
# This program is free software; you can redistribute it and/or modify
3
5
# it under the terms of the GNU General Public License as published by
4
6
# the Free Software Foundation; either version 2 of the License, or
19
21
import os
20
22
import sys
21
23
 
22
 
from optparse import OptionParser
 
24
from bzrlib.plugin import load_plugins
23
25
 
24
26
from paste import httpserver
25
 
from paste.httpexceptions import HTTPExceptionHandler
 
27
from paste.httpexceptions import HTTPExceptionHandler, HTTPInternalServerError
26
28
from paste.translogger import TransLogger
27
29
 
28
30
from loggerhead import __version__
29
 
from loggerhead.apps.filesystem import (
30
 
    BranchesFromFileSystemRoot, UserBranchesFromFileSystemRoot)
 
31
from loggerhead.apps.transport import (
 
32
    BranchesFromTransportRoot, UserBranchesFromTransportRoot)
 
33
from loggerhead.config import LoggerheadConfig
31
34
from loggerhead.util import Reloader
32
35
from loggerhead.apps.error import ErrorHandlerApp
33
36
 
34
37
 
35
 
def command_line_parser():
36
 
    parser = OptionParser("%prog [options] <path>")
37
 
    parser.set_defaults(
38
 
        user_dirs=False,
39
 
        show_version=False,
40
 
        log_folder=None,
41
 
        )
42
 
    parser.add_option("--user-dirs", action="store_true", dest="user_dirs",
43
 
                      help="Serve user directories as ~user.")
44
 
    parser.add_option("--trunk-dir", metavar="DIR",
45
 
                      help="The directory that contains the trunk branches.")
46
 
    parser.add_option("--port", dest="user_port",
47
 
                      help=("Port Loggerhead should listen on "
48
 
                            "(defaults to 8080)."))
49
 
    parser.add_option("--host", dest="user_host",
50
 
                      help="Host Loggerhead should listen on.")
51
 
    parser.add_option("--prefix", dest="user_prefix",
52
 
                      help="Specify host prefix.")
53
 
    parser.add_option("--reload", action="store_true", dest="reload",
54
 
                      help="Restarts the application when changing python"
55
 
                           " files. Only used for development purposes.")
56
 
    parser.add_option('--log-folder', dest="log_folder",
57
 
                      type=str, help="The directory to place log files in.")
58
 
    parser.add_option("--version", action="store_true", dest="show_version",
59
 
                      help="Print the software version and exit")
60
 
    return parser
61
 
 
62
 
 
63
 
def main(args):
64
 
    parser = command_line_parser()
65
 
    (options, args) = parser.parse_args(sys.argv[1:])
66
 
 
67
 
    if options.show_version:
68
 
        print "loggerhead %s" % __version__
 
38
def get_config_and_path(args):
 
39
    config = LoggerheadConfig(args)
 
40
 
 
41
    if config.get_option('show_version'):
 
42
        print "loggerhead %s" % (__version__,)
69
43
        sys.exit(0)
70
44
 
71
 
    if len(args) > 1:
72
 
        parser.print_help()
73
 
        sys.exit(1)
74
 
    elif len(args) == 1:
75
 
        [path] = args
76
 
    else:
77
 
        path = '.'
78
 
 
79
 
    if not os.path.isdir(path):
80
 
        print "%s is not a directory" % path
81
 
        sys.exit(1)
82
 
 
83
 
    if options.trunk_dir and not options.user_dirs:
 
45
    if config.arg_count > 1:
 
46
        config.print_help()
 
47
        sys.exit(1)
 
48
    elif config.arg_count == 1:
 
49
        base = config.get_arg(0)
 
50
    else:
 
51
        base = '.'
 
52
 
 
53
    if not config.get_option('allow_writes'):
 
54
        base = 'readonly+' + base
 
55
 
 
56
    return config, base
 
57
 
 
58
 
 
59
def setup_logging(config, init_logging=True, log_file=None):
 
60
    log_level = config.get_log_level()
 
61
    if init_logging:
 
62
        logging.basicConfig()
 
63
        if log_level is not None:
 
64
            logging.getLogger('').setLevel(log_level)
 
65
    logger = logging.getLogger('loggerhead')
 
66
    if log_level is not None:
 
67
        logger.setLevel(log_level)
 
68
    if log_file is not None:
 
69
        handler = logging.StreamHandler(log_file)
 
70
    else:
 
71
        if config.get_option('log_folder'):
 
72
            logfile_path = os.path.join(
 
73
                config.get_option('log_folder'), 'serve-branches.log')
 
74
        else:
 
75
            logfile_path = 'serve-branches.log'
 
76
        handler = logging.FileHandler(logfile_path, 'a')
 
77
        formatter = logging.Formatter('%(asctime)s %(levelname)-8s %(name)s:'
 
78
                                      ' %(message)s')
 
79
        handler.setFormatter(formatter)
 
80
    # We set the handler to accept all messages, the *logger* won't emit them
 
81
    # if it is configured to suppress it
 
82
    handler.setLevel(logging.DEBUG)
 
83
    logger.addHandler(handler)
 
84
    def _restrict_logging(logger_name):
 
85
        logger = logging.getLogger(logger_name)
 
86
        if logger.getEffectiveLevel() < logging.INFO:
 
87
            logger.setLevel(logging.INFO)
 
88
    # simpleTAL is *very* verbose in DEBUG mode, which is otherwise the
 
89
    # default. So quiet it up a bit.
 
90
    _restrict_logging('simpleTAL')
 
91
    _restrict_logging('simpleTALES')
 
92
    return logger
 
93
 
 
94
 
 
95
def make_app_for_config_and_path(config, base):
 
96
    if config.get_option('trunk_dir') and not config.get_option('user_dirs'):
84
97
        print "--trunk-dir is only valid with --user-dirs"
85
98
        sys.exit(1)
86
99
 
87
 
    if options.reload:
 
100
    if config.get_option('reload'):
88
101
        if Reloader.is_installed():
89
102
            Reloader.install()
90
103
        else:
91
104
            return Reloader.restart_with_reloader()
92
105
 
93
 
    if options.user_dirs:
94
 
        if not options.trunk_dir:
 
106
    if config.get_option('user_dirs'):
 
107
        if not config.get_option('trunk_dir'):
95
108
            print "You didn't specify a directory for the trunk directories."
96
109
            sys.exit(1)
97
 
        app = UserBranchesFromFileSystemRoot(path, options.trunk_dir)
98
 
    else:
99
 
        app = BranchesFromFileSystemRoot(path)
100
 
 
101
 
    # setup_logging()
102
 
    logging.basicConfig()
103
 
    logging.getLogger('').setLevel(logging.DEBUG)
104
 
    logger = getattr(app, 'log', logging.getLogger('loggerhead'))
105
 
    if options.log_folder:
106
 
        logfile_path = os.path.join(options.log_folder, 'serve-branches.log')
107
 
    else:
108
 
        logfile_path = 'serve-branches.log'
109
 
    logfile = logging.FileHandler(logfile_path, 'a')
110
 
    formatter = logging.Formatter('%(asctime)s %(levelname)-8s %(name)s:'
111
 
                                  ' %(message)s')
112
 
    logfile.setFormatter(formatter)
113
 
    logfile.setLevel(logging.DEBUG)
114
 
    logger.addHandler(logfile)
115
 
    # setup_logging() #end
116
 
    app = ErrorHandlerApp(app)
117
 
    app = HTTPExceptionHandler(app)
118
 
    app = TransLogger(app, logger=logger)
119
 
 
120
 
    if not options.user_prefix:
 
110
        app = UserBranchesFromTransportRoot(base, config)
 
111
    else:
 
112
        app = BranchesFromTransportRoot(base, config)
 
113
 
 
114
    setup_logging(config)
 
115
 
 
116
    if config.get_option('profile'):
 
117
        from loggerhead.middleware.profile import LSProfMiddleware
 
118
        app = LSProfMiddleware(app)
 
119
    if config.get_option('memory_profile'):
 
120
        from dozer import Dozer
 
121
        app = Dozer(app)
 
122
 
 
123
    if not config.get_option('user_prefix'):
121
124
        prefix = '/'
122
125
    else:
123
 
        prefix = options.user_prefix
 
126
        prefix = config.get_option('user_prefix')
 
127
        if not prefix.startswith('/'):
 
128
            prefix = '/' + prefix
124
129
 
125
130
    try:
126
131
        from paste.deploy.config import PrefixMiddleware
127
132
    except ImportError:
128
 
        pass
 
133
        cant_proxy_correctly_message = (
 
134
            'Unsupported configuration: PasteDeploy not available, but '
 
135
            'loggerhead appears to be behind a proxy.')
 
136
        def check_not_proxied(app):
 
137
            def wrapped(environ, start_response):
 
138
                if 'HTTP_X_FORWARDED_SERVER' in environ:
 
139
                    exc = HTTPInternalServerError()
 
140
                    exc.explanation = cant_proxy_correctly_message
 
141
                    raise exc
 
142
                return app(environ, start_response)
 
143
            return wrapped
 
144
        app = check_not_proxied(app)
129
145
    else:
130
146
        app = PrefixMiddleware(app, prefix=prefix)
131
147
 
132
 
    if not options.user_port:
 
148
    app = HTTPExceptionHandler(app)
 
149
    app = ErrorHandlerApp(app)
 
150
    app = TransLogger(app, logger=logging.getLogger('loggerhead'))
 
151
 
 
152
    return app
 
153
 
 
154
 
 
155
def main(args):
 
156
    load_plugins()
 
157
 
 
158
    config, path = get_config_and_path(args)
 
159
 
 
160
    app = make_app_for_config_and_path(config, path)
 
161
 
 
162
    if not config.get_option('user_port'):
133
163
        port = '8080'
134
164
    else:
135
 
        port = options.user_port
 
165
        port = config.get_option('user_port')
136
166
 
137
 
    if not options.user_host:
 
167
    if not config.get_option('user_host'):
138
168
        host = '0.0.0.0'
139
169
    else:
140
 
        host = options.user_host
141
 
 
142
 
    httpserver.serve(app, host=host, port=port)
143
 
 
144
 
 
145
 
if __name__ == "__main__":
146
 
    main(sys.argv)
 
170
        host = config.get_option('user_host')
 
171
 
 
172
    if not config.get_option('protocol'):
 
173
        protocol = 'http'
 
174
    else:
 
175
        protocol = config.get_option('protocol')
 
176
 
 
177
    if protocol == 'http':
 
178
        httpserver.serve(app, host=host, port=port)
 
179
    else:
 
180
        if protocol == 'fcgi':
 
181
            from flup.server.fcgi import WSGIServer
 
182
        elif protocol == 'scgi':
 
183
            from flup.server.scgi import WSGIServer
 
184
        elif protocol == 'ajp':
 
185
            from flup.server.ajp import WSGIServer
 
186
        else:
 
187
            print 'Unknown protocol: %s.' % (protocol)
 
188
            sys.exit(1)
 
189
        WSGIServer(app, bindAddress=(host, int(port))).run()