1""" 2Multiple SNMP engines 3+++++++++++++++++++++ 4 5Send multiple SNMP GET requests to multiple peers using multiple 6independend SNMP engines. Deal with peers asynchronously. SNMP options 7are: 8 9* with SNMPv1, community 'public' and 10 with SNMPv2c, community 'public' and 11 with SNMPv3, user 'usr-md5-des', MD5 auth and DES privacy 12* over IPv4/UDP and 13 over IPv6/UDP 14* to an Agent at demo.snmplabs.com:161 and 15 to an Agent at [::1]:161 16* for instances of SNMPv2-MIB::sysDescr.0 and 17 SNMPv2-MIB::sysLocation.0 MIB objects 18 19Within this script we have a single asynchronous TransportDispatcher 20and a single UDP-based transport serving two independent SNMP engines. 21We use a single instance of AsyncCommandGenerator with each of 22SNMP Engines to comunicate GET command request to remote systems. 23 24When we receive a [response] message from remote system we use 25a custom message router to choose what of the two SNMP engines 26data packet should be handed over. The selection criteria we 27employ here is based on peer's UDP port number. Other selection 28criterias are also possible. 29 30"""# 31from pysnmp.hlapi.asyncore import * 32from pysnmp.carrier.asyncore.dispatch import AsyncoreDispatcher 33 34# List of targets in the following format: 35# ( ( authData, transportTarget, varNames ), ... ) 36targets = ( 37 # 1-st target (SNMPv1 over IPv4/UDP) 38 (CommunityData('public', mpModel=0), 39 UdpTransportTarget(('demo.snmplabs.com', 161)), 40 (ObjectType(ObjectIdentity('SNMPv2-MIB', 'sysDescr', 0)), 41 ObjectType(ObjectIdentity('SNMPv2-MIB', 'sysLocation', 0)))), 42 # 2-nd target (SNMPv2c over IPv4/UDP) 43 (CommunityData('public'), 44 UdpTransportTarget(('demo.snmplabs.com', 1161)), 45 (ObjectType(ObjectIdentity('SNMPv2-MIB', 'sysDescr', 0)), 46 ObjectType(ObjectIdentity('SNMPv2-MIB', 'sysLocation', 0)))), 47 # 3-nd target (SNMPv3 over IPv4/UDP) 48 (UsmUserData('usr-md5-des', 'authkey1', 'privkey1'), 49 UdpTransportTarget(('demo.snmplabs.com', 2161)), 50 (ObjectType(ObjectIdentity('SNMPv2-MIB', 'sysDescr', 0)), 51 ObjectType(ObjectIdentity('SNMPv2-MIB', 'sysLocation', 0)))) 52 # N-th target 53 # ... 54) 55 56 57# Wait for responses or errors 58# noinspection PyUnusedLocal,PyUnusedLocal 59def cbFun(snmpEngine, sendRequestHandle, errorIndication, 60 errorStatus, errorIndex, varBinds, cbCtx): 61 (snmpEngine, authData, transportTarget) = cbCtx 62 print('snmpEngine %s: %s via %s' % (snmpEngine.snmpEngineID.prettyPrint(), authData, transportTarget)) 63 if errorIndication: 64 print(errorIndication) 65 return True 66 elif errorStatus: 67 print('%s at %s' % (errorStatus.prettyPrint(), 68 errorIndex and varBinds[int(errorIndex) - 1][0] or '?')) 69 return True 70 else: 71 for varBind in varBinds: 72 print(' = '.join([x.prettyPrint() for x in varBind])) 73 74 75# Instantiate the single transport dispatcher object 76transportDispatcher = AsyncoreDispatcher() 77 78# Setup a custom data routing function to select snmpEngine by transportDomain 79transportDispatcher.registerRoutingCbFun( 80 lambda td, ta, d: ta[1] % 3 and 'A' or 'B' 81) 82 83snmpEngineA = SnmpEngine() 84snmpEngineA.registerTransportDispatcher(transportDispatcher, 'A') 85 86snmpEngineB = SnmpEngine() 87snmpEngineB.registerTransportDispatcher(transportDispatcher, 'B') 88 89for authData, transportTarget, varBinds in targets: 90 snmpEngine = transportTarget.getTransportInfo()[1][1] % 3 and \ 91 snmpEngineA or snmpEngineB 92 getCmd(snmpEngine, authData, transportTarget, ContextData(), *varBinds, 93 **dict(cbFun=cbFun, cbCtx=(snmpEngine, authData, transportTarget))) 94 95transportDispatcher.runDispatcher() 96