Skip to content

Repository files navigation

ansible-role-netbox_printer_reservations

Generates and deploys Kea DHCP4 static reservations for printer devices by querying NetBox as the authoritative source of truth. The role reads device role, site, MAC addresses, and primary IPv4 from NetBox, renders a JSON reservations file, validates it, and hot-reloads the Kea DHCP4 service on the target host.

Designed to run as Phase 2 after the fortigate_dhcp_reconcile role has verified NetBox data accuracy.


Requirements

  • Ansible ≥ 2.20
  • Ubuntu Resolute on the target host
  • ISC Kea DHCP4 installed and running on the target host
  • The target host must have kea-dhcp4 accessible (for config validation)
  • The Ansible controller must have network access to the NetBox API
  • vault_netbox_token set in group_vars/all/vault.yml (ansible-vault encrypted)
  • netbox_url set in group_vars/all/main.yml

Role Variables

All variables have defaults defined in defaults/main.yml.

NetBox API Connection

Variable Default Description
netbox_url http://netbox.example.local Base URL of your NetBox instance
netbox_token {{ vault_netbox_token }} NetBox API token — must come from vault
netbox_validate_certs false Whether to validate TLS certificates
netbox_api_timeout 30 HTTP timeout in seconds for NetBox API calls

Note: The vault variable must be named vault_netbox_token. Do not use vault_netbox_api_token — that name is not recognised by this role.

NetBox Device Filters

Variable Default Description
netbox_site_slug main NetBox site slug to filter devices by
netbox_printer_role_slugs ["printer", "printer-scheduled"] List of NetBox device role slugs to include
netbox_printer_status active NetBox device status filter. Valid values: active, planned, staged, failed, inventory, decommissioning

Kea DHCP4 Target Paths

Variable Default Description
kea_reservations_dir /etc/kea/reservations Directory on the Kea server where the reservations file is deployed
kea_reservations_filename printers.json Filename for the reservations JSON file
kea_dhcp4_config /etc/kea/kea-dhcp4.conf Path to the main Kea DHCP4 configuration file
kea_dhcp4_service kea-dhcp4 systemd service name for Kea DHCP4
kea_reservations_owner _kea Owner of the deployed reservations file
kea_reservations_group _kea Group of the deployed reservations file

Behaviour Flags

Variable Default Description
kea_validate_config true Run kea-dhcp4 -t config validation after deploying the file. Set to false to skip (useful when testing before Kea is installed).
kea_service_manage true Whether to reload the Kea service after a successful deploy. Set to false to deploy the file without touching the service. Mirrors kea_service_manage in ansible-role-kea-dhcp so host_vars controls both.
netbox_require_reservations true Fail the play when NetBox returns zero printers or zero valid reservations. Set to false to allow empty results (useful in staging environments).

How It Works

The role runs three steps in sequence:

Step 0 — Pre-flight checks (tasks/preflight.yml, tags: always) Validates every required variable before making any API call or touching any file. Fails immediately with a descriptive, actionable error message so nothing is left in a partial state. Checks include:

  • ansible-core version is >= 2.20
  • NetBox URL, API token, and API timeout are set and well-formed
  • NetBox site slug, printer role slugs, and status filter are set and valid
  • Kea reservations directory, filename, config path, service name, and file owner/group are set and well-formed

Step 1 — Query NetBox (tasks/query_netbox.yml) Queries the NetBox API from the Ansible controller (delegate_to: localhost) so the Kea server never needs direct access to NetBox. Fetches all matching printer devices and their interfaces, builds a device-ID-to-MAC-address map, then constructs a list of Kea reservation entries. Devices missing a primary IPv4 address or an interface with a MAC address are skipped with a warning.

Step 2 — Deploy reservations (tasks/deploy_reservations.yml) Runs on the Kea server target. Creates the reservations directory, renders the JSON file from the kea_reservations.json.j2 template, and validates it with Python's json.load inline. Also renders a README.md (from README.md.j2) into the same directory, explaining what the JSON file is, that Kea does not read it directly, and how a consuming playbook actually gets its contents into the live config — see Integration with ansible-role-kea-dhcp. If kea_validate_config is true, the full DHCP4 config is validated with kea-dhcp4 -t. A successful deploy notifies the Reload kea-dhcp4 handler, which hot-reloads the service if kea_service_manage is true.


Integration with ansible-role-kea-dhcp

This role only writes {{ kea_reservations_dir }}/{{ kea_reservations_filename }} (e.g. /etc/kea/reservations/printers.json) — it does not modify kea-dhcp4.conf itself and does not use Kea's <?include?> directive. For the reservations in that file to actually take effect, the subnet in ansible-role-kea-dhcp's kea_dhcp4_subnets must list this file under reservation_files, e.g.:

kea_dhcp4_subnets:
  - id: 1
    subnet: "192.168.1.0/24"
    reservation_files:
      - printers.json    # must match kea_reservations_filename below

ansible-role-kea-dhcp's merge_reservations.yml reads this file's current content on the target host and fully inlines it into kea-dhcp4.conf at render time — nothing is included by reference. This means this role must run before ansible-role-kea-dhcp in the same playbook for a reservations update to reach the live config; running this role on its own (or after ansible-role-kea-dhcp already rendered the config) updates the file on disk but does not, by itself, change what Kea is currently serving. This role's own Reload kea-dhcp4 handler only reloads Kea with whatever kea-dhcp4.conf already contains — it does not cause ansible-role-kea-dhcp to re-render that file.

If kea_dhcp4_subnets does not list this file in reservation_files for any subnet, the file is written but never read — the same disconnect this integration was written to fix.


Example Playbook

- name: "Kea Printer Reservations — Query NetBox and deploy to Kea"
  hosts: kea_servers
  gather_facts: false
  become: true

  roles:
    - role: netbox_printer_reservations

With overrides:

- name: "Kea Printer Reservations — Query NetBox and deploy to Kea"
  hosts: kea_servers
  gather_facts: false
  become: true

  roles:
    - role: netbox_printer_reservations
      vars:
        netbox_site_slug: "branch-office"
        netbox_printer_role_slugs:
          - "printer"
          - "mfp"
        kea_validate_config: false
        kea_service_manage: false

Run together with ansible-role-kea-dhcp so a NetBox change actually reaches the live config — this role first, so the file is fresh before ansible-role-kea-dhcp reads and inlines it:

- name: "Deploy Kea DHCP4 with NetBox printer reservations"
  hosts: kea_servers
  become: true

  roles:
    - role: netbox_printer_reservations
    - role: ansible-role-kea-dhcp
      vars:
        kea_dhcp4_subnets:
          - id: 1
            subnet: "192.168.1.0/24"
            pools:
              - pool: "192.168.1.100 - 192.168.1.200"
            reservation_files:
              - printers.json

Usage

# Normal run
ansible-playbook netbox_printer_reservations.yml

# Dry-run (check mode)
ansible-playbook netbox_printer_reservations.yml --check

# Override site at runtime
ansible-playbook netbox_printer_reservations.yml -e netbox_site_slug=main

Prerequisites Setup

1. Store the NetBox API token in vault:

# Add to group_vars/all/vault.yml
vault_netbox_token: "your-netbox-api-token-here"

# Encrypt the file
ansible-vault encrypt group_vars/all/vault.yml

2. Set the NetBox URL in group vars:

# group_vars/all/main.yml
netbox_url: "https://netbox.example.com"

3. Verify your NetBox slugs:

  • Site slugs: GET {{ netbox_url }}/api/dcim/sites/
  • Device role slugs: GET {{ netbox_url }}/api/dcim/device-roles/

NetBox Data Requirements

Each printer device in NetBox must have:

  • A primary IPv4 address assigned
  • At least one interface with a MAC address
  • The correct site and device role slug
  • Status matching netbox_printer_status (default: active)

Devices missing either a primary IP or a MAC address are skipped and logged as warnings, not errors (unless netbox_require_reservations: true results in an empty reservation list).


Dependencies

None. This role has no Ansible Galaxy dependencies.

It is designed to be run after the fortigate_dhcp_reconcile role to ensure NetBox data is accurate before generating DHCP reservations, and before ansible-role-kea-dhcp in the same playbook — see Integration with ansible-role-kea-dhcp above.


License

MIT — Copyright (c) 2026 Bob Tanner

Author

Bob Tanner — Real Time Enterprises, Inc.

About

Generates and deploys Kea DHCP4 static reservations for printer devices from NetBox, the authoritative source of truth. Renders a validated JSON reservations file and hot-reloads Kea DHCP4. Runs as Phase 2 after fortigate_dhcp_reconcile has verified NetBox data accuracy. For Ubuntu (resolute).

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages