|
5 | 5 | # |
6 | 6 | # Main module |
7 | 7 | # |
8 | | - |
9 | 8 | """ Allows to write net-snmp subagents in Python. |
10 | 9 |
|
11 | 10 | The Python bindings that ship with net-snmp support client operations |
|
17 | 16 |
|
18 | 17 | This module, by contrast, concentrates on wrapping the net-snmp C API |
19 | 18 | 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 |
20 | 21 |
|
21 | | -import sys, os, re, inspect, ctypes, socket, struct |
22 | 22 | from collections import defaultdict |
| 23 | +import sys, os, re, inspect, ctypes, socket, struct |
| 24 | +from threading import Lock |
| 25 | + |
23 | 26 | from netsnmpapi import * |
24 | | -import netsnmpvartypes |
25 | 27 | from netsnmpvartypes import _VarType |
| 28 | +import netsnmpvartypes |
26 | 29 |
|
27 | 30 |
|
28 | | -# Helper function courtesy of Alec Thomas and taken from |
29 | | -# http://stackoverflow.com/questions/36932/how-can-i-represent-an-enum-in-python |
30 | 31 | def enum(*sequential, **named): |
31 | 32 | enums = dict(zip(sequential, range(len(sequential))), **named) |
32 | 33 | try: |
@@ -139,6 +140,10 @@ def __init__(self, **args): |
139 | 140 | if self.UseMIBFiles and self.MIBFiles is not None and type(self.MIBFiles) not in (list, tuple): |
140 | 141 | self.MIBFiles = (self.MIBFiles,) |
141 | 142 |
|
| 143 | + # Support the queueing of traps to prevent duplicates sent from threads |
| 144 | + self.queued_traps = [] |
| 145 | + self.trap_lock = Lock() |
| 146 | + |
142 | 147 | # Initialize status attribute -- until start() is called we will accept |
143 | 148 | # SNMP object registrations |
144 | 149 | self._status = netsnmpAgentStatus.REGISTRATION |
@@ -924,6 +929,26 @@ def shutdown(self): |
924 | 929 | # one effectively has to rely on the OS to release resources. |
925 | 930 | # libnsa.shutdown_agent() |
926 | 931 |
|
| 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 | + |
927 | 952 | def send_trap(self, *args, **kwargs): |
928 | 953 | '''Send SNMP traps |
929 | 954 | To send simple trap: |
|
0 commit comments