1 # vim: set encoding=utf-8 et sw=4 sts=4 :
6 import logging ; log = logging.getLogger('pymin.services.dns')
8 from pymin.seqtools import Sequence
9 from pymin.dispatcher import handler, HandlerError, Handler
10 from pymin.services.util import Restorable, ConfigWriter, InitdHandler, \
11 TransactionalHandler, ParametersHandler, \
12 DictComposedSubHandler, DictSubHandler, call
14 __ALL__ = ('DnsHandler',)
17 def __init__(self, name, ip):
20 def update(self, ip=None):
21 if ip is not None: self.ip = ip
23 return (self.name, self.ip)
25 class HostHandler(DictComposedSubHandler):
26 handler_help = u"Manage DNS hosts"
27 _comp_subhandler_cont = 'zones'
28 _comp_subhandler_attr = 'hosts'
29 _comp_subhandler_class = Host
31 class MailExchange(Sequence):
32 def __init__(self, mx, prio):
35 def update(self, prio=None):
36 if prio is not None: self.prio = prio
38 return (self.mx, self.prio)
40 class MailExchangeHandler(DictComposedSubHandler):
41 handler_help = u"Manage DNS mail exchangers (MX)"
42 _comp_subhandler_cont = 'zones'
43 _comp_subhandler_attr = 'mxs'
44 _comp_subhandler_class = MailExchange
46 class NameServer(Sequence):
47 def __init__(self, name):
52 class NameServerHandler(DictComposedSubHandler):
53 handler_help = u"Manage DNS name servers (NS)"
54 _comp_subhandler_cont = 'zones'
55 _comp_subhandler_attr = 'nss'
56 _comp_subhandler_class = NameServer
59 def __init__(self, name):
68 return (self.name, self.hosts, self.mxs, self.nss)
70 class ZoneHandler(DictSubHandler):
71 handler_help = u"Manage DNS zones"
72 _cont_subhandler_attr = 'zones'
73 _cont_subhandler_class = Zone
75 class DnsHandler(Restorable, ConfigWriter, InitdHandler, TransactionalHandler,
77 r"""DnsHandler([pickle_dir[, config_dir]]) -> DnsHandler instance.
79 Handles DNS service commands for the dns program.
81 pickle_dir - Directory where to write the persistent configuration data.
83 config_dir - Directory where to store de generated configuration files.
85 Both defaults to the current working directory.
88 handler_help = u"Manage DNS service"
92 _persistent_attrs = ('params', 'zones')
94 _restorable_defaults = dict(
104 _config_writer_files = ('named.conf', 'zoneX.zone')
105 _config_writer_tpl_dir = path.join(path.dirname(__file__), 'templates')
107 def __init__(self, pickle_dir='.', config_dir='.'):
108 r"Initialize DnsHandler object, see class documentation for details."
109 log.debug(u'DnsHandler(%r, %r)', pickle_dir, config_dir)
110 self._persistent_dir = pickle_dir
111 self._config_writer_cfg_dir = config_dir
113 self._config_build_templates()
114 InitdHandler.__init__(self)
115 self.host = HostHandler(self)
116 self.zone = ZoneHandler(self)
117 self.mx = MailExchangeHandler(self)
118 self.ns = NameServerHandler(self)
120 def _zone_filename(self, zone):
121 return zone.name + '.zone'
123 def _get_config_vars(self, config_file):
124 return dict(zones=self.zones.values(), **self.params)
126 def _write_config(self):
127 r"_write_config() -> None :: Generate all the configuration files."
128 log.debug(u'DnsHandler._write_config()')
129 delete_zones = list()
130 for a_zone in self.zones.values():
131 log.debug(u'DnsHandler._write_config: processing zone %s', a_zone)
132 if a_zone._update or a_zone._add:
133 if not a_zone._add and self._service_running:
134 log.debug(u'DnsHandler._write_config: zone updated and '
135 u'the service is running, freezing zone')
136 call(('rndc', 'freeze', a_zone.name))
139 hosts = a_zone.hosts.values(),
140 mxs = a_zone.mxs.values(),
141 nss = a_zone.nss.values()
143 self._write_single_config('zoneX.zone',
144 self._zone_filename(a_zone), vars)
145 a_zone._update = False
146 if not a_zone._add and self._service_running:
147 log.debug(u'DnsHandler._write_config: unfreezing zone')
148 call(('rndc', 'thaw', a_zone.name))
153 #borro el archivo .zone
154 log.debug(u'DnsHandler._write_config: zone deleted, removing '
155 u'the file %r', self._zone_filename(a_zone))
158 unlink(self._zone_filename(a_zone))
160 #la excepcion pude darse en caso que haga un add de una zona y
161 #luego el del, como no hice commit, no se crea el archivo
162 log.debug(u'DnsHandler._write_config: file not found')
164 delete_zones.append(a_zone.name)
166 for z in delete_zones:
170 self._write_single_config('named.conf')
172 return False # Do reload
173 return True # we don't need to reload
176 def handle_timer(self):
177 log.debug(u'DnsHandler.handle_timer()')
179 p = subprocess.Popen(('pgrep', '-f', '/usr/sbin/named'),
180 stdout=subprocess.PIPE)
181 pid = p.communicate()[0]
182 if p.returncode == 0 and len(pid) > 0:
183 log.debug(u'DnsHandler.handle_timer: pid present, running')
184 self._service_running = True
186 log.debug(u'DnsHandler.handle_timer: pid absent, NOT running')
187 self._service_running = False
191 if __name__ == '__main__':
194 level = logging.DEBUG,
195 format = '%(asctime)s %(levelname)-8s %(message)s',
196 datefmt = '%H:%M:%S',
201 dns.set('isp_dns1','la_garcha.com')
202 dns.set('bind_addr1','localhost')
203 dns.zone.add('zona_loca.com')
204 #dns.zone.update('zona_loca.com','ns1.dominio.com')
206 dns.host.add('zona_loca.com','hostname_loco','192.168.0.23')
207 dns.host.update('zona_loca.com','hostname_loco','192.168.0.66')
209 dns.host.add('zona_loca.com','hostname_kuak','192.168.0.23')
210 dns.host.delete('zona_loca.com','hostname_kuak')
212 dns.host.add('zona_loca.com','hostname_kuang','192.168.0.24')
213 dns.host.add('zona_loca.com','hostname_chan','192.168.0.25')
214 dns.host.add('zona_loca.com','hostname_kaine','192.168.0.26')
216 dns.mx.add('zona_loca.com','mx1.sarasa.com',10)
217 dns.mx.update('zona_loca.com','mx1.sarasa.com',20)
218 dns.mx.add('zona_loca.com','mx2.sarasa.com',30)
219 dns.mx.add('zona_loca.com','mx3.sarasa.com',40)
220 dns.mx.delete('zona_loca.com','mx3.sarasa.com')
222 dns.ns.add('zona_loca.com','ns1.jua.com')
223 dns.ns.add('zona_loca.com','ns2.jua.com')
224 dns.ns.add('zona_loca.com','ns3.jua.com')
225 dns.ns.delete('zona_loca.com','ns3.jua.com')
227 dns.zone.add('zona_oscura')
229 dns.host.add('zona_oscura','hostname_a','192.168.0.24')
230 dns.host.add('zona_oscura','hostname_b','192.168.0.25')
231 dns.host.add('zona_oscura','hostname_c','192.168.0.26')
233 dns.zone.delete('zona_oscura')
237 print 'ZONAS :', dns.zone.show()
239 print 'HOSTS from', z, ':', dns.host.show(z)
243 # dns.zone.update('zone-sarasa','lalal')
244 #except ZoneNotFoundError, inst:
245 # print 'Error: ', inst
247 from pymin.services.util import ItemNotFoundError, ItemAlreadyExistsError, \
248 ContainerNotFoundError
251 dns.zone.delete('zone-sarasa')
252 except ItemNotFoundError, inst:
253 print 'Error: ', inst
256 # dns.zone.add('zona_loca.com','ns1.dom.com','ns2.dom.com')
257 #except ZoneAlreadyExistsError, inst:
258 # print 'Error: ', inst
263 dns.host.update('zone-sarasa','kuak','192.68')
264 except ContainerNotFoundError, inst:
265 print 'Error: ', inst
268 dns.host.update('zona_loca.com','kuak','192.68')
269 except ItemNotFoundError, inst:
270 print 'Error: ', inst
273 dns.host.delete('zone-sarasa','lala')
274 except ContainerNotFoundError, inst:
275 print 'Error: ', inst
278 dns.host.delete('zona_loca.com','lala')
279 except ItemNotFoundError, inst:
280 print 'Error: ', inst
283 dns.host.add('zona','hostname_loco','192.168.0.23')
284 except ContainerNotFoundError, inst:
285 print 'Error: ', inst
288 dns.host.add('zona_loca.com','hostname_loco','192.168.0.23')
289 except ItemAlreadyExistsError, inst:
290 print 'Error: ', inst