Question

I would like to check tree system's status, I'm using the following code, but I have problem with the timeout, for example when one of the system is down than in the next system I'm getting a time out as well.

try:
    snmp = pySNMPCom( ip="192.168.0.1", 23434, 30 )
    """It's hangig 30 seconds that is the timeout"""            
    data = snmp.emite_command( command )
    snmp.destroye()                
except:  
    """Smtp timeout"""
    snmp.destroye()  

try:
    snmp = pySNMPCom( ip="192.168.0.2", 23434, 30 )
    """It's going to the exception immediately, it suppose to hung 30 seconds...""" 
    data = snmp.emite_command( command )
    snmp.destroye()                
except:  
    """Smtp timeout"""
    snmp.destroye()  

The class:

# -*- coding: utf-8 -*-
from pysnmp.carrier.asynsock.dispatch import AsynsockDispatcher
from pysnmp.carrier.asynsock.dgram import udp
from pyasn1.codec.ber import encoder, decoder
from pysnmp.proto import api
from time import time


class pySNMPCom():

    def __init__( self, ip, port, timeout ):
        self.__host = ip
        self.__port = port
        self.__timeout = timeout

    def set_cmd( self, cmd ):
        self.cmd = cmd

    def __set_message( self ):
        self.__pMod = api.protoModules[api.protoVersion1]

        self.__reqPDU = self.__pMod.GetRequestPDU()
        self.__pMod.apiPDU.setDefaults( self.__reqPDU )
        self.__pMod.apiPDU.setVarBinds( 
            self.__reqPDU, ( ( self.cmd, self.__pMod.Null( '' ) ),
                )
            )
        # Build message
        self.__reqMsg = self.__pMod.Message()
        self.__pMod.apiMessage.setDefaults( self.__reqMsg )
        self.__pMod.apiMessage.setCommunity( self.__reqMsg, 'public' )
        self.__pMod.apiMessage.setPDU( self.__reqMsg, self.__reqPDU )

    def __cbTimerFun( self, timeNow, startedAt = time() ):
        if timeNow - startedAt > self.__timeout:
            raise "Request timed out"

    def __cbRecvFun( self, transportDispatcher, transportDomain, transportAddress, wholeMsg, reqPDU = '' ):
        if not reqPDU:
            reqPDU = self.__reqPDU
        self.ret = ''
        while wholeMsg:
            rspMsg, wholeMsg = decoder.decode( wholeMsg, asn1Spec = self.__pMod.Message() )
            rspPDU = self.__pMod.apiMessage.getPDU( rspMsg )
            # Match response to request
            if self.__pMod.apiPDU.getRequestID( reqPDU ) == self.__pMod.apiPDU.getRequestID( rspPDU ):
                # Check for SNMP errors reported
                errorStatus = self.__pMod.apiPDU.getErrorStatus( rspPDU )
                if errorStatus:
                    print errorStatus.prettyPrint()
                else:
                    for oid, val in self.__pMod.apiPDU.getVarBinds( rspPDU ):                        
                        self.ret = val

                transportDispatcher.jobFinished( 1 )

    def emite_command( self, cmd = '' ):
        if not cmd:
            cmd = self.cmd
        self.set_cmd( cmd )
        self.__set_message()        

        transportDispatcher = AsynsockDispatcher()
        transportDispatcher.registerTransport( 
            udp.domainName, udp.UdpSocketTransport().openClientMode()
            )
        transportDispatcher.registerRecvCbFun( self.__cbRecvFun )
        transportDispatcher.registerTimerCbFun( self.__cbTimerFun )
        transportDispatcher.sendMessage( 
            encoder.encode( self.__reqMsg ), udp.domainName, ( self.__host, self.__port )
            )
        transportDispatcher.jobStarted( 1 )
        transportDispatcher.runDispatcher()
        transportDispatcher.closeDispatcher()

        return self.ret

    def destroye( self ):
        del self      
Was it helpful?

Solution

You initialize the startedAt variable as a defaulted method parameter. That happens only once in a module runtime and never repeats on class re-instantiation. So all your queries timings are measured against the initial staredAt value. Therefore all queries occurring past startedAt + 30 will timeout right away.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top