最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

python - pysnmp How to stop and restart snmpEngine and it's dispatcher in runtime? - Stack Overflow

programmeradmin4浏览0评论

I've implemented a decent SNMP agent using lextudio/pysnmp. I am using 2 threads in my application:

  1. dispatcher thread (responds to manager's requests)
  2. main thread (updates values in MIB, sends notifications (traps))

SNMP agent working fine but only if run once. What I need is to be able to fully shutdown SNMP agent and dispatcher (free resources, exit dispatcher thread). And restart it from scratch (e.g. with new settings).

I've made an MRE that fully represents my problem. I use iReasoning MIB browser to connect to SNMPv2c agent at 127.0.0.1:1161 and request value at 1.3.6.5.1.0

from pysnmp.entity import engine, config
from pysnmp.entity.rfc3413 import cmdrsp, context
from pysnmp.carrier.asyncio.dgram import udp
from pysnmp.proto.api import v2c
from threading import Thread
from time import sleep


def create_and_set_engine():
    # basic setup
    snmpEngine = engine.SnmpEngine()
    config.add_transport(snmpEngine, udp.DOMAIN_NAME, udp.UdpTransport().open_server_mode(("127.0.0.1", 1161)))
    config.add_v1_system(snmpEngine, "my-area", "public")
    config.add_vacm_user(snmpEngine, 2, "my-area", "noAuthNoPriv", (1, 3, 6, 5))
    snmpContext = context.SnmpContext(snmpEngine)
    mibInstrum = snmpContext.get_mib_instrum()
    mibBuilder = mibInstrum.get_mib_builder()

    # create scalar OctetString object and it's instance at 1.3.6.5.1
    MibScalar, MibScalarInstance = mibBuilder.import_symbols("SNMPv2-SMI", "MibScalar", "MibScalarInstance")
    mibBuilder.export_symbols(
        "__MY_MIB",
        MibScalar((1, 3, 6, 5, 1), v2c.OctetString()),
        MibScalarInstance((1, 3, 6, 5, 1), (0,), v2c.OctetString()),
    )

    # write value
    mibInstrum.write_variables(((1, 3, 6, 5, 1, 0), 'benis'))

    # Register SNMP Applications at the SNMP engine for particular SNMP context
    cmdrsp.GetCommandResponder(snmpEngine, snmpContext)
    cmdrsp.NextCommandResponder(snmpEngine, snmpContext)
    cmdrsp.BulkCommandResponder(snmpEngine, snmpContext)

    return snmpEngine


def run_dispatcher(snmpEngine: engine.SnmpEngine):
    # Register an imaginary never-ending job to keep I/O dispatcher running forever
    snmpEngine.transport_dispatcher.job_started(1)
    # Run I/O dispatcher which would receive queries and send responses
    try:
        snmpEngine.open_dispatcher()
        print('open_dispatcher() exited')
    except:
        snmpEngine.close_dispatcher()
        raise




my_engine = create_and_set_engine()
th_dispatcher = Thread(target=run_dispatcher, args=(my_engine,) ,daemon=True)
th_dispatcher.start()
print('Let dispatcher work for 10 s')
sleep(10)
my_engine.close_dispatcher()
del my_engine
del th_dispatcher
print('Now dispatcher is closed. No requests will be responded')
print('Sleep 10 s, then restart the engine and dispatcher')
sleep(10)
my_engine = create_and_set_engine()
th_dispatcher = Thread(target=run_dispatcher, args=(my_engine,) ,daemon=True)
th_dispatcher.start()
print('Main thread is still running. Press Ctrl + C to stop application.')
while True:
    sleep(3)

After executing my_engine.close_dispatcher(), agent stops responding as expected. But the problem is that thread continues and never stops. If I open a new thread with my_engine.open_dispatcher(), dispatcher doesn't work anymore. Recreating my_engine object doesn't help either. Probably I just don't understand how to properly work with threads.

发布评论

评论列表(0)

  1. 暂无评论