This discussion has been locked. The information referenced herein may be inaccurate due to age, software updates, or external references.
You can no longer post new replies to this discussion. If you have a similar question you can start a new discussion in this forum.

Setting CreateCorePluginConfiguration details for Orion.Discovery in python

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()

  • 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>

  • 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 .

  • 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.

  • 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'}]

  • FormerMember
    0 FormerMember in reply to kritzisc

    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.

  • 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

    attachments.zip
  • FormerMember
    0 FormerMember in reply to kritzisc

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

    wisdom_of_the_ancients.png

  • I haven't posted anything back on this emoticons_happy.png

    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()

  • 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!!

  • 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.