Tuesday, 1 December 2015

Extending SNMP

One of the things I love about SNMP is how easy it is to extend and use it as a wrapper service.

I was training some of my colleagues today on SNMP and as part of the course we covered extending SNMP in detail.

Beyond the simple things like echoing back a value, it's great that it can call external scripts and pass arguments to them.

An example of this is to be able to get the percentage of used disk space on a hard drive.
To extend snmp, we add a line to snmpd.conf file.
extend rootspace /bin/bash /scripts/getdiskspace.sh /dev/disk1

/scripts/getdiskspace.sh - the script to call

/dev/disk1 - the parameter to pass to the script.

Once we have set this up, we can get all of the extended parameters by walking the NET-SNMP-EXTEND-MIB::nsExtendObjects OID

snmpwalk -c public NET-SNMP-EXTEND-MIB::nsExtendObjects

Which gives us:
NET-SNMP-EXTEND-MIB::nsExtendNumEntries.0 = INTEGER: 2
NET-SNMP-EXTEND-MIB::nsExtendCommand."dataspace" = STRING: /bin/bash
NET-SNMP-EXTEND-MIB::nsExtendCommand."rootspace" = STRING: /bin/bash
NET-SNMP-EXTEND-MIB::nsExtendArgs."dataspace" = STRING: /scripts/getdiskspace.sh /Volumes/Data
NET-SNMP-EXTEND-MIB::nsExtendArgs."rootspace" = STRING: /scripts/getdiskspace.sh /dev/disk1
NET-SNMP-EXTEND-MIB::nsExtendInput."dataspace" = STRING: NET-SNMP-EXTEND-MIB::nsExtendInput."rootspace" = STRING: NET-SNMP-EXTEND-MIB::nsExtendCacheTime."dataspace" = INTEGER: 5
NET-SNMP-EXTEND-MIB::nsExtendCacheTime."rootspace" = INTEGER: 5
NET-SNMP-EXTEND-MIB::nsExtendExecType."dataspace" = INTEGER: exec(1)
NET-SNMP-EXTEND-MIB::nsExtendExecType."rootspace" = INTEGER: exec(1)
NET-SNMP-EXTEND-MIB::nsExtendRunType."dataspace" = INTEGER: run-on-read(1)
NET-SNMP-EXTEND-MIB::nsExtendRunType."rootspace" = INTEGER: run-on-read(1)
NET-SNMP-EXTEND-MIB::nsExtendStorage."dataspace" = INTEGER: permanent(4)
NET-SNMP-EXTEND-MIB::nsExtendStorage."rootspace" = INTEGER: permanent(4)
NET-SNMP-EXTEND-MIB::nsExtendStatus."dataspace" = INTEGER: active(1)
NET-SNMP-EXTEND-MIB::nsExtendStatus."rootspace" = INTEGER: active(1)
NET-SNMP-EXTEND-MIB::nsExtendOutput1Line."dataspace" = STRING: 93
NET-SNMP-EXTEND-MIB::nsExtendOutput1Line."rootspace" = STRING: 76
NET-SNMP-EXTEND-MIB::nsExtendOutputFull."dataspace" = STRING: 93
NET-SNMP-EXTEND-MIB::nsExtendOutputFull."rootspace" = STRING: 76
NET-SNMP-EXTEND-MIB::nsExtendOutNumLines."dataspace" = INTEGER: 1
NET-SNMP-EXTEND-MIB::nsExtendOutNumLines."rootspace" = INTEGER: 1
NET-SNMP-EXTEND-MIB::nsExtendResult."dataspace" = INTEGER: 0
NET-SNMP-EXTEND-MIB::nsExtendResult."rootspace" = INTEGER: 0
NET-SNMP-EXTEND-MIB::nsExtendOutLine."dataspace".1 = STRING: 93
NET-SNMP-EXTEND-MIB::nsExtendOutLine."rootspace".1 = STRING: 76

The info we are interested in are the output lines:

NET-SNMP-EXTEND-MIB::nsExtendOutput1Line."rootspace" = STRING: 93
NET-SNMP-EXTEND-MIB::nsExtendOutLine."rootspace".1 = STRING: 93

The result value gives the exit status of the script, so we could pass an integer on exit to this parameter

NET-SNMP-EXTEND-MIB::nsExtendResult."rootspace" = INTEGER: 0

To get just a single response with snmpget, we would use the following:

snmpget -c public 'NET-SNMP-EXTEND-MIB::nsExtendOutput1Line."rootspace"'
which responds with:

NET-SNMP-EXTEND-MIB::nsExtendOutput1Line."rootspace" = STRING: 76

This format of the above line is:
extend - the extend directive
rootspace - the extension command that the daemon will respond to
/bin/bash - the external environment to run the extension in