1 # vim: set encoding=utf-8 et sw=4 sts=4 :
7 import logging ; log = logging.getLogger('pymin.services.vpn')
9 from pymin.validation import Item, Field, HostName, CIDR, Validator
10 from pymin.dispatcher import handler, HandlerError
11 from pymin.service.util import Restorable, ConfigWriter, InitdHandler, \
12 TransactionalHandler, DictSubHandler, \
15 from host import HostHandler
17 __all__ = ('VpnHandler',)
21 name = Field(HostName(not_empty=True))
22 connect_to = Field(HostName(not_empty=True))
23 local_addr = Field(CIDR(not_empty=True))
24 public_key = Field(Validator)
25 private_key = Field(Validator)
27 def __init__(self, *args, **kwargs):
28 Item.__init__(self, *args, **kwargs)
33 class VpnHandler(Restorable, ConfigWriter,
34 TransactionalHandler, DictSubHandler):
36 handler_help = u"Manage vpn service"
38 _cont_subhandler_attr = 'vpns'
39 _cont_subhandler_class = Vpn
41 _persistent_attrs = ('vpns','hosts')
43 _restorable_defaults = dict(
48 _config_writer_files = ('tinc.conf','tinc-up','host')
49 _config_writer_tpl_dir = path.join(path.dirname(__file__), 'templates')
51 def __init__(self, pickle_dir='.', config_dir='/etc/tinc'):
52 log.debug(u'VpnHandler(%r, %r)', pickle_dir, config_dir)
53 DictSubHandler.__init__(self, self)
54 self._config_writer_cfg_dir = config_dir
55 self._persistent_dir = pickle_dir
56 self._config_build_templates()
58 self.host = HostHandler(self)
60 @handler('usage: start <vpn_name>')
61 def start(self, net_name):
62 log.debug(u'VpnHandler.start(%r)', net_name)
63 if net_name in self.vpns:
64 call(('tincd','--net=' + net_name))
66 @handler('usage: stop <vpn_name>')
67 def stop(self, net_name):
68 log.debug(u'VpnHandler.stop(%r)', net_name)
69 if net_name in self.vpns:
70 pid_file = '/var/run/tinc.' + net_name + '.pid'
71 log.debug(u'VpnHandler.stop: getting pid from %r', pid_file)
72 if path.exists(pid_file):
73 pid = file(pid_file).readline()
74 pid = int(pid.strip())
76 log.debug(u'VpnHandler.stop: killing pid %r', pid)
77 os.kill(pid, signal.SIGTERM)
79 log.debug(u'VpnHandler.stop: error killing: %r', e)
81 log.debug(u'VpnHandler.stop: pid file not found')
83 def _write_config(self):
84 log.debug(u'VpnHandler._write_config()')
85 for v in self.vpns.values():
86 log.debug(u'VpnHandler._write_config: processing %r', v)
87 #chek whether it's been created or not.
89 if v.public_key is None:
90 log.debug(u'VpnHandler._write_config: new VPN, generating '
93 log.debug(u'VpnHandler._write_config: creating dir %r',
94 path.join(self._config_writer_cfg_dir,
96 #first create the directory for the vpn
98 os.makedirs(path.join(self._config_writer_cfg_dir,
100 except (IOError, OSError), e:
101 if e.errno != errno.EEXIST:
102 raise HandlerError(u"Can't create VPN config "
103 "directory '%s' (%s)'"
104 % (e.filename, e.strerror))
105 #this command should generate 2 files inside the vpn
106 #dir, one rsa_key.priv and one rsa_key.pub
107 #for some reason debian does not work like this
108 # FIXME if the < /dev/null works, is magic!
109 log.debug(u'VpnHandler._write_config: creating key...')
110 call(('tincd', '-n', v.name, '-K', '<', '/dev/null'))
111 #open the created files and load the keys
113 f = file(path.join(self._config_writer_cfg_dir,
114 v.name, 'rsa_key.pub'),
118 except (IOError, OSError), e:
119 raise HandlerError(u"Can't read VPN key '%s' (%s)'"
120 % (e.filename, e.strerror))
124 except ExecutionError, e:
125 log.debug(u'VpnHandler._write_config: error executing '
126 'the command: %r', e)
128 self._write_single_config('tinc.conf',
129 path.join(v.name, 'tinc.conf'), dict(vpn=v))
130 self._write_single_config('tinc-up',
131 path.join(v.name, 'tinc-up'), dict(vpn=v))
132 for h in v.hosts.values():
134 self._write_single_config('host',
135 path.join(v.name, 'hosts', h.name),
138 log.debug(u'VpnHandler._write_config: removing...')
140 # FIXME use os.unlink()
142 path.join(v.name, 'hosts', h.name)))
144 except ExecutionError, e:
145 log.debug(u'VpnHandler._write_config: error '
146 'removing files: %r', e)
148 #delete the vpn root at tinc dir
149 if path.exists('/etc/tinc/' + v.name):
151 call(('rm','-rf','/etc/tinc/' + v.name))
152 del self.vpns[v.name]
155 if __name__ == '__main__':
158 level = logging.DEBUG,
159 format = '%(asctime)s %(levelname)-8s %(message)s',
160 datefmt = '%H:%M:%S',
163 v = VpnHandler('/tmp', '/tmp')
164 v.add('prueba','sarasa','192.168.0.188','255.255.255.0')
165 v.host.add('prueba', 'azazel' ,'192.168.0.77', '192.168.0.0',
166 'kjdhfkbdskljvkjblkbjeslkjbvkljbselvslberjhbvslbevlhb')