--- a/bin/pvl.hosts-dhcp Thu Feb 26 14:40:14 2015 +0200
+++ b/bin/pvl.hosts-dhcp Thu Feb 26 14:40:37 2015 +0200
@@ -1,93 +1,28 @@
#!/usr/bin/env python
-import pvl.args
-import pvl.hosts
-
-import configobj
import logging; log = logging.getLogger('pvl.hosts-dhcp')
import optparse
-
-def build_host (host_name, *items) :
- yield "host {host} {{".format(host=host_name)
- for item in items :
- if isinstance(item, dict) :
- for setting, value in item.iteritems() :
- if value :
- yield "\t{setting:30} {value};".format(setting=setting, value=value)
- else :
- raise ValueError("Unknown item: %r", item)
- yield "}"
-
-def dhcp_quote (value) :
- if value is None :
- return None
- else :
- return '"{value}"'.format(value=value)
-
-def process_host (options, host) :
- if host.boot :
- if ':' in host.boot :
- next_server, filename = host.boot.split(':', 1)
- elif host.boot.startswith('/') :
- next_server = None
- filename = host.boot
- elif host.boot.endswith(':') :
- next_server = host.boot
- filename = None
- else :
- log.error("%s: invalid boot: %s", host, host.boot)
- else :
- next_server = filename = None
+import pvl.args
+import pvl.hosts
+import pvl.hosts.dhcp
- if set(host.ethernet) == set([None]) :
- host_fmt = "{host.name}"
- elif host.ethernet :
- host_fmt = "{host.name}-{index}"
- else :
- # nothing there
- return
-
- if host.owner :
- yield u"# Owner: {host.owner}".format(host=host)
-
- for index, ethernet in host.ethernet.iteritems() :
- for line in build_host(host_fmt.format(host=host, index=index),
- { 'option host-name': dhcp_quote(host.name) },
- { 'hardware ethernet': ethernet },
- { 'fixed-address': host.ip },
- { 'next-server': next_server },
- { 'filename': dhcp_quote(filename) },
- ) :
- yield line
-
- yield ""
-
-def process_hosts (options, hosts) :
- for host in hosts :
- for line in process_host(options, host) :
- yield line
-
-def apply_conf (options, lines) :
- for line in lines :
- print line
-
-def main (argv) :
+def main (argv):
"""
Generate DHCP host configs from host definitions.
"""
parser = optparse.OptionParser(main.__doc__)
parser.add_option_group(pvl.args.parser(parser))
- parser.add_option_group(pvl.hosts.optparser(parser))
-
- options, args = parser.parse_args(argv[1:])
- pvl.args.apply(options)
+ parser.add_option_group(pvl.hosts.config.optparser(parser))
# input
+ options, args = pvl.args.parse(parser, argv)
+
hosts = pvl.hosts.apply(options, args)
# process
- apply_conf(options, process_hosts(options, hosts))
+ for line in pvl.hosts.dhcp.apply_hosts_dhcp(options, hosts):
+ print line
if __name__ == '__main__':
pvl.args.main(main)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/pvl/hosts/dhcp.py Thu Feb 26 14:40:37 2015 +0200
@@ -0,0 +1,80 @@
+import pvl.dhcp.config
+import pvl.hosts.host
+
+class HostDHCPError(pvl.hosts.host.HostError):
+ pass
+
+def dhcp_host_options (host, ethernet):
+ """
+ Yield specific dhcp.conf host { ... } parameters for build_block()
+ """
+
+ yield 'option', 'host-name', host.name
+ yield 'hardware', 'ethernet', ethernet
+
+ if host.ip:
+ yield 'fixed-address', str(host.ip)
+
+ if not host.boot:
+ next_server = filename = None
+ elif ':' in host.boot :
+ next_server, filename = host.boot.split(':', 1)
+ elif host.boot.startswith('/') :
+ next_server = None
+ filename = host.boot
+ elif host.boot.endswith(':') :
+ next_server = host.boot
+ filename = None
+ else :
+ raise HostError(host, "invalid boot={host.boot}".format(host=host))
+
+ if next_server:
+ yield 'next-server', next_server
+
+ if filename:
+ yield 'filename', filename
+
+def dhcp_host (host):
+ """
+ Yield (block, items, **opts) tuples for pvl.dhcp.config.build_block().
+ """
+
+ if set(host.ethernet) == set([None]) :
+ host_fmt = "{host.name}"
+ elif host.ethernet :
+ host_fmt = "{host.name}-{index}"
+ else :
+ # nothing to be seen here
+ return
+
+ if host.owner :
+ comment = u"Owner: {host.owner}".format(host=host)
+ else:
+ comment = None
+
+ for index, ethernet in host.ethernet.iteritems() :
+ name = host_fmt.format(host=host, index=index)
+
+ yield ('host', name), list(dhcp_host_options(host, ethernet)), dict(comment=comment)
+
+def apply_hosts_dhcp (options, hosts):
+ """
+ Generate dhcp.conf output lines for the set of hosts.
+
+ Verifies that there are no dupliate hosts.
+ """
+
+ blocks = { }
+
+ for host in hosts:
+ for block, items, opts in dhcp_host(host):
+ if block in blocks:
+ raise HostDHCPError(host, "dupliate host block {block}: {other}".format(block=block, other=blocks[block]))
+
+ blocks[block] = block
+
+ for line in pvl.dhcp.config.build_block(block, items, **opts):
+ yield line
+
+ yield ''
+
--- a/pvl/hosts/tests.py Thu Feb 26 14:40:14 2015 +0200
+++ b/pvl/hosts/tests.py Thu Feb 26 14:40:37 2015 +0200
@@ -436,5 +436,37 @@
('6', 'PTR'): ['ufc.domain.'],
})
+class TestDhcp(unittest.TestCase):
+ def setUp(self):
+ self.options = pvl.args.options(
+ hosts_charset = 'utf-8',
+ hosts_domain = None,
+ hosts_include = None,
+ )
+
+ def assertBlocksEqual(self, blockdefs, expected):
+ for (_block, _items, _opts), (block, items, opts) in zip(blockdefs, expected):
+ self.assertEqual(_block, block)
+ self.assertItemsEqual(_items, items)
+
+ if opts is not None:
+ self.assertEqual(_opts, opts)
+
+ self.assertEqual(len(blockdefs), len(expected))
+
+ def testHost(self):
+ host = Host.build('foo', 'test',
+ ip = '192.0.2.1',
+ ethernet = '00:11:22:33:44:55',
+ )
+
+ self.assertBlocksEqual(list(dhcp.dhcp_host(host)), [
+ (('host', 'foo'), [
+ ('option', 'host-name', "foo"),
+ ('fixed-address', '192.0.2.1'),
+ ('hardware', 'ethernet', '00:11:22:33:44:55'),
+ ], None)
+ ])
+
if __name__ == '__main__':
unittest.main()