VMware Cloud Community
vin01
Expert
Expert
Jump to solution

vms shutdown and update once completed

Can someone help me on this script.

I am trying to shutdown all the vms and update after power state changes poweredoff for all vms.

There are certain conditions like Shutdown-VMGuest is initiated for vms where tools status ok but guest os is not responding to shutdown so in that condition I should do stop-vm.

so not clear till what time I should wait to do force shutdown

Is there any way to check the status the status of those vms (Like any change in vmtools status when Shutdown-VMGuest is initiated)

Get-VM | Where-Object { $_.powerstate -eq 'PoweredOn' -or $_.PowerState -eq 'suspended' }| ForEach-Object -Process {

     if($_.ExtensionData.Guest.ToolsRunningStatus -eq "GuestToolsNotRunning"){

        Stop-VM -VM $_ -Confirm:$false -RunAsync

    }

    else{

        Shutdown-VMGuest -VM $_ -Confirm:$false

   }

}

while(Get-VM | Where-Object { $_.powerstate -eq 'PoweredOn' -or $_.PowerState -eq 'suspended'}){

Start-Sleep 5

}

Write-Host "all vms shutdown completed"

Regards Vineeth.K
1 Solution

Accepted Solutions
LucD
Leadership
Leadership
Jump to solution

Try something like this.

It will use a Shutdown-VMGuest when the VMware Tools are running otherwise it will do a Stop-VM.

If a Shutdown-VMGuest was done and a defined interval is passed, it will still do a Stop-VM.

$maxTime = 300

Get-VM | Where-Object { $_.powerstate -eq 'PoweredOn' -or $_.PowerState -eq 'suspended' } |

ForEach-Object -Process {

    $triedStop = $false

    $triedGuest = $false

    $now = Get-Date


    while ($_.ExtensionData.Runtime.PowerState -ne [Vmware.Vim.VirtualMachinePowerState]::poweredOff -and -not $triedStop) {

        if ($_.ExtensionData.Guest.ToolsRunningStatus -eq "GuestToolsRunning" -and -not $triedGuest) {

            Shutdown-VMGuest -VM $_ -Confirm:$false

            $triedGuest = $true

        } else {

            if (($triedGuest -and (New-TimeSpan -Start $now -End (Get-Date)).TotalSeconds -gt $maxTime) -or -not $triedStop) {

                Stop-VM -VM $_ -Confirm:$false -RunAsync

                $triedStop = $true

            }

        }

        Start-Sleep 5

        $_.ExtensionData.UpdateViewData()

    }

}


Write-Host "all vms shutdown completed"


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

View solution in original post

8 Replies
LucD
Leadership
Leadership
Jump to solution

Try something like this.

It will use a Shutdown-VMGuest when the VMware Tools are running otherwise it will do a Stop-VM.

If a Shutdown-VMGuest was done and a defined interval is passed, it will still do a Stop-VM.

$maxTime = 300

Get-VM | Where-Object { $_.powerstate -eq 'PoweredOn' -or $_.PowerState -eq 'suspended' } |

ForEach-Object -Process {

    $triedStop = $false

    $triedGuest = $false

    $now = Get-Date


    while ($_.ExtensionData.Runtime.PowerState -ne [Vmware.Vim.VirtualMachinePowerState]::poweredOff -and -not $triedStop) {

        if ($_.ExtensionData.Guest.ToolsRunningStatus -eq "GuestToolsRunning" -and -not $triedGuest) {

            Shutdown-VMGuest -VM $_ -Confirm:$false

            $triedGuest = $true

        } else {

            if (($triedGuest -and (New-TimeSpan -Start $now -End (Get-Date)).TotalSeconds -gt $maxTime) -or -not $triedStop) {

                Stop-VM -VM $_ -Confirm:$false -RunAsync

                $triedStop = $true

            }

        }

        Start-Sleep 5

        $_.ExtensionData.UpdateViewData()

    }

}


Write-Host "all vms shutdown completed"


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

vin01
Expert
Expert
Jump to solution

Its worked I just tested by replacing $maxTime = 300 to 10. However when compared to my orginal script this execution time got increased.

Is it possible check the status once both stop-vm and  Shutdown-VMGuest are initiated on first attempt and then wait for $maxTime = 300 then if still vm is in poweron state the we can do stop-vm.

Regards Vineeth.K
0 Kudos
LucD
Leadership
Leadership
Jump to solution

That is exactly what the script is doing as I see it.

- is the VM powered on and did we not do a Stop-VM?

     - yes

          - are VMware tools running and did we not try a Shutdown-VMGuest yet?

               - yes

                    - do a Shutdown-VMGuest

                    - wait for power off or time expired

               - no

                    - did we try a Shutdown-VMGuest and did the interval expire OR did we not yet do a Stop-VM?

                         - yes

                              - do a Stop-VM

          - wait for powered off

     - no

          - continue

The increase of the execution time might be because the script is trying to do a Shutdown-VMGuest, wait for the timeout and then try a Stop-VM.

In your original script that was not the case as far as I can see it.


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

vin01
Expert
Expert
Jump to solution

Thanks for your explanation LucD.

Right now I have tested on 1000 VMs (Powered on+Suspended)It taken appox 3hr 30mins. However with the earlier script it just taken 2hr appox. (Fortunately those vms which are having tools ok they are responded for  Shutdown-VMGuest cmdlet). Don't know if it will be executed on much larger environment.

My idea is to first execute Shutdown-VMGuest(vmware tools active) & Stop-VM and wait for sometime and if any vms are still in poweron state even though Shutdown-VMGuest cmdlet executed on that vms then script should execute Stop-VM on those Vms. Why I am looking this way because I need to execute on 8000+ vms.

Regards Vineeth.K
0 Kudos
LucD
Leadership
Leadership
Jump to solution

The long duration is partially explained since you are doing everything sequentially.

An option could be to run the script in parallel (via Start-Job), each instance for a specific number of VMs.

Is that an option?


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

vin01
Expert
Expert
Jump to solution

Yeah That works for me. But how to give vc credentials every time from a credential file(.xml)

I will split the vms 500 each and execute multiple jobs.

Any possibility by using  ForEach-Object -Parallel  cmdlet?

Regards Vineeth.K
0 Kudos
LucD
Leadership
Leadership
Jump to solution

In the current PowerCLI release the -Parallel switch is not supported.

The PowerCLI Dev team is working on it.

You can upvote the idea at Support for the PSv7 feature Foreach -Parallel

You can start multiple jobs from a main script.

If you make the connection in the main script, the background jobs can reuse that connection with the SessionId parameter.

See my Running a background job post.


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

0 Kudos
vin01
Expert
Expert
Jump to solution

Ok Thanks LucD.

Regards Vineeth.K
0 Kudos