]> git.llucax.com Git - software/pymin.git/commitdiff
Merge baryon.com.ar:workspace/pymin
authorNicolas Emiliani <nemiliani@integratech.com.ar>
Sat, 10 Nov 2007 19:56:14 +0000 (16:56 -0300)
committerNicolas Emiliani <nemiliani@integratech.com.ar>
Sat, 10 Nov 2007 19:56:14 +0000 (16:56 -0300)
Conflicts:

config.py

config.py
pymin/eventloop.py
pymin/services/ip/__init__.py
pymin/services/ip/templates/ip_add
pymin/services/ppp/__init__.py
pymin/services/ppp/templates/nameX
pymin/services/util.py
pymin/services/vpn/__init__.py [new file with mode: 0644]
pymin/services/vpn/templates/host [new file with mode: 0644]
pymin/services/vpn/templates/tinc-up [new file with mode: 0644]
pymin/services/vpn/templates/tinc.conf [new file with mode: 0644]

index 57d0f5a2586b92ca42a14b6c2109d5e8d8df6182..b4c454d3bad9dcb52a3488eb7089b5e516686042 100644 (file)
--- a/config.py
+++ b/config.py
@@ -10,31 +10,46 @@ pickle_path = join(base_path, 'pickle')
 config_path = join(base_path, 'config')
 
 class Root(Handler):
-    ip = IpHandler(
-        pickle_dir = join(pickle_path, 'ip'),
-        config_dir = join(config_path, 'ip'))
+
     firewall = FirewallHandler(
         pickle_dir = join(pickle_path, 'firewall'),
-        config_dir = join(config_path, 'firewall'))
+        config_dir = '/tmp')
+
     nat = NatHandler(pickle_dir = join(pickle_path, 'nat'))
+
+    ppp = PppHandler(
+        pickle_dir = join(pickle_path, 'ppp'),
+        config_dir = {
+            'pap-secrets':  '/etc/ppp',
+            'chap-secrets': '/etc/ppp',
+            'options.X':    '/etc/ppp',
+            'nameX':        '/etc/ppp/peers',
+        })
+
+    ip = IpHandler(
+        pickle_dir = join(pickle_path, 'ip'),
+        config_dir = join(config_path, 'ip'))
+
     dns = DnsHandler(
         pickle_dir = join(pickle_path, 'dns'),
         config_dir = {
-            'named.conf': join(config_path, 'dns'),
-            'zoneX.zone': join(config_path, 'dns', 'zones'),
+            'named.conf': '/etc',
+            'zoneX.zone': '/var/lib/named',
         })
+
     dhcp = DhcpHandler(
         pickle_dir = join(pickle_path, 'dhcp'),
-        config_dir = join(config_path, 'dhcp'))
-    ppp = PppHandler(
-        pickle_dir = join(pickle_path, 'ppp'),
-        config_dir = join(config_path, 'ppp'))
-    vrrp = VrrpHandler(
-        pickle_dir = join(pickle_path, 'vrrp'),
-        config_dir = join(config_path, 'vrrp'))
+        config_dir = '/etc')
+
     proxy = ProxyHandler(
         pickle_dir = join(pickle_path, 'proxy'),
         config_dir = join(config_path, 'proxy'))
+
+    vrrp = VrrpHandler(
+        pickle_dir = join(pickle_path, 'vrrp'),
+        config_dir = join(config_path, 'vrrp'),
+        pid_dir    = '/var/run')
+
     qos = QoSHandler(
        pickle_dir = join(pickle_path, 'qos'),
        config_dir = join(config_path, 'qos'))
index b6be5a1003d891b7e857a166b9523647de3a3005..86b89324eae7cfeff644cf1623d02e827185325a 100644 (file)
@@ -147,6 +147,7 @@ class EventLoop:
         # If we use a timer, we set up the signal
         if self.timer is not None:
             signal.signal(signal.SIGALRM, alarm_handler)
+            self.handle_timer()
             signal.alarm(self.timer)
         while True:
             try:
index 560e2f58747af7b498231ca132c5cc72aff726f6..0c0ea5f1457995d51869f0b4c245168ae15b44a8 100644 (file)
@@ -8,7 +8,7 @@ from pymin.dispatcher import handler, HandlerError, Handler
 from pymin.services.util import Restorable, ConfigWriter, InitdHandler, \
                                 TransactionalHandler, SubHandler, call, \
                                 get_network_devices, ListComposedSubHandler, \
-                                DictComposedSubHandler
+                                DictComposedSubHandler, Device, Address, ExecutionError
 
 __ALL__ = ('IpHandler',)
 
@@ -105,16 +105,6 @@ class RouteHandler(ListComposedSubHandler):
     _comp_subhandler_attr = 'routes'
     _comp_subhandler_class = Route
 
-class Address(Sequence):
-    def __init__(self, ip, netmask, broadcast=None):
-        self.ip = ip
-        self.netmask = netmask
-        self.broadcast = broadcast
-    def update(self, netmask=None, broadcast=None):
-        if netmask is not None: self.netmask = netmask
-        if broadcast is not None: self.broadcast = broadcast
-    def as_tuple(self):
-        return (self.ip, self.netmask, self.broadcast)
 
 class AddressHandler(DictComposedSubHandler):
     handler_help = u"Manage IP addresses"
@@ -122,14 +112,6 @@ class AddressHandler(DictComposedSubHandler):
     _comp_subhandler_attr = 'addrs'
     _comp_subhandler_class = Address
 
-class Device(Sequence):
-    def __init__(self, name, mac):
-        self.name = name
-        self.mac = mac
-        self.addrs = dict()
-        self.routes = list()
-    def as_tuple(self):
-        return (self.name, self.mac)
 
 class DeviceHandler(SubHandler):
 
@@ -172,8 +154,7 @@ class IpHandler(Restorable, ConfigWriter, TransactionalHandler):
     _persistent_attrs = ('devices','hops')
 
     _restorable_defaults = dict(
-                            devices=dict((dev, Device(dev, mac))
-                                for (dev, mac) in get_network_devices().items()),
+                            devices=get_network_devices(),
                             hops = list()
                             )
 
@@ -196,34 +177,52 @@ class IpHandler(Restorable, ConfigWriter, TransactionalHandler):
     def _write_config(self):
         r"_write_config() -> None :: Execute all commands."
         for device in self.devices.values():
-            call(self._render_config('route_flush', dict(dev=device.name)), shell=True)
-            call(self._render_config('ip_flush', dict(dev=device.name)), shell=True)
+            try:
+                call(self._render_config('route_flush', dict(dev=device.name)), shell=True)
+            except ExecutionError, e:
+                print e
+            try:
+                call(self._render_config('ip_flush', dict(dev=device.name)), shell=True)
+            except ExecutionError, e:
+                print e
             for address in device.addrs.values():
                 broadcast = address.broadcast
                 if broadcast is None:
                     broadcast = '+'
-                call(self._render_config('ip_add', dict(
+                try:
+                    call(self._render_config('ip_add', dict(
                         dev = device.name,
                         addr = address.ip,
                         netmask = address.netmask,
+                        peer = address.peer,
                         broadcast = broadcast,
-                    )
-                ), shell=True)
+                        )
+                    ), shell=True)
+                except ExecutionError, e:
+                      print e
             for route in device.routes:
-                call(self._render_config('route_add', dict(
-                        dev = device.name,
-                        net_addr = route.net_addr,
-                        prefix = route.prefix,
-                        gateway = route.gateway,
-                    )
-                ), shell=True)
-
+                try:
+                    call(self._render_config('route_add', dict(
+                            dev = device.name,
+                            net_addr = route.net_addr,
+                            prefix = route.prefix,
+                            gateway = route.gateway,
+                        )
+                     ), shell=True)
+                except ExecutionError, e:
+                    print e
         if self.hops:
-            call('ip route del default', shell=True)
-            call(self._render_config('hop', dict(
-                        hops = self.hops,
-                    )
-                 ), shell=True)
+            try:
+                call('ip route del default', shell=True)
+            except ExecutionError, e:
+                print e
+            try:
+                call(self._render_config('hop', dict(
+                    hops = self.hops,
+                        )
+                ), shell=True)
+            except ExecutionError, e:
+                print e
 
 
     def handle_timer(self):
@@ -235,7 +234,7 @@ class IpHandler(Restorable, ConfigWriter, TransactionalHandler):
         #add not registered devices
         for k,v in devices.items():
             if k not in self.devices:
-                self.devices[k] = Device(k,v)
+                self.devices[k] = v
         #delete dead devices
         for k in self.devices.keys():
             if k not in devices:
index d6307b31b6cc90b62085b6dade97d8d93ff606f0..8f5cc15bd062e6b6db07c33f90d5e4dc1ed62bbb 100644 (file)
@@ -1 +1,5 @@
-ip addr add dev ${dev} ${addr}/${netmask} broadcast ${broadcast}
\ No newline at end of file
+%if peer is None:
+ip addr add dev ${dev} ${addr}/${netmask} broadcast ${broadcast}
+%else:
+ip addr add dev ${dev} ${addr} peer ${peer}
+%endif
index caf8f4ed1cd308f3b23525c81a75105dec6ef790..db2a53541857d45f5f9bb4884563c657e81572d6 100644 (file)
@@ -1,6 +1,7 @@
 # vim: set encoding=utf-8 et sw=4 sts=4 :
 
 import os
+import subprocess
 from os import path
 from signal import SIGTERM
 
@@ -120,7 +121,6 @@ class PppHandler(Restorable, ConfigWriter, ReloadHandler, TransactionalHandler):
         for name in names:
             if name in self.conns:
                 if self.conns[name]._running:
-                    call(('poff', name))
                     if path.exists('/var/run/ppp-' + name + '.pid'):
                         pid = file('/var/run/ppp-' + name + '.pid').readline()
                         try:
@@ -162,6 +162,16 @@ class PppHandler(Restorable, ConfigWriter, ReloadHandler, TransactionalHandler):
         else:
             raise ConnectionNotFoundError(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."
         #guardo los pass que van el pap-secrets
index ee70cf118dcd6a845df8455b9e88769436b3f3ab..0e9716e957a17896c32196d37775269dbc42aea2 100644 (file)
@@ -1,6 +1,6 @@
 updetach
 % if conn.type != 'TUNNEL':
-name ${conn.username}
+user ${conn.username}
 file /etc/ppp/options.${conn.name}
 ipparam ${conn.name}
 # pppoe has a lower mtu/mru
@@ -11,6 +11,7 @@ nopcomp
 # this is recommended
 novjccomp
 noccp
+noauth
 % else:
 pty "pptp ${conn.server} --nolaunchpppd"
 name ${conn.username}
index 6e09148f864f471157a11de5bbf225945ffbce21..91d28c3213830bd5064d5c4705bd2a449088e831 100644 (file)
@@ -11,9 +11,10 @@ except ImportError:
 
 from pymin.dispatcher import Handler, handler, HandlerError, \
                                 CommandNotFoundError
+from pymin.seqtools import Sequence
 
-#DEBUG = False
-DEBUG = True
+DEBUG = False
+#DEBUG = True
 
 __ALL__ = ('Error', 'ReturnNot0Error', 'ExecutionError', 'ItemError',
             'ItemAlreadyExistsError', 'ItemNotFoundError', 'ContainerError',
@@ -21,7 +22,7 @@ __ALL__ = ('Error', 'ReturnNot0Error', 'ExecutionError', 'ItemError',
             'Persistent', 'Restorable', 'ConfigWriter', 'ServiceHandler',
             'RestartHandler', 'ReloadHandler', 'InitdHandler', 'SubHandler',
             'DictSubHandler', 'ListSubHandler', 'ComposedSubHandler',
-            'ListComposedSubHandler', 'DictComposedSubHandler')
+            'ListComposedSubHandler', 'DictComposedSubHandler', 'Device','Address')
 
 class Error(HandlerError):
     r"""
@@ -152,6 +153,30 @@ class ContainerNotFoundError(ContainerError):
         r"Initialize the object. See class documentation for more info."
         self.message = u'Container not found: "%s"' % key
 
+class Address(Sequence):
+    def __init__(self, ip, netmask, broadcast=None, peer=None):
+        self.ip = ip
+        self.netmask = netmask
+        self.broadcast = broadcast
+        self.peer = peer
+    def update(self, netmask=None, broadcast=None):
+        if netmask is not None: self.netmask = netmask
+        if broadcast is not None: self.broadcast = broadcast
+    def as_tuple(self):
+        return (self.ip, self.netmask, self.broadcast, self.peer)
+
+
+class Device(Sequence):
+    def __init__(self, name, mac, ppp):
+        self.name = name
+        self.mac = mac
+        self.ppp = ppp
+        self.addrs = dict()
+        self.routes = list()
+    def as_tuple(self):
+        return (self.name, self.mac, self.addrs)
+
+
 
 def get_network_devices():
     p = subprocess.Popen(('ip', '-o', 'link'), stdout=subprocess.PIPE,
@@ -165,16 +190,38 @@ def get_network_devices():
         if dev.find('link/ether') != -1:
             i = dev.find('link/ether')
             mac = dev[i+11 : i+11+17]
-            i = dev.find(':',2)
-            name = dev[3: i]
-            d[name] = mac
+            i = dev.find(':')
+            j = dev.find(':', i+1)
+            name = dev[i+2: j]
+            d[name] = Device(name,mac,False)
         elif dev.find('link/ppp') != -1:
             i = dev.find('link/ppp')
             mac =  '00:00:00:00:00:00'
-            i = dev.find(':',2)
-            name = dev[3 : i]
-            d[name] = mac
+            i = dev.find(':')
+            j = dev.find(':', i+1)
+            name = dev[i+2 : j]
+            d[name] = Device(name,mac,True)
+            #since the device is ppp, get the address and peer
+            try:
+                p = subprocess.Popen(('ip', '-o', 'addr', 'show', name), stdout=subprocess.PIPE,
+                                                        close_fds=True, stderr=subprocess.PIPE)
+                string = p.stdout.read()
+                p.wait()
+                addrs = string.splitlines()
+                inet = addrs[1].find('inet')
+                peer = addrs[1].find('peer')
+                bar = addrs[1].find('/')
+                from_addr = addrs[1][inet+5 : peer-1]
+                to_addr = addrs[1][peer+5 : bar]
+                d[name].addrs[from_addr] = Address(from_addr,24, peer=to_addr)
+            except IndexError:
+                pass
+            
     return d
+       
+def get_peers():
+    p = subprocess.Popen(('ip', '-o', 'addr'), stdout=subprocess.PIPE,
+                                                    close_fds=True)
 
 def call(command, stdin=subprocess.PIPE, stdout=subprocess.PIPE,
             stderr=subprocess.PIPE, close_fds=True, universal_newlines=True,
@@ -185,6 +232,7 @@ def call(command, stdin=subprocess.PIPE, stdout=subprocess.PIPE,
         print 'Executing command:', command
         return
     try:
+        print 'Executing command:', command
         r = subprocess.call(command, stdin=stdin, stdout=stdout, stderr=stderr,
                                 universal_newlines=universal_newlines,
                                 close_fds=close_fds, **kw)
@@ -591,6 +639,15 @@ class InitdHandler(ServiceHandler):
                                 action)
         ServiceHandler.__init__(self, **actions)
 
+    def handle_timer(self):
+        p = subprocess.Popen(('pgrep', '-f', self._initd_name),
+                                stdout=subprocess.PIPE)
+        pid = p.communicate()[0]
+        if p.wait() == 0 and len(pid) > 0:
+            c._service_running = True
+        else:
+            c._service_running = False
+
 class TransactionalHandler(Handler):
     r"""Handle command transactions providing a commit and rollback commands.
 
@@ -1039,6 +1096,8 @@ class DictComposedSubHandler(ComposedSubHandler):
 
 if __name__ == '__main__':
 
+    import sys
+
     # Execution tests
     class STestHandler1(ServiceHandler):
         _service_start = ('service', 'start')
@@ -1141,3 +1200,5 @@ if __name__ == '__main__':
     os.rmdir('templates')
     print
 
+    print get_network_devices()
+
diff --git a/pymin/services/vpn/__init__.py b/pymin/services/vpn/__init__.py
new file mode 100644 (file)
index 0000000..789d137
--- /dev/null
@@ -0,0 +1,171 @@
+# vim: set encoding=utf-8 et sw=4 sts=4 :
+
+import os
+from os import path
+
+from pymin.seqtools import Sequence
+from pymin.dispatcher import Handler, handler, HandlerError
+from pymin.services.util import Restorable, ConfigWriter, InitdHandler, \
+                                TransactionalHandler, DictSubHandler, DictComposedSubHandler, call, ExecutionError
+
+
+class Host(Sequence):
+    def __init__(self, vpn_src, ip, vpn_src_net, key):
+        self.name = vpn_src
+        self.ip = ip
+        self.src_net = vpn_src_net
+        self.pub_key = key
+        self.dele = False
+
+    def as_tuple(self):
+        return(self.name, self.ip, self.src_net, self.pub_key)
+
+class HostHandler(DictComposedSubHandler):
+
+    handler_help = u"Manage hosts for a vpn"
+    _comp_subhandler_cont = 'vpns'
+    _comp_subhandler_attr = 'hosts'
+    _comp_subhandler_class = Host
+
+    @handler('usage: add <vpn_src> <ip> <vpn_src_net> <key>')
+    def delete(self, vpn_src, host):
+        DictComposedSubHandler.delete(self, vpn_src, host)
+        if vpn_src in parent.vpns:
+            if host in parent.vpns[vpn_src].hosts:
+                parent.vpns[vpn_src].hosts[host].dele = True
+
+
+class Vpn(Sequence):
+    def __init__(self, vpn_src, vpn_dst, vpn_src_ip, vpn_src_mask, pub_key, priv_key):
+        self.vpn_src = vpn_src
+        self.vpn_dst = vpn_dst
+        self.vpn_src_ip = vpn_src_ip
+        self.vpn_src_mask = vpn_src_mask
+        self.pub_key = pub_key
+        self.priv_key = priv_key
+        self.hosts = dict()
+        self.dele = False
+
+    def as_tuple(self):
+        return(self.vpn_src, self.vpn_dst, self.vpn_src_ip, self.vpn_src_mask, self.pub_key, self.priv_key)
+
+    def update(self, vpn_dst=None, vpn_src_ip=None, vpn_src_mask=None):
+        if vpn_dst is not None:
+            self.vpn_dst = vpn_dst
+        if vpn_src_ip is not None:
+            self.vpn_src_ip = vpn_src_ip
+        if vpn_src_mask is not None:
+            self.vpn_src_mask = vpn_src_mask
+
+
+class VpnHandler(Restorable, ConfigWriter,
+                   TransactionalHandler, DictSubHandler):
+
+    handler_help = u"Manage vpn service"
+
+    _cont_subhandler_attr = 'vpns'
+    _cont_subhandler_class = Vpn
+
+    _persistent_attrs = ('vpns','hosts')
+
+    _restorable_defaults = dict(
+            vpns = dict(),
+            hosts = dict(),
+    )
+
+    _config_writer_files = ('tinc.conf','tinc-up','host')
+    _config_writer_tpl_dir = path.join(path.dirname(__file__), 'templates')
+
+    def __init__(self,  pickle_dir='.', config_dir='/etc/tinc'):
+        DictSubHandler.__init__(self,self)
+        self._config_writer_cfg_dir = config_dir
+        self._persistent_dir = pickle_dir
+        self._config_build_templates()
+        self._restore()
+        self.host = HostHandler(self)
+
+    @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 :
+                self.vpns[vpn_src] = False
+
+    @handler('usage : delete <vpn_name>')
+    def delete(self, vpn_src):
+        if vpn_src in self.vpns:
+            self.vpns[vpn_src].dele = True;
+
+
+    @handler('usage: start <vpn_name>')
+    def start(self, vpn_src):
+        if vpn_src in self.vpns:
+            call(('tincd','--net=',vpn_src))
+
+    @handler('usage: stop <vpn_name>')
+    def stop(self, vpn_src):
+        if vpn_src in self.vpns:
+            if path.exists('/var/lib/run/tincd.' + vpn_src + '.pid'):
+                pid = file('/var/lib/run/tincd.' + vpn_src + '.pid').readline()
+                try:
+                    os.kill(int(pid.strip()), SIGTERM)
+                except OSError:
+                    pass # XXX report error?
+
+    def _write_config(self):
+        for v in self.vpns.values():
+            #chek whether it's been created or not.
+            if not v.dele:
+                if v.pub_key is None :
+                    try:
+                        print 'douugh'
+                        #first create the directory for the vpn
+                        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'))
+                        #open the created files and load the keys
+                        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')
+                        pub = f.read()
+                        f.close()
+                        v.pub_key = pub
+                        v.priv_key = priv
+                    except ExecutionError, e:
+                        print 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)
+                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)
+                    else:
+                        try:
+                            call(('rm','-f', path.join(v.vpn_src,'hosts',h.name)))
+                            del v.hosts[h.name]
+                        except ExecutionError, e:
+                            print e
+            else:
+                #delete the vpn root at tinc dir
+                if path.exists('/etc/tinc/' + v.vpn_src):
+                    self.stop(v.vpn_src)
+                    call(('rm','-rf','/etc/tinc/' + v.vpn_src))
+                    del self.vpns[v.vpn_src]
+
+
+if __name__ == '__main__':
+    v = VpnHandler()
+    v.add('test','127.0.0.1','192.168.0.1','255.255.255.0')
+    #v.host.add('test', 'sarasa' ,'127.0.0.1', '205.25.36.36','kjdhfkbdskljvkjblkbjeslkjbvkljbselvslberjhbvslbevlhb')
+    v.delete('test')
+    v.commit()
diff --git a/pymin/services/vpn/templates/host b/pymin/services/vpn/templates/host
new file mode 100644 (file)
index 0000000..c2a2acb
--- /dev/null
@@ -0,0 +1,3 @@
+Address = ${host.ip}
+Subnet = ${host.src_net}
+${host.pub_key}
diff --git a/pymin/services/vpn/templates/tinc-up b/pymin/services/vpn/templates/tinc-up
new file mode 100644 (file)
index 0000000..fa9b987
--- /dev/null
@@ -0,0 +1 @@
+ifconfig $INTERFACE ${vpn.vpn_src_ip} netmask ${vpn.vpn_src_mask}
diff --git a/pymin/services/vpn/templates/tinc.conf b/pymin/services/vpn/templates/tinc.conf
new file mode 100644 (file)
index 0000000..a3e45ff
--- /dev/null
@@ -0,0 +1,4 @@
+Name = ${vpn.vpn_src}
+Device = /dev/net/tun
+PrivateKeyFile = /etc/tinc/${vpn.vpn_src}/rsa_key.priv
+ConnectTo = ${vpn.vpn_dst}