使用 Pysnmp 从代理端动态更新 SNMP 表

Posted

技术标签:

【中文标题】使用 Pysnmp 从代理端动态更新 SNMP 表【英文标题】:Use Pysnmp to update SNMP Table dynamically from agent side 【发布时间】:2016-08-01 13:00:36 【问题描述】:

我一直在寻找一种在 SNMP 代理运行期间使用 pysnmp 动态更新 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 专家。如果你有时间,你能帮我解决一下吗?

兄弟, -焦大鹏

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】:

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

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

    扩展 MibTableColumn 类并实现其 readGet/readGetNext 方法,以便在调用时查看您的数据并返回 OID/值对。这里的复杂之处在于,要处理 GETNEXT 查询,您需要保持某种一致的 OID 排序并搜索大于给定的下一个。

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

回答您的其他问题:

重启服务只是为了更新它的服务日期不是一个好主意。 您可以动态更新它(定时器回调或线程),除非您的 SNMP 表中确实有这么多 (2^31) 行。如果它们超过数百个,唯一的方法是将所有警报数据保留在当前位置,在查询到来时读取它并从中构建 SNMP 响应。 OID 的哪一部分属于 SNMP 表索引的知识属于MibTableRowMibTableColumn 类。因此,如果您扩展它们,您可以弄清楚。不过有 helper methods 用于此目的。

【讨论】:

以上是关于使用 Pysnmp 从代理端动态更新 SNMP 表的主要内容,如果未能解决你的问题,请参考以下文章

Python网络编程6-使用Pysnmp实现简单网管

使用带有选项 privProtocol=usm3DESEDEPrivProtocol 的 pysnmp 时出错

python pysnmp使用

Python 封装SNMP调用接口

从背景音频代理更新动态磁贴?

请问我电脑如何通过SNMP管理DELL服务器,SNMP协议已经安装,也设置代理,陷阱等,感觉好像还该安装个软件