]> git.llucax.com Git - software/pymin.git/commitdiff
Merge ../pymin
authorFede <fedux@linux-kt9u.site>
Sat, 6 Oct 2007 13:04:02 +0000 (10:04 -0300)
committerFede <fedux@linux-kt9u.site>
Sat, 6 Oct 2007 13:04:02 +0000 (10:04 -0300)
TODO
config.py
doc/config/iptables.txt [new file with mode: 0644]
pymin/dispatcher.py
pymin/pymindaemon.py
pymin/services/dhcp/__init__.py
pymin/services/dns/__init__.py
pymin/services/firewall/__init__.py
pymin/services/ip/__init__.py
pymin/services/proxy/__init__.py
pymind

diff --git a/TODO b/TODO
index 362b434a91b895c8e25d83965ca2bf00dc3d831c..b8d9c03853380c9db7272a5ad4f9ff6513a309fd 100644 (file)
--- a/TODO
+++ b/TODO
@@ -1,19 +1,6 @@
 
 Ideas / TODO:
 
-* Hacer el protocolo completamente introspectivo, de manera que el cliente pueda
-  ser muy simple y genérico y en caso de agregar funcionalidad no sea necesario
-  modificarlo.
-
-* Evaluar hacer un RootHandler en vez de un diccionario con los handlers de la
-  raiz para simplificar la introspección y tener un help/commands global.
-
-* Evaluar que el dispatcher vea si se llama a un HandlerContainer y de ser así
-  que tire una ayuda en vez de un CommandNotFound (por ejemplo si se pone:
-  "dhcp" solo que tire una ayuda). Y si hay un subcomando no encontrado, que
-  tire un Command Not Found in handler (por ej "dhcp lala" -> Command "lala" not
-  found in "dhcp").
-
 * Agregar logging.
 
 * Agregar validación con formencode.
index 059faaeea54762900ef6162904c8888a767a0b30..ca0cc650e5bed824baa70fa742df40feba129999 100644 (file)
--- a/config.py
+++ b/config.py
@@ -1,36 +1,30 @@
 # vim: set et sts=4 sw=4 encoding=utf-8 :
 
 from pymin.services import *
-from pymin.dispatcher import handler
+from pymin.dispatcher import Handler
+from os.path import join
 
-# XXX for testing only
-@handler
-def test_func(*args):
-    print 'func:', args
+base_path = join('var', 'lib', 'pymin')
+pickle_path = join(base_path, 'pickle')
+# FIXME, this should be specific for each service
+config_path = join(base_path, 'config')
 
-routes = dict \
-(
+class Root(Handler):
     dhcp = DhcpHandler(
-        pickle_dir = 'var/lib/pymin/pickle/dhcp',
-        config_dir = 'var/lib/pymin/config/dhcp',
-    ),
+        pickle_dir = join(pickle_path, 'dhcp'),
+        config_dir = join(config_path, 'dhcp'))
     dns = DnsHandler(
-        pickle_dir = 'var/lib/pymin/pickle/dns',
-        config_dir = 'var/lib/pymin/config/dns',
-    ),
+        pickle_dir = join(pickle_path, 'dns'),
+        config_dir = join(config_path, 'dns'))
     firewall = FirewallHandler(
-        pickle_dir = 'var/lib/pymin/pickle/firewall',
-        config_dir = 'var/lib/pymin/config/firewall',
-    ),
+        pickle_dir = join(pickle_path, 'firewall'),
+        config_dir = join(config_path, 'firewall'))
     ip = IpHandler(
-        pickle_dir = 'var/lib/pymin/pickle/ip',
-        config_dir = 'var/lib/pymin/config/ip',
-    ),
+        pickle_dir = join(pickle_path, 'ip'),
+        config_dir = join(config_path, 'ip'))
     proxy = ProxyHandler(
-        pickle_dir = 'var/lib/pymin/pickle/proxy',
-        config_dir = 'var/lib/pymin/config/proxy',
-    ),
-)
+        pickle_dir = join(pickle_path, 'proxy'),
+        config_dir = join(config_path, 'proxy'))
 
 bind_addr = \
 (
diff --git a/doc/config/iptables.txt b/doc/config/iptables.txt
new file mode 100644 (file)
index 0000000..982c181
--- /dev/null
@@ -0,0 +1,35 @@
+Configruacion de iptables:
+
+1) Listar las reglas de una tabla
+
+# iptables -t ${table} -L -v
+
+2) Para listar reglas de fitrado
+
+# iptables -t filter -L -v
+
+2.1) Agregar una regla de filtrado
+
+# iptables -t filter -I ${chain} ${pos} -j ${target} [-s ${src_ip}/${src_ip_prefix_length}] [-d ${dest_ip}/${dst_ip_prefix_length}] [-p ${protocol}]
+
+Si el protocolo (opcion -p) es udp o tcp se puede agregar los puertos de origen o destino
+
+# iptables -t filter -I ${chain} ${num} -j ${target} [-s ${src_ip}/${src_ip_prefix_length}] [-d ${dest_ip}/${dst_ip_prefix_length}] [-p ${protocol}] -m ${protocolo} [--sport ${src_port}] [--dport ${dst_port}]
+
+Donde:
+- ${chain} es INPUT, OUTPUT o FORWARD
+- ${pos} es el numero de regla dentro de la tabla
+- ${protocol} es udp, tcp, icmp o all
+- ${target} es DROP, ACCEPT, REJECT
+
+2.1) Eliminar una regla de una tabla
+
+# iptables -t ${table} -D ${chain} ${num}
+
+2.2) Eliminar todas las reglas de una tabla
+
+# iptables -t ${table} -F
+
+2.3) Eliminar todas las reglas dentro de una cadena de una tabla
+
+# iptables -t ${table} -F ${chain}
index c7d260bda6f1910d27b610a3f79f4b579613256e..39b4b75cf6522f64e78b2d097422a2bfc69285e1 100644 (file)
@@ -19,7 +19,16 @@ class Error(RuntimeError):
     command - is the command that raised the exception, expressed as a list of
               paths (or subcommands).
     """
-    pass
+
+    def __init__(self, message):
+        r"Initialize the Error object. See class documentation for more info."
+        self.message = message
+
+    def __unicode__(self):
+        return self.message
+
+    def __str__(self):
+        return unicode(self).encode('utf-8')
 
 class HandlerError(Error):
     r"""HandlerError(command) -> HandlerError instance :: Base handlers error.
@@ -37,25 +46,59 @@ class CommandError(Error):
     """
 
     def __init__(self, command):
-        r"""Initialize the object.
-
-        See class documentation for more info.
-        """
+        r"Initialize the object, see class documentation for more info."
         self.command = command
 
-    def __str__(self):
-        return 'Command error: "%s"' % self.command
+    def __unicode__(self):
+        return u'Error in command "%s".' % u' '.join(self.command)
+
+class CommandNotSpecifiedError(CommandError):
+    r"""CommandNotSpecifiedError() -> CommandNotSpecifiedError instance.
+
+    This exception is raised when an empty command string is received.
+    """
+
+    def __init__(self):
+        r"Initialize the object, see class documentation for more info."
+        pass
+
+    def __unicode__(self):
+        return u'Command not specified.'
+
+class CommandIsAHandlerError(CommandError):
+    r"""CommandIsAHandlerError() -> CommandIsAHandlerError instance.
+
+    This exception is raised when a command is a handler containing commands
+    instead of a command itself.
+    """
+
+    def __unicode__(self):
+        command = ' '.join(self.command)
+        return u'"%s" is a handler, not a command (type "%s help" for help).' \
+                    % (command, command)
+
+class CommandNotInHandlerError(CommandError):
+    r"""CommandNotInHandlerError() -> CommandNotInHandlerError instance.
+
+    This exception is raised when a command parent is a hanlder containing
+    commands, but the command itself is not found.
+    """
+
+    def __unicode__(self):
+        return u'Command "%(c)s" not found in handler "%(h)s" ' \
+                u'(type "%(h)s help" for help).' \
+                        % dict(c=u' '.join(self.command[-1:]),
+                                h=u' '.join(self.command[0:-1]))
 
 class CommandNotFoundError(CommandError):
-    r"""CommandNotFoundError(command) -> CommandNotFoundError instance.
+    r"""CommandNotFoundError(command[, handler]) -> CommandNotFoundError object.
 
     This exception is raised when the command received can't be dispatched
     because there is no handlers to process it.
     """
 
-    def __str__(self):
-        return 'Command not found: "%s"' % ' '.join(
-                                                repr(c) for c in self.command)
+    def __unicode__(self):
+        return u'Command "%s" not found.' % u' '.join(self.command)
 
 class ParseError(CommandError):
     r"""ParseError(command[, desc]) -> ParseError instance
@@ -75,8 +118,26 @@ class ParseError(CommandError):
         self.command = command
         self.desc = desc
 
-    def __str__(self):
-        return 'Syntax error, %s: %s' % (self.desc, self.command)
+    def __unicode__(self):
+        return u'Syntax error, %s: %s' % (self.desc, self.command)
+
+class HelpNotFoundError(Error):
+    r"""HelpNotFoundError(command) -> HelpNotFoundError instance.
+
+    This exception is raised when a help command can't find the command
+    asked for help.
+    """
+
+    def __init__(self, command):
+        r"""Initialize the object.
+
+        See class documentation for more info.
+        """
+        self.command = command
+
+    def __unicode__(self):
+        return u"Can't get help for '%s', command not found." % self.command
+
 
 def handler(help):
     r"""handler(help) -> function wrapper :: Mark a callable as a handler.
@@ -88,33 +149,32 @@ def handler(help):
     def wrapper(f):
         if not help:
             raise TypeError("'help' should not be empty")
-        f._dispatcher_help = help
+        f._dispatcher_handler = True
+        f.handler_help = help
         return f
     return wrapper
 
 def is_handler(handler):
     r"is_handler(handler) -> bool :: Tell if a object is a handler."
-    return callable(handler) and hasattr(handler, '_dispatcher_help')
-
-def get_help(handler):
-    r"get_help(handler) -> unicode :: Get a handler's help string."
-    if not is_handler(handler):
-        raise TypeError("'%s' should be a handler" % handler.__name__)
-    return handler._dispatcher_help
+    return callable(handler) and hasattr(handler, '_dispatcher_handler') \
+                and handler._dispatcher_handler
 
 class Handler:
     r"""Handler() -> Handler instance :: Base class for all dispatcher handlers.
 
     All dispatcher handlers should inherit from this class to have some extra
-    commands, like help.
+    commands, like help. You should override the 'handler_help' attribute to a
+    nice help message describing the handler.
     """
 
-    @handler(u'List available commands.')
+    handler_help = u'Undocumented handler'
+
+    @handler(u'List available commands')
     def commands(self):
         r"""commands() -> generator :: List the available commands."""
         return (a for a in dir(self) if is_handler(getattr(self, a)))
 
-    @handler(u'Show available commands with their help.')
+    @handler(u'Show available commands with their help')
     def help(self, command=None):
         r"""help([command]) -> unicode/dict :: Show help on available commands.
 
@@ -123,14 +183,19 @@ class Handler:
         and values are the help strings.
         """
         if command is None:
-            return dict((a, get_help(getattr(self, a)))
-                        for a in dir(self) if is_handler(getattr(self, a)))
-        if not hasattr(self, command):
-            raise CommandNotFoundError(command)
-        handler = getattr(self, command)
-        if not is_handler(handler):
-            raise CommandNotFoundError(command)
-        return get_help(handler)
+            d = dict()
+            for a in dir(self):
+                h = getattr(self, a)
+                if is_handler(h) or isinstance(h, Handler):
+                    d[a] = h.handler_help
+            return d
+        # A command was specified
+        if not hasattr(self, command.encode('utf-8')):
+            raise HelpNotFoundError(command)
+        handler = getattr(self, command.encode('utf-8'))
+        if not is_handler(handler) and not hasattr(handler):
+            raise HelpNotFoundError(command)
+        return handler.handler_help
 
 def parse_command(command):
     r"""parse_command(command) -> (args, kwargs) :: Parse a command.
@@ -294,15 +359,13 @@ def parse_command(command):
     return (seq, dic)
 
 class Dispatcher:
-    r"""Dispatcher([routes]) -> Dispatcher instance :: Command dispatcher
+    r"""Dispatcher([root]) -> Dispatcher instance :: Command dispatcher.
 
     This class provides a modular and extensible dispatching mechanism. You
-    can specify root 'routes' (as a dict where the key is the string of the
-    root command and the value is a callable object to handle that command,
-    or a subcommand if the callable is an instance and the command can be
-    sub-routed).
+    specify a root handler (probably as a pymin.dispatcher.Handler subclass),
 
-    The command can have arguments, separated by (any number of) spaces.
+    The command can have arguments, separated by (any number of) spaces and
+    keyword arguments (see parse_command for more details).
 
     The dispatcher tries to route the command as deeply as it can, passing
     the other "path" components as arguments to the callable. To route the
@@ -311,79 +374,79 @@ class Dispatcher:
 
     Example:
     >>> d = Dispatcher(dict(handler=some_handler))
-    >>> d.dispatch('handler attribute method arg1 arg2 "third argument"')
+    >>> d.dispatch('handler attribute method arg1 "arg 2" arg=3')
 
     If 'some_handler' is an object with an 'attribute' that is another
     object which has a method named 'method', then
-    some_handler.attribute.method('arg1', 'arg2') will be called. If
-    some_handler is a function, then some_handler('attribute', 'method',
-    'arg1', 'arg2') will be called. The handler "tree" can be as complex
-    and deep as you want.
+    some_handler.attribute.method('arg1', 'arg 2', arg=3) will be called.
+    If some_handler is a function, then some_handler('attribute', 'method',
+    'arg1', 'arg 2', arg=3) will be called. The handler "tree" can be as
+    complex and deep as you want.
 
-    If some command can't be dispatched (because there is no root handler or
-    there is no matching callable attribute), a CommandNotFoundError is raised.
+    If some command can't be dispatched, a CommandError subclass is raised.
     """
 
-    def __init__(self, routes=dict()):
+    def __init__(self, root):
         r"""Initialize the Dispatcher object.
 
         See Dispatcher class documentation for more info.
         """
-        self.routes = routes
+        self.root = root
 
     def dispatch(self, route):
         r"""dispatch(route) -> None :: Dispatch a command string.
 
         This method searches for a suitable callable object in the routes
-        "tree" and call it, or raises a CommandNotFoundError if the command
+        "tree" and call it, or raises a CommandError subclass if the command
         can't be dispatched.
+
+        route - *unicode* string with the command route.
         """
         command = list()
         (route, kwargs) = parse_command(route)
         if not route:
-            raise CommandNotFoundError(command)
-        command.append(route[0])
-        handler = self.routes.get(route[0], None)
-        if handler is None:
-            raise CommandNotFoundError(command)
-        route = route[1:]
+            raise CommandNotSpecifiedError()
+        handler = self.root
         while not is_handler(handler):
             if len(route) is 0:
+                if isinstance(handler, Handler):
+                    raise CommandIsAHandlerError(command)
                 raise CommandNotFoundError(command)
             command.append(route[0])
-            if not hasattr(handler, route[0]):
+            if not hasattr(handler, route[0].encode('utf-8')):
+                if isinstance(handler, Handler) and len(command) > 1:
+                    raise CommandNotInHandlerError(command)
                 raise CommandNotFoundError(command)
-            handler = getattr(handler, route[0])
+            handler = getattr(handler, route[0].encode('utf-8'))
             route = route[1:]
         return handler(*route, **kwargs)
 
 
 if __name__ == '__main__':
 
-    @handler(u"test: Print all the arguments, return nothing.")
+    @handler(u"test: Print all the arguments, return nothing")
     def test_func(*args):
         print 'func:', args
 
     class TestClassSubHandler(Handler):
-        @handler(u"subcmd: Print all the arguments, return nothing.")
+        @handler(u"subcmd: Print all the arguments, return nothing")
         def subcmd(self, *args):
             print 'class.subclass.subcmd:', args
 
     class TestClass(Handler):
-        @handler(u"cmd1: Print all the arguments, return nothing.")
+        @handler(u"cmd1: Print all the arguments, return nothing")
         def cmd1(self, *args):
             print 'class.cmd1:', args
-        @handler(u"cmd2: Print all the arguments, return nothing.")
+        @handler(u"cmd2: Print all the arguments, return nothing")
         def cmd2(self, *args):
             print 'class.cmd2:', args
         subclass = TestClassSubHandler()
 
-    test_class = TestClass()
+    class RootHandler(Handler):
+        func = staticmethod(test_func)
+        inst = TestClass()
 
-    d = Dispatcher(dict(
-            func=test_func,
-            inst=test_class,
-    ))
+    d = Dispatcher(RootHandler())
 
     d.dispatch(r'''func arg1 arg2 arg3 "fourth 'argument' with \", a\ttab and\n\\n"''')
     print 'inst commands:', tuple(d.dispatch('inst commands'))
@@ -394,7 +457,7 @@ if __name__ == '__main__':
     d.dispatch('inst subclass subcmd arg1 arg2 arg3 arg4 arg5')
     try:
         d.dispatch('')
-    except CommandNotFoundError, e:
+    except CommandNotSpecifiedError, e:
         print 'Not found:', e
     try:
         d.dispatch('sucutrule piquete culete')
@@ -402,8 +465,14 @@ if __name__ == '__main__':
         print 'Not found:', e
     try:
         d.dispatch('inst cmd3 arg1 arg2 arg3')
-    except CommandNotFoundError, e:
+    except CommandNotInHandlerError, e:
+        print 'Not found:', e
+    try:
+        d.dispatch('inst')
+    except CommandIsAHandlerError, e:
         print 'Not found:', e
+    print
+    print
 
     # Parser tests
     p = parse_command('hello world')
index be2c9750d29339d7b79d696bdf6218898ed267c8..f7497536835ae72670cc2ca3acbcf55ba5d58ba3 100644 (file)
@@ -11,28 +11,33 @@ command-line.
 import signal
 import socket
 
+from pymin.dispatcher import handler
+from pymin import dispatcher
 from pymin import eventloop
 from pymin import serializer
 
 class PyminDaemon(eventloop.EventLoop):
-    r"""PyminDaemon(bind_addr, routes) -> PyminDaemon instance
+    r"""PyminDaemon(root, bind_addr) -> PyminDaemon instance
 
     This class is well suited to run as a single process. It handles
     signals for controlled termination (SIGINT and SIGTERM), as well as
     a user signal to reload the configuration files (SIGUSR1).
 
-    bind_addr - is a tuple of (ip, port) where to bind the UDP socket to.
+    root - the root handler. This is passed directly to the Dispatcher.
 
-    routes - is a dictionary where the key is a command string and the value
-             is the command handler. This is passed directly to the Dispatcher.
+    bind_addr - is a tuple of (ip, port) where to bind the UDP socket to.
 
     Here is a simple usage example:
 
-    >>> def test_handler(*args): print 'test:', args
-    >>> PyminDaemon(('', 9999), dict(test=test_handler)).run()
+    >>> from pymin import dispatcher
+    >>> class Root(dispatcher.Handler):
+            @handler('Test command.')
+            def test(self, *args):
+                print 'test:', args
+    >>> PyminDaemon(Root(), ('', 9999)).run()
     """
 
-    def __init__(self, routes=dict(), bind_addr=('', 9999)):
+    def __init__(self, root, bind_addr=('', 9999)):
         r"""Initialize the PyminDaemon object.
 
         See PyminDaemon class documentation for more info.
@@ -44,7 +49,8 @@ class PyminDaemon(eventloop.EventLoop):
         # Create EventLoop
         eventloop.EventLoop.__init__(self, sock)
         # Create Dispatcher
-        self.dispatcher = Dispatcher(routes)
+        #TODO root.pymin = PyminHandler()
+        self.dispatcher = dispatcher.Dispatcher(root)
         # Signal handling
         def quit(signum, frame):
             print "Shuting down ..."
@@ -60,7 +66,7 @@ class PyminDaemon(eventloop.EventLoop):
         r"handle() -> None :: Handle incoming events using the dispatcher."
         (msg, addr) = self.file.recvfrom(65535)
         try:
-            result = self.dispatcher.dispatch(msg)
+            result = self.dispatcher.dispatch(unicode(msg, 'utf-8'))
             if result is not None:
                 result = serializer.serialize(result)
             response = u'OK '
@@ -76,7 +82,7 @@ class PyminDaemon(eventloop.EventLoop):
             response += u'0\n'
         else:
             response += u'%d\n%s' % (len(result), result)
-        self.file.sendto(response, addr)
+        self.file.sendto(response.encode('utf-8'), addr)
 
     def run(self):
         r"run() -> None :: Run the event loop (shortcut to loop())"
@@ -87,14 +93,14 @@ class PyminDaemon(eventloop.EventLoop):
 
 if __name__ == '__main__':
 
-    @handler(u"Print all the arguments, return nothing.")
-    def test_handler(*args):
-        print 'test:', args
-
-    @handler(u"Echo the message passed as argument.")
-    def echo_handler(message):
-        print 'echo:', message
-        return message
+    class Root(dispatcher.Handler):
+        @handler(u"Print all the arguments, return nothing.")
+        def test(self, *args):
+            print 'test:', args
+        @handler(u"Echo the message passed as argument.")
+        def echo(self, message):
+            print 'echo:', message
+            return message
 
-    PyminDaemon(dict(test=test_handler, echo=echo_handler)).run()
+    PyminDaemon(Root()).run()
 
index 8f42e1ac013db09d6739720e8537285505b4023c..0dcb0d4abe3bb920ec93efb4eea00b67a41c91b5 100644 (file)
@@ -19,13 +19,7 @@ class Error(HandlerError):
 
     message - A descriptive error message.
     """
-
-    def __init__(self, message):
-        r"Initialize the Error object. See class documentation for more info."
-        self.message = message
-
-    def __str__(self):
-        return self.message
+    pass
 
 class HostError(Error, KeyError):
     r"""
@@ -36,7 +30,7 @@ class HostError(Error, KeyError):
 
     def __init__(self, hostname):
         r"Initialize the object. See class documentation for more info."
-        self.message = 'Host error: "%s"' % hostname
+        self.message = u'Host error: "%s"' % hostname
 
 class HostAlreadyExistsError(HostError):
     r"""
@@ -47,7 +41,7 @@ class HostAlreadyExistsError(HostError):
 
     def __init__(self, hostname):
         r"Initialize the object. See class documentation for more info."
-        self.message = 'Host already exists: "%s"' % hostname
+        self.message = u'Host already exists: "%s"' % hostname
 
 class HostNotFoundError(HostError):
     r"""
@@ -59,7 +53,7 @@ class HostNotFoundError(HostError):
 
     def __init__(self, hostname):
         r"Initialize the object. See class documentation for more info."
-        self.message = 'Host not found: "%s"' % hostname
+        self.message = u'Host not found: "%s"' % hostname
 
 
 class Host(Sequence):
@@ -89,18 +83,20 @@ class HostHandler(Handler):
     hosts - A dictionary with string keys (hostnames) and Host instances values.
     """
 
+    handler_help = u"Manage DHCP hosts"
+
     def __init__(self, hosts):
         r"Initialize HostHandler object, see class documentation for details."
         self.hosts = hosts
 
-    @handler(u'Add a new host.')
+    @handler(u'Add a new host')
     def add(self, name, ip, mac):
         r"add(name, ip, mac) -> None :: Add a host to the hosts list."
         if name in self.hosts:
             raise HostAlreadyExistsError(name)
         self.hosts[name] = Host(name, ip, mac)
 
-    @handler(u'Update a host.')
+    @handler(u'Update a host')
     def update(self, name, ip=None, mac=None):
         r"update(name[, ip[, mac]]) -> None :: Update a host of the hosts list."
         if not name in self.hosts:
@@ -110,26 +106,26 @@ class HostHandler(Handler):
         if mac is not None:
             self.hosts[name].mac = mac
 
-    @handler(u'Delete a host.')
+    @handler(u'Delete a host')
     def delete(self, name):
         r"delete(name) -> None :: Delete a host of the hosts list."
         if not name in self.hosts:
             raise HostNotFoundError(name)
         del self.hosts[name]
 
-    @handler(u'Get information about a host.')
+    @handler(u'Get information about a host')
     def get(self, name):
         r"get(name) -> Host :: List all the information of a host."
         if not name in self.hosts:
             raise HostNotFoundError(name)
         return self.hosts[name]
 
-    @handler(u'List hosts.')
+    @handler(u'List hosts')
     def list(self):
         r"list() -> tuple :: List all the hostnames."
         return self.hosts.keys()
 
-    @handler(u'Get information about all hosts.')
+    @handler(u'Get information about all hosts')
     def show(self):
         r"show() -> list of Hosts :: List all the complete hosts information."
         return self.hosts.values()
@@ -148,6 +144,8 @@ class DhcpHandler(Restorable, ConfigWriter, InitdHandler, TransactionalHandler,
     Both defaults to the current working directory.
     """
 
+    handler_help = u"Manage DHCP service"
+
     _initd_name = 'dhcpd'
 
     _persistent_attrs = ('params', 'hosts')
index 624dfc44c14e67690a1a59d3572df6d089fdba1f..cf44ea4e4036334ef70747416aaa7500e2056bb4 100644 (file)
@@ -29,13 +29,7 @@ class Error(HandlerError):
 
     message - A descriptive error message.
     """
-
-    def __init__(self, message):
-        r"Initialize the Error object. See class documentation for more info."
-        self.message = message
-
-    def __str__(self):
-        return self.message
+    pass
 
 class ZoneError(Error, KeyError):
     r"""
@@ -46,7 +40,7 @@ class ZoneError(Error, KeyError):
 
     def __init__(self, zonename):
         r"Initialize the object. See class documentation for more info."
-        self.message = 'Zone error: "%s"' % zonename
+        self.message = u'Zone error: "%s"' % zonename
 
 class ZoneNotFoundError(ZoneError):
     r"""
@@ -58,7 +52,7 @@ class ZoneNotFoundError(ZoneError):
 
     def __init__(self, zonename):
         r"Initialize the object. See class documentation for more info."
-        self.message = 'zone not found: "%s"' % zonename
+        self.message = u'zone not found: "%s"' % zonename
 
 class ZoneAlreadyExistsError(ZoneError):
     r"""
@@ -69,7 +63,7 @@ class ZoneAlreadyExistsError(ZoneError):
 
     def __init__(self, zonename):
         r"Initialize the object. See class documentation for more info."
-        self.message = 'Zone already exists: "%s"' % zonename
+        self.message = u'Zone already exists: "%s"' % zonename
 
 class HostError(Error, KeyError):
     r"""
@@ -80,7 +74,7 @@ class HostError(Error, KeyError):
 
     def __init__(self, hostname):
         r"Initialize the object. See class documentation for more info."
-        self.message = 'Host error: "%s"' % hostname
+        self.message = u'Host error: "%s"' % hostname
 
 class HostAlreadyExistsError(HostError):
     r"""
@@ -91,11 +85,11 @@ class HostAlreadyExistsError(HostError):
 
     def __init__(self, hostname):
         r"Initialize the object. See class documentation for more info."
-        self.message = 'Host already exists: "%s"' % hostname
+        self.message = u'Host already exists: "%s"' % hostname
 
 class HostNotFoundError(HostError):
     r"""
-    HostNotFoundError(hostname) -> HostNotFoundError instance
+    HostNotFoundError(hostname) -> HostNotFoundError instance.
 
     This exception is raised when trying to operate on a hostname that doesn't
     exists.
@@ -103,36 +97,36 @@ class HostNotFoundError(HostError):
 
     def __init__(self, hostname):
         r"Initialize the object. See class documentation for more info."
-        self.message = 'Host not found: "%s"' % hostname
+        self.message = u'Host not found: "%s"' % hostname
 
 class MailExchangeError(Error, KeyError):
     r"""
-    MailExchangeError(hostname) -> MailExchangeError instance
+    MailExchangeError(hostname) -> MailExchangeError instance.
 
     This is the base exception for all mail exchange related errors.
     """
 
     def __init__(self, mx):
         r"Initialize the object. See class documentation for more info."
-        self.message = 'Mail Exchange error: "%s"' % mx
+        self.message = u'Mail Exchange error: "%s"' % mx
 
 class MailExchangeAlreadyExistsError(MailExchangeError):
     r"""
-    MailExchangeAlreadyExistsError(hostname) -> MailExchangeAlreadyExistsError instance
+    MailExchangeAlreadyExistsError(hostname) -> MailExchangeAlreadyExistsError.
 
     This exception is raised when trying to add a mail exchange that already exists.
     """
 
     def __init__(self, mx):
         r"Initialize the object. See class documentation for more info."
-        self.message = 'Mail Exchange already exists: "%s"' % mx
+        self.message = u'Mail Exchange already exists: "%s"' % mx
 
 class MailExchangeNotFoundError(MailExchangeError):
     r"""
-    MailExchangeNotFoundError(hostname) -> MailExchangeNotFoundError instance
+    MailExchangeNotFoundError(hostname) -> MailExchangeNotFoundError instance.
 
-    This exception is raised when trying to operate on a mail exchange that doesn't
-    exists.
+    This exception is raised when trying to operate on a mail exchange that
+    doesn't exists.
     """
 
     def __init__(self, mx):
@@ -152,9 +146,10 @@ class NameServerError(Error, KeyError):
 
 class NameServerAlreadyExistsError(NameServerError):
     r"""
-    NameServerAlreadyExistsError(hostname) -> NameServerAlreadyExistsError instance
+    NameServerAlreadyExistsError(hostname) -> NameServerAlreadyExistsError.
 
-    This exception is raised when trying to add a name server that already exists.
+    This exception is raised when trying to add a name server that already
+    exists.
     """
 
     def __init__(self, ns):
@@ -163,10 +158,10 @@ class NameServerAlreadyExistsError(NameServerError):
 
 class NameServerNotFoundError(NameServerError):
     r"""
-    NameServerNotFoundError(hostname) -> NameServerNotFoundError instance
+    NameServerNotFoundError(hostname) -> NameServerNotFoundError instance.
 
-    This exception is raised when trying to operate on a name server that doesn't
-    exists.
+    This exception is raised when trying to operate on a name server that
+    doesn't exists.
     """
 
     def __init__(self, ns):
@@ -183,6 +178,9 @@ class Host(Sequence):
         return (self.name, self.ip)
 
 class HostHandler(Handler):
+
+    handler_help = u"Manage DNS hosts"
+
     def __init__(self,zones):
         self.zones = zones
 
@@ -233,6 +231,8 @@ class MailExchange(Sequence):
 
 class MailExchangeHandler(Handler):
 
+    handler_help = u"Manage DNS mail exchangers (MX)"
+
     def __init__(self, zones):
         self.zones = zones
 
@@ -282,6 +282,8 @@ class NameServer(Sequence):
 
 class NameServerHandler(Handler):
 
+    handler_help = u"Manage DNS name servers (NS)"
+
     def __init__(self, zones):
         self.zones = zones
 
@@ -326,7 +328,6 @@ class Zone(Sequence):
         return (self.name, self.hosts, self.mxs, self.nss)
 
 class ZoneHandler(Handler):
-
     r"""ZoneHandler(zones) -> ZoneHandler instance :: Handle a list of zones.
 
     This class is a helper for DnsHandler to do all the work related to zone
@@ -334,6 +335,9 @@ class ZoneHandler(Handler):
 
     zones - A dictionary with string keys (zone name) and Zone instances values.
     """
+
+    handler_help = u"Manage DNS zones"
+
     def __init__(self, zones):
         self.zones = zones
 
@@ -378,6 +382,8 @@ class DnsHandler(Restorable, ConfigWriter, InitdHandler, TransactionalHandler,
     Both defaults to the current working directory.
     """
 
+    handler_help = u"Manage DNS service"
+
     _initd_name = 'bind'
 
     _persistent_attrs = ('params', 'zones')
index dbf9b155015e4053cc32cc83e96c2537d18dec09..229cc207a3a2a5efff14b7d2f1e59bc02fb3bab8 100644 (file)
@@ -22,13 +22,7 @@ class Error(HandlerError):
 
     message - A descriptive error message.
     """
-
-    def __init__(self, message):
-        r"Initialize the Error object. See class documentation for more info."
-        self.message = message
-
-    def __str__(self):
-        return self.message
+    pass
 
 class RuleError(Error, KeyError):
     r"""
@@ -39,7 +33,7 @@ class RuleError(Error, KeyError):
 
     def __init__(self, rule):
         r"Initialize the object. See class documentation for more info."
-        self.message = 'Rule error: "%s"' % rule
+        self.message = u'Rule error: "%s"' % rule
 
 class RuleAlreadyExistsError(RuleError):
     r"""
@@ -50,7 +44,7 @@ class RuleAlreadyExistsError(RuleError):
 
     def __init__(self, rule):
         r"Initialize the object. See class documentation for more info."
-        self.message = 'Rule already exists: "%s"' % rule
+        self.message = u'Rule already exists: "%s"' % rule
 
 class RuleNotFoundError(RuleError):
     r"""
@@ -62,7 +56,7 @@ class RuleNotFoundError(RuleError):
 
     def __init__(self, rule):
         r"Initialize the object. See class documentation for more info."
-        self.message = 'Rule not found: "%s"' % rule
+        self.message = u'Rule not found: "%s"' % rule
 
 
 class Rule(Sequence):
@@ -129,11 +123,13 @@ class RuleHandler(Handler):
     rules - A list of Rule objects.
     """
 
+    handler_help = u"Manage firewall rules"
+
     def __init__(self, rules):
         r"Initialize the object, see class documentation for details."
         self.rules = rules
 
-    @handler(u'Add a new rule.')
+    @handler(u'Add a new rule')
     def add(self, *args, **kwargs):
         r"add(rule) -> None :: Add a rule to the rules list (see Rule doc)."
         rule = Rule(*args, **kwargs)
@@ -141,7 +137,7 @@ class RuleHandler(Handler):
             raise RuleAlreadyExistsError(rule)
         self.rules.append(rule)
 
-    @handler(u'Update a rule.')
+    @handler(u'Update a rule')
     def update(self, index, *args, **kwargs):
         r"update(index, rule) -> None :: Update a rule (see Rule doc)."
         # TODO check if the modified rule is the same of an existing one
@@ -151,7 +147,7 @@ class RuleHandler(Handler):
         except IndexError:
             raise RuleNotFoundError(index)
 
-    @handler(u'Delete a rule.')
+    @handler(u'Delete a rule')
     def delete(self, index):
         r"delete(index) -> Rule :: Delete a rule from the list returning it."
         index = int(index) # TODO validation
@@ -160,7 +156,7 @@ class RuleHandler(Handler):
         except IndexError:
             raise RuleNotFoundError(index)
 
-    @handler(u'Get information about a rule.')
+    @handler(u'Get information about a rule')
     def get(self, index):
         r"get(rule) -> Rule :: Get all the information about a rule."
         index = int(index) # TODO validation
@@ -169,7 +165,7 @@ class RuleHandler(Handler):
         except IndexError:
             raise RuleNotFoundError(index)
 
-    @handler(u'Get information about all rules.')
+    @handler(u'Get information about all rules')
     def show(self):
         r"show() -> list of Rules :: List all the complete rules information."
         return self.rules
@@ -188,6 +184,8 @@ class FirewallHandler(Restorable, ConfigWriter, ServiceHandler,
     Both defaults to the current working directory.
     """
 
+    handler_help = u"Manage firewall service"
+
     _persistent_attrs = 'rules'
 
     _restorable_defaults = dict(rules=list())
index 4330eeb359b8cdb8a31d49295505c07a69d9d911..c512d26a46bf0766c89416887e4795998330af51 100644 (file)
@@ -21,53 +21,47 @@ class Error(HandlerError):
 
     message - A descriptive error message.
     """
-
-    def __init__(self, message):
-        r"Initialize the Error object. See class documentation for more info."
-        self.message = message
-
-    def __str__(self):
-        return self.message
+    pass
 
 class DeviceError(Error):
 
     def __init__(self, device):
-        self.message = 'Device error : "%s"' % device
+        self.message = u'Device error : "%s"' % device
 
 class DeviceNotFoundError(DeviceError):
 
     def __init__(self, device):
-        self.message = 'Device not found : "%s"' % device
+        self.message = u'Device not found : "%s"' % device
 
 class AddressError(Error):
 
     def __init__(self, addr):
-        self.message = 'Address error : "%s"' % addr
+        self.message = u'Address error : "%s"' % addr
 
 class AddressNotFoundError(AddressError):
 
     def __init__(self, address):
-        self.message = 'Address not found : "%s"' % address
+        self.message = u'Address not found : "%s"' % address
 
 class AddressAlreadyExistsError(AddressError):
 
     def __init__(self, address):
-        self.message = 'Address already exists : "%s"' % address
+        self.message = u'Address already exists : "%s"' % address
 
 class RouteError(Error):
 
     def __init__(self, route):
-        self.message = 'Route error : "%s"' % route
+        self.message = u'Route error : "%s"' % route
 
 class RouteNotFoundError(RouteError):
 
     def __init__(self, route):
-        self.message = 'Route not found : "%s"' % route
+        self.message = u'Route not found : "%s"' % route
 
 class RouteAlreadyExistsError(RouteError):
 
     def __init__(self, route):
-        self.message = 'Route already exists : "%s"' % route
+        self.message = u'Route already exists : "%s"' % route
 
 
 class Route(Sequence):
@@ -89,6 +83,8 @@ class Route(Sequence):
 
 class RouteHandler(Handler):
 
+    handler_help = u"Manage IP routes"
+
     def __init__(self, devices):
         self.devices = devices
 
@@ -149,6 +145,8 @@ class Address(Sequence):
 
 class AddressHandler(Handler):
 
+    handler_help = u"Manage IP addresses"
+
     def __init__(self, devices):
         self.devices = devices
 
@@ -204,6 +202,8 @@ class Device(Sequence):
 
 class DeviceHandler(Handler):
 
+    handler_help = u"Manage network devices"
+
     def __init__(self, devices):
         # FIXME remove templates to execute commands
         from mako.template import Template
@@ -251,6 +251,8 @@ def get_devices():
 
 class IpHandler(Restorable, ConfigWriter, TransactionalHandler):
 
+    handler_help = u"Manage IP devices, addresses and routes"
+
     _persistent_attrs = 'devices'
 
     _restorable_defaults = dict(devices=get_devices())
index 5e8460e21ac075fd5ae1f288cc16fd249fe44abd..2740cc8c8ab0f8d546cf6b8986d19bb37d825b17 100644 (file)
@@ -21,13 +21,7 @@ class Error(HandlerError):
 
     message - A descriptive error message.
     """
-
-    def __init__(self, message):
-        r"Initialize the Error object. See class documentation for more info."
-        self.message = message
-
-    def __str__(self):
-        return self.message
+    pass
 
 class HostError(Error, KeyError):
     r"""
@@ -38,7 +32,7 @@ class HostError(Error, KeyError):
 
     def __init__(self, hostname):
         r"Initialize the object. See class documentation for more info."
-        self.message = 'Host error: "%s"' % hostname
+        self.message = u'Host error: "%s"' % hostname
 
 class HostAlreadyExistsError(HostError):
     r"""
@@ -49,7 +43,7 @@ class HostAlreadyExistsError(HostError):
 
     def __init__(self, hostname):
         r"Initialize the object. See class documentation for more info."
-        self.message = 'Host already exists: "%s"' % hostname
+        self.message = u'Host already exists: "%s"' % hostname
 
 class HostNotFoundError(HostError):
     r"""
@@ -61,7 +55,7 @@ class HostNotFoundError(HostError):
 
     def __init__(self, hostname):
         r"Initialize the object. See class documentation for more info."
-        self.message = 'Host not found: "%s"' % hostname
+        self.message = u'Host not found: "%s"' % hostname
 
 
 class Host(Sequence):
@@ -74,6 +68,8 @@ class Host(Sequence):
 
 class HostHandler(Handler):
 
+    handler_help = u"Manage proxy hosts"
+
     def __init__(self, hosts):
         self.hosts = hosts
 
@@ -116,6 +112,8 @@ class UserHandler(Handler):
 class ProxyHandler(Restorable, ConfigWriter, InitdHandler,
                    TransactionalHandler, ParametersHandler):
 
+    handler_help = u"Manage proxy service"
+
     _initd_name = 'squid'
 
     _persistent_attrs = ('params', 'hosts', 'users')
diff --git a/pymind b/pymind
index 27a972269c7597f73a4fe40926cc592a90bf0e9b..a04307d1920909bbd3a25cce42c0c9d8fbb5dbcf 100755 (executable)
--- a/pymind
+++ b/pymind
@@ -4,5 +4,5 @@
 from pymin.pymindaemon import PyminDaemon
 import config
 
-PyminDaemon(config.routes, config.bind_addr).run()
+PyminDaemon(config.Root(), config.bind_addr).run()