2 # vim: set encoding=utf-8 et sw=4 sts=4 :
4 import logging ; log = logging.getLogger('pymind')
5 # First of all, we need to setup the logging framework
6 # FIXME: this should go in a configuration file
9 format = '%(asctime)s %(name)-24s %(levelname)-8s %(message)s',
10 datefmt = '%a, %d %b %Y %H:%M:%S',
15 from formencode import Invalid, validators as V
17 from pymin.config import OptionGroup, Option, ConfigOption, ListOption
18 from pymin.config import load_config, options
19 from pymin.config import ConfigError, MissingSectionHeaderError, ParsingError
20 from pymin.dispatcher import Handler
21 from pymin.pymindaemon import PyminDaemon
22 from pymin.service import load_service, LoadError
24 # exit status (1 is reserved for command-line errors)
28 # default locations where to look for configuration files
29 # all found files will be processed, overriding the previous configuration
33 '/etc/pymin/pymin.ini',
34 os.path.expanduser('~/.pymin.ini'),
35 os.path.expanduser('~/.pymin/pymin.ini'),
38 # default locations where to look for service plug-ins
39 # search stops when a service plug-in is found
41 os.path.expanduser('~/.pymin/services'),
42 '/usr/share/pymin/services',
45 # default configuration variables
46 # these are useful variables to help the user writing the configuration file
48 'pymind-data-dir': '/var/lib/pymin',
49 'pymind-pickle-dir': '/var/lib/pymin/pickle',
50 'pymind-config-dir': '/var/lib/pymin/config',
53 # Validator to check if is a valid Python identifier
54 PythonIdentifier = V.Regex(r'^[a-zA-Z_]\w*$')
56 options.init('pymind', 'Pymin daemon global options', [
57 Option('bind_addr', V.CIDR, 'a', default='127.0.0.1', metavar='ADDR',
58 help='Bind to IP ADDR'),
59 Option('bind_port', V.Int(min=1, max=65535), 'p', default=9999,
60 metavar='PORT', help="Bind to port PORT"),
61 ListOption('services', PythonIdentifier, 's', default=[],
62 metavar='SERVICE', help="manage service SERVICE"),
63 ListOption('services_dirs', V.String, 'd', default=[],
64 metavar='DIR', help="search for services in DIR"),
65 ConfigOption('config_file', 'c', metavar='FILE',
66 help="load the configuration file FILE after the default "
67 "configuration files"),
68 ConfigOption('replace_config_file', 'C', override=True, metavar='FILE',
69 help="don't load the default configuration files, just FILE"),
75 f = file("/proc/sys/net/ipv4/ip_forward","w")
78 except (IOError, OSError), e:
79 log.warning("Can't set ip_forward: %s", e)
82 def get_config(paths, version, desc, add_options, defaults):
83 global config_file_paths
85 (config, args) = load_config(paths, version, desc, add_options, defaults)
86 except ConfigError, e:
88 sys.exit(EXIT_CONFIG_ERROR)
89 except MissingSectionHeaderError, e:
90 log.error("%s:%s: missing section header near: %s", e.filename, e.lineno,
92 sys.exit(EXIT_CONFIG_ERROR)
93 except ParsingError, e:
94 for (lineno, line) in e.errors:
95 log.error("%s:%s: invalid syntax near: %s", e.filename, lineno, line)
96 log.error(str(e.errors))
97 sys.exit(EXIT_CONFIG_ERROR)
99 log.error(str(e.unpack_errors()))
100 sys.exit(EXIT_CONFIG_ERROR)
102 log.error("service '%s' not found (see option --services-dir)",
104 sys.exit(EXIT_NO_SERVICE)
105 return (config, args)
110 self.services = dict()
111 def add_config_options(self, config, args):
112 for service in config.services:
113 s = load_service(service, config.services_dirs)
114 s.setup_service(options, config)
115 self.services[service] = s
117 def build_root(config, args, services):
118 from pymin.dispatcher import Handler
121 # TODO check services dependencies
123 for name, service in services.items():
124 setattr(root, name, service.get_service(config))
129 services = Services()
130 (config, args) = get_config(config_file_paths, '%prog 0.1',
131 'Router services administration daemon',
132 services.add_config_options, config_defaults)
133 root_handler = build_root(config, args, services.services)
134 PyminDaemon(root_handler, (config.bind_addr, config.bind_port)).run()
136 if __name__ == '__main__':