19 January 2011

Re-Registering VMs Removed from Inventory

The cache module on the array controller failed on a host, and ESXi was wasted. The host stopped responding in vCenter, but did not fail hard enough to trigger HA. Most of the VMs on it were still up and their OSes were responsive to ping requests. Eventually we had to remove the host from vCenter. At that point, all VMs registered on it also are removed from inventory.

I grabbed the info for the guests that were in "disconnected" state _BEFORE_ removing the affected host from vCenter, then removed the host, then re-registered VMs and started them as such:
## Script function:  re-register VMs after host removal from vCenter
## Author: vNugglets.com
## Jan 2011

## cluster in which troubled host resides
$strAffectedCluster = "myCluster"

## get array BEFORE removing bad host from vCenter!!! Else, will not be able to get this info in this manner, since disconnected VMs are removed from inventory at that time, too

## get an array of VM .Net View objects where their OverallStatus is "gray"; optimized for low memory consumption
$arrVMsToHandle = Get-View -ViewType VirtualMachine -SearchRoot (Get-Cluster $strAffectedCluster | Get-View).MoRef -Property Name,Parent,LayoutEx.File,Summary.OverallStatus -Filter @{"Summary.OverallStatus" = "gray"}

## get the hosts in the cluster, to be used for re-registering VMs
$arrHostsInAffectedCluster = Get-Cluster $strAffectedCluster | Get-VMHost

## for each set of VM name, parent folder ID, and .VMX file path, add VM to inventory via New-VM cmdlet; add to random host within the cluster
$arrVMsToHandle | Select Name, Parent, @{n="vmxFilePath"; e={($_.layoutex.File | ? {$_.name -like "*.vmx"}).name}} | %{
New-VM -VMFilePath $_.vmxFilePath -VMHost ($arrHostsInAffectedCluster | Get-Random) -Location (Get-VIObjectByVIView $_.Parent) -RunAsync
} ## end ForEach-Object

## start all of the VMs (may cause a boot storm if huge number of VMs -- split up by groups of x VMs as necessary)
$arrVMsToHandle | %{Start-VM $_.Name -RunAsync}

You could also have put the "Start-VM" call inside of the "ForEach-Object" loop (say, before line 19), but that makes the process more linear than quick. This would require the removal of the "-RunAsync" from the "New-VM" call on line 18.

This could come in handy for you someday. Enjoy!


  1. This is excellent stuff and thank you for this! I was able to test and add additional lines to make this work for vDSwitch implementations. When the bad host is removed the orphaned VMs lose their Network Adapter vDS-PortGroups when added back to inventory. This will collect the network information and reconfigure the VM's Network Adapters with their appropriate PortGroups. Hope this helps people out there!

    ## Get Network adapters and PortGroups per VM
    $arrVMnets = Get-VM $arrVMsToHandle.Name | Get-NetworkAdapter | Select Name,NetworkName,@{N="VM";E={$_.Parent.Name}}

    ##Reconfigure VM Nics with PortGroups
    ForEach($Adapter in $arrVMnets){Get-VM $Adapter.VM | Get-NetworkAdapter | Where{$_.Name -like $Adapter.Name} | Set-NetworkAdapter -NetworkName $Adapter.NetworkName -Confirm:$false}

    I did it per adapter as some VMs may have multiple.


    1. Hello, Kristopher-

      Thanks for the feedback, and for sharing your add-on. I see the [uncredited] reproduction of most of this post on your blog -- glad to help and inspire (though, you might want to cite references (or at least put others' work in quotes or something to show that it is a quote) in the future).


Note: Only a member of this blog may post a comment.