Translating pysnmp oids to human readable strings
birdsong
david.birdsong at gmail.com
Thu Mar 5 16:12:50 EST 2009
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.
More information about the Python-list
mailing list