DHCP Fail...Over

One of the great features of Server 2012 R2 is the concept of DHCP Failover. Unfortunately, one of the crappy features of this is that DHCP reservations are not automatically synced between failover partners, unlike scope configuration and leases. Seems odd that the one thing that has personally caused headaches amongst DHCP administrators- the laziness of other admins not creating reservations in split scopes- was left out, but anyway…

After a little Googling, I found a script that promised to do exactly what I wanted: Automatic syncing of configuration changes between 2 DHCP failover servers. However, on further investigation it seems to only support one-way replication- designed for a Primary/Secondary setup. Ideally I wanted to idiot-proof the creation of reservations and have reservation changed replicated bidirectionally within the failover relationship.

With this in mind, I initially started looking at modifying DhcpFailoverAutoConfigSyncTool.ps1 to support syncing both ways. After a little investigation, it seemed easier to scrap that idea and utilise the ability of task scheduler to subscribe to event log events. Specifically, events 106 (DHCP reservation modification) and 107 (Delete) in the Microsoft-Windows-Dhcp-Server/Operational log.

First off was to create the scheduled task to trigger a script on modifications. I followed the guide available here.

Taking inspiration from DhcpFailoverAutoConfigSyncTool.ps1 I added code to create a registry key on the secondary server to prevent events ping-ponging between servers, however it seems like this was wasted effort as the scopes do not appear to replicate if they are in sync. I have left it in the final script anyway as there is no real harm in it.

Hopefully this script helps you out as well, and ideally Microsoft will build this into Server vNext DHCP role.

The script is available below. USE AT YOUR OWN RISK- please test before putting into a production environment. This script won’t support multiple failover partners, but would be trivial to change.

<# 
.SYNOPSIS 
   Triggered based on events from DHCP server to sync reservations.
   
.DESCRIPTION
   Script is trigged based on events 106 and 107 in DHCP server event log to 
   sync DHCP reservations in a particular scope to failover partner.

.NOTES 
   File Name  : Invoke-DHCPSync.ps1 
   Author     : John Sneddon - @JohnSneddonAU
   Version    : 1.0

.LINK
   https://www.sneddo.net/2015/05/dhcp-fail-over/

.INPUTS
   No inputs required
.OUTPUTS
   None

.PARAMETER eventRecordID
   Event ID of the triggering event

.PARAMETER eventChannel
   Event Channel of the triggering event - will always be Microsoft-Windows-Dhcp-Server/Operational
#>
param($eventRecordID,$eventChannel)

$regKey = "SYSTEM\CurrentControlSet\Services\DHCPServer\Parameters"
$regKeyName = "SyncInProgress"

# Get the exact event

$event = Get-WinEvent -LogName $eventChannel -FilterXPath "<QueryList><Query Id='0' Path='$eventChannel'><Select Path='$eventChannel'>*[System[(EventRecordID=$eventRecordID)]]</Select></Query></QueryList>"

if (!(Get-Item Registry::HKEY_LOCAL_MACHINE\$regkey -ErrorAction SilentlyContinue).Value)
{
   # Match the event Property to ScopeID - Format [[172.x.x.x]Scope name]

   if ($event.Properties[1].value -match "\[\[(.*)\].*\]")
   {
      $date = Get-date
      $scope = $Matches[1]
      $state = (Get-DhcpServerv4Scope $scope).State
      
      # Get scope and find the partner 

      $partner = (Get-DhcpServerv4Failover -ScopeId $scope).PartnerServer
      
      # set reg key on partner

      $BaseKey = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey('LocalMachine',$partner)
      $SubKey = $BaseKey.OpenSubKey($regKey,$true)
      $SubKey.SetValue($regKeyName , 1, [Microsoft.Win32.RegistryValueKind]::DWORD)
      
      # start replication

      Invoke-DhcpServerv4FailoverReplication –ScopeID $scope -Force
      
      # Remove reg key from partner

      $SubKey.SetValue($regKeyName , 0, [Microsoft.Win32.RegistryValueKind]::DWORD)
   }
}