Sooo… It’s Friday the 13th and you need to restore your vCenter server

Shares

I think it’s a safe bet to say that most of vCenter servers out there are virtualized nowadays. In the end if you trust Vmware to virtualize your mission critical business applications why not run vCenter in a virtual machine, especially that vCenter itself is not a critical component of vSphere infrastructure (unless you’re hosting/cloud provider using functionality like Chargeback etc).
So you’ve got your vCenter virtual, secured by Vmware HA and just to be on the safe side you create backup clone(s) of this server on regular basis.
Cloning vCenter for backup purposes is fully supported, about one year ago Artur posted a PowerCLI script to automate this task.

But then the Friday 13th comes, something bad happens, you can not get your vCenter running and you don’t want to leave your infrastructure “unmanaged” over the weekend, so you decide to use that backup clone and restore your vCenter.
You “power on” the cloned vm just to recognize that (if your vCenter is Windows – and I think large part of vCenter servers still is) your IP configuration inside Windows is gone :S.

This is because cloned vm receives new MAC address(es) for each virtual nic and subsequently Windows detects these vnics as new, unconfigured hardware (which makes some sense tbh).

Then you need to manually configure the IP settings of your vCenter, which is really annoying if you planned to go home early this Friday.

What about we extend the functionality of the script that creates the clone to also save IP configuration somewhere in a form that can be used to restore this settings by another script?
The only place to safely store this IP configuration file is of course vCenter itself, we assume no networking connectivity during restore, so it can not be network share of any kind and if we save this configuration file before making the clone it will be copied with the whole server, right?

Artur’s script after modification should look like this:

Add-PSSnapin VMware.VimAutomation.Core
#variables
$VC='vcenter-server-FQDN-or-IP'
 
#import credentials
$pwd = Get-Content D:\tools\scripts\ap-vcs-credentials | ConvertTo-SecureString
$credentials = New-Object System.Management.Automation.PsCredential “username“, $pwd

$ScriptRoot = Split-Path $MyInvocation.MyCommand.Path
$xml_output = "$ScriptRoot\vcenter_nics_ipconfig.xml"

#create array of objects representing ip settings of all vmware network adapters

$nics = 	@(get-wmiobject win32_networkadapterconfiguration | 
			where-object {$_.macaddress -like "00:50:56:*"} |
			select-object description, ipaddress, ipsubnet, defaultipgateway, dnsserversearchorder |
			sort-object -descending -property index)
			
#export configuration to xml file

$nics | export-clixml -path $xml_output

#Connect to vCenter
Connect-VIServer -Server $VC
$sourceVM = 'test01'
 
#in $respool you can specify ESX host, cluster or resource pool
$respool=Get-VMhost -Name "ESXi host name"
$datastore=Get-datastore -Name 'datastore name'
$cloneName = $sourceVM+'-01'
#Remove second copy of VM
Remove-VM $sourceVM'-02' -Confirm:$false -DeletePermanently:$true
#Rename latest VM copy
Get-VM -Name $sourceVM'-01' | Set-VM -Name $sourceVM'-02' -confirm:$false
#Clone VM
if(New-VM -Name $cloneName -VM $sourceVM -ResourcePool $respool -Datastore $datastore -DiskStorageFormat Thin ){"DONE"}else{"Something wrong with cloning"}
Disconnect-VIServer -Confirm:$false

The IP configuration is exported to vcenter_nics_ipconfig.xml file (I assume you run this script from vCenter itself, as a Windows Scheduled Task probably) just before connecting vCenter to create the clone.

The restoring of this IP configuration can be somewhat tricky, mainly because Windows not only detects vnics as a new hardware but also (if you have more than one vnic in your vCenter) there is no easy way to detect the order in which they are connected (at least I couldn’t figure out anything workable, probably it can be done if you save also PCI IDs of your vnics along with IP configuration).

In general – there is no problem with vCenter that has one vnic only (obviously), when there are two vnics (like I usually have) the solution (or workaround to the problem) is fairly easy, you just try one order of configuration, test the connectivity (ping the default gateway probably – and there should be only one default gateway, right?) if it doesn’t work – just try the reverse order (and the script below does all of that for you)

<#
.SYNOPSIS
   Script configures vmware network adapters to ip settings loaded from vcenter_nics.xml file
.DESCRIPTION
   This script can be useful in scenario of cloning and restoring (virtual machine) vcenter server
   After clone is restored vnics receive new MAC addresses and subsequently are detected as new hardware in Windows, with no ip configuration
   The script creates array of current ($new_nics) WMI win32_networkadapterconfiguration objects that have vmware specific MAC addres prefix 
   (00:50:56: ) then sorts it in descending order of "index" property
   It is assumed that the higher number of vnic in vmware the higher number of network adapter index in windows 
   (i. e. Network adapter 1 in vmware <-> Network adapter index #7 in windows AND Network adapter 2 in vmware <-> Network adapter index #8 in windows)
   UNFORTUNATELY THIS IS NOT ALWAYS TRUE
   The script tries to detect and handle possible error by testing connectivity (ping) to default gateway (should always be only one in any system!)
   If ping is successful it is assumed ip configuration is OK
   If unsuccessful script tries to apply the settings in reverse order and test ping again
   That should do the trick for conifgurations with no more than 2 nics you know ;)
   If you have more than 2 nics and still no connectivity after 2nd ping attempt - you're on your own ;)
   After array of current nics is created the ip configuration is loaded from vcenter_nics_ipconfig.xml file, this file should be created
   before cloning vcenter using store_vcenter_ipconfig.ps1 script
   With a little interaction from administrator using the script (it is assumed restore from clone is not completely automated operation)
   a for loop assigns ip configuration so that it matches configuration stored in .xml file
.PARAMETER <paramName>
   none
.EXAMPLE
   trivia
#>

#general scope variables
$ScriptRoot = Split-Path $MyInvocation.MyCommand.Path
$xml_input = "$ScriptRoot\vcenter_nics_ipconfig.xml"

#create array of objects representing ip settings of all current vmware network adapters
$new_nics = @(get-wmiobject win32_networkadapterconfiguration | 
			where-object {$_.macaddress -like "00:50:56:*"} |
			sort-object -descending -property index)
			
$old_nics = import-clixml -path $xml_input

$new_nics_count = $new_nics.count
$old_nics_count = $old_nics.count

#write what will be done to the screen
write-host "CURRENT nic count is $new_nics_count" -foreground green
write-host "STORED  nic count is $old_nics_count" -foreground red
write-host "This script will set following configuration" -foreground green

for ($i=0; $i -lt $old_nics_count; $i++) {
#using index 0 for ipaddress properties is to make sure IPv4 address is selected
$ip = $old_nics[$i].ipaddress[0]
$subnet = $old_nics[$i].ipsubnet[0]
$gateway = $old_nics[$i].defaultipgateway
$dns = $old_nics[$i].dnsserversearchorder

write-host $new_nics[$i].macaddress will get address $ip and subnet $subnet
write-host $new_nics[$i].macaddress will get gateway $gateway
write-host $new_nics[$i].macaddress will get dns $dns
}

#give the engineer performing restore chance to abort 
write-host "This is your LAST CHANCE TO ABORT" -foreground yellow
write-host "STOP NOW If STORED nic count doesn't match CURRENT nic count or if you see any ip misconfiguration" -foreground red
write-host "Press Y + ENTER to continue" -foreground green
write-host "Press any other key + ENTER to ABORT..." -nonewline -foreground red

$response = read-host

if ( $response -ne "Y" ) { 
write-host "Operation ABORTED, no changes have been made to network settings" -foreground red
#exit
}
else {
#assume there is no connectivity
$ping_test = $false
for ($i=0; $i -lt $old_nics_count; $i++) {
#using index 0 for ipaddress properties is to make sure IPv4 address is selected
$ip = $old_nics[$i].ipaddress[0]
$subnet = $old_nics[$i].ipsubnet[0]
$gateway = $old_nics[$i].defaultipgateway
$dns = $old_nics[$i].dnsserversearchorder

#this is where we finally change these IPs
write-host Setting $new_nics[$i].macaddress with address $ip and subnet $subnet
$new_nics[$i].enablestatic($ip, $subnet) | out-null
write-host Setting $new_nics[$i].macaddress with gateway $gateway
$new_nics[$i].setgateways($gateway) | out-null
write-host Setting $new_nics[$i].macaddress with dns $dns
$new_nics[$i].setdnsserversearchorder($dns) | out-null

#try to ping default gateway
if ((!$ping_test) -and $gateway) {
write-host "TESTING network settings..." -foreground yellow
$ping_test = test-connection $gateway -quiet
}
}

#if received pong from default gateway we assume configuration is OK
if ($ping_test) {
write-host "PING to default gateway successful" -foreground green
write-host "Assuming IP configuration is correct... My work here is D0N3" -foreground green
write-host "It's a good idea to REBOOT NOW" -foreground green
#exit
}
else {
#damn, no pongs try to reconfigure nics in reverse order
write-host "OOPS, no ping response from default gateway, trying reverse nic order" -foreground yellow
$new_nics_asc = @(get-wmiobject win32_networkadapterconfiguration | 
			where-object {$_.macaddress -like "00:50:56:*"} |
			sort-object -property index)
#well this is false anyway, but I copy-pasted it just to be sure
$ping_test = $false
for ($i=0; $i -lt $old_nics_count; $i++) {
#using index 0 for ipaddress properties is to make sure IPv4 address is selected
$ip = $old_nics[$i].ipaddress[0]
$subnet = $old_nics[$i].ipsubnet[0]
$gateway = $old_nics[$i].defaultipgateway
$dns = $old_nics[$i].dnsserversearchorder

#last attempt to set-up IPs
write-host Setting $new_nics_asc[$i].macaddress with address $ip and subnet $subnet
$new_nics_asc[$i].enablestatic($ip, $subnet) | out-null
write-host Setting $new_nics_asc[$i].macaddress with gateway $gateway
$new_nics_asc[$i].setgateways($gateway) | out-null
write-host Setting $new_nics_asc[$i].macaddress with dns $dns
$new_nics_asc[$i].setdnsserversearchorder($dns) | out-null

#and ping the gateway again
if ((!$ping_test) -and $gateway) {
write-host "TESTING network settings AGAIN..." -foreground yellow
$ping_test = test-connection $gateway -quiet
}
}

#if true we quit happy, otherwise we give up
if ($ping_test) {
write-host "PING to default gateway successful" -foreground green
write-host "Assuming IP configuration is correct... My work here is D0N3" -foreground green
write-host "It's a good idea to REBOOT NOW" -foreground green
#exit
}
else {
write-host "OOPS, STILL no ping from default gateway, I have no idea what to do next... Exiting :( " -foreground red
#exit
}
}
}

The script is a bit interactive – it requires you to confirm you want to apply IP configuration stored in .xml file, I just don’t trust myself enough to let it run in fully automated mode (especially on Friday the 13th 😉 ).

It will probably not work (unless you’re lucky) with 3 and more vnics in vCenter – there is simply more than 2 possible permutations of vnics order, but why would you need more than 2 vnics in vCenter anyways? 😉

Also note that it doesn’t configure things like DNS search suffixes or persistent routes (if you have any), but it can be easily extended to do so.

I actually had “real life” opportunity to see this script working and it did it’s job – restored vCenter connectivity to the point where I could go home for the weekend and finish minor things (like these DNS suffixes) on Monday.

I hope you find this script useful, any comments are welcome!

0 0 votes
Article Rating

Sebastian Baryło

Successfully jumping to conclusions since 2001.

You may also like...

Subscribe
Notify of
guest
0 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x

FOR FREE. Download Nutanix port diagrams

Join our mailing list to receive an email with instructions on how to download 19 port diagrams in MS Visio format.

NOTE: if you do not get an email within 1h, check your SPAM filters

You have Successfully Subscribed!

Pin It on Pinterest