Error malicioso en el cliente pysnmp twisted con más de 1000 hosts

Tengo este codigo

from twisted.internet import reactor from twisted.internet import defer, task from pysnmp.entity import engine, config from pysnmp.carrier.twisted import dispatch from pysnmp.carrier.twisted.dgram import udp from pysnmp.entity.rfc3413.twisted import cmdgen import __webimport__ import tools.config from tools.database import makedsn import psycopg2 def cmp_varBinds(varBind, varName): if varName[0] in str(varBind[0]): return True def cbFun(cbCtx, ip, varNames): (errorIndication, errorStatus, errorIndex, varBinds) = cbCtx if varBinds and any(map(cmp_varBinds, varBinds[0], varNames)): print ip, [str(x[1]) for x in varBinds[0]] df = defer.Deferred() df.addCallback(cbFun, ip=ip, varNames=varNames) return df # This also indicates that we wish to continue walkin def parallel(iterable, count, callable, *args, **named): coop = task.Cooperator() work = (callable(elem, *args, **named) for elem in iterable) return defer.DeferredList([coop.coiterate(work) for i in xrange(count)]) def fetch(host): id, ip, community, hc = host snmpEngine = engine.SnmpEngine() snmpEngine.registerTransportDispatcher(dispatch.TwistedDispatcher()) config.addV1System(snmpEngine, 'test-agent', community) config.addTargetParams(snmpEngine, 'myParams', 'test-agent', 'noAuthNoPriv', 1) config.addTargetAddr( snmpEngine, 'myRouter', config.snmpUDPDomain, (ip, 161), 'myParams', timeout=1 ) # Transport config.addSocketTransport( snmpEngine, udp.domainName, udp.UdpTwistedTransport().openClientMode() ) getCmdGen = cmdgen.NextCommandGenerator() varNames = [('1.3.6.1.2.1.2.2.1.11', None), ('1.3.6.1.2.1.2.2.1.12', None), ('1.3.6.1.2.1.2.2.1.13', None), ('1.3.6.1.2.1.2.2.1.14', None)] df = getCmdGen.sendReq(snmpEngine, 'myRouter', varNames) df.addCallback(cbFun, ip=ip, varNames=varNames) return df dsn = makedsn(tools.config.main_db) connection = psycopg2.connect(dsn) cursor = connection.cursor() cursor.execute("""SELECT e.id, e.ip, e.snmpcomm, e.hccnt FROM snmp_ports sp, equipment e WHERE e.snmp = 'Y' and sp.equipment = e.id GROUP BY e.id,e.ip,e.snmpcomm,e.hccnt ORDER BY e.id""") hosts = cursor.fetchall() finished = parallel(hosts, len(hosts), fetch) finished.addErrback(log.err) finished.addCallback(lambda ign: reactor.stop()) reactor.run() 

Obtengo 4000 hosts de la base de datos y pregunto a cada uno de ellos. Si configuro el límite 1000 en la consulta de SQL funciona bien. Pero cuando los hosts son más de 1000 me sale un error:

 Unhandled Error Traceback (most recent call last): File "crawler.py", line 98, in  File "/home/kalombo/.virtualenvs/dev/local/lib/python2.7/site-packages/twisted/internet/base.py", line 1192, in run File "/home/kalombo/.virtualenvs/dev/local/lib/python2.7/site-packages/twisted/internet/base.py", line 1201, in mainLoop ---  --- File "/home/kalombo/.virtualenvs/dev/local/lib/python2.7/site-packages/twisted/internet/base.py", line 824, in runUntilCurrent File "/home/kalombo/.virtualenvs/dev/local/lib/python2.7/site-packages/pysnmp/carrier/base.py", line 52, in _cbFun File "/home/kalombo/.virtualenvs/dev/local/lib/python2.7/site-packages/pysnmp/entity/engine.py", line 64, in __receiveMessageCbFun File "/home/kalombo/.virtualenvs/dev/local/lib/python2.7/site-packages/pysnmp/proto/rfc3412.py", line 274, in receiveMessage File "/home/kalombo/.virtualenvs/dev/local/lib/python2.7/site-packages/pysnmp/smi/builder.py", line 299, in importSymbols File "/home/kalombo/.virtualenvs/dev/local/lib/python2.7/site-packages/pysnmp/smi/builder.py", line 270, in loadModules pysnmp.smi.error.SmiError: MIB file "__SNMPv2-MIB.py[co]" not found in search path 

Y luego el script se detiene. ¿Por qué sucede esto?

¿Qué pysnmp estás usando? Asegúrese de que está utilizando la última versión de pysnmp.

Como nota al margen, su enfoque es súper ineficiente, ya que parece que reinicializa SnmpEngine [pesado] en cada operación GET. Mejor manera sería mantener una única instancia de SnmpEngine persistente por proceso / hilo.

Si esto solo sucede cuando aumenta el nivel de concurrencia, entonces una explicación probable es que se ha topado con el límite en el número de archivos abiertos que la plataforma le permitirá tener en cualquier momento. Cada socket abierto cuenta para este límite, al igual que los archivos “regulares” (desde el sistema de archivos).

Si usas todos los archivos permitidos, Python no puede leer el código fuente de los módulos fuera del disco porque esa plataforma no lo deja abrirlos.

No es del todo obvio que esto es lo que está sucediendo en este caso, ya que (si lo es), pysnmp está manejando la excepción real y está reenviando una nueva excepción que oculta los detalles.

Si este es el problema, puede resolverlo elevando el límite de archivos abiertos. La mayoría de las veces puedes hacer esto ejecutando:

 $ ulimit -Sn 2048 

Lea más sobre ulimit ( help ulimit en su shell, en Internet ) para obtener más detalles sobre cómo controlar ese límite.