Krisz
Krisz

Reputation: 743

Async snmp table walk with PySnmp

I try to to collect table async with PySnmp, but example give back only first record.

Could anyone suggest what is wrong?

import asyncio
from pysnmp.hlapi.asyncio import *

@asyncio.coroutine
def run():
    snmp_engine=SnmpEngine()
    count=0
    while True:
        errorIndication, errorStatus, errorIndex, varBinds = yield from nextCmd(
            snmp_engine,
            CommunityData('public'),
            UdpTransportTarget(('demo.pysnmp.com', 161)),
            ContextData(),
            ObjectType(ObjectIdentity('SNMPv2-MIB', 'system')),
        )
        
        for next_var in varBinds:
            print(next_var[0])
        
        count+=1
        #break
        if count > 10:
            break

asyncio.get_event_loop().run_until_complete(run())  

Upvotes: 2

Views: 1576

Answers (2)

kara
kara

Reputation: 130

I have experienced same issue recently. I think the asynchronous nextCmd is not working like the sync nextCmd. You have to update the oid in each iteration. This code may help:

import asyncio
from pysnmp.hlapi.asyncio import *


def inc_oid(oid):
    _oid = oid.split(".")
    lastint = int(_oid[-1])
    _oid[-1] = str(lastint + 1)
    return ".".join(_oid)

snmp_engine=SnmpEngine()

@asyncio.coroutine
def snmp_walk_async(oid):
    endoid = inc_oid(oid)
    while True:
        errorIndication, errorStatus, errorIndex, varBinds = yield from nextCmd(
            snmp_engine,
            CommunityData("public"),
            UdpTransportTarget(("demo.pysnmp.com", 161)),
            ContextData(),
            ObjectType(ObjectIdentity(oid)),
            lexicographicMode=False,
        )

        #Some Error Checkings

        varBind = varBinds[0][0]
        oid, value = varBind
        oid = str(oid)

        if oid >= endoid:
            break

        for varBind in varBinds:
            print(' = '.join([x.prettyPrint() for x in varBind]))


asyncio.get_event_loop().run_until_complete(snmp_walk_async("1.3.6.1.2.1.1"))  

Upvotes: 1

Danube
Danube

Reputation: 1

This is an implementation that works for me with python 3.10.7, 3.11 and pysnmp-lextudio 5.0.29.

Note: SnmpEngine and UdpTransportTarget objects must be created in an async function in order to work.

# snmpwalk
import asyncio
import time

from pysnmp.hlapi.asyncio import *
import sys


async def walk(str_oid):
    res = []

    snmp_engine = SnmpEngine()
    usm = UsmUserData('user', 
                      'auth_password', 
                      'priv_password', 
                      authProtocol=usmHMACSHAAuthProtocol, 
                      privProtocol=usmAesCfb128Protocol)
    udp_transport_target = UdpTransportTarget(('192.168.1.48', 161))
    context_data = ContextData()
    var_binds = [ObjectType(ObjectIdentity(str_oid))]
    loop = True
    while loop is True:
        error_indication, error_status, error_index, var_bind_table = await nextCmd(
            snmp_engine,
            usm,
            udp_transport_target,
            context_data,
            *var_binds
        )

        if error_indication:
            print(error_indication)
            return
        elif error_status:
            print('%s at %s' % (error_status.prettyPrint(),
                                error_index and var_bind_table[int(error_index) - 1][0] or '?'))
            return
        else:
            if isEndOfMib(var_bind_table[-1]):
                break
            else:
                for var_bind_row in var_bind_table:
                    for var_bind in var_bind_row:
                        oid = str(var_bind[0])
                        value = str(var_bind[1])
                        if oid.startswith(str_oid[1:]) is True:
                            res.append((oid, value))
                var_binds = var_bind_table[-1]

    return res

ubs = ".1.3.6.1.4.1.11348.856683"
ubsC = ".1.3.6.1.4.1.11348.856683.1"
ubsM = ".1.3.6.1.4.1.11348.856683.2"

for oid in [ubs, ubsC, ubsM]:
    res = asyncio.run(walk(oid))
    print(f'walking {oid}')
    for r in res:
        print(r[0], ' = ', r[1])

Upvotes: 0

Related Questions