1 # vim: set encoding=utf-8 et sw=4 sts=4 :
3 from subprocess import Popen, PIPE
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
11 __ALL__ = ('IpHandler', 'Error','DeviceError', 'DeviceNotFoundError',
12 'RouteError', 'RouteNotFoundError', 'RouteAlreadyExistsError',
13 'AddressError', 'AddressNotFoundError', 'AddressAlreadyExistsError')
15 class Error(HandlerError):
17 Error(command) -> Error instance :: Base IpHandler exception class.
19 All exceptions raised by the IpHandler inherits from this one, so you can
20 easily catch any IpHandler exception.
22 message - A descriptive error message.
26 class DeviceError(Error):
28 def __init__(self, device):
29 self.message = u'Device error : "%s"' % device
31 class DeviceNotFoundError(DeviceError):
33 def __init__(self, device):
34 self.message = u'Device not found : "%s"' % device
36 class AddressError(Error):
38 def __init__(self, addr):
39 self.message = u'Address error : "%s"' % addr
41 class AddressNotFoundError(AddressError):
43 def __init__(self, address):
44 self.message = u'Address not found : "%s"' % address
46 class AddressAlreadyExistsError(AddressError):
48 def __init__(self, address):
49 self.message = u'Address already exists : "%s"' % address
51 class RouteError(Error):
53 def __init__(self, route):
54 self.message = u'Route error : "%s"' % route
56 class RouteNotFoundError(RouteError):
58 def __init__(self, route):
59 self.message = u'Route not found : "%s"' % route
61 class RouteAlreadyExistsError(RouteError):
63 def __init__(self, route):
64 self.message = u'Route already exists : "%s"' % route
66 class HopError(Error):
68 def __init__(self, hop):
69 self.message = u'Hop error : "%s"' % hop
71 class HopNotFoundError(HopError):
73 def __init__(self, hop):
74 self.message = u'Hop not found : "%s"' % hop
76 class HopAlreadyExistsError(HopError):
78 def __init__(self, hop):
79 self.message = u'Hop already exists : "%s"' % hop
84 def __init__(self, gateway, device):
85 self.gateway = gateway
89 return (self.gateway, self.device)
91 def __cmp__(self, other):
92 if self.gateway == other.gateway \
93 and self.device == other.device:
95 return cmp(id(self), id(other))
97 class HopHandler(Handler):
99 def __init__(self, parent):
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)
108 self.parent.hops.index(h)
109 raise HopAlreadyExistsError(gw + '->' + dev)
111 self.parent.hops.append(h)
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)
119 self.parent.hops.remove(h)
121 raise HopNotFoundError(gw + '->' + dev)
123 @handler(u'Lists hops : list <dev>')
124 def list(self, device):
126 k = self.parent.hops.keys()
131 @handler(u'Get information about all hops: show <dev>')
132 def show(self, device):
134 k = self.parent.hops.values()
140 class Route(Sequence):
142 def __init__(self, net_addr, prefix, gateway):
143 self.net_addr = net_addr
145 self.gateway = gateway
148 return(self.addr, self.prefix, self.gateway)
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:
155 return cmp(id(self), id(other))
157 class RouteHandler(Handler):
159 handler_help = u"Manage IP routes"
161 def __init__(self, parent):
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)
170 self.parent.devices[device].routes.index(r)
171 raise RouteAlreadyExistsError(net_addr + '/' + prefix + '->' + gateway)
173 self.parent.devices[device].routes.append(r)
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)
181 self.parent.devices[device].routes.remove(r)
183 raise RouteNotFoundError(net_addr + '/' + prefix + '->' + gateway)
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()
192 @handler(u'List routes')
193 def list(self, device):
195 k = self.parent.devices[device].routes.keys()
200 @handler(u'Get information about all routes')
201 def show(self, device):
203 k = self.parent.devices[device].routes.values()
209 class Address(Sequence):
211 def __init__(self, ip, prefix, broadcast):
214 self.broadcast = broadcast
217 return (self.ip, self.prefix, self.broadcast)
219 class AddressHandler(Handler):
221 handler_help = u"Manage IP addresses"
223 def __init__(self, parent):
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)
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]
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()
248 @handler(u'List all addresses from a device')
249 def list(self, device):
251 k = self.parent.devices[device].addrs.keys()
256 @handler(u'Get information about addresses from a device')
257 def show(self, device):
259 k = self.parent.devices[device].addrs.values()
265 class Device(Sequence):
267 def __init__(self, name, mac):
274 return (self.name, self.mac)
276 class DeviceHandler(Handler):
278 handler_help = u"Manage network devices"
280 def __init__(self, parent):
281 # FIXME remove templates to execute commands
282 from mako.template import Template
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)
288 @handler(u'Bring the device up')
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')
294 raise DeviceNotFoundError(name)
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')
302 raise DeviceNotFoundError(name)
304 @handler(u'List all devices')
306 return self.parent.devices.keys()
308 @handler(u'Get information about a device')
310 return self.parent.devices.items()
314 p = Popen(('ip', 'link', 'list'), stdout=PIPE, close_fds=True)
315 string = p.stdout.read()
318 i = string.find('eth')
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)
327 class IpHandler(Restorable, ConfigWriter, TransactionalHandler):
329 handler_help = u"Manage IP devices, addresses, routes and hops"
331 _persistent_attrs = ('devices','hops')
334 devs['eth0'] = Device('eth0','00:00:00:00')
335 devs['eth1'] = Device('eth1','00:00:00:00')
337 _restorable_defaults = dict(
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')
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()
352 self.addr = AddressHandler(self)
353 self.route = RouteHandler(self)
354 self.dev = DeviceHandler(self)
355 self.hop = HopHandler(self)
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(
368 prefix = address.prefix,
369 broadcast = address.broadcast,
371 #call(self._render_config('ip_add', dict(
374 #prefix = address.prefix,
375 #broadcast = address.broadcast,
378 for route in device.routes:
379 print self._render_config('route_add', dict(
381 net_addr = route.net_addr,
382 prefix = route.prefix,
383 gateway = route.gateway,
385 #call(self._render_config('route_add', dict(
387 #net_addr = route.net_addr,
388 #prefix = route.prefix,
389 #gateway = route.gateway,
394 print 'ip route del default'
395 #call('ip route del default', shell=True)
396 print self._render_config('hop', dict(
399 #call(self._render_config('hop', dict(
405 if __name__ == '__main__':
408 print '----------------------'
409 ip.hop.add('201.21.32.53','eth0')
410 ip.hop.add('205.65.65.25','eth1')
413 ip.addr.add('eth0','192.168.0.23','24','192.168.255.255')
414 ip.addr.add('eth0','192.168.0.26','24')
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')
419 ip.hop.delete('201.21.32.53','eth0')