I recently experienced a downtime of about 12 hours, which I initially thought was due to power failure, but there had been no outage in my area (except a day before, which may have screwed the router).

As it turns out, the IP address (dynamic) assigned by the ISP changed, and the router by default only updates the CloudFlare entry every… day. Usually it changes when the power goes out so when it is restored the router automatically updates the IP address. Edge case. I guess the timing is good since Tomato firmware’s DDNS updater supports CloudFlare’s API v1, which is getting deprecated this year. So it’s a good time for me to migrate to API v4 and script it in the scheduler instead of the DDNS page. But that’s for another time.

Today I am updating the PowerShell script that I was using in Windows Server to update its IPv6 address. When my network came back online I realized that the server’s IDRAC IPv4 address wasn’t being updated, so I decided to make the script more flexible and maybe eventually use it to update everything. Now the messy script looks like this:

$Headers = New-Object "System.Collections.Generic.Dictionary[[String],[String]]"
$Headers.Add("X-Auth-Email", "[email protected]")
$Headers.Add("X-Auth-Key", "some auth key")

function UpdateDNSRecord($record, $IP) {
    if($record.content -eq $IP) { return }
    $Data = @{
    $JsonData = $Data | ConvertTo-Json
    $Uri = 'https://api.cloudflare.com/client/v4/zones/<some zone id>/dns_records/' + $record.id
    Invoke-RestMethod -Uri $Uri -Method Put -ContentType "application/json" -Headers $Headers -Body $JsonData

$CimInstance = Get-NetIPAddress -AddressFamily IPv6 -AddressState Preferred -PrefixOrigin DHCP -InterfaceIndex 13
$IPAddress = $CimInstance[0].IPv6Address

$IPv4Address = Invoke-RestMethod -Uri http://ipecho.net/plain

$zone = Invoke-RestMethod -Uri https://api.cloudflare.com/client/v4/zones/<some zone id>/dns_records -Method Get -ContentType "application/json" -Headers $Headers
$zonesToUpdate = $zone.result | where {$_.name -eq "something.example.com" -or $_.name -eq "something.else.example.com"}

ForEach ($record In $zonesToUpdate){
    UpdateDNSRecord $record $IPAddress

# update zones for a remote machine (idrac)
$idracIPv6Address = racadm getconfig -g cfgIPv6LanNetworking -o cfgIPv6Address2
$idracZone = $zone.result | where {$_.name -eq "idrac.example.com"}
$idracA = $idracZone | where {$_.type -eq "A"}
$idracAAAA = $idracZone | where {$_.type -eq "AAAA"}

UpdateDNSRecord $idracA $IPv4Address
UpdateDNSRecord $idracAAAA $idracIPv6Address

That’s fine and all, but now I am left with one small issue: in the event of a power failure, the server will power off cleanly thanks to the UPS, but then not power back on. There might be a setting somewhere to allow the server to automatically power back on when power is restored. But in the meanwhile this means that this script will not run after a power failure, and I won’t be able to access the IDRAC to turn the server back on.

to be continued…