terom@269: #!/usr/bin/env python terom@269: terom@269: import pvl.args terom@270: import pvl.hosts terom@269: import pvl.dns.zone terom@269: terom@269: import ipaddr terom@269: import logging; log = logging.getLogger('pvl.hosts-dns') terom@269: import optparse terom@269: terom@273: def process_hosts_names (options, hosts, domain) : terom@269: """ terom@273: Yield ZoneRecords for the given domain's hosts. terom@269: """ terom@269: terom@270: for host in hosts : terom@270: if options.forward_zone and host.domain != domain : terom@269: continue terom@269: terom@270: if host.ip : terom@270: yield pvl.dns.zone.ZoneRecord.A(host, host.ip) terom@269: terom@270: for alias in host.alias : terom@270: yield pvl.dns.zone.ZoneRecord.CNAME(alias, host) terom@269: terom@273: def process_hosts_forward (options, hosts, domain) : terom@273: """ terom@273: Generate DNS ZoneRecords for the given domain's zone for hosts. terom@273: """ terom@273: terom@273: by_name = dict() terom@273: terom@273: for rr in process_hosts_names(options, hosts, domain) : terom@273: if rr.name in by_name : terom@273: raise ValueError("%s: duplicate name: %s: %s" % (rr.name, rr, by_name[rr.name])) terom@273: else : terom@273: by_name[rr.name] = rr terom@273: terom@273: # preserve ordering terom@273: yield rr terom@273: terom@272: def process_hosts_ips (options, hosts, prefix) : terom@269: """ terom@272: Yield (ip, fqnd) for hosts within given prefix. terom@269: """ terom@269: terom@270: for host in hosts : terom@283: if prefix.version == 4 : terom@283: ip = host.ip terom@283: elif prefix.version == 6 : terom@283: ip = host.ip6 terom@283: else : terom@283: raise ValueError("%s: unknown ip version: %s" % (prefix, prefix.version)) terom@283: terom@283: if not ip : terom@270: continue terom@269: terom@283: if ip not in prefix : terom@269: continue terom@272: terom@283: yield ip, pvl.dns.zone.fqdn(host, host.domain) terom@272: terom@272: def process_hosts_reverse (options, hosts, prefix) : terom@272: """ terom@272: Generate DNS ZoneRecords within the given prefix's reverse-dns zone for hosts. terom@272: """ terom@272: terom@272: # collect data for records terom@272: by_ip = dict() terom@272: for ip, fqdn in process_hosts_ips(options, hosts, prefix) : terom@272: if ip in by_ip : terom@272: raise ValueError("%s: duplicate ip: %s: %s" % (fqdn, ip, by_ip[ip])) terom@272: else : terom@272: by_ip[ip] = fqdn terom@272: terom@278: if options.unknown_host : terom@278: # enumerate all of them terom@278: iter_ips = prefix.iterhosts() terom@278: else : terom@278: iter_ips = sorted(by_ip) terom@278: terom@278: for ip in iter_ips : terom@272: if ip in by_ip : terom@272: fqdn = by_ip[ip] terom@272: elif options.unknown_host : terom@272: fqdn = pvl.dns.zone.fqdn(options.unknown_host, options.hosts_domain) terom@272: else : terom@272: fqdn = None terom@269: terom@272: if fqdn : terom@272: # reverse against the reverse-dns zone origin terom@272: yield pvl.dns.zone.ZoneRecord.PTR(pvl.dns.zone.reverse_label(prefix, ip), fqdn) terom@270: terom@270: def apply_zone (options, zone) : terom@270: """ terom@270: Output given ZoneRecord's terom@270: """ terom@270: terom@270: for record in zone : terom@270: print unicode(record) terom@269: terom@269: def main (argv) : terom@269: """ terom@269: Generate bind zonefiles from host definitions. terom@269: """ terom@269: terom@269: parser = optparse.OptionParser(main.__doc__) terom@269: parser.add_option_group(pvl.args.parser(parser)) terom@270: parser.add_option_group(pvl.hosts.optparser(parser)) terom@269: terom@269: parser.add_option('--forward-zone', metavar='DOMAIN', terom@269: help="Generate forward zone for domain") terom@269: terom@269: parser.add_option('--reverse-zone', metavar='PREFIX', terom@269: help="Generate reverse zone for prefx") terom@269: terom@272: parser.add_option('--unknown-host', metavar='NAME', terom@272: help="Generate records for unused IPs") terom@272: terom@269: options, args = parser.parse_args(argv[1:]) terom@269: pvl.args.apply(options) terom@269: terom@269: # input terom@270: hosts = pvl.hosts.apply(options, args) terom@269: terom@270: # process terom@269: if options.forward_zone : terom@270: apply_zone(options, terom@270: process_hosts_forward(options, hosts, options.forward_zone), terom@270: ) terom@269: terom@270: if options.reverse_zone : terom@270: apply_zone(options, terom@270: process_hosts_reverse(options, hosts, ipaddr.IPNetwork(options.reverse_zone)), terom@270: ) terom@269: terom@269: if __name__ == '__main__': terom@269: pvl.args.main(main)