Extending the Cumulus Linux Net-SNMP Implementation

Follow

The Cumulus Linux implementation of SNMP can be configured/extended in a number of ways, in environments where required features are currently not included. Below are examples that can be adapted for extending Cumulus Linux to add:

  • an MIB for SNMP get

  • a trigger for SNMP trap

  • a log event for syslog

SNMP get MIB

To add an MIB for SNMP get:

  1. Copy the following example file, named sample_pass_persist.py, to /usr/share/snmp/sample_pass_persist.py:

    #! /usr/bin/python -u
    # This is a simple pass_persist example that
    # returns the output of uname -a as a string
    #
    # To activate this, you would need to put this
    # script in /usr/share/snmp/sample_pass_persist.py
    # and include lines in /etc/snmp/snmpd.conf
    # that look like the following:
    #
    # # this exposes our new objects for viewing
    # view   systemonly  included   .1.3.6.1.4.1.40310.666
    # # this calls our python pass_persist script for this OID
    # pass_persist .1.3.6.1.4.1.40310.666 /usr/share/snmp/sample_pass_persist.py
    #
    
    import subprocess
    import cms_passpersist as snmp
    
    # to test this, set debug to 1 and run from the commandline
    debug = 0
    
    oid_base = '.1.3.6.1.4.1.40310.666'
    
    if debug:
        print('sample_pass_persist.py: running in debug mode')
        
    def update():
        """
        Simply grab the output of uname -a and stick it in our MIB
        """
        oid = '1.1.1'
        try:
            unameOutput = subprocess.Popen((['/bin/uname','-a']),
                                           stdout=subprocess.PIPE,
                                           shell=False).communicate()[0]
        except:
            # if the uname -a command fails, just continue
            pass
    
        if debug:
            print('%s' % oid,unameOutput.strip())
        else:
            pp.add_str('%s' % oid,unameOutput.strip())
    
    if debug:
        update()
    else:
        pp = snmp.PassPersist(oid_base)
        pp.start(update, 40)
  2. Add the following lines to /etc/snmp/snmpd.conf, and save the file:

    view systemonly included .1.3.6.1.4.1.40310.666 pass_persist .1.3.6.1.4.1.40310.666 /usr/share/snmp/sample_pass_persist.py
  3. Restart snmp.

    # sudo service snmp restart

This example file will update the .1.3.6.1.4.1.40310.666.1.1.1 MIB every 40 seconds.

Example:

cumulus@switch:~ # snmpwalk -v 2c -c public localhost .1.3.6.1.4.1.40310.666
iso.3.6.1.4.1.40310.666.1.1.1 = STRING: "Linux sw19 3.2.68-6 #3.2.68-6 SMP Fri Oct 9 19:37:09 PDT 2015 ppc powerpc GNU/Linux"
iso.3.6.1.4.1.40310.666.1.1.1 = No more variables left in this MIB View (It is past the end of the MIB tree)

SNMP Trap Trigger

The example file below, testtrap.py, can be run as a cron job at the desired frequency, in order to trigger an SNMP trap:

#!/usr/bin/env python
#
# This is sample pythonscript that checks the
# output of smonctl and sends an snmptrap and
# logs a syslog message to /var/log/syslog.
# This assumes that snmptrapd and snmp is installed
# and configured.
#
# Run only in a test network after customizing.


import subprocess
import logging
import logging.handlers
import time

log = logging.getLogger(__name__)
log.setLevel(logging.DEBUG)
handler = logging.handlers.SysLogHandler(address='/dev/log')
formatter = logging.Formatter('%(module)s.%(funcName)s: %(message)s')

handler.setFormatter(formatter)
log.addHandler(handler)

def deviceChecker():
    # modify trap command to your liking
    while(True):
        badOutput = subprocess.Popen('smonctl | grep "BAD" ',
                                     shell=True,
                                     stdout=subprocess.PIPE)\
                                     .communicate()[0].strip()
        # split the output to find the bad device
        log.info('Checking the output of smonctl for BAD devices')
        if badOutput:
            device = badOutput.split()[0]
        else:
            device = None
        if device:
            # make sure we send a trap
            trapcommand = '''/usr/bin/snmptrap -v 1 -c public  localhost .1.3.6.1.6.3.1.1.5.2 0 0 "" "" .1.3.6.1.4.1 s "BAD DEVICE=%s"''' % device
            trap = subprocess.Popen(trapcommand,
                                    shell=True,stderr=subprocess.PIPE,
                                    stdout=subprocess.PIPE)
            stream = trap.communicate()[0]
            rc = trap.returncode
            if rc > 0:
                log.error('Error running the snmptrap command')
            else:
                # make sure we log it
                log.critical('Critical Error: device %s is BAD'%device)

        time.sleep(60)

if __name__ == '__main__':
    deviceChecker()

Example:

cumulus@switch:~ # ./testtrap.py 
cumulus@switch:/var/log # tcpdump -i lo
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on lo, link-type EN10MB (Ethernet), capture size 65535 bytes
18:38:28.119719 IP localhost.localdomain.41568 > localhost.localdomain.snmp-trap: Trap(57) S:1.1.5.2 0.0.0.0 coldStart 36391889 E:="BAD DEVICE=PSU1"
18:38:28.119772 IP localhost.localdomain > localhost.localdomain: ICMP localhost.localdomain udp port snmp-trap unreachable, length 108

Log Events for syslog

The example file below, testsyslog.py can be run as a cron job at desired intervals, to create a log event for syslog.

#!/usr/bin/env python
#
# This is sample pythonscript that checks the
# output of smonctl and 
# logs a syslog message to /var/log/syslog.
#
# Run only in a test network after customizing.


import subprocess
import logging
import logging.handlers
import time

log = logging.getLogger(__name__)
log.setLevel(logging.DEBUG)
handler = logging.handlers.SysLogHandler(address='/dev/log')
formatter = logging.Formatter('%(module)s.%(funcName)s: %(message)s')

handler.setFormatter(formatter)
log.addHandler(handler)

def deviceChecker():
    # modify trap command to your liking
    while(True):
        badOutput = subprocess.Popen('smonctl | grep "BAD" ',
                                     shell=True,
                                     stdout=subprocess.PIPE)\
                                     .communicate()[0].strip()
        # split the output to find the bad device
        log.info('Checking the output of smonctl for BAD devices')
        if badOutput:
            device = badOutput.split()[0]
        else:
            device = None
        if device:
            # make sure we log it
            log.critical('Critical Error: device %s is BAD'%device)

        return
        time.sleep(60)

if __name__ == '__main__':
    deviceChecker()

Example:

cumulus@switch:~ # ./testtrap.py 
cumulus@switch:/var/log # tail -f syslog 
2015-10-20T18:38:14.320323+00:00 cumulus testtrap.deviceChecker: Checking the output of smonctl for BAD devices
2015-10-20T18:38:14.370416+00:00 cumulus testtrap.deviceChecker: Critical Error: device PSU1 is BAD
2015-10-20T18:38:28.070017+00:00 cumulus testtrap.deviceChecker: Checking the output of smonctl for BAD devices
2015-10-20T18:38:28.128689+00:00 cumulus testtrap.deviceChecker: Critical Error: device PSU1 is BAD
2015-10-20T18:39:43.817566+00:00 cumulus testtrap.deviceChecker: Checking the output of smonctl for BAD devices
2015-10-20T18:39:43.872684+00:00 cumulus testtrap.deviceChecker: Critical Error: device PSU1 is BAD
Have more questions? Submit a request

Comments

Powered by Zendesk