Reputation: 319
I am looking to standardize the way in which I retrieve OID indices in PySNMP. I need for all indices to be "fully resolved" regardless of OID and data type. It gets a little complex when the indices are made up of multiple parts and of different data types.
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
Sample output for the above code looks like so:
# 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
My ultimate goal is to end up with a nested dictionary(default dict)
in the format of of mib_dict[node][index] = value
, where mib_dict
is the name of my default dictionary.
As you can tell, my above code does not work for all OIDs. For LLDP-MIB::lldpLocManAddrIfId
the value for index
is ipV4.0x0a0001c8
instead of being 1.4.10.0.1.200
. I can get the IP address portion of the index by doing the following: print('.'.join(('%d' % x for x in index_tuple[1].asNumbers())))
but this would not work for indices that do not have the asNumbers()
attribute.
How can I write a piece of code that works for the indices of all OIDs regardless of OID length and composition(data type(s))? Is there a way to apply the same principle to extracting values?
Upvotes: 0
Views: 525
Reputation: 5555
I am not sure what would be the ideal index
type... One possibility is to have just bare unresolved OID there, the index part of it. If that's a way to go, perhaps you could compute it by cutting the index part off the managed object instance OID.
To figure out the position where to cut the OID, you can use the OID associated with MIB managed object (e.g. LLDP-MIB::lldpLocManAddrIfId) - it's the static prefix of the OID that does not include any variable index part:
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):]
We should have a shortcut in pysnmp to make it simpler...
Upvotes: 2