如果在 table 创建时不知道新的行索引,如何 enable/use pysnmp 上的 SNMPv2 RowStatus 功能?

How to enable/use SNMPv2 RowStatus feature on pysnmp if new row indexes aren't known on table creation?

我正在使用 pysnmp 实现 NTCIP 代理,其中有很多 tables 包含 SNMPv2 RowStatus 列。

我需要允许客户端在现有代理 table 上创建新的概念行,但是在创建这些行之前无法知道它们的索引。因此,我不能在 pysnmp 上创建这样的 RowStatus 对象实例。没有这个实例,客户端没有对象发出 SET 命令以向 table.

添加概念行

在 pysnmp 上有什么办法可以处理这个问题吗?也许是列通用回调机制或类似的东西。

我认为使用 SNMP 通常您无法在不知道索引的情况下远程创建 table 行。因为索引是您向 SNMP 代理传达信息的方式,所以行应该驻留在 table.

中的确切位置

在技术术语中,要为列调用 RowStatus 对象,您需要知道其索引(例如行 ID)。

如果我弄错了,请解释一下它是如何工作的?

另一种情况是当您没有远程创建 table 行,而只是通过 SNMP tables 机制公开您在 SNMP 代理中已有的数据。然后您可以只根据现有数据构建索引。这不需要您的 SNMP 管理器事先知道索引。

可能的 mid-ground 方法是,如果您的 SNMP 代理公开一些信息,SNMP 管理器可以使用这些信息为要创建的 table 行构建适当的索引。

总而言之,我认为讨论将受益于对您的情况的更多提示。 ;-)

我想我发现了创建新行的问题。

原始(ASN.1)mib文件将所有RowStatus列定义为read-write,但是如果符号访问权限不是[=21],pysnmp MibTableColumn createTest方法失败=]read-create。更改 MIB 源上的 RowStatus 定义解决了问题。

这样做之后我可以创建新行,但注意到另一个问题:table 上的 snmp 遍历导致超时。问题是 pysnmp 不知道将哪些值放在新行元素上,这些元素不是索引并且没有定义默认值,因此它放置 None - 这会导致 'Attempted "__hash__" operation on ASN.1 schema object' PyAsn1Error。为了处理这个问题,客户端必须在获取它们之前向新创建的行中的每个字段发出 SET 命令,或者将默认值添加到列对象(对此不确定,但默认值不会被 mibdump 填充,因为原始 ASN.1 mibs 从来没有根据定义,定义不是可选的 itens 的默认值)。我为我的 StaticTable class 导出列的代码如下(代码不完整,但我认为一些方法和属性名称本身就说明了)。

def add_create_test_callback(superclass, create_callback, error_callback=None):
    """Create a class based on superclass that calls callback function when element is changed"""
    class VarCCb(superclass):
        def createTest(self, name, val, idx, acInfo):
            if create_callback and val in [4, 'createAndWait', 5, 'createAndGo']:
                superclass.createTest(self, name, val, idx, acInfo)
                create_callback(name, val, idx, acInfo)
            else:
                if error_callback:
                    error_callback(name, 'optionNotSupported')

                raise error.NoCreationError(idx=idx, name=name)

return VarCCb

class StaticTable:
    # ....

    def config_cols(self):
        """Add callback do RowStatus columns and default values for other columns that are not indices"""
        MibTableColumn, = self.mib_builder.importSymbols('SNMPv2-SMI', 'MibTableColumn')

        _, column_symbols = self.import_column_symbols()

        for index, symbol in enumerate(column_symbols):
            if symbol.syntax.__class__.__name__ == 'DcmRowStatus':
                # add callback for row creation on all row status columns
                MibTableColumnWCb = add_create_test_callback(MibTableColumn, self.create_callback,
                                                               self.error_callback)
                # setMaxAccess needs to be defined, otherwise symbol is defaulted as readonly
                new_col = MibTableColumnWCb(symbol.name, symbol.syntax.clone()).setMaxAccess('readcreate')
                named_col = {symbol.label: new_col}
            elif index >= self.index_n and self.column_default_values:
                new_col = MibTableColumn(symbol.name, symbol.syntax.clone(self.column_default_values[index]))
                named_col = {symbol.label: new_col}
            else:
                new_col = None
                named_col = None

            if new_col:
                self.mib_builder.unexportSymbols(self.mib_name, symbol.label)
                self.mib_builder.exportSymbols(self.mib_name, **named_col)

    # ...

不确定这样做是否正确,如果我错了请指正。也许我不应该在这里包括这个,但它是解决原始问题的方法的一部分,可能会对其他人有所帮助。

谢谢!