pvl.hosts: update boot= to support split boot.next-server= boot.filename=, which enables inheriting defaults
authorTero Marttila <tero.marttila@aalto.fi>
Mon, 02 Mar 2015 17:58:24 +0200
changeset 689 c258e3ff6d32
parent 688 dfc5fcb6a06c
child 690 517527835381
pvl.hosts: update boot= to support split boot.next-server= boot.filename=, which enables inheriting defaults
pvl/hosts/dhcp.py
pvl/hosts/host.py
pvl/hosts/tests.py
test.sh
--- a/pvl/hosts/dhcp.py	Mon Mar 02 13:30:15 2015 +0200
+++ b/pvl/hosts/dhcp.py	Mon Mar 02 17:58:24 2015 +0200
@@ -15,24 +15,9 @@
     if host.ip:
         yield 'fixed-address', str(host.ip)
       
-    if not host.boot:
-        next_server = filename = None
-    elif host.boot.startswith('/'):
-        next_server = None
-        filename = host.boot[1:]
-    elif host.boot.endswith(':'):
-        next_server = host.boot[:-1]
-        filename = None
-    elif ':' in host.boot :
-        next_server, filename = host.boot.split(':', 1)
-    else :
-        raise HostError(host, "invalid boot={host.boot}".format(host=host))
-
-    if next_server:
-        yield 'next-server', next_server
-    
-    if filename:
-        yield 'filename', filename
+    for bootopt in ('next-server', 'filename'):
+        if bootopt in host.boot:
+            yield bootopt, host.boot[bootopt]
 
 def dhcp_host (host):
     """
--- a/pvl/hosts/host.py	Mon Mar 02 13:30:15 2015 +0200
+++ b/pvl/hosts/host.py	Mon Mar 02 17:58:24 2015 +0200
@@ -69,6 +69,50 @@
 
     return ':'.join('%02x' % int(x, 16) for x in value.split(':'))
 
+def parse_dhcp_boot(boot):
+    """
+        Parse the dhcp boot=... option
+
+        >>> print parse_dhcp_boot(None)
+        {}
+        >>> print parse_dhcp_boot({'filename': '/foo'})
+        {'filename': '/foo'}
+        >>> print parse_dhcp_boot({'filename': '/foo', 'next-server': 'bar'})
+        {'next-server': 'bar', 'filename': '/foo'}
+        >>> print parse_dhcp_boot('/foo')
+        {'filename': '/foo'}
+        >>> print parse_dhcp_boot('bar:/foo')
+        {'next-server': 'bar', 'filename': '/foo'}
+        >>> print parse_dhcp_boot('bar:')
+        {'next-server': 'bar'}
+        >>> print parse_dhcp_boot('foo')
+        Traceback (most recent call last):
+            ...
+        ValueError: invalid boot=foo
+    """
+
+    if not boot:
+        return { }
+
+    elif isinstance(boot, dict):
+        if set(boot) <= set(('filename', 'next-server')):
+            return boot
+        else:
+            raise ValueError("invalid boot={boot}".format(boot=boot))
+
+    elif boot.startswith('/'):
+        return {'filename': boot}
+
+    elif boot.endswith(':'):
+        return {'next-server': boot[:-1]}
+
+    elif ':' in boot :
+        next_server, filename = boot.split(':', 1)
+        return {'next-server': next_server, 'filename': filename}
+
+    else :
+        raise ValueError("invalid boot={boot}".format(boot=boot))
+
 def parse_str(value):
     """
         Normalize optional string value.
@@ -133,7 +177,7 @@
                 forward     = parse_str(forward),
                 reverse     = parse_str(reverse),
                 down        = parse_bool(down),
-                boot        = boot,
+                boot        = parse_dhcp_boot(boot),
                 extensions  = extensions,
         )
 
--- a/pvl/hosts/tests.py	Mon Mar 02 13:30:15 2015 +0200
+++ b/pvl/hosts/tests.py	Mon Mar 02 17:58:24 2015 +0200
@@ -137,6 +137,26 @@
                 ('bar@quux.test', dict(ip=ipaddr.IPAddress('127.0.0.2'))),
         ])
 
+    def testHostsConfigDdefaults(self):
+        hosts = config.apply_hosts_config(self.options, ConfFile('test', """
+boot.next-server = boot.lan
+
+[foo]
+    ip = 192.0.2.1
+    ethernet.eth0 = 00:11:22:33:44:55
+    boot.filename = /pxelinux.0
+        """))
+        
+        self.assertHostsEqual(hosts, [
+                ('foo@test', dict(
+                    ip          = ipaddr.IPAddress('192.0.2.1'),
+                    ethernet    = { 'eth0': '00:11:22:33:44:55' },
+                    boot        = { 'next-server': 'boot.lan', 'filename': '/pxelinux.0' },
+                )),
+        ])
+
+
+ 
     def testApplyIncludes(self):
         self.assertHostsEqual(config.apply_hosts_files(self.options, ['etc/hosts/test']), [
                 ('bar@test', dict(
@@ -664,6 +684,10 @@
                         ethernet    = '00:11:22:33:44:55',
                         boot        = '/debian/wheezy/pxelinux.0',
                 ),
+                Host.build('foo4', 'test',
+                        ethernet    = '00:11:22:33:44:55',
+                        boot        = {'next-server': 'boot.lan', 'filename': '/debian/wheezy/pxelinux.0' },
+                ),
         ]
 
         self.assertBlocksEqual(list(dhcp.dhcp_hosts(hosts)), [
@@ -681,10 +705,16 @@
             (('host', 'foo3'), [
                 ('option', 'host-name', "foo3"),
                 ('hardware', 'ethernet', '00:11:22:33:44:55'),
-                ('filename', 'debian/wheezy/pxelinux.0'),
+                ('filename', '/debian/wheezy/pxelinux.0'),
+            ], []),
+            (('host', 'foo4'), [
+                ('option', 'host-name', "foo4"),
+                ('hardware', 'ethernet', '00:11:22:33:44:55'),
+                ('next-server', 'boot.lan'),
+                ('filename', '/debian/wheezy/pxelinux.0'),
             ], []),
         ])
-
+    
     def testHosts(self):
         hosts = [
                 Host.build('foo', 'test',
--- a/test.sh	Mon Mar 02 13:30:15 2015 +0200
+++ b/test.sh	Mon Mar 02 17:58:24 2015 +0200
@@ -5,6 +5,7 @@
     pvl/dns/labels.py
     pvl/dns/reverse.py
     pvl/dns/generate.py
+    pvl/hosts/host.py
 )
 
 UNITTEST=(