PowerCLI Script to Shutdown My Home Lab

December 14, 2011 in vHersey, VMware

Ran across a PowerCLI script that can be used to shutdown your virtual infrastructure written by Alan Renouf and thought it would be pretty handy to use to automate shutting down my home lab.

The original script attempts to shutdown VMs “cleanly” using Shutdown-VMGuest. Shutdown-VMGuest attempts to shutdown the VMs OS and requires that VM Tools be installed and running. Most of the VMs in my lab are running Damn Small Linux (DSL) and do not have VM tools installed so this would not work and it would shutdown the host without shutting down the VMs first. Not really a big deal but I wanted to make the process just a bit cleaner.

I changed the script to first shutdown VMs that are powered on and have VM tools running. It then waits $waittime in seconds and uses Stop-VM to forcefully power off any remaining powered on VMs. As in the original script it then waits $waittime or until no VMs are powered on to shutdown the ESXi hosts.

Connect-VIServer MyVIServer

# Set the amount of time to wait before assuming the remaining powered on guests are stuck
$waittime = 60 #Seconds

# Get All the ESX Hosts
$ESXSRV = Get-VMHost

# For each of the powered on VMs with running VM Tools
Foreach ($VM in ($ESXSRV | Get-VM | Where {$_.PowerState -eq "poweredOn" -and $_.Guest.State -eq "Running"})){
    # Shutdown Guest
    write-host "Shutting down $VM"
    $VM | Shutdown-VMGuest -Confirm:$false
}

Write-host "Pausing for $waittime seconds to allow VMs to shutdown cleanly"
sleep $waittime

#Force Poweroff of any VMs still running
Foreach ($VM in ($ESXSRV | Get-VM | Where {$_.PowerState -eq "poweredOn"})){
      # Power off Guest 
      write-host "Powering off $VM"
      $VM | Stop-VM -Confirm:$false
}

$Time = (Get-Date).TimeofDay
do {
    # Wait for the VMs to poweroff
    sleep 1.0
    $timeleft = $waittime - ($Newtime.seconds)
    $numvms = ($ESXSRV | Get-VM | Where { $_.PowerState -eq "poweredOn" }).Count
    Write-host "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
Write-host "Shutting down hosts"
$ESXSRV | Foreach {Get-View $_.ID} | Foreach {$_.ShutdownHost_Task($TRUE)}

Write-Host "Shutdown Complete"

To use the script just change MyVIServer in line 1 to be the IP address or hostname of you vCenter server. Set $waittime at line 4 to be the number of seconds to wait before forcefully powering off VMs. The $waittime may need to be increased depending on the speed of your lab and the number of VMs that are shutting down. Run the script as you would any other PowerCLI script.

It is probably not completely necessary to force the shutdown of all VMs before shutting down the hosts. They will be shutdown when the host they are running on is shutdown. It just gave me some PowerCLI practice and it works.

Be EXTREMELY careful with this script. When you run it all VMs and Host managed by the vCenter you are connecting to will be shutdown!

DO NOT RUN THE SCRIPT AGAINST YOUR vCENTER SERVER IF YOU DO NOT WANT TO SHUTDOWN VMs!

Thanks again to Alan Renouf for the original script which can be found at http://www.virtu-al.net/2010/01/06/powercli-shutdown-your-virtual-infrastructure/.

If you found this script useful or have other ideas for improvements post to the comments.