Categories
Uncategorized

Reusing DHCP config in ISC dhcpd

This is quite a niche thing, but since it took me ages to piece it together, here it is.

I run a PXE build environment for bare-metal install of new systems. I use PuppetLabs’ Razor to do the installation bit, and that works well. I do this for multiple environments, and I wanted to have a single server serve all of these related subnets (they come and go as projects complete). The single server acts as TFTP, DHCP, & Razor server for each subnet, as well as a NAT for external access, so it’s possible to use any IP addressing inside the build environment (except the network the razor box is on, of course).

In each subnet, the DHCP config is somewhat complicated. Aside from the normal DHCP stuff (IPs, gateway etc), the boot file to be used varies depending on the client-id of the host. EFI devices get a difference iPXE boot file from BIOS devices. Also, iPXE then makes its own DHCP request, which needs to be given a script instead. The script filename is different per subnet. The naive way to do all that results in an enormous tangle to update as projects change.

So my goals:

  1. Single copy of the boot file switchy config
  2. Simple to update/edit config for new subnets

For the switching stuff, I started with this Gist from robinsmidsrod, and chopped out the cases I don’t care about. That leaves me with this include file:

option ipxe.no-pxedhcp 1;

if exists user-class and option user-class = "iPXE" {
    # THIS IS DIFFERENT PER SUBNET
    filename "bootstrap-172.19.19.0.ipxe";
}
elsif option arch = 00:06 {
    # EFI 32-bit
    filename "ipxe-x86.efi";
}
elsif option arch = 00:07 {
    # EFI 64-bit    
    filename "ipxe-x64.efi";
}
elsif option arch = 00:00 {
    # Legacy BIOS x86 mode
    filename "ipxe.pxe";
}

and scopes like:

# Network 1
subnet 172.19.19.0 netmask 255.255.255.0 {
   range 172.19.19.10 172.19.19.49;
   option routers 172.19.19.1;
   next-server 172.19.19.1;

   include "/etc/dhcp/ipxe-common-172.19.19.0.conf";
}

So that works, but has a lot of duplication! Being able to define parameters would be useful.

So that looks like this:

option bootstrap_file code 254 = string;

# Network 1
subnet 172.19.19.0 netmask 255.255.255.0 {
   range 172.19.19.10 172.19.19.49;
   option routers 172.19.19.1;
   next-server 172.19.19.1;

   option bootstrap_file "bootstrap-172.19.19.0.ipxe";

   include "/etc/dhcp/ipxe-common.conf";
}

and then:

if exists user-class and option user-class = "iPXE" {
    # THIS IS *NO LONGER* DIFFERENT PER SUBNET
    option bootfile-name = concat("",config-option bootstrap_file);
}

in the included file means that nothing needs to change in there anymore. I can just add a new scope in a few lines, drop in the appropriate TFTP file and be up and running.