Agent Relationship Discovery Data Source

Microsoft.SystemCenter.ADIntegrationRelationshipDiscovery (DataSourceModuleType)

Element properties:

TypeDataSourceModuleType
IsolationAny
AccessibilityInternal
RunAsSystem.PrivilegedMonitoringAccount
OutputTypeSystem.Discovery.Data

Member Modules:

ID Module Type TypeId RunAs 
DataSource DataSource Microsoft.Windows.TimedPowerShell.DiscoveryProvider Default

Overrideable Parameters:

IDParameterTypeSelectorDisplay NameDescription
IntervalSecondsint$Config/IntervalSeconds$Interval Seconds
TimeoutSecondsint$Config/TimeoutSeconds$Timeout Seconds

Source Code:

<DataSourceModuleType ID="Microsoft.SystemCenter.ADIntegrationRelationshipDiscovery" Accessibility="Internal" RunAs="System!System.PrivilegedMonitoringAccount" Batching="false">
<Configuration>
<xsd:element name="IntervalSeconds" type="xsd:integer"/>
<xsd:element 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="DataSource" TypeID="Windows!Microsoft.Windows.TimedPowerShell.DiscoveryProvider">
<IntervalSeconds>$Config/IntervalSeconds$</IntervalSeconds>
<SyncTime/>
<ScriptName>DiscoverHealthServiceCommunicationRelationships.ps1</ScriptName>
<ScriptBody><Script>
param($SourceType, $SourceId, $ManagedEntityId, $ComputerIdentity, $ManagementGroupName)

function SafeRegRead($registryPath, $regkeyName)
{
try
{
if($regkeyName -eq "" -or $regkeyName -eq $null)
{
return $oReg = Get-ItemProperty $registryPath -ErrorAction stop;
}else{
return $oReg = Get-ItemProperty $registryPath | select $regkeyName -ErrorAction stop;
}
}
catch
{
switch ($Error[0].Exception.GetType().FullName)
{
# HRESULT 0x80070002: ERROR_FILE_NOT_FOUND - Severity: FAILURE (1), FACILITY_WIN32 (0x7), Code 0x2
# If UseActiveDirectory RegValue DOES NOT EXIST the agent for this Management Group IS AD Integrated
'System.Management.Automation.ItemNotFoundException' {
CheckADRegKeyType($registryPath);
break;
}
default {
Write ("\nSourceType: " + $SourceType);
PrintError($Error);
}
}
}
}

function CheckADRegKeyType($registryPath)
{
Write-Host("\nRegistry Path: " + $registryPath);

$regExCriteria = '(Primary|Secondary) SCP Info\s{0,1}\d*';
Write-Host ("Registry Criteria: " + $regExCriteria);

$matchResults = $registryPath -imatch $regExCriteria;
Write-Host ("RegEx Results: " + $matchResults);

if ($matchResults -ne $null)
{
switch ($matchResults)
{
"Primary SCP Info" {
$ENU_MESSAGE = $ENU_MESSAGE_BASE;
$ENU_MESSAGE += "Could not find " + "\" + $registryPath + "\" + "\n";
$ENU_MESSAGE += "The HealthService needs at least a primary management server to communicate.\n";
$ENU_MESSAGE += "This may indicate that the following:\n";
$ENU_MESSAGE += "\t* HealthService has not queried and cached the AD SCPs yet\n";
$ENU_MESSAGE += "\t* HealthService doesn't have access to any SCPs, yet is configured for AD Integration\n";
$ENU_MESSAGE += "Match results: " + $matchResults[1];
$oAPI.LogScriptEvent($SCRIPT_NAME, 6028, $EVENTLOG_WARNING_TYPE, $ENU_MESSAGE);
Exit 1;
break;
}
"Secondary SCP Info " {
Write ("\nCould not find \ $matchResults[1] \ Service DNS Name\ under \ $SecondarySCPInfoRootRegKey \");
Write ("\nThis is not a fatal error as the HealthService may not have any failovers.");
Write ("\nMatch results: " + $matchResults[1]);
break;
}
default {
throw("Unknown RegKey Type");
}
}
}
}


function PrintError($error)
{
Write ("============================= BEGIN ERROR =================================\n");
Write ("Error Type : " + $error);
Write ("Error Number : " + $Error[0].Exception.GetType().FullName);
#Write ("Error Code : " + ($error.Count -band 0xFFFF));
#Write ("Win32 Facility : " + ($error.number -shr 16 -band 0x1FFF));
Write ("Error Source : " + $error.Source);
Write ("Error Description : " + $error.description);
Write ("============================== END ERROR ==================================\n");
}





Write ("`nSourceType: " + $SourceType);
Write ("SourceId " + $SourceId);
Write ("ManagedEntityId: " + $ManagedEntityId);
Write ("ComputerIdentity: " + $ComputerIdentity);
Write ("ManagementGroupName: " + $ManagementGroupName);
$oAPI = new-object -comobject "MOM.ScriptAPI"
$SCRIPT_NAME = "DiscoverHealthServiceCommunicationRelationships.ps1";
$ENU_MESSAGE_BASE = "HealthServiceCommuncation relationship discovery for HealthServices configured via AD Integration\n\r";
$MAX_FAILOVERS = 10;

$EVENTLOG_SUCCESS = 0x0000; # Information event */
$EVENTLOG_AUDIT_FAILURE = 0x0010; # Failure Audit event */
$EVENTLOG_AUDIT_SUCCESS = 0x0008; # Success Audit event */
$EVENTLOG_ERROR_TYPE = 0x0001; # Error event */
$EVENTLOG_INFORMATION_TYPE = 0x0004; # Information event */
$EVENTLOG_WARNING_TYPE = 0x0002; # Warning event */

# Checking for the EnableADIntegration and UseActiveDirectory keys are also done in the DiscoverAgentRelationships.ps1 discovery
# That script actually updates the HealthService.ActiveDirectoryManaged property as well as submits discovery data for
# the AgentRelationshipSettings object. These checks are duplicated here just for error checking in case the RegKeys were
# manually removed and we have not run discovery yet.
$MOMCONNECTOR_CLSID = "{534E71F9-7970-42D6-921F-59CFB873855F}"; # MomConnecotr CLSID */
$EnableADIntegrationRegValue = "HKLM:\SYSTEM\CurrentControlSet\Services\HealthService\Parameters\ConnectorManager";
$UseActiveDirectoryRegValue = "HKLM:\SOFTWARE\Microsoft\Microsoft Operations Manager\3.0\Agent Management Groups\" + $ManagementGroupName;
$PrimarySCPInfoRegValue = "HKLM:\SOFTWARE\Microsoft\Microsoft Operations Manager\3.0\Agent Management Groups\" + $ManagementGroupName + "\AD Cache\Primary SCP Info";
$SecondarySCPInfoRootRegKey = "HKLM:\SOFTWARE\Microsoft\Microsoft Operations Manager\3.0\Agent Management Groups\" + $ManagementGroupName + "\AD Cache\Secondary SCP Info Root\";
$ConnectorCLSIDRegValue = "HKLM:\SYSTEM\CurrentControlSet\services\HealthService\Parameters\Management Groups\" + $ManagementGroupName
try
{
$ConnectorCLSID = Get-ItemProperty $ConnectorCLSIDRegValue -ErrorAction stop
$ConnectorCLSID = $ConnectorCLSID.'Connector CLSID'
}
catch
{
switch ($Error[0].Exception.GetType().FullName)
{
# HRESULT 0x80070002: ERROR_FILE_NOT_FOUND - Severity: FAILURE (1), FACILITY_WIN32 (0x7), Code 0x2
# If ConnectorCLSID RegValue DOES NOT EXIST, the agent for this Management Group IS NOT AD Integrated
'System.Management.Automation.ItemNotFoundException' {
$ConnectorCLSID = "";
break;
}
default {
PrintError($Error);
throw($Error);
}
}
}
if ($ConnectorCLSID -ne $MOMCONNECTOR_CLSID)
{
$oDiscovery = $oAPI.CreateDiscoveryData($SourceType, $SourceId, $ManagedEntityId);
$oDiscovery.IsSnapshot = $false;
return $oDiscovery
}
$EnableADIntegration = SafeRegRead $EnableADIntegrationRegValue "EnableADIntegration"
$EnableADIntegration = $EnableADIntegration.EnableADIntegration
Try
{
$UseActiveDirectory = Get-ItemProperty $UseActiveDirectoryRegValue -ErrorAction stop;
$UseActiveDirectory = $UseActiveDirectory."UseActiveDirectory"
}
Catch
{
switch ($Error[0].Exception.GetType().FullName)
{
# HRESULT 0x80070002: ERROR_FILE_NOT_FOUND - Severity: FAILURE (1), FACILITY_WIN32 (0x7), Code 0x2
# If UseActiveDirectory RegValue DOES NOT EXIST the agent for this Management Group IS AD Integrated
'System.Management.Automation.ItemNotFoundException' {
$UseActiveDirectory = "TRUE";
break;
}
default {
Write ("\nSourceType: " + $SourceType);
PrintError($Error);
throw($Error);
}
}
}


Write ("`nEnableADIntegration value: " + $EnableADIntegration);
Write ("UseActiveDirectory value: " + $UseActiveDirectory);

if ((-not $EnableADIntegration) -or (-not $UseActiveDirectory))
{
$oDiscovery = $oAPI.CreateDiscoveryData($SourceType, $SourceId, $ManagedEntityId);
$oDiscovery.IsSnapshot = $false;
return $oDiscovery
}


if (($EnableADIntegration) -and ($UseActiveDirectory))
{
$PrimarySCPInfo = SafeRegRead $PrimarySCPInfoRegValue "Service DNS Name"
$PrimarySCPInfo = $PrimarySCPInfo."Service DNS Name"
Write ("\nPrimary SCP Info value: " + $PrimarySCPInfo);
}

if (($EnableADIntegration) -and ($UseActiveDirectory))
{
# There can be many Secondary SCP Info reg keys. For RC1, just going to do 10
# In RC2 may change this to WMI StdRegProv so we can enumerate through the Secondary SCP Info Root key
# WshShell.RegRead() doesn't return objects.

$SecondarySCPInfoPrefix = "Secondary SCP Info ";
$SecondarySCPInfoRegKeys = new-object int[] ($MAX_FAILOVERS -1);

for ($i = 0; $i -lt $MAX_FAILOVERS; $i++)
{
if ($PrimarySCPInfo -ne $null)
{
$regPath = $SecondarySCPInfoRootRegKey + $SecondarySCPInfoPrefix + ($i+1).toString();
$regValue = SafeRegRead $regPath "Service DNS Name"
$regValue = $regValue."Service DNS Name"
if ($regValue -ne $null)
{
# Verify Topology
# -- Bad Topo #1: 2 Primary relationships.
# This one can't happen since I only read one specific RegValue and create only 1 relationship instance
# Note that if there are ever any 2 Secondary TARGETs pointing to the same server, its already handled on the server side
# -- Bad Topo #2: Both Primary and Secondary TARGETs point to same DNS Name
if ($PrimarySCPInfo.toString().toLowerCase() -eq $regValue.toString().toLowerCase())
{
$ENU_MESSAGE = $ENU_MESSAGE_BASE
$ENU_MESSAGE += "Invalid topology detected.\n";
$ENU_MESSAGE += "\tRelationship Source (Agent) : " + $ComputerIdentity + "\n";
$ENU_MESSAGE += "\tRelationship Target (Primary SCP Info) : " + $PrimarySCPInfo.toString() + "\n";
$ENU_MESSAGE += "\tRelationship Target (Secondary SCP Info): " + $regValue.toString() + "\n\n";
$ENU_MESSAGE += "Ignoring cached Secondary SCP Info from: " + $regPath + "\n";

$oAPI.LogScriptEvent($SCRIPT_NAME, 6029, $EVENTLOG_WARNING_TYPE, $ENU_MESSAGE);

Write ($PrimarySCPInfo.toString().toLowerCase());
Write ($regValue.toString().toLowerCase());
Write ($ENU_MESSAGE);
}
else
{
$SecondarySCPInfoRegKeys[$i] = $regValue;
}
}
}
}
$SecondarySCPInfoRegKeys = $SecondarySCPInfoRegKeys | Sort-Object
}


if (($PrimarySCPInfo -ne $null) -or ($SecondarySCPInfoRegKeys -ne $null))
{
$oDiscovery = $oAPI.CreateDiscoveryData($SourceType, $SourceId, $ManagedEntityId);

# Discovery data for Primary communication - Microsoft.SystemCenter.HealthServiceCommunication

# Source of HealthServiceCommunication relationship
$oHSCommunicationSource = $oDiscovery.CreateClassInstance("$MPElement[Name='SCLibrary!Microsoft.SystemCenter.HealthService']$");
$oHSCommunicationSource.AddProperty("$MPElement[Name='Windows!Microsoft.Windows.Computer']/PrincipalName$", $ComputerIdentity);

# Target of HealthServiceCommunication relationship
$oHSCommunicationTarget = $oDiscovery.CreateClassInstance("$MPElement[Name='SCLibrary!Microsoft.SystemCenter.HealthService']$");
$oHSCommunicationTarget.AddProperty("$MPElement[Name='Windows!Microsoft.Windows.Computer']/PrincipalName$", $PrimarySCPInfo.toString());

$oHealthServiceCommunication = $oDiscovery.CreateRelationshipInstance("$MPElement[Name='SCLibrary!Microsoft.SystemCenter.HealthServiceCommunication']$");
$oHealthServiceCommunication.Source = $oHSCommunicationSource;
$oHealthServiceCommunication.Target = $oHSCommunicationTarget;

$oDiscovery.AddInstance($oHealthServiceCommunication);

# Discovery data for Secondary failover communcation instances - Microsoft.SystemCenter.HealthServiceSecondaryCommunication
# Can be null since there may be no failovers configured at all
if ($SecondarySCPInfoRootRegKey -ne $null)
{
# Source of HealthServiceSecondaryCommunication relationship
$oHSSecondaryCommunicationSource = $oDiscovery.CreateClassInstance("$MPElement[Name='SCLibrary!Microsoft.SystemCenter.HealthService']$");
$oHSSecondaryCommunicationSource.AddProperty("$MPElement[Name='Windows!Microsoft.Windows.Computer']/PrincipalName$", $ComputerIdentity);

# Target of HealthServiceSecondaryCommunication relationship
$oHSSecondaryCommunicationTarget;

foreach ($key in $SecondarySCPInfoRegKeys)
{
if ($SecondarySCPInfoRegKeys[$key] -ne $null)
{
$oHSSecondaryCommunicationTarget = $oDiscovery.CreateClassInstance("$MPElement[Name='SCLibrary!Microsoft.SystemCenter.HealthService']$");
$oHSSecondaryCommunicationTarget.AddProperty("$MPElement[Name='Windows!Microsoft.Windows.Computer']/PrincipalName$", $SecondarySCPInfoRegKeys[$key].toString());

$oHealthServiceSecondaryCommunication = $oDiscovery.CreateRelationshipInstance("$MPElement[Name='SCLibrary!Microsoft.SystemCenter.HealthServiceSecondaryCommunication']$");
$oHealthServiceSecondaryCommunication.Source = $oHSSecondaryCommunicationSource;
$oHealthServiceSecondaryCommunication.Target = $oHSSecondaryCommunicationTarget;

$oDiscovery.AddInstance($oHealthServiceSecondaryCommunication);
}
}
}

return $oDiscovery
}
</Script></ScriptBody>
<Parameters>
<Parameter>
<Name>SourceType</Name>
<Value>0</Value>
</Parameter>
<Parameter>
<Name>SourceId</Name>
<Value>$MPElement$</Value>
</Parameter>
<Parameter>
<Name>ManagedEntityId</Name>
<Value>$Target/Id$</Value>
</Parameter>
<Parameter>
<Name>ComputerIdentity</Name>
<Value>$Target/Host/Property[Type="Windows!Microsoft.Windows.Computer"]/PrincipalName$</Value>
</Parameter>
<Parameter>
<Name>ManagementGroupName</Name>
<Value>$Target/ManagementGroup/Name$</Value>
</Parameter>
</Parameters>
<TimeoutSeconds>$Config/TimeoutSeconds$</TimeoutSeconds>
</DataSource>
</MemberModules>
<Composition>
<Node ID="DataSource"/>
</Composition>
</Composite>
</ModuleImplementation>
<OutputType>System!System.Discovery.Data</OutputType>
</DataSourceModuleType>