Advanced Command Generator
**************************


Walk multiple Agents at once
============================

Iterate over MIBs of multiple SNMP Agents asynchronously using the
following options:

* with SNMPv1, community 'public' and with SNMPv2c, community 'public'
  and with SNMPv3, user 'usr-md5-des', MD5 auth and DES privacy

* over IPv4/UDP and over IPv6/UDP

* to an Agent at demo.snmplabs.com:161 and to an Agent at [::1]:161

* pull variables till EOM

   from pysnmp.hlapi.asyncore import *

   # List of targets in the followin format:
   # ( ( authData, transportTarget, varNames ), ... )
   targets = (
       # 1-st target (SNMPv1 over IPv4/UDP)
       (CommunityData('public', mpModel=0),
        UdpTransportTarget(('demo.snmplabs.com', 161)),
        (ObjectType(ObjectIdentity('1.3.6.1.2.1')),
         ObjectType(ObjectIdentity('1.3.6.1.3.1')))),
       # 2-nd target (SNMPv2c over IPv4/UDP)
       (CommunityData('public'),
        UdpTransportTarget(('demo.snmplabs.com', 161)),
        (ObjectType(ObjectIdentity('1.3.6.1.4.1')),)),
       # 3-nd target (SNMPv3 over IPv4/UDP)
       (UsmUserData('usr-md5-des', 'authkey1', 'privkey1'),
        UdpTransportTarget(('demo.snmplabs.com', 161)),
        (ObjectType(ObjectIdentity('SNMPv2-MIB', 'system')),)),
       # 4-th target (SNMPv3 over IPv6/UDP)
       (UsmUserData('usr-md5-none', 'authkey1'),
        Udp6TransportTarget(('::1', 161)),
        (ObjectType(ObjectIdentity('IF-MIB', 'ifTable')),))
       # N-th target
       # ...
   )


   # Wait for responses or errors, submit GETNEXT requests for further OIDs
   # noinspection PyUnusedLocal,PyUnusedLocal
   def cbFun(snmpEngine, sendRequestHandle, errorIndication,
             errorStatus, errorIndex, varBindTable, cbCtx):
       (authData, transportTarget) = cbCtx
       print('%s via %s' % (authData, transportTarget))
       if errorIndication:
           print(errorIndication)
           return
       elif errorStatus:
           print('%s at %s' % (errorStatus.prettyPrint(),
                               errorIndex and varBindTable[-1][int(errorIndex) - 1][0] or '?'))
           return
       else:
           for varBindRow in varBindTable:
               for varBind in varBindRow:
                   print(' = '.join([x.prettyPrint() for x in varBind]))

           return True  # continue table retrieval


   snmpEngine = SnmpEngine()

   # Submit initial GETNEXT requests and wait for responses
   for authData, transportTarget, varBinds in targets:
       nextCmd(snmpEngine, authData, transportTarget, ContextData(),
               *varBinds, **dict(cbFun=cbFun, cbCtx=(authData, transportTarget)))

   snmpEngine.transportDispatcher.runDispatcher()

"Download" script.


Multiple SNMP engines
=====================

Send multiple SNMP GET requests to multiple peers using multiple
independend SNMP engines. Deal with peers asynchronously. SNMP options
are:

* with SNMPv1, community 'public' and with SNMPv2c, community 'public'
  and with SNMPv3, user 'usr-md5-des', MD5 auth and DES privacy

* over IPv4/UDP and over IPv6/UDP

* to an Agent at demo.snmplabs.com:161 and to an Agent at [::1]:161

* for instances of SNMPv2-MIB::sysDescr.0 and
  SNMPv2-MIB::sysLocation.0 MIB objects

Within this script we have a single asynchronous TransportDispatcher
and a single UDP-based transport serving two independent SNMP engines.
We use a single instance of AsyncCommandGenerator with each of SNMP
Engines to comunicate GET command request to remote systems.

When we receive a [response] message from remote system we use a
custom message router to choose what of the two SNMP engines data
packet should be handed over. The selection criteria we employ here is
based on peer's UDP port number. Other selection criterias are also
possible.

   from pysnmp.hlapi.asyncore import *
   from pysnmp.carrier.asyncore.dispatch import AsyncoreDispatcher

   # List of targets in the following format:
   # ( ( authData, transportTarget, varNames ), ... )
   targets = (
       # 1-st target (SNMPv1 over IPv4/UDP)
       (CommunityData('public', mpModel=0),
        UdpTransportTarget(('demo.snmplabs.com', 161)),
        (ObjectType(ObjectIdentity('SNMPv2-MIB', 'sysDescr', 0)),
         ObjectType(ObjectIdentity('SNMPv2-MIB', 'sysLocation', 0)))),
       # 2-nd target (SNMPv2c over IPv4/UDP)
       (CommunityData('public'),
        UdpTransportTarget(('demo.snmplabs.com', 1161)),
        (ObjectType(ObjectIdentity('SNMPv2-MIB', 'sysDescr', 0)),
         ObjectType(ObjectIdentity('SNMPv2-MIB', 'sysLocation', 0)))),
       # 3-nd target (SNMPv3 over IPv4/UDP)
       (UsmUserData('usr-md5-des', 'authkey1', 'privkey1'),
        UdpTransportTarget(('demo.snmplabs.com', 2161)),
        (ObjectType(ObjectIdentity('SNMPv2-MIB', 'sysDescr', 0)),
         ObjectType(ObjectIdentity('SNMPv2-MIB', 'sysLocation', 0))))
       # N-th target
       # ...
   )


   # Wait for responses or errors
   # noinspection PyUnusedLocal,PyUnusedLocal
   def cbFun(snmpEngine, sendRequestHandle, errorIndication,
             errorStatus, errorIndex, varBinds, cbCtx):
       (snmpEngine, authData, transportTarget) = cbCtx
       print('snmpEngine %s: %s via %s' % (snmpEngine.snmpEngineID.prettyPrint(), authData, transportTarget))
       if errorIndication:
           print(errorIndication)
           return True
       elif errorStatus:
           print('%s at %s' % (errorStatus.prettyPrint(),
                               errorIndex and varBinds[int(errorIndex) - 1][0] or '?'))
           return True
       else:
           for varBind in varBinds:
               print(' = '.join([x.prettyPrint() for x in varBind]))


   # Instantiate the single transport dispatcher object
   transportDispatcher = AsyncoreDispatcher()

   # Setup a custom data routing function to select snmpEngine by transportDomain
   transportDispatcher.registerRoutingCbFun(
       lambda td, ta, d: ta[1] % 3 and 'A' or 'B'
   )

   snmpEngineA = SnmpEngine()
   snmpEngineA.registerTransportDispatcher(transportDispatcher, 'A')

   snmpEngineB = SnmpEngine()
   snmpEngineB.registerTransportDispatcher(transportDispatcher, 'B')

   for authData, transportTarget, varBinds in targets:
       snmpEngine = transportTarget.getTransportInfo()[1][1] % 3 and \
                    snmpEngineA or snmpEngineB
       getCmd(snmpEngine, authData, transportTarget, ContextData(), *varBinds,
              **dict(cbFun=cbFun, cbCtx=(snmpEngine, authData, transportTarget)))

   transportDispatcher.runDispatcher()

"Download" script.


Multiple concurrent queries
===========================

Send a bunch of different SNMP GET requests to different peers all at
once, wait for responses asynchronously:

* with SNMPv1, community 'public' and with SNMPv2c, community 'public'
  and with SNMPv3, user 'usr-md5-des', MD5 auth and DES privacy

* over IPv4/UDP and over IPv6/UDP

* to an Agent at demo.snmplabs.com:161 and to an Agent at [::1]:161

* for instances of SNMPv2-MIB::sysDescr.0 and
  SNMPv2-MIB::sysLocation.0 MIB objects

   from pysnmp.hlapi.asyncore import *

   # List of targets in the followin format:
   # ( ( authData, transportTarget, varNames ), ... )
   targets = (
       # 1-st target (SNMPv1 over IPv4/UDP)
       (CommunityData('public', mpModel=0),
        UdpTransportTarget(('demo.snmplabs.com', 161)),
        (ObjectType(ObjectIdentity('SNMPv2-MIB', 'sysDescr', 0)),
         ObjectType(ObjectIdentity('SNMPv2-MIB', 'sysLocation', 0)))),
       # 2-nd target (SNMPv2c over IPv4/UDP)
       (CommunityData('public'),
        UdpTransportTarget(('demo.snmplabs.com', 161)),
        (ObjectType(ObjectIdentity('SNMPv2-MIB', 'sysDescr', 0)),
         ObjectType(ObjectIdentity('SNMPv2-MIB', 'sysLocation', 0)))),
       # 3-nd target (SNMPv2c over IPv4/UDP) - same community and 
       # different transport address.
       (CommunityData('public'),
        UdpTransportTarget(('localhost', 161)),
        (ObjectType(ObjectIdentity('SNMPv2-MIB', 'sysContact', 0)),
         ObjectType(ObjectIdentity('SNMPv2-MIB', 'sysName', 0)))),
       # 4-nd target (SNMPv3 over IPv4/UDP)
       (UsmUserData('usr-md5-des', 'authkey1', 'privkey1'),
        UdpTransportTarget(('demo.snmplabs.com', 161)),
        (ObjectType(ObjectIdentity('SNMPv2-MIB', 'sysDescr', 0)),
         ObjectType(ObjectIdentity('SNMPv2-MIB', 'sysLocation', 0)))),
       # 5-th target (SNMPv3 over IPv6/UDP)
       (UsmUserData('usr-md5-none', 'authkey1'),
        Udp6TransportTarget(('::1', 161)),
        (ObjectType(ObjectIdentity('SNMPv2-MIB', 'sysDescr', 0)),
         ObjectType(ObjectIdentity('SNMPv2-MIB', 'sysLocation', 0)))),
       # N-th target
       # ...
   )


   # Wait for responses or errors
   # noinspection PyUnusedLocal,PyUnusedLocal
   def cbFun(snmpEngine, sendRequestHandle, errorIndication,
             errorStatus, errorIndex, varBinds, cbCtx):
       authData, transportTarget = cbCtx
       print('%s via %s' % (authData, transportTarget))
       if errorIndication:
           print(errorIndication)
           return True
       elif errorStatus:
           print('%s at %s' % (errorStatus.prettyPrint(),
                               errorIndex and varBinds[int(errorIndex) - 1][0] or '?'))
           return True
       else:
           for varBind in varBinds:
               print(' = '.join([x.prettyPrint() for x in varBind]))


   snmpEngine = SnmpEngine()

   # Submit GET requests
   for authData, transportTarget, varNames in targets:
       getCmd(snmpEngine, authData, transportTarget, ContextData(), *varNames,
              **dict(cbFun=cbFun, cbCtx=(authData, transportTarget)))

   snmpEngine.transportDispatcher.runDispatcher()

"Download" script.

See also: library reference.
