1 # vim: set encoding=utf-8 et sw=4 sts=4 :
6 from signal import SIGTERM
8 from pymin.seqtools import Sequence
9 from pymin.dispatcher import Handler, handler, HandlerError
10 from pymin.services.util import Restorable, ConfigWriter, ReloadHandler, \
11 TransactionalHandler, DictSubHandler, call
13 __ALL__ = ('PppHandler',)
15 class ConnectionError(HandlerError, KeyError):
17 ConnectionError(hostname) -> ConnectionError instance
19 This is the base exception for all connection related errors.
22 def __init__(self, connection):
23 r"Initialize the object. See class documentation for more info."
24 self.message = u'Connection error: "%s"' % connection
26 class ConnectionNotFoundError(ConnectionError):
27 def __init__(self, connection):
28 r"Initialize the object. See class documentation for more info."
29 self.message = u'Connection not found error: "%s"' % connection
31 class Connection(Sequence):
33 def __init__(self, name, username, password, type, **kw):
35 self.username = username
36 self.password = password
40 if not 'device' in kw:
41 raise ConnectionError('Bad arguments for type=OE')
42 self.device = kw['device']
43 elif type == 'TUNNEL':
44 if not 'server' in kw:
45 raise ConnectionError('Bad arguments for type=TUNNEL')
46 self.server = kw['server']
47 self.username = self.username.replace('\\','\\\\')
49 if not 'device' in kw:
50 raise ConnectionError('Bad arguments for type=PPP')
51 self.device = kw['device']
53 raise ConnectionError('Bad arguments, unknown or unspecified type')
56 if self.type == 'TUNNEL':
57 return (self.name, self.username, self.password, self.type, self.server)
58 elif self.type == 'PPP' or self.type == 'OE':
59 return (self.name, self.username, self.password, self.type, self.device)
61 def update(self, device=None, username=None, password=None):
62 if device is not None:
64 if username is not None:
65 self.username = username
66 if password is not None:
67 self.password = password
70 class ConnectionHandler(DictSubHandler):
72 handler_help = u"Manages connections for the ppp service"
74 _cont_subhandler_attr = 'conns'
75 _cont_subhandler_class = Connection
77 class PppHandler(Restorable, ConfigWriter, ReloadHandler, TransactionalHandler):
79 handler_help = u"Manage ppp service"
81 _persistent_attrs = ['conns']
83 _restorable_defaults = dict(
87 _config_writer_files = ('options.X','pap-secrets','chap-secrets','nameX')
88 _config_writer_tpl_dir = path.join(path.dirname(__file__), 'templates')
90 def __init__(self, pickle_dir='.', config_dir='.'):
91 r"Initialize Ppphandler object, see class documentation for details."
92 self._persistent_dir = pickle_dir
93 self._config_writer_cfg_dir = config_dir
94 self._config_build_templates()
96 for conn in self.conns.values():
100 self.conn = ConnectionHandler(self)
102 @handler(u'Start one or all the connections.')
103 def start(self, name=None):
106 names = self.conns.keys()
108 if name in self.conns:
109 if not self.conns[name]._running:
110 call(('pppd', 'call', name))
111 self.conns[name]._running = True
112 self._dump_attr('conns')
114 raise ConnectionNotFoundError(name)
116 @handler(u'Stop one or all the connections.')
117 def stop(self, name=None):
120 names = self.conns.keys()
122 if name in self.conns:
123 if self.conns[name]._running:
124 if path.exists('/var/run/ppp-' + name + '.pid'):
125 pid = file('/var/run/ppp-' + name + '.pid').readline()
127 os.kill(int(pid.strip()), SIGTERM)
129 pass # XXX report error?
130 self.conns[name]._running = False
131 self._dump_attr('conns')
133 raise ConnectionNotFoundError(name)
135 @handler(u'Restart one or all the connections (even disconnected ones).')
136 def restart(self, name=None):
139 names = self.conns.keys()
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."
149 names = self.conns.keys()
151 if self.conns[name]._running:
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."
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)
163 raise ConnectionNotFoundError(name)
165 def handle_timer(self):
166 for c in self.conns.values():
167 p = subprocess.Popen(('pgrep', '-f', 'pppd call ' + c.name),
168 stdout=subprocess.PIPE)
169 pid = p.communicate()[0]
170 if p.wait() == 0 and len(pid) > 0:
175 def _write_config(self):
176 r"_write_config() -> None :: Generate all the configuration files."
177 #guardo los pass que van el pap-secrets
179 for conn in self.conns.values():
180 if conn.type == 'OE' or conn.type == 'PPP':
181 vars_pap[conn.name] = conn
182 vars = dict(conns=vars_pap)
183 self._write_single_config('pap-secrets','pap-secrets',vars)
184 #guardo los pass que van el chap-secrets
186 for conn in self.conns.values():
187 if conn.type == 'TUNNEL' :
188 vars_chap[conn.name] = conn
189 vars = dict(conns=vars_chap)
190 self._write_single_config('chap-secrets','chap-secrets',vars)
192 for conn in self.conns.values():
193 vars = dict(conn=conn)
194 self._write_single_config('nameX',conn.name, vars)
195 self._write_single_config('options.X','options.' + conn.name, vars)
198 if __name__ == '__main__':
201 p.conn.add('ppp_c','nico','nico',type='PPP',device='tty0')
202 p.conn.add('pppoe_c','fede','fede',type='OE',device='tty1')
203 p.conn.add('ppptunnel_c','dominio\luca','luca',type='TUNNEL',server='192.168.0.23')