Design Decisions

Another SNMP package?

There are at least 3 more SNMP packages out there. Those are:

So why another package? API simplicity, Maintainability & MIB independence

The existing libraries all suffer from an overall complexity to use in simple applications. This complexity is partially dictated by the SNMP RFCs like RFC 3411. The focus on usage simplicity has driven many of the following design decisions.

While usage simplicity is one thing, maintainability is another. For that, see the point about RFC-divergence below.

Finally, all existing modules have a strong focus on MIBs, which can be problematic at times. Especially for heterogenuous networks. puresnmp makes it easy to work without MIBs.

Extensive Documentation

Simple and useful documentation is an additional focus of this library. The documentation provides a lot of example-code which should make usage of the library a lot easier. The examples in the documetnation are covered by doctests wherever possible. This forces the examples in the docstrings to be complete and should be fairly copy/pasteable.

Most of these examples are located in puresnmp.api.raw.Client (aliased for convenience as puresnmp.Client)

Note

When using the documentation examples from puresnmp.api.raw.Client also consider using puresnmp.api.pythonic.PyWrapper (aliased as puresnmp.PyWrapper) to decouple internal data-types from your application.

Simple Data-Types

Using puresnmp.api.pythonic.PyWrapper all data-types are converted at the seam between the internal Python world and the SNMP worls (with the exception of “SET” requests).

Applications using the PyWrapper will be strongly decoupled from any internal changes inside puresnmp.

All internal datatypes inherit from x690.types.X690Type and provide the value property to retrieve the pure-Python value.

This may hide details from the exchanged data-types with the remote SNMP device. For example, both Counter and Integer are converted to pure-Python integers. For most use-cases this is useful and convenient. But if needed, they can always be accessed by using puresnmp.api.pythonic.PyWrapper.client.

No MIB Support?

Experience has shown that MIB modules can be very fragile, especially on very heterogenuous networks. Raw OIDs are much more stable and reliable, at the expense of “human-readility”.

puresnmp skips the processing of MIBs for this reason. Adding MIB support is still possible as “wrapper” aruond the lower level primitives, but at the moment there are no plans for development of this. Note that the library is currently actively used on a large network with over 6k devices of various manufacturers. All without MIBs, all without problems.

Effectively, MIBs sit between the user and the SNMP protocol. puresnmp provides low-level support for SNMP.

Not having native support for MIBs might seem very limiting at first. Let’s look at the benefits of MIBs:

  • They provide additional data-types (which are always sub-types of native/vanilla SNMP types)

  • They provide definitions for “tables”

  • They provide human-readable names for OIDs

All data-types used by puresnmp are compatible with the data-types defined in MIBs. Some more esoteric data-types may be reported as x690.types.OctetString without MIBs, but they always represent the real value.

Low-level table support is provided by puresnmp.api.pythonic.PyWrapper.table() and puresnmp.api.raw.Client.table() but row-indeces may need to be post-processed.

Converting OIDs to/from human-readable text should primarily be done on the UI level. This is not the responsibility of the library.

Divergence from RFC-3411

RFC 3411 dictates an overall architecture which is very generic. That architecture is “open” enough to allow it being implemented in many programming languages. Dynamic languages like Python allow for different implementations which would suffer from strict adherence to the RFC.

The RFC has one clear aim: Being future-proof by “pluggability”.

This pluggability is provided in puresnmp by the use of “namespace modules”. This allows us to provide new functionality in the future without sacrificing “pythonic” code. It does therefore slightly diverge from the RFC-3411 process of how “plugins” are looked up.

Finally, the library has a primary focus on being an SNMP client. Not an SNMP server. For this reason, a lot of implementations from the RFC have been skipped.

Like MIB support, adding support to respond to SNMP requests is not out of the question, but not planned either. Feel free to contact the author(s) if you want to provide support for this.

Type Hinting

The library is fully type-hinted providing a stable and maintainable code-base.

Async first

The library only provides async functions. This allows us to have one common code-base for everything. The previous version (v1.x) of puresnmp contained both a “sync” and “async” implementation, making maintainance cumbersome and error-prone.

puresnmp can be easily integrated into a non-async application by using asyncio.run().