36 Replies Latest reply on Jul 22, 2016 1:23 AM by e.solonin

    How do we programmatically discover the non-interface properties [in Orion] and enable them

    scottfraley

      We are automating the hydration of assets in Orion, and after adding a node, we know how to discover the interfaces, but how do we programmatically discover the non-interface properties and enable them like the sample below?Orion interface discovery ss.png


      Thanks,

      Scott F.


        • Re: How do we programmatically discover the non-interface properties [in Orion] and enable them
          aaswi

          as long as snmp is configured on the device(s) properly, a network discovery (which can be ran on a scheduled basis) will pick these up. 

          • Re: How do we programmatically discover the non-interface properties [in Orion] and enable them
            RichardLetts

            for all except hardware health you add the right set of pollers for the device.

             

                    $swis->Create("Orion.Pollers", {

                    'PollerType'=>$poller,

                    'NetObject'=>"N:$node",

                    'NetObjectType'=>'N',

                    'NetObjectID'=>$node

                    });

             

            Here's a list of the (current) pollers.

             

            N.MulticastRouting.SNMP.MulticastRoutingTable

             

            N.Routing.SNMP.Ipv4CidrRoutingTable

            N.Routing.SNMP.Ipv4RoutingTable

            N.Routing.SNMP.Ipv6RoutingTable

            N.RoutingNeighbor.SNMP.BGP

            N.RoutingNeighbor.SNMP.OSPF

            N.RoutingNeighbor.SNMP.OSPFv3

            N.RoutingNeighbor.SNMP.OSPFv3Juniper

             

            N.Topology_CDP.SNMP.cdpCacheTable

            N.Topology_Layer2.SNMP.Dot1dTpFdb

            N.Topology_Layer2.SNMP.Dot1dTpFdbNoVLANs

            N.Topology_Layer2.SNMP.Dot1qTpFdbNoVLANs

            N.Topology_Layer3.SNMP.ipNetToMedia

            N.Topology_Layer3_IpRouting.SNMP.ipCidrRouter

            N.Topology_Layer3_IpRouting.SNMP.rolesRouter

            N.Topology_LLDP.SNMP.lldpRemoteSystemsData

            N.Topology_PortsMap.SNMP.Dot1dBase

            N.Topology_PortsMap.SNMP.Dot1dBaseNoVLANs

            N.Topology_PortsMap.SNMP.Dot1qVlanEgressPorts

            N.Topology_PortsMap.SNMP.JuniperExVlan

            N.Topology_STP.SNMP.Dot1dStp

            N.Topology_Vlans.SNMP.Dot1q

            N.Topology_Vlans.SNMP.JuniperExVlan

            N.Topology_Vlans.SNMP.VmMembershipSummary

            N.Topology_Vlans.SNMP.VtpVlan

             

            N.VRFRouting.SNMP.JuniperObsolete

            N.VRFRouting.SNMP.JuniperStandard

            N.VRFRouting.SNMP.MPLSVPNObsolete

            N.VRFRouting.SNMP.MPLSVPNStandard

             

            [I haven't found a way to determine which pollers should be added, I turn up what I need for a node, then look to see what pollers got added]

              • Re: Re: How do we programmatically discover the non-interface properties [in Orion] and enable them
                scottfraley

                Wow, do I have to add each one of those in a separate call?

                 

                Also, can you show me what that looks like as a REST call? (What the json body/data needs to look like.)

                Actually, I went back to the PDF docs and I see body data that looks like this: {"PollerType":"hi from curl 2", "NetObject":"N:123", "NetObjectType":"N", "NetObjectID":123}  Although, "hi from curl 2" doesn't make much sense if I'm trying to specify one of the pollers in the list. Can I assume that "$poller" in your example somehow represents, for instance, "N.Routing.SNMP.Ipv4CidrRoutingTable" ?  And if so, is that the string that goes in there, or... ?

                 

                Oh, also, in the documentation it appears that if my poller addition is successful, I get back the swis:// uri of the poller along with it's ID number. Is that correct?  And if my call fails, what should I be looking for as a return value?

                 

                 

                Thanks again,

                Scott Fraley

                  • Re: Re: How do we programmatically discover the non-interface properties [in Orion] and enable them
                    RichardLetts

                    [I use perl + SWIS because the API just works, I've been writing perl code for over 20 years, ]

                     

                    yes, separate calls. :-(

                     

                    $poller is one of the strings

                     

                    I've never had AddPoller fail -- it feels like there is no error checking on the server-side for Create operations given a valid nodeid.

                    I seem to remember that it will add duplicate pollers, and pollers that do not actually exist.

                     

                    In my code, this is called immediately after Creating a Node, so I know that there are no node-pollers assigned yet.

                    I have a chunk of code that matches the OID of the device, and adds the pollers to it.

                    e.g.

                                    if (index($oid,"1.3.6.1.4.1.2636")==0) {

                                            &add_poller($AddedNode,"N.Cpu.SNMP.JuniperJunOS");

                                            &add_poller($AddedNode,"N.Memory.SNMP.JuniperJunOS");

                                            &add_poller($AddedNode,'N.Topology_Layer3.SNMP.ipNetToMedia') if (index($oid,'1.3.6.1.4.1.2636.1.1.1.2.18')==0);

                                            &add_poller($AddedNode,'N.Topology_Layer3.SNMP.ipNetToMedia') if (index($oid,'1.3.6.1.4.1.2636.1.1.1.2.24')==0);

                                            &add_poller($AddedNode,'N.Topology_Layer3.SNMP.ipNetToMedia') if (index($oid,'1.3.6.1.4.1.2636.1.1.1.2.25')==0);

                                            &add_poller($AddedNode,'N.Topology_Layer3.SNMP.ipNetToMedia') if (index($oid,'1.3.6.1.4.1.2636.1.1.1.2.57')==0);

                                    };

                     

                    In another universe I'd pass an array of pollers to the system and it would do that for me, or have an asynchronous API where I just stream requests a-la-SNMP and match the replies up with them...

                    1 of 1 people found this helpful
                    • Re: How do we programmatically discover the non-interface properties [in Orion] and enable them
                      johnny ringo

                      We use something like this SQL Query to programmatically turn off pollers we do not want to use.  We flag devices to apply this script against based on their membership in a group that uses a dynamic query.  You could use this to do the opposite I think.  However, if the node/pollers have not been discovered yet then you will have to work with the discovered nodes.  I am just beginning to look at the schema for the discovery tables, so if you have gain insights into how they work, please post.  thanks


                      UPDATE Pollers SET Enabled = 0

                      WHERE (NetObjectType = 'N') AND

                      (PollerType LIKE '%Routing%'

                      OR PollerType LIKE '%Topology%'

                      OR PollerType LIKE '%VRFRouting%')

                      AND (Enabled = 1)

                      AND

                      (EXISTS (SELECT S.EntityID

                      FROM [ContainerMemberSnapshots] S

                      JOIN [Containers] C ON S.ContainerID = C.ContainerID

                      WHERE S.EntityDisplayName = 'Node' AND C.IsDeleted = '0' AND S.ContainerID = '8'))

                      AND

                      (NetObjectID IN (SELECT S.EntityID

                      FROM [ContainerMemberSnapshots] S

                      JOIN [Containers] C ON S.ContainerID = C.ContainerID

                      WHERE S.EntityDisplayName = 'Node' AND C.IsDeleted = '0' AND S.ContainerID = '8'))

                       

                    • Re: Re: How do we programmatically discover the non-interface properties [in Orion] and enable them
                      scottfraley

                      After talking with the boss, the question we're really trying to ask is, when I hit the List Resources button from the Management pane of a Node Details screen, what's going on in the background, and more importantly, do we have the ability, via the SDK/API, to do the same thing(s) ?

                       

                      For instance, we don't want to add 58+ pollers to any one device just because we don't know which ones go with said device. It seems like List Resources knows how to get just those interfaces/VLANs/etc. that go with the selected Node/device.

                       

                       

                      Thanks!

                        • Re: Re: How do we programmatically discover the non-interface properties [in Orion] and enable them
                          tdanner

                          What the "List Resources" process actually does is somewhat complicated and, unfortunately, not directly exposed through anything you could call.

                           

                          We are testing a possible solution that might give you what you need. I should be able to let you know soon if it works out or not.

                          • Re: Re: How do we programmatically discover the non-interface properties [in Orion] and enable them
                            madhavan

                            Hi,

                             

                            Provided below the powershell script to discover and import results. This is for automatic discovery.

                            In order to add a node via SDK and all the resources of it needs to be discovered and added automatically, follow the below provided steps.

                            In case you need to add a resource that is not found in discovery (like non interface resources), you can added the specific poller to the node and rediscover to see that resource on the UI (As mentioned by Richard Letts).

                             

                            #Step 1) Create Core plugin Configuration - IP ranges, subnets, IP bulk list, credentials

                            # You can provide the desired IPs or IP Ranges or Subnets as in the UI with already configured credentials.

                            # Query Orion.Credential to get the desired Credential ID

                             

                            $xmlParam = ([xml]"

                            <CorePluginConfigurationContext xmlns:i='http://www.w3.org/2001/XMLSchema-instance' xmlns='http://schemas.solarwinds.com/2012/Orion/Core'>

                            <BulkList>

                            <IpAddress>

                            <Address>10.199.3.1</Address>

                            </IpAddress>

                            <IpAddress>

                            <Address>10.199.2.22</Address>

                            </IpAddress>

                            <IpAddress>

                              <Address>2001:1:0:104:250:56ff:fe90:68dd</Address>

                              </IpAddress>          

                            </BulkList>

                            <IpRanges>

                            <IpAddressRange>

                              <StartAddress>10.199.1.1</StartAddress>

                              <EndAddress>10.199.2.1</EndAddress>

                            </IpAddressRange>

                            </IpRanges>

                            <Subnets/>

                            <Credentials>     

                            <SharedCredentialInfo>

                              <CredentialID>4</CredentialID>

                            <Order>1</Order>

                            </SharedCredentialInfo>   

                            <SharedCredentialInfo>

                              <CredentialID>2</CredentialID>

                            <Order>2</Order>

                            </SharedCredentialInfo> 

                            <SharedCredentialInfo>

                              <CredentialID>1</CredentialID>

                            <Order>3</Order>

                            </SharedCredentialInfo>   

                            <SharedCredentialInfo>

                            <CredentialID>5</CredentialID>

                            <Order>4</Order>

                            </SharedCredentialInfo> 

                            </Credentials>

                            <WmiRetriesCount>1</WmiRetriesCount>

                              <WmiRetryIntervalMiliseconds>1000</WmiRetryIntervalMiliseconds>

                            </CorePluginConfigurationContext>"

                            ).DocumentElement

                             

                            $coreCfg = Invoke-SwisVerb $SWIS_Connection "Orion.Discovery" "CreateCorePluginConfiguration" @($xmlParam)

                             

                            $coreCfgText = $coreCfg.InnerXml

                             

                            #--------------------------------------------------------------------------------------------------

                             

                            #Step 2) Create VIM plugin Configuration

                             

                            $vimParam = ([xml]"

                            <VimPluginConfigurationContext xmlns:i='http://www.w3.org/2001/XMLSchema-instance' xmlns='http://schemas.solarwinds.com/2012/Orion/VIM'>

                            <Enabled>true</Enabled>

                            <Credentials>

                            <SharedCredentialInfo>

                              <CredentialID>3</CredentialID>

                            </SharedCredentialInfo>

                            </Credentials>

                            </VimPluginConfigurationContext>"

                            ).DocumentElement

                             

                            $vimCfg = Invoke-SwisVerb $SWIS_Connection "Orion.VIM.Discovery" "CreateVimPluginConfiguration" @($vimParam)

                             

                            $vimCfgText = $vimCfg.InnerXml

                            #--------------------------------------------------------------------------------------------------

                             

                            #Step 3) Create Discovery Configuration

                            # You can modify various parameters like Engine ID, SNMPPort,.. based on your environment

                             

                            $startDiscoveryParam = ([xml]@("

                            <StartDiscoveryContext xmlns:i='http://www.w3.org/2001/XMLSchema-instance' xmlns='http://schemas.solarwinds.com/2012/Orion/Core'>

                            <Name>AutomaticDiscovery1</Name>

                            <EngineId>1</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>$coreCfgText</PluginConfigurationItem>

                            </PluginConfiguration>",

                            "<PluginConfiguration>

                            <PluginConfigurationItem>$vimCfgText</PluginConfigurationItem>

                            </PluginConfiguration>",

                            "</PluginConfigurations>

                            </StartDiscoveryContext>"

                            )).DocumentElement   

                             

                                Invoke-SwisVerb $SWIS_Connection "Orion.Discovery" "StartDiscovery" @($startDiscoveryParam) | Out-Null

                              • Re: How do we programmatically discover the non-interface properties [in Orion] and enable them
                                humejo

                                Little bit of an old post I know, and also excuse my lack of knowledge as I am still quite new to the SDK and don't have a ton of scripting/programming experience in my background.  I'm trying to find a way to automate cleaning up orphaned volumes.  There seem to be helpful verbs and swql data for cleaning up interfaces, but not a lot for volumes.

                                 

                                I write all of the below out not because you necessarily need to know all of it, but because I wanted to not only document the basic steps that I think should be taken for my own reference, but also to have others weigh in on whether or not this is the best, most efficient approach and maybe make suggestions on how to improve one or many of these steps.

                                 

                                Mostly, I originally replied to ask a single question though.  madhavan, in your reply above that contains the "powershell script to discover and import results" I don't actually see how the script imports the results?  It creates and starts a discovery, but then the script just ends.  Did it get cut off or is there something obvious I'm missing?

                                 

                                Anyways, I came across this post while researching the automation of fixing orphaned volumes, mostly because my thinking is that I will need to do the following (I will be using powershell to accomplish this):

                                • query swql for a list of volumes that are not responding and whose index is equal to 0 (this is the way I identify them in my custom report, so if there is a better indicator of orphaned volumes, please let me know).
                                • Then, run a discovery up against the nodes that have orphaned volumes from the previous query (because this post seems to indicate there is no way to programmatically do a List Resources against each node using the SDK).
                                • Import the Volumes found in this discovery (The best way I can think to do this would be to:)
                                  • query the DiscoveredVolumes table and compare the first 3 characters of the volumes found there against the orphaned volumes where the Node Name and/or IP match as well as the drive letter matches (I'm only concerned with Windows volumes at this point) but the label can be different (a SubString function in SWQL seems to be able to allow me to just compare the first 3 characters).  Also, I'm not exactly sure how to match items in there since the Node and Volume ID's that the DiscoveredVolumes and DiscoveredNodes tables have in no way match the actual NodeID and VolumeID numbers of nodes and volumes previously imported into the Orion database.  I imagine I can use the GetDiscoveryProgress verb to get some info about the discovery right after it was started, including the ProfileID, then, once it completes, only compare Volumes in that Profile to my orphaned results?
                                  • Then (and this is where I'm not sure what to do as well) import just the Volumes from this discovery (I'm not concerned with anything else that the discovery found, just the matching orphaned volumes that have ":\" in the caption).  I know there is an ImportDiscoveryResults verb, and I see the info in the Metadata.VerbArguments table, but I'm not really sure how to use it as the verb arguments don't exactly clear up a lot of mystery for a noob like me...
                                • Next would be to delete the old orphaned volumes, however I would want to do another check here to verify I'm only deleting orphaned volumes where a new matching drive letter was imported to replace them.  In other words, if drives C:\ D:\ and E:\ were orphaned on a Node, but the discovery only found new versions of C:\ and D:\ on that Node, I would not want the script to delete drive E:\, since nothing replaced it.  It should only delete the old C:\ and D:\.  Drive E:\ can maybe be logged or have its Comments custom property updated to state that the script could not find a replacement volume for it and that a user should manually investigate it.

                                 

                                Sorry for the length of this, like I said, this was mostly just to ask a question (at first) and then to document the steps while I was thinking about them, and if it helps someone else that needs the same thing, then cool, that's a bonus.

                                 

                                Thanks!

                                Jordan

                                  • Re: How do we programmatically discover the non-interface properties [in Orion] and enable them
                                    johnny ringo

                                    I concur.  tdanner, madhavan,

                                    Is what Jordan describes correct?  I am looking at my discovered Nodes, Discovered volumes tables and it is unclear what is populating them as they only have a few nnodes in the former table and nothing in the latter.  Like Jordan said I am also trying to automate the import of nodes, volumes, etc.  thanks

                                    • Re: How do we programmatically discover the non-interface properties [in Orion] and enable them
                                      madhavan

                                      Hi,

                                       

                                      Your method for finding the orphaned volumes looks correct.

                                       

                                      Removing a orphaned volume from the system

                                       

                                      use the below provided powershell script. This will work for volumes that are already added to the system.

                                       

                                      $uris = Get-SwisData $swis "Select Uri from Orion.Volumes where VolumeIndex = 0 and VolumeResponding = 'N'"
                                      $uris | Remove-SwisObject $swis 
                                      
                                      


                                      ImportDiscoveryResults


                                      Discovery is a 2 step process - Discover and Import.


                                      Discover - Discovers all the interfaces, volumes for nodes to be discovered. Once the discovery is complete, you can see the discovered nodes, volumes, interfaces in the corresponding entities Orion.DiscoveredNodes, Orion.DiscoveredVolumes and Orion.DiscoveredInterfaces.

                                      Import - Imports all the discovered details to the system for monitoring.


                                      In the script provided in this thread, you can see an entry <IsAutoImport>true</IsAutoImport> in StartDiscoveryContext. This entry determines whether Import should happen immediately after Discovery or will be imported manually later.


                                      ImportDiscoveryResults verb is used here, provide the profile id and also nodes to be imported (incase you need to import specific nodes) and invoke the verb so import happens.


                                      I don't think removing orphaned volumes has nothing to do with discovery. But if you want to filter some discovered volumes / interfaces from import, you need to manually remove it from the discoveredVolumes, discoveredinterfaces database tables before invoking ImportDiscoveryResults verb (this operation is not advisable as it involves direct sql operation and not controlled by the product)




                                    • Re: Re: How do we programmatically discover the non-interface properties [in Orion] and enable them
                                      johnny ringo

                                      Hi @madhavan,

                                      Question about using these discovery verbs in NPM 11.5.2.  Do you have to provide all of the xml information you list above even if the discovery is already present in the Discovery Profiles table?  I am just trying to automate running a discovery but powershell keeps throwing an error saying "StartDiscovery cannot unpackage parameter 0".  Here s a subset of my script:

                                       

                                      $uri= Get-swisdata $swis "SELECT v.URI FROM Orion.DiscoveryProfiles AS V WHERE ProfileID= '146' "

                                      $out=Invoke-SwisVerb $swis "Orion.Discovery" "StartDiscovery" @($uri) | out-null

                                       

                                      I also may need another arguement for this verb but I can't find documentation on this verb to verify for sure.

                                       

                                      thanks