blob: 1dbe3b1fafad1681d5028b6a5c49876befe1dd5a [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;
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 Hunt1911fe42017-05-02 18:25:58 -070085import static org.onosproject.net.device.DeviceEvent.Type.*;
Thomas Vachuska329af532015-03-10 02:08:33 -070086import static org.onosproject.net.host.HostEvent.Type.HOST_ADDED;
87import static org.onosproject.net.link.LinkEvent.Type.LINK_ADDED;
Simon Huntd3ceffa2015-08-25 12:44:35 -070088import static org.onosproject.ui.JsonUtils.envelope;
Viswanath KSP0f297702016-08-13 18:02:43 +053089import static org.onosproject.ui.JsonUtils.string;
Simon Hunt52560662015-08-27 22:46:44 -070090import static org.onosproject.ui.topo.TopoJson.highlightsMessage;
91import static org.onosproject.ui.topo.TopoJson.json;
Thomas Vachuska329af532015-03-10 02:08:33 -070092
93/**
94 * Web socket capable of interacting with the GUI topology view.
95 */
96public class TopologyViewMessageHandler extends TopologyViewMessageHandlerBase {
97
Simon Huntb745ca62015-07-28 15:37:11 -070098 // incoming event types
Simon Huntd2747a02015-04-30 22:41:16 -070099 private static final String REQ_DETAILS = "requestDetails";
100 private static final String UPDATE_META = "updateMeta";
101 private static final String ADD_HOST_INTENT = "addHostIntent";
Viswanath KSP0f297702016-08-13 18:02:43 +0530102 private static final String REMOVE_INTENT = "removeIntent";
Deepa Vaddireddy63340922017-01-19 08:15:31 +0530103 private static final String REMOVE_INTENTS = "removeIntents";
Viswanath KSP14aee092016-10-02 01:47:40 +0530104 private static final String RESUBMIT_INTENT = "resubmitIntent";
Simon Huntd2747a02015-04-30 22:41:16 -0700105 private static final String ADD_MULTI_SRC_INTENT = "addMultiSourceIntent";
106 private static final String REQ_RELATED_INTENTS = "requestRelatedIntents";
107 private static final String REQ_NEXT_INTENT = "requestNextRelatedIntent";
108 private static final String REQ_PREV_INTENT = "requestPrevRelatedIntent";
109 private static final String REQ_SEL_INTENT_TRAFFIC = "requestSelectedIntentTraffic";
Simon Hunt4a6b54b2015-10-27 22:08:25 -0700110 private static final String SEL_INTENT = "selectIntent";
Simon Hunt21281fd2017-03-30 22:28:28 -0700111 private static final String REQ_ALL_TRAFFIC = "requestAllTraffic";
Simon Huntd2747a02015-04-30 22:41:16 -0700112 private static final String REQ_DEV_LINK_FLOWS = "requestDeviceLinkFlows";
113 private static final String CANCEL_TRAFFIC = "cancelTraffic";
114 private static final String REQ_SUMMARY = "requestSummary";
115 private static final String CANCEL_SUMMARY = "cancelSummary";
116 private static final String EQ_MASTERS = "equalizeMasters";
117 private static final String SPRITE_LIST_REQ = "spriteListRequest";
118 private static final String SPRITE_DATA_REQ = "spriteDataRequest";
119 private static final String TOPO_START = "topoStart";
Simon Hunte05cae42015-07-23 17:35:24 -0700120 private static final String TOPO_SELECT_OVERLAY = "topoSelectOverlay";
Simon Huntd2747a02015-04-30 22:41:16 -0700121 private static final String TOPO_STOP = "topoStop";
Andrea Campanella732ea832017-02-06 09:25:59 -0800122 private static final String SEL_PROTECTED_INTENT = "selectProtectedIntent";
123 private static final String CANCEL_PROTECTED_INTENT_HIGHLIGHT = "cancelProtectedIntentHighlight";
124
Simon Huntb745ca62015-07-28 15:37:11 -0700125 // outgoing event types
126 private static final String SHOW_SUMMARY = "showSummary";
127 private static final String SHOW_DETAILS = "showDetails";
128 private static final String SPRITE_LIST_RESPONSE = "spriteListResponse";
129 private static final String SPRITE_DATA_RESPONSE = "spriteDataResponse";
130 private static final String UPDATE_INSTANCE = "updateInstance";
Simon Hunt4a6b54b2015-10-27 22:08:25 -0700131 private static final String TOPO_START_DONE = "topoStartDone";
Simon Huntb745ca62015-07-28 15:37:11 -0700132
133 // fields
Simon Hunt5c1a9382016-06-01 19:35:35 -0700134 private static final String PAYLOAD = "payload";
135 private static final String EXTRA = "extra";
Simon Huntb745ca62015-07-28 15:37:11 -0700136 private static final String ID = "id";
Simon Hunt4a6b54b2015-10-27 22:08:25 -0700137 private static final String KEY = "key";
138 private static final String APP_ID = "appId";
139 private static final String APP_NAME = "appName";
Simon Huntb745ca62015-07-28 15:37:11 -0700140 private static final String DEVICE = "device";
141 private static final String HOST = "host";
142 private static final String CLASS = "class";
143 private static final String UNKNOWN = "unknown";
144 private static final String ONE = "one";
145 private static final String TWO = "two";
146 private static final String SRC = "src";
147 private static final String DST = "dst";
148 private static final String DATA = "data";
149 private static final String NAME = "name";
150 private static final String NAMES = "names";
151 private static final String ACTIVATE = "activate";
152 private static final String DEACTIVATE = "deactivate";
Viswanath KSP813a20d2016-09-13 04:25:41 +0530153 private static final String PURGE = "purge";
Simon Hunt21281fd2017-03-30 22:28:28 -0700154 private static final String TRAFFIC_TYPE = "trafficType";
Simon Huntb745ca62015-07-28 15:37:11 -0700155
Simon Hunt21281fd2017-03-30 22:28:28 -0700156 // field values
157 private static final String FLOW_STATS_BYTES = "flowStatsBytes";
158 private static final String PORT_STATS_BIT_SEC = "portStatsBitSec";
159 private static final String PORT_STATS_PKT_SEC = "portStatsPktSec";
Simon Huntd2747a02015-04-30 22:41:16 -0700160
Simon Hunt4a6b54b2015-10-27 22:08:25 -0700161 private static final String MY_APP_ID = "org.onosproject.gui";
Thomas Vachuska329af532015-03-10 02:08:33 -0700162
Simon Hunta17fa672015-08-19 18:42:22 -0700163 private static final long TRAFFIC_PERIOD = 5000;
164 private static final long SUMMARY_PERIOD = 30000;
Thomas Vachuska329af532015-03-10 02:08:33 -0700165
166 private static final Comparator<? super ControllerNode> NODE_COMPARATOR =
Simon Hunt8a0429a2017-01-06 16:52:47 -0800167 Comparator.comparing(o -> o.id().toString());
Thomas Vachuska329af532015-03-10 02:08:33 -0700168
169
Thomas Vachuska52c98bd2015-05-27 20:54:02 -0700170 private final Timer timer = new Timer("onos-topology-view");
Thomas Vachuska329af532015-03-10 02:08:33 -0700171
172 private static final int MAX_EVENTS = 1000;
173 private static final int MAX_BATCH_MS = 5000;
174 private static final int MAX_IDLE_MS = 1000;
175
176 private ApplicationId appId;
177
178 private final ClusterEventListener clusterListener = new InternalClusterListener();
179 private final MastershipListener mastershipListener = new InternalMastershipListener();
180 private final DeviceListener deviceListener = new InternalDeviceListener();
181 private final LinkListener linkListener = new InternalLinkListener();
182 private final HostListener hostListener = new InternalHostListener();
183 private final IntentListener intentListener = new InternalIntentListener();
184 private final FlowRuleListener flowListener = new InternalFlowListener();
185
186 private final Accumulator<Event> eventAccummulator = new InternalEventAccummulator();
Thomas Vachuska52c98bd2015-05-27 20:54:02 -0700187 private final ExecutorService msgSender =
Yuta HIGUCHI1624df12016-07-21 16:54:33 -0700188 newSingleThreadExecutor(groupedThreads("onos/gui", "msg-sender", log));
Thomas Vachuska329af532015-03-10 02:08:33 -0700189
Simon Hunta17fa672015-08-19 18:42:22 -0700190 private TopoOverlayCache overlayCache;
Simon Hunt4fc86852015-08-20 17:57:52 -0700191 private TrafficMonitor traffic;
Andrea Campanella732ea832017-02-06 09:25:59 -0800192 private ProtectedIntentMonitor protectedIntentMonitor;
Thomas Vachuska329af532015-03-10 02:08:33 -0700193
Simon Huntd2747a02015-04-30 22:41:16 -0700194 private TimerTask summaryTask = null;
195 private boolean summaryRunning = false;
Thomas Vachuska329af532015-03-10 02:08:33 -0700196
Simon Huntd5b96732016-07-08 13:22:27 -0700197 private volatile boolean listenersRemoved = false;
Thomas Vachuska329af532015-03-10 02:08:33 -0700198
Thomas Vachuska329af532015-03-10 02:08:33 -0700199
200 @Override
201 public void init(UiConnection connection, ServiceDirectory directory) {
202 super.init(connection, directory);
Simon Hunt4a6b54b2015-10-27 22:08:25 -0700203 appId = directory.get(CoreService.class).registerApplication(MY_APP_ID);
Simon Hunt1911fe42017-05-02 18:25:58 -0700204 traffic = new TrafficMonitor(TRAFFIC_PERIOD, services, this);
205 protectedIntentMonitor = new ProtectedIntentMonitor(TRAFFIC_PERIOD, services, this);
Thomas Vachuska329af532015-03-10 02:08:33 -0700206 }
207
208 @Override
209 public void destroy() {
210 cancelAllRequests();
Thomas Vachuska2bb48632015-04-28 14:40:42 -0700211 removeListeners();
Thomas Vachuska329af532015-03-10 02:08:33 -0700212 super.destroy();
213 }
214
Thomas Vachuska329af532015-03-10 02:08:33 -0700215 @Override
Simon Huntda580882015-05-12 20:58:18 -0700216 protected Collection<RequestHandler> createRequestHandlers() {
Simon Huntd2747a02015-04-30 22:41:16 -0700217 return ImmutableSet.of(
218 new TopoStart(),
Simon Hunte05cae42015-07-23 17:35:24 -0700219 new TopoSelectOverlay(),
Simon Huntd2747a02015-04-30 22:41:16 -0700220 new TopoStop(),
221 new ReqSummary(),
222 new CancelSummary(),
223 new SpriteListReq(),
224 new SpriteDataReq(),
225 new RequestDetails(),
226 new UpdateMeta(),
227 new EqMasters(),
Thomas Vachuska329af532015-03-10 02:08:33 -0700228
Simon Huntd2747a02015-04-30 22:41:16 -0700229 // TODO: migrate traffic related to separate app
230 new AddHostIntent(),
231 new AddMultiSourceIntent(),
Viswanath KSP0f297702016-08-13 18:02:43 +0530232 new RemoveIntent(),
Viswanath KSP14aee092016-10-02 01:47:40 +0530233 new ResubmitIntent(),
Deepa Vaddireddy63340922017-01-19 08:15:31 +0530234 new RemoveIntents(),
Simon Hunta17fa672015-08-19 18:42:22 -0700235
Simon Hunt21281fd2017-03-30 22:28:28 -0700236 new ReqAllTraffic(),
Simon Hunta17fa672015-08-19 18:42:22 -0700237 new ReqDevLinkFlows(),
Simon Huntd2747a02015-04-30 22:41:16 -0700238 new ReqRelatedIntents(),
239 new ReqNextIntent(),
240 new ReqPrevIntent(),
241 new ReqSelectedIntentTraffic(),
Simon Hunt4a6b54b2015-10-27 22:08:25 -0700242 new SelIntent(),
Andrea Campanella732ea832017-02-06 09:25:59 -0800243 new SelProtectedIntent(),
Simon Hunta17fa672015-08-19 18:42:22 -0700244
Andrea Campanella732ea832017-02-06 09:25:59 -0800245 new CancelTraffic(),
246 new CancelProtectedIntentHighlight()
Simon Huntd2747a02015-04-30 22:41:16 -0700247 );
248 }
Thomas Vachuska329af532015-03-10 02:08:33 -0700249
Simon Hunte05cae42015-07-23 17:35:24 -0700250 /**
251 * Injects the topology overlay cache.
252 *
253 * @param overlayCache injected cache
254 */
255 void setOverlayCache(TopoOverlayCache overlayCache) {
256 this.overlayCache = overlayCache;
257 }
258
Simon Huntd2747a02015-04-30 22:41:16 -0700259 // ==================================================================
Thomas Vachuska329af532015-03-10 02:08:33 -0700260
Simon Huntd2747a02015-04-30 22:41:16 -0700261 private final class TopoStart extends RequestHandler {
262 private TopoStart() {
263 super(TOPO_START);
264 }
Thomas Vachuska329af532015-03-10 02:08:33 -0700265
Simon Huntd2747a02015-04-30 22:41:16 -0700266 @Override
Simon Hunt8a0429a2017-01-06 16:52:47 -0800267 public void process(ObjectNode payload) {
Simon Huntd2747a02015-04-30 22:41:16 -0700268 addListeners();
269 sendAllInstances(null);
270 sendAllDevices();
271 sendAllLinks();
272 sendAllHosts();
Simon Hunt4a6b54b2015-10-27 22:08:25 -0700273 sendTopoStartDone();
Thomas Vachuska329af532015-03-10 02:08:33 -0700274 }
275 }
276
Simon Hunte05cae42015-07-23 17:35:24 -0700277 private final class TopoSelectOverlay extends RequestHandler {
278 private TopoSelectOverlay() {
279 super(TOPO_SELECT_OVERLAY);
280 }
281
282 @Override
Simon Hunt8a0429a2017-01-06 16:52:47 -0800283 public void process(ObjectNode payload) {
Simon Huntb745ca62015-07-28 15:37:11 -0700284 String deact = string(payload, DEACTIVATE);
285 String act = string(payload, ACTIVATE);
Simon Hunte05cae42015-07-23 17:35:24 -0700286 overlayCache.switchOverlay(deact, act);
287 }
288 }
289
Simon Huntd2747a02015-04-30 22:41:16 -0700290 private final class TopoStop extends RequestHandler {
291 private TopoStop() {
292 super(TOPO_STOP);
293 }
294
295 @Override
Simon Hunt8a0429a2017-01-06 16:52:47 -0800296 public void process(ObjectNode payload) {
Simon Hunt1ad59272015-11-10 15:23:21 -0800297 removeListeners();
Simon Huntd2747a02015-04-30 22:41:16 -0700298 stopSummaryMonitoring();
Simon Hunt4fc86852015-08-20 17:57:52 -0700299 traffic.stopMonitoring();
Simon Huntd2747a02015-04-30 22:41:16 -0700300 }
301 }
302
303 private final class ReqSummary extends RequestHandler {
304 private ReqSummary() {
305 super(REQ_SUMMARY);
306 }
307
308 @Override
Simon Hunt8a0429a2017-01-06 16:52:47 -0800309 public void process(ObjectNode payload) {
310 requestSummary();
Simon Huntd2747a02015-04-30 22:41:16 -0700311 startSummaryMonitoring();
312 }
313 }
314
315 private final class CancelSummary extends RequestHandler {
316 private CancelSummary() {
317 super(CANCEL_SUMMARY);
318 }
319
320 @Override
Simon Hunt8a0429a2017-01-06 16:52:47 -0800321 public void process(ObjectNode payload) {
Simon Huntd2747a02015-04-30 22:41:16 -0700322 stopSummaryMonitoring();
323 }
324 }
325
326 private final class SpriteListReq extends RequestHandler {
327 private SpriteListReq() {
328 super(SPRITE_LIST_REQ);
329 }
330
331 @Override
Simon Hunt8a0429a2017-01-06 16:52:47 -0800332 public void process(ObjectNode payload) {
Simon Huntda580882015-05-12 20:58:18 -0700333 ObjectNode root = objectNode();
334 ArrayNode names = arrayNode();
Simon Huntd2747a02015-04-30 22:41:16 -0700335 get(SpriteService.class).getNames().forEach(names::add);
Simon Huntb745ca62015-07-28 15:37:11 -0700336 root.set(NAMES, names);
Simon Hunt8a0429a2017-01-06 16:52:47 -0800337 sendMessage(SPRITE_LIST_RESPONSE, root);
Simon Huntd2747a02015-04-30 22:41:16 -0700338 }
339 }
340
341 private final class SpriteDataReq extends RequestHandler {
342 private SpriteDataReq() {
343 super(SPRITE_DATA_REQ);
344 }
345
346 @Override
Simon Hunt8a0429a2017-01-06 16:52:47 -0800347 public void process(ObjectNode payload) {
Simon Huntb745ca62015-07-28 15:37:11 -0700348 String name = string(payload, NAME);
Simon Huntda580882015-05-12 20:58:18 -0700349 ObjectNode root = objectNode();
Simon Huntb745ca62015-07-28 15:37:11 -0700350 root.set(DATA, get(SpriteService.class).get(name));
Simon Hunt8a0429a2017-01-06 16:52:47 -0800351 sendMessage(SPRITE_DATA_RESPONSE, root);
Simon Huntd2747a02015-04-30 22:41:16 -0700352 }
353 }
354
355 private final class RequestDetails extends RequestHandler {
356 private RequestDetails() {
357 super(REQ_DETAILS);
358 }
359
360 @Override
Simon Hunt8a0429a2017-01-06 16:52:47 -0800361 public void process(ObjectNode payload) {
Simon Huntb745ca62015-07-28 15:37:11 -0700362 String type = string(payload, CLASS, UNKNOWN);
363 String id = string(payload, ID);
364 PropertyPanel pp = null;
Simon Huntd2747a02015-04-30 22:41:16 -0700365
Simon Huntb745ca62015-07-28 15:37:11 -0700366 if (type.equals(DEVICE)) {
Simon Huntde99e0b2015-10-23 18:54:06 -0700367 DeviceId did = deviceId(id);
Simon Hunt8a0429a2017-01-06 16:52:47 -0800368 pp = deviceDetails(did);
Simon Huntde99e0b2015-10-23 18:54:06 -0700369 overlayCache.currentOverlay().modifyDeviceDetails(pp, did);
Simon Huntb745ca62015-07-28 15:37:11 -0700370 } else if (type.equals(HOST)) {
Simon Huntde99e0b2015-10-23 18:54:06 -0700371 HostId hid = hostId(id);
Simon Hunt8a0429a2017-01-06 16:52:47 -0800372 pp = hostDetails(hid);
Simon Huntde99e0b2015-10-23 18:54:06 -0700373 overlayCache.currentOverlay().modifyHostDetails(pp, hid);
Simon Huntd2747a02015-04-30 22:41:16 -0700374 }
Simon Huntb745ca62015-07-28 15:37:11 -0700375
Simon Hunt8a0429a2017-01-06 16:52:47 -0800376 sendMessage(envelope(SHOW_DETAILS, json(pp)));
Simon Huntd2747a02015-04-30 22:41:16 -0700377 }
378 }
379
380 private final class UpdateMeta extends RequestHandler {
381 private UpdateMeta() {
382 super(UPDATE_META);
383 }
384
385 @Override
Simon Hunt8a0429a2017-01-06 16:52:47 -0800386 public void process(ObjectNode payload) {
Simon Huntd2747a02015-04-30 22:41:16 -0700387 updateMetaUi(payload);
388 }
389 }
390
391 private final class EqMasters extends RequestHandler {
392 private EqMasters() {
393 super(EQ_MASTERS);
394 }
395
396 @Override
Simon Hunt8a0429a2017-01-06 16:52:47 -0800397 public void process(ObjectNode payload) {
Simon Hunt1911fe42017-05-02 18:25:58 -0700398 services.mastershipAdmin().balanceRoles();
Simon Huntd2747a02015-04-30 22:41:16 -0700399 }
400 }
401
Simon Hunta17fa672015-08-19 18:42:22 -0700402
403 // ========= -----------------------------------------------------------------
404
Simon Huntd2747a02015-04-30 22:41:16 -0700405 // === TODO: move traffic related classes to traffic app
406
407 private final class AddHostIntent extends RequestHandler {
408 private AddHostIntent() {
409 super(ADD_HOST_INTENT);
410 }
411
412 @Override
Simon Hunt8a0429a2017-01-06 16:52:47 -0800413 public void process(ObjectNode payload) {
Simon Huntd2747a02015-04-30 22:41:16 -0700414 // TODO: add protection against device ids and non-existent hosts.
Simon Huntb745ca62015-07-28 15:37:11 -0700415 HostId one = hostId(string(payload, ONE));
416 HostId two = hostId(string(payload, TWO));
Simon Huntd2747a02015-04-30 22:41:16 -0700417
418 HostToHostIntent intent = HostToHostIntent.builder()
Thomas Vachuskacb5016f2015-05-18 14:11:43 -0700419 .appId(appId)
420 .one(one)
421 .two(two)
422 .build();
Simon Huntd2747a02015-04-30 22:41:16 -0700423
Simon Hunt1911fe42017-05-02 18:25:58 -0700424 services.intent().submit(intent);
Simon Huntd2862c32015-08-24 17:41:51 -0700425 if (overlayCache.isActive(TrafficOverlay.TRAFFIC_ID)) {
426 traffic.monitor(intent);
427 }
Simon Huntd2747a02015-04-30 22:41:16 -0700428 }
429 }
430
Viswanath KSP0f297702016-08-13 18:02:43 +0530431 private Intent findIntentByPayload(ObjectNode payload) {
Yi Tseng3a9b01c2017-02-16 14:24:28 -0800432 Intent intent;
433 Key key;
Viswanath KSP0f297702016-08-13 18:02:43 +0530434 int appId = Integer.parseInt(string(payload, APP_ID));
435 String appName = string(payload, APP_NAME);
436 ApplicationId applicId = new DefaultApplicationId(appId, appName);
Yi Tseng3a9b01c2017-02-16 14:24:28 -0800437 String stringKey = string(payload, KEY);
438 try {
439 // FIXME: If apps use different string key, but they contains
440 // same numeric value (e.g. "020", "0x10", "16", "#10")
441 // and one intent using long key (e.g. 16L)
442 // this function might return wrong intent.
Viswanath KSP0f297702016-08-13 18:02:43 +0530443
Yi Tseng3a9b01c2017-02-16 14:24:28 -0800444 long longKey = Long.decode(stringKey);
445 key = Key.of(longKey, applicId);
Simon Hunt1911fe42017-05-02 18:25:58 -0700446 intent = services.intent().getIntent(key);
Yi Tseng3a9b01c2017-02-16 14:24:28 -0800447
448 if (intent == null) {
449 // Intent might using string key, not long key
450 key = Key.of(stringKey, applicId);
Simon Hunt1911fe42017-05-02 18:25:58 -0700451 intent = services.intent().getIntent(key);
Yi Tseng3a9b01c2017-02-16 14:24:28 -0800452 }
453 } catch (NumberFormatException ex) {
454 // string key
455 key = Key.of(stringKey, applicId);
Simon Hunt1911fe42017-05-02 18:25:58 -0700456 intent = services.intent().getIntent(key);
Yi Tseng3a9b01c2017-02-16 14:24:28 -0800457 }
458
Viswanath KSP0f297702016-08-13 18:02:43 +0530459 log.debug("Attempting to select intent by key={}", key);
460
Yi Tseng3a9b01c2017-02-16 14:24:28 -0800461 return intent;
Viswanath KSP0f297702016-08-13 18:02:43 +0530462 }
463
464 private final class RemoveIntent extends RequestHandler {
465 private RemoveIntent() {
466 super(REMOVE_INTENT);
467 }
468
Viswanath KSP813a20d2016-09-13 04:25:41 +0530469 private boolean isIntentToBePurged(ObjectNode payload) {
470 return bool(payload, PURGE);
471 }
472
Viswanath KSP0f297702016-08-13 18:02:43 +0530473 @Override
Simon Hunt8a0429a2017-01-06 16:52:47 -0800474 public void process(ObjectNode payload) {
Viswanath KSP0f297702016-08-13 18:02:43 +0530475 Intent intent = findIntentByPayload(payload);
476 if (intent == null) {
477 log.warn("Unable to find intent from payload {}", payload);
478 } else {
Viswanath KSP813a20d2016-09-13 04:25:41 +0530479 log.debug("Withdrawing / Purging intent {}", intent.key());
480 if (isIntentToBePurged(payload)) {
Simon Hunt1911fe42017-05-02 18:25:58 -0700481 services.intent().purge(intent);
Viswanath KSP813a20d2016-09-13 04:25:41 +0530482 } else {
Simon Hunt1911fe42017-05-02 18:25:58 -0700483 services.intent().withdraw(intent);
Viswanath KSP813a20d2016-09-13 04:25:41 +0530484 }
Viswanath KSP0f297702016-08-13 18:02:43 +0530485 }
486 }
487 }
488
Viswanath KSP14aee092016-10-02 01:47:40 +0530489 private final class ResubmitIntent extends RequestHandler {
490 private ResubmitIntent() {
491 super(RESUBMIT_INTENT);
492 }
493
494 @Override
Simon Hunt8a0429a2017-01-06 16:52:47 -0800495 public void process(ObjectNode payload) {
Viswanath KSP14aee092016-10-02 01:47:40 +0530496 Intent intent = findIntentByPayload(payload);
497 if (intent == null) {
498 log.warn("Unable to find intent from payload {}", payload);
499 } else {
500 log.debug("Resubmitting intent {}", intent.key());
Simon Hunt1911fe42017-05-02 18:25:58 -0700501 services.intent().submit(intent);
Viswanath KSP14aee092016-10-02 01:47:40 +0530502 }
503 }
504 }
505
Simon Huntd2747a02015-04-30 22:41:16 -0700506 private final class AddMultiSourceIntent extends RequestHandler {
507 private AddMultiSourceIntent() {
508 super(ADD_MULTI_SRC_INTENT);
509 }
510
511 @Override
Simon Hunt8a0429a2017-01-06 16:52:47 -0800512 public void process(ObjectNode payload) {
Simon Huntd2747a02015-04-30 22:41:16 -0700513 // TODO: add protection against device ids and non-existent hosts.
Simon Huntb745ca62015-07-28 15:37:11 -0700514 Set<HostId> src = getHostIds((ArrayNode) payload.path(SRC));
515 HostId dst = hostId(string(payload, DST));
Simon Hunt1911fe42017-05-02 18:25:58 -0700516 Host dstHost = services.host().getHost(dst);
Simon Huntd2747a02015-04-30 22:41:16 -0700517
518 Set<ConnectPoint> ingressPoints = getHostLocations(src);
519
520 // FIXME: clearly, this is not enough
521 TrafficSelector selector = DefaultTrafficSelector.builder()
522 .matchEthDst(dstHost.mac()).build();
523 TrafficTreatment treatment = DefaultTrafficTreatment.emptyTreatment();
524
525 MultiPointToSinglePointIntent intent =
526 MultiPointToSinglePointIntent.builder()
527 .appId(appId)
528 .selector(selector)
529 .treatment(treatment)
530 .ingressPoints(ingressPoints)
531 .egressPoint(dstHost.location())
532 .build();
533
Simon Hunt1911fe42017-05-02 18:25:58 -0700534 services.intent().submit(intent);
Simon Huntd2862c32015-08-24 17:41:51 -0700535 if (overlayCache.isActive(TrafficOverlay.TRAFFIC_ID)) {
536 traffic.monitor(intent);
537 }
Simon Huntd2747a02015-04-30 22:41:16 -0700538 }
539 }
540
Deepa Vaddireddy63340922017-01-19 08:15:31 +0530541 private final class RemoveIntents extends RequestHandler {
542 private RemoveIntents() {
543 super(REMOVE_INTENTS);
544 }
545
546
547 @Override
548 public void process(ObjectNode payload) {
549 IntentService intentService = get(IntentService.class);
550 for (Intent intent : intentService.getIntents()) {
551 if (intentService.getIntentState(intent.key()) == IntentState.WITHDRAWN) {
552 intentService.purge(intent);
553 }
554 }
555
556 }
557 }
558
Simon Hunta17fa672015-08-19 18:42:22 -0700559 // ========= -----------------------------------------------------------------
Simon Huntd2747a02015-04-30 22:41:16 -0700560
Simon Hunt21281fd2017-03-30 22:28:28 -0700561 private final class ReqAllTraffic extends RequestHandler {
562 private ReqAllTraffic() {
563 super(REQ_ALL_TRAFFIC);
Simon Huntd2747a02015-04-30 22:41:16 -0700564 }
565
566 @Override
Simon Hunt8a0429a2017-01-06 16:52:47 -0800567 public void process(ObjectNode payload) {
Simon Hunt21281fd2017-03-30 22:28:28 -0700568 String trafficType = string(payload, TRAFFIC_TYPE, FLOW_STATS_BYTES);
Thomas Vachuskaf0397b52015-05-29 13:50:17 -0700569
Simon Hunt21281fd2017-03-30 22:28:28 -0700570 switch (trafficType) {
571 case FLOW_STATS_BYTES:
572 traffic.monitor(Mode.ALL_FLOW_TRAFFIC_BYTES);
573 break;
574 case PORT_STATS_BIT_SEC:
575 traffic.monitor(Mode.ALL_PORT_TRAFFIC_BIT_PS);
576 break;
577 case PORT_STATS_PKT_SEC:
578 traffic.monitor(Mode.ALL_PORT_TRAFFIC_PKT_PS);
579 break;
580 default:
581 break;
582 }
Simon Huntd2747a02015-04-30 22:41:16 -0700583 }
584 }
585
Simon Hunt1911fe42017-05-02 18:25:58 -0700586 private NodeSelection makeNodeSelection(ObjectNode payload) {
587 return new NodeSelection(payload, services.device(), services.host(),
588 services.link());
589 }
590
591
Simon Huntd2747a02015-04-30 22:41:16 -0700592 private final class ReqDevLinkFlows extends RequestHandler {
593 private ReqDevLinkFlows() {
594 super(REQ_DEV_LINK_FLOWS);
595 }
596
597 @Override
Simon Hunt8a0429a2017-01-06 16:52:47 -0800598 public void process(ObjectNode payload) {
Simon Hunt1911fe42017-05-02 18:25:58 -0700599 traffic.monitor(Mode.DEV_LINK_FLOWS, makeNodeSelection(payload));
Simon Hunta17fa672015-08-19 18:42:22 -0700600 }
601 }
602
603 private final class ReqRelatedIntents extends RequestHandler {
604 private ReqRelatedIntents() {
605 super(REQ_RELATED_INTENTS);
606 }
607
608 @Override
Simon Hunt8a0429a2017-01-06 16:52:47 -0800609 public void process(ObjectNode payload) {
Simon Hunt1911fe42017-05-02 18:25:58 -0700610 traffic.monitor(Mode.RELATED_INTENTS, makeNodeSelection(payload));
Simon Hunta17fa672015-08-19 18:42:22 -0700611 }
612 }
613
614 private final class ReqNextIntent extends RequestHandler {
615 private ReqNextIntent() {
616 super(REQ_NEXT_INTENT);
617 }
618
619 @Override
Simon Hunt8a0429a2017-01-06 16:52:47 -0800620 public void process(ObjectNode payload) {
Simon Hunt4fc86852015-08-20 17:57:52 -0700621 traffic.selectNextIntent();
Simon Hunta17fa672015-08-19 18:42:22 -0700622 }
623 }
624
625 private final class ReqPrevIntent extends RequestHandler {
626 private ReqPrevIntent() {
627 super(REQ_PREV_INTENT);
628 }
629
630 @Override
Simon Hunt8a0429a2017-01-06 16:52:47 -0800631 public void process(ObjectNode payload) {
Simon Hunt4fc86852015-08-20 17:57:52 -0700632 traffic.selectPreviousIntent();
Simon Hunta17fa672015-08-19 18:42:22 -0700633 }
634 }
635
636 private final class ReqSelectedIntentTraffic extends RequestHandler {
637 private ReqSelectedIntentTraffic() {
638 super(REQ_SEL_INTENT_TRAFFIC);
639 }
640
641 @Override
Simon Hunt8a0429a2017-01-06 16:52:47 -0800642 public void process(ObjectNode payload) {
Simon Hunt4fc86852015-08-20 17:57:52 -0700643 traffic.monitor(Mode.SELECTED_INTENT);
Simon Huntd2747a02015-04-30 22:41:16 -0700644 }
645 }
646
Simon Hunt4a6b54b2015-10-27 22:08:25 -0700647 private final class SelIntent extends RequestHandler {
648 private SelIntent() {
649 super(SEL_INTENT);
650 }
651
652 @Override
Simon Hunt8a0429a2017-01-06 16:52:47 -0800653 public void process(ObjectNode payload) {
Viswanath KSP0f297702016-08-13 18:02:43 +0530654 Intent intent = findIntentByPayload(payload);
Simon Hunt4a6b54b2015-10-27 22:08:25 -0700655 if (intent == null) {
Viswanath KSP0f297702016-08-13 18:02:43 +0530656 log.warn("Unable to find intent from payload {}", payload);
Simon Hunt4a6b54b2015-10-27 22:08:25 -0700657 } else {
Viswanath KSP0f297702016-08-13 18:02:43 +0530658 log.debug("starting to monitor intent {}", intent.key());
Simon Hunt4a6b54b2015-10-27 22:08:25 -0700659 traffic.monitor(intent);
660 }
661 }
662 }
663
Andrea Campanella732ea832017-02-06 09:25:59 -0800664 private final class SelProtectedIntent extends RequestHandler {
665 private SelProtectedIntent() {
666 super(SEL_PROTECTED_INTENT);
667 }
668
669 @Override
670 public void process(ObjectNode payload) {
671 Intent intent = findIntentByPayload(payload);
672 if (intent == null) {
673 log.warn("Unable to find protected intent from payload {}", payload);
674 } else {
675 log.debug("starting to monitor protected intent {}", intent.key());
676 protectedIntentMonitor.monitor(intent);
677 }
678 }
679 }
680
Simon Huntd2747a02015-04-30 22:41:16 -0700681 private final class CancelTraffic extends RequestHandler {
682 private CancelTraffic() {
683 super(CANCEL_TRAFFIC);
684 }
685
686 @Override
Simon Hunt8a0429a2017-01-06 16:52:47 -0800687 public void process(ObjectNode payload) {
Simon Hunt4fc86852015-08-20 17:57:52 -0700688 traffic.stopMonitoring();
Simon Huntd2747a02015-04-30 22:41:16 -0700689 }
690 }
691
Andrea Campanella732ea832017-02-06 09:25:59 -0800692 private final class CancelProtectedIntentHighlight extends RequestHandler {
693 private CancelProtectedIntentHighlight() {
694 super(CANCEL_PROTECTED_INTENT_HIGHLIGHT);
695 }
696
697 @Override
698 public void process(ObjectNode payload) {
699 protectedIntentMonitor.stopMonitoring();
700 }
701 }
702
Simon Huntd2747a02015-04-30 22:41:16 -0700703 //=======================================================================
704
Simon Hunta17fa672015-08-19 18:42:22 -0700705 // Converts highlights to JSON format and sends the message to the client
Simon Hunt8a0429a2017-01-06 16:52:47 -0800706 void sendHighlights(Highlights highlights) {
Simon Hunt52560662015-08-27 22:46:44 -0700707 sendMessage(highlightsMessage(highlights));
Thomas Vachuska329af532015-03-10 02:08:33 -0700708 }
709
Simon Huntd2747a02015-04-30 22:41:16 -0700710 // Subscribes for summary messages.
Simon Hunt8a0429a2017-01-06 16:52:47 -0800711 private synchronized void requestSummary() {
712 PropertyPanel pp = summmaryMessage();
Simon Hunt0af1ec32015-07-24 12:17:55 -0700713 overlayCache.currentOverlay().modifySummary(pp);
Simon Hunt8a0429a2017-01-06 16:52:47 -0800714 sendMessage(envelope(SHOW_SUMMARY, json(pp)));
Thomas Vachuska329af532015-03-10 02:08:33 -0700715 }
716
Simon Huntd2747a02015-04-30 22:41:16 -0700717
Thomas Vachuska329af532015-03-10 02:08:33 -0700718 private void cancelAllRequests() {
719 stopSummaryMonitoring();
Simon Hunt4fc86852015-08-20 17:57:52 -0700720 traffic.stopMonitoring();
Thomas Vachuska329af532015-03-10 02:08:33 -0700721 }
722
723 // Sends all controller nodes to the client as node-added messages.
724 private void sendAllInstances(String messageType) {
Simon Hunt1911fe42017-05-02 18:25:58 -0700725 List<ControllerNode> nodes = new ArrayList<>(services.cluster().getNodes());
Simon Hunt8a0429a2017-01-06 16:52:47 -0800726 nodes.sort(NODE_COMPARATOR);
Thomas Vachuska329af532015-03-10 02:08:33 -0700727 for (ControllerNode node : nodes) {
728 sendMessage(instanceMessage(new ClusterEvent(INSTANCE_ADDED, node),
Andrea Campanella732ea832017-02-06 09:25:59 -0800729 messageType));
Thomas Vachuska329af532015-03-10 02:08:33 -0700730 }
731 }
732
733 // Sends all devices to the client as device-added messages.
734 private void sendAllDevices() {
735 // Send optical first, others later for layered rendering
Simon Hunt1911fe42017-05-02 18:25:58 -0700736 for (Device device : services.device().getDevices()) {
Rimon Ashkenazy8ebfff02016-02-01 11:56:36 +0200737 if ((device.type() == Device.Type.ROADM) ||
Simon Hunt5c1a9382016-06-01 19:35:35 -0700738 (device.type() == Device.Type.OTN)) {
Thomas Vachuska329af532015-03-10 02:08:33 -0700739 sendMessage(deviceMessage(new DeviceEvent(DEVICE_ADDED, device)));
740 }
741 }
Simon Hunt1911fe42017-05-02 18:25:58 -0700742 for (Device device : services.device().getDevices()) {
Rimon Ashkenazy8ebfff02016-02-01 11:56:36 +0200743 if ((device.type() != Device.Type.ROADM) &&
Simon Hunt5c1a9382016-06-01 19:35:35 -0700744 (device.type() != Device.Type.OTN)) {
Thomas Vachuska329af532015-03-10 02:08:33 -0700745 sendMessage(deviceMessage(new DeviceEvent(DEVICE_ADDED, device)));
746 }
747 }
748 }
749
750 // Sends all links to the client as link-added messages.
751 private void sendAllLinks() {
752 // Send optical first, others later for layered rendering
Simon Hunt1911fe42017-05-02 18:25:58 -0700753 for (Link link : services.link().getLinks()) {
Thomas Vachuska329af532015-03-10 02:08:33 -0700754 if (link.type() == Link.Type.OPTICAL) {
Simon Hunt5c1a9382016-06-01 19:35:35 -0700755 sendMessage(composeLinkMessage(new LinkEvent(LINK_ADDED, link)));
Thomas Vachuska329af532015-03-10 02:08:33 -0700756 }
757 }
Simon Hunt1911fe42017-05-02 18:25:58 -0700758 for (Link link : services.link().getLinks()) {
Thomas Vachuska329af532015-03-10 02:08:33 -0700759 if (link.type() != Link.Type.OPTICAL) {
Simon Hunt5c1a9382016-06-01 19:35:35 -0700760 sendMessage(composeLinkMessage(new LinkEvent(LINK_ADDED, link)));
Thomas Vachuska329af532015-03-10 02:08:33 -0700761 }
762 }
763 }
764
Simon Hunt5c1a9382016-06-01 19:35:35 -0700765 // Temporary mechanism to support topology overlays adding their own
766 // properties to the link events.
767 private ObjectNode composeLinkMessage(LinkEvent event) {
768 // start with base message
769 ObjectNode msg = linkMessage(event);
770 Map<String, String> additional =
771 overlayCache.currentOverlay().additionalLinkData(event);
772
773 if (additional != null) {
774 // attach additional key-value pairs as extra data structure
775 ObjectNode payload = (ObjectNode) msg.get(PAYLOAD);
776 payload.set(EXTRA, createExtra(additional));
777 }
778 return msg;
779 }
780
781 private ObjectNode createExtra(Map<String, String> additional) {
782 ObjectNode extra = objectNode();
783 for (Map.Entry<String, String> entry : additional.entrySet()) {
784 extra.put(entry.getKey(), entry.getValue());
785 }
786 return extra;
787 }
788
Thomas Vachuska329af532015-03-10 02:08:33 -0700789 // Sends all hosts to the client as host-added messages.
790 private void sendAllHosts() {
Simon Hunt1911fe42017-05-02 18:25:58 -0700791 for (Host host : services.host().getHosts()) {
Thomas Vachuska329af532015-03-10 02:08:33 -0700792 sendMessage(hostMessage(new HostEvent(HOST_ADDED, host)));
793 }
794 }
795
Thomas Vachuska329af532015-03-10 02:08:33 -0700796 private Set<ConnectPoint> getHostLocations(Set<HostId> hostIds) {
797 Set<ConnectPoint> points = new HashSet<>();
798 for (HostId hostId : hostIds) {
799 points.add(getHostLocation(hostId));
800 }
801 return points;
802 }
803
804 private HostLocation getHostLocation(HostId hostId) {
Simon Hunt1911fe42017-05-02 18:25:58 -0700805 return services.host().getHost(hostId).location();
Thomas Vachuska329af532015-03-10 02:08:33 -0700806 }
807
808 // Produces a list of host ids from the specified JSON array.
809 private Set<HostId> getHostIds(ArrayNode ids) {
810 Set<HostId> hostIds = new HashSet<>();
811 for (JsonNode id : ids) {
812 hostIds.add(hostId(id.asText()));
813 }
814 return hostIds;
815 }
816
Simon Hunt4a6b54b2015-10-27 22:08:25 -0700817 private void sendTopoStartDone() {
818 sendMessage(JsonUtils.envelope(TOPO_START_DONE, objectNode()));
819 }
Thomas Vachuska329af532015-03-10 02:08:33 -0700820
Simon Huntd2747a02015-04-30 22:41:16 -0700821 private synchronized void startSummaryMonitoring() {
Thomas Vachuska329af532015-03-10 02:08:33 -0700822 stopSummaryMonitoring();
Thomas Vachuska329af532015-03-10 02:08:33 -0700823 summaryTask = new SummaryMonitor();
Simon Hunta17fa672015-08-19 18:42:22 -0700824 timer.schedule(summaryTask, SUMMARY_PERIOD, SUMMARY_PERIOD);
Simon Huntd2747a02015-04-30 22:41:16 -0700825 summaryRunning = true;
Thomas Vachuska329af532015-03-10 02:08:33 -0700826 }
827
828 private synchronized void stopSummaryMonitoring() {
Simon Huntd2747a02015-04-30 22:41:16 -0700829 if (summaryTask != null) {
Thomas Vachuska329af532015-03-10 02:08:33 -0700830 summaryTask.cancel();
831 summaryTask = null;
Thomas Vachuska329af532015-03-10 02:08:33 -0700832 }
Simon Huntd2747a02015-04-30 22:41:16 -0700833 summaryRunning = false;
Thomas Vachuska9ed335b2015-04-14 12:07:47 -0700834 }
835
Thomas Vachuska329af532015-03-10 02:08:33 -0700836
837 // Adds all internal listeners.
Thomas Vachuska35fa3d42015-04-30 10:11:47 -0700838 private synchronized void addListeners() {
Thomas Vachuskae586b792015-03-26 13:59:38 -0700839 listenersRemoved = false;
Simon Hunt1911fe42017-05-02 18:25:58 -0700840 services.cluster().addListener(clusterListener);
841 services.mastership().addListener(mastershipListener);
842 services.device().addListener(deviceListener);
843 services.link().addListener(linkListener);
844 services.host().addListener(hostListener);
845 services.intent().addListener(intentListener);
846 services.flow().addListener(flowListener);
Thomas Vachuska329af532015-03-10 02:08:33 -0700847 }
848
849 // Removes all internal listeners.
850 private synchronized void removeListeners() {
851 if (!listenersRemoved) {
852 listenersRemoved = true;
Simon Hunt1911fe42017-05-02 18:25:58 -0700853 services.cluster().removeListener(clusterListener);
854 services.mastership().removeListener(mastershipListener);
855 services.device().removeListener(deviceListener);
856 services.link().removeListener(linkListener);
857 services.host().removeListener(hostListener);
858 services.intent().removeListener(intentListener);
859 services.flow().removeListener(flowListener);
Thomas Vachuska329af532015-03-10 02:08:33 -0700860 }
861 }
862
863 // Cluster event listener.
Simon Hunt7092cc42016-04-06 18:40:17 -0700864 // TODO: Superceded by UiSharedTopologyModel.ModelEventListener
865 @Deprecated
Thomas Vachuska329af532015-03-10 02:08:33 -0700866 private class InternalClusterListener implements ClusterEventListener {
867 @Override
868 public void event(ClusterEvent event) {
Thomas Vachuskac7f79962015-05-28 09:37:34 -0700869 msgSender.execute(() -> sendMessage(instanceMessage(event, null)));
Thomas Vachuska329af532015-03-10 02:08:33 -0700870 }
871 }
872
873 // Mastership change listener
Simon Hunt7092cc42016-04-06 18:40:17 -0700874 // TODO: Superceded by UiSharedTopologyModel.ModelEventListener
875 @Deprecated
Thomas Vachuska329af532015-03-10 02:08:33 -0700876 private class InternalMastershipListener implements MastershipListener {
877 @Override
878 public void event(MastershipEvent event) {
Thomas Vachuska52c98bd2015-05-27 20:54:02 -0700879 msgSender.execute(() -> {
Simon Huntb745ca62015-07-28 15:37:11 -0700880 sendAllInstances(UPDATE_INSTANCE);
Simon Hunt1911fe42017-05-02 18:25:58 -0700881 Device device = services.device().getDevice(event.subject());
Thomas Vachuska52c98bd2015-05-27 20:54:02 -0700882 if (device != null) {
883 sendMessage(deviceMessage(new DeviceEvent(DEVICE_UPDATED, device)));
884 }
885 });
Thomas Vachuska329af532015-03-10 02:08:33 -0700886 }
887 }
888
889 // Device event listener.
Simon Hunt7092cc42016-04-06 18:40:17 -0700890 // TODO: Superceded by UiSharedTopologyModel.ModelEventListener
891 @Deprecated
Thomas Vachuska329af532015-03-10 02:08:33 -0700892 private class InternalDeviceListener implements DeviceListener {
893 @Override
894 public void event(DeviceEvent event) {
Thomas Vachuskacb5016f2015-05-18 14:11:43 -0700895 if (event.type() != PORT_STATS_UPDATED) {
Thomas Vachuskac7f79962015-05-28 09:37:34 -0700896 msgSender.execute(() -> sendMessage(deviceMessage(event)));
Simon Hunta1f1c022016-03-03 15:54:57 -0800897 msgSender.execute(traffic::pokeIntent);
Thomas Vachuskacb5016f2015-05-18 14:11:43 -0700898 eventAccummulator.add(event);
899 }
Thomas Vachuska329af532015-03-10 02:08:33 -0700900 }
901 }
902
903 // Link event listener.
Simon Hunt7092cc42016-04-06 18:40:17 -0700904 // TODO: Superceded by UiSharedTopologyModel.ModelEventListener
905 @Deprecated
Thomas Vachuska329af532015-03-10 02:08:33 -0700906 private class InternalLinkListener implements LinkListener {
907 @Override
908 public void event(LinkEvent event) {
Simon Hunt5c1a9382016-06-01 19:35:35 -0700909 msgSender.execute(() -> sendMessage(composeLinkMessage(event)));
Simon Hunta1f1c022016-03-03 15:54:57 -0800910 msgSender.execute(traffic::pokeIntent);
Thomas Vachuska329af532015-03-10 02:08:33 -0700911 eventAccummulator.add(event);
912 }
913 }
914
915 // Host event listener.
Simon Hunt7092cc42016-04-06 18:40:17 -0700916 // TODO: Superceded by UiSharedTopologyModel.ModelEventListener
917 @Deprecated
Thomas Vachuska329af532015-03-10 02:08:33 -0700918 private class InternalHostListener implements HostListener {
919 @Override
920 public void event(HostEvent event) {
Thomas Vachuskac7f79962015-05-28 09:37:34 -0700921 msgSender.execute(() -> sendMessage(hostMessage(event)));
Simon Hunta1f1c022016-03-03 15:54:57 -0800922 msgSender.execute(traffic::pokeIntent);
Thomas Vachuska329af532015-03-10 02:08:33 -0700923 eventAccummulator.add(event);
924 }
925 }
926
927 // Intent event listener.
Simon Hunt7092cc42016-04-06 18:40:17 -0700928 // TODO: Superceded by UiSharedTopologyModel.ModelEventListener
929 @Deprecated
Thomas Vachuska329af532015-03-10 02:08:33 -0700930 private class InternalIntentListener implements IntentListener {
931 @Override
932 public void event(IntentEvent event) {
Simon Hunt4fc86852015-08-20 17:57:52 -0700933 msgSender.execute(traffic::pokeIntent);
Thomas Vachuska329af532015-03-10 02:08:33 -0700934 eventAccummulator.add(event);
935 }
936 }
937
938 // Intent event listener.
Simon Hunt7092cc42016-04-06 18:40:17 -0700939 // TODO: Superceded by UiSharedTopologyModel.ModelEventListener
940 @Deprecated
Thomas Vachuska329af532015-03-10 02:08:33 -0700941 private class InternalFlowListener implements FlowRuleListener {
942 @Override
943 public void event(FlowRuleEvent event) {
944 eventAccummulator.add(event);
945 }
946 }
947
Simon Huntd2747a02015-04-30 22:41:16 -0700948
Simon Hunta17fa672015-08-19 18:42:22 -0700949 // === SUMMARY MONITORING
Thomas Vachuska329af532015-03-10 02:08:33 -0700950
951 // Periodic update of the summary information
952 private class SummaryMonitor extends TimerTask {
953 @Override
954 public void run() {
955 try {
Simon Huntd2747a02015-04-30 22:41:16 -0700956 if (summaryRunning) {
Simon Hunt8a0429a2017-01-06 16:52:47 -0800957 msgSender.execute(() -> requestSummary());
Thomas Vachuska329af532015-03-10 02:08:33 -0700958 }
959 } catch (Exception e) {
960 log.warn("Unable to handle summary request due to {}", e.getMessage());
961 log.warn("Boom!", e);
962 }
963 }
964 }
965
966 // Accumulates events to drive methodic update of the summary pane.
967 private class InternalEventAccummulator extends AbstractAccumulator<Event> {
968 protected InternalEventAccummulator() {
969 super(new Timer("topo-summary"), MAX_EVENTS, MAX_BATCH_MS, MAX_IDLE_MS);
970 }
971
972 @Override
973 public void processItems(List<Event> items) {
Simon Hunta17fa672015-08-19 18:42:22 -0700974 // Start-of-Debugging -- Keep in until ONOS-2572 is fixed for reals
Simon Hunt8d22c4b2015-08-06 16:24:43 -0700975 long now = System.currentTimeMillis();
976 String me = this.toString();
977 String miniMe = me.replaceAll("^.*@", "me@");
978 log.debug("Time: {}; this: {}, processing items ({} events)",
Andrea Campanella732ea832017-02-06 09:25:59 -0800979 now, miniMe, items.size());
Simon Hunt8d22c4b2015-08-06 16:24:43 -0700980 // End-of-Debugging
981
Thomas Vachuska329af532015-03-10 02:08:33 -0700982 try {
Simon Huntd2747a02015-04-30 22:41:16 -0700983 if (summaryRunning) {
Simon Hunt8a0429a2017-01-06 16:52:47 -0800984 msgSender.execute(() -> requestSummary());
Thomas Vachuska329af532015-03-10 02:08:33 -0700985 }
986 } catch (Exception e) {
987 log.warn("Unable to handle summary request due to {}", e.getMessage());
988 log.debug("Boom!", e);
989 }
990 }
991 }
992}