AK560576

Monitor_AK560576 (UnitMonitor)

Check for Windows cluster hotfix 2550886

Knowledge Base article:

External

http://go.microsoft.com/fwlink/?LinkId=234281

Element properties:

TargetMicrosoft.KnowledgeServices.Exchange.2010.MailboxRole
Parent MonitorSystem.Health.ConfigurationState
CategoryAlert
EnabledTrue
Alert GenerateTrue
Alert SeverityWarning
Alert PriorityNormal
Alert Auto ResolveTrue
Monitor TypeMicrosoft.KnowledgeServices.Library.PowerShellMonitorEx
RemotableTrue
AccessibilityPublic
Alert Message
Check for Windows cluster hotfix 2550886
<Details>
<Content>Hotfix KB 2550886 is recommended on all the Exchange MailBox servers that are part of a Database Availbility Group. KB 2550886 improves Windows Failover Cluster transient communication instability when deploying stretched Database Availability Groups across data centers.</Content>
<CollectedInformation>
<Info>
<Name>HasIssue</Name>
<Value>{0}</Value>
</Info>
</CollectedInformation>
</Details>
RunAsDefault
CommentSupportTopic=TBD;VersionNumber=1.1.0.0;

Source Code:

<UnitMonitor ID="Monitor_AK560576" Comment="SupportTopic=TBD;VersionNumber=1.1.0.0;" Accessibility="Public" Enabled="true" Target="MicrosoftKnowledgeServicesExchange2010Library!Microsoft.KnowledgeServices.Exchange.2010.MailboxRole" ParentMonitorID="Health!System.Health.ConfigurationState" Remotable="true" Priority="Normal" TypeID="KnowledgeServicesLibrary!Microsoft.KnowledgeServices.Library.PowerShellMonitorEx" ConfirmDelivery="true">
<Category>Alert</Category>
<AlertSettings AlertMessage="MonitorMessage333b5d56ec244ba6afb261dbe575392e">
<AlertOnState>Error</AlertOnState>
<AutoResolve>true</AutoResolve>
<AlertPriority>Normal</AlertPriority>
<AlertSeverity>Warning</AlertSeverity>
<AlertParameters>
<AlertParameter1>$Data/Context/Property[@Name='HasIssue']$</AlertParameter1>
</AlertParameters>
</AlertSettings>
<OperationalStates>
<OperationalState ID="Success" MonitorTypeStateID="Success" HealthState="Success"/>
<OperationalState ID="Error" MonitorTypeStateID="Error" HealthState="Error"/>
</OperationalStates>
<Configuration>
<ScriptName>AK560576.ps1</ScriptName>
<Parameters>
<Parameter>
<Name>ServerName</Name>
<Value>$Target/Property[Type="MicrosoftKnowledgeServicesExchange2010Library!Microsoft.KnowledgeServices.Exchange.2010.MailboxRole"]/Name$</Value>
</Parameter>
<Parameter>
<Name>OSVersion</Name>
<Value>$Target/Host/Host/Property[Type="MicrosoftKnowledgeServicesExchange2010Library!Microsoft.KnowledgeServices.Exchange.2010.Installation"]/OSVersion$</Value>
</Parameter>
<Parameter>
<Name>OSCaption</Name>
<Value>$Target/Host/Host/Property[Type="MicrosoftKnowledgeServicesExchange2010Library!Microsoft.KnowledgeServices.Exchange.2010.Installation"]/OSCaption$</Value>
</Parameter>
</Parameters>
<ScriptBody><Script>


param($ServerName,$OSVersion,$OSCaption)

$ErrorActionPreference = "Stop"

# Set up the arguments
$scriptargs = new-object psobject
$scriptargs | add-member NoteProperty "ServerName" $ServerName
$scriptargs | add-member NoteProperty "OSVersion" $OSVersion
$scriptargs | add-member NoteProperty "OSCaption" $OSCaption

# Set up the output
$global:scriptoutput = new-object psobject
$scriptoutput | add-member NoteProperty "HasIssue" $false
# Private function, please use CheckFilesIsInstalled instead.
function CheckFileInstalled([String]$KbID, [String]$RequiredFileLocation, [Version]$RequiredVersion, [bool]$Required, [bool]$ForceFileComparation)
{
if(([String]::IsNullOrEmpty($KbID)) -or ([String]::IsNullOrEmpty($RequiredFileLocation)) -or ($RequiredVersion -eq $null))
{
return $true
}

if((test-path $RequiredFileLocation))
{
$FileVersionInfo = [System.Diagnostics.FileVersionInfo]::GetVersionInfo($RequiredFileLocation)
$CurrentFileVersion = "{0}.{1}.{2}.{3}" -f $FileVersionInfo.FileMajorPart,$FileVersionInfo.FileMinorPart,$FileVersionInfo.FileBuildPart,$FileVersionInfo.FilePrivatePart
$RequiredVersionPart = "{0}.{1}.{2}" -f $RequiredVersion.Major,$RequiredVersion.Minor,$RequiredVersion.Build

if($CurrentFileVersion.ToString().StartsWith($RequiredVersionPart))
{
if(($FileVersionInfo.FileMajorPart -ge 6) -and ($FileVersionInfo.FileBuildPart -ge 6000))
{
# Check if the current file version is GDR or LDR:
# http://blogs.technet.com/b/joscon/archive/2011/11/30/how-does-windows-choose-which-version-of-a-file-to-install.aspx
if(-not $ForceFileComparation -and (($FileVersionInfo.FilePrivatePart.ToString("d4").StartsWith(2) -and $RequiredVersion.Revision.ToString("d4").StartsWith(1)) -or `
($FileVersionInfo.FilePrivatePart.ToString("d4").StartsWith(1) -and $RequiredVersion.Revision.ToString("d4").StartsWith(2))))
{
return $true
}
}
}
return [Version]$CurrentFileVersion -ge $RequiredVersion
}

return -not $Required
}

function CheckFilesIsInstalled($fileInfos)
{
&lt;#
.DESCRIPTION
Check specified files are installed or not
.EXAMPLE
PS: CheckFilesIsInstalled $fileInfos
#&gt;

$array = @()

foreach($fileInfo in $fileInfos)
{
if(($fileInfo -ne $null) -and (-not (CheckFileInstalled $fileInfo.KbID $fileInfo.RequiredFileLocation $fileInfo.RequiredVersion $fileInfo.Required $fileInfo.ForceFileComparation)))
{
if((test-path $fileInfo.RequiredFileLocation))
{
$FileVersionInfo = [System.Diagnostics.FileVersionInfo]::GetVersionInfo($fileInfo.RequiredFileLocation)
$CurrentFileVersion = "{0}.{1}.{2}.{3}" -f $FileVersionInfo.FileMajorPart,$FileVersionInfo.FileMinorPart,$FileVersionInfo.FileBuildPart,$FileVersionInfo.FilePrivatePart
$fileInfo.CurrentVersion = [Version]$CurrentFileVersion
}
else
{
$fileInfo.CurrentVersion = [Version]"0.0.0.0"
}
$array += $fileInfo
}
}
return $array
}

$hotfixInfoType = [System.Type] "PSObject"
$hotfixInfoListType = [System.Collections.Generic.List``1]
$hotfixInfoList = $hotfixInfoListType.MakeGenericType(@($hotfixInfoType))
$checkedFiles = [Activator]::CreateInstance($hotfixInfoList)

function CreateHotfixInfo([String]$KbID, [String]$RequiredFileLocation, [Version]$RequiredVersion, [bool]$Required, [bool]$ForceFileComparation=$false)
{
&lt;#
.DESCRIPTION
Create Hotfix
.EXAMPLE
PS: CreateHotfixInfo -KbID "KB2876391" -RequiredFileLocation "C:\Windows\System32\drivers\Mpio.sys" -RequiredVersion "6.1.7601.18251" -Required $true
#&gt;

if(([String]::IsNullOrEmpty($KbID)) -or ([String]::IsNullOrEmpty($RequiredFileLocation)) -or ($RequiredVersion -eq $null))
{
return $null
}

return $(New-Object PSObject -Property @{"KbID"=$KbID; "RequiredFileLocation"=$RequiredFileLocation; "RequiredVersion"=$RequiredVersion; "CurrentVersion"=[Version]"0.0.0.0"; "Required"=$Required; "ForceFileComparation"=$ForceFileComparation})
}
#-----------------------------------------------------
# MAIN CODE SECTION
#-----------------------------------------------------

# Environment

$scriptenv = new-object psobject
$scriptenv | add-member NoteProperty "IsAMemberOfDAG" $false
$scriptenv | add-member NoteProperty "DAGList" $null
$scriptenv | add-member NoteProperty "ErrorFlag" $null



# Helper functions

#function to check is the MailboxServer a member of a DAG
Function Check-IsAMemberOfDAG{

# Get this Exchange Database Abailablity Groups
$scriptenv.DAGList = Get-DatabaseAvailabilityGroup -ErrorAction SilentlyContinue

If($scriptenv.DAGList -ne $null){
Foreach($Dag in $scriptenv.DAGList){
Foreach($Server in $Dag.Servers){
If($server.Name -eq $scriptargs.ServerName){
$scriptenv.IsAMemberOfDAG = $true
break
}
}
If($scriptenv.IsAMemberOfDAG -eq $true){
break
}
}
}
}


# Main function

Function AdvisorRule($scriptargs, $scriptoutput)
{
# All parameters should be populated outside of the main function.
# The mian function should only include the detection logic so that it can be easyly reused by the Atlanta authoring tool.
trap [Exception] {
$scriptenv.ErrorFlag = $true
continue
}

# Initialize parameters
$scriptenv.IsAMemberOfDAG = $false
$scriptoutput.HasIssue = $false
$scriptenv.ErrorFlag = $false

# Set parameter values
# $checkedFiles variable and CreateHotfixInfo function are defined in the Common\Library\CommonRuleLibrary.ps1
$clussvc_filepath = Join-Path $Env:windir "Cluster\Clussvc.exe"
$cluswmi_filepath = Join-Path $Env:windir "system32\Wbem\Cluswmi.dll"
if($scriptargs.OSVersion.Tostring().StartsWith("6.1.7600")
{
$checkedFiles.Add($(CreateHotfixInfo -KbID "KB2550886" -RequiredFileLocation $clussvc_filepath -RequiredVersion "6.1.7600.21010" -Required $true -ForceFileComparation $true))
$checkedFiles.Add($(CreateHotfixInfo -KbID "KB2550886" -RequiredFileLocation $cluswmi_filepath -RequiredVersion "6.1.7600.21010" -Required $true -ForceFileComparation $true))
}
if($scriptargs.OSVersion.Tostring().StartsWith("6.1.7601")
{
$checkedFiles.Add($(CreateHotfixInfo -KbID "KB2550886" -RequiredFileLocation $clussvc_filepath -RequiredVersion "6.1.7601.21772" -Required $true -ForceFileComparation $true))
$checkedFiles.Add($(CreateHotfixInfo -KbID "KB2550886" -RequiredFileLocation $cluswmi_filepath -RequiredVersion "6.1.7601.21772" -Required $true -ForceFileComparation $true))
}

$filesNotApplied = @(CheckFilesIsInstalled($checkedFiles))

Check-IsAMemberOfDAG

# Detection Logic

# Is the plantform Windows Server 2008 or Windows Server 2008 R2
If($scriptargs.OSVersion.Tostring().StartsWith("6.") -and $scriptargs.OSCaption.Tostring().Contains("2008")){
# Is Exchange Server a Member of DAG
If($scriptenv.IsAMemberOfDAG -eq $true){
# Is the hotfix KB2550886 installed
If($filesNotApplied.Count -gt 0){
If($scriptenv.ErrorFlag -ne $true){
# Raise alert
$scriptoutput.HasIssue = $true
}
}
}
}
}
AdvisorRule $scriptargs $scriptoutput

# set the output
$mom = new-object -comobject "MOM.ScriptAPI"
$bag = $mom.CreatePropertyBag()

if ($scriptoutput.HasIssue -ne $null)
{
$bag.AddValue("HasIssue", $scriptoutput.HasIssue)
}

$bag

</Script></ScriptBody>
<SnapIns>
<SnapIn>Microsoft.Exchange.Management.PowerShell.E2010</SnapIn>
</SnapIns>
<TimeoutSeconds>300</TimeoutSeconds>
<Schedule>86372</Schedule>
<ErrorExpression>
<SimpleExpression>
<ValueExpression>
<XPathQuery Type="Boolean">Property[@Name='HasIssue']</XPathQuery>
</ValueExpression>
<Operator>Equal</Operator>
<ValueExpression>
<Value Type="Boolean">true</Value>
</ValueExpression>
</SimpleExpression>
</ErrorExpression>
<SuccessExpression>
<Not>
<Expression>
<SimpleExpression>
<ValueExpression>
<XPathQuery Type="Boolean">Property[@Name='HasIssue']</XPathQuery>
</ValueExpression>
<Operator>Equal</Operator>
<ValueExpression>
<Value Type="Boolean">true</Value>
</ValueExpression>
</SimpleExpression>
</Expression>
</Not>
</SuccessExpression>
</Configuration>
</UnitMonitor>