blob: 8acdc2cfbb417545fac86239e65e3c470593432f [file] [log] [blame]
Thomas Vachuska329af532015-03-10 02:08:33 -07001/*
2 * Copyright 2015 Open Networking Laboratory
3 *
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;
30import org.onosproject.event.Event;
31import org.onosproject.mastership.MastershipAdminService;
32import org.onosproject.mastership.MastershipEvent;
33import org.onosproject.mastership.MastershipListener;
34import org.onosproject.net.ConnectPoint;
35import org.onosproject.net.Device;
36import org.onosproject.net.Host;
37import org.onosproject.net.HostId;
38import org.onosproject.net.HostLocation;
39import org.onosproject.net.Link;
40import org.onosproject.net.device.DeviceEvent;
41import org.onosproject.net.device.DeviceListener;
42import org.onosproject.net.flow.DefaultTrafficSelector;
43import org.onosproject.net.flow.DefaultTrafficTreatment;
44import org.onosproject.net.flow.FlowRuleEvent;
45import org.onosproject.net.flow.FlowRuleListener;
46import org.onosproject.net.flow.TrafficSelector;
47import org.onosproject.net.flow.TrafficTreatment;
48import org.onosproject.net.host.HostEvent;
49import org.onosproject.net.host.HostListener;
50import org.onosproject.net.intent.HostToHostIntent;
Thomas Vachuska329af532015-03-10 02:08:33 -070051import org.onosproject.net.intent.IntentEvent;
52import org.onosproject.net.intent.IntentListener;
53import org.onosproject.net.intent.MultiPointToSinglePointIntent;
54import org.onosproject.net.link.LinkEvent;
55import org.onosproject.net.link.LinkListener;
Simon Huntd2747a02015-04-30 22:41:16 -070056import org.onosproject.ui.RequestHandler;
Thomas Vachuska329af532015-03-10 02:08:33 -070057import org.onosproject.ui.UiConnection;
Simon Hunt4fc86852015-08-20 17:57:52 -070058import org.onosproject.ui.impl.TrafficMonitor.Mode;
Simon Hunta17fa672015-08-19 18:42:22 -070059import org.onosproject.ui.topo.Highlights;
Simon Huntd3ceffa2015-08-25 12:44:35 -070060import org.onosproject.ui.topo.NodeSelection;
Simon Hunt0af1ec32015-07-24 12:17:55 -070061import org.onosproject.ui.topo.PropertyPanel;
Thomas Vachuska329af532015-03-10 02:08:33 -070062
63import java.util.ArrayList;
Simon Huntd2747a02015-04-30 22:41:16 -070064import java.util.Collection;
Thomas Vachuska329af532015-03-10 02:08:33 -070065import java.util.Collections;
66import java.util.Comparator;
67import java.util.HashSet;
68import java.util.List;
69import java.util.Set;
70import java.util.Timer;
71import java.util.TimerTask;
Thomas Vachuska52c98bd2015-05-27 20:54:02 -070072import java.util.concurrent.ExecutorService;
Thomas Vachuska329af532015-03-10 02:08:33 -070073
Thomas Vachuska52c98bd2015-05-27 20:54:02 -070074import static java.util.concurrent.Executors.newSingleThreadExecutor;
75import static org.onlab.util.Tools.groupedThreads;
Thomas Vachuska329af532015-03-10 02:08:33 -070076import static org.onosproject.cluster.ClusterEvent.Type.INSTANCE_ADDED;
77import static org.onosproject.net.DeviceId.deviceId;
78import static org.onosproject.net.HostId.hostId;
Thomas Vachuskacb5016f2015-05-18 14:11:43 -070079import static org.onosproject.net.device.DeviceEvent.Type.*;
Thomas Vachuska329af532015-03-10 02:08:33 -070080import static org.onosproject.net.host.HostEvent.Type.HOST_ADDED;
81import static org.onosproject.net.link.LinkEvent.Type.LINK_ADDED;
Simon Huntd3ceffa2015-08-25 12:44:35 -070082import static org.onosproject.ui.JsonUtils.envelope;
Simon Hunt52560662015-08-27 22:46:44 -070083import static org.onosproject.ui.topo.TopoJson.highlightsMessage;
84import static org.onosproject.ui.topo.TopoJson.json;
Thomas Vachuska329af532015-03-10 02:08:33 -070085
86/**
87 * Web socket capable of interacting with the GUI topology view.
88 */
89public class TopologyViewMessageHandler extends TopologyViewMessageHandlerBase {
90
Simon Huntb745ca62015-07-28 15:37:11 -070091 // incoming event types
Simon Huntd2747a02015-04-30 22:41:16 -070092 private static final String REQ_DETAILS = "requestDetails";
93 private static final String UPDATE_META = "updateMeta";
94 private static final String ADD_HOST_INTENT = "addHostIntent";
95 private static final String ADD_MULTI_SRC_INTENT = "addMultiSourceIntent";
96 private static final String REQ_RELATED_INTENTS = "requestRelatedIntents";
97 private static final String REQ_NEXT_INTENT = "requestNextRelatedIntent";
98 private static final String REQ_PREV_INTENT = "requestPrevRelatedIntent";
99 private static final String REQ_SEL_INTENT_TRAFFIC = "requestSelectedIntentTraffic";
Thomas Vachuskaf0397b52015-05-29 13:50:17 -0700100 private static final String REQ_ALL_FLOW_TRAFFIC = "requestAllFlowTraffic";
101 private static final String REQ_ALL_PORT_TRAFFIC = "requestAllPortTraffic";
Simon Huntd2747a02015-04-30 22:41:16 -0700102 private static final String REQ_DEV_LINK_FLOWS = "requestDeviceLinkFlows";
103 private static final String CANCEL_TRAFFIC = "cancelTraffic";
104 private static final String REQ_SUMMARY = "requestSummary";
105 private static final String CANCEL_SUMMARY = "cancelSummary";
106 private static final String EQ_MASTERS = "equalizeMasters";
107 private static final String SPRITE_LIST_REQ = "spriteListRequest";
108 private static final String SPRITE_DATA_REQ = "spriteDataRequest";
109 private static final String TOPO_START = "topoStart";
Simon Hunt732bb2e2015-05-13 18:32:16 -0700110 private static final String TOPO_HEARTBEAT = "topoHeartbeat";
Simon Hunte05cae42015-07-23 17:35:24 -0700111 private static final String TOPO_SELECT_OVERLAY = "topoSelectOverlay";
Simon Huntd2747a02015-04-30 22:41:16 -0700112 private static final String TOPO_STOP = "topoStop";
113
Simon Huntb745ca62015-07-28 15:37:11 -0700114 // outgoing event types
115 private static final String SHOW_SUMMARY = "showSummary";
116 private static final String SHOW_DETAILS = "showDetails";
117 private static final String SPRITE_LIST_RESPONSE = "spriteListResponse";
118 private static final String SPRITE_DATA_RESPONSE = "spriteDataResponse";
119 private static final String UPDATE_INSTANCE = "updateInstance";
120
121 // fields
122 private static final String ID = "id";
Simon Huntb745ca62015-07-28 15:37:11 -0700123 private static final String DEVICE = "device";
124 private static final String HOST = "host";
125 private static final String CLASS = "class";
126 private static final String UNKNOWN = "unknown";
127 private static final String ONE = "one";
128 private static final String TWO = "two";
129 private static final String SRC = "src";
130 private static final String DST = "dst";
131 private static final String DATA = "data";
132 private static final String NAME = "name";
133 private static final String NAMES = "names";
134 private static final String ACTIVATE = "activate";
135 private static final String DEACTIVATE = "deactivate";
Simon Huntb745ca62015-07-28 15:37:11 -0700136
Simon Huntd2747a02015-04-30 22:41:16 -0700137
Thomas Vachuska329af532015-03-10 02:08:33 -0700138 private static final String APP_ID = "org.onosproject.gui";
139
Simon Hunta17fa672015-08-19 18:42:22 -0700140 private static final long TRAFFIC_PERIOD = 5000;
141 private static final long SUMMARY_PERIOD = 30000;
Thomas Vachuska329af532015-03-10 02:08:33 -0700142
143 private static final Comparator<? super ControllerNode> NODE_COMPARATOR =
Thomas Vachuskac0fe09a2015-05-21 12:56:22 -0700144 (o1, o2) -> o1.id().toString().compareTo(o2.id().toString());
Thomas Vachuska329af532015-03-10 02:08:33 -0700145
146
Thomas Vachuska52c98bd2015-05-27 20:54:02 -0700147 private final Timer timer = new Timer("onos-topology-view");
Thomas Vachuska329af532015-03-10 02:08:33 -0700148
149 private static final int MAX_EVENTS = 1000;
150 private static final int MAX_BATCH_MS = 5000;
151 private static final int MAX_IDLE_MS = 1000;
152
153 private ApplicationId appId;
154
155 private final ClusterEventListener clusterListener = new InternalClusterListener();
156 private final MastershipListener mastershipListener = new InternalMastershipListener();
157 private final DeviceListener deviceListener = new InternalDeviceListener();
158 private final LinkListener linkListener = new InternalLinkListener();
159 private final HostListener hostListener = new InternalHostListener();
160 private final IntentListener intentListener = new InternalIntentListener();
161 private final FlowRuleListener flowListener = new InternalFlowListener();
162
163 private final Accumulator<Event> eventAccummulator = new InternalEventAccummulator();
Thomas Vachuska52c98bd2015-05-27 20:54:02 -0700164 private final ExecutorService msgSender =
165 newSingleThreadExecutor(groupedThreads("onos/gui", "msg-sender"));
Thomas Vachuska329af532015-03-10 02:08:33 -0700166
Simon Hunta17fa672015-08-19 18:42:22 -0700167 private TopoOverlayCache overlayCache;
Simon Hunt4fc86852015-08-20 17:57:52 -0700168 private TrafficMonitor traffic;
Thomas Vachuska329af532015-03-10 02:08:33 -0700169
Simon Huntd2747a02015-04-30 22:41:16 -0700170 private TimerTask summaryTask = null;
171 private boolean summaryRunning = false;
Thomas Vachuska329af532015-03-10 02:08:33 -0700172
173 private boolean listenersRemoved = false;
174
Thomas Vachuska329af532015-03-10 02:08:33 -0700175
176 @Override
177 public void init(UiConnection connection, ServiceDirectory directory) {
178 super.init(connection, directory);
Thomas Vachuska329af532015-03-10 02:08:33 -0700179 appId = directory.get(CoreService.class).registerApplication(APP_ID);
Simon Hunt4fc86852015-08-20 17:57:52 -0700180 traffic = new TrafficMonitor(TRAFFIC_PERIOD, servicesBundle, this);
Thomas Vachuska329af532015-03-10 02:08:33 -0700181 }
182
183 @Override
184 public void destroy() {
185 cancelAllRequests();
Thomas Vachuska2bb48632015-04-28 14:40:42 -0700186 removeListeners();
Thomas Vachuska329af532015-03-10 02:08:33 -0700187 super.destroy();
188 }
189
Thomas Vachuska329af532015-03-10 02:08:33 -0700190 @Override
Simon Huntda580882015-05-12 20:58:18 -0700191 protected Collection<RequestHandler> createRequestHandlers() {
Simon Huntd2747a02015-04-30 22:41:16 -0700192 return ImmutableSet.of(
193 new TopoStart(),
Simon Hunt732bb2e2015-05-13 18:32:16 -0700194 new TopoHeartbeat(),
Simon Hunte05cae42015-07-23 17:35:24 -0700195 new TopoSelectOverlay(),
Simon Huntd2747a02015-04-30 22:41:16 -0700196 new TopoStop(),
197 new ReqSummary(),
198 new CancelSummary(),
199 new SpriteListReq(),
200 new SpriteDataReq(),
201 new RequestDetails(),
202 new UpdateMeta(),
203 new EqMasters(),
Thomas Vachuska329af532015-03-10 02:08:33 -0700204
Simon Huntd2747a02015-04-30 22:41:16 -0700205 // TODO: migrate traffic related to separate app
206 new AddHostIntent(),
207 new AddMultiSourceIntent(),
Simon Hunta17fa672015-08-19 18:42:22 -0700208
209 new ReqAllFlowTraffic(),
210 new ReqAllPortTraffic(),
211 new ReqDevLinkFlows(),
Simon Huntd2747a02015-04-30 22:41:16 -0700212 new ReqRelatedIntents(),
213 new ReqNextIntent(),
214 new ReqPrevIntent(),
215 new ReqSelectedIntentTraffic(),
Simon Hunta17fa672015-08-19 18:42:22 -0700216
Simon Huntd2747a02015-04-30 22:41:16 -0700217 new CancelTraffic()
218 );
219 }
Thomas Vachuska329af532015-03-10 02:08:33 -0700220
Simon Hunte05cae42015-07-23 17:35:24 -0700221 /**
222 * Injects the topology overlay cache.
223 *
224 * @param overlayCache injected cache
225 */
226 void setOverlayCache(TopoOverlayCache overlayCache) {
227 this.overlayCache = overlayCache;
228 }
229
Simon Huntd2747a02015-04-30 22:41:16 -0700230 // ==================================================================
Thomas Vachuska329af532015-03-10 02:08:33 -0700231
Simon Huntd2747a02015-04-30 22:41:16 -0700232 private final class TopoStart extends RequestHandler {
233 private TopoStart() {
234 super(TOPO_START);
235 }
Thomas Vachuska329af532015-03-10 02:08:33 -0700236
Simon Huntd2747a02015-04-30 22:41:16 -0700237 @Override
238 public void process(long sid, ObjectNode payload) {
239 addListeners();
240 sendAllInstances(null);
241 sendAllDevices();
242 sendAllLinks();
243 sendAllHosts();
Thomas Vachuska329af532015-03-10 02:08:33 -0700244 }
245 }
246
Simon Hunt732bb2e2015-05-13 18:32:16 -0700247 private final class TopoHeartbeat extends RequestHandler {
248 private TopoHeartbeat() {
249 super(TOPO_HEARTBEAT);
250 }
251
252 @Override
253 public void process(long sid, ObjectNode payload) {
254 // place holder for now
255 }
256 }
257
Simon Hunte05cae42015-07-23 17:35:24 -0700258 private final class TopoSelectOverlay extends RequestHandler {
259 private TopoSelectOverlay() {
260 super(TOPO_SELECT_OVERLAY);
261 }
262
263 @Override
264 public void process(long sid, ObjectNode payload) {
Simon Huntb745ca62015-07-28 15:37:11 -0700265 String deact = string(payload, DEACTIVATE);
266 String act = string(payload, ACTIVATE);
Simon Hunte05cae42015-07-23 17:35:24 -0700267 overlayCache.switchOverlay(deact, act);
268 }
269 }
270
Simon Huntd2747a02015-04-30 22:41:16 -0700271 private final class TopoStop extends RequestHandler {
272 private TopoStop() {
273 super(TOPO_STOP);
274 }
275
276 @Override
277 public void process(long sid, ObjectNode payload) {
278 stopSummaryMonitoring();
Simon Hunt4fc86852015-08-20 17:57:52 -0700279 traffic.stopMonitoring();
Simon Huntd2747a02015-04-30 22:41:16 -0700280 }
281 }
282
283 private final class ReqSummary extends RequestHandler {
284 private ReqSummary() {
285 super(REQ_SUMMARY);
286 }
287
288 @Override
289 public void process(long sid, ObjectNode payload) {
290 requestSummary(sid);
291 startSummaryMonitoring();
292 }
293 }
294
295 private final class CancelSummary extends RequestHandler {
296 private CancelSummary() {
297 super(CANCEL_SUMMARY);
298 }
299
300 @Override
301 public void process(long sid, ObjectNode payload) {
302 stopSummaryMonitoring();
303 }
304 }
305
306 private final class SpriteListReq extends RequestHandler {
307 private SpriteListReq() {
308 super(SPRITE_LIST_REQ);
309 }
310
311 @Override
312 public void process(long sid, ObjectNode payload) {
Simon Huntda580882015-05-12 20:58:18 -0700313 ObjectNode root = objectNode();
314 ArrayNode names = arrayNode();
Simon Huntd2747a02015-04-30 22:41:16 -0700315 get(SpriteService.class).getNames().forEach(names::add);
Simon Huntb745ca62015-07-28 15:37:11 -0700316 root.set(NAMES, names);
317 sendMessage(SPRITE_LIST_RESPONSE, sid, root);
Simon Huntd2747a02015-04-30 22:41:16 -0700318 }
319 }
320
321 private final class SpriteDataReq extends RequestHandler {
322 private SpriteDataReq() {
323 super(SPRITE_DATA_REQ);
324 }
325
326 @Override
327 public void process(long sid, ObjectNode payload) {
Simon Huntb745ca62015-07-28 15:37:11 -0700328 String name = string(payload, NAME);
Simon Huntda580882015-05-12 20:58:18 -0700329 ObjectNode root = objectNode();
Simon Huntb745ca62015-07-28 15:37:11 -0700330 root.set(DATA, get(SpriteService.class).get(name));
331 sendMessage(SPRITE_DATA_RESPONSE, sid, root);
Simon Huntd2747a02015-04-30 22:41:16 -0700332 }
333 }
334
335 private final class RequestDetails extends RequestHandler {
336 private RequestDetails() {
337 super(REQ_DETAILS);
338 }
339
340 @Override
341 public void process(long sid, ObjectNode payload) {
Simon Huntb745ca62015-07-28 15:37:11 -0700342 String type = string(payload, CLASS, UNKNOWN);
343 String id = string(payload, ID);
344 PropertyPanel pp = null;
Simon Huntd2747a02015-04-30 22:41:16 -0700345
Simon Huntb745ca62015-07-28 15:37:11 -0700346 if (type.equals(DEVICE)) {
347 pp = deviceDetails(deviceId(id), sid);
348 overlayCache.currentOverlay().modifyDeviceDetails(pp);
349 } else if (type.equals(HOST)) {
350 pp = hostDetails(hostId(id), sid);
351 overlayCache.currentOverlay().modifyHostDetails(pp);
Simon Huntd2747a02015-04-30 22:41:16 -0700352 }
Simon Huntb745ca62015-07-28 15:37:11 -0700353
Simon Huntd3ceffa2015-08-25 12:44:35 -0700354 sendMessage(envelope(SHOW_DETAILS, sid, json(pp)));
Simon Huntd2747a02015-04-30 22:41:16 -0700355 }
356 }
357
358 private final class UpdateMeta extends RequestHandler {
359 private UpdateMeta() {
360 super(UPDATE_META);
361 }
362
363 @Override
364 public void process(long sid, ObjectNode payload) {
365 updateMetaUi(payload);
366 }
367 }
368
369 private final class EqMasters extends RequestHandler {
370 private EqMasters() {
371 super(EQ_MASTERS);
372 }
373
374 @Override
375 public void process(long sid, ObjectNode payload) {
376 directory.get(MastershipAdminService.class).balanceRoles();
377 }
378 }
379
Simon Hunta17fa672015-08-19 18:42:22 -0700380
381 // ========= -----------------------------------------------------------------
382
Simon Huntd2747a02015-04-30 22:41:16 -0700383 // === TODO: move traffic related classes to traffic app
384
385 private final class AddHostIntent extends RequestHandler {
386 private AddHostIntent() {
387 super(ADD_HOST_INTENT);
388 }
389
390 @Override
391 public void process(long sid, ObjectNode payload) {
392 // TODO: add protection against device ids and non-existent hosts.
Simon Huntb745ca62015-07-28 15:37:11 -0700393 HostId one = hostId(string(payload, ONE));
394 HostId two = hostId(string(payload, TWO));
Simon Huntd2747a02015-04-30 22:41:16 -0700395
396 HostToHostIntent intent = HostToHostIntent.builder()
Thomas Vachuskacb5016f2015-05-18 14:11:43 -0700397 .appId(appId)
398 .one(one)
399 .two(two)
400 .build();
Simon Huntd2747a02015-04-30 22:41:16 -0700401
402 intentService.submit(intent);
Simon Huntd2862c32015-08-24 17:41:51 -0700403 if (overlayCache.isActive(TrafficOverlay.TRAFFIC_ID)) {
404 traffic.monitor(intent);
405 }
Simon Huntd2747a02015-04-30 22:41:16 -0700406 }
407 }
408
409 private final class AddMultiSourceIntent extends RequestHandler {
410 private AddMultiSourceIntent() {
411 super(ADD_MULTI_SRC_INTENT);
412 }
413
414 @Override
415 public void process(long sid, ObjectNode payload) {
416 // TODO: add protection against device ids and non-existent hosts.
Simon Huntb745ca62015-07-28 15:37:11 -0700417 Set<HostId> src = getHostIds((ArrayNode) payload.path(SRC));
418 HostId dst = hostId(string(payload, DST));
Simon Huntd2747a02015-04-30 22:41:16 -0700419 Host dstHost = hostService.getHost(dst);
420
421 Set<ConnectPoint> ingressPoints = getHostLocations(src);
422
423 // FIXME: clearly, this is not enough
424 TrafficSelector selector = DefaultTrafficSelector.builder()
425 .matchEthDst(dstHost.mac()).build();
426 TrafficTreatment treatment = DefaultTrafficTreatment.emptyTreatment();
427
428 MultiPointToSinglePointIntent intent =
429 MultiPointToSinglePointIntent.builder()
430 .appId(appId)
431 .selector(selector)
432 .treatment(treatment)
433 .ingressPoints(ingressPoints)
434 .egressPoint(dstHost.location())
435 .build();
436
437 intentService.submit(intent);
Simon Huntd2862c32015-08-24 17:41:51 -0700438 if (overlayCache.isActive(TrafficOverlay.TRAFFIC_ID)) {
439 traffic.monitor(intent);
440 }
Simon Huntd2747a02015-04-30 22:41:16 -0700441 }
442 }
443
Simon Hunta17fa672015-08-19 18:42:22 -0700444 // ========= -----------------------------------------------------------------
Simon Huntd2747a02015-04-30 22:41:16 -0700445
Thomas Vachuskaf0397b52015-05-29 13:50:17 -0700446 private final class ReqAllFlowTraffic extends RequestHandler {
447 private ReqAllFlowTraffic() {
448 super(REQ_ALL_FLOW_TRAFFIC);
Simon Huntd2747a02015-04-30 22:41:16 -0700449 }
450
451 @Override
452 public void process(long sid, ObjectNode payload) {
Simon Hunt4fc86852015-08-20 17:57:52 -0700453 traffic.monitor(Mode.ALL_FLOW_TRAFFIC);
Thomas Vachuskaf0397b52015-05-29 13:50:17 -0700454 }
455 }
456
457 private final class ReqAllPortTraffic extends RequestHandler {
458 private ReqAllPortTraffic() {
459 super(REQ_ALL_PORT_TRAFFIC);
460 }
461
462 @Override
463 public void process(long sid, ObjectNode payload) {
Simon Hunt4fc86852015-08-20 17:57:52 -0700464 traffic.monitor(Mode.ALL_PORT_TRAFFIC);
Simon Huntd2747a02015-04-30 22:41:16 -0700465 }
466 }
467
468 private final class ReqDevLinkFlows extends RequestHandler {
469 private ReqDevLinkFlows() {
470 super(REQ_DEV_LINK_FLOWS);
471 }
472
473 @Override
474 public void process(long sid, ObjectNode payload) {
Simon Hunta17fa672015-08-19 18:42:22 -0700475 NodeSelection nodeSelection =
476 new NodeSelection(payload, deviceService, hostService);
Simon Hunt4fc86852015-08-20 17:57:52 -0700477 traffic.monitor(Mode.DEV_LINK_FLOWS, nodeSelection);
Simon Hunta17fa672015-08-19 18:42:22 -0700478 }
479 }
480
481 private final class ReqRelatedIntents extends RequestHandler {
482 private ReqRelatedIntents() {
483 super(REQ_RELATED_INTENTS);
484 }
485
486 @Override
487 public void process(long sid, ObjectNode payload) {
488 NodeSelection nodeSelection =
489 new NodeSelection(payload, deviceService, hostService);
Simon Hunt4fc86852015-08-20 17:57:52 -0700490 traffic.monitor(Mode.RELATED_INTENTS, nodeSelection);
Simon Hunta17fa672015-08-19 18:42:22 -0700491 }
492 }
493
494 private final class ReqNextIntent extends RequestHandler {
495 private ReqNextIntent() {
496 super(REQ_NEXT_INTENT);
497 }
498
499 @Override
500 public void process(long sid, ObjectNode payload) {
Simon Hunt4fc86852015-08-20 17:57:52 -0700501 traffic.selectNextIntent();
Simon Hunta17fa672015-08-19 18:42:22 -0700502 }
503 }
504
505 private final class ReqPrevIntent extends RequestHandler {
506 private ReqPrevIntent() {
507 super(REQ_PREV_INTENT);
508 }
509
510 @Override
511 public void process(long sid, ObjectNode payload) {
Simon Hunt4fc86852015-08-20 17:57:52 -0700512 traffic.selectPreviousIntent();
Simon Hunta17fa672015-08-19 18:42:22 -0700513 }
514 }
515
516 private final class ReqSelectedIntentTraffic extends RequestHandler {
517 private ReqSelectedIntentTraffic() {
518 super(REQ_SEL_INTENT_TRAFFIC);
519 }
520
521 @Override
522 public void process(long sid, ObjectNode payload) {
Simon Hunt4fc86852015-08-20 17:57:52 -0700523 traffic.monitor(Mode.SELECTED_INTENT);
Simon Huntd2747a02015-04-30 22:41:16 -0700524 }
525 }
526
527 private final class CancelTraffic extends RequestHandler {
528 private CancelTraffic() {
529 super(CANCEL_TRAFFIC);
530 }
531
532 @Override
533 public void process(long sid, ObjectNode payload) {
Simon Hunt4fc86852015-08-20 17:57:52 -0700534 traffic.stopMonitoring();
Simon Huntd2747a02015-04-30 22:41:16 -0700535 }
536 }
537
538 //=======================================================================
539
Simon Hunta17fa672015-08-19 18:42:22 -0700540 // Converts highlights to JSON format and sends the message to the client
541 protected void sendHighlights(Highlights highlights) {
Simon Hunt52560662015-08-27 22:46:44 -0700542 sendMessage(highlightsMessage(highlights));
Thomas Vachuska329af532015-03-10 02:08:33 -0700543 }
544
Simon Huntd2747a02015-04-30 22:41:16 -0700545 // Subscribes for summary messages.
546 private synchronized void requestSummary(long sid) {
Simon Hunt0af1ec32015-07-24 12:17:55 -0700547 PropertyPanel pp = summmaryMessage(sid);
548 overlayCache.currentOverlay().modifySummary(pp);
Simon Huntd3ceffa2015-08-25 12:44:35 -0700549 sendMessage(envelope(SHOW_SUMMARY, sid, json(pp)));
Thomas Vachuska329af532015-03-10 02:08:33 -0700550 }
551
Simon Huntd2747a02015-04-30 22:41:16 -0700552
Thomas Vachuska329af532015-03-10 02:08:33 -0700553 private void cancelAllRequests() {
554 stopSummaryMonitoring();
Simon Hunt4fc86852015-08-20 17:57:52 -0700555 traffic.stopMonitoring();
Thomas Vachuska329af532015-03-10 02:08:33 -0700556 }
557
558 // Sends all controller nodes to the client as node-added messages.
559 private void sendAllInstances(String messageType) {
560 List<ControllerNode> nodes = new ArrayList<>(clusterService.getNodes());
561 Collections.sort(nodes, NODE_COMPARATOR);
562 for (ControllerNode node : nodes) {
563 sendMessage(instanceMessage(new ClusterEvent(INSTANCE_ADDED, node),
564 messageType));
565 }
566 }
567
568 // Sends all devices to the client as device-added messages.
569 private void sendAllDevices() {
570 // Send optical first, others later for layered rendering
571 for (Device device : deviceService.getDevices()) {
572 if (device.type() == Device.Type.ROADM) {
573 sendMessage(deviceMessage(new DeviceEvent(DEVICE_ADDED, device)));
574 }
575 }
576 for (Device device : deviceService.getDevices()) {
577 if (device.type() != Device.Type.ROADM) {
578 sendMessage(deviceMessage(new DeviceEvent(DEVICE_ADDED, device)));
579 }
580 }
581 }
582
583 // Sends all links to the client as link-added messages.
584 private void sendAllLinks() {
585 // Send optical first, others later for layered rendering
586 for (Link link : linkService.getLinks()) {
587 if (link.type() == Link.Type.OPTICAL) {
588 sendMessage(linkMessage(new LinkEvent(LINK_ADDED, link)));
589 }
590 }
591 for (Link link : linkService.getLinks()) {
592 if (link.type() != Link.Type.OPTICAL) {
593 sendMessage(linkMessage(new LinkEvent(LINK_ADDED, link)));
594 }
595 }
596 }
597
598 // Sends all hosts to the client as host-added messages.
599 private void sendAllHosts() {
600 for (Host host : hostService.getHosts()) {
601 sendMessage(hostMessage(new HostEvent(HOST_ADDED, host)));
602 }
603 }
604
Thomas Vachuska329af532015-03-10 02:08:33 -0700605 private Set<ConnectPoint> getHostLocations(Set<HostId> hostIds) {
606 Set<ConnectPoint> points = new HashSet<>();
607 for (HostId hostId : hostIds) {
608 points.add(getHostLocation(hostId));
609 }
610 return points;
611 }
612
613 private HostLocation getHostLocation(HostId hostId) {
614 return hostService.getHost(hostId).location();
615 }
616
617 // Produces a list of host ids from the specified JSON array.
618 private Set<HostId> getHostIds(ArrayNode ids) {
619 Set<HostId> hostIds = new HashSet<>();
620 for (JsonNode id : ids) {
621 hostIds.add(hostId(id.asText()));
622 }
623 return hostIds;
624 }
625
626
Simon Huntd2747a02015-04-30 22:41:16 -0700627 private synchronized void startSummaryMonitoring() {
Thomas Vachuska329af532015-03-10 02:08:33 -0700628 stopSummaryMonitoring();
Thomas Vachuska329af532015-03-10 02:08:33 -0700629 summaryTask = new SummaryMonitor();
Simon Hunta17fa672015-08-19 18:42:22 -0700630 timer.schedule(summaryTask, SUMMARY_PERIOD, SUMMARY_PERIOD);
Simon Huntd2747a02015-04-30 22:41:16 -0700631 summaryRunning = true;
Thomas Vachuska329af532015-03-10 02:08:33 -0700632 }
633
634 private synchronized void stopSummaryMonitoring() {
Simon Huntd2747a02015-04-30 22:41:16 -0700635 if (summaryTask != null) {
Thomas Vachuska329af532015-03-10 02:08:33 -0700636 summaryTask.cancel();
637 summaryTask = null;
Thomas Vachuska329af532015-03-10 02:08:33 -0700638 }
Simon Huntd2747a02015-04-30 22:41:16 -0700639 summaryRunning = false;
Thomas Vachuska9ed335b2015-04-14 12:07:47 -0700640 }
641
Thomas Vachuska329af532015-03-10 02:08:33 -0700642
643 // Adds all internal listeners.
Thomas Vachuska35fa3d42015-04-30 10:11:47 -0700644 private synchronized void addListeners() {
Thomas Vachuskae586b792015-03-26 13:59:38 -0700645 listenersRemoved = false;
Thomas Vachuska329af532015-03-10 02:08:33 -0700646 clusterService.addListener(clusterListener);
647 mastershipService.addListener(mastershipListener);
648 deviceService.addListener(deviceListener);
649 linkService.addListener(linkListener);
650 hostService.addListener(hostListener);
651 intentService.addListener(intentListener);
652 flowService.addListener(flowListener);
653 }
654
655 // Removes all internal listeners.
656 private synchronized void removeListeners() {
657 if (!listenersRemoved) {
658 listenersRemoved = true;
659 clusterService.removeListener(clusterListener);
660 mastershipService.removeListener(mastershipListener);
661 deviceService.removeListener(deviceListener);
662 linkService.removeListener(linkListener);
663 hostService.removeListener(hostListener);
664 intentService.removeListener(intentListener);
665 flowService.removeListener(flowListener);
666 }
667 }
668
669 // Cluster event listener.
670 private class InternalClusterListener implements ClusterEventListener {
671 @Override
672 public void event(ClusterEvent event) {
Thomas Vachuskac7f79962015-05-28 09:37:34 -0700673 msgSender.execute(() -> sendMessage(instanceMessage(event, null)));
Thomas Vachuska329af532015-03-10 02:08:33 -0700674 }
675 }
676
677 // Mastership change listener
678 private class InternalMastershipListener implements MastershipListener {
679 @Override
680 public void event(MastershipEvent event) {
Thomas Vachuska52c98bd2015-05-27 20:54:02 -0700681 msgSender.execute(() -> {
Simon Huntb745ca62015-07-28 15:37:11 -0700682 sendAllInstances(UPDATE_INSTANCE);
Thomas Vachuska52c98bd2015-05-27 20:54:02 -0700683 Device device = deviceService.getDevice(event.subject());
684 if (device != null) {
685 sendMessage(deviceMessage(new DeviceEvent(DEVICE_UPDATED, device)));
686 }
687 });
Thomas Vachuska329af532015-03-10 02:08:33 -0700688 }
689 }
690
691 // Device event listener.
692 private class InternalDeviceListener implements DeviceListener {
693 @Override
694 public void event(DeviceEvent event) {
Thomas Vachuskacb5016f2015-05-18 14:11:43 -0700695 if (event.type() != PORT_STATS_UPDATED) {
Thomas Vachuskac7f79962015-05-28 09:37:34 -0700696 msgSender.execute(() -> sendMessage(deviceMessage(event)));
Thomas Vachuskacb5016f2015-05-18 14:11:43 -0700697 eventAccummulator.add(event);
698 }
Thomas Vachuska329af532015-03-10 02:08:33 -0700699 }
700 }
701
702 // Link event listener.
703 private class InternalLinkListener implements LinkListener {
704 @Override
705 public void event(LinkEvent event) {
Thomas Vachuskac7f79962015-05-28 09:37:34 -0700706 msgSender.execute(() -> sendMessage(linkMessage(event)));
Thomas Vachuska329af532015-03-10 02:08:33 -0700707 eventAccummulator.add(event);
708 }
709 }
710
711 // Host event listener.
712 private class InternalHostListener implements HostListener {
713 @Override
714 public void event(HostEvent event) {
Thomas Vachuskac7f79962015-05-28 09:37:34 -0700715 msgSender.execute(() -> sendMessage(hostMessage(event)));
Thomas Vachuska329af532015-03-10 02:08:33 -0700716 eventAccummulator.add(event);
717 }
718 }
719
720 // Intent event listener.
721 private class InternalIntentListener implements IntentListener {
722 @Override
723 public void event(IntentEvent event) {
Simon Hunt4fc86852015-08-20 17:57:52 -0700724 msgSender.execute(traffic::pokeIntent);
Thomas Vachuska329af532015-03-10 02:08:33 -0700725 eventAccummulator.add(event);
726 }
727 }
728
729 // Intent event listener.
730 private class InternalFlowListener implements FlowRuleListener {
731 @Override
732 public void event(FlowRuleEvent event) {
733 eventAccummulator.add(event);
734 }
735 }
736
Simon Huntd2747a02015-04-30 22:41:16 -0700737
Simon Hunta17fa672015-08-19 18:42:22 -0700738 // === SUMMARY MONITORING
Thomas Vachuska329af532015-03-10 02:08:33 -0700739
740 // Periodic update of the summary information
741 private class SummaryMonitor extends TimerTask {
742 @Override
743 public void run() {
744 try {
Simon Huntd2747a02015-04-30 22:41:16 -0700745 if (summaryRunning) {
Thomas Vachuskac7f79962015-05-28 09:37:34 -0700746 msgSender.execute(() -> requestSummary(0));
Thomas Vachuska329af532015-03-10 02:08:33 -0700747 }
748 } catch (Exception e) {
749 log.warn("Unable to handle summary request due to {}", e.getMessage());
750 log.warn("Boom!", e);
751 }
752 }
753 }
754
755 // Accumulates events to drive methodic update of the summary pane.
756 private class InternalEventAccummulator extends AbstractAccumulator<Event> {
757 protected InternalEventAccummulator() {
758 super(new Timer("topo-summary"), MAX_EVENTS, MAX_BATCH_MS, MAX_IDLE_MS);
759 }
760
761 @Override
762 public void processItems(List<Event> items) {
Simon Hunta17fa672015-08-19 18:42:22 -0700763 // Start-of-Debugging -- Keep in until ONOS-2572 is fixed for reals
Simon Hunt8d22c4b2015-08-06 16:24:43 -0700764 long now = System.currentTimeMillis();
765 String me = this.toString();
766 String miniMe = me.replaceAll("^.*@", "me@");
767 log.debug("Time: {}; this: {}, processing items ({} events)",
768 now, miniMe, items.size());
769 // End-of-Debugging
770
Thomas Vachuska329af532015-03-10 02:08:33 -0700771 try {
Simon Huntd2747a02015-04-30 22:41:16 -0700772 if (summaryRunning) {
Thomas Vachuskac7f79962015-05-28 09:37:34 -0700773 msgSender.execute(() -> requestSummary(0));
Thomas Vachuska329af532015-03-10 02:08:33 -0700774 }
775 } catch (Exception e) {
776 log.warn("Unable to handle summary request due to {}", e.getMessage());
777 log.debug("Boom!", e);
778 }
779 }
780 }
781}