Ejemplo n.º 1
0
def run_in_cp_tree(app, after_start=None):

    cpconfig = {'engine.autoreload.on': False}
    if hasattr(bvconfig, 'host') and bvconfig.host is not None:
        cpconfig['server.socket_host'] = bvconfig.host
    if hasattr(bvconfig, 'port') and bvconfig.port is not None:
        cpconfig['server.socket_port'] = bvconfig.port
    if hasattr(bvconfig, 'log_to_screen'):
        cpconfig['log.screen'] = bvconfig.log_to_screen
    if hasattr(bvconfig, 'log_file') and bvconfig.log_file is not None:
        cpconfig['log.error_file'] = bvconfig.log_file

    cp.config.update(cpconfig)

    if hasattr(bvconfig, 'daemon') and bvconfig.daemon:
        cpconfig['log.screen'] = False
        cp.config.update(cpconfig)
        plugins.Daemonizer(cp.engine).subscribe()
    cp.engine.signals.subscribe()
    if hasattr(bvconfig, 'user') or hasattr(bvconfig, 'group'):
        user = bvconfig.user if hasattr(bvconfig, 'user') else None
        group = bvconfig.group if hasattr(bvconfig, 'group') else None
        plugins.DropPrivileges(cp.engine, uid=user, gid=group).subscribe()
    if hasattr(bvconfig, 'pid_file') and bvconfig.pid_file is not None:
        plugins.PIDFile(cp.engine, bvconfig.pid_file).subscribe()

    cp.tree.graft(app, script_name='/')
    try:
        cp.engine.start()
    except:
        sys.exit(1)
    else:
        if after_start is not None:
            after_start()
        cp.engine.block()
Ejemplo n.º 2
0
    def run(self, daemonize=None, pidfile=None, user=None, group=None):
        engine = cherrypy.engine

        if daemonize:
            # Don't print anything to stdout/sterr.
            cherrypy.config.update({'log.screen': False})
            plugins.Daemonizer(engine).subscribe()

        if pidfile:
            plugins.PIDFile(engine, pidfile).subscribe()

        if user or group:
            plugins.DropPrivileges(engine, uid=user, gid=group).subscribe()

        if hasattr(engine, "signal_handler"):
            engine.signal_handler.subscribe()
        if hasattr(engine, "console_control_handler"):
            engine.console_control_handler.subscribe()

        # Always start the engine; this will start all other services
        try:
            engine.start()
        except:
            # Assume the error has been logged already via bus.log.
            sys.exit(1)
        else:
            engine.block()
Ejemplo n.º 3
0
def main():
    """ Main function. """

    # default config
    cherrypy.config.update({
        'uid': 0,
        'gid': 0,
        'server_name': 'localhost',
        'genshi.template_dir': os.path.join(install_dir, 'templates'),
        'daemonize': False,
        'pidfile': None,
        'host': 'localhost',
        'file_host': 'localhost',
        })

    cherrypy.config.update(CHERRYPY_CONFIG)

    extra_config = ''
    for config_filename in LOCAL_CONFIG:
        try:
            cherrypy.config.update(config_filename)
            extra_config = config_filename
            break
        except IOError:
            pass

    # Rotating Logs
    # CherryPy will already open log files if present in config
    error_file = access_file = ''
    # read the logger file locations from config file.
    if not cherrypy.log.error_file:
        error_file = cherrypy.config.get('logger.error_file', '')
    if not cherrypy.log.access_file:
        access_file = cherrypy.config.get('logger.access_file', '')

    # disable log file handlers
    cherrypy.log.error_file = ""
    cherrypy.log.access_file = ""

    # set up python logging
    max_bytes = getattr(cherrypy.log, "rot_max_bytes", 100 * 1024 * 1024)
    backup_count = getattr(cherrypy.log, "rot_backup_count", 2)

    if error_file:
        h = logging.handlers.RotatingFileHandler(error_file, 'a', max_bytes, backup_count, 'utf-8')
        h.setLevel(logging.INFO)
        h.setFormatter(cherrypy._cplogging.logfmt)
        cherrypy.log.error_log.addHandler(h)

    if access_file:
        h = logging.handlers.RotatingFileHandler(access_file, 'a', max_bytes, backup_count, 'utf-8')
        h.setLevel(logging.INFO)
        h.setFormatter(cherrypy._cplogging.logfmt)
        cherrypy.log.access_log.addHandler(h)



    if not cherrypy.config['daemonize']:
        ch = logging.StreamHandler()
        ch.setLevel(logging.DEBUG)
        ch.setFormatter(cherrypy._cplogging.logfmt)
        cherrypy.log.error_log.addHandler(ch)

    # continue app init
    #

    cherrypy.log('*' * 80, context='ENGINE', severity=logging.INFO)
    cherrypy.log("Using config file '%s'." % CHERRYPY_CONFIG,
                  context='ENGINE', severity=logging.INFO)
    if extra_config:
        cherrypy.log('extra_config: %s' % extra_config, context='ENGINE', severity=logging.INFO)

    # after cherrypy.config is parsed
    Formatters.init()
    cherrypy.log("Continuing App Init", context='ENGINE', severity=logging.INFO)

    cherrypy.log("Continuing App Init", context='ENGINE', severity=logging.INFO)
    cherrypy.tools.I18nTool = i18n_tool.I18nTool()

    cherrypy.log("Continuing App Init", context='ENGINE', severity=logging.INFO)

    # Used to bust the cache on js and css files.  This should be the
    # files' mtime, but the files are not stored on the app server.
    # This is a `good enough´ replacement though.
    t = str(int(time.time()))
    cherrypy.config['css_mtime'] = t
    cherrypy.config['js_mtime']  = t

    cherrypy.config['all_hosts'] = (
        cherrypy.config['host'], cherrypy.config['file_host'])
    
    cherrypy.config.update({'error_page.404': error_page_404})

    if hasattr(cherrypy.engine, 'signal_handler'):
        cherrypy.engine.signal_handler.subscribe()

    GutenbergDatabase.options.update(cherrypy.config)
    cherrypy.engine.pool = plugins.ConnectionPool(
        cherrypy.engine, params=GutenbergDatabase.get_connection_params(cherrypy.config))
    cherrypy.engine.pool.subscribe()

    plugins.Timer(cherrypy.engine).subscribe()

    cherrypy.log("Daemonizing", context='ENGINE', severity=logging.INFO)

    if cherrypy.config['daemonize']:
        plugins.Daemonizer(cherrypy.engine).subscribe()

    uid = cherrypy.config['uid']
    gid = cherrypy.config['gid']
    if uid > 0 or gid > 0:
        plugins.DropPrivileges(cherrypy.engine, uid=uid, gid=gid, umask=0o22).subscribe()

    if cherrypy.config['pidfile']:
        pid = plugins.PIDFile(cherrypy.engine, cherrypy.config['pidfile'])
        # Write pidfile after privileges are dropped(prio == 77)
        # or we will not be able to remove it.
        cherrypy.engine.subscribe('start', pid.start, 78)
        cherrypy.engine.subscribe('exit', pid.exit, 78)


    cherrypy.log("Setting up routes", context='ENGINE', severity=logging.INFO)

    # setup 'routes' dispatcher
    #
    # d = cherrypy.dispatch.RoutesDispatcher(full_result=True)
    d = MyRoutesDispatcher(full_result=True)
    cherrypy.routes_mapper = d.mapper

    def check_id(environ, result):
        """ Check if id is a valid number. """
        try:
            return str(int(result['id'])) == result['id']
        except:
            return False

    d.connect('start', r'/ebooks{.format}/',
               controller=StartPage.Start())

    d.connect('suggest', r'/ebooks/suggest{.format}/',
               controller=SuggestionsPage.Suggestions())

    # search pages

    d.connect('search', r'/ebooks/search{.format}/',
               controller=BookSearchPage())

    d.connect('author_search', r'/ebooks/authors/search{.format}/',
               controller=AuthorSearchPage())

    d.connect('subject_search', r'/ebooks/subjects/search{.format}/',
               controller=SubjectSearchPage())

    d.connect('bookshelf_search', r'/ebooks/bookshelves/search{.format}/',
               controller=BookshelfSearchPage())

    # 'id' pages

    d.connect('author', r'/ebooks/author/{id:\d+}{.format}',
               controller=AuthorPage(), conditions=dict(function=check_id))

    d.connect('subject', r'/ebooks/subject/{id:\d+}{.format}',
               controller=SubjectPage(), conditions=dict(function=check_id))

    d.connect('bookshelf', r'/ebooks/bookshelf/{id:\d+}{.format}',
               controller=BookshelfPage(), conditions=dict(function=check_id))

    d.connect('also', r'/ebooks/{id:\d+}/also/{.format}',
               controller=AlsoDownloadedPage(), conditions=dict(function=check_id))

    # bibrec pages

    d.connect('download', r'/ebooks/{id:\d+}/download{.format}',
               controller=Page.NullPage(), _static=True)

    d.connect('bibrec', r'/ebooks/{id:\d+}{.format}',
               controller=BibrecPage(), conditions=dict(function=check_id))


    # legacy compatibility with /ebooks/123.bibrec
    d.connect('bibrec2', r'/ebooks/{id:\d+}.bibrec{.format}',
               controller=BibrecPage(), conditions=dict(function=check_id))

    d.connect('cover', r'/covers/{size:small|medium}/{order:latest|popular}/{count}',
               controller=CoverPages.CoverPages())

    d.connect('qrcode', r'/qrcode/',
               controller=QRCodePage.QRCodePage())

    d.connect('iplimit', r'/iplimit/',
               controller=Page.NullPage())

    d.connect('diagnostics', r'/diagnostics/',
               controller=diagnostics.DiagnosticsPage())

    d.connect('stats', r'/stats/',
               controller=Page.NullPage(), _static=True)

    d.connect('honeypot_send', r'/ebooks/send/megaupload/{id:\d+}.{filetype}',
               controller=Page.NullPage(), _static=True)

    # /w/captcha/question/ so varnish will cache it
    d.connect('captcha.question', r'/w/captcha/question/',
               controller=Page.GoHomePage())

    d.connect('captcha.answer', r'/w/captcha/answer/',
               controller=Page.GoHomePage())

    # sitemap protocol access control requires us to place sitemaps in /ebooks/
    d.connect('sitemap', r'/ebooks/sitemaps/',
               controller=Sitemap.SitemapIndex())

    d.connect('sitemap_index', r'/ebooks/sitemaps/{page:\d+}',
               controller=Sitemap.Sitemap())

    if 'dropbox_client_id' in cherrypy.config:
        import Dropbox
        dropbox = Dropbox.Dropbox()
        cherrypy.log("Dropbox Client Id: %s" % cherrypy.config['dropbox_client_id'],
                      context='ENGINE', severity=logging.INFO)
        d.connect('dropbox_send', r'/ebooks/send/dropbox/{id:\d+}.{filetype}',
                   controller=dropbox, conditions=dict(function=check_id))
        d.connect('dropbox_callback', r'/ebooks/send/dropbox/',
                   controller=dropbox)

    if 'gdrive_client_id' in cherrypy.config:
        import GDrive
        gdrive = GDrive.GDrive()
        cherrypy.log("GDrive Client Id: %s" % cherrypy.config['gdrive_client_id'],
                      context='ENGINE', severity=logging.INFO)
        d.connect('gdrive_send', r'/ebooks/send/gdrive/{id:\d+}.{filetype}',
                   controller=gdrive, conditions=dict(function=check_id))
        d.connect('gdrive_callback', r'/ebooks/send/gdrive/',
                   controller=gdrive)

    if 'msdrive_client_id' in cherrypy.config:
        import MSDrive
        msdrive = MSDrive.MSDrive()
        cherrypy.log("MSDrive Client Id: %s" % cherrypy.config['msdrive_client_id'],
                      context='ENGINE', severity=logging.INFO)
        d.connect('msdrive_send', r'/ebooks/send/msdrive/{id:\d+}.{filetype}',
                   controller=msdrive, conditions=dict(function=check_id))
        d.connect('msdrive_callback', r'/ebooks/send/msdrive/',
                   controller=msdrive)

    # start http server
    #

    cherrypy.log("Mounting root", context='ENGINE', severity=logging.INFO)

    app = cherrypy.tree.mount(root=None, config=CHERRYPY_CONFIG)

    app.merge({'/': {'request.dispatch': d}})
    return app
Ejemplo n.º 4
0
def run():
    MEDIA_DIR = os.path.join(DATADIR, 'Pellmonweb', 'media')
    argparser = argparse.ArgumentParser(prog='pellmonweb')
    argparser.add_argument('-D',
                           '--DAEMONIZE',
                           action='store_true',
                           help='Run as daemon')
    argparser.add_argument('-P',
                           '--PIDFILE',
                           default='/tmp/pellmonweb.pid',
                           help='Full path to pidfile')
    argparser.add_argument('-U', '--USER', help='Run as USER')
    argparser.add_argument('-G',
                           '--GROUP',
                           default='nogroup',
                           help='Run as GROUP')
    argparser.add_argument('-C',
                           '--CONFIG',
                           default='pellmon.conf',
                           help='Full path to config file')
    argparser.add_argument('-d',
                           '--DBUS',
                           default='SESSION',
                           choices=['SESSION', 'SYSTEM'],
                           help='which bus to use, SESSION is default')
    argparser.add_argument('-V',
                           '--version',
                           action='version',
                           version='%(prog)s version ' + __version__)
    args = argparser.parse_args()

    global dbus
    dbus = Dbus_handler(args.DBUS)

    #Look for temlates in this directory
    global lookup
    lookup = myLookup(
        directories=[os.path.join(DATADIR, 'Pellmonweb', 'html')], dbus=dbus)

    config_file = args.CONFIG

    pidfile = args.PIDFILE
    if pidfile:
        plugins.PIDFile(cherrypy.engine, pidfile).subscribe()

    if args.USER:

        config_file = os.path.join(CONFDIR, 'pellmon.conf')

        try:
            parser.read(config_file)
        except:
            cherrypy.log("can not parse config file")
            sys.exit(1)
        try:
            config_dir = parser.get('conf', 'config_dir')
            walk_config_dir(config_dir, parser)
        except ConfigParser.NoOptionError:
            pass

        try:
            accesslog = parser.get('weblog', 'accesslog')
            logdir = os.path.dirname(accesslog)
            if not os.path.isdir(logdir):
                os.mkdir(logdir)
            uid = pwd.getpwnam(args.USER).pw_uid
            gid = grp.getgrnam(args.GROUP).gr_gid
            os.chown(logdir, uid, gid)
            if os.path.isfile(accesslog):
                os.chown(accesslog, uid, gid)
        except:
            pass
        try:
            errorlog = parser.get('weblog', 'errorlog')
            logdir = os.path.dirname(errorlog)
            if not os.path.isdir(logdir):
                os.mkdir(logdir)
            uid = pwd.getpwnam(args.USER).pw_uid
            gid = grp.getgrnam(args.GROUP).gr_gid
            os.chown(logdir, uid, gid)
            if os.path.isfile(errorlog):
                os.chown(errorlog, uid, gid)
        except:
            pass
        uid = pwd.getpwnam(args.USER).pw_uid
        gid = grp.getgrnam(args.GROUP).gr_gid
        plugins.DropPrivileges(cherrypy.engine, uid=uid, gid=gid,
                               umask=033).subscribe()

    # Load the configuration file
    try:
        parser.read(config_file)
        config_dir = parser.get('conf', 'config_dir')
        walk_config_dir(config_dir, parser)
    except ConfigParser.NoOptionError:
        pass
    except ConfigParser.NoSectionError:
        cherrypy.log("can not parse config file")
    except:
        cherrypy.log("Config file not found")

    # The RRD database, updated by pellMon
    global polling, db
    try:
        polling = True
        db = parser.get('conf', 'database')
        graph_file = os.path.join(os.path.dirname(db), 'graph.png')
    except:
        polling = False
        db = ''

    # the colors to use when drawing the graph
    global colorsDict
    try:
        colors = parser.items('graphcolors')
        colorsDict = {}
        for key, value in colors:
            colorsDict[key] = value
    except:
        colorsDict = {}

    # Get the names of the polled data
    global polldata
    try:
        polldata = parser.items("pollvalues")
        # Get the names of the polled data
        rrd_ds_names = parser.items("rrd_ds_names")
        ds_names = {}
        for key, value in rrd_ds_names:
            ds_names[key] = value
    except:
        ds_names = {}
        polldata = []

    try:
        # Get the optional scales
        scales = parser.items("scaling")
        scale_data = {}
        for key, value in scales:
            scale_data[key] = value
    except:
        scale_data = {}

    global graph_lines
    graph_lines = []
    global logtick
    logtick = None
    for key, value in polldata:
        if key in colorsDict and key in ds_names:
            graph_lines.append({
                'name': value,
                'color': colorsDict[key],
                'ds_name': ds_names[key]
            })
            if key in scale_data:
                graph_lines[-1]['scale'] = scale_data[key]
        if value == '_logtick' and key in ds_names:
            logtick = ds_names[key]

    global credentials
    try:
        credentials = parser.items('authentication')
    except:
        credentials = [('testuser', '12345')]

    global logfile
    try:
        logfile = parser.get('conf', 'logfile')
    except:
        logfile = None

    try:
        webroot = parser.get('conf', 'webroot')
    except:
        webroot = '/'

    global system_image
    try:
        system_image = os.path.join(os.path.join(MEDIA_DIR, 'img'),
                                    parser.get('conf', 'system_image'))
    except:
        system_image = os.path.join(MEDIA_DIR, 'img/system.svg')

    global frontpage_widgets
    frontpage_widgets = []
    try:
        for row, widgets in parser.items('frontpage_widgets'):
            frontpage_widgets.append([s.strip() for s in widgets.split(',')])
    except ConfigParser.NoSectionError:
        frontpage_widgets = [['systemimage', 'events'], ['graph'],
                             ['consumption7d', 'silolevel']]

    global timeChoices
    timeChoices = ['time1h', 'time3h', 'time8h', 'time24h', 'time3d', 'time1w']
    global timeNames
    timeNames = [
        t.replace(' ', ' ') for t in
        ['1 hour', '3 hours', '8 hours', '24 hours', '3 days', '1 week']
    ]
    global timeSeconds
    timeSeconds = [
        3600, 3600 * 3, 3600 * 8, 3600 * 24, 3600 * 24 * 3, 3600 * 24 * 7
    ]
    ft = False
    fc = False
    for a, b in polldata:
        if b == 'feeder_capacity':
            fc = True
        if b == 'feeder_time':
            ft = True
    if fc and ft:
        consumption_graph = True
        consumption_file = os.path.join(os.path.dirname(db), 'consumption.png')
    else:
        consumption_graph = False
    if websockets:
        #make sure WebSocketPlugin runs after daemonizer plugin (priority 65)
        #see cherrypy plugin documentation for default plugin priorities
        WebSocketPlugin.start.__func__.priority = 66
        WebSocketPlugin(cherrypy.engine).subscribe()
        cherrypy.tools.websocket = WebSocketTool()
    try:
        port = int(parser.get('conf', 'port'))
    except:
        port = 8081

    global_conf = {
            'global':   { #w'server.environment': 'debug',
                          'tools.sessions.on' : True,
                          'tools.sessions.timeout': 7200,
                          'tools.auth.on': True,
                          'server.socket_host': '0.0.0.0',
                          'server.socket_port': port,

                          #'engine.autoreload.on': False,
                          #'checker.on': False,
                          #'tools.log_headers.on': False,
                          #'request.show_tracebacks': False,
                          'request.show_mismatched_params': False,
                          #'log.screen': False,
                          'engine.SIGHUP': None,
                          'engine.SIGTERM': None,

                        }
                  }
    app_conf = {
        '/media': {
            'tools.staticdir.on': True,
            'tools.staticdir.dir': MEDIA_DIR
        },
    }

    if websockets:
        ws_conf = {
            '/ws': {
                'tools.websocket.on': True,
                'tools.websocket.handler_cls': WebSocket
            }
        }

    current_dir = os.path.dirname(os.path.abspath(__file__))
    cherrypy.config.update(global_conf)

    # Only daemonize if asked to.
    if args.DAEMONIZE:
        # Don't print anything to stdout/sterr.
        cherrypy.config.update({
            'log.screen': False,
            'engine.autoreload.on': False
        })
        plugins.Daemonizer(cherrypy.engine).subscribe()

    cherrypy.tree.mount(PellMonWeb(), webroot, config=app_conf)
    if websockets:
        cherrypy.tree.mount(WsHandler(),
                            os.path.join(webroot, 'websocket'),
                            config=ws_conf)

    try:
        cherrypy.config.update({'log.access_file': accesslog})
    except:
        pass
    try:
        cherrypy.config.update({'log.error_file': errorlog})
    except:
        pass

    GObject.threads_init()

    # Always start the engine; this will start all other services
    try:
        cherrypy.engine.start()
    except:
        # Assume the error has been logged already via bus.log.
        sys.exit(1)
    else:
        # Needed to be able to use threads with a glib main loop running

        # A main loop is needed for dbus "name watching" to work
        main_loop = GLib.MainLoop()

        # cherrypy has it's own mainloop, cherrypy.engine.block, that
        # regularly calls engine.publish every 100ms. The most reliable
        # way to run dbus and cherrypy together seems to be to use the
        # glib mainloop for both, ie call engine.publish from the glib
        # mainloop instead of calling engine.block.
        def publish():
            try:
                cherrypy.engine.publish('main')
                if cherrypy.engine.execv:
                    main_loop.quit()
                    cherrypy.engine._do_execv()
            except KeyboardInterrupt:
                pass
            return True

        # Use our own signal handler to stop on ctrl-c, seems to be simpler
        # than subscribing to cherrypy's signal handler
        def signal_handler(signal, frame):
            cherrypy.engine.exit()
            main_loop.quit()

        signal.signal(signal.SIGINT, signal_handler)

        # Handle cherrypy's main loop needs from here
        GLib.timeout_add(100, publish)

        dbus.start()
        try:
            main_loop.run()
        except KeyboardInterrupt:
            pass
Ejemplo n.º 5
0
def start(cgi=False,
          config=None,
          daemon=False,
          debug=False,
          environment=None,
          fastcgi=False,
          gid=None,
          imports=None,
          logs=None,
          path=None,
          pidfile=None,
          quiet=False,
          scgi=False,
          uid=None):
    """Subscribe all engine plugins and start the engine."""

    # Insert paths to the search path
    for p in path or []:
        sys.path.insert(0, p)

    # Import requested modules
    for i in imports or []:
        exec('import %s' % i)

    # SQLAlchemy plugin
    from bdosoa.cherrypy.plugin import SQLAlchemyPlugin
    SQLAlchemyPlugin(cherrypy.engine).subscribe()

    # SQLAlchemy tool
    from bdosoa.cherrypy.tool import SQLAlchemyTool
    cherrypy.tools.sqlalchemy = SQLAlchemyTool()

    # Root App
    from bdosoa.app import App
    root_app = cherrypy.tree.mount(App)

    # Merge configuration files
    for c in config or []:
        cherrypy.config.update(c)

        # If there's only one app mounted, merge config into it.
        if len(cherrypy.tree.apps) == 1:
            for app in cherrypy.tree.apps.values():
                if isinstance(app, cherrypy.Application):
                    app.merge(c)

        # Else merge to the root app
        else:
            root_app.merge(c)

    # Set CherryPy environment
    if environment is not None:
        cherrypy.config.update({'environment': environment})

    # Only daemonize if asked to.
    if daemon:
        # Don't print anything to stdout/sterr.
        cherrypy.config.update({'log.screen': False})
        plugins.Daemonizer(cherrypy.engine).subscribe()

    # Write PID file
    if pidfile:
        plugins.PIDFile(cherrypy.engine, pidfile).subscribe()

    # Drop privileges
    if gid or uid:

        try:
            gid = int(gid) if gid else None
        except ValueError:
            # Get the gid from the group name
            import grp
            gid = grp.getgrnam(gid).gr_gid

        try:
            uid = int(uid) if uid else None
        except ValueError:
            # Get the uid from the user name
            import pwd
            uid = pwd.getpwnam(uid).pw_uid

        plugins.DropPrivileges(cherrypy.engine, uid=uid, gid=gid).subscribe()

    # Handle OS signals
    cherrypy.engine.signals.subscribe()

    # Start a *cgi server instead of the default HTTP server
    if (fastcgi and (scgi or cgi)) or (scgi and cgi):
        cherrypy.log.error(
            'You may only specify one of the cgi, fastcgi, and scgi options.',
            'ENGINE')
        sys.exit(1)

    if fastcgi or scgi or cgi:
        # Turn off autoreload when using *cgi.
        cherrypy.config.update({'engine.autoreload.on': False})

        # Turn off the default HTTP server (which is subscribed by default).
        cherrypy.server.unsubscribe()

        if fastcgi:
            httpserver = servers.FlupFCGIServer(
                application=cherrypy.tree,
                bindAddress=cherrypy.server.bind_addr)
        elif scgi:
            httpserver = servers.FlupSCGIServer(
                application=cherrypy.tree,
                bindAddress=cherrypy.server.bind_addr)
        else:
            httpserver = servers.FlupCGIServer(application=cherrypy.tree)

        cherrypy.server = servers.ServerAdapter(cherrypy.engine, httpserver,
                                                cherrypy.server.bind_addr)
        cherrypy.server.subscribe()

    # Set logging level
    if debug and quiet:
        cherrypy.log.error(
            'You may only specify one of the debug, quiet options',
            'ENGINE',
            severity=50)
        sys.exit(1)

    if debug:
        cherrypy.log.error_log.setLevel(10)
    elif quiet:
        cherrypy.log.error_log.setLevel(30)

    # Setup logging for other modules
    for name in logs or []:

        # Get CherryPy builtin handlers
        cherrypy_log_handlers = [
            cherrypy.log._get_builtin_handler(cherrypy.log.error_log, h)
            for h in ['screen', 'file', 'wsgi']
        ]

        # Create logger for the module
        logger = getLogger(name)
        logger.setLevel(cherrypy.log.error_log.getEffectiveLevel())

        for handler in cherrypy_log_handlers:
            if handler is not None:
                logger.addHandler(handler)

    # Always start the engine; this will start all other services
    try:
        cherrypy.engine.start()
    except:
        # Assume the error has been logged already via bus.log.
        sys.exit(1)
    else:
        cherrypy.engine.block()