Let's suppose we have dedicated Windows host with UPS monitoring hardware and we can run PowerCLI script on UPS event.
For physical vCenter I wrote some script:
Get-VMHost | ForEach-Object { $myOnVMs = (Get-VM | Where-Object {$_.PowerState -eq "PoweredOn"}) $myOnVMs | Shutdown-VMGuest Start-Sleep -Seconds 300 $myOnVMs = (Get-VM | Where-Object {$_.PowerState -eq "PoweredOn"}) $myOnVMs | Stop-VM -RunAsync Start-Sleep -Seconds 60 Set-VMHost -vmhost $_ -state maintenance Stop-VMHost -vmhost $_ -RunAsync }
Any thoughts, comments, additions?
---
MCSA, MCTS Hyper-V, VCP 3/4, VMware vExpert
Could be a bit shorter by dropping the variables.
Perhaps you could include in the first Where-Object a condition to check if VMware Tools are installed.
Get-VMHost | ForEach-Object { Get-VM | Where-Object {$_.PowerState -eq "PoweredOn" -and $_.Guest.State -eq "Running"} | Shutdown-VMGuest Start-Sleep -Seconds 300 Get-VM | Where-Object {$_.PowerState -eq "PoweredOn"} | Stop-VM -RunAsync Start-Sleep -Seconds 60 Set-VMHost -vmhost $_ -state maintenance Stop-VMHost -vmhost $_ -RunAsync }
____________
Blog: LucD notes
Twitter: lucd22
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
I would do it like this:
Get-VM | Where-Object {$_.PowerState -eq "PoweredOn"} | Shutdown-VMGuest Start-Sleep -Seconds 300 Get-VM | Where-Object {$_.PowerState -eq "PoweredOn"} | Stop-VM -RunAsync Start-Sleep -Seconds 60 Get-VMHost | ForEach-Object { Set-VMHost -vmhost $_ -state maintenance Stop-VMHost -vmhost $_ -RunAsync }
The main change is that I removed the stopping of the VM's from the VMHost loop. As you have to stop the VM's only once and not for every host.
Regards, Robert
>The main change is that I removed the stopping of the VM's from the VMHost loop
Thanks, it makes sense. And helps to avoid problems if DRS migrate new VMs to host with powered off VMs.
---
MCSA, MCTS Hyper-V, VCP 3/4, VMware vExpert
And it makes the script at least (number of hosts -1) * 360 seconds faster.
Robert, you're absolutely right.
But what would you suggest for vCenter in VM?
---
MCSA, MCTS Hyper-V, VCP 3/4, VMware vExpert
If your vCenter runs in a VM, you would probably be better of to connect to the ESX(i) servers one-by-one.
If you need to keep your vCenter running till last, you can look at my Counter the self-aware VUM post to see how you can find the vCenter.
____________
Blog: LucD notes
Twitter: lucd22
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
You are right. I didn't think about the vCenter Server running as a VM. But while thinking about that, it is also possible that you are running the database server used by the vCenter server as a VM. And we have the need to sometimes shutdown only one cluster, so I wanted to be able to specify a cluster name. It is possible that the vCenter Server or the database server or both are running on that cluster. So I made a new script that handles this all. I have tested this script in my test environment. But it has only one cluster and one ESX 3.5 server in that cluster. It has five VM's, the vCenter Server and the vCenter database server included. So I was not able to test all scenario's. But I have a good confidence that it will work in other scenario's as well.
<# .SYNOPSIS This PowerCLI script stops all virtual machines and ESX servers. .DESCRIPTION If you specify the ClusterName parameter only this cluster will be stopped. You might run the vCenter Server or it's database server or both as a VM. In that case you have to specify their virtual machine names if they are running in the environment that has to be stopped. .PARAMETER VIServerName Specify the name of the vCenter Server if this is running as a virtual machine on the environment that will be stopped. .PARAMETER DBServerName Specify the name of the vCenter Server it's database server if this is running as a VM on the environment that will be stopped. .PARAMETER ClusterName Specify a cluster name if only this cluster has to be stopped. .NOTES This script requires PowerShell v2 and PowerCLI. .EXAMPLE ./Stop-vSphere -VIServerName vCenter -DBServername SQLserver -Cluster MyCluster Stops all VM's and all ESX servers of the MyCluster cluster. #> param ([string] $VIServerName, [string] $DBServerName, [string] $ClusterName) Set-StrictMode -Version 2.0 function Get-VMHostName { <# .SYNOPSIS Returns the host name of a virtual machine. .DESCRIPTION Returns the host name of a virtual machine. .PARAMETER Name Specify the name of a virtual machine. .EXAMPLE Get-VMHostName -Name MyVM Returns the host name of the MyVM virtual machine. #> param ([parameter(Mandatory=$true)][string] $Name) $VM = Get-VM -Name $Name if ($VM) { $VM.Host.Name } } function Stop-VMOnVMHost { <# .SYNOPSIS Stops a virtual machine while connected to the ESX server where the virtual machine is running. .DESCRIPTION Stops a virtual machine while connected to the ESX server where the virtual machine is running. .PARAMETER Name Specify the name of a virtual machine. .PARAMETER VMHostName Specify the name of the ESX server on which the virtual machine is running. .PARAMETER Credential Specify a PSCredential object that contains credentials for authenticating with the server. .EXAMPLE Stop-VMOnVMHost -Name MyVM -VMHostName ESX1 -Credential (Get-Credential) Stops the virtual machine MyVM while connected to ESX1. #> param ([parameter(Mandatory=$true)][string] $Name, [parameter(Mandatory=$true)][string] $VMHostName, [parameter(Mandatory=$true)][http://System.Management.Automation.PSCredential|http://System.Management.Automation.PSCredential] $Credential) Write-Debug "Connecting to $VMHostName" Connect-VIServer -Server $VMHostName -Credential $Credential # Stop the VM $VM = Get-VM -Name $Name | Where-Object {$_.PowerState -eq "PoweredOn" -and $_.Guest.State -eq "Running"} if ($VM) { Write-Debug "Shutting down the $Name server" $VM | Shutdown-VMGuest -Confirm:$False Write-Debug "Waiting 300 Seconds" Start-Sleep -Seconds 300 } $VM = Get-VM -Name $Name | Where-Object {$_.PowerState -eq "PoweredOn"} if ($VM) { Write-Debug "Stopping the $Name VM" $VM | Stop-VM -Confirm:$False Write-Debug "Waiting 60 Seconds" Start-Sleep -Seconds 60 } } function Stop-VMHostOnVMHost { <# .SYNOPSIS Stops an ESX server while connected to that ESX server. .DESCRIPTION Stops an ESX server while connected to that ESX server. .PARAMETER Name Specify the name of an ESX server. .PARAMETER Credential Specify a PSCredential object that contains credentials for authenticating with the server. .EXAMPLE Stop-VMHostOnVMHost -Name ESX1 -Credential (Get-Credential) Stops ESX server ESX1 while connected to ESX1. #> param ([parameter(Mandatory=$true)][string] $Name, [parameter(Mandatory=$true)][http://System.Management.Automation.PSCredential|http://System.Management.Automation.PSCredential] $Credential) Write-Debug "Connecting to host $Name" Connect-VIServer -Server $Name -Credential $HostCredential Write-Debug "Setting host $Name in maintenance mode" Set-VMHost -VMHost $Name -State Maintenance -Confirm:$False Write-Debug "Stopping the host $Name" Stop-VMHost -VMHost $Name -Confirm:$False -RunAsync } # Disable debugging # $DebugPreference = "SilentlyContinue" # Enable debugging $DebugPreference = "Continue" # Get the cluster if ($ClusterName) { $Cluster = Get-Cluster -Name $ClusterName } # Get the host credential "Type username and password for a host in the credentials box" $HostCredential = Get-Credential # Find the vCenter server it's host name if ($VIServerName) { $vcHostName = Get-VMHostName -Name $VIServerName } # Find the vCenter database server it's host name if ($DBServerName) { $dbHostname = Get-VMHostName -Name $DBServerName } # Shutdown all guests except the vCenter Server and the database server if ($Cluster) { $myOnVMs = $Cluster | Get-VM | Where-Object {$_.Name -ne $VIServerName -and $_.Name -ne $DBServerName -and $_.PowerState -eq "PoweredOn" -and $_.Guest.State -eq "Running"} } else { $myOnVMs = Get-VM | Where-Object {$_.Name -ne $VIServerName -and $_.Name -ne $DBServerName -and $_.PowerState -eq "PoweredOn" -and $_.Guest.State -eq "Running"} } if ($myOnVMs) { Write-Debug "Shutting down guests" $myOnVMs | Shutdown-VMGuest -Confirm:$False Write-Debug "Waiting 300 Seconds" Start-Sleep -Seconds 300 } # Stop all VM's except the vCenter Server and the database server if ($Cluster) { $myOnVMs = $Cluster | Get-VM | Where-Object {$_.Name -ne $VIServerName -and $_.Name -ne $DBServerName -and $_.PowerState -eq "PoweredOn"} } else { $myOnVMs = Get-VM | Where-Object {$_.Name -ne $VIServerName -and $_.Name -ne $DBServerName -and $_.PowerState -eq "PoweredOn"} } if ($myOnVMs) { Write-Debug "Stopping VM's" $myOnVMs | Stop-VM -Confirm:$False -RunAsync Write-Debug "Waiting 60 Seconds" Start-Sleep -Seconds 60 } # Stop all hosts except the ones running the vCenter Server and the database server if ($Cluster) { $MyHosts = $Cluster | Get-VMHost | Where-Object {$_.Name -ne $vcHostName -and $_.Name -ne $dbHostName} } else { $MyHosts = Get-VMHost | Where-Object {$_.Name -ne $vcHostName -and $_.Name -ne $dbHostName} } If ($MyHosts) { $MyHosts | ForEach-Object { Write-Debug "Setting host $_ in maintenance mode" Set-VMHost -VMHost $_ -State Maintenance -Confirm:$False Write-Debug "Stopping host $_" Stop-VMHost -VMHost $_ -Confirm:$False -RunAsync } } Disconnect-VIServer * -Confirm:$false if ($vcHostName) { # Check if the vCenter Server it's host is in the cluster if ($Cluster) { $vcHost = $Cluster | Get-VMHost -Name $vcHostName } else { $vcHost = Get-VMHost -Name $vcHostName } } if ($dbHostName) { # Check if the database server it's host is in the cluster if ($Cluster) { $dbHost = $Cluster | Get-VMHost -Name $dbHostName } else { $dbHost = Get-VMHost -Name $dbHostName } } if ($vcHost) { # Stop the vCenter Server on it's host Stop-VMOnVMHost -Name $VIServerName -VMHostName $vcHostName -Credential $HostCredential } if ($dbHost) { # Stop the database server on it's host Stop-VMOnVMHost -Name $DBServerName -VMHostName $dbHostName -Credential $HostCredential } if ($vcHost) { # Stop the host running the vCenter Server Stop-VMHostOnVMHost -Name $vcHostName -Credential $HostCredential } if ($dbHost -and ($vcHostName -ne $dbHostName)) { # Stop the host running the database server Stop-VMHostOnVMHost -Name $dbHostName -Credential $HostCredential }
As the script uses square brackets and the forum software has problems with them, I also attach the script so you can download it.
Message was edited by: RvdNieuwendijk