Active Directory 2012 R2 Upgrade and DHCP Services Migration to Meraki

I’ve recently rejiggered the lab again, this time to uplift my Active Directory Domain Services (AD DS) from Windows Server 2008 R2 to Windows Server 2012 R2 and shift around the DHCP services to a different endpoint. Surprisingly enough, the single forest / single domain structure that lives in my lab – glacier.local – is nearly 10 years old. I consider it a mark of pride that it’s survived so long, especially being from Windows Server 2000 roots. 🙂

Anyhow, I’ve documented a bit on the migration because it took a few wrinkles in the old noodle to figure out how to do it while remaining online, serving requests, and maintaining redundancy. Why, you might ask? Let’s list a few reasons below:

  • I had a pair of domain controllers named DC and DC2. My OCD hates that one server used a number, and the other didn’t. My desired outcome is having the servers named DC1 and DC2.
  • The “DC” server also controlled DHCP in a non-redundant fashion for everything in the house (lab and non-lab). I wanted to push that up to my Meraki MX60W to shift the service away from the core lab components and onto something that only rarely has planned maintenance. Even if my Meraki does go down, it means the Internet gateway is also down, and I’ll have bigger fish to fry. Using the Meraki also means no more DHCP relays from the home networks into the lab networks. I will still use isolated DHCP servers for other projects (such as Razor) but those are purpose-built.

I decided to break the activities into three major steps.

Step 1 – Migration of DHCP Services to the Meraki MX60W

I figured it would be best to start with the easy stuff: moving DHCP.


Because my lease timers are set rather high (7 days), I wasn’t too worried about doing this during production. DHCP clients tend to check in when their lease is half way towards expired, so I could be reasonably certain that I had 3.5 days remaining to get this migrated. Plenty of time!

From the Meraki Dashboard, navigate to Configure > DHCP. Each VLAN will have an option to provide DHCP configuration values. I set up my lab domain as follows:

  • Gateway IP: The SVI on my Layer 3 switch, which is for VLAN 20.
  • Lease time: 1 week (7 days) to match the old timer.
  • DNS nameservers: I used my own internal domain controllers, which are also AD integrated DNS Servers. This allows the clients to resolve the glacier.local domain.
  • DHCP options: None were required, but if you needed them for PXE or VoIP environments, stick ’em here.
  • Reserved IP ranges: This was a bit backwards from what I’m used to. Instead of specifying a block of dynamic IPs, you instead set an exclusion range. I reserve the lower 100 IPs in the fourth octet for static, giving me 154 addresses for DHCP. Should be plenty and it’s an easy way to spot a static vs dynamic address without looking at the configuration.

Here’s a look at the configuration after it’s been set in the Meraki:


Because this VLAN is not directly connected, I needed to set up a DHCP relay on my Layer 3 switch (an HP V1910) to forward requests to the Meraki. I use a small /29 subnet to route from the Meraki to the HP (VLAN 99). I constructed a relay to, which is the internal (southbound) L3 address on my Meraki, to handle DHCP requests from the lab’s VLAN 10 and VLAN 20.


I released the DHCP lease on a client and made sure that it acquired a new lease via the Meraki. Head to the Meraki Dashboard > Monitor > Event Log and filter by DHCP to see lease activity.

Step 2 – Swinging Domain Controllers and Client DNS

Now that DHCP services are migrated, I crafted a new domain controller named “DC1” using a Windows Server 2012 R2 image. I had to start with this server because there was already a “DC2” server and I didn’t want to run with a single domain controller.

I went ahead and transferred all five of the FSMO roles to the new “DC1” and did a number of health checks on DNS and AD to ensure the forest and domain were healthy.


I then pointed all of the client DNS entries to the “DC” and “DC1” servers. The “DC2” server was decommissioned.


I used a simple script to update DNS entries for anything within AD that classified as a computer object, while allowing a DHCP refresh to tackle the rest with updated DNS entries. I could have just waited for the final domain controller to be rebuilt, but I didn’t want things to start timing out because they were pointing to a dead DNS server.

Here is the script I used:

#	Set DNS Server entries for clients

# Snapins
Install-WindowsFeature -Name RSAT-AD-PowerShell
Import-Module ActiveDirectory

# DNS variables
$DNSServersDC1 = @("","","")
$DNSServersDC2 = @("","","")
$DNSServers = @("","")

# Domain Controller 1
$wmi = Get-WmiObject win32_networkadapterconfiguration -ComputerName "dc1.glacier.local" -filter "ipenabled = 'true'"
$wmi.SetDNSServerSearchOrder($DNSServersDC1) | Out-Null

# Domain Controller 2
$wmi = Get-WmiObject win32_networkadapterconfiguration -ComputerName "dc2.glacier.local" -filter "ipenabled = 'true'"
$wmi.SetDNSServerSearchOrder($DNSServersDC2) | Out-Null

# Get a list of all the computer objects that AD is aware of
$pclist = get-adcomputer -Filter 'ObjectClass -eq "Computer"' | select -ExpandProperty DNSHostName

# Run through the list and set the DNS server entries for each computer object
foreach ($_ in $pclist) {
    if ($_ -notmatch "DC*") {
        Write-Host "Connecting to $_"
        $wmi = Get-WmiObject win32_networkadapterconfiguration -ComputerName $_ -filter "ipenabled = 'true'"
        $wmi.SetDNSServerSearchOrder($DNSServers) | Out-Null

Step 3 – Balancing FSMO Roles and Final Client DNS Updates

The final activity was to repeat most of Step 2. This time, the new server was called “DC2” and the decommissioned server was that original “DC” server. Once completed, I split FSMO roles: “DC1” would take on the forest roles, while “DC2” would handle domain roles. Each is a global catalog server. I then did a health check and updated the DNS client entries once more.


The last part was a functional level update to Windows Server 2012 R2.


It was that simple! 🙂