This is the third article in a series we’re calling “SolarWinds Orion API & SDK”. The first article covered concepts, purpose and how to get started with the SDK. In the second article we took a look at interaction with the API via cURL and a REST client. By now you should have a taste of what SolarWinds’ API and SDK can bring to the table. You’re understanding how to interact with the API, and you’re starting to grasp the potential.
Manually making static changes is great and all, but wouldn’t it be cool if we could wrap these into some sort of programmatic method to save us time and energy? Sure would. In this article we’ll be looking at just that. In particular, we’ll be looking at RESTful API interactions via Python. If you’re inexperienced with Python, don’t worry too much. SolarWinds provides several example scripts we can use to test these capabilities, and if you’re so inclined, reverse engineer to fit your environment.
A couple of house-keeping items: we won’t be covering Python basics. If you’re new to it, or just want to know more, I suggest you check out various online training resources, typically free of charge. Codecademy comes to mind for Python. Oh, and you’ll want to make sure you have Python installed on your system. If you’re on Mac OSX, Python is included. If you’re on Windows, download Python here.
Python
In the first article we lightly touched on the GitHub repository called orionsdk-python. This is an important repo for us, as it contains the SwisClient applet and several examples detailing its use. Assuming you have Python installed, the first step to take is installing the orionsdk package. To do this, we’ll use the Python package manager, pip. If you’re on a Mac, you can run:
sudo easy_install pip
If you’re on Windows, follow these instructions to download the get-pip.py script and execute the following command via CLI.
python get-pip.py
Now that pip is installed, we’ll install the orionsdk package.
~$ pip install orionsdk
Downloading/unpacking orionsdk
Downloading orionsdk-0.0.4.zip
Storing download in cache at ./.pip/cache/https%3A%2F%2Fpypi.python.org%2Fpackages%2F3b%2Fbb%2F9a3b3714ca4b69cdd247f110e975aa00e82b5d407ae00e1959381c82f94d%2Forionsdk-0.0.4.zip
Running setup.py (path:/private/var/folders/0x/bl6mqjts76vgfbgj327sqjhh0000gn/T/pip_build_vosx/orionsdk/setup.py) egg_info for package orionsdk
Requirement already satisfied (use --upgrade to upgrade): six in /Library/Python/2.7/site-packages (from orionsdk)
Downloading/unpacking requests (from orionsdk)
Downloading requests-2.11.1-py2.py3-none-any.whl (514kB): 514kB downloaded
Storing download in cache at ./.pip/cache/https%3A%2F%2Fpypi.python.org%2Fpackages%2Fea%2F03%2F92d3278bf8287c5caa07dbd9ea139027d5a3592b0f4d14abf072f890fab2%2Frequests-2.11.1-py2.py3-none-any.whl
Installing collected packages: orionsdk, requests
Running setup.py install for orionsdk
Successfully installed orionsdk requests
Cleaning up...
Taking a look at the samples available in the SDK, we have see some potentially useful scripts for adding nodes, updating custom properties, querying interfaces and unmanaging nodes. This may seem basic at first, but these are common and critical tasks within the SolarWinds realm, meaning they hold high value in the automation arena.
Let’s open one of these up and take a look inside. I’ll pick on query.py.
[pastacode lang=”python” manual=”import%20requests%0Afrom%20orionsdk%20import%20SwisClient%0A%0Anpm_server%20%3D%20’localhost’%0Ausername%20%3D%20’admin’%0Apassword%20%3D%20”%0A%0Averify%20%3D%20False%0Aif%20not%20verify%3A%0A%20%20%20%20from%20requests.packages.urllib3.exceptions%20import%20InsecureRequestWarning%0A%20%20%20%20requests.packages.urllib3.disable_warnings(InsecureRequestWarning)%0A%0A%0Aswis%20%3D%20SwisClient(npm_server%2C%20username%2C%20password)%0A%0Aprint(%22Query%20Test%3A%22)%0Aresults%20%3D%20swis.query(%22SELECT%20TOP%203%20NodeID%2C%20DisplayName%20FROM%20Orion.Nodes%22)%0A%0Afor%20row%20in%20results%5B’results’%5D%3A%0A%20%20%20%20print(%22%7BNodeID%3A%3C5%7D%3A%20%7BDisplayName%7D%22.format(**row))” message=”” highlight=”” provider=”manual”/]
A little dissection tells us we’re importing “requests”, which is a simple HTTP Python library. We’re also importing SwisClient from the orionsdk package we installed a few moments ago.
[pastacode lang=”python” manual=”import%20requests%0Afrom%20orionsdk%20import%20SwisClient” message=”” highlight=”” provider=”manual”/]
Next we create some variables
[pastacode lang=”python” manual=”npm_server%20%3D%20’localhost’%0Ausername%20%3D%20’admin’%0Apassword%20%3D%20”” message=”” highlight=”” provider=”manual”/]
Bypass SSL warnings (NOT recommended, but we’re on a ‘safe’ lab network so keeping here for now)
[pastacode lang=”python” manual=”verify%20%3D%20False%0Aif%20not%20verify%3A%0A%20%20%20%20from%20requests.packages.urllib3.exceptions%20import%20InsecureRequestWarning%0A%20%20%20%20requests.packages.urllib3.disable_warnings(InsecureRequestWarning)” message=”” highlight=”” provider=”manual”/]
Next we invoke the SwisClient, which connects to the NPM server.
[pastacode lang=”python” manual=”swis%20%3D%20SwisClient(npm_server%2C%20username%2C%20password)” message=”” highlight=”” provider=”manual”/]
Lastly, this script simply selects the top 3 nodes by NodeID and prints it to the terminal.
[pastacode lang=”python” manual=”print(%22Query%20Test%3A%22)%0Aresults%20%3D%20swis.query(%22SELECT%20TOP%203%20NodeID%2C%20DisplayName%20FROM%20Orion.Nodes%22)%0Afor%20row%20in%20results%5B’results’%5D%3A%0A%20%20%20%20print(%22%7BNodeID%3A%3C5%7D%3A%20%7BDisplayName%7D%22.format(**row))” message=”” highlight=”” provider=”manual”/]
As you can tell, this isn’t a very useful script. Though it lacks in practicality, it shows us how the orionsdk module works, and shows us a basic example of the SwisClient function within the orionsdk module. The SwisClient is important to understand, as it is our means to communicate with the API via Python.
If you navigate to orionsdk-python/orionsdk/swisclient.py in the GitHub repo, you’ll find the construct of the SwisClient. Without going into gross detail, you’ll find that SwisClient has methods defined for querying, invoking, creating, reading, updating and deleting. Each of these have their respective uses. If you want to query something, use the query method. If you want to create something, use the create method. The development team at SolarWinds has clearly defined and labelled these components for you. I’ll show you how to use a few of these as this article progresses.
Python Interpreter
When learning something new in Python, I often find it most valuable to hop on an interpreter, and poke around. If you’re on a Mac, you can just type ‘python’ at the terminal. If you’re in Windows, run the Python Terminal/IDE you installed earlier.
Import the same library and functions as before
[pastacode lang=”python” manual=”%3E%3E%3E%20%0A%3E%3E%3E%20import%20requests%0A%3E%3E%3E%20from%20orionsdk%20import%20SwisClient%0A%3E%3E%3E” message=”” highlight=”” provider=”manual”/]
Set our variables
[pastacode lang=”python” manual=”%3E%3E%3E%0A%3E%3E%3E%20npm_server%20%3D%20’orion’%0A%3E%3E%3E%20username%20%3D%20’labuser’%0A%3E%3E%3E%20password%20%3D%20’mypassword’%0A%3E%3E%3E” message=”” highlight=”” provider=”manual”/]
Connect to Orion
[pastacode lang=”python” manual=”%3E%3E%3E%0A%3E%3E%3E%20swis%20%3D%20SwisClient(npm_server%2C%20username%2C%20password)” message=”” highlight=”” provider=”manual”/]
Use SwisClient to ‘query’
We should now be able to run a query. I’m going to search for my Cisco 2960 switch again and pull the address city like I did in the last article.
[pastacode lang=”python” manual=”%3E%3E%3E%0A%3E%3E%3E%20swis.query(%22SELECT%20n.Uri%2C%20n.CustomProperties._Location%2C%20n.CustomProperties.Address_1%2C%20n.CustomProperties.Address_City%20FROM%20Orion.Nodes%20n%20WHERE%20n.Caption%20%3D%20’DVARNUM_2960’%22)%0A%2Fusr%2Flocal%2Flib%2Fpython2.7%2Fsite-packages%2Frequests%2Fpackages%2Furllib3%2Fconnectionpool.py%3A838%3A%20InsecureRequestWarning%3A%20Unverified%20HTTPS%20request%20is%20being%20made.%20Adding%20certificate%20verification%20is%20strongly%20advised.%20See%3A%20https%3A%2F%2Furllib3.readthedocs.io%2Fen%2Flatest%2Fsecurity.html%0A%20InsecureRequestWarning)%0A%3E%3E%3E” message=”” highlight=”” provider=”manual”/]
Ah, and I received the unverified SSL error. Let’s ignore these for now by running the command below.
[pastacode lang=”python” manual=”%3E%3E%3E%20%0A%3E%3E%3E%20requests.packages.urllib3.disable_warnings()%0A%3E%3E%3E%20″ message=”” highlight=”” provider=”manual”/]
Try our query again
[pastacode lang=”python” manual=”%3E%3E%3E%20swis.query(%22SELECT%20n.Uri%2C%20n.CustomProperties._Location%2C%20n.CustomProperties.Address_1%2C%20n.CustomProperties.Address_City%20FROM%20Orion.Nodes%20n%20WHERE%20n.Caption%20%3D%20’DVARNUM_2960’%22)%0A%7Bu’results’%3A%20%5B%7Bu’Address_City’%3A%20u’NMS’%2C%20u’_Location’%3A%20u’Lab’%2C%20u’Uri’%3A%20u’swis%3A%2F%2Forion%2FOrion%2FOrion.Nodes%2FNodeID%3D7500’%2C%20u’Address_1’%3A%20u’1337%20Haxor%20Ln’%7D%5D%7D” message=”” highlight=”” provider=”manual”/]
And there we have it! Our results in JSON, showing the Address_City as ‘NMS’, the _Location as ‘Lab’ and Address_1 as ‘1337 Haxor Ln’.
Use SwisClient to ‘read’
If I wanted a list of all custom properties, I could simply use the read method. Reading uses a GET method, and returns the data in JSON.
[pastacode lang=”python” manual=”%3E%3E%3E%20swis.read(‘swis%3A%2F%2Forion%2FOrion%2FOrion.Nodes%2FNodeID%3D7500%2FCustomProperties’)%0A(Results%20removed%20for%20privacy%20purpose)” message=”” highlight=”” provider=”manual”/]
Use SwisClient to ‘update’
Querying is fun an all, but sometimes we want to make changes and updates to nodes. Suppose I built a new super secret lab, and I’m moving my Cisco switch to the new location. I can execute an update to accomplish this. First, let’s query again to check the current location of my switch.
[pastacode lang=”python” manual=”%3E%3E%3E%20swis.query(%22SELECT%20n.Uri%2C%20n.CustomProperties._Location%2C%20n.CustomProperties.Address_1%2C%20n.CustomProperties.Address_City%20FROM%20Orion.Nodes%20n%20WHERE%20n.Caption%20%3D%20’DVARNUM_2960’%22)%0A%7Bu’results’%3A%20%5B%7Bu’Address_City’%3A%20u’NMS’%2C%20u’_Location’%3A%20u’Lab’%2C%20u’Uri’%3A%20u’swis%3A%2F%2Forion%2FOrion%2FOrion.Nodes%2FNodeID%3D7500’%2C%20u’Address_1’%3A%20u’1337%20Haxor%20Ln’%7D%5D%7D%0A%3E%3E%3E” message=”” highlight=”” provider=”manual”/]
It’s still located in the ‘Lab’. Let’s change this location by invoking the ‘update’ method.
[pastacode lang=”python” manual=”%3E%3E%3E%20%0A%3E%3E%3E%20swis.update(‘swis%3A%2F%2Forion%2FOrion%2FOrion.Nodes%2FNodeID%3D7500%2FCustomProperties’%2C%20_Location%3D’Super%20Secret%20Lab’)%0A%3E%3E%3E” message=”” highlight=”” provider=”manual”/]
Query again to see the update.
[pastacode lang=”python” manual=”%3E%3E%3E%20swis.query(%22SELECT%20n.Uri%2C%20n.CustomProperties._Location%2C%20n.CustomProperties.Address_1%2C%20n.CustomProperties.Address_City%20FROM%20Orion.Nodes%20n%20WHERE%20n.Caption%20%3D%20’DVARNUM_2960’%22)%0A%7Bu’results’%3A%20%5B%7Bu’Address_City’%3A%20u’NMS’%2C%20u’_Location’%3A%20u’Super%20Secret%20Lab’%2C%20u’Uri’%3A%20u’swis%3A%2F%2Forion%2FOrion%2FOrion.Nodes%2FNodeID%3D7500’%2C%20u’Address_1’%3A%20u’1337%20Haxor%20Ln’%7D%5D%7D” message=”” highlight=”” provider=”manual”/]
Add a node to Orion using Python
For the next example, I’m going to show you how to add a node to Orion using Python. This is one of countless tasks you can automate, but I feel it is an important and interesting one. Again, SolarWinds provides you with a sample Python script you can build upon. This can be found here, called add_node.py.
The sample script adds a device with SNMPv2. This works just fine, but most environments these days use SNMPv3. That said, I’m going to modify this script to use my preferred SNMPv3 method. Additionally, I’d like to add some Custom Properties to my node, so I’ll append that to the script as well.
Much like the earlier example, I prefer the Python interpreter for testing Python syntax. We’ll hop on here first to run through the example. Open Python and load the necessary libraries
~/Documents/github/orionsdk-python/orionsdk$ python
[pastacode lang=”python” manual=”%3E%3E%3E%20from%20__future__%20import%20print_function%0A%3E%3E%3E%20import%20re%0A%3E%3E%3E%20import%20requests%0A%3E%3E%3E%20from%20orionsdk%20import%20SwisClient%0A%3E%3E%3E” message=”” highlight=”” provider=”manual”/]
Disable SSL warnings (if necessary)
[pastacode lang=”python” manual=”%3E%3E%3E%20requests.packages.urllib3.disable_warnings()%0A%3E%3E%3E” message=”” highlight=”” provider=”manual”/]
Configure your NPM server, username and password. We can always mask and encrypt this in an actual script, but for now we’ll just load it into the terminal for sake of simplicity.
[pastacode lang=”python” manual=”%3E%3E%3E%20npm_server%20%3D%20’orion’%0A%3E%3E%3E%20username%20%3D%20’labuser’%0A%3E%3E%3E%20password%20%3D%20’x'” message=”” highlight=”” provider=”manual”/]
Next we invoke the SwisClient, which connects to the NPM server.
[pastacode lang=”python” manual=”%3E%3E%3E%20swis%20%3D%20SwisClient(npm_server%2C%20username%2C%20password)%0A%3E%3E%3E” message=”” highlight=”” provider=”manual”/]
Setup your node properties, such as the IP address and SNMP information. If you’re running SNMPv2, just use the example provided by SolarWinds.
[pastacode lang=”python” manual=”%3E%3E%3E%20ip_address%20%3D%20’10.10.0.42’%0A%3E%3E%3E%20%0A%3E%3E%3E%20props%20%3D%20%7B%0A…%20’IPAddress’%3A%20ip_address%2C%0A…%20’EngineID’%3A%205%2C%0A…%20’ObjectSubType’%3A%20’SNMP’%2C%0A…%20’SNMPVersion’%3A%203%2C%0A…%20’Caption’%3A%20’DVARNUM_2960’%2C%0A…%20’SNMPV3AuthKey’%3A%20’MyAuthKey33’%2C%0A…%20’SNMPv3AuthKeyIsPwd’%3A%20True%2C%0A…%20’SNMPv3AuthMethod’%3A%20’SHA1’%2C%0A…%20’SNMPv3PrivKey’%3A%20’MyPrivKey33’%2C%0A…%20’SNMPv3PrivKeyIsPwd’%3A%20True%2C%0A…%20’SNMPv3PrivMethod’%3A%20’AES128’%2C%0A…%20’SNMPV3Username’%3A%20’snmpgod’%0A…%20%7D” message=”” highlight=”” provider=”manual”/]
Invoke swis.create to create the node based on the properties entered above.
[pastacode lang=”python” manual=”%3E%3E%3E%20results%20%3D%20swis.create(‘Orion.Nodes’%2C%20**props)” message=”” highlight=”” provider=”manual”/]
Extract the Node ID from the results.
[pastacode lang=”python” manual=”%3E%3E%3E%20nodeid%20%3D%20re.search(‘(%5Cd%2B)%24’%2C%20results).group(0)%0A%3E%3E%3E%20nodeid%0Au’7607′” message=”” highlight=”” provider=”manual”/]
Our new node was added to Orion and assigned Node ID 7607. Now we need to setup some pollers. This below is pulled straight from the SDK repo.
[pastacode lang=”python” manual=”%3E%3E%3E%20pollers_enabled%20%3D%20%7B%0A…%20%20%20%20%20’N.Status.ICMP.Native’%3A%20True%2C%0A…%20%20%20%20%20’N.Status.SNMP.Native’%3A%20False%2C%0A…%20%20%20%20%20’N.ResponseTime.ICMP.Native’%3A%20True%2C%0A…%20%20%20%20%20’N.ResponseTime.SNMP.Native’%3A%20False%2C%0A…%20%20%20%20%20’N.Details.SNMP.Generic’%3A%20True%2C%0A…%20%20%20%20%20’N.Uptime.SNMP.Generic’%3A%20True%2C%0A…%20%20%20%20%20’N.Cpu.SNMP.HrProcessorLoad’%3A%20True%2C%0A…%20%20%20%20%20’N.Memory.SNMP.NetSnmpReal’%3A%20True%2C%0A…%20%20%20%20%20’N.AssetInventory.Snmp.Generic’%3A%20True%2C%0A…%20%20%20%20%20’N.Status.SNMP.Native’%3A%20False%2C%0A…%20%20%20%20%20’N.ResponseTime.SNMP.Native’%3A%20False%2C%0A…%20%20%20%20%20’N.Topology_Layer3.SNMP.ipNetToMedia’%3A%20False%2C%0A…%20%20%20%20%20’N.Routing.SNMP.Ipv4CidrRoutingTable’%3A%20False%0A…%20%7D%0A%3E%3E%3E%20pollers%20%3D%20%5B%5D%0A%3E%3E%3E%20for%20k%20in%20pollers_enabled%3A%0A…%20%20%20%20%20pollers.append(%0A…%20%20%20%20%20%7B%0A…%20%20%20%20%20’PollerType’%3A%20k%2C%0A…%20%20%20%20%20’NetObject’%3A%20’N%3A’%20%2B%20nodeid%2C%0A…%20%20%20%20%20’NetObjectType’%3A%20’N’%2C%0A…%20%20%20%20%20’NetObjectID’%3A%20nodeid%2C%0A…%20%20%20%20%20’Enabled’%3A%20pollers_enabled%5Bk%5D%0A…%20%20%20%20%20%7D%0A…%20)%0A…%20%0A%3E%3E%3E%20for%20poller%20in%20pollers%3A%0A…%20%20%20%20%20print(%22%20Adding%20poller%20type%3A%20%7B%7D%20with%20status%20%7B%7D…%20%22.format(poller%5B’PollerType’%5D%2C%20poller%5B’Enabled’%5D)%2C%20end%3D%22%22)%0A…%20%20%20%20%20response%20%3D%20swis.create(‘Orion.Pollers’%2C%20**poller)%0A…%20%20%20%20%20print(%22DONE!%22)%0A…%20%0A%20Adding%20poller%20type%3A%20N.Memory.SNMP.NetSnmpReal%20with%20status%20True…%20DONE!%0A%20Adding%20poller%20type%3A%20N.ResponseTime.ICMP.Native%20with%20status%20True…%20DONE!%0A%20Adding%20poller%20type%3A%20N.ResponseTime.SNMP.Native%20with%20status%20False…%20DONE!%0A%20Adding%20poller%20type%3A%20N.Status.SNMP.Native%20with%20status%20False…%20DONE!%0A%20Adding%20poller%20type%3A%20N.Cpu.SNMP.HrProcessorLoad%20with%20status%20True…%20DONE!%0A%20Adding%20poller%20type%3A%20N.Routing.SNMP.Ipv4CidrRoutingTable%20with%20status%20False…%20DONE!%0A%20Adding%20poller%20type%3A%20N.Uptime.SNMP.Generic%20with%20status%20True…%20DONE!%0A%20Adding%20poller%20type%3A%20N.Details.SNMP.Generic%20with%20status%20True…%20DONE!%0A%20Adding%20poller%20type%3A%20N.Topology_Layer3.SNMP.ipNetToMedia%20with%20status%20False…%20DONE!%0A%20Adding%20poller%20type%3A%20N.Status.ICMP.Native%20with%20status%20True…%20DONE!%0A%20Adding%20poller%20type%3A%20N.AssetInventory.Snmp.Generic%20with%20status%20True…%20DONE!%0A%3E%3E%3E” message=”” highlight=”” provider=”manual”/]
All of our pollers were successfully added to the node. If we pull up the GUI, we can see that our node is there but the status is unknown.
My personal results have been hit and miss on this, but this could just be the default discovery interval waiting to triggered, and patience would bring our node online. Or, instead of waiting, we can force a poll using the ‘PollNow’ verb.
[pastacode lang=”python” manual=”%3E%3E%3E%20swis.invoke(‘Orion.Nodes’%2C%20’PollNow’%2C%20’N’%20%2B%20nodeid)” message=”” highlight=”” provider=”manual”/]
And now we’re in business.
Lastly, we want to add our custom properties. To do so, I create a Python dictionary with they key/value pairs, then iterate over it and ship the new values via swis.update. I’m going to use the same custom property values we used earlier, and in the previous article (link). First, notice our custom properties are currently blank on the new node.
[pastacode lang=”python” manual=”%3E%3E%3E%20results%0Au’swis%3A%2F%2Forion%2FOrion%2FOrion.Nodes%2FNodeID%3D7607’%0A%3E%3E%3E%0A%3E%3E%3E%20custom_props%20%3D%20swis.read(‘swis%3A%2F%2Forion%2FOrion%2FOrion.Nodes%2FNodeID%3D7607%2FCustomProperties’)%0A%3E%3E%3E%20pprint.pprint(updated_custom_props)%0A%7Bu’Address_1’%3A%20None%2C%0A%20u’Address_2’%3A%20None%2C%0A%20u’Address_City’%3A%20None%2C%0A%20u’Address_State’%3A%20None%2C%0A%20u’Address_Zip’%3A%20None%0A%20…truncated” message=”” highlight=”” provider=”manual”/]
I’ll create a dictionary of the custom properties I’d like to modify.
[pastacode lang=”python” manual=”%3E%3E%3E%20custom_props%20%3D%20%7B%0A…%20’Address_1’%3A%20’Lab’%2C%0A…%20’Address_2’%3A%20’1337%20Haxor%20Ln’%2C%0A…%20’Address_City’%3A%20’Suite%20API’%2C%0A…%20’Address_State’%3A%20’NMS’%2C%0A…%20’Address_Zip’%3A%20’10101’%2C%0A…%20%7D%0A%3E%3E%3E” message=”” highlight=”” provider=”manual”/]
Now, will rip through this dictionary and invoke swis.update to populate the fields.
[pastacode lang=”python” manual=”%3E%3E%3E%20for%20k%2Cv%20in%20custom_props.items()%3A%0A…%20%20%20%20%20swis.update(results%20%2B%20’%2FCustomProperties’%2C%20**%7Bk%3A%20v%7D)%0A…%20%0A%3E%3E%3E” message=”” highlight=”” provider=”manual”/]
Let’s read this back from Orion and print the results.
[pastacode lang=”python” manual=”%3E%3E%3E%20updated_custom_props%20%3D%20swis.read(‘swis%3A%2F%2Forion%2FOrion%2FOrion.Nodes%2FNodeID%3D7607%2FCustomProperties’)%0A%3E%3E%3E%20pprint.pprint(updated_custom_props)%0A%7Bu’Address_1’%3A%20u’Lab’%2C%0A%20u’Address_2’%3A%20u’1337%20Haxor%20Ln’%2C%0A%20u’Address_City’%3A%20u’Suite%20API’%2C%0A%20u’Address_State’%3A%20u’NMS’%2C%0A%20u’Address_Zip’%3A%20u’10101’%2C” message=”” highlight=”” provider=”manual”/]
There we are!!
Wrapping this up
Now that we know this works, we can wrap it up in a Python script. This particular script will ask you for the node IP and the node name. It will also prompt you to enter your password. The script will be at the bottom of this article. Here’s showing it in action:
~$ python add_node.py
Password:
Enter the node IP: 10.10.0.42
Enter the node name: DVARNUM_2960
Adding node 10.10.0.42... DONE!
Adding poller type: N.Memory.SNMP.NetSnmpReal with status True... DONE!
Adding poller type: N.ResponseTime.ICMP.Native with status True... DONE!
Adding poller type: N.ResponseTime.SNMP.Native with status False... DONE!
Adding poller type: N.Status.SNMP.Native with status False... DONE!
Adding poller type: N.Cpu.SNMP.HrProcessorLoad with status True... DONE!
Adding poller type: N.Routing.SNMP.Ipv4CidrRoutingTable with status False... DONE!
Adding poller type: N.Uptime.SNMP.Generic with status True... DONE!
Adding poller type: N.Details.SNMP.Generic with status True... DONE!
Adding poller type: N.Topology_Layer3.SNMP.ipNetToMedia with status False... DONE!
Adding poller type: N.Status.ICMP.Native with status True... DONE!
Adding poller type: N.AssetInventory.Snmp.Generic with status True... DONE!
Adding custom property: Address_City with value Suite API... DONE!
Adding custom property: Address_Zip with value 10101... DONE!
Adding custom property: Address_1 with value Lab... DONE!
Adding custom property: Address_2 with value 1337 Haxor Ln... DONE!
Adding custom property: Address_State with value NMS... DONE!
And here’s our node:
Take this baseline, get creative, and modify as needed for your environment.
Closing Thoughts
Here we’ve demonstrated the Pythonic approach to SolarWinds SDK. There’s certainly much more you can do with this, and ultimately you’d want to secure it for your production environment. Utilize the example scripts in GitHub and browse Thwack for answers to your queries. If your goal is to develop automation, Python or PowerShell are the best options for you. Poke around the GitHub repo and you’ll find PowerShell examples similar to the ones available in Python.
Stay tuned for future articles involving the SolarWinds SDK.
Python Add Node Script Example
[pastacode lang=”python” manual=”from%20__future__%20import%20print_function%0Aimport%20re%0Aimport%20requests%0Afrom%20orionsdk%20import%20SwisClient%0Aimport%20getpass%0A%0Adef%20main()%3A%0A%09requests.packages.urllib3.disable_warnings()%0A%09%0A%09npm_server%20%3D%20’orion’%0A%09username%20%3D%20’labuser’%0A%09password%20%3D%20getpass.getpass()%0A%0A%09swis%20%3D%20SwisClient(npm_server%2C%20username%2C%20password)%0A%09%0A%09%23%20Add%20the%20node%20IP%0A%09ip_address%20%3D%20raw_input(%22Enter%20the%20node%20IP%3A%20%22)%0A%09node_name%20%3D%20raw_input(%22Enter%20the%20node%20name%3A%20%22)%0A%09%0A%09%23%20Setup%20properties%20for%20the%20new%20node%0A%09props%20%3D%20%7B%0A%09%20%20%20%20’IPAddress’%3A%20ip_address%2C%0A%09%20%20%20%20’EngineID’%3A%205%2C%0A%09%20%20%20%20’ObjectSubType’%3A%20’SNMP’%2C%0A%09%20%20%20%20’SNMPVersion’%3A%203%2C%0A%09%20%20%20%20’Caption’%3A%20node_name%2C%0A%09%20%20%20%20’SNMPV3AuthKey’%3A%20’MyAuthKey33’%2C%0A%09%20%20%20%20’SNMPv3AuthKeyIsPwd’%3A%20True%2C%0A%09%20%20%20%20’SNMPv3AuthMethod’%3A%20’SHA1’%2C%0A%09%20%20%20%20’SNMPv3PrivKey’%3A%20’MyPrivKey33’%2C%0A%09%20%20%20%20’SNMPv3PrivKeyIsPwd’%3A%20True%2C%0A%09%20%20%20%20’SNMPv3PrivMethod’%3A%20’AES128’%2C%0A%09%20%20%20%20’SNMPV3Username’%3A%20’snmpgod’%0A%09%7D%0A%09%0A%09%23%20Create%20the%20node%0A%09print(%22Adding%20node%20%7B%7D…%20%22.format(props%5B’IPAddress’%5D)%2C%20end%3D%22%22)%0A%09results%20%3D%20swis.create(‘Orion.Nodes’%2C%20**props)%0A%09print(%22DONE!%22)%0A%09%0A%09%23%20Extract%20nodeID%20from%20the%20results%0A%09nodeid%20%3D%20re.search(‘(%5Cd%2B)%24’%2C%20results).group(0)%0A%0A%09%23%20Setup%20poller%20status%20for%20the%20node%0A%09pollers_enabled%20%3D%20%7B%0A%09%09’N.Status.ICMP.Native’%3A%20True%2C%0A%09%09’N.Status.SNMP.Native’%3A%20False%2C%0A%09%09’N.ResponseTime.ICMP.Native’%3A%20True%2C%0A%09%09’N.ResponseTime.SNMP.Native’%3A%20False%2C%0A%09%09’N.Details.SNMP.Generic’%3A%20True%2C%0A%09%09’N.Uptime.SNMP.Generic’%3A%20True%2C%0A%09%09’N.Cpu.SNMP.HrProcessorLoad’%3A%20True%2C%0A%09%09’N.Memory.SNMP.NetSnmpReal’%3A%20True%2C%0A%09%09’N.AssetInventory.Snmp.Generic’%3A%20True%2C%0A%09%09’N.Topology_Layer3.SNMP.ipNetToMedia’%3A%20False%2C%0A%09%09’N.Routing.SNMP.Ipv4CidrRoutingTable’%3A%20False%0A%09%7D%0A%0A%20%20%20%20%23%20Add%20node%20to%20pollers%0A%09pollers%20%3D%20%5B%5D%0A%09for%20k%20in%20pollers_enabled%3A%0A%09%09pollers.append(%0A%09%09%09%7B%0A%09%09%09%09’PollerType’%3A%20k%2C%0A%09%09%09%09’NetObject’%3A%20’N%3A’%20%2B%20nodeid%2C%0A%09%09%09%09’NetObjectType’%3A%20’N’%2C%0A%09%09%09%09’NetObjectID’%3A%20nodeid%2C%0A%09%09%09%09’Enabled’%3A%20pollers_enabled%5Bk%5D%0A%09%09%09%7D%0A%09%09)%0A%0A%09for%20poller%20in%20pollers%3A%0A%09%09print(%22%20%20Adding%20poller%20type%3A%20%7B%7D%20with%20status%20%7B%7D…%20%22.format(poller%5B’PollerType’%5D%2C%20poller%5B’Enabled’%5D)%2C%20end%3D%22%22)%0A%09%09response%20%3D%20swis.create(‘Orion.Pollers’%2C%20**poller)%0A%09%09print(%22DONE!%22)%0A%0A%20%20%20%20%23%20Poll%20the%20node%0A%09swis.invoke(‘Orion.Nodes’%2C%20’PollNow’%2C%20’N’%20%2B%20nodeid)%0A%09%0A%09%23%20Add%20custom%20properties%0A%09custom_props%20%3D%20%7B%0A%09%20%20%20%20’Address_1’%3A%20’Lab’%2C%0A%09%20%20%20%20’Address_2’%3A%20’1337%20Haxor%20Ln’%2C%0A%09%20%20%20%20’Address_City’%3A%20’Suite%20API’%2C%0A%09%20%20%20%20’Address_State’%3A%20’NMS’%2C%0A%09%20%20%20%20’Address_Zip’%3A%20’10101’%2C%0A%09%7D%0A%09%0A%09for%20k%2Cv%20in%20custom_props.items()%3A%0A%09%09print(%22%20%20Adding%20custom%20property%3A%20%7B%7D%20with%20value%20%7B%7D…%20%22.format(k%2C%20v)%2C%20end%3D%22%22)%0A%09%09swis.update(results%20%2B%20’%2FCustomProperties’%2C%20**%7Bk%3A%20v%7D)%0A%09%09print(%22DONE!%22)%0A%09%0Aif%20__name__%20%3D%3D%20’__main__’%3A%0A%20%20%20%20main()” message=”” highlight=”” provider=”manual”/]
SolarWinds Orion API & SDK – Scripting with Python FAQs
How do I access SolarWinds API?
To access SolarWinds API, you need to obtain an API key and authenticate your requests using HTTP Basic Authentication. You can then send API requests to the SolarWinds API endpoint using HTTP or HTTPS.
How do I query SolarWinds API using Python?
To query SolarWinds API using Python, you can use the requests library to send HTTP requests and retrieve JSON-formatted data. You will need to include your API key and authentication credentials in your requests, and specify the API endpoint and parameters you wish to query.
What are some common use cases for querying SolarWinds API with Python?
Some common use cases for querying SolarWinds API with Python include:
- Automating repetitive tasks, such as adding or removing nodes from monitoring
- Retrieving data for analysis or reporting, such as device availability or performance metrics
- Integrating SolarWinds products with other applications, such as a help desk or ticketing system
Are there any Python libraries or tools available for working with SolarWinds API?
Yes, there are several Python libraries and tools available for working with SolarWinds API, including the SolarWinds API Python client, the PySWQL library for querying SolarWinds Orion databases, and the SolarWinds Information Service (SWIS) client for interacting with the SolarWinds Information Service.
What are some best practices for working with SolarWinds API in Python?
Some best practices for working with SolarWinds API in Python include:
- Use a dedicated user account with limited permissions for API access
- Minimize the number of API requests to reduce network traffic and improve performance
- Use caching or data storage to avoid repeating API requests unnecessarily
- Handle errors and exceptions gracefully, and implement appropriate retry or fallback strategies
- Protect API keys and authentication credentials by storing them securely and avoiding hard-coding them in your code.
Our website relies on funding from our readers, and we may receive a commission when you make a purchase through the links on our site.
SolarWinds Orion API & SDK – Scripting with Python (Part 3)
by DAVID VARNUM, CCIE, VCP, MCSE+ - Last Updated: July 23, 2023
This is the third article in a series we’re calling “SolarWinds Orion API & SDK”. The first article covered concepts, purpose and how to get started with the SDK. In the second article we took a look at interaction with the API via cURL and a REST client. By now you should have a taste of what SolarWinds’ API and SDK can bring to the table. You’re understanding how to interact with the API, and you’re starting to grasp the potential.
Manually making static changes is great and all, but wouldn’t it be cool if we could wrap these into some sort of programmatic method to save us time and energy? Sure would. In this article we’ll be looking at just that. In particular, we’ll be looking at RESTful API interactions via Python. If you’re inexperienced with Python, don’t worry too much. SolarWinds provides several example scripts we can use to test these capabilities, and if you’re so inclined, reverse engineer to fit your environment.
A couple of house-keeping items: we won’t be covering Python basics. If you’re new to it, or just want to know more, I suggest you check out various online training resources, typically free of charge. Codecademy comes to mind for Python. Oh, and you’ll want to make sure you have Python installed on your system. If you’re on Mac OSX, Python is included. If you’re on Windows, download Python here.
Python
In the first article we lightly touched on the GitHub repository called orionsdk-python. This is an important repo for us, as it contains the SwisClient applet and several examples detailing its use. Assuming you have Python installed, the first step to take is installing the orionsdk package. To do this, we’ll use the Python package manager, pip. If you’re on a Mac, you can run:
If you’re on Windows, follow these instructions to download the get-pip.py script and execute the following command via CLI.
Now that pip is installed, we’ll install the orionsdk package.
Taking a look at the samples available in the SDK, we have see some potentially useful scripts for adding nodes, updating custom properties, querying interfaces and unmanaging nodes. This may seem basic at first, but these are common and critical tasks within the SolarWinds realm, meaning they hold high value in the automation arena.
Let’s open one of these up and take a look inside. I’ll pick on query.py.
[pastacode lang=”python” manual=”import%20requests%0Afrom%20orionsdk%20import%20SwisClient%0A%0Anpm_server%20%3D%20’localhost’%0Ausername%20%3D%20’admin’%0Apassword%20%3D%20”%0A%0Averify%20%3D%20False%0Aif%20not%20verify%3A%0A%20%20%20%20from%20requests.packages.urllib3.exceptions%20import%20InsecureRequestWarning%0A%20%20%20%20requests.packages.urllib3.disable_warnings(InsecureRequestWarning)%0A%0A%0Aswis%20%3D%20SwisClient(npm_server%2C%20username%2C%20password)%0A%0Aprint(%22Query%20Test%3A%22)%0Aresults%20%3D%20swis.query(%22SELECT%20TOP%203%20NodeID%2C%20DisplayName%20FROM%20Orion.Nodes%22)%0A%0Afor%20row%20in%20results%5B’results’%5D%3A%0A%20%20%20%20print(%22%7BNodeID%3A%3C5%7D%3A%20%7BDisplayName%7D%22.format(**row))” message=”” highlight=”” provider=”manual”/]
A little dissection tells us we’re importing “requests”, which is a simple HTTP Python library. We’re also importing SwisClient from the orionsdk package we installed a few moments ago.
[pastacode lang=”python” manual=”import%20requests%0Afrom%20orionsdk%20import%20SwisClient” message=”” highlight=”” provider=”manual”/]
Next we create some variables
[pastacode lang=”python” manual=”npm_server%20%3D%20’localhost’%0Ausername%20%3D%20’admin’%0Apassword%20%3D%20”” message=”” highlight=”” provider=”manual”/]
Bypass SSL warnings (NOT recommended, but we’re on a ‘safe’ lab network so keeping here for now)
[pastacode lang=”python” manual=”verify%20%3D%20False%0Aif%20not%20verify%3A%0A%20%20%20%20from%20requests.packages.urllib3.exceptions%20import%20InsecureRequestWarning%0A%20%20%20%20requests.packages.urllib3.disable_warnings(InsecureRequestWarning)” message=”” highlight=”” provider=”manual”/]
Next we invoke the SwisClient, which connects to the NPM server.
[pastacode lang=”python” manual=”swis%20%3D%20SwisClient(npm_server%2C%20username%2C%20password)” message=”” highlight=”” provider=”manual”/]
Lastly, this script simply selects the top 3 nodes by NodeID and prints it to the terminal.
[pastacode lang=”python” manual=”print(%22Query%20Test%3A%22)%0Aresults%20%3D%20swis.query(%22SELECT%20TOP%203%20NodeID%2C%20DisplayName%20FROM%20Orion.Nodes%22)%0Afor%20row%20in%20results%5B’results’%5D%3A%0A%20%20%20%20print(%22%7BNodeID%3A%3C5%7D%3A%20%7BDisplayName%7D%22.format(**row))” message=”” highlight=”” provider=”manual”/]
As you can tell, this isn’t a very useful script. Though it lacks in practicality, it shows us how the orionsdk module works, and shows us a basic example of the SwisClient function within the orionsdk module. The SwisClient is important to understand, as it is our means to communicate with the API via Python.
If you navigate to orionsdk-python/orionsdk/swisclient.py in the GitHub repo, you’ll find the construct of the SwisClient. Without going into gross detail, you’ll find that SwisClient has methods defined for querying, invoking, creating, reading, updating and deleting. Each of these have their respective uses. If you want to query something, use the query method. If you want to create something, use the create method. The development team at SolarWinds has clearly defined and labelled these components for you. I’ll show you how to use a few of these as this article progresses.
Python Interpreter
When learning something new in Python, I often find it most valuable to hop on an interpreter, and poke around. If you’re on a Mac, you can just type ‘python’ at the terminal. If you’re in Windows, run the Python Terminal/IDE you installed earlier.
Import the same library and functions as before
[pastacode lang=”python” manual=”%3E%3E%3E%20%0A%3E%3E%3E%20import%20requests%0A%3E%3E%3E%20from%20orionsdk%20import%20SwisClient%0A%3E%3E%3E” message=”” highlight=”” provider=”manual”/]
Set our variables
[pastacode lang=”python” manual=”%3E%3E%3E%0A%3E%3E%3E%20npm_server%20%3D%20’orion’%0A%3E%3E%3E%20username%20%3D%20’labuser’%0A%3E%3E%3E%20password%20%3D%20’mypassword’%0A%3E%3E%3E” message=”” highlight=”” provider=”manual”/]
Connect to Orion
[pastacode lang=”python” manual=”%3E%3E%3E%0A%3E%3E%3E%20swis%20%3D%20SwisClient(npm_server%2C%20username%2C%20password)” message=”” highlight=”” provider=”manual”/]
Use SwisClient to ‘query’
We should now be able to run a query. I’m going to search for my Cisco 2960 switch again and pull the address city like I did in the last article.
[pastacode lang=”python” manual=”%3E%3E%3E%0A%3E%3E%3E%20swis.query(%22SELECT%20n.Uri%2C%20n.CustomProperties._Location%2C%20n.CustomProperties.Address_1%2C%20n.CustomProperties.Address_City%20FROM%20Orion.Nodes%20n%20WHERE%20n.Caption%20%3D%20’DVARNUM_2960’%22)%0A%2Fusr%2Flocal%2Flib%2Fpython2.7%2Fsite-packages%2Frequests%2Fpackages%2Furllib3%2Fconnectionpool.py%3A838%3A%20InsecureRequestWarning%3A%20Unverified%20HTTPS%20request%20is%20being%20made.%20Adding%20certificate%20verification%20is%20strongly%20advised.%20See%3A%20https%3A%2F%2Furllib3.readthedocs.io%2Fen%2Flatest%2Fsecurity.html%0A%20InsecureRequestWarning)%0A%3E%3E%3E” message=”” highlight=”” provider=”manual”/]
Ah, and I received the unverified SSL error. Let’s ignore these for now by running the command below.
[pastacode lang=”python” manual=”%3E%3E%3E%20%0A%3E%3E%3E%20requests.packages.urllib3.disable_warnings()%0A%3E%3E%3E%20″ message=”” highlight=”” provider=”manual”/]
Try our query again
[pastacode lang=”python” manual=”%3E%3E%3E%20swis.query(%22SELECT%20n.Uri%2C%20n.CustomProperties._Location%2C%20n.CustomProperties.Address_1%2C%20n.CustomProperties.Address_City%20FROM%20Orion.Nodes%20n%20WHERE%20n.Caption%20%3D%20’DVARNUM_2960’%22)%0A%7Bu’results’%3A%20%5B%7Bu’Address_City’%3A%20u’NMS’%2C%20u’_Location’%3A%20u’Lab’%2C%20u’Uri’%3A%20u’swis%3A%2F%2Forion%2FOrion%2FOrion.Nodes%2FNodeID%3D7500’%2C%20u’Address_1’%3A%20u’1337%20Haxor%20Ln’%7D%5D%7D” message=”” highlight=”” provider=”manual”/]
And there we have it! Our results in JSON, showing the Address_City as ‘NMS’, the _Location as ‘Lab’ and Address_1 as ‘1337 Haxor Ln’.
Use SwisClient to ‘read’
If I wanted a list of all custom properties, I could simply use the read method. Reading uses a GET method, and returns the data in JSON.
[pastacode lang=”python” manual=”%3E%3E%3E%20swis.read(‘swis%3A%2F%2Forion%2FOrion%2FOrion.Nodes%2FNodeID%3D7500%2FCustomProperties’)%0A(Results%20removed%20for%20privacy%20purpose)” message=”” highlight=”” provider=”manual”/]
Use SwisClient to ‘update’
Querying is fun an all, but sometimes we want to make changes and updates to nodes. Suppose I built a new super secret lab, and I’m moving my Cisco switch to the new location. I can execute an update to accomplish this. First, let’s query again to check the current location of my switch.
[pastacode lang=”python” manual=”%3E%3E%3E%20swis.query(%22SELECT%20n.Uri%2C%20n.CustomProperties._Location%2C%20n.CustomProperties.Address_1%2C%20n.CustomProperties.Address_City%20FROM%20Orion.Nodes%20n%20WHERE%20n.Caption%20%3D%20’DVARNUM_2960’%22)%0A%7Bu’results’%3A%20%5B%7Bu’Address_City’%3A%20u’NMS’%2C%20u’_Location’%3A%20u’Lab’%2C%20u’Uri’%3A%20u’swis%3A%2F%2Forion%2FOrion%2FOrion.Nodes%2FNodeID%3D7500’%2C%20u’Address_1’%3A%20u’1337%20Haxor%20Ln’%7D%5D%7D%0A%3E%3E%3E” message=”” highlight=”” provider=”manual”/]
It’s still located in the ‘Lab’. Let’s change this location by invoking the ‘update’ method.
[pastacode lang=”python” manual=”%3E%3E%3E%20%0A%3E%3E%3E%20swis.update(‘swis%3A%2F%2Forion%2FOrion%2FOrion.Nodes%2FNodeID%3D7500%2FCustomProperties’%2C%20_Location%3D’Super%20Secret%20Lab’)%0A%3E%3E%3E” message=”” highlight=”” provider=”manual”/]
Query again to see the update.
[pastacode lang=”python” manual=”%3E%3E%3E%20swis.query(%22SELECT%20n.Uri%2C%20n.CustomProperties._Location%2C%20n.CustomProperties.Address_1%2C%20n.CustomProperties.Address_City%20FROM%20Orion.Nodes%20n%20WHERE%20n.Caption%20%3D%20’DVARNUM_2960’%22)%0A%7Bu’results’%3A%20%5B%7Bu’Address_City’%3A%20u’NMS’%2C%20u’_Location’%3A%20u’Super%20Secret%20Lab’%2C%20u’Uri’%3A%20u’swis%3A%2F%2Forion%2FOrion%2FOrion.Nodes%2FNodeID%3D7500’%2C%20u’Address_1’%3A%20u’1337%20Haxor%20Ln’%7D%5D%7D” message=”” highlight=”” provider=”manual”/]
Add a node to Orion using Python
For the next example, I’m going to show you how to add a node to Orion using Python. This is one of countless tasks you can automate, but I feel it is an important and interesting one. Again, SolarWinds provides you with a sample Python script you can build upon. This can be found here, called add_node.py.
The sample script adds a device with SNMPv2. This works just fine, but most environments these days use SNMPv3. That said, I’m going to modify this script to use my preferred SNMPv3 method. Additionally, I’d like to add some Custom Properties to my node, so I’ll append that to the script as well.
Much like the earlier example, I prefer the Python interpreter for testing Python syntax. We’ll hop on here first to run through the example. Open Python and load the necessary libraries
[pastacode lang=”python” manual=”%3E%3E%3E%20from%20__future__%20import%20print_function%0A%3E%3E%3E%20import%20re%0A%3E%3E%3E%20import%20requests%0A%3E%3E%3E%20from%20orionsdk%20import%20SwisClient%0A%3E%3E%3E” message=”” highlight=”” provider=”manual”/]
Disable SSL warnings (if necessary)
[pastacode lang=”python” manual=”%3E%3E%3E%20requests.packages.urllib3.disable_warnings()%0A%3E%3E%3E” message=”” highlight=”” provider=”manual”/]
Configure your NPM server, username and password. We can always mask and encrypt this in an actual script, but for now we’ll just load it into the terminal for sake of simplicity.
[pastacode lang=”python” manual=”%3E%3E%3E%20npm_server%20%3D%20’orion’%0A%3E%3E%3E%20username%20%3D%20’labuser’%0A%3E%3E%3E%20password%20%3D%20’x'” message=”” highlight=”” provider=”manual”/]
Next we invoke the SwisClient, which connects to the NPM server.
[pastacode lang=”python” manual=”%3E%3E%3E%20swis%20%3D%20SwisClient(npm_server%2C%20username%2C%20password)%0A%3E%3E%3E” message=”” highlight=”” provider=”manual”/]
Setup your node properties, such as the IP address and SNMP information. If you’re running SNMPv2, just use the example provided by SolarWinds.
[pastacode lang=”python” manual=”%3E%3E%3E%20ip_address%20%3D%20’10.10.0.42’%0A%3E%3E%3E%20%0A%3E%3E%3E%20props%20%3D%20%7B%0A…%20’IPAddress’%3A%20ip_address%2C%0A…%20’EngineID’%3A%205%2C%0A…%20’ObjectSubType’%3A%20’SNMP’%2C%0A…%20’SNMPVersion’%3A%203%2C%0A…%20’Caption’%3A%20’DVARNUM_2960’%2C%0A…%20’SNMPV3AuthKey’%3A%20’MyAuthKey33’%2C%0A…%20’SNMPv3AuthKeyIsPwd’%3A%20True%2C%0A…%20’SNMPv3AuthMethod’%3A%20’SHA1’%2C%0A…%20’SNMPv3PrivKey’%3A%20’MyPrivKey33’%2C%0A…%20’SNMPv3PrivKeyIsPwd’%3A%20True%2C%0A…%20’SNMPv3PrivMethod’%3A%20’AES128’%2C%0A…%20’SNMPV3Username’%3A%20’snmpgod’%0A…%20%7D” message=”” highlight=”” provider=”manual”/]
Invoke swis.create to create the node based on the properties entered above.
[pastacode lang=”python” manual=”%3E%3E%3E%20results%20%3D%20swis.create(‘Orion.Nodes’%2C%20**props)” message=”” highlight=”” provider=”manual”/]
Extract the Node ID from the results.
[pastacode lang=”python” manual=”%3E%3E%3E%20nodeid%20%3D%20re.search(‘(%5Cd%2B)%24’%2C%20results).group(0)%0A%3E%3E%3E%20nodeid%0Au’7607′” message=”” highlight=”” provider=”manual”/]
Our new node was added to Orion and assigned Node ID 7607. Now we need to setup some pollers. This below is pulled straight from the SDK repo.
[pastacode lang=”python” manual=”%3E%3E%3E%20pollers_enabled%20%3D%20%7B%0A…%20%20%20%20%20’N.Status.ICMP.Native’%3A%20True%2C%0A…%20%20%20%20%20’N.Status.SNMP.Native’%3A%20False%2C%0A…%20%20%20%20%20’N.ResponseTime.ICMP.Native’%3A%20True%2C%0A…%20%20%20%20%20’N.ResponseTime.SNMP.Native’%3A%20False%2C%0A…%20%20%20%20%20’N.Details.SNMP.Generic’%3A%20True%2C%0A…%20%20%20%20%20’N.Uptime.SNMP.Generic’%3A%20True%2C%0A…%20%20%20%20%20’N.Cpu.SNMP.HrProcessorLoad’%3A%20True%2C%0A…%20%20%20%20%20’N.Memory.SNMP.NetSnmpReal’%3A%20True%2C%0A…%20%20%20%20%20’N.AssetInventory.Snmp.Generic’%3A%20True%2C%0A…%20%20%20%20%20’N.Status.SNMP.Native’%3A%20False%2C%0A…%20%20%20%20%20’N.ResponseTime.SNMP.Native’%3A%20False%2C%0A…%20%20%20%20%20’N.Topology_Layer3.SNMP.ipNetToMedia’%3A%20False%2C%0A…%20%20%20%20%20’N.Routing.SNMP.Ipv4CidrRoutingTable’%3A%20False%0A…%20%7D%0A%3E%3E%3E%20pollers%20%3D%20%5B%5D%0A%3E%3E%3E%20for%20k%20in%20pollers_enabled%3A%0A…%20%20%20%20%20pollers.append(%0A…%20%20%20%20%20%7B%0A…%20%20%20%20%20’PollerType’%3A%20k%2C%0A…%20%20%20%20%20’NetObject’%3A%20’N%3A’%20%2B%20nodeid%2C%0A…%20%20%20%20%20’NetObjectType’%3A%20’N’%2C%0A…%20%20%20%20%20’NetObjectID’%3A%20nodeid%2C%0A…%20%20%20%20%20’Enabled’%3A%20pollers_enabled%5Bk%5D%0A…%20%20%20%20%20%7D%0A…%20)%0A…%20%0A%3E%3E%3E%20for%20poller%20in%20pollers%3A%0A…%20%20%20%20%20print(%22%20Adding%20poller%20type%3A%20%7B%7D%20with%20status%20%7B%7D…%20%22.format(poller%5B’PollerType’%5D%2C%20poller%5B’Enabled’%5D)%2C%20end%3D%22%22)%0A…%20%20%20%20%20response%20%3D%20swis.create(‘Orion.Pollers’%2C%20**poller)%0A…%20%20%20%20%20print(%22DONE!%22)%0A…%20%0A%20Adding%20poller%20type%3A%20N.Memory.SNMP.NetSnmpReal%20with%20status%20True…%20DONE!%0A%20Adding%20poller%20type%3A%20N.ResponseTime.ICMP.Native%20with%20status%20True…%20DONE!%0A%20Adding%20poller%20type%3A%20N.ResponseTime.SNMP.Native%20with%20status%20False…%20DONE!%0A%20Adding%20poller%20type%3A%20N.Status.SNMP.Native%20with%20status%20False…%20DONE!%0A%20Adding%20poller%20type%3A%20N.Cpu.SNMP.HrProcessorLoad%20with%20status%20True…%20DONE!%0A%20Adding%20poller%20type%3A%20N.Routing.SNMP.Ipv4CidrRoutingTable%20with%20status%20False…%20DONE!%0A%20Adding%20poller%20type%3A%20N.Uptime.SNMP.Generic%20with%20status%20True…%20DONE!%0A%20Adding%20poller%20type%3A%20N.Details.SNMP.Generic%20with%20status%20True…%20DONE!%0A%20Adding%20poller%20type%3A%20N.Topology_Layer3.SNMP.ipNetToMedia%20with%20status%20False…%20DONE!%0A%20Adding%20poller%20type%3A%20N.Status.ICMP.Native%20with%20status%20True…%20DONE!%0A%20Adding%20poller%20type%3A%20N.AssetInventory.Snmp.Generic%20with%20status%20True…%20DONE!%0A%3E%3E%3E” message=”” highlight=”” provider=”manual”/]
All of our pollers were successfully added to the node. If we pull up the GUI, we can see that our node is there but the status is unknown.
My personal results have been hit and miss on this, but this could just be the default discovery interval waiting to triggered, and patience would bring our node online. Or, instead of waiting, we can force a poll using the ‘PollNow’ verb.
[pastacode lang=”python” manual=”%3E%3E%3E%20swis.invoke(‘Orion.Nodes’%2C%20’PollNow’%2C%20’N’%20%2B%20nodeid)” message=”” highlight=”” provider=”manual”/]
And now we’re in business.
Lastly, we want to add our custom properties. To do so, I create a Python dictionary with they key/value pairs, then iterate over it and ship the new values via swis.update. I’m going to use the same custom property values we used earlier, and in the previous article (link). First, notice our custom properties are currently blank on the new node.
[pastacode lang=”python” manual=”%3E%3E%3E%20results%0Au’swis%3A%2F%2Forion%2FOrion%2FOrion.Nodes%2FNodeID%3D7607’%0A%3E%3E%3E%0A%3E%3E%3E%20custom_props%20%3D%20swis.read(‘swis%3A%2F%2Forion%2FOrion%2FOrion.Nodes%2FNodeID%3D7607%2FCustomProperties’)%0A%3E%3E%3E%20pprint.pprint(updated_custom_props)%0A%7Bu’Address_1’%3A%20None%2C%0A%20u’Address_2’%3A%20None%2C%0A%20u’Address_City’%3A%20None%2C%0A%20u’Address_State’%3A%20None%2C%0A%20u’Address_Zip’%3A%20None%0A%20…truncated” message=”” highlight=”” provider=”manual”/]
I’ll create a dictionary of the custom properties I’d like to modify.
[pastacode lang=”python” manual=”%3E%3E%3E%20custom_props%20%3D%20%7B%0A…%20’Address_1’%3A%20’Lab’%2C%0A…%20’Address_2’%3A%20’1337%20Haxor%20Ln’%2C%0A…%20’Address_City’%3A%20’Suite%20API’%2C%0A…%20’Address_State’%3A%20’NMS’%2C%0A…%20’Address_Zip’%3A%20’10101’%2C%0A…%20%7D%0A%3E%3E%3E” message=”” highlight=”” provider=”manual”/]
Now, will rip through this dictionary and invoke swis.update to populate the fields.
[pastacode lang=”python” manual=”%3E%3E%3E%20for%20k%2Cv%20in%20custom_props.items()%3A%0A…%20%20%20%20%20swis.update(results%20%2B%20’%2FCustomProperties’%2C%20**%7Bk%3A%20v%7D)%0A…%20%0A%3E%3E%3E” message=”” highlight=”” provider=”manual”/]
Let’s read this back from Orion and print the results.
[pastacode lang=”python” manual=”%3E%3E%3E%20updated_custom_props%20%3D%20swis.read(‘swis%3A%2F%2Forion%2FOrion%2FOrion.Nodes%2FNodeID%3D7607%2FCustomProperties’)%0A%3E%3E%3E%20pprint.pprint(updated_custom_props)%0A%7Bu’Address_1’%3A%20u’Lab’%2C%0A%20u’Address_2’%3A%20u’1337%20Haxor%20Ln’%2C%0A%20u’Address_City’%3A%20u’Suite%20API’%2C%0A%20u’Address_State’%3A%20u’NMS’%2C%0A%20u’Address_Zip’%3A%20u’10101’%2C” message=”” highlight=”” provider=”manual”/]
There we are!!
Wrapping this up
Now that we know this works, we can wrap it up in a Python script. This particular script will ask you for the node IP and the node name. It will also prompt you to enter your password. The script will be at the bottom of this article. Here’s showing it in action:
And here’s our node:
Take this baseline, get creative, and modify as needed for your environment.
Closing Thoughts
Here we’ve demonstrated the Pythonic approach to SolarWinds SDK. There’s certainly much more you can do with this, and ultimately you’d want to secure it for your production environment. Utilize the example scripts in GitHub and browse Thwack for answers to your queries. If your goal is to develop automation, Python or PowerShell are the best options for you. Poke around the GitHub repo and you’ll find PowerShell examples similar to the ones available in Python.
Stay tuned for future articles involving the SolarWinds SDK.
Python Add Node Script Example
[pastacode lang=”python” manual=”from%20__future__%20import%20print_function%0Aimport%20re%0Aimport%20requests%0Afrom%20orionsdk%20import%20SwisClient%0Aimport%20getpass%0A%0Adef%20main()%3A%0A%09requests.packages.urllib3.disable_warnings()%0A%09%0A%09npm_server%20%3D%20’orion’%0A%09username%20%3D%20’labuser’%0A%09password%20%3D%20getpass.getpass()%0A%0A%09swis%20%3D%20SwisClient(npm_server%2C%20username%2C%20password)%0A%09%0A%09%23%20Add%20the%20node%20IP%0A%09ip_address%20%3D%20raw_input(%22Enter%20the%20node%20IP%3A%20%22)%0A%09node_name%20%3D%20raw_input(%22Enter%20the%20node%20name%3A%20%22)%0A%09%0A%09%23%20Setup%20properties%20for%20the%20new%20node%0A%09props%20%3D%20%7B%0A%09%20%20%20%20’IPAddress’%3A%20ip_address%2C%0A%09%20%20%20%20’EngineID’%3A%205%2C%0A%09%20%20%20%20’ObjectSubType’%3A%20’SNMP’%2C%0A%09%20%20%20%20’SNMPVersion’%3A%203%2C%0A%09%20%20%20%20’Caption’%3A%20node_name%2C%0A%09%20%20%20%20’SNMPV3AuthKey’%3A%20’MyAuthKey33’%2C%0A%09%20%20%20%20’SNMPv3AuthKeyIsPwd’%3A%20True%2C%0A%09%20%20%20%20’SNMPv3AuthMethod’%3A%20’SHA1’%2C%0A%09%20%20%20%20’SNMPv3PrivKey’%3A%20’MyPrivKey33’%2C%0A%09%20%20%20%20’SNMPv3PrivKeyIsPwd’%3A%20True%2C%0A%09%20%20%20%20’SNMPv3PrivMethod’%3A%20’AES128’%2C%0A%09%20%20%20%20’SNMPV3Username’%3A%20’snmpgod’%0A%09%7D%0A%09%0A%09%23%20Create%20the%20node%0A%09print(%22Adding%20node%20%7B%7D…%20%22.format(props%5B’IPAddress’%5D)%2C%20end%3D%22%22)%0A%09results%20%3D%20swis.create(‘Orion.Nodes’%2C%20**props)%0A%09print(%22DONE!%22)%0A%09%0A%09%23%20Extract%20nodeID%20from%20the%20results%0A%09nodeid%20%3D%20re.search(‘(%5Cd%2B)%24’%2C%20results).group(0)%0A%0A%09%23%20Setup%20poller%20status%20for%20the%20node%0A%09pollers_enabled%20%3D%20%7B%0A%09%09’N.Status.ICMP.Native’%3A%20True%2C%0A%09%09’N.Status.SNMP.Native’%3A%20False%2C%0A%09%09’N.ResponseTime.ICMP.Native’%3A%20True%2C%0A%09%09’N.ResponseTime.SNMP.Native’%3A%20False%2C%0A%09%09’N.Details.SNMP.Generic’%3A%20True%2C%0A%09%09’N.Uptime.SNMP.Generic’%3A%20True%2C%0A%09%09’N.Cpu.SNMP.HrProcessorLoad’%3A%20True%2C%0A%09%09’N.Memory.SNMP.NetSnmpReal’%3A%20True%2C%0A%09%09’N.AssetInventory.Snmp.Generic’%3A%20True%2C%0A%09%09’N.Topology_Layer3.SNMP.ipNetToMedia’%3A%20False%2C%0A%09%09’N.Routing.SNMP.Ipv4CidrRoutingTable’%3A%20False%0A%09%7D%0A%0A%20%20%20%20%23%20Add%20node%20to%20pollers%0A%09pollers%20%3D%20%5B%5D%0A%09for%20k%20in%20pollers_enabled%3A%0A%09%09pollers.append(%0A%09%09%09%7B%0A%09%09%09%09’PollerType’%3A%20k%2C%0A%09%09%09%09’NetObject’%3A%20’N%3A’%20%2B%20nodeid%2C%0A%09%09%09%09’NetObjectType’%3A%20’N’%2C%0A%09%09%09%09’NetObjectID’%3A%20nodeid%2C%0A%09%09%09%09’Enabled’%3A%20pollers_enabled%5Bk%5D%0A%09%09%09%7D%0A%09%09)%0A%0A%09for%20poller%20in%20pollers%3A%0A%09%09print(%22%20%20Adding%20poller%20type%3A%20%7B%7D%20with%20status%20%7B%7D…%20%22.format(poller%5B’PollerType’%5D%2C%20poller%5B’Enabled’%5D)%2C%20end%3D%22%22)%0A%09%09response%20%3D%20swis.create(‘Orion.Pollers’%2C%20**poller)%0A%09%09print(%22DONE!%22)%0A%0A%20%20%20%20%23%20Poll%20the%20node%0A%09swis.invoke(‘Orion.Nodes’%2C%20’PollNow’%2C%20’N’%20%2B%20nodeid)%0A%09%0A%09%23%20Add%20custom%20properties%0A%09custom_props%20%3D%20%7B%0A%09%20%20%20%20’Address_1’%3A%20’Lab’%2C%0A%09%20%20%20%20’Address_2’%3A%20’1337%20Haxor%20Ln’%2C%0A%09%20%20%20%20’Address_City’%3A%20’Suite%20API’%2C%0A%09%20%20%20%20’Address_State’%3A%20’NMS’%2C%0A%09%20%20%20%20’Address_Zip’%3A%20’10101’%2C%0A%09%7D%0A%09%0A%09for%20k%2Cv%20in%20custom_props.items()%3A%0A%09%09print(%22%20%20Adding%20custom%20property%3A%20%7B%7D%20with%20value%20%7B%7D…%20%22.format(k%2C%20v)%2C%20end%3D%22%22)%0A%09%09swis.update(results%20%2B%20’%2FCustomProperties’%2C%20**%7Bk%3A%20v%7D)%0A%09%09print(%22DONE!%22)%0A%09%0Aif%20__name__%20%3D%3D%20’__main__’%3A%0A%20%20%20%20main()” message=”” highlight=”” provider=”manual”/]
SolarWinds Orion API & SDK – Scripting with Python FAQs
How do I access SolarWinds API?
To access SolarWinds API, you need to obtain an API key and authenticate your requests using HTTP Basic Authentication. You can then send API requests to the SolarWinds API endpoint using HTTP or HTTPS.
How do I query SolarWinds API using Python?
To query SolarWinds API using Python, you can use the requests library to send HTTP requests and retrieve JSON-formatted data. You will need to include your API key and authentication credentials in your requests, and specify the API endpoint and parameters you wish to query.
What are some common use cases for querying SolarWinds API with Python?
Some common use cases for querying SolarWinds API with Python include:
Are there any Python libraries or tools available for working with SolarWinds API?
Yes, there are several Python libraries and tools available for working with SolarWinds API, including the SolarWinds API Python client, the PySWQL library for querying SolarWinds Orion databases, and the SolarWinds Information Service (SWIS) client for interacting with the SolarWinds Information Service.
What are some best practices for working with SolarWinds API in Python?
Some best practices for working with SolarWinds API in Python include: