Hey,
Wanted to share this script I wrote to enhance the LLD for SNMP. Read comments in script for how to use it and examples. Script will need to be placed in your Zabbix ExternalScripts directory and made executable. Only addition PHP module I had to install on my Zabbix server was php-snmp.
Note: I don't do any real checking of what you pass but it should just die with an error if you pass it something wrong so run it from command line first to make sure you get JSON output.
Hope this helps someone else.
Tim
Wanted to share this script I wrote to enhance the LLD for SNMP. Read comments in script for how to use it and examples. Script will need to be placed in your Zabbix ExternalScripts directory and made executable. Only addition PHP module I had to install on my Zabbix server was php-snmp.
PHP Code:
#!/usr/bin/php
<?PHP
/* Version 2.1
* Author: Tim Koopman
*
* For doing SNMP Low Level Discoveries in ZABBIX
* Inbuilt only allows filter macros on SNMPINDEX and SNMPVALUE
* While you can change what SNMPVALUE would represent by changing the OID
* you sometimes what more values, one for filtering and one for item prototype names.
*
* This script allows you to add as many other values as you like
* I use with the following to allow me to filter for interfaces that Admin Status is Up
* while still having the interface name on each of the items names.
*
* Edit discovery rule "Network Interfaces" on template "Template SNMP Interfaces"
* Type: External check
* Key: SNMPDiscovery.php["-h", {HOST.CONN}, "-c", {$SNMP_COMMUNITY}, "--index", "IF-MIB::ifDescr", "--value", "IF-MIB::ifAdminStatus,ifAdminStatus"]
* Filter:
* Macro: {#ifAdminStatus}
* Regexp: 1
*
* When used without the --value option the result would be identical to the inbuilt SNMP LLD.
* This means all existing item prototypes will continue to work as is.
* Can add as many --value options as you need.
*
* v2.0 added --filter as I wanted to seperate SNMP storage devices between memory and disks but Zabbix
* won't allow you to have the same key with just different filters. So doing it this way
* means the keys will be different and you can leave the Zabbix filter options blank
*
* Usage
* SNMPDiscovery.php -h <host> -c <community> --index <OID> [--value <OID>,<MACRONAME>]... [--filter <OID>,<REGEX>]...
* -h : SNMP Host to query. When used in Zabbix this would normally be {HOST.CONN}
* -c : SNMP Community. When used in Zabbix this would normally be {$SNMP_COMMUNITY}
* --index : OID to walk. Is used to populate {#SNMPINDEX} and {#SNMPVALUE} macros.
* --value : Comma seperated OID and macro name to also return. Can reference in zabbix using macro {#<MACRONAME>}
* You can use --value multiple times if you need more macros returned.
* --filter : Comma seperated OID and regular expression. Any index that does not matches the regex will be excluded from the results.
* You can use --filter multiple times if you need.
*
* Returns JSON text which Zabbix LLD uses.
*
* Examples
* SNMPDiscovery.php -h 127.0.0.1 -c public --index IF-MIB::ifDescr --value IF-MIB::ifAdminStatus,ifAdminStatus
* SNMPDiscovery.php -h 127.0.0.1 -c public --index HOST-RESOURCES-MIB::hrStorageDescr --filter HOST-RESOURCES-MIB::hrStorageType,hrStorageFixedDisk$
* SNMPDiscovery.php -h 127.0.0.1 -c public --index HOST-RESOURCES-MIB::hrStorageDescr --filter 'HOST-RESOURCES-MIB::hrStorageType,(hrStorageRam|hrStorageVirtualMemory)$'
*/
error_reporting(E_ALL^ E_WARNING);
function SNMPData($data)
{
if (strPos($data, "STRING: ")===0)
{
preg_match_all('!^STRING: \"?(.*?)\"?$!', $data, $matches);
return $matches[1][0];
} elseif (strPos($data, "INTEGER: ")===0) {
preg_match_all('!\d+!', $data, $matches);
return (int) $matches[0][0];
} else {
return $data;
}
}
$options = getopt("c:h:",array("index:","value:","filter:"));
if (count($options) == 0)
{
print "Usage: SNMPDiscovery.php -h <host> -c <community> --index <OID> [--value <OID>,<MACRONAME>]... [--filter <OID>,<REGEX>]...\n";
exit(1);
}
$values = Array();
if (array_key_exists("value", $options))
{
if (is_array($options["value"]))
{
foreach($options["value"] as $value)
{
$explode = explode(",", $value);
$values[$explode[0]] = $explode[1];
}
} else {
$explode = explode(",", $options["value"]);
$values[$explode[0]] = $explode[1];
}
}
$filters = Array();
$defaultFilter = false;
if (array_key_exists("filter", $options))
{
if (is_array($options["filter"]))
{
foreach($options["filter"] as $value)
{
$explode = explode(",", $value);
$filters[$explode[0]] = $explode[1];
}
} else {
$explode = explode(",", $options["filter"]);
$filters[$explode[0]] = $explode[1];
}
} else {
$defaultFilter = true;
}
$data = Array();
$keys = snmprealwalk($options["h"], $options["c"] , $options["index"], 10000 , 5);
foreach($keys as $key => $value)
{
$key = substr($key, strlen($options["index"])+1);
$value = SNMPData($value);
$dataItem = Array();
$dataItem["{#SNMPINDEX}"] = $key;
$dataItem["{#SNMPVALUE}"] = $value;
$filtered = $defaultFilter;
foreach($filters as $oid => $regex)
{
$oidvalue = snmpget($options["h"], $options["c"], "{$oid}.{$key}", 10000, 5);
$oidvalue = SNMPData($oidvalue);
if (preg_match("/".$regex."/", $oidvalue)) $filtered = true;
}
if ($filtered)
{
foreach($values as $oid => $name)
{
$oidvalue = snmpget($options["h"], $options["c"], "{$oid}.{$key}", 10000, 5);
$oidvalue = SNMPData($oidvalue);
$dataItem["{#{$name}}"] = $oidvalue;
}
array_push($data, $dataItem);
}
}
$jsonData = Array();
$jsonData["data"] = $data;
echo json_encode($jsonData);
echo "\n";
?>
Hope this helps someone else.
Tim
Comment