pvl/hosts/dhcp.py
author Tero Marttila <terom@paivola.fi>
Mon, 09 Mar 2015 18:00:18 +0200
changeset 733 45bedeba92e5
parent 731 5e2c1b78047d
child 739 5149c39f3dfc
permissions -rw-r--r--
pvl.hosts: rename Host.ip -> Host.ip4; support instanced ip.foo = ... for foo.host A .... sub-labels
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 = '1:' + ethernet

    return pvl.dhcp.config.Block(None, [
        ('subclass', pvl.dhcp.config.String(subclass), pvl.dhcp.config.Field(hardware)),
    ])

class HostDHCPError(pvl.hosts.host.HostError):
    pass

def dhcp_host_options (host, ethernet, subclass=None):
    """
        Yield specific dhcp.conf host { ... } items.
    """

    yield 'option', 'host-name', host.name
    yield 'hardware', 'ethernet', pvl.dhcp.config.Field(ethernet)

    if host.ip4:
        yield 'fixed-address', pvl.dhcp.config.Field(str(host.ip4))
      
    for bootopt in ('next-server', 'filename'):
        if bootopt in host.boot:
            yield bootopt, host.boot[bootopt]

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 not host.ethernet:
        # 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() :
        if index:
            name = '{host.name}-{index}'.format(host=host, index=index)
        else:
            name = '{host.name}'.format(host=host)

        items = list(dhcp_host_options(host, ethernet))

        yield pvl.dhcp.config.Block(('host', name), items, comment=comment)

        if subclass:
            yield dhcp_host_subclass(host, subclass, ethernet)
    
def dhcp_hosts (hosts):
    """

        Verifies that there are no dupliate hosts.
    """

    blocks = { }

    for host in hosts:
        extensions = host.extensions.get('dhcp', {})

        for block in dhcp_host(host, **extensions):
            if not block.key:
                # TODO: check for unique Item-Blocks
                pass
            elif 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]))
            else:
                blocks[block.key] = host

            yield block