使用Pysnmp从代理端

时间:2016-08-01 13:00:36

标签: snmp pysnmp

我一直在寻找一种方法来使用pysnmp在SNMP代理运行期间动态更新SNMP表。但到目前为止还没有运气......

  

该表已在MIB文件中定义(见下文),但似乎我需要覆盖其“readGet()”方法,以便从当前系统状态返回正确的数据。

根据http://pysnmp.sourceforge.net/examples/v3arch/asyncore/agent/cmdrsp/agent-side-mib-implementations.html#implementing-conceptual-table

的说明

我可以在SNMP代理启动之前和SNMP代理启动之后构建一个具有预定义值的静态表:

# Register an imaginary never-ending job to keep I/O dispatcher running forever
self.snmpEngine.transportDispatcher.jobStarted(1)
# Run I/O dispatcher which would receive queries and send responses
try:
    self.snmpEngine.transportDispatcher.runDispatcher()
except:
    self.snmpEngine.transportDispatcher.closeDispatcher()
    raise

它能够返回我的期望值。

但对于我的系统,它会动态生成许多警报信息,这些信息需要更新到SNMP的MIB表中,这允许其他SNMP管理器发送“get / getNext”以从我的系统获取警报信息。

所以我想知道

  • 有没有办法在pysnmp中执行此操作?
  • 或者我必须始终静态更新我的闹钟表?然后在每次更新操作后重新启动SNMP代理?
  • 或者我必须在SNMP代理启动期间使用所有可能的2147483647实例初始化我的警报表?并使用“name [-1]”从每个查询中获取索引/行号?
      

    如果是这样,getNext查询怎么样?它会忽略那些空表行吗?或者它总是返回下一个,即使它是一个虚拟的?

  • 或者是否有更好的方法从查询消息中获取“索引/行”数字?

@Ilya Etingof,pysnmp的专家。如果你有时间,可以帮助我吗?

BR, -Dapeng Jiao

1

该警报表的MIB文件定义(删除了一些敏感信息)

alarmTable = MibTable((1, 3, 6, *, *, *, *, *, *, *, *, *, , 3))
alarmEntry = MibTableRow((1, 3, 6, *, *, *, *, *, *, *, *, *, , 3, 1)).setIndexNames((0, "MY-MIB", "alarmIndex"))
alarmIndex = MibTableColumn((1, 3, 6, *, *, *, *, *, *, *, *, *, , 3, 1, 1), Integer32().subtype(subtypeSpec=ValueRangeConstraint(1, 2147483647))).setMaxAccess("readonly")
alarmId = MibTableColumn((1, 3, 6, *, *, *, *, *, *, *, *, *, , 3, 1, 2), Integer32().subtype(subtypeSpec=ValueRangeConstraint(1, 2147483647))).setMaxAccess("readonly")
alarmName = MibTableColumn((1, 3, 6, *, *, *, *, *, *, *, *, *, , 3, 1, 3), DisplayString().subtype(subtypeSpec=ValueSizeConstraint(0, 255))).setMaxAccess("readonly")
alarmSeverity = MibTableColumn((1, 3, 6, *, *, *, *, *, *, *, *, *, , 3, 1, 4), AlarmSeverity()).setMaxAccess("readonly")
alarmTime = MibTableColumn((1, 3, 6, *, *, *, *, *, *, *, *, *, , 3, 1, 5), DateAndTime()).setMaxAccess("readonly")
alarmType = MibTableColumn((1, 3, 6, *, *, *, *, *, *, *, *, *, , 3, 1, 6), AlarmType()).setMaxAccess("readonly")
alarmSource = MibTableColumn((1, 3, 6, *, *, *, *, *, *, *, *, *, , 3, 1, 7), DisplayString().subtype(subtypeSpec=ValueSizeConstraint(0, 255))).setMaxAccess( "readonly")
alarmCategory = MibTableColumn((1, 3, 6, *, *, *, *, *, *, *, *, *, , 3, 1, 8), DisplayString().subtype(subtypeSpec=ValueSizeConstraint(0, 255))).setMaxAccess("readonly")
alarmProbableCause = MibTableColumn((1, 3, 6, *, *, *, *, *, *, *, *, *, , 3, 1, 9), ProbableCause()).setMaxAccess("readonly")
alarmComparable = MibTableColumn((1, 3, 6, *, *, *, *, *, *, *, *, *, , 3, 1, 10), DisplayString().subtype(subtypeSpec=ValueSizeConstraint(0, 255))).setMaxAccess("readonly")
alarmAdditionalText = MibTableColumn((1, 3, 6, *, *, *, *, *, *, *, *, *, , 3, 1, 11), DisplayString().subtype(subtypeSpec=ValueSizeConstraint(0, 255))).setMaxAccess("readonly")

1 个答案:

答案 0 :(得分:1)

可以使用pysnmp维护动态SNMP表。有很多方法可以解决这个问题:

  1. 通过调用this示例脚本中的mibInstrumentation.writeVars,定期更新您的表(通过表回调或专用线程)。背面包括在提供新数据和查询时延迟,如果它们在运行更新时出现。但是不需要太多编码。

  2. 扩展MibTableColumn类并实现其readGet / readGetNext方法,以在调用时查看数据并返回OID /值对。这里的复杂性是,要处理 GETNEXT 查询,您需要维护某种一致的OID排序并搜索下一个超过给定的值。

  3. 抛弃整个pysnmp的SMI基础架构,并在您从中读取数据的任何数据源之上实现自己的MIB controller。您需要实现readGet(简单)和可能readGetNext(更复杂,因为需要稳定的OID排序)方法。通过这种方式,您可以放心地学习相当通用和复杂的pysnmp SMI实现的细节,并专注于您的最低要求。

  4. 回答您的其他问题:

    • 重新启动服务只是为了更新服务日期不是一个好主意。
    • 您可以动态更新它(计时器回调或线程),除非您的SNMP表中确实有这么多(2 ^ 31)行。如果它们超过几百,唯一的方法是将所有报警数据保持在现在的状态,在查询到来时读取它并从中构建SNMP响应。
    • 了解OID的哪些部分属于SNMP表索引属于MibTableRowMibTableColumn类。所以,如果你扩展它们就可以解决这个问题。但是为此目的有helper methods