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', 'get_service')
17 def get_service(config):
18 return DnsHandler(config.dns.pickle_dir, config.dns.config_dir)
22 def __init__(self, name, ip):
25 def update(self, ip=None):
26 if ip is not None: self.ip = ip
28 return (self.name, self.ip)
30 class HostHandler(DictComposedSubHandler):
31 handler_help = u"Manage DNS hosts"
32 _comp_subhandler_cont = 'zones'
33 _comp_subhandler_attr = 'hosts'
34 _comp_subhandler_class = Host
36 class MailExchange(Sequence):
37 def __init__(self, mx, prio):
40 def update(self, prio=None):
41 if prio is not None: self.prio = prio
43 return (self.mx, self.prio)
45 class MailExchangeHandler(DictComposedSubHandler):
46 handler_help = u"Manage DNS mail exchangers (MX)"
47 _comp_subhandler_cont = 'zones'
48 _comp_subhandler_attr = 'mxs'
49 _comp_subhandler_class = MailExchange
51 class NameServer(Sequence):
52 def __init__(self, name):
57 class NameServerHandler(DictComposedSubHandler):
58 handler_help = u"Manage DNS name servers (NS)"
59 _comp_subhandler_cont = 'zones'
60 _comp_subhandler_attr = 'nss'
61 _comp_subhandler_class = NameServer
64 def __init__(self, name):
73 return (self.name, self.hosts, self.mxs, self.nss)
75 class ZoneHandler(DictSubHandler):
76 handler_help = u"Manage DNS zones"
77 _cont_subhandler_attr = 'zones'
78 _cont_subhandler_class = Zone
80 class DnsHandler(Restorable, ConfigWriter, InitdHandler, TransactionalHandler,
82 r"""DnsHandler([pickle_dir[, config_dir]]) -> DnsHandler instance.
84 Handles DNS service commands for the dns program.
86 pickle_dir - Directory where to write the persistent configuration data.
88 config_dir - Directory where to store de generated configuration files.
90 Both defaults to the current working directory.
93 handler_help = u"Manage DNS service"
97 _persistent_attrs = ('params', 'zones')
99 _restorable_defaults = dict(
109 _config_writer_files = ('named.conf', 'zoneX.zone')
110 _config_writer_tpl_dir = path.join(path.dirname(__file__), 'templates')
112 def __init__(self, pickle_dir='.', config_dir='.'):
113 r"Initialize DnsHandler object, see class documentation for details."
114 log.debug(u'DnsHandler(%r, %r)', pickle_dir, config_dir)
115 self._persistent_dir = pickle_dir
116 self._config_writer_cfg_dir = config_dir
118 self._config_build_templates()
119 InitdHandler.__init__(self)
120 self.host = HostHandler(self)
121 self.zone = ZoneHandler(self)
122 self.mx = MailExchangeHandler(self)
123 self.ns = NameServerHandler(self)
125 def _zone_filename(self, zone):
126 return zone.name + '.zone'
128 def _get_config_vars(self, config_file):
129 return dict(zones=self.zones.values(), **self.params)
131 def _write_config(self):
132 r"_write_config() -> None :: Generate all the configuration files."
133 log.debug(u'DnsHandler._write_config()')
134 delete_zones = list()
135 for a_zone in self.zones.values():
136 log.debug(u'DnsHandler._write_config: processing zone %s', a_zone)
137 if a_zone._update or a_zone._add:
138 if not a_zone._add and self._service_running:
139 log.debug(u'DnsHandler._write_config: zone updated and '
140 u'the service is running, freezing zone')
141 call(('rndc', 'freeze', a_zone.name))
144 hosts = a_zone.hosts.values(),
145 mxs = a_zone.mxs.values(),
146 nss = a_zone.nss.values()
148 self._write_single_config('zoneX.zone',
149 self._zone_filename(a_zone), vars)
150 a_zone._update = False
151 if not a_zone._add and self._service_running:
152 log.debug(u'DnsHandler._write_config: unfreezing zone')
153 call(('rndc', 'thaw', a_zone.name))
158 #borro el archivo .zone
159 log.debug(u'DnsHandler._write_config: zone deleted, removing '
160 u'the file %r', self._zone_filename(a_zone))
163 unlink(self._zone_filename(a_zone))
165 #la excepcion pude darse en caso que haga un add de una zona y
166 #luego el del, como no hice commit, no se crea el archivo
167 log.debug(u'DnsHandler._write_config: file not found')
169 delete_zones.append(a_zone.name)
171 for z in delete_zones:
175 self._write_single_config('named.conf')
177 return False # Do reload
178 return True # we don't need to reload
181 def handle_timer(self):
182 log.debug(u'DnsHandler.handle_timer()')
184 p = subprocess.Popen(('pgrep', '-f', '/usr/sbin/named'),
185 stdout=subprocess.PIPE)
186 pid = p.communicate()[0]
187 if p.returncode == 0 and len(pid) > 0:
188 log.debug(u'DnsHandler.handle_timer: pid present, running')
189 self._service_running = True
191 log.debug(u'DnsHandler.handle_timer: pid absent, NOT running')
192 self._service_running = False
196 if __name__ == '__main__':
199 level = logging.DEBUG,
200 format = '%(asctime)s %(levelname)-8s %(message)s',
201 datefmt = '%H:%M:%S',
206 dns.set('isp_dns1','la_garcha.com')
207 dns.set('bind_addr1','localhost')
208 dns.zone.add('zona_loca.com')
209 #dns.zone.update('zona_loca.com','ns1.dominio.com')
211 dns.host.add('zona_loca.com','hostname_loco','192.168.0.23')
212 dns.host.update('zona_loca.com','hostname_loco','192.168.0.66')
214 dns.host.add('zona_loca.com','hostname_kuak','192.168.0.23')
215 dns.host.delete('zona_loca.com','hostname_kuak')
217 dns.host.add('zona_loca.com','hostname_kuang','192.168.0.24')
218 dns.host.add('zona_loca.com','hostname_chan','192.168.0.25')
219 dns.host.add('zona_loca.com','hostname_kaine','192.168.0.26')
221 dns.mx.add('zona_loca.com','mx1.sarasa.com',10)
222 dns.mx.update('zona_loca.com','mx1.sarasa.com',20)
223 dns.mx.add('zona_loca.com','mx2.sarasa.com',30)
224 dns.mx.add('zona_loca.com','mx3.sarasa.com',40)
225 dns.mx.delete('zona_loca.com','mx3.sarasa.com')
227 dns.ns.add('zona_loca.com','ns1.jua.com')
228 dns.ns.add('zona_loca.com','ns2.jua.com')
229 dns.ns.add('zona_loca.com','ns3.jua.com')
230 dns.ns.delete('zona_loca.com','ns3.jua.com')
232 dns.zone.add('zona_oscura')
234 dns.host.add('zona_oscura','hostname_a','192.168.0.24')
235 dns.host.add('zona_oscura','hostname_b','192.168.0.25')
236 dns.host.add('zona_oscura','hostname_c','192.168.0.26')
238 dns.zone.delete('zona_oscura')
242 print 'ZONAS :', dns.zone.show()
244 print 'HOSTS from', z, ':', dns.host.show(z)
248 # dns.zone.update('zone-sarasa','lalal')
249 #except ZoneNotFoundError, inst:
250 # print 'Error: ', inst
252 from pymin.services.util import ItemNotFoundError, ItemAlreadyExistsError, \
253 ContainerNotFoundError
256 dns.zone.delete('zone-sarasa')
257 except ItemNotFoundError, inst:
258 print 'Error: ', inst
261 # dns.zone.add('zona_loca.com','ns1.dom.com','ns2.dom.com')
262 #except ZoneAlreadyExistsError, inst:
263 # print 'Error: ', inst
268 dns.host.update('zone-sarasa','kuak','192.68')
269 except ContainerNotFoundError, inst:
270 print 'Error: ', inst
273 dns.host.update('zona_loca.com','kuak','192.68')
274 except ItemNotFoundError, inst:
275 print 'Error: ', inst
278 dns.host.delete('zone-sarasa','lala')
279 except ContainerNotFoundError, inst:
280 print 'Error: ', inst
283 dns.host.delete('zona_loca.com','lala')
284 except ItemNotFoundError, inst:
285 print 'Error: ', inst
288 dns.host.add('zona','hostname_loco','192.168.0.23')
289 except ContainerNotFoundError, inst:
290 print 'Error: ', inst
293 dns.host.add('zona_loca.com','hostname_loco','192.168.0.23')
294 except ItemAlreadyExistsError, inst:
295 print 'Error: ', inst