Since the Scheduled Tasks in vCenter ain’t exportable, I went ahead and wrote a rather simple script, which lets me do this in Windows own Task Scheduler. What this script does, is initiate a graceful shutdown and if the VM isn’t shutdown within 60 seconds (12 * 5 seconds) it simply powers the VM off and immediately after that powers it back on.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
param( [string] $vCenter, [string] $VMname )

# Add the VI-Snapin if it isn't loaded already
if ( (Get-PSSnapin -Name "VMware.VimAutomation.Core" -ErrorAction SilentlyContinue) -eq $null )
{
	Add-PSSnapin -Name "VMware.VimAutomation.Core"
}

If ( !($vCenter) -or !($VMname) )
{
	Write-Host
	Write-Host "vm-reboot: <vcenter-server> <VMname>"
	Write-Host
	Write-Host "   <vcenter-server>  - DNS name of your vCenter server."
	Write-Host "   <VMname>          - Display name of the VM in this vCenter server."
	Write-Host
	exit 1
}

Connect-VIServer -Server $vCenter

$VM = Get-VM $VMname

# First, try shutting down the virtual machine gracefully
Write-Host "Stopping VM $( $VM )"
Write-Host "   - Graceful shutdown"
Shutdown-VMGuest -VM $VM -Confirm:$false
$VM = Get-VM $VMname

$i = 0
While ($VM.PowerState -ne "PoweredOff") {
	# If that doesn't work, break out the hammer and just kill it
	if ( $i -gt 12 ) {
		Write-Host "  - Forced shutdown"
		Stop-VM -VM $VMname -Confirm:$false
	}

	Start-Sleep -Seconds 5
	$VM = Get-VM $VMname
	$i++
}

If ($VM.PowerState -eq "PoweredOff") {
	Write-Host "Starting VM $( $VM )"
	Start-VM -VM $VM -Confirm:$false >$NULL
}

Disconnect-VIServer -server $vCenter -Confirm:$false

Before this implementation in PowerCLI, I needed three tasks for each VM that was to be scheduled. And when migrating vCenters (and I usually do an empty install) vCenter’s scheduled tasks are not exportable, thus you need to re-create the tasks on the new vCenter by yourself again, which for more than four virtual machines is really a pain in the ass …

Update: well, found an error that caused shit not to work … Basically Stop-VM also needs the object for $VMname, otherwise the whole point of waiting for the VM to be stopped is kinda moot (seeing as Stop-VM never stops obsessing about not having a Get-VM object or a VM name to work with).