7 Replies Latest reply on Jun 18, 2010 8:13 AM by RvdNieuwendijk

    Shutdown infrastructure on power outage

    AntonVZhbankov Guru
    vExpertUser Moderators

      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

      http://blog.vadmin.ru

        • 1. Re: Shutdown infrastructure on power outage
          LucD Guru
          Community WarriorsvExpertUser Moderators

          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

          1 person found this helpful
          • 2. Re: Shutdown infrastructure on power outage
            RvdNieuwendijk Virtuoso
            vExpertUser Moderators

            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

            1 person found this helpful
            • 3. Re: Shutdown infrastructure on power outage
              AntonVZhbankov Guru
              User ModeratorsvExpert

              >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

              http://blog.vadmin.ru

              • 4. Re: Shutdown infrastructure on power outage
                RvdNieuwendijk Virtuoso
                vExpertUser Moderators

                And it makes the script at least (number of hosts -1) * 360 seconds faster.

                • 5. Re: Shutdown infrastructure on power outage
                  AntonVZhbankov Guru
                  User ModeratorsvExpert

                  Robert, you're absolutely right.

                   

                  But what would you suggest for vCenter in VM?


                  ---

                  MCSA, MCTS Hyper-V, VCP 3/4, VMware vExpert

                  http://blog.vadmin.ru

                  • 6. Re: Shutdown infrastructure on power outage
                    LucD Guru
                    Community WarriorsUser ModeratorsvExpert

                    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

                    • 7. Re: Shutdown infrastructure on power outage
                      RvdNieuwendijk Virtuoso
                      vExpertUser Moderators

                      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