Site icon Digital Thought Disruption

Bulk VM Operations with PowerCLI: Power States, Snapshots, Tags, and Migrations

Introduction

Managing hundreds, or thousands, of VMs requires automation that is repeatable, predictable, and safe. PowerCLI allows you to apply changes across the fleet with confidence, reducing risk and saving time.

In this article, you’ll learn how to:


My Personal Repository on GitHub

VMware Repository on GitHub


Bulk Power Operations

Power Off All VMs in a Folder

$folder = Get-Folder -Name "Dev"
Get-VM -Location $folder | Stop-VM -Confirm:$false

Power On All VMs on a Host

Get-VMHost -Name "esxi03.lab.local" | Get-VM | Start-VM

Power Off VMs Gracefully by OS Type

Get-VM | Where-Object {$_.Guest.OSFullName -like "*Windows*"} | Stop-VMGuest -Confirm:$false

Snapshot Automation

Take Snapshot for All Running VMs

Get-VM | Where-Object {$_.PowerState -eq "PoweredOn"} | ForEach-Object {
New-Snapshot -VM $_ -Name "PreChange-$(Get-Date -Format yyyyMMdd-HHmm)" -Description "Snapshot before updates"
}

Remove Snapshots Older Than 7 Days

Get-VM | Get-Snapshot | Where-Object {$_.Created -lt (Get-Date).AddDays(-7)} | Remove-Snapshot -Confirm:$false

Tagging and Annotations

Assign Tag to All VMs in a Resource Pool

$pool = Get-ResourcePool -Name "Production"
$tag = Get-Tag -Name "Backup-Enabled"
Get-VM -Location $pool | New-TagAssignment -Tag $tag

Bulk Update VM Notes

Get-VM | Where-Object {$_.Name -like "*App*"} | Set-VM -Notes "Application server - reviewed 2025-07"

Storage vMotion: Moving VMs Between Datastores

Move all powered-off VMs from one datastore to another.

$source = Get-Datastore -Name "DS1"
$dest = Get-Datastore -Name "DS2"

Get-VM | Where-Object {
$_.PowerState -eq "PoweredOff" -and
($_.ExtensionData.Config.DatastoreUrl -match $source.Name)
} | Move-VM -Datastore $dest

Use with caution: Validate I/O impact and available space.


Custom Ordered Shutdown / Startup Sequences

Power off based on naming or application tier.

$orderedList = "DB-", "App-", "Web-"

foreach ($prefix in $orderedList) {
Get-VM | Where-Object {$_.Name -like "$prefix*"} | Stop-VMGuest -Confirm:$false
Start-Sleep -Seconds 10
}

Reverse the list for startup logic.


Diagram: Bulk VM Lifecycle Management


Error Handling & Common Issues

ScenarioFix
Snapshot creation fails on encrypted VMsCheck encryption policy and VM version compatibility
Stop-VMGuest hangsEnsure VMware Tools is running; fallback to Stop-VM if needed
Storage move fails due to lockVerify VM is powered off and not in backup state
Tag not found or duplicatedUse Get-Tag -Name 'TagName' and validate tag category assignment

Use Case Example: Pre-Maintenance VM Handling

Before host patching:

PowerCLI snippet:

$criticalVMs = Get-VM | Where-Object {$_.Name -match "SQL|Exchange"}
$criticalVMs | New-Snapshot -Name "PrePatch" -Description "Pre-maintenance snapshot"
$criticalVMs | Stop-VMGuest -Confirm:$false

What’s Next

In the next article, we’ll cover:

Exit mobile version