blob: 16954516f67bdc5a769550094ffec354a5fc42ce [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 Hartbd766972013-02-22 15:13:03 -080063 //protected boolean zookeeperEnabled = false;
Jonathan Hart57080fb2013-02-21 10:55:46 -080064
Jonathan Hartbd181b62013-02-17 16:05:38 -080065 protected class ParamaterizedCuratorWatcher implements CuratorWatcher {
66 private String dpid;
Jonathan Hartc6eee9e2013-02-18 14:58:27 -080067 private boolean isLeader = false;
Jonathan Hartbd181b62013-02-17 16:05:38 -080068 private String latchPath;
69
70 public ParamaterizedCuratorWatcher(String dpid, String latchPath){
71 this.dpid = dpid;
72 this.latchPath = latchPath;
73 }
74
75 @Override
Jonathan Hartedd6a442013-02-20 15:22:06 -080076 public synchronized void process(WatchedEvent event) throws Exception {
Jonathan Hartbd181b62013-02-17 16:05:38 -080077 log.debug("Watch Event: {}", event);
78
79 LeaderLatch latch = switchLatches.get(dpid);
80
Jonathan Hartc6eee9e2013-02-18 14:58:27 -080081 if (event.getState() == KeeperState.Disconnected){
82 if (isLeader) {
83 log.debug("Disconnected while leader - lost leadership for {}", dpid);
84
85 isLeader = false;
Jonathan Hart3d7730a2013-02-22 11:51:17 -080086 ControlChangeCallback cb = switchCallbacks.get(dpid);
87 if (cb != null) {
88 //Allow callback to be null if the requester doesn't want a callback
89 cb.controlChanged(HexString.toLong(dpid), false);
90 }
Jonathan Hartc6eee9e2013-02-18 14:58:27 -080091 }
92 return;
93 }
Jonathan Hartbd181b62013-02-17 16:05:38 -080094
Jonathan Hartc6eee9e2013-02-18 14:58:27 -080095 try {
Jonathan Hartedd6a442013-02-20 15:22:06 -080096
Jonathan Hartc6eee9e2013-02-18 14:58:27 -080097 Participant leader = latch.getLeader();
98
Jonathan Hartbd766972013-02-22 15:13:03 -080099 if (leader.getId().equals(controllerId) && !isLeader){
Jonathan Hartc6eee9e2013-02-18 14:58:27 -0800100 log.debug("Became leader for {}", dpid);
101
102 isLeader = true;
Jonathan Hartd82f20d2013-02-21 18:04:24 -0800103 switchCallbacks.get(dpid).controlChanged(HexString.toLong(dpid), true);
Jonathan Hartc6eee9e2013-02-18 14:58:27 -0800104 }
Jonathan Hartbd766972013-02-22 15:13:03 -0800105 else if (!leader.getId().equals(controllerId) && isLeader){
Jonathan Hartc6eee9e2013-02-18 14:58:27 -0800106 log.debug("Lost leadership for {}", dpid);
107
108 isLeader = false;
Jonathan Hartd82f20d2013-02-21 18:04:24 -0800109 switchCallbacks.get(dpid).controlChanged(HexString.toLong(dpid), false);
Jonathan Hartc6eee9e2013-02-18 14:58:27 -0800110 }
111 } catch (Exception e){
112 if (isLeader){
113 log.debug("Exception checking leadership status. Assume leadship lost for {}",
114 dpid);
115
116 isLeader = false;
Jonathan Hartd82f20d2013-02-21 18:04:24 -0800117 switchCallbacks.get(dpid).controlChanged(HexString.toLong(dpid), false);
Jonathan Hartc6eee9e2013-02-18 14:58:27 -0800118 }
Jonathan Hartbd181b62013-02-17 16:05:38 -0800119 }
120
121 client.getChildren().usingWatcher(this).inBackground().forPath(latchPath);
122 //client.getChildren().usingWatcher(this).forPath(latchPath);
123 }
Jonathan Hartc6eee9e2013-02-18 14:58:27 -0800124 }
Jonathan Hart3d7730a2013-02-22 11:51:17 -0800125
126
127 /*
128 * Listens for changes to the switch znodes in Zookeeper. This maintains the second level of
129 * PathChildrenCaches that hold the controllers contending for each switch - there's one for
130 * each switch.
131 */
132 PathChildrenCacheListener switchPathCacheListener = new PathChildrenCacheListener() {
133 @Override
134 public void childEvent(CuratorFramework client,
135 PathChildrenCacheEvent event) throws Exception {
136 // TODO Auto-generated method stub
137 log.debug("Root switch path cache got {} event", event.getType());
138
139 String strSwitch = null;
140 if (event.getData() != null){
141 log.debug("Event path {}", event.getData().getPath());
142 String[] splitted = event.getData().getPath().split("/");
143 strSwitch = splitted[splitted.length - 1];
144 log.debug("Switch name is {}", strSwitch);
145 }
146
147 switch (event.getType()){
148 case CHILD_ADDED:
149 case CHILD_UPDATED:
150 //Check we have a PathChildrenCache for this child, add one if not
151 if (switchPathCaches.get(strSwitch) == null){
152 PathChildrenCache pc = new PathChildrenCache(client,
153 event.getData().getPath(), true);
154 pc.start(StartMode.NORMAL);
155 switchPathCaches.put(strSwitch, pc);
156 }
157 break;
158 case CHILD_REMOVED:
159 //Remove our PathChildrenCache for this child
160 PathChildrenCache pc = switchPathCaches.remove(strSwitch);
161 pc.close();
162 break;
163 default:
164 //All other events are connection status events. We need to do anything
165 //as the path cache handles these on its own.
166 break;
167 }
168
169 }
170 };
Jonathan Hartedd6a442013-02-20 15:22:06 -0800171
Jonathan Hartbd181b62013-02-17 16:05:38 -0800172
173 @Override
Jonathan Hart3d7730a2013-02-22 11:51:17 -0800174 public void requestControl(long dpid, ControlChangeCallback cb) throws RegistryException {
Jonathan Hartbd766972013-02-22 15:13:03 -0800175 /*
176 if (!zookeeperEnabled) {
177 //If zookeeper connection is disabled all control requests succeed immediately
178 if (cb != null){
179 cb.controlChanged(dpid, true);
180 }
181 return;
182 }*/
Jonathan Hartc6eee9e2013-02-18 14:58:27 -0800183
Jonathan Hartbd766972013-02-22 15:13:03 -0800184 if (controllerId == null){
185 throw new RuntimeException("Must register a controller before calling requestControl");
Jonathan Hartbd181b62013-02-17 16:05:38 -0800186 }
187
188 String dpidStr = HexString.toHexString(dpid);
189 String latchPath = switchLatchesPath + "/" + dpidStr;
190
Jonathan Hartc6eee9e2013-02-18 14:58:27 -0800191 if (switchLatches.get(dpidStr) != null){
192 throw new RuntimeException("Leader election for switch " + dpidStr +
193 "is already running");
194 }
195
Jonathan Hartbd766972013-02-22 15:13:03 -0800196 LeaderLatch latch = new LeaderLatch(client, latchPath, controllerId);
Jonathan Hartbd181b62013-02-17 16:05:38 -0800197 switchLatches.put(dpidStr, latch);
Jonathan Hartbd181b62013-02-17 16:05:38 -0800198 switchCallbacks.put(dpidStr, cb);
199
200 try {
201 //client.getChildren().usingWatcher(watcher).inBackground().forPath(singleLatchPath);
202 client.getChildren().usingWatcher(
203 new ParamaterizedCuratorWatcher(dpidStr, latchPath))
204 .inBackground().forPath(latchPath);
205 latch.start();
206 } catch (Exception e) {
Jonathan Hartc6eee9e2013-02-18 14:58:27 -0800207 log.warn("Error starting leader latch: {}", e.getMessage());
Jonathan Hart3d7730a2013-02-22 11:51:17 -0800208 throw new RegistryException("Error starting leader latch for " + dpidStr, e);
Jonathan Hartbd181b62013-02-17 16:05:38 -0800209 }
210
211 }
212
213 @Override
Jonathan Hartd82f20d2013-02-21 18:04:24 -0800214 public void releaseControl(long dpid) {
Jonathan Hartbd766972013-02-22 15:13:03 -0800215 //if (!zookeeperEnabled) return;
Jonathan Hart57080fb2013-02-21 10:55:46 -0800216
Jonathan Hartc6eee9e2013-02-18 14:58:27 -0800217 String dpidStr = HexString.toHexString(dpid);
218
219 LeaderLatch latch = switchLatches.get(dpidStr);
Jonathan Hartbd181b62013-02-17 16:05:38 -0800220 if (latch == null) {
Jonathan Hartc6eee9e2013-02-18 14:58:27 -0800221 log.debug("Trying to release mastership for switch we are not contesting");
Jonathan Hartbd181b62013-02-17 16:05:38 -0800222 return;
223 }
224
225 try {
226 latch.close();
227 } catch (IOException e) {
Jonathan Hart1be46262013-02-20 16:43:51 -0800228 //I think it's OK not to do anything here. Either the node got deleted correctly,
229 //or the connection went down and the node got deleted.
230 } finally {
231 switchLatches.remove(dpidStr);
232 switchCallbacks.remove(dpidStr);
Jonathan Hartbd181b62013-02-17 16:05:38 -0800233 }
234 }
235
236 @Override
Jonathan Hartd82f20d2013-02-21 18:04:24 -0800237 public boolean hasControl(long dpid) {
Jonathan Hartbd766972013-02-22 15:13:03 -0800238 //if (!zookeeperEnabled) return false;
Jonathan Hart57080fb2013-02-21 10:55:46 -0800239
Jonathan Hartbd181b62013-02-17 16:05:38 -0800240 LeaderLatch latch = switchLatches.get(HexString.toHexString(dpid));
241
242 if (latch == null) {
243 log.warn("No leader latch for dpid {}", HexString.toHexString(dpid));
244 return false;
245 }
246
Jonathan Hartbd181b62013-02-17 16:05:38 -0800247 try {
Jonathan Hartbd766972013-02-22 15:13:03 -0800248 return latch.getLeader().getId().equals(controllerId);
Jonathan Hartbd181b62013-02-17 16:05:38 -0800249 } catch (Exception e) {
250 //TODO swallow exception?
251 return false;
252 }
253 }
254
255 @Override
256 public void setMastershipId(String id) {
Jonathan Hartbd766972013-02-22 15:13:03 -0800257 //TODO remove this method if not needed
258 //controllerId = id;
Jonathan Hartbd181b62013-02-17 16:05:38 -0800259 }
260
261 @Override
262 public String getMastershipId() {
Jonathan Hartbd766972013-02-22 15:13:03 -0800263 return controllerId;
Jonathan Hartbd181b62013-02-17 16:05:38 -0800264 }
265
Jonathan Hartedd6a442013-02-20 15:22:06 -0800266 @Override
Jonathan Hart57080fb2013-02-21 10:55:46 -0800267 public Collection<String> getAllControllers() throws RegistryException {
Jonathan Hartbd766972013-02-22 15:13:03 -0800268 //if (!zookeeperEnabled) return null;
Jonathan Hart57080fb2013-02-21 10:55:46 -0800269
Jonathan Hartedd6a442013-02-20 15:22:06 -0800270 log.debug("Getting all controllers");
Jonathan Hart1be46262013-02-20 16:43:51 -0800271
Jonathan Hartedd6a442013-02-20 15:22:06 -0800272 List<String> controllers = new ArrayList<String>();
273 for (ChildData data : controllerCache.getCurrentData()){
274
275 String d = null;
276 try {
277 d = new String(data.getData(), "UTF-8");
278 } catch (UnsupportedEncodingException e) {
Jonathan Hart57080fb2013-02-21 10:55:46 -0800279 throw new RegistryException("Error encoding string", e);
Jonathan Hartedd6a442013-02-20 15:22:06 -0800280 }
281
282 controllers.add(d);
283 }
284 return controllers;
285 }
286
287 @Override
Jonathan Hart57080fb2013-02-21 10:55:46 -0800288 public void registerController(String id) throws RegistryException {
Jonathan Hartbd766972013-02-22 15:13:03 -0800289 //if (!zookeeperEnabled) return;
Jonathan Hartd10008d2013-02-23 17:04:08 -0800290 if (controllerId != null) {
291 throw new RegistryException(
292 "Controller already registered with id " + controllerId);
293 }
Jonathan Hartbd766972013-02-22 15:13:03 -0800294
295 controllerId = id;
Jonathan Hart57080fb2013-02-21 10:55:46 -0800296
Jonathan Hartd10008d2013-02-23 17:04:08 -0800297 byte bytes[] = id.getBytes(Charsets.UTF_8);
298 /*byte bytes[] = null;
Jonathan Hartedd6a442013-02-20 15:22:06 -0800299 try {
300 bytes = id.getBytes("UTF-8");
301 } catch (UnsupportedEncodingException e1) {
Jonathan Hart57080fb2013-02-21 10:55:46 -0800302 throw new RegistryException("Error encoding string", e1);
Jonathan Hartd10008d2013-02-23 17:04:08 -0800303 }*/
Jonathan Hartedd6a442013-02-20 15:22:06 -0800304
305 String path = controllerPath + "/" + id;
306
307 log.info("Registering controller with id {}", id);
308
Jonathan Hart57080fb2013-02-21 10:55:46 -0800309 //Create ephemeral node in controller registry
Jonathan Hartedd6a442013-02-20 15:22:06 -0800310 try {
311 client.create().withProtection().withMode(CreateMode.EPHEMERAL)
312 .forPath(path, bytes);
313 } catch (Exception e) {
Jonathan Hart57080fb2013-02-21 10:55:46 -0800314 throw new RegistryException("Error contacting the Zookeeper service", e);
Jonathan Hartedd6a442013-02-20 15:22:06 -0800315 }
316 }
317
318 @Override
Jonathan Hart57080fb2013-02-21 10:55:46 -0800319 public String getControllerForSwitch(long dpid) throws RegistryException {
Jonathan Hartbd766972013-02-22 15:13:03 -0800320 //if (!zookeeperEnabled) return null;
Jonathan Hartedd6a442013-02-20 15:22:06 -0800321 // TODO Work out how we should store this controller/switch data.
322 // The leader latch might be a index to the /controllers collections
323 // which holds more info on the controller (how to talk to it for example).
324
325
326 String strDpid = HexString.toHexString(dpid);
327 LeaderLatch latch = switchLatches.get(strDpid);
328
329 if (latch == null){
330 log.warn("Tried to get controller for non-existent switch");
331 return null;
332 }
333
334 Participant leader = null;
335 try {
336 leader = latch.getLeader();
337 } catch (Exception e) {
Jonathan Hart57080fb2013-02-21 10:55:46 -0800338 throw new RegistryException("Error contacting the Zookeeper service", e);
Jonathan Hartedd6a442013-02-20 15:22:06 -0800339 }
340
341 return leader.getId();
342 }
343
344 @Override
345 public Collection<Long> getSwitchesControlledByController(String controllerId) {
Jonathan Hart3d7730a2013-02-22 11:51:17 -0800346 //TODO remove this if not needed
Jonathan Hartbd766972013-02-22 15:13:03 -0800347 throw new RuntimeException("Not yet implemented");
Jonathan Hartedd6a442013-02-20 15:22:06 -0800348 }
Jonathan Hartbd181b62013-02-17 16:05:38 -0800349
Jonathan Hartd82f20d2013-02-21 18:04:24 -0800350
351 @Override
Jonathan Hart3d7730a2013-02-22 11:51:17 -0800352 public Map<String, List<ControllerRegistryEntry>> getAllSwitches() {
353 Map<String, List<ControllerRegistryEntry>> data =
354 new HashMap<String, List<ControllerRegistryEntry>>();
355
356 for (Map.Entry<String, PathChildrenCache> entry : switchPathCaches.entrySet()){
357 List<ControllerRegistryEntry> contendingControllers =
358 new ArrayList<ControllerRegistryEntry>();
359
360 if (entry.getValue().getCurrentData().size() < 1){
361 log.info("Switch entry with no leader elections: {}", entry.getKey());
362 continue;
363 }
364
365 for (ChildData d : entry.getValue().getCurrentData()) {
366 /*
367 if (d.getPath().length() < 1){
368 log.info("Switch entry with no leader elections: {}", d.getPath());
369 continue;
370 }
371 */
372
Jonathan Hartd10008d2013-02-23 17:04:08 -0800373 /*String controllerId = null;
Jonathan Hart3d7730a2013-02-22 11:51:17 -0800374 try {
375 controllerId = new String(d.getData(), "UTF-8");
376 } catch (UnsupportedEncodingException e) {
377 log.warn("Encoding exception: {}", e.getMessage());
Jonathan Hartd10008d2013-02-23 17:04:08 -0800378 }*/
379 String controllerId = new String(d.getData(), Charsets.UTF_8);
Jonathan Hart3d7730a2013-02-22 11:51:17 -0800380
381 String[] splitted = d.getPath().split("-");
382 int sequenceNumber = Integer.parseInt(splitted[splitted.length - 1]);
383
384 contendingControllers.add(new ControllerRegistryEntry(controllerId, sequenceNumber));
385 }
386
387 Collections.sort(contendingControllers);
388 data.put(entry.getKey(), contendingControllers);
389 }
390 return data;
Jonathan Hartd82f20d2013-02-21 18:04:24 -0800391 }
392
Jonathan Hartbd181b62013-02-17 16:05:38 -0800393 /*
394 * IFloodlightModule
395 */
396
Umesh Krishnaswamyb56bb292013-02-12 20:28:27 -0800397 @Override
398 public Collection<Class<? extends IFloodlightService>> getModuleServices() {
Jonathan Hartedd6a442013-02-20 15:22:06 -0800399 Collection<Class<? extends IFloodlightService>> l =
400 new ArrayList<Class<? extends IFloodlightService>>();
Jonathan Hartd82f20d2013-02-21 18:04:24 -0800401 l.add(IControllerRegistryService.class);
Umesh Krishnaswamyb56bb292013-02-12 20:28:27 -0800402 return l;
403 }
404
405 @Override
406 public Map<Class<? extends IFloodlightService>, IFloodlightService> getServiceImpls() {
407 Map<Class<? extends IFloodlightService>, IFloodlightService> m =
408 new HashMap<Class<? extends IFloodlightService>, IFloodlightService>();
Jonathan Hartd82f20d2013-02-21 18:04:24 -0800409 m.put(IControllerRegistryService.class, this);
Umesh Krishnaswamyb56bb292013-02-12 20:28:27 -0800410 return m;
411 }
412
413 @Override
414 public Collection<Class<? extends IFloodlightService>> getModuleDependencies() {
Jonathan Hart3d7730a2013-02-22 11:51:17 -0800415 Collection<Class<? extends IFloodlightService>> l =
416 new ArrayList<Class<? extends IFloodlightService>>();
417 l.add(IRestApiService.class);
418 return l;
Umesh Krishnaswamyb56bb292013-02-12 20:28:27 -0800419 }
420
421 @Override
422 public void init (FloodlightModuleContext context) throws FloodlightModuleException {
Jonathan Hart57080fb2013-02-21 10:55:46 -0800423
Jonathan Hartbd766972013-02-22 15:13:03 -0800424 log.info("Initialising the Zookeeper Registry - Zookeeper connection required");
425
Jonathan Hart3d7730a2013-02-22 11:51:17 -0800426 restApi = context.getServiceImpl(IRestApiService.class);
427
Jonathan Hartbd766972013-02-22 15:13:03 -0800428 //We have a config option that determines whether we try and connect to
429 //zookeeper or not. By default zookeeper connection is disabled. When we don't
430 //have a zookeeper connection we act as though we are the only server in the
431 //cluster, i.e. all control requests will succeed.
432 /*Map<String, String> configOptions = context.getConfigParams(this);
Jonathan Hart57080fb2013-02-21 10:55:46 -0800433 String enableZookeeper = configOptions.get("enableZookeeper");
434 if (enableZookeeper != null) {
Jonathan Hartbd766972013-02-22 15:13:03 -0800435 log.info("Enabling Zookeeper connection");
436 zookeeperEnabled = true;
Jonathan Hart57080fb2013-02-21 10:55:46 -0800437 }
438 else {
Jonathan Hartbd766972013-02-22 15:13:03 -0800439 log.info("Zookeeper connectivity is disabled - running in standalone mode");
Jonathan Hart57080fb2013-02-21 10:55:46 -0800440 return;
Jonathan Hartbd766972013-02-22 15:13:03 -0800441 }*/
Jonathan Hart57080fb2013-02-21 10:55:46 -0800442
Jonathan Hartbd766972013-02-22 15:13:03 -0800443 /*
Jonathan Hartbd181b62013-02-17 16:05:38 -0800444 try {
445 String localHostname = java.net.InetAddress.getLocalHost().getHostName();
Jonathan Hartbd766972013-02-22 15:13:03 -0800446 controllerId = localHostname;
447 log.debug("Setting controller id to {}", controllerId);
Jonathan Hartbd181b62013-02-17 16:05:38 -0800448 } catch (UnknownHostException e) {
449 // TODO Handle this exception
450 e.printStackTrace();
Jonathan Hartbd766972013-02-22 15:13:03 -0800451 }*/
Jonathan Hartbd181b62013-02-17 16:05:38 -0800452
453 switchLatches = new HashMap<String, LeaderLatch>();
Jonathan Hartd82f20d2013-02-21 18:04:24 -0800454 switchCallbacks = new HashMap<String, ControlChangeCallback>();
Jonathan Hart3d7730a2013-02-22 11:51:17 -0800455 switchPathCaches = new HashMap<String, PathChildrenCache>();
Jonathan Hartbd181b62013-02-17 16:05:38 -0800456
Jonathan Hart3d7730a2013-02-22 11:51:17 -0800457 RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000, 3);
Jonathan Hartbd181b62013-02-17 16:05:38 -0800458 client = CuratorFrameworkFactory.newClient(connectionString, retryPolicy);
459
460 client.start();
461
462 client = client.usingNamespace(namespace);
463
Jonathan Hart3d7730a2013-02-22 11:51:17 -0800464 //Put some data in for testing
Jonathan Hartbd766972013-02-22 15:13:03 -0800465 /*
Jonathan Hart3d7730a2013-02-22 11:51:17 -0800466 try {
Jonathan Hartbd766972013-02-22 15:13:03 -0800467 registerController("zookeeperController");
Jonathan Hart3d7730a2013-02-22 11:51:17 -0800468 requestControl(2L, null);
469 } catch (RegistryException e1) {
470 // TODO Auto-generated catch block
471 e1.printStackTrace();
Jonathan Hartbd766972013-02-22 15:13:03 -0800472 }*/
Jonathan Hart3d7730a2013-02-22 11:51:17 -0800473
Jonathan Hartedd6a442013-02-20 15:22:06 -0800474 controllerCache = new PathChildrenCache(client, controllerPath, true);
Jonathan Hart3d7730a2013-02-22 11:51:17 -0800475 switchCache = new PathChildrenCache(client, switchLatchesPath, true);
476 switchCache.getListenable().addListener(switchPathCacheListener);
Jonathan Hartedd6a442013-02-20 15:22:06 -0800477
478 try {
479 controllerCache.start(StartMode.BUILD_INITIAL_CACHE);
Jonathan Hart3d7730a2013-02-22 11:51:17 -0800480
481 //Don't prime the cache, we want a notification for each child node in the path
482 switchCache.start(StartMode.NORMAL);
Jonathan Hartedd6a442013-02-20 15:22:06 -0800483 } catch (Exception e) {
484 // TODO Auto-generated catch block
485 e.printStackTrace();
486 }
Umesh Krishnaswamyb56bb292013-02-12 20:28:27 -0800487 }
488
489 @Override
490 public void startUp (FloodlightModuleContext context) {
Jonathan Hart3d7730a2013-02-22 11:51:17 -0800491 restApi.addRestletRoutable(new RegistryWebRoutable());
Umesh Krishnaswamyb56bb292013-02-12 20:28:27 -0800492 }
Jonathan Hartd82f20d2013-02-21 18:04:24 -0800493
Umesh Krishnaswamyb56bb292013-02-12 20:28:27 -0800494}