使用 Pysnmp 从代理端动态更新 SNMP Table
Use Pysnmp to update SNMP Table dynamically from agent side
我一直在寻找一种在 SNMP 代理 运行 期间使用 pysnmp 动态更新 SNMP table 的方法。但到目前为止还没有运气...
The table had been already defined in MIB file(see below), but it seems I need to overwrite its "readGet()" method in order to return correct data from current system status.
的说明
我能够在 SNMP 代理启动之前和 SNMP 代理启动之后使用预定义值构建静态 table:
# 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
它能够return我的预期值。
但是对于我的系统,它会动态生成很多告警信息,这些信息需要更新到SNMP的MIBTable,这样其他SNMP管理器就可以发送"get/getNext"来获取告警信息从我的系统。
所以我想知道
- 有没有办法在 pysnmp 中做到这一点?
- 或者我必须始终静态更新我的闹钟 table?然后在每次更新操作后重新启动 SNMP 代理?
- 或者我必须在 SNMP 代理启动期间用所有可能的 2147483647 实例初始化我的警报 table?并使用 "name[-1]" 从每个查询中获取 index/row 号码?
if so, how about getNext query? does it will ignore those empty table row? or it always return next one, even it is a dummy one?
- 或者是否有更好的方法从查询消息中获取 "index/row" 号码?
@Ilya Etingof,pysnmp专家。有空可以帮我做一下吗?
Br,
-焦大鹏
1.
该警报的 MIB 文件定义table(删除了一些敏感信息)
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")
可以使用 pysnmp 维护动态 SNMP table。有很多方法可以解决这个问题:
通过调用 this 示例脚本中的 mibInstrumentation.writeVars
定期更新您的 table(通过 table 回调或专用线程)。缺点包括在 运行 更新时延迟提供新数据和查询。但不需要太多编码。
扩展 MibTableColumn
class 并实现其 readGet
/readGetNext
方法以在被调用时查看您的数据 return OID/value 对。这里的复杂之处在于,要处理 GETNEXT 查询,您需要维护某种一致的 OID 排序并搜索下一个大于给定的查询。
放弃整个 pysnmp 的 SMI 基础结构,并在您必须从中读取数据的任何数据源之上实施您自己的 MIB controller。您将需要实现 readGet
(简单)和可能的 readGetNext
(更复杂,因为需要 stable OID 排序)方法。这样您就可以从学习相当通用和复杂的 pysnmp SMI 实现的细节中解脱出来,并专注于您的最低要求。
回答您的其他问题:
- 重启服务只是为了更新服务日期不是一个好主意。
- 除非您的 SNMP table 中确实有这么多 (2^31) 行,否则您可以动态更新它(定时器回调或线程)。如果它们超过几百个,唯一的方法是将所有警报数据保留在现在的位置,在查询到来时读取它并从中构建 SNMP 响应。
- 关于 OID 的哪一部分属于 SNMP table 索引的知识属于
MibTableRow
和 MibTableColumn
classes。所以如果你扩展它们,你就可以解决这个问题。不过有 helper methods 用于此目的。
我一直在寻找一种在 SNMP 代理 运行 期间使用 pysnmp 动态更新 SNMP table 的方法。但到目前为止还没有运气...
的说明The table had been already defined in MIB file(see below), but it seems I need to overwrite its "readGet()" method in order to return correct data from current system status.
我能够在 SNMP 代理启动之前和 SNMP 代理启动之后使用预定义值构建静态 table:
# 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
它能够return我的预期值。
但是对于我的系统,它会动态生成很多告警信息,这些信息需要更新到SNMP的MIBTable,这样其他SNMP管理器就可以发送"get/getNext"来获取告警信息从我的系统。
所以我想知道
- 有没有办法在 pysnmp 中做到这一点?
- 或者我必须始终静态更新我的闹钟 table?然后在每次更新操作后重新启动 SNMP 代理?
- 或者我必须在 SNMP 代理启动期间用所有可能的 2147483647 实例初始化我的警报 table?并使用 "name[-1]" 从每个查询中获取 index/row 号码?
if so, how about getNext query? does it will ignore those empty table row? or it always return next one, even it is a dummy one?
- 或者是否有更好的方法从查询消息中获取 "index/row" 号码?
@Ilya Etingof,pysnmp专家。有空可以帮我做一下吗?
Br, -焦大鹏
1.
该警报的 MIB 文件定义table(删除了一些敏感信息)
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")
可以使用 pysnmp 维护动态 SNMP table。有很多方法可以解决这个问题:
通过调用 this 示例脚本中的
mibInstrumentation.writeVars
定期更新您的 table(通过 table 回调或专用线程)。缺点包括在 运行 更新时延迟提供新数据和查询。但不需要太多编码。扩展
MibTableColumn
class 并实现其readGet
/readGetNext
方法以在被调用时查看您的数据 return OID/value 对。这里的复杂之处在于,要处理 GETNEXT 查询,您需要维护某种一致的 OID 排序并搜索下一个大于给定的查询。放弃整个 pysnmp 的 SMI 基础结构,并在您必须从中读取数据的任何数据源之上实施您自己的 MIB controller。您将需要实现
readGet
(简单)和可能的readGetNext
(更复杂,因为需要 stable OID 排序)方法。这样您就可以从学习相当通用和复杂的 pysnmp SMI 实现的细节中解脱出来,并专注于您的最低要求。
回答您的其他问题:
- 重启服务只是为了更新服务日期不是一个好主意。
- 除非您的 SNMP table 中确实有这么多 (2^31) 行,否则您可以动态更新它(定时器回调或线程)。如果它们超过几百个,唯一的方法是将所有警报数据保留在现在的位置,在查询到来时读取它并从中构建 SNMP 响应。
- 关于 OID 的哪一部分属于 SNMP table 索引的知识属于
MibTableRow
和MibTableColumn
classes。所以如果你扩展它们,你就可以解决这个问题。不过有 helper methods 用于此目的。