vincentbernat / snimpy

interactive SNMP tool with Python
http://snimpy.readthedocs.org/
185 stars 44 forks source link

how do I get an OID from a MIB node ? #85

Closed cbueche closed 6 years ago

cbueche commented 6 years ago

Hi Vincent and others,

My goal is to collect some large tables from the Cisco cbQoS using bulkwalk. I cannot use the high-level snimpy approach because my tables contain multiple columns. Such a table is cbQosServicePolicyTable (12 oids in it, recent versions have 14).

My current approach is: session.walkmore('1.3.6.1.4.1.9.9.166.1.1.1.1')

However, I would like to use the node-name "cbQosServicePolicyEntry" instead of the numerical oid. I have seen the mib module and its class class snimpy.mib.Node(node) plus the oid property, but I can't come to something that work. I thought something like this should do it ?

nodex = self.mib.Node("cbQosServicePolicy")
myoid = nodex.oid

but well, I'm untangled in those objects hierarchy since a few hours... Hints welcome !

vincentbernat commented 6 years ago

If the high cardinality is in the number of rows, you should be able to just walk each column separately.

If you have a manager m, you can use m.cbQosServicePolicy.proxy.oid to get the OID.

cbueche commented 6 years ago

Thanks for your answer (and the quick patching for Python 3.7 !).

I know I can walk each column, but I need about 30 of them (Cisco QoS is braindead...) so I will stick to walkmore().

I tried the m.XXX.proxy.oid, but I can only get the OID of a column, not of the enclosing table. Here is an example. I want the oid of CbQosServicePolicyEntry, which is 1.3.6.1.4.1.9.9.166.1.1.1.1, but I can only access one of its column, e.g. o = m.cbQosIfIndex.proxy.oid, which gives 1.3.6.1.4.1.9.9.166.1.1.1.1.4, as expected. Is there a way to get the enclosing OID ? See below the MIB excerpt.

The error:

  File ".../aj/qos.py", line 69, in collect
    ooidxx = m.CbQosServicePolicyEntry.proxy.oid
  File ".../venv/lib/python3.7/site-packages/snimpy/manager.py", line 318, in __getattribute__
    m, a = self._locate(attribute)
  File ".../venv/lib/python3.7/site-packages/snimpy/manager.py", line 313, in _locate
    raise AttributeError("{0} is not an attribute".format(attribute))
AttributeError: CbQosServicePolicyEntry is not an attribute

Thanks for your help !

-- The cbQosServicePolicy group

cbQosServicePolicyTable OBJECT-TYPE
    SYNTAX          SEQUENCE OF CbQosServicePolicyEntry 
    MAX-ACCESS      not-accessible
    STATUS          current
    DESCRIPTION
        "This table describes the logical interfaces/media types
        and the policymap that are attached to it."
    ::= { cbQosServicePolicy 1 }

cbQosServicePolicyEntry OBJECT-TYPE
    SYNTAX          CbQosServicePolicyEntry
    MAX-ACCESS      not-accessible
    STATUS          current
    DESCRIPTION
        "Each entry in this table describes to which a logical
        interface a given policymap is attached.  Depending on 
        the logical interface/media type, some fields may have
        meaningful values, and some may not.  Please see each
        individual descriptions."
    INDEX           { cbQosPolicyIndex } 
    ::= { cbQosServicePolicyTable 1 }

CbQosServicePolicyEntry ::= SEQUENCE {
        cbQosPolicyIndex             Unsigned32,
        cbQosIfType                  InterfaceType,
        cbQosPolicyDirection         TrafficDirection,
        cbQosIfIndex                 InterfaceIndex,
        cbQosFrDLCI                  DlciNumber,
        cbQosAtmVPI                  Unsigned32,
        cbQosAtmVCI                  Unsigned32,
        cbQosEntityIndex             EntPhysicalIndexOrZero,
        cbQosVlanIndex               VlanIndex,
        cbQosEVC                     Unsigned32,
        cbQosPolicyDiscontinuityTime TimeStamp,
        cbQosParentPolicyIndex       Unsigned32
}
vincentbernat commented 6 years ago

You can use m.cbQosServicePolicyTable.proxy.oid, but for some reason, it returns the first column instead. So, with the mib module, you can mib.get('IF-MIB', 'ifEntry').oid.

cbueche commented 6 years ago

thx again Vincent! mib.get() works, but for nodes only. cbQosIfIndex is a node, but the enclosing CbQosServicePolicyEntry is a table, so I end up with an exception. Anyway, this is not really the idea of snimpy to do such things so I stop annoying you with these details !

def get(mib, name):
    """Get a node by its name.

    :param mib: The MIB name to query
    :param name: The object name to get from the MIB
    :return: the requested MIB node (:class:`Node`)
    """
    if not isinstance(mib, bytes):
        mib = mib.encode("ascii")
    module = _get_module(mib)
    if module is None:
        raise SMIException("no module named {0}".format(mib))
    node = _smi.smiGetNode(module, name.encode("ascii"))
    if node == ffi.NULL:
        raise SMIException("in {0}, no node named {1}".format(
            mib, name))
    pnode = _kind2object(node.nodekind)
    return pnode(node)
cbueche commented 6 years ago

mea culpa, it just works !

myoid = mib.get('CISCO-CLASS-BASED-QOS-MIB', 'cbQosServicePolicyEntry').oid
#<class 'tuple'>: (1, 3, 6, 1, 4, 1, 9, 9, 166, 1, 1, 1, 1)

You rock, thanks a million !