Search code examples
python-3.xpysnmp

How to investigate errorStatus for each oid in Pysnmp when querying multiple OID's in a single transaction


I am Trying to query multiple OID's in a single getCMD command. I am looking to figure out the best way to check the response of each for errorIndication and errorStatus.One way that I have been able to achieve this is by creating a dictionary and iterating to it, like so:

startTime2 = datetime.now()
print(' From Dict '.center(100, '#'))

mibs_2_pull = {'sysDescr': ObjectType(ObjectIdentity('SNMPv2-MIB', 'sysDescr', 0)),
               'sysName': ObjectType(ObjectIdentity('SNMPv2-MIB', 'sysName', 0))
}

for mib in mibs_2_pull:
    errorIndication, errorStatus, errorIndex, varBinds = next(
    getCmd(SnmpEngine(), credentials, target,cd, mibs_2_pull[mib] ))
    if errorIndication:
        print(errorIndication)
    elif errorStatus:
        print('%s at %s' % (errorStatus.prettyPrint(),
                            errorIndex and varBinds[int(errorIndex) - 1][0] or '?'))
    else:
        for varBind in varBinds:
            print(' = '.join([x.prettyPrint() for x in varBind]))
print(datetime.now() - startTime2)

This works great as I can address each oid's errorIndication & errorStatus individually, However, this method is slower than by pulling all OID's in a single getCMD like so:

errorIndication, errorStatus, errorIndex, varBinds = next(
    getCmd(se,
           credentials,
           target,
           cd,
           ObjectType(ObjectIdentity('SNMPv2-MIB', 'sysName', 1)),
           ObjectType(ObjectIdentity('SNMPv2-MIB', 'sysDescr', 0)),
           ))
if errorIndication:
    # Invalid Credentials
    # IP not reachable

    print('errorIndication:', errorIndication)
elif errorStatus:
    # Invalid OID

    for x in varBinds:
        print(x[1].prettyPrint())
    # for an_oid, a_val in varBinds:
        # print(an_oid), a_val

        #errorStatus_string = 'errorStatus: ' + '%s at %s' % (errorStatus.prettyPrint(),
        #                                                     errorIndex and varBinds[int(errorIndex) - 1][0] or '?')
        # print(errorStatus_string)

        # return the errorStatus of a Single OID
        #   errorStatus_string = 'errorStatus: ' + '%s at %s' % (errorStatus.prettyPrint(),
        #                       errorIndex and varBinds[int(errorIndex) - 1][0] or '?')
        #   print(errorStatus_string)
        # #Determine how to check the error status for each OID individually

else:
    # Will Only Execute if everything is successful
    for an_oid, a_val in varBinds:
        print(an_oid, a_val, sep=' => ')

print (datetime.now() - startTime1)

The above snippet of code is much faster, however, I am unsure on how to access the errorStatus individually of each OID that I have queried. To be frank, it may be due to my lack of understanding of some Python fundamentals. If either of my OID's returns an errorStatus, nothing prints out under my else clause and the same errorStatus will print for both OID's under elif errorStatus:

How do I rewrite my elif errorStatus clause to print the oid and the errorStatus of only my failed OID's and still print my successful oid queries under else


Solution

  • This singularity of the single error-status field is one of the shortcomings of SNMP v1. So if you have to use SNMP v1, there is absolutely no solution.

    In SNMP v2c+ this single error-status field is deprecated in favor of so-called exception objects. The idea being to return some sentinel values in response to indicate a problem with any of the managed objects instances requested, not just one of them.

    With pysnmp your code could look like this:

    for oid, value in varBinds:
        if value.isSameTypeWith(NoSuchInstance()) or value.isSameTypeWith(NoSuchObject()):
            print('managed object %s does not exist at this agent' % (oid,))
            continue
         ...
    

    Keep in mind that these "exception objects" can only be served in response to GET or SET commands, for GETNEXT the only possible exception is "end-of-mib-view".