<DataSourceModuleType ID="Microsoft.LS.2013.Discovery.Topology.DS" Accessibility="Internal" Batching="false">
<Configuration>
<xsd:element xmlns:xsd="http://www.w3.org/2001/XMLSchema" name="IntervalSeconds" type="xsd:integer"/>
<xsd:element xmlns:xsd="http://www.w3.org/2001/XMLSchema" name="TimeoutSeconds" type="xsd:integer"/>
</Configuration>
<OverrideableParameters>
<OverrideableParameter ID="IntervalSeconds" Selector="$Config/IntervalSeconds$" ParameterType="int"/>
<OverrideableParameter ID="TimeoutSeconds" Selector="$Config/TimeoutSeconds$" ParameterType="int"/>
</OverrideableParameters>
<ModuleImplementation Isolation="Any">
<Composite>
<MemberModules>
<DataSource ID="DS" TypeID="Microsoft.LS.2013.Discovery.Common.LyncModule.DS">
<IntervalSeconds>$Config/IntervalSeconds$</IntervalSeconds>
<SyncTime/>
<ScriptName>Lync Server MP Machine Topology Discovery</ScriptName>
<ScriptFileName>DiscoverMachine.ps1</ScriptFileName>
<ScriptBody><Script>
#############################################################################
# 1. Discover Deployment.
# 2. Discover Site.
# 3. Discover DeploymentContainsSite relationship.
# 4. Foreach Cluster:
# a. Discover SiteContainsCluster relationship.
# b. Get list of roles for the cluster.
# c. Foreach Role:
# d. Discover Role.
# e. Discover all belonging Component.
# f. Discover RoleHostsComponents relationship.
# NOTE
# Reason being, Microsoft.Windows.TimedPowerShell.DiscoveryProvider's
# ParameterBinding logic cannot accept a bool value and internally casts and passes
# this parameter as a string type to the script function. This results in a
# System.Management.Automation.ParameterBindingArgumentTransformationException.
# Workaround is to define the configuration parameter as bool type
# (thus only accepts two values of true or false ), but process it as a
# string type within this script.
#############################################################################
#HELPER FUNCTIONS############################################################
function IsDiscoverableComponent($cluster, $roleId, $componentId)
{
# Need a one-off special casing for ConfServices role.
# This is because we cannot guarantee that all the MCU components will be present in a deployment.
# We need to add only those MCUs that are installed.
if($roleId -eq [Microsoft.Rtc.Management.Core.RoleName]::ConfServices)
{
$ConfServicesService = $cluster.InstalledServices[[Microsoft.Rtc.Management.Core.RoleName]::ConfServices]
$mcus = $ConfServicesService.MCUs;
# The below syntax essentially walks the $ConfServicesService object[] and extracts the
# LocalName field into a string array so that we can run a -notcontains operator.
if(($mcus | foreach-object {$_.ComponentId.LocalName}) -notcontains $componentId)
{
# This component (i.e application) is not enabled.
# so ignore adding it to the DiscoveryData
$false
return
}
}
# Need a one-off special casing for ApplicationsServer role.
# This is because they have been modeled as applications
# and not all apps can be enabled on a given ApplicationServer role.
if($roleId -eq [Microsoft.Rtc.Management.Core.RoleName]::ApplicationServer)
{
$applicationServerService = $cluster.InstalledServices[[Microsoft.Rtc.Management.Core.RoleName]::ApplicationServer]
$applications = $applicationServerService.Applications;
# The below syntax essentially walks the $applications object[] and extracts the
# LocalName field into a string array so that we can run a -notcontains operator.
if(($applications | foreach-object {$_.LocalName}) -notcontains $componentId)
{
# This component (i.e application) is not enabled.
# so ignore adding it to the DiscoveryData
$false
return
}
}
# Need a one-off special casing for PersistentChat role.
# Rule 1:
# This is because of PersistentChatCompliance. if ComplianceStore is not installed, then we should not discover PersistentChatCompliance.
# Rule 2:
# Check whether local fqdn is in active Fqdn list.
if($roleId -eq [Microsoft.Rtc.Management.Core.RoleName]::PersistentChatService)
{
$persistentChatService = $cluster.InstalledServices[[Microsoft.Rtc.Management.Core.RoleName]::PersistentChatService]
$persistentChatComplianceStoreRoleName = [Microsoft.Rtc.Management.Core.RoleName]::PersistentChatComplianceStore
$defaultUsage = [Microsoft.Rtc.Management.Deploy.DependencyUsage]::Default
$dependencyId = [Microsoft.Rtc.Management.Deploy.DependencyId]::Get($persistentChatComplianceStoreRoleName, $defaultUsage)
if ($persistentChatService.DependentServices[$dependencyId] -eq $null)
{
# Rule 1:
# This component (i.e PersistentChatCompliance) is not enabled, because PersistentChatComplianceStore dependency does not exist.
# so ignore adding it to the DiscoveryData
if ($componentId -eq "PersistentChatCompliance")
{
$false
return
}
}
else
{
# Rule 2:
# If the current machine is not in active fqdns' list, then ignore discovery of persistent chat server.
if ($persistentChatService.ActiveServers -notcontains $targetComputer)
{
$false
return
}
}
}
# Need a one-off special casing for WebServices role.
# This is because we cannot guarantee that all the Web components will be present in a deployment.
# We need to add only those web components that are installed.
if($roleId -eq [Microsoft.Rtc.Management.Core.RoleName]::WebServices)
{
# Common Component for Web Services.
if ($componentId -eq "WebInfra")
{
$true
return
}
# The below syntax essentially walks the $webComponentList object[] and extracts the
# LocalName field into a string array so that we can run a -notcontains operator.
if($webComponentList -notcontains $componentId)
{
# This web component is not enabled.
# so ignore adding it to the DiscoveryData
$false
return
}
}
# Need a one-off special casing for Registrar role.
# This is because; XmppFederation component only deployed if XmppFederation port is in registrar role.
if (($roleId -eq [Microsoft.Rtc.Management.Core.RoleName]::Registrar) -and ($componentId -eq "XmppFederation"))
{
$registrarService = $cluster.InstalledServices[[Microsoft.Rtc.Management.Core.RoleName]::Registrar]
$ports = $registrarService.NetPorts
$filteredPorts = @( $ports | where { ($_.NetPortId.Owner -eq [Microsoft.Rtc.Management.Core.ComponentId]::XmppFederation) -and ($_.Enabled -eq $true)} )
if ($filteredPorts.Count -eq 0)
{
# This XmppFederation is not present or enabled.
# so ignore adding it to the DiscoveryData
$false
return
}
}
# Need a one-off special casing for Edge Server role.
# This is because; XmppFederationProxy component only deployed if XmppFederationProxy port is in Edge Server role.
if (($roleId -eq [Microsoft.Rtc.Management.Core.RoleName]::EdgeServer) -and ($componentId -eq "XmppFederationProxy"))
{
$edgeServer = $cluster.InstalledServices[[Microsoft.Rtc.Management.Core.RoleName]::EdgeServer]
$ports = $edgeServer.NetPorts
$filteredPorts = @( $ports | where { ($_.NetPortId.Owner -eq [Microsoft.Rtc.Management.Core.ComponentId]::XmppFederationProxy) -and ($_.Enabled -eq $true)} )
if ($filteredPorts.Count -eq 0)
{
# This XmppFederationProxy is not present or enabled.
# so ignore adding it to the DiscoveryData
$false
return
}
}
# 2. Find Current machine
$currentMachineFqdn = $TargetComputer
# Local machine discovery requires only access to local topology data.
$topology = Get-CsTopology -LocalStore
$currentMachine = $topology.Machines | where {$_.Fqdn -eq $currentMachineFqdn}
if (!$currentMachine)
{
throw "Current machine {0} does not exist in the topology." -f $currentMachineFqdn
}
TRACE ("Successfully found current machine in topology. Machine Fqdn is {0}" -f $currentMachineFqdn);
# 5. Discover Pool [Cluster]
$ClustersRequireSetup = @(GetClustersRequireSetup $site)
$cluster = $ClustersRequireSetup | where {$_.Fqdn -eq $currentMachine.Cluster.Fqdn}
if (!$cluster)
{
throw "Cluster of current machine {0} does not require setup. Skipping discovery." -f $currentMachineFqdn
}
# 7. Discover Services (Roles) E.g. Registrar, UserServices, ...
$roleIds = @(SupportedRolesForCluster $cluster)
if ($roleIds.Count -eq 0)
{
throw "Cluster of current machine {0} does not have any role supported." -f $currentMachineFqdn
}
# Special handling for OcsCore role.
# Squid cmdlet does not return OCSCore as a role.
# Discovery script needs to append this role regardless of query result from squid.
$roleIds += "OcsCore"
# Common Role is used to monitor common KHIs. E.g. Disk, Process.
$roleIds += "Common"
foreach ($roleId in $roleIds)
{
#Discover all the roles
#( A cluster can have multiple machines with same services installed - we call it Roles).
$machineFqdn = $currentMachineFqdn
#Discover all the components that belong to this Role.
$components = @($componentMap[$roleId])
foreach ($component in $components)
{
$componentName = $component[0]
$componentClassId = $component[1]
if ((IsDiscoverableComponent $cluster $roleId $componentName) -eq $false)
{
continue
}