Fixed standalone bug, documented and cleaned up the registry API
diff --git a/src/main/java/net/floodlightcontroller/core/internal/Controller.java b/src/main/java/net/floodlightcontroller/core/internal/Controller.java
index 6fb9d20..20ad566 100644
--- a/src/main/java/net/floodlightcontroller/core/internal/Controller.java
+++ b/src/main/java/net/floodlightcontroller/core/internal/Controller.java
@@ -824,6 +824,12 @@
connectedSwitches.add(sw);
if (role != null) {
+ //Put the switch in SLAVE mode until we know we have control
+ log.debug("Setting new switch {} to SLAVE", sw.getStringId());
+ Collection<OFSwitchImpl> swList = new ArrayList<OFSwitchImpl>(1);
+ swList.add(sw);
+ roleChanger.submitRequest(swList, Role.SLAVE);
+
//Request control of the switch from the global registry
try {
registryService.requestControl(sw.getId(),
@@ -832,10 +838,7 @@
log.debug("Registry error: {}", e.getMessage());
}
- log.debug("Setting new switch {} to SLAVE", sw.getStringId());
- Collection<OFSwitchImpl> swList = new ArrayList<OFSwitchImpl>(1);
- swList.add(sw);
- roleChanger.submitRequest(swList, Role.SLAVE);
+
// Send a role request if role support is enabled for the controller
// This is a probe that we'll use to determine if the switch
diff --git a/src/main/java/net/onrc/onos/registry/controller/IControllerRegistryService.java b/src/main/java/net/onrc/onos/registry/controller/IControllerRegistryService.java
index 0971f40..afd9dc6 100644
--- a/src/main/java/net/onrc/onos/registry/controller/IControllerRegistryService.java
+++ b/src/main/java/net/onrc/onos/registry/controller/IControllerRegistryService.java
@@ -8,43 +8,91 @@
public interface IControllerRegistryService extends IFloodlightService {
- // Callback for all mastership changes.
- // Change callback is called when mastership is acquired or released
+ /**
+ * Callback interface for control change events
+ *
+ */
public interface ControlChangeCallback {
+ /**
+ * Called whenever the control changes from the point of view of the
+ * registry. The callee can check whether they have control or not
+ * using the hasControl parameter.
+ * @param dpid The switch that control has changed for
+ * @param hasControl Whether the listener now has control or not
+ */
public void controlChanged(long dpid, boolean hasControl);
}
- // Acquire mastership for a switch.
- public void requestControl(long dpid, ControlChangeCallback cb) throws RegistryException;
+ /**
+ * Request for control of a switch. This method does not block. When
+ * control for a switch changes, the controlChanged method on the
+ * callback object will be called. This happens any time the control
+ * changes while the request is still active (until releaseControl is
+ * called)
+ * @param dpid Switch to request control for
+ * @param cb Callback that will be used to notify caller of control
+ * changes
+ * @throws RegistryException Errors contacting the registry service
+ */
+ public void requestControl(long dpid, ControlChangeCallback cb)
+ throws RegistryException;
- // Release mastership for a switch
+ /**
+ * Stop trying to take control of a switch. This removes the entry
+ * for this controller requesting this switch in the registry.
+ * If the controller had control when this is called, another controller
+ * will now gain control of the switch. This call doesn't block.
+ * @param dpid Switch to release control of
+ */
public void releaseControl(long dpid);
-
- // Check if I am the master of a switch. This is a nonblocking call that checks if the caller is a
+
+ /**
+ * Check whether the controller has control of the switch
+ * This call doesn't block.
+ * @param dpid Switch to check control of
+ * @return
+ */
public boolean hasControl(long dpid);
- // Set/Get mastership identifier.
- // This is typically a unique identifier of the controller that does not change across restarts
+
+ /**
+ * Superseded by registerController
+ * @param id
+ */
+ @Deprecated
public void setMastershipId (String id);
+
+ /**
+ * Get the unique ID used to identify this controller in the cluster
+ * @return
+ */
public String getMastershipId ();
/**
- * Register a controller to the ONOS cluster.
- * @param controller A string identifying the controller
- * @throws errors connecting to registry service, controllerId already registered
+ * Register a controller to the ONOS cluster. Must be called before
+ * the registry can be used to take control of any switches.
+ * @param controller A unique string ID identifying this controller
+ * in the cluster
+ * @throws errors connecting to registry service,
+ * controllerId already registered
*/
public void registerController(String controllerId) throws RegistryException;
/**
* Get all controllers in the cluster
- * @return
+ * @return Collection of controller IDs
*/
public Collection<String> getAllControllers() throws RegistryException;
+ /**
+ * Get all switches in the cluster, along with which controller is
+ * in control of them (if any) and any other controllers that have
+ * requested control.
+ * @return
+ */
+ public Map<String, List<ControllerRegistryEntry>> getAllSwitches();
public String getControllerForSwitch(long dpid) throws RegistryException;
- public Map<String, List<ControllerRegistryEntry>> getAllSwitches();
-
public Collection<Long> getSwitchesControlledByController(String controllerId);
}
diff --git a/src/main/java/net/onrc/onos/registry/controller/IMastershipHelper.java b/src/main/java/net/onrc/onos/registry/controller/IMastershipHelper.java
deleted file mode 100644
index 9e07d46..0000000
--- a/src/main/java/net/onrc/onos/registry/controller/IMastershipHelper.java
+++ /dev/null
@@ -1,27 +0,0 @@
-package net.onrc.onos.registry.controller;
-
-public interface IMastershipHelper {
-
- // Callback for all mastership changes.
- // Change callback is called when mastership is acquired or released
- public interface MastershipCallback {
- public void changeCallback(long dpid);
- }
-
- // Set/get mastership identifier. This is used to set the unique identifier of the controller that is asking for mastership.
- // It needs to be set first before any mastership call can be made
- public void setMastershipId (String id);
- public String getMastershipId ();
-
- // Request mastership for a switch. Our request for mastership remains in a queue. If we win mastership, the callback
- // is called. This call is non-blocking and can be called from the packet processing context as well.
- public void requestMastership(long dpid, MastershipCallback cb);
-
- // Release mastership for a switch. If we are the master, then the mastership will be released and given to the next
- // controller who had requested mastership. If we are not the master our request for mastership will be
- // removed from the queue.
- public void releaseMastership(long dpid);
-
- // Check if I am the master of a switch and return true if I am the master.
- public boolean amMaster(long dpid);
-}
diff --git a/src/main/java/net/onrc/onos/registry/controller/MastershipHelper.java b/src/main/java/net/onrc/onos/registry/controller/MastershipHelper.java
deleted file mode 100644
index 2fcd002..0000000
--- a/src/main/java/net/onrc/onos/registry/controller/MastershipHelper.java
+++ /dev/null
@@ -1,35 +0,0 @@
-package net.onrc.onos.registry.controller;
-
-public class MastershipHelper implements IMastershipHelper {
-
- @Override
- public void setMastershipId(String id) {
- // TODO Auto-generated method stub
-
- }
-
- @Override
- public String getMastershipId() {
- // TODO Auto-generated method stub
- return null;
- }
-
- @Override
- public void requestMastership(long dpid, MastershipCallback cb) {
- // TODO Auto-generated method stub
- return;
- }
-
- @Override
- public void releaseMastership(long dpid) {
- // TODO Auto-generated method stub
-
- }
-
- @Override
- public boolean amMaster(long dpid) {
- // TODO Auto-generated method stub
- return false;
- }
-
-}
diff --git a/src/main/java/net/onrc/onos/registry/controller/ZookeeperRegistry.java b/src/main/java/net/onrc/onos/registry/controller/ZookeeperRegistry.java
index df99354..468bb07 100644
--- a/src/main/java/net/onrc/onos/registry/controller/ZookeeperRegistry.java
+++ b/src/main/java/net/onrc/onos/registry/controller/ZookeeperRegistry.java
@@ -60,7 +60,7 @@
protected Map<String, ControlChangeCallback> switchCallbacks;
protected Map<String, PathChildrenCache> switchPathCaches;
- //Performance-related configuration
+ //Zookeeper performance-related configuration
protected static final int sessionTimeout = 2000;
protected static final int connectionTimeout = 4000;
@@ -135,7 +135,6 @@
@Override
public void childEvent(CuratorFramework client,
PathChildrenCacheEvent event) throws Exception {
- // TODO Auto-generated method stub
log.debug("Root switch path cache got {} event", event.getType());
String strSwitch = null;
@@ -174,14 +173,6 @@
@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 (controllerId == null){
throw new RuntimeException("Must register a controller before calling requestControl");
@@ -214,7 +205,6 @@
@Override
public void releaseControl(long dpid) {
- //if (!zookeeperEnabled) return;
String dpidStr = HexString.toHexString(dpid);
@@ -237,7 +227,6 @@
@Override
public boolean hasControl(long dpid) {
- //if (!zookeeperEnabled) return false;
LeaderLatch latch = switchLatches.get(HexString.toHexString(dpid));
@@ -267,8 +256,6 @@
@Override
public Collection<String> getAllControllers() throws RegistryException {
- //if (!zookeeperEnabled) return null;
-
log.debug("Getting all controllers");
List<String> controllers = new ArrayList<String>();
@@ -288,7 +275,6 @@
@Override
public void registerController(String id) throws RegistryException {
- //if (!zookeeperEnabled) return;
if (controllerId != null) {
throw new RegistryException(
"Controller already registered with id " + controllerId);
@@ -297,12 +283,6 @@
controllerId = id;
byte bytes[] = id.getBytes(Charsets.UTF_8);
- /*byte bytes[] = null;
- try {
- bytes = id.getBytes("UTF-8");
- } catch (UnsupportedEncodingException e1) {
- throw new RegistryException("Error encoding string", e1);
- }*/
String path = controllerPath + "/" + id;
@@ -319,12 +299,10 @@
@Override
public String getControllerForSwitch(long dpid) throws RegistryException {
- //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).
-
String strDpid = HexString.toHexString(dpid);
LeaderLatch latch = switchLatches.get(strDpid);
@@ -365,19 +343,7 @@
}
for (ChildData d : entry.getValue().getCurrentData()) {
- /*
- if (d.getPath().length() < 1){
- log.info("Switch entry with no leader elections: {}", d.getPath());
- continue;
- }
- */
-
- /*String controllerId = null;
- try {
- controllerId = new String(d.getData(), "UTF-8");
- } catch (UnsupportedEncodingException e) {
- log.warn("Encoding exception: {}", e.getMessage());
- }*/
+
String controllerId = new String(d.getData(), Charsets.UTF_8);
String[] splitted = d.getPath().split("-");
@@ -422,57 +388,30 @@
@Override
public void init (FloodlightModuleContext context) throws FloodlightModuleException {
-
log.info("Initialising the Zookeeper Registry - Zookeeper connection required");
- restApi = context.getServiceImpl(IRestApiService.class);
-
- //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 Zookeeper connection");
- zookeeperEnabled = true;
+ //Read the Zookeeper connection string from the config
+ Map<String, String> configParams = context.getConfigParams(this);
+ String connectionString = configParams.get("connectionString");
+ if (connectionString != null){
+ this.connectionString = connectionString;
}
- else {
- log.info("Zookeeper connectivity is disabled - running in standalone mode");
- return;
- }*/
+ log.info("Setting Zookeeper connection string to {}", this.connectionString);
- /*
- try {
- String localHostname = java.net.InetAddress.getLocalHost().getHostName();
- controllerId = localHostname;
- log.debug("Setting controller id to {}", controllerId);
- } catch (UnknownHostException e) {
- // TODO Handle this exception
- e.printStackTrace();
- }*/
+ restApi = context.getServiceImpl(IRestApiService.class);
switchLatches = new HashMap<String, LeaderLatch>();
switchCallbacks = new HashMap<String, ControlChangeCallback>();
switchPathCaches = new HashMap<String, PathChildrenCache>();
RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000, 3);
- client = CuratorFrameworkFactory.newClient(connectionString,
+ client = CuratorFrameworkFactory.newClient(this.connectionString,
sessionTimeout, connectionTimeout, retryPolicy);
client.start();
client = client.usingNamespace(namespace);
-
- //Put some data in for testing
- /*
- try {
- 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);