prometheus / snmp_exporter

SNMP Exporter for Prometheus
Apache License 2.0
1.65k stars 614 forks source link

"make generate" reports msg="NetSNMP reported parse error(s)" errors=2 #867

Closed candlerb closed 1 year ago

candlerb commented 1 year ago

Host operating system: output of uname -a

Darwin MacBook-Pro-6.local 21.6.0 Darwin Kernel Version 21.6.0: Thu Mar  9 20:08:59 PST 2023; root:xnu-8020.240.18.700.8~1/RELEASE_X86_64 x86_64

(macOS 12.6.5, Intel)

snmp_exporter version: output of snmp_exporter -version

I installed generator using go install github.com/prometheus/snmp_exporter/generator@latest on 2023-04-14

generate doesn't have a "version" or "--version" subcommand.

What device/snmpwalk OID are you using?

N/A - using supplied generator.yml and make generate to fetch the MIBs

If this is a new device, please link to the MIB(s).

N/A

What did you do that produced an error?

cd generator
make generate

What did you expect to see?

Completion without errors

What did you see instead?

"NetSNMP reported parse error(s)" errors=2 followed by make terminating. Full log:

$ make generate
go build
go: downloading github.com/prometheus/common v0.40.0
>> Downloading apc-powernet-mib
>> Downloading Cisco AIRESPACE-REF-MIB
>> Downloading Cisco AIRESPACE-WIRELESS-MIB
>> Downloading ARISTA-ENTITY-SENSOR-MIB
>> Downloading ARISTA-SMI-MIB
>> Downloading ARISTA-SW-IP-FORWARDING-MIB
>> Downloading Cisco ENTITY-MIB
>> Downloading Cisco ENTITY-SENSOR-MIB
>> Downloading Cisco ENTITY-STATE-MIB
>> Downloading Cisco ENTITY-STATE-TC-MIB
>> Downloading IANA charset MIB
>> Downloading IANA ifType MIB
>> Downloading IANA printer MIB
>> Downloading Cisco ISDN-MIB
>> Downloading KEEPALIVED-MIB
>> Downloading VRRP-MIB
>> Downloading VRRPv3-MIB
>> Downloading Kemp LM MIBs to /var/folders/f8/nggm8yyx2qvbflgmqg1zq5gh0000gp/T/tmp.qcLN0K4H
Archive:  /var/folders/f8/nggm8yyx2qvbflgmqg1zq5gh0000gp/T/tmp.qcLN0K4H
  inflating: mibs/7.2.50.0.18765.RELEASE-ONE4NET-MIB.txt
  inflating: mibs/7.2.50.0.18765.RELEASE-B100-MIB.txt
  inflating: mibs/7.2.50.0.18765.RELEASE-CERTS-MIB.txt
  inflating: mibs/7.2.50.0.18765.RELEASE-IPVS-MIB.txt
# Workaround invalid timestamps.
/var/folders/f8/nggm8yyx2qvbflgmqg1zq5gh0000gp/T/tmp.qcLN0K4H
>> Downloading MIKROTIK-MIB
>> Downloading NET-SNMP mibs
>> Downloading paloalto_pano to /var/folders/f8/nggm8yyx2qvbflgmqg1zq5gh0000gp/T/tmp.KcLIq6VT
Archive:  /var/folders/f8/nggm8yyx2qvbflgmqg1zq5gh0000gp/T/tmp.KcLIq6VT
 extracting: mibs/PAN-COMMON-MIB.md5
  inflating: mibs/PAN-COMMON-MIB.my
 extracting: mibs/PAN-ENTITY-EXT-MIB.md5
  inflating: mibs/PAN-ENTITY-EXT-MIB.my
 extracting: mibs/PAN-GLOBAL-REG-MIB.md5
  inflating: mibs/PAN-GLOBAL-REG-MIB.my
 extracting: mibs/PAN-GLOBAL-TC-MIB.md5
  inflating: mibs/PAN-GLOBAL-TC-MIB.my
 extracting: mibs/PAN-LC-MIB.md5
  inflating: mibs/PAN-LC-MIB.my
 extracting: mibs/PAN-PRODUCT-MIB.md5
  inflating: mibs/PAN-PRODUCT-MIB.my
 extracting: mibs/PAN-TRAPS.md5
  inflating: mibs/PAN-TRAPS.my
/var/folders/f8/nggm8yyx2qvbflgmqg1zq5gh0000gp/T/tmp.KcLIq6VT
>> Downloading PICO-IPSEC-FLOW-MONITOR-MIB.txt
>> Downloading PICO-SMI-ID-MIB.txt
>> Downloading PICO-SMI-MIB.txt
>> Downloading Printer MIB v2
>> Downloading servertech-sentry3-mib
>> Downloading servertech-sentry4-mib
>> Downloading synology to /var/folders/f8/nggm8yyx2qvbflgmqg1zq5gh0000gp/T/tmp.nXkpo5ZJ
Archive:  /var/folders/f8/nggm8yyx2qvbflgmqg1zq5gh0000gp/T/tmp.nXkpo5ZJ
  inflating: mibs/SYNOLOGY-UPS-MIB.txt
  inflating: mibs/SYNOLOGY-SHA-MIB.txt
  inflating: mibs/SYNOLOGY-DISK-MIB.txt
  inflating: mibs/SYNOLOGY-GPUINFO-MIB.txt
  inflating: mibs/SYNOLOGY-PORT-MIB.txt
  inflating: mibs/SYNOLOGY-SYSTEM-MIB.txt
  inflating: mibs/SYNOLOGY-FLASHCACHE-MIB.txt
  inflating: mibs/SYNOLOGY-SPACEIO-MIB.txt
  inflating: mibs/SYNOLOGY-NFS-MIB.txt
  inflating: mibs/SYNOLOGY-ISCSILUN-MIB.txt
  inflating: mibs/SYNOLOGY-EBOX-MIB.txt
  inflating: mibs/SYNOLOGY-SMART-MIB.txt
  inflating: mibs/SYNOLOGY-RAID-MIB.txt
  inflating: mibs/SYNOLOGY-SERVICES-MIB.txt
  inflating: mibs/SYNOLOGY-ISCSITarget-MIB.txt
  inflating: mibs/SYNOLOGY-STORAGEIO-MIB.txt
/var/folders/f8/nggm8yyx2qvbflgmqg1zq5gh0000gp/T/tmp.nXkpo5ZJ
>> Downloading UBNT-UniFi-MIB
>> Downloading UBNT-AirFiber-MIB
>> Downloading ubnt-airos to /var/folders/f8/nggm8yyx2qvbflgmqg1zq5gh0000gp/T/tmp.W9jinGQT
Archive:  /var/folders/f8/nggm8yyx2qvbflgmqg1zq5gh0000gp/T/tmp.W9jinGQT
  inflating: mibs/UBNT-AirMAX-MIB.txt
/var/folders/f8/nggm8yyx2qvbflgmqg1zq5gh0000gp/T/tmp.W9jinGQT
>> Downloading WIENER-CRATE-MIB to /var/folders/f8/nggm8yyx2qvbflgmqg1zq5gh0000gp/T/tmp.T8iJBYg3
Archive:  /var/folders/f8/nggm8yyx2qvbflgmqg1zq5gh0000gp/T/tmp.T8iJBYg3
  inflating: mibs/WIENER-CRATE-MIB-5704.txt
/var/folders/f8/nggm8yyx2qvbflgmqg1zq5gh0000gp/T/tmp.T8iJBYg3
>> Downloading PDU-MIB
>> Downloading Infrapower-MIB.mib to /var/folders/f8/nggm8yyx2qvbflgmqg1zq5gh0000gp/T/tmp.vGfZDzx7
Archive:  /var/folders/f8/nggm8yyx2qvbflgmqg1zq5gh0000gp/T/tmp.vGfZDzx7
  inflating: mibs/IPD-03-S-MIB_Q320V1.mib
mibs/IPD-03-S-MIB_Q320V1.mib -> mibs/Infrapower-MIB.mib
/var/folders/f8/nggm8yyx2qvbflgmqg1zq5gh0000gp/T/tmp.vGfZDzx7
>> Downloading LIEBERT_GP_PDU.MIB to /var/folders/f8/nggm8yyx2qvbflgmqg1zq5gh0000gp/T/tmp.stGpbTRe
Archive:  /var/folders/f8/nggm8yyx2qvbflgmqg1zq5gh0000gp/T/tmp.stGpbTRe
  inflating: mibs/LIEBERT_GP_PDU.MIB
  inflating: mibs/LIEBERT_GP_REG.MIB
/var/folders/f8/nggm8yyx2qvbflgmqg1zq5gh0000gp/T/tmp.stGpbTRe
>> Downloading CyberPower.MIB to /var/folders/f8/nggm8yyx2qvbflgmqg1zq5gh0000gp/T/tmp.cgE4TST3
Archive:  /var/folders/f8/nggm8yyx2qvbflgmqg1zq5gh0000gp/T/tmp.cgE4TST3
  inflating: mibs/CyberPower_MIB_v2.10.MIB
mibs/CyberPower_MIB_v2.10.MIB -> mibs/CyberPower.MIB
/var/folders/f8/nggm8yyx2qvbflgmqg1zq5gh0000gp/T/tmp.cgE4TST3
MIBDIRS='mibs' ./generator --fail-on-parse-errors generate
ts=2023-04-14T13:58:17.158Z caller=net_snmp.go:161 level=info msg="Loading MIBs" from=mibs
ts=2023-04-14T13:58:17.560Z caller=main.go:119 level=warn msg="NetSNMP reported parse error(s)" errors=2
ts=2023-04-14T13:58:17.636Z caller=main.go:51 level=info msg="Generating config for module" module=raritan
ts=2023-04-14T13:58:17.662Z caller=main.go:66 level=info msg="Generated metrics" module=raritan metrics=11
ts=2023-04-14T13:58:17.662Z caller=main.go:51 level=info msg="Generating config for module" module=wiener_mpod
ts=2023-04-14T13:58:17.678Z caller=main.go:66 level=info msg="Generated metrics" module=wiener_mpod metrics=20
modules:
ts=2023-04-14T13:58:17.678Z caller=main.go:51 level=info msg="Generating config for module" module=keepalived
ts=2023-04-14T13:58:17.712Z caller=main.go:66 level=info msg="Generated metrics" module=keepalived metrics=186
ts=2023-04-14T13:58:17.712Z caller=main.go:51 level=info msg="Generating config for module" module=ubiquiti_airmax
ts=2023-04-14T13:58:17.726Z caller=main.go:66 level=info msg="Generated metrics" module=ubiquiti_airmax metrics=122
ts=2023-04-14T13:58:17.726Z caller=main.go:51 level=info msg="Generating config for module" module=nec_ix
ts=2023-04-14T13:58:17.757Z caller=main.go:66 level=info msg="Generated metrics" module=nec_ix metrics=261
ts=2023-04-14T13:58:17.757Z caller=main.go:51 level=info msg="Generating config for module" module=infrapower_pdu
ts=2023-04-14T13:58:17.775Z caller=main.go:66 level=info msg="Generated metrics" module=infrapower_pdu metrics=4
ts=2023-04-14T13:58:17.775Z caller=main.go:51 level=info msg="Generating config for module" module=servertech_sentry4
ts=2023-04-14T13:58:17.795Z caller=main.go:66 level=info msg="Generated metrics" module=servertech_sentry4 metrics=55
ts=2023-04-14T13:58:17.795Z caller=main.go:51 level=info msg="Generating config for module" module=cisco_wlc
ts=2023-04-14T13:58:17.811Z caller=main.go:66 level=info msg="Generated metrics" module=cisco_wlc metrics=62
ts=2023-04-14T13:58:17.811Z caller=main.go:51 level=info msg="Generating config for module" module=apcups
ts=2023-04-14T13:58:17.841Z caller=main.go:66 level=info msg="Generated metrics" module=apcups metrics=332
ts=2023-04-14T13:58:17.841Z caller=main.go:51 level=info msg="Generating config for module" module=servertech_sentry3
ts=2023-04-14T13:58:17.864Z caller=main.go:66 level=info msg="Generated metrics" module=servertech_sentry3 metrics=44
ts=2023-04-14T13:58:17.864Z caller=main.go:51 level=info msg="Generating config for module" module=paloalto_fw
ts=2023-04-14T13:58:17.879Z caller=main.go:66 level=info msg="Generated metrics" module=paloalto_fw metrics=228
ts=2023-04-14T13:58:17.879Z caller=main.go:51 level=info msg="Generating config for module" module=synology
ts=2023-04-14T13:58:17.904Z caller=main.go:66 level=info msg="Generated metrics" module=synology metrics=293
ts=2023-04-14T13:58:17.904Z caller=main.go:51 level=info msg="Generating config for module" module=ubiquiti_airfiber
ts=2023-04-14T13:58:17.924Z caller=main.go:66 level=info msg="Generated metrics" module=ubiquiti_airfiber metrics=193
ts=2023-04-14T13:58:17.924Z caller=main.go:51 level=info msg="Generating config for module" module=ubiquiti_unifi
ts=2023-04-14T13:58:17.955Z caller=main.go:66 level=info msg="Generated metrics" module=ubiquiti_unifi metrics=97
ts=2023-04-14T13:58:17.955Z caller=main.go:51 level=info msg="Generating config for module" module=if_mib
ts=2023-04-14T13:58:17.971Z caller=main.go:66 level=info msg="Generated metrics" module=if_mib metrics=40
ts=2023-04-14T13:58:17.971Z caller=main.go:51 level=info msg="Generating config for module" module=liebert_pdu
ts=2023-04-14T13:58:17.994Z caller=main.go:66 level=info msg="Generated metrics" module=liebert_pdu metrics=117
ts=2023-04-14T13:58:17.994Z caller=main.go:51 level=info msg="Generating config for module" module=kemp_loadmaster
ts=2023-04-14T13:58:18.015Z caller=main.go:66 level=info msg="Generated metrics" module=kemp_loadmaster metrics=141
ts=2023-04-14T13:58:18.015Z caller=main.go:51 level=info msg="Generating config for module" module=ddwrt
ts=2023-04-14T13:58:18.033Z caller=main.go:66 level=info msg="Generated metrics" module=ddwrt metrics=111
ts=2023-04-14T13:58:18.033Z caller=main.go:51 level=info msg="Generating config for module" module=printer_mib
ts=2023-04-14T13:58:18.060Z caller=main.go:66 level=info msg="Generated metrics" module=printer_mib metrics=13
ts=2023-04-14T13:58:18.060Z caller=main.go:51 level=info msg="Generating config for module" module=mikrotik
ts=2023-04-14T13:58:18.098Z caller=main.go:66 level=info msg="Generated metrics" module=mikrotik metrics=443
ts=2023-04-14T13:58:18.098Z caller=main.go:51 level=info msg="Generating config for module" module=cyberpower
ts=2023-04-14T13:58:18.128Z caller=main.go:66 level=info msg="Generated metrics" module=cyberpower metrics=306
ts=2023-04-14T13:58:18.128Z caller=main.go:51 level=info msg="Generating config for module" module=arista_sw
ts=2023-04-14T13:58:18.171Z caller=main.go:66 level=info msg="Generated metrics" module=arista_sw metrics=91
ts=2023-04-14T13:58:18.486Z caller=main.go:91 level=info msg="Config written" file=/Users/brian/git/snmp_exporter/generator/snmp.yml
make: *** [generate] Error 1
$ 

I note that snmptranslate seems happy when given a simple test:

$ MIBDIRS=mibs MIBS=: snmptranslate -On IF-MIB::ifOperStatus
.1.3.6.1.2.1.2.2.1.8

It's unclear which MIBs have the parse errors in them. snmp.yml is created, but a bit smaller than the official one:

$ ls -l snmp.yml ../snmp.yml
-rw-r--r--  1 brian  staff  1501213 28 Mar 07:51 ../snmp.yml
-rw-r--r--  1 brian  staff  1486060 14 Apr 15:21 snmp.yml

Diffing them, I see that some entries from CPS-MIB are different, but commenting out CyberPower from generator.yml doesn't make a difference.

SuperQ commented 1 year ago

I noticed this too, but haven't had time to dig into it.

Changing the generator config doesn't affect parse errors. Only changing the contents of the MIBs do. The parse errors happen before the config is used.

candlerb commented 1 year ago

Possibly to do with #508 ?

candlerb commented 1 year ago

I think it's partly to do with #508. I made this patch:

diff --git a/generator/main.go b/generator/main.go
index 113dde0..15d7fe7 100644
--- a/generator/main.go
+++ b/generator/main.go
@@ -116,7 +116,7 @@ func main() {
        parseOutput = strings.TrimSpace(parseOutput)
        parseErrors := len(parseOutput) != 0
        if parseErrors {
-               level.Warn(logger).Log("msg", "NetSNMP reported parse error(s)", "errors", len(strings.Split(parseOutput, "\n")))
+               level.Warn(logger).Log("msg", "NetSNMP reported parse error(s)", "errors", len(strings.Split(parseOutput, "\n")), "text", parseOutput)
        }

        nodes := getMIBTree()

And now I get this output:

ts=2023-04-14T15:36:35.850Z caller=main.go:119 level=warn msg="NetSNMP reported parse error(s)" errors=2 text="No log handling enabled - using stderr logging\nDid not find 'DisplayString' in module #-1 (mibs/CyberPower.MIB)"

So the message "No log handling enabled - using stderr logging" is a spurious warning and can be ignored, but the one about DisplayString is real.

Also, I can replicate that using snmptranslate:

$ MIBDIRS=mibs MIBS=: snmptranslate -On CPS-MIB::upsBaseIdentModel
No log handling enabled - using stderr logging
Did not find 'DisplayString' in module #-1 (mibs/CyberPower.MIB)
.1.3.6.1.4.1.3808.1.1.1.1.1.1
candlerb commented 1 year ago

OK, I think I found the problem:

$ grep -R RFC1213 mibs
mibs/ISDN-MIB:                FROM RFC1213-MIB;
mibs/apc-powernet-mib:   DisplayString                                        FROM RFC1213-MIB
mibs/CyberPower.MIB:   DisplayString                                    FROM RFC1213-MIB

All the other MIBs import DisplayString from SNMPv2-TC. (In fact, ISDN-MIB does too. It's importing transmission from RFC1213-MIB).

The straightforward solution, then, is to fetch this file from https://raw.githubusercontent.com/net-snmp/net-snmp/v5.9/mibs/RFC1213-MIB.txt

I can do a PR for that. It makes the generator problem go away (no error is returned).

I see two other things which would be nice to do:

  1. Print the actual warnings/errors, rather than just showing the count
  2. Find a way to configure net-snmp so that "No log handling enabled - using stderr logging" is not returned as an 'error'
candlerb commented 1 year ago

Hmm, there's a problem adding RFC1213-MIB; it overrides some of the things in IF-MIB. For example, comparing the original ../snmp.yml to the generated snmp.yml:

@@ -51,16 +52,16 @@
       1: other
       2: regular1822
       3: hdh1822
-      4: ddnX25
-      5: rfc877x25
-      6: ethernetCsmacd
-      7: iso88023Csmacd
-      8: iso88024TokenBus
-      9: iso88025TokenRing
-      10: iso88026Man
+      4: ddn-x25
+      5: rfc877-x25
+      6: ethernet-csmacd
+      7: iso88023-csmacd
+      8: iso88024-tokenBus
+      9: iso88025-tokenRing
+      10: iso88026-man
       11: starLan
-      12: proteon10Mbit
-      13: proteon80Mbit
+      12: proteon-10Mbit
+      13: proteon-80Mbit
       14: hyperchannel
       15: fddi
       16: lapb

and lots of comment differences too, e.g.

@@ -407,15 +138,14 @@
     oid: 1.3.6.1.2.1.2.2.1.10
     type: counter
     help: The total number of octets received on the interface, including framing
-      characters - 1.3.6.1.2.1.2.2.1.10
+      characters. - 1.3.6.1.2.1.2.2.1.10
     indexes:
     - labelname: ifIndex
       type: gauge
   - name: ifInUcastPkts
     oid: 1.3.6.1.2.1.2.2.1.11
     type: counter
-    help: The number of packets, delivered by this sub-layer to a higher (sub-)layer,
-      which were not addressed to a multicast or broadcast address at this sub-layer
+    help: The number of subnetwork-unicast packets delivered to a higher-layer protocol.
       - 1.3.6.1.2.1.2.2.1.11
     indexes:
     - labelname: ifIndex

So the alternative is to patch those two MIB files to import DisplayString from SNMPv2-TC instead. What do you think about that??

sed -i '' -e 's/\(DisplayString[[:space:]]*FROM \)RFC1213-MIB/\1SNMPv2-TC/' mibs/CyberPower.MIB mibs/apc-powernet-mib

"make generate" is also happy after that. (ISDN-MIB importing "transmission" from RFC1213-MIB doesn't cause any problem)

With this change, the only difference between ../snmp.yml and snmp.yml is a number of removed "fixed_size: 6" lines for PhysAddress48 objects: e.g.

--- ../snmp.yml 2023-03-28 07:51:08.000000000 +0100
+++ snmp.yml    2023-04-14 17:01:57.000000000 +0100
@@ -4776,7 +4776,6 @@
     indexes:
     - labelname: bsnAPDot3MacAddress
       type: PhysAddress48
-      fixed_size: 6
     - labelname: bsnAPIfSlotId
       type: gauge
     lookups:

(74 instances in total)

SuperQ commented 1 year ago

Ahh, interesting. I guess we need to file some upstream issues with those MIBs?

I'm not a big fan of patching MIBs, but, this seems easy enough.

candlerb commented 1 year ago

I guess we need to file some upstream issues with those MIBs?

The trouble is, I don't think there's anything technically wrong with those MIBs, even if they're outdated. They're free to import DisplayString from an older MIB if they like. Arguably, the problem is that net-snmp cannot keep track of multiple definitions of the same OID depending on the context they are referred from; if multiple MIBs define the same OID, then one overwrites the other.

If we could make the newer MIB take precedence, that would probably be OK. But I don't how to do that deterministically.

Another option might be to provide a dummy version of the RFC1213-MIB which defines DisplayString but nothing else - that feels wrong though.

Anyway, I've got a PR ready for patching the mibs at download time, you can see what you think.

dswarbrick commented 1 year ago

FWIW, SNMPv2-TC is derived from RFC 2579. Whilst that RFC doesn't specifically obsolete RFC 1213 or its descendants, it is of course more recent.

Stuff like this is why I'm in favour of moving the MIB minefield out of this repo. Just run smilint on pretty much any third party MIB and bask in the glory of all the syntax errors and standards violations. Sometimes it's a wonder that they successfully parse at all.

SuperQ commented 1 year ago

Yea, true. It's valid, but annoying.

The generator.yml was never meant to be more than a simple example config to show off what's possible. Not be a universal config for all use cases.

Some ideas:

I setup https://github.com/prometheus-community/snmp a while back to be a place to move the MIB minefield to. Something structured more like LibreNMS's MIB repo. Where we have various core MIBs available in dirs, and the vendor-specific stuff in their own dirs. Then at build time we select the collection of MIBDIRS for each generator.yml.

Thinking about this more, I'm starting to like the idea of having MIBDIRS per module. This will make build slower since we need to iterate over the net-snmp code several times. But, it would allow for better handling of these conflicts.

candlerb commented 1 year ago

Some ideas:

  • We could improve on the generator by allowing for MIBDIRS to be specified per module.
  • We move to more iterative build where fragments of snmp.yml are generated and assembled.

Yes - although I wonder if we'd also have to download each MIB into its own directory to prevent them stomping on each other. I'm not sure if specifying MIBS helps here, or whether net-snmp always reads in every file in every MIBDIRS,

Alternatively in git we could build a custom MIBDIR for each module, containing symlinks to the modules to import.

On top of this, I think it would be great if snmp_exporter itself accepted multiple snmp.yml files, e.g. it could read in snmp.d/*.yml. Then you could drop in newly built modules easily without worrying about whether your chosen build affected other working modules.

candlerb commented 1 year ago

Cross-ref: #872 for long-term solution