First cut at MIB-based discovery; not efficient

This commit is contained in:
Paul Gear
2015-06-06 21:17:24 +10:00
parent 874dc5ede5
commit d969ef679b
4 changed files with 147 additions and 10 deletions

View File

@@ -565,6 +565,7 @@ $config['discovery_modules']['toner'] = 1;
$config['discovery_modules']['ucd-diskio'] = 1;
$config['discovery_modules']['services'] = 1;
$config['discovery_modules']['charge'] = 1;
$config['discovery_modules']['mib'] = 0;
$config['modules_compat']['rfc1628']['liebert'] = 1;
$config['modules_compat']['rfc1628']['netmanplus'] = 1;

View File

@@ -0,0 +1,53 @@
<?php
/*
* LibreNMS MIB-based discovery
*
* Copyright (c) 2015 Gear Consulting Pty Ltd <github@libertysys.com.au>
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your
* option) any later version. Please see LICENSE.txt at the top level of
* the source code distribution for details.
*/
/*
* The overall plan for MIB-based support is:
*
* Discovery:
* 1. SNMP_get sysObjectID; look for a MIB matching this object (set_os_mib).
* 2. Add any extra MIBs that should be there for a given device
* (includes/discovery/os/*.inc.php).
* 3. Walk these MIBs to see if they exist in the device (this file).
* Save the ones that do in the database table device_oids.
*
* Polling:
* 5. For each MIB in the device_oids table, walk the device for that MIB.
* 6. Save each MIB value in its own RRD file. (At present there is no
* deletion of values that disappear.)
*
* Graphing:
* 7. For each MIB in the device_oids table, create a graph from the RRD
* file. All graphs go into the MIB section at present.
*/
set_os_mib($device);
$mibs = array();
// remove any existing device_oids for this device
dbDelete('device_oids', 'device_id = ?', array($device['device_id']));
// parse MIBs and check for them on the device
foreach ($device['mibs'] as $name => $module) {
d_echo("MIB discovery: $name, $module");
$mibs[$name] = snmp_mib_load($name, $module);
$oids = snmpwalk_cache_oid($device, "$module::$name", array(), $module);
// add the oids for this device
foreach ($oids[0] as $key => $val) {
$data = $mibs[$name][$key];
$data['device_id'] = $device['device_id'];
$result = dbInsert($data, 'device_oids');
d_echo("dbInsert for $name $key returned $result");
}
}

View File

@@ -3,6 +3,7 @@
* LibreNMS Ruckus Wireless OS information module
*
* Copyright (c) 2015 Søren Friis Rosiak <sorenrosiak@gmail.com>
* Copyright (c) 2015 Gear Consulting Pty Ltd <github@libertysys.com.au>
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your
@@ -14,4 +15,11 @@ if (!$os) {
$os = "ruckuswireless";
}
}
if ($os == "ruckuswireless") {
$ruckus_mibs = array(
"ruckusZDSystemStats" => "RUCKUS-ZD-SYSTEM-MIB",
);
set_mibs($ruckus_mibs, $device);
}
?>

View File

@@ -819,15 +819,17 @@ function snmp_gen_auth (&$device)
}
/*
* Translate the given MIB into a vaguely useful PHP array. Each keyword becomes an array index.
*
* Example:
* snmptranslate -Td -On -M mibs -m RUCKUS-ZD-SYSTEM-MIB RUCKUS-ZD-SYSTEM-MIB::ruckusZDSystemStatsNumSta
* .1.3.6.1.4.1.25053.1.2.1.1.1.15.30
* ruckusZDSystemStatsAllNumSta OBJECT-TYPE
* -- FROM RUCKUS-ZD-SYSTEM-MIB
* SYNTAX Unsigned32
* MAX-ACCESS read-only
* STATUS current
* DESCRIPTION "Number of All client devices"
* -- FROM RUCKUS-ZD-SYSTEM-MIB
* SYNTAX Unsigned32
* MAX-ACCESS read-only
* STATUS current
* DESCRIPTION "Number of All client devices"
* ::= { iso(1) org(3) dod(6) internet(1) private(4) enterprises(1) ruckusRootMIB(25053) ruckusObjects(1) ruckusZD(2) ruckusZDSystemModule(1) ruckusZDSystemMIB(1) ruckusZDSystemObjects(1)
* ruckusZDSystemStats(15) 30 }
*/
@@ -843,7 +845,7 @@ function snmp_mib_parse($oid, $mib, $module, $mibdir = null)
$cmd .= $lastpart;
$result = array();
$lines = preg_split('/\n+/', trim(external_exec($cmd)));
$lines = preg_split('/\n+/', trim(shell_exec($cmd)));
foreach ($lines as $l) {
$f = preg_split('/\s+/', trim($l));
// first line is all numeric
@@ -853,16 +855,16 @@ function snmp_mib_parse($oid, $mib, $module, $mibdir = null)
}
// then the name of the object type
if ($f[1] && $f[1] == "OBJECT-TYPE") {
$result[strtolower($f[1])] = $f[0];
$result['object_type'] = $f[0];
continue;
}
// then the other data elements
if ($f[0] == "--" && $f[1] == "FROM") {
$result[strtolower($f[1])] = $f[2];
$result['module'] = $f[2];
continue;
}
if ($f[0] == "MAX-ACCESS") {
$result[strtolower($f[0])] = $f[1];
$result['max_access'] = $f[1];
continue;
}
if ($f[0] == "STATUS") {
@@ -895,6 +897,10 @@ function snmp_mib_parse($oid, $mib, $module, $mibdir = null)
/*
* Walks through the given MIB module, looking for the given MIB.
* NOTE: different from snmp walk - this doesn't touch the device.
* NOTE: There's probably a better way to do this with snmptranslate.
*
* Example:
* snmptranslate -Ts -M mibs -m RUCKUS-ZD-SYSTEM-MIB | grep ruckusZDSystemStats
* .iso.org.dod.internet.private.enterprises.ruckusRootMIB.ruckusObjects.ruckusZD.ruckusZDSystemModule.ruckusZDSystemMIB.ruckusZDSystemObjects.ruckusZDSystemStats
@@ -908,7 +914,7 @@ function snmp_mib_walk($mib, $module, $mibdir = null)
$cmd .= mibdir($mibdir);
$cmd .= " -m ".$module;
$result = array();
$data = preg_split('/\n+/', external_exec($cmd));
$data = preg_split('/\n+/', shell_exec($cmd));
foreach ($data as $oid) {
// only include oids which are part of this mib
if (strstr($oid, $mib)) {
@@ -921,4 +927,73 @@ function snmp_mib_walk($mib, $module, $mibdir = null)
return $result;
}
/*
* @return an array containing all of the mib objects, keyed by object-type;
* returns an empty array if something goes wrong.
*/
function snmp_mib_load($mib, $module, $mibdir = null)
{
$mibs = array();
foreach (snmp_mib_walk($mib, $module, $mibdir) as $obj) {
$mibs[$obj['object_type']] = $obj;
}
return $mibs;
}
/*
* Turn the given oid (name or numeric value) into a MODULE::mib name.
* @return an array consisting of the module and mib names, or null if no matching MIB is found.
*/
function snmp_translate($oid, $module, $mibdir = null)
{
if ($module !== "all") {
$oid = "$module::$oid";
}
$cmd = "snmptranslate" . mibdir($mibdir);
$cmd .= " -m $module $oid"; // load all the MIBs looking for our object
$cmd .= " 2>/dev/null"; // ignore invalid MIBs
$lines = preg_split('/\n+/', shell_exec($cmd));
if (!$lines) {
d_echo("No results from snmptranslate");
return null;
}
$matches = array();
if (!preg_match('/(.*)::(.*)/', $lines[0], $matches)) {
d_echo("This doesn't look like a MIB: ".$lines[0]);
return null;
}
d_echo("SNMP translated: $module::$oid -> $matches[1]::$matches[2]");
return $matches;
}
/*
* Validate MIBs and set $device['mibs'][$name] = $module based on the results.
* Can be slow due to use of snmptranslate - call only during discovery.
*/
function set_mibs($list, &$device)
{
foreach ($list as $name => $module) {
$matches = snmp_translate($name, $module);
if ($matches) {
$device['mibs'][$matches[2]] = $matches[1];
}
}
}
/*
* Validate the MIB given in sysObjectId against our MIB collection. If none is found, do nothing.
* If one is found, call set_mibs() for the given MIB name & module.
*/
function set_os_mib(&$device)
{
$sysObjectId = trim(snmp_get($device, "SNMPv2-MIB::sysObjectID.0", "-Ovqn"));
if ($sysObjectId === false || $sysObjectID === "") {
return;
}
set_mibs(array($sysObjectId => "all"), $device);
}
?>