Skip to content

Instantly share code, notes, and snippets.

@davidlu1001
Last active June 20, 2024 11:04
Show Gist options
  • Save davidlu1001/60f2cfd0eb954f9d1ec06d7d00bac0db to your computer and use it in GitHub Desktop.
Save davidlu1001/60f2cfd0eb954f9d1ec06d7d00bac0db to your computer and use it in GitHub Desktop.
Manage DNS Failover
param(
[Parameter(Mandatory=$false)]
[string]$dnsName,
[Parameter(Mandatory=$false)]
[string]$dnsServer,
[Parameter(Mandatory=$false)]
[string]$lookupZone,
[ValidateSet("check", "failover")]
[string]$Ops = "check", # Default operation mode
[System.TimeSpan]$TTL = [System.TimeSpan]::FromMinutes(15) # Sets TTL to 15 minutes
[int]$waitTimeInit = 300, # Default init wait time in seconds before 1st check
[int]$waitTime = 60, # Default wait time in seconds for each check
[int]$maxWaitTime = 1800 # Max wait time to verify the failover (double the default TTL 15 mins)
)
function LogMessage($message) {
Write-Output "$(Get-Date) - $message"
}
function Get-ActiveHost {
try {
$ping = Test-Connection -ComputerName $dnsName -Count 1 -ErrorAction Stop
# Resolve the hostname from the IP address
$hostEntry = [System.Net.Dns]::GetHostEntry($ping.Address)
$activeHost = $hostEntry.HostName
#LogMessage "Active host : $activeHost"
return $activeHost
} catch {
LogMessage "Unable to ping $dnsName or resolve hostname. Error : $_"
return $null
}
}
function GetCurrentCnameData {
try {
$dnsRecord = Get-DnsServerResourceRecord -Name $dnsName -RRType CName -ZoneName $lookupZone -ComputerName $dnsServer -ErrorAction Stop
return $dnsRecord.RecordData.HostNameAlias
} catch {
LogMessage "Failed to get DNS record for $dnsName. Error : $_"
return $null
}
}
function Update-Cname($currentData) {
$newData = switch ($currentData) {
{$currentData -match "Prod"} {$currentData -replace "Prod", "DR"}
{$currentData -match "DR"} {$currentData -replace "DR", "Prod"}
default {
LogMessage "No matching 'Prod' or 'DR' found in $currentData."
return $false
}
}
if ($newData) {
try {
Remove-DnsServerResourceRecord -ZoneName $lookupZone -Name $dnsName -RRType CName -ComputerName $dnsServer -Force
Add-DnsServerResourceRecordCName -Name $dnsName -HostNameAlias $newData -ZoneName $lookupZone -ComputerName $dnsServer -TimeToLive $TTL
LogMessage "DNS CNAME updated to $newData"
return $true
} catch {
LogMessage "Failed to update DNS CNAME. Error : $_"
return $false
}
}
}
function Verify-Failover($initialHost) {
$elapsedTime = 0
Start-Sleep -Seconds $waitTimeInit
do {
Start-Sleep -Seconds $waitTime
$elapsedTime += $waitTime
$newHost = Get-ActiveHost
if ($newHost -ne $initialHost) {
LogMessage "DNS failover succeeded, new host is $newHost"
return
}
} while ($elapsedTime -lt $maxWaitTime)
LogMessage "DNS failover failed or is still pending propagation after $maxWaitTime seconds."
}
# Main Execution Block
switch ($Ops) {
"check" {
Get-ActiveHost
}
"failover" {
$initialHost = Get-ActiveHost
if ($initialHost) {
$currentData = GetCurrentCnameData
if ($currentData) {
if (Update-Cname $currentData) {
Verify-Failover $initialHost
}
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment