1 # vim: set encoding=utf-8 et sw=4 sts=4 :
7 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.service.util import Restorable, ConfigWriter, InitdHandler, \
12 TransactionalHandler, DictSubHandler, DictComposedSubHandler, call, ExecutionError
14 __all__ = ('VpnHandler')
18 def __init__(self, vpn_src, ip, vpn_src_net, key):
21 self.src_net = vpn_src_net
26 return(self.name, self.ip, self.src_net, self.pub_key)
28 class HostHandler(DictComposedSubHandler):
30 handler_help = u"Manage hosts for a vpn"
31 _comp_subhandler_cont = 'vpns'
32 _comp_subhandler_attr = 'hosts'
33 _comp_subhandler_class = Host
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
49 return(self.vpn_src, self.vpn_dst, self.vpn_src_ip, self.vpn_src_mask, self.pub_key, self.priv_key)
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
60 class VpnHandler(Restorable, ConfigWriter,
61 TransactionalHandler, DictSubHandler):
63 handler_help = u"Manage vpn service"
65 _cont_subhandler_attr = 'vpns'
66 _cont_subhandler_class = Vpn
68 _persistent_attrs = ('vpns','hosts')
70 _restorable_defaults = dict(
75 _config_writer_files = ('tinc.conf','tinc-up','host')
76 _config_writer_tpl_dir = path.join(path.dirname(__file__), 'templates')
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()
85 self.host = HostHandler(self)
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))
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())
103 log.debug(u'VpnHandler.stop: killing pid %r', pid)
104 os.kill(pid, signal.SIGTERM)
106 log.debug(u'VpnHandler.stop: error killing: %r', e)
108 log.debug(u'VpnHandler.stop: pid file not found')
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.
116 if v.pub_key is None:
117 log.debug(u'VpnHandler._write_config: new VPN, generating '
120 log.debug(u'VpnHandler._write_config: creating dir %r',
121 path.join(self._config_writer_cfg_dir,
123 #first create the directory for the vpn
125 os.makedirs(path.join(self._config_writer_cfg_dir,
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
140 f = file(path.join(self._config_writer_cfg_dir,
141 v.vpn_src, 'rsa_key.pub'),
145 except (IOError, OSError), e:
146 raise HandlerError(u"Can't read VPN key '%s' (%s)'"
147 % (e.filename, e.strerror))
151 except ExecutionError, e:
152 log.debug(u'VpnHandler._write_config: error executing '
153 'the command: %r', e)
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():
167 self._write_single_config('host',
168 path.join(v.vpn_src, 'hosts', h.name), vars)
170 log.debug(u'VpnHandler._write_config: removing...')
172 # FIXME use os.unlink()
174 path.join(v.vpn_src, 'hosts', h.name)))
176 except ExecutionError, e:
177 log.debug(u'VpnHandler._write_config: error '
178 'removing files: %r', e)
180 #delete the vpn root at tinc dir
181 if path.exists('/etc/tinc/' + v.vpn_src):
183 call(('rm','-rf','/etc/tinc/' + v.vpn_src))
184 del self.vpns[v.vpn_src]
187 if __name__ == '__main__':
190 level = logging.DEBUG,
191 format = '%(asctime)s %(levelname)-8s %(message)s',
192 datefmt = '%H:%M:%S',
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')