Sequential Starting of a List of VMs
In my lab environment, I often want to start a list of virtual machines, but without taxing the system in the process by starting them all at the same time. I could do that manually, but that’s no fun.
Here’s a short function I wrote to sequentially start a list of virtual machines - the script will start a VM and wait for that VM to boot before starting the next VM. You can optionally also wait additional time before starting the next VM to give the first one some time to finish starting it’s services etc.
This version currently supports Hyper-V only. The script does not currently return anything, but has a number of parameters:
- ComputerName - the name of the Hyper-V host. Specify “.” for the local machine (without quotes)
- VM - specify a comma separated list of VMs
- Wait - the number of seconds to wait between starting a VM after the previous VM. Specify the number of VMs as a number (integer) only. This will default to 180 seconds
- ShowProgress - Specify whether to show progress while starting the VMs. This is cosmetic only, but does give some indication as to how far through the boot process the script is.
- Other standard parameters such as Verbose are supported.
Function Start-SequentialVMs {
<#
.SYNOPSIS
Starts a list of VMs.
.DESCRIPTION
This function starts a list of VMs sequentially. It will wait until a VM is booted, optionally pause for a number of seconds, before starting the next VM.
.PARAMETER ComputerName
Specifies the Hyper-V host to start the VM on.
.PARAMETER VM
Specifies a list of VMs to start.
.PARAMETER Wait
Specifies a number of seconds to wait after the previous VM has booted successfully. Defaults to 180 seconds.
.PARAMETER ShowProgress
Specified whether to show progress as VMs are started.
.EXAMPLE
Start-SequentialVMs -ComputerName hyperv1 -VMList "sql1", "pvs1", "xd71" -Wait 20
.NOTES
.LINK
#>
param(
[Parameter(Mandatory=$true, Position=0,HelpMessage="Hyper-V host.")]
[string]$ComputerName = $(throw = "Please specify a remote Hyper-V host to start VMs on."),
[Parameter(Mandatory=$true, Position=1,HelpMessage="List of VMs to start.")]
[string[]]$VMList = $(throw = "Please specifiy a list of VMs to start"),
[Parameter(Mandatory=$false)]
[int]$Wait = 180,
[Parameter(Mandatory=$false)]
[bool]$ShowProgress
)
# Connect to Hyper-V host before attempting to start VMs. Stop script if unable to connect
Write-Verbose "Connecting to VM host."
Get-VMHost -ComputerName $ComputerName -Verbose $False -ErrorAction Stop
# Start progress at 0
$Percent = 0
# Step through list of provided VMs
ForEach ( $vm in $VMList ) {
# Convert current location in list of VMs to a percentage
$Percent = ($VMList.IndexOf($vm)/$VMList.Count) * 100
# Show progress if specified on the command line
If ($ShowProgress -eq $True) { Write-Progress -Activity "Starting VMs." -Status "Starting VM $vm." -PercentComplete $Percent }
# Get status for current VM
Remove-Variable currentVM -ErrorAction SilentlyContinue
Write-Verbose "Getting status for VM $vm..."
$currentVM = Get-VM -ComputerName $ComputerName -Name $vm -ErrorAction SilentlyContinue
# If the VM exists, then power it on if it is in an Off state
If ($currentVM.Length -gt 0) {
If ($currentVM.State -eq "Off" ) {
Start-VM -ComputerName $ComputerName -Name $vm -Verbose
# Wait for VM to boot and report a heartbeat
Write-Verbose "Waiting for VM heartbeat."
Do {
Start-Sleep -milliseconds 100
} Until ((Get-VMIntegrationService $currentVM | ?{$_.name -eq "Heartbeat"}).PrimaryStatusDescription -eq "OK")
# Wait the specified number of seconds before booting the next VM, unless this is the last VM in the list
If ($Wait -gt 0 -and $VMList.IndexOf($vm) -lt ($VMList.Count-1)) {
Write-Verbose "Waiting for $Wait seconds before starting next VM."
Start-Sleep -Seconds $Wait
}
} Else {
Write-Verbose "VM $vm already running."
}
} Else {
Write-Error -Message "Unable to find VM $vm on host $ComputerName." -Category ObjectNotFound
}
}
Write-Verbose "Started VMs."
# Show progress if specified on the command line
If ($ShowProgress -eq $True) { Write-Progress -Activity "Starting VMs." -Status "Started all VMs." -PercentComplete 100 }
Start-Sleep -Seconds 1
}
Save the script as Start-SequentialVMs.ps1 and run it or add the function to your PowerShell profile so that the function is available when starting PowerShell. Use Get-Help to see the full syntax and examples from within a PowerShell window.