On Demand Backup of All Registered DHCP Servers

I am a fan of having my backups as automated and concise as possible. When it comes to DHCP backups, the typical Backup-DHCPServer works great, but it only stores it on the local server.

What happens if that server dies? Well, it's time to load up our tape backups of the most recent backup of the server and start a recovery job. (Many of my sites only have a single DHCP server so we are not running any sort of high availability at those sites).

But, what if I can get Backup-DHCPServer to do my bidding and copy these backups to a completely separate server and have them backed up there as well?

The following script requires PSCX modules to be installed on your computer. The PowerShell Community Extensions are a fantastic set of cmdlets that I highly recommend anyone reading this blog installs and starts utilizing today!

You can install the PSCX module with PowerShellGet, which is included with version 5.0 of the Windows Management Framework, with the following command:

Install-Module -Name PSCX;


Now that you have the PSCX Module installed, when you run my Backup DHCP Servers script, your PC will call the module and generate a highly compressed .ZIP file of the DHCP Backups that it creates and stores on your local PC. My last DHCP Backup for my environment, uncompressed, cost me 105MM in disk space, compressed down to 607KB of disk space!

The script first imports my required modules.
Import-Module ActiveDirectory
Import-Module DhcpServer
Import-Module pscx -Verbose 

We now generate a few of our required variables and report out a little information about where we are going to store our results.
$now = Get-Date -DisplayHint DateTime -Format yyyy_MMM_dd-HH-mm-ss-tt
$dirpath = "C:\DHCP_Backups\$now"
write-host -BackgroundColor Black -ForegroundColor Green $dirpath
$directory = New-Item -Path $dirpath -ItemType Directory

Now, we query ADDS to find all registered DHCP servers, parse out the relevant return data, then store those server names into an array.
NOTE: You need to modify the Get-ADObject line in the following section to align properly with your domain's configuration. Replace the "dc=riston,dc=me" section of the -SearchBase variable to match your needs.
#region Find all registered DHCP Servers in Active Directory.

$DHCPServers_Registered = `
    Get-ADObject -SearchBase "cn=configuration,dc=riston,dc=me" -Filter "objectclass -eq 'dhcpclass' -AND Name -ne 'dhcproot'" -Properties * | select name

$DHCPServers_Registered = $DHCPServers_Registered.name

$DHCPServers_Cleaned = @()

Remove-Variable -Name DHCPServers_Online -ErrorAction SilentlyContinue

foreach ($server in $DHCPServers_Registered) {
    
    $server = $server.ToString()

        $name = $server.TrimStart("@{name=").TrimEnd("}")
        if ($server.Contains(":")) {
            Write-host Bad Name. Skipping.
            }`
        else {
            Write-Host Server is good. Adding
            $DHCPServers_Cleaned += $name
            }
        }

Now, we attempt to connect to all of thes 'Registered' domain controllers. The online server names are stored in a variable for further processing.
$DHCPServers_Online = @()

foreach ($server in $DHCPServers_Cleaned) {
    #Test that the server is online
    New-Variable Error_ServerOffline
    
    Test-Connection $server -Count 4 -ErrorVariable Error_ServerOffline

    if (($Error_ServerOffline).Count -eq 0) {
        #Our current server is online, Add it into our DHCPServers_Online variable.
        $DHCPServers_Online += $server
        } `
    Else {
        #Our current server is offline. No processing to occur. Alert the local admin.
        Write-Warning $server is not accessible. No processing on this server will occur.
        }
    
    Remove-Variable Error_ServerOffline -Force

    Write-Host DHCPServers_Online has now been populated -ForegroundColor Green -BackgroundColor Black

    }

Write-Host "
DHCPServers_Online has now been fully populated. Below is the full list.
$DHCPServers_Online" -ForegroundColor Green -BackgroundColor DarkGray

#endregion

Now, for each of our Online DHCP Servers, we generate a backup of the server using the canned Backup-DHCPServer, and then copy it to our host machine that is actually running the script. We also remove the copy on the DHCP server itself as to not overload the disk. This may not be the best solution for everyone, but I've decided that removing it from the server itself is the best option for my environment.

foreach ($DC IN $DHCPServers_Online)
    {  Write-Host "Currently processing $dc" -ForegroundColor Green -BackgroundColor Black 
       $newpath = "$dirpath\$dc\" #-Verbose
       New-Item "\\$dc\c$\DHCP_Backups\$now\$dc" -ItemType Directory #-Verbose
       New-Item $newpath -ItemType Directory -Force #-Verbose

       Backup-DhcpServer -ComputerName $DC -Path $newpath #-Verbose 
       #Write-Warning $newpath

       Write-Host "Completed Processing $DC" -ForegroundColor Green -BackgroundColor Black
       Write-Warning "Backup-DhcpServer exited with $LASTEXITCODE" 
       Write-Host ""

       Write-Host "Now Copying $DC Backup" -ForegroundColor Green -BackgroundColor Black
       Copy-Item "\\$dc\c$\DHCP_Backups\$now\$dc\" -Recurse -Destination $dirpath\$DC

       Remove-Item "\\$dc\c$\DHCP_Backups\$now\" -Force -Recurse

     #  Write-Zip -Path $directory -Level 9 -IncludeEmptyDirectories C:\DHCP_Backups\$now.zip -Verbose

     #  Remove-Item $directory -Force -Recurse

    } 

Now that the brunt of the work is done, we will generate our compressed ZIP file and remove the uncompressed source directory from my computer.

#Write out our zip file using the Write-Zip cmdlet provided from PSCX
Write-Zip -Path $directory -Level 9 -IncludeEmptyDirectories C:\DHCP_Backups\$now.zip -Verbose
#Remove the uncompressed source files locally
Remove-Item $directory -Force -Recurse

The full script follows;

Import-Module ActiveDirectory
Import-Module DhcpServer
Import-Module pscx -Verbose 

$now = Get-Date -DisplayHint DateTime -Format yyyy_MMM_dd-HH-mm-ss-tt
$dirpath = "C:\DHCP_Backups\$now"
write-host -BackgroundColor Black -ForegroundColor Green $dirpath
$directory = New-Item -Path $dirpath -ItemType Directory

#region Find all registered DHCP Servers in Active Directory.

$DHCPServers_Registered = `
    Get-ADObject -SearchBase "cn=configuration,dc=riston,dc=me" -Filter "objectclass -eq 'dhcpclass' -AND Name -ne 'dhcproot'" -Properties * | select name

$DHCPServers_Registered = $DHCPServers_Registered.name

$DHCPServers_Cleaned = @()

Remove-Variable -Name DHCPServers_Online -ErrorAction SilentlyContinue

foreach ($server in $DHCPServers_Registered) {
    
    $server = $server.ToString()

        $name = $server.TrimStart("@{name=").TrimEnd("}")
        if ($server.Contains(":")) {
            Write-host Bad Name. Skipping.
            }`
        else {
            Write-Host Server is good. Adding
            $DHCPServers_Cleaned += $name
            }
        }

$DHCPServers_Online = @()

foreach ($server in $DHCPServers_Cleaned) {
    #Test that the server is online
    New-Variable Error_ServerOffline
    
    Test-Connection $server -Count 4 -ErrorVariable Error_ServerOffline

    if (($Error_ServerOffline).Count -eq 0) {
        #Our current server is online, Add it into our DHCPServers_Online variable.
        $DHCPServers_Online += $server
        } `
    Else {
        #Our current server is offline. No processing to occur. Alert the local admin.
        Write-Warning $server is not accessible. No processing on this server will occur.
        }
    
    Remove-Variable Error_ServerOffline -Force

    Write-Host DHCPServers_Online has now been populated -ForegroundColor Green -BackgroundColor Black

    }

Write-Host "
DHCPServers_Online has now been fully populated. Below is the full list.
$DHCPServers_Online" -ForegroundColor Green -BackgroundColor DarkGray

#endregion

foreach ($DC IN $DHCPServers_Online)
    {  Write-Host "Currently processing $dc" -ForegroundColor Green -BackgroundColor Black 
       $newpath = "$dirpath\$dc\" #-Verbose
       New-Item "\\$dc\c$\DHCP_Backups\$now\$dc" -ItemType Directory #-Verbose
       New-Item $newpath -ItemType Directory -Force #-Verbose

       Backup-DhcpServer -ComputerName $DC -Path $newpath #-Verbose 
       #Write-Warning $newpath

       Write-Host "Completed Processing $DC" -ForegroundColor Green -BackgroundColor Black
       Write-Warning "Backup-DhcpServer exited with $LASTEXITCODE" 
       Write-Host ""

       Write-Host "Now Copying $DC Backup" -ForegroundColor Green -BackgroundColor Black
       Copy-Item "\\$dc\c$\DHCP_Backups\$now\$dc\" -Recurse -Destination $dirpath\$DC

       Remove-Item "\\$dc\c$\DHCP_Backups\$now\" -Force -Recurse

     #  Write-Zip -Path $directory -Level 9 -IncludeEmptyDirectories C:\DHCP_Backups\$now.zip -Verbose

     #  Remove-Item $directory -Force -Recurse



    } 

#Write out our zip file using the Write-Zip cmdlet provided from PSCX
Write-Zip -Path $directory -Level 9 -IncludeEmptyDirectories C:\DHCP_Backups\$now.zip -Verbose
#Remove the uncompressed source files locally
Remove-Item $directory -Force -Recurse

Comments

Popular Posts