Customizing dnsmasq DHCP Options with libvirt: Advanced Network Boot Configuration


26 views

When working with libvirt's network configuration, you'll notice the DHCP options for network booting are quite limited. The current implementation only exposes two parameters through the bootp element:

<bootp file='test.ipx' server='10.10.10.2'/>

This generates the following dnsmasq configuration:

dhcp-boot=test.ipx,,10.10.10.2

Many network boot scenarios require more sophisticated DHCP options that aren't directly supported by libvirt's current implementation. For example:

dhcp-userclass=set:ipxe,iPXE
dhcp-boot=tag:ipxe,http://matchbox.foo:8080/boot.ipxe

Method 1: Using libvirt hooks

Create a hook script that modifies the dnsmasq configuration after libvirt generates it:

#!/bin/bash
# /etc/libvirt/hooks/network

if [ "$1" = "default" ] && [ "$2" = "started" ]; then
    echo "dhcp-userclass=set:ipxe,iPXE" >> /var/lib/libvirt/dnsmasq/default.conf
    echo "dhcp-boot=tag:ipxe,http://matchbox.foo:8080/boot.ipxe" >> /var/lib/libvirt/dnsmasq/default.conf
    systemctl restart libvirtd
fi

Method 2: Custom dnsmasq instance

Disable libvirt's built-in dnsmasq and run your own instance:

<network>
  <name>default</name>
  <forward mode='nat'/>
  <dhcp>
    <range start='192.168.122.2' end='192.168.122.254'/>
  </dhcp>
  <dnsmasq:options xmlns:dnsmasq="http://libvirt.org/schemas/network/dnsmasq/1.0">
    <dnsmasq:option value="conf-file=/etc/dnsmasq.d/custom.conf"/>
  </dnsmasq:options>
</network>

Method 3: Direct configuration modification

For temporary testing, you can directly edit the generated configuration:

# Find the PID of dnsmasq
ps aux | grep dnsmasq

# Edit the temporary config file
vim /var/lib/libvirt/dnsmasq/default.conf

# Add your custom options and restart
systemctl restart libvirtd

The libvirt project is actively developed, and there's an open feature request for more flexible DHCP options. You might want to:

  • Subscribe to libvirt mailing lists for updates
  • Consider contributing patches if you need this functionality urgently
  • Monitor GitHub issues for progress on this feature

When working with libvirt's network configuration, the built-in dnsmasq integration provides limited DHCP options through the bootp element. The current implementation only supports:

<bootp file='test.ipx' server='10.10.10.2'/>

Which generates the following dnsmasq configuration:

dhcp-boot=test.ipx,,10.10.10.2

Many network boot scenarios require more sophisticated DHCP options that aren't exposed through libvirt's XML interface. Specifically, we often need:

  • Custom DHCP user classes
  • Conditional boot file assignments
  • Additional dnsmasq parameters

For example, when working with iPXE, we might need configuration like:

dhcp-userclass=set:ipxe,iPXE
dhcp-boot=tag:ipxe,http://matchbox.foo:8080/boot.ipxe

Method 1: Post-Processing the Generated Configuration

While libvirt doesn't directly support these options, you can modify the generated configuration:

# Create a script to append custom options
echo "dhcp-userclass=set:ipxe,iPXE" >> /var/lib/libvirt/dnsmasq/default.conf
echo "dhcp-boot=tag:ipxe,http://matchbox.foo:8080/boot.ipxe" >> /var/lib/libvirt/dnsmasq/default.conf

# Restart the network
virsh net-destroy default
virsh net-start default

Note: This approach is fragile as libvirt may overwrite the configuration during network restarts.

Method 2: Using Custom Configuration Snippets

Recent versions of dnsmasq support including additional configuration files:

# Create a custom config directory
mkdir -p /etc/libvirt/dnsmasq-custom

# Add your custom options
echo "dhcp-userclass=set:ipxe,iPXE" > /etc/libvirt/dnsmasq-custom/ipxe.conf
echo "dhcp-boot=tag:ipxe,http://matchbox.foo:8080/boot.ipxe" >> /etc/libvirt/dnsmasq-custom/ipxe.conf

# Modify the libvirt network definition
virsh net-edit default

Add this to your network XML:

<dnsmasq:options>
  <dnsmasq:option value='--conf-dir=/etc/libvirt/dnsmasq-custom'/>
</dnsmasq:options>

Method 3: Full Custom dnsmasq Configuration

For complete control, you can disable libvirt's built-in dnsmasq and run your own instance:

# Edit your network XML to disable dnsmasq
virsh net-edit default

Add or modify:

<domain name='example.com' localOnly='yes'/>
<dhcp>
  <range start='192.168.122.2' end='192.168.122.254'/>
</dhcp>

Then create a custom dnsmasq configuration file at /etc/dnsmasq.d/libvirt-custom.conf:

interface=virbr0
bind-interfaces
dhcp-range=192.168.122.2,192.168.122.254
dhcp-userclass=set:ipxe,iPXE
dhcp-boot=tag:ipxe,http://matchbox.foo:8080/boot.ipxe
  • Always test changes in a development environment first
  • Be aware of libvirt version differences in dnsmasq integration
  • Consider using network filters for more complex scenarios
  • Document your customizations for future maintenance