Virtually everything is poshable
PowerCLI: Shutdown your Virtual Infrastructure
Imagine your Power intake to your rack has failed, imagine your UPS has kicked in but is about to run out of power, you need to quickly shut down all of your virtual infrastructure…. quick run !
Or, you could let PowerCLI do the work for you and help you safely shutdown your entire virtual infrastructure, you could even tell your UPS software that when it gets to a certain amount of battery life left that it needs to run this script to safely shut things down.
When I first wrote this script it didn’t work quite as expected, we can easily tell all our guests to shut down nicely through the guest shutdown feature but as I found, this doesn’t always work, for example, what happens if one of your machines is sat there on the following screen:
If that happens then the guests never actually shut down and we are left in limbo waiting for the guests to “safely” be shut down, As you will see from the below script, I have added not only a check to see if the VMs are powered off but also a fail safe time where it just goes for it and shuts down the hosts anyway.
Connect-VIServer MyVIServer
# Get All the ESX Hosts
$ESXSRV = Get-VMHost
# For each of the VMs on the ESX hosts
Foreach ($VM in ($ESXSRV | Get-VM)){
# Shutdown the guest cleanly
$VM | Shutdown-VMGuest -Confirm:$false
}
# Set the amount of time to wait before assuming the remaining powered on guests are stuck
$waittime = 200 #Seconds
$Time = (Get-Date).TimeofDay
do {
# Wait for the VMs to be Shutdown cleanly
sleep 1.0
$timeleft = $waittime - ($Newtime.seconds)
$numvms = ($ESXSRV | Get-VM | Where { $_.PowerState -eq "poweredOn" }).Count
Write "Waiting for shutdown of $numvms VMs or until $timeleft seconds"
$Newtime = (Get-Date).TimeofDay - $Time
} until ((@($ESXSRV | Get-VM | Where { $_.PowerState -eq "poweredOn" }).Count) -eq 0 -or ($Newtime).Seconds -ge $waittime)
# Shutdown the ESX Hosts
$ESXSRV | Foreach {Get-View $_.ID} | Foreach {$_.ShutdownHost_Task($TRUE)}
Write-Host "Shutdown Complete"
This can be changed to only shutdown all vms and hosts in a certain datacenter of cluster by amending line 04 to the following:
For a specific datacenter, mine is called DC1…
$ESXSRV = Get-DataCenter “DC1” | Get-VMHost
For a specific cluster, mine is called Production…
$ESXSRV = Get-Cluster “Production” | Get-VMHost
I’m sure I don’t need to tell you that you need to be extremely careful when testing this script as one false move could shut down everything ! – Please test this to make sure it works first !
* Just to mention, this will obviously not work if your virtual center is a VM, for that you will need to do some funky connecting to each host etc, let me know if you desperately need that.
| Print article | This entry was posted by Virtu-Al on January 6, 2010 at 23:00, and is filed under PowerCLI, powershell, vmware. Follow any responses to this post through RSS 2.0. You can leave a response or trackback from your own site. |







(3)
(13)
(0)
about 7 months ago
Great post! I’m amazed at how little this topic is addressed in posts and articles.
Improvements could come in a few forms.
1. It would be nice if there were a way to dry-run test it, so that you could do some validating without it kicking in.
2. In reality, there is a general order in which one would want vm’s to gracefully shut down. It’s no fun if your DC’s shut down first.
As for your comment about vcenter not being a VM in order for this to work, I think there is another way. One would have their cluster of ESX hosts. Then, you have a cheap old PC with a few extra NIC’s, with ESXi built up, connected to the SAN as well, but only running one VM; the server running vcenter. That way you have the flexibility of it being a VM on the SAN, but living outside the cluster.
about 7 months ago
Nice script….I’m looking for a similar script to shutdown guest based on priority. I have a custom field called Priority attached to each guest with value 1,2 or 3. I would like to shutdown guest with low value 3 first followed by value 2 and last value 1
Cheers,
vishy
about 7 months ago
@vishy
Good Idea, I didnt think of using custom fields like that, mind if I write the script as a follow up post ?
Alan
about 7 months ago
Hi Alan,
That will be great, I’ll look forward for an update script.
Thanks and Regards,
Vishy
about 7 months ago
Hi,
I have been looking for something like this for a while, However I do not have vcentre and connect to my ESXi hosts directly. Unfortunately I have no PowerCLI experience. Can anyone offer any help as to how I would change this to talk to the ESXi hosts directly and not to Vcentre.
Many Thanks
Chris
about 5 months ago
Have a look at my article for free ESXi at http://www.techhead.co.uk/how-to-automatically-shut-down-vmware-esxi-gracefully-during-power-failure-using-an-apc-ups
about 5 months ago
Very cool post, I like it alot
about 4 months ago
Very cool! Only problem I came across is that we have lots of VM’s that are already shutdown or suspended. We also wanted to make the script suspend the VM’s instead of shutting them off. Pretty easy to implement both those changes:
# For each of the VMs on the ESX hosts
Foreach ($VM in ($ESXSRV | Get-VM | Where { $_.PowerState -eq “poweredOn” } )){
# Suspend the guests cleanly
$VM | Suspend-VM -Confirm:$false
about 3 months ago
In response #2 it was discused to have a priority setting of some kind to have some VM’s shutdown before others. How would one do this, we want to make sure out DC’s go down last.
I have tested your script and it works great other then this one item, thanks.
Jesse
about 3 months ago
Hello.
I am new to the vmware and powershell. I have just a small family server which is still very important for me. I am using Vmware esxi. It is now set so that when I manually shutdown the host, it waits till guests get shutdown. The order which system is starting first and shutting last is set in configuratin. As I understand the script, it shutdowns the guests first. Is there any possibility just to tell esxi to shutdown so that it uses it’s own configuration? It must be set from Windows machine and it needs to be set a reaction on some event. Scheduled task is running and when some conditions will occure I need the task to send shutdown. Is it even possible?
Thank you
Jan
about 3 months ago
Great script! There is indeed not that much information on automated full environment shutdowns out there. Has one of the priority-based scripts already found its way to the public somewhere?
Before using this script one might want to double-check for VMs with a missing VMware Tools installation. Just had a customer with mostly Linux VMs where many VMs simply didn’t have the Tools installed and thus the graceful guest shutdown wouldn’t work. Either use vCheck or something like following snippet:
$VMS_WITHOUT_TOOLS = ( get-view -viewtype virtualmachine `
-filter @{ “Guest.ToolsStatus” = “toolsNotInstalled”; “Runtime.PowerState” = “poweredOn” } `
-property Name )
if ($VMS_WITHOUT_TOOLS) {
write-host “These VMs are missing VMware Tools, Shutdown-VMGuest won’t work for them”
$TOOLS_MISSING_ON | %{ write-host “-” $_.Name }
}
Sebastian
P.S.: Perl SDK users might want to check out William’s ghettoUPSHostShutdown.pl too: http://communities.vmware.com/docs/DOC-11902
about 2 months ago
Have you had time/opportunity to figure out how this script could be adjusted to even partially work when the vCenter server is a VM??
That is, perhaps one can/should set this up to work only with the hosts that do not contain the vCenter Server, and let the UPS etc. manage the host containing vCenter Server?? It could be assumed the SAN will simply power on…
Or set things to shut down all VMs but vCenter and then go from there etc.??
I am new to PowerShell and HA so I cannot yet offer much in this regard…I know most of us VMware admins stand on the shoulders of giants like you.
Thank you, Tom