Changed the disable zookeeper mechanism. There is now a class (StandaloneRegistry) that implements IControllerRegistryService without needing zookeeper - this is intended for single-node setups e.g. during development
diff --git a/src/main/java/net/onrc/onos/registry/controller/RegistryRunner.java b/src/main/java/net/onrc/onos/registry/controller/RegistryRunner.java
index 1f4ea63..164f328 100644
--- a/src/main/java/net/onrc/onos/registry/controller/RegistryRunner.java
+++ b/src/main/java/net/onrc/onos/registry/controller/RegistryRunner.java
@@ -1,8 +1,5 @@
package net.onrc.onos.registry.controller;
-import java.util.List;
-import java.util.Map;
-
import net.floodlightcontroller.core.module.FloodlightModuleContext;
import net.floodlightcontroller.core.module.FloodlightModuleException;
import net.onrc.onos.registry.controller.IControllerRegistryService.ControlChangeCallback;
@@ -22,7 +19,7 @@
public static void main(String args[]){
FloodlightModuleContext fmc = new FloodlightModuleContext();
- RegistryManager rm = new RegistryManager();
+ ZookeeperRegistry rm = new ZookeeperRegistry();
fmc.addConfigParam(rm, "enableZookeeper", "true");
@@ -36,9 +33,13 @@
rm.init(fmc);
rm.startUp(fmc);
- if (id != null){
- rm.setMastershipId(id);
+ if (id == null){
+ log.error("No unique ID supplied");
+ System.exit(1);
}
+
+ rm.registerController(id);
+ //rm.setMastershipId(id);
rm.requestControl(1L,
new ControlChangeCallback(){
@@ -53,16 +54,16 @@
}
});
- rm.registerController(id);
-
Thread.sleep(1000);
+ /*
Map<String, List<ControllerRegistryEntry>> switches = rm.getAllSwitches();
for (List<ControllerRegistryEntry> ls : switches.values()){
for (ControllerRegistryEntry cre : ls){
log.debug("ctrlr: {}", cre.getControllerId());
}
}
+ */
//"Server" loop
while (true) {
Thread.sleep(60000);
diff --git a/src/main/java/net/onrc/onos/registry/controller/StandaloneRegistry.java b/src/main/java/net/onrc/onos/registry/controller/StandaloneRegistry.java
new file mode 100644
index 0000000..e3181fe
--- /dev/null
+++ b/src/main/java/net/onrc/onos/registry/controller/StandaloneRegistry.java
@@ -0,0 +1,162 @@
+package net.onrc.onos.registry.controller;
+
+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;
+import net.floodlightcontroller.core.module.FloodlightModuleException;
+import net.floodlightcontroller.core.module.IFloodlightModule;
+import net.floodlightcontroller.core.module.IFloodlightService;
+import net.floodlightcontroller.restserver.IRestApiService;
+
+import org.openflow.util.HexString;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class StandaloneRegistry implements IFloodlightModule,
+ IControllerRegistryService {
+ protected static Logger log = LoggerFactory.getLogger(StandaloneRegistry.class);
+
+ protected IRestApiService restApi;
+
+ //protected String controllerId;
+
+ protected String controllerId = null;
+ protected Map<String, ControlChangeCallback> switchCallbacks;
+
+
+ @Override
+ public void requestControl(long dpid, ControlChangeCallback cb)
+ throws RegistryException {
+ if (controllerId == null) {
+ throw new RuntimeException("Must register a controller before calling requestControl");
+ }
+
+ switchCallbacks.put(HexString.toHexString(dpid), cb);
+
+ log.debug("Control granted for {}", HexString.toHexString(dpid));
+
+ //Immediately grant request for control
+ if (cb != null) {
+ cb.controlChanged(dpid, true);
+ }
+ }
+
+ @Override
+ public void releaseControl(long dpid) {
+ ControlChangeCallback cb = switchCallbacks.remove(HexString.toHexString(dpid));
+
+ log.debug("Control released for {}", HexString.toHexString(dpid));
+
+ if (cb != null){
+ cb.controlChanged(dpid, false);
+ }
+ }
+
+ @Override
+ public boolean hasControl(long dpid) {
+ return switchCallbacks.containsKey(HexString.toHexString(dpid));
+ }
+
+ @Override
+ public void setMastershipId(String id) {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public String getMastershipId() {
+ return controllerId;
+ }
+
+ @Override
+ public void registerController(String controllerId)
+ throws RegistryException {
+ this.controllerId = controllerId;
+ }
+
+ @Override
+ public Collection<String> getAllControllers() throws RegistryException {
+ List<String> l = new ArrayList<String>();
+ l.add(controllerId);
+ return l;
+ }
+
+ @Override
+ public String getControllerForSwitch(long dpid) throws RegistryException {
+ return controllerId;
+ }
+
+ @Override
+ public Map<String, List<ControllerRegistryEntry>> getAllSwitches() {
+ Map<String, List<ControllerRegistryEntry>> switches =
+ new HashMap<String, List<ControllerRegistryEntry>>();
+
+ for (String strSwitch : switchCallbacks.keySet()){
+ log.debug("Swtich _{}", strSwitch);
+ List<ControllerRegistryEntry> list = new ArrayList<ControllerRegistryEntry>();
+ list.add(new ControllerRegistryEntry(controllerId, 0));
+
+ switches.put(strSwitch, list);
+ }
+
+ return switches;
+ }
+
+ @Override
+ public Collection<Long> getSwitchesControlledByController(
+ String controllerId) {
+ throw new RuntimeException("Not yet implemented");
+ }
+
+ @Override
+ public Collection<Class<? extends IFloodlightService>> getModuleServices() {
+ Collection<Class<? extends IFloodlightService>> l =
+ new ArrayList<Class<? extends IFloodlightService>>();
+ l.add(IControllerRegistryService.class);
+ return l;
+ }
+
+ @Override
+ public Map<Class<? extends IFloodlightService>, IFloodlightService> getServiceImpls() {
+ Map<Class<? extends IFloodlightService>, IFloodlightService> m =
+ new HashMap<Class<? extends IFloodlightService>, IFloodlightService>();
+ m.put(IControllerRegistryService.class, this);
+ return m;
+ }
+
+ @Override
+ public Collection<Class<? extends IFloodlightService>> getModuleDependencies() {
+ Collection<Class<? extends IFloodlightService>> l =
+ new ArrayList<Class<? extends IFloodlightService>>();
+ l.add(IRestApiService.class);
+ return l;
+ }
+
+ @Override
+ public void init(FloodlightModuleContext context)
+ throws FloodlightModuleException {
+ restApi = context.getServiceImpl(IRestApiService.class);
+
+ switchCallbacks = new HashMap<String, ControlChangeCallback>();
+
+ //Put some data in for testing
+ /*
+ try {
+ registerController("hurro");
+ requestControl(2L, null);
+ } catch (RegistryException e1) {
+ // TODO Auto-generated catch block
+ e1.printStackTrace();
+ }*/
+ }
+
+ @Override
+ public void startUp(FloodlightModuleContext context) {
+ restApi.addRestletRoutable(new RegistryWebRoutable());
+ }
+
+}
diff --git a/src/main/java/net/onrc/onos/registry/controller/SwitchRegistryResource.java b/src/main/java/net/onrc/onos/registry/controller/SwitchRegistryResource.java
index 17ad48c..d6f3dee 100644
--- a/src/main/java/net/onrc/onos/registry/controller/SwitchRegistryResource.java
+++ b/src/main/java/net/onrc/onos/registry/controller/SwitchRegistryResource.java
@@ -26,15 +26,12 @@
switches = new HashMap<String, List<ControllerRegistryEntry>>();
}
- log.debug("GETTING ALL CONTROLLERS");
-
for (List<ControllerRegistryEntry> list: switches.values()){
for (ControllerRegistryEntry en : list) {
log.debug("Controller id {}", en.getControllerId());
}
}
-
return switches;
}
}
diff --git a/src/main/java/net/onrc/onos/registry/controller/RegistryManager.java b/src/main/java/net/onrc/onos/registry/controller/ZookeeperRegistry.java
similarity index 86%
rename from src/main/java/net/onrc/onos/registry/controller/RegistryManager.java
rename to src/main/java/net/onrc/onos/registry/controller/ZookeeperRegistry.java
index a5a3576..58b8bc7 100644
--- a/src/main/java/net/onrc/onos/registry/controller/RegistryManager.java
+++ b/src/main/java/net/onrc/onos/registry/controller/ZookeeperRegistry.java
@@ -2,7 +2,6 @@
import java.io.IOException;
import java.io.UnsupportedEncodingException;
-import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
@@ -16,7 +15,6 @@
import net.floodlightcontroller.core.module.IFloodlightService;
import net.floodlightcontroller.restserver.IRestApiService;
-import org.apache.commons.lang.NotImplementedException;
import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher.Event.KeeperState;
@@ -37,10 +35,10 @@
import com.netflix.curator.framework.recipes.leader.Participant;
import com.netflix.curator.retry.ExponentialBackoffRetry;
-public class RegistryManager implements IFloodlightModule, IControllerRegistryService {
+public class ZookeeperRegistry implements IFloodlightModule, IControllerRegistryService {
- protected static Logger log = LoggerFactory.getLogger(RegistryManager.class);
- protected String mastershipId = null;
+ protected static Logger log = LoggerFactory.getLogger(ZookeeperRegistry.class);
+ protected String controllerId = null;
protected IRestApiService restApi;
@@ -61,7 +59,7 @@
protected Map<String, ControlChangeCallback> switchCallbacks;
protected Map<String, PathChildrenCache> switchPathCaches;
- protected boolean moduleEnabled = false;
+ //protected boolean zookeeperEnabled = false;
protected class ParamaterizedCuratorWatcher implements CuratorWatcher {
private String dpid;
@@ -97,13 +95,13 @@
Participant leader = latch.getLeader();
- if (leader.getId().equals(mastershipId) && !isLeader){
+ if (leader.getId().equals(controllerId) && !isLeader){
log.debug("Became leader for {}", dpid);
isLeader = true;
switchCallbacks.get(dpid).controlChanged(HexString.toLong(dpid), true);
}
- else if (!leader.getId().equals(mastershipId) && isLeader){
+ else if (!leader.getId().equals(controllerId) && isLeader){
log.debug("Lost leadership for {}", dpid);
isLeader = false;
@@ -173,11 +171,17 @@
@Override
public void requestControl(long dpid, ControlChangeCallback cb) throws RegistryException {
+ /*
+ if (!zookeeperEnabled) {
+ //If zookeeper connection is disabled all control requests succeed immediately
+ if (cb != null){
+ cb.controlChanged(dpid, true);
+ }
+ return;
+ }*/
- if (!moduleEnabled) return;
-
- if (mastershipId == null){
- throw new RuntimeException("Must set mastershipId before calling aquireMastership");
+ if (controllerId == null){
+ throw new RuntimeException("Must register a controller before calling requestControl");
}
String dpidStr = HexString.toHexString(dpid);
@@ -188,7 +192,7 @@
"is already running");
}
- LeaderLatch latch = new LeaderLatch(client, latchPath, mastershipId);
+ LeaderLatch latch = new LeaderLatch(client, latchPath, controllerId);
switchLatches.put(dpidStr, latch);
switchCallbacks.put(dpidStr, cb);
@@ -207,7 +211,7 @@
@Override
public void releaseControl(long dpid) {
- if (!moduleEnabled) return;
+ //if (!zookeeperEnabled) return;
String dpidStr = HexString.toHexString(dpid);
@@ -230,7 +234,7 @@
@Override
public boolean hasControl(long dpid) {
- if (!moduleEnabled) return false;
+ //if (!zookeeperEnabled) return false;
LeaderLatch latch = switchLatches.get(HexString.toHexString(dpid));
@@ -240,7 +244,7 @@
}
try {
- return latch.getLeader().getId().equals(mastershipId);
+ return latch.getLeader().getId().equals(controllerId);
} catch (Exception e) {
//TODO swallow exception?
return false;
@@ -249,17 +253,18 @@
@Override
public void setMastershipId(String id) {
- mastershipId = id;
+ //TODO remove this method if not needed
+ //controllerId = id;
}
@Override
public String getMastershipId() {
- return mastershipId;
+ return controllerId;
}
@Override
public Collection<String> getAllControllers() throws RegistryException {
- if (!moduleEnabled) return null;
+ //if (!zookeeperEnabled) return null;
log.debug("Getting all controllers");
@@ -280,7 +285,9 @@
@Override
public void registerController(String id) throws RegistryException {
- if (!moduleEnabled) return;
+ //if (!zookeeperEnabled) return;
+
+ controllerId = id;
byte bytes[] = null;
try {
@@ -304,7 +311,7 @@
@Override
public String getControllerForSwitch(long dpid) throws RegistryException {
- if (!moduleEnabled) return null;
+ //if (!zookeeperEnabled) return null;
// 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).
@@ -331,7 +338,7 @@
@Override
public Collection<Long> getSwitchesControlledByController(String controllerId) {
//TODO remove this if not needed
- throw new NotImplementedException();
+ throw new RuntimeException("Not yet implemented");
}
@@ -407,35 +414,40 @@
@Override
public void init (FloodlightModuleContext context) throws FloodlightModuleException {
+ log.info("Initialising the Zookeeper Registry - Zookeeper connection required");
+
restApi = context.getServiceImpl(IRestApiService.class);
- //Read config to see if we should try and connect to zookeeper
- Map<String, String> configOptions = context.getConfigParams(this);
+ //We have a config option that determines whether we try and connect to
+ //zookeeper or not. By default zookeeper connection is disabled. When we don't
+ //have a zookeeper connection we act as though we are the only server in the
+ //cluster, i.e. all control requests will succeed.
+ /*Map<String, String> configOptions = context.getConfigParams(this);
String enableZookeeper = configOptions.get("enableZookeeper");
if (enableZookeeper != null) {
- log.info("Enabling Mastership module - requires Zookeeper connection");
- moduleEnabled = true;
+ log.info("Enabling Zookeeper connection");
+ zookeeperEnabled = true;
}
else {
- log.info("Mastership module is disabled");
+ log.info("Zookeeper connectivity is disabled - running in standalone mode");
return;
- }
+ }*/
+ /*
try {
String localHostname = java.net.InetAddress.getLocalHost().getHostName();
- mastershipId = localHostname;
- log.debug("Setting mastership id to {}", mastershipId);
+ controllerId = localHostname;
+ log.debug("Setting controller id to {}", controllerId);
} catch (UnknownHostException e) {
// TODO Handle this exception
e.printStackTrace();
- }
+ }*/
switchLatches = new HashMap<String, LeaderLatch>();
switchCallbacks = new HashMap<String, ControlChangeCallback>();
switchPathCaches = new HashMap<String, PathChildrenCache>();
RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000, 3);
- //RetryPolicy retryPolicy = new RetryOneTime(0);
client = CuratorFrameworkFactory.newClient(connectionString, retryPolicy);
client.start();
@@ -443,13 +455,14 @@
client = client.usingNamespace(namespace);
//Put some data in for testing
+ /*
try {
- registerController(mastershipId);
+ registerController("zookeeperController");
requestControl(2L, null);
} catch (RegistryException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
- }
+ }*/
controllerCache = new PathChildrenCache(client, controllerPath, true);
switchCache = new PathChildrenCache(client, switchLatchesPath, true);
diff --git a/src/main/resources/META-INF/services/net.floodlightcontroller.core.module.IFloodlightModule b/src/main/resources/META-INF/services/net.floodlightcontroller.core.module.IFloodlightModule
index e784f56..9b615f5 100644
--- a/src/main/resources/META-INF/services/net.floodlightcontroller.core.module.IFloodlightModule
+++ b/src/main/resources/META-INF/services/net.floodlightcontroller.core.module.IFloodlightModule
@@ -23,6 +23,7 @@
net.floodlightcontroller.core.test.MockFloodlightProvider
net.floodlightcontroller.core.test.MockThreadPoolService
net.floodlightcontroller.firewall.Firewall
-net.onrc.onos.registry.controller.RegistryManager
+net.onrc.onos.registry.controller.ZookeeperRegistry
+net.onrc.onos.registry.controller.StandaloneRegistry
diff --git a/src/main/resources/floodlightdefault.properties b/src/main/resources/floodlightdefault.properties
index 56d42eb..68a96c5 100644
--- a/src/main/resources/floodlightdefault.properties
+++ b/src/main/resources/floodlightdefault.properties
@@ -8,7 +8,8 @@
net.floodlightcontroller.jython.JythonDebugInterface,\
net.floodlightcontroller.counter.CounterStore,\
net.floodlightcontroller.perfmon.PktInProcessingTime,\
-net.floodlightcontroller.ui.web.StaticWebRoutable
+net.floodlightcontroller.ui.web.StaticWebRoutable,\
+net.onrc.onos.registry.controller.StandaloneRegistry
net.floodlightcontroller.restserver.RestApiServer.port = 8080
net.floodlightcontroller.core.FloodlightProvider.openflowport = 6633
net.floodlightcontroller.jython.JythonDebugInterface.port = 6655