blob: df993547109ee6ff4a44a43afcfdd76eb763c8f5 [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;
Umesh Krishnaswamyb56bb292013-02-12 20:28:27 -08005import java.util.ArrayList;
6import java.util.Collection;
Jonathan Hart3d7730a2013-02-22 11:51:17 -08007import java.util.Collections;
Umesh Krishnaswamyb56bb292013-02-12 20:28:27 -08008import java.util.HashMap;
Jonathan Hartedd6a442013-02-20 15:22:06 -08009import java.util.List;
Umesh Krishnaswamyb56bb292013-02-12 20:28:27 -080010import java.util.Map;
11
Umesh Krishnaswamyb56bb292013-02-12 20:28:27 -080012import net.floodlightcontroller.core.module.FloodlightModuleContext;
13import net.floodlightcontroller.core.module.FloodlightModuleException;
14import net.floodlightcontroller.core.module.IFloodlightModule;
15import net.floodlightcontroller.core.module.IFloodlightService;
Jonathan Hart3d7730a2013-02-22 11:51:17 -080016import net.floodlightcontroller.restserver.IRestApiService;
Umesh Krishnaswamyb56bb292013-02-12 20:28:27 -080017
Jonathan Hartedd6a442013-02-20 15:22:06 -080018import org.apache.zookeeper.CreateMode;
Jonathan Hartbd181b62013-02-17 16:05:38 -080019import org.apache.zookeeper.WatchedEvent;
Jonathan Hartc6eee9e2013-02-18 14:58:27 -080020import org.apache.zookeeper.Watcher.Event.KeeperState;
Jonathan Hartbd181b62013-02-17 16:05:38 -080021import org.openflow.util.HexString;
22import org.slf4j.Logger;
23import org.slf4j.LoggerFactory;
Umesh Krishnaswamyb56bb292013-02-12 20:28:27 -080024
Jonathan Hartd10008d2013-02-23 17:04:08 -080025import com.google.common.base.Charsets;
Jonathan Hartbd181b62013-02-17 16:05:38 -080026import com.netflix.curator.RetryPolicy;
27import com.netflix.curator.framework.CuratorFramework;
28import com.netflix.curator.framework.CuratorFrameworkFactory;
29import com.netflix.curator.framework.api.CuratorWatcher;
Jonathan Hartedd6a442013-02-20 15:22:06 -080030import com.netflix.curator.framework.recipes.cache.ChildData;
31import com.netflix.curator.framework.recipes.cache.PathChildrenCache;
32import com.netflix.curator.framework.recipes.cache.PathChildrenCache.StartMode;
Jonathan Hart3d7730a2013-02-22 11:51:17 -080033import com.netflix.curator.framework.recipes.cache.PathChildrenCacheEvent;
34import com.netflix.curator.framework.recipes.cache.PathChildrenCacheListener;
Jonathan Hartbd181b62013-02-17 16:05:38 -080035import com.netflix.curator.framework.recipes.leader.LeaderLatch;
36import com.netflix.curator.framework.recipes.leader.Participant;
Jonathan Hart3d7730a2013-02-22 11:51:17 -080037import com.netflix.curator.retry.ExponentialBackoffRetry;
Jonathan Hartbd181b62013-02-17 16:05:38 -080038
Jonathan Hartbd766972013-02-22 15:13:03 -080039public class ZookeeperRegistry implements IFloodlightModule, IControllerRegistryService {
Jonathan Hartc6eee9e2013-02-18 14:58:27 -080040
Jonathan Hartbd766972013-02-22 15:13:03 -080041 protected static Logger log = LoggerFactory.getLogger(ZookeeperRegistry.class);
42 protected String controllerId = null;
Umesh Krishnaswamyb56bb292013-02-12 20:28:27 -080043
Jonathan Hart3d7730a2013-02-22 11:51:17 -080044 protected IRestApiService restApi;
45
Jonathan Hartbd181b62013-02-17 16:05:38 -080046 //TODO read this from configuration
47 protected String connectionString = "localhost:2181";
Jonathan Hart3d7730a2013-02-22 11:51:17 -080048
49
Jonathan Hartbd181b62013-02-17 16:05:38 -080050 private final String namespace = "onos";
Jonathan Hartedd6a442013-02-20 15:22:06 -080051 private final String switchLatchesPath = "/switches";
Jonathan Hart3d7730a2013-02-22 11:51:17 -080052 private final String controllerPath = "/controllers";
Jonathan Hartbd181b62013-02-17 16:05:38 -080053
54 protected CuratorFramework client;
Jonathan Hartedd6a442013-02-20 15:22:06 -080055
Jonathan Hartedd6a442013-02-20 15:22:06 -080056 protected PathChildrenCache controllerCache;
Jonathan Hart3d7730a2013-02-22 11:51:17 -080057 protected PathChildrenCache switchCache;
Jonathan Hartbd181b62013-02-17 16:05:38 -080058
59 protected Map<String, LeaderLatch> switchLatches;
Jonathan Hartd82f20d2013-02-21 18:04:24 -080060 protected Map<String, ControlChangeCallback> switchCallbacks;
Jonathan Hart3d7730a2013-02-22 11:51:17 -080061 protected Map<String, PathChildrenCache> switchPathCaches;
Jonathan Hartbd181b62013-02-17 16:05:38 -080062
Jonathan Hartcc957a02013-02-26 10:39:04 -080063 //Performance-related configuration
64 protected static final int sessionTimeout = 2000;
65 protected static final int connectionTimeout = 4000;
Jonathan Hart57080fb2013-02-21 10:55:46 -080066
Jonathan Hartbd181b62013-02-17 16:05:38 -080067 protected class ParamaterizedCuratorWatcher implements CuratorWatcher {
68 private String dpid;
Jonathan Hartc6eee9e2013-02-18 14:58:27 -080069 private boolean isLeader = false;
Jonathan Hartbd181b62013-02-17 16:05:38 -080070 private String latchPath;
71
72 public ParamaterizedCuratorWatcher(String dpid, String latchPath){
73 this.dpid = dpid;
74 this.latchPath = latchPath;
75 }
76
77 @Override
Jonathan Hartedd6a442013-02-20 15:22:06 -080078 public synchronized void process(WatchedEvent event) throws Exception {
Jonathan Hartbd181b62013-02-17 16:05:38 -080079 log.debug("Watch Event: {}", event);
80
81 LeaderLatch latch = switchLatches.get(dpid);
82
Jonathan Hartc6eee9e2013-02-18 14:58:27 -080083 if (event.getState() == KeeperState.Disconnected){
84 if (isLeader) {
85 log.debug("Disconnected while leader - lost leadership for {}", dpid);
86
87 isLeader = false;
Jonathan Hart3d7730a2013-02-22 11:51:17 -080088 ControlChangeCallback cb = switchCallbacks.get(dpid);
89 if (cb != null) {
90 //Allow callback to be null if the requester doesn't want a callback
91 cb.controlChanged(HexString.toLong(dpid), false);
92 }
Jonathan Hartc6eee9e2013-02-18 14:58:27 -080093 }
94 return;
95 }
Jonathan Hartbd181b62013-02-17 16:05:38 -080096
Jonathan Hartc6eee9e2013-02-18 14:58:27 -080097 try {
Jonathan Hartedd6a442013-02-20 15:22:06 -080098
Jonathan Hartc6eee9e2013-02-18 14:58:27 -080099 Participant leader = latch.getLeader();
100
Jonathan Hartbd766972013-02-22 15:13:03 -0800101 if (leader.getId().equals(controllerId) && !isLeader){
Jonathan Hartc6eee9e2013-02-18 14:58:27 -0800102 log.debug("Became leader for {}", dpid);
103
104 isLeader = true;
Jonathan Hartd82f20d2013-02-21 18:04:24 -0800105 switchCallbacks.get(dpid).controlChanged(HexString.toLong(dpid), true);
Jonathan Hartc6eee9e2013-02-18 14:58:27 -0800106 }
Jonathan Hartbd766972013-02-22 15:13:03 -0800107 else if (!leader.getId().equals(controllerId) && isLeader){
Jonathan Hartc6eee9e2013-02-18 14:58:27 -0800108 log.debug("Lost leadership for {}", dpid);
109
110 isLeader = false;
Jonathan Hartd82f20d2013-02-21 18:04:24 -0800111 switchCallbacks.get(dpid).controlChanged(HexString.toLong(dpid), false);
Jonathan Hartc6eee9e2013-02-18 14:58:27 -0800112 }
113 } catch (Exception e){
114 if (isLeader){
115 log.debug("Exception checking leadership status. Assume leadship lost for {}",
116 dpid);
117
118 isLeader = false;
Jonathan Hartd82f20d2013-02-21 18:04:24 -0800119 switchCallbacks.get(dpid).controlChanged(HexString.toLong(dpid), false);
Jonathan Hartc6eee9e2013-02-18 14:58:27 -0800120 }
Jonathan Hartbd181b62013-02-17 16:05:38 -0800121 }
122
123 client.getChildren().usingWatcher(this).inBackground().forPath(latchPath);
124 //client.getChildren().usingWatcher(this).forPath(latchPath);
125 }
Jonathan Hartc6eee9e2013-02-18 14:58:27 -0800126 }
Jonathan Hart3d7730a2013-02-22 11:51:17 -0800127
128
129 /*
130 * Listens for changes to the switch znodes in Zookeeper. This maintains the second level of
131 * PathChildrenCaches that hold the controllers contending for each switch - there's one for
132 * each switch.
133 */
134 PathChildrenCacheListener switchPathCacheListener = new PathChildrenCacheListener() {
135 @Override
136 public void childEvent(CuratorFramework client,
137 PathChildrenCacheEvent event) throws Exception {
138 // TODO Auto-generated method stub
139 log.debug("Root switch path cache got {} event", event.getType());
140
141 String strSwitch = null;
142 if (event.getData() != null){
143 log.debug("Event path {}", event.getData().getPath());
144 String[] splitted = event.getData().getPath().split("/");
145 strSwitch = splitted[splitted.length - 1];
146 log.debug("Switch name is {}", strSwitch);
147 }
148
149 switch (event.getType()){
150 case CHILD_ADDED:
151 case CHILD_UPDATED:
152 //Check we have a PathChildrenCache for this child, add one if not
153 if (switchPathCaches.get(strSwitch) == null){
154 PathChildrenCache pc = new PathChildrenCache(client,
155 event.getData().getPath(), true);
156 pc.start(StartMode.NORMAL);
157 switchPathCaches.put(strSwitch, pc);
158 }
159 break;
160 case CHILD_REMOVED:
161 //Remove our PathChildrenCache for this child
162 PathChildrenCache pc = switchPathCaches.remove(strSwitch);
163 pc.close();
164 break;
165 default:
166 //All other events are connection status events. We need to do anything
167 //as the path cache handles these on its own.
168 break;
169 }
170
171 }
172 };
Jonathan Hartedd6a442013-02-20 15:22:06 -0800173
Jonathan Hartbd181b62013-02-17 16:05:38 -0800174
175 @Override
Jonathan Hart3d7730a2013-02-22 11:51:17 -0800176 public void requestControl(long dpid, ControlChangeCallback cb) throws RegistryException {
Jonathan Hartbd766972013-02-22 15:13:03 -0800177 /*
178 if (!zookeeperEnabled) {
179 //If zookeeper connection is disabled all control requests succeed immediately
180 if (cb != null){
181 cb.controlChanged(dpid, true);
182 }
183 return;
184 }*/
Jonathan Hartc6eee9e2013-02-18 14:58:27 -0800185
Jonathan Hartbd766972013-02-22 15:13:03 -0800186 if (controllerId == null){
187 throw new RuntimeException("Must register a controller before calling requestControl");
Jonathan Hartbd181b62013-02-17 16:05:38 -0800188 }
189
190 String dpidStr = HexString.toHexString(dpid);
191 String latchPath = switchLatchesPath + "/" + dpidStr;
192
Jonathan Hartc6eee9e2013-02-18 14:58:27 -0800193 if (switchLatches.get(dpidStr) != null){
194 throw new RuntimeException("Leader election for switch " + dpidStr +
195 "is already running");
196 }
197
Jonathan Hartbd766972013-02-22 15:13:03 -0800198 LeaderLatch latch = new LeaderLatch(client, latchPath, controllerId);
Jonathan Hartbd181b62013-02-17 16:05:38 -0800199 switchLatches.put(dpidStr, latch);
Jonathan Hartbd181b62013-02-17 16:05:38 -0800200 switchCallbacks.put(dpidStr, cb);
201
202 try {
203 //client.getChildren().usingWatcher(watcher).inBackground().forPath(singleLatchPath);
204 client.getChildren().usingWatcher(
205 new ParamaterizedCuratorWatcher(dpidStr, latchPath))
206 .inBackground().forPath(latchPath);
207 latch.start();
208 } catch (Exception e) {
Jonathan Hartc6eee9e2013-02-18 14:58:27 -0800209 log.warn("Error starting leader latch: {}", e.getMessage());
Jonathan Hart3d7730a2013-02-22 11:51:17 -0800210 throw new RegistryException("Error starting leader latch for " + dpidStr, e);
Jonathan Hartbd181b62013-02-17 16:05:38 -0800211 }
212
213 }
214
215 @Override
Jonathan Hartd82f20d2013-02-21 18:04:24 -0800216 public void releaseControl(long dpid) {
Jonathan Hartbd766972013-02-22 15:13:03 -0800217 //if (!zookeeperEnabled) return;
Jonathan Hart57080fb2013-02-21 10:55:46 -0800218
Jonathan Hartc6eee9e2013-02-18 14:58:27 -0800219 String dpidStr = HexString.toHexString(dpid);
220
221 LeaderLatch latch = switchLatches.get(dpidStr);
Jonathan Hartbd181b62013-02-17 16:05:38 -0800222 if (latch == null) {
Jonathan Hartc6eee9e2013-02-18 14:58:27 -0800223 log.debug("Trying to release mastership for switch we are not contesting");
Jonathan Hartbd181b62013-02-17 16:05:38 -0800224 return;
225 }
226
227 try {
228 latch.close();
229 } catch (IOException e) {
Jonathan Hart1be46262013-02-20 16:43:51 -0800230 //I think it's OK not to do anything here. Either the node got deleted correctly,
231 //or the connection went down and the node got deleted.
232 } finally {
233 switchLatches.remove(dpidStr);
234 switchCallbacks.remove(dpidStr);
Jonathan Hartbd181b62013-02-17 16:05:38 -0800235 }
236 }
237
238 @Override
Jonathan Hartd82f20d2013-02-21 18:04:24 -0800239 public boolean hasControl(long dpid) {
Jonathan Hartbd766972013-02-22 15:13:03 -0800240 //if (!zookeeperEnabled) return false;
Jonathan Hart57080fb2013-02-21 10:55:46 -0800241
Jonathan Hartbd181b62013-02-17 16:05:38 -0800242 LeaderLatch latch = switchLatches.get(HexString.toHexString(dpid));
243
244 if (latch == null) {
245 log.warn("No leader latch for dpid {}", HexString.toHexString(dpid));
246 return false;
247 }
248
Jonathan Hartbd181b62013-02-17 16:05:38 -0800249 try {
Jonathan Hartbd766972013-02-22 15:13:03 -0800250 return latch.getLeader().getId().equals(controllerId);
Jonathan Hartbd181b62013-02-17 16:05:38 -0800251 } catch (Exception e) {
252 //TODO swallow exception?
253 return false;
254 }
255 }
256
257 @Override
258 public void setMastershipId(String id) {
Jonathan Hartbd766972013-02-22 15:13:03 -0800259 //TODO remove this method if not needed
260 //controllerId = id;
Jonathan Hartbd181b62013-02-17 16:05:38 -0800261 }
262
263 @Override
264 public String getMastershipId() {
Jonathan Hartbd766972013-02-22 15:13:03 -0800265 return controllerId;
Jonathan Hartbd181b62013-02-17 16:05:38 -0800266 }
267
Jonathan Hartedd6a442013-02-20 15:22:06 -0800268 @Override
Jonathan Hart57080fb2013-02-21 10:55:46 -0800269 public Collection<String> getAllControllers() throws RegistryException {
Jonathan Hartbd766972013-02-22 15:13:03 -0800270 //if (!zookeeperEnabled) return null;
Jonathan Hart57080fb2013-02-21 10:55:46 -0800271
Jonathan Hartedd6a442013-02-20 15:22:06 -0800272 log.debug("Getting all controllers");
Jonathan Hart1be46262013-02-20 16:43:51 -0800273
Jonathan Hartedd6a442013-02-20 15:22:06 -0800274 List<String> controllers = new ArrayList<String>();
275 for (ChildData data : controllerCache.getCurrentData()){
276
277 String d = null;
278 try {
279 d = new String(data.getData(), "UTF-8");
280 } catch (UnsupportedEncodingException e) {
Jonathan Hart57080fb2013-02-21 10:55:46 -0800281 throw new RegistryException("Error encoding string", e);
Jonathan Hartedd6a442013-02-20 15:22:06 -0800282 }
283
284 controllers.add(d);
285 }
286 return controllers;
287 }
288
289 @Override
Jonathan Hart57080fb2013-02-21 10:55:46 -0800290 public void registerController(String id) throws RegistryException {
Jonathan Hartbd766972013-02-22 15:13:03 -0800291 //if (!zookeeperEnabled) return;
Jonathan Hartd10008d2013-02-23 17:04:08 -0800292 if (controllerId != null) {
293 throw new RegistryException(
294 "Controller already registered with id " + controllerId);
295 }
Jonathan Hartbd766972013-02-22 15:13:03 -0800296
297 controllerId = id;
Jonathan Hart57080fb2013-02-21 10:55:46 -0800298
Jonathan Hartd10008d2013-02-23 17:04:08 -0800299 byte bytes[] = id.getBytes(Charsets.UTF_8);
300 /*byte bytes[] = null;
Jonathan Hartedd6a442013-02-20 15:22:06 -0800301 try {
302 bytes = id.getBytes("UTF-8");
303 } catch (UnsupportedEncodingException e1) {
Jonathan Hart57080fb2013-02-21 10:55:46 -0800304 throw new RegistryException("Error encoding string", e1);
Jonathan Hartd10008d2013-02-23 17:04:08 -0800305 }*/
Jonathan Hartedd6a442013-02-20 15:22:06 -0800306
307 String path = controllerPath + "/" + id;
308
309 log.info("Registering controller with id {}", id);
310
Jonathan Hart57080fb2013-02-21 10:55:46 -0800311 //Create ephemeral node in controller registry
Jonathan Hartedd6a442013-02-20 15:22:06 -0800312 try {
313 client.create().withProtection().withMode(CreateMode.EPHEMERAL)
314 .forPath(path, bytes);
315 } catch (Exception e) {
Jonathan Hart57080fb2013-02-21 10:55:46 -0800316 throw new RegistryException("Error contacting the Zookeeper service", e);
Jonathan Hartedd6a442013-02-20 15:22:06 -0800317 }
318 }
319
320 @Override
Jonathan Hart57080fb2013-02-21 10:55:46 -0800321 public String getControllerForSwitch(long dpid) throws RegistryException {
Jonathan Hartbd766972013-02-22 15:13:03 -0800322 //if (!zookeeperEnabled) return null;
Jonathan Hartedd6a442013-02-20 15:22:06 -0800323 // TODO Work out how we should store this controller/switch data.
324 // The leader latch might be a index to the /controllers collections
325 // which holds more info on the controller (how to talk to it for example).
326
327
328 String strDpid = HexString.toHexString(dpid);
329 LeaderLatch latch = switchLatches.get(strDpid);
330
331 if (latch == null){
332 log.warn("Tried to get controller for non-existent switch");
333 return null;
334 }
335
336 Participant leader = null;
337 try {
338 leader = latch.getLeader();
339 } catch (Exception e) {
Jonathan Hart57080fb2013-02-21 10:55:46 -0800340 throw new RegistryException("Error contacting the Zookeeper service", e);
Jonathan Hartedd6a442013-02-20 15:22:06 -0800341 }
342
343 return leader.getId();
344 }
345
346 @Override
347 public Collection<Long> getSwitchesControlledByController(String controllerId) {
Jonathan Hart3d7730a2013-02-22 11:51:17 -0800348 //TODO remove this if not needed
Jonathan Hartbd766972013-02-22 15:13:03 -0800349 throw new RuntimeException("Not yet implemented");
Jonathan Hartedd6a442013-02-20 15:22:06 -0800350 }
Jonathan Hartbd181b62013-02-17 16:05:38 -0800351
Jonathan Hartd82f20d2013-02-21 18:04:24 -0800352
353 @Override
Jonathan Hart3d7730a2013-02-22 11:51:17 -0800354 public Map<String, List<ControllerRegistryEntry>> getAllSwitches() {
355 Map<String, List<ControllerRegistryEntry>> data =
356 new HashMap<String, List<ControllerRegistryEntry>>();
357
358 for (Map.Entry<String, PathChildrenCache> entry : switchPathCaches.entrySet()){
359 List<ControllerRegistryEntry> contendingControllers =
360 new ArrayList<ControllerRegistryEntry>();
361
362 if (entry.getValue().getCurrentData().size() < 1){
363 log.info("Switch entry with no leader elections: {}", entry.getKey());
364 continue;
365 }
366
367 for (ChildData d : entry.getValue().getCurrentData()) {
368 /*
369 if (d.getPath().length() < 1){
370 log.info("Switch entry with no leader elections: {}", d.getPath());
371 continue;
372 }
373 */
374
Jonathan Hartd10008d2013-02-23 17:04:08 -0800375 /*String controllerId = null;
Jonathan Hart3d7730a2013-02-22 11:51:17 -0800376 try {
377 controllerId = new String(d.getData(), "UTF-8");
378 } catch (UnsupportedEncodingException e) {
379 log.warn("Encoding exception: {}", e.getMessage());
Jonathan Hartd10008d2013-02-23 17:04:08 -0800380 }*/
381 String controllerId = new String(d.getData(), Charsets.UTF_8);
Jonathan Hart3d7730a2013-02-22 11:51:17 -0800382
383 String[] splitted = d.getPath().split("-");
384 int sequenceNumber = Integer.parseInt(splitted[splitted.length - 1]);
385
386 contendingControllers.add(new ControllerRegistryEntry(controllerId, sequenceNumber));
387 }
388
389 Collections.sort(contendingControllers);
390 data.put(entry.getKey(), contendingControllers);
391 }
392 return data;
Jonathan Hartd82f20d2013-02-21 18:04:24 -0800393 }
394
Jonathan Hartbd181b62013-02-17 16:05:38 -0800395 /*
396 * IFloodlightModule
397 */
398
Umesh Krishnaswamyb56bb292013-02-12 20:28:27 -0800399 @Override
400 public Collection<Class<? extends IFloodlightService>> getModuleServices() {
Jonathan Hartedd6a442013-02-20 15:22:06 -0800401 Collection<Class<? extends IFloodlightService>> l =
402 new ArrayList<Class<? extends IFloodlightService>>();
Jonathan Hartd82f20d2013-02-21 18:04:24 -0800403 l.add(IControllerRegistryService.class);
Umesh Krishnaswamyb56bb292013-02-12 20:28:27 -0800404 return l;
405 }
406
407 @Override
408 public Map<Class<? extends IFloodlightService>, IFloodlightService> getServiceImpls() {
409 Map<Class<? extends IFloodlightService>, IFloodlightService> m =
410 new HashMap<Class<? extends IFloodlightService>, IFloodlightService>();
Jonathan Hartd82f20d2013-02-21 18:04:24 -0800411 m.put(IControllerRegistryService.class, this);
Umesh Krishnaswamyb56bb292013-02-12 20:28:27 -0800412 return m;
413 }
414
415 @Override
416 public Collection<Class<? extends IFloodlightService>> getModuleDependencies() {
Jonathan Hart3d7730a2013-02-22 11:51:17 -0800417 Collection<Class<? extends IFloodlightService>> l =
418 new ArrayList<Class<? extends IFloodlightService>>();
419 l.add(IRestApiService.class);
420 return l;
Umesh Krishnaswamyb56bb292013-02-12 20:28:27 -0800421 }
422
423 @Override
424 public void init (FloodlightModuleContext context) throws FloodlightModuleException {
Jonathan Hart57080fb2013-02-21 10:55:46 -0800425
Jonathan Hartbd766972013-02-22 15:13:03 -0800426 log.info("Initialising the Zookeeper Registry - Zookeeper connection required");
427
Jonathan Hart3d7730a2013-02-22 11:51:17 -0800428 restApi = context.getServiceImpl(IRestApiService.class);
429
Jonathan Hartbd766972013-02-22 15:13:03 -0800430 //We have a config option that determines whether we try and connect to
431 //zookeeper or not. By default zookeeper connection is disabled. When we don't
432 //have a zookeeper connection we act as though we are the only server in the
433 //cluster, i.e. all control requests will succeed.
434 /*Map<String, String> configOptions = context.getConfigParams(this);
Jonathan Hart57080fb2013-02-21 10:55:46 -0800435 String enableZookeeper = configOptions.get("enableZookeeper");
436 if (enableZookeeper != null) {
Jonathan Hartbd766972013-02-22 15:13:03 -0800437 log.info("Enabling Zookeeper connection");
438 zookeeperEnabled = true;
Jonathan Hart57080fb2013-02-21 10:55:46 -0800439 }
440 else {
Jonathan Hartbd766972013-02-22 15:13:03 -0800441 log.info("Zookeeper connectivity is disabled - running in standalone mode");
Jonathan Hart57080fb2013-02-21 10:55:46 -0800442 return;
Jonathan Hartbd766972013-02-22 15:13:03 -0800443 }*/
Jonathan Hart57080fb2013-02-21 10:55:46 -0800444
Jonathan Hartbd766972013-02-22 15:13:03 -0800445 /*
Jonathan Hartbd181b62013-02-17 16:05:38 -0800446 try {
447 String localHostname = java.net.InetAddress.getLocalHost().getHostName();
Jonathan Hartbd766972013-02-22 15:13:03 -0800448 controllerId = localHostname;
449 log.debug("Setting controller id to {}", controllerId);
Jonathan Hartbd181b62013-02-17 16:05:38 -0800450 } catch (UnknownHostException e) {
451 // TODO Handle this exception
452 e.printStackTrace();
Jonathan Hartbd766972013-02-22 15:13:03 -0800453 }*/
Jonathan Hartbd181b62013-02-17 16:05:38 -0800454
455 switchLatches = new HashMap<String, LeaderLatch>();
Jonathan Hartd82f20d2013-02-21 18:04:24 -0800456 switchCallbacks = new HashMap<String, ControlChangeCallback>();
Jonathan Hart3d7730a2013-02-22 11:51:17 -0800457 switchPathCaches = new HashMap<String, PathChildrenCache>();
Jonathan Hartbd181b62013-02-17 16:05:38 -0800458
Jonathan Hart3d7730a2013-02-22 11:51:17 -0800459 RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000, 3);
Jonathan Hartcc957a02013-02-26 10:39:04 -0800460 client = CuratorFrameworkFactory.newClient(connectionString,
461 sessionTimeout, connectionTimeout, retryPolicy);
Jonathan Hartbd181b62013-02-17 16:05:38 -0800462
463 client.start();
464
465 client = client.usingNamespace(namespace);
466
Jonathan Hart3d7730a2013-02-22 11:51:17 -0800467 //Put some data in for testing
Jonathan Hartbd766972013-02-22 15:13:03 -0800468 /*
Jonathan Hart3d7730a2013-02-22 11:51:17 -0800469 try {
Jonathan Hartbd766972013-02-22 15:13:03 -0800470 registerController("zookeeperController");
Jonathan Hart3d7730a2013-02-22 11:51:17 -0800471 requestControl(2L, null);
472 } catch (RegistryException e1) {
473 // TODO Auto-generated catch block
474 e1.printStackTrace();
Jonathan Hartbd766972013-02-22 15:13:03 -0800475 }*/
Jonathan Hart3d7730a2013-02-22 11:51:17 -0800476
Jonathan Hartedd6a442013-02-20 15:22:06 -0800477 controllerCache = new PathChildrenCache(client, controllerPath, true);
Jonathan Hart3d7730a2013-02-22 11:51:17 -0800478 switchCache = new PathChildrenCache(client, switchLatchesPath, true);
479 switchCache.getListenable().addListener(switchPathCacheListener);
Jonathan Hartedd6a442013-02-20 15:22:06 -0800480
481 try {
482 controllerCache.start(StartMode.BUILD_INITIAL_CACHE);
Jonathan Hart3d7730a2013-02-22 11:51:17 -0800483
484 //Don't prime the cache, we want a notification for each child node in the path
485 switchCache.start(StartMode.NORMAL);
Jonathan Hartedd6a442013-02-20 15:22:06 -0800486 } catch (Exception e) {
487 // TODO Auto-generated catch block
488 e.printStackTrace();
489 }
Umesh Krishnaswamyb56bb292013-02-12 20:28:27 -0800490 }
491
492 @Override
493 public void startUp (FloodlightModuleContext context) {
Jonathan Hart3d7730a2013-02-22 11:51:17 -0800494 restApi.addRestletRoutable(new RegistryWebRoutable());
Umesh Krishnaswamyb56bb292013-02-12 20:28:27 -0800495 }
Jonathan Hartd82f20d2013-02-21 18:04:24 -0800496
Umesh Krishnaswamyb56bb292013-02-12 20:28:27 -0800497}