AKN421730

Monitor_AKN421730 (UnitMonitor)

Edge server network interfaces are not properly configured

Knowledge Base article:

External

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

Element properties:

TargetMicrosoft.KnowledgeServices.Lync.2010.CsServer
Parent MonitorSystem.Health.ConfigurationState
CategoryAlert
EnabledTrue
Alert GenerateTrue
Alert SeverityWarning
Alert PriorityNormal
Alert Auto ResolveTrue
Monitor TypeMicrosoft.KnowledgeServices.Library.PowerShellMonitorEx
RemotableTrue
AccessibilityPublic
Alert Message
Edge server network interfaces are not properly configured
<Details>
<Content>Advisor has either detected that all the network interface IP addresses for the edge server are from the same subnets or there is only 1 NIC. Make sure that the server has two network interfaces that are configured with IP addresses from different subnets. See the following KB article for more information.</Content>
<CollectedInformation>
<Info>
<Name>Edge Server FQDN</Name>
<Value>{0}</Value>
</Info>
</CollectedInformation>
</Details>
RunAsMicrosoft.KnowledgeServices.ElevatedAccount
CommentSupportTopic=TBD;VersionNumber=1.0.0.0;

Source Code:

<UnitMonitor ID="Monitor_AKN421730" Comment="SupportTopic=TBD;VersionNumber=1.0.0.0;" Accessibility="Public" Enabled="true" Target="MicrosoftKnowledgeServicesLyncLibrary!Microsoft.KnowledgeServices.Lync.2010.CsServer" ParentMonitorID="Health!System.Health.ConfigurationState" Remotable="true" Priority="Normal" RunAs="KnowledgeServicesLibrary!Microsoft.KnowledgeServices.ElevatedAccount" TypeID="KnowledgeServicesLibrary!Microsoft.KnowledgeServices.Library.PowerShellMonitorEx" ConfirmDelivery="true">
<Category>Alert</Category>
<AlertSettings AlertMessage="MonitorMessageb6bf0ac2f0ac4b2186004342181ca9dc">
<AlertOnState>Error</AlertOnState>
<AutoResolve>true</AutoResolve>
<AlertPriority>Normal</AlertPriority>
<AlertSeverity>Warning</AlertSeverity>
<AlertParameters>
<AlertParameter1>$Data/Context/Property[@Name='CsServerFQDN']$</AlertParameter1>
</AlertParameters>
</AlertSettings>
<OperationalStates>
<OperationalState ID="Success" MonitorTypeStateID="Success" HealthState="Success"/>
<OperationalState ID="Error" MonitorTypeStateID="Error" HealthState="Error"/>
</OperationalStates>
<Configuration>
<ScriptName>AKN421730.ps1</ScriptName>
<Parameters>
<Parameter>
<Name>CsServerFQDN</Name>
<Value>$Target/Property[Type="MicrosoftKnowledgeServicesLyncLibrary!Microsoft.KnowledgeServices.Lync.2010.CsServer"]/ReplicaFqdn$</Value>
</Parameter>
</Parameters>
<ScriptBody><Script>PARAM($CsServerFQDN)
[ScriptBlock]$mainScriptBlock = {


param($CsServerFQDN)

$ErrorActionPreference = "Stop"

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

# Set up the output
$global:scriptoutput = new-object psobject
$scriptoutput | add-member NoteProperty "HasIssue" $false
$scriptoutput | add-member NoteProperty "CsServerFQDN" ""
#-----------------------------------------------------
# Environment
#-----------------------------------------------------
$script:lyncPath = ""
if (Join-Path $Env:CommonProgramFiles "\Microsoft Lync Server 2013\Modules\Lync\Lync.psd1" | Test-Path)
{
$script:lyncPath = Join-Path $Env:CommonProgramFiles "\Microsoft Lync Server 2013\Modules\Lync\Lync.psd1"
$script:lyncPSVer = 2013
}
elseif (Join-Path $Env:CommonProgramFiles "\Microsoft Lync Server 2010\Modules\Lync\Lync.psd1" | Test-Path)
{
$script:lyncPath = Join-Path $Env:CommonProgramFiles "\Microsoft Lync Server 2010\Modules\Lync\Lync.psd1"
$script:lyncPSVer = 2010
}
$ScriptEnv = New-Object psobject
$ScriptEnv | Add-Member NoteProperty "RuntimeError" $false
$ScriptEnv | Add-Member NoteProperty "HasIssue" $false
$ScriptEnv | add-member ScriptMethod "ImportLyncPSModule" -value {
$m = Get-Module -Name Lync
if ($m -eq $null)
{
Import-Module $script:lyncPath -ErrorAction:SilentlyContinue
}
}
$ScriptEnv | Add-Member ScriptMethod "IsCMSMaster" -Value {
Try
{
$cmsStatus = Get-CsManagementStoreReplicationStatus -CentralManagementStoreStatus
$agentHostFqdn = [System.Net.Dns]::GetHostByName([System.Net.Dns]::GetHostName()).HostName
return $cmsStatus.ActiveMasterFqdn -ieq $agentHostFqdn
}
Catch [Microsoft.Rtc.Management.ADConnect.CannotGetDomainInfoException]
{
}
Catch [Microsoft.Rtc.Common.Data.SqlConnectionException]
{
}
Catch [System.Data.SqlClient.SqlException]
{
}
return $false
}

#-----------------------------------------------------
# MAIN CODE SECTION
#-----------------------------------------------------
# Setting property 'HasIssue = true' means we assume that this rule always fire alert
$scriptenv.HasIssue = $true
$scriptenv | Add-Member NoteProperty "IsEdgeServer" $false

function NICCompare()
{
$strComputer = "."
$adapters = @(Get-WmiObject -Class "Win32_NetworkAdapterConfiguration" -Namespace "root\CIMV2" -ComputerName $strComputer -Filter "IPEnabled = true")
$networkaddressArray = @()

foreach ($adapter in $adapters)
{
$ip = $adapter.IPAddress[0]
$subnet = $adapter.IPSubnet[0]

$ipArray = $ip.Split('.')| ForEach-Object { [UInt32]$_ }
$subnetArray = $subnet.Split('.')| ForEach-Object { [UInt32]$_ }
$networkaddress = "{0}.{1}.{2}.{3}" -f ($ipArray[0] -band $subnetArray[0]),($ipArray[1] -band $subnetArray[1]),($ipArray[2] -band $subnetArray[2]),($ipArray[3] -band $subnetArray[3])

# IP addresses used to compare
$networkaddressArray += $networkaddress
}

for($i = 0;($i -lt $networkaddressArray.length);$i++)
{
for(($j = $networkaddressArray.length - 1); $j -gt $i ; $j-- )
{
# Getting IP addresses
$ip1 = $networkaddressArray[$i]
$ip2 = $networkaddressArray[$j]

if ($ip1 -ine $ip2)
{
# Don't fire alert only when there are two network interfaces that are configured with IP addresses from different subnets
$scriptenv.HasIssue = $false
break
}
}
# If we have found two network interfaces from different subnets exit this loop
if($scriptenv.HasIssue -eq $false)
{
break
}
}
}

function IsEdgeServer()
{
$edgeServices = @(Get-Service | Where-Object { $_.DisplayName -like "*edge*" })
if($edgeServices.Count -gt 0)
{
$scriptenv.IsEdgeServer = $true
}
}

# Main Function
function AdvisorRule($scriptargs, $scriptoutput)
{
if ($script:lyncPath -ne "")
{
trap [Exception]
{
$scriptenv.RuntimeError = $true
continue
}

$scriptenv.ImportLyncPSModule()

$scriptoutput.HasIssue = $false

IsEdgeServer

if($scriptenv.IsEdgeServer -eq $true)
{
NICCompare
}
else
{
$scriptenv.HasIssue = $false
}

if($scriptenv.HasIssue -eq $true -and $scriptenv.RuntimeError -eq $false)
{
$scriptoutput.HasIssue = $true
$scriptoutput.CsServerFQDN = $scriptargs.CsServerFQDN
}
}
}
AdvisorRule $scriptargs $scriptoutput

}

Function Test-NeedPSRemoting
{
$script:lyncPSVer = 0
if (Join-Path $Env:CommonProgramFiles "\Microsoft Lync Server 2013\Modules\Lync\Lync.psd1" | Test-Path)
{
$script:lyncPSVer = 2013
}
elseif (Join-Path $Env:CommonProgramFiles "\Microsoft Lync Server 2010\Modules\Lync\Lync.psd1" | Test-Path)
{
$script:lyncPSVer = 2010
}
$PSCLRVersion = [System.String]::Format("{0}.{1}", $PSVersionTable.CLRVersion.Major, $PSVersionTable.CLRVersion.Minor)
if (($PSCLRVersion -ieq "2.0") -and ($script:lyncPSVer -ieq 2013))
{
return $true
}
return $false
}

if ((Test-NeedPSRemoting))
{
[bool]$script:psRemotingEnabled = $false
# Enable PowerShell Remoting need elevated BUILTIN\Administrators privilege
$winRMService = (Get-Service WinRM -ErrorAction SilentlyContinue)
if ($winRMService -ne $null)
{
if ($winRMService.Status -ieq [System.ServiceProcess.ServiceControllerStatus]::Stopped)
{
$winRMService.Start()
$winRMService.WaitForStatus([System.ServiceProcess.ServiceControllerStatus]::Running, [System.TimeSpan]::FromSeconds(15))
}
$psSessionConfiguration = (Get-PSSessionConfiguration -Name "Microsoft.PowerShell" -ErrorAction SilentlyContinue)
if ($psSessionConfiguration.Permission.Contains("BUILTIN\Administrators AccessAllowed"))
{
$script:psRemotingEnabled = $true
}
}

# Call remote PS session when PSRemoting is enabled.
if ($script:psRemotingEnabled -eq $true)
{
$session = New-PSSession
Invoke-Command -Session $session -ScriptBlock $mainScriptBlock -ArgumentList @($CsServerFQDN)
$global:scriptoutput = Invoke-Command -Session $session -ScriptBlock {$global:scriptoutput}
Remove-PSSession -Session $session
}
}
else
{
&amp; $mainScriptBlock $CsServerFQDN
}

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

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

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

$bag

</Script></ScriptBody>
<SnapIns/>
<TimeoutSeconds>300</TimeoutSeconds>
<Schedule>14400</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>