python - query from sqlalchemy returns AttributeError: 'NoneType' object -
from pox.core import core import pox.openflow.libopenflow_01 of import re import datetime sqlalchemy import create_engine, foreignkey sqlalchemy import column, date, integer, string sqlalchemy.ext.declarative import declarative_base sqlalchemy.orm import relationship, backref sqlalchemy import create_engine sqlalchemy.orm import sessionmaker sqlalchemy.sql.expression import exists log = core.getlogger() engine = create_engine('sqlite:///nwtopology.db', echo=false) base = declarative_base() session = sessionmaker(bind=engine) session = session() ######################################################################## class sourcetoport(base): """""" __tablename__ = 'source_to_port' id = column(integer, primary_key=true) port_no = column(integer) src_address = column(string,index=true) #---------------------------------------------------------------------- def __init__(self, src_address,port_no): """""" self.src_address = src_address self.port_no = port_no ######################################################################## #create tables base.metadata.create_all(engine) class tutorial (object): def __init__ (self, connection): self.connection = connection connection.addlisteners(self) # use table keep track of ethernet address on # switch port (keys macs, values ports). self.mac_to_port = {} self.matrix={} #this keep track of traffic matrix. #matrix[i][j]=number of times packet went j def send_packet (self, buffer_id, raw_data, out_port, in_port): #print "calling send_packet" #sends packet out of specified switch port. msg = of.ofp_packet_out() msg.in_port = in_port msg.data = raw_data # add action send specified port action = of.ofp_action_output(port = out_port) msg.actions.append(action) # send message switch self.connection.send(msg) def act_like_hub (self, packet, packet_in): #flood packet on ports self.send_packet(packet_in.buffer_id, packet_in.data, of.ofpp_flood, packet_in.in_port) def act_like_switch (self, packet, packet_in): """ implement switch-like behavior. """ # learn port source mac #print "recieved port ",packet_in.in_port , "source ",packet.src # create session #session = sessionmaker(bind=engine) #session = session() self.mac_to_port[packet.src]=packet_in.in_port #if self.mac_to_port.get(packet.dst)!=none: #print "count dst",session.query(sourcetoport).filter_by(src_address=str(packet.dst)).count(),str(packet.dst) #if session.query(sourcetoport).filter_by(src_address=str(packet.dst)).count(): if session.query(exists().where(sourcetoport.src_address == str(packet.dst))).scalar() not none: #send packet print "got info database" q_res = session.query(sourcetoport).filter_by(src_address=str(packet.dst)).one() self.send_packet(packet_in.buffer_id, packet_in.data,q_res.port_no, packet_in.in_port) #create flow modification message msg = of.ofp_flow_mod() #set fields match incoming packet msg.match = of.ofp_match.from_packet(packet) #send rule switch not query controller again. msg.actions.append(of.ofp_action_output(port=q_res.port_no)) #push rule self.connection.send(msg) else: #flood packet out don't know node. print "flooding first packet" self.send_packet(packet_in.buffer_id, packet_in.data, of.ofpp_flood, packet_in.in_port) #self.matrix[(packet.src,packet.dst)]+=1 entry = sourcetoport(src_address=str(packet.src) , port_no=packet_in.in_port) #add record session object session.add(entry) #add record session object session.commit() def _handle_packetin (self, event): """ handles packet in messages switch. """ packet = event.parsed # parsed packet data. if not packet.parsed: log.warning("ignoring incomplete packet") return packet_in = event.ofp # actual ofp_packet_in message. #self.act_like_hub(packet, packet_in) self.act_like_switch(packet, packet_in) def launch (): """ starts component """ def start_switch (event): log.debug("controlling %s" % (event.connection,)) tutorial(event.connection) core.openflow.addlistenerbyname("connectionup", start_switch)
when run above code following error:
the problem facing reason if use
if session.query(exists().where(sourcetoport.src_address == str(packet.dst))).scalar() not none: in place of count query. #if session.query(sourcetoport).filter_by(src_address=str(packet.dst)).count():
the querying database
q_res = session.query(sourcetoport).filter_by(src_address=str(packet.dst)).first() self.send_packet(packet_in.buffer_id, packet_in.data,q_res.port_no, packet_in.in_port)
is giving following error:
debug:core:pox 0.1.0 (betta) going up... debug:core:running on cpython (2.7.3/aug 1 2012 05:14:39) debug:core:platform linux-3.5.0-23-generic-x86_64-with-ubuntu-12.04-precise info:core:pox 0.1.0 (betta) up. debug:openflow.of_01:listening on 0.0.0.0:6633 info:openflow.of_01:[00-00-00-00-00-02 1] connected debug:tutorial:controlling [00-00-00-00-00-02 1] got info database error:core:exception while handling connection!packetin... traceback (most recent call last): file "/home/karthik/pox/pox/lib/revent/revent.py", line 234, in raiseeventnoerrors return self.raiseevent(event, *args, **kw) file "/home/karthik/pox/pox/lib/revent/revent.py", line 281, in raiseevent rv = event._invoke(handler, *args, **kw) file "/home/karthik/pox/pox/lib/revent/revent.py", line 159, in _invoke return handler(self, *args, **kw) file "/home/karthik/pox/tutorial.py", line 118, in _handle_packetin self.act_like_switch(packet, packet_in) file "/home/karthik/pox/tutorial.py", line 86, in act_like_switch self.send_packet(packet_in.buffer_id, packet_in.data,q_res.port_no, packet_in.in_port) attributeerror: 'nonetype' object has no attribute 'port_no' got info database error:core:exception while handling connection!packetin...
this line:
if session.query(exists().where(sourcetoport.src_address == str(packet.dst))).scalar() not none:
is true. reason scalar()
returns none
if there no rows. query looks select exists (select * source_to_port source_to_port.src_address=?)
. always return 1 row 1 column. result true
or false
, never none
.
moving on line before line throws exception: first()
returns none
if there no matches, q_res
none
. since q_res
none
, q_res.port_no
on next line raises exception.
(note can use one()
if want exception thrown if there no match.)
if expecting match, double-check data , filter_by()
condition make sure doing think should.
however recommend use 1 query instead of 2 using first()
or one()
. first()
, branch based on q_res
being none
or not:
q_res = session.query(sourcetoport).filter_by(src_address=str(packet.dst)).first() if q_res not none: print "got info database" self.send_packet(....) ... else: print "flooding first packet" ...
or one()
, put "flooding" branch in exception handler:
from sqlalchemy.orm.exc import (noresultfound, multipleresultsfound) try: q_res = session.query(sourcetoport).filter_by(src_address=str(packet.dst)).one() except noresultfound: print "flooding first packet" ... # except multipleresultsfound: # print "more 1 result found! wut?!" else: print "got info database" ...
a difference between these 2 approaches one()
ensure there 1 and one result, whereas first()
doesn't care if there multiple results.
Comments
Post a Comment