[Twisted-Python] DeferredList?

Don Smith donwsmith at gmail.com
Tue Feb 26 17:41:56 EST 2008


Greetings,

I have a problem I hope someone here can assist with. I'm using TwistedSNMP
to query a bunch of SNMP devices asynchronously. The behavior I'm trying to
get is to get is to query all the devices via SNMP, each query returns a
deferred, and when all their callbacks have been fired then I want to stop
the reactor and thereby exit the program. I thought perhaps I could put each
of these SNMP deferreds in a DeferredList and add a callback to the
DeferredList that would stop the reactor but it does not do that. Enclosed
is a code sample. Am I doing something incorrectly, or should I do something
different?

Thanks! -Don

"""Trivial example to retrieve an OID from a remote Agent"""
from twisted.internet import reactor
from twistedsnmp import snmpprotocol, agentproxy
from twisted.enterprise import adbapi
from twisted.internet import defer
import os

APPNAME = 'ClearSNMP'
d_results = {} #dictionary to store results
device_name = 'Unknown'

db_conn = {'user':'sa',
            'password':'password',
            'host':'localhost',
            'database':'ClearSNMP'
            }

community_string = 'public'

deferred_list = [] #list to help group the snmp requests

outfile = open('outfile.csv','wb',0)
#add headers to the outfile
outfile.write
("device_name,link_oid,link_name,link_capacity_oid,link_capacity,traffic_in_oid,traffic_in,traffic_out_oid,traffic_out")

#create the database connection pool
dbpool = adbapi.ConnectionPool("pymssql", user=db_conn['user'],
password=db_conn['password'], host=db_conn['host'],
database=db_conn['database'])


def main( class_handler, proxy, oids ):
    """Do a getTable on proxy for OIDs and store in oidStore"""
    df = proxy.getTable(
        oids, timeout=.25, retryCount=5
    )
    if class_handler == 'tasman':
        df.addCallback( tasmanResults )
    else:
        df.addCallback( results )
    #df.addCallback( exiter )
    df.addErrback( errorReporter, proxy )
    #df.addErrback( exiter )
    return df


def tasmanResults( result ):

    """Results 'appear' to be a nested dictionary, but it is really an
object of OIDs. I figured out how to get to the OIDs by
    casting them as a dictionary using the built_in dict() function. Now I
can iterate over all the OIDs."""
    #print 'Results:'
    d_table_key = {}
    for table_key in result.keys():
        #get the device name. for some reason i have to do this in a loop as
just saying dict(result[table_key])['.1.3.6.1.2.1.1.5.0'] doesn't work
        for oid in dict(result[table_key]).keys():
            if oid=='.1.3.6.1.2.1.1.5.0':
                device_name=str(dict(result[table_key])[oid])

        d_oid = {}
        for oid in dict(result[table_key]).keys():
            d_oid[str(oid)]=dict(result[table_key])[oid]
        d_table_key[str(table_key)] = d_oid
    d_results[device_name]=d_table_key

    #specify the table oids so we can match them appropriately later
    link_name_table    = ".1.3.6.1.2.1.2.2.1.2"
    link_capacity_table    = ".1.3.6.1.2.1.2.2.1.5"
    traffic_in_table    = ".1.3.6.1.2.1.2.2.1.10"
    traffic_out_table    = ".1.3.6.1.2.1.2.2.1.16"

    # For each link name in the table I need to get the values from the
link_capacity, traffic_in and traffic_out tables and put them in the same
line

    for i in d_results.keys():
        d_row = {} #holds the column values for a row

        #set device_name in Row
        d_row['device_name'] = device_name

        for k in d_results[i][link_name_table]:
            #set link_oid and link_name in Row
            d_row['link_oid'] = k
            d_row['link_name'] =
d_results[i][link_name_table][d_row['link_oid']]

            #lookup the capacity metric for this link_oid
            #create the oid to lookup
            d_row['link_capacity_oid'] =
d_row['link_oid'].replace(link_name_table,link_capacity_table)
            d_row['link_capacity'] =
d_results[i][link_capacity_table][d_row['link_capacity_oid']]

            #lookup the traffic_in metric for this link_oid
            #create the oid to lookup
            d_row['traffic_in_oid'] =
d_row['link_oid'].replace(link_name_table,traffic_in_table)
            d_row['traffic_in'] =
d_results[i][traffic_in_table][d_row['traffic_in_oid']]

            #lookup the traffic_out metric for this link_oid
            #create the oid to lookup
            d_row['traffic_out_oid'] =
d_row['link_oid'].replace(link_name_table,traffic_out_table)
            d_row['traffic_out'] =
d_results[i][traffic_out_table][d_row['traffic_out_oid']]

            #Calculate Utilization - if we can


            #print d_row
            out =
d_row['device_name']+","+d_row['link_oid']+","+d_row['link_name']+","+d_row['link_capacity_oid']+","+str(d_row['link_capacity'])+","+d_row['traffic_in_oid']+","+str(d_row['traffic_in'])+","+d_row['traffic_out_oid']+","+str(d_row['traffic_out'])+'\r\n'
            #print out
            outfile.write(out)
    return result


def errorReporter( err, proxy ):
    #print 'ERROR', err.getTraceback()
    #log the failed snmp query attempt
    print 'Failed to retrieve SNMP counters from agent:',proxy
    return err

def exiter( value ):

    reactor.stop()
    outfile.close()

    return value


def getNetworkElements():
    return dbpool.runQuery("select top 10 ip, mkt, dns_name, dns_fqdn from
dns where dns_type='TASMAN'")

def printResult(l):
    for item in l:
        print "Fetching counters for "+item[2]
        #deferred_list.append(snmpSetup(item[0], 161, 'ctipublic','tasman'))
    ipAddress = item[0]
    portno = 161
    community = community_string
    class_handler = 'tasman'
        print ipAddress,portno
        # choose random port in range 25000 to 30000
        port = snmpprotocol.port()
        targetPort = int(portno)
        proxy = agentproxy.AgentProxy(ipAddress,
                  targetPort,
                  community = community,
                  snmpVersion = 'v1',
                  protocol = port.protocol,
                  )


        d_oids = {'.1.3.6.1.2.1.1':"System Tables",
            '.1.3.6.1.2.1.2.2.1.2':"Circuit Name",
            '.1.3.6.1.2.1.2.2.1.5':"Capacity",
            '.1.3.6.1.2.1.2.2.1.10':"Traffic In",
            '.1.3.6.1.2.1.2.2.1.16':"Traffic Out"
            }

    """Do a getTable on proxy for OIDs and store in oidStore"""
    df = proxy.getTable(
        d_oids, timeout=.25, retryCount=5
    )
    if class_handler == 'tasman':
        df.addCallback( tasmanResults )
    else:
        df.addCallback( results )
    df.addErrback( errorReporter, proxy )
    deferred_list.append(df)
    return



if __name__ == "__main__":
    import sys
    #start the log service
    from twisted.python import log
    from twisted.python import logfile
    # rotate every 100000000 bytes
    f = logfile.LogFile(APPNAME+str(os.getpid())+".log", "Logs",
rotateLength=100000000)
    # setup logging to use our new logfile
    #log.startLogging(f)


    g = getNetworkElements().addCallback(printResult)
    dl = defer.DeferredList(deferred_list, 0, 0, 1 )
    print dir(dl)
    dl.addCallback(exiter)

    reactor.run()
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://twistedmatrix.com/pipermail/twisted-python/attachments/20080226/dcde14a6/attachment.htm 


More information about the Twisted-Python mailing list