]> git.llucax.com Git - software/pymin.git/blob - services/dhcp/__init__.py
Factored out a lot of common code.
[software/pymin.git] / services / dhcp / __init__.py
1 # vim: set encoding=utf-8 et sw=4 sts=4 :
2
3 from os import path
4
5 from seqtools import Sequence
6 from dispatcher import Handler, handler, HandlerError
7 from services.util import Restorable, ConfigWriter
8 from services.util import InitdHandler, TransactionalHandler
9
10 __ALL__ = ('DhcpHandler', 'Error', 'HostError', 'HostAlreadyExistsError',
11             'HostNotFoundError', 'ParameterError', 'ParameterNotFoundError')
12
13 class Error(HandlerError):
14     r"""
15     Error(message) -> Error instance :: Base DhcpHandler exception class.
16
17     All exceptions raised by the DhcpHandler inherits from this one, so you can
18     easily catch any DhcpHandler exception.
19
20     message - A descriptive error message.
21     """
22
23     def __init__(self, message):
24         r"Initialize the Error object. See class documentation for more info."
25         self.message = message
26
27     def __str__(self):
28         return self.message
29
30 class HostError(Error, KeyError):
31     r"""
32     HostError(hostname) -> HostError instance
33
34     This is the base exception for all host related errors.
35     """
36
37     def __init__(self, hostname):
38         r"Initialize the object. See class documentation for more info."
39         self.message = 'Host error: "%s"' % hostname
40
41 class HostAlreadyExistsError(HostError):
42     r"""
43     HostAlreadyExistsError(hostname) -> HostAlreadyExistsError instance
44
45     This exception is raised when trying to add a hostname that already exists.
46     """
47
48     def __init__(self, hostname):
49         r"Initialize the object. See class documentation for more info."
50         self.message = 'Host already exists: "%s"' % hostname
51
52 class HostNotFoundError(HostError):
53     r"""
54     HostNotFoundError(hostname) -> HostNotFoundError instance
55
56     This exception is raised when trying to operate on a hostname that doesn't
57     exists.
58     """
59
60     def __init__(self, hostname):
61         r"Initialize the object. See class documentation for more info."
62         self.message = 'Host not found: "%s"' % hostname
63
64 class ParameterError(Error, KeyError):
65     r"""
66     ParameterError(paramname) -> ParameterError instance
67
68     This is the base exception for all DhcpHandler parameters related errors.
69     """
70
71     def __init__(self, paramname):
72         r"Initialize the object. See class documentation for more info."
73         self.message = 'Parameter error: "%s"' % paramname
74
75 class ParameterNotFoundError(ParameterError):
76     r"""
77     ParameterNotFoundError(hostname) -> ParameterNotFoundError instance
78
79     This exception is raised when trying to operate on a parameter that doesn't
80     exists.
81     """
82
83     def __init__(self, paramname):
84         r"Initialize the object. See class documentation for more info."
85         self.message = 'Parameter not found: "%s"' % paramname
86
87
88 class Host(Sequence):
89     r"""Host(name, ip, mac) -> Host instance :: Class representing a host.
90
91     name - Host name, should be a fully qualified name, but no checks are done.
92     ip - IP assigned to the hostname.
93     mac - MAC address to associate to the hostname.
94     """
95
96     def __init__(self, name, ip, mac):
97         r"Initialize Host object, see class documentation for details."
98         self.name = name
99         self.ip = ip
100         self.mac = mac
101
102     def as_tuple(self):
103         r"Return a tuple representing the host."
104         return (self.name, self.ip, self.mac)
105
106 class HostHandler(Handler):
107     r"""HostHandler(hosts) -> HostHandler instance :: Handle a list of hosts.
108
109     This class is a helper for DhcpHandler to do all the work related to hosts
110     administration.
111
112     hosts - A dictionary with string keys (hostnames) and Host instances values.
113     """
114
115     def __init__(self, hosts):
116         r"Initialize HostHandler object, see class documentation for details."
117         self.hosts = hosts
118
119     @handler(u'Add a new host.')
120     def add(self, name, ip, mac):
121         r"add(name, ip, mac) -> None :: Add a host to the hosts list."
122         if name in self.hosts:
123             raise HostAlreadyExistsError(name)
124         self.hosts[name] = Host(name, ip, mac)
125
126     @handler(u'Update a host.')
127     def update(self, name, ip=None, mac=None):
128         r"update(name[, ip[, mac]]) -> None :: Update a host of the hosts list."
129         if not name in self.hosts:
130             raise HostNotFoundError(name)
131         if ip is not None:
132             self.hosts[name].ip = ip
133         if mac is not None:
134             self.hosts[name].mac = mac
135
136     @handler(u'Delete a host.')
137     def delete(self, name):
138         r"delete(name) -> None :: Delete a host of the hosts list."
139         if not name in self.hosts:
140             raise HostNotFoundError(name)
141         del self.hosts[name]
142
143     @handler(u'Get information about a host.')
144     def get(self, name):
145         r"get(name) -> Host :: List all the information of a host."
146         if not name in self.hosts:
147             raise HostNotFoundError(name)
148         return self.hosts[name]
149
150     @handler(u'List hosts.')
151     def list(self):
152         r"list() -> tuple :: List all the hostnames."
153         return self.hosts.keys()
154
155     @handler(u'Get information about all hosts.')
156     def show(self):
157         r"show() -> list of Hosts :: List all the complete hosts information."
158         return self.hosts.values()
159
160 class DhcpHandler(Restorable, ConfigWriter, InitdHandler, TransactionalHandler):
161     r"""DhcpHandler([pickle_dir[, config_dir]]) -> DhcpHandler instance.
162
163     Handles DHCP service commands for the dhcpd program.
164
165     pickle_dir - Directory where to write the persistent configuration data.
166
167     config_dir - Directory where to store de generated configuration files.
168
169     Both defaults to the current working directory.
170     """
171
172     _initd_name = 'dhcpd'
173
174     _persistent_vars = ('vars', 'hosts')
175
176     _restorable_defaults = dict(
177             hosts = dict(),
178             vars  = dict(
179                 domain_name = 'example.com',
180                 dns_1       = 'ns1.example.com',
181                 dns_2       = 'ns2.example.com',
182                 net_address = '192.168.0.0',
183                 net_mask    = '255.255.255.0',
184                 net_start   = '192.168.0.100',
185                 net_end     = '192.168.0.200',
186                 net_gateway = '192.168.0.1',
187             ),
188     )
189
190     _config_writer_files = 'dhcpd.conf'
191     _config_writer_tpl_dir = path.join(path.dirname(__file__), 'templates')
192
193     def __init__(self, pickle_dir='.', config_dir='.'):
194         r"Initialize DhcpHandler object, see class documentation for details."
195         self._persistent_dir = pickle_dir
196         self._config_writer_cfg_dir = config_dir
197         self._config_build_templates()
198         self._restore()
199         self.host = HostHandler(self.hosts)
200
201     def _get_config_vars(self, config_file):
202         return dict(hosts=self.hosts.values(), **self.vars)
203
204     @handler(u'Set a DHCP parameter.')
205     def set(self, param, value):
206         r"set(param, value) -> None :: Set a DHCP parameter."
207         if not param in self.vars:
208             raise ParameterNotFoundError(param)
209         self.vars[param] = value
210
211     @handler(u'Get a DHCP parameter.')
212     def get(self, param):
213         r"get(param) -> None :: Get a DHCP parameter."
214         if not param in self.vars:
215             raise ParameterNotFoundError(param)
216         return self.vars[param]
217
218     @handler(u'List all available DHCP parameters.')
219     def list(self):
220         r"list() -> tuple :: List all the parameter names."
221         return self.vars.keys()
222
223     @handler(u'Get all DHCP parameters, with their values.')
224     def show(self):
225         r"show() -> (key, value) tuples :: List all the parameters."
226         return self.vars.items()
227
228 if __name__ == '__main__':
229
230     import os
231
232     h = DhcpHandler()
233
234     def dump():
235         print '-' * 80
236         print 'Variables:', h.list()
237         print h.show()
238         print
239         print 'Hosts:', h.host.list()
240         print h.host.show()
241         print '-' * 80
242
243     dump()
244
245     h.host.add('my_name','192.168.0.102','00:12:ff:56')
246
247     h.host.update('my_name','192.168.0.192','00:12:ff:56')
248
249     h.host.add('nico','192.168.0.188','00:00:00:00')
250
251     h.set('domain_name','baryon.com.ar')
252
253     try:
254         h.set('sarasa','baryon.com.ar')
255     except KeyError, e:
256         print 'Error:', e
257
258     h.commit()
259
260     dump()
261
262     os.system('rm -f *.pkl ' + ' '.join(h._config_writer_files))
263