Hotfix and updates check of Hyper-V and Cluster with Powershell
I read Hyper-V.nu great blog article about Christian Edwards script that checks both hosts and clusters for hotfixes and updates and found some things I wanted to improve in the script, first of all I wanted an object list instead of just some Write-Host with cool colors.. Then I can use the fabulous techniques of PowerShell to just show the once that I do not have installed or make a decent report for my cluster or just standalone hosts.
The next improvement I thought of was the automatic download of all hotfixes.. Well registering at the web page and downloading each hotfix can work for some but not many, so I extended the XML files with the DownloadURL and also changed the script to support either a host or a cluster object. The download parameter will not check what´s installed or not, it will just download all hotfixes that I found URL´s for so bare with me if it is not complete and make a comment or send me a tweet and I will try to update the xml file
Here you can see how I can run it and also as I have the result as objects filter on installed or not
And here you can see when I check a cluster and also add the parameters for downloading and the path to where the downloaded files shall reside
And here is a screendump of some of the hotfix files that are downloaded, as you can see in the script I utilize the BITS engine to download the files 🙂
Updated with hotfixes to 2013-07-15! Here is the script and the xml files with the extended DownloadURL are in this download zip file-> hyperv12updatescheck.
# Remake of Christian Edwards script to make it more flexible # http://blogs.technet.com/b/cedward/archive/2013/05/31/validating-hyper-v-2012-and-failover-clustering-hotfixes-with-powershell-part-2.aspx # # Niklas Akerlund 2013-06-28 param ( [parameter(ValueFromPipeline=$true, Position=0)] [string]$Hostname, [parameter(ValueFromPipeline=$true, Position=1)] $ClusterName, [switch]$Download, [string]$DownloadPath ) #Getting current execution path $scriptpath = $MyInvocation.MyCommand.Path $dir = Split-Path $scriptpath $listofHotfixes = @() #Loading list of updates from XML files [xml]$SourceFileHyperV = Get-Content $dir\UpdatesListHyperV.xml [xml]$SourceFileCluster = Get-Content $dir\UpdatesListCluster.xml $HyperVHotfixes = $SourceFileHyperV.Updates.Update $ClusterHotfixes = $SourceFileCluster.Updates.update #Getting installed Hotfixes from all nodes of the Cluster/hosts if ($ClusterName){ $Nodes = Get-Cluster $ClusterName | Get-ClusterNode | Select -ExpandProperty Name }else { $Nodes = $Hostname } foreach($Node in $Nodes) { $Hotfixes = Get-HotFix -ComputerName $Node |select HotfixID,description foreach($RecomendedHotfix in $HyperVHotfixes) { $witness = 0 foreach($hotfix in $Hotfixes) { If($RecomendedHotfix.id -eq $hotfix.HotfixID) { $obj = [PSCustomObject]@{ HyperVNode = $Node HotfixType = "Hyper-V" RecomendedHotfix = $RecomendedHotfix.Id Status = "Installed" Description = $RecomendedHotfix.Description DownloadURL = $RecomendedHotfix.DownloadURL } $listOfHotfixes += $obj $witness = 1 } } if($witness -eq 0) { $obj = [PSCustomObject]@{ HyperVNode = $Node HotfixType = "Hyper-V" RecomendedHotfix = $RecomendedHotfix.Id Status = "Not Installed" Description = $RecomendedHotfix.Description DownloadURL = $RecomendedHotfix.DownloadURL } $listofHotfixes += $obj } } foreach($RecomendedClusterHotfix in $ClusterHotfixes) { $witness = 0 foreach($hotfix in $Hotfixes) { If($RecomendedClusterHotfix.id -eq $hotfix.HotfixID) { $obj = [PSCustomObject]@{ HyperVNode = $Node HotfixType = "Cluster" RecomendedHotfix = $RecomendedClusterHotfix.Id Status = "Installed" Description = $RecomendedClusterHotfix.Description DownloadURL = $RecomendedClusterHotfix.DownloadURL } $listOfHotfixes += $obj $witness = 1 } } if($witness -eq 0) { $obj = [PSCustomObject]@{ HyperVNode = $Node HotfixType = "Cluster" RecomendedHotfix = $RecomendedClusterHotfix.Id Status = "Not Installed" Description = $RecomendedClusterHotfix.Description DownloadURL = $RecomendedClusterHotfix.DownloadURL } $listOfHotfixes += $obj } } } if ($Download){ foreach($RecomendedHotfix in $HyperVHotfixes){ if ($RecomendedHotfix.DownloadURL -ne ""){ Start-BitsTransfer -Source $RecomendedHotfix.DownloadURL -Destination $DownloadPath } } foreach($RecomendedClusterHotfix in $ClusterHotfixes){ if ($RecomendedClusterHotfix.DownloadURL -ne ""){ Start-BitsTransfer -Source $RecomendedClusterHotfix.DownloadURL -Destination $DownloadPath } } } $listofHotfixes