Am writing a Sample code below for fetching Cisco Switch Information through SNMP for the python pysnmp module.
after executing below code am getting 'No SNMP response received before timeout'.
from pysnmp.entity.rfc3413.oneliner import cmdgen
import time
#SNMP agent address
SNMP_AGENT_HOST = 'IPADDRESS' # IP adderess
#SNMP default port
SNMP_PORT = 161
#Add SNMP agent community here
SNMP_COMMUNITY = 'public'
cmdGen = cmdgen.CommandGenerator()
errorIndication, errorStatus, errorIndex, varBinds = cmdGen.getCmd(
cmdgen.CommunityData(SNMP_COMMUNITY),
cmdgen.UdpTransportTarget((SNMP_AGENT_HOST, SNMP_PORT)),
'1.3.6.1.4.1.9.2.1.56.0', # Cisco Switch OID
'1.3.6.1.4.1.9.2.1.57.0' #
)
# Check for errors and print out results
if errorIndication:
print(errorIndication)
else:
if errorStatus:
print('%s at %s' % (
errorStatus.prettyPrint(),
errorIndex and varBinds[int(errorIndex)-1] or '?'
)
)
else:
for name, val in varBinds:
print('%s = %s' % (name.prettyPrint(), val.prettyPrint()))
I getting the result
No SNMP response received before timeout
I want to be fetch all OID related Information through the GET call.
Your quickest way of diagnosing this is to use an EXISTING utility that you know works, and try it against that IPADDRESS with the authentication that you think should work.
If that utility, eg. NET-SNMP snmpwalk or snmpgetnext, does not work, then your problem is likely not in your code, but your understanding of how to access the SNMP agent. Eg. are you certain the community string "public" works?
It is ALWAYS better to work from success, than to interpolate from failure.
Related
I try to use PySNMP to receive SNMPv3 Traps. I found this example code:
#!/usr/bin/env /usr/bin/python3
from pysnmp.entity import engine, config
from pysnmp.carrier.asyncore.dgram import udp
from pysnmp.entity.rfc3413 import ntfrcv
from pysnmp.proto.api import v2c
from pysnmp.smi.rfc1902 import ObjectIdentity
snmpEngine = engine.SnmpEngine()
# Transport setup
# UDP over IPv4
config.addTransport(
snmpEngine,
udp.domainName,
udp.UdpTransport().openServerMode(('0.0.0.0', 162)),
)
# SNMPv3/USM setup
config.addV3User(
snmpEngine, '<username>',
config.usmHMACMD5AuthProtocol, '<password>',
config.usmAesCfb128Protocol, '<password>',
securityEngineId=v2c.OctetString(hexValue='<engineid>')
)
def cbFun(snmpEngine, stateReference, contextEngineId, contextName,
varBinds, cbCtx):
print('Notification from ContextEngineId "%s", ContextName "%s"' (contextEngineId.prettyPrint(), contextName.prettyPrint()))
for name, val in varBinds:
print('%s = %s' % (name.prettyPrint(), val.prettyPrint()))
# Register SNMP Application at the SNMP engine
ntfrcv.NotificationReceiver(snmpEngine, cbFun)
snmpEngine.transportDispatcher.jobStarted(1) # this job would never finish
# Run I/O dispatcher which would receive queries and send confirmations
try:
snmpEngine.transportDispatcher.runDispatcher()
except:
snmpEngine.transportDispatcher.closeDispatcher()
raise
This code works for me, but i get the raw Traps. I have an vendor specific MIB File I want to use. But I can't find any documentation how to bind the mib to the snmpEngine. The examples using MIBs from the PySNMP documentation show only the usage for SNMP GET operations and are not applicable here.
Has someone tried this before and can help me?
Thanks!
If your goal is to resolve raw variable-bindings you receive into human-friendly form, then you need to process those variable-bindings through the MIB browser object.
You are right, that's exactly the same operation that command generator frequently performs in the examples.
from pysnmp.smi import builder, view, compiler, rfc1902
# Assemble MIB browser
mibBuilder = builder.MibBuilder()
mibViewController = view.MibViewController(mibBuilder)
compiler.addMibCompiler(
mibBuilder, sources=['file:///usr/share/snmp/mibs',
'http://mibs.snmplabs.com/asn1/#mib#'])
# Pre-load MIB modules that define objects we receive in TRAPs
mibBuilder.loadModules('SNMPv2-MIB', 'SNMP-COMMUNITY-MIB')
# This is what we would get in a TRAP PDU
varBinds = [
('1.3.6.1.2.1.1.3.0', 12345),
('1.3.6.1.6.3.1.1.4.1.0', '1.3.6.1.6.3.1.1.5.2'),
('1.3.6.1.6.3.18.1.3.0', '0.0.0.0'),
('1.3.6.1.6.3.18.1.4.0', ''),
('1.3.6.1.6.3.1.1.4.3.0', '1.3.6.1.4.1.20408.4.1.1.2'),
('1.3.6.1.2.1.1.1.0', 'my system')
]
# Pass raw var-binds through MIB browser
varBinds = [
rfc1902.ObjectType(rfc1902.ObjectIdentity(x[0]), x[1]).resolveWithMib(mibViewController)
for x in varBinds
]
for varBind in varBinds:
print(varBind.prettyPrint())
I try to get status from my printer using SNMP protocol
The problem is, I've never used the SNMP and I have trouble understanding how can I get my status like ( PAPER OUT, RIBBON OUT, etc... ).
I configured my printer to enable the SNMP protocol using the community name "public"
I presume SNMP messages are sent on the port 161
I'm using Pysnmp because I want to integrate the python script in my program to listen to my printer and display status if there is a problem with the printer.
For now I've tried this code :
import socket
import random
from struct import pack, unpack
from datetime import datetime as dt
from pysnmp.entity.rfc3413.oneliner import cmdgen
from pysnmp.proto.rfc1902 import Integer, IpAddress, OctetString
ip = '172.20.0.229'
community = 'public'
value = (1,3,6,1,2,1,25,3,5,1,2)
generator = cmdgen.CommandGenerator()
comm_data = cmdgen.CommunityData('server', community, 1) # 1 means version SNMP v2c
transport = cmdgen.UdpTransportTarget((ip, 161))
real_fun = getattr(generator, 'getCmd')
res = (errorIndication, errorStatus, errorIndex, varBinds) \
= real_fun(comm_data, transport, value)
if not errorIndication is None or errorStatus is True:
print "Error: %s %s %s %s" % res
else:
print "%s" % varBinds
The IP address is the IP of my printer
The problem is the OID: I don't know what to put in the OID field because I have trouble understanding how does OID work.
I found this page but I'm not sure it fits with all printers ==> click here
You need your printer specific MIB file in common case. E.g., printer in my office seems to be not support both oids by your link. Also you can use snmpwalk to get available oids and values on your printer and if you somehow understand which values you need, you can use it for specific instance of your printer.
I have been trying to implement code that loads my device MIBS and walks through all the OIDS. In this one case when I try to load the OID for snmp 1.3.6.1.2.1.11 smi throws an exception when trying to load a specific OID. The previous OID works successfully: '.1.3.6.1.2.1.11.29.0' but this one generates the error message '.1.3.6.1.2.1.11.30.0'
The exception is:
File "/opt/anaconda/lib/python2.7/site-packages/pysnmp/smi/rfc1902.py", line 859, in resolveWithMib
raise SmiError('MIB object %r having type %r failed to cast value %r: %s' % (self.args[0].prettyPrint(), self.__args[0].getMibNode().getSyntax().__class.name, self.__args[1], sys.exc_info()[1]))
;SmiError: MIB object 'SNMPv2-MIB::snmpEnableAuthenTraps.0' having type 'Integer32' failed to cast value Integer32(808466736): ConstraintsIntersection(ConstraintsIntersection(ConstraintsIntersection(), ValueRangeConstraint(-2147483648, 2147483647)), SingleValueConstraint(1, 2)) failed at: "SingleValueConstraint(1, 2) failed at: "808466736"" at Integer32
Here is sample code that demonstrates the error. You will need to modify the DEVICE_IP. It is assuming that you are running SNMP v1 and against community 'public. It is running pysnmp version 4.3.2
from pysnmp.entity.rfc3413.oneliner import cmdgen
from pysnmp.smi.rfc1902 import ObjectIdentity
DEVICE_IP = 'localhost'
def get_oid(oid):
"""
Requires a valid oid as input and retrieves the given OID
"""
snmp_target = (DEVICE_IP, 161)
cmdGen = cmdgen.CommandGenerator()
result = None
errorIndication, errorStatus, errorIndex, varBindTable = cmdGen.nextCmd(
cmdgen.CommunityData('public', mpModel=0),
cmdgen.UdpTransportTarget(snmp_target),
ObjectIdentity(oid, last=True),
lexicographicMode=False
)
if errorIndication:
print(errorIndication)
else:
for varBindTableRow in varBindTable:
for name, val in varBindTableRow:
try:
result = str(val)
except:
raise
return result
# Does not Throw Error
print get_oid('.1.3.6.1.2.1.11.29.0')
# Throws Error
print get_oid('.1.3.6.1.2.1.11.30.0')
Your SNMP agent responded with 1.3.6.1.2.1.11.30.0=808466736 while OID 1.3.6.1.2.1.11.30.0 identifies MIB object snmpEnableAuthenTraps of type INTEGER with only two values permitted: 1 and 2.
Here is formal definition from SNMPv2-MIB:
snmpEnableAuthenTraps OBJECT-TYPE
SYNTAX INTEGER { enabled(1), disabled(2) }
...
So this time pysnmp seems to do the right thing - it shields you from the value that makes no sense. Root cause of this problem is the SNMP agent that sends malformed values for MIB objects.
Im reitryng to get some kids from some network switch and for that im using a purepyton library called pysnmp. its installed w/o problems.
Used a sample code that works.
from pysnmp.entity.rfc3413.oneliner import cmdgen
cmdGen = cmdgen.CommandGenerator()
datos = []
ip = 'theipaddress'
comunidad_snmp = 'thecomunityv2c'
errorIndication, errorStatus, errorIndex, varBinds = cmdGen.getCmd(
cmdgen.CommunityData(comunidad_snmp),
cmdgen.UdpTransportTarget((ip, 161)),
'.1.3.6.1.2.1.1.1.0', # sysDescr.0
lookupNames=True, lookupValues=True
)
if errorIndication:
print(errorIndication)
elif errorStatus:
print(errorStatus)
else:
for name, val in varBinds:
datos.append({'nombre': name.prettyPrint(), 'valor': val.prettyPrint()})
print datos
our problem is that if I copy this code(as is) inside any view the result its always
"No SNMP response received before timeout"
is there something we need to add for this to work as expected?.
the environment is cents 6
Could it be that your SNMP/UDP queries from Django host get filtered while your command-line tests do not?
Digging deeper: your code invokes pysnmp with default, asyncore-based transport. If Django (or some of its components) somehow uses asyncore in a non-cooperative way, pysnmp/django systems may somehow interfere... A way to avoid such interference would be use your own map of pysnmp I/O socket objects like this:
...
from pysnmp.carrier.asynsock.dispatch import AsynsockDispatcher
cmdGen.snmpEngine.registerTransportDispatcher(AsynsockDispatcher())
mySockMap = {}
cmdGen.snmpEngine.transportDispatcher.setSocketMap(mySockMap)
...
Another idea is to enable pysnmp debugging to see what's going on there:
import sys
from pysnmp import debug
debug.setLogger(debug.Debug('all', printer=sys.stderr.write))
There are other, less verbose pysnmp debugging flags (see pysnmp.debug).
I am new in using PySNMP module in Python. According to this user manual and this manual, the following python scripts perform similar things like the net-snmp command:
net-snmp v1 command:
snmpget -v1 -c public -ObentU 195.218.195.228 1.3.6.1.2.1.1.1.0
Python v1 script:
from twisted.internet import reactor, defer
from pysnmp.entity import engine, config
from pysnmp.entity.rfc3413.twisted import cmdgen
from pysnmp.carrier.twisted import dispatch
from pysnmp.carrier.twisted.dgram import udp
# Create SNMP engine instance
snmpEngine = engine.SnmpEngine()
# Instantiate and register Twisted dispatcher at SNMP engine
snmpEngine.registerTransportDispatcher(dispatch.TwistedDispatcher())
#
# SNMPv1 setup
#
# SecurityName <-> CommunityName mapping
config.addV1System(snmpEngine, 'my-area', 'public')
# Specify security settings per SecurityName (SNMPv1 - 0, SNMPv2c - 1)
config.addTargetParams(snmpEngine, 'my-creds', 'my-area', 'noAuthNoPriv', 0)
#
# Setup transport endpoint and bind it with security settings yielding
# a target name
#
# UDP/IPv4
config.addSocketTransport(
snmpEngine,
udp.domainName,
udp.UdpTwistedTransport().openClientMode()
)
config.addTargetAddr(
snmpEngine, 'my-router',
udp.domainName, ('195.218.195.228', 161),
'my-creds'
)
# Error/response receiver
def cbFun(cbCtx):
(errorIndication, errorStatus, errorIndex, varBinds) = cbCtx
if errorIndication:
print(errorIndication)
# SNMPv1 response may contain noSuchName error *and* SNMPv2c exception,
# so we ignore noSuchName error here
elif errorStatus and errorStatus != 2:
print('%s at %s' % (
errorStatus.prettyPrint(),
errorIndex and varBinds[int(errorIndex)-1][0] or '?'
)
)
else:
for oid, val in varBinds:
print('%s = %s' % (oid.prettyPrint(), val.prettyPrint()))
reactor.stop()
# Prepare request to be sent yielding Twisted deferred object
df = cmdgen.GetCommandGenerator().sendReq(
snmpEngine,
'my-router',
( ('1.3.6.1.2.1.1.1.0', None), ('1.3.6.1.2.1.1.2.0', None) ),
)
# Register error/response receiver function at deferred
df.addCallback(cbFun)
# Run Twisted main loop
reactor.run()
net-snmp v3 command:
snmpget -v3 -l authPriv -u usr-sha-aes -a SHA -A authkey1 -x AES -X privkey1 -ObentU 195.218.195.228:161 1.3.6.1.2.1.1.1.0
Python v3 script:
from twisted.internet import reactor, defer
from pysnmp.entity import engine, config
from pysnmp.entity.rfc3413.twisted import cmdgen
from pysnmp.carrier.twisted import dispatch
from pysnmp.carrier.twisted.dgram import udp
# Create SNMP engine instance
snmpEngine = engine.SnmpEngine()
# Instantiate and register Twisted dispatcher at SNMP engine
snmpEngine.registerTransportDispatcher(dispatch.TwistedDispatcher())
#
# SNMPv3/USM setup
#
# user: usr-sha-aes, auth: SHA, priv AES
config.addV3User(
snmpEngine, 'usr-sha-aes',
config.usmHMACSHAAuthProtocol, 'authkey1',
config.usmAesCfb128Protocol, 'privkey1'
)
config.addTargetParams(snmpEngine, 'my-creds', 'usr-sha-aes', 'authPriv')
#
# Setup transport endpoint and bind it with security settings yielding
# a target name
#
# UDP/IPv4
config.addSocketTransport(
snmpEngine,
udp.domainName,
udp.UdpTwistedTransport().openClientMode()
)
config.addTargetAddr(
snmpEngine, 'my-router',
udp.domainName, ('195.218.195.228', 161),
'my-creds'
)
# Error/response receiver
def cbFun(cbCtx):
(errorIndication, errorStatus, errorIndex, varBinds) = cbCtx
if errorIndication:
print(errorIndication)
elif errorStatus:
print('%s at %s' % (
errorStatus.prettyPrint(),
errorIndex and varBinds[int(errorIndex)-1][0] or '?'
)
)
else:
for oid, val in varBinds:
print('%s = %s' % (oid.prettyPrint(), val.prettyPrint()))
reactor.stop()
# Prepare request to be sent yielding Twisted deferred object
df = cmdgen.GetCommandGenerator().sendReq(
snmpEngine,
'my-router',
( ('1.3.6.1.2.1.1.1.0', None), ),
)
# Register error/response receiver function at deferred
df.addCallback(cbFun)
# Run Twisted main loop
reactor.run()
In the above net-snmp commands, you can see that there is no 'my-creds', 'my-area', and 'my-router' parameters. However, these parameters are used in the Python scripts.
May I know what is 'my-creds', 'my-area', and 'my-router' in these Python PySNMP scripts?
In SNMP (not just pysnmp), system configuration is scattered across several 'SNMP tables'. They are defined in their respective MIBs and their rows can be logically linked one with the other by columnar names.
In the end you can refer to all SNMP configuration details for a particular SNMP peer via a single ID. Also, you can re-use common parts of SNMP configuration for multiple distinct peers.
In most pysnmp scripts you can spot the following tables and their relations:
securityName + securityLevel + snmpMessageProcessingModel (3) -> snmpTargetParameters (see SNMP-TARGET-MIB::snmpTargetParams)
securityName + communityName + snmpMessageVersion (1|2c) -> snmpTargetParameters (see SNMP-COMMUNITY-MIB::snmpCommunity)
snmpTargetParameters + targetAddress + timeout + retries -> snmpTarget (see SNMP-TARGET-MIB::snmpTargetAddr)
So snmpTarget (e.g. 'my-router') is the top-level ID that can be referred to when requesting SNMP application (like Command Generator) to send SNMP request to specific peer via specific SNMP version and with specific credentials.
One of the features of this configuration model (for at least for SNMP Agent situation) is that it can be managed remotely through SNMP.