I'm new to SNMP, and finding it difficult to understand some of the mechanisms in PySNMP. I need to implement a table with read-create permissions to monitor and control a bridge on my network. I think it would be helpful if I had more clarity on one of the pieces of example code to understand what's happening in the framework when a manager attempts to create a new row.
I've been examining the sample code for implementing a conceptual table and executing the example snmpset/walk commands:
$ snmpset -v2c -c public 127.0.0.1 1.3.6.6.1.5.2.97.98.99 s “my value”
$ snmpset -v2c -c public 127.0.0.1 1.3.6.6.1.5.4.97.98.99 i 4
$ snmpwalk -v2c -c public 127.0.0.1 1.3.6
As far as I can tell, the set commands work because the MIB promises that exampleTableColumn2
describes OctetString
scalars. How is this data created/stored by the agent? Is a generic scalar object created with the suffix ".97.98.99," or is this information somehow associated with the instance of exampleTableColumn2
? If I were to subsequently run an snmpget or snmpset command on the object we just created, what would I be interacting with in the eyes of the framework?
In a real-world implementation, the agent would really be querying the device to create a new entry in some internal table, and you would need custom scalar objects with modified readGet/writeCommit methods, but the sample code hasn't established scalar classes to implement get/set methods. By understanding how columns with read-create permissions should be handled in PySNMP, I think I can implement a more robust agent application. Any help/clarity is sincerely appreciated.
How is this data created/stored by the agent? Is a generic scalar object created with the suffix ".97.98.99," or is this information somehow associated with the instance of exampleTableColumn2?
This is a generic scalar value of type OctetString
associated with a leaf node in a tree of objects (MIB tree) of type MibTableColumn
. In the MIB tree you will find a handful of node types each exhibiting distinct behavior (see docstrings), but otherwise they are very similar. Each node is identified by an OID.
If I were to subsequently run an snmpget or snmpset command on the object we just created, what would I be interacting with in the eyes of the framework?
The MIB tree object responsible for the OID you are querying will receive read* (for SNMP GET) or read*Next (for SNMP GETNEXT/GETBULK) events to which it should respond with a value.
In a real-world implementation, the agent would really be querying the device to create a new entry in some internal table, and you would need custom scalar objects with modified readGet/writeCommit methods
There are a couple of approaches to this problem, the way I've been pursuing it so far is to override some of these read*
/read*Next
/write*
methods to read or write the value from/to its ultimate source (your internal table).
To simplify and keep your code in-sync with the MIB you are implementing, the pysmi library can turn a MIB into Python code with stubs via Jinja2 templates. From these stubs you can access your internal table whenever SNMP request triggers a read or write event. You can put your custom code into these stubs and/or into Jinja2 templates from which these stubs are generated.
Alternatively to implementing your own SNMP agent, you might consider this general purpose tool, which is driven by the same technology.