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
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".