VMware Cloud Community
Vlad_Belo
Enthusiast
Enthusiast
Jump to solution

Remove 'Orphaned' VMs, and Register Back (Fix Orphaned VMs)

Is there a powershell script that can "fix" orphaned VMs?

We have 2 big environments, one with 190 hosts, the other with 140 hosts

both of the environments had "partially" crashed, and caused many hosts to reboot.

the reboots caused many VMs (1800+) to get in 'Orphaned' states.

I'm working on a powershell script which will eventually do the following:

search over each host for the 'Orphaned' VMs, save the names of the VMs + Save the parent host name\IP (in a side variable, which will be used later)

Remove the 'Orphaned' VMs from inventory

Go to the DS, search the host name\IP that saved (to a side variable) from before, look for the VM name (of the orphaned that removed from inventory) register back the .vmx file 'Register VM...'

if any one could help with that it will be real amazing!

Thanks in advance!

Reply
0 Kudos
1 Solution

Accepted Solutions
LucD
Leadership
Leadership
Jump to solution

There are probably more than 1 VM on that ESXi node, hence $VMHost is an array.

Why not try like this?

 

 

$vCenter = "vc"
$vCUser = "user"
$vCPW = "pass"

Connect-VIServer $vCenter -User $vCUser -Password $vCPW -Force

$ResourcePool = "hostname"
Get-VMHost -Name $ResourcePool | Get-VM | 
Where-Object{$_.ExtensionData.Runtime.ConnectionState -eq "orphaned"} | 
ForEach-Object -Process {
  Remove-VM -VM $_.Name -Confirm:$false
  New-VM -Name $_.Name -VMHost $_.VMHost -VMFilePath $_.ExtensionData.Summary.Config.VmPathName -Confirm:$false
}

Disconnect-VIServer -Server $vCenter -Force -Confirm:$false

 

 


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

View solution in original post

21 Replies
LucD
Leadership
Leadership
Jump to solution

Can't you just
- find the orphaned VMs
- get/save the path of the VMX file
- use Remove-VM (without the DeletePermanently switch) to unregister them
- register them with New-VM and the VMFilePath parameter using the VMX path you saved in step 2


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

Reply
0 Kudos
Vlad_Belo
Enthusiast
Enthusiast
Jump to solution

Hi LucD, Thanks for Replying so fast!

Yes that is basically what I need, but before I start deleting 

I'm having a little struggle to get/save the path of the VMX files of the orphaned VMs

for example, I find the orphaned VMs like this 

$orphanedVMS = Get-VM -Name * | ?{$_.ExtensionData.Runtime.ConnectionState -eq "orphaned"} 

and that gives me a lot of information, and I want to reduce the information of the VMs to only the VM.name and parent Host.name

its a lot of hosts, and a lot of VMs on each host, and I would like to register back the exact VMs that has been removed from each specific host

Reply
0 Kudos
LucD
Leadership
Leadership
Jump to solution

You can find teh VMX path under the ExtensionData property, see Solved: Re: Get VMx path and then reregister - VMware Technology Network VMTN
The VMHost parameter is not needed on the New-VM cmdlet when you use the VMFilePath parameter.
That info is available in the VMX file and will be used when registering the VM


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

Reply
0 Kudos
Vlad_Belo
Enthusiast
Enthusiast
Jump to solution

Could you help me with this script?

each time I run it, its either doesn't save the names hence cant register back

$vCenter = "vc"
$vCUser = "user"
$vCPW = "pass"

Connect-VIServer $vCenter -User $vCUser -Password $vCPW -Force

$ResourcePool = "hostname"

$VMHost = Get-VMHost -Name $ResourcePool | Get-VM -Name * | ?{$_.ExtensionData.Runtime.ConnectionState -eq "orphaned"} | Select-Object Name, @{N = 'VMX'; E = { $_.ExtensionData.Summary.Config.VmPathName}}

Remove-VM -VM $VMHost.Name -Confirm:$false

New-VM -Name $VMHost.Name -ResourcePool $ResourcePool

Disconnect-VIServer -Server $vCenter -Force -Confirm:$false

Reply
0 Kudos
LucD
Leadership
Leadership
Jump to solution

There are probably more than 1 VM on that ESXi node, hence $VMHost is an array.

Why not try like this?

 

 

$vCenter = "vc"
$vCUser = "user"
$vCPW = "pass"

Connect-VIServer $vCenter -User $vCUser -Password $vCPW -Force

$ResourcePool = "hostname"
Get-VMHost -Name $ResourcePool | Get-VM | 
Where-Object{$_.ExtensionData.Runtime.ConnectionState -eq "orphaned"} | 
ForEach-Object -Process {
  Remove-VM -VM $_.Name -Confirm:$false
  New-VM -Name $_.Name -VMHost $_.VMHost -VMFilePath $_.ExtensionData.Summary.Config.VmPathName -Confirm:$false
}

Disconnect-VIServer -Server $vCenter -Force -Confirm:$false

 

 


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

Vlad_Belo
Enthusiast
Enthusiast
Jump to solution

Thanks! 

but still having issue with register back New-VM:

New-VM Please specify at least one of the following parameters: "ResourcePool" or "VMHost".

 

edit:

actually it looks like I fixed with removing the VMFilePath switch, and just replace with the resourcepool like so

New-VM -Name $_.Name -ResourcePool $ResourcePool -Confirm:$false

I think because its already in the loop so it does register within the info in the VMX file of the path like you said previously.

so it looks like its working perfectly!

 

only one more request if you can please, this scrips is meant for each host...

could you possibly help me out to make such script but for full vc site? and not only for each host seperatly?

but with same methods, for it to register back to each specific host it was removed from?

if it possible then thanks a lot!!

 

Reply
0 Kudos
LucD
Leadership
Leadership
Jump to solution

For re-registring you need to use the VMFilePath parameter.
All other parameters in the RegisterVM parameter set are optional.
Not sure how you used the script or the exact error you are getting.


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

Reply
0 Kudos
Vlad_Belo
Enthusiast
Enthusiast
Jump to solution

this is what I use:

 

$vCenter = "vc"

$vCenter = "vc"
$vCUser = "user"
$vCPW = "pass"

Connect-VIServer $vCenter -User $vCUser -Password $vCPW -Force

$ResourcePool = "hostname"

Get-VMHost -Name $ResourcePool | Get-VM |
Where-Object{$_.ExtensionData.Runtime.ConnectionState -eq "orphaned"} |

ForEach-Object -Process {
Remove-VM -VM $_.Name -Confirm:$false
New-VM -Name $_.Name -ResourcePool $ResourcePool -Confirm:$false
#Start-VM -VM $_.Name -Confirm:$false
}

Disconnect-VIServer -Server $vCenter -Force -Confirm:$false

 

and its working good I've tested it few times now

 

Reply
0 Kudos
LucD
Leadership
Leadership
Jump to solution

That is not what I posted


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

Reply
0 Kudos
Vlad_Belo
Enthusiast
Enthusiast
Jump to solution

I Know its not, like I said before, with what you posted, I've got error on New-VM 

Reply
0 Kudos
LucD
Leadership
Leadership
Jump to solution

Did you include the VMFilePath and VMHost parameter (see updated code above)?


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

Reply
0 Kudos
LucD
Leadership
Leadership
Jump to solution

Your code is creating a new VM, not re-registering an existing VM


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

Reply
0 Kudos
Vlad_Belo
Enthusiast
Enthusiast
Jump to solution

Yes, I've updated to your now again:

Get-VMHost -Name $ResourcePool | Get-VM | 
Where-Object{$_.ExtensionData.Runtime.ConnectionState -eq "orphaned"} |

ForEach-Object -Process {
    Remove-VM -VM $_.Name -Confirm:$false
    New-VM -Name $_.Name -VMHost $vm.VMHost -VMFilePath $_.ExtensionData.Summary.Config.VmPathName -Confirm:$false
   
}

 

And its still showing the error: 

New-VM : 6/28/2022 3:12:49 PM	New-VM		Please specify at least one of the following parameters: "ResourcePool" or "VMHost".
Reply
0 Kudos
LucD
Leadership
Leadership
Jump to solution

My bad, that should have said -VMHost $_.VMhost not -VMHost $vm.VMHost.
I corrected the code above.


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

Vlad_Belo
Enthusiast
Enthusiast
Jump to solution

Yes I see it now and I actually changed it too my self a moment ago 🙂

since the other statements was also $_. 

so cool thanks a lot look like it works perfectly!

Reply
0 Kudos
Vlad_Belo
Enthusiast
Enthusiast
Jump to solution

Hi Again LucD,

got another small question.

for the machines I've mistaken instead of 'Register' I've 'Created' new machines.

to fix that, I can just change the 

Where-Object{$_.ExtensionData.Runtime.ConnectionState -eq "orphaned"}

to something like that:

Where-Object{$_.PowerState -eq 'PoweredOff'}

 

since it created the VMs and left off, I can look for the powered off on each Host, remove from inventory and register back with the right VMX file?

or since it's already created new VM it will be a problem?

Reply
0 Kudos
LucD
Leadership
Leadership
Jump to solution

Are you sure these VMs are registered?
If not, they are in fact orphaned VMs that do not appear with a Get-VM.
You could use my Orphaned files and folders – Spring cleaning post to find those.


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

Reply
0 Kudos
Vlad_Belo
Enthusiast
Enthusiast
Jump to solution

I'm not sure they are registered, this was before you said "Your code is creating a new VM, not re-registering an existing VM

so I think it did not re-register an existing VM it just created new VMs with the same names

so my question is, is it enough just to change the 'Where-Object' for the PoweredOff state?

I'm asking that, because I did try it with the PoweredOff state, it only removed the new created VMs 

but did not register back... so perhaps I'm doing something wrong?

Reply
0 Kudos
LucD
Leadership
Leadership
Jump to solution

This should be a 2-step process.
1. Remove the incorrect new VMs. If these are registered you can just use Remove-VM with the DeletePermanently switch
2. Register the VMX files from the original list of VMs


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

Reply
0 Kudos