Lattice does not parse dhcpd.conf, Microsoft XML, Kea JSON, or Infoblox CSV in-process. Same rule as NetBox: you dump, you map, you POST /api/v1. There is no “import leases and keep talking ISC failover.”
Microsoft DHCP is the primary buyer we wrote this for. Failover relationships and split scopes do not come with you. Relays (ip helper-address) stay on the L3 switch; you change the helper target. relays. Prefix vs scope: first-subnet. Linux/SSH: windows-admin.
This page is the playbook. Objects: 04-DATA-MODEL.md. API: 08-API.md. Cutover DNS: dns-how.
Just show me the steps — dump + POST at the bottom, without the mapping lecture.
Vendor documentation (cmdlet names and export UIs change between Windows Server releases). Use these for the latest dump steps; this page is the Lattice mapping.
| Topic | Official docs |
|---|---|
| Full server dump | Export-DhcpServer |
| Scopes / reservations / exclusions / leases / options | Get-DhcpServerv4Scope · Get-DhcpServerv4Reservation · Get-DhcpServerv4ExclusionRange · Get-DhcpServerv4Lease · Get-DhcpServerv4OptionValue |
| Failover (do not import) | DHCP failover |
| ISC dhcpd.conf | dhcpd.conf (ISC) |
| ISC Kea | Kea ARM |
1. What you are actually moving
| Their object | Lattice object | Import? |
|---|---|---|
| Scope / subnet | prefix (plan) + subnet (L3) | Yes — create |
| Dynamic range | pool | Yes — create |
| Exclusion / reserved-but-not-DHCP | exclude | Yes — gateway, VIP, junk statics |
| Reservation / host / fixed-address (DHCP client) | reservation (IP + MAC or DUID) | Yes — printers, phones |
| Static server / no DHCP | assignment (IP + hostname) | Yes — counts on the license cap |
| Server VLAN with no DHCP | subnet dhcp_enabled=false | Yes — no pools |
| Scope option (router, DNS, NTP, domain) | Subnet fields + dhcp_option | Yes — map, do not paste dhcpd.conf snippets |
| PXE next-server / filename | Subnet next_server / boot_file | Yes |
| Client class / vendor class | client_class + pool class_id | Maybe — start simple |
| Live leases | lease rows | No |
| Failover partner / split scope / ISC failover | — | Throw away. Shared Postgres is HA |
| Super-scope / shared-network | One subnet per L3, or two subnets if you truly have two prefixes on the wire | Map carefully |
| DDNS on the old server | Subnet ddns_* + a Lattice adapter | Rebuild; do not copy nsupdate cron |
Do not import the lease database. Leases are reality this dhcpd granted. If you inject Microsoft/ISC lease rows, Lattice will defend IPs it never Acked, clocks will not match, and a Renew from a client the old server knew can still NAK.
How clients keep (or change) their IP is section 5.
NetBox is not a DHCP migration. netbox only creates missing prefixes. Pools, reservations, and leases stay Lattice’s.
2. Order of operations
- Install Lattice beside the old server. Relays still point at the old box. install-prerequisites.
- Recreate intent in Lattice: prefix → subnet → exclude gateway/VIP → pool → reservations → options. Dark: dhcpd may run but nothing relays to it yet.
- Match the license cap. Reservations count as managed IPs. 800 Microsoft reservations on community (1,000) leaves little room for dynamic leases.
- Pick one DNS mode per zone before cutover. dns-how. Option 6 on the subnet must be whatever the site resolver is (usually AD/Unbound), not lattice-dns, unless that zone is all clients query.
- Prove one VLAN: list the relay in Settings → trusted relays, then point one relay at Lattice (
giaddrin that subnet). Or on the node:lattice-dhcptest -server 127.0.0.1:67 -giaddr <gateway>. Overview shows a lease. Same-VLAN broadcasts often miss Dockerized dhcpd. - Lower old lease time (e.g. 1h) a day before, so Renews come soon after you switch. Leave the Lattice subnet at 1 day unless it is guest (DHCP lease time).
- Switch relays (or the VIP they already use) to Lattice. Confirm those relay IPs are in Settings → trusted relays. Disable new Offers on the old server (deactivate scopes) the same hour.
- Do not turn the old box into scrap until Renews have succeeded for a full old-lease period. Keep it for rollback: point relays back.
3. Mapping (any vendor)
Prefix vs subnet vs pool
Their “scope 10.20.20.0/24” is usually:
- Prefix
10.20.20.0/24(or a parent10.20.0.0/16you already use as the plan) - Subnet
10.20.20.0/24withgateway= their router option - Pool
start–end= their dynamic range minus exclusions you will model as excludes/reservations
If they had a /16 scope with a small range, still make the subnet the L3 network (what giaddr sits in), not the range. Microsoft “start range .10” is a pool, not the subnet CIDR.
You can recreate the first VLAN entirely in the console (Addresses → subnet → pool) without curl. Use the API when you have hundreds of reservations — Excel → script, or a few dozen POST clicks is still normal. first-subnet.
Reservations
IP + MAC (DHCPv4) or DUID (v6). Hostname optional. At least one identity is required. Unique per subnet per IP and per MAC.
If the address is in an exclude, reservation create is rejected. Exclude the gateway; reserve the printer.
Options
| Common old option | Lattice |
|---|---|
| 1 mask | Built-in from subnet CIDR |
| 3 router | Subnet gateway |
| 6 DNS | DHCP option code 6, {"addresses":["10.0.0.1"]} — dns-how |
| 15 domain | Option 15, {"string":"office.example.com"} |
| 42 NTP | Subnet NTP servers (or option 42 JSON; stored option wins) |
| 51 lease | Subnet lease_time_seconds |
| 66/67 PXE | Subnet PXE next-server / boot file, not JSON |
| 43 vendor | Option 43 + vendor_class if needed |
Classes
Match vendor_class, user_class, or mac_prefix. Attach to a pool to steer. Do not recreate every Microsoft vendor-class as a Lattice class on day one. Reservations cover the devices that must not move.
4. Vendor export
Use their tools. Then POST Lattice JSON. Idempotency-Key on creates if you re-run a script.
Microsoft DHCP (Windows Server)
Primary buyer we wrote the vision for. Failover relationships and split scopes do not come with you.
On the DHCP server (PowerShell as administrator). These cmdlets do not take -All. Reservation, exclusion, lease, and per-scope option cmdlets need a scope: pipe from Get-DhcpServerv4Scope (that object carries ScopeId). Confirm parameters on Microsoft Learn if your Server version differs.
Get-DhcpServerv4Scope | Export-Csv scopes.csv -NoTypeInformation
Get-DhcpServerv4Scope | Get-DhcpServerv4Reservation | Export-Csv reservations.csv -NoTypeInformation
Get-DhcpServerv4Scope | Get-DhcpServerv4ExclusionRange | Export-Csv exclusions.csv -NoTypeInformation
# Server-level options (no scope):
Get-DhcpServerv4OptionValue | Export-Csv options-server.csv -NoTypeInformation
# Per-scope options:
Get-DhcpServerv4Scope | Get-DhcpServerv4OptionValue | Export-Csv options-scope.csv -NoTypeInformation
# Optional: current bindings to *turn into reservations* (section 5)
Get-DhcpServerv4Scope | Get-DhcpServerv4Lease |
Where-Object AddressState -eq 'Active' |
Export-Csv leases.csv -NoTypeInformation
Export-DhcpServer -File C:\temp\dhcp.xml is a full dump (Microsoft Learn); still map by hand or script — Lattice will not ingest the XML. Add -Leases only if you want the lease table for section 5.
Columns you care about:
- Scope:
ScopeId,SubnetMask,Name,LeaseDuration - Reservation:
IPAddress,ClientId(MAC),Name,Description - Exclusion:
StartRange,EndRange - Option 3/6/15/42 at scope vs server level — server-level becomes every Lattice subnet unless you meant that
Microsoft ClientId for Windows clients is typically a hyphenated MAC (F0-DE-F1-7A-00-5E), not colon-separated. Normalize to lowercase aa:bb:cc:dd:ee:ff before POST. If ClientId is not a six-octet hardware address (custom identifiers exist), do not treat it as a Lattice MAC.
ISC dhcpd (dhcpd.conf)
There is no first-class parser. Read the conf:
subnet 10.20.20.0 netmask 255.255.255.0 {
range 10.20.20.100 10.20.20.200;
option routers 10.20.20.1;
option domain-name-servers 10.0.0.1;
}
host printer {
hardware ethernet aa:bb:cc:dd:ee:ff;
fixed-address 10.20.20.10;
}
→ subnet + pool + gateway + option 6 + reservation.
allow/deny unknown-clients, pool { } allow lists, and shared-network need a human. dhcpd.leases is not an import file (section 5).
ISC Kea
kea-dhcp4.conf is JSON (subnet4, pools, reservations, option-data). Same mapping. kea-admin lease-dump is the same as Microsoft leases.csv — optional reservation seed, not a lease import.
dnsmasq
dhcp-range= → pool. dhcp-host=mac,ip,name → reservation. dhcp-option=6,… → option 6. Tiny configs: type them under Addresses.
Infoblox / BlueCat / EfficientIP
Export CSV or API (networks, DHCP ranges, fixed addresses, exclusion). Map to the same four objects. Do not expect Grid/BAM XML to load. Their HA/Anycast story is not ours; relays point at the Lattice VIP and health-check /readyz.
Cisco IOS / pfSense / OPNsense / libvirt
Same four objects. show ip dhcp binding / pfSense “leases” are lease dumps (section 5). pfSense/OPNsense are often ISC or Kea under the GUI — export the backend config if you can.
5. Cutover and IP stability
When a client Renews at Lattice with an IP Lattice never Acked, Lattice NAKs. The client Discovers. Lattice Offers from the pool (or a reservation). The client may get a different IP.
That is expected. Pick a strategy before you switch relays:
| Goal | What to do |
|---|---|
| IPs may change | Import pools + real reservations only. Shorten old lease time. Switch relays. Accept NAK→Discover. |
| Printers/servers keep IPs | Import those as reservations. Dynamic laptops can move. |
| Almost everyone keeps current IP | From the old lease dump, create Lattice reservations (MAC→IP) for active bindings that sit in the pool. After a week of clean Renews, delete reservations you want to become dynamic again. Counts against the license cap until you delete them. |
| Zero surprise on one VLAN | Cut that relay first. Watch Overview + NAK logs. |
Do not: copy dhcpd.leases into Postgres. Do not: run Microsoft and Lattice on the same UDP VIP. Do not: leave both offering on the same giaddr.
Rollback: relays back to the old server. Lattice leases stay in Postgres (harmless). Old server still has its own lease file — clients that already took a new Lattice IP will Renew to the old box and may NAK there too. Rollback is cleanest before many clients have rediscovered.
6. API sketch (after dump)
Admin token. Default tenant if you omit tenant_id. Idempotency-Key per create if the script is replay-safe.
# prefix (plan)
curl -s -X POST "$API/api/v1/prefixes" -H "authorization: Bearer $TOKEN" \
-H 'content-type: application/json' \
-d '{"cidr":"10.20.0.0/16","description":"from microsoft"}'
# subnet (use the prefix id)
curl -s -X POST "$API/api/v1/subnets" -H "authorization: Bearer $TOKEN" \
-H 'content-type: application/json' \
-d '{"prefix_id":"…","cidr":"10.20.20.0/24","gateway":"10.20.20.1","lease_time_seconds":3600}'
# exclude gateway
curl -s -X POST "$API/api/v1/subnets/$SUB/excludes" -H "authorization: Bearer $TOKEN" \
-H 'content-type: application/json' \
-d '{"start_ip":"10.20.20.1","end_ip":"10.20.20.1"}'
# pool
curl -s -X POST "$API/api/v1/subnets/$SUB/pools" -H "authorization: Bearer $TOKEN" \
-H 'content-type: application/json' \
-d '{"name":"dynamic","start_ip":"10.20.20.100","end_ip":"10.20.20.200"}'
# reservation
curl -s -X POST "$API/api/v1/subnets/$SUB/reservations" -H "authorization: Bearer $TOKEN" \
-H 'content-type: application/json' \
-d '{"ip":"10.20.20.10","mac":"aa:bb:cc:dd:ee:ff","hostname":"printer-01"}'
# option 6 (site resolver — usually AD, not lattice-dns)
curl -s -X POST "$API/api/v1/subnets/$SUB/options" -H "authorization: Bearer $TOKEN" \
-H 'content-type: application/json' \
-d '{"code":6,"payload":{"addresses":["10.0.0.1","10.0.0.2"]}}'
Conflicts (409) on overlap are the importer telling you the dump double-counted a range. 402 license_limit means too many reservations for this entitlement — delete optional MAC→IP seeds or raise the tier.
The console Addresses / subnet pages are the same objects. Spreadsheet → a few dozen curl POSTs is a normal first site. Thousands of reservations: script the CSV; do not paste XML into the UI.
7. DNS during migration
Old Microsoft/ISC DDNS into AD can keep running until you switch adapters.
- Keep AD: set subnet
ddns_adapter=ad_gsstsig(all tiers, including community), same forward/reverse zones, option 6 still the DCs. Worker GSS-TSIG replaces the old dhcpdnsupdate. Creating the dedicated user and keytab: ad-ddns. - Keep BIND:
bind_tsig. Option 6 unchanged. Minting the TSIG key: bind-ddns. - Keep PowerDNS Auth:
powerdns_http. Zones must already exist. powerdns. - Do not enable
embeddedon a zone the old server still updates. Split brain.
Map of adapters: integrations. Clients do not “find Lattice DNS” because you migrated DHCP. dns-how.
8. What success looks like
- One test VLAN: Discover/Request/Ack on Lattice; unique IPs; Overview lease count moves.
- Reservations: that MAC always gets that IP (
lattice-dhcptestcannot steal it). - Relays:
giaddrin the subnet;/readyzon dhcpd;LATTICE_TRUSTED_RELAYSset. - Old failover pair is off. One Lattice VIP (or single node).
- Names: if DDNS is on, A/PTR appear via the outbox, not on Ack.
- Rollback window elapsed; old DHCP role uninstalled.
If NAK storms after cutover: clients are Renewing IPs Lattice does not know — you skipped reservations for devices that must keep the address, or the pool does not include their old IP. Add reservations or widen the pool, do not “import the lease file.”
Just the steps
On the old Microsoft DHCP server (PowerShell as administrator). These cmdlets do not take -All. Confirm on Microsoft Learn.
Get-DhcpServerv4Scope | Export-Csv scopes.csv -NoTypeInformation
Get-DhcpServerv4Scope | Get-DhcpServerv4Reservation | Export-Csv reservations.csv -NoTypeInformation
Get-DhcpServerv4Scope | Get-DhcpServerv4ExclusionRange | Export-Csv exclusions.csv -NoTypeInformation
Get-DhcpServerv4OptionValue | Export-Csv options-server.csv -NoTypeInformation
Get-DhcpServerv4Scope | Get-DhcpServerv4OptionValue | Export-Csv options-scope.csv -NoTypeInformation
Get-DhcpServerv4Scope | Get-DhcpServerv4Lease |
Where-Object AddressState -eq 'Active' |
Export-Csv leases.csv -NoTypeInformation
Normalize reservation ClientId from F0-DE-F1-… to aa:bb:cc:dd:ee:ff. Then POST Lattice objects (prefix → subnet → exclude gateway → pool → reservations → option 6). Full curl bodies are in §6. Do not import the lease file as leases. Relays: one helper, trusted in Settings, then cut.