WIP: Adding PathInstallRuntime for installing flow entries using FlowPusher

I also had to add several methods to our base classes to do type conversion,
which is a bit messy. Also, do to naming overlaps, we need to have some fully
specified class names.

Adding IntentRuntime service to drive the runtimes.

Change-Id: I675fbfe243b0bf18536425dfd9f9e6e5ca795845
diff --git a/src/main/java/net/onrc/onos/intent/Action.java b/src/main/java/net/onrc/onos/intent/Action.java
index ddf4474..2f109d1 100644
--- a/src/main/java/net/onrc/onos/intent/Action.java
+++ b/src/main/java/net/onrc/onos/intent/Action.java
@@ -1,11 +1,14 @@
 package net.onrc.onos.intent;
 
+import net.onrc.onos.ofcontroller.util.FlowEntryAction;
+
 /**
  * 
  * @author Brian O'Connor <bocon@onlab.us>
  *
  */
 
-public class Action {
+public abstract class Action {
 
+    public abstract FlowEntryAction getFlowEntryAction();
 }
diff --git a/src/main/java/net/onrc/onos/intent/FlowEntry.java b/src/main/java/net/onrc/onos/intent/FlowEntry.java
index 4c52324..14d1038 100644
--- a/src/main/java/net/onrc/onos/intent/FlowEntry.java
+++ b/src/main/java/net/onrc/onos/intent/FlowEntry.java
@@ -6,6 +6,9 @@
 import net.floodlightcontroller.util.MACAddress;
 import net.onrc.onos.ofcontroller.networkgraph.Port;
 import net.onrc.onos.ofcontroller.networkgraph.Switch;
+import net.onrc.onos.ofcontroller.util.Dpid;
+import net.onrc.onos.ofcontroller.util.FlowEntryActions;
+import net.onrc.onos.ofcontroller.util.FlowEntryId;
 
 /**
  * 
@@ -29,4 +32,21 @@
 	public String toString() {
 		return match + "->" + actions;
 	}
+	
+	public Switch getSwitch() {
+	    return sw;
+	}
+	
+	public net.onrc.onos.ofcontroller.util.FlowEntry getFlowEntry() {
+		net.onrc.onos.ofcontroller.util.FlowEntry entry = new net.onrc.onos.ofcontroller.util.FlowEntry();
+		entry.setDpid(new Dpid(sw.getDpid()));
+		entry.setFlowEntryId(new FlowEntryId(0)); // all zero for now
+		entry.setFlowEntryMatch(match.getFlowEntryMatch());
+		FlowEntryActions flowEntryActions = new FlowEntryActions();
+		for(Action action : actions) {
+		    flowEntryActions.addAction(action.getFlowEntryAction());
+		}
+		entry.setFlowEntryActions(flowEntryActions);
+		return entry;
+	}
 }
\ No newline at end of file
diff --git a/src/main/java/net/onrc/onos/intent/ForwardAction.java b/src/main/java/net/onrc/onos/intent/ForwardAction.java
index 245a918..c6769b8 100644
--- a/src/main/java/net/onrc/onos/intent/ForwardAction.java
+++ b/src/main/java/net/onrc/onos/intent/ForwardAction.java
@@ -1,6 +1,7 @@
 package net.onrc.onos.intent;
 
 import net.onrc.onos.ofcontroller.networkgraph.Port;
+import net.onrc.onos.ofcontroller.util.FlowEntryAction;
 
 /**
  * 
@@ -18,5 +19,12 @@
 	public String toString() {
 		return dstPort.toString();
 	}
+
+	@Override
+	public FlowEntryAction getFlowEntryAction() {
+	    FlowEntryAction action = new FlowEntryAction();
+	    action.setActionOutput(new net.onrc.onos.ofcontroller.util.Port(dstPort.getNumber().shortValue()));
+	    return action;
+	}
 	
 }
\ No newline at end of file
diff --git a/src/main/java/net/onrc/onos/intent/Match.java b/src/main/java/net/onrc/onos/intent/Match.java
index c81fe00..3f95ce4 100644
--- a/src/main/java/net/onrc/onos/intent/Match.java
+++ b/src/main/java/net/onrc/onos/intent/Match.java
@@ -3,6 +3,7 @@
 import net.floodlightcontroller.util.MACAddress;
 import net.onrc.onos.ofcontroller.networkgraph.Port;
 import net.onrc.onos.ofcontroller.networkgraph.Switch;
+import net.onrc.onos.ofcontroller.util.FlowEntryMatch;
 
 /**
  * 
@@ -38,6 +39,14 @@
 		}
 	}
 	
+	public FlowEntryMatch getFlowEntryMatch(){
+	    FlowEntryMatch match = new FlowEntryMatch();
+	    match.enableSrcMac(srcMac);
+	    match.enableDstMac(dstMac);
+	    match.enableInPort(new net.onrc.onos.ofcontroller.util.Port(srcPort.getNumber().shortValue()));
+	    return match;
+	}
+	
 	public String toString() {
 		return "(" + srcPort + "," + srcMac + "," + dstMac + ")";
 	}
diff --git a/src/main/java/net/onrc/onos/intent/runtime/IntentRuntime.java b/src/main/java/net/onrc/onos/intent/runtime/IntentRuntime.java
new file mode 100644
index 0000000..567986e
--- /dev/null
+++ b/src/main/java/net/onrc/onos/intent/runtime/IntentRuntime.java
@@ -0,0 +1,55 @@
+package net.onrc.onos.intent.runtime;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Map;
+
+import net.floodlightcontroller.core.IFloodlightProviderService;
+import net.floodlightcontroller.core.module.FloodlightModuleContext;
+import net.floodlightcontroller.core.module.FloodlightModuleException;
+import net.floodlightcontroller.core.module.IFloodlightModule;
+import net.floodlightcontroller.core.module.IFloodlightService;
+import net.floodlightcontroller.restserver.IRestApiService;
+import net.onrc.onos.ofcontroller.networkgraph.INetworkGraphService;
+
+public class IntentRuntime implements IFloodlightModule {
+    protected volatile IFloodlightProviderService floodlightProvider;
+    protected volatile INetworkGraphService networkGraph;
+    protected volatile IRestApiService restApi;
+
+    @Override
+    public void init(FloodlightModuleContext context)
+	    throws FloodlightModuleException {
+	floodlightProvider = context.getServiceImpl(IFloodlightProviderService.class);
+	networkGraph = context.getServiceImpl(INetworkGraphService.class);
+	restApi = context.getServiceImpl(IRestApiService.class);
+    }
+
+    @Override
+    public void startUp(FloodlightModuleContext context) {
+	restApi.addRestletRoutable(new IntentWebRoutable());
+    }
+    
+    @Override
+    public Collection<Class<? extends IFloodlightService>> getModuleDependencies() {
+	Collection<Class<? extends IFloodlightService>> l =
+		new ArrayList<Class<? extends IFloodlightService>>();
+	l.add(IFloodlightProviderService.class);
+	l.add(INetworkGraphService.class);
+	l.add(IRestApiService.class);
+	return l;
+    }
+    
+    @Override
+    public Collection<Class<? extends IFloodlightService>> getModuleServices() {
+	// TODO Auto-generated method stub
+	return null;
+    }
+
+    @Override
+    public Map<Class<? extends IFloodlightService>, IFloodlightService> getServiceImpls() {
+	// TODO Auto-generated method stub
+	return null;
+    }
+
+}
diff --git a/src/main/java/net/onrc/onos/intent/runtime/IntentWebRoutable.java b/src/main/java/net/onrc/onos/intent/runtime/IntentWebRoutable.java
new file mode 100644
index 0000000..533b55b
--- /dev/null
+++ b/src/main/java/net/onrc/onos/intent/runtime/IntentWebRoutable.java
@@ -0,0 +1,23 @@
+package net.onrc.onos.intent.runtime;
+
+import org.restlet.Context;
+import org.restlet.Restlet;
+import org.restlet.routing.Router;
+
+import net.floodlightcontroller.restserver.RestletRoutable;
+
+public class IntentWebRoutable implements RestletRoutable {
+
+    @Override
+    public Restlet getRestlet(Context context) {
+	Router router = new Router(context);
+	// TODO: add routes
+	return router;
+    }
+
+    @Override
+    public String basePath() {
+	return "/wm/onos/intent";
+    }
+
+}
diff --git a/src/main/java/net/onrc/onos/intent/runtime/PathInstallRuntime.java b/src/main/java/net/onrc/onos/intent/runtime/PathInstallRuntime.java
new file mode 100644
index 0000000..0b74cfc
--- /dev/null
+++ b/src/main/java/net/onrc/onos/intent/runtime/PathInstallRuntime.java
@@ -0,0 +1,48 @@
+package net.onrc.onos.intent.runtime;
+
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import net.floodlightcontroller.core.IFloodlightProviderService;
+import net.floodlightcontroller.core.IOFSwitch;
+import net.onrc.onos.intent.FlowEntry;
+import net.onrc.onos.ofcontroller.flowprogrammer.IFlowPusherService;
+import net.onrc.onos.ofcontroller.networkgraph.NetworkGraph;
+import net.onrc.onos.ofcontroller.util.Pair;
+
+/**
+ * 
+ * @author Brian O'Connor <bocon@onlab.us>
+ *
+ */
+
+public class PathInstallRuntime {
+    NetworkGraph graph;
+    IFlowPusherService pusher;
+    IFloodlightProviderService provider;
+    protected List<Set<FlowEntry>> plan;
+
+    public PathInstallRuntime(NetworkGraph graph) {
+	this.graph = graph;
+    }
+
+    public void installPlan(List<Set<FlowEntry>> plan) {
+	this.plan = plan;
+	Map<Long,IOFSwitch> switches = provider.getSwitches();
+	for(Set<FlowEntry> phase : plan) {
+	    Set<Pair<IOFSwitch, net.onrc.onos.ofcontroller.util.FlowEntry>> entries 
+	    = new HashSet<>();
+	    // convert flow entries and create pairs
+	    for(FlowEntry entry : phase) {
+		entries.add(new Pair<>(switches.get(entry.getSwitch().getDpid()), 
+			entry.getFlowEntry()));
+	    }
+	    // push flow entries to switches
+	    pusher.pushFlowEntries(entries);
+	    // TODO: wait for confirmation messages before proceeding
+	}
+    }
+
+}