Ansible DHCPD and DNS
Using Ansible to configure DHCPD and NDS on OpenBSD

Host data is stored in csv files
Ansible templates to create config files
Restart services

hostname-setup.yml
---
- hosts: localhost
tasks:
- name: read subnet 10
read_csv:
path: 10.csv
fieldnames: mac,ip,hostname
register: subnet_10
- name: read subnet 11
read_csv:
path: 11.csv
fieldnames: mac,ip,hostname
register: subnet_11
- name: read static
read_csv:
path: static.csv
fieldnames: hostname,ip
register: static_ip

- name: write dhcp file
template:
src: dhcpd.conf.j2
dest: /etc/dhcpd.conf
validate: dhcpd -nc %s
- name: write local.lan zone file
template:
src: local.lan.zone.j2
dest: /var/nsd/zones/master/local.lan
owner: root
group: _nsd
validate: nsd-checkzone local.lan %s
- name: nsd_conf
copy:
src: nsd.conf
dest: /var/nsd/etc/nsd.conf
owner: root
group: _nsd
validate: nsd-checkconf %s
- name: restart nsd
service:
name: nsd
state: restarted
- name: restart dhcpd
service:
name: dhcpd
state: restarted
- name: restart unbound
service:
name: unbound
state: restarted
10.csv
b8:27:eb:8b:7a:6d,192.168.10.100,pi3a
b8:27:eb:ef:f2:d4,192.168.10.101,pi3b
28:10:7b:25:d5:60,192.168.10.79,ipcam3
28:10:7b:0c:fa:7b,192.168.10.80,ipcam1
f0:7d:68:0b:ca:56,192.168.10.81,ipcam2
static.csv
tplink,192.168.10.2
gate,192.168.10.10
www,192.168.10.10
fox,192.168.10.17
dhcpd.conf.j2
option domain-name "local.lan";
option domain-name-servers 192.168.10.10;

subnet 192.168.10.0 netmask 255.255.255.0 {
option routers 192.168.10.10;
range 192.168.10.161 192.168.10.179;
{% for host in subnet_10.list %}
host static-client { hardware ethernet {{ host.mac }};fixed-address {{ host.ip }};} #{{ host.hostname }}
{% endfor %}
}

subnet 192.168.11.0 netmask 255.255.255.0 {
option routers 192.168.11.10;
range 192.168.11.72 192.168.11.127;
{% for host in subnet_11.list %}
host static-client { hardware ethernet {{ host.mac }};fixed-address {{ host.ip }};} #{{ host.hostname }}
{% endfor %}
}

Rendered DHCP entires
host static-client { hardware ethernet b8:27:eb:de:2f:38;fixed-address 192.168.10.45;} #pi3a
host static-client { hardware ethernet 28:10:7b:25:d5:60;fixed-address 192.168.10.79;} #ipcam3
host static-client { hardware ethernet 28:10:7b:0c:fa:7b;fixed-address 192.168.10.80;} #ipcam1

local.lan.zone.j2
$TTL 3600
local.lan. IN SOA a.root-servers.net. root. (
2016092901 ; Serial
3H ; refresh after 3 hours
1H ; retry after 1 hour
1W ; expire after 1 week
1D) ; minimum TTL of 1 day

IN NS gate.

IN MX 50 gate.local.lan.

local.lan. IN A 192.168.10.10

{% for host in static_ip.list%}
{{ host.hostname }} IN A {{ host.ip }}
{% endfor %}

{% for host in subnet_10.list%}
{{ host.hostname }} IN A {{ host.ip }}
{% endfor %}

{% for host in subnet_11.list%}
{{ host.hostname }} IN A {{ host.ip }}
{% endfor %}

Rendered A records
pi3b IN A 192.168.10.101
pi3a IN A 192.168.10.45
ipcam3 IN A 192.168.10.79
ipcam1 IN A 192.168.10.80
Run the playbook
ansible-playbook hostname-setup.yml