<WriteActionModuleType Accessibility="Public" ID="HealthServicesAnalyzeAndRepair">
<Configuration>
<xsd:element xmlns:xsd="http://www.w3.org/2001/XMLSchema" name="LastSamplesIntervalInMinutes" minOccurs="0" type="xsd:integer"/>
<xsd:element xmlns:xsd="http://www.w3.org/2001/XMLSchema" name="TimeoutSeconds" type="xsd:integer"/>
</Configuration>
<OverrideableParameters>
<OverrideableParameter ID="LastSamplesIntervalInMinutes" ParameterType="int" Selector="$Config/LastSamplesIntervalInMinutes$"/>
<OverrideableParameter ID="TimeoutSeconds" ParameterType="int" Selector="$Config/TimeoutSeconds$"/>
</OverrideableParameters>
<ModuleImplementation>
<Composite>
<MemberModules>
<WriteAction ID="WR" TypeID="Windows!Microsoft.Windows.PowerShellWriteAction">
<ScriptName>GetUnhealthyAgents.ps1</ScriptName>
<ScriptBody><Script><![CDATA[#=================================================================================
# Script to analyze health service status and based on status repair the agent via PowerShell
#
# This script will query OperationsManager db.
# Takes a single parameter of time in minutes to get last ping sample, should be around 5 minutes by default.
# since by default ping check sample take every 5 minutes.
# Will be executed all management servers pool.
# For each health service ping status will be executed task
# if ping status equal 0 then restart agent
# if ping status equal 14 (Bad Address) delete agent
# v 1.0
#=================================================================================
$SqlQuery = @"
SELECT
tb.StatusCode
,tb.AgentServerName
,tb.ManagementServerName
,d.HealthServiceFQDN
,d.HealthServiceID
,d.ManagementServer
,d.ManagementServerID
FROM (SELECT
ROW_NUMBER() OVER (PARTITION BY AgentServerName ORDER BY AgentServerName) RN
,Status
,StatusCode
,ResponseTime
,AgentServerName
,ManagementServerName
,TimeGenerated
,DATEADD(MINUTE, ((DATEPART(MINUTE, TimeGenerated) / 5) * 5), DATEADD(HOUR, DATEDIFF(HOUR, 0, TimeGenerated), 0)) AS TimeGeneratedFixed
FROM EventAllView
OUTER APPLY (SELECT
CAST(EventParameters AS XML) AS EventParametersXML) x
OUTER APPLY (SELECT
x.value('Param[1]', 'VARCHAR(80)') AS Status
,x.value('Param[2]', 'VARCHAR(80)') AS StatusCode
,x.value('Param[3]', 'VARCHAR(80)') AS ResponseTime
,x.value('Param[4]', 'VARCHAR(80)') AS AgentServerName
,x.value('Param[5]', 'VARCHAR(80)') AS ManagementServerName
FROM x.EventParametersXML.nodes('/') AS NodeValues (x)) y
WHERE PublisherName = 'ServerConnectivityCheck'
AND DATEADD(MINUTE, ((DATEPART(MINUTE, TimeGenerated) / 5) * 5), DATEADD(HOUR, DATEDIFF(HOUR, 0, TimeGenerated), 0)) >
DATEADD(MINUTE, ((DATEPART(MINUTE, TimeGenerated) / 5) * 5) - $($LastSamplesIntervalInMinutes), DATEADD(HOUR, DATEDIFF(HOUR, 0, TimeGenerated), 0))
) AS tb
JOIN (SELECT
SourceBME.BaseManagedEntityId HealthServiceID
,TargetBME.BaseManagedEntityId ManagementServerID
,SourceBME.DisplayName AS HealthServiceFQDN
,LEFT(SourceBME.DisplayName, CHARINDEX('.', SourceBME.DisplayName) - 1) AS HealthServiceMachineName
,TargetBME.DisplayName AS ManagementServer
FROM Relationship R WITH (NOLOCK)
JOIN (SELECT
hs.BaseManagedEntityId
,hs.DisplayName
FROM State s
LEFT JOIN MaintenanceMode mm
ON s.BaseManagedEntityId = mm.BaseManagedEntityId
JOIN (SELECT BaseManagedEntityId ,Name FROM BaseManagedEntity WHERE BaseManagedTypeId = 'A4899740-EF2F-1541-6C1D-51D34B739491') bme
ON bme.BaseManagedEntityId = s.BaseManagedEntityId
JOIN MTV_HealthService hs
ON hs.BaseManagedEntityId = bme.Name
WHERE MonitorId = 'B59F78CE-C42A-8995-F099-E705DBB34FD4'
AND HealthState <> 1
AND (mm.IsInMaintenanceMode = 0
OR mm.BaseManagedEntityId IS NULL) AND hs.IsAgent=1 ) SourceBME
ON R.SourceEntityID = SourceBME.BaseManagedEntityID
JOIN BaseManagedEntity TargetBME
ON R.TargetEntityID = TargetBME.BaseManagedEntityID
WHERE R.RelationshipTypeId = dbo.fn_ManagedTypeId_MicrosoftSystemCenterHealthServiceCommunication()) d
ON d.HealthServiceFQDN = tb.AgentServerName
WHERE tb.RN = 1
"@
try
{
Foreach($row in $DS.Tables[0].Rows){
if($row["StatusCode"] -eq 0)
{
# the machine answer to ping, it mean restart to agent
$TaskRestart = Get-SCOMTask -Name SCOMAdministrationAddOns.RestartHealthServiceTask
$task_run=Start-SCOMTask -Task $TaskRestart -Instance $MSInstance -Override $override
}
if ($row["StatusCode"] -eq 14){
# the machine have a bad address, it mean the server account in AD was deleted
$TaskDeleteAgent = Get-SCOMTask -Name SCOMAdministrationAddOns.DeleteHealthServiceTask