We’re currently thinking about automating Windows Updates and the involved disaster snapshot-copy to a degree, where we don’t need to intervene anymore.

Right now, we already have a rudimentary scheduler in place, which does the reboots for some (200 ..) systems already. Now, we’d like to extend it to also cover the bi-weekly Windows Update spree.

Since PowerShell (and PowerCLI) work quite well with vSphere automation, I cooked up the below script to first shutdown a virtual machine (for snapshot consistency reasons), then take a snapshot and power on the virtual machine again afterwards.

 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
# LICENSE:     GNU General Public License v2
# COPYRIGHT:   Copyright 2010 Christian Heim

if ($args.length -lt 1) {
    Write-Host
    Write-Host "  OfflineSnapshot.ps1 "
    Write-Host
    Write-Host "       - Name of the virtual machine."
    Write-Host "                  Please be aware: This script uses the supplied name to shutdown a virtual machine."
    Write-Host "                  Make sure, that a) the name is unique before using this script and b) don't blame me"
    Write-Host
    exit 1
}

$vcenter = "vcenter.home.barfoo.org"

# 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"
}

Connect-VIServer -server $vcenter >$NULL 2>&1

$VMname = $args[0]
$VMname = "$VMname*"
$VM = Get-VM $VMname

Shutdown-VMGuest -VM $VM -Confirm:$false >$NULL 2>&1
$VM = Get-VM $VMname

# Need to loop here, since Shutdown-VMGuest is asynchronous, meaning it returns after
# the command has been sent, instead of returning when the VM is powered off!
While ($VM.PowerState -ne "PoweredOff") {
    Start-Sleep -Seconds 5
    $VM = Get-VM $VMname
}

$fulltime = Get-Date -f "F"
$VM | New-Snapshot -Name ( Get-Date -f "d" ) -Description "Automatic snapshot for Windows-Updates, dated $fulltime" >$NULL
Start-Sleep -Seconds 5 >$NULL
Start-VM -VM $VM -Confirm:$false >$NULL