]> git.llucax.com Git - software/pymin.git/blob - pymin/services/ip/__init__.py
Add logging to pymin.services.vrrp module.
[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 import logging ; log = logging.getLogger('pymin.services.ip')
6
7 from pymin.seqtools import Sequence
8 from pymin.dispatcher import handler, HandlerError, Handler
9 from pymin.services.util import Restorable, ConfigWriter, InitdHandler, \
10                                 TransactionalHandler, SubHandler, call, \
11                                 get_network_devices, ListComposedSubHandler, \
12                                 DictComposedSubHandler, Device, Address, \
13                                 ExecutionError
14
15 __ALL__ = ('IpHandler',)
16
17 # TODO: convertir HopHandler a ComposedSubHandler
18
19 class HopError(HandlerError):
20
21     def __init__(self, hop):
22         self.message = u'Hop error : "%s"' % hop
23
24 class HopNotFoundError(HopError):
25
26     def __init__(self, hop):
27         self.message = u'Hop not found : "%s"' % hop
28
29 class HopAlreadyExistsError(HopError):
30
31     def __init__(self, hop):
32         self.message = u'Hop already exists : "%s"' % hop
33
34
35 class Hop(Sequence):
36
37     def __init__(self, gateway, device):
38         self.gateway = gateway
39         self.device = device
40
41     def as_tuple(self):
42         return (self.gateway, self.device)
43
44     def __cmp__(self, other):
45         if self.gateway == other.gateway \
46                 and self.device == other.device:
47             return 0
48         return cmp(id(self), id(other))
49
50 class HopHandler(Handler):
51
52     def __init__(self, parent):
53         self.parent = parent
54
55     @handler('Adds a hop : add <gateway> <device>')
56     def add(self, gw, dev):
57         if not dev in self.parent.devices:
58             raise DeviceNotFoundError(device)
59         h = Hop(gw, dev)
60         try:
61             self.parent.hops.index(h)
62             raise HopAlreadyExistsError(gw  + '->' + dev)
63         except ValueError:
64             self.parent.hops.append(h)
65
66     @handler(u'Deletes a hop : delete <gateway> <device>')
67     def delete(self, gw, dev):
68         if not dev in self.parent.devices:
69             raise DeviceNotFoundError(device)
70         h = Hop(gw, dev)
71         try:
72             self.parent.hops.remove(h)
73         except ValueError:
74             raise HopNotFoundError(gw + '->' + dev)
75
76     @handler(u'Lists hops : list <dev>')
77     def list(self, device):
78         try:
79             k = self.parent.hops.keys()
80         except ValueError:
81             k = list()
82         return k
83
84     @handler(u'Get information about all hops: show <dev>')
85     def show(self, device):
86         try:
87             k = self.parent.hops.values()
88         except ValueError:
89             k = list()
90         return k
91
92 class Route(Sequence):
93     def __init__(self, net_addr, prefix, gateway):
94         self.net_addr = net_addr
95         self.prefix = prefix
96         self.gateway = gateway
97     def update(self, net_addr=None, prefix=None, gateway=None):
98         if net_addr is not None: self.net_addr = net_addr
99         if prefix is not None: self.prefix = prefix
100         if gateway is not None: self.gateway = gateway
101     def as_tuple(self):
102         return(self.net_addr, self.prefix, self.gateway)
103
104 class RouteHandler(ListComposedSubHandler):
105     handler_help = u"Manage IP routes"
106     _comp_subhandler_cont = 'devices'
107     _comp_subhandler_attr = 'routes'
108     _comp_subhandler_class = Route
109
110
111 class AddressHandler(DictComposedSubHandler):
112     handler_help = u"Manage IP addresses"
113     _comp_subhandler_cont = 'devices'
114     _comp_subhandler_attr = 'addrs'
115     _comp_subhandler_class = Address
116
117
118 class DeviceHandler(SubHandler):
119
120     handler_help = u"Manage network devices"
121
122     def __init__(self, parent):
123         log.debug(u'DeviceHandler(%r)', parent)
124         # FIXME remove templates to execute commands
125         from mako.template import Template
126         self.parent = parent
127         template_dir = path.join(path.dirname(__file__), 'templates')
128         dev_fn = path.join(template_dir, 'device')
129         self.device_template = Template(filename=dev_fn)
130
131     @handler(u'Bring the device up')
132     def up(self, name):
133         log.debug(u'DeviceHandler.up(%r)', name)
134         if name in self.parent.devices:
135             call(self.device_template.render(dev=name, action='up'), shell=True)
136         else:
137             log.debug(u'DeviceHandler.up: device not found')
138             raise DeviceNotFoundError(name)
139
140     @handler(u'Bring the device down')
141     def down(self, name):
142         log.debug(u'DeviceHandler.down(%r)', name)
143         if name in self.parent.devices:
144             call(self.device_template.render(dev=name, action='down'), shell=True)
145         else:
146             log.debug(u'DeviceHandler.up: device not found')
147             raise DeviceNotFoundError(name)
148
149     @handler(u'List all devices')
150     def list(self):
151         log.debug(u'DeviceHandler.list()')
152         return self.parent.devices.keys()
153
154     @handler(u'Get information about a device')
155     def show(self):
156         log.debug(u'DeviceHandler.show()')
157         return self.parent.devices.items()
158
159 class IpHandler(Restorable, ConfigWriter, TransactionalHandler):
160
161     handler_help = u"Manage IP devices, addresses, routes and hops"
162
163     _persistent_attrs = ('devices','hops')
164
165     _restorable_defaults = dict(
166                             devices=get_network_devices(),
167                             hops = list()
168                             )
169
170     _config_writer_files = ('device', 'ip_add', 'ip_del', 'ip_flush',
171                             'route_add', 'route_del', 'route_flush', 'hop')
172     _config_writer_tpl_dir = path.join(path.dirname(__file__), 'templates')
173
174     def __init__(self, pickle_dir='.', config_dir='.'):
175         r"Initialize DhcpHandler object, see class documentation for details."
176         log.debug(u'IpHandler(%r, %r)', pickle_dir, config_dir)
177         self._persistent_dir = pickle_dir
178         self._config_writer_cfg_dir = config_dir
179         self._config_build_templates()
180         self._restore()
181         self._write_config()
182         self.addr = AddressHandler(self)
183         self.route = RouteHandler(self)
184         self.dev = DeviceHandler(self)
185         self.hop = HopHandler(self)
186
187     def _write_config(self):
188         r"_write_config() -> None :: Execute all commands."
189         log.debug(u'IpHandler._write_config()')
190         for device in self.devices.values():
191             log.debug(u'IpHandler._write_config: processing device %s', device)
192             try:
193                 log.debug(u'IpHandler._write_config: flushing routes...')
194                 call(self._render_config('route_flush', dict(dev=device.name)),
195                         shell=True)
196             except ExecutionError, e:
197                 log.debug(u'IpHandler._write_config: error flushing -> %r', e)
198             try:
199                 log.debug(u'IpHandler._write_config: flushing addrs...')
200                 call(self._render_config('ip_flush', dict(dev=device.name)),
201                         shell=True)
202             except ExecutionError, e:
203                 log.debug(u'IpHandler._write_config: error flushing -> %r', e)
204             for address in device.addrs.values():
205                 broadcast = address.broadcast
206                 if broadcast is None:
207                     broadcast = '+'
208                 try:
209                     log.debug(u'IpHandler._write_config: adding %r', address)
210                     call(self._render_config('ip_add', dict(
211                             dev = device.name,
212                             addr = address.ip,
213                             netmask = address.netmask,
214                             peer = address.peer,
215                             broadcast = broadcast,
216                         )), shell=True)
217                 except ExecutionError, e:
218                     log.debug(u'IpHandler._write_config: error adding -> %r', e)
219             for route in device.routes:
220                 try:
221                     log.debug(u'IpHandler._write_config: adding %r', route)
222                     call(self._render_config('route_add', dict(
223                             dev = device.name,
224                             net_addr = route.net_addr,
225                             prefix = route.prefix,
226                             gateway = route.gateway,
227                         )), shell=True)
228                 except ExecutionError, e:
229                     log.debug(u'IpHandler._write_config: error adding -> %r', e)
230         if self.hops:
231             log.debug(u'IpHandler._write_config: we have hops: %r', self.hops)
232             try:
233                 log.debug(u'IpHandler._write_config: flushing default route')
234                 call('ip route del default', shell=True)
235             except ExecutionError, e:
236                 log.debug(u'IpHandler._write_config: error adding -> %r', e)
237             try:
238                 log.debug(u'IpHandler._write_config: configuring hops')
239                 call(self._render_config('hop', dict(
240                     hops = self.hops,
241                         )
242                 ), shell=True)
243             except ExecutionError, e:
244                 log.debug(u'IpHandler._write_config: error adding -> %r', e)
245
246     def handle_timer(self):
247         log.debug(u'IpHandler.handle_timer()')
248         self.refresh_devices()
249
250     def refresh_devices(self):
251         log.debug(u'IpHandler.update_devices()')
252         devices = get_network_devices()
253         #add not registered devices
254         for k,v in devices.items():
255             if k not in self.devices:
256                 log.debug(u'IpHandler.update_devices: adding %r', v)
257                 self.devices[k] = v
258         #delete dead devices
259         for k in self.devices.keys():
260             if k not in devices:
261                 log.debug(u'IpHandler.update_devices: removing %s', k)
262                 del self.devices[k]
263
264
265
266 if __name__ == '__main__':
267
268     logging.basicConfig(
269         level   = logging.DEBUG,
270         format  = '%(asctime)s %(levelname)-8s %(message)s',
271         datefmt = '%H:%M:%S',
272     )
273
274     ip = IpHandler()
275     print '----------------------'
276     ip.hop.add('201.21.32.53','eth0')
277     ip.hop.add('205.65.65.25','eth1')
278     ip.commit()
279     ip.dev.up('eth0')
280     ip.addr.add('eth0','192.168.0.23','24','192.168.255.255')
281     ip.addr.add('eth0','192.168.0.26','24')
282     ip.commit()
283     ip.route.add('eth0','192.168.0.0','24','192.168.0.1')
284     ip.route.add('eth0','192.168.0.5','24','192.168.0.1')
285     ip.commit()
286     ip.hop.delete('201.21.32.53','eth0')
287     ip.route.clear('eth0')
288     ip.commit()
289
290
291