【问题标题】:PySNMP Instrumentation Controller with asyncio带有 asyncio 的 PySNMP 仪表控制器
【发布时间】:2017-03-12 02:28:16
【问题描述】:

我需要编写简单的 SNMP 响应程序,其中部分工作是通过 asyncio.subprocess 模块调用一些外部脚本。现在我正在尝试pysnmp,但在示例中稍作修改的代码不起作用:

import asyncio                                                                                                                                     

from pysnmp.entity import engine, config                                                                                                           
from pysnmp.entity.rfc3413 import cmdrsp, context                                                                                                  
from pysnmp.carrier.asyncio.dgram import udp                                                                                                       
from pysnmp.smi import instrum                                                                                                                     
from pysnmp.proto.api import v2c                                                                                                                   

snmpEngine = engine.SnmpEngine()                                                                                                                   

config.addTransport(                                                                                                                               
    snmpEngine,                                                                                                                                    
    udp.domainName,                                                                                                                                
    udp.UdpTransport().openServerMode(('0.0.0.0', 161))                                                                                            
)                                                                                                                                                  

# config.addV1System(snmpEngine, 'my-area', 'public')                                                                                              
config.addV1System(snmpEngine, 'public', 'public', contextName='my-context')                                                                       
config.addV1System(snmpEngine, 'private', 'private', contextName='my-context')                                                                     

# Allow full MIB access for each user at VACM                                                                                                      
config.addVacmUser(snmpEngine, 2, "public", 'noAuthNoPriv', (1, 3, 6, 1, 2, 1), (1, 3, 6, 1, 2, 1))                                                
config.addVacmUser(snmpEngine, 2, "private", 'noAuthNoPriv', (1, 3, 6, 1, 2, 1), (1, 3, 6, 1, 2, 1))                                               

# Create an SNMP context                                                                                                                           
snmpContext = context.SnmpContext(snmpEngine)                                                                                                      

# Very basic Management Instrumentation Controller without                                                                                         
# any Managed Objects attached. It supports only GET's and                                                                                         
# always echos request var-binds in response.                                                                                                      
class EchoMibInstrumController(instrum.AbstractMibInstrumController):                                                                              
    @asyncio.coroutine                                                                                                                             
    def readVars(self, varBinds, acInfo=(None, None)):                                                                                             
        yield from asyncio.sleep(1)                                                                                                                
        return [(ov[0], v2c.OctetString('You queried OID %s' % ov[0])) for ov in varBinds]                                                         

# Create a custom Management Instrumentation Controller and register at                                                                            
# SNMP Context under ContextName 'my-context'                                                                                                      
snmpContext.registerContextName(                                                                                                                   
    v2c.OctetString('my-context'),  # Context Name                                                                                                 
    EchoMibInstrumController()  # Management Instrumentation                                                                                       
)                                                                                                                                                  

# Register GET&SET Applications at the SNMP engine for a custom SNMP context                                                                       
cmdrsp.GetCommandResponder(snmpEngine, snmpContext)                                                                                                
cmdrsp.SetCommandResponder(snmpEngine, snmpContext)                                                                                                

loop = asyncio.get_event_loop()                                                                                                                    
loop.run_forever()

当尝试使用以下命令进行查询时 snmpget -v 2c -c public 127.0.0.1 .1.3.6.1.2.1.1.1.0 脚本失败并出现以下回溯。

Exception in callback AbstractTransportDispatcher._cbFun(<pysnmp.carri...x7f4c7540d518>, ('127.0.0.1', 44209), b'0)\x02\x01\...1\x00\x05\x00') 
handle: <Handle AbstractTransportDispatcher._cbFun(<pysnmp.carri...x7f4c7540d518>, ('127.0.0.1', 44209), b'0)\x02\x01\...1\x00\x05\x00')>      
Traceback (most recent call last):                                                                                                             
  File "/usr/lib/python3.4/asyncio/events.py", line 120, in _run                                                                               
    self._callback(*self._args)                                                                                                                
  File "/opt/profiset2/lib/python3.4/site-packages/pysnmp/carrier/base.py", line 70, in _cbFun                                                 
    self, transportDomain, transportAddress, incomingMessage                                                                                   
  File "/opt/profiset2/lib/python3.4/site-packages/pysnmp/entity/engine.py", line 154, in __receiveMessageCbFun                                
    self, transportDomain, transportAddress, wholeMsg                                                                                          
  File "/opt/profiset2/lib/python3.4/site-packages/pysnmp/proto/rfc3412.py", line 421, in receiveMessage                                       
    PDU, maxSizeResponseScopedPDU, stateReference)                                                                                             
  File "/opt/profiset2/lib/python3.4/site-packages/pysnmp/entity/rfc3413/cmdrsp.py", line 140, in processPdu                                   
    (self.__verifyAccess, snmpEngine))                                                                                                         
  File "/opt/profiset2/lib/python3.4/site-packages/pysnmp/entity/rfc3413/cmdrsp.py", line 247, in handleMgmtOperation                          
    mgmtFun(v2c.apiPDU.getVarBinds(PDU), (acFun, acCtx)))                                                                                      
  File "/opt/profiset2/lib/python3.4/site-packages/pysnmp/entity/rfc3413/cmdrsp.py", line 46, in sendVarBinds                                  
    v2c.apiPDU.setVarBinds(PDU, varBinds)                                                                                                      
  File "/opt/profiset2/lib/python3.4/site-packages/pysnmp/proto/api/v1.py", line 135, in setVarBinds                                           
    varBindList.getComponentByPosition(idx), varBind                                                                                           
  File "/opt/profiset2/lib/python3.4/site-packages/pysnmp/proto/api/v1.py", line 38, in setOIDVal                                              
    oid, val = oidVal[0], oidVal[1]                                                                                                            
TypeError: 'Future' object does not support indexing

可能是我在做一些愚蠢的事情,并且我承认我对 SNMP 了解不多,那么,请指引我正确的方向。

【问题讨论】:

    标签: async-await python-asyncio pysnmp


    【解决方案1】:

    这是因为 CommandResponder MIB 控制器交互是currently synchronous。换句话说,你不能yield from MIB 控制器,你只能return 来自它。它不能是coroutine。删除这两件事后,您的代码可能会正常工作。

    mgmtFun(在我上面链接的代码中)可以返回Future的方式重构pysnmp代码绝对可行,一旦Future完成,它会触发其余代码(例如sendVarBinds) .这将使您的 MIB 控制器异步。

    这是你需要的吗?然后考虑针对 pysnmp 的 PR 或 FR。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-11-23
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多