Create Discovery for Agent via API

Hey Thwackers,

I'm looking to do targeted re-discoveries of some of our server nodes automatically via the API which includes both SNMPv2c, and agent nodes. The primary goal is to rediscover and add new volumes, however another goal as well would be to initially add volumes and interfaces once the nodes get created automatically via the API as well (or an agent is registered).

All the documentation is essentially for discovery of SNMP or WMI nodes. Does anyone happen to know how to adjust the XML for the script up on GitHub to accommodate for Agents? In my own digging, I've taken a look at some of the XML from creating a discovery via the web UI and have been attempting to inject it into the CorePluginConfiguration (with little success).

What I found are these settings but I'm not sure where they may go or which ones are required and the appropriate syntax either (or better yet... if this is even technically supported via the API yet)

<AgentsFilterDefinition>filter:/Orion.Nodes</AgentsFilterDefinition>
<AgentsFilterQuery>1=1</AgentsFilterQuery>

https://github.com/solarwinds/OrionSDK/blob/master/Samples/PowerShell/DiscoverSnmpV3Node.ps1

Any and all help and/or suggestions appreciated, thanks!

Parents
  • The discovery process is the same for all nodes irrespective of the polling method. The purpose of 'Check existing nodes polled by agent' in the discovery workflow is to keep all or a subset of agents updated. It has been a while since I last looked at this but if I remember the easiest way I have found to check what XML is expected is to 1st create the profile in the UI ad then check out the PluginConfigurations field in the DiscoveryProfiles table directly in the database, This contains the <DiscoveryPluginConfigurationBase> element which should show what you are looking for.

    This KB may also help https://support.solarwinds.com/SuccessCenter/s/article/Update-resources-on-an-agent-node-using-SWQL?language=en_US

    Here is an example of the XML element for reference

    <DiscoveryPluginConfigurationBase xmlns:d2p1="http://schemas.solarwinds.com/2008/Orion" i:type="d2p1:CoreDiscoveryPluginConfiguration">
    				<d2p1:ActiveDirectoryList/>
    				<d2p1:AddressRange/>
    				<d2p1:AgentsAddresses xmlns:d3p1="http://schemas.microsoft.com/2003/10/Serialization/Arrays"/>
    				<d2p1:AgentsFilterDefinition>filter:/Orion.Nodes[IsServer='True']</d2p1:AgentsFilterDefinition>
    				<d2p1:AgentsFilterQuery>Nodes.IsServer = 'True'</d2p1:AgentsFilterQuery>
    				<d2p1:AutoImportVolumeTypes xmlns:d3p1="http://schemas.datacontract.org/2004/07/SolarWinds.Common.Snmp">
    					<d3p1:VolumeType>Unknown</d3p1:VolumeType>
    					<d3p1:VolumeType>Other</d3p1:VolumeType>
    					<d3p1:VolumeType>RAM</d3p1:VolumeType>
    					<d3p1:VolumeType>VirtualMemory</d3p1:VolumeType>
    					<d3p1:VolumeType>FixedDisk</d3p1:VolumeType>
    					<d3p1:VolumeType>RAMDisk</d3p1:VolumeType>
    					<d3p1:VolumeType>FlashMemory</d3p1:VolumeType>
    					<d3p1:VolumeType>NetworkDisk</d3p1:VolumeType>
    					<d3p1:VolumeType>MountPoint</d3p1:VolumeType>
    				</d2p1:AutoImportVolumeTypes>
    				<d2p1:BulkList xmlns:d3p1="http://schemas.microsoft.com/2003/10/Serialization/Arrays"/>
    				<d2p1:Credentials i:nil="true"/>
    				<d2p1:DiscoverAgentNodes>true</d2p1:DiscoverAgentNodes>
    				<d2p1:PreferredPollingMethod>WMI</d2p1:PreferredPollingMethod>
    				<d2p1:SharedCredentials xmlns:d3p1="http://schemas.microsoft.com/2003/10/Serialization/Arrays">
    					<d3p1:KeyValueOfintint>
    						<d3p1:Key>0</d3p1:Key>
    						<d3p1:Value>4</d3p1:Value>
    					</d3p1:KeyValueOfintint>
    					<d3p1:KeyValueOfintint>
    						<d3p1:Key>1</d3p1:Key>
    						<d3p1:Value>5</d3p1:Value>
    					</d3p1:KeyValueOfintint>
    				</d2p1:SharedCredentials>
    				<d2p1:SubnetList>
    					<d2p1:Subnet>
    						<d2p1:Selected>true</d2p1:Selected>
    						<d2p1:SubnetIP>10.199.20.0</d2p1:SubnetIP>
    						<d2p1:SubnetMask>255.255.255.0</d2p1:SubnetMask>
    					</d2p1:Subnet>
    				</d2p1:SubnetList>
    				<d2p1:WMICredentials/>
    				<d2p1:WmiRetries>1</d2p1:WmiRetries>
    				<d2p1:WmiRetryInterval>PT10S</d2p1:WmiRetryInterval>
    			</DiscoveryPluginConfigurationBase>

  • Thank you  for the tips! I'll give this a whirl and spend some more time digging into it.

Reply Children
  • I think I've hit a wall here. I've thrown quite a bit at attempting the XML markup expected and nothing I seem to do will work. Some values I notice don't show up the same once the configuration is invoked from the context created.. For example we set the property <WmiRetriesCount> and <WmiRetryIntervalMiliseconds>, however they get converted to <WmiRetries> and <WmiRetryInterval> when invoking creation of the configuration. Attempting to create the configuration with the latter results in a failure. So while digging into the database is quite useful to help understand some of it -- it doesn't provide much insight in the way of determining the appropriate XML markup and properties to get this going. Disappointed

    I've got a mock script put together (patched together from the various different sources of the API discoveries) and I'm trying to get it to be super simple for now until I get it working.

    Unfortunately I cannot make sense of this and there's very little guidance / documentation around it. The script below works just fine and appears to run a discovery against SNMP nodes but so far no dice with getting any agent settings in there.

    The values for the agent settings always show up like so still regardless of how I've put it together.

    Any help appreciated. Thanks

    <d2p1:AgentsAddresses xmlns:d3p1="http://schemas.microsoft.com/2003/10/Serialization/Arrays" />
    <d2p1:AgentsFilterDefinition i:nil="true" />
    <d2p1:AgentsFilterQuery i:nil="true" />
    <d2p1:DiscoverAgentNodes>false</d2p1:DiscoverAgentNodes>

    <# finding the default values SQL query:
    
    SELECT dp.Name, dp.IsHidden, dp.IsAutoImport, dp.Status, dp.StatusDescription
    , SUBSTRING(dp.PluginConfigurations, CHARINDEX('PreferredPollingMethod', dp.PluginConfigurations) + 23, 4) AS [PreferredPollingMethod]
    , SUBSTRING(dp.PluginConfigurations, CHARINDEX('DiscoverAgentNodes', dp.PluginConfigurations) + 19, 5) AS [DiscoverAgentNodes]
    , dp.PluginConfigurations
    FROM SolarWindsOrion.dbo.DiscoveryProfiles AS dp
    WHERE ( dp.Name IS NOT NULL AND dp.Name != '' )
    ORDER BY dp.Name DESC
    
    #>
    
    Import-Module -Name SwisPowerShell
    
    $swis = Connect-Swis -Hostname 'hostname' -Username 'username' -Password 'password'
    
    $ip = 'x.x.y.y'
    $credentialsId = '0'
    $engindId = '0'
    
    $CorePluginConfigurationContext = ([xml]"
    <CorePluginConfigurationContext xmlns='http://schemas.solarwinds.com/2012/Orion/Core' xmlns:i='http://www.w3.org/2001/XMLSchema-instance'>
        <ActiveDirectoryList />
        <AddressRange />
        <AgentsAddresses xmlns:a='http://schemas.microsoft.com/2003/10/Serialization/Arrays'>
            <AgentsFilterDefinition>filter:/Orion.Nodes</AgentsFilterDefinition>
            <AgentsFilterQuery>1=1</AgentsFilterQuery>
        </AgentsAddresses>
        <AutoImportVolumeTypes xmlns='http://schemas.datacontract.org/2004/07/SolarWinds.Common.Snmp'>
            <VolumeType>FixedDisk</VolumeType>
        </AutoImportVolumeTypes>
        <BulkList>
    		<IpAddress>
    			<Address>$ip</Address>
    		</IpAddress>
    	</BulkList>
    	<Credentials>
    		<SharedCredentialInfo>
    			<CredentialID>$credentialsId</CredentialID>
    			<Order>1</Order>
    		</SharedCredentialInfo>
    	</Credentials>
        <SubnetList />
        <WMICredentials />
        <DiscoverAgentNodes>true</DiscoverAgentNodes>
    	<WmiRetriesCount>1</WmiRetriesCount>
    	<WmiRetryIntervalMiliseconds>1000</WmiRetryIntervalMiliseconds>
        <PreferredPollingMethod>SNMP</PreferredPollingMethod>
    </CorePluginConfigurationContext>
    ").DocumentElement
    
    $CorePluginConfiguration = Invoke-SwisVerb $swis Orion.Discovery CreateCorePluginConfiguration @($CorePluginConfigurationContext)
    
    $InterfacesPluginConfigurationContext = ([xml]"
    <InterfacesDiscoveryPluginContext xmlns='http://schemas.solarwinds.com/2008/Interfaces' xmlns:a='http://schemas.microsoft.com/2003/10/Serialization/Arrays'>
        <AutoImportStatus>
            <a:string>Up</a:string>
        </AutoImportStatus>
        <AutoImportVirtualTypes>
            <a:string>Virtual</a:string>
            <a:string>Physical</a:string>
        </AutoImportVirtualTypes>
        <AutoImportVlanPortTypes>
            <a:string>Trunk</a:string>
            <a:string>Access</a:string>
            <a:string>Unknown</a:string>
        </AutoImportVlanPortTypes>
        <AutoImportExpressionFilter>
            <a:string>{'Prop': 'Name', 'Op': 'Regex', 'Val': '^Eth.*'}</a:string>
        </AutoImportExpressionFilter>
        <UseDefaults>false</UseDefaults>
    </InterfacesDiscoveryPluginContext>
    ").DocumentElement
    
    $InterfacesPluginConfiguration = Invoke-SwisVerb $swis Orion.NPM.Interfaces CreateInterfacesPluginConfiguration @($InterfacesPluginConfigurationContext)
    
    $StartDiscoveryContext = ([xml]"
    <StartDiscoveryContext xmlns='http://schemas.solarwinds.com/2012/Orion/Core' xmlns:i='http://www.w3.org/2001/XMLSchema-instance'>
    	<Name>Script Discovery $([DateTime]::Now)</Name>
    	<EngineId>$engindId</EngineId>
    	<JobTimeoutSeconds>3600</JobTimeoutSeconds>
    	<SearchTimeoutMiliseconds>2000</SearchTimeoutMiliseconds>
    	<SnmpTimeoutMiliseconds>2000</SnmpTimeoutMiliseconds>
    	<SnmpRetries>1</SnmpRetries>
    	<RepeatIntervalMiliseconds>1500</RepeatIntervalMiliseconds>
    	<SnmpPort>161</SnmpPort>
    	<HopCount>0</HopCount>
    	<PreferredSnmpVersion>SNMP2c</PreferredSnmpVersion>
    	<DisableIcmp>false</DisableIcmp>
    	<AllowDuplicateNodes>false</AllowDuplicateNodes>
    	<IsAutoImport>true</IsAutoImport>
    	<IsHidden>false</IsHidden>
    	<PluginConfigurations>
    		<PluginConfiguration>
    			<PluginConfigurationItem>$($CorePluginConfiguration.InnerXml)</PluginConfigurationItem>
                <PluginConfigurationItem>$($InterfacesPluginConfiguration.InnerXml)</PluginConfigurationItem>
    		</PluginConfiguration>
    	</PluginConfigurations>
    </StartDiscoveryContext>
    ").DocumentElement
    
    $DiscoveryProfileID = (Invoke-SwisVerb $swis Orion.Discovery StartDiscovery @($StartDiscoveryContext)).InnerText
    
    Write-Host -NoNewline "Discovery profile #$DiscoveryProfileID running..."
    
    # Wait until the discovery completes
    do {
        Write-Host -NoNewline "."
        Start-Sleep -Seconds 1
        $Status = Get-SwisData $swis "SELECT Status FROM Orion.DiscoveryProfiles WHERE ProfileID = @profileId" @{profileId = $DiscoveryProfileID}
    } while ($Status -eq 1)
    
    $Result = Get-SwisData $swis "SELECT Result, ResultDescription, ErrorMessage, BatchID FROM Orion.DiscoveryLogs WHERE ProfileID = @profileId" @{profileId = $DiscoveryProfileID}
    
    # Print the outcome
    switch ($Result.Result) {
        0 {"Unknown"}
        1 {"InProgress"}
        2 {"Finished"}
        3 {"Error"}
        4 {"NotScheduled"}
        5 {"Scheduled"}
        6 {"NotCompleted"}
        7 {"Canceling"}
        8 {"ReadyForImport"}
    }
    $Result.ResultDescription
    $Result.ErrorMessage
    
    if ($Result.Result -eq 2) { # if discovery completed successfully
        # Find out what objects were discovered
        $Discovered = Get-SwisData $swis "SELECT EntityType, DisplayName, NetObjectID FROM Orion.DiscoveryLogItems WHERE BatchID = @batchId" @{batchId = $Result.BatchID}
        "$($Discovered.Count) items imported."
        $Discovered
    }