Snmpwalk Mib Descriptive Essay

Dieser Artikel wird nicht mehr gepflegt und ist unter Umständen nicht mehr gültig!

1. Preparations and SNMP basics

SNMP based checks work exactly like the agent based ones with one exception: Instead of using a section from an agent's output you specify a list of subtrees in an SNMP MIB as data source. Check_MK will retrieve each of the subtrees with a separate and combine the output into a table compatible with those used by the agent based checks.

1.1. SNMPv1 versus SNMPv2

Before we can start I want to say a few words about the different SNMP versions. Check_MK supports three of them: v1, v2c and v3. When calling you always have to specify the SNMP version to use (, or ) Please note that:

  • Some information is only available via and !
  • Some older devices do not support and , however
  • is about encryption and security and inconvenient for testing.

Do not wonder that you cannot find any 64 bit counters when using . SNMPv1 does not support them. So rather try in that case. Please note, that users must declare such SNMPv2c-hosts in in .

1.2. Vendor specific MIBs

Many people have an unclear understand of what a MIB (file) is. Some assume that with the installation of a MIB file a monitoring system automatically knows how to monitor the device in question. The truth is that:

  • A MIB file is just a translation from numeric OIDs and enumeration values into texts.
  • It also might contain some human readable explanation of its variables.
  • Check_MK does not need (nor use) MIB files.

MIB files are quite helpful during the development of checks since they give us information about the existing OIDs and their meaning. They help finding the OIDs interesting for the monitoring and the possible values they can have. There are two ways for installing a MIB file:

  1. Install it as in
  2. Install it as user in (do a mkdir -p before this)

If you correctly have installed a MIB files, will show names instead of numbers at the places in question.

1.3. Finding the correct OIDs

If you have setup your SNMP environment, then next step in implementing our own SNMP check is to find the interesting places (OIDs) in the whole tree of SNMP variables your device supports.

In this tutorial we want to write a simple check for testing the operational state of network interfaces. Check_MK already ships a powerful check that can do this and much more (/). But as an example this will do perfectly (and it will work on almost every SNMP device).

After some investigation with we find the place in the OID tree where information about local network interfaces is provided:

root@linux# snmpwalk -v1 -c public ifTable IF-MIB::ifIndex.1 = INTEGER: 1 IF-MIB::ifIndex.2 = INTEGER: 2 IF-MIB::ifIndex.3 = INTEGER: 3 IF-MIB::ifDescr.1 = STRING: lo IF-MIB::ifDescr.2 = STRING: eth0 IF-MIB::ifDescr.3 = STRING: eth1 IF-MIB::ifType.1 = INTEGER: softwareLoopback(24) IF-MIB::ifType.2 = INTEGER: ethernetCsmacd(6) IF-MIB::ifType.3 = INTEGER: ethernetCsmacd(6) IF-MIB::ifMtu.1 = INTEGER: 16436

Since Check_MK in general works with numeric OIDs, lets call again, this time with the option :

root@linux# snmpwalk -On -v2c -c public ifTable. = INTEGER: 1 . = INTEGER: 2 . = INTEGER: 3 . = STRING: lo . = STRING: eth0 . = STRING: eth1 . = INTEGER: softwareLoopback(24) . = INTEGER: ethernetCsmacd(6) . = INTEGER: ethernetCsmacd(6) . = INTEGER: 16436 . = INTEGER: 1500 . = INTEGER: 1500 . = Gauge32: 10000000 . = Gauge32: 10000000 . = Gauge32: 10000000 . = STRING: . = STRING: 8:0:27:38:45:b1 . = STRING: 8:0:27:f4:e2:e . = INTEGER: up(1) . = INTEGER: up(1) . = INTEGER: up(1) . = INTEGER: up(1) . = INTEGER: up(1) . = INTEGER: down(2)

I marked the interesting OIDs in the example output. The longest common prefix of all relevant OIDs is in our case. We'll remember that for later. Now we have to decide, which subtrees are needed. In our case we will use the following sub OIDs:

2The name of the interface
3The type of the interface
8The operational state of the interface

1.4. Declaration of the OIDs in the check file

Now let's create a check file with the name . The needed OIDs are declared in the array . You specify a pair of

  • The base OID (= the prefix)
  • A python list with the sub OIDs to retrieve below this base OID
snmp_info["mynics"] = ( ".", [ "2", "3", "8" ] )

Note: If you are using OMD, then you put your check files as site user directly into your site's local area into .

As soon as an entry exists for a check Check_MK knows that it is of type SNMP (and not TCP). During inventory and during checking Check_MK will fetch the three sub-OIDs , and below the prefix with three separate calls to .

2. The implementation of the check

2.1. Dummy implementation

Just as in tutorial for agent based checks, we first write dummy functions and output the data arriving at the inventory function. Here is a complete check implementation:

def inventory_mynics(info): # Debug: lets see how the data we get looks like print info return [] def check_mynics(item, params, info): return (3, "UNKNOWN - not yet implemented") check_info["mynics"] = { "check_function" : check_mynics, "inventory_function" : inventory_mynics, "service_description" : "NIC %s", "snmp_info" : ( ".", [ "2", "3", "8" ] )

An explanations of for those who have not read the tutorial for agent based checks:

  • The first entry is the check function
  • The second entry is the Nagios service description. The will be replaced with the check item. If your check does not have an item (uses ) then you must not use a .
  • The third entry is if the check outputs performance data and otherwise.
  • The forth entry is the inventory function or if you check does not support inventory.

We know that that declaration is a bit strange. This has historical reasons, of course. During the version 1.1.11 it will probably cleaned up...

2.2. A first test of our check

Before we can try a first inventory, we must declare the host as an SNMP host in . Otherwise Check_MK will not even contact the host via SNMP (this has changed in version 1.1.9. Please read the migration notes for details).

Simply add the host tag:

all_hosts = [ "|snmp", ]

A test inventory of that host now shows this debug output:

root@linux# check_mk --checks mynics -I [['lo', '24', '1'], ['eth0', '6', '2'], ['wlan0', '6', '1'], ['usb0', '6', '2'], ['vboxnet0', '6', '2'], ['pan0', '6', '2']]

If your SNMP info is more complex, then that output quickly becomes unreadable. Fortunately Python provides the module for pretting printing Python objects. Here is a variant that uses :

def inventory_mynics(info): # Debug: lets see how the data we get looks like import pprint ; pprint.pprint(info) return []

And its output:

root@linux# check_mk -I mynics [['lo', '24', '1'], ['eth0', '6', '2'], ['wlan0', '6', '1'], ['usb0', '6', '2'], ['vboxnet0', '6', '2'], ['pan0', '6', '2']]

You might have noticed from this that Check_MK transforms the SNMP output such that each item is in one line (one list). So from now on everything works exactly like at agent based checks.

When looping over the lines in , we can make use of Python's list assignment feature and directly unpack each line into the three variables , and :

def inventory_mynics(info): for nic, type, state in info:

Now let our inventory function skip the loopback device , since it is its task to decide which items make sense being checked. The loopback device certainly does not. For that purpose we have declared the second column in : the interface type. As a look into the MIB file will confirm, the type means ethernet and is used for "normal" interfaces. Furthermore we only want to monitor NICs that are currently up.

When making comparisons please have in mind, that - though SNMP is sometimes sending numbers - Check_MK provides everything as strings. So we need to check for type and state (up):

def inventory_mynics(info): for nic, type, state in info: if type == "6" and state == "1":

So what if we find a match? Simply add a pair for item and parameter to the inventory. Since our check does not use a parameter, we specify as second argument. Here is the complete inventory function:

def inventory_mynics(info): for nic, type, state in info: if type == "6" and state == "1": yield, nic, None

An inventory will now find one check for our host:

root@linux# check_mk --checks mynics -I mynics 1 new checks

2.3. The check function

For each item (in this case NIC) the check function will be called once, with the following arguments:

  • The item (e.g.
  • The parameters for the check
  • The agent data (just the same as for inventory)

How to work with parameters is explained in the tutorial for agent based checks. It is good style to name the argument if you check does not process any parameters.

The check now is free in how to computes its result and returns a pair or triple of values:

  • The Nagios status (, , or
  • The plugin output for Nagios (free text)
  • optional: performance data

Our check just checks the operations status of the NIC and returns an according state:

def check_mynics(item, _no_params, info): for nic, type, state in info: if nic == item: if state == "1": return 0, "OK - link is up" else: return 2, "CRITICAL - link is " + state

Now we can try and check the host:

root@linux# cmk -nv localhost Check_mk version 1.1.9i9 NIC eth0 OK - link is up

2.4. What's next?

If you got so far, you can further improve your check, for example:

If you thing that your check is really useful and also well implemented then consider donating it to the official Check_MK project. Our check development guidelines tell you what criteria a check must fullfil to be accepted into our distribution.

If your check ist not completely matching our guidelines but still of use for others than you can make an MKP package out of it and upload it to the Check_MK Exchange.

Write Your Own MIB File (Tabular)

In General Linux on 9 September 2011 with 1 comment 10426 views

When it comes to writing our own MIB, a practical choice might be to write the whole objects as of scalar type (RFC-1212). That means, let’s say we have 2 battery statuses, each of them must be explicitly written individually within the MIB file. Example of calling their voltages:

If additional 3rd battery is to be monitored, in this example must be modified. In small scale we don’t need consistent MIB as changes are manageable, but if a whole bunch of different people must reference to this, a better way is to have tabular object where the above batteries are indexed instead of ended with “” scalar identifier.

Quick approach by checking established shows at least we need three object definitions inside the MIB file:

Components of writing tabular MIB

Its stemmed MIB tree to show the (1) , (2) , and (3) :

Now the writing part of those three types to our MIB, plus the which is the actual object to be indexed in the final SNMP monitoring.

75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 batteryTable OBJECT-TYPE SYNTAX SEQUENCE OF BatteryEntry MAX-ACCESS not-accessible STATUS current DESCRIPTION "The (conceptual) table of batteries contained by the module." ::= { monitor 1}   batteryEntry OBJECT-TYPE SYNTAX BatteryEntry MAX-ACCESS not-accessible STATUS current DESCRIPTION "A (conceptual) entry for one battery contained by the module. The batteryIndex in the index represents the entry in the batteryTable that corresponds to the batteryEntry.   As an example of how objects in this table are named, an instance of the batteryVoltage object might be named batteryVoltage.3" INDEX { batteryIndex } ::= { batteryTable 1}   batteryIndex OBJECT-TYPE SYNTAX DeviceIndex MAX-ACCESS read-only STATUS current DESCRIPTION "A unique value, greater than zero, for each battery. It is recommended that values are assigned contiguously starting from 1." ::= { batteryEntry 1}   batteryVoltage OBJECT-TYPE SYNTAX Integer32 ACCESS read-only STATUS current DESCRIPTION "Voltage A/D value" ::= { batteryEntry 2}

There are some header parts of course, check the resulting here.

The tree view becomes:

and example of getting SNMP is

in the above example any additional 3rd battery voltage insertion will be OID ““

$ snmpwalk -m +REKTRONIK-MIB -v1-c public monitored-host . ... REKTRONIK-MIB::battery1Voltage.0 = INTEGER: 9 REKTRONIK-MIB::battery2Voltage.0 = INTEGER: 11 ...
... ||| +--lmFanSensorsTable(3)||||||||| +--lmFanSensorsEntry(1)||||| Index: lmFanSensorsIndex ||||||||| +-- -R-- Integer32 lmFanSensorsIndex(1)||||| Range: 0..65535 ...
+--private(4)||| +--enterprises(1)||| +--rektronik(39559) ... ||| +--monitor(2)||||| +--batteryTable(1)||||||| +--batteryEntry(1)|||| Index: batteryIndex ||||||| +-- -R-- Integer32 batteryIndex(1)|||| Textual Convention: DeviceIndex |||| Range: 1..2147483647 ||| +-- -R-- Integer32 batteryVoltage(2)||| +-- -R-- Integer32 batteryCurrent(3)||||| +--environment(2)||||||| +-- -R-- Integer32 temperature(1)||| +-- -R-- Integer32 humidity(2) ...
$ snmpwalk -m +REKTRONIK-MIB -v1-c public monitored-host . REKTRONIK-MIB::name.0 = STRING: "RekMini" REKTRONIK-MIB::version.0 = STRING: "1.0" REKTRONIK-MIB::date.0 = STRING: "2011-09-08" REKTRONIK-MIB::batteryIndex.22 = INTEGER: 22 REKTRONIK-MIB::batteryIndex.23 = INTEGER: 23 REKTRONIK-MIB::batteryVoltage.22 = INTEGER: 9 REKTRONIK-MIB::batteryVoltage.23 = INTEGER: 11 REKTRONIK-MIB::batteryCurrent.22 = INTEGER: 2 REKTRONIK-MIB::batteryCurrent.23 = INTEGER: 2 ...

← Running Raddle (2): snmpd & Replay Custom Private Enterprise MIBRunning Ubuntu on DevKit8500D (Natty Kernel and Lucid RootFS) →

One thought on “Snmpwalk Mib Descriptive Essay

Leave a Reply

Your email address will not be published. Required fields are marked *