blob: 59a7442e1b0f075596941e0f972303d586e8c609 [file] [log] [blame]
Thomas Vachuska329af532015-03-10 02:08:33 -07001/*
Brian O'Connor5ab426f2016-04-09 01:19:45 -07002 * Copyright 2015-present Open Networking Laboratory
Thomas Vachuska329af532015-03-10 02:08:33 -07003 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16package org.onosproject.ui.impl;
17
18import com.fasterxml.jackson.databind.JsonNode;
19import com.fasterxml.jackson.databind.node.ArrayNode;
20import com.fasterxml.jackson.databind.node.ObjectNode;
21import com.google.common.collect.ImmutableSet;
22import org.onlab.osgi.ServiceDirectory;
23import org.onlab.util.AbstractAccumulator;
24import org.onlab.util.Accumulator;
25import org.onosproject.cluster.ClusterEvent;
26import org.onosproject.cluster.ClusterEventListener;
27import org.onosproject.cluster.ControllerNode;
28import org.onosproject.core.ApplicationId;
29import org.onosproject.core.CoreService;
Simon Hunt4a6b54b2015-10-27 22:08:25 -070030import org.onosproject.core.DefaultApplicationId;
Thomas Vachuska329af532015-03-10 02:08:33 -070031import org.onosproject.event.Event;
32import org.onosproject.mastership.MastershipAdminService;
33import org.onosproject.mastership.MastershipEvent;
34import org.onosproject.mastership.MastershipListener;
35import org.onosproject.net.ConnectPoint;
36import org.onosproject.net.Device;
Simon Huntde99e0b2015-10-23 18:54:06 -070037import org.onosproject.net.DeviceId;
Thomas Vachuska329af532015-03-10 02:08:33 -070038import org.onosproject.net.Host;
39import org.onosproject.net.HostId;
40import org.onosproject.net.HostLocation;
41import org.onosproject.net.Link;
42import org.onosproject.net.device.DeviceEvent;
43import org.onosproject.net.device.DeviceListener;
44import org.onosproject.net.flow.DefaultTrafficSelector;
45import org.onosproject.net.flow.DefaultTrafficTreatment;
46import org.onosproject.net.flow.FlowRuleEvent;
47import org.onosproject.net.flow.FlowRuleListener;
48import org.onosproject.net.flow.TrafficSelector;
49import org.onosproject.net.flow.TrafficTreatment;
50import org.onosproject.net.host.HostEvent;
51import org.onosproject.net.host.HostListener;
52import org.onosproject.net.intent.HostToHostIntent;
Simon Hunt4a6b54b2015-10-27 22:08:25 -070053import org.onosproject.net.intent.Intent;
Thomas Vachuska329af532015-03-10 02:08:33 -070054import org.onosproject.net.intent.IntentEvent;
55import org.onosproject.net.intent.IntentListener;
Simon Hunt4a6b54b2015-10-27 22:08:25 -070056import org.onosproject.net.intent.Key;
Thomas Vachuska329af532015-03-10 02:08:33 -070057import org.onosproject.net.intent.MultiPointToSinglePointIntent;
58import org.onosproject.net.link.LinkEvent;
59import org.onosproject.net.link.LinkListener;
Simon Hunt4a6b54b2015-10-27 22:08:25 -070060import org.onosproject.ui.JsonUtils;
Simon Huntd2747a02015-04-30 22:41:16 -070061import org.onosproject.ui.RequestHandler;
Thomas Vachuska329af532015-03-10 02:08:33 -070062import org.onosproject.ui.UiConnection;
Simon Hunt4fc86852015-08-20 17:57:52 -070063import org.onosproject.ui.impl.TrafficMonitor.Mode;
Simon Hunta17fa672015-08-19 18:42:22 -070064import org.onosproject.ui.topo.Highlights;
Simon Huntd3ceffa2015-08-25 12:44:35 -070065import org.onosproject.ui.topo.NodeSelection;
Simon Hunt0af1ec32015-07-24 12:17:55 -070066import org.onosproject.ui.topo.PropertyPanel;
Thomas Vachuska329af532015-03-10 02:08:33 -070067
68import java.util.ArrayList;
Simon Huntd2747a02015-04-30 22:41:16 -070069import java.util.Collection;
Thomas Vachuska329af532015-03-10 02:08:33 -070070import java.util.Collections;
71import java.util.Comparator;
72import java.util.HashSet;
73import java.util.List;
Simon Hunt5c1a9382016-06-01 19:35:35 -070074import java.util.Map;
Thomas Vachuska329af532015-03-10 02:08:33 -070075import java.util.Set;
76import java.util.Timer;
77import java.util.TimerTask;
Thomas Vachuska52c98bd2015-05-27 20:54:02 -070078import java.util.concurrent.ExecutorService;
Thomas Vachuska329af532015-03-10 02:08:33 -070079
Thomas Vachuska52c98bd2015-05-27 20:54:02 -070080import static java.util.concurrent.Executors.newSingleThreadExecutor;
81import static org.onlab.util.Tools.groupedThreads;
Thomas Vachuska329af532015-03-10 02:08:33 -070082import static org.onosproject.cluster.ClusterEvent.Type.INSTANCE_ADDED;
83import static org.onosproject.net.DeviceId.deviceId;
84import static org.onosproject.net.HostId.hostId;
Simon Hunt4a6b54b2015-10-27 22:08:25 -070085import static org.onosproject.net.device.DeviceEvent.Type.DEVICE_ADDED;
86import static org.onosproject.net.device.DeviceEvent.Type.DEVICE_UPDATED;
87import static org.onosproject.net.device.DeviceEvent.Type.PORT_STATS_UPDATED;
Thomas Vachuska329af532015-03-10 02:08:33 -070088import static org.onosproject.net.host.HostEvent.Type.HOST_ADDED;
89import static org.onosproject.net.link.LinkEvent.Type.LINK_ADDED;
Simon Huntd3ceffa2015-08-25 12:44:35 -070090import static org.onosproject.ui.JsonUtils.envelope;
Viswanath KSP0f297702016-08-13 18:02:43 +053091import static org.onosproject.ui.JsonUtils.string;
Simon Hunt52560662015-08-27 22:46:44 -070092import static org.onosproject.ui.topo.TopoJson.highlightsMessage;
93import static org.onosproject.ui.topo.TopoJson.json;
Thomas Vachuska329af532015-03-10 02:08:33 -070094
95/**
96 * Web socket capable of interacting with the GUI topology view.
97 */
98public class TopologyViewMessageHandler extends TopologyViewMessageHandlerBase {
99
Simon Huntb745ca62015-07-28 15:37:11 -0700100 // incoming event types
Simon Huntd2747a02015-04-30 22:41:16 -0700101 private static final String REQ_DETAILS = "requestDetails";
102 private static final String UPDATE_META = "updateMeta";
103 private static final String ADD_HOST_INTENT = "addHostIntent";
Viswanath KSP0f297702016-08-13 18:02:43 +0530104 private static final String REMOVE_INTENT = "removeIntent";
Viswanath KSP14aee092016-10-02 01:47:40 +0530105 private static final String RESUBMIT_INTENT = "resubmitIntent";
Simon Huntd2747a02015-04-30 22:41:16 -0700106 private static final String ADD_MULTI_SRC_INTENT = "addMultiSourceIntent";
107 private static final String REQ_RELATED_INTENTS = "requestRelatedIntents";
108 private static final String REQ_NEXT_INTENT = "requestNextRelatedIntent";
109 private static final String REQ_PREV_INTENT = "requestPrevRelatedIntent";
110 private static final String REQ_SEL_INTENT_TRAFFIC = "requestSelectedIntentTraffic";
Simon Hunt4a6b54b2015-10-27 22:08:25 -0700111 private static final String SEL_INTENT = "selectIntent";
Thomas Vachuskaf0397b52015-05-29 13:50:17 -0700112 private static final String REQ_ALL_FLOW_TRAFFIC = "requestAllFlowTraffic";
113 private static final String REQ_ALL_PORT_TRAFFIC = "requestAllPortTraffic";
Simon Huntd2747a02015-04-30 22:41:16 -0700114 private static final String REQ_DEV_LINK_FLOWS = "requestDeviceLinkFlows";
115 private static final String CANCEL_TRAFFIC = "cancelTraffic";
116 private static final String REQ_SUMMARY = "requestSummary";
117 private static final String CANCEL_SUMMARY = "cancelSummary";
118 private static final String EQ_MASTERS = "equalizeMasters";
119 private static final String SPRITE_LIST_REQ = "spriteListRequest";
120 private static final String SPRITE_DATA_REQ = "spriteDataRequest";
121 private static final String TOPO_START = "topoStart";
Simon Hunt732bb2e2015-05-13 18:32:16 -0700122 private static final String TOPO_HEARTBEAT = "topoHeartbeat";
Simon Hunte05cae42015-07-23 17:35:24 -0700123 private static final String TOPO_SELECT_OVERLAY = "topoSelectOverlay";
Simon Huntd2747a02015-04-30 22:41:16 -0700124 private static final String TOPO_STOP = "topoStop";
125
Simon Huntb745ca62015-07-28 15:37:11 -0700126 // outgoing event types
127 private static final String SHOW_SUMMARY = "showSummary";
128 private static final String SHOW_DETAILS = "showDetails";
129 private static final String SPRITE_LIST_RESPONSE = "spriteListResponse";
130 private static final String SPRITE_DATA_RESPONSE = "spriteDataResponse";
131 private static final String UPDATE_INSTANCE = "updateInstance";
Simon Hunt4a6b54b2015-10-27 22:08:25 -0700132 private static final String TOPO_START_DONE = "topoStartDone";
Simon Huntb745ca62015-07-28 15:37:11 -0700133
134 // fields
Simon Hunt5c1a9382016-06-01 19:35:35 -0700135 private static final String PAYLOAD = "payload";
136 private static final String EXTRA = "extra";
Simon Huntb745ca62015-07-28 15:37:11 -0700137 private static final String ID = "id";
Simon Hunt4a6b54b2015-10-27 22:08:25 -0700138 private static final String KEY = "key";
139 private static final String APP_ID = "appId";
140 private static final String APP_NAME = "appName";
Simon Huntb745ca62015-07-28 15:37:11 -0700141 private static final String DEVICE = "device";
142 private static final String HOST = "host";
143 private static final String CLASS = "class";
144 private static final String UNKNOWN = "unknown";
145 private static final String ONE = "one";
146 private static final String TWO = "two";
147 private static final String SRC = "src";
148 private static final String DST = "dst";
149 private static final String DATA = "data";
150 private static final String NAME = "name";
151 private static final String NAMES = "names";
152 private static final String ACTIVATE = "activate";
153 private static final String DEACTIVATE = "deactivate";
Viswanath KSP813a20d2016-09-13 04:25:41 +0530154 private static final String PURGE = "purge";
Simon Huntb745ca62015-07-28 15:37:11 -0700155
Simon Huntd2747a02015-04-30 22:41:16 -0700156
Simon Hunt4a6b54b2015-10-27 22:08:25 -0700157 private static final String MY_APP_ID = "org.onosproject.gui";
Thomas Vachuska329af532015-03-10 02:08:33 -0700158
Simon Hunta17fa672015-08-19 18:42:22 -0700159 private static final long TRAFFIC_PERIOD = 5000;
160 private static final long SUMMARY_PERIOD = 30000;
Thomas Vachuska329af532015-03-10 02:08:33 -0700161
162 private static final Comparator<? super ControllerNode> NODE_COMPARATOR =
Thomas Vachuskac0fe09a2015-05-21 12:56:22 -0700163 (o1, o2) -> o1.id().toString().compareTo(o2.id().toString());
Thomas Vachuska329af532015-03-10 02:08:33 -0700164
165
Thomas Vachuska52c98bd2015-05-27 20:54:02 -0700166 private final Timer timer = new Timer("onos-topology-view");
Thomas Vachuska329af532015-03-10 02:08:33 -0700167
168 private static final int MAX_EVENTS = 1000;
169 private static final int MAX_BATCH_MS = 5000;
170 private static final int MAX_IDLE_MS = 1000;
171
172 private ApplicationId appId;
173
174 private final ClusterEventListener clusterListener = new InternalClusterListener();
175 private final MastershipListener mastershipListener = new InternalMastershipListener();
176 private final DeviceListener deviceListener = new InternalDeviceListener();
177 private final LinkListener linkListener = new InternalLinkListener();
178 private final HostListener hostListener = new InternalHostListener();
179 private final IntentListener intentListener = new InternalIntentListener();
180 private final FlowRuleListener flowListener = new InternalFlowListener();
181
182 private final Accumulator<Event> eventAccummulator = new InternalEventAccummulator();
Thomas Vachuska52c98bd2015-05-27 20:54:02 -0700183 private final ExecutorService msgSender =
Yuta HIGUCHI1624df12016-07-21 16:54:33 -0700184 newSingleThreadExecutor(groupedThreads("onos/gui", "msg-sender", log));
Thomas Vachuska329af532015-03-10 02:08:33 -0700185
Simon Hunta17fa672015-08-19 18:42:22 -0700186 private TopoOverlayCache overlayCache;
Simon Hunt4fc86852015-08-20 17:57:52 -0700187 private TrafficMonitor traffic;
Thomas Vachuska329af532015-03-10 02:08:33 -0700188
Simon Huntd2747a02015-04-30 22:41:16 -0700189 private TimerTask summaryTask = null;
190 private boolean summaryRunning = false;
Thomas Vachuska329af532015-03-10 02:08:33 -0700191
Simon Huntd5b96732016-07-08 13:22:27 -0700192 private volatile boolean listenersRemoved = false;
Thomas Vachuska329af532015-03-10 02:08:33 -0700193
Thomas Vachuska329af532015-03-10 02:08:33 -0700194
195 @Override
196 public void init(UiConnection connection, ServiceDirectory directory) {
197 super.init(connection, directory);
Simon Hunt4a6b54b2015-10-27 22:08:25 -0700198 appId = directory.get(CoreService.class).registerApplication(MY_APP_ID);
Simon Hunt4fc86852015-08-20 17:57:52 -0700199 traffic = new TrafficMonitor(TRAFFIC_PERIOD, servicesBundle, this);
Thomas Vachuska329af532015-03-10 02:08:33 -0700200 }
201
202 @Override
203 public void destroy() {
204 cancelAllRequests();
Thomas Vachuska2bb48632015-04-28 14:40:42 -0700205 removeListeners();
Thomas Vachuska329af532015-03-10 02:08:33 -0700206 super.destroy();
207 }
208
Thomas Vachuska329af532015-03-10 02:08:33 -0700209 @Override
Simon Huntda580882015-05-12 20:58:18 -0700210 protected Collection<RequestHandler> createRequestHandlers() {
Simon Huntd2747a02015-04-30 22:41:16 -0700211 return ImmutableSet.of(
212 new TopoStart(),
Simon Hunt732bb2e2015-05-13 18:32:16 -0700213 new TopoHeartbeat(),
Simon Hunte05cae42015-07-23 17:35:24 -0700214 new TopoSelectOverlay(),
Simon Huntd2747a02015-04-30 22:41:16 -0700215 new TopoStop(),
216 new ReqSummary(),
217 new CancelSummary(),
218 new SpriteListReq(),
219 new SpriteDataReq(),
220 new RequestDetails(),
221 new UpdateMeta(),
222 new EqMasters(),
Thomas Vachuska329af532015-03-10 02:08:33 -0700223
Simon Huntd2747a02015-04-30 22:41:16 -0700224 // TODO: migrate traffic related to separate app
225 new AddHostIntent(),
226 new AddMultiSourceIntent(),
Viswanath KSP0f297702016-08-13 18:02:43 +0530227 new RemoveIntent(),
Viswanath KSP14aee092016-10-02 01:47:40 +0530228 new ResubmitIntent(),
Simon Hunta17fa672015-08-19 18:42:22 -0700229
230 new ReqAllFlowTraffic(),
231 new ReqAllPortTraffic(),
232 new ReqDevLinkFlows(),
Simon Huntd2747a02015-04-30 22:41:16 -0700233 new ReqRelatedIntents(),
234 new ReqNextIntent(),
235 new ReqPrevIntent(),
236 new ReqSelectedIntentTraffic(),
Simon Hunt4a6b54b2015-10-27 22:08:25 -0700237 new SelIntent(),
Simon Hunta17fa672015-08-19 18:42:22 -0700238
Simon Huntd2747a02015-04-30 22:41:16 -0700239 new CancelTraffic()
240 );
241 }
Thomas Vachuska329af532015-03-10 02:08:33 -0700242
Simon Hunte05cae42015-07-23 17:35:24 -0700243 /**
244 * Injects the topology overlay cache.
245 *
246 * @param overlayCache injected cache
247 */
248 void setOverlayCache(TopoOverlayCache overlayCache) {
249 this.overlayCache = overlayCache;
250 }
251
Simon Huntd2747a02015-04-30 22:41:16 -0700252 // ==================================================================
Thomas Vachuska329af532015-03-10 02:08:33 -0700253
Simon Huntd2747a02015-04-30 22:41:16 -0700254 private final class TopoStart extends RequestHandler {
255 private TopoStart() {
256 super(TOPO_START);
257 }
Thomas Vachuska329af532015-03-10 02:08:33 -0700258
Simon Huntd2747a02015-04-30 22:41:16 -0700259 @Override
260 public void process(long sid, ObjectNode payload) {
261 addListeners();
262 sendAllInstances(null);
263 sendAllDevices();
264 sendAllLinks();
265 sendAllHosts();
Simon Hunt4a6b54b2015-10-27 22:08:25 -0700266 sendTopoStartDone();
Thomas Vachuska329af532015-03-10 02:08:33 -0700267 }
268 }
269
Simon Hunt732bb2e2015-05-13 18:32:16 -0700270 private final class TopoHeartbeat extends RequestHandler {
271 private TopoHeartbeat() {
272 super(TOPO_HEARTBEAT);
273 }
274
275 @Override
276 public void process(long sid, ObjectNode payload) {
277 // place holder for now
278 }
279 }
280
Simon Hunte05cae42015-07-23 17:35:24 -0700281 private final class TopoSelectOverlay extends RequestHandler {
282 private TopoSelectOverlay() {
283 super(TOPO_SELECT_OVERLAY);
284 }
285
286 @Override
287 public void process(long sid, ObjectNode payload) {
Simon Huntb745ca62015-07-28 15:37:11 -0700288 String deact = string(payload, DEACTIVATE);
289 String act = string(payload, ACTIVATE);
Simon Hunte05cae42015-07-23 17:35:24 -0700290 overlayCache.switchOverlay(deact, act);
291 }
292 }
293
Simon Huntd2747a02015-04-30 22:41:16 -0700294 private final class TopoStop extends RequestHandler {
295 private TopoStop() {
296 super(TOPO_STOP);
297 }
298
299 @Override
300 public void process(long sid, ObjectNode payload) {
Simon Hunt1ad59272015-11-10 15:23:21 -0800301 removeListeners();
Simon Huntd2747a02015-04-30 22:41:16 -0700302 stopSummaryMonitoring();
Simon Hunt4fc86852015-08-20 17:57:52 -0700303 traffic.stopMonitoring();
Simon Huntd2747a02015-04-30 22:41:16 -0700304 }
305 }
306
307 private final class ReqSummary extends RequestHandler {
308 private ReqSummary() {
309 super(REQ_SUMMARY);
310 }
311
312 @Override
313 public void process(long sid, ObjectNode payload) {
314 requestSummary(sid);
315 startSummaryMonitoring();
316 }
317 }
318
319 private final class CancelSummary extends RequestHandler {
320 private CancelSummary() {
321 super(CANCEL_SUMMARY);
322 }
323
324 @Override
325 public void process(long sid, ObjectNode payload) {
326 stopSummaryMonitoring();
327 }
328 }
329
330 private final class SpriteListReq extends RequestHandler {
331 private SpriteListReq() {
332 super(SPRITE_LIST_REQ);
333 }
334
335 @Override
336 public void process(long sid, ObjectNode payload) {
Simon Huntda580882015-05-12 20:58:18 -0700337 ObjectNode root = objectNode();
338 ArrayNode names = arrayNode();
Simon Huntd2747a02015-04-30 22:41:16 -0700339 get(SpriteService.class).getNames().forEach(names::add);
Simon Huntb745ca62015-07-28 15:37:11 -0700340 root.set(NAMES, names);
341 sendMessage(SPRITE_LIST_RESPONSE, sid, root);
Simon Huntd2747a02015-04-30 22:41:16 -0700342 }
343 }
344
345 private final class SpriteDataReq extends RequestHandler {
346 private SpriteDataReq() {
347 super(SPRITE_DATA_REQ);
348 }
349
350 @Override
351 public void process(long sid, ObjectNode payload) {
Simon Huntb745ca62015-07-28 15:37:11 -0700352 String name = string(payload, NAME);
Simon Huntda580882015-05-12 20:58:18 -0700353 ObjectNode root = objectNode();
Simon Huntb745ca62015-07-28 15:37:11 -0700354 root.set(DATA, get(SpriteService.class).get(name));
355 sendMessage(SPRITE_DATA_RESPONSE, sid, root);
Simon Huntd2747a02015-04-30 22:41:16 -0700356 }
357 }
358
359 private final class RequestDetails extends RequestHandler {
360 private RequestDetails() {
361 super(REQ_DETAILS);
362 }
363
364 @Override
365 public void process(long sid, ObjectNode payload) {
Simon Huntb745ca62015-07-28 15:37:11 -0700366 String type = string(payload, CLASS, UNKNOWN);
367 String id = string(payload, ID);
368 PropertyPanel pp = null;
Simon Huntd2747a02015-04-30 22:41:16 -0700369
Simon Huntb745ca62015-07-28 15:37:11 -0700370 if (type.equals(DEVICE)) {
Simon Huntde99e0b2015-10-23 18:54:06 -0700371 DeviceId did = deviceId(id);
372 pp = deviceDetails(did, sid);
373 overlayCache.currentOverlay().modifyDeviceDetails(pp, did);
Simon Huntb745ca62015-07-28 15:37:11 -0700374 } else if (type.equals(HOST)) {
Simon Huntde99e0b2015-10-23 18:54:06 -0700375 HostId hid = hostId(id);
376 pp = hostDetails(hid, sid);
377 overlayCache.currentOverlay().modifyHostDetails(pp, hid);
Simon Huntd2747a02015-04-30 22:41:16 -0700378 }
Simon Huntb745ca62015-07-28 15:37:11 -0700379
Simon Huntd3ceffa2015-08-25 12:44:35 -0700380 sendMessage(envelope(SHOW_DETAILS, sid, json(pp)));
Simon Huntd2747a02015-04-30 22:41:16 -0700381 }
382 }
383
384 private final class UpdateMeta extends RequestHandler {
385 private UpdateMeta() {
386 super(UPDATE_META);
387 }
388
389 @Override
390 public void process(long sid, ObjectNode payload) {
391 updateMetaUi(payload);
392 }
393 }
394
395 private final class EqMasters extends RequestHandler {
396 private EqMasters() {
397 super(EQ_MASTERS);
398 }
399
400 @Override
401 public void process(long sid, ObjectNode payload) {
402 directory.get(MastershipAdminService.class).balanceRoles();
403 }
404 }
405
Simon Hunta17fa672015-08-19 18:42:22 -0700406
407 // ========= -----------------------------------------------------------------
408
Simon Huntd2747a02015-04-30 22:41:16 -0700409 // === TODO: move traffic related classes to traffic app
410
411 private final class AddHostIntent extends RequestHandler {
412 private AddHostIntent() {
413 super(ADD_HOST_INTENT);
414 }
415
416 @Override
417 public void process(long sid, ObjectNode payload) {
418 // TODO: add protection against device ids and non-existent hosts.
Simon Huntb745ca62015-07-28 15:37:11 -0700419 HostId one = hostId(string(payload, ONE));
420 HostId two = hostId(string(payload, TWO));
Simon Huntd2747a02015-04-30 22:41:16 -0700421
422 HostToHostIntent intent = HostToHostIntent.builder()
Thomas Vachuskacb5016f2015-05-18 14:11:43 -0700423 .appId(appId)
424 .one(one)
425 .two(two)
426 .build();
Simon Huntd2747a02015-04-30 22:41:16 -0700427
428 intentService.submit(intent);
Simon Huntd2862c32015-08-24 17:41:51 -0700429 if (overlayCache.isActive(TrafficOverlay.TRAFFIC_ID)) {
430 traffic.monitor(intent);
431 }
Simon Huntd2747a02015-04-30 22:41:16 -0700432 }
433 }
434
Viswanath KSP0f297702016-08-13 18:02:43 +0530435 private Intent findIntentByPayload(ObjectNode payload) {
436 int appId = Integer.parseInt(string(payload, APP_ID));
437 String appName = string(payload, APP_NAME);
438 ApplicationId applicId = new DefaultApplicationId(appId, appName);
439 long intentKey = Long.decode(string(payload, KEY));
440
441 Key key = Key.of(intentKey, applicId);
442 log.debug("Attempting to select intent by key={}", key);
443
Viswanath KSP813a20d2016-09-13 04:25:41 +0530444 return intentService.getIntent(key);
Viswanath KSP0f297702016-08-13 18:02:43 +0530445 }
446
447 private final class RemoveIntent extends RequestHandler {
448 private RemoveIntent() {
449 super(REMOVE_INTENT);
450 }
451
Viswanath KSP813a20d2016-09-13 04:25:41 +0530452 private boolean isIntentToBePurged(ObjectNode payload) {
453 return bool(payload, PURGE);
454 }
455
Viswanath KSP0f297702016-08-13 18:02:43 +0530456 @Override
457 public void process(long sid, ObjectNode payload) {
458 Intent intent = findIntentByPayload(payload);
459 if (intent == null) {
460 log.warn("Unable to find intent from payload {}", payload);
461 } else {
Viswanath KSP813a20d2016-09-13 04:25:41 +0530462 log.debug("Withdrawing / Purging intent {}", intent.key());
463 if (isIntentToBePurged(payload)) {
464 intentService.purge(intent);
465 } else {
466 intentService.withdraw(intent);
467 }
Viswanath KSP0f297702016-08-13 18:02:43 +0530468 }
469 }
470 }
471
Viswanath KSP14aee092016-10-02 01:47:40 +0530472 private final class ResubmitIntent extends RequestHandler {
473 private ResubmitIntent() {
474 super(RESUBMIT_INTENT);
475 }
476
477 @Override
478 public void process(long sid, ObjectNode payload) {
479 Intent intent = findIntentByPayload(payload);
480 if (intent == null) {
481 log.warn("Unable to find intent from payload {}", payload);
482 } else {
483 log.debug("Resubmitting intent {}", intent.key());
484 intentService.submit(intent);
485 }
486 }
487 }
488
Simon Huntd2747a02015-04-30 22:41:16 -0700489 private final class AddMultiSourceIntent extends RequestHandler {
490 private AddMultiSourceIntent() {
491 super(ADD_MULTI_SRC_INTENT);
492 }
493
494 @Override
495 public void process(long sid, ObjectNode payload) {
496 // TODO: add protection against device ids and non-existent hosts.
Simon Huntb745ca62015-07-28 15:37:11 -0700497 Set<HostId> src = getHostIds((ArrayNode) payload.path(SRC));
498 HostId dst = hostId(string(payload, DST));
Simon Huntd2747a02015-04-30 22:41:16 -0700499 Host dstHost = hostService.getHost(dst);
500
501 Set<ConnectPoint> ingressPoints = getHostLocations(src);
502
503 // FIXME: clearly, this is not enough
504 TrafficSelector selector = DefaultTrafficSelector.builder()
505 .matchEthDst(dstHost.mac()).build();
506 TrafficTreatment treatment = DefaultTrafficTreatment.emptyTreatment();
507
508 MultiPointToSinglePointIntent intent =
509 MultiPointToSinglePointIntent.builder()
510 .appId(appId)
511 .selector(selector)
512 .treatment(treatment)
513 .ingressPoints(ingressPoints)
514 .egressPoint(dstHost.location())
515 .build();
516
517 intentService.submit(intent);
Simon Huntd2862c32015-08-24 17:41:51 -0700518 if (overlayCache.isActive(TrafficOverlay.TRAFFIC_ID)) {
519 traffic.monitor(intent);
520 }
Simon Huntd2747a02015-04-30 22:41:16 -0700521 }
522 }
523
Simon Hunta17fa672015-08-19 18:42:22 -0700524 // ========= -----------------------------------------------------------------
Simon Huntd2747a02015-04-30 22:41:16 -0700525
Thomas Vachuskaf0397b52015-05-29 13:50:17 -0700526 private final class ReqAllFlowTraffic extends RequestHandler {
527 private ReqAllFlowTraffic() {
528 super(REQ_ALL_FLOW_TRAFFIC);
Simon Huntd2747a02015-04-30 22:41:16 -0700529 }
530
531 @Override
532 public void process(long sid, ObjectNode payload) {
Simon Hunt4fc86852015-08-20 17:57:52 -0700533 traffic.monitor(Mode.ALL_FLOW_TRAFFIC);
Thomas Vachuskaf0397b52015-05-29 13:50:17 -0700534 }
535 }
536
537 private final class ReqAllPortTraffic extends RequestHandler {
538 private ReqAllPortTraffic() {
539 super(REQ_ALL_PORT_TRAFFIC);
540 }
541
542 @Override
543 public void process(long sid, ObjectNode payload) {
Simon Hunt4fc86852015-08-20 17:57:52 -0700544 traffic.monitor(Mode.ALL_PORT_TRAFFIC);
Simon Huntd2747a02015-04-30 22:41:16 -0700545 }
546 }
547
548 private final class ReqDevLinkFlows extends RequestHandler {
549 private ReqDevLinkFlows() {
550 super(REQ_DEV_LINK_FLOWS);
551 }
552
553 @Override
554 public void process(long sid, ObjectNode payload) {
Simon Hunta17fa672015-08-19 18:42:22 -0700555 NodeSelection nodeSelection =
Prince Pereira46c82d42016-09-19 13:30:50 +0530556 new NodeSelection(payload, deviceService, hostService, linkService);
Simon Hunt4fc86852015-08-20 17:57:52 -0700557 traffic.monitor(Mode.DEV_LINK_FLOWS, nodeSelection);
Simon Hunta17fa672015-08-19 18:42:22 -0700558 }
559 }
560
561 private final class ReqRelatedIntents extends RequestHandler {
562 private ReqRelatedIntents() {
563 super(REQ_RELATED_INTENTS);
564 }
565
566 @Override
567 public void process(long sid, ObjectNode payload) {
568 NodeSelection nodeSelection =
Prince Pereira46c82d42016-09-19 13:30:50 +0530569 new NodeSelection(payload, deviceService, hostService, linkService);
Simon Hunt4fc86852015-08-20 17:57:52 -0700570 traffic.monitor(Mode.RELATED_INTENTS, nodeSelection);
Simon Hunta17fa672015-08-19 18:42:22 -0700571 }
572 }
573
574 private final class ReqNextIntent extends RequestHandler {
575 private ReqNextIntent() {
576 super(REQ_NEXT_INTENT);
577 }
578
579 @Override
580 public void process(long sid, ObjectNode payload) {
Simon Hunt4fc86852015-08-20 17:57:52 -0700581 traffic.selectNextIntent();
Simon Hunta17fa672015-08-19 18:42:22 -0700582 }
583 }
584
585 private final class ReqPrevIntent extends RequestHandler {
586 private ReqPrevIntent() {
587 super(REQ_PREV_INTENT);
588 }
589
590 @Override
591 public void process(long sid, ObjectNode payload) {
Simon Hunt4fc86852015-08-20 17:57:52 -0700592 traffic.selectPreviousIntent();
Simon Hunta17fa672015-08-19 18:42:22 -0700593 }
594 }
595
596 private final class ReqSelectedIntentTraffic extends RequestHandler {
597 private ReqSelectedIntentTraffic() {
598 super(REQ_SEL_INTENT_TRAFFIC);
599 }
600
601 @Override
602 public void process(long sid, ObjectNode payload) {
Simon Hunt4fc86852015-08-20 17:57:52 -0700603 traffic.monitor(Mode.SELECTED_INTENT);
Simon Huntd2747a02015-04-30 22:41:16 -0700604 }
605 }
606
Simon Hunt4a6b54b2015-10-27 22:08:25 -0700607 private final class SelIntent extends RequestHandler {
608 private SelIntent() {
609 super(SEL_INTENT);
610 }
611
612 @Override
613 public void process(long sid, ObjectNode payload) {
Viswanath KSP0f297702016-08-13 18:02:43 +0530614 Intent intent = findIntentByPayload(payload);
Simon Hunt4a6b54b2015-10-27 22:08:25 -0700615 if (intent == null) {
Viswanath KSP0f297702016-08-13 18:02:43 +0530616 log.warn("Unable to find intent from payload {}", payload);
Simon Hunt4a6b54b2015-10-27 22:08:25 -0700617 } else {
Viswanath KSP0f297702016-08-13 18:02:43 +0530618 log.debug("starting to monitor intent {}", intent.key());
Simon Hunt4a6b54b2015-10-27 22:08:25 -0700619 traffic.monitor(intent);
620 }
621 }
622 }
623
Simon Huntd2747a02015-04-30 22:41:16 -0700624 private final class CancelTraffic extends RequestHandler {
625 private CancelTraffic() {
626 super(CANCEL_TRAFFIC);
627 }
628
629 @Override
630 public void process(long sid, ObjectNode payload) {
Simon Hunt4fc86852015-08-20 17:57:52 -0700631 traffic.stopMonitoring();
Simon Huntd2747a02015-04-30 22:41:16 -0700632 }
633 }
634
635 //=======================================================================
636
Simon Hunta17fa672015-08-19 18:42:22 -0700637 // Converts highlights to JSON format and sends the message to the client
638 protected void sendHighlights(Highlights highlights) {
Simon Hunt52560662015-08-27 22:46:44 -0700639 sendMessage(highlightsMessage(highlights));
Thomas Vachuska329af532015-03-10 02:08:33 -0700640 }
641
Simon Huntd2747a02015-04-30 22:41:16 -0700642 // Subscribes for summary messages.
643 private synchronized void requestSummary(long sid) {
Simon Hunt0af1ec32015-07-24 12:17:55 -0700644 PropertyPanel pp = summmaryMessage(sid);
645 overlayCache.currentOverlay().modifySummary(pp);
Simon Huntd3ceffa2015-08-25 12:44:35 -0700646 sendMessage(envelope(SHOW_SUMMARY, sid, json(pp)));
Thomas Vachuska329af532015-03-10 02:08:33 -0700647 }
648
Simon Huntd2747a02015-04-30 22:41:16 -0700649
Thomas Vachuska329af532015-03-10 02:08:33 -0700650 private void cancelAllRequests() {
651 stopSummaryMonitoring();
Simon Hunt4fc86852015-08-20 17:57:52 -0700652 traffic.stopMonitoring();
Thomas Vachuska329af532015-03-10 02:08:33 -0700653 }
654
655 // Sends all controller nodes to the client as node-added messages.
656 private void sendAllInstances(String messageType) {
657 List<ControllerNode> nodes = new ArrayList<>(clusterService.getNodes());
658 Collections.sort(nodes, NODE_COMPARATOR);
659 for (ControllerNode node : nodes) {
660 sendMessage(instanceMessage(new ClusterEvent(INSTANCE_ADDED, node),
Simon Hunt5c1a9382016-06-01 19:35:35 -0700661 messageType));
Thomas Vachuska329af532015-03-10 02:08:33 -0700662 }
663 }
664
665 // Sends all devices to the client as device-added messages.
666 private void sendAllDevices() {
667 // Send optical first, others later for layered rendering
668 for (Device device : deviceService.getDevices()) {
Rimon Ashkenazy8ebfff02016-02-01 11:56:36 +0200669 if ((device.type() == Device.Type.ROADM) ||
Simon Hunt5c1a9382016-06-01 19:35:35 -0700670 (device.type() == Device.Type.OTN)) {
Thomas Vachuska329af532015-03-10 02:08:33 -0700671 sendMessage(deviceMessage(new DeviceEvent(DEVICE_ADDED, device)));
672 }
673 }
674 for (Device device : deviceService.getDevices()) {
Rimon Ashkenazy8ebfff02016-02-01 11:56:36 +0200675 if ((device.type() != Device.Type.ROADM) &&
Simon Hunt5c1a9382016-06-01 19:35:35 -0700676 (device.type() != Device.Type.OTN)) {
Thomas Vachuska329af532015-03-10 02:08:33 -0700677 sendMessage(deviceMessage(new DeviceEvent(DEVICE_ADDED, device)));
678 }
679 }
680 }
681
682 // Sends all links to the client as link-added messages.
683 private void sendAllLinks() {
684 // Send optical first, others later for layered rendering
685 for (Link link : linkService.getLinks()) {
686 if (link.type() == Link.Type.OPTICAL) {
Simon Hunt5c1a9382016-06-01 19:35:35 -0700687 sendMessage(composeLinkMessage(new LinkEvent(LINK_ADDED, link)));
Thomas Vachuska329af532015-03-10 02:08:33 -0700688 }
689 }
690 for (Link link : linkService.getLinks()) {
691 if (link.type() != Link.Type.OPTICAL) {
Simon Hunt5c1a9382016-06-01 19:35:35 -0700692 sendMessage(composeLinkMessage(new LinkEvent(LINK_ADDED, link)));
Thomas Vachuska329af532015-03-10 02:08:33 -0700693 }
694 }
695 }
696
Simon Hunt5c1a9382016-06-01 19:35:35 -0700697 // Temporary mechanism to support topology overlays adding their own
698 // properties to the link events.
699 private ObjectNode composeLinkMessage(LinkEvent event) {
700 // start with base message
701 ObjectNode msg = linkMessage(event);
702 Map<String, String> additional =
703 overlayCache.currentOverlay().additionalLinkData(event);
704
705 if (additional != null) {
706 // attach additional key-value pairs as extra data structure
707 ObjectNode payload = (ObjectNode) msg.get(PAYLOAD);
708 payload.set(EXTRA, createExtra(additional));
709 }
710 return msg;
711 }
712
713 private ObjectNode createExtra(Map<String, String> additional) {
714 ObjectNode extra = objectNode();
715 for (Map.Entry<String, String> entry : additional.entrySet()) {
716 extra.put(entry.getKey(), entry.getValue());
717 }
718 return extra;
719 }
720
Thomas Vachuska329af532015-03-10 02:08:33 -0700721 // Sends all hosts to the client as host-added messages.
722 private void sendAllHosts() {
723 for (Host host : hostService.getHosts()) {
724 sendMessage(hostMessage(new HostEvent(HOST_ADDED, host)));
725 }
726 }
727
Thomas Vachuska329af532015-03-10 02:08:33 -0700728 private Set<ConnectPoint> getHostLocations(Set<HostId> hostIds) {
729 Set<ConnectPoint> points = new HashSet<>();
730 for (HostId hostId : hostIds) {
731 points.add(getHostLocation(hostId));
732 }
733 return points;
734 }
735
736 private HostLocation getHostLocation(HostId hostId) {
737 return hostService.getHost(hostId).location();
738 }
739
740 // Produces a list of host ids from the specified JSON array.
741 private Set<HostId> getHostIds(ArrayNode ids) {
742 Set<HostId> hostIds = new HashSet<>();
743 for (JsonNode id : ids) {
744 hostIds.add(hostId(id.asText()));
745 }
746 return hostIds;
747 }
748
Simon Hunt4a6b54b2015-10-27 22:08:25 -0700749 private void sendTopoStartDone() {
750 sendMessage(JsonUtils.envelope(TOPO_START_DONE, objectNode()));
751 }
Thomas Vachuska329af532015-03-10 02:08:33 -0700752
Simon Huntd2747a02015-04-30 22:41:16 -0700753 private synchronized void startSummaryMonitoring() {
Thomas Vachuska329af532015-03-10 02:08:33 -0700754 stopSummaryMonitoring();
Thomas Vachuska329af532015-03-10 02:08:33 -0700755 summaryTask = new SummaryMonitor();
Simon Hunta17fa672015-08-19 18:42:22 -0700756 timer.schedule(summaryTask, SUMMARY_PERIOD, SUMMARY_PERIOD);
Simon Huntd2747a02015-04-30 22:41:16 -0700757 summaryRunning = true;
Thomas Vachuska329af532015-03-10 02:08:33 -0700758 }
759
760 private synchronized void stopSummaryMonitoring() {
Simon Huntd2747a02015-04-30 22:41:16 -0700761 if (summaryTask != null) {
Thomas Vachuska329af532015-03-10 02:08:33 -0700762 summaryTask.cancel();
763 summaryTask = null;
Thomas Vachuska329af532015-03-10 02:08:33 -0700764 }
Simon Huntd2747a02015-04-30 22:41:16 -0700765 summaryRunning = false;
Thomas Vachuska9ed335b2015-04-14 12:07:47 -0700766 }
767
Thomas Vachuska329af532015-03-10 02:08:33 -0700768
769 // Adds all internal listeners.
Thomas Vachuska35fa3d42015-04-30 10:11:47 -0700770 private synchronized void addListeners() {
Thomas Vachuskae586b792015-03-26 13:59:38 -0700771 listenersRemoved = false;
Thomas Vachuska329af532015-03-10 02:08:33 -0700772 clusterService.addListener(clusterListener);
773 mastershipService.addListener(mastershipListener);
774 deviceService.addListener(deviceListener);
775 linkService.addListener(linkListener);
776 hostService.addListener(hostListener);
777 intentService.addListener(intentListener);
778 flowService.addListener(flowListener);
779 }
780
781 // Removes all internal listeners.
782 private synchronized void removeListeners() {
783 if (!listenersRemoved) {
784 listenersRemoved = true;
785 clusterService.removeListener(clusterListener);
786 mastershipService.removeListener(mastershipListener);
787 deviceService.removeListener(deviceListener);
788 linkService.removeListener(linkListener);
789 hostService.removeListener(hostListener);
790 intentService.removeListener(intentListener);
791 flowService.removeListener(flowListener);
792 }
793 }
794
795 // Cluster event listener.
Simon Hunt7092cc42016-04-06 18:40:17 -0700796 // TODO: Superceded by UiSharedTopologyModel.ModelEventListener
797 @Deprecated
Thomas Vachuska329af532015-03-10 02:08:33 -0700798 private class InternalClusterListener implements ClusterEventListener {
799 @Override
800 public void event(ClusterEvent event) {
Thomas Vachuskac7f79962015-05-28 09:37:34 -0700801 msgSender.execute(() -> sendMessage(instanceMessage(event, null)));
Thomas Vachuska329af532015-03-10 02:08:33 -0700802 }
803 }
804
805 // Mastership change listener
Simon Hunt7092cc42016-04-06 18:40:17 -0700806 // TODO: Superceded by UiSharedTopologyModel.ModelEventListener
807 @Deprecated
Thomas Vachuska329af532015-03-10 02:08:33 -0700808 private class InternalMastershipListener implements MastershipListener {
809 @Override
810 public void event(MastershipEvent event) {
Thomas Vachuska52c98bd2015-05-27 20:54:02 -0700811 msgSender.execute(() -> {
Simon Huntb745ca62015-07-28 15:37:11 -0700812 sendAllInstances(UPDATE_INSTANCE);
Thomas Vachuska52c98bd2015-05-27 20:54:02 -0700813 Device device = deviceService.getDevice(event.subject());
814 if (device != null) {
815 sendMessage(deviceMessage(new DeviceEvent(DEVICE_UPDATED, device)));
816 }
817 });
Thomas Vachuska329af532015-03-10 02:08:33 -0700818 }
819 }
820
821 // Device event listener.
Simon Hunt7092cc42016-04-06 18:40:17 -0700822 // TODO: Superceded by UiSharedTopologyModel.ModelEventListener
823 @Deprecated
Thomas Vachuska329af532015-03-10 02:08:33 -0700824 private class InternalDeviceListener implements DeviceListener {
825 @Override
826 public void event(DeviceEvent event) {
Thomas Vachuskacb5016f2015-05-18 14:11:43 -0700827 if (event.type() != PORT_STATS_UPDATED) {
Thomas Vachuskac7f79962015-05-28 09:37:34 -0700828 msgSender.execute(() -> sendMessage(deviceMessage(event)));
Simon Hunta1f1c022016-03-03 15:54:57 -0800829 msgSender.execute(traffic::pokeIntent);
Thomas Vachuskacb5016f2015-05-18 14:11:43 -0700830 eventAccummulator.add(event);
831 }
Thomas Vachuska329af532015-03-10 02:08:33 -0700832 }
833 }
834
835 // Link event listener.
Simon Hunt7092cc42016-04-06 18:40:17 -0700836 // TODO: Superceded by UiSharedTopologyModel.ModelEventListener
837 @Deprecated
Thomas Vachuska329af532015-03-10 02:08:33 -0700838 private class InternalLinkListener implements LinkListener {
839 @Override
840 public void event(LinkEvent event) {
Simon Hunt5c1a9382016-06-01 19:35:35 -0700841 msgSender.execute(() -> sendMessage(composeLinkMessage(event)));
Simon Hunta1f1c022016-03-03 15:54:57 -0800842 msgSender.execute(traffic::pokeIntent);
Thomas Vachuska329af532015-03-10 02:08:33 -0700843 eventAccummulator.add(event);
844 }
845 }
846
847 // Host event listener.
Simon Hunt7092cc42016-04-06 18:40:17 -0700848 // TODO: Superceded by UiSharedTopologyModel.ModelEventListener
849 @Deprecated
Thomas Vachuska329af532015-03-10 02:08:33 -0700850 private class InternalHostListener implements HostListener {
851 @Override
852 public void event(HostEvent event) {
Thomas Vachuskac7f79962015-05-28 09:37:34 -0700853 msgSender.execute(() -> sendMessage(hostMessage(event)));
Simon Hunta1f1c022016-03-03 15:54:57 -0800854 msgSender.execute(traffic::pokeIntent);
Thomas Vachuska329af532015-03-10 02:08:33 -0700855 eventAccummulator.add(event);
856 }
857 }
858
859 // Intent event listener.
Simon Hunt7092cc42016-04-06 18:40:17 -0700860 // TODO: Superceded by UiSharedTopologyModel.ModelEventListener
861 @Deprecated
Thomas Vachuska329af532015-03-10 02:08:33 -0700862 private class InternalIntentListener implements IntentListener {
863 @Override
864 public void event(IntentEvent event) {
Simon Hunt4fc86852015-08-20 17:57:52 -0700865 msgSender.execute(traffic::pokeIntent);
Thomas Vachuska329af532015-03-10 02:08:33 -0700866 eventAccummulator.add(event);
867 }
868 }
869
870 // Intent event listener.
Simon Hunt7092cc42016-04-06 18:40:17 -0700871 // TODO: Superceded by UiSharedTopologyModel.ModelEventListener
872 @Deprecated
Thomas Vachuska329af532015-03-10 02:08:33 -0700873 private class InternalFlowListener implements FlowRuleListener {
874 @Override
875 public void event(FlowRuleEvent event) {
876 eventAccummulator.add(event);
877 }
878 }
879
Simon Huntd2747a02015-04-30 22:41:16 -0700880
Simon Hunta17fa672015-08-19 18:42:22 -0700881 // === SUMMARY MONITORING
Thomas Vachuska329af532015-03-10 02:08:33 -0700882
883 // Periodic update of the summary information
884 private class SummaryMonitor extends TimerTask {
885 @Override
886 public void run() {
887 try {
Simon Huntd2747a02015-04-30 22:41:16 -0700888 if (summaryRunning) {
Thomas Vachuskac7f79962015-05-28 09:37:34 -0700889 msgSender.execute(() -> requestSummary(0));
Thomas Vachuska329af532015-03-10 02:08:33 -0700890 }
891 } catch (Exception e) {
892 log.warn("Unable to handle summary request due to {}", e.getMessage());
893 log.warn("Boom!", e);
894 }
895 }
896 }
897
898 // Accumulates events to drive methodic update of the summary pane.
899 private class InternalEventAccummulator extends AbstractAccumulator<Event> {
900 protected InternalEventAccummulator() {
901 super(new Timer("topo-summary"), MAX_EVENTS, MAX_BATCH_MS, MAX_IDLE_MS);
902 }
903
904 @Override
905 public void processItems(List<Event> items) {
Simon Hunta17fa672015-08-19 18:42:22 -0700906 // Start-of-Debugging -- Keep in until ONOS-2572 is fixed for reals
Simon Hunt8d22c4b2015-08-06 16:24:43 -0700907 long now = System.currentTimeMillis();
908 String me = this.toString();
909 String miniMe = me.replaceAll("^.*@", "me@");
910 log.debug("Time: {}; this: {}, processing items ({} events)",
Simon Hunt5c1a9382016-06-01 19:35:35 -0700911 now, miniMe, items.size());
Simon Hunt8d22c4b2015-08-06 16:24:43 -0700912 // End-of-Debugging
913
Thomas Vachuska329af532015-03-10 02:08:33 -0700914 try {
Simon Huntd2747a02015-04-30 22:41:16 -0700915 if (summaryRunning) {
Thomas Vachuskac7f79962015-05-28 09:37:34 -0700916 msgSender.execute(() -> requestSummary(0));
Thomas Vachuska329af532015-03-10 02:08:33 -0700917 }
918 } catch (Exception e) {
919 log.warn("Unable to handle summary request due to {}", e.getMessage());
920 log.debug("Boom!", e);
921 }
922 }
923 }
924}