Tag Archives: SCVMM

Automating SCVMM Patching

Patching. What a pain in the backside it is. It’s bad enough when you just have to look after one or two machines at home. When you have thousands of the things to look after, it can be horrific.

A recent brace of high level, out of band Microsoft security updates has forced me to take a close look at our patching infrastructure at work and make some improvements. Among those improvements was to look at the patching of our Hyper-V hosts. I’m a little ashamed to admit it but I haven’t really looked at patching our virtual hosts since they were installed back in August 2013. This meant that when I went to install those updates, there were another 130 to install with them. Not so good.

We are using System Center Virtual Machine Manager to manage our virtualisation farms. Part of its functionality is keeping your hosts patched. To do so through the UI is a pretty long winded process, you have to add a WSUS server to the SCVMM infrastructure, synchronise SCVMM with WSUS, add any new updates to a baseline, scan the hosts against that baseline to see if they’re compliant and remediate them if they’re not. It’s simple enough but it’s long winded. Unfortunately there is no way to automate this process through the GUI.

However, thanks to PowerShell it can be scripted! I am using this script to mostley automate the process for me:

Import-Module virtualmachinemanager
Import-Module virtualmachinemanagercore

$anonUsername = "anonymous"
$anonPassword = ConvertTo-SecureString -String "anonymous" -AsPlainText -Force
$anonCredentials = New-Object System.Management.Automation.PSCredential($anonUsername,$anonPassword)
$PSEmailServer = "smtp.server.domain"

Get-VMMServer -ComputerName scvmm.domain.com
Start-SCUpdateServerSynchronization -UpdateServer wsus.server.domain

$2012Updates = $(Get-SCUpdate | Where-Object -FilterScript { `
        $_.Products -like "Windows Server 2012" -and `
        $_.IsSuperseded -eq $false -and `
        $_.CreationDate -gt $((Get-Date).AddMonths(-1)) `

$Baseline = New-SCBaseline -Name "$(Get-Date -format y) Updates"
$AddedUpdateList = @()
$2012Updates | foreach {
        $AddedUpdateList += Get-SCUpdate -ID $_.ID

$scope = Get-SCVMHostGroup -Name "Hyper-V" -ID "8db6c432-7326-429d-af6d-8c93d201ca9f"
Set-SCBaseline -Baseline $baseline -AddAssignmentScope $scope -JobGroup "a0bcf812-b866-474b-a69a-13db8f8ec360" -RunAsynchronously
Set-SCBaseline -Baseline $baseline -RunAsynchronously -AddUpdates $addedUpdateList -JobGroup "a0bcf812-b866-474b-a69a-13db8f8ec360" -StartNow

Start-Sleep -Seconds 10

Get-SCVMHostCluster -Name "cluster1.domain.com" | Start-SCComplianceScan
Get-SCVMHostCluster -Name "cluster2.domain.com" | Start-SCComplianceScan

Send-MailMessage -to "helpdesk@domain.com" `
       -from "scvmm@domain.com" `
       -subject "Time to patch the Hyper-V Farms" `
       -Body "Dear IT Support,

Virtual Machine Manager has downloaded the $(Get-Date -format y) updates for the Windows hosts in the Hyper-V clusters. Please ask a member of the team to check the compliance status of the hosts in SCVMM and remediate any problems that are found.


       -priority High `
       -credential $anonCredentials

That script connects to SCVMM, looks for any updates released for Windows Server 2012 in the last month and adds them to a new baseline named after the month. It assigns the new updates to a group called Hyper-V and starts a compliance scan on two clusters. Finally, it emails the helpdesk to let them know that there are new updates to be installed. That’s what the anonymous credentials are in there for, the account that I use to run the script doesn’t have a mailbox so our Exchange server rejects the message when it tries to authenticate using it.

If you’re feeling particularly brave, you can add this to the script:

Get-VMHostCluster -Name ClusterName | Start-SCUpdateRemediation -RemediateAllClusterNodes

That will, in theory, cycle through each of the hosts in your cluster putting them into maintenance mode, migrate the VMs on that host onto another in the cluster, install the updates and reboot them. I say “In theory” because I haven’t managed to get this to work 100% reliably yet.

I then created a scheduled task which runs this script on the second Wednesday of every month.

Anyway, there you have it. Feel free to steal this if you want it but run it at your own risk, I’m not responsible if it does something unfortunate.