blob: abae9954687b4bfb8350cf913ba50a75b9106e80 [file] [log] [blame]
Simon Hunt1ee09852015-09-29 12:28:14 -07001#set( $symbol_pound = '#' )
2#set( $symbol_dollar = '$' )
3#set( $symbol_escape = '\' )
4/*
Jian Lic6c76dc2016-01-26 14:22:51 -08005 * Copyright ${year} Open Networking Laboratory
Simon Hunt1ee09852015-09-29 12:28:14 -07006 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 */
19package ${package};
20
21import com.fasterxml.jackson.databind.node.ObjectNode;
22import com.google.common.base.Strings;
23import com.google.common.collect.ImmutableSet;
24import org.onlab.osgi.ServiceDirectory;
25import org.onosproject.net.Device;
26import org.onosproject.net.DeviceId;
27import org.onosproject.net.Element;
28import org.onosproject.net.HostId;
29import org.onosproject.net.Link;
30import org.onosproject.net.device.DeviceService;
31import org.onosproject.net.host.HostService;
32import org.onosproject.net.link.LinkService;
33import org.onosproject.ui.RequestHandler;
34import org.onosproject.ui.UiConnection;
35import org.onosproject.ui.UiMessageHandler;
Simon Huntde99e0b2015-10-23 18:54:06 -070036import org.onosproject.ui.topo.DeviceHighlight;
Simon Hunt1ee09852015-09-29 12:28:14 -070037import org.onosproject.ui.topo.Highlights;
Simon Huntde99e0b2015-10-23 18:54:06 -070038import org.onosproject.ui.topo.NodeBadge;
39import org.onosproject.ui.topo.NodeBadge.Status;
Simon Hunt1ee09852015-09-29 12:28:14 -070040import org.onosproject.ui.topo.TopoJson;
41import org.slf4j.Logger;
42import org.slf4j.LoggerFactory;
43
44import java.util.Collection;
45import java.util.HashSet;
46import java.util.Set;
47import java.util.Timer;
48import java.util.TimerTask;
49
50/**
51 * Skeletal ONOS UI Topology-Overlay message handler.
52 */
53public class AppUiTopovMessageHandler extends UiMessageHandler {
54
Simon Hunt40098072015-10-13 17:22:26 -070055 private static final String SAMPLE_TOPOV_DISPLAY_START = "sampleTopovDisplayStart";
56 private static final String SAMPLE_TOPOV_DISPLAY_UPDATE = "sampleTopovDisplayUpdate";
57 private static final String SAMPLE_TOPOV_DISPLAY_STOP = "sampleTopovDisplayStop";
Simon Hunt1ee09852015-09-29 12:28:14 -070058
59 private static final String ID = "id";
60 private static final String MODE = "mode";
61
62 private static final long UPDATE_PERIOD_MS = 1000;
63
64 private static final Link[] EMPTY_LINK_SET = new Link[0];
65
66 private enum Mode { IDLE, MOUSE, LINK }
67
68 private final Logger log = LoggerFactory.getLogger(getClass());
69
70 private DeviceService deviceService;
71 private HostService hostService;
72 private LinkService linkService;
73
74 private final Timer timer = new Timer("sample-overlay");
75 private TimerTask demoTask = null;
76 private Mode currentMode = Mode.IDLE;
77 private Element elementOfNote;
78 private Link[] linkSet = EMPTY_LINK_SET;
79 private int linkIndex;
80
81
82 // ===============-=-=-=-=-=-======================-=-=-=-=-=-=-================================
83
84
85 @Override
86 public void init(UiConnection connection, ServiceDirectory directory) {
87 super.init(connection, directory);
88 deviceService = directory.get(DeviceService.class);
89 hostService = directory.get(HostService.class);
90 linkService = directory.get(LinkService.class);
91 }
92
93 @Override
94 protected Collection<RequestHandler> createRequestHandlers() {
95 return ImmutableSet.of(
96 new DisplayStartHandler(),
97 new DisplayUpdateHandler(),
98 new DisplayStopHandler()
99 );
100 }
101
102 // === -------------------------
103 // === Handler classes
104
105 private final class DisplayStartHandler extends RequestHandler {
106 public DisplayStartHandler() {
Thomas Vachuskae1753232015-10-15 18:31:53 -0700107 super(SAMPLE_TOPOV_DISPLAY_START);
Simon Hunt1ee09852015-09-29 12:28:14 -0700108 }
109
110 @Override
111 public void process(long sid, ObjectNode payload) {
112 String mode = string(payload, MODE);
113
114 log.debug("Start Display: mode [{}]", mode);
115 clearState();
116 clearForMode();
117
118 switch (mode) {
119 case "mouse":
120 currentMode = Mode.MOUSE;
121 cancelTask();
122 sendMouseData();
123 break;
124
125 case "link":
126 currentMode = Mode.LINK;
127 scheduleTask();
128 initLinkSet();
129 sendLinkData();
130 break;
131
132 default:
133 currentMode = Mode.IDLE;
134 cancelTask();
135 break;
136 }
137 }
138 }
139
140 private final class DisplayUpdateHandler extends RequestHandler {
141 public DisplayUpdateHandler() {
Thomas Vachuskae1753232015-10-15 18:31:53 -0700142 super(SAMPLE_TOPOV_DISPLAY_UPDATE);
Simon Hunt1ee09852015-09-29 12:28:14 -0700143 }
144
145 @Override
146 public void process(long sid, ObjectNode payload) {
147 String id = string(payload, ID);
148 log.debug("Update Display: id [{}]", id);
149 if (!Strings.isNullOrEmpty(id)) {
150 updateForMode(id);
151 } else {
152 clearForMode();
153 }
154 }
155 }
156
157 private final class DisplayStopHandler extends RequestHandler {
158 public DisplayStopHandler() {
Thomas Vachuskae1753232015-10-15 18:31:53 -0700159 super(SAMPLE_TOPOV_DISPLAY_STOP);
Simon Hunt1ee09852015-09-29 12:28:14 -0700160 }
161
162 @Override
163 public void process(long sid, ObjectNode payload) {
164 log.debug("Stop Display");
165 cancelTask();
166 clearState();
167 clearForMode();
168 }
169 }
170
171 // === ------------
172
173 private void clearState() {
174 currentMode = Mode.IDLE;
175 elementOfNote = null;
176 linkSet = EMPTY_LINK_SET;
177 }
178
179 private void updateForMode(String id) {
180 log.debug("host service: {}", hostService);
181 log.debug("device service: {}", deviceService);
182
183 try {
184 HostId hid = HostId.hostId(id);
185 log.debug("host id {}", hid);
186 elementOfNote = hostService.getHost(hid);
187 log.debug("host element {}", elementOfNote);
188
189 } catch (Exception e) {
190 try {
191 DeviceId did = DeviceId.deviceId(id);
192 log.debug("device id {}", did);
193 elementOfNote = deviceService.getDevice(did);
194 log.debug("device element {}", elementOfNote);
195
196 } catch (Exception e2) {
197 log.debug("Unable to process ID [{}]", id);
198 elementOfNote = null;
199 }
200 }
201
202 switch (currentMode) {
203 case MOUSE:
204 sendMouseData();
205 break;
206
207 case LINK:
208 sendLinkData();
209 break;
210
211 default:
212 break;
213 }
214
215 }
216
217 private void clearForMode() {
218 sendHighlights(new Highlights());
219 }
220
221 private void sendHighlights(Highlights highlights) {
222 sendMessage(TopoJson.highlightsMessage(highlights));
223 }
224
225
226 private void sendMouseData() {
227 if (elementOfNote != null && elementOfNote instanceof Device) {
228 DeviceId devId = (DeviceId) elementOfNote.id();
229 Set<Link> links = linkService.getDeviceEgressLinks(devId);
Simon Huntde99e0b2015-10-23 18:54:06 -0700230 Highlights highlights = fromLinks(links, devId);
231 addDeviceBadge(highlights, devId, links.size());
232 sendHighlights(highlights);
Simon Hunt1ee09852015-09-29 12:28:14 -0700233 }
234 // Note: could also process Host, if available
235 }
236
Simon Huntde99e0b2015-10-23 18:54:06 -0700237 private void addDeviceBadge(Highlights h, DeviceId devId, int n) {
238 DeviceHighlight dh = new DeviceHighlight(devId.toString());
239 dh.setBadge(createBadge(n));
240 h.add(dh);
241 }
242
243 private NodeBadge createBadge(int n) {
244 Status status = n > 3 ? Status.ERROR : Status.WARN;
245 String noun = n > 3 ? "(critical)" : "(problematic)";
246 String msg = "Egress links: " + n + " " + noun;
247 return NodeBadge.number(status, n, msg);
248 }
249
Simon Hunt1ee09852015-09-29 12:28:14 -0700250 private Highlights fromLinks(Set<Link> links, DeviceId devId) {
251 DemoLinkMap linkMap = new DemoLinkMap();
252 if (links != null) {
253 log.debug("Processing {} links", links.size());
254 links.forEach(linkMap::add);
255 } else {
256 log.debug("No egress links found for device {}", devId);
257 }
258
259 Highlights highlights = new Highlights();
260
261 for (DemoLink dlink : linkMap.biLinks()) {
262 dlink.makeImportant().setLabel("Yo!");
263 highlights.add(dlink.highlight(null));
264 }
265 return highlights;
266 }
267
268 private void initLinkSet() {
269 Set<Link> links = new HashSet<>();
270 for (Link link : linkService.getActiveLinks()) {
271 links.add(link);
272 }
273 linkSet = links.toArray(new Link[links.size()]);
274 linkIndex = 0;
275 log.debug("initialized link set to {}", linkSet.length);
276 }
277
278 private void sendLinkData() {
279 DemoLinkMap linkMap = new DemoLinkMap();
280 for (Link link : linkSet) {
281 linkMap.add(link);
282 }
283 DemoLink dl = linkMap.add(linkSet[linkIndex]);
284 dl.makeImportant().setLabel(Integer.toString(linkIndex));
285 log.debug("sending link data (index {})", linkIndex);
286
287 linkIndex += 1;
288 if (linkIndex >= linkSet.length) {
289 linkIndex = 0;
290 }
291
292 Highlights highlights = new Highlights();
293 for (DemoLink dlink : linkMap.biLinks()) {
294 highlights.add(dlink.highlight(null));
295 }
296
297 sendHighlights(highlights);
298 }
299
300 private synchronized void scheduleTask() {
301 if (demoTask == null) {
302 log.debug("Starting up demo task...");
303 demoTask = new DisplayUpdateTask();
304 timer.schedule(demoTask, UPDATE_PERIOD_MS, UPDATE_PERIOD_MS);
305 } else {
306 log.debug("(demo task already running");
307 }
308 }
309
310 private synchronized void cancelTask() {
311 if (demoTask != null) {
312 demoTask.cancel();
313 demoTask = null;
314 }
315 }
316
317
318 private class DisplayUpdateTask extends TimerTask {
319 @Override
320 public void run() {
321 try {
322 switch (currentMode) {
323 case LINK:
324 sendLinkData();
325 break;
326
327 default:
328 break;
329 }
330 } catch (Exception e) {
331 log.warn("Unable to process demo task: {}", e.getMessage());
332 log.debug("Oops", e);
333 }
334 }
335 }
336
337}