--- a/bin/pvl.hosts-dns Sat Dec 21 22:57:48 2013 +0200
+++ b/bin/pvl.hosts-dns Sun Dec 22 17:25:09 2013 +0200
@@ -42,7 +42,20 @@
fqdn = pvl.dns.join(host, host.domain)
label = fqdn[:(len(fqdn) - len(origin) - 1)]
else :
- log.debug("%s: %s out of zone: %s", host, host.domain, origin)
+ log.debug("%s: domain %s out of zone: %s", host, host.domain, origin)
+ continue
+
+ if host.forward is None :
+ pass
+ elif host.forward :
+ forward = pvl.dns.join(host, host.forward, host.domain)
+
+ log.info("%s: forward: %s", host, forward)
+
+ yield pvl.dns.zone.ZoneRecord.CNAME(label, forward)
+ continue
+ else :
+ log.info("%s: skip forward", host)
continue
if host.ip :
@@ -173,11 +186,26 @@
log.debug("%s: %s out of prefix: %s", host, ip, prefix)
continue
- fqdn = host.fqdn()
+ label = pvl.dns.zone.reverse_label(prefix, ip)
+
+ if host.reverse is None :
+ fqdn = host.fqdn()
- log.debug("%s: ip=%s domain=%s: %s", host, ip, host.domain, fqdn)
+ log.info("%s %s[%s]: PTR %s", host, prefix, ip, fqdn)
- yield ip, fqdn
+ yield host, ip, pvl.dns.zone.ZoneRecord.PTR(label, fqdn)
+
+ elif host.reverse :
+ alias = pvl.dns.join(label, host.reverse, host.domain)
+
+ log.info("%s %s[%s]: CNAME %s", host, prefix, ip, alias)
+
+ yield host, ip, pvl.dns.zone.ZoneRecord.CNAME(label, alias)
+
+ else :
+ log.info("%s %s[%s]: omit", host, prefix, ip)
+ continue
+
def process_hosts_reverse (options, hosts, prefix) :
"""
@@ -186,11 +214,11 @@
# collect data for records
by_ip = dict()
- for ip, fqdn in process_hosts_ips(options, hosts, prefix) :
+ for host, ip, rr in process_hosts_ips(options, hosts, prefix) :
if ip in by_ip :
- raise ValueError("%s: duplicate ip: %s: %s" % (fqdn, ip, by_ip[ip]))
+ raise ValueError("%s: duplicate ip: %s: %s" % (host, ip, by_ip[ip]))
else :
- by_ip[ip] = fqdn
+ by_ip[ip] = rr
if options.unknown_host :
# enumerate all of them
@@ -200,17 +228,16 @@
for ip in iter_ips :
if ip in by_ip :
- fqdn = by_ip[ip]
+ yield by_ip[ip]
elif options.unknown_host :
+ label = pvl.dns.zone.reverse_label(prefix, ip)
fqdn = pvl.dns.zone.fqdn(options.unknown_host, options.hosts_domain)
+
+ log.info("%s %s[%s]: unused PTR %s", options.unknown_host, ip, prefix, fqdn)
+
+ yield pvl.dns.zone.ZoneRecord.PTR(label, fqdn)
else :
- fqdn = None
-
- log.info("%s: %s", ip, fqdn)
-
- if fqdn :
- # reverse against the reverse-dns zone origin
- yield pvl.dns.zone.ZoneRecord.PTR(pvl.dns.zone.reverse_label(prefix, ip), fqdn)
+ continue
def apply_zone (options, zone) :
"""
--- a/pvl/hosts.py Sat Dec 21 22:57:48 2013 +0200
+++ b/pvl/hosts.py Sun Dec 22 17:25:09 2013 +0200
@@ -10,6 +10,8 @@
import optparse
import os.path
+import logging; log = logging.getLogger('pvl.hosts')
+
def optparser (parser) :
hosts = optparse.OptionGroup(parser, "Hosts input")
hosts.add_option('--hosts-charset', metavar='CHARSET', default='utf-8',
@@ -26,22 +28,41 @@
ALIAS6_FMT = '{host}-ipv6'
@classmethod
- def expand (cls, options, host, range, ip, **opts) :
+ def expand (cls, options, range, host, domain, ip, **opts) :
host = pvl.dns.zone.parse_generate_field(host)
ip = pvl.dns.zone.parse_generate_field(ip)
for i in range :
- yield cls.build(options, host(i),
+ yield cls.build(options, host(i), domain,
ip = ip(i),
**opts
)
@classmethod
- def config (cls, options, host, ip=None, **extra) :
+ def config (cls, options, host, section=None, domain=None, ip=None, **extra) :
"""
Yield Hosts from a config section's scalars.
+
+ options - pvl.args Options
+ host - the name of the section (or file) containing this host item.
+ section - the parent section containing this host item, or None
+ used for domain
"""
+ if domain :
+ log.debug("%s: explicit domain: %s", host, domain)
+ elif options.hosts_domain :
+ log.debug("%s: default domain to --hots-domain: %s", host, options.hosts_domain)
+ domain = options.hosts_domain
+ elif section :
+ log.debug("%s: default domain to section: %s", host, section)
+ domain = section
+ elif '.' in host :
+ log.debug("%s: using as fqdn without domain", host)
+ domain = None
+ else :
+ raise ValueError("%s: no domain given" % (host, ))
+
if '{' in host :
pre, host = host.split('{', 1)
range, post = host.rsplit('}', 1)
@@ -49,15 +70,18 @@
range = pvl.dns.zone.parse_generate_range(range)
host = pre + "$" + post
- for host in cls.expand(options, host, range, ip, **extra) :
+ for host in cls.expand(options, range, host, domain, ip, **extra) :
yield host
else :
- yield cls.build(options, host, ip=ip, **extra)
+ yield cls.build(options, host, domain, ip=ip, **extra)
@classmethod
- def build (cls, options, host, domain=None, ip=None, ip6=None, owner=None, boot=None, alias=None, alias4=None, alias6=None, **extra) :
+ def build (cls, options, host, domain,
+ ip=None, ip6=None, owner=None, boot=None, alias=None, alias4=None, alias6=None, forward=None, reverse=None,
+ **extra) :
"""
Return a Host from a config section's scalars.
+
"""
if alias :
@@ -92,9 +116,27 @@
else :
raise ValueError("%s: Unknown host field: %s=%s" % (host, field, value))
- if domain is None :
- domain = options.hosts_domain
+
+ if forward is None :
+ # normal zone
+ pass
+ elif forward :
+ # alias to external zone
+ pass
+ else :
+ # omit
+ forward = False
+ if reverse is None :
+ # normal zone
+ pass
+ elif reverse :
+ # alias to external zone
+ pass
+ else :
+ # omit
+ reverse = False
+
return cls(host,
domain = domain,
ip = ipaddr.IPv4Address(ip) if ip else None,
@@ -105,9 +147,20 @@
alias6 = alias6,
owner = owner,
boot = boot,
+ forward = forward,
+ reverse = reverse,
)
- def __init__ (self, host, domain=None, ip=None, ip6=None, ethernet={ }, alias=(), owner=None, boot=None, alias4=None, alias6=None) :
+ def __init__ (self, host,
+ domain=None,
+ ip=None, ip6=None,
+ ethernet={ },
+ alias=(),
+ owner=None,
+ boot=None,
+ alias4=None, alias6=None,
+ forward=None, reverse=None,
+ ) :
"""
host - str
domain - str
@@ -118,7 +171,10 @@
owner - str: LDAP uid
alias4 - list (CNAME -> A)
alias6 - list (CNAME -> AAAA)
+ forward - generate forward records, or CNAME into given zone
+ reverse - generate reverse records, or CNAME into given zone
"""
+
self.host = host
self.domain = domain
self.ip = ip
@@ -129,6 +185,8 @@
self.alias6 = alias6
self.owner = owner
self.boot = boot
+ self.forward = forward
+ self.reverse = reverse
def fqdn (self) :
if '.' in self.host :
@@ -141,7 +199,7 @@
def __str__ (self) :
return str(self.host)
-def apply_hosts_config (options, config, name, defaults={}) :
+def apply_hosts_config (options, config, name, defaults={}, parent=None) :
"""
Load hosts from a ConfigObj section.
"""
@@ -150,18 +208,18 @@
if config.sections :
# recurse; this is a domain meta-section
- params = dict(defaults, domain=name)
+ params = dict(defaults)
params.update(**scalars) # override
for section in config.sections :
- for host in apply_hosts_config(options, config[section], section, params) :
+ for host in apply_hosts_config(options, config[section], section, params, name) :
yield host
elif name :
params = dict(defaults, **scalars)
# this is a host section
- for host in Host.config(options, name, **params) :
+ for host in Host.config(options, name, parent, **params) :
yield host
else :