]> git.llucax.com Git - software/pymin.git/blob - pymin/services/ppp/__init__.py
Update TODO list.
[software/pymin.git] / pymin / services / ppp / __init__.py
1 # vim: set encoding=utf-8 et sw=4 sts=4 :
2
3 import os
4 from os import path
5 from signal import SIGTERM
6
7 from pymin.seqtools import Sequence
8 from pymin.dispatcher import Handler, handler, HandlerError
9 from pymin.services.util import Restorable, ConfigWriter, ReloadHandler, \
10                                 TransactionalHandler, DictSubHandler, call
11
12 __ALL__ = ('PppHandler',)
13
14 class ConnectionError(HandlerError, KeyError):
15     r"""
16     ConnectionError(hostname) -> ConnectionError instance
17
18     This is the base exception for all connection related errors.
19     """
20
21     def __init__(self, connection):
22         r"Initialize the object. See class documentation for more info."
23         self.message = u'Connection error: "%s"' % connection
24
25 class ConnectionNotFoundError(ConnectionError):
26     def __init__(self, connection):
27         r"Initialize the object. See class documentation for more info."
28         self.message = u'Connection not found error: "%s"' % connection
29
30 class Connection(Sequence):
31
32     def __init__(self, name, username, password, type, **kw):
33         self.name = name
34         self.username = username
35         self.password = password
36         self.type = type
37         self._running = False
38         if type == 'OE':
39             if not 'device' in kw:
40                 raise ConnectionError('Bad arguments for type=OE')
41             self.device = kw['device']
42         elif type == 'TUNNEL':
43             if not 'server' in kw:
44                 raise ConnectionError('Bad arguments for type=TUNNEL')
45             self.server = kw['server']
46             self.username = self.username.replace('\\','\\\\')
47         elif type == 'PPP':
48             if not 'device' in kw:
49                 raise ConnectionError('Bad arguments for type=PPP')
50             self.device = kw['device']
51         else:
52             raise ConnectionError('Bad arguments, unknown or unspecified type')
53
54     def as_tuple(self):
55         if self.type == 'TUNNEL':
56             return (self.name, self.username, self.password, self.type, self.server)
57         elif self.type == 'PPP' or self.type == 'OE':
58             return (self.name, self.username, self.password, self.type, self.device)
59
60     def update(self, device=None, username=None, password=None):
61         if device is not None:
62             self.device = device
63         if username is not None:
64             self.username = username
65         if password is not None:
66             self.password = password
67
68
69 class ConnectionHandler(DictSubHandler):
70
71     handler_help = u"Manages connections for the ppp service"
72
73     _cont_subhandler_attr = 'conns'
74     _cont_subhandler_class = Connection
75
76 class PppHandler(Restorable, ConfigWriter, ReloadHandler, TransactionalHandler):
77
78     handler_help = u"Manage ppp service"
79
80     _persistent_attrs = ['conns']
81
82     _restorable_defaults = dict(
83         conns  = dict(),
84     )
85
86     _config_writer_files = ('options.X','pap-secrets','chap-secrets','nameX')
87     _config_writer_tpl_dir = path.join(path.dirname(__file__), 'templates')
88
89     def __init__(self, pickle_dir='.', config_dir='.'):
90         r"Initialize Ppphandler object, see class documentation for details."
91         self._persistent_dir = pickle_dir
92         self._config_writer_cfg_dir = config_dir
93         self._config_build_templates()
94         self._restore()
95         for conn in self.conns.values():
96             if conn._running:
97                 conn._running = False
98                 self.start(conn.name)
99         self.conn = ConnectionHandler(self)
100
101     @handler(u'Start one or all the connections.')
102     def start(self, name=None):
103         names = [name]
104         if name is None:
105             names = self.conns.keys()
106         for name in names:
107             if name in self.conns:
108                 if not self.conns[name]._running:
109                     call(('pppd', 'call', name))
110                     self.conns[name]._running = True
111                     self._dump_attr('conns')
112             else:
113                 raise ConnectionNotFoundError(name)
114
115     @handler(u'Stop one or all the connections.')
116     def stop(self, name=None):
117         names = [name]
118         if name is None:
119             names = self.conns.keys()
120         for name in names:
121             if name in self.conns:
122                 if self.conns[name]._running:
123                     call(('poff', name))
124                     if path.exists('/var/run/ppp-' + name + '.pid'):
125                         pid = file('/var/run/ppp-' + name + '.pid').readline()
126                         try:
127                             os.kill(int(pid.strip()), SIGTERM)
128                         except OSError:
129                             pass # XXX report error?
130                     self.conns[name]._running = False
131                     self._dump_attr('conns')
132             else:
133                 raise ConnectionNotFoundError(name)
134
135     @handler(u'Restart one or all the connections (even disconnected ones).')
136     def restart(self, name=None):
137         names = [name]
138         if name is None:
139             names = self.conns.keys()
140         for name in names:
141             self.stop(name)
142             self.start(name)
143
144     @handler(u'Restart only one or all the already running connections.')
145     def reload(self, name=None):
146         r"reload() -> None :: Reload the configuration of the service."
147         names = [name]
148         if name is None:
149             names = self.conns.keys()
150         for name in names:
151             if self.conns[name]._running:
152                 self.stop(name)
153                 self.start(name)
154
155     @handler(u'Tell if the service is running.')
156     def running(self, name=None):
157         r"reload() -> None :: Reload the configuration of the service."
158         if name is None:
159             return [c.name for c in self.conns.values() if c._running]
160         if name in self.conns:
161             return int(self.conns[name]._running)
162         else:
163             raise ConnectionNotFoundError(name)
164
165     def _write_config(self):
166         r"_write_config() -> None :: Generate all the configuration files."
167         #guardo los pass que van el pap-secrets
168         vars_pap = dict()
169         for conn in self.conns.values():
170             if conn.type == 'OE' or conn.type == 'PPP':
171                 vars_pap[conn.name] = conn
172         vars = dict(conns=vars_pap)
173         self._write_single_config('pap-secrets','pap-secrets',vars)
174         #guardo los pass que van el chap-secrets
175         vars_chap = dict()
176         for conn in self.conns.values():
177             if conn.type == 'TUNNEL' :
178                 vars_chap[conn.name] = conn
179         vars = dict(conns=vars_chap)
180         self._write_single_config('chap-secrets','chap-secrets',vars)
181         #guard las conns
182         for conn in self.conns.values():
183             vars = dict(conn=conn)
184             self._write_single_config('nameX',conn.name, vars)
185             self._write_single_config('options.X','options.' + conn.name, vars)
186
187
188 if __name__ == '__main__':
189     p = PppHandler()
190     p.conn.add('ppp_c','nico','nico',type='PPP',device='tty0')
191     p.conn.add('pppoe_c','fede','fede',type='OE',device='tty1')
192     p.conn.add('ppptunnel_c','dominio\luca','luca',type='TUNNEL',server='192.168.0.23')
193     p.commit()
194     print p.conn.list()
195     print p.conn.show()
196