Translating pysnmp oids to human readable strings

birdsong david.birdsong at gmail.com
Thu Mar 5 19:10:24 EST 2009


On Mar 5, 2:30 pm, SpamMePlease PleasePlease
<spankthes... at googlemail.com> wrote:
> On Thu, Mar 5, 2009 at 10:12 PM, birdsong <david.birds... at gmail.com> wrote:
> > On Mar 5, 1:05 pm, birdsong <david.birds... at gmail.com> wrote:
> >> On Mar 5, 12:32 pm, SpamMePlease PleasePlease
>
> >> <spankthes... at googlemail.com> wrote:
> >> > Hey list,
>
> >> > I was given a task, to reproduce functionality of command specified
> >> > below by writing proper python functions to reuse in some monitoring
> >> > script:
>
> >> > rivendell# snmpwalk -Os -mALL -v1 -cgabilgathol 10.0.6.66
> >> > .1.3.6.1.4.1.2636.5.1.1.2
> >> > jnxBgpM2PeerIdentifier.0.ipv4."".unknown."".0.1.38.101.87.145 =
> >> > STRING: 66.250.1.253
> >> > jnxBgpM2PeerIdentifier.0.ipv4.38.101.161.119.1.38.101.161.118 =
> >> > STRING: 66.28.1.85
> >> > jnxBgpM2PeerIdentifier.0.ipv4.64.200.59.74.1.64.200.59.73 = STRING: 64.200.68.12
> >> > jnxBgpM2PeerIdentifier.0.ipv4.72.37.131.250.1.72.37.131.249 = STRING:
> >> > 64.235.224.240
> >> > jnxBgpM2PeerState.0.ipv4."".unknown."".0.1.38.101.87.145 = INTEGER:
> >> > established(6)
> >> > jnxBgpM2PeerState.0.ipv4.38.101.161.119.1.38.101.161.118 = INTEGER:
> >> > established(6)
> >> > jnxBgpM2PeerState.0.ipv4.64.200.59.74.1.64.200.59.73 = INTEGER: established(6)
> >> > jnxBgpM2PeerState.0.ipv4.72.37.131.250.1.72.37.131.249 = INTEGER: established(6)
> >> > (more output)
>
> >> > I have already found a pysnmp library to fetch the data from the
> >> > device with a minimal amount of code:
>
> >> > from pysnmp.entity.rfc3413.oneliner import cmdgen
> >> > from pysnmp.smi import *
> >> > import string
>
> >> > cmdGen = cmdgen.CommandGenerator()
> >> > errorIndication, errorStatus, errorIndex, varBinds =
> >> > cmdgen.CommandGenerator().nextCmd(cmdgen.CommunityData('AmonMuil',
> >> > 'gabilgathol', 0),
> >> > cmdgen.UdpTransportTarget(('fw-1.datacenter.gondor.net', 161)),
> >> > (1,3,6,1,4,1,2636,5,1,1,2))
>
> >> > print errorIndication, errorStatus
> >> > for i in varBinds:
> >> >     print i
>
> >> > The problem is that I have completely stuck on the result I am
> >> > experiencing being totally human unreadable, like this:
>
> >> > rivendell# python snmp.py
> >> > None 0
> >> > [(ObjectName('1.3.6.1.4.1.2636.5.1.1.2.1.1.1.1.0.1.0.0.0.0.1.38.101.87.145'),
> >> > OctetString('B\xfa\x01\xfd'))]
> >> > [(ObjectName('1.3.6.1.4.1.2636.5.1.1.2.1.1.1.1.0.1.38.101.161.119.1.38.101.161.118'),
> >> > OctetString('B\x1c\x01U'))]
> >> > [(ObjectName('1.3.6.1.4.1.2636.5.1.1.2.1.1.1.1.0.1.64.200.59.74.1.64.200.59.73'),
> >> > OctetString('@\xc8D\x0c'))]
> >> > [(ObjectName('1.3.6.1.4.1.2636.5.1.1.2.1.1.1.1.0.1.72.37.131.250.1.72.37.131.249'),
> >> > OctetString('@\xeb\xe0\xf0'))]
> >> > [(ObjectName('1.3.6.1.4.1.2636.5.1.1.2.1.1.1.2.0.1.0.0.0.0.1.38.101.87.145'),
> >> > Integer32('6'))]
> >> > [(ObjectName('1.3.6.1.4.1.2636.5.1.1.2.1.1.1.2.0.1.38.101.161.119.1.38.101.161.118'),
> >> > Integer32('6'))]
> >> > [(ObjectName('1.3.6.1.4.1.2636.5.1.1.2.1.1.1.2.0.1.64.200.59.74.1.64.200.59.73'),
> >> > Integer32('6'))]
> >> > [(ObjectName('1.3.6.1.4.1.2636.5.1.1.2.1.1.1.2.0.1.72.37.131.250.1.72.37.131.249'),
> >> > Integer32('6'))]
> >> > [(ObjectName('1.3.6.1.4.1.2636.5.1.1.2.1.1.1.3.0.1.0.0.0.0.1.38.101.87.145'),
> >> > Integer32('2'))]
>
> >> > Since I cant find any way to translate these numbers to the same thing
> >> > snmpwalk produce, is there any clue on how to achieve that? Is it
> >> > possible at all for different devices (this one happend to be Juniper
> >> > firewall if that does matter). Also, how can I know where does this
> >> > magic oid ends and where does additional information starts (like ip
> >> > addresses added to oid 0 they all looks like another oid string
> >> > numbers) ?
>
> >> > Any sample of code, or hint to another lib will be very appreciated!
>
> >> > --
> >> > --------------------
> >> > Spank The Spam!
>
> >> Here's an example of walk that's part of a class I wrote, hopefully
> >> indentation survives the paste.  I borrowed heavily from example code
> >> on the pysnmp site.
>
> >> from pysnmp import asn1, v2c
> >> from pysnmp import role
>
> >>   def walk(self, community_string, base_oids):
>
> >>     if type(base_oids) is str: base_oids = [base_oids]
> >>     # this this does what it says, dont bother asking for oids that
> >> we'll see in our walk
> >>     base_oids = self.remove_child_oids(base_oids)
> >>     # h_pair is just (host, port)
> >>     client = role.manager(self.h_pair)
> >>     client.timeout = 10
> >>     req = v2c.GETNEXTREQUEST(community=community_string)
> >>     rsp = v2c.GETRESPONSE()
> >>     req['encoded_oids'] = map(asn1.OBJECTID().encode, base_oids)
>
> >>     oids_values = {}
> >>     while req['encoded_oids']:
> >>       try:
> >>         answer, host_tuple = client.send_and_receive(req.encode())
> >>       except (role.NoResponse, role.NetworkError):
> >>         return oids_values
>
> >>       rsp.decode(answer)
>
> >>       parsed_oids_vals = self.parse_response(rsp, base_oids)
> >>       oids_values.update(parsed_oids_vals)
>
> >>       req['request_id'] += 1
> >>       req['encoded_oids'] = map(asn1.OBJECTID().encode,
> >> parsed_oids_vals.keys())
>
> >>     return oids_values
>
> > Just realized the parse_response() is needed to makes sense of it:
>
> > def parse_response(self, rsp, head_oids):
> >    # list of indices
> >    overshot_oids = []
>
> >    vals = map(lambda x: x[0](), map(asn1.decode, rsp
> > ['encoded_vals']))
> >    oids = map(lambda x: asn1.OBJECTID().decode(x)[0], rsp
> > ['encoded_oids'])
> >    oids_vals = dict(map(None, oids, vals))
>
> >    for oid in oids_vals:
> >      if not filter(lambda h: asn1.OBJECTID(h).isaprefix(oid),
> > head_oids):
> >        overshot_oids.append(oid)
>
> >    map(lambda x: oids_vals.pop(x), overshot_oids)
>
> >    return oids_vals
>
> > I welcome critique btw, I'm here to learn.
> > --
> >http://mail.python.org/mailman/listinfo/python-list
>
> Sorry, but I dont understand the code at all. Where does it takes the
> names for the oid numbers? Why the translation needs a 'walk' at all?
> Isnt that possible to perform an acion on given oid (my code produces
> a list of them) to translate it to human readable output like snmpwalk
> binary does?
>
> --
> --------------------
> Spank The Spam!

I haven't looked at the newer version of pysnmp, but I dont know if
there's a library that maps oids to human readable oids.  Besides, I
didn't really need to read the OIDs as a human, I wanted the values
for injecting into data stores.  Here's a link I found really helpful
while figuring out my necessary OIDs
http://www.oid-info.com/

I was responding to your call for example code.  I didn't get this in
the first 2 hours I poured over pysnmp either. Experiment in the
interpreter, you'll get it. You should be able to use my two functions
with very minor editing to walk an oid and return values in a
dictionary. The values will have already been decoded to something you
should recognize.



More information about the Python-list mailing list