Giter VIP home page Giter VIP logo

snimpy's Introduction

snimpy

image

image

image

---

Interactive SNMP tool.

Snimpy is a Python-based tool providing a simple interface to build SNMP query. Here is a very simplistic example that allows us to display the routing table of a given host:

load("IP-FORWARD-MIB")
m=M("localhost", "public", 2)
routes = m.ipCidrRouteNextHop
for x in routes:
    net, netmask, tos, src = x
    print("%15s/%-15s via %-15s src %-15s" % (net, netmask, routes[x], src))

You can either use Snimpy interactively throught its console (derived from Python own console or from IPython if available) or write Snimpy scripts which are just Python scripts with some global variables available.

Snimpy requires libsmi to work correctly. See the documentation for more information.

Features

Snimpy is aimed at being the more Pythonic possible. You should forget that you are doing SNMP requests. Snimpy will rely on MIB to hide SNMP details. Here are some "features":

  • MIB parser based on libsmi (through CFFI)
  • SNMP requests are handled by PySNMP (SNMPv1, SNMPv2 and SNMPv3 support)
  • scalars are just attributes of your session object
  • columns are like a Python dictionary and made available as an attribute
  • getting an attribute is like issuing a GET method
  • setting an attribute is like issuing a SET method
  • iterating over a table is like using GETNEXT
  • when something goes wrong, you get an exception

snimpy's People

Contributors

daemonae avatar dependabot[bot] avatar edouard-lopez avatar fragfutter avatar joostdetollenaere avatar juliantaylor avatar maugier avatar robertcheramy avatar sergitron2 avatar stgraber avatar unikmhz avatar vincentbernat avatar wroniasty avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

snimpy's Issues

Docs (readthedocs) with some problems

The docs from snimpy are with errors in the API reference:

As a workarround, users can use the docs from snimpy 0.8.0:

However, the problem doesn't exist if the docs are generated in a development env using make docs. All the docs are correctly generated.

May be was interesting to generate new docs and uploading them to the readthedocs.

PS: Thanks for the project!

Report exception on "No Such Object on this agent at this OID"

Hi there,

There is no disctintion between the return type when a device reports it doesn't support a requested OID, and when the device reports an empty result. A quick example:

snmpwalk -c public -v 2c sw-foo lldpRemSysName
LLDP-MIB::lldpRemSysName = No Such Object available on this agent at this OID
snmpwalk -c public -v 2c sw-bar lldpRemSysName
LLDP-MIB::lldpRemSysName = No Such Instance currently exists at this OID

But in snimpy:

dict(dev["sw-foo"]._snmp._m.lldpRemSysName)
{}
dict(dev["sw-bar"]._snmp._m.lldpRemSysName)
{}

I tried to make a quick fix, but lost myself to the ProxyColumn object.

Cheers

Table traversal

Not a real issue, just some notes to table traversal:
(1) the recipe for table traversal in documentation is wrong (very inefficient):

for index in manager.ifDescr:
    print(manager.ifDescr[index]) # results in one more (useless) SNMP get
                                  # for every iteration

it shoud be rewritten (should work in head, but tested only with 0.8.3) as:

for index, ifDescr in manager.ifDescr.iteritems():
    print(ifDescr)

or without the index if you also implement a ProxyColumn.itervalues(),
(2) in last versions, one is allowed to change the default bulk parameters, but I would propose to change them also "per traversal" - like .iteritems(bulk = False) or .iteritems(max_bulk = 10) - it is quite usefull,
(3) why does the .iteritems() method walk all values before yielding first item? it could yield first value(s) after first (bulk) response -- this would not only speed up first results, but would be also more efficient if the caller does not consume all the values (i.e. break in the mentioned for ... constructs).

RuntimeError due to Dictionary Size change when Cache is enabled

- STACKTRACE

[2015-06-11 16:04:16,276: WARNING/Worker-3] Traceback (most recent call last):
  File "/home/masac/masac/masac/seed/tasks.py", line 382, in send_router_metrics
    metrics[m.ifDescr[index]]['ifHCOutOctets'] = m.ifHCOutOctets[index]
  File "/home/masac/.virtualenvs/masac-dj1.8-py3.4/lib/python3.4/site-packages/snimpy/manager.py", line 365, in __getitem__
    return self._op("get", index)
  File "/home/masac/.virtualenvs/masac-dj1.8-py3.4/lib/python3.4/site-packages/snimpy/manager.py", line 352, in _op
    *args)
  File "/home/masac/.virtualenvs/masac-dj1.8-py3.4/lib/python3.4/site-packages/snimpy/manager.py", line 122, in get
    return self.getorwalk("get", *args)
  File "/home/masac/.virtualenvs/masac-dj1.8-py3.4/lib/python3.4/site-packages/snimpy/manager.py", line 118, in getorwalk
    self.flush()
  File "/home/masac/.virtualenvs/masac-dj1.8-py3.4/lib/python3.4/site-packages/snimpy/manager.py", line 132, in flush
    for k in keys:
RuntimeError: dictionary changed size during iteration


  • If you put a condition while looping on m.ifDescr, while cache is enabled, you get the above error.
metrics = {}
                        try:
                                m = M(host=ip, retries=0, community=comm, version=2, timeout=SWITCH_TIMEOUT, cache=1)
                        except:
                                print(traceback.format_exc())
                        try:
                                for index in m.ifDescr:
                                        try:
                                                if "thernet" in str(m.ifDescr[index]) and "unrouted" not in str(m.ifDescr[index]) and "Vlan" not in str(m.ifDescr[index]) and "Null" not in str(m.ifDescr[index]):
                                                        metrics[m.ifDescr[index]] = {}
                                                        metrics[m.ifDescr[index]]['ifHCOutOctets'] = m.ifHCOutOctets[index]
                                                        metrics[m.ifDescr[index]]['ifHCInOctets'] = m.ifHCInOctets[index]
                                                        # print(index, repr(m.ifDescr[index]), repr(m.ifHCOutOctets[index]), repr(m.ifHCInOctets[index]))
                                        except SNMPNoSuchInstance:
                                                if LOG_DEBUG == True:
                                                        print("SNMPNoSuchInstance for " + hostname + " " + ip + " " + comm)
                                                continue
                        except gaierror as ge:
                                # print(traceback.format_exc())
                                print("gaierror for " + hostname + " " + ip + " " + comm)
                                if LOG_DEBUG == True:
                                        print("Snimpy Manager Exception: gaierror")
### Remainder of code.....

More OIDs returned when calling walk on snmp.Session

Hi all,

I try to call walk directly on a Session instance. The data returned do start at the correct point/OID, however there are extra OIDs at the end. I suspect I am doing something wrong when calling it. Minimal example:

#!/usr/bin/env python

import argparse
from snimpy.snmp import Session as S

parser = argparse.ArgumentParser()
parser.add_argument("host", default="localhost", nargs="?",
                    help="Agent to retrieve variables from")
parser.add_argument("community", default="public", nargs="?",
                    help="Community to query the agent")
options = parser.parse_args()

s = S(options.host, options.community, 2)

res = s.walk((1,3,6,1,2,1,2,2,1))
for r in res:
    oid = ".".join(str(v) for v in r[0])
    print(oid)

The output is:

1.3.6.1.2.1.2.2.1.1.1
1.3.6.1.2.1.2.2.1.1.2
1.3.6.1.2.1.2.2.1.1.3
1.3.6.1.2.1.2.2.1.2.1
1.3.6.1.2.1.2.2.1.2.2
...
1.3.6.1.2.1.2.2.1.22.3
1.3.6.1.2.1.3.1.1.1.2.1.192.168.2.25
1.3.6.1.2.1.3.1.1.1.2.1.192.168.2.61
1.3.6.1.2.1.3.1.1.1.2.1.192.168.2.253
1.3.6.1.2.1.3.1.1.1.3.1.192.168.4.2
1.3.6.1.2.1.3.1.1.2.2.1.192.168.2.25
1.3.6.1.2.1.3.1.1.2.2.1.192.168.2.61
1.3.6.1.2.1.3.1.1.2.2.1.192.168.2.253
1.3.6.1.2.1.3.1.1.2.3.1.192.168.4.2
1.3.6.1.2.1.3.1.1.3.2.1.192.168.2.25
1.3.6.1.2.1.3.1.1.3.2.1.192.168.2.61
1.3.6.1.2.1.3.1.1.3.2.1.192.168.2.253
1.3.6.1.2.1.3.1.1.3.3.1.192.168.4.2
1.3.6.1.2.1.4.1.0
1.3.6.1.2.1.4.2.0

Shouldn't it stop at 1.3.6.1.2.1.2.2.1.22.3? Why am I getting the extra ones? I also tried the walk using a string instead of a tuple... same output. Any help would be appreciated.

Thanks,

Andreas

Add agent support

Currently, snimpy only implements a manager. Adding agent support would be nice. At first, constant values could be registered to the agent with the exact same syntax than with the manager :

a = Agent()
a.ifDescr[2] = "eth0"
a.ifDescr[3] = "eth1"
a.ifInOctets[2] = 54548754
a.ifInOctets[3] = 0
a.serve()

Then, we could attach functions. When attached to a table object, they will be provided with the appropriate index.

def randomValue(ifindex):
   if ifindex in range(2,6):
      return random.randint(0, 1 << 32 - 1)
   return None

a = Agent()
a.ifDescr[2] = "eth0"
a.ifDescr[3] = "eth1"
a.ifDescr[4] = "eth2"
a.ifDescr[5] = "eth3"
a.ifInOctets = randomValue
a.ifOutOctets = randomValue

Later, we could add write support too!

Attribute missing

Running snimpy on OSX and trying to get list of OIDS from mib files. I'm going through the examples in the docs to test it out and I'm getting this error in every format. I've tried through the console, as a script, and a python module.

mib.py

#!/usr/bin/env snimpy

load("RS-COMMON-MIB.mib")
m = M("localhost")
print(m.ifDescr[0])

Error


Traceback (most recent call last):
  File "/usr/local/bin/snimpy", line 11, in <module>
    sys.exit(interact())
  File "/usr/local/lib/python2.7/site-packages/snimpy/main.py", line 70, in interact
    exec(compile(open(argv[0]).read(), argv[0], 'exec')) in local
  File "mib.py", line 5, in <module>
    print(m.ifDescr[0])
  File "/usr/local/lib/python2.7/site-packages/snimpy/manager.py", line 316, in __getattribute__
    m, a = self._locate(attribute)
  File "/usr/local/lib/python2.7/site-packages/snimpy/manager.py", line 311, in _locate
    raise AttributeError("{0} is not an attribute".format(attribute))
AttributeError: ifDescr is not an attribute

SegFault on Ubuntu 14.04

Hello,

I'm trying to use snimpy on my monitoring environnement and a segfault has been raised. On my laptop (where plugins has been developed), i'm using virtualenv and python 2.7. No problem to run my script on my laptop.
On my production environement, no virtualenv but python 2.7 too and script raised a segfault.

On production env, snimpy has been installed with apt-get method.

This is my script:

#!/usr/bin/python
from snimpy.manager import Manager as M
from snimpy.manager import load
import optparse
import os
import sys
import optparse
import struct

load("mibs/SNMPv2-TC.my")
load("mibs/PerfHist-TC-MIB.my")
load("mibs/ADSL-LINE-MIB.my")
load("mibs/IF-MIB.my")
VERSION = "0.1"
OK = 0
WARNING = 1
CRITICAL = 2
UNKNOWN = 3

def _divised_by_ten(value):
   value = value / 10
   return value

def _convert_bytes(value):
   value = value / 1000000.00
   return value

def _run_adsl_state(m):
  for index in m.adslAtucCurrOutputPwr:
    sync_down_speed = m.adslAtucChanCurrTxRate[index]
    sync_up_speed = m.adslAturCurrAttainableRate[index]
    atn = m.adslAtucCurrAtn[index]
    snr = m.adslAturCurrSnrMgn[index]
    error = m.adslAturPerfESs[index]
    text = "ADSL status UP: {0} DOWN: {1}".format(_convert_bytes(sync_up_speed), _convert_bytes(sync_down_speed))

    print text
    sys.exit(0)
  print "Error"
  sys.exit(0)

parser = optparse.OptionParser(
    "%prog [options]", version="%prog " + VERSION)
parser.add_option('-H', '--hostname',
                  dest="hostname", help='Hostname to connect to')
if __name__ == '__main__':
  # Ok first job : parse args
  opts, args = parser.parse_args()
  sys.exit(0)
  host = opts.hostname

  m = M(host=host,
     version=3,
     secname="monit",
     authprotocol="MD5", authpassword="xxxx",
     privprotocol="DES", privpassword="xxxx")
  _run_adsl_state(m)

Please find stack trace related to this code:

Program received signal SIGSEGV, Segmentation fault.
0x00007ffff4aeff74 in duplicateType () from /usr/lib/x86_64-linux-gnu/libsmi.so.2
(gdb) backtrace
#0  0x00007ffff4aeff74 in duplicateType () from /usr/lib/x86_64-linux-gnu/libsmi.so.2
#1  0x00007ffff4b001a1 in smiparse () from /usr/lib/x86_64-linux-gnu/libsmi.so.2
#2  0x00007ffff4af19db in loadModule () from /usr/lib/x86_64-linux-gnu/libsmi.so.2
#3  0x00007ffff4af7c0a in smiLoadModule () from /usr/lib/x86_64-linux-gnu/libsmi.so.2
#4  0x00007ffff4af7e90 in smiReadConfig () from /usr/lib/x86_64-linux-gnu/libsmi.so.2
#5  0x00007ffff4af79c3 in smiInit () from /usr/lib/x86_64-linux-gnu/libsmi.so.2
#6  0x00007ffff4d4019c in _cffi_f_smiInit (self=<optimized out>, arg0=0x7ffff7ea6480) at /usr/lib/python2.7/dist-packages/snimpy/__pycache__/_cffi__x3a5e05ccxa0dd8598.c:929
#7  0x0000000000499c7b in PyEval_EvalFrameEx ()
#8  0x0000000000499ef2 in PyEval_EvalFrameEx ()
#9  0x00000000004a090c in PyEval_EvalCodeEx ()
#10 0x0000000000588d42 in PyEval_EvalCode ()
#11 0x0000000000588dfa in PyImport_ExecCodeModuleEx ()
#12 0x00000000005b1f0f in ?? ()
#13 0x0000000000540948 in ?? ()
#14 0x0000000000487195 in ?? ()
#15 0x00000000005411c1 in ?? ()
#16 0x000000000051dd20 in ?? ()
#17 0x00000000004dc9cb in PyEval_CallObjectWithKeywords ()
#18 0x000000000049b87e in PyEval_EvalFrameEx ()
#19 0x00000000004a090c in PyEval_EvalCodeEx ()
#20 0x0000000000588d42 in PyEval_EvalCode ()
#21 0x0000000000588dfa in PyImport_ExecCodeModuleEx ()
#22 0x00000000005b1f0f in ?? ()
#23 0x0000000000540948 in ?? ()
#24 0x0000000000540d08 in ?? ()
#25 0x0000000000541510 in ?? ()
#26 0x000000000051dc50 in ?? ()
#27 0x00000000004dc9cb in PyEval_CallObjectWithKeywords ()
#28 0x000000000049b87e in PyEval_EvalFrameEx ()
#29 0x00000000004a1634 in ?? ()
#30 0x000000000044e4a5 in PyRun_FileExFlags ()
#31 0x000000000044ec9f in PyRun_SimpleFileExFlags ()
#32 0x000000000044f904 in Py_Main ()
#33 0x00007ffff7818ec5 in __libc_start_main (main=0x44f9c2 <main>, argc=4, argv=0x7fffffffe5d8, init=<optimized out>, fini=<optimized out>, rtld_fini=<optimized out>, stack_end=0x7fffffffe5c8)
    at libc-start.c:287
#34 0x0000000000578c4e in _start ()

Has i can see, libsmi2 generate a "duplicateType" error. Do you know what it means ?
Any relation with apt package ?

Thanks in advance.
Regards.

Benchmark comparison: Snimpy vs netsnmp

We've been using the netsnmp package for a while in collecting data from our network devices. Unfortunately, due to the lack of a BULKWALK implementation and the significant memory leak we've found with the WALK implementation we've had to look to alternatives. fastsnmpy was the first adapter/extension/package we came across that did well to fetch data we needed. However, the BULKWALK implementation would sometimes skip the first OID. I've attempted, thus far unsuccessfully, to modify it myself but I cannot seem to get it to behave properly. Thankfully snimpy has made the process much easier

One concern we have is with the performance of snimpy. We've completed a cloned script that replaces fastsnmpy with snimpy with success and compared it to the older implementation. Unfortunately we have found that snimpy runs at half the speed of fastsnmpy. I am not 100% certain if this is due to how we implemented it or if this is to be expected.

Statistics


Devices being polled: 2,693
Values being accessed per device: varies, 4 to 64
Each device being queried is done immediately one after the other.
Script goes through all devices then sleeps for 5 minutes before looping again.
Script runs 24/7

Timed Results

fastsnmpy : averages 124 seconds
snimpy : averages 242 seconds

Memory footprint:

fastsnmpy WALK: 30MB for first loop, adds 10MB for every loop thereafter (yikes!!)
fastsnmpy GETBULK: 40MB avg. throughout full runtime
snimpy : 45MB avg. throughout full runtime


Source Code (for implementation comparison)

With snimpy
def Query(self, arrays, community_str):
        responded = {}                                  # Valid Arrays, used for ZIP
        doc_uploaded = 0
        doc_failed = 0
        for array in arrays:                    
            try:
                session = M(array, community_str, timeout = 2, retries = 1, cache = True)
                antennas = {}
                model = str(session.arrayModel)
                ip = str(session.ethIPAddress[1])
                slots = 0
                for ant in session.iapType:
                    slots = ant                         
                    if session.iapPresent[ant] and not session.iapDot11Mode[ant] == 2:                  
                        antennas[ant] = session.iapNumStations[ant]         
                responded[array] = {'model' : model, 'ip' : ip, 'antennas' : antennas, 'radioSlots' : slots}
                #del session
                #del antennas
            except:                 # Host is not found. Quick alternative to a PING
                continue
            . . .
Using fastsnmpy

(method seqwalk() is essentially just netsnmp.Session.walk())

def Query(self, arrays, community_str, var):    # `var` is a List of OIDs to target. We have only three for this script
        session = SnmpSession ( timeout = 1000000 ,
                retries = 1,
                verbose = self.verbose,
                oidlist = var,
                targets = arrays, 
                community = community_str
                )

        #results = session.bulkwalk()       # Sometimes omits the first value/OID returned. I'll debug this myself in the future
        results = session.seqwalk()     # Finished.
        del session

        last_host = None
        hosts = []                                # the list of hosts
        host_responses = []                   # the list of responses for each host
        responses = []
        for output in results:
            if output.val is not None:
                if output.hostname != last_host:         # new host
                    if last_host:    # only append host_responses after a new host
                        host_responses.append(responses)
                    hosts.append(output.hostname)
                    responses = [output.val]             # start the new list of responses
                    last_host = output.hostname
                else:                                            # same host, append the response
                    responses.append(output.val)
            . . .

If there's something I'm doing wrong I would greatly appreciate the feedback, however I must insist that you attempt to benchmark something similar and compare it with netsnmp. I am of the opinion that snimpy can perform faster than this.

SmiObject.conformance always returns 1

Hi again.

Already have snmpd running and can query:

[root@t21 ~]# snmpwalk -m+SNMPv2-MIB -c public localhost sysDescr.0
SNMPv2-MIB::sysDescr.0 = STRING: Linux t21 3.10.12 #1 SMP Thu Oct 23 11:15:42 EDT 2014 armv7l

Trying an example script:

from snimpy.manager import Manager as M
from snimpy.manager import load

load("/usr/share/snmp/mibs/SNMPv2-MIB")
m = M("localhost", "public", 2)
print(m.sysDescr)

Would always return this:

Traceback (most recent call last):
  File "test.py", line 4, in <module>
    load("/usr/share/snmp/mibs//SNMPv2-MIB")
  File "/usr/lib/python2.7/site-packages/snimpy-0.8.4-py2.7-linux-x86_64.egg/snimpy/manager.py", line 435, in load
    m = mib.load(mibname)
  File "/usr/lib/python2.7/site-packages/snimpy-0.8.4-py2.7-linux-x86_64.egg/snimpy/mib.py", line 550, in load
    "(check with smilint -s -l1)".format(mib))
snimpy.mib.SMIException: /usr/share/snmp/mibs/IF-MIB.txt contains major SMI error (check with smilint -s -l1)

Tried with other well know mibs and verified that the MIB is OK:

$ smilint -l1 -s SNMPv2-MIB
$ echo $?
0

Seems that the SmiObject.conformance was returning 1:

-> if m.conformance and m.conformance <= 1:
(Pdb) print ffi
<cffi.api.FFI object at 0x17360f0>
(Pdb) print m.conformance
1
(Pdb) print m
<cdata 'SmiModule *' 0x1580368>

So I thought I would just bypass that error to see what happens

Traceback (most recent call last):
  File "test.py", line 6, in <module>
    print(m.sysDescr)
  File "/usr/lib/python2.7/site-packages/snimpy-0.8.4-py2.7-linux-x86_64.egg/snimpy/manager.py", line 269, in __getattribute__
    oid, result = self._session.get(a.oid + (0,))[0]
  File "/usr/lib/python2.7/site-packages/snimpy-0.8.4-py2.7-linux-x86_64.egg/snimpy/snmp.py", line 256, in get
    return self._op(self._cmdgen.getCmd, *oids)
  File "/usr/lib/python2.7/site-packages/snimpy-0.8.4-py2.7-linux-x86_64.egg/snimpy/snmp.py", line 248, in _op
    return tuple([(oid, self._convert(val)) for oid, val in results])
  File "/usr/lib/python2.7/site-packages/snimpy-0.8.4-py2.7-linux-x86_64.egg/snimpy/snmp.py", line 220, in _convert
    self._check_exception(value)
  File "/usr/lib/python2.7/site-packages/snimpy-0.8.4-py2.7-linux-x86_64.egg/snimpy/snmp.py", line 198, in _check_exception
    raise SNMPNoSuchObject("No such object was found")  # nopep8
snimpy.snmp.SNMPNoSuchObject: No such object was found

Running snmpd is debug mode and spotted me this:

ccitt.1.1.0 = No Such Object available on this agent at this OID

Maybe something to do with the way my library stack is used.

So I was suspecting an issue in the underlying oid look up, so I figure I'd try to bypass with my rusty python skills:

from snimpy import snmp
s = snmp.Session("localhost", "public", 2)
r = s.get("1.3.6.1.2.1.1.1.0")
r.print

((1, 3, 6, 1, 2, 1, 1, 1, 0), 'Linux t21 3.10.12 #1 SMP Thu Oct 23 11:15:42 EDT 2014 armv7l')

Yay! A response. I can live with that if I have too, but a web developer will hate it.

I don't mind debugging this out a bit further out myself, but not sure what to start to tackle:

  1. libffi
  2. cffi
  3. cffi double build, host + target, and snimpy build with one but run-time on the other
  4. What the heck is ccitt?

Thanks

Ignore NoSuchInstance in Session._check_exception (multiple OIDs get())

Hi all,

This is a feature request to optionally ignore NoSuchInstance in Session._check_exception when more than one oids are queried via get(*oids). Minor changes are also needed in Session._convert to be able to handle this.

Why??

I am using the Session directly and I have been told that this is not the way snimpy is designed... so feel free to close this as invalid - I just thought I 'd ask...

What I need to do is query all the metrics of specific interface (I know the ifIndex) without fetching the whole ifTable. I am constructing all the OIDs and passing them directly to Session.get()

The problem is that different vendors support different OIDs! or they sometimes think is a good idea to randomly skip some... This causes get() to raise an exception while checking pysnmp's errorIndication.

Workaround

At the moment I am replacing the methods _check_exception and _convert. On the first I only remove the check for NoSuchInstance and on the second I add 2 lines:

   ...
            if isinstance(value, cl):
                return fn(value)

            # ... check for no instance ...
            if isinstance(value, rfc1905.NoSuchInstance):
                return "NoSuchInstance"

        # back to the original code    
        self._check_exception(value)

The output for a Cisco I test here:

ifOutErrors              : 0
ifAdminStatus            : 1
ifInOctets               : 0
ifInDiscards             : 0
ifOutDiscards            : 0
ifInUnknownProtos        : 0
ifDescr                  : b'Vlan500'
ifSpeed                  : 1000000000
ifOutNUcastPkts          : NoSuchInstance
ifMtu                    : 1998
ifInUcastPkts            : 0
ifLastChange             : 15925
ifInNUcastPkts           : NoSuchInstance
ifSpecific               : NoSuchInstance
ifType                   : 53
ifOutUcastPkts           : 65
ifOutQLen                : NoSuchInstance
ifOutOctets              : 4160
ifOperStatus             : 1
ifIndex                  : 500
ifPhysAddress            : b'blah'
ifInErrors               : 0

I think that would be a nice feature to have (disabled by default) that we can enable via Session.set_relax_no_instance(True) or something similar.

Please let me know if there an easier/other way of doing the same query with snimpy without working directly with pysnmp (I really like your Session :) ) and sorry for abusing snimpy again...

Andreas

Crash in _toBytes()

I'm seeing the following exception when accessing an SNMP OID SNMPv2-SMI::enterprises.23022.2.50.1.1.3.1.2.0:

ValueError: u'ila_040106_010815\n' cannot be parsed because it does not match format 255a at index 17

snmp value in question looks like this in the output of snmpwalk:

SNMPv2-SMI::enterprises.23022.2.50.1.1.3.1.2.0 = STRING: "ila_040105_070213
"
(This is a NetOptics inline tap, LA-2407)

It sounds like the parser chokes on the newline when converting? (No real idea, it's just a guess.)

I'm running snimpy==0.8.4.

Cross-compile snimpy

Trying to cross compile but having issues with cffi. Scenario (buildroot style):
Host (not distro) python is built and installed in a host folder struct.
Host python builds native python which is installed in a staging folder.
Host python can build and install python modules that are installed in "host" and/or staging depending if they are needed for other modules (in this case cffi and pycparser to satisfy snimpy prereqs).

I can build snimpy cffi module as either host mode or cross mode, but host mode, which succeeds, is not useful for the target and cross mode fails to build since it wants to load the module (which I can't, different architecture).

I did see someone else had the same issue on a different project (I see you were involved), but I was not able to determine what the solution was. Similarly the target system does not have a compiler.

Is there a way to generate snimpy's cffi so file in a cross build system or is it locked into a coupled build-and-load compile?

Doc example fails: snimpy.mib.SMIException: unable to find b'IF-MIB' (check the path)

I followed the doc but got the following error:

>>> from snimpy.manager import Manager as M
from snimpy.manager import load

load("IF-MIB")
m = M("localhost")
print(m.ifDescr[0])
Traceback (most recent call last):
  File "<input>", line 4, in <module>
  File "/home/ed8/projects/coaxis-opt/env/lib/python3.5/site-packages/snimpy/manager.py", line 578, in load
    m = mib.load(mibname)
  File "/home/ed8/projects/coaxis-opt/env/lib/python3.5/site-packages/snimpy/mib.py", line 605, in load
    raise SMIException("unable to find {0} (check the path)".format(mib))
snimpy.mib.SMIException: unable to find b'IF-MIB' (check the path)

What is IF-MIB? Do I need to install some package on my system?

cce0501 breaks reinitializing manager when using snmpv3

This code breaks:

m = snimpy.manager.Manager(host='switch1', version=3, authpassword='myAuthPasswordSwitch1', authprotocol='SHA', privpassword='myPrivPasswordSwitch1', privprotocol='AES128', secname='root')
print m.sysDescr

m = snimpy.manager.Manager(host='switch2', version=3, authpassword='myAuthPasswordSwitch2', authprotocol='SHA', privpassword='myPrivPasswordSwitch2', privprotocol='AES128', secname='root')
print m.sysDescr

Traceback (most recent call last):
  File "./snimpyTest.py", line 36, in <module>
    print m.sysDescr
  File "/usr/lib/python2.7/dist-packages/snimpy/manager.py", line 274, in __getattribute__
    oid, result = self._session.get(a.oid + (0,))[0]
  File "/usr/lib/python2.7/dist-packages/snimpy/snmp.py", line 257, in get
    return self._op(self._cmdgen.getCmd, *oids)
  File "/usr/lib/python2.7/dist-packages/snimpy/snmp.py", line 230, in _op
    raise SNMPException(str(errorIndication))
snimpy.snmp.SNMPException: wrongDigest

Reverting cce0501 fixes the issue.

get session from manager

This is not really an issue but more a question: if I create a manager using something like this m = M(host=devicename, community=...) but I need the session to do a session.get() or session.walkmore(), how can I recover it ?

I'm using session = m._session._session but it looks a bit ugly to me. Any advice ?

SNMPTooBig

Is there any way to get around the SNMPTooBig exception?

Snimpy [18]> m.extremeEdpNeighborVlanIpAddress.items()
---------------------------------------------------------------------------
SNMPTooBig                                Traceback (most recent call last)
/usr/lib/python2.7/_abcoll.pyc in items(self)
    367
    368     def items(self):
--> 369         return [(key, self[key]) for key in self]
    370
    371     def values(self):

/usr/local/lib/python2.7/dist-packages/snimpy/manager.pyc in __iter__(self)
    366
    367     def __iter__(self):
--> 368         for k, _ in self.iteritems():
    369             yield k
    370

/usr/local/lib/python2.7/dist-packages/snimpy/manager.pyc in iteritems(self)
    377         indexes = self.proxy.table.index
    378
--> 379         for noid, result in self.session.walk(oid):
    380             if noid <= oid:
    381                 noid = None

/usr/local/lib/python2.7/dist-packages/snimpy/snmp.pyc in walk(self, *oids)
    268             return self._op(self._cmdgen.nextCmd, *oids)
    269         args = [0, self.bulk] + list(oids)
--> 270         return self._op(self._cmdgen.bulkCmd, *args)
    271
    272     def set(self, *args):

/usr/local/lib/python2.7/dist-packages/snimpy/snmp.pyc in _op(self, cmd, *oids)
    233             exc = "SNMP{0}".format(exc[0].upper() + exc[1:])
    234             if str(exc) in globals():
--> 235                 raise globals()[exc]
    236             raise SNMPException(errorStatus.prettyPrint())
    237         if cmd in [self._cmdgen.getCmd, self._cmdgen.setCmd]:

SNMPTooBig:

history writing on exit without ipython broken

readline is imported lazily in 0.5.1 causing write_history_file to fail due to the undefined readline variable.
the variable must be declared global for it to work:

    except ImportError:
        global readline
        readline = None

This only happens when ipython is not installed.

# snimpy 
Snimpy (0.5.1) -- An interactive SNMP tool.
  load        -> load an additional MIB
  M           -> manager object
[snimpy]> exit()
Error in atexit._run_exitfuncs:
Traceback (most recent call last):
  File "/usr/lib/python2.7/atexit.py", line 24, in _run_exitfuncs
    func(*targs, **kargs)
  File "/usr/lib/python2.7/dist-packages/snimpy/main.py", line 47, in write_history_file
    if readline and conf.histfile:
NameError: global name 'readline' is not defined
Error in sys.exitfunc:
Traceback (most recent call last):
  File "/usr/lib/python2.7/atexit.py", line 24, in _run_exitfuncs
    func(*targs, **kargs)
  File "/usr/lib/python2.7/dist-packages/snimpy/main.py", line 47, in write_history_file
    if readline and conf.histfile:
NameError: global name 'readline' is not defined

Calling type on a table node segfaults in snimpy.mib

Hi,

I'm attempting to use snimpy's MIB parsing stuff, as pysnmp's seems like it's got a bit of a steep learning curve.

The following causes a segfault of snimpy 0.8.6 on both OS X (python 2.7.6) and Linux (python 2.7.10). libsmi 0.4.8 on both.

import snimpy.mib
snimpy.mib.load('SNMPv2-SMI')
snimpy.mib.load('IF-MIB')
a = snimpy.mib.get('IF-MIB', 'ifTable')
a.type

I suspect this isn't desired behaviour, or if type() isn't appropriate to call here, perhaps we should have a guard condition to prevent it segfaulting?

SNMPv3 request fails

Hi there,

Firstly, thank you for this excellent tool. It simplifies queries very nicely.

It however appears snimpy doesn't support all the SNMPv3 fields as described in:
http://www.net-snmp.org/tutorial/tutorial-5/commands/snmpv3.html

In particular there appears to be no way to set securityLevel. I have also found that no matter the secname the username 'public' always gets submitted along with 'noauth' securityLevel. My Cisco devices are alsways configured with 'authPriv'

The reuslt is the following exception which is consistent with the Cisco debug also below.
snimpy.snmp.SNMPException: unknownUserName

Output from Cisco debug;
Incoming SNMP packet
*Dec 2 02:04:48.290 UTC: v3 packet security model: v3 security level: noauth
*Dec 2 02:04:48.290 UTC: username: public
*Dec 2 02:04:48.290 UTC: snmpEngineID: 800000090300AABBCC000100
*Dec 2 02:04:48.290 UTC: snmpEngineBoots: 0 snmpEngineTime: 0
*Dec 2 02:04:48.290 UTC: SNMP: Report, reqid 2147483647, errstat 0, erridx 0
internet.6.3.15.1.1.3.0 = 34
*Dec 2 02:04:48.294 UTC: SNMP: Packet sent via UDP to 172.23.1.113
process_mgmt_req_int: UDP packet being de-queued

*Dec 2 02:04:48.297 UTC: SNMP: Packet received via UDP from 172.23.1.113 on Ethernet0/0SrParseV3SnmpMessage:Wrong User Name.
SrParseV3SnmpMessage: Failed.
SrDoSnmp: authentication failure, Unknown User Name

Parameters passed into snimpy function
{'secname': 'test', 'authprotocol': 'SHA1', 'privprotocol': 'AES128', 'host': '10.252.1.1', 'version': 3, 'privpassword': '12345678', 'authpassword': '12345678'}

I'm setting all the snimpy parameters as per docs plus some extra ones for my custom class and data storage.

SNMPv2 works like a charm;
{'host': '10.252.1.1', 'version': 2, 'community': 'public'}
(7, 'Loopback0', 'up(1)', '10.252.1.1', '255.255.255.255', 1514, '', '0:00:05.280000')
ifDescr : 7
ifOperStatus : Loopback0
ipAdEntAddr : up(1)
ipAdEntNetMask : 10.252.1.1
ifMtu : 255.255.255.255
ifPhysAddress : 1514
ifLastChange :
(2, 'Ethernet0/1', 'up(1)', '10.254.1.239', '255.255.255.0', 1500, 'aa:bb:cc:0:1:10', '0:00:06.320000')
ifDescr : 2
ifOperStatus : Ethernet0/1
ipAdEntAddr : up(1)
ipAdEntNetMask : 10.254.1.239
ifMtu : 255.255.255.0
ifPhysAddress : 1500
ifLastChange : aa:bb:cc:0:1:10
(1, 'Ethernet0/0', 'up(1)', '172.22.1.239', '255.255.255.0', 1500, 'aa:bb:cc:0:1:0', '0:00:06.310000')
ifDescr : 1
ifOperStatus : Ethernet0/0
ipAdEntAddr : up(1)
ipAdEntNetMask : 172.22.1.239
ifMtu : 255.255.255.0
ifPhysAddress : 1500
ifLastChange : aa:bb:cc:0:1:0

SNMPv3 seems like it needs a little more attention, or I'm terrible and mis-reading the documentation :)

Thanks
Donald

Two different MIBs with the same scalar name

I have two different MIBs with the same scalar name that I need to load. Is there a way to prefix the scalar name with the module name?

We have a.mib and b.mib and they both have the scalar 'foo'. What would happen if we do
snimpy.manager.load('a.mib') followed by snimpy.manager.load('b.mib')? What would happen if I loaded them in the other order? Could you add manager['A-MIB::foo']? Or manager['A-MIB'].foo?

Snimpy Memory Leak

Using Snimpy in some Celery Tasks, the server RAM consumption grows non-stop to the point kernel starts killing Celery workers process (oom).
After running Valgrind against a simple Snimpy Script, Memory leak is detected:

valgrind --leak-check=yes --track-origins=yes python sdsl.py

==10762== LEAK SUMMARY:
==10762==    definitely lost: 609 bytes in 45 blocks
==10762==    indirectly lost: 0 bytes in 0 blocks
==10762==      possibly lost: 3,456 bytes in 6 blocks
==10762==    still reachable: 1,192,945 bytes in 5,951 blocks
==10762==         suppressed: 0 bytes in 0 blocks
==10762== Reachable blocks (those to which a pointer was found) are not shown.
==10762== To see them, rerun with: --leak-check=full --show-reachable=yes
==10762== 
==10762== For counts of detected and suppressed errors, rerun with: -v
==10762== ERROR SUMMARY: 4499 errors from 134 contexts (suppressed: 103 from 9)

#!/usr/bin/python
#import traceback
import os
import sys
from snimpy.manager import Manager as M
from snimpy.manager import load

def sdsl_test(hostname, community):
        mib_path = os.path.join('/home/masac/masac', 'scripts', 'mib')
        load(os.path.join(mib_path, 'SNMPv2-SMI.txt'))
        load(os.path.join(mib_path, 'SNMPv2-TC.txt'))
        load(os.path.join(mib_path, 'SNMPv2-CONF.txt'))
        load(os.path.join(mib_path, 'SNMPv2-MIB.txt'))
        load(os.path.join(mib_path, 'IANAifType-MIB.txt'))
        load(os.path.join(mib_path, 'IF-MIB.txt'))
        """ If you put cache to a value other than 0, you get RuntimeError relative to Dictionary size change"""
        m = M(host=hostname, retries=0, community=community, version=2, timeout=1, cache=0)
        uptime = 0
        try:
                with m:
                        uptime = m.sysUpTime
                        try:
                                for ix in m.ifDescr:
                                        desc = m.ifDescr[ix]
                                        metric = m.ifHCInOctets[ix]
                                        print(desc + " " + str(metric))
                        except Exception as e:
                                print(e)
        except Exception as e:
                print(e)
        finally:
                if uptime:
                        print(uptime)
sdsl_test('Router.IP','my-community')
sys.exit()

If needed, I can provide code of the Celery Task using Snimpy. basically the task loop over a list of network routers, fetches metrics and send them to a server.

tag 0.8.6 missing

on pypi version 0.8.6 is available, but the git repository has no matching tag

Socket leakage

I'm using snimpy as a client to gathering snmp data and scheduling the tasks with apscheduler and threadpool.

Recently, I found fd of our process has been used out. During debug, I found that there are many udp ports are open even when no snmp task is running.

I'm curious about the reason why udp ports must be kept open.

What matters more is that I found the number of open ports is increasing slowly.

I'm monitoring about 70 devices with snimpy once half hour, but there is 100 open udp port now. Every half hour this number increase one or more. Several days ago, my process exit for too many fds after running for three days.

SNMPv3 contextName

Is it possible to specify a specific SNMPv3 contextName, for example, snmpwalk -n vlan-713 ?

pip install fail: No package 'libffi' found

Env

pip

$ pip -V
pip 8.1.1 from /data/projects/coaxis-opt/env/lib/python3.5/site-packages (python 3.5)

python

$ python -V
Python 3.5.2

OS

$ lsb_release -a
No LSB modules are available.
Distributor ID: LinuxMint
Description:    Linux Mint 18 Sarah
Release:        18
Codename:       sarah

Error

Collecting snimpy
  Using cached snimpy-0.8.11.tar.gz
    Complete output from command python setup.py egg_info:
    zip_safe flag not set; analyzing archive contents...

    Installed /tmp/pip-build-igenunw5/snimpy/.eggs/vcversioner-2.16.0.0-py3.5.egg
    Searching for cffi>=1.0.0
    Reading https://pypi.python.org/simple/cffi/
    Best match: cffi 1.8.3
    Downloading https://pypi.python.org/packages/0a/f3/686af8873b70028fccf67b15c78fd4e4667a3da995007afc71e786d61b0a/cffi-1.8.3.tar.gz#md5=c8e877fe0426a99d0cf5872cf2f95b27
    Processing cffi-1.8.3.tar.gz
    Writing /tmp/easy_install-dikbzaa_/cffi-1.8.3/setup.cfg
    Running cffi-1.8.3/setup.py -q bdist_egg --dist-dir /tmp/easy_install-dikbzaa_/cffi-1.8.3/egg-dist-tmp-0skqbjnt
    Package libffi was not found in the pkg-config search path.
    Perhaps you should add the directory containing `libffi.pc'
    to the PKG_CONFIG_PATH environment variable
    No package 'libffi' found
    Package libffi was not found in the pkg-config search path.
    Perhaps you should add the directory containing `libffi.pc'
    to the PKG_CONFIG_PATH environment variable
    No package 'libffi' found
    Package libffi was not found in the pkg-config search path.
    Perhaps you should add the directory containing `libffi.pc'
    to the PKG_CONFIG_PATH environment variable
    No package 'libffi' found
    Package libffi was not found in the pkg-config search path.
    Perhaps you should add the directory containing `libffi.pc'
    to the PKG_CONFIG_PATH environment variable
    No package 'libffi' found
    Package libffi was not found in the pkg-config search path.
    Perhaps you should add the directory containing `libffi.pc'
    to the PKG_CONFIG_PATH environment variable
    No package 'libffi' found
    c/_cffi_backend.c:15:17: fatal error: ffi.h: No such file or directory
    compilation terminated.
    Traceback (most recent call last):
      File "/usr/lib/python3.5/distutils/unixccompiler.py", line 118, in _compile
        extra_postargs)
      File "/usr/lib/python3.5/distutils/ccompiler.py", line 909, in spawn
        spawn(cmd, dry_run=self.dry_run)
      File "/usr/lib/python3.5/distutils/spawn.py", line 36, in spawn
        _spawn_posix(cmd, search_path, dry_run=dry_run)
      File "/usr/lib/python3.5/distutils/spawn.py", line 159, in _spawn_posix
        % (cmd, exit_status))
    distutils.errors.DistutilsExecError: command 'x86_64-linux-gnu-gcc' failed with exit status 1

    During handling of the above exception, another exception occurred:

    Traceback (most recent call last):
      File "/usr/lib/python3.5/distutils/core.py", line 148, in setup
        dist.run_commands()
      File "/usr/lib/python3.5/distutils/dist.py", line 955, in run_commands
        self.run_command(cmd)
      File "/usr/lib/python3.5/distutils/dist.py", line 974, in run_command
        cmd_obj.run()
      File "/data/projects/coaxis-opt/env/lib/python3.5/site-packages/setuptools/command/bdist_egg.py", line 161, in run
        cmd = self.call_command('install_lib', warn_dir=0)
      File "/data/projects/coaxis-opt/env/lib/python3.5/site-packages/setuptools/command/bdist_egg.py", line 147, in call_command
        self.run_command(cmdname)
      File "/usr/lib/python3.5/distutils/cmd.py", line 313, in run_command
        self.distribution.run_command(command)
      File "/usr/lib/python3.5/distutils/dist.py", line 974, in run_command
        cmd_obj.run()
      File "/data/projects/coaxis-opt/env/lib/python3.5/site-packages/setuptools/command/install_lib.py", line 23, in run
        self.build()
      File "/usr/lib/python3.5/distutils/command/install_lib.py", line 109, in build
        self.run_command('build_ext')
      File "/usr/lib/python3.5/distutils/cmd.py", line 313, in run_command
        self.distribution.run_command(command)
      File "/usr/lib/python3.5/distutils/dist.py", line 974, in run_command
        cmd_obj.run()
      File "/data/projects/coaxis-opt/env/lib/python3.5/site-packages/setuptools/command/build_ext.py", line 49, in run
        _build_ext.run(self)
      File "/usr/lib/python3.5/distutils/command/build_ext.py", line 338, in run
        self.build_extensions()
      File "/usr/lib/python3.5/distutils/command/build_ext.py", line 447, in build_extensions
        self._build_extensions_serial()
      File "/usr/lib/python3.5/distutils/command/build_ext.py", line 472, in _build_extensions_serial
        self.build_extension(ext)
      File "/data/projects/coaxis-opt/env/lib/python3.5/site-packages/setuptools/command/build_ext.py", line 174, in build_extension
        _build_ext.build_extension(self, ext)
      File "/usr/lib/python3.5/distutils/command/build_ext.py", line 532, in build_extension
        depends=ext.depends)
      File "/usr/lib/python3.5/distutils/ccompiler.py", line 574, in compile
        self._compile(obj, src, ext, cc_args, extra_postargs, pp_opts)
      File "/usr/lib/python3.5/distutils/unixccompiler.py", line 120, in _compile
        raise CompileError(msg)
    distutils.errors.CompileError: command 'x86_64-linux-gnu-gcc' failed with exit status 1

    During handling of the above exception, another exception occurred:

    Traceback (most recent call last):
      File "/data/projects/coaxis-opt/env/lib/python3.5/site-packages/setuptools/sandbox.py", line 154, in save_modules
        yield saved
      File "/data/projects/coaxis-opt/env/lib/python3.5/site-packages/setuptools/sandbox.py", line 195, in setup_context
        yield
      File "/data/projects/coaxis-opt/env/lib/python3.5/site-packages/setuptools/sandbox.py", line 243, in run_setup
        DirectorySandbox(setup_dir).run(runner)
      File "/data/projects/coaxis-opt/env/lib/python3.5/site-packages/setuptools/sandbox.py", line 273, in run
        return func()
      File "/data/projects/coaxis-opt/env/lib/python3.5/site-packages/setuptools/sandbox.py", line 242, in runner
        _execfile(setup_script, ns)
      File "/data/projects/coaxis-opt/env/lib/python3.5/site-packages/setuptools/sandbox.py", line 46, in _execfile
        exec(code, globals, locals)
      File "/tmp/easy_install-dikbzaa_/cffi-1.8.3/setup.py", line 193, in <module>
      File "/usr/lib/python3.5/distutils/core.py", line 163, in setup
        raise SystemExit("error: " + str(msg))
    SystemExit: error: command 'x86_64-linux-gnu-gcc' failed with exit status 1

    During handling of the above exception, another exception occurred:

    Traceback (most recent call last):
      File "/data/projects/coaxis-opt/env/lib/python3.5/site-packages/setuptools/command/easy_install.py", line 1087, in run_setup
        run_setup(setup_script, args)
      File "/data/projects/coaxis-opt/env/lib/python3.5/site-packages/setuptools/sandbox.py", line 246, in run_setup
        raise
      File "/usr/lib/python3.5/contextlib.py", line 77, in __exit__
        self.gen.throw(type, value, traceback)
      File "/data/projects/coaxis-opt/env/lib/python3.5/site-packages/setuptools/sandbox.py", line 195, in setup_context
        yield
      File "/usr/lib/python3.5/contextlib.py", line 77, in __exit__
        self.gen.throw(type, value, traceback)
      File "/data/projects/coaxis-opt/env/lib/python3.5/site-packages/setuptools/sandbox.py", line 166, in save_modules
        saved_exc.resume()
      File "/data/projects/coaxis-opt/env/lib/python3.5/site-packages/setuptools/sandbox.py", line 141, in resume
        six.reraise(type, exc, self._tb)
      File "/data/projects/coaxis-opt/env/lib/python3.5/site-packages/pkg_resources/_vendor/six.py", line 685, in reraise
        raise value.with_traceback(tb)
      File "/data/projects/coaxis-opt/env/lib/python3.5/site-packages/setuptools/sandbox.py", line 154, in save_modules
        yield saved
      File "/data/projects/coaxis-opt/env/lib/python3.5/site-packages/setuptools/sandbox.py", line 195, in setup_context
        yield
      File "/data/projects/coaxis-opt/env/lib/python3.5/site-packages/setuptools/sandbox.py", line 243, in run_setup
        DirectorySandbox(setup_dir).run(runner)
      File "/data/projects/coaxis-opt/env/lib/python3.5/site-packages/setuptools/sandbox.py", line 273, in run
        return func()
      File "/data/projects/coaxis-opt/env/lib/python3.5/site-packages/setuptools/sandbox.py", line 242, in runner
        _execfile(setup_script, ns)
      File "/data/projects/coaxis-opt/env/lib/python3.5/site-packages/setuptools/sandbox.py", line 46, in _execfile
        exec(code, globals, locals)
      File "/tmp/easy_install-dikbzaa_/cffi-1.8.3/setup.py", line 193, in <module>
      File "/usr/lib/python3.5/distutils/core.py", line 163, in setup
        raise SystemExit("error: " + str(msg))
    SystemExit: error: command 'x86_64-linux-gnu-gcc' failed with exit status 1

    During handling of the above exception, another exception occurred:

    Traceback (most recent call last):
      File "<string>", line 1, in <module>
      File "/tmp/pip-build-igenunw5/snimpy/setup.py", line 66, in <module>
        'version_module_paths': ['snimpy/_version.py'],
      File "/usr/lib/python3.5/distutils/core.py", line 108, in setup
        _setup_distribution = dist = klass(attrs)
      File "/data/projects/coaxis-opt/env/lib/python3.5/site-packages/setuptools/dist.py", line 269, in __init__
        self.fetch_build_eggs(attrs['setup_requires'])
      File "/data/projects/coaxis-opt/env/lib/python3.5/site-packages/setuptools/dist.py", line 313, in fetch_build_eggs
        replace_conflicting=True,
      File "/data/projects/coaxis-opt/env/lib/python3.5/site-packages/pkg_resources/__init__.py", line 826, in resolve
        dist = best[req.key] = env.best_match(req, ws, installer)
      File "/data/projects/coaxis-opt/env/lib/python3.5/site-packages/pkg_resources/__init__.py", line 1092, in best_match
        return self.obtain(req, installer)
      File "/data/projects/coaxis-opt/env/lib/python3.5/site-packages/pkg_resources/__init__.py", line 1104, in obtain
        return installer(requirement)
      File "/data/projects/coaxis-opt/env/lib/python3.5/site-packages/setuptools/dist.py", line 380, in fetch_build_egg
        return cmd.easy_install(req)
      File "/data/projects/coaxis-opt/env/lib/python3.5/site-packages/setuptools/command/easy_install.py", line 663, in easy_install
        return self.install_item(spec, dist.location, tmpdir, deps)
      File "/data/projects/coaxis-opt/env/lib/python3.5/site-packages/setuptools/command/easy_install.py", line 693, in install_item
        dists = self.install_eggs(spec, download, tmpdir)
      File "/data/projects/coaxis-opt/env/lib/python3.5/site-packages/setuptools/command/easy_install.py", line 873, in install_eggs
        return self.build_and_install(setup_script, setup_base)
      File "/data/projects/coaxis-opt/env/lib/python3.5/site-packages/setuptools/command/easy_install.py", line 1101, in build_and_install
        self.run_setup(setup_script, setup_base, args)
      File "/data/projects/coaxis-opt/env/lib/python3.5/site-packages/setuptools/command/easy_install.py", line 1089, in run_setup
        raise DistutilsError("Setup script exited with %s" % (v.args[0],))
    distutils.errors.DistutilsError: Setup script exited with error: command 'x86_64-linux-gnu-gcc' failed with exit status 1

    ----------------------------------------

IPv6 Regex

Hi,

The IPv6 regex in snimpy/snmp.py line 178 seems incorrect :

        mo = re.match(r'^(?:'
                      r'\[(?P<ipv6>[\d:]+)\]|'
                      r'(?P<ipv4>[\d\.]+)|'
                      r'(?P<any>.*?))'
                      r'(?::(?P<port>\d+))?$',
                      host)

It doesn't take into account an IPv6 address also consist of the A-F letters (2001:67c:2e8:22::c100:68b won't be match). I would suggest to use these regex :

mo = re.match(r'^(?:'
                      r'\[(?P<ipv6>[\d:A-Fa-f]+)\]|'
                      r'\[(?P<ipv4>[\d\.]+)\]|'
                      r'(?P<any>.*?))'
                      r'(?::(?P<port>\d+))?$',
                      host)

Is a pull request welcomed ?

Snmptable request

Hi all.
First of all congratulations about yout work. This module likes very good.

After many time trying to use Collectd, tcollector, etc We decide make our own network analizer based on SNMP. I made the mistake do it on my own, parsing snmp table line command output inside of use an existing module that supports snmptable operation.

I would like your advice about using snimpy to make request about snmptable OIDs.

The class who make the request is:
https://github.com/wtelecom/net-interviewer/blob/master/src/snmp/table.py#L10

Regards!

Threading example

Hello

I am trying to use snimpy in a multi-threaded app and run into two issues (see stack traces). I have tried to isolate the problem in the example below. The approach is to load the MIBs in the main thread then create a Manager in each additional thread. I also tried creating the managers in the main thread but that did not help. Is this the right/supported approach? (Could you provide an example maybe?)

These errors do not happen systematically, I noticed at least one of them ~50% of the time with the example code.

Environment
  • python v2.7.8
  • snimpy v0.8.6
  • pysnmp v4.2.5
  • (4 cores machines)
Example
#!/usr/bin/env python

import threading
from snimpy.manager import load
import time
from snimpy.manager import Manager as M
from datetime import datetime
import collections
import pprint


def cpumem(config={}, switch={}):
    m = M(
        host=switch['hostname'],
        community=switch['community'],
        version=2,
        cache=config.get('cache', 8),
        timeout=config.get('timeout', 5),
        retries=config.get('retries', 1),
        none=True)

    oids = [
        ('cpmCPUTotal5secRev', int),
        ('cpmCPUTotal1minRev', int),
        ('cpmCPUTotal5minRev', int),
        ('cpmCPUMemoryUsed', int),
        ('cpmCPUMemoryFree', int),
    ]

    cpus = collections.defaultdict(dict)

    for oidtype in oids:
        oid = oidtype[0]
        data = m.__getattribute__(oid)
        for idx in data:
            cpus[idx][oid] = (oidtype[1](data[idx]), datetime.utcnow())
    pprint.pprint(cpus)


class ThPoller(threading.Thread):

    def __init__(self, switch):
        super(ThPoller, self).__init__()
        self.switch = switch

    def run(self):
        for i in range(2):
            cpumem({}, self.switch)
            time.sleep(0.5)

switches = [
    {
        'switch': {'hostname': 'switch1.example.org', 'community': 'abcdef'},
        'config': {},
    },
    {
        'switch': {'hostname': 'switch2.example.org', 'community': 'abcdef'},
        'config': {},
    },
]

load('./mibs/IF-MIB')
load('./mibs/CISCO-SMI.my')
load('./mibs/CISCO-TC.my')
load('./mibs/CISCO-PROCESS-MIB.my')
load('./mibs/RFC1213-MIB.my')

tp1 = ThPoller(switches[0]['switch'])
tp2 = ThPoller(switches[1]['switch'])
tp1.start()
tp2.start()

tp1.join()
tp2.join()
IndexError: pop from empty list
Exception in thread Thread-1:
Traceback (most recent call last):
  File "/usr/lib64/python2.7/threading.py", line 813, in __bootstrap_inner
    self.run()
  File "./th.py", line 48, in run
    cpumem({}, self.switch)
  File "./th.py", line 35, in cpumem
    for idx in data:
  File "/usr/lib64/python2.7/site-packages/snimpy/manager.py", line 384, in __iter__
    for k, _ in self.iteritems():
  File "/usr/lib64/python2.7/site-packages/snimpy/manager.py", line 395, in iteritems
    for noid, result in self.session.walk(oid):
  File "/usr/lib64/python2.7/site-packages/snimpy/manager.py", line 126, in walk
    return self.getorwalk("walk", *args)
  File "/usr/lib64/python2.7/site-packages/snimpy/manager.py", line 111, in getorwalk
    value = getattr(self._session, op)(*args)
  File "/usr/lib64/python2.7/site-packages/snimpy/snmp.py", line 273, in walk
    return self._op(self._cmdgen.bulkCmd, *args)
  File "/usr/lib64/python2.7/site-packages/snimpy/snmp.py", line 227, in _op
    self._auth, self._transport, *oids)
  File "/usr/lib/python2.7/site-packages/pysnmp/entity/rfc3413/oneliner/cmdgen.py", line 633, in bulkCmd
    self.__asynCmdGen.snmpEngine.transportDispatcher.runDispatcher()
  File "/usr/lib/python2.7/site-packages/pysnmp/carrier/asynsock/dispatch.py", line 41, in runDispatcher
    raise PySnmpError('poll error: %s' % ';'.join(format_exception(*exc_info())))
PySnmpError: poll error: Traceback (most recent call last):
;  File "/usr/lib/python2.7/site-packages/pysnmp/carrier/asynsock/dispatch.py", line 37, in runDispatcher
    use_poll=True, map=self.__sockMap, count=1)
;  File "/usr/lib64/python2.7/asyncore.py", line 220, in loop
    poll_fun(timeout, map)
;  File "/usr/lib64/python2.7/asyncore.py", line 201, in poll2
    readwrite(obj, flags)
;  File "/usr/lib64/python2.7/asyncore.py", line 123, in readwrite
    obj.handle_error()
;  File "/usr/lib64/python2.7/asyncore.py", line 110, in readwrite
    obj.handle_write_event()
;  File "/usr/lib64/python2.7/asyncore.py", line 468, in handle_write_event
    self.handle_write()
;  File "/usr/lib/python2.7/site-packages/pysnmp/carrier/asynsock/dgram/base.py", line 60, in handle_write
    outgoingMessage, transportAddress = self.__outQueue.pop(0)
;IndexError: pop from empty list
CarrierError: Transport (1, 3, 6, 1, 6, 1, 1) already registered

This one typically happens when the program starts, as if a duplicate transport was being registered with pysnmp.

Exception in thread Thread-1:
Traceback (most recent call last):
  File "/usr/lib64/python2.7/threading.py", line 813, in __bootstrap_inner
    self.run()
  File "./th.py", line 48, in run
    cpumem({}, self.switch)
  File "./th.py", line 35, in cpumem
    for idx in data:
  File "/usr/lib64/python2.7/site-packages/snimpy/manager.py", line 384, in __iter__
    for k, _ in self.iteritems():
  File "/usr/lib64/python2.7/site-packages/snimpy/manager.py", line 395, in iteritems
    for noid, result in self.session.walk(oid):
  File "/usr/lib64/python2.7/site-packages/snimpy/manager.py", line 126, in walk
    return self.getorwalk("walk", *args)
  File "/usr/lib64/python2.7/site-packages/snimpy/manager.py", line 111, in getorwalk
    value = getattr(self._session, op)(*args)
  File "/usr/lib64/python2.7/site-packages/snimpy/snmp.py", line 273, in walk
    return self._op(self._cmdgen.bulkCmd, *args)
  File "/usr/lib64/python2.7/site-packages/snimpy/snmp.py", line 227, in _op
    self._auth, self._transport, *oids)
  File "/usr/lib/python2.7/site-packages/pysnmp/entity/rfc3413/oneliner/cmdgen.py", line 630, in bulkCmd
    contextEngineId, contextName
  File "/usr/lib/python2.7/site-packages/pysnmp/entity/rfc3413/oneliner/cmdgen.py", line 380, in bulkCmd
    authData, transportTarget
  File "/usr/lib/python2.7/site-packages/pysnmp/entity/rfc3413/oneliner/cmdgen.py", line 96, in cfgCmdGen
    transport
  File "/usr/lib/python2.7/site-packages/pysnmp/entity/config.py", line 321, in addTransport
    transportDomain, transport
  File "/usr/lib/python2.7/site-packages/pysnmp/carrier/asynsock/dispatch.py", line 20, in registerTransport
    AbstractTransportDispatcher.registerTransport(self, tDomain, t)
  File "/usr/lib/python2.7/site-packages/pysnmp/carrier/base.py", line 97, in registerTransport
    'Transport %s already registered' % (tDomain,)
CarrierError: Transport (1, 3, 6, 1, 6, 1, 1) already registered

Thanks!

How to index table with two indexes?

The following mib has two indexes "INDEX { cpuUtilizationCnIndex, cpuIndex }". How do I dereference on both indexes?

cpuUtilizationNumber OBJECT-TYPE
    SYNTAX Integer32
    MAX-ACCESS read-only
    STATUS current
    DESCRIPTION
        "The number of CPUs which may be present on this
         system."
    ::= { utilization 1 }

cpuUtilizationTable OBJECT-TYPE
    SYNTAX SEQUENCE OF CpuUtilizationEntry
    MAX-ACCESS not-accessible
    STATUS current
    DESCRIPTION
        "A table of usage information relevant to each CPU
         which may be present on this system.

         The number of entries in this table is given by the value
         of cpuUtilizationNumber."
    ::= { utilization 2 }

cpuUtilizationEntry OBJECT-TYPE
    SYNTAX CpuUtilizationEntry
    MAX-ACCESS not-accessible
    STATUS current
    DESCRIPTION
        "Usage information for a CPU which may be
         present on this system."
    INDEX { cpuUtilizationCnIndex, cpuIndex }
    ::= { cpuUtilizationTable 1 }

CpuUtilizationEntry ::=
    SEQUENCE {
        cpuUtilizationCnIndex
            Unsigned32,
        cpuIndex
            Unsigned32,
        cpuUtilization
            Unsigned32
    }

cpuUtilizationCnIndex OBJECT-TYPE
    SYNTAX Unsigned32 (1..255)
    MAX-ACCESS read-only
    STATUS current
    DESCRIPTION
        "The cluster node for this value."
    ::= { cpuUtilizationEntry 1 }

cpuIndex OBJECT-TYPE
    SYNTAX Unsigned32
    MAX-ACCESS read-only
    STATUS current
    DESCRIPTION
        "CPU core index."
    ::= { cpuUtilizationEntry 2 }

cpuUtilization OBJECT-TYPE
    SYNTAX Unsigned32
    MAX-ACCESS read-only
    STATUS current
    DESCRIPTION
        "Current percentage usage of this CPU."
    ::= { cpuUtilizationEntry 3 }

BLUEARC-SERVER-MIB::cpuUtilizationCnIndex.1.0 = Gauge32: 1
BLUEARC-SERVER-MIB::cpuUtilizationCnIndex.1.1 = Gauge32: 1
BLUEARC-SERVER-MIB::cpuUtilizationCnIndex.1.2 = Gauge32: 1
BLUEARC-SERVER-MIB::cpuUtilizationCnIndex.1.3 = Gauge32: 1
BLUEARC-SERVER-MIB::cpuUtilizationCnIndex.2.0 = Gauge32: 2
BLUEARC-SERVER-MIB::cpuUtilizationCnIndex.2.1 = Gauge32: 2
BLUEARC-SERVER-MIB::cpuUtilizationCnIndex.2.2 = Gauge32: 2
BLUEARC-SERVER-MIB::cpuUtilizationCnIndex.2.3 = Gauge32: 2
BLUEARC-SERVER-MIB::cpuIndex.1.0 = Gauge32: 0
BLUEARC-SERVER-MIB::cpuIndex.1.1 = Gauge32: 1
BLUEARC-SERVER-MIB::cpuIndex.1.2 = Gauge32: 2
BLUEARC-SERVER-MIB::cpuIndex.1.3 = Gauge32: 3
BLUEARC-SERVER-MIB::cpuIndex.2.0 = Gauge32: 0
BLUEARC-SERVER-MIB::cpuIndex.2.1 = Gauge32: 1
BLUEARC-SERVER-MIB::cpuIndex.2.2 = Gauge32: 2
BLUEARC-SERVER-MIB::cpuIndex.2.3 = Gauge32: 3
BLUEARC-SERVER-MIB::cpuUtilization.1.0 = Gauge32: 0
BLUEARC-SERVER-MIB::cpuUtilization.1.1 = Gauge32: 3
BLUEARC-SERVER-MIB::cpuUtilization.1.2 = Gauge32: 0
BLUEARC-SERVER-MIB::cpuUtilization.1.3 = Gauge32: 0
BLUEARC-SERVER-MIB::cpuUtilization.2.0 = Gauge32: 1
BLUEARC-SERVER-MIB::cpuUtilization.2.1 = Gauge32: 1
BLUEARC-SERVER-MIB::cpuUtilization.2.2 = Gauge32: 0
BLUEARC-SERVER-MIB::cpuUtilization.2.3 = Gauge32: 0

Slight inconsistency with partial indexes

Hello again.

There is a slight inconsistency with my previous PR - using iteritems() iterates over index-value pairs, and using subscript syntax [] iterates over indexes only. Although this behaviour is consistent with existing snimpy syntax, this is not reflected in the docs.

I can create a new PR addressing this in one of the following ways:

  1. Patch documentation to reflect this fact. This is ok; the only nitpick that python coders don't generally think of iteritems() as accepting an argument.
  2. Modify subscript with partial indexes to behave like original iteritems() - iterating over index-value pairs. This can work, but is inconsistent with using "normal" (non-subscripted) syntax, which iterates over indexes only.

Can you advise on which way should I go, or suggest an alternative solution? Thanks, and sorry to bother you.

ValueError: () is too short for an integer

Hi,

I have been using Snimpy for a few months now and have been able to successfully monitor a wide variety of devices, such as HP, SuperMicro, Cisco, and Arista. I am now trying to monitor HP blades (BladeSystem c7000 Enclosure G2), but I'm running into an error.

Here is what I'm seeing:

Snimpy (0.8.1) -- interactive SNMP tool.
  load        -> load an additional MIB
  M           -> manager object
[snimpy]> load("../blade/mibs/SNMPv2-MIB")
[snimpy]> load("../blade/mibs/CPQHOST.MIB")
[snimpy]> load("../blade/mibs/CPQRACK-MIB.mib")
[snimpy]> m = M("chidbld23a","public",2)
[snimpy]> import snimpy.mib
[snimpy]> for index in m.cpqRackName: print m.cpqRackName[index]
...
SR-23
[snimpy]> for index in m.cpqRackCommonEnclosureRack: print m.cpqRackCommonEnclosureRack[index]
...
Traceback (most recent call last):
  File "<console>", line 1, in <module>
  File "/usr/lib/python2.6/site-packages/snimpy-0.8.1-py2.6.egg/snimpy/manager.py", line 362, in __iter__
    for k, _ in self.iteritems():
  File "/usr/lib/python2.6/site-packages/snimpy-0.8.1-py2.6.egg/snimpy/manager.py", line 388, in iteritems
    l, o = x.type.fromOid(x, tuple(index))
  File "/usr/lib/python2.6/site-packages/snimpy-0.8.1-py2.6.egg/snimpy/basictypes.py", line 565, in fromOid
    raise ValueError("{0} is too short for an integer".format(oid))
ValueError: () is too short for an integer

I have tried with different versions of the MIB and with different devices, but I always get this error for pretty much anything I try to query from the CPQRACK-MIB.

Any thoughts on how I can resolve this?

Thanks!

snimpy.snmp.SNMPNoSuchObject: No such object was found

I'm having an exception raised, but I don't get why

snimpy.snmp.SNMPNoSuchObject: No such object was found

Code

from snimpy import manager as snimpy

def snmp(hostname, oids, mibs):
    logger.debug(hostname)
    logger.debug(oids)
    logger.debug(mibs)
    for mib in mibs:
        snimpy.load(mib)

    session = snimpy.snmp.Session(hostname, "public", 1)
    details = session.get(*oids)

    return [{
                'oid': '.' + '.'.join(repr(node) for node in oid[0]),
                'value': oid[1]
            } for oid in details]

oids = ['.1.3.6.1.2.1.25.3.2.1.3.1', '.1.3.6.1.2.1.43.10.2.1.4.1.1.1.3.6.1.2.1.1.4.0', '.1.3.6.1.2.1.1.1.0', '.1.3.6.1.2.1.1.5.0', '.1.3.6.1.2.1.1.3.0']
hostname = '192.168.2.250'
mibs = ['DISMAN-EVENT-MIB', 'HOST-RESOURCES-MIB', 'SNMPv2-MIB', 'SNMPv2-SMI']
snmp(hostname, oids, mibs)

Error

>>> scanner.get_device_infos('192.168.2.250')
Traceback (most recent call last):
  File "<input>", line 1, in <module>
  File "~/project/daemon/api/scanner.py", line 62, in get_device_infos
    infos = self.network_tools.snmp(hostname, oids, mibs)
  File "~/project/daemon/api/network_tools.py", line 26, in snmp
    logger.debug(type(oids))
  File "~/project/env/lib/python3.5/site-packages/snimpy/snmp.py", line 286, in get
    return self._op(self._cmdgen.getCmd, *oids)
  File "~/project/env/lib/python3.5/site-packages/snimpy/snmp.py", line 278, in _op
    return tuple([(oid, self._convert(val)) for oid, val in results])
  File "~/project/env/lib/python3.5/site-packages/snimpy/snmp.py", line 278, in <listcomp>
    return tuple([(oid, self._convert(val)) for oid, val in results])
  File "~/project/env/lib/python3.5/site-packages/snimpy/snmp.py", line 249, in _convert
    self._check_exception(value)
  File "~/project/env/lib/python3.5/site-packages/snimpy/snmp.py", line 217, in _check_exception
    raise SNMPNoSuchObject("No such object was found")  # nopep8
snimpy.snmp.SNMPNoSuchObject: No such object was found

Doing it in bash works

Reaching the equipment using bash and snmpget command works fine:

declare -a oids=(
'.1.3.6.1.2.1.25.3.2.1.3.1'  # HOST-RESOURCES-MIB::hrDeviceDescr.1
'.1.3.6.1.2.1.43.10.2.1.4.1.1'  # SNMPv2-SMI::mib-2.43.10.2.1.4.1.1 page count
'.1.3.6.1.2.1.1.4.0'  # SNMPv2-MIB::sysContact.0
'.1.3.6.1.2.1.1.1.0'  # SNMPv2-MIB::sysDescr.0
'.1.3.6.1.2.1.1.5.0'  # SNMPv2-MIB::sysName.0
'.1.3.6.1.2.1.1.3.0'  # DISMAN-EVENT-MIB::sysUpTimeInstance
)

for oid in ${oids[@]}; do
    echo "$oid"
    snmpget -v 1 -t .3 -r 2 -c public 192.168.2.250 -m +SNMPv2-MIB "$oid"
    echo
done

output:

.1.3.6.1.2.1.25.3.2.1.3.1
HOST-RESOURCES-MIB::hrDeviceDescr.1 = STRING: Brother HL-5250DN series

.1.3.6.1.2.1.43.10.2.1.4.1.1
SNMPv2-SMI::mib-2.43.10.2.1.4.1.1 = Counter32: 22629

.1.3.6.1.2.1.1.4.0
SNMPv2-MIB::sysContact.0 = STRING: 

.1.3.6.1.2.1.1.1.0
SNMPv2-MIB::sysDescr.0 = STRING: Brother NC-6400h, Firmware Ver.1.01  (05.08.31),MID 84UZ92

.1.3.6.1.2.1.1.5.0
SNMPv2-MIB::sysName.0 = STRING: BRN_7D3B43

.1.3.6.1.2.1.1.3.0
DISMAN-EVENT-MIB::sysUpTimeInstance = Timeticks: (168019770) 19 days, 10:43:17.70

Question

What's the matter here?

MIB caching

For some scripts, MIB loading can take some time. It would be great to be able to enable a cache for MIBs. This would also enable the possibility to run scripts without the corresponding MIB.

Using session throws pyasn1.type.error.ValueConstraintError

Hello I am trying to use your library instead of pysnmp.

pysnmp example:

cmdGen = cmdgen.CommandGenerator()
errorIndication, errorStatus, errorIndex, varBindTable = cmdGen.nextCmd(
    cmdgen.CommunityData(config.COMMUNITY),
    cmdgen.UdpTransportTarget((config.HOST, config.PORT)),
    config.OID,
    lexicographicMode=False,
    ignoreNonIncreasingOid=True,
    lookupValue=False, lookupNames=False
)
for varBindTableRow in varBindTable:
    for name, val in varBindTableRow:
        print('%s' % (val,))

snimpy example:

s = Session(config.HOST+':'+str(config.PORT), community=config.COMMUNITY, version=2)
res = s.walk('.'+config.OID)
print res

pysnmp yields:
230
0
0
49
10

while snimpy throws an error

Traceback (most recent call last):
  File "/usr/lib/python2.7/runpy.py", line 162, in _run_module_as_main
    "__main__", fname, loader, pkg_name)
  File "/usr/lib/python2.7/runpy.py", line 72, in _run_code
    exec code in run_globals
  File "/home/martin/.virtualenvs/snmp/lib/python2.7/site-packages/memory_profiler.py", line 853, in <module>
    execfile(__file__, ns, ns)
  File "test3.py", line 17, in <module>
    test()
  File "/home/martin/.virtualenvs/snmp/lib/python2.7/site-packages/memory_profiler.py", line 445, in f
    result = func(*args, **kwds)
  File "test3.py", line 10, in test
    res = s.walk('.'+config.OID)
  File "/home/martin/.virtualenvs/snmp/local/lib/python2.7/site-packages/snimpy/snmp.py", line 272, in walk
    return self._op(self._cmdgen.bulkCmd, *args)
  File "/home/martin/.virtualenvs/snmp/local/lib/python2.7/site-packages/snimpy/snmp.py", line 226, in _op
    self._auth, self._transport, *oids)
  File "/home/martin/.virtualenvs/snmp/local/lib/python2.7/site-packages/pysnmp/entity/rfc3413/oneliner/cmdgen.py", line 630, in bulkCmd
    contextEngineId, contextName
  File "/home/martin/.virtualenvs/snmp/local/lib/python2.7/site-packages/pysnmp/entity/rfc3413/oneliner/cmdgen.py", line 380, in bulkCmd
    authData, transportTarget
  File "/home/martin/.virtualenvs/snmp/local/lib/python2.7/site-packages/pysnmp/entity/rfc3413/oneliner/cmdgen.py", line 55, in cfgCmdGen
    authData.securityName
  File "/home/martin/.virtualenvs/snmp/local/lib/python2.7/site-packages/pysnmp/entity/config.py", line 59, in addV1System
    snmpEngine, communityIndex
  File "/home/martin/.virtualenvs/snmp/local/lib/python2.7/site-packages/pysnmp/entity/config.py", line 52, in __cookV1SystemInfo
    tblIdx = snmpCommunityEntry.getInstIdFromIndices(communityIndex)
  File "/home/martin/.virtualenvs/snmp/lib/python2.7/site-packages/pysnmp/smi/mibs/SNMPv2-SMI.py", line 1096, in getInstIdFromIndices
    mibObj.syntax.clone(indices[idx]), impliedFlag
  File "/home/martin/.virtualenvs/snmp/local/lib/python2.7/site-packages/pyasn1/type/univ.py", line 300, in clone
    value, tagSet, subtypeSpec, encoding, binValue, hexValue
  File "/home/martin/.virtualenvs/snmp/local/lib/python2.7/site-packages/pyasn1/type/univ.py", line 284, in __init__
    base.AbstractSimpleAsn1Item.__init__(self, value, tagSet, subtypeSpec)
  File "/home/martin/.virtualenvs/snmp/local/lib/python2.7/site-packages/pyasn1/type/base.py", line 69, in __init__
    self._verifySubtypeSpec(value)
  File "/home/martin/.virtualenvs/snmp/local/lib/python2.7/site-packages/pyasn1/type/base.py", line 33, in _verifySubtypeSpec
    raise c('%s at %s' % (i, self.__class__.__name__))
pyasn1.type.error.ValueConstraintError: ConstraintsIntersection(ConstraintsIntersection(ConstraintsIntersection(ConstraintsIntersection(), ValueSizeConstraint(0, 65535)), ValueSizeConstraint(0, 255)), ValueSizeConstraint(1, 32)) failed at: "ValueSizeConstraint(1, 32) failed at: "1.3.6.1.4.1.318.1.3.2.17_APC_AP9630"" at SnmpAdminString

Am I using it wrong? This section is not really documented and I am a beginner regarding snmp.

SNMP get on sysObjectID ends with AttributeError: prettyOut

operation : get sysObjectID from a Cisco switch

works on snimpy 0.8.1

m2 = M(host='test2.domain', community='comm')
m2.sysObjectID

returns the expected value:

<Oid: 1.3.6.1.4.1.9.1.1208>

broken on snimpy 0.8.8

m2 = M(host='test2.domain', community='comm')
m2.sysObjectID

fails with:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/Users/myself/.pyenv/versions/venv266/lib/python2.6/site-packages/snimpy/manager.py", line 298, in __getattribute__
    oid, result = self._session.get(a.oid + (0,))[0]
  File "/Users/myself/.pyenv/versions/venv266/lib/python2.6/site-packages/snimpy/snmp.py", line 271, in get
    :return: a list of tuples with the retrieved OID and the raw value.
  File "/Users/myself/.pyenv/versions/venv266/lib/python2.6/site-packages/snimpy/snmp.py", line 263, in _op
    # This seems to be filtered
  File "/Users/myself/.pyenv/versions/venv266/lib/python2.6/site-packages/snimpy/snmp.py", line 221, in _convert
    rfc1902.OctetString: bytes,
  File "/Users/myself/.pyenv/versions/venv266/lib/python2.6/site-packages/pysnmp/smi/rfc1902.py", line 573, in __getattr__
    raise AttributeError(attr)
AttributeError: prettyOut

SNMP sniffing shows correct answer from switch

sudo tcpdump port 161

16:07:07.709666 IP 10.251.5.163.58394 > test2.domain.snmp:  C=comm GetRequest(28)  system.sysObjectID.0
16:07:07.712976 IP test2.domain.snmp > 10.251.5.163.58394:  C=comm GetResponse(37)  system.sysObjectID.0=E:cisco.1.1317

I guess something is not correct, but I do not really understand why the sysOid value get's interpreted as rfc1902.IpAddress in _convert().

I can easily run test code if desired.

functional degradation

I writed the function

def get(ip, community):                                                                   
    load(                                                                                 
        os.path.join(                                                                     
            CONF['abs_path'],                                                             
            "app/snmp/mib/SNMPv2-SMI.my"                                                  
        )                                                                                 
    )                                                                                     
    load(                                                                                 
        os.path.join(                                                                     
            CONF['abs_path'],                                                             
            "app/snmp/mib/BGP4-MIB.my"                                                    
        )                                                                                 
    )                                                                                     
    m = M(ip, community, 2)                                                               
    result = {}                                                                           
    try:                                                                                  
        result = dict([(str(idx), {'value': str(m.bgpPeerIdentifier[idx])})               
            for idx in m.bgpPeerIdentifier])                                              
    except SNMPException, err:                                                            
        print(err)                                                                        

    return result                                                                         
  • for snimpy==0.6.4:
    result is a dict with necessary data
  • for snimpy==0.7.0:
    TypeError: initializer for ctype 'char *' must be a str or list or tuple, not unicode
  • for snimpy==0.8.0:
    OIDs are not increasing
    {}

As example: the snmpwalk tool in shell returned also necessary data, but append similar error.

Sorry for my poor English.

Snimpy manager performs unnecessary SNMP gets

When iterating through the values of a column, snimpy manager does an SNMP Get for each item, when ProxyColumn.iteritems() already retrieved all or most of the values through SNMP GetBulk. This makes Snimpy fairly slow since it is retrieving the same data more than once.

Example:

from snimpy.manager import Manager as M
from snimpy.manager import load

load("IF-MIB.my)

m = M(host='EthernetSwitch.example.com', community="MySecret", version=2)

# this invokes ProxyColumn.iteritems() which does our GetBulk when it iterates through the items in self.session.walk(oid).. We already have all of our data.
for idx in m.ifName:

     # This ends up calling ProxyColumn._op("get", index) for each iteration, which contains records that were already retrieved with GetBulk as soon as we called m.ifName.iteritems()
     print m.ifName[idx]

Doc example fails: Doc example fails:

I followed the doc but got the following error:

from snimpy.manager import Manager as M
from snimpy.manager import load

load("IF-MIB")
m = M("localhost")
print(m.ifDescr[0])
Traceback (most recent call last):
  File "<input>", line 6, in <module>
  File "/home/ed8/projects/coaxis-opt/env/lib/python3.5/site-packages/snimpy/manager.py", line 537, in __getitem__
    return self._op("get", self._oid_suffix + index)
  File "/home/ed8/projects/coaxis-opt/env/lib/python3.5/site-packages/snimpy/manager.py", line 403, in _op
    *args)
  File "/home/ed8/projects/coaxis-opt/env/lib/python3.5/site-packages/snimpy/snmp.py", line 286, in get
    return self._op(self._cmdgen.getCmd, *oids)
  File "/home/ed8/projects/coaxis-opt/env/lib/python3.5/site-packages/snimpy/snmp.py", line 258, in _op
    raise SNMPException(str(errorIndication))
snimpy.snmp.SNMPException: No SNMP response received before timeout

I tried with another device I can ping and telnet to with same result

Question

Do I need to install a client/agent on my machine to be able to run snmp?

Windows support

In the installation docs libsmi is listed as a dependency for this tool. The docs elaborate various ways of installing on OS / Linux. Is there a recommended way of installing on windows?

Correction on issue #65

My apologies. I wasn't setting contextname through the parameters on Manager().

I was setting the context like this:
m._session._session._contextname = 'vlan-713'

It turns out that setting contextname when instantiating Manager doesn't work. I think you want to make this change:

diff --git a/snimpy/snmp.py b/snimpy/snmp.py
index 8a94e56..bc08c03 100644
--- a/snimpy/snmp.py
+++ b/snimpy/snmp.py
@@ -132,12 +132,12 @@ class Session(object):
         self._none = none
         if version == 3:
             self._cmdgen = cmdgen.CommandGenerator()
-            self._contextname = None
+            self._contextname = contextname
         else:
             if not hasattr(self._tls, "cmdgen"):
                 self._tls.cmdgen = cmdgen.CommandGenerator()
             self._cmdgen = self._tls.cmdgen
-            self._contextname = contextname
+            self._contextname = None
         if version == 1 and none:
             raise ValueError("None-GET requests not compatible with SNMPv1")

cffi/gcc failures preventing use of snimpy

OS: ArchLinux
Python: Version 2.7

I first installed snimpy with pip and it grabbed dependencies and cleared out as expected. When importing the manager module or running python2 -m snimpy, it raised the following:

$ python2 -m snimpy               
Traceback (most recent call last):
  File "/usr/lib/python2.7/runpy.py", line 162, in _run_module_as_main
    "__main__", fname, loader, pkg_name)
  File "/usr/lib/python2.7/runpy.py", line 72, in _run_code
    exec code in run_globals
  File "/usr/lib/python2.7/site-packages/snimpy/__main__.py", line 20, in <module>
    from snimpy import main
  File "/usr/lib/python2.7/site-packages/snimpy/main.py", line 41, in <module>
    from snimpy import manager
  File "/usr/lib/python2.7/site-packages/snimpy/manager.py", line 33, in <module>
    from snimpy import snmp, mib, basictypes
  File "/usr/lib/python2.7/site-packages/snimpy/mib.py", line 155, in <module>
    """, libraries=["smi"])
  File "/usr/lib/python2.7/site-packages/cffi/api.py", line 340, in verify
    lib = self.verifier.load_library()
  File "/usr/lib/python2.7/site-packages/cffi/verifier.py", line 73, in load_library
    self._write_source()
  File "/usr/lib/python2.7/site-packages/cffi/verifier.py", line 125, in _write_source
    file = open(self.sourcefilename, 'w')
IOError: [Errno 2] No such file or directory: '/usr/lib/python2.7/site-packages/snimpy/__pycache__/_cffi__x3a5e05ccxa0dd8598.c'

I had uninstall using pip and then grabbed the tarball directly from git, extracted, and when trying to create the sdist I get:

snimpy/__pycache__/_Mib_cffi_450f4c01x7b87f776.c:186:17: fatal error: smi.h: No such file or directory
 #include <smi.h>
                 ^
compilation terminated.
Traceback (most recent call last):
  File "setup.py", line 13, in <module>
    import snimpy.mib
  File "/home/codey/tmp/snimpy-master/snimpy/mib.py", line 161, in <module>
    modulename=cffi_fix.create_modulename("Mib", _CDEF, _SOURCE))
  File "/usr/lib/python2.7/site-packages/cffi/api.py", line 340, in verify
    lib = self.verifier.load_library()
  File "/usr/lib/python2.7/site-packages/cffi/verifier.py", line 74, in load_library
    self._compile_module()
  File "/usr/lib/python2.7/site-packages/cffi/verifier.py", line 139, in _compile_module
    outputfilename = ffiplatform.compile(tmpdir, self.get_extension())
  File "/usr/lib/python2.7/site-packages/cffi/ffiplatform.py", line 25, in compile
    outputfilename = _build(tmpdir, ext)
  File "/usr/lib/python2.7/site-packages/cffi/ffiplatform.py", line 51, in _build
    raise VerificationError('%s: %s' % (e.__class__.__name__, e))
cffi.ffiplatform.VerificationError: CompileError: command 'gcc' failed with exit status 1

Running the nose test returns the same:

$ python2 -m nose tests/test_snmp.py
snimpy/__pycache__/_Mib_cffi_450f4c01x7b87f776.c:186:17: fatal error: smi.h: No such file or directory
 #include <smi.h>
                 ^
compilation terminated.
E
======================================================================
ERROR: Failure: VerificationError (CompileError: command 'gcc' failed with exit status 1)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/usr/lib/python2.7/site-packages/nose/loader.py", line 414, in loadTestsFromName
    addr.filename, addr.module)
  File "/usr/lib/python2.7/site-packages/nose/importer.py", line 47, in importFromPath
    return self.importFromDir(dir_path, fqname)
  File "/usr/lib/python2.7/site-packages/nose/importer.py", line 94, in importFromDir
    mod = load_module(part_fqname, fh, filename, desc)
  File "/home/codey/tmp/snimpy-master/tests/test_snmp.py", line 4, in <module>
    from snimpy import basictypes, snmp, mib
  File "snimpy/basictypes.py", line 35, in <module>
    from snimpy import mib
  File "snimpy/mib.py", line 161, in <module>
    modulename=cffi_fix.create_modulename("Mib", _CDEF, _SOURCE))
  File "/usr/lib/python2.7/site-packages/cffi/api.py", line 340, in verify
    lib = self.verifier.load_library()
  File "/usr/lib/python2.7/site-packages/cffi/verifier.py", line 74, in load_library
    self._compile_module()
  File "/usr/lib/python2.7/site-packages/cffi/verifier.py", line 139, in _compile_module
    outputfilename = ffiplatform.compile(tmpdir, self.get_extension())
  File "/usr/lib/python2.7/site-packages/cffi/ffiplatform.py", line 25, in compile
    outputfilename = _build(tmpdir, ext)
  File "/usr/lib/python2.7/site-packages/cffi/ffiplatform.py", line 51, in _build
    raise VerificationError('%s: %s' % (e.__class__.__name__, e))
VerificationError: CompileError: command 'gcc' failed with exit status 1

----------------------------------------------------------------------
Ran 1 test in 0.001s

FAILED (errors=1)

Let me know if there's something I'm leaving out. I like the more pythonic interface here compared to pysnmp and look forward to getting it to work.

libsmi requirement seems obsolete

Just a quick note that pysnmp does not depend on libsmi anymore. It relies on pure-Python MIB parser which pysnmp calls behind the scenes.

That should work with any modern pysnmp, without any code modification on snmpy side.

-

Wrong repo

UnicodeDecodeError on value conversion

I'm currently using snimpy (in a python2.6 virtualenv) to pull the cdp info from a variety of network devices.

Having set up a manager object:

host = "192.168.1.1"
comm = "public"

mibs = ("/usr/lib/net/MIBs/CISCO-SMI.my",
        "/usr/lib/net/MIBs/CISCO-TC.my",
        "/usr/lib/net/MIBs/CISCO-VTP-MIB.my",
        "/usr/lib/net/MIBs/CISCO-CDP-MIB.my")

for mib in mibs:
    snimpy.manager.load(mib)

session = snimpy.manager.Manager(host,
                                 community=comm,
                                 version=2,
                                 cache=True)

I then want to get cdpCacheDevicePort:

for index, port in session.cdpCacheDevicePort.iteritems():
    print repr((index, port))

Results:

((<Integer: 1>, <Integer: 1>), '26')
((<Integer: 2>, <Integer: 1>), '4')
((<Integer: 3>, <Integer: 1>), '3')
((<Integer: 75>, <Integer: 1>), '\x00`\xb9\xb7\xf6v')
((<Integer: 148>, <Integer: 1>), '\x00`\xb9\xb6\xc4~')

However, if I iterate over another related oid, and use it's index for that iteration to query the value of this field, I get an error when it reaches the 'hex format' values:

for index, chassis in session.cdpCacheDeviceId.iteritems():
    print repr((index, session.cdpCacheDevicePort[index]))

Results:

((<Integer: 1>, <Integer: 1>), <String: 26>)
((<Integer: 2>, <Integer: 1>), <String: 4>)
((<Integer: 3>, <Integer: 1>), <String: 3>)
Traceback (most recent call last):
  File "/tmp/snmpy.py", line 23, in <module>
    print repr((index, session.cdpCacheDevicePort[index]))
  File "/home/mrichar1/git/netmap/networkx/lib/python2.6/site-packages/snimpy/manager.py", line 347, in __getitem__
    return self._op("get", index)
  File "/home/mrichar1/git/netmap/networkx/lib/python2.6/site-packages/snimpy/manager.py", line 343, in _op
    return self.proxy.type(self.proxy, result)
  File "/home/mrichar1/git/netmap/networkx/lib/python2.6/site-packages/snimpy/basictypes.py", line 109, in __new__
    value = String._internal(entity, self)
  File "/home/mrichar1/git/netmap/networkx/lib/python2.6/site-packages/snimpy/basictypes.py", line 533, in _internal
    return cls._fromBytes(value._value, entity.fmt)
  File "/home/mrichar1/git/netmap/networkx/lib/python2.6/site-packages/snimpy/basictypes.py", line 442, in _fromBytes
    result += bb.decode("ascii")
UnicodeDecodeError: 'ascii' codec can't decode byte 0xb9 in position 2: ordinal not in range(128)

It looks like in the iteration the raw value is returned - however when asking for a specific instance, some formatting is done (e.g '3' versus '<String: 3>'). Is this a bug? Or Is there a way to avoid this behaviour (without having to iterate over the oid to get a specific value) and always get the raw value?

Thanks!

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.