haxtibal / netsnmptable

A Python C Extension package to query SNMP tables and table subsets, complementing the original Net-SNMP Python Bindings.
Other
7 stars 0 forks source link

netsnmptable

A Python C Extension package to query SNMP tables and table subsets based on the Net-SNMP libraries.

Goals

The project aims to bring SNMP table query functionality for Python.

Current state and future

The API is currently not yet stable. Implementation works and is tested on following targets

IMO it would be good to eventually integrate the table functions into a more complete, all-in-one Python SNMP Client package. If you are the maintainer of such a package and like the idea, please let me know.

I currently do monkey patching of the original Net-SNMP Python Bindings to fake that integration, but are looking forward for better options.

How to build and install

Prerequisites:

Download and extract the source package, then

~/netsnmptable$ python setup.py build
~/netsnmptable$ sudo python setup.py install

License

This software is released under the LGPLv3 license.

Some re-used code is copyrighted. See the LICENSE file for full license text and the original copyright notices.

Examples

Here are some examples how to use netsnmptable.

Example 1: Print out the Host Resources Storage Table

import netsnmp
import netsnmptable

# create a table object
session = netsnmp.Session(Version=2, DestHost='localhost', Community='public')
table = session.table_from_mib('HOST-RESOURCES-MIB::hrStorageTable')

# go and get the table...
tbldict = table.get_entries()
if (netsnmp_session.ErrorNum):
    print("Can't query HOST-RESOURCES-MIB:hrStorageTable.")
    exit(-1)

print("{:10s} {:25s} {:10s} {:10s} {:10s}".format("Index", "Description", "Units", "Size", "Used"))
row_keys = sorted(list(tbldict.keys()))
for row_key in row_keys:
    row = tbldict[row_key]
    cell_list = [element.val if element else "" for element in
                 [row.get('hrStorageIndex'), row.get('hrStorageDescr'),
                  row.get('hrStorageAllocationUnits'), row.get('hrStorageSize'),
                  row.get('hrStorageUsed')]]
    print("{:10s} {:25s} {:10s} {:10s} {:10s}".format(*cell_list))

Results in

Index      Description               Units      Size       Used      
1          Physical memory           1024       2054128    233540    
3          Virtual memory            1024       3099628    361064    
6          Memory buffers            1024       2054128    14564     
7          Cached memory             1024       82232      82232     
8          Shared memory             1024       0                    
10         Swap space                1024       1045500    127524    
31         /dev                      4096       2560       0         
32         /                         4096       10063200   2495552   
33         /sys/fs/fuse/connections  4096       0          0         
34         /run/vmblock-fuse         512        0          0         
35         /media/sources            4096       121833215  92355036  
36         /media/sandboxes          4096       121833215  92355036  
37         /media/cdrom0             2048       32876      32876    

Example 2: Query a multi-indexed table

Tables with more than one index are no problem. The row key tuple just gets more elements.

Let's setup following table in snmpd.conf:

table MYTABLETEST::testTable 
#                               idx1          idx2            aValue  anotherValue
add_row MYTABLETEST::testTable "OuterIdx_1"   "InnerIdx_1"     1       2
add_row MYTABLETEST::testTable "OuterIdx_1"   "InnerIdx_2"     3       4
add_row MYTABLETEST::testTable "OuterIdx_2"   "InnerIdx_1"     5       6
add_row MYTABLETEST::testTable "OuterIdx_2"   "InnerIdx_2"     7       8
add_row MYTABLETEST::testTable "OuterIdx_3"   "InnerIdx_1"     9      10
add_row MYTABLETEST::testTable "OuterIdx_3"   "InnerIdx_2"    11      12

Now query it with

import netsnmp
import netsnmptable
import pprint
from types import MethodType

def varbind_to_repr(self):
    return self.type + ":" + self.val
netsnmp.Varbind.__repr__ = MethodType(varbind_to_repr, None, netsnmp.Varbind)

session = netsnmp.Session(Version=2, DestHost='localhost', Community='public')
table = session.table_from_mib('MYTABLETEST::testTable')
tbldict = table.get_entries()
pprint.pprint(tbldict)

This gives

{('OuterIdx_1', 'InnerIdx_1'): {'aValue': INTEGER32:1,
                                'anotherValue': INTEGER32:2},
 ('OuterIdx_1', 'InnerIdx_2'): {'aValue': INTEGER32:3,
                                'anotherValue': INTEGER32:4},
 ('OuterIdx_2', 'InnerIdx_1'): {'aValue': INTEGER32:5,
                                'anotherValue': INTEGER32:6},
 ('OuterIdx_2', 'InnerIdx_2'): {'aValue': INTEGER32:7,
                                'anotherValue': INTEGER32:8},
 ('OuterIdx_3', 'InnerIdx_1'): {'aValue': INTEGER32:9,
                                'anotherValue': INTEGER32:10},
 ('OuterIdx_3', 'InnerIdx_2'): {'aValue': INTEGER32:11,
                                'anotherValue': INTEGER32:12}}

Example 3: Query a multi-indexed table with only selected index values

Say we want to fetch from the same table, but only entries for "OuterIdx_2".

session = netsnmp.Session(Version=2, DestHost='localhost', Community='public')
table = session.table_from_mib('MYTABLETEST::testTable')
tbldict = table.get_entries(iid = netsnmptable.str_to_varlen_iid("OuterIdx_2"))
pprint.pprint(tbldict)

Results in

{('OuterIdx_2', 'InnerIdx_1'): {'aValue': INTEGER32:5,
                                'anotherValue': INTEGER32:6},
 ('OuterIdx_2', 'InnerIdx_2'): {'aValue': INTEGER32:7,
                                'anotherValue': INTEGER32:8}}

Development Resources

Credits

Thanks to Pieter Hollants pieter@hollants.com for python-netsnmpagent. The tests.testagent package is heavily based on it.

Related work

Other people also tackle the hassle of dealing with SNMP in Python and found interesting approaches. Below is an incomplete and unordered list.

Libraries

Table handling