# Created By - Shabarianth Ramadasan - InsideVirtualization.Com # shabarinath@insidevirtualization.com # Data - 11/05/2014 Import-Module -Name FailoverClusters, hyper-v $ResultFile = "HyperV-Host-Details.htm" New-Item -ItemType File $ResultFile -Force $dt = Get-Date $Nodes = Get-ClusterNode -Cluster YOURCLUSTERNAME $Count = $Nodes.Count Get-ClusterNode -Cluster cs-mshv-clu6 |Foreach {$MasterUpdateList = $MasterUpdateList + (Get-HotFix -Computer $_.Name).HotfixID} $MasterUpdateList = $MasterUpdateList|Sort -Unique $TechnetWikiPage = Invoke-WebRequest "http://social.technet.microsoft.com/wiki/contents/articles/20885.hyper-v-update-list-for-windows-server-2012-r2.aspx" @($TechnetWikiPage.ParsedHtml.getElementsByTagName("table"))[1]|Select-Object OuterText |Select-String -Pattern "KB"|Out-File KB.txt foreach ($line in (Get-Content .\kb.txt)) { if ($line -match "KB" -And $Line -notmatch "kb article" -And $line.length -gt "20") { $line.substring($line.IndexOf("KB"),10) |Out-File KbList.Txt -append } } $kblist = Get-content kblist.txt $kblen = $kblist.length For ($i=0; $i -lt $kblen; $i++) { If($kblist[$i].IndexOf(" ")) { $kblist[$i] = $kblist[$i].Replace(" ","") } If($kblist[$i].IndexOf(":")) { $kblist[$i] = $kblist[$i].Replace(":","") } } Remove-Item kb.txt -Force Remove-item KbList.Txt -Force Function fWriteHtmlHeader { Param ($FileName) $date = ( get-date ).ToString('yyyy/MM/dd') Add-Content $FileName "" Add-Content $FileName "" Add-Content $FileName "" Add-Content $FileName 'Hyper-V Cluster - Updates/Driver/Firmware Consistency Report' Add-Content $FileName '" Add-Content $FileName "" Add-Content $FileName "" Add-Content $FileName "" Add-Content $FileName "" Add-Content $FileName "" Add-Content $FileName "" Add-Content $FileName "
" Add-Content $FileName "Hyper-V Cluster - Windows Updates/Driver/Firmware Consistency Report - $date" Add-Content $FileName "
" } Function fWriteHyperVUpdateTableHeader { Param ($FileName) $TechnetWikiURL = "Technet Wiki" Add-Content $FileName "" Add-Content $FileName "" Add-Content $FileName "" Add-Content $FileName "" Add-Content $FileName "
Hyper-V Update Status - Based on $TechnetWikiURL
" [int] $Spacing = 100/($Count + 1) Add-Content $FileName "" Add-Content $FileName "" Add-Content $FileName "" For ($i=0; $i -lt $Count; $i++) { $cname = $Nodes[$i].Name Add-Content $FileName "" $cname } Add-Content $FileName "" } Function fWriteHyperVUpdateTable { Param ($FileName, $KBid) [int] $Spacing = 100/($Count + 1) Add-Content $FileName "" For ($j=0; $j -lt $count; $j++) { IF (Get-HotFix -Id $KBid -ComputerName $Nodes.Name[$j] -ErrorAction SilentlyContinue) { Add-Content $FileName "" } Else { Add-Content $FileName "" } } Add-Content $FileName "" } Function fWriteWindowsUpdateTableHeader { Param ($FileName) Add-Content $FileName "
KB$cname
$KBidInstalledNotInstalled
" Add-Content $FileName "" Add-Content $FileName "" Add-Content $FileName "" Add-Content $FileName "
Windows Update Check - To identify all cluster nodes has same level of updates
" Add-Content $FileName "" Add-Content $FileName "" Add-Content $FileName "" Add-Content $FileName "" Add-Content $FileName "" Add-Content $FileName "" Add-Content $FileName "" } Function fWriteWindowsUpdateTable { Param ($FileName, $cname, $installedu, $missingu, $missingkb) Add-Content $FileName "" Add-Content $FileName "" Add-Content $FileName "" Add-Content $FileName "" Add-Content $FileName "" Add-Content $FileName "" } Function fWriteHBATableHeader { Param ($FileName) Add-Content $FileName "
NodeNameTotalPatchesInstalledTotalMissingPatchesMissingPatches
$cname$installedu$missingu$missingkb
" Add-Content $FileName "" Add-Content $FileName "" Add-Content $FileName "" Add-Content $FileName "
HBA Check - To identify all cluster nodes as same level of HBA Drivers/Firmware
" Add-Content $FileName "" Add-Content $FileName "" Add-Content $FileName "" Add-Content $FileName "" Add-Content $FileName "" Add-Content $FileName "" Add-Content $FileName "" Add-Content $FileName "" Add-Content $FileName "" Add-Content $FileName "" Add-Content $FileName "" Add-Content $FileName "" Add-Content $FileName "" Add-Content $FileName "" Add-Content $FileName "" Add-Content $FileName "" Add-Content $FileName "" Add-Content $FileName "" } Function fWriteHBATable { Param ($FileName, $cname, $HBA1Model, $HBA1ModelD, $HBA1Status, $HBA1WWN, $HBA1DriverN, $HBA1DriverV, $HBA1FirmwareV, $HBA2Model, $HBA2ModelD, $HBA2Status, $HBA2WWN, $HBA2DriverN, $HBA2DriverV, $HBA2FirmwareV) Add-Content $FileName "" Add-Content $FileName "" Add-Content $FileName "" Add-Content $FileName "" Add-Content $FileName "" Add-Content $FileName "" Add-Content $FileName "" Add-Content $FileName "" Add-Content $FileName "" Add-Content $FileName "" Add-Content $FileName "" Add-Content $FileName "" Add-Content $FileName "" Add-Content $FileName "" Add-Content $FileName "" Add-Content $FileName "" Add-Content $FileName "" } Function fWriteNICTableHeader { Param ($FileName) Add-Content $FileName "
NodeNameHBA1ModelHBA1-ModelDescriptionHBA1StatusHBA1WWNHBA1DriverNameHBA1DriverVerHBA1FirmwareVerHBA2ModelHBA2-ModelDescriptionHBA2StatusHBA2WWNHBA2DriverHBA2DriverVerHBA2FirmwareVer
$cname$HBA1Model$HBA1ModelD$HBA1Status$HBA1WWN$HBA1DriverN$HBA1DriverV$HBA1FirmwareV$HBA2Model$HBA2ModelD$HBA2Status$HBA2WWN$HBA2DriverN$HBA2DriverV$HBA2FirmwareV
" Add-Content $FileName "" Add-Content $FileName "" Add-Content $FileName "" Add-Content $FileName "
Network Interface Check - To identify all cluster nodes has same version of NIC Drivers
" Add-Content $FileName "" Add-Content $FileName "" Add-Content $FileName "" Add-Content $FileName "" Add-Content $FileName "" Add-Content $FileName "" Add-Content $FileName "" Add-Content $FileName "" Add-Content $FileName "" Add-Content $FileName "" Add-Content $FileName "" Add-Content $FileName "" Add-Content $FileName "" Add-Content $FileName "" Add-Content $FileName "" Add-Content $FileName "" Add-Content $FileName "" Add-Content $FileName "" Add-Content $FileName "" Add-Content $FileName "" Add-Content $FileName "" Add-Content $FileName "" } Function fWriteNICTable { Param ($FileName, $cname, $Nic1Name, $Nic1Mac, $Nic1Driver, $Nic2Name, $Nic2Mac, $Nic2Driver, $Nic3Name, $Nic3Mac, $Nic3Driver, $Nic4Name, $Nic4Mac, $Nic4Driver, $Nic5Name, $Nic5Mac, $Nic5Driver, $Nic6Name, $Nic6Mac, $Nic6Driver) Add-Content $FileName "" Add-Content $FileName "" Add-Content $FileName "" Add-Content $FileName "" Add-Content $FileName "" Add-Content $FileName "" Add-Content $FileName "" Add-Content $FileName "" Add-Content $FileName "" Add-Content $FileName "" Add-Content $FileName "" Add-Content $FileName "" Add-Content $FileName "" Add-Content $FileName "" Add-Content $FileName "" Add-Content $FileName "" Add-Content $FileName "" Add-Content $FileName "" Add-Content $FileName "" Add-Content $FileName "" Add-Content $FileName "" } Function fWriteHtmlFooter { Param ($FileName) Add-Content $FileName "" Add-Content $FileName "" } Function Get-HBAWin { Param ([String[]]$ComputerName = $ENV:ComputerName, [Switch]$LogOffline) $ComputerName | ForEach-Object { try { $Computer = $_ $Params = @{ Namespace = 'root\WMI' class = 'MSFC_FCAdapterHBAAttributes' ComputerName = $Computer ErrorAction = 'Stop' } Get-WmiObject @Params | ForEach-Object { $hash=@{ ComputerName = $_.__SERVER NodeWWN = (($_.NodeWWN) | ForEach-Object {"{0:x}" -f $_}) -join ":" Active = $_.Active DriverName = $_.DriverName DriverVersion = $_.DriverVersion FirmwareVersion = $_.FirmwareVersion Model = $_.Model ModelDescription = $_.ModelDescription } New-Object psobject -Property $hash }#Foreach-Object(Adapter) }#try catch { Write-Warning -Message $_ if ($LogOffline) { "$Computer is offline or not supported" } } }#Foreach-Object(Computer) }#Get-HBAWin fWriteHtmlHeader $ResultFile fWriteHyperVUpdateTableHeader $ResultFile $KbList |Foreach {fWriteHyperVUpdateTable $ResultFile $_} Add-Content $ResultFile "
NodeNameNIC1-NameNIC1MACNIC1DriverVerNIC2-NameNIC2MACNIC2DriverVerNIC3-NameNIC3MACNIC3DriverVerNIC4-NameNIC4MACNIC4DriverVerNIC5-NameNIC5MACNIC5DriverVerNIC6-NameNIC6MACNIC6DriverVer
$cname$Nic1Name$Nic1Mac$Nic1Driver$Nic2Name$Nic2Mac$Nic2Driver$Nic3Name$Nic3Mac$Nic3Driver$Nic4Name$Nic4Mac$Nic4Driver$Nic5Name$Nic5Mac$Nic5Driver$Nic6Name$Nic6Mac$Nic6Driver
" fWriteWindowsUpdateTableHeader $ResultFile For ($l=0; $l -lt $Count; $l++) { $miskb = "" [array] $InstalledUpdates = Get-Hotfix -ComputerName $Nodes.Name[$l] $MissingUpdates = (Compare-Object -ReferenceObject $MasterUpdateList -DifferenceObject (($InstalledUpdates).HotfixID))|Select InputObject $MissingUpdates |foreach {[string] $miskb +=" "+ $_.Inputobject } fWriteWindowsUpdateTable $ResultFile $nodes.name[$l] $InstalledUpdates.Count $MissingUpdates.Count $miskb } Add-Content $ResultFile "" fWriteHBATableHeader $ResultFile For ($m=0; $m -lt $Count; $m++) { $HBAResult = Get-HBAWin -Computer $Nodes[$m].name fWriteHBATable $ResultFile $HBAResult[0].ComputerName $HBAResult[0].Model $HBAResult[0].ModelDescription $HBAResult[0].Active $HBAResult[0].NodeWWN $HBAResult[0].DriverName $HBAResult[0].DriverVersion $HBAResult[0].FirmwareVersion $HBAResult[1].Model $HBAResult[1].ModelDescription $HBAResult[1].Active $HBAResult[1].NodeWWN $HBAResult[1].DriverName $HBAResult[1].DriverVersion $HBAResult[1].FirmwareVersion } Add-Content $ResultFile "" $TableInit = "0" For ($n=0; $n -lt $Count; $n++) { If (Test-WSMan -ComputerName $Nodes.Name[$n]) { If ($TableInit -eq "0") { fWriteNICTableHeader $ResultFile $TableInit = "1" } $NicResult = Invoke-Command -ComputerName $Nodes.Name[$n] -ScriptBlock {Get-NetAdapter -Physical} fWriteNICTable $ResultFile $Nodes.Name[$n] $NicResult.Name[0] $NicResult.MacAddress[0] $NicResult.DriverVersionString[0] $NicResult.Name[1] $NicResult.MacAddress[1] $NicResult.DriverVersionString[1] $NicResult.Name[2] $NicResult.MacAddress[2] $NicResult.DriverVersionString[2] $NicResult.Name[3] $NicResult.MacAddress[3] $NicResult.DriverVersionString[3] $NicResult.Name[4] $NicResult.MacAddress[4] $NicResult.DriverVersionString[4] $NicResult.Name[5] $NicResult.MacAddress[5] $NicResult.DriverVersionString[5] } } Add-Content $ResultFile "" fWriteHtmlFooter $ResultFile Send-MailMessage -To youremail@yourdomain.com -From HyperV-Dashboard@InsideVirtualization.com -Body (Get-Content $ResultFile |Out-String) -SmtpServer yoursmtpserver.yourdomain.com -Subject "HyperV Host - Consistency Report" -BodyAsHtml Remove-Item $ResultFile -Force