Added more switch/controller registry APIs and curator implementations
diff --git a/mastership-test.sh b/mastership-test.sh
index 06189df..06907f0 100755
--- a/mastership-test.sh
+++ b/mastership-test.sh
@@ -1 +1 @@
-java -Dlogback.configurationFile=logback.xml -cp target/floodlight-only.jar:lib/*:lib/titan/* net.floodlightcontroller.mastership.MastershipManager $1
+java -Dlogback.configurationFile=logback.xml -cp target/floodlight-only.jar:lib/*:lib/titan/* net.floodlightcontroller.mastership.MastershipRunner $1
diff --git a/src/main/java/net/floodlightcontroller/mastership/IMastershipService.java b/src/main/java/net/floodlightcontroller/mastership/IMastershipService.java
index 83800c3..fdcb5c0 100644
--- a/src/main/java/net/floodlightcontroller/mastership/IMastershipService.java
+++ b/src/main/java/net/floodlightcontroller/mastership/IMastershipService.java
@@ -1,7 +1,10 @@
package net.floodlightcontroller.mastership;
+import java.util.Collection;
+
import net.floodlightcontroller.core.module.IFloodlightService;
+//Will change to something like IRegistryService
public interface IMastershipService extends IFloodlightService {
// Callback for all mastership changes.
@@ -24,4 +27,21 @@
public void setMastershipId (String id);
public String getMastershipId ();
+ /**
+ * Register a controller to the ONOS cluster
+ * @param controller A string identifying the controller and (possibly) how to talk to it.
+ * (We will have to develop a convention for this - most likely hostname:port)
+ */
+ public void registerController(String controllerId);
+
+ /**
+ * Get all controllers in the cluster
+ * @return
+ */
+ public Collection<String> getAllControllers();
+
+
+ public String getControllerForSwitch(long dpid);
+
+ public Collection<Long> getSwitchesControlledByController(String controllerId);
}
diff --git a/src/main/java/net/floodlightcontroller/mastership/MastershipManager.java b/src/main/java/net/floodlightcontroller/mastership/MastershipManager.java
index 46b533e..f4230ae 100644
--- a/src/main/java/net/floodlightcontroller/mastership/MastershipManager.java
+++ b/src/main/java/net/floodlightcontroller/mastership/MastershipManager.java
@@ -1,10 +1,12 @@
package net.floodlightcontroller.mastership;
import java.io.IOException;
+import java.io.UnsupportedEncodingException;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
+import java.util.List;
import java.util.Map;
import net.floodlightcontroller.core.module.FloodlightModuleContext;
@@ -12,6 +14,7 @@
import net.floodlightcontroller.core.module.IFloodlightModule;
import net.floodlightcontroller.core.module.IFloodlightService;
+import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher.Event.KeeperState;
import org.openflow.util.HexString;
@@ -22,6 +25,9 @@
import com.netflix.curator.framework.CuratorFramework;
import com.netflix.curator.framework.CuratorFrameworkFactory;
import com.netflix.curator.framework.api.CuratorWatcher;
+import com.netflix.curator.framework.recipes.cache.ChildData;
+import com.netflix.curator.framework.recipes.cache.PathChildrenCache;
+import com.netflix.curator.framework.recipes.cache.PathChildrenCache.StartMode;
import com.netflix.curator.framework.recipes.leader.LeaderLatch;
import com.netflix.curator.framework.recipes.leader.Participant;
import com.netflix.curator.retry.ExponentialBackoffRetry;
@@ -34,9 +40,12 @@
//TODO read this from configuration
protected String connectionString = "localhost:2181";
private final String namespace = "onos";
- private final String switchLatchesPath = "/switchmastership";
+ private final String switchLatchesPath = "/switches";
protected CuratorFramework client;
+
+ private final String controllerPath = "/controllers";
+ protected PathChildrenCache controllerCache;
protected Map<String, LeaderLatch> switchLatches;
protected Map<String, MastershipCallback> switchCallbacks;
@@ -52,7 +61,7 @@
}
@Override
- public void process(WatchedEvent event) throws Exception {
+ public synchronized void process(WatchedEvent event) throws Exception {
log.debug("Watch Event: {}", event);
LeaderLatch latch = switchLatches.get(dpid);
@@ -68,6 +77,7 @@
}
try {
+
Participant leader = latch.getLeader();
if (leader.getId().equals(mastershipId) && !isLeader){
@@ -96,6 +106,7 @@
//client.getChildren().usingWatcher(this).forPath(latchPath);
}
}
+
@Override
public void acquireMastership(long dpid, MastershipCallback cb) throws Exception {
@@ -176,6 +187,83 @@
return mastershipId;
}
+ @Override
+ public Collection<String> getAllControllers() {
+ // TODO Auto-generated method stub
+ log.debug("Getting all controllers");
+ List<String> controllers = new ArrayList<String>();
+ for (ChildData data : controllerCache.getCurrentData()){
+
+ String d = null;
+ try {
+ d = new String(data.getData(), "UTF-8");
+ } catch (UnsupportedEncodingException e) {
+ // TODO unlikely(throw exception)
+ e.printStackTrace();
+ }
+
+ controllers.add(d);
+ }
+ return controllers;
+ }
+
+ @Override
+ public void registerController(String id) {
+ // TODO Auto-generated method stub
+ byte bytes[] = null;
+ try {
+ bytes = id.getBytes("UTF-8");
+ } catch (UnsupportedEncodingException e1) {
+ // TODO Throw some exception (very unlikely this will happen)
+ e1.printStackTrace();
+ }
+
+ String path = controllerPath + "/" + id;
+
+ log.info("Registering controller with id {}", id);
+
+ //Create ephemeral node with my id
+ try {
+ client.create().withProtection().withMode(CreateMode.EPHEMERAL)
+ .forPath(path, bytes);
+ } catch (Exception e) {
+ // TODO Auto-generated catch block
+ // TODO Make an exception that will be thrown here
+ e.printStackTrace();
+ }
+ }
+
+ @Override
+ public String getControllerForSwitch(long dpid) {
+ // TODO Work out how we should store this controller/switch data.
+ // The leader latch might be a index to the /controllers collections
+ // which holds more info on the controller (how to talk to it for example).
+
+
+ String strDpid = HexString.toHexString(dpid);
+ LeaderLatch latch = switchLatches.get(strDpid);
+
+ if (latch == null){
+ log.warn("Tried to get controller for non-existent switch");
+ return null;
+ }
+
+ Participant leader = null;
+ try {
+ leader = latch.getLeader();
+ } catch (Exception e) {
+ // TODO Zookeeper issue, throw exception
+ e.printStackTrace();
+ }
+
+ return leader.getId();
+ }
+
+ @Override
+ public Collection<Long> getSwitchesControlledByController(String controllerId) {
+ // TODO Auto-generated method stub
+ return null;
+ }
/*
* IFloodlightModule
@@ -183,7 +271,8 @@
@Override
public Collection<Class<? extends IFloodlightService>> getModuleServices() {
- Collection<Class<? extends IFloodlightService>> l = new ArrayList<Class<? extends IFloodlightService>>();
+ Collection<Class<? extends IFloodlightService>> l =
+ new ArrayList<Class<? extends IFloodlightService>>();
l.add(IMastershipService.class);
return l;
}
@@ -224,58 +313,21 @@
client = client.usingNamespace(namespace);
- return;
+ controllerCache = new PathChildrenCache(client, controllerPath, true);
+
+ try {
+ controllerCache.start(StartMode.BUILD_INITIAL_CACHE);
+
+
+ } catch (Exception e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+
}
@Override
public void startUp (FloodlightModuleContext context) {
// Nothing to be done on startup
}
-
- public static void main(String args[]){
- FloodlightModuleContext fmc = new FloodlightModuleContext();
- MastershipManager mm = new MastershipManager();
-
- String id = null;
- if (args.length > 0){
- id = args[0];
- log.info("Using unique id: {}", id);
- }
-
- try {
- mm.init(fmc);
- mm.startUp(fmc);
-
- if (id != null){
- mm.setMastershipId(id);
- }
-
- mm.acquireMastership(1L,
- new MastershipCallback(){
- @Override
- public void changeCallback(long dpid, boolean isMaster) {
- if (isMaster){
- log.debug("Callback for becoming master for {}", HexString.toHexString(dpid));
- }
- else {
- log.debug("Callback for losing mastership for {}", HexString.toHexString(dpid));
- }
- }
- });
-
- //"Server" loop
- while (true) {
- Thread.sleep(60000);
- }
-
- } catch (FloodlightModuleException e) {
- e.printStackTrace();
- } catch (InterruptedException e) {
- e.printStackTrace();
- } catch (Exception e) {
- e.printStackTrace();
- }
-
- log.debug("is master: {}", mm.amMaster(1L));
- }
}
diff --git a/src/main/java/net/floodlightcontroller/mastership/MastershipRunner.java b/src/main/java/net/floodlightcontroller/mastership/MastershipRunner.java
new file mode 100644
index 0000000..a28a9c5
--- /dev/null
+++ b/src/main/java/net/floodlightcontroller/mastership/MastershipRunner.java
@@ -0,0 +1,70 @@
+package net.floodlightcontroller.mastership;
+
+import net.floodlightcontroller.core.module.FloodlightModuleContext;
+import net.floodlightcontroller.core.module.FloodlightModuleException;
+import net.floodlightcontroller.mastership.IMastershipService.MastershipCallback;
+
+import org.openflow.util.HexString;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Used for lightweight testing of the mastership module without having
+ * to load up the entire ONOS.
+ * @author jono
+ *
+ */
+public class MastershipRunner {
+ protected static Logger log = LoggerFactory.getLogger(MastershipRunner.class);
+
+ public static void main(String args[]){
+ FloodlightModuleContext fmc = new FloodlightModuleContext();
+ MastershipManager mm = new MastershipManager();
+
+ String id = null;
+ if (args.length > 0){
+ id = args[0];
+ log.info("Using unique id: {}", id);
+ }
+
+ try {
+ mm.init(fmc);
+ mm.startUp(fmc);
+
+ if (id != null){
+ mm.setMastershipId(id);
+ }
+
+ mm.acquireMastership(1L,
+ new MastershipCallback(){
+ @Override
+ public void changeCallback(long dpid, boolean isMaster) {
+ if (isMaster){
+ log.debug("Callback for becoming master for {}", HexString.toHexString(dpid));
+ }
+ else {
+ log.debug("Callback for losing mastership for {}", HexString.toHexString(dpid));
+ }
+ }
+ });
+
+ mm.registerController(id);
+
+ Thread.sleep(5000);
+
+ //"Server" loop
+ while (true) {
+ Thread.sleep(60000);
+ }
+
+ } catch (FloodlightModuleException e) {
+ e.printStackTrace();
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+
+ log.debug("is master: {}", mm.amMaster(1L));
+ }
+}