]> git.llucax.com Git - software/pymin.git/blobdiff - pymind
Hack to overcome Python's bug 3136 in logging system (refs #7).
[software/pymin.git] / pymind
diff --git a/pymind b/pymind
index 29d296bd2f5ec06fd862c31457e2eb2014aa5603..fa4fa36f5c9d5b537704bec3c1b996d8d35bab3e 100755 (executable)
--- a/pymind
+++ b/pymind
@@ -1,14 +1,10 @@
 #!/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 logging, logging.config ; log = logging.getLogger('pymind')
+# default logging configuration
+# (this is used before the user configuration file gets parsed)
+logging.basicConfig(format='%(levelname)s: %(message)s')
 
 import os
 import sys
@@ -35,6 +31,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 +66,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"),
@@ -70,38 +76,39 @@ options.init('pymind', 'Pymin daemon global options', [
 ])
 
 
-# FIXME
-try:
-    f = file("/proc/sys/net/ipv4/ip_forward","w")
-    f.write("1")
-    f.close()
-except (IOError, OSError), e:
-    log.warning("Can't set ip_forward: %s", e)
+# FIXME: move to IpHandler or someplace else
+def activate_ip_forward():
+    try:
+        f = file("/proc/sys/net/ipv4/ip_forward","w")
+        f.write("1")
+        f.close()
+    except (IOError, OSError), e:
+        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)
 
 
@@ -125,13 +132,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()