Implementing a custom MIB in a PySNMP agent - snmp
I'm having difficulty implementing a custom MIB in a PySNMP agent.
I've started with:
http://pysnmp.sourceforge.net/examples/4.x/v3arch/agent/cmdrsp.html
created my own MIB file, used build-pysnmp-mib to make a Python module and successfully imported the symbol.
I can't see where to go next. I need to somehow mount the imported symbol on the list of served MIBs and provide an implementation. (It's currently a MIB with one read-only INTEGER property.)
The MIB file passes smilint without warnings, but I've had to manually add a missing MibScalar import to the generated module.
MIB:
TRS-MIB DEFINITIONS ::= BEGIN
internet OBJECT IDENTIFIER ::= { iso(1) org(3) dod(6) 1 }
enterprises OBJECT IDENTIFIER ::= { internet private(4) 1 }
thorcom OBJECT IDENTIFIER ::= { enterprises 27817 }
trs OBJECT IDENTIFIER ::= { thorcom 2 }
trsEntry OBJECT IDENTIFIER ::= { trs 1 }
trsDeliveryTime OBJECT-TYPE
SYNTAX Integer32
ACCESS not-accessible
STATUS mandatory
DESCRIPTION "Average message delivery time in milliseconds."
::= { trsEntry 1 }
END
Code:
#!/usr/bin/env python
# Command Responder
from pysnmp.entity import engine, config
from pysnmp.carrier.asynsock.dgram import udp
#from pysnmp.carrier.asynsock.dgram import udp6
from pysnmp.entity.rfc3413 import cmdrsp, context
from pysnmp.proto.rfc1902 import OctetString
from pysnmp.smi import builder
from pysnmp import debug
debug.setLogger(debug.Debug('all'))
# Create SNMP engine with autogenernated engineID and pre-bound
# to socket transport dispatcher
snmpEngine = engine.SnmpEngine()
# Setup UDP over IPv4 transport endpoint
config.addSocketTransport(
snmpEngine,
udp.domainName,
udp.UdpSocketTransport().openServerMode(('127.0.0.1', 161))
)
# Start of new code
mibBuilder = snmpEngine.msgAndPduDsp.mibInstrumController.mibBuilder
mibSources = mibBuilder.getMibSources() + (
builder.DirMibSource('.'),
)
mibBuilder.setMibSources(*mibSources)
# Create and put on-line my managed object
deliveryTime, = mibBuilder.importSymbols('TRS-MIB', 'trsDeliveryTime')
Integer32, = snmpEngine.msgAndPduDsp.mibInstrumController.mibBuilder.importSymbols('SNMPv2-SMI', 'Integer32')
MibScalarInstance, = mibBuilder.importSymbols('SNMPv2-SMI', 'MibScalarInstance')
class MyDeliveryTime(Integer32):
def readGet(self, name, val, idx, (acFun, acCtx)):
return name, self.syntax.clone(42)
deliveryTimeInstance = MibScalarInstance(
deliveryTime.name, (0,), deliveryTime.syntax
)
mibBuilder.exportSymbols('TRS-MIB', deliveryTimeInstance=deliveryTimeInstance) # creating MIB
# End of new code
# v1/2 setup
config.addV1System(snmpEngine, 'test-agent', 'public')
# v3 setup
config.addV3User(
snmpEngine, 'test-user',
config.usmHMACMD5AuthProtocol, 'authkey1',
config.usmDESPrivProtocol, 'privkey1'
)
# VACM setup
config.addContext(snmpEngine, '')
config.addRwUser(snmpEngine, 1, 'test-agent', 'noAuthNoPriv', (1,3,6)) # v1
config.addRwUser(snmpEngine, 2, 'test-agent', 'noAuthNoPriv', (1,3,6)) # v2c
config.addRwUser(snmpEngine, 3, 'test-user', 'authPriv', (1,3,6)) # v3
# SNMP context
snmpContext = context.SnmpContext(snmpEngine)
# Apps registration
cmdrsp.GetCommandResponder(snmpEngine, snmpContext)
cmdrsp.SetCommandResponder(snmpEngine, snmpContext)
cmdrsp.NextCommandResponder(snmpEngine, snmpContext)
cmdrsp.BulkCommandResponder(snmpEngine, snmpContext)
snmpEngine.transportDispatcher.jobStarted(1) # this job would never finish
snmpEngine.transportDispatcher.runDispatcher()
Generated and amended TRS-MIB.py:
# PySNMP SMI module. Autogenerated from smidump -f python TRS-MIB
# by libsmi2pysnmp-0.1.1 at Fri Aug 31 13:56:45 2012,
# Python version (2, 6, 6, 'final', 0)
# Imported just in case new ASN.1 types would be created
from pyasn1.type import constraint, namedval
# Imports
( Integer, ObjectIdentifier, OctetString, ) = mibBuilder.importSymbols("ASN1", "Integer", "ObjectIdentifier", "OctetString")
( Bits, Integer32, MibIdentifier, MibScalar, TimeTicks, ) = mibBuilder.importSymbols("SNMPv2-SMI", "Bits", "Integer32", "MibIdentifier", "MibScalar", "TimeTicks")
# Objects
internet = MibIdentifier((1, 3, 6, 1))
enterprises = MibIdentifier((1, 3, 6, 1, 4, 1))
thorcom = MibIdentifier((1, 3, 6, 1, 4, 1, 27817))
trs = MibIdentifier((1, 3, 6, 1, 4, 1, 27817, 2))
trsEntry = MibIdentifier((1, 3, 6, 1, 4, 1, 27817, 2, 1))
trsDeliveryTime = MibScalar((1, 3, 6, 1, 4, 1, 27817, 2, 1, 1), Integer32()).setMaxAccess("noaccess")
if mibBuilder.loadTexts: trsDeliveryTime.setDescription("Average message delivery time in milliseconds.")
# Augmentions
# Exports
# Objects
mibBuilder.exportSymbols("TRS-MIB", internet=internet, enterprises=enterprises, thorcom=thorcom, trs=trs, trsEntry=trsEntry, trsDeliveryTime=trsDeliveryTime)
Update:
I now have one error left:
$ snmpget -v2c -c public localhost .1.3.6.1.4.1.27817.2.1.1
Error in packet
Reason: noAccess
Failed object: iso.3.6.1.4.1.27817.2.1.1
The debug is:
DBG: handle_read: transportAddress ('127.0.0.1', 48191) incomingMessage '0,\x02\x01\x01\x04\x06public\xa0\x1f\x02\x04>9\xc4\xa0\x02\x01\x00\x02\x01\x000\x110\x0f\x06\x0b+\x06\x01\x04\x01\x81\xd9)\x02\x01\x01\x05\x00'
DBG: receiveMessage: msgVersion 1, msg decoded
DBG: prepareDataElements: Message:
version='version-2'
community=public
data=PDUs:
get-request=GetRequestPDU:
request-id=1043973280
error-status='noError'
error-index=0
variable-bindings=VarBindList:
VarBind:
name=1.3.6.1.4.1.27817.2.1.1
=_BindValue:
unSpecified=
DBG: value index rebuilt at (1, 3, 6, 1, 6, 3, 18, 1, 1, 1, 2), 1 entries
DBG: processIncomingMsg: looked up securityName MibScalarInstance((1, 3, 6, 1, 6, 3, 18, 1, 1, 1, 3, 116, 101, 115, 116, 45, 97, 103, 101, 110, 116), test-agent) contextEngineId MibScalarInstance((1, 3, 6, 1, 6, 3, 18, 1, 1, 1, 4, 116, 101, 115, 116, 45, 97, 103, 101, 110, 116), �O�c�#��) contextName MibScalarInstance((1, 3, 6, 1, 6, 3, 18, 1, 1, 1, 5, 116, 101, 115, 116, 45, 97, 103, 101, 110, 116), ) by communityName MibScalarInstance((1, 3, 6, 1, 6, 3, 18, 1, 1, 1, 2, 116, 101, 115, 116, 45, 97, 103, 101, 110, 116), public)
DBG: processIncomingMsg: generated maxSizeResponseScopedPDU 65379 securityStateReference 12831470
DBG: prepareDataElements: SM returned securityEngineID SnmpEngineID(hexValue='8004fb857f00163de40e2b7') securityName test-agent
DBG: prepareDataElements: cached by new stateReference 2662033
DBG: receiveMessage: MP succeded
DBG: receiveMessage: PDU GetRequestPDU:
request-id=1043973280
error-status='noError'
error-index=0
variable-bindings=VarBindList:
VarBind:
name=1.3.6.1.4.1.27817.2.1.1
=_BindValue:
unSpecified=
DBG: receiveMessage: pduType TagSet(Tag(tagClass=128, tagFormat=32, tagId=0))
DBG: processPdu: stateReference 2662033, varBinds [(ObjectName(1.3.6.1.4.1.27817.2.1.1), Null(''))]
DBG: getMibInstrum: contextName "", mibInstum <pysnmp.smi.instrum.MibInstrumController instance at 0x7fcbfe3d5e60>
DBG: flipFlopFsm: inputNameVals [(ObjectName(1.3.6.1.4.1.27817.2.1.1), Null(''))]
DBG: flipFlopFsm: state start status ok -> fsmState readTest
DBG: flipFlopFsm: fun <bound method MibTree.readTest of MibTree((1,), None)> failed NoAccessError({'name': (1, 3, 6, 1, 4, 1, 27817, 2, 1, 1), 'idx': 0}) for 1.3.6.1.4.1.27817.2.1.1=Null('')
DBG: flipFlopFsm: state readTest status err -> fsmState stop
DBG: sendRsp: stateReference 2662033, errorStatus noAccess, errorIndex 1, varBinds [(ObjectName(1.3.6.1.4.1.27817.2.1.1), Null(''))]
DBG: returnResponsePdu: PDU ResponsePDU:
request-id=1043973280
error-status='noAccess'
error-index=1
variable-bindings=VarBindList:
VarBind:
name=1.3.6.1.4.1.27817.2.1.1
=_BindValue:
unSpecified=
DBG: prepareResponseMessage: cache read msgID 1043973280 transportDomain (1, 3, 6, 1, 6, 1, 1) transportAddress ('127.0.0.1', 48191) by stateReference 2662033
DBG: prepareResponseMessage: using contextEngineId SnmpEngineID(hexValue='8004fb857f00163de40e2b7') contextName
DBG: generateResponseMsg: recovered community public by securityStateReference 12831470
DBG: generateResponseMsg: Message:
version='version-2'
community=public
data=PDUs:
response=ResponsePDU:
request-id=1043973280
error-status='noAccess'
error-index=1
variable-bindings=VarBindList:
VarBind:
name=1.3.6.1.4.1.27817.2.1.1
=_BindValue:
unSpecified=
DBG: returnResponsePdu: MP suceeded
DBG: receiveMessage: processPdu succeeded
DBG: handle_write: transportAddress ('127.0.0.1', 48191) outgoingMessage '0,\x02\x01\x01\x04\x06public\xa2\x1f\x02\x04>9\xc4\xa0\x02\x01\x06\x02\x01\x010\x110\x0f\x06\x0b+\x06\x01\x04\x01\x81\xd9)\x02\x01\x01\x05\x00'
As for implementing a Managed Object Instance, you have two choices:
Load and subclass the MibScalarInstance class, then override its readGet() method to make it returning your live value. Then instantiate your new class (make sure to pass it appropriate OID that identifies it) and pass it to exportSymbols(), so its OID will get registered at pysnmp Agent.
Load the Integer32 class, subclass it and override its "clone()" method to make it returning your live value. Then load the MibScalarInstance class, instantiate it passing appropriate OID and the instance of your Integer32 subclass, then pass MibScalarInstance object to exportSymbols(), so its OID will get registered at pysnmp Agent.
It may make sense to keep all your code in your own MIB module. Take a look at pysnmp/smi/mibs/instances/*.py to get an idea.
From within your Agent app, invoke mibBuilder.loadModules('TRC-MIB') to load your MIB module into Agent.
In your code you seem to somehow combine the above two approaches: MyDeliveryTime.readGet() will not work, however MyDeliveryTime.clone() or deliveryTimeInstance.readGet() will.
I also faced a similar issue:
Tried putting the MY-MIB.[pyc] files in the ~/.pysnmp/mibs folders but I think what really worked was putting these files in the folder /usr/lib/pytho*/site/pysnmp/smi/mibs/ .
Am working on pysnmp-4.3.9
Related
Micropython: How to use utime.mktime() without knowing the weekday/yearday?
I'm trying to convert an ISO time string like '2021-05-11T18:21:35Z' to an int (seconds from epoch), which mktime() does, except it seems strange to me that it requires the weekday and yearday as part of the argument. In general, it seems unlikely that you would know this, and in my situation I don't. Obviously in python this is doable with things like datetime, but in uPython these don't exist and I haven't seen a non-external-library way to do this.
Much like with regular Python, the values of weekday and yearday are ignored (they get computed from the other values and are only accepted so that you can pass mktime the tuple returned by e.g. localtime). You can run: MicroPython v1.14 on 2021-03-07; ESP module with ESP8266 Type "help()" for more information. >>> import time >>> res = time.mktime((2021, 5, 11, 18, 21, 35, 0, 0)) >>> res 674072495 >>> time.localtime(res) (2021, 5, 11, 18, 21, 35, 1, 131)
Elixir POST file to Heroku file Attachment Scanner add-on
I am trying to scan uploaded documents for viruses when a user uploads, using the Heroku Add-on Attachment Scanner. I am attempting to encode the file directly with Poison.encode, but it is throwing an error so am not sure this is the correct method. Any help appreciated, below is my attempted HTTPoison post request, and the error from Poison.encode!. def scan do url = System.get_env("ATTACHMENT_SCANNER_URL") <> "/requests" token = System.get_env("ATTACHMENT_SCANNER_API_TOKEN") headers = [ "Authorization": "bearer " <> token, "Content-Type": "multipart/form-data", ] file_path = local_path_to_pdf_file file = file_path |> File.read! body = Poison.encode!(%{file: file}) res = HTTPoison.post(url, body, headers, recv_timeout: 40_000) end Poison.encode(file) error: iex(3)> Poison.encode(file) ** (FunctionClauseError) no function clause matching in Poison.Encoder.BitString.chunk_size/3 The following arguments were given to Poison.Encoder.BitString.chunk_size/3: # 1 <<226, 227, 207, 211, 13, 10, 49, 48, 51, 32, 48, 32, 111, 98, 106, 13, 60, 60, 47, 76, 105, 110, 101, 97, 114, 105, 122, 101, 100, 32, 49, 47, 76, 32, 50, 53, 50, 53, 51, 52, 51, 47, 79, 32, 49, 48, 53, 47, 69, 32, ...>> # 2 nil # 3 1 ps. I need to send the file directly, and am unable to host the image publicly, so the node.js examples in the docs will not work.
file = "/some/path/video.mp4" HTTPoison.post( "api.vid.me/video/upload";, {:multipart, [{:file, file, {"form-data", [name: "filedata", filename: Path.basename(file)]}, []}]}, ["AccessToken": "XXXXX"] ) will this help you?.. reference
Following on from Dinesh' answer, here is the code snippet which I went for: headers = [ "Authorization": "bearer " <> token, "Content-Type": "multipart/form-data", ] file_path = Ev2.Lib.MergerAPI.get_timecard_document_path body = {:multipart, [{:file, file_path}]} res = HTTPoison.post(url, body, headers)
Having both NER and RegexNER tags in StanfordCoreNLPServer output?
I am using the StanfordCoreNLPServer to extract some informations from text (such as surfaces, street names) The street is given by a specifically trained NER model, and the surface by a simple regex via the RegexNER. Each of them work fine separately but when used together, only the NER result is present in the output, under the ner tag. Why isn't there a regexnertag? Is there a way to also have the RegexNER result? For information: StanfordCoreNLP v3.6.0 the URL used: 'http://127.0.0.1:9000/' '?properties={"annotators":"tokenize,ssplit,pos,ner,regexner", ' '"pos.model":"edu/stanford/nlp/models/pos-tagger/french/french.tagger",' '"tokenize.language":"fr",' '"ner.model":"ner-model.ser.gz", ' # custom NER model with STREET labels '"regexner.mapping":"rules.tsv", ' # SURFACE label '"outputFormat": "json"}' as suggested here, the regexner annotator is after the ner, but still... The current output (extract): {u'index': 4, u'word': u'dans', u'lemma': u'dans', u'pos': u'P', u'characterOffsetEnd': 12, u'characterOffsetBegin': 8, u'originalText': u'dans', u'ner': u'O'} {u'index': 5, u'word': u'la', u'lemma': u'la', u'pos': u'DET', u'characterOffsetEnd': 15, u'characterOffsetBegin': 13, u'originalText': u'la', u'ner': u'O'} {u'index': 6, u'word': u'rue', u'lemma': u'rue', u'pos': u'NC', u'characterOffsetEnd': 19, u'characterOffsetBegin': 16, u'originalText': u'rue', u'ner': u'STREET'} {u'index': 7, u'word': u'du', u'lemma': u'du', u'pos': u'P', u'characterOffsetEnd': 22, u'characterOffsetBegin': 20, u'originalText': u'du', u'ner': u'STREET'} [...] {u'index': 43, u'word': u'165', u'lemma': u'165', u'normalizedNER': u'165.0', u'pos': u'DET', u'characterOffsetEnd': 196, u'characterOffsetBegin': 193, u'originalText': u'165', u'ner': u'NUMBER'} {u'index': 44, u'word': u'm', u'lemma': u'm', u'pos': u'NC', u'characterOffsetEnd': 198, u'characterOffsetBegin': 197, u'originalText': u'm', u'ner': u'O'} {u'index': 45, u'word': u'2', u'lemma': u'2', u'normalizedNER': u'2.0', u'pos': u'ADJ', u'characterOffsetEnd': 199, u'characterOffsetBegin': 198, u'originalText': u'2', u'ner': u'NUMBER'} Expected output : I would like the last 3 items to be labelled with SURFACE, ie the RegexNER result. Let me know if more details are needed.
Here's what the RegexNER documentation says about this: RegexNER will not overwrite an existing entity assignment, unless you give it permission in a third tab-separated column, which contains a comma-separated list of entity types that can be overwritten. Only the non-entity O label can always be overwritten, but you can specify extra entity tags which can always be overwritten as well. Bachelor of (Arts|Laws|Science|Engineering|Divinity) DEGREE Lalor LOCATION PERSON Labor ORGANIZATION I'm not sure what your mapping file exactly looks like, but if it just maps entities to labels, then the original NER will label your entities as NUMBER, and RegexNER won't be able to overwrite them. If you explicitly declare that some NUMBER entities should be overwritten as SURFACE in your mapping file, then it should work.
Ok, things seem to work as I want if I put the regexner first: "annotators":"regexner,tokenize,ssplit,pos,ner", seems there is an ordering problem at some stage of the process?
Update for coreNLP 3.9.2 server via python: When using coreNLP 3.9.2 server via python, the regexner can also now be initiated as part of ner as per the docs. For example: from pycorenlp import StanfordCoreNLP nlp = StanfordCoreNLP('http://localhost:9000') properties={"annotators":"tokenize,ssplit,pos,lemma,ner,coref,openie", "outputFormat": "json", "ner.fine.regexner.mapping":"rules.txt",} output = nlp.annotate(text,properties=properties) I could not get regexner annotator to work by calling it directly. I think this is due to reloading of dependencies and or the method used to translate outputs to JSON e.g. this issue
How to set multiple values for a key in a hash in prototype.js?
How to set multiple values for a key in a hash in prototype.js? For Eg: var hash={2005: [107, 31, 635, 203, 2]}
you can take exactly what you have written and convert to a Hash like this var hash=$H({2005: [107, 31, 635, 203, 2]}); console.log(hash.get(2005)); //returns [107, 31, 635, 203, 2] as an array
Can you optimize this descending sorting array with Ruby?
Do you know a better, faster, smarter, efficent or just more elegat way of doing the following ? due this array a = [171, 209, 3808, "723", "288", "6", "5", 27, "22", 207, 473, "256", 67, 1536] get this a.map{|i|i.to_i}.sort{|a,b|b<=>a} => [3808, 1536, 723, 473, 288, 256, 209, 207, 171, 67, 27, 22, 6, 5]
You can use in-place mutations to avoid creating new arrays: a.map!(&:to_i).sort!.reverse! Hard to know if it's faster or more efficient without a benchmark, though.
Here's one using symbol#to_proc a.map(&:to_i).sort.reverse This is faster than using in-place modifier (!) methods but uses more memory. As a bonus, it keeps the original array a intact if you want to do anything else with it.