Skip to content

v0.3.2

Choose a tag to compare

@github-actions github-actions released this 03 Oct 09:16

Added

  • pixie dhcp-config [target] [--apply] [--as USER] — prints the server-side
    configuration a config needs but netboot may not be able to create: the Windows
    policy and its user class, a dhcpd.conf group, a Kea client-classes entry.
    Printing contacts nothing, so the output goes straight into a change ticket;
    --apply runs it and --as prompts for an admin password. It is the only
    command that prompts, because initiate and complete run unattended and a
    prompt there would hang a pipeline. Run once per condition; routine arming then
    needs none of those rights.

  • windhcp:// takes transport=local — run PowerShell on this machine, with
    server= pointing the cmdlets at the DHCP server, which is the ordinary RSAT
    shape and needs no sshd, WinRM or credential. An empty host
    (windhcp:///?server=dhcp01) defaults to it; a named host still uses a
    transport. The account for WinRM can now come from $PIXIE_WINDHCP_USER when
    the URI names none.

  • dhcp_complete: — what a finished target's DHCP entry becomes. A machine
    that still receives boot-file-name after its install boots the installer
    again; pixie complete removed the reservation to prevent that, which also
    threw away the fixed address. Now keep: true leaves the address and drops the
    boot options (firmware falls through to local disk), and options: serves
    something else instead — an iPXE sanboot script, for firmware with no
    local-disk fallback. Router, DNS and subnet mask are never touched, and a kept
    entry also loses its dhcp_when membership so the condition cannot keep serving
    it the installer. The default is unchanged. All four backends implement it;
    verified against a real Windows Server 2025 for each of the three outcomes.

  • dhcp_when: — conditional options, declared once and translated per
    backend. A mapping keyed by name, where the name is the construct each
    server uses: a Windows scope policy, a dhcpd group or inline if, a Kea client
    class. It layers zone → image → target by name, so two targets share one
    policy and a target can replace an image's condition. match takes
    user-class and vendor-class; options takes the usual option names. This
    is the iPXE chainload said once: undionly.kpxe for a PXE ROM,
    boot.ipxe for iPXE.

    On Windows a condition becomes two policies for that target — one matched on
    its MAC plus the test, one on the MAC alone — and the overridden option is
    kept off the reservation, because a reservation's options outrank every
    policy and would otherwise make the condition dead while the configuration
    looked right. conditions=shared gives the other shape: one policy per
    condition for the whole scope, which an administrator can create once on a host
    where netboot cannot create policies at all.

    A backend that cannot create the construct says exactly what to run
    (Add-DhcpServerv4Class/Add-DhcpServerv4Policy, a dhcpd.conf group, the
    Kea client-classes JSON), and one that cannot express conditions at all
    (dnsmasq://, because the tag needs a dhcp-match line in config netboot does
    not own) refuses rather than arming a target whose chainload would never fire.
    Either way the zone's other servers are armed, since arming is best effort.

  • DhcpServer.ensure_condition() / .condition_recipe() /
    .remove_condition_member() — the contract above, for a plugin backend.

Changed

  • netimps>=0.3.3 (was >=0.3.1), and three things netboot hand-rolled are
    now the library's. No behaviour netboot documented changes, except where noted:

    • repository addresses are split by normalize_host, so a malformed one
      (mirror.example:http, mirror.example:) now raises PixieConfigError
      naming the repo instead of being treated as a hostname and handed to DNS as
      one. [v6]:port still produces http://[2001:db8::1]:8080/... — the host
      comes back unbracketed and pathlib_next brackets it itself.
    • "the target has no address" is is_wildcard, which also covers None
      and a %zone suffix (::%eth0); the check it replaced knew 0.0.0.0 and
      :: only, so a scoped unspecified address produced a template candidate
      named after it.
    • the windhcp:// netsh client id is MACAddress.hex() rather than
      formatting with separators and stripping them again.
  • netboot.utils.net.Host is now netimps' Host, subclassed rather than
    reimplemented. The local class claimed Host was "a netboot concept"; netimps
    has had the same type since 0.2.0, written for the same reason, and this
    module's stated principle is to use the library's vocabulary. Nothing is
    removed
    : .try_ip(), .address (readable and writable) and Host() with
    no argument all behave as before, so this is not an API break.

    What you gain for free: .ip() caches its result, failures included, so a
    repo asked for several services resolves once where the old class resolved
    every time (refresh=True retries). Also inherited: .value (the same text as
    .address), .is_address (no DNS), and, on netimps 0.3.3, .fqdn.

    Two behaviour differences worth knowing, neither of them a documented contract:
    Host("a") == "a" is now True with matching hashes, where the old class
    returned NotImplemented; and faking resolution in a test means patching
    netimps.get_ip, which .ip() imports at call time, rather than netboot's
    own resolve re-export.

Full Changelog: v0.3.1...v0.3.2