pvl.hosts-dns: generate --forward-zone=paivola.fi and --reverse-zone=194.197.235.0/24
#!/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)