blob: 7d1420ac38f2f1c425dbadbe52b55265697fc1d7 [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;
Jonathan Hart89187372013-03-14 16:41:09 -070011import java.util.concurrent.ConcurrentHashMap;
Umesh Krishnaswamyb56bb292013-02-12 20:28:27 -080012
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 Hartedd6a442013-02-20 15:22:06 -080019import org.apache.zookeeper.CreateMode;
Jonathan Hartbd181b62013-02-17 16:05:38 -080020import org.openflow.util.HexString;
21import org.slf4j.Logger;
22import org.slf4j.LoggerFactory;
Umesh Krishnaswamyb56bb292013-02-12 20:28:27 -080023
Jonathan Hartd10008d2013-02-23 17:04:08 -080024import com.google.common.base.Charsets;
Jonathan Hartbd181b62013-02-17 16:05:38 -080025import com.netflix.curator.RetryPolicy;
26import com.netflix.curator.framework.CuratorFramework;
27import com.netflix.curator.framework.CuratorFrameworkFactory;
Jonathan Hartedd6a442013-02-20 15:22:06 -080028import com.netflix.curator.framework.recipes.cache.ChildData;
29import com.netflix.curator.framework.recipes.cache.PathChildrenCache;
30import com.netflix.curator.framework.recipes.cache.PathChildrenCache.StartMode;
Jonathan Hart3d7730a2013-02-22 11:51:17 -080031import com.netflix.curator.framework.recipes.cache.PathChildrenCacheEvent;
32import com.netflix.curator.framework.recipes.cache.PathChildrenCacheListener;
Jonathan Hartbd181b62013-02-17 16:05:38 -080033import com.netflix.curator.framework.recipes.leader.LeaderLatch;
Jonathan Hart0de09492013-03-13 14:37:21 -070034import com.netflix.curator.framework.recipes.leader.LeaderLatchEvent;
35import com.netflix.curator.framework.recipes.leader.LeaderLatchListener;
Jonathan Hartbd181b62013-02-17 16:05:38 -080036import 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 Hart7bf62172013-02-28 13:17:18 -080039/**
40 * A registry service that uses Zookeeper. All data is stored in Zookeeper,
41 * so this can be used as a global registry in a multi-node ONOS cluster.
42 * @author jono
43 *
44 */
Jonathan Hartbd766972013-02-22 15:13:03 -080045public class ZookeeperRegistry implements IFloodlightModule, IControllerRegistryService {
Jonathan Hartc6eee9e2013-02-18 14:58:27 -080046
Jonathan Hartbd766972013-02-22 15:13:03 -080047 protected static Logger log = LoggerFactory.getLogger(ZookeeperRegistry.class);
48 protected String controllerId = null;
Umesh Krishnaswamyb56bb292013-02-12 20:28:27 -080049
Jonathan Hart3d7730a2013-02-22 11:51:17 -080050 protected IRestApiService restApi;
51
Jonathan Hart7bf62172013-02-28 13:17:18 -080052 //This is the default, it's overwritten by the connectionString configuration parameter
Jonathan Hartbd181b62013-02-17 16:05:38 -080053 protected String connectionString = "localhost:2181";
Jonathan Hart3d7730a2013-02-22 11:51:17 -080054
Jonathan Hartbd181b62013-02-17 16:05:38 -080055 private final String namespace = "onos";
Jonathan Hartedd6a442013-02-20 15:22:06 -080056 private final String switchLatchesPath = "/switches";
Jonathan Hart3d7730a2013-02-22 11:51:17 -080057 private final String controllerPath = "/controllers";
Jonathan Hartbd181b62013-02-17 16:05:38 -080058
59 protected CuratorFramework client;
Jonathan Hartedd6a442013-02-20 15:22:06 -080060
Jonathan Hartedd6a442013-02-20 15:22:06 -080061 protected PathChildrenCache controllerCache;
Jonathan Hart3d7730a2013-02-22 11:51:17 -080062 protected PathChildrenCache switchCache;
Jonathan Hartbd181b62013-02-17 16:05:38 -080063
Jonathan Hart89187372013-03-14 16:41:09 -070064 protected ConcurrentHashMap<String, SwitchLeadershipData> switches;
Jonathan Hart3d7730a2013-02-22 11:51:17 -080065 protected Map<String, PathChildrenCache> switchPathCaches;
Jonathan Hartbd181b62013-02-17 16:05:38 -080066
Jonathan Hart97801ac2013-02-26 14:29:16 -080067 //Zookeeper performance-related configuration
Jonathan Hartcc957a02013-02-26 10:39:04 -080068 protected static final int sessionTimeout = 2000;
69 protected static final int connectionTimeout = 4000;
Jonathan Hart57080fb2013-02-21 10:55:46 -080070
Jonathan Hartbd181b62013-02-17 16:05:38 -080071
Jonathan Hart89187372013-03-14 16:41:09 -070072 protected class SwitchLeaderListener implements LeaderLatchListener{
Jonathan Hart0de09492013-03-13 14:37:21 -070073 String dpid;
74 LeaderLatch latch;
75
Jonathan Hart89187372013-03-14 16:41:09 -070076 public SwitchLeaderListener(String dpid, LeaderLatch latch){
Jonathan Hart0de09492013-03-13 14:37:21 -070077 this.dpid = dpid;
78 this.latch = latch;
79 }
80
81 @Override
82 public void leaderLatchEvent(CuratorFramework arg0,
83 LeaderLatchEvent arg1) {
Jonathan Hart89187372013-03-14 16:41:09 -070084 log.debug("Leadership changed for {}, now {}",
Jonathan Hart0de09492013-03-13 14:37:21 -070085 dpid, latch.hasLeadership());
86
Jonathan Hart89187372013-03-14 16:41:09 -070087 //Check that the leadership request is still active - the client
88 //may have since released the request or even begun another request
89 //(this is why we use == to check the object instance is the same)
90 SwitchLeadershipData swData = switches.get(dpid);
91 if (swData != null && swData.getLatch() == latch){
92 swData.getCallback().controlChanged(
93 HexString.toLong(dpid), latch.hasLeadership());
94 }
95 else {
96 log.debug("Latch for {} has changed", dpid);
97 }
Jonathan Hart0de09492013-03-13 14:37:21 -070098 }
99 }
100
Jonathan Hart3d7730a2013-02-22 11:51:17 -0800101
Jonathan Hart7bf62172013-02-28 13:17:18 -0800102 /**
103 * Listens for changes to the switch znodes in Zookeeper. This maintains
104 * the second level of PathChildrenCaches that hold the controllers
105 * contending for each switch - there's one for each switch.
Jonathan Hart3d7730a2013-02-22 11:51:17 -0800106 */
107 PathChildrenCacheListener switchPathCacheListener = new PathChildrenCacheListener() {
108 @Override
109 public void childEvent(CuratorFramework client,
110 PathChildrenCacheEvent event) throws Exception {
Jonathan Hart3d7730a2013-02-22 11:51:17 -0800111 log.debug("Root switch path cache got {} event", event.getType());
112
113 String strSwitch = null;
114 if (event.getData() != null){
115 log.debug("Event path {}", event.getData().getPath());
116 String[] splitted = event.getData().getPath().split("/");
117 strSwitch = splitted[splitted.length - 1];
118 log.debug("Switch name is {}", strSwitch);
119 }
120
121 switch (event.getType()){
122 case CHILD_ADDED:
123 case CHILD_UPDATED:
124 //Check we have a PathChildrenCache for this child, add one if not
125 if (switchPathCaches.get(strSwitch) == null){
126 PathChildrenCache pc = new PathChildrenCache(client,
127 event.getData().getPath(), true);
128 pc.start(StartMode.NORMAL);
129 switchPathCaches.put(strSwitch, pc);
130 }
131 break;
132 case CHILD_REMOVED:
133 //Remove our PathChildrenCache for this child
134 PathChildrenCache pc = switchPathCaches.remove(strSwitch);
135 pc.close();
136 break;
137 default:
138 //All other events are connection status events. We need to do anything
139 //as the path cache handles these on its own.
140 break;
141 }
142
143 }
144 };
Jonathan Hartedd6a442013-02-20 15:22:06 -0800145
Jonathan Hartbd181b62013-02-17 16:05:38 -0800146
147 @Override
Jonathan Hart3d7730a2013-02-22 11:51:17 -0800148 public void requestControl(long dpid, ControlChangeCallback cb) throws RegistryException {
Jonathan Hart7bf62172013-02-28 13:17:18 -0800149 log.info("Requesting control for {}", HexString.toHexString(dpid));
Jonathan Hartc6eee9e2013-02-18 14:58:27 -0800150
Jonathan Hartbd766972013-02-22 15:13:03 -0800151 if (controllerId == null){
152 throw new RuntimeException("Must register a controller before calling requestControl");
Jonathan Hartbd181b62013-02-17 16:05:38 -0800153 }
154
155 String dpidStr = HexString.toHexString(dpid);
156 String latchPath = switchLatchesPath + "/" + dpidStr;
157
Jonathan Hart89187372013-03-14 16:41:09 -0700158 if (switches.get(dpidStr) != null){
Jonathan Hart3c0eccd2013-03-12 22:32:50 -0700159 log.debug("Already contesting {}, returning", HexString.toHexString(dpid));
160 return;
Jonathan Hartc6eee9e2013-02-18 14:58:27 -0800161 }
162
Jonathan Hartbd766972013-02-22 15:13:03 -0800163 LeaderLatch latch = new LeaderLatch(client, latchPath, controllerId);
Jonathan Hart89187372013-03-14 16:41:09 -0700164 latch.addListener(new SwitchLeaderListener(dpidStr, latch));
Jonathan Hartbd181b62013-02-17 16:05:38 -0800165
Jonathan Hart44e56fc2013-03-14 16:53:59 -0700166
Jonathan Hart89187372013-03-14 16:41:09 -0700167 SwitchLeadershipData swData = new SwitchLeadershipData(latch, cb);
168 SwitchLeadershipData oldData = switches.putIfAbsent(dpidStr, swData);
169
170 if (oldData != null){
171 //There was already data for that key in the map
172 //i.e. someone else got here first so we can't succeed
173 log.debug("Already requested control for {}", dpidStr);
174 throw new RegistryException("Already requested control for " + dpidStr);
175 }
176
177 //Now that we know we were able to add our latch to the collection,
Jonathan Hart44e56fc2013-03-14 16:53:59 -0700178 //we can start the leader election in Zookeeper. However I don't know
179 //how to handle if the start fails - the latch is already in our
180 //switches list.
181 //TODO seems like there's a Curator bug when latch.start is called when
182 //there's no Zookeeper connection which causes two znodes to be put in
183 //Zookeeper at the latch path when we reconnect to Zookeeper.
Jonathan Hartbd181b62013-02-17 16:05:38 -0800184 try {
Jonathan Hartbd181b62013-02-17 16:05:38 -0800185 latch.start();
186 } catch (Exception e) {
Jonathan Hartc6eee9e2013-02-18 14:58:27 -0800187 log.warn("Error starting leader latch: {}", e.getMessage());
Jonathan Hart3d7730a2013-02-22 11:51:17 -0800188 throw new RegistryException("Error starting leader latch for " + dpidStr, e);
Jonathan Hartbd181b62013-02-17 16:05:38 -0800189 }
190
191 }
192
193 @Override
Jonathan Hartd82f20d2013-02-21 18:04:24 -0800194 public void releaseControl(long dpid) {
Jonathan Hart7bf62172013-02-28 13:17:18 -0800195 log.info("Releasing control for {}", HexString.toHexString(dpid));
Jonathan Hart57080fb2013-02-21 10:55:46 -0800196
Jonathan Hartc6eee9e2013-02-18 14:58:27 -0800197 String dpidStr = HexString.toHexString(dpid);
198
Jonathan Hart89187372013-03-14 16:41:09 -0700199 SwitchLeadershipData swData = switches.remove(dpidStr);
200
201 if (swData == null) {
Jonathan Hart7bf62172013-02-28 13:17:18 -0800202 log.debug("Trying to release control of a switch we are not contesting");
Jonathan Hartbd181b62013-02-17 16:05:38 -0800203 return;
204 }
Jonathan Hart89187372013-03-14 16:41:09 -0700205
Jonathan Hart89187372013-03-14 16:41:09 -0700206 LeaderLatch latch = swData.getLatch();
Jonathan Hartbd181b62013-02-17 16:05:38 -0800207
208 try {
209 latch.close();
210 } catch (IOException e) {
Jonathan Hart7bf62172013-02-28 13:17:18 -0800211 //I think it's OK not to do anything here. Either the node got
212 //deleted correctly, or the connection went down and the node got deleted.
Jonathan Hartbd181b62013-02-17 16:05:38 -0800213 }
214 }
215
216 @Override
Jonathan Hartd82f20d2013-02-21 18:04:24 -0800217 public boolean hasControl(long dpid) {
Jonathan Hart89187372013-03-14 16:41:09 -0700218 String dpidStr = HexString.toHexString(dpid);
Jonathan Hart57080fb2013-02-21 10:55:46 -0800219
Jonathan Hart89187372013-03-14 16:41:09 -0700220 SwitchLeadershipData swData = switches.get(dpidStr);
Jonathan Hartbd181b62013-02-17 16:05:38 -0800221
Jonathan Hart89187372013-03-14 16:41:09 -0700222 if (swData == null) {
223 log.warn("No leader latch for dpid {}", dpidStr);
Jonathan Hartbd181b62013-02-17 16:05:38 -0800224 return false;
225 }
226
Jonathan Hart89187372013-03-14 16:41:09 -0700227 return swData.getLatch().hasLeadership();
Jonathan Hartbd181b62013-02-17 16:05:38 -0800228 }
229
230 @Override
Jonathan Hart7bf62172013-02-28 13:17:18 -0800231 public String getControllerId() {
Jonathan Hartbd766972013-02-22 15:13:03 -0800232 return controllerId;
Jonathan Hartbd181b62013-02-17 16:05:38 -0800233 }
234
Jonathan Hartedd6a442013-02-20 15:22:06 -0800235 @Override
Jonathan Hart57080fb2013-02-21 10:55:46 -0800236 public Collection<String> getAllControllers() throws RegistryException {
Jonathan Hartedd6a442013-02-20 15:22:06 -0800237 log.debug("Getting all controllers");
Jonathan Hart1be46262013-02-20 16:43:51 -0800238
Jonathan Hartbc4893a2013-03-14 22:21:37 -0700239 //Rebuild the cache to make sure we have the latest data
240 //If we don't have ZK connection this will hang until we do. Undesirable.
241 try {
242 controllerCache.rebuild();
243 } catch (Exception e1) {
244 return null;
245 }
246
Jonathan Hartedd6a442013-02-20 15:22:06 -0800247 List<String> controllers = new ArrayList<String>();
Jonathan Hartbc4893a2013-03-14 22:21:37 -0700248
Jonathan Hartedd6a442013-02-20 15:22:06 -0800249 for (ChildData data : controllerCache.getCurrentData()){
250
251 String d = null;
252 try {
253 d = new String(data.getData(), "UTF-8");
254 } catch (UnsupportedEncodingException e) {
Jonathan Hart57080fb2013-02-21 10:55:46 -0800255 throw new RegistryException("Error encoding string", e);
Jonathan Hartedd6a442013-02-20 15:22:06 -0800256 }
257
258 controllers.add(d);
259 }
260 return controllers;
261 }
262
263 @Override
Jonathan Hart57080fb2013-02-21 10:55:46 -0800264 public void registerController(String id) throws RegistryException {
Jonathan Hartbc4893a2013-03-14 22:21:37 -0700265 //TODO this isn't replaced if we lose Zookeeper connection
Jonathan Hartd10008d2013-02-23 17:04:08 -0800266 if (controllerId != null) {
267 throw new RegistryException(
268 "Controller already registered with id " + controllerId);
269 }
Jonathan Hartbd766972013-02-22 15:13:03 -0800270
271 controllerId = id;
Jonathan Hart57080fb2013-02-21 10:55:46 -0800272
Jonathan Hartd10008d2013-02-23 17:04:08 -0800273 byte bytes[] = id.getBytes(Charsets.UTF_8);
Jonathan Hartedd6a442013-02-20 15:22:06 -0800274
275 String path = controllerPath + "/" + id;
276
277 log.info("Registering controller with id {}", id);
278
Jonathan Hart57080fb2013-02-21 10:55:46 -0800279 //Create ephemeral node in controller registry
Jonathan Hartedd6a442013-02-20 15:22:06 -0800280 try {
281 client.create().withProtection().withMode(CreateMode.EPHEMERAL)
282 .forPath(path, bytes);
283 } catch (Exception e) {
Jonathan Hart57080fb2013-02-21 10:55:46 -0800284 throw new RegistryException("Error contacting the Zookeeper service", e);
Jonathan Hartedd6a442013-02-20 15:22:06 -0800285 }
286 }
287
288 @Override
Jonathan Hart57080fb2013-02-21 10:55:46 -0800289 public String getControllerForSwitch(long dpid) throws RegistryException {
Jonathan Hart89187372013-03-14 16:41:09 -0700290 // TODO work out synchronization
Jonathan Hartedd6a442013-02-20 15:22:06 -0800291
Jonathan Hart89187372013-03-14 16:41:09 -0700292 String dpidStr = HexString.toHexString(dpid);
Jonathan Hart44e56fc2013-03-14 16:53:59 -0700293
Pankaj Berde017960a2013-03-14 20:32:26 -0700294
295 LeaderLatch latch = (switches.get(dpidStr) != null)?switches.get(dpidStr).getLatch():null;
Jonathan Hartedd6a442013-02-20 15:22:06 -0800296
297 if (latch == null){
298 log.warn("Tried to get controller for non-existent switch");
299 return null;
300 }
301
302 Participant leader = null;
303 try {
304 leader = latch.getLeader();
305 } catch (Exception e) {
Jonathan Hart57080fb2013-02-21 10:55:46 -0800306 throw new RegistryException("Error contacting the Zookeeper service", e);
Jonathan Hartedd6a442013-02-20 15:22:06 -0800307 }
308
309 return leader.getId();
310 }
311
312 @Override
313 public Collection<Long> getSwitchesControlledByController(String controllerId) {
Jonathan Hart3d7730a2013-02-22 11:51:17 -0800314 //TODO remove this if not needed
Jonathan Hartbd766972013-02-22 15:13:03 -0800315 throw new RuntimeException("Not yet implemented");
Jonathan Hartedd6a442013-02-20 15:22:06 -0800316 }
Jonathan Hartbd181b62013-02-17 16:05:38 -0800317
Jonathan Hartd82f20d2013-02-21 18:04:24 -0800318
Jonathan Hart89187372013-03-14 16:41:09 -0700319 //TODO what should happen when there's no ZK connection? Currently we just return
320 //the cache but this may lead to false impressions - i.e. we don't actually know
321 //what's in ZK so we shouldn't say we do
Jonathan Hartd82f20d2013-02-21 18:04:24 -0800322 @Override
Jonathan Hart3d7730a2013-02-22 11:51:17 -0800323 public Map<String, List<ControllerRegistryEntry>> getAllSwitches() {
324 Map<String, List<ControllerRegistryEntry>> data =
325 new HashMap<String, List<ControllerRegistryEntry>>();
326
327 for (Map.Entry<String, PathChildrenCache> entry : switchPathCaches.entrySet()){
328 List<ControllerRegistryEntry> contendingControllers =
329 new ArrayList<ControllerRegistryEntry>();
330
331 if (entry.getValue().getCurrentData().size() < 1){
332 log.info("Switch entry with no leader elections: {}", entry.getKey());
333 continue;
334 }
335
336 for (ChildData d : entry.getValue().getCurrentData()) {
Jonathan Hart97801ac2013-02-26 14:29:16 -0800337
Jonathan Hartd10008d2013-02-23 17:04:08 -0800338 String controllerId = new String(d.getData(), Charsets.UTF_8);
Jonathan Hart3d7730a2013-02-22 11:51:17 -0800339
340 String[] splitted = d.getPath().split("-");
341 int sequenceNumber = Integer.parseInt(splitted[splitted.length - 1]);
342
343 contendingControllers.add(new ControllerRegistryEntry(controllerId, sequenceNumber));
344 }
345
346 Collections.sort(contendingControllers);
347 data.put(entry.getKey(), contendingControllers);
348 }
349 return data;
Jonathan Hartd82f20d2013-02-21 18:04:24 -0800350 }
351
Jonathan Hartbd181b62013-02-17 16:05:38 -0800352 /*
353 * IFloodlightModule
354 */
355
Umesh Krishnaswamyb56bb292013-02-12 20:28:27 -0800356 @Override
357 public Collection<Class<? extends IFloodlightService>> getModuleServices() {
Jonathan Hartedd6a442013-02-20 15:22:06 -0800358 Collection<Class<? extends IFloodlightService>> l =
359 new ArrayList<Class<? extends IFloodlightService>>();
Jonathan Hartd82f20d2013-02-21 18:04:24 -0800360 l.add(IControllerRegistryService.class);
Umesh Krishnaswamyb56bb292013-02-12 20:28:27 -0800361 return l;
362 }
363
364 @Override
365 public Map<Class<? extends IFloodlightService>, IFloodlightService> getServiceImpls() {
366 Map<Class<? extends IFloodlightService>, IFloodlightService> m =
367 new HashMap<Class<? extends IFloodlightService>, IFloodlightService>();
Jonathan Hartd82f20d2013-02-21 18:04:24 -0800368 m.put(IControllerRegistryService.class, this);
Umesh Krishnaswamyb56bb292013-02-12 20:28:27 -0800369 return m;
370 }
371
372 @Override
373 public Collection<Class<? extends IFloodlightService>> getModuleDependencies() {
Jonathan Hart3d7730a2013-02-22 11:51:17 -0800374 Collection<Class<? extends IFloodlightService>> l =
375 new ArrayList<Class<? extends IFloodlightService>>();
376 l.add(IRestApiService.class);
377 return l;
Umesh Krishnaswamyb56bb292013-02-12 20:28:27 -0800378 }
379
Jonathan Hart89187372013-03-14 16:41:09 -0700380 //TODO currently blocks startup when it can't get a Zookeeper connection.
381 //Do we support starting up with no Zookeeper connection?
Umesh Krishnaswamyb56bb292013-02-12 20:28:27 -0800382 @Override
383 public void init (FloodlightModuleContext context) throws FloodlightModuleException {
Jonathan Hartbd766972013-02-22 15:13:03 -0800384 log.info("Initialising the Zookeeper Registry - Zookeeper connection required");
385
Jonathan Hart97801ac2013-02-26 14:29:16 -0800386 //Read the Zookeeper connection string from the config
387 Map<String, String> configParams = context.getConfigParams(this);
388 String connectionString = configParams.get("connectionString");
389 if (connectionString != null){
390 this.connectionString = connectionString;
Jonathan Hart57080fb2013-02-21 10:55:46 -0800391 }
Jonathan Hart97801ac2013-02-26 14:29:16 -0800392 log.info("Setting Zookeeper connection string to {}", this.connectionString);
Jonathan Hart57080fb2013-02-21 10:55:46 -0800393
Jonathan Hart97801ac2013-02-26 14:29:16 -0800394 restApi = context.getServiceImpl(IRestApiService.class);
Jonathan Hartbd181b62013-02-17 16:05:38 -0800395
Jonathan Hart89187372013-03-14 16:41:09 -0700396 switches = new ConcurrentHashMap<String, SwitchLeadershipData>();
Jonathan Hart3d7730a2013-02-22 11:51:17 -0800397 switchPathCaches = new HashMap<String, PathChildrenCache>();
Jonathan Hartbd181b62013-02-17 16:05:38 -0800398
Jonathan Hart3d7730a2013-02-22 11:51:17 -0800399 RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000, 3);
Jonathan Hart97801ac2013-02-26 14:29:16 -0800400 client = CuratorFrameworkFactory.newClient(this.connectionString,
Jonathan Hartcc957a02013-02-26 10:39:04 -0800401 sessionTimeout, connectionTimeout, retryPolicy);
Jonathan Hartbd181b62013-02-17 16:05:38 -0800402
403 client.start();
Jonathan Hartbd181b62013-02-17 16:05:38 -0800404 client = client.usingNamespace(namespace);
Jonathan Hart97801ac2013-02-26 14:29:16 -0800405
Jonathan Hart3d7730a2013-02-22 11:51:17 -0800406
Jonathan Hartedd6a442013-02-20 15:22:06 -0800407 controllerCache = new PathChildrenCache(client, controllerPath, true);
Jonathan Hart3d7730a2013-02-22 11:51:17 -0800408 switchCache = new PathChildrenCache(client, switchLatchesPath, true);
409 switchCache.getListenable().addListener(switchPathCacheListener);
Jonathan Hartedd6a442013-02-20 15:22:06 -0800410
411 try {
412 controllerCache.start(StartMode.BUILD_INITIAL_CACHE);
Jonathan Hart3d7730a2013-02-22 11:51:17 -0800413
414 //Don't prime the cache, we want a notification for each child node in the path
415 switchCache.start(StartMode.NORMAL);
Jonathan Hartedd6a442013-02-20 15:22:06 -0800416 } catch (Exception e) {
Jonathan Hart7bf62172013-02-28 13:17:18 -0800417 throw new FloodlightModuleException("Error initialising ZookeeperRegistry: "
418 + e.getMessage());
Jonathan Hartedd6a442013-02-20 15:22:06 -0800419 }
Umesh Krishnaswamyb56bb292013-02-12 20:28:27 -0800420 }
421
422 @Override
423 public void startUp (FloodlightModuleContext context) {
Jonathan Hart3d7730a2013-02-22 11:51:17 -0800424 restApi.addRestletRoutable(new RegistryWebRoutable());
Umesh Krishnaswamyb56bb292013-02-12 20:28:27 -0800425 }
Umesh Krishnaswamyb56bb292013-02-12 20:28:27 -0800426}