Pysnmp не может получить несколько oids, если один из них не найден с помощью SNMPv1.

Когда я использую pysnmp и пытаюсь получить несколько oid в одной команде getCmd, но один из oid не существует, я не могу получить ни одно из значений oid, если только я не использую SNMPv2 или SNMPv3 (изменить mpmodel в коде)

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()

Если оба оида существуют, я получаю два значения.
Если хотя бы один из оидов не существует, тогда все значения будут "Нет такого объекта в настоящее время с этим OID".
Я могу использовать asyncGetCmd команда для получения нескольких oids, но это не то, что мне нужно.
В основном мне нужно было бы открыть поток для каждого oid и просканировать его по отдельности, что является очень неэффективным методом.
Например:

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()

Как я могу использовать pysnmp для получения нескольких oids, даже если некоторые из oids не существуют?


person yuval    schedule 31.08.2015    source источник


Ответы (1)


Вы пытаетесь собрать существующие переменные из ответа SNMP v1, содержащего несуществующие переменные? В этом случае я не уверен, что это соответствует стандартам SNMP. Согласно 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.

Поскольку запрос GET обычно содержит NULL в качестве значений, вы не собираетесь [надежно] получать какие-либо значения от агента SNMP v1 всякий раз, когда отсутствует хотя бы одна переменная.

Я имею в виду перевод v1->v2c PDU здесь, потому что API pysnmp, который вы используете, работает как объект v2c на уровне API PDU независимо от версии SNMP.

Если вы считаете, что ваш конкретный агент v1 по-прежнему возвращает что-то значимое даже вместе с сообщением о статусе ошибки, вы можете использовать API на уровне пакетов для работы с SNMPv1 PDU, так как это не вызовет код перевода v1->v2c PDU, уничтожающий все в ответе v1. Прежде чем пытаться это сделать, вы можете включить отладку pysnmp, чтобы увидеть, что на самом деле находится в v1 RESPONSE PDU, который вы получаете.

Если вы считаете, что такое поведение pysnmp противоречит стандартам SNMP, уточните свою точку зрения.

person Ilya Etingof    schedule 31.08.2015