pvl.hosts.dhcp: implement support for dhcp:subclass=... using hardware ethernet
authorTero Marttila <tero.marttila@aalto.fi>
Mon, 02 Mar 2015 19:45:56 +0200
changeset 698 656178fb8607
parent 697 3c3ac207ce3f
child 699 d34567c1b21a
pvl.hosts.dhcp: implement support for dhcp:subclass=... using hardware ethernet
pvl/hosts/dhcp.py
pvl/hosts/tests.py
--- a/pvl/hosts/dhcp.py	Mon Mar 02 19:45:06 2015 +0200
+++ b/pvl/hosts/dhcp.py	Mon Mar 02 19:45:56 2015 +0200
@@ -1,10 +1,22 @@
 import pvl.dhcp.config
 import pvl.hosts.host
 
+def dhcp_host_subclass (host, subclass, ethernet):
+    """
+        Build a DHCP Item for declaring a subclass for a host.
+    """
+    
+    # hardware-type prefixed hardware-address
+    hardware = pvl.dhcp.config.Field('1:' + ethernet)
+
+    return pvl.dhcp.config.Block(None, [
+        ('subclass', subclass, hardware),
+    ])
+
 class HostDHCPError(pvl.hosts.host.HostError):
     pass
 
-def dhcp_host_options (host, ethernet):
+def dhcp_host_options (host, ethernet, subclass=None):
     """
         Yield specific dhcp.conf host { ... } items.
     """
@@ -19,9 +31,15 @@
         if bootopt in host.boot:
             yield bootopt, host.boot[bootopt]
 
-def dhcp_host (host):
+def dhcp_host (host,
+        subclass    = None,
+):
     """
         Yield pvl.dhcp.config.Block's
+
+        Takes dhcp:* extensions as keyword arguments
+
+            subclass: name      - generate a subclass name $ethernet for this host
     """
 
     if set(host.ethernet) == set([None]) :
@@ -39,8 +57,12 @@
 
     for index, ethernet in host.ethernet.iteritems() :
         name = host_fmt.format(host=host, index=index)
+        items = list(dhcp_host_options(host, ethernet))
 
-        yield pvl.dhcp.config.Block(('host', name), list(dhcp_host_options(host, ethernet)), comment=comment)
+        yield pvl.dhcp.config.Block(('host', name), items, comment=comment)
+
+        if subclass:
+            yield dhcp_host_subclass(host, subclass, ethernet)
     
 def dhcp_hosts (hosts):
     """
@@ -51,7 +73,9 @@
     blocks = { }
 
     for host in hosts:
-        for block in dhcp_host(host):
+        extensions = host.extensions.get('dhcp', {})
+
+        for block in dhcp_host(host, **extensions):
             if block.key in blocks:
                 raise HostDHCPError(host, "dhcp {block} conflict with {other}; hosts on multiple networks must use unique ethernet.XXX=... naming".format(block=block, other=blocks[block.key]))
 
--- a/pvl/hosts/tests.py	Mon Mar 02 19:45:06 2015 +0200
+++ b/pvl/hosts/tests.py	Mon Mar 02 19:45:56 2015 +0200
@@ -799,6 +799,23 @@
                 ], []),
         ])
 
+    def testHostSubclass(self):
+        hosts = [Host.build('foo', 'test',
+                ethernet    = '00:11:22:33:44:55',
+                extensions  = dict(dhcp=dict(
+                    subclass    = 'debian',
+                )),
+        )]
+
+        self.assertBlocksEqual(list(dhcp.dhcp_hosts(hosts)), [
+            (('host', 'foo'), [
+                ('option', 'host-name', "foo"),
+                ('hardware', 'ethernet', '00:11:22:33:44:55'),
+            ], []),
+            (None, [
+                ('subclass', 'debian', '1:00:11:22:33:44:55'),
+            ], []),
+        ])
 
 if __name__ == '__main__':
     unittest.main()