bin/pvl.hosts-dns
changeset 269 713d0495288e
child 270 bafcda3a3c0d
equal deleted inserted replaced
268:560ba0544254 269:713d0495288e
       
     1 #!/usr/bin/env python
       
     2 
       
     3 
       
     4 import pvl.args
       
     5 import pvl.dns.zone
       
     6 
       
     7 import configobj
       
     8 import ipaddr
       
     9 import logging; log = logging.getLogger('pvl.hosts-dns')
       
    10 import math
       
    11 import optparse
       
    12 
       
    13 def apply_hosts_file (options, file) :
       
    14     """
       
    15         Load hosts from a file.
       
    16     """
       
    17     config = configobj.ConfigObj(file,
       
    18             encoding    = options.hosts_charset,
       
    19     )
       
    20 
       
    21     for host in config.sections :
       
    22         yield host, config[host]
       
    23 
       
    24 def apply_hosts (options, args) :
       
    25     """
       
    26         Load hosts from arguments.
       
    27     """
       
    28 
       
    29     for file in pvl.args.apply_files(args, 'r') :
       
    30         for host in apply_hosts_file(options, file) :
       
    31             yield host
       
    32 
       
    33 def process_hosts_forward (options, hosts) :
       
    34     for host, fields in hosts :
       
    35         domain = fields.get('domain', options.hosts_domain)
       
    36 
       
    37         if options.forward_zone and domain != options.forward_zone :
       
    38             continue
       
    39         
       
    40         ip = fields.get('ip')
       
    41 
       
    42         if ip :
       
    43             yield pvl.dns.zone.ZoneRecord.A(host, value)
       
    44         
       
    45         # aliases
       
    46         for field, value in fields.iteritems() :
       
    47             if field.startswith('alias.') :
       
    48                 yield pvl.dns.zone.ZoneRecord.CNAME(value, host)
       
    49 
       
    50 def apply_reverse_zone (options, prefix, address) :
       
    51     """
       
    52         Determine the correct reverse-dns name for the given address with the reverse zone for the given prefix.
       
    53     """
       
    54 
       
    55     assert prefix.version == address.version
       
    56     
       
    57     hostbits = prefix.max_prefixlen - prefix.prefixlen
       
    58 
       
    59     if prefix.version == 4 :
       
    60         labelbytes = int(math.ceil(hostbits / 8.0))
       
    61         labelraw = address.packed[-labelbytes:]
       
    62 
       
    63         return '.'.join(reversed([str(ord(x)) for x in labelraw]))
       
    64     else :
       
    65         raise ValueError("unsupported address version: %s" % (prefix, ))
       
    66 
       
    67 def process_hosts_reverse (options, hosts) :
       
    68     for host, fields in hosts :
       
    69         domain = fields.get('domain', options.hosts_domain)
       
    70         ip = fields.get('ip')
       
    71 
       
    72         if ip :
       
    73             ip = ipaddr.IPAddress(ip)
       
    74 
       
    75         if not ip or ip not in options.reverse_zone :
       
    76             continue
       
    77         
       
    78         # reverse against the prefix origin
       
    79         ptr = apply_reverse_zone(options, options.reverse_zone, ip)
       
    80         
       
    81         yield pvl.dns.zone.ZoneRecord.PTR(ptr, pvl.dns.zone.fqdn(host, domain))
       
    82 
       
    83 def main (argv) :
       
    84     """
       
    85         Generate bind zonefiles from host definitions.
       
    86     """
       
    87 
       
    88     parser = optparse.OptionParser(main.__doc__)
       
    89     parser.add_option_group(pvl.args.parser(parser))
       
    90     
       
    91     hosts = optparse.OptionGroup(parser, "Hosts input")
       
    92     hosts.add_option('--hosts-charset',         metavar='CHARSET',  default='utf-8', 
       
    93             help="Encoding used for host files")
       
    94 
       
    95     hosts.add_option('--hosts-domain',          metavar='DOMAIN',
       
    96             help="Default domain for hosts")
       
    97     
       
    98     parser.add_option_group(hosts)
       
    99 
       
   100     parser.add_option('--forward-zone',         metavar='DOMAIN',
       
   101             help="Generate forward zone for domain")
       
   102 
       
   103     parser.add_option('--reverse-zone',         metavar='PREFIX',
       
   104             help="Generate reverse zone for prefx")
       
   105 
       
   106     options, args = parser.parse_args(argv[1:])
       
   107     pvl.args.apply(options)
       
   108 
       
   109     # input
       
   110     hosts = list(apply_hosts(options, args))
       
   111 
       
   112 
       
   113     if options.forward_zone :
       
   114         zone = process_hosts_forward(options, hosts)
       
   115     
       
   116     elif options.reverse_zone :
       
   117         options.reverse_zone = ipaddr.IPNetwork(options.reverse_zone)
       
   118 
       
   119         zone = process_hosts_reverse(options, hosts)
       
   120 
       
   121     else :
       
   122         log.error("nothing to do")
       
   123         return 1
       
   124     
       
   125     for record in zone :
       
   126         print unicode(record)
       
   127 
       
   128 if __name__ == '__main__':
       
   129     pvl.args.main(main)