From 4af7dd8225b94bc7432bbf4211f5d6be4ebdf9a4 Mon Sep 17 00:00:00 2001 From: Paul Gear Date: Mon, 8 Jun 2015 14:58:22 +1000 Subject: [PATCH] First cut at working poller for MIBs --- doc/General/MIB-based-polling.md | 6 +- doc/Support/Poller Support.md | 3 + includes/common.php | 10 +++ includes/polling/functions.inc.php | 24 ++++++ includes/polling/os/ruckuswireless.inc.php | 6 ++ includes/snmp.inc.php | 98 ++++++++++++++++++---- 6 files changed, 129 insertions(+), 18 deletions(-) diff --git a/doc/General/MIB-based-polling.md b/doc/General/MIB-based-polling.md index cb5ccb012..f21bc4816 100644 --- a/doc/General/MIB-based-polling.md +++ b/doc/General/MIB-based-polling.md @@ -11,10 +11,8 @@ Polling: - walk that MIB on the device - store any numeric results in individual RRD files - update/add graph definitions in the database - - Individual OSes can add extra MIBs that should be there for a given - OS (includes/polling/os/*.inc.php). The MIB poller will poll, - store, and update graph definitions for them after attempting the - sysObjectID-based MIB poll. + - Individual OSes (includes/polling/os/*.inc.php) can poll extra MIBs + that should be there for a given OS by calling poll_mib(). - Devices may be excluded from MIB polling by adding poll_mib = 0 to devices_attribs (see /device/device=ID/tab=edit/section=modules/) diff --git a/doc/Support/Poller Support.md b/doc/Support/Poller Support.md index 0a980e251..616698630 100644 --- a/doc/Support/Poller Support.md +++ b/doc/Support/Poller Support.md @@ -70,6 +70,7 @@ $config['poller_modules']['aruba-controller'] = 1; $config['poller_modules']['entity-physical'] = 1; $config['poller_modules']['applications'] = 1; $config['poller_modules']['cisco-asa-firewall'] = 1; +$config['poller_modules']['mib'] = 0; ``` #### Poller modules @@ -138,6 +139,8 @@ $config['poller_modules']['cisco-asa-firewall'] = 1; `cisco-asa-firewall`: Cisco ASA firewall support. +`mib`: Support for generic MIB parsing. + #### Running Here are some examples of running poller from within your install directory. diff --git a/includes/common.php b/includes/common.php index d14395e7f..9f94a2b65 100644 --- a/includes/common.php +++ b/includes/common.php @@ -453,6 +453,16 @@ function get_dev_attribs($device) return $attribs; } +function is_dev_attrib_enabled($device, $attrib) +{ + foreach (get_dev_attribs($device) as $name => $val) { + if ($name == $attrib && $val == 0) { + return false; + } + } + return true; +} + function get_dev_entity_state($device) { $state = array(); diff --git a/includes/polling/functions.inc.php b/includes/polling/functions.inc.php index 9700edb2d..5df7b181d 100644 --- a/includes/polling/functions.inc.php +++ b/includes/polling/functions.inc.php @@ -346,4 +346,28 @@ function poll_mib_def($device, $mib_name_table, $mib_subdir, $mib_oids, $mib_gra return TRUE; } +/* + * Please use this instead of creating & updating RRD files manually. + * @param device Device object - only 'hostname' is used at present + * @param name Array of name objects - filename will be constructed using this with a "-" delimiter + * @param def Array of data definitions + * @param val Array of value definitions + * + */ +function rrd_create_update($device, $name, $def, $val, $step = 300) +{ + global $config; + $rrd = implode("/", array($config['rrd_dir'], $device['hostname'], safename(implode("-", $name)).".rrd")); + d_echo("RRD file: $rrd"); + + if (!is_file($rrd)) { + // add the --step and the rra definitions to the array + $newdef = "--step $step ".implode(' ', $def).$config['rrd_rra']; + d_echo("Creating RRD $rrd: $newdef"); + rrdtool_create($rrd, $newdef); + } + + rrdtool_update($rrd, $val); +} + ?> diff --git a/includes/polling/os/ruckuswireless.inc.php b/includes/polling/os/ruckuswireless.inc.php index 1c9b1b0ec..31776ae77 100644 --- a/includes/polling/os/ruckuswireless.inc.php +++ b/includes/polling/os/ruckuswireless.inc.php @@ -39,4 +39,10 @@ $ruckuscountry = first_oid_match($device, $ruckuscountries); if (isset($ruckuscountry) && $ruckuscountry != "") { $version .= " ($ruckuscountry)"; } + +$ruckus_mibs = array( + "ruckusZDSystemStats" => "RUCKUS-ZD-SYSTEM-MIB", +); +poll_mibs($ruckus_mibs, $device); + ?> diff --git a/includes/snmp.inc.php b/includes/snmp.inc.php index c9ff65ca0..b25e31382 100644 --- a/includes/snmp.inc.php +++ b/includes/snmp.inc.php @@ -953,34 +953,104 @@ function snmp_translate($oid, $module, $mibdir = null) } d_echo("SNMP translated: $module::$oid -> $matches[1]::$matches[2]"); - return $matches; + return array($matches[1], $matches[2]); } /* - * Validate MIBs and set $device['mibs'][$name] = $module based on the results. - * Can be slow due to use of snmptranslate - call only during discovery. + * check if the type of the oid is a numeric type, and if so, + * @return the name of RRD type that is best suited to saving it */ -function set_mibs($list, &$device) +function oid_rrd_type($oid, $mibdefs) { + if (!isset($mibdefs[$oid])) { + return false; + } + switch ($mibdefs[$oid]['syntax']) { + + case 'OCTET': + case 'IpAddress': + return false; + + case 'TimeTicks': + // Need to find a way to flag that this should be parsed + //return 'COUNTER'; + return false; + + case 'Counter64': + return 'COUNTER:600:0:U'; + + case 'Unsigned32': + return 'GAUGE:600:U:U'; + + } + return false; +} + +/* + * Shorten the RRD variable name to less than 19 characters + * Substitute for "mibval" if necessary. + */ +function rrd_shorten($name, $prefix) { - foreach ($list as $name => $module) { - $matches = snmp_translate($name, $module); - if ($matches) { - $device['mibs'][$matches[2]] = $matches[1]; + if (strlen($name) > 19 && strpos($name, $prefix) == 0) { + $newname = str_replace($prefix, '', $name); + d_echo("Shortened $name to $newname"); + $name = $newname; + } + if (strlen($name) > 19) { + d_echo("Shortened $name to mibval"); + $name = "mibval"; + } + return $name; +} + +/* + * Save all of the measurable oids for the device in their own RRDs. + */ +function save_mibs($device, $mibname, $oids, $mibdefs) +{ + foreach ($oids as $index => $array) { + foreach ($array as $oid => $val) { + $type = oid_rrd_type($oid, $mibdefs); + if (!$type) { + continue; + } + rrd_create_update( + $device, + array($mibname, $oid, $index), + array("DS:".rrd_shorten($oid, $mibname).":$type"), + "N:$val" + ); } } } /* - * 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. + * Take a list of MIB name => module pairs. + * Validate MIBs and poll based on the results. + * Can be slow due to use of snmptranslate. */ -function set_os_mib(&$device) +function poll_mibs($list, $device) { - $sysObjectId = trim(snmp_get($device, "SNMPv2-MIB::sysObjectID.0", "-Ovqn")); - if ($sysObjectId === false || $sysObjectID === "") { + if (!is_dev_attrib_enabled($device, "poll_mib")) { + d_echo("MIB module disabled for ".$device['hostname']); return; } - set_mibs(array($sysObjectId => "all"), $device); + $mibdefs = array(); + foreach ($list as $name => $module) { + d_echo("MIB searching: $module::$name"); + $translated = snmp_translate($name, $module); + if ($translated) { + $mod = $translated[0]; + $nam = $translated[1]; + d_echo("MIB found: $mod::$nam"); + $mibdefs[$nam] = snmp_mib_load($nam, $mod); + $oids = snmpwalk_cache_oid($device, "$mod::$nam", array(), $mod); + save_mibs($device, $nam, $oids, $mibdefs[$nam]); + } + else { + d_echo("MIB: no match for $module::$name"); + } + } } ?>