]> git.llucax.com Git - software/pymin.git/blob - services/vpn/handler.py
Remove plug-in code from handler module in services (refs #27).
[software/pymin.git] / services / vpn / handler.py
1 # vim: set encoding=utf-8 et sw=4 sts=4 :
2
3 import os
4 import errno
5 import signal
6 from os import path
7 import logging ; log = logging.getLogger('pymin.services.vpn')
8
9 from pymin.seqtools import Sequence
10 from pymin.dispatcher import Handler, handler, HandlerError
11 from pymin.service.util import Restorable, ConfigWriter, InitdHandler, \
12                                TransactionalHandler, DictSubHandler, DictComposedSubHandler, call, ExecutionError
13
14 __all__ = ('VpnHandler')
15
16
17 class Host(Sequence):
18     def __init__(self, vpn_src, ip, vpn_src_net, key):
19         self.name = vpn_src
20         self.ip = ip
21         self.src_net = vpn_src_net
22         self.pub_key = key
23         self._delete = False
24
25     def as_tuple(self):
26         return(self.name, self.ip, self.src_net, self.pub_key)
27
28 class HostHandler(DictComposedSubHandler):
29
30     handler_help = u"Manage hosts for a vpn"
31     _comp_subhandler_cont = 'vpns'
32     _comp_subhandler_attr = 'hosts'
33     _comp_subhandler_class = Host
34
35
36 class Vpn(Sequence):
37     def __init__(self, vpn_src, vpn_dst, vpn_src_ip, vpn_src_mask,
38                     pub_key=None, priv_key=None):
39         self.vpn_src = vpn_src
40         self.vpn_dst = vpn_dst
41         self.vpn_src_ip = vpn_src_ip
42         self.vpn_src_mask = vpn_src_mask
43         self.pub_key = pub_key
44         self.priv_key = priv_key
45         self.hosts = dict()
46         self._delete = False
47
48     def as_tuple(self):
49         return(self.vpn_src, self.vpn_dst, self.vpn_src_ip, self.vpn_src_mask, self.pub_key, self.priv_key)
50
51     def update(self, vpn_dst=None, vpn_src_ip=None, vpn_src_mask=None):
52         if vpn_dst is not None:
53             self.vpn_dst = vpn_dst
54         if vpn_src_ip is not None:
55             self.vpn_src_ip = vpn_src_ip
56         if vpn_src_mask is not None:
57             self.vpn_src_mask = vpn_src_mask
58
59
60 class VpnHandler(Restorable, ConfigWriter,
61                    TransactionalHandler, DictSubHandler):
62
63     handler_help = u"Manage vpn service"
64
65     _cont_subhandler_attr = 'vpns'
66     _cont_subhandler_class = Vpn
67
68     _persistent_attrs = ('vpns','hosts')
69
70     _restorable_defaults = dict(
71             vpns = dict(),
72             hosts = dict(),
73     )
74
75     _config_writer_files = ('tinc.conf','tinc-up','host')
76     _config_writer_tpl_dir = path.join(path.dirname(__file__), 'templates')
77
78     def __init__(self,  pickle_dir='.', config_dir='/etc/tinc'):
79         log.debug(u'VpnHandler(%r, %r)', pickle_dir, config_dir)
80         DictSubHandler.__init__(self, self)
81         self._config_writer_cfg_dir = config_dir
82         self._persistent_dir = pickle_dir
83         self._config_build_templates()
84         self._restore()
85         self.host = HostHandler(self)
86
87     @handler('usage: start <vpn_name>')
88     def start(self, vpn_src):
89         log.debug(u'VpnHandler.start(%r)', vpn_src)
90         if vpn_src in self.vpns:
91             call(('tincd','--net='+ vpn_src))
92
93     @handler('usage: stop <vpn_name>')
94     def stop(self, vpn_src):
95         log.debug(u'VpnHandler.stop(%r)', vpn_src)
96         if vpn_src in self.vpns:
97             pid_file = '/var/run/tinc.' + vpn_src + '.pid'
98             log.debug(u'VpnHandler.stop: getting pid from %r', pid_file)
99             if path.exists(pid_file):
100                 pid = file(pid_file).readline()
101                 pid = int(pid.strip())
102                 try:
103                     log.debug(u'VpnHandler.stop: killing pid %r', pid)
104                     os.kill(pid, signal.SIGTERM)
105                 except OSError:
106                     log.debug(u'VpnHandler.stop: error killing: %r', e)
107             else:
108                 log.debug(u'VpnHandler.stop: pid file not found')
109
110     def _write_config(self):
111         log.debug(u'VpnHandler._write_config()')
112         for v in self.vpns.values():
113             log.debug(u'VpnHandler._write_config: processing %r', v)
114             #chek whether it's been created or not.
115             if not v._delete:
116                 if v.pub_key is None:
117                     log.debug(u'VpnHandler._write_config: new VPN, generating '
118                                 'key...')
119                     try:
120                         log.debug(u'VpnHandler._write_config: creating dir %r',
121                                     path.join(self._config_writer_cfg_dir,
122                                                 v.vpn_src ,'hosts'))
123                         #first create the directory for the vpn
124                         try:
125                             os.makedirs(path.join(self._config_writer_cfg_dir,
126                                                   v.vpn_src, 'hosts'))
127                         except (IOError, OSError), e:
128                             if e.errno != errno.EEXIST:
129                                 raise HandlerError(u"Can't create VPN config "
130                                                    "directory '%s' (%s)'"
131                                                     % (e.filename, e.strerror))
132                         #this command should generate 2 files inside the vpn
133                         #dir, one rsa_key.priv and one rsa_key.pub
134                         #for some reason debian does not work like this
135                         # FIXME if the < /dev/null works, is magic!
136                         log.debug(u'VpnHandler._write_config: creating key...')
137                         call(('tincd', '-n', v.vpn_src, '-K', '<', '/dev/null'))
138                         #open the created files and load the keys
139                         try:
140                             f = file(path.join(self._config_writer_cfg_dir,
141                                                v.vpn_src, 'rsa_key.pub'),
142                                      'r')
143                             pub = f.read()
144                             f.close()
145                         except (IOError, OSError), e:
146                             raise HandlerError(u"Can't read VPN key '%s' (%s)'"
147                                                 % (e.filename, e.strerror))
148
149                         v.pub_key = pub
150                         v.priv_key = priv
151                     except ExecutionError, e:
152                         log.debug(u'VpnHandler._write_config: error executing '
153                                     'the command: %r', e)
154
155                 vars = dict(
156                     vpn = v,
157                 )
158                 self._write_single_config('tinc.conf',
159                                 path.join(v.vpn_src, 'tinc.conf'), vars)
160                 self._write_single_config('tinc-up',
161                                 path.join(v.vpn_src, 'tinc-up'), vars)
162                 for h in v.hosts.values():
163                     if not h._delete:
164                         vars = dict(
165                             host = h,
166                         )
167                         self._write_single_config('host',
168                                 path.join(v.vpn_src, 'hosts', h.name), vars)
169                     else:
170                         log.debug(u'VpnHandler._write_config: removing...')
171                         try:
172                             # FIXME use os.unlink()
173                             call(('rm','-f',
174                                     path.join(v.vpn_src, 'hosts', h.name)))
175                             del v.hosts[h.name]
176                         except ExecutionError, e:
177                             log.debug(u'VpnHandler._write_config: error '
178                                     'removing files: %r', e)
179             else:
180                 #delete the vpn root at tinc dir
181                 if path.exists('/etc/tinc/' + v.vpn_src):
182                     self.stop(v.vpn_src)
183                     call(('rm','-rf','/etc/tinc/' + v.vpn_src))
184                     del self.vpns[v.vpn_src]
185
186
187 if __name__ == '__main__':
188
189     logging.basicConfig(
190         level   = logging.DEBUG,
191         format  = '%(asctime)s %(levelname)-8s %(message)s',
192         datefmt = '%H:%M:%S',
193     )
194
195     v = VpnHandler()
196     v.add('prueba','sarasa','192.168.0.188','255.255.255.0')
197     v.host.add('prueba', 'azazel' ,'192.168.0.77', '192.168.0.0',
198                 'kjdhfkbdskljvkjblkbjeslkjbvkljbselvslberjhbvslbevlhb')
199     v.commit()
200