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.service.util import Restorable, ConfigWriter, InitdHandler, \
11 TransactionalHandler, ParametersHandler, \
12 DictComposedSubHandler, DictSubHandler, call
14 __all__ = ('DnsHandler')
18 def __init__(self, name, ip):
21 def update(self, ip=None):
22 if ip is not None: self.ip = ip
24 return (self.name, self.ip)
26 class HostHandler(DictComposedSubHandler):
27 handler_help = u"Manage DNS hosts"
28 _comp_subhandler_cont = 'zones'
29 _comp_subhandler_attr = 'hosts'
30 _comp_subhandler_class = Host
32 class MailExchange(Sequence):
33 def __init__(self, mx, prio):
36 def update(self, prio=None):
37 if prio is not None: self.prio = prio
39 return (self.mx, self.prio)
41 class MailExchangeHandler(DictComposedSubHandler):
42 handler_help = u"Manage DNS mail exchangers (MX)"
43 _comp_subhandler_cont = 'zones'
44 _comp_subhandler_attr = 'mxs'
45 _comp_subhandler_class = MailExchange
47 class NameServer(Sequence):
48 def __init__(self, name):
53 class NameServerHandler(DictComposedSubHandler):
54 handler_help = u"Manage DNS name servers (NS)"
55 _comp_subhandler_cont = 'zones'
56 _comp_subhandler_attr = 'nss'
57 _comp_subhandler_class = NameServer
60 def __init__(self, name):
69 return (self.name, self.hosts, self.mxs, self.nss)
71 class ZoneHandler(DictSubHandler):
72 handler_help = u"Manage DNS zones"
73 _cont_subhandler_attr = 'zones'
74 _cont_subhandler_class = Zone
76 class DnsHandler(Restorable, ConfigWriter, InitdHandler, TransactionalHandler,
78 r"""DnsHandler([pickle_dir[, config_dir]]) -> DnsHandler instance.
80 Handles DNS service commands for the dns program.
82 pickle_dir - Directory where to write the persistent configuration data.
84 config_dir - Directory where to store de generated configuration files.
86 Both defaults to the current working directory.
89 handler_help = u"Manage DNS service"
93 _persistent_attrs = ('params', 'zones')
95 _restorable_defaults = dict(
105 _config_writer_files = ('named.conf', 'zoneX.zone')
106 _config_writer_tpl_dir = path.join(path.dirname(__file__), 'templates')
108 def __init__(self, pickle_dir='.', config_dir='.'):
109 r"Initialize DnsHandler object, see class documentation for details."
110 log.debug(u'DnsHandler(%r, %r)', pickle_dir, config_dir)
111 self._persistent_dir = pickle_dir
112 self._config_writer_cfg_dir = config_dir
114 self._config_build_templates()
115 InitdHandler.__init__(self)
116 self.host = HostHandler(self)
117 self.zone = ZoneHandler(self)
118 self.mx = MailExchangeHandler(self)
119 self.ns = NameServerHandler(self)
121 def _zone_filename(self, zone):
122 return zone.name + '.zone'
124 def _get_config_vars(self, config_file):
125 return dict(zones=self.zones.values(), **self.params)
127 def _write_config(self):
128 r"_write_config() -> None :: Generate all the configuration files."
129 log.debug(u'DnsHandler._write_config()')
130 delete_zones = list()
131 for a_zone in self.zones.values():
132 log.debug(u'DnsHandler._write_config: processing zone %s', a_zone)
133 if a_zone._update or a_zone._add:
134 if not a_zone._add and self._service_running:
135 log.debug(u'DnsHandler._write_config: zone updated and '
136 u'the service is running, freezing zone')
137 call(('rndc', 'freeze', a_zone.name))
140 hosts = a_zone.hosts.values(),
141 mxs = a_zone.mxs.values(),
142 nss = a_zone.nss.values()
144 self._write_single_config('zoneX.zone',
145 self._zone_filename(a_zone), vars)
146 a_zone._update = False
147 if not a_zone._add and self._service_running:
148 log.debug(u'DnsHandler._write_config: unfreezing zone')
149 call(('rndc', 'thaw', a_zone.name))
154 #borro el archivo .zone
155 log.debug(u'DnsHandler._write_config: zone deleted, removing '
156 u'the file %r', self._zone_filename(a_zone))
159 unlink(self._zone_filename(a_zone))
161 #la excepcion pude darse en caso que haga un add de una zona y
162 #luego el del, como no hice commit, no se crea el archivo
163 log.debug(u'DnsHandler._write_config: file not found')
165 delete_zones.append(a_zone.name)
167 for z in delete_zones:
171 self._write_single_config('named.conf')
173 return False # Do reload
174 return True # we don't need to reload
177 def handle_timer(self):
178 log.debug(u'DnsHandler.handle_timer()')
180 p = subprocess.Popen(('pgrep', '-f', '/usr/sbin/named'),
181 stdout=subprocess.PIPE)
182 pid = p.communicate()[0]
183 if p.returncode == 0 and len(pid) > 0:
184 log.debug(u'DnsHandler.handle_timer: pid present, running')
185 self._service_running = True
187 log.debug(u'DnsHandler.handle_timer: pid absent, NOT running')
188 self._service_running = False
192 if __name__ == '__main__':
195 level = logging.DEBUG,
196 format = '%(asctime)s %(levelname)-8s %(message)s',
197 datefmt = '%H:%M:%S',
202 dns.set('isp_dns1','la_garcha.com')
203 dns.set('bind_addr1','localhost')
204 dns.zone.add('zona_loca.com')
205 #dns.zone.update('zona_loca.com','ns1.dominio.com')
207 dns.host.add('zona_loca.com','hostname_loco','192.168.0.23')
208 dns.host.update('zona_loca.com','hostname_loco','192.168.0.66')
210 dns.host.add('zona_loca.com','hostname_kuak','192.168.0.23')
211 dns.host.delete('zona_loca.com','hostname_kuak')
213 dns.host.add('zona_loca.com','hostname_kuang','192.168.0.24')
214 dns.host.add('zona_loca.com','hostname_chan','192.168.0.25')
215 dns.host.add('zona_loca.com','hostname_kaine','192.168.0.26')
217 dns.mx.add('zona_loca.com','mx1.sarasa.com',10)
218 dns.mx.update('zona_loca.com','mx1.sarasa.com',20)
219 dns.mx.add('zona_loca.com','mx2.sarasa.com',30)
220 dns.mx.add('zona_loca.com','mx3.sarasa.com',40)
221 dns.mx.delete('zona_loca.com','mx3.sarasa.com')
223 dns.ns.add('zona_loca.com','ns1.jua.com')
224 dns.ns.add('zona_loca.com','ns2.jua.com')
225 dns.ns.add('zona_loca.com','ns3.jua.com')
226 dns.ns.delete('zona_loca.com','ns3.jua.com')
228 dns.zone.add('zona_oscura')
230 dns.host.add('zona_oscura','hostname_a','192.168.0.24')
231 dns.host.add('zona_oscura','hostname_b','192.168.0.25')
232 dns.host.add('zona_oscura','hostname_c','192.168.0.26')
234 dns.zone.delete('zona_oscura')
238 print 'ZONAS :', dns.zone.show()
240 print 'HOSTS from', z, ':', dns.host.show(z)
244 # dns.zone.update('zone-sarasa','lalal')
245 #except ZoneNotFoundError, inst:
246 # print 'Error: ', inst
248 from pymin.services.util import ItemNotFoundError, ItemAlreadyExistsError, \
249 ContainerNotFoundError
252 dns.zone.delete('zone-sarasa')
253 except ItemNotFoundError, inst:
254 print 'Error: ', inst
257 # dns.zone.add('zona_loca.com','ns1.dom.com','ns2.dom.com')
258 #except ZoneAlreadyExistsError, inst:
259 # print 'Error: ', inst
264 dns.host.update('zone-sarasa','kuak','192.68')
265 except ContainerNotFoundError, inst:
266 print 'Error: ', inst
269 dns.host.update('zona_loca.com','kuak','192.68')
270 except ItemNotFoundError, inst:
271 print 'Error: ', inst
274 dns.host.delete('zone-sarasa','lala')
275 except ContainerNotFoundError, inst:
276 print 'Error: ', inst
279 dns.host.delete('zona_loca.com','lala')
280 except ItemNotFoundError, inst:
281 print 'Error: ', inst
284 dns.host.add('zona','hostname_loco','192.168.0.23')
285 except ContainerNotFoundError, inst:
286 print 'Error: ', inst
289 dns.host.add('zona_loca.com','hostname_loco','192.168.0.23')
290 except ItemAlreadyExistsError, inst:
291 print 'Error: ', inst