pvl.hosts: rename Host.ip -> Host.ip4; support instanced ip.foo = ... for foo.host A .... sub-labels
--- a/pvl/hosts/dhcp.py Sat Mar 07 16:31:11 2015 +0200
+++ b/pvl/hosts/dhcp.py Mon Mar 09 18:00:18 2015 +0200
@@ -24,8 +24,8 @@
yield 'option', 'host-name', host.name
yield 'hardware', 'ethernet', pvl.dhcp.config.Field(ethernet)
- if host.ip:
- yield 'fixed-address', pvl.dhcp.config.Field(str(host.ip))
+ if host.ip4:
+ yield 'fixed-address', pvl.dhcp.config.Field(str(host.ip4))
for bootopt in ('next-server', 'filename'):
if bootopt in host.boot:
--- a/pvl/hosts/host.py Sat Mar 07 16:31:11 2015 +0200
+++ b/pvl/hosts/host.py Mon Mar 09 18:00:18 2015 +0200
@@ -176,10 +176,16 @@
This handles all string parsing to our data types.
"""
+ ip4 = parse_dict(ip, ipaddr.IPv4Address)
+ ip6 = parse_dict(ip6, ipaddr.IPv6Address)
+
+ ip = {label: (ip4.get(label), ip6.get(label)) for label in set(ip4) | set(ip6)}
+
return cls(name,
domain = domain,
- ip = parse_ip(ip, ipaddr.IPv4Address),
- ip6 = parse_ip(ip6, ipaddr.IPv6Address),
+ ip4 = ip4.get(None),
+ ip6 = ip6.get(None),
+ ip = ip,
ethernet = parse_dict(ethernet, parse_ethernet),
owner = owner,
location = parse_location(location, domain),
@@ -194,7 +200,8 @@
)
def __init__ (self, name, domain,
- ip=None, ip6=None,
+ ip4=None, ip6=None,
+ ip={},
ethernet={ },
owner=None,
location=None,
@@ -207,8 +214,9 @@
"""
name - str
domain - str
- ip - ipaddr.IPv4Address
- ip6 - ipaddr.IPv6Address
+ ip4 - primary ipaddr.IPv4Address
+ ip6 - primary ipaddr.IPv6Address
+ ip - secondary { index: (ip4, ip6) } interface addresses
ethernet - { index: ethernet }
alias - [ str ]: generate CNAMEs for given relative names
owner - str: LDAP uid
@@ -226,8 +234,9 @@
self.name = name
self.domain = domain
+ self.ip4 = ip4
+ self.ip6 = ip6
self.ip = ip
- self.ip6 = ip6
self.ethernet = ethernet
self.alias = alias
self.alias4 = alias4
--- a/pvl/hosts/tests.py Sat Mar 07 16:31:11 2015 +0200
+++ b/pvl/hosts/tests.py Mon Mar 09 18:00:18 2015 +0200
@@ -99,10 +99,12 @@
])
def testApplyHostExpand(self):
- self.assertHostsEqual(config.apply_hosts('test', 'asdf{1-3}', { 'ip': '10.100.100.$' }), [
- ('asdf1@test', dict(ip=ipaddr.IPAddress('10.100.100.1'))),
- ('asdf2@test', dict(ip=ipaddr.IPAddress('10.100.100.2'))),
- ('asdf3@test', dict(ip=ipaddr.IPAddress('10.100.100.3'))),
+ self.assertHostsEqual(config.apply_hosts('test', 'asdf{1-3}',
+ { 'ip': '10.100.100.$' }
+ ), [
+ ('asdf1@test', dict(ip4=ipaddr.IPAddress('10.100.100.1'))),
+ ('asdf2@test', dict(ip4=ipaddr.IPAddress('10.100.100.2'))),
+ ('asdf3@test', dict(ip4=ipaddr.IPAddress('10.100.100.3'))),
])
def testApplyHostsFileError(self):
@@ -119,8 +121,8 @@
""")
self.assertHostsEqual(config.apply_hosts_config(self.options, conf_file), [
- ('foo@test', dict(ip=ipaddr.IPAddress('127.0.0.1'))),
- ('bar@test', dict(ip=ipaddr.IPAddress('127.0.0.2'))),
+ ('foo@test', dict(ip4=ipaddr.IPAddress('127.0.0.1'))),
+ ('bar@test', dict(ip4=ipaddr.IPAddress('127.0.0.2'))),
])
def testApplyHostsConfigNested(self):
@@ -135,8 +137,8 @@
""")
self.assertHostsEqual(config.apply_hosts_config(self.options, conf_file), [
- ('foo@asdf.test', dict(ip=ipaddr.IPAddress('127.0.0.1'))),
- ('bar@quux.test', dict(ip=ipaddr.IPAddress('127.0.0.2'))),
+ ('foo@asdf.test', dict(ip4=ipaddr.IPAddress('127.0.0.1'))),
+ ('bar@quux.test', dict(ip4=ipaddr.IPAddress('127.0.0.2'))),
])
def testHostsConfigDdefaults(self):
@@ -151,7 +153,7 @@
self.assertHostsEqual(hosts, [
('foo@test', dict(
- ip = ipaddr.IPAddress('192.0.2.1'),
+ ip4 = ipaddr.IPAddress('192.0.2.1'),
ethernet = { 'eth0': '00:11:22:33:44:55' },
boot = { 'next-server': 'boot.lan', 'filename': '/pxelinux.0' },
)),
@@ -162,10 +164,10 @@
def testApplyIncludes(self):
self.assertHostsEqual(config.apply_hosts_files(self.options, ['etc/hosts/test']), [
('bar@test', dict(
- ip = ipaddr.IPAddress('192.0.2.2'),
+ ip4 = ipaddr.IPAddress('192.0.2.2'),
)),
('foo@test', dict(
- ip = ipaddr.IPAddress('192.0.2.1'),
+ ip4 = ipaddr.IPAddress('192.0.2.1'),
)),
])
@@ -176,10 +178,10 @@
include = etc/hosts/test
""")), [
('bar@test', dict(
- ip = ipaddr.IPAddress('192.0.2.2'),
+ ip4 = ipaddr.IPAddress('192.0.2.2'),
)),
('foo@test', dict(
- ip = ipaddr.IPAddress('192.0.2.1'),
+ ip4 = ipaddr.IPAddress('192.0.2.1'),
)),
])
@@ -194,13 +196,13 @@
self.assertHostsEqual(hosts, [
('quux@asdf.test', dict(
- ip = ipaddr.IPAddress('192.0.2.5'),
+ ip4 = ipaddr.IPAddress('192.0.2.5'),
)),
('bar@test', dict(
- ip = ipaddr.IPAddress('192.0.2.2'),
+ ip4 = ipaddr.IPAddress('192.0.2.2'),
)),
('foo@test', dict(
- ip = ipaddr.IPAddress('192.0.2.1'),
+ ip4 = ipaddr.IPAddress('192.0.2.1'),
)),
])
@@ -216,11 +218,11 @@
def testApply(self):
self.assertHostsEqual(config.apply(self.options, ['etc/hosts/example.com']), [
('foo@example.com', dict(
- ip = ipaddr.IPAddress('192.0.2.1'),
+ ip4 = ipaddr.IPAddress('192.0.2.1'),
ethernet = {None: '00:11:22:33:44:55'},
)),
('bar@example.com', dict(
- ip = ipaddr.IPAddress('192.0.2.2'),
+ ip4 = ipaddr.IPAddress('192.0.2.2'),
ethernet = {None: '01:23:45:67:89:ab'},
)),
])
--- a/pvl/hosts/zone.py Sat Mar 07 16:31:11 2015 +0200
+++ b/pvl/hosts/zone.py Mon Mar 09 18:00:18 2015 +0200
@@ -31,15 +31,21 @@
elif host.forward is None:
# forward
- if host.ip :
- log.info("%s: ip: %s@%s A %s", host, label, origin, host.ip)
+ for sublabel, (ip4, ip6) in host.ip.iteritems():
+ if sublabel:
+ sublabel = pvl.dns.join(sublabel, label)
+ else:
+ sublabel = label
+
+ if ip4:
+ log.info("%s: ip: %s@%s A %s", host, sublabel, origin, ip4)
- yield pvl.dns.ZoneRecord.A(label, host.ip)
+ yield pvl.dns.ZoneRecord.A(sublabel, ip4)
- if host.ip6 :
- log.info("%s: ip6: %s@%s AAAA %s", host, label, origin, host.ip6)
+ if ip6:
+ log.info("%s: ip6: %s@%s AAAA %s", host, label, origin, ip6)
- yield pvl.dns.ZoneRecord.AAAA(label, host.ip6)
+ yield pvl.dns.ZoneRecord.AAAA(sublabel, ip6)
else:
log.info("%s: skip forward", host)
@@ -57,10 +63,10 @@
yield pvl.dns.ZoneRecord.CNAME(pvl.dns.relative(origin, host.domain, alias), label)
for alias in host.alias4:
- if not host.ip:
- raise HostZoneError(host, "alias4={host.alias4} without ip=".format(host=host))
+ if not host.ip4:
+ raise HostZoneError(host, "alias4={host.alias4} without ip4=".format(host=host))
- yield pvl.dns.ZoneRecord.A(pvl.dns.relative(origin, host.domain, alias), host.ip)
+ yield pvl.dns.ZoneRecord.A(pvl.dns.relative(origin, host.domain, alias), host.ip4)
for alias in host.alias6:
if not host.ip6:
@@ -72,50 +78,54 @@
"""
Yield (ipaddr.IPAddress, ZoneRecord) tuples for host within given prefix's reverse-dns zone.
"""
-
- if prefix.version == 4 :
- ip = host.ip
-
- # reverse= is IPv4-only
- reverse = host.reverse
-
- elif prefix.version == 6 :
- ip = host.ip6
-
- # if reverse= is set, always omit, for lack of reverse6=
- reverse = None if host.reverse is None else False
-
- else :
- raise ValueError("%s: unknown ip version: %s" % (prefix, prefix.version))
-
- if not ip :
- log.debug("%s: no ip%d", host, prefix.version)
- return
+
+ for sublabel, (ip4, ip6) in host.ip.iteritems():
+ if prefix.version == 4:
+ ip = ip4
+
+ # reverse= is IPv4-only
+ reverse = host.reverse
- if ip not in prefix :
- log.debug("%s: %s out of prefix: %s", host, ip, prefix)
- return
-
- # relative label
- label = pvl.dns.reverse_label(prefix, ip)
-
- if reverse:
- alias = pvl.dns.fqdn(reverse)
-
- log.info("%s %s[%s]: CNAME %s", host, prefix, ip, alias)
+ elif prefix.version == 6:
+ ip = ip6
+
+ # if reverse= is set, always omit, for lack of reverse6=
+ reverse = None if host.reverse is None else False
- yield ip, pvl.dns.zone.ZoneRecord.CNAME(label, alias)
-
- elif reverse is None :
- fqdn = host.fqdn()
+ else:
+ raise ValueError("%s: unknown ip version: %s" % (prefix, prefix.version))
- log.info("%s %s[%s]: PTR %s", host, prefix, ip, fqdn)
+ if not ip:
+ log.debug("%s: no ip%d", host, prefix.version)
+ continue
- yield ip, pvl.dns.zone.ZoneRecord.PTR(label, fqdn)
+ if ip not in prefix:
+ log.debug("%s: %s out of prefix: %s", host, ip, prefix)
+ continue
+
+ # relative label
+ label = pvl.dns.reverse_label(prefix, ip)
+
+ if reverse:
+ alias = pvl.dns.fqdn(reverse)
+
+ log.info("%s %s[%s]: CNAME %s", host, prefix, ip, alias)
- else:
- log.info("%s %s[%s]: omit", host, prefix, ip)
-
+ yield ip, pvl.dns.zone.ZoneRecord.CNAME(label, alias)
+
+ elif reverse is None:
+ fqdn = host.fqdn()
+
+ if sublabel:
+ fqdn = pvl.dns.join(sublabel, fqdn)
+
+ log.info("%s %s[%s]: PTR %s", host, prefix, ip, fqdn)
+
+ yield ip, pvl.dns.zone.ZoneRecord.PTR(label, fqdn)
+
+ else:
+ log.info("%s %s[%s]: omit", host, prefix, ip)
+
def apply_hosts_forward (hosts, origin,
add_origin = False,
check_conflicts = False,