pysnmp: how to make an oid writable - python

I would like to emulate a SNMP device, who i don't have the MIB file from device.
I just need to emulate one function, a writable OctectString value.
Here is my code:
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 import api
import time, bisect
from pysnmp import debug
debug.setLogger(debug.Debug('all'))
class SysDescr:
name = (1, 3, 6, 1, 2, 1, 1, 1, 0)
def __eq__(self, other): return self.name == other
def __ne__(self, other): return self.name != other
def __lt__(self, other): return self.name < other
def __le__(self, other): return self.name <= other
def __gt__(self, other): return self.name > other
def __ge__(self, other): return self.name >= other
def __call__(self, protoVer):
return api.protoModules[protoVer].OctetString(
'PySNMP responder'
)
class Domabox:
name = (1, 3, 6, 1, 2, 1, 1, 2, 0)
def __eq__(self, other): return self.name == other
def __ne__(self, other): return self.name != other
def __lt__(self, other): return self.name < other
def __le__(self, other): return self.name <= other
def __gt__(self, other): return self.name > other
def __ge__(self, other): return self.name >= other
def __call__(self, protoVer):
return api.protoModules[protoVer].OctetString(
'Domabox responder'
)
class Uptime:
name = (1, 3, 6, 1, 2, 1, 1, 3, 0)
birthday = time.time()
def __eq__(self, other): return self.name == other
def __ne__(self, other): return self.name != other
def __lt__(self, other): return self.name < other
def __le__(self, other): return self.name <= other
def __gt__(self, other): return self.name > other
def __ge__(self, other): return self.name >= other
def __call__(self, protoVer):
return api.protoModules[protoVer].TimeTicks(
(time.time()-self.birthday)*100
)
class Remote:
name = (1, 3, 6, 1, 2, 1, 1, 4, 0)
def __eq__(self, other): return self.name == other
def __ne__(self, other): return self.name != other
def __lt__(self, other): return self.name < other
def __le__(self, other): return self.name <= other
def __gt__(self, other): return self.name > other
def __ge__(self, other): return self.name >= other
def __call__(self, protoVer):
return api.protoModules[protoVer].OctetString(
'Remote'
)
mibInstr = (
SysDescr(), Domabox(), Uptime(), Remote(), # sorted by object name
)
mibInstrIdx = {}
for mibVar in mibInstr:
mibInstrIdx[mibVar.name] = mibVar
def cbFun(transportDispatcher, transportDomain, transportAddress, wholeMsg):
while wholeMsg:
msgVer = api.decodeMessageVersion(wholeMsg)
pMod = api.protoModules[api.protoVersion1]
reqMsg, wholeMsg = decoder.decode(
wholeMsg, asn1Spec=pMod.Message(),
)
rspMsg = pMod.apiMessage.getResponse(reqMsg)
rspPDU = pMod.apiMessage.getPDU(rspMsg)
reqPDU = pMod.apiMessage.getPDU(reqMsg)
print "reqPDU", reqPDU
varBinds = []; pendingErrors = []
errorIndex = 0
# GETNEXT PDU
if reqPDU.isSameTypeWith(pMod.GetNextRequestPDU()):
# Produce response var-binds
for oid, val in pMod.apiPDU.getVarBinds(reqPDU):
errorIndex = errorIndex + 1
# Search next OID to report
nextIdx = bisect.bisect(mibInstr, oid)
if nextIdx == len(mibInstr):
# Out of MIB
varBinds.append((oid, val))
pendingErrors.append(
(pMod.apiPDU.setEndOfMibError, errorIndex)
)
else:
# Report value if OID is found
varBinds.append(
(mibInstr[nextIdx].name, mibInstr[nextIdx](msgVer))
)
elif reqPDU.isSameTypeWith(pMod.GetRequestPDU()):
for oid, val in pMod.apiPDU.getVarBinds(reqPDU):
if oid in mibInstrIdx:
varBinds.append((oid, mibInstrIdx[oid](msgVer)))
else:
# No such instance
varBinds.append((oid, val))
pendingErrors.append(
(pMod.apiPDU.setNoSuchInstanceError, errorIndex)
)
break
elif reqPDU.isSameTypeWith(pMod.setRequestPDU()):
print "request ?"
else:
print "unsupported..."
# Report unsupported request type
pMod.apiPDU.setErrorStatus(rspPDU, 'genErr')
pMod.apiPDU.setVarBinds(rspPDU, varBinds)
# Commit possible error indices to response PDU
for f, i in pendingErrors:
f(rspPDU, i)
transportDispatcher.sendMessage(
encoder.encode(rspMsg), transportDomain, transportAddress
)
return wholeMsg
transportDispatcher = AsynsockDispatcher()
transportDispatcher.registerRecvCbFun(cbFun)
# UDP/IPv4
transportDispatcher.registerTransport(
udp.domainName, udp.UdpSocketTransport().openServerMode(('localhost', 161))
)
# UDP/IPv6
transportDispatcher.registerTransport(
udp6.domainName, udp6.Udp6SocketTransport().openServerMode(('::1', 161))
)
transportDispatcher.jobStarted(1)
try:
# Dispatcher will never finish as job#1 never reaches zero
transportDispatcher.runDispatcher()
except:
transportDispatcher.closeDispatcher()
raise
When i send a snmp write value, i got
;AttributeError: 'module' object has no attribute 'setRequestPDU'
from line
elif reqPDU.isSameTypeWith(pMod.setRequestPDU()):
var reqPDU content:
reqPDU SetRequestPDU().setComponentByPosition(0, Integer(1639861451)).setComponentByPosition(1, Integer('noError')).setComponentByPosition(2, Integer(0)).setComponentByPosition(3, VarBindList().setComponentByPosition(0, VarBind().setComponentByPosition(0, ObjectName(1.3.6.1.2.1.1.4.0)).setComponentByPosition(1, ObjectSyntax().setComponentByPosition(0, SimpleSyntax().setComponentByPosition(1, OctetString('57'))))))
Thanks.

You probably meant pMod.SetRequestPDU() in your code (notice capital 'S').
However, instead of writing your own emulator, I'd suggest considering a general purpose SNMP simulator which could be configured to emulate a full blown SNMP-capable device.

Related

Overriding <= and >= for Python Class

I have following class:
class Word:
def __init__(self, key: str):
self.key = key
self.value = ''.join(sorted(key))
def __lt__(self, other):
if self.value < other.value:
return True
return False
def __gt__(self, other):
if self.value > other.value:
return True
return False
def __eq__(self, other):
val = other.value
if self.value == val:
return True
return False
and < works. But when I try <= I get following error:
TypeError: '<=' not supported between instances of 'Word' and 'Word'
How to override <= for python class?
You need to implement __ge__ & __le__
class Word:
def __init__(self, key: str):
self.key = key
self.value = ''.join(sorted(key))
def __lt__(self, other):
if self.value < other.value:
return True
return False
def __gt__(self, other):
if self.value > other.value:
return True
return False
def __le__(self, other):
if self.value <= other.value:
return True
return False
def __ge__(self, other):
if self.value >= other.value:
return True
return False
def __eq__(self, other):
val = other.value
if self.value == val:
return True
return False
You need to override def __le__(self, other) (lesser-equal) and def __ge__(self, other) (greater equal) as well.
Beside that you should check if your given other actually is a Word instance, else you might crash because no other.value can be accessed:
w = Word("hello")
print( w > 1234 ) # crash: AttributeError: 'int' object has no attribute 'value'
Source / Documentation of all of them: object.__le__
See
python overloading operators
Potential fix for comparison:
def __lt__(self, other):
if isinstance(other, Word):
if self.value < other.value:
return True
else:
# return True or False if it makes sense - else use better exception
raise ValueError(f"Cannot compare Word vs. {type(other)}")
return False
There is another special method for this:
def __le__(self, other):
if self.value <= other.value:
return True
else:
return False

How to update classes

class Dog(object):
def __init__(self, number):
self.number = number
def number_update(self):
self.number += 1
class Cat(object):
def __init__(self, number):
self.number = number
class1 = Dog(1)
class2 = Cat(class1.number * 0.5)
class1.number_update()
print(class1.number)
print(class2.number)
Current output: 2, 0.5
I want: 2, 1
I really simplified it, so I hope you will understand
Thank you for help
You are running class1.number_update() after you define the class2 variable, so the class1 variable has a value of 1 when you define class2, and after you define class2, class1 becomes into 2. To fix this, just switch around those two lines:
class Dog(object):
def __init__(self, number):
self.number = number
def number_update(self):
self.number += 1
class Cat(object):
def __init__(self, number):
self.number = number
class1 = Dog(1)
class1.number_update()
class2 = Cat(class1.number * 0.5)
print(class1.number)
print(class2.number)
You could return the number in number_update():
class Dog(object):
def __init__(self, number):
self.number = number
def number_update(self):
self.number += 1
return self.number
class Cat(object):
def __init__(self, number):
self.number = number
class1 = Dog(1)
class2 = Cat(class1.number_update() * .5)
print(class1.number)
print(class2.number)
Output:
2
1.0
As suggested in the comments, to do this exactly as you want, you'll have to write your own expression and number classes, such as this:
class Op:
def __init__(self, op):
self.op = op
def __call__(self, a, b):
if self.op == "*":
return a * b
if self.op == "/":
return a / b
if self.op == "-":
return a - b
if self.op == "+":
return a + b
raise TypeError(f"Unknown op {repr(self.op)}")
def __repr__(self):
return self.op
mul = Op("*")
div = Op("/")
add = Op("+")
sub = Op("-")
class Expr:
def __init__(self, a, b, op):
self.op = op
self.a = a
self.b = b
def eval(self):
return self.op(self.a.eval(), self.b.eval())
def __repr__(self):
return f"({self.a} {self.op} {self.b})"
def __mul__(self, other):
if isinstance(other, (int, float)):
b = Number(other)
else:
b = other
a = self
return Expr(a, b, mul)
def __div__(self, other):
if isinstance(other, (int, float)):
b = Number(other)
else:
b = other
a = self
return Expr(a, b, div)
def __add__(self, other):
if isinstance(other, (int, float)):
b = Number(other)
else:
b = other
a = self
return Expr(a, b, add)
def __sub__(self, other):
if isinstance(other, (int, float)):
b = Number(other)
else:
b = other
a = self
return Expr(a, b, sub)
def __rmul__(self, other):
return self.__class__.__mul__(other, self)
def __rdiv__(self, other):
return self.__class__.__div__(other, self)
def __rsub__(self, other):
return self.__class__.__sub__(other, self)
def __radd__(self, other):
return self.__class__.__add__(other, self)
class Number(Expr):
def __init__(self, value):
self._value = value
def get(self):
return self._value
def set(self, new):
self._value = new
def increment(self):
self._value += 1
def eval(self):
return self._value
def __repr__(self):
return str(self._value)
class Dog:
def __init__(self, number):
self.number = Number(number)
def number_update(self):
self.number.increment()
class Cat:
def __init__(self, number):
self._number = number
#property
def number(self):
return self._number.eval()
#number.setter
def number(self, new):
if isinstance(new, (int, float)):
new = Number(new)
self._number = new
cls1 = Dog(1)
cls2 = Cat(cls1.number * 0.5)
cls1.number_update()
print(cls1.number)
print(cls2.number)
Here, we get the expected output of
2
1.0
Lets go through the lines of your main function and trace the values of Dog and Cat
class1 = Dog(1) # Dog=1; Cat=undefined
class2 = Cat(class1.number * 0.5) # Dog=1; Cat=1*0.5=0.5
class1.number_update() # Dog=2; Cat=0.5
print(class1.number) # >>>"2"
print(class2.number) # >>>"0.5"
Your class doesn't have a reference to Dog's number member, it just references the Cat class property.
EDIT: It doesn't copy, it creates a reference directly to the object.

Min/Max Heap implementation in Python

This is my implementation of a MinHeap and MaxHeap in python. This uses a comparator to reverse the sequence of storage in the MaxHeap
import heapq
class MinHeap:
def __init__(self):
self.heap = []
def push(self, item):
heapq.heappush(self.heap, item)
def pop(self):
return heapq.heappop(self.heap)
def peek(self):
return self.heap[0]
def __getitem__(self, item):
return self.heap[item]
def __len__(self):
return len(self.heap)
class MaxHeap(MinHeap):
def push(self, item):
heapq.heappush(self.heap, Comparator(item))
def pop(self):
return heapq.heappop(self.heap)
def peek(self):
return self.heap[0]
def __getitem__(self, i):
return self.heap[i].val
class Comparator:
def __init__(self, val):
self.val = val
def __lt__(self, other):
return self.val > other
def __eq__(self, other):
return self.val == other
if __name__ == '__main__':
max_heap = MaxHeap()
max_heap.push(12)
max_heap.push(3)
max_heap.push(17)
print(max_heap.pop())
The MinHeap seems to work fine, however the MaxHeap throw up the following error.
<__main__.Comparator object at 0x10a5c1080>
I don't quite seem to understand what am I doing wrong here. Can someone help me with this.
I've added __repr__ and __gt__ methods to your Comparator class, so the code now runs, and the Comparator instances display their val when printed.
The important thing is to get those comparison methods to do the comparisons correctly between two Comparator instances.
You'll notice that I've eliminated most of the methods from MaxHeap. They aren't needed because the methods inherited from MinHeap work ok. You may wish to restore this one to MaxHeap
def __getitem__(self, i):
return self.heap[i].val
depending on how you intend to use MaxHeap.
import heapq
class MinHeap:
def __init__(self):
self.heap = []
def push(self, item):
heapq.heappush(self.heap, item)
def pop(self):
return heapq.heappop(self.heap)
def peek(self):
return self.heap[0]
def __getitem__(self, item):
return self.heap[item]
def __len__(self):
return len(self.heap)
class MaxHeap(MinHeap):
def push(self, item):
heapq.heappush(self.heap, Comparator(item))
class Comparator:
def __init__(self, val):
self.val = val
def __lt__(self, other):
return self.val > other.val
def __eq__(self, other):
return self.val == other.val
def __repr__(self):
return repr(self.val)
if __name__ == '__main__':
max_heap = MaxHeap()
max_heap.push(12)
max_heap.push(3)
max_heap.push(17)
while True:
try:
print(max_heap.pop())
except IndexError:
# The heap's empty, bail out
break
output
17
12
3
It's probably a Good Idea to give Comparator the full set of rich comparison methods. They aren't needed to make the above code work, but they will make the Comparator instances more flexible. So in case you want them, here they are:
def __lt__(self, other):
return self.val > other.val
def __le__(self, other):
return self.val >= other.val
def __gt__(self, other):
return self.val < other.val
def __ge__(self, other):
return self.val <= other.val
def __eq__(self, other):
return self.val == other.val
def __ne__(self, other):
return self.val != other.val

How to rebuild the object with repr?

My code works perfectly except the last part. I want to recreate the object with repr function but it clearly doesn't work. I tried everything here and on the web but i'm still so confuse. Is there any way to do it and if so what is the syntax ?
class Modulo(object):
def __init__(self, grondtal, waarde = 0):
self.grondtal = grondtal
self.waarde = waarde % grondtal
def __call__(self, m):
return Modulo(self.grondtal, m)
def __add__(self, other):
return Modulo(self.grondtal, self.waarde + other.waarde)
def __sub__(self, other):
return Modulo(self.grondtal, self.waarde - other.waarde)
def __mul__(self, other):
return Modulo(self.grondtal, self.waarde * other.waarde)
def __eq__(self, other):
return self.waarde == other.waarde and self.grondtal == other.grondtal
def __ne__(self, other):
return not self.__eq__(other)
def __str__(self):
return '[%s %% %s]' % (str(self.grondtal), str(self.waarde))
def __repr__(self):
return '%s' %Modulo(self.grondtal, self.waarde)
You probably want this:
def __repr__(self):
return "Modulo(%d,%d)" % (self.grondtal, self.waarde)
Or, a little bit more generic:
def __repr__(self):
return "%s(%d,%d)" % (self.__class__.__name__, self.grondtal, self.waarde)
For example:
>>> m = Modulo(3,2)
>>> repr(m)
'Modulo(3,2)'

How to make the "in" and "subset" method of python works?

I am relatively new to python. I have a class Time, and I want to check if a set of Time objects contains another set of Time objects.
a = {Time(10,10)}
print {Time(10,10)}.issubset(a) >> "result is False"
for i in a:
print i in a >> "result is True"
And in the class, I have implemented these methods
def to_min(self):
return self.h * 60 + self.m
def __cmp__(self, other):
if isinstance(other, Time):
if self.to_min() > other.to_min():
return 1
else:
if self.to_min() == other.to_min():
return 0
else:
return -1
def __eq__(self, other):
if isinstance(other, Time):
if self.to_min() == other.to_min():
return True
else:
return False
def __gt__(self, other):
return self.to_min() > other.to_min()
def __ge__(self, other):
return self.to_min() >= other.to_min()
def __lt__(self, other):
return self.to_min() < other.to_min()
def __le__(self, other):
return self.to_min() <= other.to_min()
def __str__ (self):
return str(self.h) + ":" + str(self.m)
def __hash__(self):
return self.to_min()
I wonder what else should I implement or change to make the following lines of code to print to true. I have read the=at there is a contains method. But I am not going check if one Time object contains other components.
a = {Time(10,10)}
print {Time(10,10)}.issubset(a) >>
I replaced this
self.to_min() == other.to_min()
with this
self.__hash__() == other.__hash__()
And also edited the eq to return boollean, rather than integer
Now it works, I still wonders.
Anyway, this is full code if anyone is interested:
class Time(object):
'''
classdocs
'''
def __init__(self, h, m):
if isinstance(h, int) and isinstance(h, int):
self.m = m
self.h = h
if(self.m >= 60):
self.h += self.m // 60
self.m %= 60
def __add__(self, m):
return Time(self.h, self.m + m)
def to_min(self):
return self.h * 60 + self.m
def __cmp__(self, other):
print "__cmp__"
if isinstance(other, Time):
if self.to_min() > other.to_min():
return 1
else:
if self.__hash__() == other.__hash__():
return 0
else:
return -1
def __eq__(self, other):
print "__eq__"
if isinstance(other, Time):
if self.to_min() == other.to_min():
return True
else:
return False
def __gt__(self, other):
return self.to_min() > other.to_min()
def __ge__(self, other):
return self.to_min() >= other.to_min()
def __lt__(self, other):
return self.to_min() < other.to_min()
def __le__(self, other):
return self.to_min() <= other.to_min()
def __str__ (self):
return str(self.h) + ":" + str(self.m)
def __hash__(self):
print "__hash__"
return self.to_min()
# return 1
def __ne__(self, other):
print "__ne__"
return not self == other
# a = set([Time(10,10), Time(10,20)])
# b = set([Time(10,10)])
# print a in set([b])
a = {Time(10,10)}
print {Time(10,10)}.issubset(a)
# print b.issubset( a)
# for i in a:
# print i in a

Categories