blob: a5a35762ade2df596eb871ae2a709ce44ef850c3 [file] [log] [blame]
Jonathan Hartd82f20d2013-02-21 18:04:24 -08001package net.onrc.onos.registry.controller;
Umesh Krishnaswamyb56bb292013-02-12 20:28:27 -08002
Jonathan Hartbd181b62013-02-17 16:05:38 -08003import java.io.IOException;
Jonathan Hartedd6a442013-02-20 15:22:06 -08004import java.io.UnsupportedEncodingException;
Jonathan Hartbd181b62013-02-17 16:05:38 -08005import java.net.UnknownHostException;
Umesh Krishnaswamyb56bb292013-02-12 20:28:27 -08006import java.util.ArrayList;
7import java.util.Collection;
Jonathan Hart3d7730a2013-02-22 11:51:17 -08008import java.util.Collections;
Umesh Krishnaswamyb56bb292013-02-12 20:28:27 -08009import java.util.HashMap;
Jonathan Hartedd6a442013-02-20 15:22:06 -080010import java.util.List;
Umesh Krishnaswamyb56bb292013-02-12 20:28:27 -080011import java.util.Map;
12
Umesh Krishnaswamyb56bb292013-02-12 20:28:27 -080013import net.floodlightcontroller.core.module.FloodlightModuleContext;
14import net.floodlightcontroller.core.module.FloodlightModuleException;
15import net.floodlightcontroller.core.module.IFloodlightModule;
16import net.floodlightcontroller.core.module.IFloodlightService;
Jonathan Hart3d7730a2013-02-22 11:51:17 -080017import net.floodlightcontroller.restserver.IRestApiService;
Umesh Krishnaswamyb56bb292013-02-12 20:28:27 -080018
Jonathan Hart3d7730a2013-02-22 11:51:17 -080019import org.apache.commons.lang.NotImplementedException;
Jonathan Hartedd6a442013-02-20 15:22:06 -080020import org.apache.zookeeper.CreateMode;
Jonathan Hartbd181b62013-02-17 16:05:38 -080021import org.apache.zookeeper.WatchedEvent;
Jonathan Hartc6eee9e2013-02-18 14:58:27 -080022import org.apache.zookeeper.Watcher.Event.KeeperState;
Jonathan Hartbd181b62013-02-17 16:05:38 -080023import org.openflow.util.HexString;
24import org.slf4j.Logger;
25import org.slf4j.LoggerFactory;
Umesh Krishnaswamyb56bb292013-02-12 20:28:27 -080026
Jonathan Hartbd181b62013-02-17 16:05:38 -080027import com.netflix.curator.RetryPolicy;
28import com.netflix.curator.framework.CuratorFramework;
29import com.netflix.curator.framework.CuratorFrameworkFactory;
30import com.netflix.curator.framework.api.CuratorWatcher;
Jonathan Hartedd6a442013-02-20 15:22:06 -080031import com.netflix.curator.framework.recipes.cache.ChildData;
32import com.netflix.curator.framework.recipes.cache.PathChildrenCache;
33import com.netflix.curator.framework.recipes.cache.PathChildrenCache.StartMode;
Jonathan Hart3d7730a2013-02-22 11:51:17 -080034import com.netflix.curator.framework.recipes.cache.PathChildrenCacheEvent;
35import com.netflix.curator.framework.recipes.cache.PathChildrenCacheListener;
Jonathan Hartbd181b62013-02-17 16:05:38 -080036import com.netflix.curator.framework.recipes.leader.LeaderLatch;
37import com.netflix.curator.framework.recipes.leader.Participant;
Jonathan Hart3d7730a2013-02-22 11:51:17 -080038import com.netflix.curator.retry.ExponentialBackoffRetry;
Jonathan Hartbd181b62013-02-17 16:05:38 -080039
Jonathan Hartd82f20d2013-02-21 18:04:24 -080040public class RegistryManager implements IFloodlightModule, IControllerRegistryService {
Jonathan Hartc6eee9e2013-02-18 14:58:27 -080041
Jonathan Hartd82f20d2013-02-21 18:04:24 -080042 protected static Logger log = LoggerFactory.getLogger(RegistryManager.class);
Jonathan Hartc6eee9e2013-02-18 14:58:27 -080043 protected String mastershipId = null;
Umesh Krishnaswamyb56bb292013-02-12 20:28:27 -080044
Jonathan Hart3d7730a2013-02-22 11:51:17 -080045 protected IRestApiService restApi;
46
Jonathan Hartbd181b62013-02-17 16:05:38 -080047 //TODO read this from configuration
48 protected String connectionString = "localhost:2181";
Jonathan Hart3d7730a2013-02-22 11:51:17 -080049
50
Jonathan Hartbd181b62013-02-17 16:05:38 -080051 private final String namespace = "onos";
Jonathan Hartedd6a442013-02-20 15:22:06 -080052 private final String switchLatchesPath = "/switches";
Jonathan Hart3d7730a2013-02-22 11:51:17 -080053 private final String controllerPath = "/controllers";
Jonathan Hartbd181b62013-02-17 16:05:38 -080054
55 protected CuratorFramework client;
Jonathan Hartedd6a442013-02-20 15:22:06 -080056
Jonathan Hartedd6a442013-02-20 15:22:06 -080057 protected PathChildrenCache controllerCache;
Jonathan Hart3d7730a2013-02-22 11:51:17 -080058 protected PathChildrenCache switchCache;
Jonathan Hartbd181b62013-02-17 16:05:38 -080059
60 protected Map<String, LeaderLatch> switchLatches;
Jonathan Hartd82f20d2013-02-21 18:04:24 -080061 protected Map<String, ControlChangeCallback> switchCallbacks;
Jonathan Hart3d7730a2013-02-22 11:51:17 -080062 protected Map<String, PathChildrenCache> switchPathCaches;
Jonathan Hartbd181b62013-02-17 16:05:38 -080063
Jonathan Hart57080fb2013-02-21 10:55:46 -080064 protected boolean moduleEnabled = false;
65
Jonathan Hartbd181b62013-02-17 16:05:38 -080066 protected class ParamaterizedCuratorWatcher implements CuratorWatcher {
67 private String dpid;
Jonathan Hartc6eee9e2013-02-18 14:58:27 -080068 private boolean isLeader = false;
Jonathan Hartbd181b62013-02-17 16:05:38 -080069 private String latchPath;
70
71 public ParamaterizedCuratorWatcher(String dpid, String latchPath){
72 this.dpid = dpid;
73 this.latchPath = latchPath;
74 }
75
76 @Override
Jonathan Hartedd6a442013-02-20 15:22:06 -080077 public synchronized void process(WatchedEvent event) throws Exception {
Jonathan Hartbd181b62013-02-17 16:05:38 -080078 log.debug("Watch Event: {}", event);
79
80 LeaderLatch latch = switchLatches.get(dpid);
81
Jonathan Hartc6eee9e2013-02-18 14:58:27 -080082 if (event.getState() == KeeperState.Disconnected){
83 if (isLeader) {
84 log.debug("Disconnected while leader - lost leadership for {}", dpid);
85
86 isLeader = false;
Jonathan Hart3d7730a2013-02-22 11:51:17 -080087 ControlChangeCallback cb = switchCallbacks.get(dpid);
88 if (cb != null) {
89 //Allow callback to be null if the requester doesn't want a callback
90 cb.controlChanged(HexString.toLong(dpid), false);
91 }
Jonathan Hartc6eee9e2013-02-18 14:58:27 -080092 }
93 return;
94 }
Jonathan Hartbd181b62013-02-17 16:05:38 -080095
Jonathan Hartc6eee9e2013-02-18 14:58:27 -080096 try {
Jonathan Hartedd6a442013-02-20 15:22:06 -080097
Jonathan Hartc6eee9e2013-02-18 14:58:27 -080098 Participant leader = latch.getLeader();
99
100 if (leader.getId().equals(mastershipId) && !isLeader){
101 log.debug("Became leader for {}", dpid);
102
103 isLeader = true;
Jonathan Hartd82f20d2013-02-21 18:04:24 -0800104 switchCallbacks.get(dpid).controlChanged(HexString.toLong(dpid), true);
Jonathan Hartc6eee9e2013-02-18 14:58:27 -0800105 }
106 else if (!leader.getId().equals(mastershipId) && isLeader){
107 log.debug("Lost leadership for {}", dpid);
108
109 isLeader = false;
Jonathan Hartd82f20d2013-02-21 18:04:24 -0800110 switchCallbacks.get(dpid).controlChanged(HexString.toLong(dpid), false);
Jonathan Hartc6eee9e2013-02-18 14:58:27 -0800111 }
112 } catch (Exception e){
113 if (isLeader){
114 log.debug("Exception checking leadership status. Assume leadship lost for {}",
115 dpid);
116
117 isLeader = false;
Jonathan Hartd82f20d2013-02-21 18:04:24 -0800118 switchCallbacks.get(dpid).controlChanged(HexString.toLong(dpid), false);
Jonathan Hartc6eee9e2013-02-18 14:58:27 -0800119 }
Jonathan Hartbd181b62013-02-17 16:05:38 -0800120 }
121
122 client.getChildren().usingWatcher(this).inBackground().forPath(latchPath);
123 //client.getChildren().usingWatcher(this).forPath(latchPath);
124 }
Jonathan Hartc6eee9e2013-02-18 14:58:27 -0800125 }
Jonathan Hart3d7730a2013-02-22 11:51:17 -0800126
127
128 /*
129 * Listens for changes to the switch znodes in Zookeeper. This maintains the second level of
130 * PathChildrenCaches that hold the controllers contending for each switch - there's one for
131 * each switch.
132 */
133 PathChildrenCacheListener switchPathCacheListener = new PathChildrenCacheListener() {
134 @Override
135 public void childEvent(CuratorFramework client,
136 PathChildrenCacheEvent event) throws Exception {
137 // TODO Auto-generated method stub
138 log.debug("Root switch path cache got {} event", event.getType());
139
140 String strSwitch = null;
141 if (event.getData() != null){
142 log.debug("Event path {}", event.getData().getPath());
143 String[] splitted = event.getData().getPath().split("/");
144 strSwitch = splitted[splitted.length - 1];
145 log.debug("Switch name is {}", strSwitch);
146 }
147
148 switch (event.getType()){
149 case CHILD_ADDED:
150 case CHILD_UPDATED:
151 //Check we have a PathChildrenCache for this child, add one if not
152 if (switchPathCaches.get(strSwitch) == null){
153 PathChildrenCache pc = new PathChildrenCache(client,
154 event.getData().getPath(), true);
155 pc.start(StartMode.NORMAL);
156 switchPathCaches.put(strSwitch, pc);
157 }
158 break;
159 case CHILD_REMOVED:
160 //Remove our PathChildrenCache for this child
161 PathChildrenCache pc = switchPathCaches.remove(strSwitch);
162 pc.close();
163 break;
164 default:
165 //All other events are connection status events. We need to do anything
166 //as the path cache handles these on its own.
167 break;
168 }
169
170 }
171 };
Jonathan Hartedd6a442013-02-20 15:22:06 -0800172
Jonathan Hartbd181b62013-02-17 16:05:38 -0800173
174 @Override
Jonathan Hart3d7730a2013-02-22 11:51:17 -0800175 public void requestControl(long dpid, ControlChangeCallback cb) throws RegistryException {
Jonathan Hartc6eee9e2013-02-18 14:58:27 -0800176
Jonathan Hart57080fb2013-02-21 10:55:46 -0800177 if (!moduleEnabled) return;
178
Jonathan Hartc6eee9e2013-02-18 14:58:27 -0800179 if (mastershipId == null){
180 throw new RuntimeException("Must set mastershipId before calling aquireMastership");
Jonathan Hartbd181b62013-02-17 16:05:38 -0800181 }
182
183 String dpidStr = HexString.toHexString(dpid);
184 String latchPath = switchLatchesPath + "/" + dpidStr;
185
Jonathan Hartc6eee9e2013-02-18 14:58:27 -0800186 if (switchLatches.get(dpidStr) != null){
187 throw new RuntimeException("Leader election for switch " + dpidStr +
188 "is already running");
189 }
190
Jonathan Hartbd181b62013-02-17 16:05:38 -0800191 LeaderLatch latch = new LeaderLatch(client, latchPath, mastershipId);
192 switchLatches.put(dpidStr, latch);
Jonathan Hartbd181b62013-02-17 16:05:38 -0800193 switchCallbacks.put(dpidStr, cb);
194
195 try {
196 //client.getChildren().usingWatcher(watcher).inBackground().forPath(singleLatchPath);
197 client.getChildren().usingWatcher(
198 new ParamaterizedCuratorWatcher(dpidStr, latchPath))
199 .inBackground().forPath(latchPath);
200 latch.start();
201 } catch (Exception e) {
Jonathan Hartc6eee9e2013-02-18 14:58:27 -0800202 log.warn("Error starting leader latch: {}", e.getMessage());
Jonathan Hart3d7730a2013-02-22 11:51:17 -0800203 throw new RegistryException("Error starting leader latch for " + dpidStr, e);
Jonathan Hartbd181b62013-02-17 16:05:38 -0800204 }
205
206 }
207
208 @Override
Jonathan Hartd82f20d2013-02-21 18:04:24 -0800209 public void releaseControl(long dpid) {
Jonathan Hart57080fb2013-02-21 10:55:46 -0800210 if (!moduleEnabled) return;
211
Jonathan Hartc6eee9e2013-02-18 14:58:27 -0800212 String dpidStr = HexString.toHexString(dpid);
213
214 LeaderLatch latch = switchLatches.get(dpidStr);
Jonathan Hartbd181b62013-02-17 16:05:38 -0800215 if (latch == null) {
Jonathan Hartc6eee9e2013-02-18 14:58:27 -0800216 log.debug("Trying to release mastership for switch we are not contesting");
Jonathan Hartbd181b62013-02-17 16:05:38 -0800217 return;
218 }
219
220 try {
221 latch.close();
222 } catch (IOException e) {
Jonathan Hart1be46262013-02-20 16:43:51 -0800223 //I think it's OK not to do anything here. Either the node got deleted correctly,
224 //or the connection went down and the node got deleted.
225 } finally {
226 switchLatches.remove(dpidStr);
227 switchCallbacks.remove(dpidStr);
Jonathan Hartbd181b62013-02-17 16:05:38 -0800228 }
229 }
230
231 @Override
Jonathan Hartd82f20d2013-02-21 18:04:24 -0800232 public boolean hasControl(long dpid) {
Jonathan Hart57080fb2013-02-21 10:55:46 -0800233 if (!moduleEnabled) return false;
234
Jonathan Hartbd181b62013-02-17 16:05:38 -0800235 LeaderLatch latch = switchLatches.get(HexString.toHexString(dpid));
236
237 if (latch == null) {
238 log.warn("No leader latch for dpid {}", HexString.toHexString(dpid));
239 return false;
240 }
241
Jonathan Hartbd181b62013-02-17 16:05:38 -0800242 try {
243 return latch.getLeader().getId().equals(mastershipId);
244 } catch (Exception e) {
245 //TODO swallow exception?
246 return false;
247 }
248 }
249
250 @Override
251 public void setMastershipId(String id) {
Jonathan Hartbd181b62013-02-17 16:05:38 -0800252 mastershipId = id;
253 }
254
255 @Override
256 public String getMastershipId() {
Jonathan Hartbd181b62013-02-17 16:05:38 -0800257 return mastershipId;
258 }
259
Jonathan Hartedd6a442013-02-20 15:22:06 -0800260 @Override
Jonathan Hart57080fb2013-02-21 10:55:46 -0800261 public Collection<String> getAllControllers() throws RegistryException {
262 if (!moduleEnabled) return null;
263
Jonathan Hartedd6a442013-02-20 15:22:06 -0800264 log.debug("Getting all controllers");
Jonathan Hart1be46262013-02-20 16:43:51 -0800265
Jonathan Hartedd6a442013-02-20 15:22:06 -0800266 List<String> controllers = new ArrayList<String>();
267 for (ChildData data : controllerCache.getCurrentData()){
268
269 String d = null;
270 try {
271 d = new String(data.getData(), "UTF-8");
272 } catch (UnsupportedEncodingException e) {
Jonathan Hart57080fb2013-02-21 10:55:46 -0800273 throw new RegistryException("Error encoding string", e);
Jonathan Hartedd6a442013-02-20 15:22:06 -0800274 }
275
276 controllers.add(d);
277 }
278 return controllers;
279 }
280
281 @Override
Jonathan Hart57080fb2013-02-21 10:55:46 -0800282 public void registerController(String id) throws RegistryException {
283 if (!moduleEnabled) return;
284
Jonathan Hartedd6a442013-02-20 15:22:06 -0800285 byte bytes[] = null;
286 try {
287 bytes = id.getBytes("UTF-8");
288 } catch (UnsupportedEncodingException e1) {
Jonathan Hart57080fb2013-02-21 10:55:46 -0800289 throw new RegistryException("Error encoding string", e1);
Jonathan Hartedd6a442013-02-20 15:22:06 -0800290 }
291
292 String path = controllerPath + "/" + id;
293
294 log.info("Registering controller with id {}", id);
295
Jonathan Hart57080fb2013-02-21 10:55:46 -0800296 //Create ephemeral node in controller registry
Jonathan Hartedd6a442013-02-20 15:22:06 -0800297 try {
298 client.create().withProtection().withMode(CreateMode.EPHEMERAL)
299 .forPath(path, bytes);
300 } catch (Exception e) {
Jonathan Hart57080fb2013-02-21 10:55:46 -0800301 throw new RegistryException("Error contacting the Zookeeper service", e);
Jonathan Hartedd6a442013-02-20 15:22:06 -0800302 }
303 }
304
305 @Override
Jonathan Hart57080fb2013-02-21 10:55:46 -0800306 public String getControllerForSwitch(long dpid) throws RegistryException {
307 if (!moduleEnabled) return null;
Jonathan Hartedd6a442013-02-20 15:22:06 -0800308 // TODO Work out how we should store this controller/switch data.
309 // The leader latch might be a index to the /controllers collections
310 // which holds more info on the controller (how to talk to it for example).
311
312
313 String strDpid = HexString.toHexString(dpid);
314 LeaderLatch latch = switchLatches.get(strDpid);
315
316 if (latch == null){
317 log.warn("Tried to get controller for non-existent switch");
318 return null;
319 }
320
321 Participant leader = null;
322 try {
323 leader = latch.getLeader();
324 } catch (Exception e) {
Jonathan Hart57080fb2013-02-21 10:55:46 -0800325 throw new RegistryException("Error contacting the Zookeeper service", e);
Jonathan Hartedd6a442013-02-20 15:22:06 -0800326 }
327
328 return leader.getId();
329 }
330
331 @Override
332 public Collection<Long> getSwitchesControlledByController(String controllerId) {
Jonathan Hart3d7730a2013-02-22 11:51:17 -0800333 //TODO remove this if not needed
334 throw new NotImplementedException();
Jonathan Hartedd6a442013-02-20 15:22:06 -0800335 }
Jonathan Hartbd181b62013-02-17 16:05:38 -0800336
Jonathan Hartd82f20d2013-02-21 18:04:24 -0800337
338 @Override
Jonathan Hart3d7730a2013-02-22 11:51:17 -0800339 public Map<String, List<ControllerRegistryEntry>> getAllSwitches() {
340 Map<String, List<ControllerRegistryEntry>> data =
341 new HashMap<String, List<ControllerRegistryEntry>>();
342
343 for (Map.Entry<String, PathChildrenCache> entry : switchPathCaches.entrySet()){
344 List<ControllerRegistryEntry> contendingControllers =
345 new ArrayList<ControllerRegistryEntry>();
346
347 if (entry.getValue().getCurrentData().size() < 1){
348 log.info("Switch entry with no leader elections: {}", entry.getKey());
349 continue;
350 }
351
352 for (ChildData d : entry.getValue().getCurrentData()) {
353 /*
354 if (d.getPath().length() < 1){
355 log.info("Switch entry with no leader elections: {}", d.getPath());
356 continue;
357 }
358 */
359
360 String controllerId = null;
361 try {
362 controllerId = new String(d.getData(), "UTF-8");
363 } catch (UnsupportedEncodingException e) {
364 log.warn("Encoding exception: {}", e.getMessage());
365 }
366
367 String[] splitted = d.getPath().split("-");
368 int sequenceNumber = Integer.parseInt(splitted[splitted.length - 1]);
369
370 contendingControllers.add(new ControllerRegistryEntry(controllerId, sequenceNumber));
371 }
372
373 Collections.sort(contendingControllers);
374 data.put(entry.getKey(), contendingControllers);
375 }
376 return data;
Jonathan Hartd82f20d2013-02-21 18:04:24 -0800377 }
378
Jonathan Hartbd181b62013-02-17 16:05:38 -0800379 /*
380 * IFloodlightModule
381 */
382
Umesh Krishnaswamyb56bb292013-02-12 20:28:27 -0800383 @Override
384 public Collection<Class<? extends IFloodlightService>> getModuleServices() {
Jonathan Hartedd6a442013-02-20 15:22:06 -0800385 Collection<Class<? extends IFloodlightService>> l =
386 new ArrayList<Class<? extends IFloodlightService>>();
Jonathan Hartd82f20d2013-02-21 18:04:24 -0800387 l.add(IControllerRegistryService.class);
Umesh Krishnaswamyb56bb292013-02-12 20:28:27 -0800388 return l;
389 }
390
391 @Override
392 public Map<Class<? extends IFloodlightService>, IFloodlightService> getServiceImpls() {
393 Map<Class<? extends IFloodlightService>, IFloodlightService> m =
394 new HashMap<Class<? extends IFloodlightService>, IFloodlightService>();
Jonathan Hartd82f20d2013-02-21 18:04:24 -0800395 m.put(IControllerRegistryService.class, this);
Umesh Krishnaswamyb56bb292013-02-12 20:28:27 -0800396 return m;
397 }
398
399 @Override
400 public Collection<Class<? extends IFloodlightService>> getModuleDependencies() {
Jonathan Hart3d7730a2013-02-22 11:51:17 -0800401 Collection<Class<? extends IFloodlightService>> l =
402 new ArrayList<Class<? extends IFloodlightService>>();
403 l.add(IRestApiService.class);
404 return l;
Umesh Krishnaswamyb56bb292013-02-12 20:28:27 -0800405 }
406
407 @Override
408 public void init (FloodlightModuleContext context) throws FloodlightModuleException {
Jonathan Hart57080fb2013-02-21 10:55:46 -0800409
Jonathan Hart3d7730a2013-02-22 11:51:17 -0800410 restApi = context.getServiceImpl(IRestApiService.class);
411
Jonathan Hart57080fb2013-02-21 10:55:46 -0800412 //Read config to see if we should try and connect to zookeeper
413 Map<String, String> configOptions = context.getConfigParams(this);
414 String enableZookeeper = configOptions.get("enableZookeeper");
415 if (enableZookeeper != null) {
416 log.info("Enabling Mastership module - requires Zookeeper connection");
417 moduleEnabled = true;
418 }
419 else {
420 log.info("Mastership module is disabled");
421 return;
422 }
423
Jonathan Hartbd181b62013-02-17 16:05:38 -0800424 try {
425 String localHostname = java.net.InetAddress.getLocalHost().getHostName();
426 mastershipId = localHostname;
427 log.debug("Setting mastership id to {}", mastershipId);
428 } catch (UnknownHostException e) {
429 // TODO Handle this exception
430 e.printStackTrace();
431 }
432
433 switchLatches = new HashMap<String, LeaderLatch>();
Jonathan Hartd82f20d2013-02-21 18:04:24 -0800434 switchCallbacks = new HashMap<String, ControlChangeCallback>();
Jonathan Hart3d7730a2013-02-22 11:51:17 -0800435 switchPathCaches = new HashMap<String, PathChildrenCache>();
Jonathan Hartbd181b62013-02-17 16:05:38 -0800436
Jonathan Hart3d7730a2013-02-22 11:51:17 -0800437 RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000, 3);
438 //RetryPolicy retryPolicy = new RetryOneTime(0);
Jonathan Hartbd181b62013-02-17 16:05:38 -0800439 client = CuratorFrameworkFactory.newClient(connectionString, retryPolicy);
440
441 client.start();
442
443 client = client.usingNamespace(namespace);
444
Jonathan Hart3d7730a2013-02-22 11:51:17 -0800445 //Put some data in for testing
446 try {
447 registerController(mastershipId);
448 requestControl(2L, null);
449 } catch (RegistryException e1) {
450 // TODO Auto-generated catch block
451 e1.printStackTrace();
452 }
453
Jonathan Hartedd6a442013-02-20 15:22:06 -0800454 controllerCache = new PathChildrenCache(client, controllerPath, true);
Jonathan Hart3d7730a2013-02-22 11:51:17 -0800455 switchCache = new PathChildrenCache(client, switchLatchesPath, true);
456 switchCache.getListenable().addListener(switchPathCacheListener);
Jonathan Hartedd6a442013-02-20 15:22:06 -0800457
458 try {
459 controllerCache.start(StartMode.BUILD_INITIAL_CACHE);
Jonathan Hart3d7730a2013-02-22 11:51:17 -0800460
461 //Don't prime the cache, we want a notification for each child node in the path
462 switchCache.start(StartMode.NORMAL);
Jonathan Hartedd6a442013-02-20 15:22:06 -0800463 } catch (Exception e) {
464 // TODO Auto-generated catch block
465 e.printStackTrace();
466 }
Umesh Krishnaswamyb56bb292013-02-12 20:28:27 -0800467 }
468
469 @Override
470 public void startUp (FloodlightModuleContext context) {
Jonathan Hart3d7730a2013-02-22 11:51:17 -0800471 restApi.addRestletRoutable(new RegistryWebRoutable());
Umesh Krishnaswamyb56bb292013-02-12 20:28:27 -0800472 }
Jonathan Hartd82f20d2013-02-21 18:04:24 -0800473
Umesh Krishnaswamyb56bb292013-02-12 20:28:27 -0800474}