]> git.llucax.com Git - software/pymin.git/blob - pymin/services/ip/__init__.py
Se agrega soporto para balanceo de carga.
[software/pymin.git] / pymin / services / ip / __init__.py
1 # vim: set encoding=utf-8 et sw=4 sts=4 :
2
3 from subprocess import Popen, PIPE
4 from os import path
5
6 from pymin.seqtools import Sequence
7 from pymin.dispatcher import handler, HandlerError, Handler
8 from pymin.services.util import Restorable, ConfigWriter, InitdHandler, \
9                                 TransactionalHandler, call
10
11 __ALL__ = ('IpHandler', 'Error','DeviceError', 'DeviceNotFoundError',
12            'RouteError', 'RouteNotFoundError', 'RouteAlreadyExistsError',
13            'AddressError', 'AddressNotFoundError', 'AddressAlreadyExistsError')
14
15 class Error(HandlerError):
16     r"""
17     Error(command) -> Error instance :: Base IpHandler exception class.
18
19     All exceptions raised by the IpHandler inherits from this one, so you can
20     easily catch any IpHandler exception.
21
22     message - A descriptive error message.
23     """
24     pass
25
26 class DeviceError(Error):
27
28     def __init__(self, device):
29         self.message = u'Device error : "%s"' % device
30
31 class DeviceNotFoundError(DeviceError):
32
33     def __init__(self, device):
34         self.message = u'Device not found : "%s"' % device
35
36 class AddressError(Error):
37
38     def __init__(self, addr):
39         self.message = u'Address error : "%s"' % addr
40
41 class AddressNotFoundError(AddressError):
42
43     def __init__(self, address):
44         self.message = u'Address not found : "%s"' % address
45
46 class AddressAlreadyExistsError(AddressError):
47
48     def __init__(self, address):
49         self.message = u'Address already exists : "%s"' % address
50
51 class RouteError(Error):
52
53     def __init__(self, route):
54         self.message = u'Route error : "%s"' % route
55
56 class RouteNotFoundError(RouteError):
57
58     def __init__(self, route):
59         self.message = u'Route not found : "%s"' % route
60
61 class RouteAlreadyExistsError(RouteError):
62
63     def __init__(self, route):
64         self.message = u'Route already exists : "%s"' % route
65
66 class HopError(Error):
67
68     def __init__(self, hop):
69         self.message = u'Hop error : "%s"' % hop
70
71 class HopNotFoundError(HopError):
72
73     def __init__(self, hop):
74         self.message = u'Hop not found : "%s"' % hop
75
76 class HopAlreadyExistsError(HopError):
77
78     def __init__(self, hop):
79         self.message = u'Hop already exists : "%s"' % hop
80
81
82 class Hop(Sequence):
83
84     def __init__(self, gateway, device):
85         self.gateway = gateway
86         self.device = device
87
88     def as_tuple(self):
89         return (self.gateway, self.device)
90
91     def __cmp__(self, other):
92         if self.gateway == other.gateway \
93                 and self.device == other.device:
94             return 0
95         return cmp(id(self), id(other))
96
97 class HopHandler(Handler):
98
99     def __init__(self, parent):
100         self.parent = parent
101
102     @handler('Adds a hop : add <gateway> <device>')
103     def add(self, gw, dev):
104         if not dev in self.parent.devices:
105             raise DeviceNotFoundError(device)
106         h = Hop(gw, dev)
107         try:
108             self.parent.hops.index(h)
109             raise HopAlreadyExistsError(gw  + '->' + dev)
110         except ValueError:
111             self.parent.hops.append(h)
112
113     @handler(u'Deletes a hop : delete <gateway> <device>')
114     def delete(self, gw, dev):
115         if not dev in self.parent.devices:
116             raise DeviceNotFoundError(device)
117         h = Hop(gw, dev)
118         try:
119             self.parent.hops.remove(h)
120         except ValueError:
121             raise HopNotFoundError(gw + '->' + dev)
122
123     @handler(u'Lists hops : list <dev>')
124     def list(self, device):
125         try:
126             k = self.parent.hops.keys()
127         except ValueError:
128             k = list()
129         return k
130
131     @handler(u'Get information about all hops: show <dev>')
132     def show(self, device):
133         try:
134             k = self.parent.hops.values()
135         except ValueError:
136             k = list()
137         return k
138
139
140 class Route(Sequence):
141
142     def __init__(self, net_addr, prefix, gateway):
143         self.net_addr = net_addr
144         self.prefix = prefix
145         self.gateway = gateway
146
147     def as_tuple(self):
148         return(self.addr, self.prefix, self.gateway)
149
150     def __cmp__(self, other):
151         if self.net_addr == other.net_addr \
152                 and self.prefix == other.prefix \
153                 and self.gateway == other.gateway:
154             return 0
155         return cmp(id(self), id(other))
156
157 class RouteHandler(Handler):
158
159     handler_help = u"Manage IP routes"
160
161     def __init__(self, parent):
162         self.parent = parent
163
164     @handler(u'Adds a route to a device')
165     def add(self, device, net_addr, prefix, gateway):
166         if not device in self.parent.devices:
167             raise DeviceNotFoundError(device)
168         r = Route(net_addr, prefix, gateway)
169         try:
170             self.parent.devices[device].routes.index(r)
171             raise RouteAlreadyExistsError(net_addr + '/' + prefix + '->' + gateway)
172         except ValueError:
173             self.parent.devices[device].routes.append(r)
174
175     @handler(u'Deletes a route from a device')
176     def delete(self, device, net_addr, prefix, gateway):
177         if not device in self.parent.devices:
178             raise DeviceNotFoundError(device)
179         r = Route(net_addr, prefix, gateway)
180         try:
181             self.parent.devices[device].routes.remove(r)
182         except ValueError:
183             raise RouteNotFoundError(net_addr + '/' + prefix + '->' + gateway)
184
185     @handler(u'Flushes routes from a device')
186     def flush(self, device):
187         if not device in self.parent.devices:
188             raise DeviceNotFoundError(device)
189         self.parent.devices[device].routes = list()
190
191
192     @handler(u'List routes')
193     def list(self, device):
194         try:
195             k = self.parent.devices[device].routes.keys()
196         except ValueError:
197             k = list()
198         return k
199
200     @handler(u'Get information about all routes')
201     def show(self, device):
202         try:
203             k = self.parent.devices[device].routes.values()
204         except ValueError:
205             k = list()
206         return k
207
208
209 class Address(Sequence):
210
211     def __init__(self, ip, prefix, broadcast):
212         self.ip = ip
213         self.prefix = prefix
214         self.broadcast = broadcast
215
216     def as_tuple(self):
217         return (self.ip, self.prefix, self.broadcast)
218
219 class AddressHandler(Handler):
220
221     handler_help = u"Manage IP addresses"
222
223     def __init__(self, parent):
224         self.parent = parent
225
226     @handler(u'Adds an address to a device')
227     def add(self, device, ip, prefix, broadcast='+'):
228         if not device in self.parent.devices:
229             raise DeviceNotFoundError(device)
230         if ip in self.parent.devices[device].addrs:
231             raise AddressAlreadyExistsError(ip)
232         self.parent.devices[device].addrs[ip] = Address(ip, prefix, broadcast)
233
234     @handler(u'Deletes an address from a device')
235     def delete(self, device, ip):
236         if not device in self.parent.devices:
237             raise DeviceNotFoundError(device)
238         if not ip in self.parent.devices[device].addrs:
239             raise AddressNotFoundError(ip)
240         del self.parent.devices[device].addrs[ip]
241
242     @handler(u'Flushes addresses from a device')
243     def flush(self, device):
244         if not device in self.parent.devices:
245             raise DeviceNotFoundError(device)
246         self.parent.devices[device].addrs = dict()
247
248     @handler(u'List all addresses from a device')
249     def list(self, device):
250         try:
251             k = self.parent.devices[device].addrs.keys()
252         except ValueError:
253             k = list()
254         return k
255
256     @handler(u'Get information about addresses from a device')
257     def show(self, device):
258         try:
259             k = self.parent.devices[device].addrs.values()
260         except ValueError:
261             k = list()
262         return k
263
264
265 class Device(Sequence):
266
267     def __init__(self, name, mac):
268         self.name = name
269         self.mac = mac
270         self.addrs = dict()
271         self.routes = list()
272
273     def as_tuple(self):
274         return (self.name, self.mac)
275
276 class DeviceHandler(Handler):
277
278     handler_help = u"Manage network devices"
279
280     def __init__(self, parent):
281         # FIXME remove templates to execute commands
282         from mako.template import Template
283         self.parent = parent
284         template_dir = path.join(path.dirname(__file__), 'templates')
285         dev_fn = path.join(template_dir, 'device')
286         self.device_template = Template(filename=dev_fn)
287
288     @handler(u'Bring the device up')
289     def up(self, name):
290         if name in self.parent.devices:
291             #call(self.device_template.render(dev=name, action='up'), shell=True)
292             print self.device_template.render(dev=name, action='up')
293         else:
294             raise DeviceNotFoundError(name)
295
296     @handler(u'Bring the device down')
297     def down(self, name):
298         if name in self.parent.devices:
299             #call(self.device_template.render(dev=name, action='down'), shell=True)
300             print self.device_template.render(dev=name, action='down')
301         else:
302             raise DeviceNotFoundError(name)
303
304     @handler(u'List all devices')
305     def list(self):
306         return self.parent.devices.keys()
307
308     @handler(u'Get information about a device')
309     def show(self):
310         return self.parent.devices.items()
311
312
313 def get_devices():
314     p = Popen(('ip', 'link', 'list'), stdout=PIPE, close_fds=True)
315     string = p.stdout.read()
316     p.wait()
317     d = dict()
318     i = string.find('eth')
319     while i != -1:
320         eth = string[i:i+4]
321         m = string.find('link/ether', i+4)
322         mac = string[ m+11 : m+11+17]
323         d[eth] = Device(eth, mac)
324         i = string.find('eth', m+11+17)
325     return d
326
327 class IpHandler(Restorable, ConfigWriter, TransactionalHandler):
328
329     handler_help = u"Manage IP devices, addresses, routes and hops"
330
331     _persistent_attrs = ('devices','hops')
332
333     devs = dict();
334     devs['eth0'] = Device('eth0','00:00:00:00')
335     devs['eth1'] = Device('eth1','00:00:00:00')
336
337     _restorable_defaults = dict(
338                             devices=devs,
339                             hops = list()
340                             )
341
342     _config_writer_files = ('device', 'ip_add', 'ip_del', 'ip_flush',
343                             'route_add', 'route_del', 'route_flush', 'hop')
344     _config_writer_tpl_dir = path.join(path.dirname(__file__), 'templates')
345
346     def __init__(self, pickle_dir='.', config_dir='.'):
347         r"Initialize DhcpHandler object, see class documentation for details."
348         self._persistent_dir = pickle_dir
349         self._config_writer_cfg_dir = config_dir
350         self._config_build_templates()
351         self._restore()
352         self.addr = AddressHandler(self)
353         self.route = RouteHandler(self)
354         self.dev = DeviceHandler(self)
355         self.hop = HopHandler(self)
356
357     def _write_config(self):
358         r"_write_config() -> None :: Execute all commands."
359         for device in self.devices.values():
360             #call(self._render_config('route_flush', dict(dev=device.name)), shell=True)
361             print self._render_config('route_flush', dict(dev=device.name))
362             #call(self._render_config('ip_flush', dict(dev=device.name)), shell=True)
363             print self._render_config('ip_flush', dict(dev=device.name))
364             for address in device.addrs.values():
365                 print self._render_config('ip_add', dict(
366                         dev = device.name,
367                         addr = address.ip,
368                         prefix = address.prefix,
369                         broadcast = address.broadcast,
370                     ))
371                 #call(self._render_config('ip_add', dict(
372                         #dev = device.name,
373                         #addr = address.ip,
374                         #prefix = address.prefix,
375                         #broadcast = address.broadcast,
376                     #)
377                 #), shell=True)
378             for route in device.routes:
379                 print self._render_config('route_add', dict(
380                         dev = device.name,
381                         net_addr = route.net_addr,
382                         prefix = route.prefix,
383                         gateway = route.gateway,
384                     ))
385                 #call(self._render_config('route_add', dict(
386                         #dev = device.name,
387                         #net_addr = route.net_addr,
388                         #prefix = route.prefix,
389                         #gateway = route.gateway,
390                     #)
391                 #), shell=True)
392
393         if self.hops:
394             print 'ip route del default'
395             #call('ip route del default', shell=True)
396             print self._render_config('hop', dict(
397                         hops = self.hops,
398                     ))
399             #call(self._render_config('hop', dict(
400                         #hops = self.hops,
401                     #)
402                  #), shell=True)
403
404
405 if __name__ == '__main__':
406
407     ip = IpHandler()
408     print '----------------------'
409     ip.hop.add('201.21.32.53','eth0')
410     ip.hop.add('205.65.65.25','eth1')
411     ip.commit()
412     ip.dev.up('eth0')
413     ip.addr.add('eth0','192.168.0.23','24','192.168.255.255')
414     ip.addr.add('eth0','192.168.0.26','24')
415     ip.commit()
416     ip.route.add('eth0','192.168.0.0','24','192.168.0.1')
417     ip.route.add('eth0','192.168.0.5','24','192.168.0.1')
418     ip.commit()
419     ip.hop.delete('201.21.32.53','eth0')
420     ip.commit()
421
422
423