cancel
Showing results for 
Search instead for 
Did you mean: 
Create Post
Level 9

Setting CreateCorePluginConfiguration details for Orion.Discovery in python

Jump to solution

I've been trying to manage adding and removing nodes using the API.  My language of choice is python.  I have most of the discovery profile details figured out, but am not able to understand how to set things linke the Volume Types, Vlan Port Types, etc...

I'm not able to figure out how to specify that I only want Flash and Ram volume types. Only Access and Trunk interfaces.

I've tried various permutations of (Look at the code for the details of where this is applied):

    'AutoImportStatus': [{'IfAutoImportStatus':'Up'}],

    'AutoImportVlanPortTypes': [{'Trunk': False}, {'Access':False}]

    'AutoImportVlanPortTypes': [{'VlanPortType':'Trunk'}, {'VlanPortType':'Access'}],

    'AutoImportVolumeTypes': [{'VolumeType': 'FlashMemory'},{'VolumeType': 'RAM'}]

Here is the python code I have so far:

from __future__ import print_function

import re

import requests

from orionsdk import SwisClient

def main():

    npm_server = 'MyServer'

    username = 'MyUser'

    password = 'MyPass'

    names = ['MyDev1','MyDev2','MyDev3']

    bulkList_names = []

    for name in names:

        bulkList_names.append({'Address': name})

    print (bulkList_names)

    orion_engine_id = 1

    swis = SwisClient(npm_server, username, password)

    corePluginContext = {

    'BulkList': bulkList_names,

    'Credentials': [

    {

    'CredentialID': 5,

    'Order': 1

    }

    ],

    'WmiRetriesCount': 0,

    'WmiRetryIntervalMiliseconds': 1000,

    'IsDiscoveryForVimEnabled': False,

#    'AutoImportStatus': [{'IfAutoImportStatus':'Up'}],

#    'AutoImportVlanPortTypes': [{'Trunk': False}, {'Access':False}]

#    'AutoImportVlanPortTypes': [{'VlanPortType':'Trunk'}, {'VlanPortType':'Access'}],

#    'AutoImportVolumeTypes': [{'VolumeType': 'FlashMemory'},{'VolumeType': 'RAM'}]

    }

    corePluginConfig = swis.invoke('Orion.Discovery', 'CreateCorePluginConfiguration', corePluginContext)

    discoveryProfile = {

    'Name': 'API discovery',

    'EngineID': orion_engine_id,

    'JobTimeoutSeconds': 3600,

    'SearchTimeoutMiliseconds': 5000,

    'SnmpTimeoutMiliseconds': 5000,

    'SnmpRetries': 2,

    'RepeatIntervalMiliseconds': 1800,

    'SnmpPort': 161,

    'HopCount': 0,

    'PreferredSnmpVersion': 'SNMP2c',

    'DisableIcmp': False,

    'AllowDuplicateNodes': False,

    'IsAutoImport': True,

    'IsHidden': False,

    'PluginConfigurations': [{'PluginConfigurationItem': corePluginConfig}]

    }

    print("Running discovery...")

    result = swis.invoke('Orion.Discovery', 'StartDiscovery', discoveryProfile)

    print("Returned discovery profile id {}".format(result))

requests.packages.urllib3.disable_warnings()

if __name__ == '__main__':

    main()

0 Kudos
1 Solution

To control what interfaces are imported, you need to create a configuration object for the discovery plugin that handles interfaces by calling Orion.NPM.Interfaces.CreateInterfacesPluginConfiguration. Like this:

interfacesPluginContext = {

  'AutoImportStatus': ['Up'], # Also available: Down, Shutdown

  'AutoImportVlanPortTypes': ['Trunk', 'Access'], # Also available: Unknown

  #'AutoImportVirtualTypes': ['Physical', 'Virtual', 'Unknown'],

  #'AutoImportExpressionFilter': [{'Prop': 'Alias', 'Op': 'Regex', 'Val': '.*Nortel.*'}]

  # Available values for Prop: Type, Name, Descr, Alias, Node, All, Vlan

  # Available values for Op: All, !All, Any, !Any, Equals, !Equals, Regex, !Regex, #All, !#All, #Any, !#Any

  # Val is the literal value to compare Prop to

  # If more than one expression is provided, the interface must match all of the expressions to be imported

  # To specify more than one number or string for the All and Any operators (including variants), separate them by spaces

}

interfacesPluginConfig = swis.invoke('Orion.NPM.Interfaces', 'CreateInterfacesPluginConfiguration', interfacesPluginContext)

Then include this config object in the list of plugin configurations when you create the discovery profile, like this:

discoveryProfile = {

  'Name': 'API discovery',

  'EngineID': orion_engine_id,

  'JobTimeoutSeconds': 3600,

  'SearchTimeoutMiliseconds': 5000,

  'SnmpTimeoutMiliseconds': 5000,

  'SnmpRetries': 2,

  'RepeatIntervalMiliseconds': 1800,

  'SnmpPort': 161,

  'HopCount': 0,

  'PreferredSnmpVersion': 'SNMP2c',

  'DisableIcmp': False,

  'AllowDuplicateNodes': True,

  'IsAutoImport': True,

  'IsHidden': False,

  'PluginConfigurations': [

       {'PluginConfigurationItem': corePluginConfig},

       {'PluginConfigurationItem': interfacesPluginConfig},  # Add your interfaces plugin config here

  ]

}

It is not currently possible to control the set of volumes that get imported during discovery through the API. I recommend you just let it discover all of them and then delete the ones you don't want. To track the discovery and wait for it to complete so you can clean up the volumes, follow the example here: https://github.com/solarwinds/OrionSDK/blob/master/Samples/PowerShell/DiscoverSnmpV3Node.ps1 .

View solution in original post

16 Replies
Level 9

tdanner​ Thanks for the help.  This worked great to wait for the discovery to finish and report on what was discovered. 

Now to get the remove un-needed stuff to work correctly.  I assume that there is some way to remove an entity based on it's NetObjectID. Are there any examples that you can point me to that do this for volumes and interfaces?

Once I'm done doing this I'll post my complete product here so that it hopefully helps others work through these issues.

I haven't posted anything back on this

Here is what I've been using for a couple months:

def solarwindsDiscovery(hosts):

    # Init SWIS API

    npm_server = 'solarwinds-hostname'

    username = 'solarwinds-username'

    password = 'solarwinds-password'

    swis = SwisClient(npm_server, username, password)

    bulkList_hosts = []

    for host in hosts:

        bulkList_hosts.append({'Address': host})

    pprint.pprint(bulkList_hosts)

    # Make Discovery Profile

    orion_engine_id = 1

    corePluginContext = {

        'BulkList': bulkList_hosts,

        'Credentials': [

            {

                'CredentialID': 5,

                'Order': 1

            }

        ],

        'WmiRetriesCount': 0,

        'WmiRetryIntervalMiliseconds': 1000,

        'IsDiscoveryForVimEnabled': False

    }

    corePluginConfig = swis.invoke('Orion.Discovery', 'CreateCorePluginConfiguration', corePluginContext)

    interfacesPluginContext = {

        'AutoImportStatus': ['Up'],  # Also available: Down, Shutdown

        'AutoImportVlanPortTypes': ['Trunk', 'Access', 'Unknown'],  # Also available: Unknown

        # 'AutoImportVirtualTypes': ['Physical', 'Virtual', 'Unknown'],

        # 'AutoImportExpressionFilter': [{'Prop': 'Alias', 'Op': 'Regex', 'Val': '.*Nortel.*'}]

        # Available values for Prop: Type, Name, Descr, Alias, Node, All, Vlan

        # Available values for Op: All, !All, Any, !Any, Equals, !Equals, Regex, !Regex, #All, !#All, #Any, !#Any

        # Val is the literal value to compare Prop to

        # If more than one expression is provided, the interface must match all of the expressions to be imported

        # To specify more than one number or string for the All and Any operators (including variants), separate them by spaces

    }

    interfacesPluginConfig = swis.invoke('Orion.NPM.Interfaces', 'CreateInterfacesPluginConfiguration',

                                        interfacesPluginContext)

    discoveryProfile = {

        'Name': 'API discovery',

        'EngineID': orion_engine_id,

        'JobTimeoutSeconds': 3600,

        'SearchTimeoutMiliseconds': 2000,

        'SnmpTimeoutMiliseconds': 3000,

        'SnmpRetries': 1,

        'RepeatIntervalMiliseconds': 1800,

        'SnmpPort': 161,

        'HopCount': 0,

        'PreferredSnmpVersion': 'SNMP2c',

        'DisableIcmp': False,

        'AllowDuplicateNodes': False,

        'IsAutoImport': True,

        'IsHidden': True,

        'PluginConfigurations': [{'PluginConfigurationItem': corePluginConfig},

                                {'PluginConfigurationItem': interfacesPluginConfig}]

    }

    # Start Discovery

    print("Running discovery...")

    discoveryProfileID = swis.invoke('Orion.Discovery', 'StartDiscovery', discoveryProfile)

    print("Returned discovery profile id {}".format(discoveryProfileID))

    discoveryStatusState = {0: "Unknown", 1: "InProgress", 2: "Finished", 3: "Error", 4: "NotScheduled", 5: "Scheduled",

                            6: "NotCompleted", 7: "Canceling", 8: "ReadyForImport"}

    # Wait until it's done with discovery

    running = True  # InProgress

    while running:

        sys.stdout.write('.')

        sys.stdout.flush()

        query = "SELECT Status FROM Orion.DiscoveryProfiles WHERE ProfileID = " + str(discoveryProfileID)

        result = swis.query(query)

        if len(result['results']) < 1:

            running = False

        time.sleep(5)

    print(' ')

    print('Done with discovery')

    query = "SELECT Result, ResultDescription, ErrorMessage, BatchID FROM Orion.DiscoveryLogs WHERE ProfileID = '" + str(

        discoveryProfileID) + "'"

    result = swis.query(query)['results'][0]

    print(result)

    time.sleep(5)

    if result['Result'] == 2:  # if discovery completed sucessfully

        #  Find out what objects were discovered

        query = "SELECT EntityType, DisplayName, NetObjectID FROM Orion.DiscoveryLogItems WHERE BatchID = '" + result[

            'BatchID'] + "'"

        print(query)

        discovered = swis.query(query)

        pprint.pprint(discovered)

        discoveredNodes = []

        discoveredVolumes = []

        discoveredInterfaces = []

        if len(discovered['results']) > 0:  # dSomething new was discovered

            discoveredItems = discovered['results']

            discoveredNodes = []

            discoveredVolumes = []

            discoveredInterfaces = []

            pprint.pprint(discoveredItems)

            for entry in discoveredItems:

                if entry['EntityType'] == 'Orion.Nodes':

                    discoveredNodes.append(entry)

                if entry['EntityType'] == 'Orion.Volumes':

                    discoveredVolumes.append(entry)

                if entry['EntityType'] == 'Orion.Interfaces':

                    discoveredInterfaces.append(entry)

                    # Remove un-needed stuff

                    # removeVolumes = []

                    # for volume in discoveredVolumes:

                    #    if volume['NetObjectID']

            #removeVolumes.append(volume['NetObjectID'])

            # pprint.pprint(removeVolumes)

            # Perform swis volume removal somehow

            # swis.delete()

0 Kudos

Has anyone tried setting Description in the disocveryProfile? I can't seem to find it documented, but went ahead and tried this, inserting between Name and EngineID:

discoveryProfile = {

    'Name': 'API discovery',

    'Description': 'request_desc',

    'EngineID': 3,

    'JobTimeoutSeconds': 3600,

The discovery completed, but description was not updated, still blank. Any thoughts?

Thanks!!

0 Kudos

This API does not provide a way to set the description of a discovery profile. You can add arbitrary extra fields to the object you send to StartDiscovery, but they will just be ignored by the json parser.

Bummer. Thanks for the quick reply though.

0 Kudos
Level 9

I should mention that I'm working from a XML dump of a manually created discovery profile that has these parts:

<pluginItem>

   <ArrayOfDiscoveryPluginConfigurationBase xmlns:i="http://www.w3.org/2001/XMLSchema-instance"

   xmlns="http://schemas.datacontract.org/2004/07/SolarWinds.Orion.Core.Models.Discovery">

   <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:AutoImportVolumeTypes xmlns:d3p1="http://schemas.datacontract.org/2004/07/SolarWinds.Common.Snmp">

   <d3p1:VolumeType>FlashMemory</d3p1:VolumeType>

   <d3p1:VolumeType>RAM</d3p1:VolumeType>

   </d2p1:AutoImportVolumeTypes>

<DiscoveryPluginConfigurationBase xmlns:d2p1="http://schemas.solarwinds.com/2008/Interfaces"

   i:type="d2p1:InterfacesDiscoveryPluginConfiguration">

   <d2p1:AutoImportExpressionFilter xmlns:d3p1="http://schemas.datacontract.org/2004/07/"/>

   <d2p1:AutoImportStatus

   xmlns:d3p1="http://schemas.datacontract.org/2004/07/SolarWinds.Interfaces.Common.Enums">

   <d3p1:IfAutoImportStatus>Up</d3p1:IfAutoImportStatus>

   </d2p1:AutoImportStatus>

   <d2p1:AutoImportVirtualTypes xmlns:d3p1="http://schemas.datacontract.org/2004/07/System">

   <d3p1:boolean>false</d3p1:boolean>

   <d3p1:boolean>true</d3p1:boolean>

   <d3p1:boolean i:nil="true"/>

   </d2p1:AutoImportVirtualTypes>

   <d2p1:AutoImportVlanPortTypes

   xmlns:d3p1="http://schemas.datacontract.org/2004/07/SolarWinds.Orion.Core.Models.Enums">

   <d3p1:VlanPortType>Trunk</d3p1:VlanPortType>

   <d3p1:VlanPortType>Access</d3p1:VlanPortType>

   <d3p1:VlanPortType>Unknown</d3p1:VlanPortType>

   </d2p1:AutoImportVlanPortTypes>

   <d2p1:DiscoverVLANs>false</d2p1:DiscoverVLANs>

</DiscoveryPluginConfigurationBase>

</ArrayOfDiscoveryPluginConfigurationBase>

</pluginItem>

0 Kudos

To control what interfaces are imported, you need to create a configuration object for the discovery plugin that handles interfaces by calling Orion.NPM.Interfaces.CreateInterfacesPluginConfiguration. Like this:

interfacesPluginContext = {

  'AutoImportStatus': ['Up'], # Also available: Down, Shutdown

  'AutoImportVlanPortTypes': ['Trunk', 'Access'], # Also available: Unknown

  #'AutoImportVirtualTypes': ['Physical', 'Virtual', 'Unknown'],

  #'AutoImportExpressionFilter': [{'Prop': 'Alias', 'Op': 'Regex', 'Val': '.*Nortel.*'}]

  # Available values for Prop: Type, Name, Descr, Alias, Node, All, Vlan

  # Available values for Op: All, !All, Any, !Any, Equals, !Equals, Regex, !Regex, #All, !#All, #Any, !#Any

  # Val is the literal value to compare Prop to

  # If more than one expression is provided, the interface must match all of the expressions to be imported

  # To specify more than one number or string for the All and Any operators (including variants), separate them by spaces

}

interfacesPluginConfig = swis.invoke('Orion.NPM.Interfaces', 'CreateInterfacesPluginConfiguration', interfacesPluginContext)

Then include this config object in the list of plugin configurations when you create the discovery profile, like this:

discoveryProfile = {

  'Name': 'API discovery',

  'EngineID': orion_engine_id,

  'JobTimeoutSeconds': 3600,

  'SearchTimeoutMiliseconds': 5000,

  'SnmpTimeoutMiliseconds': 5000,

  'SnmpRetries': 2,

  'RepeatIntervalMiliseconds': 1800,

  'SnmpPort': 161,

  'HopCount': 0,

  'PreferredSnmpVersion': 'SNMP2c',

  'DisableIcmp': False,

  'AllowDuplicateNodes': True,

  'IsAutoImport': True,

  'IsHidden': False,

  'PluginConfigurations': [

       {'PluginConfigurationItem': corePluginConfig},

       {'PluginConfigurationItem': interfacesPluginConfig},  # Add your interfaces plugin config here

  ]

}

It is not currently possible to control the set of volumes that get imported during discovery through the API. I recommend you just let it discover all of them and then delete the ones you don't want. To track the discovery and wait for it to complete so you can clean up the volumes, follow the example here: https://github.com/solarwinds/OrionSDK/blob/master/Samples/PowerShell/DiscoverSnmpV3Node.ps1 .

View solution in original post

Did this functionality change? I am able to successfully execute a discovery with an interface configuration plugin defined, however, no interfaces are auto imported. 

0 Kudos

Did something change in this functionality? I am able to execute the discovery successfully, however, no interfaces are auto imported. 

0 Kudos

Has anyone managed to get the  'AutoImportExpressionFilter': [{'Prop': 'Name', 'Op': 'Regex', 'Val': 'Ethernet1/1'}]   method to  work ?   The other AutoImport methods work fine, I cant get Regex to work.

I am trying to use the method to provide a list of interfaces I want to import example :

'AutoImportExpressionFilter': [{'Prop': 'Name', 'Op': 'Regex', 'Val': 'Ethernet1/1|Ethernet2/1'}]

0 Kudos

Same here I can't get the regex to work with the Desc field.  Has anyone been able to get the AutoImportExpressionFilter to work?  If so will you provide a working copy? 

0 Kudos

Here is a working copy of mine:

interfacesPluginContext = {

    'AutoImportStatus': ['Up'],  # Also available: Down, Shutdown

    'AutoImportVlanPortTypes': ['Trunk', 'Access', 'Unknown'],

    'AutoImportVirtualTypes': ['Physical', 'Virtual'],  # Also available: Unknown

    'AutoImportExpressionFilter': [{'Prop': 'Name',

                                    'Op': 'Regex',

                                    'Val': '^failover$|'

                                           '^gigabitethernet1/[1-2,7-8]$|'

                                           '^gi0/0/[0-1]$|'

                                           '^gi0/0/0.101$|'

                                           '^se0/1/0|'

                                           '^tu1|'

                                           'tu[1-2]0|'

                                           '^tu[1-2]0[0-2]$|'

                                           '^tu1.28$|'

                                           '^gi[1-2]/0/4[0-4,6-8]$'}

                                   ]

0 Kudos

Does the Op and Val fields change for you?  I can get my regex syntax to set correctly in the console however when I view the discovery in the console I am not able to set prop to alias and op to Regex.  Can you provide a complete copy of your code for comparison? 

0 Kudos

kritzisc wrote:

'AutoImportExpressionFilter': [{'Prop': 'Name', 'Op': 'Regex', 'Val': 'Ethernet1/1|Ethernet2/1'}]

I have not played with this specific function, but from a general regexp perspective, 'Ethernet1/1|Ethernet2/1' isn't a great regexp matching string.  You would need to enclose multiple characters in parans in order to group them, and you may/may not have to escape the slashes with a backslash.

Might want to try:

'Val': 'Ethernet(1|2)\/1'

instead.

0 Kudos

Brandon

I solved the problem

Note : 1)The "Name" Prop doesn't use the full name of the interface

2) It appears you can't use the AutoImportExpressionFilter by itself, I had to include the 'AutoImportStatus' to get it to work

interfacesPluginContext = {

'AutoImportStatus': ,

'AutoImportExpressionFilter': {'Prop': 'Name', 'Op': 'Regex', 'Val': 'Gi4/0/1$,

}

Regards

Sean Kritzinger

Cell: (201)563-3798

Glad you figured it out - even happier you came back to post about it to avoid one of these:

wisdom_of_the_ancients.png