1 # vim: set encoding=utf-8 et sw=4 sts=4 :
6 import logging ; log = logging.getLogger('pymin.services.vpn')
9 from pymin.seqtools import Sequence
10 from pymin.dispatcher import Handler, handler, HandlerError
11 from pymin.services.util import Restorable, ConfigWriter, InitdHandler, \
12 TransactionalHandler, DictSubHandler, DictComposedSubHandler, call, ExecutionError
16 def __init__(self, vpn_src, ip, vpn_src_net, key):
19 self.src_net = vpn_src_net
24 return(self.name, self.ip, self.src_net, self.pub_key)
26 class HostHandler(DictComposedSubHandler):
28 handler_help = u"Manage hosts for a vpn"
29 _comp_subhandler_cont = 'vpns'
30 _comp_subhandler_attr = 'hosts'
31 _comp_subhandler_class = Host
33 @handler('usage: add <vpn_src> <ip> <vpn_src_net> <key>')
34 def delete(self, vpn_src, host):
35 DictComposedSubHandler.delete(self, vpn_src, host)
36 if vpn_src in parent.vpns:
37 if host in parent.vpns[vpn_src].hosts:
38 parent.vpns[vpn_src].hosts[host].dele = True
42 def __init__(self, vpn_src, vpn_dst, vpn_src_ip, vpn_src_mask, pub_key, priv_key):
43 self.vpn_src = vpn_src
44 self.vpn_dst = vpn_dst
45 self.vpn_src_ip = vpn_src_ip
46 self.vpn_src_mask = vpn_src_mask
47 self.pub_key = pub_key
48 self.priv_key = priv_key
53 return(self.vpn_src, self.vpn_dst, self.vpn_src_ip, self.vpn_src_mask, self.pub_key, self.priv_key)
55 def update(self, vpn_dst=None, vpn_src_ip=None, vpn_src_mask=None):
56 if vpn_dst is not None:
57 self.vpn_dst = vpn_dst
58 if vpn_src_ip is not None:
59 self.vpn_src_ip = vpn_src_ip
60 if vpn_src_mask is not None:
61 self.vpn_src_mask = vpn_src_mask
64 class VpnHandler(Restorable, ConfigWriter,
65 TransactionalHandler, DictSubHandler):
67 handler_help = u"Manage vpn service"
69 _cont_subhandler_attr = 'vpns'
70 _cont_subhandler_class = Vpn
72 _persistent_attrs = ('vpns','hosts')
74 _restorable_defaults = dict(
79 _config_writer_files = ('tinc.conf','tinc-up','host')
80 _config_writer_tpl_dir = path.join(path.dirname(__file__), 'templates')
82 def __init__(self, pickle_dir='.', config_dir='/etc/tinc'):
83 log.debug(u'VpnHandler(%r, %r)', pickle_dir, config_dir)
84 DictSubHandler.__init__(self, self)
85 self._config_writer_cfg_dir = config_dir
86 self._persistent_dir = pickle_dir
87 self._config_build_templates()
89 self.host = HostHandler(self)
91 @handler('usage : add <vpn_name> <vpn_dst> <vpn_src_ip> <vpn_src_mask>')
92 def add(self, vpn_src, vpn_dst, vpn_src_ip, vpn_src_mask):
93 log.debug(u'VpnHandler.add(%r, %r, %r, %r)', vpn_src, vpn_dst,
94 vpn_src_ip, vpn_src_mask)
95 if vpn_src in self.vpns:
96 if self.vpns[vpn_src].dele:
97 log.debug(u'VpnHandler.add: deleted, undeleting')
98 self.vpns[vpn_src] = False
100 DictSubHandler.add(self, vpn_src, vpn_dst, vpn_src_ip,
101 vpn_src_mask, None, None)
103 @handler('usage : delete <vpn_name>')
104 def delete(self, vpn_src):
105 log.debug(u'VpnHandler.delete(%r)', vpn_src)
106 if vpn_src in self.vpns:
107 self.vpns[vpn_src].dele = True;
110 @handler('usage: start <vpn_name>')
111 def start(self, vpn_src):
112 log.debug(u'VpnHandler.start(%r)', vpn_src)
113 if vpn_src in self.vpns:
114 call(('tincd','--net='+ vpn_src))
116 @handler('usage: stop <vpn_name>')
117 def stop(self, vpn_src):
118 log.debug(u'VpnHandler.stop(%r)', vpn_src)
119 if vpn_src in self.vpns:
120 pid_file = '/var/run/tinc.' + vpn_src + '.pid'
121 log.debug(u'VpnHandler.stop: getting pid from %r', pid_file)
122 if path.exists(pid_file):
123 pid = file(pid_file).readline()
124 pid = int(pid.strip())
126 log.debug(u'VpnHandler.stop: killing pid %r', pid)
127 os.kill(pid, signal.SIGTERM)
129 log.debug(u'VpnHandler.stop: error killing: %r', e)
131 log.debug(u'VpnHandler.stop: pid file not found')
133 def _write_config(self):
134 log.debug(u'VpnHandler._write_config()')
135 for v in self.vpns.values():
136 log.debug(u'VpnHandler._write_config: processing %r', v)
137 #chek whether it's been created or not.
139 if v.pub_key is None:
140 log.debug(u'VpnHandler._write_config: new VPN, generating '
143 log.debug(u'VpnHandler._write_config: creating dir %r',
144 path.join(self._config_writer_cfg_dir,
146 #first create the directory for the vpn
147 call(('mkdir', '-p', path.join(
148 self._config_writer_cfg_dir,
149 v.vpn_src, 'hosts')))
150 #this command should generate 2 files inside the vpn
151 #dir, one rsa_key.priv and one rsa_key.pub
152 #for some reason debian does not work like this
153 # FIXME if the < /dev/null works, is magic!
154 log.debug(u'VpnHandler._write_config: creating key...')
155 call(('tincd', '-n', v.vpn_src, '-K', '<', '/dev/null'))
156 #open the created files and load the keys
157 f = file(path.join(self._config_writer_cfg_dir,
158 v.vpn_src, 'rsa_key.priv'), 'r')
161 f = file(path.join(self._config_writer_cfg_dir,
162 v.vpn_src, 'rsa_key.pub'), 'r')
167 except ExecutionError, e:
168 log.debug(u'VpnHandler._write_config: error executing '
169 'the command: %r', e)
174 self._write_single_config('tinc.conf',
175 path.join(v.vpn_src, 'tinc.conf'), vars)
176 self._write_single_config('tinc-up',
177 path.join(v.vpn_src, 'tinc-up'), vars)
178 for h in v.hosts.values():
183 self._write_single_config('host',
184 path.join(v.vpn_src, 'hosts', h.name), vars)
186 log.debug(u'VpnHandler._write_config: removing...')
188 # FIXME use os.unlink()
190 path.join(v.vpn_src, 'hosts', h.name)))
192 except ExecutionError, e:
193 log.debug(u'VpnHandler._write_config: error '
194 'removing files: %r', e)
196 #delete the vpn root at tinc dir
197 if path.exists('/etc/tinc/' + v.vpn_src):
199 call(('rm','-rf','/etc/tinc/' + v.vpn_src))
200 del self.vpns[v.vpn_src]
203 if __name__ == '__main__':
206 level = logging.DEBUG,
207 format = '%(asctime)s %(levelname)-8s %(message)s',
208 datefmt = '%H:%M:%S',
212 v.add('prueba','sarasa','192.168.0.188','255.255.255.0')
213 v.host.add('prueba', 'azazel' ,'192.168.0.77', '192.168.0.0',
214 'kjdhfkbdskljvkjblkbjeslkjbvkljbselvslberjhbvslbevlhb')