SCOM On Demand Discovery Example


A little known feature within SCOM is the ability to trigger a discovery manually, sometimes referred to as "on demand".

"This is not to be confused with OnDemandDetection which is an optional component of most monitor types and is also what makes the "Recalculate" feature work in the Health Explorer window."

- Some SCOM Nerd

The procedure can be a bit tricky so here's a quick explanation of how you can manually trigger a discovery. The agent task is located in the "Agents By Version" state view as shown below.

The Trigger On Demand Discovery task includes a default value '$Target/Id$' which is a variable that represents the Target ID of the task target class:
Microsoft.SystemCenter.HealthService
but don’t let this fool you. To run successfully, the task requires the actual InstanceID of the desired Discovery target.

clip_image002[4]

That is to say that the TargetInstanceId must be an instance of a class that must agree with the discovery target class type.
If the discovery targets DBEngine, your TargetInstanceId must be that of a specific DBEngine object.

EXAMPLE: This discovery below discovers SQL agents, but the discovery targets the DBEngine.

Discovery: MSSQL on Windows: Discover SQL Server Agent for a Database Engine

Note: Graph in screenshot created with New-SCOMClassGraph. List of all graphs from my 2016 lab HERE.

Identify the the Discovery:
The easiest way to identify all discoveries associated with a class (there can be more than one) is with a graph like the one shown below. Once you identify the correct class type that you wish to discover, you can create the graph. With the graph, you can identify the related discovery ID (DiscoveryId) and the ID of the discovery target class type. We still need to find the ID of the specific instance of that target class type (TargetInstanceId).

clip_image003[4]
# Get DB Engine ID
$Engine = (Get-SCOMClass -Name Microsoft.SQLServer.Windows.DBEngine | Get-SCOMClassInstance | ? {$_.fullname -match 'devdb01'} ).Id.Guid

# Another way to reveal the Discovery ID
$Disco = (Get-SCOMDiscovery -Name 'Microsoft.SQLServer.Windows.Discovery.Agent').Id.Guid

Write-Host "Engine: $Engine" -F Red
Write-Host "Discovery: $Disco" -F Green 

The discovery targets a DBEngine, specifically, "Microsoft.SQLServer.Windows.DBEngine".
I must determine the ID of a specific DBEngine instance, in this case my lab machine, "devdb01"

clip_image005[4]


Shown below I have the Id of the discovery to run along with the specific DBEngine instance ID (which lives on my dev server).

clip_image007[4]
clip_image009[4]


For your convenience, here's a snippet to do this with PowerShell

<# 
    Description: OnDemand Discovery Example
    Author: Tyson Paul
    Date: 2022.11.21
#>

$AgentName = 'devdb01.contoso.com' #FQDN of agent
$TargetInstanceDisplayName = 'DEVDB01\MSSQLSERVER' #A specific instance of the discovery target type/class.

# Discovery workflow
$Discovery = (Get-SCOMDiscovery -DisplayName 'MSSQL on Windows: Discover SQL Server Agent for a Database Engine')

# OnDemand discovery task
$Task = Get-SCOMTask -Name 'Microsoft.SystemCenter.TriggerOnDemandDiscovery'

# Retrieve the agent for which the task should be executed.
$HealthService = Get-SCOMClass -Id $Task.Target.Id | Get-SCOMClassInstance  | ? {$_.DisplayName -eq $AgentName }

# Retrieve the specific target instance for the discovery workflow.
$TrgtInstance = Get-SCOMClass -Id $Discovery.Target.Id | Get-SCOMClassInstance | ? {$_.DisplayName -eq $TargetInstanceDisplayName }

# Required overrides for the OnDemand discovery task
$TaskOverrides = @{
    "DiscoveryId" = [string]($Discovery.Id)
    "TargetInstanceId" = [string]($TrgtInstance.Id)
    "TaskTimeoutSeconds" = [string]'60'
}

<# 
    Kick off the task, feed it the agent instance along with the hashtables of overrides.
    This example is shown executed with default credentials (credentual is null).
#>
$RunningTask = Start-SCOMTask -Instance $HealthService -Task $Task -TaskCredentials $null -Override $TaskOverrides

Start-Sleep -Seconds 3
$TaskResult = Get-SCOMTaskResult -BatchID $RunningTask.BatchId
If (-NOT $TaskResult.Output) {
  Write-Host "`nNo task result available yet. Run the following command to view the task output:" -ForegroundColor Cyan
  Write-Host 'Get-SCOMTaskResult -BatchID $RunningTask.BatchId.Guid' -ForegroundColor Yellow
}
Else {
  $TaskResult
}

Leave a Reply

Your email address will not be published. Required fields are marked *