如果在创建表时不知道新的行索引,如何在pysnmp上启用/使用SNMPv2 RowStatus功能?

时间:2018-03-01 23:21:28

标签: snmp pysnmp

我正在使用pysnmp实现一个NTCIP代理,其中包含许多包含SNMPv2 RowStatus列的表。

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

有没有办法在pysnmp上处理这个?也许是列通用回调机制或类似的东西。

2 个答案:

答案 0 :(得分:1)

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

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

执行此操作后,我可以创建新行,但注意到另一个问题:在表上执行snmp会导致超时。问题是pysnmp不知道哪些值放在不是索引的新行元素上并且没有定义默认值,所以它放置None - 这导致在ASN.1模式对象上'尝试'__hash__“操作' PyAsn1Error。为了处理这个问题,客户端必须在获取它们之前向新创建的行中的每个字段发出SET命令,或者向列对象添加默认值(不确定,但默认值不会被mibdump填充为原始ASN.1 mibs永远不会根据定义,定义itens的默认值,这些默认值不是可选的。我的导出我的StaticTable类列的代码如下(不完整的代码,但我认为一些方法和属性名称可以自己说明。)

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)

    # ...

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

谢谢!

答案 1 :(得分:0)

我认为通常使用SNMP,您无法在不知道其索引的情况下远程创建表行。因为索引是传递SNMP代理的方式,所以该行的确切位于表中。

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

如果我弄错了,请解释一下这是怎么回事?

另一种情况是,您不是远程创建表行,而只是通过SNMP表机制公开SNMP代理中已有的数据。然后你可以从现有数据中建立索引。这不需要您的SNMP管理员事先知道索引。

如果您的SNMP代理公开了SNMP管理器可以用来为要创建的表行构建正确索引的一些信息,那么可能的中间方法就是这样。

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