Skip to content

Commit 3ab7efa

Browse files
committed
added queue_trap() and send_queued_traps() methods to better support
threads sending traps
1 parent 606a781 commit 3ab7efa

File tree

2 files changed

+35
-7
lines changed

2 files changed

+35
-7
lines changed

examples/simple_agent_trap.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -236,7 +236,8 @@ def HupHandler(signum, frame):
236236
# Since we didn't give simpleCounter, simpleCounter64 and simpleTimeTicks
237237
# a real meaning in the SIMPLE-MIB, we can basically do with them whatever
238238
# we want. Here, we just increase them, although in different manners.
239-
simpleCounter32.update(simpleCounter32.value() + 2)
239+
# simpleCounter32.update(simpleCounter32.value() + 2)
240+
simpleCounter32.update(simpleCounter32.value() + 1)
240241
simpleCounter64.update(simpleCounter64.value() + 4294967294)
241242
simpleTimeTicks.update(simpleTimeTicks.value() + 1)
242243

@@ -247,10 +248,12 @@ def HupHandler(signum, frame):
247248
# agent.check_and_process() is trigering when trap is send so to disable endless loop
248249
# there is flag set to skip sending trap on next check
249250
if sendTrap:
251+
print('Sending trap with simpleCounter32.value: {:}'.format(simpleCounter32.value()))
250252
trapOid = 'SNMPv2-MIB::sysDescr'
251253
trapData = [
252254
{ 'oid':'SNMPv2-MIB::sysDescr.0', 'val':'test state' },
253-
{ 'oid':'SIMPLE-MIB::simpleCounter64.0', 'val':1234567890L },
255+
{ 'oid':'SIMPLE-MIB::simpleCounter32.0', 'val':simpleCounter32.value() },
256+
# { 'oid':'SIMPLE-MIB::simpleCounter64.0', 'val':simpleCounter64.value() },
254257
]
255258
agent.send_trap(
256259
oid = trapOid,

netsnmpagent.py

Lines changed: 30 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
#
66
# Main module
77
#
8-
98
""" Allows to write net-snmp subagents in Python.
109
1110
The Python bindings that ship with net-snmp support client operations
@@ -17,16 +16,18 @@
1716
1817
This module, by contrast, concentrates on wrapping the net-snmp C API
1918
for SNMP subagents in an easy manner. """
19+
# Helper function courtesy of Alec Thomas and taken from
20+
# http://stackoverflow.com/questions/36932/how-can-i-represent-an-enum-in-python
2021

21-
import sys, os, re, inspect, ctypes, socket, struct
2222
from collections import defaultdict
23+
import sys, os, re, inspect, ctypes, socket, struct
24+
from threading import Lock
25+
2326
from netsnmpapi import *
24-
import netsnmpvartypes
2527
from netsnmpvartypes import _VarType
28+
import netsnmpvartypes
2629

2730

28-
# Helper function courtesy of Alec Thomas and taken from
29-
# http://stackoverflow.com/questions/36932/how-can-i-represent-an-enum-in-python
3031
def enum(*sequential, **named):
3132
enums = dict(zip(sequential, range(len(sequential))), **named)
3233
try:
@@ -139,6 +140,10 @@ def __init__(self, **args):
139140
if self.UseMIBFiles and self.MIBFiles is not None and type(self.MIBFiles) not in (list, tuple):
140141
self.MIBFiles = (self.MIBFiles,)
141142

143+
# Support the queueing of traps to prevent duplicates sent from threads
144+
self.queued_traps = []
145+
self.trap_lock = Lock()
146+
142147
# Initialize status attribute -- until start() is called we will accept
143148
# SNMP object registrations
144149
self._status = netsnmpAgentStatus.REGISTRATION
@@ -924,6 +929,26 @@ def shutdown(self):
924929
# one effectively has to rely on the OS to release resources.
925930
# libnsa.shutdown_agent()
926931

932+
def queue_trap(self, *args, **kwargs):
933+
'''This method queues a trap to be sent from the main thread loop.
934+
In SNMP v5.7.3 (and likely others), many traps sent from threads in agentx
935+
sub-agents are duplicated. This method and send_queued_traps() support
936+
queueing traps in non-main threads and actually sending them from the
937+
main thread in the "check_and_process loop."
938+
'''
939+
with self.trap_lock:
940+
self.queued_traps.append((args, kwargs))
941+
942+
def send_queued_traps(self):
943+
'''This method must be called from the main thread loop and dequeues and
944+
send all queued traps.
945+
'''
946+
with self.trap_lock:
947+
for arg_tuple in self.queued_traps:
948+
(args, kwargs) = arg_tuple
949+
self.send_trap(*args, **kwargs)
950+
self.queued_traps.clear()
951+
927952
def send_trap(self, *args, **kwargs):
928953
'''Send SNMP traps
929954
To send simple trap:

0 commit comments

Comments
 (0)