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