Как стандартизировать поиск индекса OID в PySNMP?

Я пытаюсь стандартизировать способ получения индексов OID в PySNMP. Мне нужно, чтобы все индексы были «полностью разрешены» независимо от OID и типа данных. Это становится немного сложным, когда индексы состоят из нескольких частей и разных типов данных.

def execute_snmp(transactions, address, pp=True):
    mib_dict = defaultdict(dict)
    for ei, es, ex, vb in transactions:
        if ei:
            raise SNMPAgentUnreachable(ei)
        elif es:
            err_reason = f"{es.prettyPrint()} {ex and transactions[int(ex) - 1][0] or '?'}"
            raise ValueError(err_reason)
        else:
            for mib, val in vb:
                node, index_tuple = mib.getMibSymbol()[1:]
                # print('.'.join(('%d' % x for x in index_tuple[1].asNumbers())))
                # print(*(type(x) for x in index_tuple))
                index = '.'.join(x.prettyPrint() for x in index_tuple)
                print(mib, mib.prettyPrint(), mib.prettyPrint().split('.', 1)[-1], index, sep=' ====== ')
                value = val.prettyPrint() if pp else val
                mib_dict[node][index] = value

Пример вывода для приведенного выше кода выглядит так:

# 1.0.8802.1.1.2.1.3.8.1.5.1.4.10.0.1.200 ====== LLDP-MIB::lldpLocManAddrIfId.ipV4."0x0a0001c8" ====== ipV4."0x0a0001c8" ====== ipV4.0x0a0001c8
# 1.3.6.1.2.1.17.4.3.1.1.228.224.166.29.95.216 ====== BRIDGE-MIB::dot1dTpFdbAddress."e4:e0:a6:1d:5f:d8" ====== "e4:e0:a6:1d:5f:d8" ====== e4:e0:a6:1d:5f:d8
# 1.3.6.1.2.1.4.22.1.4.1.10.0.1.220 ====== IP-MIB::ipNetToMediaType.1.10.0.1.220 ====== 1.10.0.1.220 ====== 1.10.0.1.220

Моя конечная цель — получить вложенный dictionary(default dict) в формате mib_dict[node][index] = value, где mib_dict — это имя моего словаря по умолчанию.

Как вы понимаете, мой приведенный выше код не работает для всех OID. Для LLDP-MIB::lldpLocManAddrIfId значение для index равно ipV4.0x0a0001c8 вместо 1.4.10.0.1.200. Я могу получить часть индекса с IP-адресом, выполнив следующие действия: print('.'.join(('%d' % x for x in index_tuple[1].asNumbers()))), но это не сработает для индексов, не имеющих атрибута asNumbers().

Как я могу написать фрагмент кода, который работает для индексов всех OID независимо от длины и состава OID (типа(ов) данных)? Есть ли способ применить тот же принцип для извлечения значений?


person adamz88    schedule 16.11.2019    source источник


Ответы (1)


Я не уверен, каким был бы идеальный тип index... Одна из возможностей - иметь там просто неразрешенный OID, его индексную часть. Если это возможно, возможно, вы могли бы вычислить его, отрезав часть индекса от OID экземпляра управляемого объекта.

Чтобы определить позицию, в которой нужно вырезать OID, вы можете использовать OID, связанный с управляемым объектом MIB (например, LLDP-MIB::lldpLocManAddrIfId) — это статический префикс OID, который не включает переменную часть индекса:

for var_bind in var_binds:
    object_identity, value = var_bind
    mib_node = object_identity.getMibNode()
    object_instance_oid = object_identity.getOid()
    object_oid = mib_node.getName()
    index_part = object_instance_oid[len(object_oid):]

У нас должен быть ярлык в pysnmp, чтобы сделать его проще...

person Ilya Etingof    schedule 16.11.2019
comment
Работал как шарм! Ярлык в будущих выпусках был бы хорош. :). - person adamz88; 17.11.2019