yuval
yuval

Reputation: 3088

Pysnmp can't get multiple oids if one of them is not found using SNMPv1

When I use pysnmp and try to get multiple oids in one getCmd command, but one of the oids does not exist then I can't receive any of the oids' values, unless i use SNMPv2 or SNMPv3(change mpmodel in the code)

from pysnmp.entity.rfc3413.oneliner import cmdgen
from pysnmp.smi import builder, view, error

def cbFun_OID(sendRequestHandle, errorIndication, errorStatus, errorIndex, varBinds, cbCtx):
    (authData, transportTarget) = cbCtx
    for oid, val in varBinds:
        print val.prettyPrint()
ip='192.168.0.101'
cmdGen = cmdgen.AsynCommandGenerator()
cmdGen.getCmd(
   cmdgen.CommunityData('public', mpModel=0),
   cmdgen.UdpTransportTarget((ip, 161)),
   ((1,3,6,1,2,1,43,10,2,1,4,1,1),(1,3,6,1,2,1,43,5,1,1,1,1,123456)),
   (cbFun_OID, (cmdgen.CommunityData('public', mpModel=0), cmdgen.UdpTransportTarget((ip, 161)))))
cmdGen.snmpEngine.transportDispatcher.runDispatcher()

If both of the oids exist i get two values.
If at least one of the oids doesn't exist then all the values will be 'No Such Object currently exists at this OID'.
I can use the asyncGetCmd command to get multiple oids but this is not what i want.
I would basically need to open a thread for each oid and scan it individually which is a very inefficient method.
For example:

from pysnmp.entity.rfc3413.oneliner import cmdgen
from pysnmp.smi import builder, view, error

def cbFun_OID(sendRequestHandle, errorIndication, errorStatus, errorIndex, varBinds, cbCtx):
(authData, transportTarget) = cbCtx
for oid, val in varBinds:
    print val.prettyPrint()
ip='192.168.0.101'
cmdGen = cmdgen.AsynCommandGenerator()
cmdGen.asyncGetCmd(
   cmdgen.CommunityData('public', mpModel=0),
   cmdgen.UdpTransportTarget((ip, 161)),
   ((1,3,6,1,2,1,43,10,2,1,4,1,1),),
   (cbFun_OID, (cmdgen.CommunityData('public', mpModel=0), cmdgen.UdpTransportTarget((ip, 161)))))
cmdGen.asyncGetCmd(
   cmdgen.CommunityData('public', mpModel=0),
   cmdgen.UdpTransportTarget((ip, 161)),
   ((1,3,6,1,2,1,43,5,1,1,1,1,123456),),
   (cbFun_OID, (cmdgen.CommunityData('public', mpModel=0), cmdgen.UdpTransportTarget((ip, 161)))))
cmdGen.snmpEngine.transportDispatcher.runDispatcher()

How can I use pysnmp to get multiple oids even if some of the oids don't exist?

Upvotes: 1

Views: 1395

Answers (1)

Ilya Etingof
Ilya Etingof

Reputation: 5555

Are you trying to gather existing variables from SNMP v1 response containing non-existing variables? In that case I'm not sure that goes well with SNMP standards. As per RFC 2576:

4.1.2.3.1. If the error-status is anything other than noError,
  ...
  -  The variable binding list of the response PDU SHALL be made
     exactly the same as the variable binding list that was received
     in the original request.

Since GET request normally contain NULLs as values, you are not going to [reliably] receive any values from SNMP v1 Agent whenever at least one variable is missing.

I'm referring to v1->v2c PDU translation here because pysnmp API you use works as a v2c entity at the PDU API level regardless of SNMP version peer is talking.

If you think your particular v1 Agent still returns something meaningful even along with error-status being reported, you could use packet-level API to work with SNMPv1 PDU, as that would not invoke v1->v2c PDU translation code trashing everything in v1 response. Before trying that you may wish to enable pysnmp debugging to see what is actually in the v1 RESPONSE PDU you are getting.

If you think this pysnmp behaviour is against SNMP standards, please elaborate your point.

Upvotes: 3

Related Questions