pysnmp
pysnmp copied to clipboard
walkCmd not returning from loaded custom MIB
Expected behavior
Code Block to Walk SNMP MIB
Consider the following block of code:
import asyncio
from pysnmp.hlapi.asyncio import *
from pysnmp.smi import builder, view, compiler, rfc1902
# Initialize the MIB builder
mib_builder = builder.MibBuilder()
# Add MIB sources, including the directory containing the converted MIB file
custom_mib_path = '/home/conrad/.pysnmp/mibs'
mib_sources = mib_builder.getMibSources() + (builder.DirMibSource(custom_mib_path),)
mib_builder.setMibSources(*mib_sources)
# Load custom MIB files
compiler.addMibCompiler(mib_builder, sources=['file://' + custom_mib_path])
mib_builder.loadModules('ELTEK-BC2000-DC-POWER-MIB-V2-12')
# Create MIB viewer
mib_view_controller = view.MibViewController(mib_builder)
async def snmp_walk_custom_mib(oid, ip, community='public'):
result = []
try:
identity = ObjectIdentity('ELTEK-BC2000-DC-POWER-MIB-V2-12', oid).loadMibs('ELTEK-BC2000-DC-POWER-MIB-V2-12')
identity = identity.resolveWithMib(mib_view_controller)
except Exception as e:
print(f"Error resolving OID {oid}: {e}")
return []
iterator = walkCmd(
SnmpEngine(),
CommunityData(community),
UdpTransportTarget((ip, 161)),
ContextData(),
ObjectType(identity),
lexicographicMode=False
)
async for error_indication, error_status, error_index, var_binds in iterator:
if error_indication:
print(f"Error indication: {error_indication}")
break
elif error_status:
print(f"Error status: {error_status.prettyPrint()} at {error_index}")
break
else:
for var_bind in var_binds:
oid, value = var_bind
try:
oid_label = oid.resolveWithMib(mib_view_controller)
oid_number = oid.getOid()._value
oid_label = mib_view_controller.getNodeName((oid_number))
except Exception as e:
oid_label = 'Unknown'
print(f"Error getting label for OID {oid}: {e}")
result.append(f'{oid.prettyPrint()} = {value.prettyPrint()} ({oid_label})')
return result
async def main():
value1 = await snmp_walk_custom_mib('vpwrPanelModuleSerNum', '10.115.0.10')
print("\n".join(value1))
# Run the main function
asyncio.run(main())
Expected Output
The code should return the correct MIB from ELTEK-BC2000-DC-POWER-MIB-V2-12:
ELTEK-BC2000-DC-POWER-MIB-V2-12::vpwrPanelModuleSerNum.0 = 183886010176
Actual Output
However, it returns:
SNMPv2-SMI::enterprises.13858.2.4.2.1.3.5.1 = 183886010176
Actual behavior
Issue
The returned object from the walkCmd doesn't use the right MIB but defaults to the SNMPv2-SMI MIB file:
SNMPv2-SMI::enterprises.13858.2.4.2.1.3.5.1 = 183886010176
I believe this is a similar issue than this bug from "etingof" repo: https://github.com/etingof/pysnmp/issues/273
Detailed steps
Issue
From the debug log, we can see that my ELTEK-BC2000-DC-POWER-MIB-V2-12 mib file is loaded properly. Also the mib_view_controller object contains my mib file as well.
Note
This issue only happens for the walkCmd
, it works as intended with the getCmd
.
The workaround that I've found is to reinstantiate the object based on the returned OID number with the correct MIB:
for device_result in completed_tasks:
task_results = []
for oid_result in device_result:
if oid_result is not None:
for varBind in oid_result:
if varBind[0]._ObjectIdentity__modName == "ELTEK-BC2000-DC-POWER-MIB-V2-12":
full_oid = varBind[0].prettyPrint()
key = full_oid.split('::')[-1]
value = varBind[1].prettyPrint()
task_results.append({key: value})
all_keys.add(key)
else:
full_oid = varBind[0].getOid()._value
resolved_varBind = mibViewController.getNodeName((full_oid))
last_value = resolved_varBind[1][-1]
resolved_varBind_2_str = '.' + '.'.join(map(str, resolved_varBind[2]))
key = last_value + resolved_varBind_2_str
value = varBind[1]._value
if isinstance(value, bytes):
decoded_value = value.decode('utf-8')
else:
decoded_value = value
task_results.append({key: decoded_value})
all_keys.add(key)
Partial log
2024-07-25 16:44:27,548 DEBUG exportSymbols: symbol ELTEK-BC2000-DC-POWER-MIB-V2-12::vpwrDcPowerUnkModule 2024-07-25 16:44:27,548 DEBUG exportSymbols: symbol ELTEK-BC2000-DC-POWER-MIB-V2-12::thirdPartyProduct 2024-07-25 16:44:27,548 DEBUG loadModule: loaded /home/conrad/.pyenv/versions/3.12.0/lib/python3.12/site-packages/pysnmp/smi/mibs/ELTEK-BC2000-DC-POWER-MIB-V2-12/home/conrad/.pyenv/versions/3.12.0/lib/python3.12/site-packages/pysnmp/smi/mibs/ELTEK-BC2000-DC-POWER-MIB-V2-12.py 2024-07-25 16:44:27,548 DEBUG MIB loaded successfully ...
Python package information
pysnmp-lextudio 6.2.1
Operating system information
Ubuntu 22.04.4 LTS
Python information
3.12.0
(Optional) Contents of your test script
No response
Relevant log output
No response