def cbRecvFun(transportDispatcher, transportDomain, transportAddress, wholeMsg, reqPDU=reqPDU): while wholeMsg: rspMsg, wholeMsg = decoder.decode(wholeMsg, asn1Spec=pMod.Message()) rspPDU = pMod.apiMessage.getPDU(rspMsg) # Match response to request if pMod.apiPDU.getRequestID(reqPDU) == pMod.apiPDU.getRequestID( rspPDU): # Check for SNMP errors reported errorStatus = pMod.apiPDU.getErrorStatus(rspPDU) if errorStatus: print(errorStatus.prettyPrint()) else: print('INFORM message delivered, response var-binds follow') for oid, val in pMod.apiPDU.getVarBinds(rspPDU): print('%s = %s' % (oid.prettyPrint(), val.prettyPrint())) transportDispatcher.jobFinished(1) return wholeMsg
def cbRecvFun( transportDispatcher, transportDomain, transportAddress, wholeMsg, reqPDU=reqPDU, headVars=headVars, ): while wholeMsg: rspMsg, wholeMsg = decoder.decode(wholeMsg, asn1Spec=v2c.Message()) rspPDU = v2c.apiMessage.getPDU(rspMsg) # Match response to request if v2c.apiBulkPDU.getRequestID( reqPDU) == v2c.apiBulkPDU.getRequestID(rspPDU): # Format var-binds table varBindTable = v2c.apiBulkPDU.getVarBindTable(reqPDU, rspPDU) # Check for SNMP errors reported errorStatus = v2c.apiBulkPDU.getErrorStatus(rspPDU) if errorStatus and errorStatus != 2: errorIndex = v2c.apiBulkPDU.getErrorIndex(rspPDU) print("%s at %s" % ( errorStatus.prettyPrint(), errorIndex and varBindTable[int(errorIndex) - 1] or "?", )) transportDispatcher.jobFinished(1) break # Report SNMP table for tableRow in varBindTable: for name, val in tableRow: # print mib data print("from: %s, %s = %s" % (transportAddress, name.prettyPrint(), val.prettyPrint())) output_list.append( "from: %s, %s = %s\n" % (transportAddress, name.prettyPrint(), val.prettyPrint())) # Stop on EOM for _oid, val in varBindTable[-1]: if not isinstance(val, v2c.Null): break else: transportDispatcher.jobFinished(1) # Generate request for next row v2c.apiBulkPDU.setVarBinds(reqPDU, [(x, v2c.null) for x, y in varBindTable[-1]]) v2c.apiBulkPDU.setRequestID(reqPDU, v2c.getNextRequestID()) transportDispatcher.sendMessage(encoder.encode(reqMsg), transportDomain, transportAddress) return wholeMsg
def cbRecvFun(transportDispatcher, transportDomain, transportAddress, wholeMsg, reqPDU=reqPDU, headVars=headVars): while wholeMsg: rspMsg, wholeMsg = decoder.decode(wholeMsg, asn1Spec=v2c.Message()) rspPDU = v2c.apiMessage.getPDU(rspMsg) # Match response to request if v2c.apiBulkPDU.getRequestID(reqPDU) == v2c.apiBulkPDU.getRequestID( rspPDU): # Format var-binds table varBindTable = v2c.apiBulkPDU.getVarBindTable(reqPDU, rspPDU) # Check for SNMP errors reported errorStatus = v2c.apiBulkPDU.getErrorStatus(rspPDU) if errorStatus and errorStatus != 2: errorIndex = v2c.apiBulkPDU.getErrorIndex(rspPDU) print( '%s at %s' % (errorStatus.prettyPrint(), errorIndex and varBindTable[int(errorIndex) - 1] or '?')) transportDispatcher.jobFinished(1) break # Report SNMP table for tableRow in varBindTable: for name, val in tableRow: print('from: %s, %s = %s' % (transportAddress, name.prettyPrint(), val.prettyPrint())) # Stop on EOM for oid, val in varBindTable[-1]: if not isinstance(val, v2c.Null): break else: transportDispatcher.jobFinished(1) continue # Generate request for next row v2c.apiBulkPDU.setVarBinds(reqPDU, [(x, v2c.null) for x, y in varBindTable[-1]]) v2c.apiBulkPDU.setRequestID(reqPDU, v2c.getNextRequestID()) transportDispatcher.sendMessage(encoder.encode(reqMsg), transportDomain, transportAddress) global startedAt if time() - startedAt > 3: raise Exception('Request timed out') startedAt = time() return wholeMsg
def _trap_receiver_cb(transport, domain, sock, msg): if decodeMessageVersion(msg) != protoVersion2c: raise RuntimeError('Only SNMP v2c traps are supported.') req, msg = decoder.decode(msg, asn1Spec=v2c.Message()) pdu = v2c.apiMessage.getPDU(req) # ignore any non trap PDUs if not pdu.isSameTypeWith(v2c.TrapPDU()): return # Stop the receiver if the trap we are looking for was received. if trap_filter(domain, sock, pdu): transport.jobFinished(1)
| $ snmpinform -v2c -c public udp:demo.snmplabs.com 0 1.3.6.1.6.3.1.1.5.1 | $ snmpinform -v2c -c public udp6:[::1] 0 1.3.6.1.6.3.1.1.5.1 """# from time import time from pysnmp.carrier.asynsock.dispatch import AsynsockDispatcher from pysnmp.carrier.asynsock.dgram import udp, udp6 from pyasn1.codec.ber import encoder, decoder from pysnmp.proto.api import v2c as pMod # Build PDU reqPDU = pMod.InformRequestPDU() pMod.apiTrapPDU.setDefaults(reqPDU) # Build message trapMsg = pMod.Message() pMod.apiMessage.setDefaults(trapMsg) pMod.apiMessage.setCommunity(trapMsg, 'public') pMod.apiMessage.setPDU(trapMsg, reqPDU) startedAt = time() def cbTimerFun(timeNow): if timeNow - startedAt > 3: raise Exception("Request timed out") # noinspection PyUnusedLocal,PyUnusedLocal def cbRecvFun(transportDispatcher, transportDomain,
class SnmpV2cMessageProcessingModel(SnmpV1MessageProcessingModel): messageProcessingModelID = 1 # SNMPv2c _snmpMsgSpec = v2c.Message()
def SnmpwalkAsync(target_IP=None, oid=None, community='public', walk_timeout=10, mode='ipv4'): """Script to run in the remote device for snmp mib walk. This script can be copied to the remote device eg:wan and can be executed directly using python for snmp mib walk The walk can done for both ipv6 and ipv4 :param target_IP: device IP for mib query :type target_IP: string :param oid: mib query OID :type oid: string :param community: community string for mib query, defaults to public :type community: string, optional :param walk_timeout: snmp walk timeout, defaults to 10 :type walk_timeout: integer, optional :param mode: mib query mode, defaults to ipv4 :type mode: string, optional :return: mib query output :rtype: string """ # SNMP table header headVars = [v2c.ObjectIdentifier((oid))] # Build PDU reqPDU = v2c.GetBulkRequestPDU() v2c.apiBulkPDU.setDefaults(reqPDU) v2c.apiBulkPDU.setNonRepeaters(reqPDU, 0) v2c.apiBulkPDU.setMaxRepetitions(reqPDU, 25) v2c.apiBulkPDU.setVarBinds(reqPDU, [(x, v2c.null) for x in headVars]) # Build message reqMsg = v2c.Message() v2c.apiMessage.setDefaults(reqMsg) v2c.apiMessage.setCommunity(reqMsg, community) v2c.apiMessage.setPDU(reqMsg, reqPDU) startedAt = time.time() output_list = [] def cbTimerFun(timeNow): # Duration if timeNow - startedAt > walk_timeout: if walk_timeout != 0: raise Exception("Request timed out") else: if timeNow - startedAt > 30: transportDispatcher.jobFinished(1) # noinspection PyUnusedLocal def cbRecvFun(transportDispatcher, transportDomain, transportAddress, wholeMsg, reqPDU=reqPDU, headVars=headVars): while wholeMsg: rspMsg, wholeMsg = decoder.decode(wholeMsg, asn1Spec=v2c.Message()) rspPDU = v2c.apiMessage.getPDU(rspMsg) # Match response to request if v2c.apiBulkPDU.getRequestID( reqPDU) == v2c.apiBulkPDU.getRequestID(rspPDU): # Format var-binds table varBindTable = v2c.apiBulkPDU.getVarBindTable(reqPDU, rspPDU) # Check for SNMP errors reported errorStatus = v2c.apiBulkPDU.getErrorStatus(rspPDU) if errorStatus and errorStatus != 2: errorIndex = v2c.apiBulkPDU.getErrorIndex(rspPDU) print('%s at %s' % (errorStatus.prettyPrint(), errorIndex and varBindTable[int(errorIndex) - 1] or '?')) transportDispatcher.jobFinished(1) break # Report SNMP table for tableRow in varBindTable: for name, val in tableRow: # print mib data print('from: %s, %s = %s' % (transportAddress, name.prettyPrint(), val.prettyPrint())) output_list.append( 'from: %s, %s = %s\n' % (transportAddress, name.prettyPrint(), val.prettyPrint())) # Stop on EOM for oid, val in varBindTable[-1]: if not isinstance(val, v2c.Null): break else: transportDispatcher.jobFinished(1) # Generate request for next row v2c.apiBulkPDU.setVarBinds(reqPDU, [(x, v2c.null) for x, y in varBindTable[-1]]) v2c.apiBulkPDU.setRequestID(reqPDU, v2c.getNextRequestID()) transportDispatcher.sendMessage(encoder.encode(reqMsg), transportDomain, transportAddress) return wholeMsg transportDispatcher = AsyncoreDispatcher() transportDispatcher.registerRecvCbFun(cbRecvFun) transportDispatcher.registerTimerCbFun(cbTimerFun) if mode == 'ipv4': transportDispatcher.registerTransport( udp.domainName, udp.UdpSocketTransport().openClientMode()) transportDispatcher.sendMessage(encoder.encode(reqMsg), udp.domainName, (target_IP, 161)) else: transportDispatcher.registerTransport( udp6.domainName, udp6.Udp6SocketTransport().openClientMode()) transportDispatcher.sendMessage(encoder.encode(reqMsg), udp6.domainName, (target_IP, 161)) transportDispatcher.jobStarted(1) # Dispatcher will finish as job#1 counter reaches zero transportDispatcher.runDispatcher() transportDispatcher.closeDispatcher() if output_list != []: return output_list else: return
from pyasn1.codec.ber import encoder, decoder from pysnmp.proto.api import v2c from time import time # SNMP table header headVars = [v2c.ObjectIdentifier((1, 3, 6))] # Build PDU reqPDU = v2c.GetBulkRequestPDU() v2c.apiBulkPDU.setDefaults(reqPDU) v2c.apiBulkPDU.setNonRepeaters(reqPDU, 0) v2c.apiBulkPDU.setMaxRepetitions(reqPDU, 25) v2c.apiBulkPDU.setVarBinds(reqPDU, [(x, v2c.null) for x in headVars]) # Build message reqMsg = v2c.Message() v2c.apiMessage.setDefaults(reqMsg) v2c.apiMessage.setCommunity(reqMsg, 'public') v2c.apiMessage.setPDU(reqMsg, reqPDU) startedAt = time() def cbTimerFun(timeNow): if timeNow - startedAt > 3: raise Exception("Request timed out") # noinspection PyUnusedLocal def cbRecvFun(transportDispatcher, transportDomain,
def callback(self, transportDispatcher, transportDomain, transportAddress, wholeMsg, reqPDU=None, headVars=None): """ Callback function called when SNMP answer arrives """ aBP = v2c.apiBulkPDU # Get PDU if reqPDU: self.reqPDU = reqPDU # Get headVars (OID list) if headVars: self.headVars = headVars while wholeMsg: # Do some stuff to read SNMP anser self.rspMsg, wholeMsg = decoder.decode(wholeMsg, asn1Spec=v2c.Message()) self.rspPDU = v2c.apiMessage.getPDU(self.rspMsg) if aBP.getRequestID(self.reqPDU) == aBP.getRequestID(self.rspPDU): # Check for SNMP errors reported errorStatus = aBP.getErrorStatus(self.rspPDU) if errorStatus and errorStatus != 2: logger.error('[SnmpBooster] SNMP Request error 2: %s' % str(errorStatus)) self.set_exit("SNMP Request error 2: " + str(errorStatus), rc=3) return wholeMsg # Format var-binds table varBindTable = aBP.getVarBindTable(self.reqPDU, self.rspPDU) # Initialize mapping_instance dict mapping_instance = {} # Read datas from the anser for tableRow in varBindTable: # TODO: MAYBE: Check if the current 'tableRow' is in the list of the # need tables. If NOT, maybe we can jump the current 'tableRow' ?? (continue) # Read all oid in the 'tableRow' for oid, val in tableRow: # Clean the oid oid = "." + oid.prettyPrint() # Check what kind of datas we have if oid in self.oids_waiting_values: # Standard datas # Get value and save it in the result dict self.results_oid_dict[oid] = str(val) elif any([oid.startswith(m_oid + ".") for m_oid in self.mapping_oids]): # Mapping datas # TODO: Need more detail for m_oid in self.mapping_oids: if oid.startswith(m_oid + "."): instance = oid.replace(m_oid + ".", "") val = re.sub("[,:/ ]", "_", str(val)) mapping_instance[val] = instance elif oid in self.limit_oids: # get limits => What is a limit ???????????? try: self.results_limits_dict[oid] = float(val) except ValueError: logger.error('[SnmpBooster] Bad limit for ' 'oid: %s - Skipping' % str(oid)) else: # The current oid is not needed pass # IF the mapping is done, we can look for OID values if self.mapping_done: # Get all OIDS that we want datas oids = set(self.oids_waiting_values.keys() + self.limit_oids.keys()) # Get all OIDS that we have datas results_oids = set(self.results_oid_dict.keys() + self.results_limits_dict.keys()) # Get all OIDS which have not datas YET self.remaining_oids = oids - results_oids # We have to determinate which OIDs we need to ask, # to get the datas for our wanted OIDs... tableRow = [] for oid in self.remaining_oids: # For all current OIDs, we need to get the previous OID # But if in the current OID is last number is 0 # We get the parent table if int(oid.rsplit(".", 1)[1]) - 1 >= 0: # Get previous oid here tableRow.append(oid[1:].rsplit(".", 1)[0] + "." + str(int(oid[1:].rsplit(".", 1)[1]) - 1)) else: # Get parent table here tableRow.append(oid[1:].rsplit(".", 1)[0]) # We need to get more OIDs (the request ask more than 100 oids) # - From the __init__ function # => We didn't query all needed oids YET # - From "oids != results_oids" # => Some OIDs doesn't have value, so probably the table # that we queried is long (more than 100 children) if len(self.remaining_tablerow) > 0: # SNMP BULK is limited to 100 OIDs in same request if len(self.remaining_tablerow) >= 100: oids_to_check = [self.remaining_tablerow.pop() for x in xrange(99)] else: oids_to_check = self.remaining_tablerow self.remaining_tablerow = set() # Prepare request to get nest OIDs aBP.setVarBinds(self.reqPDU, [(x, v2c.null) for x in oids_to_check]) aBP.setRequestID(self.reqPDU, v2c.getNextRequestID()) transportDispatcher.sendMessage(encoder.encode(self.reqMsg), transportDomain, transportAddress) # Count the number of requests done for one host/frequency couple self.nb_next_requests = self.nb_next_requests + 1 return wholeMsg # Some oids doesn't have any value (oids != results_oids) # We make a new request to get this values if oids != results_oids and self.nb_next_requests < 5: # SNMP BULK is limited to 100 OIDs in same request if len(tableRow) >= 100: # Add missing oid to self.remaining_tablerow # This oids will be checked in a few requests # Here : "if len(self.remaining_tablerow) > 0:" self.remaining_tablerow.update(set(tableRow[99:])) tableRow = tableRow[:99] aBP.setVarBinds(self.reqPDU, [(v2c.ObjectIdentifier(x), v2c.null) for x in tableRow]) aBP.setRequestID(self.reqPDU, v2c.getNextRequestID()) transportDispatcher.sendMessage(encoder.encode(self.reqMsg), transportDomain, transportAddress) self.nb_next_requests = self.nb_next_requests + 1 return wholeMsg # LOCKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKK try: # Get OID from memcache self.obj = self.memcached.get(self.obj_key) except ValueError, e: logger.error('[SnmpBooster] Memcached error while getting: `%s' % self.obj_key) self.set_exit("Memcached error: `%s'" % self.memcached.get(self.obj_key), 3, transportDispatcher) return wholeMsg self.obj.frequences[self.check_interval].old_check_time = copy.copy(self.obj.frequences[self.check_interval].check_time) self.obj.frequences[self.check_interval].check_time = self.start_time # We have to do the mapping instance if not self.mapping_done: # TODO: need more documentation self.obj.instances = mapping_instance self.obj.map_instances(self.check_interval) s = self.obj.frequences[self.check_interval].services[self.serv_key] self.obj.frequences[self.check_interval].checking = False self.memcached.set(self.obj_key, self.obj, time=604800) if s.instance.startswith("map("): result_oids_mapping = set([".%s" % str(o).rsplit(".", 1)[0] for t in varBindTable for o, _ in t]) if not result_oids_mapping.intersection(set(self.mapping_oids.keys())): s.instance = "NOTFOUND" self.obj.frequences[self.check_interval].checking = False self.memcached.set(self.obj_key, self.obj, time=604800) logger.info("[SnmpBooster] - Instance mapping not found. " "Please check your config") self.set_exit("%s: Instance mapping not found. " "Please check your config" % s.instance_name, 3, transportDispatcher) # Stop if oid not in mappping oidS return # Mapping not finished aBP.setVarBinds(self.reqPDU, [(x, v2c.null) for x, y in varBindTable[-1]]) aBP.setRequestID(self.reqPDU, v2c.getNextRequestID()) transportDispatcher.sendMessage(encoder.encode(self.reqMsg), transportDomain, transportAddress) return wholeMsg logger.info("[SnmpBooster] - Instance mapping completed. " "Expect results at next check") self.set_exit("Instance mapping completed. " "Expect results at next check", 3, transportDispatcher) return # set Limits if not self.limits_done: self.obj.set_limits(self.check_interval, self.results_limits_dict) self.memcached.set(self.obj_key, self.obj, time=604800) # Save values self.oids_to_check = self.obj.get_oids_by_frequence(self.check_interval) for oid, value in self.results_oid_dict.items(): if value != None: self.oids_to_check[oid].raw_value = str(value) else: self.oids_to_check[oid].raw_value = None # save data self.obj.frequences[self.check_interval].checking = False self.memcached.set(self.obj_key, self.obj, time=604800) # UNLOCKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKK if time.time() - self.snmp_request_start_time > self.timeout: self.set_exit("SNMP Request timed out", 3, transportDispatcher) #return wholeMsg self.snmp_request_start_time = time.time()
self.reqPDU = v2c.GetBulkRequestPDU() v2c.apiBulkPDU.setDefaults(self.reqPDU) v2c.apiBulkPDU.setNonRepeaters(self.reqPDU, 0) v2c.apiBulkPDU.setMaxRepetitions(self.reqPDU, self.max_repetitions) # Cut SNMP request if it is too long if len(self.headVars) >= 100: self.remaining_tablerow = set(self.headVars[99:]) self.headVars = self.headVars[:99] v2c.apiBulkPDU.setVarBinds(self.reqPDU, [(v2c.ObjectIdentifier(tuple(int(i) for i in x.split("."))), v2c.null) for x in sorted(self.headVars)]) # Build message self.reqMsg = v2c.Message() v2c.apiMessage.setDefaults(self.reqMsg) v2c.apiMessage.setCommunity(self.reqMsg, self.community) v2c.apiMessage.setPDU(self.reqMsg, self.reqPDU) # Save the time when snmp request start self.snmp_request_start_time = time.time() # Prepare SNMP Request transportDispatcher = AsynsockDispatcher() transportDispatcher.registerTransport(udp.domainName, udp.UdpSocketTransport().openClientMode()) transportDispatcher.registerRecvCbFun(self.callback) transportDispatcher.registerTimerCbFun(self.callback_timer) transportDispatcher.sendMessage(encoder.encode(self.reqMsg), udp.domainName,