Merge pull request #303 from pgreyson/master

add/delete flow implemented
diff --git a/scripts/ctrl-one.sh b/scripts/ctrl-one.sh
new file mode 100755
index 0000000..207d3f2
--- /dev/null
+++ b/scripts/ctrl-one.sh
@@ -0,0 +1,26 @@
+#! /bin/bash
+
+if [ "x$1" == "x" ];
+then
+    echo "No controller specified"
+    exit 1
+fi
+
+#controller=`hostname`
+controller=$1
+switches=`ifconfig -a | grep sw |grep -v eth | awk '{print $1}'`
+
+function host2ip (){
+   ip=`grep $1 /etc/hosts |grep -v "ip6"|  awk '{print $1}'`
+   echo $ip
+}
+
+url=""
+for c in $controller; do
+  url="$url tcp:`host2ip $c`:6633"
+done
+echo $url
+for s in $switches; do
+    echo "set switch $s controller $url"
+    sudo ovs-vsctl set-controller $s $url
+done
diff --git a/src/main/java/net/floodlightcontroller/flowcache/FlowManager.java b/src/main/java/net/floodlightcontroller/flowcache/FlowManager.java
index 0e37e17..25cf367 100644
--- a/src/main/java/net/floodlightcontroller/flowcache/FlowManager.java
+++ b/src/main/java/net/floodlightcontroller/flowcache/FlowManager.java
@@ -1323,7 +1323,7 @@
      * @return the list of flows that are going out from the port.
      */
     @Override
-    public Iterable<FlowPath> getFlows(IPortObject port) {
+    public Iterable<FlowPath> getOutFlows(IPortObject port) {
 	// TODO: We need it now: Pankaj
 	return null;
     }
diff --git a/src/main/java/net/floodlightcontroller/routing/TopoRouteService.java b/src/main/java/net/floodlightcontroller/routing/TopoRouteService.java
index fd7c364..773083b 100644
--- a/src/main/java/net/floodlightcontroller/routing/TopoRouteService.java
+++ b/src/main/java/net/floodlightcontroller/routing/TopoRouteService.java
@@ -13,6 +13,7 @@
 
 import net.floodlightcontroller.core.INetMapTopologyObjects.ISwitchObject;
 import net.floodlightcontroller.core.INetMapTopologyService.ITopoRouteService;
+import net.floodlightcontroller.core.ISwitchStorage.SwitchState;
 import net.floodlightcontroller.core.module.FloodlightModuleContext;
 import net.floodlightcontroller.core.module.FloodlightModuleException;
 import net.floodlightcontroller.core.module.IFloodlightModule;
@@ -23,14 +24,12 @@
 import net.floodlightcontroller.util.Port;
 import net.floodlightcontroller.util.SwitchPort;
 import net.onrc.onos.util.GraphDBConnection;
+import net.onrc.onos.util.GraphDBConnection.Transaction;
 
 import org.openflow.util.HexString;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import com.thinkaurelius.titan.core.TitanFactory;
-import com.thinkaurelius.titan.core.TitanGraph;
-import com.thinkaurelius.titan.core.TitanTransaction;
 import com.tinkerpop.blueprints.Direction;
 import com.tinkerpop.blueprints.TransactionalGraph.Conclusion;
 import com.tinkerpop.blueprints.Vertex;
@@ -194,17 +193,15 @@
      */
     
     public void prepareShortestPathTopo() {
-	TitanGraph titanGraph = TitanFactory.open("/tmp/cassandra.titan");
-	TitanTransaction titanTransaction = titanGraph.startTransaction();
 	shortestPathTopo = new HashMap<Long, Node>();
 
 	//
 	// Fetch the relevant info from the Switch and Port vertices
 	// from the Titan Graph.
 	//
-	Iterable<Vertex> nodes = titanTransaction.getVertices("type", "switch");
-	for (Vertex nodeVertex : nodes) {
-	
+	Iterable<ISwitchObject> nodes = conn.utils().getActiveSwitches(conn);
+	for (ISwitchObject switchObj : nodes) {
+	    Vertex nodeVertex = switchObj.asVertex();
 	    //
 	    // The Switch info
 	    //
@@ -245,6 +242,11 @@
 		    // The neighbor Switch info
 		    //
 		    for (Vertex neighborVertex : neighborPortVertex.getVertices(Direction.IN, "on")) {
+			// Ignore inactive switches
+			String state = neighborVertex.getProperty("state").toString();
+			if (! state.equals(SwitchState.ACTIVE.toString()))
+			    continue;
+
 			String neighborDpid = neighborVertex.getProperty("dpid").toString();
 			long neighborId = HexString.toLong(neighborDpid);
 			Node neighbor = shortestPathTopo.get(neighborId);
@@ -257,8 +259,7 @@
 		}
 	    }
 	}
-
-	titanTransaction.stopTransaction(Conclusion.SUCCESS);
+	conn.endTx(Transaction.COMMIT);
     }
 
     /**
@@ -409,12 +410,17 @@
 	result_data_path.setSrcPort(src);
 	result_data_path.setDstPort(dest);
 
-	TitanGraph titanGraph = TitanFactory.open("/tmp/cassandra.titan");
-	TitanTransaction titanTransaction = titanGraph.startTransaction();
-
 	String dpid_src = src.dpid().toString();
 	String dpid_dest = dest.dpid().toString();
 
+	// Get the source and destination switches
+	ISwitchObject srcSwitch =
+	    conn.utils().searchActiveSwitch(conn, dpid_src);
+	ISwitchObject destSwitch =
+	    conn.utils().searchActiveSwitch(conn, dpid_dest);
+	if (srcSwitch == null || destSwitch == null) {
+	    return null;
+	}
 
 	//
 	// Test whether we are computing a path from/to the same DPID.
@@ -426,22 +432,10 @@
 	    flowEntry.setInPort(src.port());
 	    flowEntry.setOutPort(dest.port());
 	    result_data_path.flowEntries().add(flowEntry);
-	    titanTransaction.stopTransaction(Conclusion.SUCCESS);
-	    // titanTransaction.shutdown();
+	    conn.endTx(Transaction.COMMIT);
 	    return result_data_path;
 	}
 
-
-	// Get the source vertex
-
-	ISwitchObject srcSwitch = conn.utils().searchSwitch(conn, dpid_src);
-	ISwitchObject destSwitch = conn.utils().searchSwitch(conn, dpid_dest);
-
-	if (srcSwitch == null || destSwitch == null) {
-		return null;
-	}
-
-
 	Vertex v_src = srcSwitch.asVertex();	
 	Vertex v_dest = destSwitch.asVertex();
 
@@ -464,6 +458,11 @@
 	    for (Vertex parentPort : nextVertex.getVertices(Direction.OUT, "on")) {
 		for (Vertex childPort : parentPort.getVertices(Direction.OUT, "link")) {
 		    for (Vertex child : childPort.getVertices(Direction.IN, "on")) {
+			// Ignore inactive switches
+			String state = child.getProperty("state").toString();
+			if (! state.equals(SwitchState.ACTIVE.toString()))
+			    continue;
+
 			if (! visitedSet.contains(child)) {
 			    previousVertexMap.put(parentPort, nextVertex);
 			    previousVertexMap.put(childPort, parentPort);
@@ -489,7 +488,6 @@
 	Collections.reverse(resultPath);
 
 
-
 	//
 	// Loop through the result and prepare the return result
 	// as a list of Flow Entries.
@@ -553,8 +551,7 @@
 	    result_data_path.flowEntries().add(flowEntry);
 	}
 
-	titanTransaction.stopTransaction(Conclusion.SUCCESS);
-	// titanTransaction.shutdown();
+	conn.endTx(Transaction.COMMIT);
 	if (result_data_path.flowEntries().size() > 0)
 	    return result_data_path;
 
diff --git a/src/main/java/net/floodlightcontroller/util/FlowPath.java b/src/main/java/net/floodlightcontroller/util/FlowPath.java
index 7fcb2e6..f4c25c2 100644
--- a/src/main/java/net/floodlightcontroller/util/FlowPath.java
+++ b/src/main/java/net/floodlightcontroller/util/FlowPath.java
@@ -1,5 +1,9 @@
 package net.floodlightcontroller.util;
 
+import java.util.ArrayList;
+
+import net.floodlightcontroller.core.INetMapTopologyObjects.IFlowEntry;
+import net.floodlightcontroller.core.INetMapTopologyObjects.IFlowPath;
 import net.floodlightcontroller.util.CallerId;
 import net.floodlightcontroller.util.DataPath;
 import net.floodlightcontroller.util.FlowId;
@@ -20,6 +24,75 @@
     public FlowPath() {
 	dataPath = new DataPath();
     }
+    
+    /**
+     * Constructor to instantiate from object in Network Map
+     */
+    public FlowPath(IFlowPath flowObj) {
+    	dataPath = new DataPath();
+    	this.setFlowId(new FlowId(flowObj.getFlowId()));
+    	this.setInstallerId(new CallerId(flowObj.getInstallerId()));
+    	this.dataPath().srcPort().setDpid(new Dpid(flowObj.getSrcSwitch()));
+    	this.dataPath().srcPort().setPort(new Port(flowObj.getSrcPort()));
+    	this.dataPath().dstPort().setDpid(new Dpid(flowObj.getDstSwitch()));
+    	this.dataPath().dstPort().setPort(new Port(flowObj.getDstPort()));
+
+    	//
+    	// Extract all Flow Entries
+    	//
+    	Iterable<IFlowEntry> flowEntries = flowObj.getFlowEntries();
+    	for (IFlowEntry flowEntryObj : flowEntries) {
+    	    FlowEntry flowEntry = new FlowEntry();
+    	    flowEntry.setFlowEntryId(new FlowEntryId(flowEntryObj.getFlowEntryId()));
+    	    flowEntry.setDpid(new Dpid(flowEntryObj.getSwitchDpid()));
+
+    	    //
+    	    // Extract the match conditions
+    	    //
+    	    FlowEntryMatch match = new FlowEntryMatch();
+    	    Short matchInPort = flowEntryObj.getMatchInPort();
+    	    if (matchInPort != null)
+    		match.enableInPort(new Port(matchInPort));
+    	    Short matchEthernetFrameType = flowEntryObj.getMatchEthernetFrameType();
+    	    if (matchEthernetFrameType != null)
+    		match.enableEthernetFrameType(matchEthernetFrameType);
+    	    String matchSrcIPv4Net = flowEntryObj.getMatchSrcIPv4Net();
+    	    if (matchSrcIPv4Net != null)
+    		match.enableSrcIPv4Net(new IPv4Net(matchSrcIPv4Net));
+    	    String matchDstIPv4Net = flowEntryObj.getMatchDstIPv4Net();
+    	    if (matchDstIPv4Net != null)
+    		match.enableDstIPv4Net(new IPv4Net(matchDstIPv4Net));
+    	    String matchSrcMac = flowEntryObj.getMatchSrcMac();
+    	    if (matchSrcMac != null)
+    		match.enableSrcMac(MACAddress.valueOf(matchSrcMac));
+    	    String matchDstMac = flowEntryObj.getMatchDstMac();
+    	    if (matchDstMac != null)
+    		match.enableDstMac(MACAddress.valueOf(matchDstMac));
+    	    flowEntry.setFlowEntryMatch(match);
+
+    	    //
+    	    // Extract the actions
+    	    //
+    	    ArrayList<FlowEntryAction> actions = new ArrayList<FlowEntryAction>();
+    	    Short actionOutputPort = flowEntryObj.getActionOutput();
+    	    if (actionOutputPort != null) {
+    		FlowEntryAction action = new FlowEntryAction();
+    		action.setActionOutput(new Port(actionOutputPort));
+    		actions.add(action);
+    	    }
+    	    flowEntry.setFlowEntryActions(actions);
+
+    	    String userState = flowEntryObj.getUserState();
+    	    flowEntry.setFlowEntryUserState(FlowEntryUserState.valueOf(userState));
+    	    String switchState = flowEntryObj.getSwitchState();
+    	    flowEntry.setFlowEntrySwitchState(FlowEntrySwitchState.valueOf(switchState));
+    	    //
+    	    // TODO: Take care of the FlowEntryMatch, FlowEntryAction set,
+    	    // and FlowEntryErrorState.
+    	    //
+    	    this.dataPath().flowEntries().add(flowEntry);
+    	}
+    }
 
     /**
      * Get the flow path Flow ID.
diff --git a/src/main/java/net/onrc/onos/flow/FlowManagerImpl.java b/src/main/java/net/onrc/onos/flow/FlowManagerImpl.java
new file mode 100644
index 0000000..a516108
--- /dev/null
+++ b/src/main/java/net/onrc/onos/flow/FlowManagerImpl.java
@@ -0,0 +1,104 @@
+package net.onrc.onos.flow;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+import net.floodlightcontroller.core.INetMapTopologyObjects.IFlowEntry;
+import net.floodlightcontroller.core.INetMapTopologyObjects.IFlowPath;
+import net.floodlightcontroller.core.INetMapTopologyObjects.IPortObject;
+import net.floodlightcontroller.core.IOFSwitch;
+import net.floodlightcontroller.util.FlowEntry;
+import net.floodlightcontroller.util.FlowPath;
+
+public class FlowManagerImpl implements IFlowManager {
+
+	@Override
+	public void createFlow(IPortObject src_port, IPortObject dest_port) {
+		// TODO Auto-generated method stub
+
+	}
+
+	@Override
+	public Iterable<FlowPath> getFlows(IPortObject src_port,
+			IPortObject dest_port) {
+		// TODO Auto-generated method stub
+		return null;
+	}
+
+	@Override
+	public Iterable<FlowPath> getOutFlows(IPortObject port) {
+		// TODO Auto-generated method stub
+		List<FlowPath> flowPaths = new ArrayList<FlowPath> ();
+		Iterable<IFlowEntry> flowEntries = port.getOutFlowEntries();
+
+		for(IFlowEntry fe: flowEntries) {
+			IFlowPath flow = fe.getFlow();
+			FlowPath flowPath = new FlowPath(flow);
+			flowPaths.add(flowPath);
+		}
+		return flowPaths;
+	}
+
+	@Override
+	public void reconcileFlows(IPortObject src_port) {
+		// TODO Auto-generated method stub
+
+		Iterable<IFlowEntry> flowEntries = src_port.getOutFlowEntries();
+
+		for(IFlowEntry fe: flowEntries) {
+			IFlowPath flow = fe.getFlow();
+			reconcileFlow(flow);
+		}
+	}
+
+	private void reconcileFlow(IFlowPath flow) {
+		// TODO Auto-generated method stub
+		
+	}
+
+	@Override
+	public void reconcileFlow(IPortObject src_port, IPortObject dest_port) {
+		// TODO Auto-generated method stub
+
+	}
+
+	@Override
+	public FlowPath computeFlowPath(IPortObject src_port, IPortObject dest_port) {
+		// TODO Auto-generated method stub
+		return null;
+	}
+
+	@Override
+	public Iterable<FlowEntry> getFlowEntries(FlowPath flow) {
+		// TODO Auto-generated method stub
+		return null;
+	}
+
+
+	@Override
+	public boolean installRemoteFlowEntry(FlowEntry entry) {
+		// TODO Auto-generated method stub
+		return false;
+	}
+
+	@Override
+	public boolean removeRemoteFlowEntry(FlowEntry entry) {
+		return false;
+		// TODO Auto-generated method stub
+
+	}
+
+	@Override
+	public boolean installFlowEntry(IOFSwitch mySwitch, FlowEntry flowEntry) {
+		// TODO Auto-generated method stub
+		return false;
+	}
+
+	@Override
+	public boolean removeFlowEntry(IOFSwitch mySwitch, FlowEntry flowEntry) {
+		// TODO Auto-generated method stub
+		return false;
+	}
+
+}
diff --git a/src/main/java/net/onrc/onos/flow/IFlowManager.java b/src/main/java/net/onrc/onos/flow/IFlowManager.java
index cd9cd3c..d163760 100644
--- a/src/main/java/net/onrc/onos/flow/IFlowManager.java
+++ b/src/main/java/net/onrc/onos/flow/IFlowManager.java
@@ -38,7 +38,7 @@
      * @param port the port to match.
      * @return the list of flows that are going out from the port.
      */
-    public Iterable<FlowPath> getFlows(IPortObject port);
+    public Iterable<FlowPath> getOutFlows(IPortObject port);
 
     /**
      * Reconcile all flows on inactive switch port.
diff --git a/src/main/java/net/onrc/onos/util/GraphDBUtils.java b/src/main/java/net/onrc/onos/util/GraphDBUtils.java
index ba48103..7283d09 100644
--- a/src/main/java/net/onrc/onos/util/GraphDBUtils.java
+++ b/src/main/java/net/onrc/onos/util/GraphDBUtils.java
@@ -44,6 +44,16 @@
 	}
 
 	@Override
+	public ISwitchObject searchActiveSwitch(GraphDBConnection conn, String dpid) {
+	    ISwitchObject sw = searchSwitch(conn, dpid);
+	    if ((sw != null) &&
+		sw.getState().equals(SwitchState.ACTIVE.toString())) {
+		return sw;
+	    }
+	    return null;
+	}
+
+	@Override
 	public IDeviceObject searchDevice(GraphDBConnection conn, String macAddr) {
 		// TODO Auto-generated method stub
 		FramedGraph<TitanGraph> fg = conn.getFramedGraph();	
diff --git a/src/main/java/net/onrc/onos/util/IDBUtils.java b/src/main/java/net/onrc/onos/util/IDBUtils.java
index 864e227..51948a2 100644
--- a/src/main/java/net/onrc/onos/util/IDBUtils.java
+++ b/src/main/java/net/onrc/onos/util/IDBUtils.java
@@ -10,6 +10,7 @@
 
 public interface IDBUtils {	
 	public ISwitchObject searchSwitch(GraphDBConnection conn, String dpid);
+	public ISwitchObject searchActiveSwitch(GraphDBConnection conn, String dpid);
 	public Iterable<ISwitchObject> getActiveSwitches(GraphDBConnection conn);
 	public Iterable<ISwitchObject> getAllSwitches(GraphDBConnection conn);
 	public Iterable<ISwitchObject> getInactiveSwitches(GraphDBConnection conn);
diff --git a/src/main/java/net/onrc/onos/util/LocalTopologyEventListener.java b/src/main/java/net/onrc/onos/util/LocalTopologyEventListener.java
new file mode 100644
index 0000000..186ba58
--- /dev/null
+++ b/src/main/java/net/onrc/onos/util/LocalTopologyEventListener.java
@@ -0,0 +1,92 @@
+package net.onrc.onos.util;
+
+import net.floodlightcontroller.core.INetMapTopologyObjects.IFlowEntry;
+import net.floodlightcontroller.core.INetMapTopologyObjects.IFlowPath;
+import net.floodlightcontroller.core.INetMapTopologyObjects.IPortObject;
+import net.floodlightcontroller.linkdiscovery.internal.TopoLinkServiceImpl;
+import net.floodlightcontroller.util.FlowPath;
+import net.onrc.onos.flow.FlowManagerImpl;
+import net.onrc.onos.flow.IFlowManager;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.thinkaurelius.titan.core.TitanEdge;
+import com.tinkerpop.blueprints.Direction;
+import com.tinkerpop.blueprints.Edge;
+import com.tinkerpop.blueprints.Vertex;
+import com.tinkerpop.blueprints.util.wrappers.event.listener.GraphChangedListener;
+
+public class LocalTopologyEventListener implements GraphChangedListener {
+	
+	protected static Logger log = LoggerFactory.getLogger(LocalTopologyEventListener.class);
+	protected static GraphDBConnection conn = GraphDBConnection.getInstance("");
+
+	@Override
+	public void edgeAdded(Edge arg0) {
+		// TODO Auto-generated method stub
+		// Convert this Event into NetMapEvent (LinkAdded, FlowEntryEnabled, HostAttached, PortEnabled)
+	}
+
+	@Override
+	public void edgePropertyChanged(Edge arg0, String arg1, Object arg2) {
+		// TODO Auto-generated method stub
+        // Generate State change events on edges too
+	}
+
+	@Override
+	public void edgePropertyRemoved(Edge arg0, String arg1, Object arg2) {
+		// TODO Auto-generated method stub
+		// Currently not needed
+
+	}
+
+	@Override
+	public void edgeRemoved(Edge e) {
+		// TODO Auto-generated method stub
+		// Fire NetMapEvents (LinkRemoved, FlowEntryRemoved, HostRemoved, PortRemoved)
+		TitanEdge edge = (TitanEdge) e;
+		log.debug("TopologyEvents: Received edge removed event: {}",edge.toString());
+		String label = edge.getLabel();
+		if (label.equals("link")) {
+			Vertex v = edge.getVertex(Direction.IN);
+			IPortObject src_port = conn.getFramedGraph().frame(v, IPortObject.class);
+			v = edge.getVertex(Direction.OUT);
+			IPortObject dest_port = conn.getFramedGraph().frame(v, IPortObject.class);
+
+			log.debug("TopologyEvents: link broken {}", new Object []{src_port.getSwitch().getDPID(),
+																src_port.getNumber(),
+																dest_port.getSwitch().getDPID(),
+																dest_port.getNumber()});
+			IFlowManager manager = new FlowManagerImpl();
+			// TODO: Find the flows and add to reconcile queue
+			manager.reconcileFlows(src_port);
+		}
+	}
+
+	@Override
+	public void vertexAdded(Vertex arg0) {
+		// TODO Auto-generated method stub
+
+	}
+
+	@Override
+	public void vertexPropertyChanged(Vertex arg0, String arg1, Object arg2) {
+		// TODO Auto-generated method stub
+		
+
+	}
+
+	@Override
+	public void vertexPropertyRemoved(Vertex arg0, String arg1, Object arg2) {
+		// TODO Auto-generated method stub
+
+	}
+
+	@Override
+	public void vertexRemoved(Vertex arg0) {
+		// TODO Auto-generated method stub
+
+	}
+
+}
diff --git a/web/topology_rest.py b/web/topology_rest.py
index ff1b32f..0306de9 100755
--- a/web/topology_rest.py
+++ b/web/topology_rest.py
@@ -796,7 +796,7 @@
 #* Create Flow
 #http://localhost:9000/gui/addflow/<src_dpid>/<src_port>/<dst_dpid>/<dst_port>/<srcMAC>/<dstMAC>
 #1 FOOBAR 00:00:00:00:00:00:01:01 1 00:00:00:00:00:00:01:0b 1 matchSrcMac 00:00:00:00:00:00 matchDstMac 00:01:00:00:00:00
-@app.route("/gui/addfow/<src_dpid>/<src_port>/<dst_dpid>/<dst_port>/<srcMAC>/<dstMAC>")
+@app.route("/gui/addflow/<src_dpid>/<src_port>/<dst_dpid>/<dst_port>/<srcMAC>/<dstMAC>")
 def add_flow(src_dpid, src_port, dst_dpid, dst_port, srcMAC, dstMAC):
   command =  "/home/ubuntu/ONOS/web/get_flow.py  all |grep FlowPath  |gawk '{print strtonum($4)}'| sort -n | tail -n 1"
   print command