X-Git-Url: https://git.llucax.com/software/pymin.git/blobdiff_plain/70f8e4029ac29abefcac22618984d27dc60bb559..875ef9a6250b27228ea7e8f0a02b9d6679de3e07:/pymind diff --git a/pymind b/pymind index 7922afa..78939f0 100755 --- a/pymind +++ b/pymind @@ -1,19 +1,21 @@ #!/usr/bin/env python # vim: set encoding=utf-8 et sw=4 sts=4 : -import logging ; log = logging.getLogger('pymind') -# First of all, we need to setup the logging framework -# FIXME: this should go in a configuration file -logging.basicConfig( - level = logging.DEBUG, - format = '%(asctime)s %(name)-24s %(levelname)-8s %(message)s', - datefmt = '%a, %d %b %Y %H:%M:%S', -) - import os import sys from formencode import Invalid, validators as V +import logging, logging.config ; log = logging.getLogger('pymind') +# default logging configuration +# (this is used before the user configuration file gets parsed) +try: + # first we try to load a log config file + default = '/etc/pymin/log.init.ini' + logging.config.fileConfig(os.getenv('PYMIND_LOGINITCONF', default)) +except: + # then we try to load a reasonable default + logging.basicConfig(format='%(levelname)s: %(message)s') + from pymin.config import OptionGroup, Option, ConfigOption, ListOption from pymin.config import load_config, options from pymin.config import ConfigError, MissingSectionHeaderError, ParsingError @@ -35,6 +37,14 @@ config_file_paths = [ os.path.expanduser('~/.pymin/pymin.ini'), ] +# default locations where to look for the log configuration file +# all found files will be processed, overriding the previous configuration +# files values. +log_file_paths = [ + '/etc/pymin/log.ini', + os.path.expanduser('~/.pymin/log.ini'), +] + # default locations where to look for service plug-ins # search stops when a service plug-in is found services_paths = [ @@ -62,6 +72,8 @@ options.init('pymind', 'Pymin daemon global options', [ metavar='SERVICE', help="manage service SERVICE"), ListOption('services_dirs', V.String, 'd', default=[], metavar='DIR', help="search for services in DIR"), + ListOption('log_config_files', V.String, 'l', default=log_file_paths, + metavar='FILE', help="load log configuration FILE"), ConfigOption('config_file', 'c', metavar='FILE', help="load the configuration file FILE after the default " "configuration files"), @@ -80,29 +92,29 @@ def activate_ip_forward(): log.warning("Can't set ip_forward: %s", e) +def die(status, msg, *args): + log.critical(msg, *args) + logging.shutdown() + sys.exit(status) + def get_config(paths, version, desc, add_options, defaults): global config_file_paths try: (config, args) = load_config(paths, version, desc, add_options, defaults) except ConfigError, e: - log.error(str(e)) - sys.exit(EXIT_CONFIG_ERROR) + die(EXIT_CONFIG_ERROR, str(e)) except MissingSectionHeaderError, e: - log.error("%s:%s: missing section header near: %s", e.filename, e.lineno, - e.line) - sys.exit(EXIT_CONFIG_ERROR) + dir(EXIT_CONFIG_ERROR, "%s:%s: missing section header near: %s", + e.filename, e.lineno, e.line) except ParsingError, e: for (lineno, line) in e.errors: - log.error("%s:%s: invalid syntax near: %s", e.filename, lineno, line) - log.error(str(e.errors)) - sys.exit(EXIT_CONFIG_ERROR) + log.critical("%s:%s: invalid syntax near: %s", e.filename, lineno, line) + die(EXIT_CONFIG_ERROR, str(e.errors)) except Invalid, e: - log.error(str(e.unpack_errors())) - sys.exit(EXIT_CONFIG_ERROR) + die(EXIT_CONFIG_ERROR, str(e.unpack_errors())) except LoadError, e: - log.error("service '%s' not found (see option --services-dir)", - e.service_name) - sys.exit(EXIT_NO_SERVICE) + die(EXIT_NO_SERVICE, "service '%s' not found (see option " \ + "--services-dir)", e.service_name) return (config, args) @@ -126,14 +138,40 @@ def build_root(config, args, services): return root +def setup_logging(config_files): + # XXX: this is a hack for re-enabling loggers not configured via + # fileConfig(). This function disable all existing loggers that + # has no configuration specified in the config file, so we have + # to re-enable the by hand. + # See Python bug 3136: http://bugs.python.org/issue3136 + existing = logging.root.manager.loggerDict.keys() + loaded_files = 0 + for f in config_files: + try: + f = open(f) + except Exception, e: + log.info("config file '%s' can't be readed (%s)", f, e) + continue + logging.config.fileConfig(f) + f.close() + loaded_files += 1 + if not loaded_files: + log.warning('no log config file loaded') + # XXX: finish the hack commented above + for log in existing: + logging.root.manager.loggerDict[log].disabled = 0 + + def main(): services = Services() (config, args) = get_config(config_file_paths, '%prog 0.1', 'Router services administration daemon', services.add_config_options, config_defaults) + setup_logging(config.log_config_files) root_handler = build_root(config, args, services.services) activate_ip_forward() PyminDaemon(root_handler, (config.bind_addr, config.bind_port)).run() + logging.shutdown() if __name__ == '__main__': main()