See www.zabbix.com for the official Zabbix site.

Advanced SNMP Discovery

From Zabbix.org
Jump to: navigation, search

Zabbix SNMP Low-Level discovery (LLD) is powerfull but lacks some advanced functionality. The community tries to counter this with some custom external checks that can be used for advanced SNMP LLD such as LLD using multiple and dynamic indexes.
See also Forum thread: https://www.zabbix.com/forum/showthread.php?t=25310

Advanced SNMP Discovery

Forum user netmon has written an advanced.discovery script with the ability to define multiple SNMP indexes of variable length found and described here: https://github.com/simonkowallik/Zabbix-Addons

Turbo-simple-commanded SNMP Discovery

An alternative version of the advanced SNMP discovery script using different OID analysing techniques to dynamically determine multiple indexes written by forum user jhgrc can be found here: https://github.com/joriws/tsicsnmp.discovery

Multiple Values SNMP Discovery

In case you need to discover multiple values all having common indexes, you can use the mvsnmp.discovery script cited here:

#!/usr/bin/php
<?php

/**
 * SNMP discovery script for Zabbix providing multiple SNMP values combined by index
 *
 * @author Robin Roevens <robin.roevens (at) gmail.com>
 */

$snmpwalk = '/usr/bin/snmpwalk';
$argv[0] = basename($argv[0]);

$usage = <<<EOM
{$argv[0]} is an alternative to the build-in SNMP low level discovery of Zabbix 2.0+
allowing to retreive multiple SNMP OID values by a common index.
It integrates seamless into Zabbix by using "External check" discovery rules.

Usage: {$argv[0]} <ip|host> <snmpwalk args> <OID1> [<OID2> ...]
Example: {$argv[0]} 192.1.1.1 "-v2c -cpublic" 1.3.6.1.4.1.19746.1.15.1.1.1.2 1.3.6.1.4.1.19746.1.15.1.1.1.8
This wil retreive all values for both given OIDs sorted under their common indexes in the form
{#MVSNMPINDEX}  = 0
{#MVSNMPVALUE1} = value of first OID.0
{#MVSNMPVALUE2} = value of second OID.0
{#MVSNMPINDEX}  = 1
{#MVSNMPVALUE1} = value of first OID.1
{#MVSNMPVALUE2} = value of second OID.1
and so on for all available indexes in both OIDs.
If an index is missing in one OID, then the value of that OID for that index will be empty.

Usage in Zabbx:
Define a discovery rule and select "External Check".
In the "Key"-field, you specify: {$argv[0]}[<ip|host>,<snmpwalk args>,<OID1>[,<OID2>,...]]

Example:
{$argv[0]}[192.1.1.1,"-v2c -c\{\$SNMP_COMMUNITY\}",1.3.6.1.4.1.19746.1.15.1.1.1.2,1.3.6.1.4.1.19746.1.15.1.1.1.8]


EOM;
array_shift($argv);

// Check input
if (!is_array($argv) || !array_key_exists(0, $argv)) {
    die($usage);
}

$host = $argv[0];
array_shift($argv);

if (!array_key_exists(0, $argv)) {
    die($usage);
}

$snmpArgs = $argv[0];
array_shift($argv);

if (!array_key_exists(0, $argv)) {
    die($usage);
}

$oids = $argv;

// Get values
$multivalues = array();
foreach ($oids as $oidIndex => $oid) {
        $output = shell_exec("$snmpwalk $snmpArgs -On -Oq $host $oid");
        if (preg_match_all('/\.(\d+) "?([^"\r\n]*)/', $output, $matches)) {
            foreach ($matches[1] as $key => $valuesIndex) {
                $multivalues[$valuesIndex][$oidIndex] = $matches[2][$key];
            }
        }
}

if (count($multivalues) == 0) {
    die("No values found");
}

// Build data array
$data = array('data' => array());
$i = 0;
foreach ($multivalues as $valuesIndex => $values) {
        $data['data'][$i]['{#MVSNMPINDEX}'] = (int)$valuesIndex;
        foreach ($values as $oidIndex => $value) {
            $data['data'][$i]['{#MVSNMPVALUE'.($oidIndex + 1).'}'] = trim($value);
        }
        $i++;
}

// Spit it out as JSON
print json_encode($data);

Enhanced SNMP Discovery

This script was provided by forum user koopmant and also enables to retreive multiple values by index and even apply filters on it.
See: https://www.zabbix.com/forum/showthread.php?t=45689

#!/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";
?>