]> git.llucax.com Git - software/pymin.git/blob - pymind
7922afa148a38fc894ff0f7ec84238b154a678a3
[software/pymin.git] / pymind
1 #!/usr/bin/env python
2 # vim: set encoding=utf-8 et sw=4 sts=4 :
3
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
7 logging.basicConfig(
8         level   = logging.DEBUG,
9         format  = '%(asctime)s %(name)-24s %(levelname)-8s %(message)s',
10         datefmt = '%a, %d %b %Y %H:%M:%S',
11 )
12
13 import os
14 import sys
15 from formencode import Invalid, validators as V
16
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
23
24 # exit status (1 is reserved for command-line errors)
25 EXIT_CONFIG_ERROR = 2
26 EXIT_NO_SERVICE   = 3
27
28 # default locations where to look for configuration files
29 # all found files will be processed, overriding the previous configuration
30 # files values.
31 config_file_paths = [
32     '/etc/pymin.ini',
33     '/etc/pymin/pymin.ini',
34     os.path.expanduser('~/.pymin.ini'),
35     os.path.expanduser('~/.pymin/pymin.ini'),
36 ]
37
38 # default locations where to look for service plug-ins
39 # search stops when a service plug-in is found
40 services_paths = [
41     os.path.expanduser('~/.pymin/services'),
42     '/usr/share/pymin/services',
43 ]
44
45 # default configuration variables
46 # these are useful variables to help the user writing the configuration file
47 config_defaults = {
48     'pymind-data-dir':   '/var/lib/pymin',
49     'pymind-pickle-dir': '/var/lib/pymin/pickle',
50     'pymind-config-dir': '/var/lib/pymin/config',
51 }
52
53 # Validator to check if is a valid Python identifier
54 PythonIdentifier = V.Regex(r'^[a-zA-Z_]\w*$')
55
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"),
70 ])
71
72
73 # FIXME: move to IpHandler or someplace else
74 def activate_ip_forward():
75     try:
76         f = file("/proc/sys/net/ipv4/ip_forward","w")
77         f.write("1")
78         f.close()
79     except (IOError, OSError), e:
80         log.warning("Can't set ip_forward: %s", e)
81
82
83 def get_config(paths, version, desc, add_options, defaults):
84     global config_file_paths
85     try:
86         (config, args) = load_config(paths, version, desc, add_options, defaults)
87     except ConfigError, e:
88         log.error(str(e))
89         sys.exit(EXIT_CONFIG_ERROR)
90     except MissingSectionHeaderError, e:
91         log.error("%s:%s: missing section header near: %s", e.filename, e.lineno,
92                   e.line)
93         sys.exit(EXIT_CONFIG_ERROR)
94     except ParsingError, e:
95         for (lineno, line) in e.errors:
96             log.error("%s:%s: invalid syntax near: %s", e.filename, lineno, line)
97         log.error(str(e.errors))
98         sys.exit(EXIT_CONFIG_ERROR)
99     except Invalid, e:
100         log.error(str(e.unpack_errors()))
101         sys.exit(EXIT_CONFIG_ERROR)
102     except LoadError, e:
103         log.error("service '%s' not found (see option --services-dir)",
104                   e.service_name)
105         sys.exit(EXIT_NO_SERVICE)
106     return (config, args)
107
108
109 class Services:
110     def __init__(self):
111         self.services = dict()
112     def add_config_options(self, config, args):
113         for service in config.services:
114             s = load_service(service, config.services_dirs)
115             s.setup_service(options, config)
116             self.services[service] = s
117
118 def build_root(config, args, services):
119     from pymin.dispatcher import Handler
120     class Root(Handler):
121         pass
122     # TODO check services dependencies
123     root = Root()
124     for name, service in services.items():
125         setattr(root, name, service.get_service(config))
126     return root
127
128
129 def main():
130     services = Services()
131     (config, args) = get_config(config_file_paths, '%prog 0.1',
132                                 'Router services administration daemon',
133                                 services.add_config_options, config_defaults)
134     root_handler = build_root(config, args, services.services)
135     activate_ip_forward()
136     PyminDaemon(root_handler, (config.bind_addr, config.bind_port)).run()
137
138 if __name__ == '__main__':
139     main()
140