]> git.llucax.com Git - software/pymin.git/commitdiff
Merge branch 'master' of git.llucax.com.ar:/var/lib/git/software/pymin into logging
authorLeandro Lucarella <llucax@gmail.com>
Mon, 24 Dec 2007 05:24:38 +0000 (02:24 -0300)
committerLeandro Lucarella <llucax@gmail.com>
Mon, 24 Dec 2007 05:24:38 +0000 (02:24 -0300)
* 'master' of git.llucax.com.ar:/var/lib/git/software/pymin:
  Add protocol specification of firewall and nat commands.
  Added the protocol specification.
  Root class inyects ip forwrading in constructor.
  Added route handling capabilities and service restarting
  Fix so that when a device is brought back up, the routes
  Added support to hook services to IPHandler.
  Support for inactive devices added in IPHandler.

Conflicts:

pymin/services/ip/__init__.py

14 files changed:
config.py
pymin/dispatcher.py
pymin/eventloop.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/nat/__init__.py
pymin/services/ppp/__init__.py
pymin/services/proxy/__init__.py
pymin/services/util.py
pymin/services/vpn/__init__.py
pymin/services/vrrp/__init__.py

index a0b5498cc228f50a57a330ef3319c239a5c21b47..7a9b60452ddeb6cef41be1a2c78e9a6b5121d8d5 100644 (file)
--- a/config.py
+++ b/config.py
@@ -1,5 +1,13 @@
 # vim: set et sts=4 sw=4 encoding=utf-8 :
 
+# First of all, we need to setup the logging framework
+import logging
+logging.basicConfig(
+        level   = logging.DEBUG,
+        format  = '%(asctime)s %(name)-24s %(levelname)-8s %(message)s',
+        datefmt = '%a, %d %b %Y %H:%M:%S',
+)
+
 from pymin.services import *
 from pymin.dispatcher import Handler
 from os.path import join
index 24f0d1f14e6a52b6f97fd49664d767b07382a99a..bde8603ed69b240281a926c6e1d7000d2ac15fa8 100644 (file)
@@ -8,6 +8,7 @@ and translates commands to functions/objects/methods.
 """
 
 import re
+import logging ; log = logging.getLogger('pymin.dispatcher')
 
 __ALL__ = ('Error', 'HandlerError', 'CommandNotFoundError', 'Handler',
             'Dispatcher', 'handler', 'is_handler', 'get_help')
@@ -434,6 +435,7 @@ class Dispatcher:
 
         See Dispatcher class documentation for more info.
         """
+        log.debug(u'Dispatcher(%r)', root)
         self.root = root
 
     def dispatch(self, route):
@@ -445,28 +447,44 @@ class Dispatcher:
 
         route - *unicode* string with the command route.
         """
+        log.debug('Dispatcher.dispatch(%r)', route)
         command = list()
         (route, kwargs) = parse_command(route)
+        log.debug(u'Dispatcher.dispatch: route=%r, kwargs=%r', route, kwargs)
         if not route:
+            log.debug(u'Dispatcher.dispatch: command not specified')
             raise CommandNotSpecifiedError()
         handler = self.root
         while not is_handler(handler):
+            log.debug(u'Dispatcher.dispatch: handler=%r, route=%r',
+                        handler, route)
             if len(route) is 0:
                 if isinstance(handler, Handler):
+                    log.debug(u'Dispatcher.dispatch: command is a handler')
                     raise CommandIsAHandlerError(command)
+                log.debug(u'Dispatcher.dispatch: command not found')
                 raise CommandNotFoundError(command)
             command.append(route[0])
+            log.debug(u'Dispatcher.dispatch: command=%r', command)
             if route[0] == 'parent':
+                log.debug(u'Dispatcher.dispatch: is parent => not found')
                 raise CommandNotFoundError(command)
             if not hasattr(handler, route[0].encode('utf-8')):
                 if isinstance(handler, Handler) and len(command) > 1:
+                    log.debug(u'Dispatcher.dispatch: command not in handler')
                     raise CommandNotInHandlerError(command)
+                log.debug(u'Dispatcher.dispatch: command not found')
                 raise CommandNotFoundError(command)
             handler = getattr(handler, route[0].encode('utf-8'))
             route = route[1:]
+        log.debug(u'Dispatcher.dispatch: %r is a handler, calling it with '
+                    u'route=%r, kwargs=%r', handler, route, kwargs)
         try:
+            r = handler(*route, **kwargs)
+            log.debug(u'Dispatcher.dispatch: handler returned %s', r)
             return handler(*route, **kwargs)
         except TypeError, e:
+            log.debug(u'Dispatcher.dispatch: type error (%r)', e)
             m = args_re.match(unicode(e))
             if m:
                 (quant, n_ok, n_bad)  = m.groups()
@@ -477,18 +495,29 @@ class Dispatcher:
                 pl = ''
                 if n_ok > 1:
                     pl = 's'
-                raise WrongArgumentsError(handler, u'takes %s %s argument%s, '
+                e = WrongArgumentsError(handler, u'takes %s %s argument%s, '
                             '%s given' % (quant, n_ok, pl, n_bad))
+                log.debug(u'Dispatcher.dispatch: wrong arguments (%r)', e)
+                raise e
             m = kw_re.match(unicode(e))
             if m:
                 (kw,)  = m.groups()
-                raise WrongArgumentsError(handler,
+                e = WrongArgumentsError(handler,
                         u'got an unexpected keyword argument %s' % kw)
+                log.debug(u'Dispatcher.dispatch: wrong arguments (%r)', e)
+                raise e
+            log.debug(u'Dispatcher.dispatch: some other TypeError, re-raising')
             raise
 
 
 if __name__ == '__main__':
 
+    logging.basicConfig(
+        level   = logging.DEBUG,
+        format  = '%(asctime)s %(levelname)-8s %(message)s',
+        datefmt = '%H:%M:%S',
+    )
+
     @handler(u"test: Print all the arguments, return nothing")
     def test_func(*args):
         print 'func:', args
index 86b89324eae7cfeff644cf1623d02e827185325a..c9f6adeccecb653c284236af5550b7cf1acabf97 100644 (file)
@@ -10,6 +10,7 @@ import select
 import errno
 import signal
 from select import POLLIN, POLLPRI, POLLERR
+import logging ; log = logging.getLogger('pymin.eventloop')
 
 __ALL__ = ('EventLoop', 'LoopInterruptedError')
 
@@ -93,6 +94,8 @@ class EventLoop:
 
         See EventLoop class documentation for more info.
         """
+        log.debug(u'EventLoop(%r, %r, %r, %r)', file, handler,
+                    timer, timer_handler)
         self.poll = select.poll()
         self._stop = False
         self.__register(file)
@@ -134,6 +137,7 @@ class EventLoop:
         The event loop will be interrupted as soon as the current handler
         finishes.
         """
+        log.debug(u'EventLoop.stop()')
         self._stop = True
 
     def loop(self, once=False):
@@ -142,6 +146,7 @@ class EventLoop:
         Wait for events and handle then when they arrive. If once is True,
         then only 1 event is processed and then this method returns.
         """
+        log.debug(u'EventLoop.loop(%s)', once)
         # Flag modified by the signal handler
         global timeout
         # If we use a timer, we set up the signal
@@ -151,6 +156,7 @@ class EventLoop:
             signal.alarm(self.timer)
         while True:
             try:
+                log.debug(u'EventLoop.loop: polling')
                 res = self.poll.poll()
             except select.error, e:
                 # The error is not an interrupt caused by the alarm, then raise
@@ -158,14 +164,17 @@ class EventLoop:
                     raise LoopInterruptedError(e)
             # There was a timeout, so execute the timer handler
             if timeout:
+                log.debug(u'EventLoop.loop: timer catched, handling...')
                 timeout = False
                 self.handle_timer()
                 signal.alarm(self.timer)
             # Not a timeout, execute the regular handler
             else:
+                log.debug(u'EventLoop.loop: no timeout, handle event')
                 self.handle()
             # Look if we have to stop
             if self._stop or once:
+                log.debug(u'EventLoop.loop: stopped')
                 self._stop = False
                 break
 
@@ -179,6 +188,12 @@ class EventLoop:
 
 if __name__ == '__main__':
 
+    logging.basicConfig(
+        level   = logging.DEBUG,
+        format  = '%(asctime)s %(levelname)-8s %(message)s',
+        datefmt = '%H:%M:%S',
+    )
+
     import os
     import time
 
index 8ed3f1576b93b2db18fd793e5e4b2e99fc1615e9..a65f19cf57fa7d73f2f7f7bcaf6dbbf0f3227e12 100644 (file)
@@ -10,6 +10,7 @@ command-line.
 
 import signal
 import socket
+import logging ; log = logging.getLogger('pymin.pymindaemon')
 
 from pymin.dispatcher import handler
 from pymin import dispatcher
@@ -42,6 +43,7 @@ class PyminDaemon(eventloop.EventLoop):
 
         See PyminDaemon class documentation for more info.
         """
+        log.debug(u'PyminDaemon(%r, %r, %r)', root, bind_addr, timer)
         # Create and bind socket
         sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
         sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
@@ -53,10 +55,12 @@ class PyminDaemon(eventloop.EventLoop):
         self.dispatcher = dispatcher.Dispatcher(root)
         # Signal handling
         def quit(signum, frame):
-            print "Shuting down ..."
+            log.debug(u'PyminDaemon quit() handler: signal %r', signum)
+            log.info(u'Shutting down...')
             self.stop() # tell main event loop to stop
         def reload_config(signum, frame):
-            print "Reloading configuration..."
+            log.debug(u'PyminDaemon reload_config() handler: signal %r', signum)
+            log.info(u'Reloading configuration...')
             # TODO iterate handlers list propagating reload action
         signal.signal(signal.SIGINT, quit)
         signal.signal(signal.SIGTERM, quit)
@@ -65,6 +69,7 @@ class PyminDaemon(eventloop.EventLoop):
     def handle(self):
         r"handle() -> None :: Handle incoming events using the dispatcher."
         (msg, addr) = self.file.recvfrom(65535)
+        log.debug(u'PyminDaemon.handle: message %r from %r', msg, addr)
         try:
             result = self.dispatcher.dispatch(unicode(msg, 'utf-8'))
             if result is not None:
@@ -76,12 +81,13 @@ class PyminDaemon(eventloop.EventLoop):
         except Exception, e:
             import traceback
             result = u'Internal server error\n'
-            traceback.print_exc() # TODO logging!
             response = u'ERROR '
+            log.exception(u'PyminDaemon.handle: unhandled exception')
         if result is None:
             response += u'0\n'
         else:
             response += u'%d\n%s' % (len(result), result)
+        log.debug(u'PyminDaemon.handle: response %r to %r', response, addr)
         self.file.sendto(response.encode('utf-8'), addr)
 
     def handle_timer(self):
@@ -90,13 +96,21 @@ class PyminDaemon(eventloop.EventLoop):
 
     def run(self):
         r"run() -> None :: Run the event loop (shortcut to loop())"
+        log.debug(u'PyminDaemon.loop()')
         try:
             return self.loop()
         except eventloop.LoopInterruptedError, e:
+            log.debug(u'PyminDaemon.loop: interrupted')
             pass
 
 if __name__ == '__main__':
 
+    logging.basicConfig(
+        level   = logging.DEBUG,
+        format  = '%(asctime)s %(levelname)-8s %(message)s',
+        datefmt = '%H:%M:%S',
+    )
+
     class Root(dispatcher.Handler):
         @handler(u"Print all the arguments, return nothing.")
         def test(self, *args):
index de1515b092c7955e4ee6970387f0545758693aea..51f7ecbad7f56af65896c3a40ed7b842c4b14457 100644 (file)
@@ -1,6 +1,7 @@
 # vim: set encoding=utf-8 et sw=4 sts=4 :
 
 from os import path
+import logging ; log = logging.getLogger('pymin.services.dhcp')
 
 from pymin.seqtools import Sequence
 from pymin.dispatcher import Handler, handler, HandlerError
@@ -84,6 +85,7 @@ class DhcpHandler(Restorable, ConfigWriter, ReloadHandler, TransactionalHandler,
 
     def __init__(self, pickle_dir='.', config_dir='.'):
         r"Initialize DhcpHandler object, see class documentation for details."
+        log.debug(u'DhcpHandler(%r, %r)', pickle_dir, config_dir)
         self._persistent_dir = pickle_dir
         self._config_writer_cfg_dir = config_dir
         self._config_build_templates()
@@ -96,6 +98,12 @@ class DhcpHandler(Restorable, ConfigWriter, ReloadHandler, TransactionalHandler,
 
 if __name__ == '__main__':
 
+    logging.basicConfig(
+        level   = logging.DEBUG,
+        format  = '%(asctime)s %(levelname)-8s %(message)s',
+        datefmt = '%H:%M:%S',
+    )
+
     import os
 
     h = DhcpHandler()
index 9324afbba3006c73e3031e9329d22c05d5d2c6a8..f57386c9f4dcf474d9371946ffeae9a423579bda 100644 (file)
@@ -3,6 +3,7 @@
 # TODO COMMENT
 from os import path
 from os import unlink
+import logging ; log = logging.getLogger('pymin.services.dns')
 
 from pymin.seqtools import Sequence
 from pymin.dispatcher import handler, HandlerError, Handler
@@ -105,6 +106,7 @@ class DnsHandler(Restorable, ConfigWriter, InitdHandler, TransactionalHandler,
 
     def __init__(self, pickle_dir='.', config_dir='.'):
         r"Initialize DnsHandler object, see class documentation for details."
+        log.debug(u'DnsHandler(%r, %r)', pickle_dir, config_dir)
         self._persistent_dir = pickle_dir
         self._config_writer_cfg_dir = config_dir
         self._update = False
@@ -123,10 +125,14 @@ class DnsHandler(Restorable, ConfigWriter, InitdHandler, TransactionalHandler,
 
     def _write_config(self):
         r"_write_config() -> None :: Generate all the configuration files."
+        log.debug(u'DnsHandler._write_config()')
         delete_zones = list()
         for a_zone in self.zones.values():
+            log.debug(u'DnsHandler._write_config: processing zone %s', a_zone)
             if a_zone._update or a_zone._add:
                 if not a_zone._add and self._service_running:
+                    log.debug(u'DnsHandler._write_config: zone updated and '
+                                u'the service is running, freezing zone')
                     call(('rndc', 'freeze', a_zone.name))
                 vars = dict(
                     zone = a_zone,
@@ -138,18 +144,22 @@ class DnsHandler(Restorable, ConfigWriter, InitdHandler, TransactionalHandler,
                                             self._zone_filename(a_zone), vars)
                 a_zone._update = False
                 if not a_zone._add and self._service_running:
+                    log.debug(u'DnsHandler._write_config: unfreezing zone')
                     call(('rndc', 'thaw', a_zone.name))
                 else :
                     self._update = True
                     a_zone._add = False
             if a_zone._delete:
                 #borro el archivo .zone
+                log.debug(u'DnsHandler._write_config: zone deleted, removing '
+                            u'the file %r', self._zone_filename(a_zone))
                 try:
                     self._update = True
                     unlink(self._zone_filename(a_zone))
                 except OSError:
                     #la excepcion pude darse en caso que haga un add de una zona y
                     #luego el del, como no hice commit, no se crea el archivo
+                    log.debug(u'DnsHandler._write_config: file not found')
                     pass
                 delete_zones.append(a_zone.name)
         #borro las zonas
@@ -164,19 +174,28 @@ class DnsHandler(Restorable, ConfigWriter, InitdHandler, TransactionalHandler,
 
     # HACK!!!!
     def handle_timer(self):
+        log.debug(u'DnsHandler.handle_timer()')
         import subprocess
         p = subprocess.Popen(('pgrep', '-f', '/usr/sbin/named'),
                                 stdout=subprocess.PIPE)
         pid = p.communicate()[0]
         if p.returncode == 0 and len(pid) > 0:
+            log.debug(u'DnsHandler.handle_timer: pid present, running')
             self._service_running = True
         else:
+            log.debug(u'DnsHandler.handle_timer: pid absent, NOT running')
             self._service_running = False
 
 
 
 if __name__ == '__main__':
 
+    logging.basicConfig(
+        level   = logging.DEBUG,
+        format  = '%(asctime)s %(levelname)-8s %(message)s',
+        datefmt = '%H:%M:%S',
+    )
+
     dns = DnsHandler();
 
     dns.set('isp_dns1','la_garcha.com')
index 06b41915cd4a78b66a300dee08f0ce51eec666cc..8809235edb262c43e292026bfd25ae24bfbabd45 100644 (file)
@@ -4,6 +4,7 @@
 # of using script templates.
 
 from os import path
+import logging ; log = logging.getLogger('pymin.services.firewall')
 
 from pymin.seqtools import Sequence
 from pymin.dispatcher import Handler, handler, HandlerError
@@ -93,6 +94,7 @@ class FirewallHandler(Restorable, ConfigWriter, ServiceHandler,
 
     def __init__(self, pickle_dir='.', config_dir='.'):
         r"Initialize the object, see class documentation for details."
+        log.debug(u'FirewallHandler(%r, %r)', pickle_dir, config_dir)
         self._persistent_dir = pickle_dir
         self._config_writer_cfg_dir = config_dir
         self._service_start = ('sh', path.join(self._config_writer_cfg_dir,
@@ -110,6 +112,12 @@ class FirewallHandler(Restorable, ConfigWriter, ServiceHandler,
 
 if __name__ == '__main__':
 
+    logging.basicConfig(
+        level   = logging.DEBUG,
+        format  = '%(asctime)s %(levelname)-8s %(message)s',
+        datefmt = '%H:%M:%S',
+    )
+
     import os
 
     fw_handler = FirewallHandler()
index b1d50b2262378aed9ca20d1c4d144438a89b757c..a7e23cba0a251b40122f0eb1e8c8ec4eb0ebd922 100644 (file)
@@ -2,13 +2,15 @@
 
 from subprocess import Popen, PIPE
 from os import path
+import logging ; log = logging.getLogger('pymin.services.ip')
 
 from pymin.seqtools import Sequence
 from pymin.dispatcher import handler, HandlerError, Handler
 from pymin.services.util import Restorable, ConfigWriter, InitdHandler, \
                                 TransactionalHandler, SubHandler, call, \
                                 get_network_devices, ListComposedSubHandler, \
-                                DictComposedSubHandler, Device, Address, ExecutionError
+                                DictComposedSubHandler, Device, Address, \
+                                ExecutionError
 
 __ALL__ = ('IpHandler',)
 
@@ -150,6 +152,7 @@ class DeviceHandler(SubHandler):
     handler_help = u"Manage network devices"
 
     def __init__(self, parent):
+        log.debug(u'DeviceHandler(%r)', parent)
         # FIXME remove templates to execute commands
         from mako.template import Template
         self.parent = parent
@@ -159,11 +162,13 @@ class DeviceHandler(SubHandler):
 
     @handler(u'Bring the device up')
     def up(self, name):
+        log.debug(u'DeviceHandler.up(%r)', name)
         if name in self.parent.devices:
             call(self.device_template.render(dev=name, action='up'), shell=True)
             #bring up all the route asocitaed to the device
             for route in self.parent.devices[name].routes:
                 try:
+                    log.debug(u'IpHandler.up: adding %r', route)
                     call(self.parent._render_config('route_add', dict(
                             dev = name,
                             net_addr = route.net_addr,
@@ -172,27 +177,32 @@ class DeviceHandler(SubHandler):
                         )
                     ), shell=True)
                 except ExecutionError, e:
-                    print e
+                    log.debug(u'IpHandler.up: error adding %r -> %r', route, e)
             self.parent._bring_up_no_dev_routes()
             self.parent._restart_services()
         else:
+            log.debug(u'DeviceHandler.up: device not found')
             raise DeviceNotFoundError(name)
 
     @handler(u'Bring the device down')
     def down(self, name):
+        log.debug(u'DeviceHandler.down(%r)', name)
         if name in self.parent.devices:
             call(self.device_template.render(dev=name, action='down'), shell=True)
             self.parent._bring_up_no_dev_routes()
             self.parent._restart_services()
         else:
+            log.debug(u'DeviceHandler.up: device not found')
             raise DeviceNotFoundError(name)
 
     @handler(u'List all devices')
     def list(self):
+        log.debug(u'DeviceHandler.list()')
         return self.parent.devices.keys()
 
     @handler(u'Get information about a device')
     def show(self):
+        log.debug(u'DeviceHandler.show()')
         return self.parent.devices.items()
 
 class IpHandler(Restorable, ConfigWriter, TransactionalHandler):
@@ -213,6 +223,7 @@ class IpHandler(Restorable, ConfigWriter, TransactionalHandler):
 
     def __init__(self, pickle_dir='.', config_dir='.'):
         r"Initialize DhcpHandler object, see class documentation for details."
+        log.debug(u'IpHandler(%r, %r)', pickle_dir, config_dir)
         self._persistent_dir = pickle_dir
         self._config_writer_cfg_dir = config_dir
         self._config_build_templates()
@@ -227,15 +238,19 @@ class IpHandler(Restorable, ConfigWriter, TransactionalHandler):
 
     def _write_config(self):
         r"_write_config() -> None :: Execute all commands."
+        log.debug(u'IpHandler._write_config()')
         for device in self.devices.values():
+            log.debug(u'IpHandler._write_config: processing device %s', device)
             if device.active:
                 self._write_config_for_device(device)
         self._bring_up_no_dev_routes()
         self._write_hops()
 
     def _bring_up_no_dev_routes(self):
+        log.debug(u'IpHandler._bring_up_no_dev_routes()')
         for route in self.no_device_routes:
             try:
+                log.debug(u'IpHandler._bring_up_no_dev_routes: add %r', route)
                 call(self._render_config('route_add', dict(
                         dev = None,
                         net_addr = route.net_addr,
@@ -244,16 +259,20 @@ class IpHandler(Restorable, ConfigWriter, TransactionalHandler):
                     )
                 ), shell=True)
             except ExecutionError, e:
-                print e
+                log.debug(u'IpHandler._write_config: error flushing -> %r', e)
 
     def _write_hops(self):
         r"_write_hops() -> None :: Execute all hops."
+        log.debug(u'IpHandler._write_hops()')
         if self.hops:
+            log.debug(u'IpHandler._write_hops: we have hops: %r', self.hops)
             try:
+                log.debug(u'IpHandler._write_hops: flushing default hops')
                 call('ip route del default', shell=True)
             except ExecutionError, e:
-                print e
+                log.debug(u'IpHandler._write_hops: error adding -> %r', e)
             try:
+                log.debug(u'IpHandler._write_hops: configuring hops')
                 #get hops for active devices
                 active_hops = dict()
                 for h in self.hops:
@@ -265,23 +284,32 @@ class IpHandler(Restorable, ConfigWriter, TransactionalHandler):
                         )
                 ), shell=True)
             except ExecutionError, e:
-                print e
+                log.debug(u'IpHandler._write_hops: error adding -> %r', e)
 
     def _write_config_for_device(self, device):
-        r"_write_config_for_device(self, device) -> None :: Execute all commands for a device."
+        r"_write_config_for_device(self, device) -> None :: Execute commands."
+        log.debug(u'IpHandler._write_config_for_device()')
         try:
-            call(self._render_config('route_flush', dict(dev=device.name)), shell=True)
+            log.debug(u'IpHandler._write_config_for_device: flushing routes...')
+            call(self._render_config('route_flush', dict(dev=device.name)),
+                        shell=True)
         except ExecutionError, e:
-            print e
+            log.debug(u'IpHandler._write_config_for_device: error flushing '
+                        u'-> %r', e)
         try:
-            call(self._render_config('ip_flush', dict(dev=device.name)), shell=True)
+            log.debug(u'IpHandler._write_config_for_device: flushing addrs...')
+            call(self._render_config('ip_flush', dict(dev=device.name)),
+                        shell=True)
         except ExecutionError, e:
-            print e
+            log.debug(u'IpHandler._write_config_for_device: error flushing '
+                        u'-> %r', e)
         for address in device.addrs.values():
             broadcast = address.broadcast
             if broadcast is None:
                 broadcast = '+'
             try:
+                log.debug(u'IpHandler._write_config_for_device: adding %r',
+                            address)
                 call(self._render_config('ip_add', dict(
                     dev = device.name,
                     addr = address.ip,
@@ -291,9 +319,12 @@ class IpHandler(Restorable, ConfigWriter, TransactionalHandler):
                     )
                 ), shell=True)
             except ExecutionError, e:
-                print e
+                log.debug(u'IpHandler._write_config_for_device: error adding '
+                            u'-> %r', e)
         for route in device.routes:
             try:
+                log.debug(u'IpHandler._write_config_for_device: adding %r',
+                            route)
                 call(self._render_config('route_add', dict(
                         dev = device.name,
                         net_addr = route.net_addr,
@@ -302,18 +333,21 @@ class IpHandler(Restorable, ConfigWriter, TransactionalHandler):
                     )
                 ), shell=True)
             except ExecutionError, e:
-                print e
+                log.debug(u'IpHandler._write_config_for_device: error adding '
+                            u'-> %r', e)
 
     def handle_timer(self):
+        log.debug(u'IpHandler.handle_timer()')
         self.refresh_devices()
 
-
     def refresh_devices(self):
+        log.debug(u'IpHandler.update_devices()')
         devices = get_network_devices()
         #add not registered and active devices
         go_active = False
         for k,v in devices.items():
             if k not in self.devices:
+                log.debug(u'IpHandler.update_devices: adding %r', v)
                 self.devices[k] = v
             elif not self.devices[k].active:
                 self.active = True
@@ -328,6 +362,7 @@ class IpHandler(Restorable, ConfigWriter, TransactionalHandler):
         for k in self.devices.keys():
             go_down = False
             if k not in devices:
+                log.debug(u'IpHandler.update_devices: removing %s', k)
                 self.devices[k].active = False
                 go_down = True
             if go_down:
@@ -358,7 +393,13 @@ class IpHandler(Restorable, ConfigWriter, TransactionalHandler):
 
 if __name__ == '__main__':
 
-    ip = IpHanlder()
+    logging.basicConfig(
+        level   = logging.DEBUG,
+        format  = '%(asctime)s %(levelname)-8s %(message)s',
+        datefmt = '%H:%M:%S',
+    )
+
+    ip = IpHandler()
     print '----------------------'
     ip.hop.add('201.21.32.53','eth0')
     ip.hop.add('205.65.65.25','eth1')
index a30f4c76dbabb2806781d10b7e67348cce5719f4..21a357e6c2712965ace241a3ec140a65bc6996a0 100644 (file)
@@ -1,6 +1,7 @@
 # vim: set encoding=utf-8 et sw=4 sts=4 :
 
 from os import path
+import logging ; log = logging.getLogger('pymin.services.nat')
 
 from pymin.seqtools import Sequence
 from pymin.dispatcher import Handler, handler, HandlerError
@@ -204,21 +205,27 @@ class NatHandler(Restorable, ConfigWriter, ReloadHandler, ServiceHandler,
     )
 
     def _service_start(self):
+        log.debug(u'NatHandler._service_start(): flushing nat table')
         call(('iptables', '-t', 'nat', '-F'))
         for (index, port) in enumerate(self.ports):
+            log.debug(u'NatHandler._service_start: adding port %r', port)
             call(['iptables'] + port.as_call_list(index+1))
         for (index, snat) in enumerate(self.snats):
+            log.debug(u'NatHandler._service_start: adding snat %r', snat)
             call(['iptables'] + snat.as_call_list(index+1))
         for (index, masq) in enumerate(self.masqs):
+            log.debug(u'NatHandler._service_start: adding masq %r', masq)
             call(['iptables'] + masq.as_call_list(index+1))
 
     def _service_stop(self):
+        log.debug(u'NatHandler._service_stop(): flushing nat table')
         call(('iptables', '-t', 'nat', '-F'))
 
     _service_restart = _service_start
 
     def __init__(self, pickle_dir='.'):
         r"Initialize the object, see class documentation for details."
+        log.debug(u'NatHandler(%r)', pickle_dir)
         self._persistent_dir = pickle_dir
         ServiceHandler.__init__(self)
         self.forward = PortForwardHandler(self)
@@ -228,6 +235,12 @@ class NatHandler(Restorable, ConfigWriter, ReloadHandler, ServiceHandler,
 
 if __name__ == '__main__':
 
+    logging.basicConfig(
+        level   = logging.DEBUG,
+        format  = '%(asctime)s %(levelname)-8s %(message)s',
+        datefmt = '%H:%M:%S',
+    )
+
     import os
 
     handler = NatHandler()
index db2a53541857d45f5f9bb4884563c657e81572d6..1dce3158f90650bb440f565212900cece647303f 100644 (file)
@@ -4,6 +4,7 @@ import os
 import subprocess
 from os import path
 from signal import SIGTERM
+import logging ; log = logging.getLogger('pymin.services.ppp')
 
 from pymin.seqtools import Sequence
 from pymin.dispatcher import Handler, handler, HandlerError
@@ -89,51 +90,69 @@ class PppHandler(Restorable, ConfigWriter, ReloadHandler, TransactionalHandler):
 
     def __init__(self, pickle_dir='.', config_dir='.'):
         r"Initialize Ppphandler object, see class documentation for details."
+        log.debug(u'PppHandler(%r, %r)', pickle_dir, config_dir)
         self._persistent_dir = pickle_dir
         self._config_writer_cfg_dir = config_dir
         self._config_build_templates()
         self._restore()
+        log.debug(u'PppHandler(): restoring connections...')
         for conn in self.conns.values():
             if conn._running:
+                log.debug(u'PppHandler(): starting connection %r', conn.name)
                 conn._running = False
                 self.start(conn.name)
         self.conn = ConnectionHandler(self)
 
     @handler(u'Start one or all the connections.')
     def start(self, name=None):
+        log.debug(u'PppHandler.start(%r)', name)
         names = [name]
         if name is None:
             names = self.conns.keys()
         for name in names:
             if name in self.conns:
                 if not self.conns[name]._running:
+                    log.debug(u'PppHandler.start: starting connection %r', name)
                     call(('pppd', 'call', name))
                     self.conns[name]._running = True
                     self._dump_attr('conns')
             else:
+                log.debug(u'PppHandler.start: connection not found')
                 raise ConnectionNotFoundError(name)
 
     @handler(u'Stop one or all the connections.')
     def stop(self, name=None):
+        log.debug(u'PppHandler.stop(%r)', name)
+        names = [name]
         names = [name]
         if name is None:
             names = self.conns.keys()
         for name in names:
             if name in self.conns:
                 if self.conns[name]._running:
-                    if path.exists('/var/run/ppp-' + name + '.pid'):
-                        pid = file('/var/run/ppp-' + name + '.pid').readline()
+                    pid_file = '/var/run/ppp-' + name + '.pid'
+                    log.debug(u'PppHandler.stop: getting pid from %r', pid_file)
+                    if path.exists(pid_file):
+                        pid = file(pid_file).readline()
+                        pid = int(pid.strip())
                         try:
-                            os.kill(int(pid.strip()), SIGTERM)
-                        except OSError:
-                            pass # XXX report error?
+                            log.debug(u'PppHandler.stop: killing pid %r', pid)
+                            os.kill(pid, SIGTERM)
+                        except OSError, e:
+                            log.debug(u'PppHandler.stop: error killing: %r', e)
+                    else:
+                        log.debug(u'PppHandler.stop: pid file not found')
                     self.conns[name]._running = False
                     self._dump_attr('conns')
+                else:
+                    log.debug(u'PppHandler.stop: connection not running')
             else:
+                log.debug(u'PppHandler.stop: connection not found')
                 raise ConnectionNotFoundError(name)
 
     @handler(u'Restart one or all the connections (even disconnected ones).')
     def restart(self, name=None):
+        log.debug(u'PppHandler.restart(%r)', name)
         names = [name]
         if name is None:
             names = self.conns.keys()
@@ -144,6 +163,7 @@ class PppHandler(Restorable, ConfigWriter, ReloadHandler, TransactionalHandler):
     @handler(u'Restart only one or all the already running connections.')
     def reload(self, name=None):
         r"reload() -> None :: Reload the configuration of the service."
+        log.debug(u'PppHandler.reload(%r)', name)
         names = [name]
         if name is None:
             names = self.conns.keys()
@@ -155,25 +175,32 @@ class PppHandler(Restorable, ConfigWriter, ReloadHandler, TransactionalHandler):
     @handler(u'Tell if the service is running.')
     def running(self, name=None):
         r"reload() -> None :: Reload the configuration of the service."
+        log.debug(u'PppHandler.running(%r)', name)
         if name is None:
             return [c.name for c in self.conns.values() if c._running]
         if name in self.conns:
             return int(self.conns[name]._running)
         else:
+            log.debug(u'PppHandler.running: connection not found')
             raise ConnectionNotFoundError(name)
 
     def handle_timer(self):
+        log.debug(u'PppHandler.handle_timer()')
         for c in self.conns.values():
+            log.debug(u'PppHandler.handle_timer: processing connection %r', c)
             p = subprocess.Popen(('pgrep', '-f', 'pppd call ' + c.name),
                                     stdout=subprocess.PIPE)
             pid = p.communicate()[0]
-            if p.wait() == 0 and len(pid) > 0:
+            if p.returncode == 0 and len(pid) > 0:
+                log.debug(u'PppHandler.handle_timer: pid present, running')
                 c._running = True
             else:
+                log.debug(u'PppHandler.handle_timer: pid absent, NOT running')
                 c._running = False
 
     def _write_config(self):
         r"_write_config() -> None :: Generate all the configuration files."
+        log.debug(u'PppHandler._write_config()')
         #guardo los pass que van el pap-secrets
         vars_pap = dict()
         for conn in self.conns.values():
@@ -197,6 +224,12 @@ class PppHandler(Restorable, ConfigWriter, ReloadHandler, TransactionalHandler):
 
 if __name__ == '__main__':
 
+    logging.basicConfig(
+        level   = logging.DEBUG,
+        format  = '%(asctime)s %(levelname)-8s %(message)s',
+        datefmt = '%H:%M:%S',
+    )
+
     p = PppHandler()
     p.conn.add('ppp_c','nico','nico',type='PPP',device='tty0')
     p.conn.add('pppoe_c','fede','fede',type='OE',device='tty1')
index a02e6c58df2e7c69a8d8508f2029c84c23f461c6..1e24cd44656e2ed66cb16268ddd1bd6291c59371 100644 (file)
@@ -1,6 +1,7 @@
 # vim: set encoding=utf-8 et sw=4 sts=4 :
 
 from os import path
+import logging ; log = logging.getLogger('pymin.services.proxy')
 
 from pymin.seqtools import Sequence
 from pymin.dispatcher import Handler, handler, HandlerError
@@ -67,6 +68,7 @@ class ProxyHandler(Restorable, ConfigWriter, InitdHandler,
 
     def __init__(self, pickle_dir='.', config_dir='.'):
         r"Initialize DhcpHandler object, see class documentation for details."
+        log.debug(u'ProxyHandler(%r, %r)', pickle_dir, config_dir)
         self._persistent_dir = pickle_dir
         self._config_writer_cfg_dir = config_dir
         self._config_build_templates()
@@ -82,6 +84,12 @@ class ProxyHandler(Restorable, ConfigWriter, InitdHandler,
 
 if __name__ == '__main__':
 
+    logging.basicConfig(
+        level   = logging.DEBUG,
+        format  = '%(asctime)s %(levelname)-8s %(message)s',
+        datefmt = '%H:%M:%S',
+    )
+
     px = ProxyHandler()
     px.set('ip','192.66.66.66')
     px.set('port','666')
index cb97815e2b1bf9892bbf7b1803de06240859350f..69864cf36c0949ada6ba4a55fed7ef6b8307a75a 100644 (file)
@@ -8,6 +8,7 @@ try:
     import cPickle as pickle
 except ImportError:
     import pickle
+import logging ; log = logging.getLogger('pymin.services.util')
 
 from pymin.dispatcher import Handler, handler, HandlerError, \
                                 CommandNotFoundError
@@ -210,17 +211,16 @@ def get_peers():
 def call(command, stdin=subprocess.PIPE, stdout=subprocess.PIPE,
             stderr=subprocess.PIPE, close_fds=True, universal_newlines=True,
             **kw):
+    log.debug(u'call(%r)', command)
     if DEBUG:
-        if not isinstance(command, basestring):
-            command = ' '.join(command)
-        print 'Executing command:', command
+        log.debug(u'call: not really executing, DEBUG mode')
         return
     try:
-        print 'Executing command:', command
-        r = subprocess.check_call(command, stdin=stdin, stdout=stdout,
+        subprocess.check_call(command, stdin=stdin, stdout=stdout,
                     stderr=stderr, close_fds=close_fds,
                     universal_newlines=universal_newlines, **kw)
     except Exception, e:
+        log.debug(u'call: Execution error %r', e)
         raise ExecutionError(command, e)
 
 class Persistent:
@@ -278,14 +278,22 @@ class Persistent:
 
     def _dump_attr(self, attrname):
         r"_dump_attr() -> None :: Dump a specific variable to a pickle file."
+        fname = self._pickle_filename(attrname)
+        attr = getattr(self, attrname)
+        log.debug(u'Persistent._dump_attr(%r) -> file=%r, value=%r',
+                attrname, fname, attr)
         f = file(self._pickle_filename(attrname), 'wb')
-        pickle.dump(getattr(self, attrname), f, 2)
+        pickle.dump(attr, f, 2)
         f.close()
 
     def _load_attr(self, attrname):
         r"_load_attr() -> object :: Load a specific pickle file."
-        f = file(self._pickle_filename(attrname))
-        setattr(self, attrname, pickle.load(f))
+        fname = self._pickle_filename(attrname)
+        f = file(fname)
+        attr = pickle.load(f)
+        log.debug(u'Persistent._load_attr(%r) -> file=%r, value=%r',
+                attrname, fname, attr)
+        setattr(self, attrname, attr)
         f.close()
 
     def _pickle_filename(self, name):
@@ -329,18 +337,27 @@ class Restorable(Persistent):
 
     def _restore(self):
         r"_restore() -> bool :: Restore persistent data or create a default."
+        log.debug(u'Restorable._restore()')
         try:
+            log.debug(u'Restorable._restore: trying to load...')
             self._load()
+            log.debug(u'Restorable._restore: load OK')
             return True
         except IOError:
+            log.debug(u'Restorable._restore: load FAILED, making defaults: %r',
+                        self._restorable_defaults)
             for (k, v) in self._restorable_defaults.items():
                 setattr(self, k, v)
             # TODO tener en cuenta servicios que hay que levantar y los que no
             if hasattr(self, 'commit'):
+                log.debug(u'Restorable._restore: commit() found, commiting...')
                 self.commit()
                 return False
+            log.debug(u'Restorable._restore: dumping new defaults...')
             self._dump()
             if hasattr(self, '_write_config'):
+                log.debug(u'Restorable._restore: _write_config() found, '
+                            u'writing new config...')
                 self._write_config()
             return False
 
@@ -404,6 +421,7 @@ class ConfigWriter:
 
     def _config_build_templates(self):
         r"_config_writer_templates() -> None :: Build the template objects."
+        log.debug(u'ConfigWriter.build_templates()')
         if isinstance(self._config_writer_files, basestring):
             self._config_writer_files = (self._config_writer_files,)
         if not hasattr(self, '_config_writer_templates') \
@@ -428,6 +446,8 @@ class ConfigWriter:
                 vars = dict()
         elif callable(vars):
             vars = vars(template_name)
+        log.debug(u'ConfigWriter._render_config: rendering template %r with '
+                    u'vars=%r', template_name, vars)
         return self._config_writer_templates[template_name].render(**vars)
 
     def _get_config_path(self, template_name, config_filename=None):
@@ -458,8 +478,11 @@ class ConfigWriter:
                 vars = dict()
         elif callable(vars):
             vars = vars(template_name)
-        f = file(self._get_config_path(template_name, config_filename), 'w')
+        fname = self._get_config_path(template_name, config_filename)
+        f = file(fname, 'w')
         ctx = Context(f, **vars)
+        log.debug(u'ConfigWriter._write_single_config: rendering template '
+                    u'%r with vars=%r to file %r', template_name, vars, fname)
         self._config_writer_templates[template_name].render_context(ctx)
         f.close()
 
@@ -496,23 +519,31 @@ class ServiceHandler(Handler, Restorable):
 
     def __init__(self, start=None, stop=None, restart=None, reload=None):
         r"Initialize the object, see the class documentation for details."
+        log.debug(u'ServiceHandler(%r, %r, %r, %r)', start, stop, restart,
+                    reload)
         for (name, action) in dict(start=start, stop=stop, restart=restart,
                                                     reload=reload).items():
             if action is not None:
-                setattr(self, '_service_%s' % name, action)
+                attr_name = '_service_%s' % name
+                log.debug(u'ServiceHandler: using %r as %s', attr_name, action)
+                setattr(self, attr_name, action)
         self._persistent_attrs = list(self._persistent_attrs)
         self._persistent_attrs.append('_service_running')
         if '_service_running' not in self._restorable_defaults:
             self._restorable_defaults['_service_running'] = False
+        log.debug(u'ServiceHandler: restoring service configuration...')
         self._restore()
         if self._service_running:
+            log.debug(u'ServiceHandler: service was running, starting it...')
             self._service_running = False
             self.start()
 
     @handler(u'Start the service.')
     def start(self):
         r"start() -> None :: Start the service."
+        log.debug(u'ServiceHandler.start()')
         if not self._service_running:
+            log.debug(u'ServiceHandler.start: not running, starting it...')
             if callable(self._service_start):
                 self._service_start()
             else:
@@ -522,8 +553,10 @@ class ServiceHandler(Handler, Restorable):
 
     @handler(u'Stop the service.')
     def stop(self):
+        log.debug(u'ServiceHandler.stop()')
         r"stop() -> None :: Stop the service."
         if self._service_running:
+            log.debug(u'ServiceHandler.stop: running, stoping it...')
             if callable(self._service_stop):
                 self._service_stop()
             else:
@@ -534,6 +567,7 @@ class ServiceHandler(Handler, Restorable):
     @handler(u'Restart the service.')
     def restart(self):
         r"restart() -> None :: Restart the service."
+        log.debug(u'ServiceHandler.restart()')
         if callable(self._service_restart):
             self._service_restart()
         else:
@@ -544,7 +578,9 @@ class ServiceHandler(Handler, Restorable):
     @handler(u'Reload the service config (without restarting, if possible).')
     def reload(self):
         r"reload() -> None :: Reload the configuration of the service."
+        log.debug(u'ServiceHandler.reload()')
         if self._service_running:
+            log.debug(u'ServiceHandler.reload: running, reloading...')
             if callable(self._service_reload):
                 self._service_reload()
             else:
@@ -553,6 +589,7 @@ class ServiceHandler(Handler, Restorable):
     @handler(u'Tell if the service is running.')
     def running(self):
         r"reload() -> None :: Reload the configuration of the service."
+        log.debug(u'ServiceHandler.running() -> %r', self._service_running)
         if self._service_running:
             return 1
         else:
@@ -569,6 +606,7 @@ class RestartHandler(Handler):
     @handler(u'Restart the service (alias to stop + start).')
     def restart(self):
         r"restart() -> None :: Restart the service calling stop() and start()."
+        log.debug(u'RestartHandler.restart()')
         self.stop()
         self.start()
 
@@ -582,7 +620,9 @@ class ReloadHandler(Handler):
     @handler(u'Reload the service config (alias to restart).')
     def reload(self):
         r"reload() -> None :: Reload the configuration of the service."
+        log.debug(u'ReloadHandler.reload()')
         if hasattr(self, '_service_running') and self._service_running:
+            log.debug(u'ReloadHandler.reload: running, reloading...')
             self.restart()
 
 class InitdHandler(ServiceHandler):
@@ -611,6 +651,7 @@ class InitdHandler(ServiceHandler):
 
     def __init__(self, initd_name=None, initd_dir=None):
         r"Initialize the object, see the class documentation for details."
+        log.debug(u'InitdHandler(%r, %r)', initd_name, initd_dir)
         if initd_name is not None:
             self._initd_name = initd_name
         if initd_dir is not None:
@@ -622,12 +663,16 @@ class InitdHandler(ServiceHandler):
         ServiceHandler.__init__(self, **actions)
 
     def handle_timer(self):
+        # TODO documentation
+        log.debug(u'InitdHandler.handle_timer(): self=%r', self)
         p = subprocess.Popen(('pgrep', '-f', self._initd_name),
                                 stdout=subprocess.PIPE)
         pid = p.communicate()[0]
         if p.returncode == 0 and len(pid) > 0:
+            log.debug(u'InitdHandler.handle_timer: pid present, running')
             self._service_running = True
         else:
+            log.debug(u'InitdHandler.handle_timer: pid absent, NOT running')
             self._service_running = False
 
 class TransactionalHandler(Handler):
@@ -649,18 +694,28 @@ class TransactionalHandler(Handler):
     @handler(u'Commit the changes (reloading the service, if necessary).')
     def commit(self):
         r"commit() -> None :: Commit the changes and reload the service."
+        log.debug(u'TransactionalHandler.commit()')
         if hasattr(self, '_dump'):
+            log.debug(u'TransactionalHandler.commit: _dump() present, '
+                        u'dumping...')
             self._dump()
         unchanged = False
         if hasattr(self, '_write_config'):
+            log.debug(u'TransactionalHandler.commit: _write_config() present, '
+                        u'writing config...')
             unchanged = self._write_config()
         if not unchanged and hasattr(self, 'reload'):
+            log.debug(u'TransactionalHandler.commit: reload() present, and'
+                        u'configuration changed, reloading...')
             self.reload()
 
     @handler(u'Discard all the uncommited changes.')
     def rollback(self):
         r"rollback() -> None :: Discard the changes not yet commited."
+        log.debug(u'TransactionalHandler.reload()')
         if hasattr(self, '_load'):
+            log.debug(u'TransactionalHandler.reload: _load() present, loading'
+                        u'pickled values...')
             self._load()
 
 class ParametersHandler(Handler):
@@ -684,33 +739,41 @@ class ParametersHandler(Handler):
 
     def __init__(self, attr=None):
         r"Initialize the object, see the class documentation for details."
+        log.debug(u'ParametersHandler(%r)', attr)
         if attr is not None:
             self._parameters_attr = attr
 
     @handler(u'Set a service parameter.')
     def set(self, param, value):
         r"set(param, value) -> None :: Set a service parameter."
+        log.debug(u'ParametersHandler.set(%r, %r)', param, value)
         if not param in self.params:
+            log.debug(u'ParametersHandler.set: parameter not found')
             raise ParameterNotFoundError(param)
         self.params[param] = value
         if hasattr(self, '_update'):
+            log.debug(u'ParametersHandler.set: _update found, setting to True')
             self._update = True
 
     @handler(u'Get a service parameter.')
     def get(self, param):
         r"get(param) -> None :: Get a service parameter."
+        log.debug(u'ParametersHandler.get(%r)', param)
         if not param in self.params:
+            log.debug(u'ParametersHandler.get: parameter not found')
             raise ParameterNotFoundError(param)
         return self.params[param]
 
     @handler(u'List all available service parameters.')
     def list(self):
         r"list() -> tuple :: List all the parameter names."
+        log.debug(u'ParametersHandler.list()')
         return self.params.keys()
 
     @handler(u'Get all service parameters, with their values.')
     def show(self):
         r"show() -> (key, value) tuples :: List all the parameters."
+        log.debug(u'ParametersHandler.show()')
         return self.params.items()
 
 class SubHandler(Handler):
@@ -724,6 +787,7 @@ class SubHandler(Handler):
 
     def __init__(self, parent):
         r"Initialize the object, see the class documentation for details."
+        log.debug(u'SubHandler(%r)', parent)
         self.parent = parent
 
 class ContainerSubHandler(SubHandler):
@@ -753,6 +817,7 @@ class ContainerSubHandler(SubHandler):
 
     def __init__(self, parent, attr=None, cls=None):
         r"Initialize the object, see the class documentation for details."
+        log.debug(u'ContainerSubHandler(%r, %r, %r)', parent, attr, cls)
         self.parent = parent
         if attr is not None:
             self._cont_subhandler_attr = attr
@@ -774,17 +839,21 @@ class ContainerSubHandler(SubHandler):
     @handler(u'Add a new item')
     def add(self, *args, **kwargs):
         r"add(...) -> None :: Add an item to the list."
+        log.debug(u'ContainerSubHandler.add(%r, %r)', args, kwargs)
         item = self._cont_subhandler_class(*args, **kwargs)
         if hasattr(item, '_add'):
+            log.debug(u'ContainerSubHandler.add: _add found, setting to True')
             item._add = True
         key = item
         if isinstance(self._attr(), dict):
             key = item.as_tuple()[0]
         # do we have the same item? then raise an error
         if key in self._vattr():
+            log.debug(u'ContainerSubHandler.add: allready exists')
             raise ItemAlreadyExistsError(item)
         # do we have the same item, but logically deleted? then update flags
         if key in self._attr():
+            log.debug(u'ContainerSubHandler.add: was deleted, undeleting it')
             index = key
             if not isinstance(self._attr(), dict):
                 index = self._attr().index(item)
@@ -801,39 +870,51 @@ class ContainerSubHandler(SubHandler):
     @handler(u'Update an item')
     def update(self, index, *args, **kwargs):
         r"update(index, ...) -> None :: Update an item of the container."
+        log.debug(u'ContainerSubHandler.update(%r, %r, %r)',
+                    index, args, kwargs)
         # TODO make it right with metaclasses, so the method is not created
         # unless the update() method really exists.
-        # TODO check if the modified item is the same of an existing one
         if not isinstance(self._attr(), dict):
             index = int(index) # TODO validation
         if not hasattr(self._cont_subhandler_class, 'update'):
+            log.debug(u'ContainerSubHandler.update: update() not found, '
+                        u"can't really update, raising command not found")
             raise CommandNotFoundError(('update',))
         try:
             item = self._vattr()[index]
             item.update(*args, **kwargs)
             if hasattr(item, '_update'):
+                log.debug(u'ContainerSubHandler.update: _update found, '
+                            u'setting to True')
                 item._update = True
         except LookupError:
+            log.debug(u'ContainerSubHandler.update: item not found')
             raise ItemNotFoundError(index)
 
     @handler(u'Delete an item')
     def delete(self, index):
         r"delete(index) -> None :: Delete an item of the container."
+        log.debug(u'ContainerSubHandler.delete(%r)', index)
         if not isinstance(self._attr(), dict):
             index = int(index) # TODO validation
         try:
             item = self._vattr()[index]
             if hasattr(item, '_delete'):
+                log.debug(u'ContainerSubHandler.delete: _delete found, '
+                            u'setting to True')
                 item._delete = True
             else:
                 del self._attr()[index]
             return item
         except LookupError:
+            log.debug(u'ContainerSubHandler.delete: item not found')
             raise ItemNotFoundError(index)
 
     @handler(u'Remove all items (use with care).')
     def clear(self):
         r"clear() -> None :: Delete all items of the container."
+        log.debug(u'ContainerSubHandler.clear()')
+        # FIXME broken really, no _delete attribute is setted :S
         if isinstance(self._attr(), dict):
             self._attr.clear()
         else:
@@ -842,16 +923,19 @@ class ContainerSubHandler(SubHandler):
     @handler(u'Get information about an item')
     def get(self, index):
         r"get(index) -> item :: List all the information of an item."
+        log.debug(u'ContainerSubHandler.get(%r)', index)
         if not isinstance(self._attr(), dict):
             index = int(index) # TODO validation
         try:
             return self._vattr()[index]
         except LookupError:
+            log.debug(u'ContainerSubHandler.get: item not found')
             raise ItemNotFoundError(index)
 
     @handler(u'Get information about all items')
     def show(self):
         r"show() -> list of items :: List all the complete items information."
+        log.debug(u'ContainerSubHandler.show()')
         if isinstance(self._attr(), dict):
             return self._attr().values()
         return self._vattr()
@@ -866,6 +950,7 @@ class ListSubHandler(ContainerSubHandler):
     @handler(u'Get how many items are in the list')
     def len(self):
         r"len() -> int :: Get how many items are in the list."
+        log.debug(u'ListContainerSubHandler.len()')
         return len(self._vattr())
 
 class DictSubHandler(ContainerSubHandler):
@@ -878,6 +963,7 @@ class DictSubHandler(ContainerSubHandler):
     @handler(u'List all the items by key')
     def list(self):
         r"list() -> tuple :: List all the item keys."
+        log.debug(u'DictContainerSubHandler.list()')
         return self._attr().keys()
 
 class ComposedSubHandler(SubHandler):
@@ -921,6 +1007,8 @@ class ComposedSubHandler(SubHandler):
 
     def __init__(self, parent, cont=None, attr=None, cls=None):
         r"Initialize the object, see the class documentation for details."
+        log.debug(u'ComposedSubHandler(%r, %r, %r, %r)',
+                    parent, cont, attr, cls)
         self.parent = parent
         if cont is not None:
             self._comp_subhandler_cont = cont
@@ -947,19 +1035,24 @@ class ComposedSubHandler(SubHandler):
     @handler(u'Add a new item')
     def add(self, cont, *args, **kwargs):
         r"add(cont, ...) -> None :: Add an item to the list."
+        log.debug(u'ComposedSubHandler.add(%r, %r, %r)', cont, args, kwargs)
         if not cont in self._cont():
+            log.debug(u'ComposedSubHandler.add: container not found')
             raise ContainerNotFoundError(cont)
         item = self._comp_subhandler_class(*args, **kwargs)
         if hasattr(item, '_add'):
+            log.debug(u'ComposedSubHandler.add: _add found, setting to True')
             item._add = True
         key = item
         if isinstance(self._attr(cont), dict):
             key = item.as_tuple()[0]
         # do we have the same item? then raise an error
         if key in self._vattr(cont):
+            log.debug(u'ComposedSubHandler.add: allready exists')
             raise ItemAlreadyExistsError(item)
         # do we have the same item, but logically deleted? then update flags
         if key in self._attr(cont):
+            log.debug(u'ComposedSubHandler.add: was deleted, undeleting it')
             index = key
             if not isinstance(self._attr(cont), dict):
                 index = self._attr(cont).index(item)
@@ -973,6 +1066,8 @@ class ComposedSubHandler(SubHandler):
             else:
                 self._attr(cont).append(item)
         if hasattr(self._cont()[cont], '_update'):
+            log.debug(u"ComposedSubHandler.add: container's _update found, "
+                        u'setting to True')
             self._cont()[cont]._update = True
 
     @handler(u'Update an item')
@@ -980,46 +1075,66 @@ class ComposedSubHandler(SubHandler):
         r"update(cont, index, ...) -> None :: Update an item of the container."
         # TODO make it right with metaclasses, so the method is not created
         # unless the update() method really exists.
-        # TODO check if the modified item is the same of an existing one
+        log.debug(u'ComposedSubHandler.update(%r, %r, %r, %r)',
+                    cont, index, args, kwargs)
         if not cont in self._cont():
+            log.debug(u'ComposedSubHandler.add: container not found')
             raise ContainerNotFoundError(cont)
         if not isinstance(self._attr(cont), dict):
             index = int(index) # TODO validation
         if not hasattr(self._comp_subhandler_class, 'update'):
+            log.debug(u'ComposedSubHandler.update: update() not found, '
+                        u"can't really update, raising command not found")
             raise CommandNotFoundError(('update',))
         try:
             item = self._vattr(cont)[index]
             item.update(*args, **kwargs)
             if hasattr(item, '_update'):
+                log.debug(u'ComposedSubHandler.update: _update found, '
+                            u'setting to True')
                 item._update = True
             if hasattr(self._cont()[cont], '_update'):
+                log.debug(u"ComposedSubHandler.add: container's _update found, "
+                            u'setting to True')
                 self._cont()[cont]._update = True
         except LookupError:
+            log.debug(u'ComposedSubHandler.update: item not found')
             raise ItemNotFoundError(index)
 
     @handler(u'Delete an item')
     def delete(self, cont, index):
         r"delete(cont, index) -> None :: Delete an item of the container."
+        log.debug(u'ComposedSubHandler.delete(%r, %r)', cont, index)
         if not cont in self._cont():
+            log.debug(u'ComposedSubHandler.add: container not found')
             raise ContainerNotFoundError(cont)
         if not isinstance(self._attr(cont), dict):
             index = int(index) # TODO validation
         try:
             item = self._vattr(cont)[index]
             if hasattr(item, '_delete'):
+                log.debug(u'ComposedSubHandler.delete: _delete found, '
+                            u'setting to True')
                 item._delete = True
             else:
                 del self._attr(cont)[index]
             if hasattr(self._cont()[cont], '_update'):
+                log.debug(u"ComposedSubHandler.add: container's _update found, "
+                            u'setting to True')
                 self._cont()[cont]._update = True
             return item
         except LookupError:
+            log.debug(u'ComposedSubHandler.delete: item not found')
             raise ItemNotFoundError(index)
 
     @handler(u'Remove all items (use with care).')
     def clear(self, cont):
         r"clear(cont) -> None :: Delete all items of the container."
+        # FIXME broken really, no item or container _delete attribute is
+        #       setted :S
+        log.debug(u'ComposedSubHandler.clear(%r)', cont)
         if not cont in self._cont():
+            log.debug(u'ComposedSubHandler.add: container not found')
             raise ContainerNotFoundError(cont)
         if isinstance(self._attr(cont), dict):
             self._attr(cont).clear()
@@ -1029,19 +1144,24 @@ class ComposedSubHandler(SubHandler):
     @handler(u'Get information about an item')
     def get(self, cont, index):
         r"get(cont, index) -> item :: List all the information of an item."
+        log.debug(u'ComposedSubHandler.get(%r, %r)', cont, index)
         if not cont in self._cont():
+            log.debug(u'ComposedSubHandler.add: container not found')
             raise ContainerNotFoundError(cont)
         if not isinstance(self._attr(cont), dict):
             index = int(index) # TODO validation
         try:
             return self._vattr(cont)[index]
         except LookupError:
+            log.debug(u'ComposedSubHandler.get: item not found')
             raise ItemNotFoundError(index)
 
     @handler(u'Get information about all items')
     def show(self, cont):
         r"show(cont) -> list of items :: List all the complete items information."
+        log.debug(u'ComposedSubHandler.show(%r)', cont)
         if not cont in self._cont():
+            log.debug(u'ComposedSubHandler.add: container not found')
             raise ContainerNotFoundError(cont)
         if isinstance(self._attr(cont), dict):
             return self._attr(cont).values()
@@ -1057,6 +1177,7 @@ class ListComposedSubHandler(ComposedSubHandler):
     @handler(u'Get how many items are in the list')
     def len(self, cont):
         r"len(cont) -> int :: Get how many items are in the list."
+        log.debug(u'ListComposedSubHandler.len(%r)', cont)
         if not cont in self._cont():
             raise ContainerNotFoundError(cont)
         return len(self._vattr(cont))
@@ -1071,6 +1192,7 @@ class DictComposedSubHandler(ComposedSubHandler):
     @handler(u'List all the items by key')
     def list(self, cont):
         r"list(cont) -> tuple :: List all the item keys."
+        log.debug(u'DictComposedSubHandler.list(%r)', cont)
         if not cont in self._cont():
             raise ContainerNotFoundError(cont)
         return self._attr(cont).keys()
@@ -1078,6 +1200,12 @@ class DictComposedSubHandler(ComposedSubHandler):
 
 if __name__ == '__main__':
 
+    logging.basicConfig(
+        level   = logging.DEBUG,
+        format  = '%(asctime)s %(levelname)-8s %(message)s',
+        datefmt = '%H:%M:%S',
+    )
+
     import sys
 
     # Execution tests
index d25164032323face72f1f5f990532c2ffa3222e6..3b5046efbf5626cd1af7dccaf64a9d0ab936fd4d 100644 (file)
@@ -3,6 +3,7 @@
 import os
 import signal
 from os import path
+import logging ; log = logging.getLogger('pymin.services.vpn')
 
 
 from pymin.seqtools import Sequence
@@ -79,7 +80,8 @@ class VpnHandler(Restorable, ConfigWriter,
     _config_writer_tpl_dir = path.join(path.dirname(__file__), 'templates')
 
     def __init__(self,  pickle_dir='.', config_dir='/etc/tinc'):
-        DictSubHandler.__init__(self,self)
+        log.debug(u'VpnHandler(%r, %r)', pickle_dir, config_dir)
+        DictSubHandler.__init__(self, self)
         self._config_writer_cfg_dir = config_dir
         self._persistent_dir = pickle_dir
         self._config_build_templates()
@@ -88,75 +90,108 @@ class VpnHandler(Restorable, ConfigWriter,
 
     @handler('usage : add <vpn_name> <vpn_dst> <vpn_src_ip> <vpn_src_mask>')
     def add(self, vpn_src, vpn_dst, vpn_src_ip, vpn_src_mask):
-        if not vpn_src in self.vpns:
-            DictSubHandler.add(self,  vpn_src, vpn_dst, vpn_src_ip, vpn_src_mask, None, None)
-        elif vpn_src in self.vpns:
-            if self.vpns[vpn_src].dele :
+        log.debug(u'VpnHandler.add(%r, %r, %r, %r)', vpn_src, vpn_dst,
+                    vpn_src_ip, vpn_src_mask)
+        if vpn_src in self.vpns:
+            if self.vpns[vpn_src].dele:
+                log.debug(u'VpnHandler.add: deleted, undeleting')
                 self.vpns[vpn_src] = False
+        else:
+            DictSubHandler.add(self, vpn_src, vpn_dst, vpn_src_ip,
+                                vpn_src_mask, None, None)
 
     @handler('usage : delete <vpn_name>')
     def delete(self, vpn_src):
+        log.debug(u'VpnHandler.delete(%r)', vpn_src)
         if vpn_src in self.vpns:
             self.vpns[vpn_src].dele = True;
 
 
     @handler('usage: start <vpn_name>')
     def start(self, vpn_src):
+        log.debug(u'VpnHandler.start(%r)', vpn_src)
         if vpn_src in self.vpns:
             call(('tincd','--net='+ vpn_src))
 
     @handler('usage: stop <vpn_name>')
     def stop(self, vpn_src):
+        log.debug(u'VpnHandler.stop(%r)', vpn_src)
         if vpn_src in self.vpns:
-            if path.exists('/var/run/tinc.' + vpn_src + '.pid'):
-                pid = file('/var/run/tinc.' + vpn_src + '.pid').readline()
+            pid_file = '/var/run/tinc.' + vpn_src + '.pid'
+            log.debug(u'VpnHandler.stop: getting pid from %r', pid_file)
+            if path.exists(pid_file):
+                pid = file(pid_file).readline()
+                pid = int(pid.strip())
                 try:
-                    os.kill(int(pid.strip()), signal.SIGTERM)
+                    log.debug(u'VpnHandler.stop: killing pid %r', pid)
+                    os.kill(pid, signal.SIGTERM)
                 except OSError:
-                    pass # XXX report error?
+                    log.debug(u'VpnHandler.stop: error killing: %r', e)
+            else:
+                log.debug(u'VpnHandler.stop: pid file not found')
 
     def _write_config(self):
+        log.debug(u'VpnHandler._write_config()')
         for v in self.vpns.values():
+            log.debug(u'VpnHandler._write_config: processing %r', v)
             #chek whether it's been created or not.
             if not v.dele:
-                if v.pub_key is None :
+                if v.pub_key is None:
+                    log.debug(u'VpnHandler._write_config: new VPN, generating '
+                                'key...')
                     try:
-                        print 'douugh'
+                        log.debug(u'VpnHandler._write_config: creating dir %r',
+                                    path.join(self._config_writer_cfg_dir,
+                                                v.vpn_src ,'hosts'))
                         #first create the directory for the vpn
-                        call(('mkdir','-p', path.join(self._config_writer_cfg_dir, v.vpn_src ,'hosts')))
+                        call(('mkdir', '-p', path.join(
+                                            self._config_writer_cfg_dir,
+                                            v.vpn_src, 'hosts')))
                         #this command should generate 2 files inside the vpn
                         #dir, one rsa_key.priv and one rsa_key.pub
                         #for some reason debian does not work like this
-                        call(('tincd','-n', v.vpn_src,'-K','<','/dev/null'))
+                        # FIXME if the < /dev/null works, is magic!
+                        log.debug(u'VpnHandler._write_config: creating key...')
+                        call(('tincd', '-n', v.vpn_src, '-K', '<', '/dev/null'))
                         #open the created files and load the keys
-                        f = file(path.join(self._config_writer_cfg_dir, v.vpn_src , 'rsa_key.priv'), 'r')
+                        f = file(path.join(self._config_writer_cfg_dir,
+                                            v.vpn_src, 'rsa_key.priv'), 'r')
                         priv = f.read()
                         f.close()
-                        f = file(path.join(self._config_writer_cfg_dir, v.vpn_src ,'rsa_key.pub'), 'r')
+                        f = file(path.join(self._config_writer_cfg_dir,
+                                            v.vpn_src, 'rsa_key.pub'), 'r')
                         pub = f.read()
                         f.close()
                         v.pub_key = pub
                         v.priv_key = priv
                     except ExecutionError, e:
-                        print e
+                        log.debug(u'VpnHandler._write_config: error executing '
+                                    'the command: %r', e)
 
                 vars = dict(
                     vpn = v,
                 )
-                self._write_single_config('tinc.conf',path.join(v.vpn_src,'tinc.conf'),vars)
-                self._write_single_config('tinc-up',path.join(v.vpn_src,'tinc-up'),vars)
+                self._write_single_config('tinc.conf',
+                                path.join(v.vpn_src, 'tinc.conf'), vars)
+                self._write_single_config('tinc-up',
+                                path.join(v.vpn_src, 'tinc-up'), vars)
                 for h in v.hosts.values():
                     if not h.dele:
                         vars = dict(
                             host = h,
                         )
-                        self._write_single_config('host',path.join(v.vpn_src,'hosts',h.name),vars)
+                        self._write_single_config('host',
+                                path.join(v.vpn_src, 'hosts', h.name), vars)
                     else:
+                        log.debug(u'VpnHandler._write_config: removing...')
                         try:
-                            call(('rm','-f', path.join(v.vpn_src,'hosts',h.name)))
+                            # FIXME use os.unlink()
+                            call(('rm','-f',
+                                    path.join(v.vpn_src, 'hosts', h.name)))
                             del v.hosts[h.name]
                         except ExecutionError, e:
-                            print e
+                            log.debug(u'VpnHandler._write_config: error '
+                                    'removing files: %r', e)
             else:
                 #delete the vpn root at tinc dir
                 if path.exists('/etc/tinc/' + v.vpn_src):
@@ -166,7 +201,16 @@ class VpnHandler(Restorable, ConfigWriter,
 
 
 if __name__ == '__main__':
+
+    logging.basicConfig(
+        level   = logging.DEBUG,
+        format  = '%(asctime)s %(levelname)-8s %(message)s',
+        datefmt = '%H:%M:%S',
+    )
+
     v = VpnHandler()
     v.add('prueba','sarasa','192.168.0.188','255.255.255.0')
-    v.host.add('prueba', 'azazel' ,'192.168.0.77', '192.168.0.0','kjdhfkbdskljvkjblkbjeslkjbvkljbselvslberjhbvslbevlhb')
+    v.host.add('prueba', 'azazel' ,'192.168.0.77', '192.168.0.0',
+                'kjdhfkbdskljvkjblkbjeslkjbvkljbselvslberjhbvslbevlhb')
     v.commit()
+
index 403cd364fdac153229282e8fb6230cc921680eb3..4739c528fc3e874f1299e1301f647826b4e34f9e 100644 (file)
@@ -4,6 +4,7 @@ import os
 from os import path
 from signal import SIGTERM
 from subprocess import Popen, PIPE
+import logging ; log = logging.getLogger('pymin.services.vrrp')
 
 from pymin.seqtools import Sequence
 from pymin.dispatcher import Handler, handler, HandlerError
@@ -29,6 +30,7 @@ class VrrpHandler(Restorable, ParametersHandler, ReloadHandler, RestartHandler,
                             )
 
     def _service_start(self):
+        log.debug(u'VrrpHandler._service_start()')
         if self.params['prio'] != '':
             call(('vrrp', '-i', self.params['dev'], '-v', self.params['id'],
                     '-p', self.params['prio'], self.params['ipaddress']))
@@ -37,22 +39,34 @@ class VrrpHandler(Restorable, ParametersHandler, ReloadHandler, RestartHandler,
                     self.params['ipaddress']))
 
     def _service_stop(self):
+        log.debug(u'VrrpHandler._service_stop()')
         try:
             pid_filename = 'vrrpd_%(dev)s_%(id)s.pid' % self.params
-            pid = file(path.join(self._pid_dir, pid_filename )).read().strip()
-            os.kill(int(pid), SIGTERM)
-        except (IOError, OSError):
-            # TODO log
-            pass
+            log.debug(u'VrrpHandler._service_stop: getting pid from %r',
+                        pid_filename)
+            pid = file(path.join(self._pid_dir, pid_filename )).read()
+            pid = int(pid.strip())
+            log.debug(u'VrrpHandler._service_stop: killing pid %r', pid)
+            os.kill(pid, SIGTERM)
+        except (IOError, OSError), e:
+            log.debug(u'VrrpHandler._service_stop: error %r', e)
 
     def __init__(self, pickle_dir='.', config_dir='.', pid_dir='.'):
+        log.debug(u'VrrpHandler(%r, %r, $r)', pickle_dir, config_dir, pid_dir)
         self._persistent_dir = pickle_dir
         self._pid_dir = pid_dir
         ServiceHandler.__init__(self)
 
 
 if __name__ == '__main__':
+
+    logging.basicConfig(
+        level   = logging.DEBUG,
+        format  = '%(asctime)s %(levelname)-8s %(message)s',
+        datefmt = '%H:%M:%S',
+    )
+
     v = VrrpHandler()
-    v.set('prio','10')
+    v.set('prio', '10')
     v.commit()