Munin SNMP Plugin

This page is an extension to my blog entry Improving Munin SNMP Performance. If you haven't read the article you might want to do it now before using the code presented on this wiki page.

The Plugin presented in my blog entry was a first version and rather naive. The version presented here includes some changes in the 'configure' section to include the interface names in the graph title.

#! /usr/bin/env python
#
# SNMP plugin for Munin written and (c) by Arne Brodowski
# Use it as a drop-in replacement for the bundled snmp__if_ and snmp__if_err_
# plugins.
# Feel free to redistribute this code under the terms of the new BSD license.

import os
import sys
import re
import subprocess

community = os.environ.get('community', 'public')
m = re.match(r'(.*)snmp_(?P<host>[^_]*)_if_(?P<if>[\d]*)', sys.argv[0])
conf = m.groupdict()
conf.update({'community': community})

try:
    if(sys.argv[1] == "config"):
        # fetch interface name via snmp
        cmd = ["snmpget",
                "-v","2c",
                "-c","%(community)s"%conf,
                "-O","v", "%(host)s"%conf,
                "1.3.6.1.2.1.2.2.1.2.%(if)s"%conf,
            ]
        out = subprocess.Popen(cmd, stdout=subprocess.PIPE).communicate()[0]
        if ":" in out:
            ifname = out.split()[1]
        else:
            ifname = conf['if']

        print "host_name %(host)s" % conf
        print "graph_title Interface %s traffic and errors" % ifname
        print "graph_order recv send errin errout"
        print "graph_args --base 1000"
        print "graph_vlabel bits in (-) / out (+) per \${graph_period}"
        print "graph_category network"
        print "graph_info This graph shows traffic and errors for interface %s." % ifname

        print "send.info Bits sent/received by this interface.";

        print "recv.label recv bps"
        print "recv.type DERIVE"
        print "recv.cdef recv,8,*"
        print "recv.max 2000000000"
        print "recv.min 0"

        print "send.label bits/s"
        print "send.type DERIVE"
        print "send.negative recv" #that's why recv doesn't has it's own label
        print "send.cdef send,8,*"
        print "send.max 2000000000"
        print "send.min 0"

        print "errout.info Bits unsuccessfully sent/received by this interface."

        print "errin.label err in"
        print "errin.type DERIVE"
        print "errin.cdef errin,8,*"
        print "errin.max 2000000000"
        print "errin.min 0"

        print "errout.label errors"
        print "errout.type DERIVE"
        print "errout.negative errin"
        print "errout.cdef errout,8,*"
        print "errout.max 2000000000"
        print "errout.min 0"

        sys.exit(0)
except IndexError:
    pass


cmd = ["snmpget",
        "-v","2c",
        "-c","%(community)s"%conf,
        "-O","v", "%(host)s"%conf,
        "1.3.6.1.2.1.2.2.1.10.%(if)s"%conf,
        "1.3.6.1.2.1.2.2.1.16.%(if)s"%conf,
        "1.3.6.1.2.1.2.2.1.14.%(if)s"%conf,
        "1.3.6.1.2.1.2.2.1.20.%(if)s"%conf,
    ]
out = subprocess.Popen(cmd, stdout=subprocess.PIPE).communicate()[0]

for x in zip(('recv', 'send', 'errin', 'errout'), out.splitlines()):
    print "%s.value %s"%(x[0], x[1].split()[1])

It seems that munin requests the "config" part every 5 minutes together with the data. Therefore the first version of this plugin made no snmp requests in the config part.

Update

I received the following notes from Zinching Dang (fg-networking.de):