feature: Allow snmpget in os discovery yaml (#7558)

* feature: Allow snmpget in os discovery yaml
Convert all remaining os except airos.

Affected OS: asuswrt-merlin, ddnons, dsm, extrahop, huaweiups, ibmtl, pcoweb, pktj, qnap, remoteeye4, sentry3, sentry4, tomato

There should be not change in detection.

* Fix, asuswrt-merlin and tomato with snmpsim.  May not have been an issue with actual devices because of -Oa leading " was a bit odd.

* missed file
This commit is contained in:
Tony Murray
2017-10-26 20:48:33 +01:00
committed by Neil Lathwood
parent e968e37cdc
commit 193db02475
24 changed files with 245 additions and 104 deletions
+2
View File
@@ -29,7 +29,9 @@ Other options are available:
- `sysObjectId` The preferred operator. Checks if the sysObjectID starts with one of the strings under this item
- `sysDescr` Use this in addition to sysObjectId if required. Check that the sysDescr contains one of the strings under this item
- `sysObjectId_regex` Please avoid use of this. Checks if the sysObjectId matches one of the regex statements under this item
- `sysDescr_regex` Please avoid use of this. Checks if the sysDescr matches one of the regex statements under this item
- `snmpget` Do not use this unless none of the other methods work. Fetch an oid and compare it against a value.
- `_except` You can add this to any of the above to exclude that element. As an example:
```yaml
+7 -1
View File
@@ -6,4 +6,10 @@ over:
- { graph: device_bits, text: 'Device Traffic' }
- { graph: device_processor, text: 'CPU Usage' }
- { graph: device_mempool, text: 'Memory Usage' }
discovery:
-
sysObjectId: .1.3.6.1.4.1.8072.3.2.10
snmpget:
oid: .1.3.6.1.4.1.2021.7890.1.101.1
op: regex
value: '/^"?ASUSWRT-Merlin/'
+7
View File
@@ -6,3 +6,10 @@ over:
- { graph: device_bits, text: 'Device Traffic' }
- { graph: device_processor, text: 'Processor Usage' }
- { graph: device_mempool, text: 'Memory Usage' }
discovery:
-
sysObjectId: .1.3.6.1.4.1.8072.3.2.10
snmpget:
oid: SFA-INFO::systemName.0
op: '!=='
value: false
+16
View File
@@ -10,3 +10,19 @@ over:
mib_dir:
- synology
processor_stacked: 1
discovery:
-
sysDescr_regex: '/^Linux /'
snmpget:
oid: systemStatus.0
mib: SYNOLOGY-SYSTEM-MIB
mibdir: synology
op: '!=='
value: false
-
sysDescr_regex: '/^Linux /'
snmpget:
oid: HOST-RESOURCES-MIB::hrSystemInitialLoadParameters.0
value:
- 'syno_hw_version'
- 'syno_dyn_module'
+9
View File
@@ -9,3 +9,12 @@ over:
- { graph: device_mempool, text: 'Memory Usage' }
mib_dir: extrahop
processor_stacked: 1
discovery:
-
sysObjectId: .1.3.6.1.4.1.8072.3.2.10
snmpget:
oid: extrahopInfoVersionString
mib: EXTRAHOP-MIB
mibdir: extrahop
op: '!=='
value: false
+6
View File
@@ -6,3 +6,9 @@ icon: huawei
rfc1628_compat: 1
over:
- { graph: device_current, text: Current }
discovery:
-
sysDescr: Linux GSE200M
snmpget:
oid: UPS-MIB::upsIdentManufacturer.0
value: HUAWEI
+4
View File
@@ -4,3 +4,7 @@ type: storage
icon: generic
over:
- { graph: device_bits, text: Traffic }
discovery:
- snmpget:
oid: SML-MIB::product-Name.0
value: IBM System Storage TS3500 Tape Library
+10
View File
@@ -9,3 +9,13 @@ over:
icon: carel
icons:
- uniflair
discovery:
- sysDescr: pCO Gateway
-
sysObjectId: .1.3.6.1.4.1.8072.3.2.10
snmpget:
oid: roomTemp.0
mib: CAREL-ug40cdz-MIB
mibdir: carel
op: '!=='
value: false
+7
View File
@@ -8,3 +8,10 @@ over:
- { graph: device_processor, text: 'Processor Usage' }
- { graph: device_mempool, text: 'Memory Usage' }
processor_stacked: 1
discovery:
-
sysDescr_regex: '/^Linux/'
snmpget:
oid: GANDI-MIB::rxCounter.0
op: '!=='
value: false
+7
View File
@@ -10,3 +10,10 @@ over:
processor_stacked: 1
discovery:
- sysObjectId: .1.3.6.1.4.1.24681
-
sysDescr: Linux TS-
snmpget:
oid: entPhysicalMfgName.1
mib: ENTITY-MIB
op: starts
value: QNAP Systems
+7 -1
View File
@@ -3,4 +3,10 @@ text: 'Toshiba RemotEye4'
type: power
icon: toshiba
mib_dir:
- toshiba
- toshiba
discovery:
-
sysObjectId: .1.3.6.1.4.1.8072.3.2.10
snmpget:
oid: UPS-MIB::upsIdentAgentSoftwareVersion.0
value: RemotEye4
+11
View File
@@ -6,3 +6,14 @@ over:
icon: servertech
mib_dir:
- sentry
discovery:
-
sysDescr:
- Switched
- Smart
snmpget:
oid: serverTech.4.1.1.1.3.0
mib: Sentry3-MIB
mibdir: sentry
op: regex
value: '/[^\s]* [0-7]/'
+11
View File
@@ -6,3 +6,14 @@ over:
icon: servertech
mib_dir:
- sentry
discovery:
-
sysDescr:
- Switched
- Smart
snmpget:
oid: serverTech.4.1.1.1.3.0
mib: Sentry3-MIB
mibdir: sentry
op: regex
value: '/[^\s]* [^0-7]/'
+7
View File
@@ -6,3 +6,10 @@ over:
- { graph: device_bits, text: 'Device Traffic' }
- { graph: device_processor, text: 'CPU Usage' }
- { graph: device_mempool, text: 'Memory Usage' }
discovery:
-
sysObjectId: .1.3.6.1.4.1.8072.3.2.10
snmpget:
oid: .1.3.6.1.4.1.2021.7890.1.101.1
op: regex
value: '/^"?Tomato/'
+14
View File
@@ -0,0 +1,14 @@
<?php
if (starts_with($sysDescr, 'Linux') || starts_with($sysObjectId, '.1.3.6.1.4.1.8072.3.2.10')) {
if (starts_with($sysObjectId, array('.1.3.6.1.4.1.10002.1', '.1.3.6.1.4.1.41112.1.4'))
|| str_contains(snmp_walk($device, 'dot11manufacturerName', '-Osqnv', 'IEEE802dot11-MIB'), 'Ubiquiti')
) {
$os = 'airos';
if (str_contains(snmp_walk($device, 'dot11manufacturerProductName', '-Osqnv', 'IEEE802dot11-MIB'), 'UAP')) {
$os = 'unifi';
} elseif (snmp_get($device, 'fwVersion.1', '-Osqnv', 'UBNT-AirFIBER-MIB', 'ubnt') !== false) {
$os = 'airos-af';
}
}
}
-17
View File
@@ -1,17 +0,0 @@
<?php
// Synology DSM
if (starts_with($sysDescr, 'Linux')) {
$init_params = array(
'syno_hw_version',
'syno_dyn_module',
);
if (snmp_get($device, 'systemStatus.0', '-Osqnv', 'SYNOLOGY-SYSTEM-MIB', 'synology')) {
$os = 'dsm';
}
if (str_contains(snmp_get($device, 'HOST-RESOURCES-MIB::hrSystemInitialLoadParameters.0', '-Osqnv'), $init_params)) {
$os = 'dsm';
}
}
-7
View File
@@ -1,7 +0,0 @@
<?php
if (starts_with($sysDescr, 'Linux GSE200M')) {
if (str_contains(snmp_get($device, 'UPS-MIB::upsIdentManufacturer.0', '-Oqv', ''), 'HUAWEI')) {
$os = 'huaweiups';
}
}
-17
View File
@@ -1,17 +0,0 @@
<?php
/*
* LibreNMS
*
* Copyright (c) 2015 Søren Friis Rosiak <sorenrosiak@gmail.com>
* 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.
*/
$ibmtl_snmpget = snmp_get($device, 'SML-MIB::product-Name.0', '-Oqv', '');
if (str_contains($ibmtl_snmpget, 'IBM System Storage TS3500 Tape Library', true)) {
$os = 'ibmtl';
}
+1 -29
View File
@@ -1,35 +1,7 @@
<?php
// do not move to yaml, this check needs to happen last
if (starts_with($sysDescr, 'Linux') || starts_with($sysObjectId, '.1.3.6.1.4.1.8072.3.2.10')) {
$os = 'linux';
// Specific Linux-derivatives
if (starts_with($sysObjectId, array('.1.3.6.1.4.1.10002.1', '.1.3.6.1.4.1.41112.1.4')) || str_contains(snmp_walk($device, 'dot11manufacturerName', '-Osqnv', 'IEEE802dot11-MIB'), 'Ubiquiti')) {
$os = 'airos';
if (str_contains(snmp_walk($device, 'dot11manufacturerProductName', '-Osqnv', 'IEEE802dot11-MIB'), 'UAP')) {
$os = 'unifi';
} elseif (snmp_get($device, 'fwVersion.1', '-Osqnv', 'UBNT-AirFIBER-MIB', 'ubnt') !== false) {
$os = 'airos-af';
}
} elseif (snmp_get($device, 'extrahopInfoVersionString', '-Osqnv', 'EXTRAHOP-MIB', 'extrahop') !== false) {
$os = 'extrahop';
} elseif (snmp_get($device, 'GANDI-MIB::rxCounter.0', '-Osqnv', 'GANDI-MIB') !== false) {
$os = 'pktj';
} elseif (snmp_get($device, 'SFA-INFO::systemName.0', '-Osqnv', 'SFA-INFO') !== false) {
$os = 'ddnos';
} elseif (is_numeric(trim(snmp_get($device, 'roomTemp.0', '-OqvU', 'CAREL-ug40cdz-MIB', 'carel')))) {
$os = 'pcoweb'; // Carel PCOweb
} elseif ($wrt = snmp_get($device, '.1.3.6.1.4.1.2021.7890.1.101.1', '-Osqnv')) {
$wrt = trim($wrt, '"');
if (starts_with($wrt, 'ASUSWRT-Merlin')) {
$os = 'asuswrt-merlin';
} elseif (starts_with($wrt, 'Tomato ')) {
$os = 'tomato';
}
} elseif (preg_match('/^QNAP Systems/', snmp_get($device, "entPhysicalMfgName.1", "-Ovqn", "ENTITY-MIB"))) {
$os = 'qnap';
} elseif (str_contains(snmp_get($device, 'upsIdentAgentSoftwareVersion.0', '-Osqnv', 'UPS-MIB'), 'RemotEye4')) {
$os = 'remoteye4';
}
}
-14
View File
@@ -1,14 +0,0 @@
<?php
if (starts_with($sysDescr, 'Sentry') && str_contains($sysDescr, array('Switched', 'Smart'))) {
// ServerTech doesn't have a way to distinguish between sentry3 and sentry4 devices
// Hopefully, we can use the version string to figure it out
$version = trim(snmp_get($device, 'serverTech.4.1.1.1.3.0', '-Osqnv', 'Sentry3-MIB', 'sentry'));
$version = explode(" ", $version);
$version = intval($version[1]);
// It appears that version 8 and up is good for sentry4
if ($version < 8) {
$os = 'sentry3';
}
}
-14
View File
@@ -1,14 +0,0 @@
<?php
if (starts_with($sysDescr, 'Sentry') && str_contains($sysDescr, array('Switched', 'Smart'))) {
// ServerTech doesn't have a way to distinguish between sentry3 and sentry4 devices
// Hopefully, we can use the version string to figure it out
$version = trim(snmp_get($device, 'serverTech.4.1.1.1.3.0', '-Osqnv', 'Sentry3-MIB', 'sentry'));
$version = explode(" ", $version);
$version = intval($version[1]);
// It appears that version 8 and up is good for sentry4
if ($version >= 8) {
$os = 'sentry4';
}
}
+60 -2
View File
@@ -118,7 +118,7 @@ function getHostOS($device)
if (isset($tmp['discovery']) && is_array($tmp['discovery'])) {
foreach ($tmp['discovery'] as $item) {
// check each item individually, if all the conditions in that item are true, we have a match
if (checkDiscovery($item, $sysObjectId, $sysDescr)) {
if (checkDiscovery($device, $item, $sysObjectId, $sysDescr)) {
return $tmp['os'];
}
}
@@ -143,13 +143,17 @@ function getHostOS($device)
* sysObjectId if sysObjectId starts with any of the values under this item
* sysDescr if sysDescr contains any of the values under this item
* sysDescr_regex if sysDescr matches any of the regexes under this item
* snmpget perform an snmpget on `oid` and check if the result contains `value`. Other subkeys: options, mib, mibdir
*
* Appending _except to any condition will invert the match.
*
* @param array $device
* @param array $array Array of items, keys should be sysObjectId, sysDescr, or sysDescr_regex
* @param string $sysObjectId The sysObjectId to check against
* @param string $sysDescr the sysDesr to check against
* @return bool the result (all items passed return true)
*/
function checkDiscovery($array, $sysObjectId, $sysDescr)
function checkDiscovery($device, $array, $sysObjectId, $sysDescr)
{
// all items must be true
foreach ($array as $key => $value) {
@@ -173,6 +177,17 @@ function checkDiscovery($array, $sysObjectId, $sysDescr)
if (preg_match_any($sysObjectId, $value) == $check) {
return false;
}
} elseif ($key == 'snmpget') {
$options = isset($value['options']) ? $value['options'] : '-Oqv';
$mib = isset($value['mib']) ? $value['mib'] : null;
$mib_dir = isset($value['mibdir']) ? $value['mibdir'] : null;
$op = isset($value['op']) ? $value['op'] : 'contains';
$get_value = snmp_get($device, $value['oid'], $options, $mib, $mib_dir);
if (compare_var($get_value, $value['value'], $op) == $check) {
return false;
}
}
}
@@ -196,6 +211,49 @@ function preg_match_any($subject, $regexes)
return false;
}
/**
* Perform comparison of two items based on give comparison method
* Valid comparisons: =, !=, ==, !==, >=, <=, >, <, contains, starts, ends, regex
* contains, starts, ends: $a haystack, $b needle(s)
* regex: $a subject, $b regex
*
* @param mixed $a
* @param mixed $b
* @param string $comparison =, !=, ==, !== >=, <=, >, <, contains, starts, ends, regex
* @return bool
*/
function compare_var($a, $b, $comparison = '=')
{
switch ($comparison) {
case "=":
return $a == $b;
case "!=":
return $a != $b;
case "==":
return $a === $b;
case "!==":
return $a !== $b;
case ">=":
return $a >= $b;
case "<=":
return $a <= $b;
case ">":
return $a > $b;
case "<":
return $a < $b;
case "contains":
return str_contains($a, $b);
case "starts":
return starts_with($a, $b);
case "ends":
return ends_with($a, $b);
case "regex":
return (bool)preg_match($b, $a);
default:
return false;
}
}
function percent_colour($perc)
{
$r = min(255, 5 * ($perc - 25));
+57
View File
@@ -33,6 +33,43 @@ use Symfony\Component\Yaml\Yaml;
class YamlTest extends \PHPUnit_Framework_TestCase
{
private $valid_keys = array(
'sysDescr',
'sysDescr_except',
'sysObjectId',
'sysObjectId_except',
'sysDescr_regex',
'sysDescr_regex_except',
'sysObjectId_regex',
'sysObjectId_regex_except',
'snmpget',
'snmpget_except'
);
private $valid_snmpget_keys = array(
'oid',
'options',
'mib',
'mibdir',
'op',
'value',
);
private $valid_comparisons = array(
'=',
'!=',
'==',
'!==',
'<=',
'>=',
'<',
'>',
'starts',
'ends',
'contains',
'regex',
);
public function testOSYaml()
{
$pattern = Config::get('install_dir') . '/includes/definitions/*.yaml';
@@ -46,6 +83,26 @@ class YamlTest extends \PHPUnit_Framework_TestCase
$this->assertArrayHasKey('os', $data, $file);
$this->assertArrayHasKey('type', $data, $file);
$this->assertArrayHasKey('text', $data, $file);
// test discovery keys
if (isset($data['discovery'])) {
foreach ((array)$data['discovery'] as $group) {
foreach ((array)$group as $key => $item) {
$this->assertContains($key, $this->valid_keys, "$file: invalid discovery type $key");
if (starts_with($key, 'snmpget')) {
foreach ($item as $get_key => $get_val) {
$this->assertContains($get_key, $this->valid_snmpget_keys, "$file: invalid snmpget option $get_key");
}
$this->assertArrayHasKey('oid', $item, "$file: snmpget discovery must specify oid");
$this->assertArrayHasKey('value', $item, "$file: snmpget discovery must specify value");
if (isset($item['op'])) {
$this->assertContains($item['op'], $this->valid_comparisons, "$file: invalid op ${item['op']}");
}
}
}
}
}
}
}
+2 -2
View File
@@ -218,11 +218,11 @@ function snmp_get($device, $oid, $options = null, $mib = null, $mibdir = null)
$result = '.' . $data[1];
}
d_echo("[SNMP] snmpget $community $num_oid: $result\n");
d_echo("[SNMP] snmpget $community $oid ($num_oid): $result\n");
return $result;
} catch (Exception $e) {
d_echo("[SNMP] snmpget $community $num_oid: no data\n");
d_echo("[SNMP] snmpget $community $oid ($num_oid): no data\n");
return false;
}
}