Adding support for a new MIB
Adding support for a new MIB to Observium requires writing code and/or definitions to describe the contents of the MIB and the entities to be collected. The MIB itself assists in this, but isn't sufficient by itself.
Writing MIB definitions and code can be relatively straight forward or it can be quite complex, depending upon the structure and design of the MIB. Support for sensors and other entities can be quite straightforward on well-designed MIBs.
Adding a MIB definition
As an example we'll add support for the UEC-STARLINE-MIB, a MIB used for Universal Electronic Corporation devices, containing several power-related sensors and counters.
First we need to check if there is already a directory for this vendor's MIBs and create one if there isn't. Then we need to place the MIB(s) in this directory and check if there's an Observium include file for this vendor's MIBs, and again create if necessary.
For this UEC MIB, the correct place would be mibs/uec/
in the Observium directory and the correct definition filename would be includes/definitions/mibs/uec.inc.php
.
Once the MIBs are in place, you can create an initial definition for the MIB, like below:
$mib = 'UEC-STARLINE-MIB';
$config['mibs'][$mib]['enable'] = 1;
$config['mibs'][$mib]['mib_dir'] = 'uec';
$config['mibs'][$mib]['identity_num'] = '.1.3.6.1.4.1.35774';
$config['mibs'][$mib]['descr'] = 'MIB module for managing measurement and control devices produced by the Universal Electric Corporation.';
This data should be fairly self-explanatory. The description field can often be copied from the module description near the top of the MIB file:
--
-- Universal Electric Corp.
-- STARLINE measurement and control devices MIB
--
UEC-STARLINE-MIB DEFINITIONS ::= BEGIN
uecStarline MODULE-IDENTITY
...
DESCRIPTION
"MIB module for managing measurement and control devices
produced by the Universal Electric Corporation."
The module identity can be determined using a number of different methods. Easiest is probably to use snmptranslate
to find the OID that correspnds to the MODULE-IDENTITY:
root@dev:/opt/observium# snmptranslate -Pu -Tso -M mibs/uec/:mibs/rfc -m UEC-STARLINE-MIB
...
.1.3.6.1.4.1
.iso.org.dod.internet.private.enterprises
.1.3.6.1.4.1.35774
.iso.org.dod.internet.private.enterprises.uecStarline
.1.3.6.1.4.1.35774.2
.iso.org.dod.internet.private.enterprises.uecStarline.cpm
...
Here we can see that the uecStarline
OID is a child of enterprises
, and has the OID of .1.3.6.1.4.1.35774
. This could also be obtained from other modules which are children of enterprises by looking at the end of the MODULE-IDENTITY entry, after the REVISION sections:
::= { enterprises 35774 }
Associating a MIB to an OS
A MIB can be assigned to an OS by adding it to the OSes list of MIBs, this is done in the OS's definition section, in this case in includes/definitions/os.inc.php
, this may be a vendor-specific file such as includes/definitions/os/uec.inc.php
.
$os = "uec-starline";
...
$config['os'][$os]['mibs'][] = "UEC-STARLINE-MIB";
This instructs the poller and discovery processes to use any definitions or files related to this MIB during polling and discovery.
Collecting an SNMPwalk of the MIB
Before we start extracting data from the MIB, we need to see what data is in there. You can use the commandline snmpwalk tools for this. A simple way is to snmpwalk the MIB's base oid. You can adjust the command below with the MIB names and directories you've already used. An SNMPv3 configuration will be more complex, and will require you to set the correct options.
We'll pipe this to a text file, uec-starline-mib.txt` so we don't have to keep walking the table.
snmpwalk -v2c -c <community> -M mibs/rfc:mibs/uec> -m UEC-STARLINE-MIB .1.3.6.1.4.1.35774 > uec-starline-mib.txt
Extracting device metadata from the MIB
Some MIBs contain device-level metadata such as serial and uptime. These can be defined in the MIB definition.
UEC-STARLINE-MIB::cpmAcDeviceName.0 = STRING: FlexLab Busway Meter
UEC-STARLINE-MIB::cpmAcDeviceLocation.0 = STRING: FlexLab
UEC-STARLINE-MIB::cpmAcDeviceId.0 = STRING: 01
UEC-STARLINE-MIB::cpmAcModelNumber.0 = STRING: M43D
UEC-STARLINE-MIB::cpmAcSerialNumber.0 = STRING: 0008xxx
UEC-STARLINE-MIB::cpmAcCatalogNumber.0 = STRING: UF250T5C4S-SLSN-0100C-BLU0-M43D3
UEC-STARLINE-MIB::cpmAcFirmwareVersion.0 = STRING: M22276-116 v3.87
From the above SNMP walk we can use the serial number, model number and firmware version data.
$config['mibs'][$mib]['serial'][] = array('oid' => 'cpmAcSerialNumber.0');
$config['mibs'][$mib]['version'][] = array('oid' => 'cpmAcFirmwareVersion.0');
$config['mibs'][$mib]['hardware'][] = array('oid' => 'cpmAcModelNumber.0');
Once these are configured on the MIB, they'll be collected and used on any device whos OS as this MIB assigned to it.
Adding a Sensor
Adding a sensor is similar, but a little more involved. To add a simple sensor we'll take this one from the walk as an example:
UEC-STARLINE-MIB::cpmAcInfTotLineCurrDemand.0 = STRING: 11.55 Amps (rms)
We can look in the MIB for more details on this OID. It can be helpful to use a graphical MIB browser for this, but just looking in the text file itself is sufficient.
cpmAcInfTotLineCurrDemand OBJECT-TYPE
SYNTAX DisplayString
UNITS "amps per demand interval"
MAX-ACCESS read-write
STATUS current
DESCRIPTION
"The current demand of this line."
::= { cpmAcInfeedLineEntry 9 }
This is a quite straightforward sensor, as it's scalar (the index is 0) and not part of a table, and it's returning its value in base units. We can add it like this
We can set a static description, and can obtain the numeric OID by using snmptranslate or snmpget to make sure the value matches. -On
tells snmpwalk to return numeric indexes.
root@dev:/opt/observium# snmpwalk -v2c -c starline -M mibs/rfc:mibs/uec/ -m ALL -On starline.sim.observium.org:4567 cpmAcInfTotLineCurrDemand
.1.3.6.1.4.1.35774.2.1.4.4.0 = STRING: 11.55 Amps (rms)
root@dev:/opt/observium#
The oid_num element requires the oid without the index part, so we remove the .0.
$config['mibs'][$mib]['sensor'][] = array('oid' => 'cpmAcInfTotLineCurrDemand',
'class' => 'current',
'descr' => 'Infeed Total',
'oid_num' => '.1.3.6.1.4.1.35774.2.1.4.4');
We can also add sensors from tables, automatically pulling dynamic descritptions from indexes or other oids. We can use a similar OID as an example:
cpmAcInfeedLineIndex.line1 = INTEGER: line1(1)
cpmAcInfeedLineIndex.line2 = INTEGER: line2(2)
cpmAcInfeedLineIndex.line3 = INTEGER: line3(3)
cpmAcInfeedLineIndex.neutralC = INTEGER: neutralC(4)
cpmAcInfeedLineIndex.neutralM = INTEGER: neutralM(5)
cpmAcInfLineCurrent.line1 = STRING: 13.04 amps (rms)
cpmAcInfLineCurrent.line2 = STRING: 11.19 amps (rms)
cpmAcInfLineCurrent.line3 = STRING: 10.26 amps (rms)
cpmAcInfLineCurrent.neutralC = STRING: 0.06 amps (rms)
cpmAcInfLineCurrent.neutralM = STRING: 9999.99 amps (rms)
In this output we can see that the MIB provides the text version of the index in cpmAcInfeedLineIndex
as a value we can use as a description, and it seem that the MIB uses 9999.99 as an "invalid" value, so we can try to screen this out.
$config['mibs'][$mib]['sensor'][] = array('oid' => 'cpmAcInfLineCurrent',
'class' => 'current',
'oid_descr' => 'cpmAcInfeedLineIndex',
'descr' => 'Infeed %oid_descr%',
'oid_num' => '.1.3.6.1.4.1.35774.2.1.5.1.3',
'invalid' => 9999.99);
Testing the sensor definition
Once you've created a definition, you can test it using discovery using ./discovery.php -h <device_id> -m sensors
If you've created it correctly you should see the MIB being called during the sensor discovery process, and the OIDs defined being checked.
root@dev:/opt/observium# ./discovery.php -h 780 -m sensors
___ _ _
/ _ \ | |__ ___ ___ _ __ __ __(_) _ _ _ __ ___
| | | || '_ \ / __| / _ \| '__|\ \ / /| || | | || '_ ` _ \
| |_| || |_) |\__ \| __/| | \ V / | || |_| || | | | | |
\___/ |_.__/ |___/ \___||_| \_/ |_| \__,_||_| |_| |_|
Observium Professional 22.4.11928
https://www.observium.org
##### Starting discovery run at 2022-04-04 14:37:26 #####
##### starline.observium.org [780] #####
o OS Type uec-starline
o SNMP Version v2c
o Last discovery 2022-04-04 14:36:51
o Last duration 0.92 seconds
##### Module Start: sensors #####
o UEC-STARLINE-MIB cpmAcInfTotLineCurrDemand [+] cpmAcInfLineCurrDemand [++++]
o Duration 0.7934s
##### starline.observium.org [780] completed discovery modules at 2022-04-04 14:37:27 #####
o Discovery time 0.7966 seconds
##### Finished discovery run at 2022-04-04 14:37:27 #####
o Devices Discovered 1
o Discovery Time 0.828 secs
o Memory usage 20MB (peak: 20MB)
o MySQL Usage Cell[39/0.018s] Row[112/0.027s] Rows[40/0.018s] Column[1/0s] Update[1/0.003s] Insert[1/0.002s] Delete[1/0.001s]
o RRDTool Usage
More Examples
Further examples on more complex matching, exclusion and description setting can be found by looking through the existing definitions in includes/definitions/mibs/
.
QNap NAS-MIB
This example shows constructing a description from multiple additional OIDs collected with oid_extra
NAS-MIB::hdDescr.1 = STRING: "HDD1"
NAS-MIB::hdTemperature.1 = STRING: "41 C/105 F"
NAS-MIB::hdStatus.2 = INTEGER: ready(0)
NAS-MIB::hdModel.1 = STRING: "ST6000VN0001-1SF17Z"
NAS-MIB::hdCapacity.1 = STRING: "5.46 TB"
NAS-MIB::hdSmartInfo.1 = STRING: "GOOD"
$config['mibs'][$mib]['sensor'][] = [
'oid' => 'hdTemperature',
'descr' => '%hdDescr% (%hdModel%, %hdCapacity%)',
'oid_num' => '.1.3.6.1.4.1.24681.1.2.11.1.3',
'class' => 'temperature',
'oid_extra' => [ 'hdDescr', 'hdCapacity', 'hdModel' ],
];
Adding a Status Entity
Status entities are similar to sensors in that they involve a single OID, but they need a translation table to translate the return value into a usable status. We'll use an example from KohlerGCon-MIB
which can be foind in includes/definitions/mibs/kohler.inc.php
.
KohlerGCon-MIB::gconStatus.1 = INTEGER: good(1)
We can look at the MIB to see what the possible values for this OID are:
gconStatus OBJECT-TYPE
SYNTAX INTEGER {
unknown(0),
good(1),
error(2)}
ACCESS read-only
STATUS mandatory
DESCRIPTION "Generator controller comm status."
::= { gconEntry 3 }
From this we can construct a definition for this status. In this instance the 'type' is specific to the OID, so is named after the OID. In some cases the values may be defined in a separate OBJECT-TYPE that is used by multiple OIDs. In these cases it can be defined once and used in multiple OIDs via the type
option.
$config['mibs'][$mib]['status'][] = array(
'oid' => 'gconStatus',
'descr' => 'Controller communication',
'measured' => 'controller',
'type' => 'gconStatus');
$type = 'gconStatus';
$config['mibs'][$mib]['states'][$type][0] = array('name' => 'unknown', 'event' => 'exclude');
$config['mibs'][$mib]['states'][$type][1] = array('name' => 'good', 'event' => 'ok');
$config['mibs'][$mib]['states'][$type][2] = array('name' => 'error', 'event' => 'alert');
Possible events are ok
warn
alert
ignore
and exclude
. The first four events produce states in Observium. The fifth, exclude
causes the status to be filtered by the discovery process and not added to Observium..
More Examples
QNap NAS-MIB
NAS-MIB::hdDescr.1 = STRING: "HDD1"
NAS-MIB::hdStatus.2 = INTEGER: ready(0)
NAS-MIB::hdModel.1 = STRING: "ST6000VN0001-1SF17Z"
NAS-MIB::hdCapacity.1 = STRING: "5.46 TB"
NAS-MIB::hdSmartInfo.1 = STRING: "GOOD"
$config['mibs'][$mib]['status'][] = [
'oid' => 'hdStatus',
'descr' => '%hdDescr% (%hdModel%, %hdCapacity%)',
'oid_extra' => [ 'hdDescr', 'hdCapacity', 'hdModel' ],
'oid_num' => '.1.3.6.1.4.1.24681.1.2.11.1.4',
'type' => 'nas-mib-hd-state',
'measured' => 'storage',
];
$type = 'nas-mib-hd-state';
$config['mibs'][$mib]['states'][$type][0] = array('name' => 'ready', 'event' => 'ok');
$config['mibs'][$mib]['states'][$type][-5] = array('name' => 'noDisk', 'event' => 'exclude');
$config['mibs'][$mib]['states'][$type][-6] = array('name' => 'invalid', 'event' => 'alert');
$config['mibs'][$mib]['states'][$type][-9] = array('name' => 'rwError', 'event' => 'alert');
$config['mibs'][$mib]['states'][$type][-4] = array('name' => 'unknown', 'event' => 'ignore');