def walk_v1(self, oid): def cbFun(sendRequestHandle, errorIndication, errorStatus, errorIndex, varBinds, cbCtx): cbCtx['errorIndication'] = errorIndication cbCtx['errorStatus'] = errorStatus cbCtx['errorIndex'] = errorIndex for varBindRow in varBinds: inTableFlag = 0 for oi, val in varBindRow: if val is None or not oid.isPrefixOf(oi): continue inTableFlag = 1 if not inTableFlag: return # stop on end-of-table cbCtx['varBinds'].append(varBindRow) return 1 # continue walking cb = {} cb['varBinds'] = [] #self.__lock.acquire() cmdgen.NextCommandGenerator().sendReq(self.__snmp_engine, 'myRouter', ((oid, None), ), cbFun, cb) self.__snmp_engine.transportDispatcher.runDispatcher() #self.__lock.release() self.__errorIndication = cb['errorIndication'] self.__errorStatus = cb['errorStatus'] self.__errorIndex = cb['errorIndex'] self.__varBinds = cb['varBinds'] if self.getErrorStatus(): log.critical("Error in snmp walk (v1) " + str(self.showError())) return self.__varBinds
def nextCmd(self, authData, transportTarget, varNames, cbInfo, lookupNames=False, lookupValues=False, contextEngineId=None, contextName=null): def __cbFun(sendRequestHandle, errorIndication, errorStatus, errorIndex, varBindTable, cbCtx): lookupNames, lookupValues, cbFun, cbCtx = cbCtx return cbFun(sendRequestHandle, errorIndication, errorStatus, errorIndex, [ self.unmakeVarBinds(varBindTableRow, lookupNames, lookupValues) for varBindTableRow in varBindTable ], cbCtx) # for backward compatibility if contextName is null and authData.contextName: contextName = authData.contextName (cbFun, cbCtx) = cbInfo addrName, paramsName = self.cfgCmdGen(authData, transportTarget) return cmdgen.NextCommandGenerator().sendReq( self.snmpEngine, addrName, self.makeReadVarBinds(varNames), __cbFun, (lookupNames, lookupValues, cbFun, cbCtx), contextEngineId, contextName)
def nextCmd(self, snmpEngine, authData, transportTarget, varNames, cbInfo, lookupNames=False, lookupValues=False, contextEngineId=None, contextName=null): def __cbFun(sendRequestHandle, errorIndication, errorStatus, errorIndex, varBindTable, cbCtx): lookupNames, lookupValues, cbFun, cbCtx = cbCtx return cbFun( sendRequestHandle, errorIndication, errorStatus, errorIndex, [ self.unmakeVarBinds(snmpEngine, varBindTableRow, lookupNames, lookupValues) for varBindTableRow in varBindTable ], cbCtx ) (cbFun, cbCtx) = cbInfo addrName, paramsName = self.cfgCmdGen( snmpEngine, authData, transportTarget ) return cmdgen.NextCommandGenerator().sendReq( snmpEngine, addrName, self.makeVarBinds(snmpEngine, [(x, self._null) for x in varNames]), __cbFun, (lookupNames, lookupValues, cbFun, cbCtx), contextEngineId, contextName )
def nextCmd(self, authData, transportTarget, varNames, cbInfo): (cbFun, cbCtx) = cbInfo addrName, paramsName = self.cfgCmdGen(authData, transportTarget) varBinds = self.makeReadVarBinds(varNames) return cmdgen.NextCommandGenerator().sendReq(self.snmpEngine, addrName, varBinds, cbFun, cbCtx, authData.contextEngineId, authData.contextName)
def walk_command(self, OID, callback=None): if not callback: callback = self.cbFun cmdgen.NextCommandGenerator().sendReq( self.snmpEngine, 'my-router', (OID, ), callback, )
def send_walk_var_binds(self, oid, cb_ctx): cmd_gen = cmdgen.NextCommandGenerator() cmd_gen.sendVarBinds( self.snmp_parameters.snmp_engine, 'tgt', self.snmp_parameters.v3_context_engine_id, self.snmp_parameters.v3_context, [(oid, None)], self.cb_fun, cb_ctx )
def snmp_getnext(config, oids, lookup_mib, ignore_nonincreasing_oid): # type: (InstanceConfig, list, bool, bool) -> Generator """Call SNMP GETNEXT on a list of oids. It will iterate on the results if it happens to be under the same prefix.""" def callback( # type: ignore snmpEngine, sendRequestHandle, errorIndication, errorStatus, errorIndex, varBindTable, cbCtx): var_bind_table = [ vbProcessor.unmakeVarBinds(snmpEngine, row, lookup_mib) for row in varBindTable ] if ignore_nonincreasing_oid and errorIndication and isinstance( errorIndication, errind.OidNotIncreasing): errorIndication = None cbCtx['error'] = errorIndication cbCtx['var_bind_table'] = var_bind_table[0] ctx = {} # type: Dict[str, Any] initial_vars = [ x[0] for x in vbProcessor.makeVarBinds(config._snmp_engine, oids) ] var_binds = oids gen = cmdgen.NextCommandGenerator() while True: gen.sendVarBinds( config._snmp_engine, config._addr_name, config._context_data.contextEngineId, config._context_data.contextName, var_binds, callback, ctx, ) config._snmp_engine.transportDispatcher.runDispatcher() _handle_error(ctx, config) var_binds = [] new_initial_vars = [] for col, var_bind in enumerate(ctx['var_bind_table']): name, val = var_bind if not isinstance(val, Null) and initial_vars[col].isPrefixOf(name): var_binds.append(var_bind) new_initial_vars.append(initial_vars[col]) yield var_bind if not var_binds: return initial_vars = new_initial_vars
def createSNMP(host, community=None): if community is None: community = "public" ip = gethostbyname(host) snmpEngine = engine.SnmpEngine() config.addV1System(snmpEngine, 'my-area', community) config.addTargetParams(snmpEngine, 'my-creds', 'my-area', 'noAuthNoPriv', 0) config.addTransport(snmpEngine, udp.domainName, udp.UdpSocketTransport().openClientMode()) config.addTargetAddr(snmpEngine, 'my-router', udp.domainName, (ip, 161), 'my-creds') cmdgen.NextCommandGenerator().sendVarBinds( snmpEngine, 'my-router', None, '', [((1, 3, 6, 1, 2, 1, 1, 0, 0), None)], getHost) snmpEngine.transportDispatcher.runDispatcher() cmdgen.NextCommandGenerator().sendVarBinds( snmpEngine, 'my-router', None, '', [((1, 3, 6, 1, 2, 1, 4, 34, 1, 3, 2, 16), None)], getAddrs) snmpEngine.transportDispatcher.runDispatcher()
def _send_walk_var_binds(self, oid, cb_fun=None): cmd_gen = cmdgen.NextCommandGenerator() if not cb_fun: cb_fun = self.cb_walk_fun cmd_gen.sendVarBinds( self._snmp_engine, "tgt", self._context_id, self._context_name, [(oid, None)], cb_fun, self.cb_ctx, )
def nextCmd(self, agent, context, host, port, *varNames): self._setup(agent, context, host, port) ## @brief call back function # @param sendRequestHandle # @param errorIndication indicates error # @param errorStatus status of error # @param errorIndex index of error # @param varBindTable table of variable bindings # @param cbCtx application state # @returns cbCtx application state def cbFun(sendRequestHandle, errorIndication, errorStatus, errorIndex, varBindTable, cbCtx): if errorIndication or errorStatus: cbCtx['errorIndication'] = errorIndication cbCtx['errorStatus'] = errorStatus cbCtx['errorIndex'] = errorIndex cbCtx['varBindTable'] = varBindTable return else: varBindTableRow = varBindTable[-1] for idx in range(len(varBindTableRow)): _, val = varBindTableRow[idx] # XXX extra rows if val is not None: continue else: cbCtx['errorIndication'] = errorIndication cbCtx['errorStatus'] = errorStatus cbCtx['errorIndex'] = errorIndex cbCtx['varBindTable'] = varBindTableRow return return 1 # continue walking cbCtx = {} varBinds = [] for varName in varNames: varBinds.append((varName, None)) cmdgen.NextCommandGenerator().sendReq(self.snmpEngine, 'myRouter', varBinds, cbFun, cbCtx) self.snmpEngine.transportDispatcher.runDispatcher() return (cbCtx['errorIndication'], cbCtx['errorStatus'], cbCtx['errorIndex'], cbCtx['varBindTable'])
def _onTabularResult(sendRequestHandle, errorIndication, errorStatus, errorIndex, varBindTable, df): """Process a (partial) tabular result""" foundRoots = {} foundNonNull = False for row in varBindTable: foundNonNull = False for (key, value) in row: if value is not None: foundNonNull = True for r in roots: if key[:len(r)] == r: tbl = result.get(r) if tbl is None: tbl = result[r] = {} tbl[key] = value foundRoots[r] = key if not foundRoots or not foundNonNull: df.callback(result) else: roots[:] = foundRoots.keys() if self.snmpVersion != '1': cmdgen.BulkCommandGenerator().sendReq( self.engine, self.targetName, 0, # nonRepeaters (count) maxRepetitions, [(r, None) for r in foundRoots.values()], # varBinds _onTabularResult, df, ) else: cmdgen.NextCommandGenerator().sendReq( self.engine, self.targetName, [(r, None) for r in foundRoots.values()], _onTabularResult, df)
def nextCmd(snmpEngine, authData, transportTarget, contextData, *varBinds, **options): """Performs SNMP GETNEXT query. Based on passed parameters, prepares SNMP GETNEXT packet (:RFC:`1905#section-4.2.2`) and schedules its transmission by :mod:`twisted` I/O framework at a later point of time. Parameters ---------- snmpEngine : :class:`~pysnmp.hlapi.SnmpEngine` Class instance representing SNMP engine. authData : :class:`~pysnmp.hlapi.CommunityData` or :class:`~pysnmp.hlapi.UsmUserData` Class instance representing SNMP credentials. transportTarget : :class:`~pysnmp.hlapi.twisted.UdpTransportTarget` or :class:`~pysnmp.hlapi.twisted.Udp6TransportTarget` Class instance representing transport type along with SNMP peer address. contextData : :class:`~pysnmp.hlapi.ContextData` Class instance representing SNMP ContextEngineId and ContextName values. \*varBinds : :class:`~pysnmp.smi.rfc1902.ObjectType` One or more class instances representing MIB variables to place into SNMP request. Other Parameters ---------------- \*\*options : Request options: * `lookupMib` - load MIB and resolve response MIB variables at the cost of slightly reduced performance. Default is `True`. * `ignoreNonIncreasingOid` - continue iteration even if response MIB variables (OIDs) are not greater then request MIB variables. Be aware that setting it to `True` may cause infinite loop between SNMP management and agent applications. Default is `False`. Returns ------- deferred : :class:`~twisted.internet.defer.Deferred` Twisted Deferred object representing work-in-progress. User is expected to attach his own `success` and `error` callback functions to the Deferred object though :meth:`~twisted.internet.defer.Deferred.addCallbacks` method. Raises ------ PySnmpError Or its derivative indicating that an error occurred while performing SNMP operation. Notes ----- User `success` callback is called with the following tuple as its first argument: * errorStatus (str) : True value indicates SNMP PDU error. * errorIndex (int) : Non-zero value refers to `varBinds[errorIndex-1]` * varBinds (tuple) : A sequence of sequences (e.g. 2-D array) of :py:class:`~pysnmp.smi.rfc1902.ObjectType` class instances representing a table of MIB variables returned in SNMP response. Inner sequences represent table rows and ordered exactly the same as `varBinds` in request. Response to GETNEXT always contain a single row. User `error` callback is called with `errorIndication` object wrapped in :class:`~twisted.python.failure.Failure` object. Examples -------- >>> from twisted.internet.task import react >>> from pysnmp.hlapi.twisted import * >>> >>> def success(args): ... (errorStatus, errorIndex, varBindTable) = args ... print(errorStatus, errorIndex, varBindTable) ... >>> def failure(errorIndication): ... print(errorIndication) ... >>> def run(reactor): ... d = nextCmd(SnmpEngine(), ... CommunityData('public'), ... UdpTransportTarget(('demo.snmplabs.com', 161)), ... ContextData(), ... ObjectType(ObjectIdentity('SNMPv2-MIB', 'system')) ... d.addCallback(success).addErrback(failure) ... return d ... >>> react(run) (0, 0, [[ObjectType(ObjectIdentity(ObjectName('1.3.6.1.2.1.1.1.0')), DisplayString('SunOS zeus.snmplabs.com 4.1.3_U1 1 sun4m'))]]) >>> """ def __cbFun(snmpEngine, sendRequestHandle, errorIndication, errorStatus, errorIndex, varBindTable, cbCtx): lookupMib, deferred = cbCtx if (options.get('ignoreNonIncreasingOid', False) and errorIndication and isinstance(errorIndication, errind.OidNotIncreasing)): errorIndication = None if errorIndication: deferred.errback(Failure(errorIndication)) else: try: varBindsUnmade = [vbProcessor.unmakeVarBinds(snmpEngine.cache, varBindTableRow, lookupMib) for varBindTableRow in varBindTable] except Exception as e: deferred.errback(Failure(e)) else: deferred.callback((errorStatus, errorIndex, varBindsUnmade)) addrName, paramsName = lcd.configure( snmpEngine, authData, transportTarget, contextData.contextName) deferred = Deferred() cmdgen.NextCommandGenerator().sendVarBinds( snmpEngine, addrName, contextData.contextEngineId, contextData.contextName, vbProcessor.makeVarBinds(snmpEngine.cache, varBinds), __cbFun, (options.get('lookupMib', True), deferred) ) return deferred
'total': 0, 'count': 0, 'errors': 0, 'iteration': 0, 'reqTime': time.time(), 'retries': continueOnErrors, 'lastOID': startOID } if getBulkFlag: cmdGen = cmdgen.BulkCommandGenerator() cmdGen.sendVarBinds(snmpEngine, 'tgt', v3ContextEngineId, v3Context, 0, getBulkRepetitions, [(startOID, None)], cbFun, cbCtx) else: cmdGen = cmdgen.NextCommandGenerator() cmdGen.sendVarBinds(snmpEngine, 'tgt', v3ContextEngineId, v3Context, [(startOID, None)], cbFun, cbCtx) log.info('Sending initial %s request for %s (stop at %s)....' % (getBulkFlag and 'GETBULK' or 'GETNEXT', startOID, stopOID or '<end-of-mib>')) t = time.time() # Python 2.4 does not support the "finally" clause exc_info = None try:
def nextCmd(snmpEngine, authData, transportTarget, contextData, *varBinds, **options): """Performs SNMP GETNEXT query. Based on passed parameters, prepares SNMP GETNEXT packet (:RFC:`1905#section-4.2.2`) and schedules its transmission by I/O framework at a later point of time. Parameters ---------- snmpEngine : :py:class:`~pysnmp.hlapi.SnmpEngine` Class instance representing SNMP engine. authData : :py:class:`~pysnmp.hlapi.CommunityData` or :py:class:`~pysnmp.hlapi.UsmUserData` Class instance representing SNMP credentials. transportTarget : :py:class:`~pysnmp.hlapi.asyncore.UdpTransportTarget` or :py:class:`~pysnmp.hlapi.asyncore.Udp6TransportTarget` Class instance representing transport type along with SNMP peer address. contextData : :py:class:`~pysnmp.hlapi.ContextData` Class instance representing SNMP ContextEngineId and ContextName values. \*varBinds : :py:class:`~pysnmp.smi.rfc1902.ObjectType` One or more class instances representing MIB variables to place into SNMP request. Other Parameters ---------------- \*\*options : Request options: * `lookupMib` - load MIB and resolve response MIB variables at the cost of slightly reduced performance. Default is `True`. * `cbFun` (callable) - user-supplied callable that is invoked to pass SNMP response data or error to user at a later point of time. Default is `None`. * `cbCtx` (object) - user-supplied object passing additional parameters to/from `cbFun`. Default is `None`. Notes ----- User-supplied `cbFun` callable must have the following call signature: * snmpEngine (:py:class:`~pysnmp.hlapi.SnmpEngine`): Class instance representing SNMP engine. * sendRequestHandle (int): Unique request identifier. Can be used for matching multiple ongoing requests with received responses. * errorIndication (str): True value indicates SNMP engine error. * errorStatus (str): True value indicates SNMP PDU error. * errorIndex (int): Non-zero value refers to `varBinds[errorIndex-1]` * varBinds (tuple): A sequence of sequences (e.g. 2-D array) of :py:class:`~pysnmp.smi.rfc1902.ObjectType` class instances representing a table of MIB variables returned in SNMP response. Inner sequences represent table rows and ordered exactly the same as `varBinds` in request. Response to GETNEXT always contain a single row. * `cbCtx` : Original user-supplied object. Returns ------- sendRequestHandle : int Unique request identifier. Can be used for matching received responses with ongoing requests. Raises ------ PySnmpError Or its derivative indicating that an error occurred while performing SNMP operation. Examples -------- >>> from pysnmp.hlapi.asyncore import * >>> def cbFun(snmpEngine, sendRequestHandle, errorIndication, errorStatus, errorIndex, varBinds, cbCtx): ... print(errorIndication, errorStatus, errorIndex, varBinds) >>> >>> snmpEngine = SnmpEngine() >>> nextCmd(snmpEngine, ... CommunityData('public'), ... UdpTransportTarget(('demo.snmplabs.com', 161)), ... ContextData(), ... ObjectType(ObjectIdentity('SNMPv2-MIB', 'system')), ... cbFun=cbFun) >>> snmpEngine.transportDispatcher.runDispatcher() (None, 0, 0, [ [ObjectType(ObjectIdentity(ObjectName('1.3.6.1.2.1.1.1.0')), DisplayString('SunOS zeus.snmplabs.com 4.1.3_U1 1 sun4m'))] ]) >>> """ def __cbFun(snmpEngine, sendRequestHandle, errorIndication, errorStatus, errorIndex, varBindTable, cbCtx): lookupMib, cbFun, cbCtx = cbCtx return cbFun(snmpEngine, sendRequestHandle, errorIndication, errorStatus, errorIndex, [ vbProcessor.unmakeVarBinds(snmpEngine.cache, varBindTableRow, lookupMib) for varBindTableRow in varBindTable ], cbCtx) addrName, paramsName = lcd.configure(snmpEngine, authData, transportTarget, contextData.contextName) return cmdgen.NextCommandGenerator().sendVarBinds( snmpEngine, addrName, contextData.contextEngineId, contextData.contextName, vbProcessor.makeVarBinds(snmpEngine.cache, varBinds), __cbFun, (options.get('lookupMib', True), options.get('cbFun'), options.get('cbCtx')))
config.addTargetAddr(snmpEngine, 'my-router', udp.domainName, ('195.218.195.228', 161), 'my-creds') # Error/response receiver def cbFun(sendRequestHandle, errorIndication, errorStatus, errorIndex, varBindTable, cbCtx): if errorIndication: print(errorIndication) return if errorStatus: print('%s at %s' % (errorStatus.prettyPrint(), errorIndex and varBindTable[-1][int(errorIndex) - 1][0] or '?')) return # stop on error for varBindRow in varBindTable: for oid, val in varBindRow: if initialOID.isPrefixOf(oid): print('%s = %s' % (oid.prettyPrint(), val.prettyPrint())) else: return False # signal dispatcher to stop return True # signal dispatcher to continue # Prepare initial request to be sent cmdgen.NextCommandGenerator().sendReq(snmpEngine, 'my-router', ((initialOID, None), ), cbFun) # Run I/O dispatcher which would send pending queries and process responses snmpEngine.transportDispatcher.runDispatcher()
('195.218.195.228', 161), 'my-creds') # Error/response receiver def cbFun(sendRequestHandle, errorIndication, errorStatus, errorIndex, varBindTable, cbCtx): if errorIndication: print(errorIndication) return # SNMPv1 response may contain noSuchName error *and* SNMPv2c exception, # so we ignore noSuchName error here if errorStatus and errorStatus != 2: print('%s at %s' % (errorStatus.prettyPrint(), errorIndex and varBindTable[-1][int(errorIndex) - 1][0] or '?')) return # stop on error for varBindRow in varBindTable: for oid, val in varBindRow: print('%s = %s' % (oid.prettyPrint(), val.prettyPrint())) return 1 # signal dispatcher to continue # Prepare initial request to be sent cmdgen.NextCommandGenerator().sendReq(snmpEngine, 'my-router', ( ((1, 3, 6, 1, 2, 1, 1), None), ((1, 3, 6, 1, 4, 1, 1), None), ), cbFun) # Run I/O dispatcher which would send pending queries and process responses snmpEngine.transportDispatcher.runDispatcher()
def getTable( self, roots, includeStart=0, recordCallback=None, retryCount=4, timeout=2.0, maxRepetitions=DEFAULT_BULK_REPETITION_SIZE, startOIDs=None, ): """Convenience method for creating and running a TableRetriever roots -- root OIDs to retrieve includeStart -- whether to include the starting OID in the set of results, by default, return the OID *after* the root oids. Note: Only implemented for v1 protocols, and likely to be dropped eventually, as it seems somewhat superfluous. recordCallback -- called for each new record discovered recordCallback( root, oid, value ) retryCount -- number of retries timeout -- initial timeout, is multipled by 1.5 on each timeout iteration. maxRepetitions -- size for each block requested from the server, i.e. how many records to download at a single time startOIDs -- optional OID markers to be used as starting point, i.e. if passed in, we retrieve the table from startOIDs to the end of the table excluding startOIDs themselves, rather than from roots to the end of the table. Will use bulk downloading when available (i.e. if we have implementation v2c, not v1). return value is a defered for a { rootOID: { oid: value } } mapping """ df = defer.Deferred() result = {} if startOIDs is None: startOIDs = roots def _onTabularResult(sendRequestHandle, errorIndication, errorStatus, errorIndex, varBindTable, df): """Process a (partial) tabular result""" foundRoots = {} foundNonNull = False for row in varBindTable: foundNonNull = False for (key, value) in row: if value is not None: foundNonNull = True for r in roots: if key[:len(r)] == r: tbl = result.get(r) if tbl is None: tbl = result[r] = {} tbl[key] = value foundRoots[r] = key if not foundRoots or not foundNonNull: df.callback(result) else: roots[:] = foundRoots.keys() if self.snmpVersion != '1': cmdgen.BulkCommandGenerator().sendReq( self.engine, self.targetName, 0, # nonRepeaters (count) maxRepetitions, [(r, None) for r in foundRoots.values()], # varBinds _onTabularResult, df, ) else: cmdgen.NextCommandGenerator().sendReq( self.engine, self.targetName, [(r, None) for r in foundRoots.values()], _onTabularResult, df) if self.snmpVersion != '1': cmdgen.BulkCommandGenerator().sendReq( self.engine, self.targetName, 0, # nonRepeaters (count) maxRepetitions, [(r, None) for r in startOIDs], # varBinds _onTabularResult, df, ) else: cmdgen.NextCommandGenerator().sendReq(self.engine, self.targetName, [(r, None) for r in startOIDs], _onTabularResult, df) return df
def nextCmd(snmpEngine, authData, transportTarget, contextData, *varBinds, **options): """Creates a generator to perform SNMP GETNEXT query. When itereator gets advanced by :py:mod:`asyncio` main loop, SNMP GETNEXT request is send (:RFC:`1905#section-4.2.2`). The iterator yields :py:class:`asyncio.Future` which gets done whenever response arrives or error occurs. Parameters ---------- snmpEngine : :py:class:`~pysnmp.hlapi.SnmpEngine` Class instance representing SNMP engine. authData : :py:class:`~pysnmp.hlapi.CommunityData` or :py:class:`~pysnmp.hlapi.UsmUserData` Class instance representing SNMP credentials. transportTarget : :py:class:`~pysnmp.hlapi.asyncio.UdpTransportTarget` or :py:class:`~pysnmp.hlapi.asyncio.Udp6TransportTarget` Class instance representing transport type along with SNMP peer address. contextData : :py:class:`~pysnmp.hlapi.ContextData` Class instance representing SNMP ContextEngineId and ContextName values. \*varBinds : :py:class:`~pysnmp.smi.rfc1902.ObjectType` One or more class instances representing MIB variables to place into SNMP request. Other Parameters ---------------- \*\*options : Request options: * `lookupMib` - load MIB and resolve response MIB variables at the cost of slightly reduced performance. Default is `True`. Yields ------ errorIndication : str True value indicates SNMP engine error. errorStatus : str True value indicates SNMP PDU error. errorIndex : int Non-zero value refers to `varBinds[errorIndex-1]` varBinds : tuple A sequence of sequences (e.g. 2-D array) of :py:class:`~pysnmp.smi.rfc1902.ObjectType` class instances representing a table of MIB variables returned in SNMP response. Inner sequences represent table rows and ordered exactly the same as `varBinds` in request. Response to GETNEXT always contain a single row. Raises ------ PySnmpError Or its derivative indicating that an error occurred while performing SNMP operation. Examples -------- >>> import asyncio >>> from pysnmp.hlapi.asyncio import * >>> >>> @asyncio.coroutine ... def run(): ... errorIndication, errorStatus, errorIndex, varBinds = yield from nextCmd( ... SnmpEngine(), ... CommunityData('public'), ... UdpTransportTarget(('demo.snmplabs.com', 161)), ... ContextData(), ... ObjectType(ObjectIdentity('SNMPv2-MIB', 'system')) ... ) ... print(errorIndication, errorStatus, errorIndex, varBinds) >>> >>> asyncio.get_event_loop().run_until_complete(run()) (None, 0, 0, [[ObjectType(ObjectIdentity('1.3.6.1.2.1.1.1.0'), DisplayString('Linux i386'))]]) >>> """ def __cbFun(snmpEngine, sendRequestHandle, errorIndication, errorStatus, errorIndex, varBindTable, cbCtx): lookupMib, future = cbCtx if future.cancelled(): return try: varBindsUnmade = [vbProcessor.unmakeVarBinds(snmpEngine, varBindTableRow, lookupMib) for varBindTableRow in varBindTable] except Exception as e: future.set_exception(e) else: future.set_result( (errorIndication, errorStatus, errorIndex, varBindsUnmade) ) addrName, paramsName = lcd.configure(snmpEngine, authData, transportTarget) future = asyncio.Future() cmdgen.NextCommandGenerator().sendVarBinds( snmpEngine, addrName, contextData.contextEngineId, contextData.contextName, vbProcessor.makeVarBinds(snmpEngine, varBinds), __cbFun, (options.get('lookupMib', True), future) ) return future
# Error/response receiver # noinspection PyUnusedLocal,PyUnusedLocal,PyUnusedLocal def cbFun(snmpEngine, sendRequestHandle, errorIndication, errorStatus, errorIndex, varBindTable, cbCtx): if errorIndication: print(errorIndication) return if errorStatus: print('%s at %s' % (errorStatus.prettyPrint(), errorIndex and varBindTable[-1][int(errorIndex) - 1][0] or '?')) return # stop on error for varBindRow in varBindTable: for oid, val in varBindRow: print('%s = %s' % (oid.prettyPrint(), val.prettyPrint())) return 1 # signal dispatcher to continue # Prepare initial request to be sent cmdgen.NextCommandGenerator().sendVarBinds( snmpEngine, 'my-router', None, '', # contextEngineId, contextName [((1, 3, 6, 1, 2, 1, 1), None), ((1, 3, 6, 1, 2, 1, 11), None)], cbFun ) # Run I/O dispatcher which would send pending queries and process responses snmpEngine.transportDispatcher.runDispatcher()
if errorStatus and errorStatus != 2: print('%s at %s' % (errorStatus.prettyPrint(), errorIndex and varBindTable[-1][int(errorIndex) - 1][0] or '?')) return # stop on error for varBindRow in varBindTable: for varBind in varBindRow: print( rfc1902.ObjectType(rfc1902.ObjectIdentity(varBind[0]), varBind[1]).resolveWithMib( mibViewController).prettyPrint()) return 1 # signal dispatcher to continue # Prepare initial request to be sent cmdgen.NextCommandGenerator().sendVarBinds( snmpEngine, 'my-router', None, '', # contextEngineId, contextName [ rfc1902.ObjectType(rfc1902.ObjectIdentity( 'iso.org.dod')).resolveWithMib(mibViewController), rfc1902.ObjectType(rfc1902.ObjectIdentity( 'IF-MIB', 'ifMIB')).resolveWithMib(mibViewController) ], cbFun) # Run I/O dispatcher which would send pending queries and process responses snmpEngine.transportDispatcher.runDispatcher()
def main(): variation_module = None parser = argparse.ArgumentParser(description=DESCRIPTION) parser.add_argument( '-v', '--version', action='version', version=utils.TITLE) parser.add_argument( '--quiet', action='store_true', help='Do not print out informational messages') parser.add_argument( '--debug', choices=pysnmp_debug.flagMap, action='append', type=str, default=[], help='Enable one or more categories of SNMP debugging.') parser.add_argument( '--debug-asn1', choices=pyasn1_debug.FLAG_MAP, action='append', type=str, default=[], help='Enable one or more categories of ASN.1 debugging.') parser.add_argument( '--logging-method', type=lambda x: x.split(':'), metavar='=<%s[:args]>]' % '|'.join(log.METHODS_MAP), default='stderr', help='Logging method.') parser.add_argument( '--log-level', choices=log.LEVELS_MAP, type=str, default='info', help='Logging level.') v1arch_group = parser.add_argument_group('SNMPv1/v2c parameters') v1arch_group.add_argument( '--protocol-version', choices=['1', '2c'], default='2c', help='SNMPv1/v2c protocol version') v1arch_group.add_argument( '--community', type=str, default='public', help='SNMP community name') v3arch_group = parser.add_argument_group('SNMPv3 parameters') v3arch_group.add_argument( '--v3-user', metavar='<STRING>', type=functools.partial(_parse_sized_string, min_length=1), help='SNMPv3 USM user (security) name') v3arch_group.add_argument( '--v3-auth-key', type=_parse_sized_string, help='SNMPv3 USM authentication key (must be > 8 chars)') v3arch_group.add_argument( '--v3-auth-proto', choices=AUTH_PROTOCOLS, type=lambda x: x.upper(), default='NONE', help='SNMPv3 USM authentication protocol') v3arch_group.add_argument( '--v3-priv-key', type=_parse_sized_string, help='SNMPv3 USM privacy (encryption) key (must be > 8 chars)') v3arch_group.add_argument( '--v3-priv-proto', choices=PRIV_PROTOCOLS, type=lambda x: x.upper(), default='NONE', help='SNMPv3 USM privacy (encryption) protocol') v3arch_group.add_argument( '--v3-context-engine-id', type=lambda x: univ.OctetString(hexValue=x[2:]), help='SNMPv3 context engine ID') v3arch_group.add_argument( '--v3-context-name', type=str, default='', help='SNMPv3 context engine ID') parser.add_argument( '--use-getbulk', action='store_true', help='Use SNMP GETBULK PDU for mass SNMP managed objects retrieval') parser.add_argument( '--getbulk-repetitions', type=int, default=25, help='Use SNMP GETBULK PDU for mass SNMP managed objects retrieval') endpoint_group = parser.add_mutually_exclusive_group(required=True) endpoint_group.add_argument( '--agent-udpv4-endpoint', type=endpoints.parse_endpoint, metavar='<[X.X.X.X]:NNNNN>', help='SNMP agent UDP/IPv4 address to pull simulation data ' 'from (name:port)') endpoint_group.add_argument( '--agent-udpv6-endpoint', type=functools.partial(endpoints.parse_endpoint, ipv6=True), metavar='<[X:X:..X]:NNNNN>', help='SNMP agent UDP/IPv6 address to pull simulation data ' 'from ([name]:port)') parser.add_argument( '--timeout', type=int, default=3, help='SNMP command response timeout (in seconds)') parser.add_argument( '--retries', type=int, default=3, help='SNMP command retries') parser.add_argument( '--start-object', metavar='<MIB::Object|OID>', type=_parse_mib_object, default=univ.ObjectIdentifier('1.3.6'), help='Drop all simulation data records prior to this OID specified ' 'as MIB object (MIB::Object) or OID (1.3.6.)') parser.add_argument( '--stop-object', metavar='<MIB::Object|OID>', type=functools.partial(_parse_mib_object, last=True), help='Drop all simulation data records after this OID specified ' 'as MIB object (MIB::Object) or OID (1.3.6.)') parser.add_argument( '--mib-source', dest='mib_sources', metavar='<URI|PATH>', action='append', type=str, default=['http://mibs.snmplabs.com/asn1/@mib@'], help='One or more URIs pointing to a collection of ASN.1 MIB files.' 'Optional "@mib@" token gets replaced with desired MIB module ' 'name during MIB search.') parser.add_argument( '--destination-record-type', choices=variation.RECORD_TYPES, default='snmprec', help='Produce simulation data with record of this type') parser.add_argument( '--output-file', metavar='<FILE>', type=str, help='SNMP simulation data file to write records to') parser.add_argument( '--continue-on-errors', metavar='<tolerance-level>', type=int, default=0, help='Keep on pulling SNMP data even if intermittent errors occur') variation_group = parser.add_argument_group( 'Simulation data variation options') parser.add_argument( '--variation-modules-dir', action='append', type=str, help='Search variation module by this path') variation_group.add_argument( '--variation-module', type=str, help='Pass gathered simulation data through this variation module') variation_group.add_argument( '--variation-module-options', type=str, default='', help='Variation module options') args = parser.parse_args() if args.debug: pysnmp_debug.setLogger(pysnmp_debug.Debug(*args.debug)) if args.debug_asn1: pyasn1_debug.setLogger(pyasn1_debug.Debug(*args.debug_asn1)) if args.output_file: ext = os.path.extsep ext += variation.RECORD_TYPES[args.destination_record_type].ext if not args.output_file.endswith(ext): args.output_file += ext record = variation.RECORD_TYPES[args.destination_record_type] args.output_file = record.open(args.output_file, 'wb') else: args.output_file = sys.stdout if sys.version_info >= (3, 0, 0): # binary mode write args.output_file = sys.stdout.buffer elif sys.platform == "win32": import msvcrt msvcrt.setmode(sys.stdout.fileno(), os.O_BINARY) # Catch missing params if args.protocol_version == '3': if not args.v3_user: sys.stderr.write('ERROR: --v3-user is missing\r\n') parser.print_usage(sys.stderr) return 1 if args.v3_priv_key and not args.v3_auth_key: sys.stderr.write('ERROR: --v3-auth-key is missing\r\n') parser.print_usage(sys.stderr) return 1 if AUTH_PROTOCOLS[args.v3_auth_proto] == config.usmNoAuthProtocol: if args.v3_auth_key: args.v3_auth_proto = 'MD5' else: if not args.v3_auth_key: sys.stderr.write('ERROR: --v3-auth-key is missing\r\n') parser.print_usage(sys.stderr) return 1 if PRIV_PROTOCOLS[args.v3_priv_proto] == config.usmNoPrivProtocol: if args.v3_priv_key: args.v3_priv_proto = 'DES' else: if not args.v3_priv_key: sys.stderr.write('ERROR: --v3-priv-key is missing\r\n') parser.print_usage(sys.stderr) return 1 proc_name = os.path.basename(sys.argv[0]) try: log.set_logger(proc_name, *args.logging_method, force=True) if args.log_level: log.set_level(args.log_level) except error.SnmpsimError as exc: sys.stderr.write('%s\r\n' % exc) parser.print_usage(sys.stderr) return 1 if args.use_getbulk and args.protocol_version == '1': log.info('will be using GETNEXT with SNMPv1!') args.use_getbulk = False # Load variation module if args.variation_module: for variation_modules_dir in ( args.variation_modules_dir or confdir.variation): log.info( 'Scanning "%s" directory for variation ' 'modules...' % variation_modules_dir) if not os.path.exists(variation_modules_dir): log.info('Directory "%s" does not exist' % variation_modules_dir) continue mod = os.path.join(variation_modules_dir, args.variation_module + '.py') if not os.path.exists(mod): log.info('Variation module "%s" not found' % mod) continue ctx = {'path': mod, 'moduleContext': {}} try: with open(mod) as fl: exec (compile(fl.read(), mod, 'exec'), ctx) except Exception as exc: log.error('Variation module "%s" execution failure: ' '%s' % (mod, exc)) return 1 variation_module = ctx log.info('Variation module "%s" loaded' % args.variation_module) break else: log.error('variation module "%s" not found' % args.variation_module) return 1 # SNMP configuration snmp_engine = engine.SnmpEngine() if args.protocol_version == '3': if args.v3_priv_key is None and args.v3_auth_key is None: secLevel = 'noAuthNoPriv' elif args.v3_priv_key is None: secLevel = 'authNoPriv' else: secLevel = 'authPriv' config.addV3User( snmp_engine, args.v3_user, AUTH_PROTOCOLS[args.v3_auth_proto], args.v3_auth_key, PRIV_PROTOCOLS[args.v3_priv_proto], args.v3_priv_key) log.info( 'SNMP version 3, Context EngineID: %s Context name: %s, SecurityName: %s, ' 'SecurityLevel: %s, Authentication key/protocol: %s/%s, Encryption ' '(privacy) key/protocol: ' '%s/%s' % ( args.v3_context_engine_id and args.v3_context_engine_id.prettyPrint() or '<default>', args.v3_context_name and args.v3_context_name.prettyPrint() or '<default>', args.v3_user, secLevel, args.v3_auth_key is None and '<NONE>' or args.v3_auth_key, args.v3_auth_proto, args.v3_priv_key is None and '<NONE>' or args.v3_priv_key, args.v3_priv_proto)) else: args.v3_user = '******' secLevel = 'noAuthNoPriv' config.addV1System(snmp_engine, args.v3_user, args.community) log.info( 'SNMP version %s, Community name: ' '%s' % (args.protocol_version, args.community)) config.addTargetParams( snmp_engine, 'pms', args.v3_user, secLevel, VERSION_MAP[args.protocol_version]) if args.agent_udpv6_endpoint: config.addSocketTransport( snmp_engine, udp6.domainName, udp6.Udp6SocketTransport().openClientMode()) config.addTargetAddr( snmp_engine, 'tgt', udp6.domainName, args.agent_udpv6_endpoint, 'pms', args.timeout * 100, args.retries) log.info('Querying UDP/IPv6 agent at [%s]:%s' % args.agent_udpv6_endpoint) elif args.agent_udpv4_endpoint: config.addSocketTransport( snmp_engine, udp.domainName, udp.UdpSocketTransport().openClientMode()) config.addTargetAddr( snmp_engine, 'tgt', udp.domainName, args.agent_udpv4_endpoint, 'pms', args.timeout * 100, args.retries) log.info('Querying UDP/IPv4 agent at %s:%s' % args.agent_udpv4_endpoint) log.info('Agent response timeout: %d secs, retries: ' '%s' % (args.timeout, args.retries)) if (isinstance(args.start_object, ObjectIdentity) or isinstance(args.stop_object, ObjectIdentity)): compiler.addMibCompiler( snmp_engine.getMibBuilder(), sources=args.mib_sources) mib_view_controller = view.MibViewController( snmp_engine.getMibBuilder()) try: if isinstance(args.start_object, ObjectIdentity): args.start_object.resolveWithMib(mib_view_controller) if isinstance(args.stop_object, ObjectIdentity): args.stop_object.resolveWithMib(mib_view_controller) except PySnmpError as exc: sys.stderr.write('ERROR: %s\r\n' % exc) return 1 # Variation module initialization if variation_module: log.info('Initializing variation module...') for x in ('init', 'record', 'shutdown'): if x not in variation_module: log.error('missing "%s" handler at variation module ' '"%s"' % (x, args.variation_module)) return 1 try: handler = variation_module['init'] handler(snmpEngine=snmp_engine, options=args.variation_module_options, mode='recording', startOID=args.start_object, stopOID=args.stop_object) except Exception as exc: log.error( 'Variation module "%s" initialization FAILED: ' '%s' % (args.variation_module, exc)) else: log.info( 'Variation module "%s" initialization OK' % args.variation_module) data_file_handler = variation.RECORD_TYPES[args.destination_record_type] # SNMP worker def cbFun(snmp_engine, send_request_handle, error_indication, error_status, error_index, var_bind_table, cb_ctx): if error_indication and not cb_ctx['retries']: cb_ctx['errors'] += 1 log.error('SNMP Engine error: %s' % error_indication) return # SNMPv1 response may contain noSuchName error *and* SNMPv2c exception, # so we ignore noSuchName error here if error_status and error_status != 2 or error_indication: log.error( 'Remote SNMP error %s' % ( error_indication or error_status.prettyPrint())) if cb_ctx['retries']: try: next_oid = var_bind_table[-1][0][0] except IndexError: next_oid = cb_ctx['lastOID'] else: log.error('Failed OID: %s' % next_oid) # fuzzy logic of walking a broken OID if len(next_oid) < 4: pass elif (args.continue_on_errors - cb_ctx['retries']) * 10 / args.continue_on_errors > 5: next_oid = next_oid[:-2] + (next_oid[-2] + 1,) elif next_oid[-1]: next_oid = next_oid[:-1] + (next_oid[-1] + 1,) else: next_oid = next_oid[:-2] + (next_oid[-2] + 1, 0) cb_ctx['retries'] -= 1 cb_ctx['lastOID'] = next_oid log.info( 'Retrying with OID %s (%s retries left)' '...' % (next_oid, cb_ctx['retries'])) # initiate another SNMP walk iteration if args.use_getbulk: cmd_gen.sendVarBinds( snmp_engine, 'tgt', args.v3_context_engine_id, args.v3_context_name, 0, args.getbulk_repetitions, [(next_oid, None)], cbFun, cb_ctx) else: cmd_gen.sendVarBinds( snmp_engine, 'tgt', args.v3_context_engine_id, args.v3_context_name, [(next_oid, None)], cbFun, cb_ctx) cb_ctx['errors'] += 1 return if args.continue_on_errors != cb_ctx['retries']: cb_ctx['retries'] += 1 if var_bind_table and var_bind_table[-1] and var_bind_table[-1][0]: cb_ctx['lastOID'] = var_bind_table[-1][0][0] stop_flag = False # Walk var-binds for var_bind_row in var_bind_table: for oid, value in var_bind_row: # EOM if args.stop_object and oid >= args.stop_object: stop_flag = True # stop on out of range condition elif (value is None or value.tagSet in (rfc1905.NoSuchObject.tagSet, rfc1905.NoSuchInstance.tagSet, rfc1905.EndOfMibView.tagSet)): stop_flag = True # remove value enumeration if value.tagSet == rfc1902.Integer32.tagSet: value = rfc1902.Integer32(value) if value.tagSet == rfc1902.Unsigned32.tagSet: value = rfc1902.Unsigned32(value) if value.tagSet == rfc1902.Bits.tagSet: value = rfc1902.OctetString(value) # Build .snmprec record context = { 'origOid': oid, 'origValue': value, 'count': cb_ctx['count'], 'total': cb_ctx['total'], 'iteration': cb_ctx['iteration'], 'reqTime': cb_ctx['reqTime'], 'args.start_object': args.start_object, 'stopOID': args.stop_object, 'stopFlag': stop_flag, 'variationModule': variation_module } try: line = data_file_handler.format(oid, value, **context) except error.MoreDataNotification as exc: cb_ctx['count'] = 0 cb_ctx['iteration'] += 1 more_data_notification = exc if 'period' in more_data_notification: log.info( '%s OIDs dumped, waiting %.2f sec(s)' '...' % (cb_ctx['total'], more_data_notification['period'])) time.sleep(more_data_notification['period']) # initiate another SNMP walk iteration if args.use_getbulk: cmd_gen.sendVarBinds( snmp_engine, 'tgt', args.v3_context_engine_id, args.v3_context_name, 0, args.getbulk_repetitions, [(args.start_object, None)], cbFun, cb_ctx) else: cmd_gen.sendVarBinds( snmp_engine, 'tgt', args.v3_context_engine_id, args.v3_context_name, [(args.start_object, None)], cbFun, cb_ctx) stop_flag = True # stop current iteration except error.NoDataNotification: pass except error.SnmpsimError as exc: log.error(exc) continue else: args.output_file.write(line) cb_ctx['count'] += 1 cb_ctx['total'] += 1 if cb_ctx['count'] % 100 == 0: log.info('OIDs dumped: %s/%s' % ( cb_ctx['iteration'], cb_ctx['count'])) # Next request time cb_ctx['reqTime'] = time.time() # Continue walking return not stop_flag cb_ctx = { 'total': 0, 'count': 0, 'errors': 0, 'iteration': 0, 'reqTime': time.time(), 'retries': args.continue_on_errors, 'lastOID': args.start_object } if args.use_getbulk: cmd_gen = cmdgen.BulkCommandGenerator() cmd_gen.sendVarBinds( snmp_engine, 'tgt', args.v3_context_engine_id, args.v3_context_name, 0, args.getbulk_repetitions, [(args.start_object, rfc1902.Null(''))], cbFun, cb_ctx) else: cmd_gen = cmdgen.NextCommandGenerator() cmd_gen.sendVarBinds( snmp_engine, 'tgt', args.v3_context_engine_id, args.v3_context_name, [(args.start_object, rfc1902.Null(''))], cbFun, cb_ctx) log.info( 'Sending initial %s request for %s (stop at %s)' '....' % (args.use_getbulk and 'GETBULK' or 'GETNEXT', args.start_object, args.stop_object or '<end-of-mib>')) started = time.time() try: snmp_engine.transportDispatcher.runDispatcher() except KeyboardInterrupt: log.info('Shutting down process...') finally: if variation_module: log.info('Shutting down variation module ' '%s...' % args.variation_module) try: handler = variation_module['shutdown'] handler(snmpEngine=snmp_engine, options=args.variation_module_options, mode='recording') except Exception as exc: log.error( 'Variation module %s shutdown FAILED: ' '%s' % (args.variation_module, exc)) else: log.info( 'Variation module %s shutdown OK' % args.variation_module) snmp_engine.transportDispatcher.closeDispatcher() started = time.time() - started cb_ctx['total'] += cb_ctx['count'] log.info( 'OIDs dumped: %s, elapsed: %.2f sec, rate: %.2f OIDs/sec, errors: ' '%d' % (cb_ctx['total'], started, started and cb_ctx['count'] // started or 0, cb_ctx['errors'])) args.output_file.flush() args.output_file.close() return cb_ctx.get('errors', 0) and 1 or 0
if syntax is None: raise error.PySnmpError( 'Value type MIB lookup failed for %s' % repr(varName)) varVal = syntax.clone(varVal) __varBinds.append((name + oid, varVal)) return cmdgen.SetCommandGenerator().sendReq(self.snmpEngine, addrName, __varBinds, cbFun, cbCtx) def asyncNextCmd(self, authData, transportTarget, varNames, (cbFun, cbCtx)): addrName, paramsName = self.cfgCmdGen(authData, transportTarget) varBinds = [] for varName in varNames: name, oid = mibvar.mibNameToOid(self.mibViewController, varName) varBinds.append((name + oid, self._null)) return cmdgen.NextCommandGenerator().sendReq(self.snmpEngine, addrName, varBinds, cbFun, cbCtx) def asyncBulkCmd(self, authData, transportTarget, nonRepeaters, maxRepetitions, varNames, (cbFun, cbCtx)): addrName, paramsName = self.cfgCmdGen(authData, transportTarget) varBinds = [] for varName in varNames: name, oid = mibvar.mibNameToOid(self.mibViewController, varName) varBinds.append((name + oid, self._null)) return cmdgen.BulkCommandGenerator().sendReq(self.snmpEngine, addrName, nonRepeaters, maxRepetitions, varBinds, cbFun, cbCtx) class CommandGenerator(AsynCommandGenerator):
def cbFun(snmpEngine, sendRequestHandle, errorIndication, errorStatus, errorIndex, varBindTable, cbCtx): if errorIndication: print(errorIndication) return if errorStatus: print('%s at %s' % (errorStatus.prettyPrint(), errorIndex and varBindTable[-1][int(errorIndex) - 1][0] or '?')) return # stop on error for varBindRow in varBindTable: for oid, val in varBindRow: if initialOID.isPrefixOf(oid): print('%s = %s' % (oid.prettyPrint(), val.prettyPrint())) else: return False # signal dispatcher to stop return True # signal dispatcher to continue # Prepare initial request to be sent cmdgen.NextCommandGenerator().sendVarBinds( snmpEngine, 'my-router', None, '', # contextEngineId, contextName [(initialOID, None)], cbFun) # Run I/O dispatcher which would send pending queries and process responses snmpEngine.transportDispatcher.runDispatcher()
# Apply configuration to SNMP entity main.generator((snmpEngine, ctx), ast) msgmod.generator((snmpEngine, ctx), ast) secmod.generator((snmpEngine, ctx), ast) mibview.generator((snmpEngine, ctx), ast) target.generator((snmpEngine, ctx), ast) pdu.readPduGenerator((snmpEngine, ctx), ast) generator((snmpEngine, ctx), ast) ctx['myHeadVars'] = [ rfc1902.ObjectName(x[0]) for x in ctx['varBinds'] ] cmdgen.NextCommandGenerator().sendVarBinds( snmpEngine, ctx['addrName'], ctx.get('contextEngineId'), ctx.get('contextName', ''), ctx['varBinds'], cbFun, ctx ) snmpEngine.transportDispatcher.runDispatcher() except KeyboardInterrupt: sys.stderr.write('Shutting down...\n') except error.PySnmpError: sys.stderr.write('Error: %s\n%s' % (sys.exc_info()[1], getUsage())) sys.exit(-1) except Exception: sys.stderr.write('Process terminated: %s\n' % sys.exc_info()[1])
class MyCmdGen(object): DEBUG = False ## @brief the constructor # @param self The object pointer # @returns None def __init__(self): self.snmpEngine = None ## @brief Set up the SNMP engine, user or system, address and socket # @param self The object pointer # @param agent Information about the agent to add # @param context context information (to add V1 system) # @param host Host address # @param port port number # @returns None # @todo support changes to context etc and make a new connection??? def _setup(self, agent, context, host, port): # TODO support changes to context etc and make a new connection??? if self.snmpEngine is None: self.snmpEngine = engine.SnmpEngine() else: return # already setup if isinstance(agent, UsmUserData): config.addV3User(self.snmpEngine, agent.securityName, agent.authProtocol, agent.authKey, agent.privProtocol, agent.privKey) config.addTargetParams(self.snmpEngine, 'myParams', agent.securityName, agent.securityLevel) else: config.addV1System(self.snmpEngine, agent, context) config.addTargetParams(self.snmpEngine, 'myParams', agent, 'noAuthNoPriv', 1) config.addTargetAddr(self.snmpEngine, 'myRouter', config.snmpUDPDomain, (host, port), 'myParams', timeout=900) config.addSocketTransport(self.snmpEngine, udp.domainName, udp.UdpSocketTransport().openClientMode()) ## @brief call for pysnmp method for traps # @param port the port number to use # @param intWaitSec time to wait # @returns the trap collection def trapCmd(self, port, intWaitSec): ## @brief print/log trap data nicely # @param varBinds variable bindings (object ID and value) # @param transportAddress IP address to identify by # @param strFname file name to open # @returns none def printItNice(varBinds, transportAddress, strFname): fHandle = open(sys.path[0] + '//' + strFname, 'a') timeMilli = datetime.datetime.now().microsecond / 1000 timeTrapTime = strftime("%Y-%b-%d %H:%M:%S.") + str(timeMilli) strPrintTxt = '\n\n%s :TRAP RECEIVED from %s: ' % ( timeTrapTime, transportAddress[0]) fHandle.write(strPrintTxt) if self.DEBUG: print strPrintTxt dicTrapData = {} dicTrapData['IP'] = transportAddress[0] for strOid, strVal in varBinds: strOid = strOid.prettyPrint() strVal = strVal.getComponent().getComponent().getComponent( ).prettyPrint() strPrintTxt = strOid + ' ' * (45 - len(strOid)) + strVal fHandle.write('\n' + strPrintTxt) if self.DEBUG: print strPrintTxt dicTrapData[strOid] = strVal dicTrapCollection[timeTrapTime] = dicTrapData fHandle.close() ## @brief function handler timer # @param timeTick time between events (reference period) # @returns none def timeFun(timeTick): timeNewTime = datetime.datetime.now() timeDelta = timeNewTime - timeReference if int(timeDelta.seconds) >= intWaitSec: transportDispatcher.jobFinished(1) transportDispatcher.closeDispatcher() ## @brief function handler for data processing # @param transportDispatcher I/O dispatcher # @param transportDomain transport domain # @param transportAddress destination address # @param wholeMsg data to process # @returns the processed data def cbFun(transportDispatcher, transportDomain, transportAddress, wholeMsg): strFname = 'Trap_' + str( transportAddress[0]) + '_' + str(port) + '.log' while wholeMsg: msgVer = int(api.decodeMessageVersion(wholeMsg)) if api.protoModules.has_key(msgVer): pMod = api.protoModules[msgVer] else: print 'Unsupported SNMP version %s' % msgVer return reqMsg, wholeMsg = decoder.decode( wholeMsg, asn1Spec=pMod.Message(), ) reqPDU = pMod.apiMessage.getPDU(reqMsg) if reqPDU.isSameTypeWith(pMod.TrapPDU()): if msgVer == api.protoVersion1: varBinds = pMod.apiTrapPDU.getVarBindList(reqPDU) else: varBinds = pMod.apiPDU.getVarBindList(reqPDU) printItNice(varBinds, transportAddress, strFname) return wholeMsg dicTrapCollection = {} timeReference = datetime.datetime.now() transportDispatcher = AsynsockDispatcher() transportDispatcher.timeout = 0.3 transportDispatcher.registerTransport( udp.domainName, udp.UdpSocketTransport().openServerMode(('0.0.0.0', port))) transportDispatcher.registerRecvCbFun(cbFun) transportDispatcher.registerTimerCbFun(timeFun) transportDispatcher.jobStarted(1) transportDispatcher.runDispatcher() return dicTrapCollection ## @brief Prepare SNMP get request # @param self The object pointer # @param agent Information about the agent to add # @param context context information # @param host Host address # @param port port number # @param *varNames names of variables # @returns data from the callback function (application state) def getCmd(self, agent, context, host, port, *varNames): self._setup(agent, context, host, port) ## @brief call back function # @param sendRequestHandle # @param errorIndication indicates error # @param errorStatus status of error # @param errorIndex index of error # @param varBinds variable bindings (sequence) # @param cbCtx application state # @returns cbCtx application state def cbFun(sendRequestHandle, errorIndication, errorStatus, errorIndex, varBinds, cbCtx): cbCtx['errorIndication'] = errorIndication cbCtx['errorStatus'] = errorStatus cbCtx['errorIndex'] = errorIndex cbCtx['varBinds'] = varBinds # Used to pass data from callback function cbCtx = {} varBinds = [] for varName in varNames: varBinds.append((varName, None)) cmdgen.GetCommandGenerator().sendReq(self.snmpEngine, 'myRouter', varBinds, cbFun, cbCtx) self.snmpEngine.transportDispatcher.runDispatcher() return (cbCtx['errorIndication'], cbCtx['errorStatus'], cbCtx['errorIndex'], cbCtx['varBinds']) ## @brief Prepare SNMP set request # @param self The object pointer # @param agent Information about the agent to add # @param context context information # @param host Host address # @param port port number # @param *varBinds variable bindings (sequence) # @returns data from the callback function (application state) def setCmd(self, agent, context, host, port, *varBinds): self._setup(agent, context, host, port) ## @brief call back function # @param sendRequestHandle # @param errorIndication indicates error # @param errorStatus status of error # @param errorIndex index of error # @param varBinds variable bindings (sequence) # @param cbCtx application state # @returns cbCtx application state def cbFun(sendRequestHandle, errorIndication, errorStatus, errorIndex, varBinds, cbCtx): cbCtx['errorIndication'] = errorIndication cbCtx['errorStatus'] = errorStatus cbCtx['errorIndex'] = errorIndex cbCtx['varBinds'] = varBinds cbCtx = {} __varBinds = [] for varName, varVal in varBinds: __varBinds.append((varName, varVal)) cmdgen.SetCommandGenerator().sendReq(self.snmpEngine, 'myRouter', __varBinds, cbFun, cbCtx) self.snmpEngine.transportDispatcher.runDispatcher() #the 'getColumn' SNMP command return (cbCtx['errorIndication'], cbCtx['errorStatus'], cbCtx['errorIndex'], cbCtx['varBinds']) ## @brief wraps the SNMP get request for columns # @param self The object pointer # @param agent Information about the agent to add # @param context context information # @param host Host address # @param port port number # @param *varNames variable names # @returns data from the callback function (application state) def getColumn(self, agent, context, host, port, *varNames): self._setup(agent, context, host, port) ## @brief call back function # @param sendRequestHandle # @param errorIndication indicates error # @param errorStatus status of error # @param errorIndex index of error # @param varBindTable table of variable bindings # @param varBindHead variable bindings table header # @param varBindTotalTable table of variable bindings total # @param cbCtx application state # @returns cbCtx application state def cbFun(sendRequestHandle, errorIndication, errorStatus, errorIndex, varBindTable, (varBindHead, varBindTotalTable, cbCtx)): if errorIndication or errorStatus: cbCtx['errorIndication'] = errorIndication cbCtx['errorStatus'] = errorStatus cbCtx['errorIndex'] = errorIndex cbCtx['varBindTable'] = varBindTotalTable return else: varBindTableRow = varBindTable[-1] for idx in range(len(varBindTableRow)): name, val = varBindTableRow[idx] # XXX extra rows if val is not None and varBindHead[idx].isPrefixOf(name): break else: cbCtx['errorIndication'] = errorIndication cbCtx['errorStatus'] = errorStatus cbCtx['errorIndex'] = errorIndex cbCtx['varBindTable'] = varBindTotalTable return varBindTotalTable.extend(varBindTable) return 1 # continue walking cbCtx = {} varBinds = [] for varName in varNames: varBinds.append((varName, None)) varBindHead = map(lambda (x): univ.ObjectIdentifier(x), varNames) cmdgen.NextCommandGenerator().sendReq(self.snmpEngine, 'myRouter', varBinds, cbFun, (varBindHead, [], cbCtx)) self.snmpEngine.transportDispatcher.runDispatcher() return (cbCtx['errorIndication'], cbCtx['errorStatus'], cbCtx['errorIndex'], cbCtx['varBindTable'])