PySNMP Project Logo

Project diary
Documentation
Examples
License
Download
Mailing lists

Projects using PySNMP
TwistedSNMP
Zenoss


Relevant projects
SNMPy
YAPSNMP
LibSMI
Scotty software

SourceForge Logo

import sys, getopt
from pysnmp.proto import v1, v2c
from pysnmp.mapping.udp import role
import pysnmp.proto.api.generic
import pysnmp.proto.cli.ucd

# Initialize help messages
options =           'Options:\n'
options = options + '  -p       port to communicate with at the agent. Default is 161.\n'
options = options + '  -r    number of retries to be used in requests. Default is 5.\n'
options = options + '  -t    timeout between retries. Default is 1.\n'
options = options + '  -v    SNMP version to use [1, 2c]. Default is 1 (version one).\n'
options = options + '  -R             report variables types on output.'
usage = 'Usage: %s [options] ' % sys.argv[0]
usage = usage + ' ' + v2c.GetRequest().cliUcdGetUsage() + '\n' + options
    
# Initialize defaults
port = 161; retries = 5; timeout = 1; version = '1'; reportTypeFlag = None;

# Parse possible options
try:
    (opts, args) = getopt.getopt(sys.argv[1:], 'hp:r:t:v:R',\
                                 ['help', 'port=', 'retries=', \
                                  'timeout=', 'version=', 'report-type'])
except getopt.error, why:
    print 'getopt error: %s\n%s' % (why, usage)
    sys.exit(-1)

try:
    for opt in opts:
        if opt[0] == '-h' or opt[0] == '--help':
            print usage
            sys.exit(0)
        
        if opt[0] == '-p' or opt[0] == '--port':
            port = int(opt[1])

        if opt[0] == '-r' or opt[0] == '--retries':
            retries = int(opt[1])

        if opt[0] == '-t' or opt[0] == '--timeout':
            timeout = int(opt[1])

        if opt[0] == '-v' or opt[0] == '--version':
            version = opt[1]

        if opt[0] == '-R' or opt[0] == '--report-type':
            reportTypeFlag = 1

except ValueError, why:
    print 'Bad parameter \'%s\' for option %s: %s\n%s' \
          % (opt[1], opt[0], why, usage)
    sys.exit(-1)

if len(args) < 1:
    print 'Insufficient number of arguments supplied\n%s' % usage
    sys.exit(-1)

# Create SNMP manager object
client = role.manager((args[0], port))

# Pass it a few options
client.timeout = timeout
client.retries = retries

# Choose protocol version specific module
try:
    snmp = eval('v' + version)

except (NameError, AttributeError):
    print 'Unsupported SNMP protocol version: %s\n%s' % (version, usage)
    sys.exit(-1)

# Create SNMP GET/GETNEXT request
req = snmp.GetRequest(); nextReq = snmp.GetNextRequest()

# Initialize request message from C/L params
req.cliUcdSetArgs(args[1:]); nextReq.cliUcdSetArgs(args[1:])

# Create a response message framework
rsp = snmp.Response()

# Store tables headers
headVars = map(lambda x: x[0], req.apiGenGetPdu().apiGenGetVarBind())

# Traverse agent MIB
while 1:
    def cb_fun(answer, src):
        """This is meant to verify inbound messages against out-of-order
           messages
        """
        # Decode message
        rsp.decode(answer)
        
        # Make sure response matches request
        if req.match(rsp):
            return 1
        
    # Encode SNMP request message and try to send it to SNMP agent and
    # receive a response
    (answer, src) = client.send_and_receive(req.encode(), (None, 0), cb_fun)

    # Fetch Object ID's and associated values
    vars = rsp.apiGenGetPdu().apiGenGetVarBind()

    # Check for remote SNMP agent failure
    if rsp.apiGenGetPdu().apiGenGetErrorStatus():
        # SNMP agent reports 'no such name' when walk is over
        if rsp.apiGenGetPdu().apiGenGetErrorStatus() == 2:
            # Switch over to GETNEXT req on error
            # XXX what if one of multiple vars fails?
            if not (req is nextReq):
                req = nextReq
                continue
            # One of the tables exceeded
            for l in vars, headVars:
                del l[rsp['pdu'].values()[0]['error_index'].get()-1]
            if not vars:
                sys.exit(0)
        else:
            raise str(rsp['pdu'].values()[0]['error_status']) + ' at '\
                  + str(vars[rsp.apiGenGetPdu().apiGenGetErrorIndex()-1][0])

    # Exclude completed var-binds
    while 1:
        for idx in range(len(headVars)):
            if not snmp.ObjectIdentifier(headVars[idx]).isaprefix(vars[idx][0]):
                # One of the tables exceeded
                for l in vars, headVars:
                    del l[idx]
                break
        else:
            break

    if not headVars:
        sys.exit(0)

    # Print out results
    for (oid, val) in vars:
        print oid, ' ---> ',
        if reportTypeFlag:
            print val
        else:
            print repr(val.get())

    # Update request ID
    req.apiGenGetPdu().apiGenSetRequestId(req.apiGenGetPdu().apiGenGetRequestId()+1)

    # Switch over GETNEXT PDU for if not done
    if not (req is nextReq):
        req = nextReq

    # Load get-next'ed vars into new req
    req.apiGenGetPdu().apiGenSetVarBind(vars)

Need help? Try PySNMP mailing lists.