blob: 3cbce06e091f881898d2b7a1e7ceb7d5d158cb20 [file] [log] [blame]
Thomas Vachuska329af532015-03-10 02:08:33 -07001/*
Brian O'Connora09fe5b2017-08-03 21:12:30 -07002 * Copyright 2015-present Open Networking Foundation
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;
Thomas Vachuska329af532015-03-10 02:08:33 -070032import org.onosproject.mastership.MastershipEvent;
33import org.onosproject.mastership.MastershipListener;
34import org.onosproject.net.ConnectPoint;
35import org.onosproject.net.Device;
Simon Huntde99e0b2015-10-23 18:54:06 -070036import org.onosproject.net.DeviceId;
Thomas Vachuska329af532015-03-10 02:08:33 -070037import org.onosproject.net.Host;
38import org.onosproject.net.HostId;
39import org.onosproject.net.HostLocation;
40import org.onosproject.net.Link;
41import org.onosproject.net.device.DeviceEvent;
42import org.onosproject.net.device.DeviceListener;
43import org.onosproject.net.flow.DefaultTrafficSelector;
44import org.onosproject.net.flow.DefaultTrafficTreatment;
45import org.onosproject.net.flow.FlowRuleEvent;
46import org.onosproject.net.flow.FlowRuleListener;
47import org.onosproject.net.flow.TrafficSelector;
48import org.onosproject.net.flow.TrafficTreatment;
49import org.onosproject.net.host.HostEvent;
50import org.onosproject.net.host.HostListener;
51import org.onosproject.net.intent.HostToHostIntent;
Simon Hunt4a6b54b2015-10-27 22:08:25 -070052import org.onosproject.net.intent.Intent;
Thomas Vachuska329af532015-03-10 02:08:33 -070053import org.onosproject.net.intent.IntentEvent;
54import org.onosproject.net.intent.IntentListener;
Deepa Vaddireddy63340922017-01-19 08:15:31 +053055import org.onosproject.net.intent.IntentService;
Andrea Campanella732ea832017-02-06 09:25:59 -080056import org.onosproject.net.intent.IntentState;
Simon Hunt21281fd2017-03-30 22:28:28 -070057import org.onosproject.net.intent.Key;
58import org.onosproject.net.intent.MultiPointToSinglePointIntent;
Thomas Vachuska329af532015-03-10 02:08:33 -070059import org.onosproject.net.link.LinkEvent;
60import org.onosproject.net.link.LinkListener;
Simon Hunt4a6b54b2015-10-27 22:08:25 -070061import org.onosproject.ui.JsonUtils;
Simon Huntd2747a02015-04-30 22:41:16 -070062import org.onosproject.ui.RequestHandler;
Thomas Vachuska329af532015-03-10 02:08:33 -070063import org.onosproject.ui.UiConnection;
Simon Hunt1911fe42017-05-02 18:25:58 -070064import org.onosproject.ui.impl.TrafficMonitorBase.Mode;
Simon Hunta17fa672015-08-19 18:42:22 -070065import org.onosproject.ui.topo.Highlights;
Simon Huntd3ceffa2015-08-25 12:44:35 -070066import org.onosproject.ui.topo.NodeSelection;
Simon Hunt0af1ec32015-07-24 12:17:55 -070067import org.onosproject.ui.topo.PropertyPanel;
Thomas Vachuska329af532015-03-10 02:08:33 -070068
69import java.util.ArrayList;
Simon Huntd2747a02015-04-30 22:41:16 -070070import java.util.Collection;
Thomas Vachuska329af532015-03-10 02:08:33 -070071import 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 Hunt879ce452017-08-10 23:32:00 -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";
Deepa Vaddireddy63340922017-01-19 08:15:31 +0530105 private static final String REMOVE_INTENTS = "removeIntents";
Viswanath KSP14aee092016-10-02 01:47:40 +0530106 private static final String RESUBMIT_INTENT = "resubmitIntent";
Simon Huntd2747a02015-04-30 22:41:16 -0700107 private static final String ADD_MULTI_SRC_INTENT = "addMultiSourceIntent";
108 private static final String REQ_RELATED_INTENTS = "requestRelatedIntents";
109 private static final String REQ_NEXT_INTENT = "requestNextRelatedIntent";
110 private static final String REQ_PREV_INTENT = "requestPrevRelatedIntent";
111 private static final String REQ_SEL_INTENT_TRAFFIC = "requestSelectedIntentTraffic";
Simon Hunt4a6b54b2015-10-27 22:08:25 -0700112 private static final String SEL_INTENT = "selectIntent";
Simon Hunt21281fd2017-03-30 22:28:28 -0700113 private static final String REQ_ALL_TRAFFIC = "requestAllTraffic";
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 Hunte05cae42015-07-23 17:35:24 -0700122 private static final String TOPO_SELECT_OVERLAY = "topoSelectOverlay";
Simon Huntd2747a02015-04-30 22:41:16 -0700123 private static final String TOPO_STOP = "topoStop";
Andrea Campanella732ea832017-02-06 09:25:59 -0800124 private static final String SEL_PROTECTED_INTENT = "selectProtectedIntent";
125 private static final String CANCEL_PROTECTED_INTENT_HIGHLIGHT = "cancelProtectedIntentHighlight";
126
Simon Huntb745ca62015-07-28 15:37:11 -0700127 // outgoing event types
128 private static final String SHOW_SUMMARY = "showSummary";
129 private static final String SHOW_DETAILS = "showDetails";
130 private static final String SPRITE_LIST_RESPONSE = "spriteListResponse";
131 private static final String SPRITE_DATA_RESPONSE = "spriteDataResponse";
132 private static final String UPDATE_INSTANCE = "updateInstance";
Simon Hunt4a6b54b2015-10-27 22:08:25 -0700133 private static final String TOPO_START_DONE = "topoStartDone";
Simon Huntb745ca62015-07-28 15:37:11 -0700134
135 // fields
Simon Hunt5c1a9382016-06-01 19:35:35 -0700136 private static final String PAYLOAD = "payload";
137 private static final String EXTRA = "extra";
Simon Huntb745ca62015-07-28 15:37:11 -0700138 private static final String ID = "id";
Simon Hunt4a6b54b2015-10-27 22:08:25 -0700139 private static final String KEY = "key";
140 private static final String APP_ID = "appId";
141 private static final String APP_NAME = "appName";
Simon Huntb745ca62015-07-28 15:37:11 -0700142 private static final String DEVICE = "device";
143 private static final String HOST = "host";
144 private static final String CLASS = "class";
145 private static final String UNKNOWN = "unknown";
146 private static final String ONE = "one";
147 private static final String TWO = "two";
148 private static final String SRC = "src";
149 private static final String DST = "dst";
150 private static final String DATA = "data";
151 private static final String NAME = "name";
152 private static final String NAMES = "names";
153 private static final String ACTIVATE = "activate";
154 private static final String DEACTIVATE = "deactivate";
Viswanath KSP813a20d2016-09-13 04:25:41 +0530155 private static final String PURGE = "purge";
Simon Hunt21281fd2017-03-30 22:28:28 -0700156 private static final String TRAFFIC_TYPE = "trafficType";
Simon Huntb745ca62015-07-28 15:37:11 -0700157
Simon Hunt21281fd2017-03-30 22:28:28 -0700158 // field values
159 private static final String FLOW_STATS_BYTES = "flowStatsBytes";
160 private static final String PORT_STATS_BIT_SEC = "portStatsBitSec";
161 private static final String PORT_STATS_PKT_SEC = "portStatsPktSec";
Simon Huntd2747a02015-04-30 22:41:16 -0700162
Simon Hunt4a6b54b2015-10-27 22:08:25 -0700163 private static final String MY_APP_ID = "org.onosproject.gui";
Thomas Vachuska329af532015-03-10 02:08:33 -0700164
Simon Hunta17fa672015-08-19 18:42:22 -0700165 private static final long TRAFFIC_PERIOD = 5000;
166 private static final long SUMMARY_PERIOD = 30000;
Thomas Vachuska329af532015-03-10 02:08:33 -0700167
168 private static final Comparator<? super ControllerNode> NODE_COMPARATOR =
Simon Hunt8a0429a2017-01-06 16:52:47 -0800169 Comparator.comparing(o -> o.id().toString());
Thomas Vachuska329af532015-03-10 02:08:33 -0700170
171
Thomas Vachuska52c98bd2015-05-27 20:54:02 -0700172 private final Timer timer = new Timer("onos-topology-view");
Thomas Vachuska329af532015-03-10 02:08:33 -0700173
174 private static final int MAX_EVENTS = 1000;
175 private static final int MAX_BATCH_MS = 5000;
176 private static final int MAX_IDLE_MS = 1000;
177
178 private ApplicationId appId;
179
180 private final ClusterEventListener clusterListener = new InternalClusterListener();
181 private final MastershipListener mastershipListener = new InternalMastershipListener();
182 private final DeviceListener deviceListener = new InternalDeviceListener();
183 private final LinkListener linkListener = new InternalLinkListener();
184 private final HostListener hostListener = new InternalHostListener();
185 private final IntentListener intentListener = new InternalIntentListener();
186 private final FlowRuleListener flowListener = new InternalFlowListener();
187
188 private final Accumulator<Event> eventAccummulator = new InternalEventAccummulator();
Thomas Vachuska52c98bd2015-05-27 20:54:02 -0700189 private final ExecutorService msgSender =
Yuta HIGUCHI1624df12016-07-21 16:54:33 -0700190 newSingleThreadExecutor(groupedThreads("onos/gui", "msg-sender", log));
Thomas Vachuska329af532015-03-10 02:08:33 -0700191
Simon Hunta17fa672015-08-19 18:42:22 -0700192 private TopoOverlayCache overlayCache;
Simon Hunt4fc86852015-08-20 17:57:52 -0700193 private TrafficMonitor traffic;
Andrea Campanella732ea832017-02-06 09:25:59 -0800194 private ProtectedIntentMonitor protectedIntentMonitor;
Thomas Vachuska329af532015-03-10 02:08:33 -0700195
Simon Huntd2747a02015-04-30 22:41:16 -0700196 private TimerTask summaryTask = null;
197 private boolean summaryRunning = false;
Thomas Vachuska329af532015-03-10 02:08:33 -0700198
Simon Huntd5b96732016-07-08 13:22:27 -0700199 private volatile boolean listenersRemoved = false;
Thomas Vachuska329af532015-03-10 02:08:33 -0700200
Thomas Vachuska329af532015-03-10 02:08:33 -0700201
202 @Override
203 public void init(UiConnection connection, ServiceDirectory directory) {
204 super.init(connection, directory);
Simon Hunt4a6b54b2015-10-27 22:08:25 -0700205 appId = directory.get(CoreService.class).registerApplication(MY_APP_ID);
Simon Hunt1911fe42017-05-02 18:25:58 -0700206 traffic = new TrafficMonitor(TRAFFIC_PERIOD, services, this);
207 protectedIntentMonitor = new ProtectedIntentMonitor(TRAFFIC_PERIOD, services, this);
Thomas Vachuska329af532015-03-10 02:08:33 -0700208 }
209
210 @Override
211 public void destroy() {
212 cancelAllRequests();
Thomas Vachuska2bb48632015-04-28 14:40:42 -0700213 removeListeners();
Thomas Vachuska329af532015-03-10 02:08:33 -0700214 super.destroy();
215 }
216
Thomas Vachuska329af532015-03-10 02:08:33 -0700217 @Override
Simon Huntda580882015-05-12 20:58:18 -0700218 protected Collection<RequestHandler> createRequestHandlers() {
Simon Huntd2747a02015-04-30 22:41:16 -0700219 return ImmutableSet.of(
220 new TopoStart(),
Simon Hunte05cae42015-07-23 17:35:24 -0700221 new TopoSelectOverlay(),
Simon Huntd2747a02015-04-30 22:41:16 -0700222 new TopoStop(),
223 new ReqSummary(),
224 new CancelSummary(),
225 new SpriteListReq(),
226 new SpriteDataReq(),
227 new RequestDetails(),
228 new UpdateMeta(),
229 new EqMasters(),
Thomas Vachuska329af532015-03-10 02:08:33 -0700230
Simon Huntd2747a02015-04-30 22:41:16 -0700231 // TODO: migrate traffic related to separate app
232 new AddHostIntent(),
233 new AddMultiSourceIntent(),
Viswanath KSP0f297702016-08-13 18:02:43 +0530234 new RemoveIntent(),
Viswanath KSP14aee092016-10-02 01:47:40 +0530235 new ResubmitIntent(),
Deepa Vaddireddy63340922017-01-19 08:15:31 +0530236 new RemoveIntents(),
Simon Hunta17fa672015-08-19 18:42:22 -0700237
Simon Hunt21281fd2017-03-30 22:28:28 -0700238 new ReqAllTraffic(),
Simon Hunta17fa672015-08-19 18:42:22 -0700239 new ReqDevLinkFlows(),
Simon Huntd2747a02015-04-30 22:41:16 -0700240 new ReqRelatedIntents(),
241 new ReqNextIntent(),
242 new ReqPrevIntent(),
243 new ReqSelectedIntentTraffic(),
Simon Hunt4a6b54b2015-10-27 22:08:25 -0700244 new SelIntent(),
Andrea Campanella732ea832017-02-06 09:25:59 -0800245 new SelProtectedIntent(),
Simon Hunta17fa672015-08-19 18:42:22 -0700246
Andrea Campanella732ea832017-02-06 09:25:59 -0800247 new CancelTraffic(),
248 new CancelProtectedIntentHighlight()
Simon Huntd2747a02015-04-30 22:41:16 -0700249 );
250 }
Thomas Vachuska329af532015-03-10 02:08:33 -0700251
Simon Hunte05cae42015-07-23 17:35:24 -0700252 /**
253 * Injects the topology overlay cache.
254 *
255 * @param overlayCache injected cache
256 */
257 void setOverlayCache(TopoOverlayCache overlayCache) {
258 this.overlayCache = overlayCache;
259 }
260
Simon Huntd2747a02015-04-30 22:41:16 -0700261 // ==================================================================
Thomas Vachuska329af532015-03-10 02:08:33 -0700262
Simon Huntd2747a02015-04-30 22:41:16 -0700263 private final class TopoStart extends RequestHandler {
264 private TopoStart() {
265 super(TOPO_START);
266 }
Thomas Vachuska329af532015-03-10 02:08:33 -0700267
Simon Huntd2747a02015-04-30 22:41:16 -0700268 @Override
Simon Hunt8a0429a2017-01-06 16:52:47 -0800269 public void process(ObjectNode payload) {
Simon Huntd2747a02015-04-30 22:41:16 -0700270 addListeners();
271 sendAllInstances(null);
272 sendAllDevices();
273 sendAllLinks();
274 sendAllHosts();
Simon Hunt4a6b54b2015-10-27 22:08:25 -0700275 sendTopoStartDone();
Thomas Vachuska329af532015-03-10 02:08:33 -0700276 }
277 }
278
Simon Hunte05cae42015-07-23 17:35:24 -0700279 private final class TopoSelectOverlay extends RequestHandler {
280 private TopoSelectOverlay() {
281 super(TOPO_SELECT_OVERLAY);
282 }
283
284 @Override
Simon Hunt8a0429a2017-01-06 16:52:47 -0800285 public void process(ObjectNode payload) {
Simon Huntb745ca62015-07-28 15:37:11 -0700286 String deact = string(payload, DEACTIVATE);
287 String act = string(payload, ACTIVATE);
Simon Hunte05cae42015-07-23 17:35:24 -0700288 overlayCache.switchOverlay(deact, act);
289 }
290 }
291
Simon Huntd2747a02015-04-30 22:41:16 -0700292 private final class TopoStop extends RequestHandler {
293 private TopoStop() {
294 super(TOPO_STOP);
295 }
296
297 @Override
Simon Hunt8a0429a2017-01-06 16:52:47 -0800298 public void process(ObjectNode payload) {
Simon Hunt1ad59272015-11-10 15:23:21 -0800299 removeListeners();
Simon Huntd2747a02015-04-30 22:41:16 -0700300 stopSummaryMonitoring();
Simon Hunt4fc86852015-08-20 17:57:52 -0700301 traffic.stopMonitoring();
Simon Huntd2747a02015-04-30 22:41:16 -0700302 }
303 }
304
305 private final class ReqSummary extends RequestHandler {
306 private ReqSummary() {
307 super(REQ_SUMMARY);
308 }
309
310 @Override
Simon Hunt8a0429a2017-01-06 16:52:47 -0800311 public void process(ObjectNode payload) {
312 requestSummary();
Simon Huntd2747a02015-04-30 22:41:16 -0700313 startSummaryMonitoring();
314 }
315 }
316
317 private final class CancelSummary extends RequestHandler {
318 private CancelSummary() {
319 super(CANCEL_SUMMARY);
320 }
321
322 @Override
Simon Hunt8a0429a2017-01-06 16:52:47 -0800323 public void process(ObjectNode payload) {
Simon Huntd2747a02015-04-30 22:41:16 -0700324 stopSummaryMonitoring();
325 }
326 }
327
328 private final class SpriteListReq extends RequestHandler {
329 private SpriteListReq() {
330 super(SPRITE_LIST_REQ);
331 }
332
333 @Override
Simon Hunt8a0429a2017-01-06 16:52:47 -0800334 public void process(ObjectNode payload) {
Simon Huntda580882015-05-12 20:58:18 -0700335 ObjectNode root = objectNode();
336 ArrayNode names = arrayNode();
Simon Huntd2747a02015-04-30 22:41:16 -0700337 get(SpriteService.class).getNames().forEach(names::add);
Simon Huntb745ca62015-07-28 15:37:11 -0700338 root.set(NAMES, names);
Simon Hunt8a0429a2017-01-06 16:52:47 -0800339 sendMessage(SPRITE_LIST_RESPONSE, root);
Simon Huntd2747a02015-04-30 22:41:16 -0700340 }
341 }
342
343 private final class SpriteDataReq extends RequestHandler {
344 private SpriteDataReq() {
345 super(SPRITE_DATA_REQ);
346 }
347
348 @Override
Simon Hunt8a0429a2017-01-06 16:52:47 -0800349 public void process(ObjectNode payload) {
Simon Huntb745ca62015-07-28 15:37:11 -0700350 String name = string(payload, NAME);
Simon Huntda580882015-05-12 20:58:18 -0700351 ObjectNode root = objectNode();
Simon Huntb745ca62015-07-28 15:37:11 -0700352 root.set(DATA, get(SpriteService.class).get(name));
Simon Hunt8a0429a2017-01-06 16:52:47 -0800353 sendMessage(SPRITE_DATA_RESPONSE, root);
Simon Huntd2747a02015-04-30 22:41:16 -0700354 }
355 }
356
357 private final class RequestDetails extends RequestHandler {
358 private RequestDetails() {
359 super(REQ_DETAILS);
360 }
361
362 @Override
Simon Hunt8a0429a2017-01-06 16:52:47 -0800363 public void process(ObjectNode payload) {
Simon Huntb745ca62015-07-28 15:37:11 -0700364 String type = string(payload, CLASS, UNKNOWN);
365 String id = string(payload, ID);
366 PropertyPanel pp = null;
Simon Huntd2747a02015-04-30 22:41:16 -0700367
Simon Huntb745ca62015-07-28 15:37:11 -0700368 if (type.equals(DEVICE)) {
Simon Huntde99e0b2015-10-23 18:54:06 -0700369 DeviceId did = deviceId(id);
Simon Hunt8a0429a2017-01-06 16:52:47 -0800370 pp = deviceDetails(did);
Simon Huntde99e0b2015-10-23 18:54:06 -0700371 overlayCache.currentOverlay().modifyDeviceDetails(pp, did);
Simon Huntb745ca62015-07-28 15:37:11 -0700372 } else if (type.equals(HOST)) {
Simon Huntde99e0b2015-10-23 18:54:06 -0700373 HostId hid = hostId(id);
Simon Hunt8a0429a2017-01-06 16:52:47 -0800374 pp = hostDetails(hid);
Simon Huntde99e0b2015-10-23 18:54:06 -0700375 overlayCache.currentOverlay().modifyHostDetails(pp, hid);
Simon Huntd2747a02015-04-30 22:41:16 -0700376 }
Simon Huntb745ca62015-07-28 15:37:11 -0700377
Simon Hunt8a0429a2017-01-06 16:52:47 -0800378 sendMessage(envelope(SHOW_DETAILS, json(pp)));
Simon Huntd2747a02015-04-30 22:41:16 -0700379 }
380 }
381
382 private final class UpdateMeta extends RequestHandler {
383 private UpdateMeta() {
384 super(UPDATE_META);
385 }
386
387 @Override
Simon Hunt8a0429a2017-01-06 16:52:47 -0800388 public void process(ObjectNode payload) {
Simon Huntd2747a02015-04-30 22:41:16 -0700389 updateMetaUi(payload);
390 }
391 }
392
393 private final class EqMasters extends RequestHandler {
394 private EqMasters() {
395 super(EQ_MASTERS);
396 }
397
398 @Override
Simon Hunt8a0429a2017-01-06 16:52:47 -0800399 public void process(ObjectNode payload) {
Simon Hunt1911fe42017-05-02 18:25:58 -0700400 services.mastershipAdmin().balanceRoles();
Simon Huntd2747a02015-04-30 22:41:16 -0700401 }
402 }
403
Simon Hunta17fa672015-08-19 18:42:22 -0700404
405 // ========= -----------------------------------------------------------------
406
Simon Huntd2747a02015-04-30 22:41:16 -0700407 // === TODO: move traffic related classes to traffic app
408
409 private final class AddHostIntent extends RequestHandler {
410 private AddHostIntent() {
411 super(ADD_HOST_INTENT);
412 }
413
414 @Override
Simon Hunt8a0429a2017-01-06 16:52:47 -0800415 public void process(ObjectNode payload) {
Simon Huntd2747a02015-04-30 22:41:16 -0700416 // TODO: add protection against device ids and non-existent hosts.
Simon Huntb745ca62015-07-28 15:37:11 -0700417 HostId one = hostId(string(payload, ONE));
418 HostId two = hostId(string(payload, TWO));
Simon Huntd2747a02015-04-30 22:41:16 -0700419
420 HostToHostIntent intent = HostToHostIntent.builder()
Thomas Vachuskacb5016f2015-05-18 14:11:43 -0700421 .appId(appId)
422 .one(one)
423 .two(two)
424 .build();
Simon Huntd2747a02015-04-30 22:41:16 -0700425
Simon Hunt1911fe42017-05-02 18:25:58 -0700426 services.intent().submit(intent);
Simon Huntd2862c32015-08-24 17:41:51 -0700427 if (overlayCache.isActive(TrafficOverlay.TRAFFIC_ID)) {
428 traffic.monitor(intent);
429 }
Simon Huntd2747a02015-04-30 22:41:16 -0700430 }
431 }
432
Viswanath KSP0f297702016-08-13 18:02:43 +0530433 private Intent findIntentByPayload(ObjectNode payload) {
Yi Tseng3a9b01c2017-02-16 14:24:28 -0800434 Intent intent;
435 Key key;
Viswanath KSP0f297702016-08-13 18:02:43 +0530436 int appId = Integer.parseInt(string(payload, APP_ID));
437 String appName = string(payload, APP_NAME);
438 ApplicationId applicId = new DefaultApplicationId(appId, appName);
Yi Tseng3a9b01c2017-02-16 14:24:28 -0800439 String stringKey = string(payload, KEY);
440 try {
441 // FIXME: If apps use different string key, but they contains
442 // same numeric value (e.g. "020", "0x10", "16", "#10")
443 // and one intent using long key (e.g. 16L)
444 // this function might return wrong intent.
Viswanath KSP0f297702016-08-13 18:02:43 +0530445
Yi Tseng3a9b01c2017-02-16 14:24:28 -0800446 long longKey = Long.decode(stringKey);
447 key = Key.of(longKey, applicId);
Simon Hunt1911fe42017-05-02 18:25:58 -0700448 intent = services.intent().getIntent(key);
Yi Tseng3a9b01c2017-02-16 14:24:28 -0800449
450 if (intent == null) {
451 // Intent might using string key, not long key
452 key = Key.of(stringKey, applicId);
Simon Hunt1911fe42017-05-02 18:25:58 -0700453 intent = services.intent().getIntent(key);
Yi Tseng3a9b01c2017-02-16 14:24:28 -0800454 }
455 } catch (NumberFormatException ex) {
456 // string key
457 key = Key.of(stringKey, applicId);
Simon Hunt1911fe42017-05-02 18:25:58 -0700458 intent = services.intent().getIntent(key);
Yi Tseng3a9b01c2017-02-16 14:24:28 -0800459 }
460
Viswanath KSP0f297702016-08-13 18:02:43 +0530461 log.debug("Attempting to select intent by key={}", key);
462
Yi Tseng3a9b01c2017-02-16 14:24:28 -0800463 return intent;
Viswanath KSP0f297702016-08-13 18:02:43 +0530464 }
465
466 private final class RemoveIntent extends RequestHandler {
467 private RemoveIntent() {
468 super(REMOVE_INTENT);
469 }
470
Viswanath KSP813a20d2016-09-13 04:25:41 +0530471 private boolean isIntentToBePurged(ObjectNode payload) {
472 return bool(payload, PURGE);
473 }
474
Viswanath KSP0f297702016-08-13 18:02:43 +0530475 @Override
Simon Hunt8a0429a2017-01-06 16:52:47 -0800476 public void process(ObjectNode payload) {
Viswanath KSP0f297702016-08-13 18:02:43 +0530477 Intent intent = findIntentByPayload(payload);
478 if (intent == null) {
479 log.warn("Unable to find intent from payload {}", payload);
480 } else {
Viswanath KSP813a20d2016-09-13 04:25:41 +0530481 log.debug("Withdrawing / Purging intent {}", intent.key());
482 if (isIntentToBePurged(payload)) {
Simon Hunt1911fe42017-05-02 18:25:58 -0700483 services.intent().purge(intent);
Viswanath KSP813a20d2016-09-13 04:25:41 +0530484 } else {
Simon Hunt1911fe42017-05-02 18:25:58 -0700485 services.intent().withdraw(intent);
Viswanath KSP813a20d2016-09-13 04:25:41 +0530486 }
Viswanath KSP0f297702016-08-13 18:02:43 +0530487 }
488 }
489 }
490
Viswanath KSP14aee092016-10-02 01:47:40 +0530491 private final class ResubmitIntent extends RequestHandler {
492 private ResubmitIntent() {
493 super(RESUBMIT_INTENT);
494 }
495
496 @Override
Simon Hunt8a0429a2017-01-06 16:52:47 -0800497 public void process(ObjectNode payload) {
Viswanath KSP14aee092016-10-02 01:47:40 +0530498 Intent intent = findIntentByPayload(payload);
499 if (intent == null) {
500 log.warn("Unable to find intent from payload {}", payload);
501 } else {
502 log.debug("Resubmitting intent {}", intent.key());
Simon Hunt1911fe42017-05-02 18:25:58 -0700503 services.intent().submit(intent);
Viswanath KSP14aee092016-10-02 01:47:40 +0530504 }
505 }
506 }
507
Simon Huntd2747a02015-04-30 22:41:16 -0700508 private final class AddMultiSourceIntent extends RequestHandler {
509 private AddMultiSourceIntent() {
510 super(ADD_MULTI_SRC_INTENT);
511 }
512
513 @Override
Simon Hunt8a0429a2017-01-06 16:52:47 -0800514 public void process(ObjectNode payload) {
Simon Huntd2747a02015-04-30 22:41:16 -0700515 // TODO: add protection against device ids and non-existent hosts.
Simon Huntb745ca62015-07-28 15:37:11 -0700516 Set<HostId> src = getHostIds((ArrayNode) payload.path(SRC));
517 HostId dst = hostId(string(payload, DST));
Simon Hunt1911fe42017-05-02 18:25:58 -0700518 Host dstHost = services.host().getHost(dst);
Simon Huntd2747a02015-04-30 22:41:16 -0700519
520 Set<ConnectPoint> ingressPoints = getHostLocations(src);
521
522 // FIXME: clearly, this is not enough
523 TrafficSelector selector = DefaultTrafficSelector.builder()
524 .matchEthDst(dstHost.mac()).build();
525 TrafficTreatment treatment = DefaultTrafficTreatment.emptyTreatment();
526
527 MultiPointToSinglePointIntent intent =
528 MultiPointToSinglePointIntent.builder()
529 .appId(appId)
530 .selector(selector)
531 .treatment(treatment)
532 .ingressPoints(ingressPoints)
533 .egressPoint(dstHost.location())
534 .build();
535
Simon Hunt1911fe42017-05-02 18:25:58 -0700536 services.intent().submit(intent);
Simon Huntd2862c32015-08-24 17:41:51 -0700537 if (overlayCache.isActive(TrafficOverlay.TRAFFIC_ID)) {
538 traffic.monitor(intent);
539 }
Simon Huntd2747a02015-04-30 22:41:16 -0700540 }
541 }
542
Deepa Vaddireddy63340922017-01-19 08:15:31 +0530543 private final class RemoveIntents extends RequestHandler {
544 private RemoveIntents() {
545 super(REMOVE_INTENTS);
546 }
547
548
549 @Override
550 public void process(ObjectNode payload) {
551 IntentService intentService = get(IntentService.class);
552 for (Intent intent : intentService.getIntents()) {
553 if (intentService.getIntentState(intent.key()) == IntentState.WITHDRAWN) {
554 intentService.purge(intent);
555 }
556 }
557
558 }
559 }
560
Simon Hunta17fa672015-08-19 18:42:22 -0700561 // ========= -----------------------------------------------------------------
Simon Huntd2747a02015-04-30 22:41:16 -0700562
Simon Hunt21281fd2017-03-30 22:28:28 -0700563 private final class ReqAllTraffic extends RequestHandler {
564 private ReqAllTraffic() {
565 super(REQ_ALL_TRAFFIC);
Simon Huntd2747a02015-04-30 22:41:16 -0700566 }
567
568 @Override
Simon Hunt8a0429a2017-01-06 16:52:47 -0800569 public void process(ObjectNode payload) {
Simon Hunt21281fd2017-03-30 22:28:28 -0700570 String trafficType = string(payload, TRAFFIC_TYPE, FLOW_STATS_BYTES);
Thomas Vachuskaf0397b52015-05-29 13:50:17 -0700571
Simon Hunt21281fd2017-03-30 22:28:28 -0700572 switch (trafficType) {
573 case FLOW_STATS_BYTES:
574 traffic.monitor(Mode.ALL_FLOW_TRAFFIC_BYTES);
575 break;
576 case PORT_STATS_BIT_SEC:
577 traffic.monitor(Mode.ALL_PORT_TRAFFIC_BIT_PS);
578 break;
579 case PORT_STATS_PKT_SEC:
580 traffic.monitor(Mode.ALL_PORT_TRAFFIC_PKT_PS);
581 break;
582 default:
583 break;
584 }
Simon Huntd2747a02015-04-30 22:41:16 -0700585 }
586 }
587
Simon Hunt1911fe42017-05-02 18:25:58 -0700588 private NodeSelection makeNodeSelection(ObjectNode payload) {
589 return new NodeSelection(payload, services.device(), services.host(),
590 services.link());
591 }
592
593
Simon Huntd2747a02015-04-30 22:41:16 -0700594 private final class ReqDevLinkFlows extends RequestHandler {
595 private ReqDevLinkFlows() {
596 super(REQ_DEV_LINK_FLOWS);
597 }
598
599 @Override
Simon Hunt8a0429a2017-01-06 16:52:47 -0800600 public void process(ObjectNode payload) {
Simon Hunt1911fe42017-05-02 18:25:58 -0700601 traffic.monitor(Mode.DEV_LINK_FLOWS, makeNodeSelection(payload));
Simon Hunta17fa672015-08-19 18:42:22 -0700602 }
603 }
604
605 private final class ReqRelatedIntents extends RequestHandler {
606 private ReqRelatedIntents() {
607 super(REQ_RELATED_INTENTS);
608 }
609
610 @Override
Simon Hunt8a0429a2017-01-06 16:52:47 -0800611 public void process(ObjectNode payload) {
Simon Hunt1911fe42017-05-02 18:25:58 -0700612 traffic.monitor(Mode.RELATED_INTENTS, makeNodeSelection(payload));
Simon Hunta17fa672015-08-19 18:42:22 -0700613 }
614 }
615
616 private final class ReqNextIntent extends RequestHandler {
617 private ReqNextIntent() {
618 super(REQ_NEXT_INTENT);
619 }
620
621 @Override
Simon Hunt8a0429a2017-01-06 16:52:47 -0800622 public void process(ObjectNode payload) {
Simon Hunt4fc86852015-08-20 17:57:52 -0700623 traffic.selectNextIntent();
Simon Hunta17fa672015-08-19 18:42:22 -0700624 }
625 }
626
627 private final class ReqPrevIntent extends RequestHandler {
628 private ReqPrevIntent() {
629 super(REQ_PREV_INTENT);
630 }
631
632 @Override
Simon Hunt8a0429a2017-01-06 16:52:47 -0800633 public void process(ObjectNode payload) {
Simon Hunt4fc86852015-08-20 17:57:52 -0700634 traffic.selectPreviousIntent();
Simon Hunta17fa672015-08-19 18:42:22 -0700635 }
636 }
637
638 private final class ReqSelectedIntentTraffic extends RequestHandler {
639 private ReqSelectedIntentTraffic() {
640 super(REQ_SEL_INTENT_TRAFFIC);
641 }
642
643 @Override
Simon Hunt8a0429a2017-01-06 16:52:47 -0800644 public void process(ObjectNode payload) {
Simon Hunt4fc86852015-08-20 17:57:52 -0700645 traffic.monitor(Mode.SELECTED_INTENT);
Simon Huntd2747a02015-04-30 22:41:16 -0700646 }
647 }
648
Simon Hunt4a6b54b2015-10-27 22:08:25 -0700649 private final class SelIntent extends RequestHandler {
650 private SelIntent() {
651 super(SEL_INTENT);
652 }
653
654 @Override
Simon Hunt8a0429a2017-01-06 16:52:47 -0800655 public void process(ObjectNode payload) {
Viswanath KSP0f297702016-08-13 18:02:43 +0530656 Intent intent = findIntentByPayload(payload);
Simon Hunt4a6b54b2015-10-27 22:08:25 -0700657 if (intent == null) {
Viswanath KSP0f297702016-08-13 18:02:43 +0530658 log.warn("Unable to find intent from payload {}", payload);
Simon Hunt4a6b54b2015-10-27 22:08:25 -0700659 } else {
Viswanath KSP0f297702016-08-13 18:02:43 +0530660 log.debug("starting to monitor intent {}", intent.key());
Simon Hunt4a6b54b2015-10-27 22:08:25 -0700661 traffic.monitor(intent);
662 }
663 }
664 }
665
Andrea Campanella732ea832017-02-06 09:25:59 -0800666 private final class SelProtectedIntent extends RequestHandler {
667 private SelProtectedIntent() {
668 super(SEL_PROTECTED_INTENT);
669 }
670
671 @Override
672 public void process(ObjectNode payload) {
673 Intent intent = findIntentByPayload(payload);
674 if (intent == null) {
675 log.warn("Unable to find protected intent from payload {}", payload);
676 } else {
677 log.debug("starting to monitor protected intent {}", intent.key());
678 protectedIntentMonitor.monitor(intent);
679 }
680 }
681 }
682
Simon Huntd2747a02015-04-30 22:41:16 -0700683 private final class CancelTraffic extends RequestHandler {
684 private CancelTraffic() {
685 super(CANCEL_TRAFFIC);
686 }
687
688 @Override
Simon Hunt8a0429a2017-01-06 16:52:47 -0800689 public void process(ObjectNode payload) {
Simon Hunt4fc86852015-08-20 17:57:52 -0700690 traffic.stopMonitoring();
Simon Huntd2747a02015-04-30 22:41:16 -0700691 }
692 }
693
Andrea Campanella732ea832017-02-06 09:25:59 -0800694 private final class CancelProtectedIntentHighlight extends RequestHandler {
695 private CancelProtectedIntentHighlight() {
696 super(CANCEL_PROTECTED_INTENT_HIGHLIGHT);
697 }
698
699 @Override
700 public void process(ObjectNode payload) {
701 protectedIntentMonitor.stopMonitoring();
702 }
703 }
704
Simon Huntd2747a02015-04-30 22:41:16 -0700705 //=======================================================================
706
Simon Hunta17fa672015-08-19 18:42:22 -0700707 // Converts highlights to JSON format and sends the message to the client
Simon Hunt8a0429a2017-01-06 16:52:47 -0800708 void sendHighlights(Highlights highlights) {
Simon Hunt52560662015-08-27 22:46:44 -0700709 sendMessage(highlightsMessage(highlights));
Thomas Vachuska329af532015-03-10 02:08:33 -0700710 }
711
Simon Huntd2747a02015-04-30 22:41:16 -0700712 // Subscribes for summary messages.
Simon Hunt8a0429a2017-01-06 16:52:47 -0800713 private synchronized void requestSummary() {
714 PropertyPanel pp = summmaryMessage();
Simon Hunt0af1ec32015-07-24 12:17:55 -0700715 overlayCache.currentOverlay().modifySummary(pp);
Simon Hunt8a0429a2017-01-06 16:52:47 -0800716 sendMessage(envelope(SHOW_SUMMARY, json(pp)));
Thomas Vachuska329af532015-03-10 02:08:33 -0700717 }
718
Simon Huntd2747a02015-04-30 22:41:16 -0700719
Thomas Vachuska329af532015-03-10 02:08:33 -0700720 private void cancelAllRequests() {
721 stopSummaryMonitoring();
Simon Hunt4fc86852015-08-20 17:57:52 -0700722 traffic.stopMonitoring();
Thomas Vachuska329af532015-03-10 02:08:33 -0700723 }
724
725 // Sends all controller nodes to the client as node-added messages.
726 private void sendAllInstances(String messageType) {
Simon Hunt1911fe42017-05-02 18:25:58 -0700727 List<ControllerNode> nodes = new ArrayList<>(services.cluster().getNodes());
Simon Hunt8a0429a2017-01-06 16:52:47 -0800728 nodes.sort(NODE_COMPARATOR);
Thomas Vachuska329af532015-03-10 02:08:33 -0700729 for (ControllerNode node : nodes) {
730 sendMessage(instanceMessage(new ClusterEvent(INSTANCE_ADDED, node),
Andrea Campanella732ea832017-02-06 09:25:59 -0800731 messageType));
Thomas Vachuska329af532015-03-10 02:08:33 -0700732 }
733 }
734
735 // Sends all devices to the client as device-added messages.
736 private void sendAllDevices() {
737 // Send optical first, others later for layered rendering
Simon Hunt1911fe42017-05-02 18:25:58 -0700738 for (Device device : services.device().getDevices()) {
Rimon Ashkenazy8ebfff02016-02-01 11:56:36 +0200739 if ((device.type() == Device.Type.ROADM) ||
Simon Hunt5c1a9382016-06-01 19:35:35 -0700740 (device.type() == Device.Type.OTN)) {
Thomas Vachuska329af532015-03-10 02:08:33 -0700741 sendMessage(deviceMessage(new DeviceEvent(DEVICE_ADDED, device)));
742 }
743 }
Simon Hunt1911fe42017-05-02 18:25:58 -0700744 for (Device device : services.device().getDevices()) {
Rimon Ashkenazy8ebfff02016-02-01 11:56:36 +0200745 if ((device.type() != Device.Type.ROADM) &&
Simon Hunt5c1a9382016-06-01 19:35:35 -0700746 (device.type() != Device.Type.OTN)) {
Thomas Vachuska329af532015-03-10 02:08:33 -0700747 sendMessage(deviceMessage(new DeviceEvent(DEVICE_ADDED, device)));
748 }
749 }
750 }
751
752 // Sends all links to the client as link-added messages.
753 private void sendAllLinks() {
754 // Send optical first, others later for layered rendering
Simon Hunt1911fe42017-05-02 18:25:58 -0700755 for (Link link : services.link().getLinks()) {
Thomas Vachuska329af532015-03-10 02:08:33 -0700756 if (link.type() == Link.Type.OPTICAL) {
Simon Hunt5c1a9382016-06-01 19:35:35 -0700757 sendMessage(composeLinkMessage(new LinkEvent(LINK_ADDED, link)));
Thomas Vachuska329af532015-03-10 02:08:33 -0700758 }
759 }
Simon Hunt1911fe42017-05-02 18:25:58 -0700760 for (Link link : services.link().getLinks()) {
Thomas Vachuska329af532015-03-10 02:08:33 -0700761 if (link.type() != Link.Type.OPTICAL) {
Simon Hunt5c1a9382016-06-01 19:35:35 -0700762 sendMessage(composeLinkMessage(new LinkEvent(LINK_ADDED, link)));
Thomas Vachuska329af532015-03-10 02:08:33 -0700763 }
764 }
765 }
766
Simon Hunt5c1a9382016-06-01 19:35:35 -0700767 // Temporary mechanism to support topology overlays adding their own
768 // properties to the link events.
769 private ObjectNode composeLinkMessage(LinkEvent event) {
770 // start with base message
771 ObjectNode msg = linkMessage(event);
772 Map<String, String> additional =
773 overlayCache.currentOverlay().additionalLinkData(event);
774
775 if (additional != null) {
776 // attach additional key-value pairs as extra data structure
777 ObjectNode payload = (ObjectNode) msg.get(PAYLOAD);
778 payload.set(EXTRA, createExtra(additional));
779 }
780 return msg;
781 }
782
783 private ObjectNode createExtra(Map<String, String> additional) {
784 ObjectNode extra = objectNode();
785 for (Map.Entry<String, String> entry : additional.entrySet()) {
786 extra.put(entry.getKey(), entry.getValue());
787 }
788 return extra;
789 }
790
Thomas Vachuska329af532015-03-10 02:08:33 -0700791 // Sends all hosts to the client as host-added messages.
792 private void sendAllHosts() {
Simon Hunt1911fe42017-05-02 18:25:58 -0700793 for (Host host : services.host().getHosts()) {
Thomas Vachuska329af532015-03-10 02:08:33 -0700794 sendMessage(hostMessage(new HostEvent(HOST_ADDED, host)));
795 }
796 }
797
Thomas Vachuska329af532015-03-10 02:08:33 -0700798 private Set<ConnectPoint> getHostLocations(Set<HostId> hostIds) {
799 Set<ConnectPoint> points = new HashSet<>();
800 for (HostId hostId : hostIds) {
801 points.add(getHostLocation(hostId));
802 }
803 return points;
804 }
805
806 private HostLocation getHostLocation(HostId hostId) {
Simon Hunt1911fe42017-05-02 18:25:58 -0700807 return services.host().getHost(hostId).location();
Thomas Vachuska329af532015-03-10 02:08:33 -0700808 }
809
810 // Produces a list of host ids from the specified JSON array.
811 private Set<HostId> getHostIds(ArrayNode ids) {
812 Set<HostId> hostIds = new HashSet<>();
813 for (JsonNode id : ids) {
814 hostIds.add(hostId(id.asText()));
815 }
816 return hostIds;
817 }
818
Simon Hunt4a6b54b2015-10-27 22:08:25 -0700819 private void sendTopoStartDone() {
820 sendMessage(JsonUtils.envelope(TOPO_START_DONE, objectNode()));
821 }
Thomas Vachuska329af532015-03-10 02:08:33 -0700822
Simon Huntd2747a02015-04-30 22:41:16 -0700823 private synchronized void startSummaryMonitoring() {
Thomas Vachuska329af532015-03-10 02:08:33 -0700824 stopSummaryMonitoring();
Thomas Vachuska329af532015-03-10 02:08:33 -0700825 summaryTask = new SummaryMonitor();
Simon Hunta17fa672015-08-19 18:42:22 -0700826 timer.schedule(summaryTask, SUMMARY_PERIOD, SUMMARY_PERIOD);
Simon Huntd2747a02015-04-30 22:41:16 -0700827 summaryRunning = true;
Thomas Vachuska329af532015-03-10 02:08:33 -0700828 }
829
830 private synchronized void stopSummaryMonitoring() {
Simon Huntd2747a02015-04-30 22:41:16 -0700831 if (summaryTask != null) {
Thomas Vachuska329af532015-03-10 02:08:33 -0700832 summaryTask.cancel();
833 summaryTask = null;
Thomas Vachuska329af532015-03-10 02:08:33 -0700834 }
Simon Huntd2747a02015-04-30 22:41:16 -0700835 summaryRunning = false;
Thomas Vachuska9ed335b2015-04-14 12:07:47 -0700836 }
837
Thomas Vachuska329af532015-03-10 02:08:33 -0700838
839 // Adds all internal listeners.
Thomas Vachuska35fa3d42015-04-30 10:11:47 -0700840 private synchronized void addListeners() {
Thomas Vachuskae586b792015-03-26 13:59:38 -0700841 listenersRemoved = false;
Simon Hunt1911fe42017-05-02 18:25:58 -0700842 services.cluster().addListener(clusterListener);
843 services.mastership().addListener(mastershipListener);
844 services.device().addListener(deviceListener);
845 services.link().addListener(linkListener);
846 services.host().addListener(hostListener);
847 services.intent().addListener(intentListener);
848 services.flow().addListener(flowListener);
Thomas Vachuska329af532015-03-10 02:08:33 -0700849 }
850
851 // Removes all internal listeners.
852 private synchronized void removeListeners() {
853 if (!listenersRemoved) {
854 listenersRemoved = true;
Simon Hunt1911fe42017-05-02 18:25:58 -0700855 services.cluster().removeListener(clusterListener);
856 services.mastership().removeListener(mastershipListener);
857 services.device().removeListener(deviceListener);
858 services.link().removeListener(linkListener);
859 services.host().removeListener(hostListener);
860 services.intent().removeListener(intentListener);
861 services.flow().removeListener(flowListener);
Thomas Vachuska329af532015-03-10 02:08:33 -0700862 }
863 }
864
865 // Cluster event listener.
Simon Hunt7092cc42016-04-06 18:40:17 -0700866 // TODO: Superceded by UiSharedTopologyModel.ModelEventListener
867 @Deprecated
Thomas Vachuska329af532015-03-10 02:08:33 -0700868 private class InternalClusterListener implements ClusterEventListener {
869 @Override
870 public void event(ClusterEvent event) {
Thomas Vachuskac7f79962015-05-28 09:37:34 -0700871 msgSender.execute(() -> sendMessage(instanceMessage(event, null)));
Thomas Vachuska329af532015-03-10 02:08:33 -0700872 }
873 }
874
875 // Mastership change listener
Simon Hunt7092cc42016-04-06 18:40:17 -0700876 // TODO: Superceded by UiSharedTopologyModel.ModelEventListener
877 @Deprecated
Thomas Vachuska329af532015-03-10 02:08:33 -0700878 private class InternalMastershipListener implements MastershipListener {
879 @Override
880 public void event(MastershipEvent event) {
Thomas Vachuska52c98bd2015-05-27 20:54:02 -0700881 msgSender.execute(() -> {
Simon Huntb745ca62015-07-28 15:37:11 -0700882 sendAllInstances(UPDATE_INSTANCE);
Simon Hunt1911fe42017-05-02 18:25:58 -0700883 Device device = services.device().getDevice(event.subject());
Thomas Vachuska52c98bd2015-05-27 20:54:02 -0700884 if (device != null) {
885 sendMessage(deviceMessage(new DeviceEvent(DEVICE_UPDATED, device)));
886 }
887 });
Thomas Vachuska329af532015-03-10 02:08:33 -0700888 }
889 }
890
891 // Device event listener.
Simon Hunt7092cc42016-04-06 18:40:17 -0700892 // TODO: Superceded by UiSharedTopologyModel.ModelEventListener
893 @Deprecated
Thomas Vachuska329af532015-03-10 02:08:33 -0700894 private class InternalDeviceListener implements DeviceListener {
895 @Override
896 public void event(DeviceEvent event) {
Thomas Vachuskacb5016f2015-05-18 14:11:43 -0700897 if (event.type() != PORT_STATS_UPDATED) {
Thomas Vachuskac7f79962015-05-28 09:37:34 -0700898 msgSender.execute(() -> sendMessage(deviceMessage(event)));
Simon Hunta1f1c022016-03-03 15:54:57 -0800899 msgSender.execute(traffic::pokeIntent);
Thomas Vachuskacb5016f2015-05-18 14:11:43 -0700900 eventAccummulator.add(event);
901 }
Thomas Vachuska329af532015-03-10 02:08:33 -0700902 }
903 }
904
905 // Link event listener.
Simon Hunt7092cc42016-04-06 18:40:17 -0700906 // TODO: Superceded by UiSharedTopologyModel.ModelEventListener
907 @Deprecated
Thomas Vachuska329af532015-03-10 02:08:33 -0700908 private class InternalLinkListener implements LinkListener {
909 @Override
910 public void event(LinkEvent event) {
Simon Hunt5c1a9382016-06-01 19:35:35 -0700911 msgSender.execute(() -> sendMessage(composeLinkMessage(event)));
Simon Hunta1f1c022016-03-03 15:54:57 -0800912 msgSender.execute(traffic::pokeIntent);
Thomas Vachuska329af532015-03-10 02:08:33 -0700913 eventAccummulator.add(event);
914 }
915 }
916
917 // Host event listener.
Simon Hunt7092cc42016-04-06 18:40:17 -0700918 // TODO: Superceded by UiSharedTopologyModel.ModelEventListener
919 @Deprecated
Thomas Vachuska329af532015-03-10 02:08:33 -0700920 private class InternalHostListener implements HostListener {
921 @Override
922 public void event(HostEvent event) {
Thomas Vachuskac7f79962015-05-28 09:37:34 -0700923 msgSender.execute(() -> sendMessage(hostMessage(event)));
Simon Hunta1f1c022016-03-03 15:54:57 -0800924 msgSender.execute(traffic::pokeIntent);
Thomas Vachuska329af532015-03-10 02:08:33 -0700925 eventAccummulator.add(event);
926 }
927 }
928
929 // Intent event listener.
Simon Hunt7092cc42016-04-06 18:40:17 -0700930 // TODO: Superceded by UiSharedTopologyModel.ModelEventListener
931 @Deprecated
Thomas Vachuska329af532015-03-10 02:08:33 -0700932 private class InternalIntentListener implements IntentListener {
933 @Override
934 public void event(IntentEvent event) {
Simon Hunt4fc86852015-08-20 17:57:52 -0700935 msgSender.execute(traffic::pokeIntent);
Thomas Vachuska329af532015-03-10 02:08:33 -0700936 eventAccummulator.add(event);
937 }
938 }
939
940 // Intent event listener.
Simon Hunt7092cc42016-04-06 18:40:17 -0700941 // TODO: Superceded by UiSharedTopologyModel.ModelEventListener
942 @Deprecated
Thomas Vachuska329af532015-03-10 02:08:33 -0700943 private class InternalFlowListener implements FlowRuleListener {
944 @Override
945 public void event(FlowRuleEvent event) {
946 eventAccummulator.add(event);
947 }
948 }
949
Simon Huntd2747a02015-04-30 22:41:16 -0700950
Simon Hunta17fa672015-08-19 18:42:22 -0700951 // === SUMMARY MONITORING
Thomas Vachuska329af532015-03-10 02:08:33 -0700952
953 // Periodic update of the summary information
954 private class SummaryMonitor extends TimerTask {
955 @Override
956 public void run() {
957 try {
Simon Huntd2747a02015-04-30 22:41:16 -0700958 if (summaryRunning) {
Simon Hunt8a0429a2017-01-06 16:52:47 -0800959 msgSender.execute(() -> requestSummary());
Thomas Vachuska329af532015-03-10 02:08:33 -0700960 }
961 } catch (Exception e) {
962 log.warn("Unable to handle summary request due to {}", e.getMessage());
963 log.warn("Boom!", e);
964 }
965 }
966 }
967
968 // Accumulates events to drive methodic update of the summary pane.
969 private class InternalEventAccummulator extends AbstractAccumulator<Event> {
970 protected InternalEventAccummulator() {
971 super(new Timer("topo-summary"), MAX_EVENTS, MAX_BATCH_MS, MAX_IDLE_MS);
972 }
973
974 @Override
975 public void processItems(List<Event> items) {
Simon Hunta17fa672015-08-19 18:42:22 -0700976 // Start-of-Debugging -- Keep in until ONOS-2572 is fixed for reals
Simon Hunt8d22c4b2015-08-06 16:24:43 -0700977 long now = System.currentTimeMillis();
978 String me = this.toString();
979 String miniMe = me.replaceAll("^.*@", "me@");
980 log.debug("Time: {}; this: {}, processing items ({} events)",
Andrea Campanella732ea832017-02-06 09:25:59 -0800981 now, miniMe, items.size());
Simon Hunt8d22c4b2015-08-06 16:24:43 -0700982 // End-of-Debugging
983
Thomas Vachuska329af532015-03-10 02:08:33 -0700984 try {
Simon Huntd2747a02015-04-30 22:41:16 -0700985 if (summaryRunning) {
Simon Hunt8a0429a2017-01-06 16:52:47 -0800986 msgSender.execute(() -> requestSummary());
Thomas Vachuska329af532015-03-10 02:08:33 -0700987 }
988 } catch (Exception e) {
989 log.warn("Unable to handle summary request due to {}", e.getMessage());
990 log.debug("Boom!", e);
991 }
992 }
993 }
994}