VMware Cloud Community
ganapa2000
Hot Shot
Hot Shot
Jump to solution

Exclude VM from file and Shutdown VM based on ESXi Host

Hi,

I am trying shutdown VM based on ESXi hosts and want to exclude few Infra Servers based on the exclude VM file list.

Let me know, if this good or needs any modification

$list = Import-Csv ".\myexclude.csv"

$maxTime = 10
$maxRun = 5
$vms = [System.Collections.ArrayList]@()
foreach ($entry in $list) {[string[]]$exclude+= Get-VM -Name $entry.Name}
Get-VMHost "myhost" | Get-VM | Where-Object {$_.powerstate -eq 'PoweredOn' -and $exclude -notcontains $_.Name} |
ForEach-Object -Process {
$vms.Add($_.Name)

 

$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()
}
while ($vms.Count -ge $maxRun) {
Get-VM -Name $vms | where { $_.PowerState -eq 'PoweredOff' } | ForEach-Object {
$vms.Remove($_.Name)
}
Start-Sleep 5
}
}
Write-Host "all vms shutdown completed"

0 Kudos
1 Solution

Accepted Solutions
LucD
Leadership
Leadership
Jump to solution

Assuming the myexclude.csv contains a column named Name, you can add a -notcontains to the Where-clause.
Something like this for example

$list = Import-Csv -Path ".\myexclude.csv" -UseCulture

$maxTime = 10
$maxRun = 5
$vms = [System.Collections.ArrayList]@()

Get-VMHost "myhost" | Get-VM | Where-Object { $_.powerstate -eq 'PoweredOn' -and $list.Name -notcontains $_.Name } |
    ForEach-Object -Process {
        $vms.Add($_.Name)

        $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()
        }
        while ($vms.Count -ge $maxRun) {
            Get-VM -Name $vms | where { $_.PowerState -eq 'PoweredOff' } | ForEach-Object {
                $vms.Remove($_.Name)
            }
            Start-Sleep 5
        }
    }
Write-Host "all vms shutdown completed"

  


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

View solution in original post

0 Kudos
4 Replies
LucD
Leadership
Leadership
Jump to solution

Assuming the myexclude.csv contains a column named Name, you can add a -notcontains to the Where-clause.
Something like this for example

$list = Import-Csv -Path ".\myexclude.csv" -UseCulture

$maxTime = 10
$maxRun = 5
$vms = [System.Collections.ArrayList]@()

Get-VMHost "myhost" | Get-VM | Where-Object { $_.powerstate -eq 'PoweredOn' -and $list.Name -notcontains $_.Name } |
    ForEach-Object -Process {
        $vms.Add($_.Name)

        $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()
        }
        while ($vms.Count -ge $maxRun) {
            Get-VM -Name $vms | where { $_.PowerState -eq 'PoweredOff' } | ForEach-Object {
                $vms.Remove($_.Name)
            }
            Start-Sleep 5
        }
    }
Write-Host "all vms shutdown completed"

  


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

0 Kudos
ganapa2000
Hot Shot
Hot Shot
Jump to solution

LucD,

What is this purpose of below Add and Remove does ?

 ForEach-Object -Process {
        $vms.Add($_.Name)

 

while ($vms.Count -ge $maxRun) {
            Get-VM -Name $vms | where { $_.PowerState -eq 'PoweredOff' } | ForEach-Object {
                $vms.Remove($_.Name)

 

0 Kudos
LucD
Leadership
Leadership
Jump to solution

That is to keep track of the VMs that are being stopped and shutdown.
The last While loop checks those VMs in a loop till they are effectively powered off.
If they are, they are removed from the list.
The number of items (VM names) in the list is used to limit the number of VMs that are bing powered off or shutdown


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

0 Kudos
ganapa2000
Hot Shot
Hot Shot
Jump to solution

Thank you very much LucD. I will try this tomorrow and update you 🙂

0 Kudos