pvl.hosts: extension mechanism
authorTero Marttila <terom@paivola.fi>
Mon, 09 Mar 2015 19:47:10 +0200
changeset 734 5770ed34c1f0
parent 733 45bedeba92e5
child 735 008cfe47b194
pvl.hosts: extension mechanism
pvl/hosts/__init__.py
pvl/hosts/host.py
pvl/hosts/zone.py
--- a/pvl/hosts/__init__.py	Mon Mar 09 18:00:18 2015 +0200
+++ b/pvl/hosts/__init__.py	Mon Mar 09 19:47:10 2015 +0200
@@ -7,4 +7,5 @@
 from pvl.hosts.host import (
         HostError,
         Host,
+        extension,
 )
--- a/pvl/hosts/host.py	Mon Mar 09 18:00:18 2015 +0200
+++ b/pvl/hosts/host.py	Mon Mar 09 19:47:10 2015 +0200
@@ -154,10 +154,18 @@
         A host is a network node that can have multiple ethernet interfaces, and multiple IP addresses in different domains.
     """
 
-    # the label used for alias4/6 hosts
-    ALIAS4_FMT = '{host}-ipv4'
-    ALIAS6_FMT = '{host}-ipv6'
-   
+    EXTENSIONS = { }
+
+    @classmethod
+    def build_extensions(cls, extensions):
+        for extension, value in extensions.iteritems():
+            extension_cls = cls.EXTENSIONS.get(extension)
+
+            if extension_cls:
+                yield extension, extension_cls.build(**value)
+            else:
+                log.warning("skip unknown extension: %s", extension)
+
     @classmethod
     def build (cls, name, domain,
             ip=None, ip6=None,
@@ -181,6 +189,7 @@
 
         ip = {label: (ip4.get(label), ip6.get(label)) for label in set(ip4) | set(ip6)}
 
+
         return cls(name,
                 domain      = domain,
                 ip4         = ip4.get(None),
@@ -196,7 +205,7 @@
                 reverse     = parse_str(reverse),
                 down        = parse_bool(down),
                 boot        = parse_dhcp_boot(boot),
-                extensions  = extensions,
+                extensions  = dict(cls.build_extensions(extensions)),
         )
 
     def __init__ (self, name, domain,
@@ -260,6 +269,23 @@
             # sorts first
             return ipaddr.IPAddress(0)
 
+    def addresses (self):
+        """
+            Yield (sublabel, ipaddr) records.
+        """
+
+        for sublabel, (ip4, ip6) in self.ip.iteritems():
+
+            if ip4:
+                yield sublabel, ip4
+
+            if ip6:
+                yield sublabel, ip6
+
+        for extension in self.extensions.itervalues():
+            for sublabel, ip in extension.addresses():
+                yield sublabel, ip
+
     def fqdn (self):
         if self.domain:
             return pvl.dns.fqdn(self.name, self.domain)
@@ -270,3 +296,19 @@
         return "{self.name}@{domain}".format(self=self,
                 domain      = self.domain or '',
         )
+
+class HostExtension (object):
+    """
+        Extension hooks
+    """
+
+    def addresses (self):
+        return ()
+
+def extension (cls):
+    """
+        Register an extension class
+    """
+
+    Host.EXTENSIONS[cls.EXTENSION] = cls
+
--- a/pvl/hosts/zone.py	Mon Mar 09 18:00:18 2015 +0200
+++ b/pvl/hosts/zone.py	Mon Mar 09 19:47:10 2015 +0200
@@ -31,21 +31,24 @@
     
     elif host.forward is None:
         # forward
-        for sublabel, (ip4, ip6) in host.ip.iteritems():
+        for sublabel, ip in host.addresses():
             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)
+            if ip.version == 4:
+                log.info("%s: ip: %s@%s A %s", host, sublabel, origin, ip)
 
-                yield pvl.dns.ZoneRecord.A(sublabel, ip4)
+                yield pvl.dns.ZoneRecord.A(sublabel, ip)
 
-            if ip6:
-                log.info("%s: ip6: %s@%s AAAA %s", host, label, origin, ip6)
+            elif ip.version == 6:
+                log.info("%s: ip6: %s@%s AAAA %s", host, label, origin, ip)
 
-                yield pvl.dns.ZoneRecord.AAAA(sublabel, ip6)
+                yield pvl.dns.ZoneRecord.AAAA(sublabel, ip)
+
+            else:
+                raise ValueError(ip)
 
     else:
         log.info("%s: skip forward", host)
@@ -79,30 +82,22 @@
         Yield (ipaddr.IPAddress, ZoneRecord) tuples for host within given prefix's reverse-dns zone.
     """
     
-    for sublabel, (ip4, ip6) in host.ip.iteritems():
-        if prefix.version == 4:
-            ip = ip4
-            
-            # reverse= is IPv4-only
-            reverse = host.reverse
-
-        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
-
-        else:
-            raise ValueError("%s: unknown ip version: %s" % (prefix, prefix.version))
-
-        if not ip:
-            log.debug("%s: no ip%d", host, prefix.version)
+    for sublabel, ip in host.addresses():
+        if ip.version != prefix.version:
             continue
 
         if ip not in prefix:
             log.debug("%s: %s out of prefix: %s", host, ip, prefix)
             continue
-        
+
+        if ip.version == 4:
+            # reverse= is IPv4-only
+            reverse = host.reverse
+
+        elif prefix.version == 6:
+            # if reverse= is set, always omit, for lack of reverse6=
+            reverse = None if host.reverse is None else False
+
         # relative label
         label = pvl.dns.reverse_label(prefix, ip)