]> git.llucax.com Git - software/pymin.git/blobdiff - pymin/services/ppp/__init__.py
Improve ProcessManager to manage registerable named services.
[software/pymin.git] / pymin / services / ppp / __init__.py
index c57960069f3e2a08e18b37147328726418b36cc4..db2a53541857d45f5f9bb4884563c657e81572d6 100644 (file)
@@ -1,26 +1,18 @@
 # vim: set encoding=utf-8 et sw=4 sts=4 :
 
+import os
+import subprocess
 from os import path
+from signal import SIGTERM
 
 from pymin.seqtools import Sequence
 from pymin.dispatcher import Handler, handler, HandlerError
-from pymin.services.util import Restorable, ConfigWriter \
-                                ,TransactionalHandler, DictSubHandler, call
+from pymin.services.util import Restorable, ConfigWriter, ReloadHandler, \
+                                TransactionalHandler, DictSubHandler, call
 
-__ALL__ = ('PppHandler')
+__ALL__ = ('PppHandler',)
 
-class Error(HandlerError):
-    r"""
-    Error(command) -> Error instance :: Base ConnectionHandler exception class.
-
-    All exceptions raised by the ConnectionHandler inherits from this one, so you can
-    easily catch any ConnectionHandler exception.
-
-    message - A descriptive error message.
-    """
-    pass
-
-class ConnectionError(Error, KeyError):
+class ConnectionError(HandlerError, KeyError):
     r"""
     ConnectionError(hostname) -> ConnectionError instance
 
@@ -38,18 +30,37 @@ class ConnectionNotFoundError(ConnectionError):
 
 class Connection(Sequence):
 
-    def __init__(self, name, dev, username=None, password=None):
+    def __init__(self, name, username, password, type, **kw):
         self.name = name
-        self.dev = dev
         self.username = username
         self.password = password
+        self.type = type
+        self._running = False
+        if type == 'OE':
+            if not 'device' in kw:
+                raise ConnectionError('Bad arguments for type=OE')
+            self.device = kw['device']
+        elif type == 'TUNNEL':
+            if not 'server' in kw:
+                raise ConnectionError('Bad arguments for type=TUNNEL')
+            self.server = kw['server']
+            self.username = self.username.replace('\\','\\\\')
+        elif type == 'PPP':
+            if not 'device' in kw:
+                raise ConnectionError('Bad arguments for type=PPP')
+            self.device = kw['device']
+        else:
+            raise ConnectionError('Bad arguments, unknown or unspecified type')
 
     def as_tuple(self):
-        return (self.name, self.dev, self.username, self.password)
-
-    def update(self, dev=None, username=None, password=None):
-        if dev is not None:
-            self.dev = dev
+        if self.type == 'TUNNEL':
+            return (self.name, self.username, self.password, self.type, self.server)
+        elif self.type == 'PPP' or self.type == 'OE':
+            return (self.name, self.username, self.password, self.type, self.device)
+
+    def update(self, device=None, username=None, password=None):
+        if device is not None:
+            self.device = device
         if username is not None:
             self.username = username
         if password is not None:
@@ -60,20 +71,20 @@ class ConnectionHandler(DictSubHandler):
 
     handler_help = u"Manages connections for the ppp service"
 
-    _dict_subhandler_attr = 'conns'
-    _dict_subhandler_class = Connection
+    _cont_subhandler_attr = 'conns'
+    _cont_subhandler_class = Connection
 
-class PppHandler(Restorable, ConfigWriter, TransactionalHandler):
+class PppHandler(Restorable, ConfigWriter, ReloadHandler, TransactionalHandler):
 
     handler_help = u"Manage ppp service"
 
-    _persistent_attrs = ('conns')
+    _persistent_attrs = ['conns']
 
     _restorable_defaults = dict(
         conns  = dict(),
     )
 
-    _config_writer_files = ('options.X','pap-secrets','nameX')
+    _config_writer_files = ('options.X','pap-secrets','chap-secrets','nameX')
     _config_writer_tpl_dir = path.join(path.dirname(__file__), 'templates')
 
     def __init__(self, pickle_dir='.', config_dir='.'):
@@ -82,34 +93,102 @@ class PppHandler(Restorable, ConfigWriter, TransactionalHandler):
         self._config_writer_cfg_dir = config_dir
         self._config_build_templates()
         self._restore()
+        for conn in self.conns.values():
+            if conn._running:
+                conn._running = False
+                self.start(conn.name)
         self.conn = ConnectionHandler(self)
 
-    @handler('Starts the service')
-    def start(self, name):
+    @handler(u'Start one or all the connections.')
+    def start(self, name=None):
+        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:
+                    call(('pppd', 'call', name))
+                    self.conns[name]._running = True
+                    self._dump_attr('conns')
+            else:
+                raise ConnectionNotFoundError(name)
+
+    @handler(u'Stop one or all the connections.')
+    def stop(self, name=None):
+        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()
+                        try:
+                            os.kill(int(pid.strip()), SIGTERM)
+                        except OSError:
+                            pass # XXX report error?
+                    self.conns[name]._running = False
+                    self._dump_attr('conns')
+            else:
+                raise ConnectionNotFoundError(name)
+
+    @handler(u'Restart one or all the connections (even disconnected ones).')
+    def restart(self, name=None):
+        names = [name]
+        if name is None:
+            names = self.conns.keys()
+        for name in names:
+            self.stop(name)
+            self.start(name)
+
+    @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."
+        names = [name]
+        if name is None:
+            names = self.conns.keys()
+        for name in names:
+            if self.conns[name]._running:
+                self.stop(name)
+                self.start(name)
+
+    @handler(u'Tell if the service is running.')
+    def running(self, name=None):
+        r"reload() -> None :: Reload the configuration of the service."
+        if name is None:
+            return [c.name for c in self.conns.values() if c._running]
         if name in self.conns:
-            #call(('pon', name))
-            print ('pon', name)
+            return int(self.conns[name]._running)
         else:
             raise ConnectionNotFoundError(name)
 
-    @handler('Stops the service')
-    def stop(self, name):
-        if name in self.conns:
-            #call(('poff', name))
-            print ('poff', name)
-        else:
-            raise ConnectionNotFoundError(name)
-
-    @handler('Reloads the service')
-    def reload(self):
-        for conn in self.conns.values():
-            self.stop(conn.name)
-            self.start(conn.name)
+    def handle_timer(self):
+        for c in self.conns.values():
+            p = subprocess.Popen(('pgrep', '-f', 'pppd call ' + c.name),
+                                    stdout=subprocess.PIPE)
+            pid = p.communicate()[0]
+            if p.wait() == 0 and len(pid) > 0:
+                c._running = True
+            else:
+                c._running = False
 
     def _write_config(self):
         r"_write_config() -> None :: Generate all the configuration files."
-        vars = dict(conns=self.conns)
+        #guardo los pass que van el pap-secrets
+        vars_pap = dict()
+        for conn in self.conns.values():
+            if conn.type == 'OE' or conn.type == 'PPP':
+                vars_pap[conn.name] = conn
+        vars = dict(conns=vars_pap)
         self._write_single_config('pap-secrets','pap-secrets',vars)
+        #guardo los pass que van el chap-secrets
+        vars_chap = dict()
+        for conn in self.conns.values():
+            if conn.type == 'TUNNEL' :
+                vars_chap[conn.name] = conn
+        vars = dict(conns=vars_chap)
+        self._write_single_config('chap-secrets','chap-secrets',vars)
+        #guard las conns
         for conn in self.conns.values():
             vars = dict(conn=conn)
             self._write_single_config('nameX',conn.name, vars)
@@ -117,8 +196,12 @@ class PppHandler(Restorable, ConfigWriter, TransactionalHandler):
 
 
 if __name__ == '__main__':
+
     p = PppHandler()
-    p.conn.add('test2','tty2','luca','luca')
+    p.conn.add('ppp_c','nico','nico',type='PPP',device='tty0')
+    p.conn.add('pppoe_c','fede','fede',type='OE',device='tty1')
+    p.conn.add('ppptunnel_c','dominio\luca','luca',type='TUNNEL',server='192.168.0.23')
     p.commit()
     print p.conn.list()
-    print p.conn.show()
\ No newline at end of file
+    print p.conn.show()
+