Writing a Management Pack Discovery Script For A Custom MP

1.7k views Asked by At

CONTEXT: Creating a custom management pack for SCOM[System Center]. Working on the script discovery stage presently.

When ran, my script returns the required values from a rest endpoint exposed in json.

###########
## Authentication variables
$user = "darthMaul"
$pwd = "!deathstar" | ConvertTo-SecureString -asPlainText -Force
$limit = 1

function GetServiceStates($offset)
{

    $defUrl = "https://demo1.galacticempire.co.uk/tie-fighter/api/v2/service_states?limit=$limit&offset=$offset"
    $cred = New-Object System.Management.Automation.PSCredential($user,$pwd)
    #$stackStatus = Invoke-WebRequest -Uri $url -Credential $cred
    $stackStatus = Invoke-RestMethod -Uri $defUrl -Credential $cred

    if ($stackStatus.Count -ge 1) {
        #appends only the service url for an individual service
        $parsedUrls = $stackStatus.serviceUrl
        #secure requests required else the call fails
        $UrlsParsed = $parsedUrls.Replace("http","https")
        #$UrlsParsed 

        #for each service found perform an addition call to determine the status of the service. 
        foreach ($Url in $UrlsParsed)
        {
            $sep = Invoke-WebRequest -uri $url -Credential $cred
            $svcStatus = $sep | select @{name="Response";Expression ={$_.statuscode}}, @{name="Status";Expression ={$_.statusdescription}} 
            $svcCall = $sep | ConvertFrom-Json | select displayname, serviceTypeUrl, port, serviceport

            $svcStatus | Add-Member -MemberType NoteProperty -Name displayname -Value $svcCall.displayname
            $svcStatus | Add-Member -MemberType NoteProperty -Name serviceTypeUrl -Value $svcCall.serviceTypeUrl
            $svcStatus | Add-Member -MemberType NoteProperty -Name port -Value $svcCall.port
            $svcStatus | Add-Member -MemberType NoteProperty -Name servicePort -Value $svcCall.servicePort
            $svcStatus | ft
            $offset++

        }

            if($offset -ge $limit){
                GetServiceStates($offset)
            }

    } 
}

GetServiceStates(0)

FYI results look like this enter image description here


DIFFICULTY/PROBLEM/CHALLENGE: Having some trouble converting this into a discovery object.
Here's my breaking script.

param($sourceId,$managedEntityId)

## Authentication variables
$user = "darthMaul"
$pwd = "!deathstar" | ConvertTo-SecureString -asPlainText -Force
$limit = 1

$api = New-Object -comObject 'MOM.ScriptAPI'
$discoveryData = $api.CreateDiscoveryData(0, $sourceId, $managedEntityId)
#Log script event
#$api.LogScriptEvent('Scripts/ManageAppServiceStatus.ps1',999,4,$service)

$defUrl = "https://demo1.galacticempire.co.uk/tie-fighter/api/v2/service_states?limit=$limit&offset=$offset"
$cred = New-Object System.Management.Automation.PSCredential($user,$pwd)
$stackStatus = Invoke-RestMethod -Uri $defUrl -Credential $cred

if ($stackStatus.Count -ge 1) 
{
    #appends only the service url for an individual service
    $parsedUrls = $stackStatus.serviceUrl
    #secure requests required else the call fails
    $UrlsParsed = $parsedUrls.Replace("http","https")
    #$UrlsParsed 

    #for each service found perform an addition call to determine the status of the service. 
    foreach ($Url in $UrlsParsed)
    {
        #create discoverty instance
        $instance = $discoveryData.CreateClassInstance("$MPElement[Name='StackAppServiceStatus.Discovery.ProbeService']$")

        $sep = Invoke-WebRequest -uri $url -Credential $cred
        #collects first different data sets
        $svcStatus = $sep | select @{name="Response";Expression ={$_.statuscode}}, @{name="Status";Expression ={$_.statusdescription}} 
        #collects seconds different data sets
        $svcCall = $sep | ConvertFrom-Json | select displayname, serviceTypeUrl, port, serviceport
        #appends both data set together
        $svcStatus | Add-Member -MemberType NoteProperty -Name displayname -Value $svcCall.displayname
        $svcStatus | Add-Member -MemberType NoteProperty -Name serviceTypeUrl -Value $svcCall.serviceTypeUrl
        $svcStatus | Add-Member -MemberType NoteProperty -Name port -Value $svcCall.port
        $svcStatus | Add-Member -MemberType NoteProperty -Name servicePort -Value $svcCall.servicePort
        #formats results
        $svcStatus | ft
        $offset++

        $instance.AddProperty("$MPElement[Name='StackAppServiceStatus.Discovery.ProbeService']/Response$", 'Response' + $svcStatus.response)
        $instance.AddProperty("$MPElement[Name='StackAppServiceStatus.Discovery.ProbeService']/Status$", 'Status' + $svcStatus.status)
        $instance.AddProperty("$MPElement[Name='StackAppServiceStatus.Discovery.ProbeService']/Displayname$", 'Displayname' + $svcStatus.displayname)
        $instance.AddProperty("$MPElement[Name='StackAppServiceStatus.Discovery.ProbeService']/Port$", 'Port' + $svcStatus.port)

        #store all variables into instance
        $discoveryData.AddInstance($instance)

    }

        if($offset -ge $limit)
        {
            GetServiceStates($offset)
        }

} 

$discoveryData = GetServiceStates(0)


Although this is very frustrating, enjoying it. Just need direction or structure of some sort. Any help is appreciated.
Thanks.

ERROR MESSAGE

 Exception calling "CreateDiscoveryData" with "3" argument(s): "Invalid class string (Exception from HRESULT: 0x800401F3 
(CO_E_CLASSSTRING))"
At line:13 char:1
+ $discoveryData = $api.CreateDiscoveryData(0, $sourceId, $managedEntityId)
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [], MethodInvocationException
    + FullyQualifiedErrorId : ComMethodTargetInvocation

You cannot call a method on a null-valued expression.
At line:33 char:9
+         $instance = $discoveryData.CreateClassInstance("$MPElement[Name='StackAp ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (:) [], RuntimeException
    + FullyQualifiedErrorId : InvokeMethodOnNull
1

There are 1 answers

0
Roman Yuferev On

First exception - it looks like that you are not passing target class and discovery class IDs to discovery script correctly, so MOMAPI can't create DiscoveryData instance.

$sourceID must be initialized with $MPElement$ value $managedEntityID must be initialize with $Target/Id$ value

You can read more details about using parameters in scripts there: https://msdn.microsoft.com/en-us/library/hh329047.aspx

The second exception is caused by the first one because discoveryData wasn't created so it's null :)

Good luck! Roman.