pvl.hosts-dns: generate --forward-zone=paivola.fi and --reverse-zone=194.197.235.0/24
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/bin/pvl.hosts-dns Mon Dec 16 18:37:08 2013 +0200
@@ -0,0 +1,129 @@
+#!/usr/bin/env python
+
+
+import pvl.args
+import pvl.dns.zone
+
+import configobj
+import ipaddr
+import logging; log = logging.getLogger('pvl.hosts-dns')
+import math
+import optparse
+
+def apply_hosts_file (options, file) :
+ """
+ Load hosts from a file.
+ """
+ config = configobj.ConfigObj(file,
+ encoding = options.hosts_charset,
+ )
+
+ for host in config.sections :
+ yield host, config[host]
+
+def apply_hosts (options, args) :
+ """
+ Load hosts from arguments.
+ """
+
+ for file in pvl.args.apply_files(args, 'r') :
+ for host in apply_hosts_file(options, file) :
+ yield host
+
+def process_hosts_forward (options, hosts) :
+ for host, fields in hosts :
+ domain = fields.get('domain', options.hosts_domain)
+
+ if options.forward_zone and domain != options.forward_zone :
+ continue
+
+ ip = fields.get('ip')
+
+ if ip :
+ yield pvl.dns.zone.ZoneRecord.A(host, value)
+
+ # aliases
+ for field, value in fields.iteritems() :
+ if field.startswith('alias.') :
+ yield pvl.dns.zone.ZoneRecord.CNAME(value, host)
+
+def apply_reverse_zone (options, prefix, address) :
+ """
+ Determine the correct reverse-dns name for the given address with the reverse zone for the given prefix.
+ """
+
+ assert prefix.version == address.version
+
+ hostbits = prefix.max_prefixlen - prefix.prefixlen
+
+ if prefix.version == 4 :
+ labelbytes = int(math.ceil(hostbits / 8.0))
+ labelraw = address.packed[-labelbytes:]
+
+ return '.'.join(reversed([str(ord(x)) for x in labelraw]))
+ else :
+ raise ValueError("unsupported address version: %s" % (prefix, ))
+
+def process_hosts_reverse (options, hosts) :
+ for host, fields in hosts :
+ domain = fields.get('domain', options.hosts_domain)
+ ip = fields.get('ip')
+
+ if ip :
+ ip = ipaddr.IPAddress(ip)
+
+ if not ip or ip not in options.reverse_zone :
+ continue
+
+ # reverse against the prefix origin
+ ptr = apply_reverse_zone(options, options.reverse_zone, ip)
+
+ yield pvl.dns.zone.ZoneRecord.PTR(ptr, pvl.dns.zone.fqdn(host, domain))
+
+def main (argv) :
+ """
+ Generate bind zonefiles from host definitions.
+ """
+
+ parser = optparse.OptionParser(main.__doc__)
+ parser.add_option_group(pvl.args.parser(parser))
+
+ hosts = optparse.OptionGroup(parser, "Hosts input")
+ hosts.add_option('--hosts-charset', metavar='CHARSET', default='utf-8',
+ help="Encoding used for host files")
+
+ hosts.add_option('--hosts-domain', metavar='DOMAIN',
+ help="Default domain for hosts")
+
+ parser.add_option_group(hosts)
+
+ parser.add_option('--forward-zone', metavar='DOMAIN',
+ help="Generate forward zone for domain")
+
+ parser.add_option('--reverse-zone', metavar='PREFIX',
+ help="Generate reverse zone for prefx")
+
+ options, args = parser.parse_args(argv[1:])
+ pvl.args.apply(options)
+
+ # input
+ hosts = list(apply_hosts(options, args))
+
+
+ if options.forward_zone :
+ zone = process_hosts_forward(options, hosts)
+
+ elif options.reverse_zone :
+ options.reverse_zone = ipaddr.IPNetwork(options.reverse_zone)
+
+ zone = process_hosts_reverse(options, hosts)
+
+ else :
+ log.error("nothing to do")
+ return 1
+
+ for record in zone :
+ print unicode(record)
+
+if __name__ == '__main__':
+ pvl.args.main(main)