7c35cc53530268dca7fcc2b50103be399208fca2
[onosfw.git] /
1 #set( $symbol_pound = '#' )
2 #set( $symbol_dollar = '$' )
3 #set( $symbol_escape = '\' )
4 /*
5  * Copyright 2014,2015 Open Networking Laboratory
6  *
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  */
19 package ${package};
20
21 import com.fasterxml.jackson.databind.node.ObjectNode;
22 import com.google.common.base.Strings;
23 import com.google.common.collect.ImmutableSet;
24 import org.onlab.osgi.ServiceDirectory;
25 import org.onosproject.net.Device;
26 import org.onosproject.net.DeviceId;
27 import org.onosproject.net.Element;
28 import org.onosproject.net.HostId;
29 import org.onosproject.net.Link;
30 import org.onosproject.net.device.DeviceService;
31 import org.onosproject.net.host.HostService;
32 import org.onosproject.net.link.LinkService;
33 import org.onosproject.ui.RequestHandler;
34 import org.onosproject.ui.UiConnection;
35 import org.onosproject.ui.UiMessageHandler;
36 import org.onosproject.ui.topo.Highlights;
37 import org.onosproject.ui.topo.TopoJson;
38 import org.slf4j.Logger;
39 import org.slf4j.LoggerFactory;
40
41 import java.util.Collection;
42 import java.util.HashSet;
43 import java.util.Set;
44 import java.util.Timer;
45 import java.util.TimerTask;
46
47 /**
48  * Skeletal ONOS UI Topology-Overlay message handler.
49  */
50 public class AppUiTopovMessageHandler extends UiMessageHandler {
51
52     private static final String SAMPLE_TOPOV_DISPLAY_START = "sampleTopovDisplayStart";
53     private static final String SAMPLE_TOPOV_DISPLAY_UPDATE = "sampleTopovDisplayUpdate";
54     private static final String SAMPLE_TOPOV_DISPLAY_STOP = "sampleTopovDisplayStop";
55
56     private static final String ID = "id";
57     private static final String MODE = "mode";
58
59     private static final long UPDATE_PERIOD_MS = 1000;
60
61     private static final Link[] EMPTY_LINK_SET = new Link[0];
62
63     private enum Mode { IDLE, MOUSE, LINK }
64
65     private final Logger log = LoggerFactory.getLogger(getClass());
66
67     private DeviceService deviceService;
68     private HostService hostService;
69     private LinkService linkService;
70
71     private final Timer timer = new Timer("sample-overlay");
72     private TimerTask demoTask = null;
73     private Mode currentMode = Mode.IDLE;
74     private Element elementOfNote;
75     private Link[] linkSet = EMPTY_LINK_SET;
76     private int linkIndex;
77
78
79     // ===============-=-=-=-=-=-======================-=-=-=-=-=-=-================================
80
81
82     @Override
83     public void init(UiConnection connection, ServiceDirectory directory) {
84         super.init(connection, directory);
85         deviceService = directory.get(DeviceService.class);
86         hostService = directory.get(HostService.class);
87         linkService = directory.get(LinkService.class);
88     }
89
90     @Override
91     protected Collection<RequestHandler> createRequestHandlers() {
92         return ImmutableSet.of(
93                 new DisplayStartHandler(),
94                 new DisplayUpdateHandler(),
95                 new DisplayStopHandler()
96         );
97     }
98
99     // === -------------------------
100     // === Handler classes
101
102     private final class DisplayStartHandler extends RequestHandler {
103         public DisplayStartHandler() {
104             super(SAMPLE_TOPOV_DISPLAY_START);
105         }
106
107         @Override
108         public void process(long sid, ObjectNode payload) {
109             String mode = string(payload, MODE);
110
111             log.debug("Start Display: mode [{}]", mode);
112             clearState();
113             clearForMode();
114
115             switch (mode) {
116                 case "mouse":
117                     currentMode = Mode.MOUSE;
118                     cancelTask();
119                     sendMouseData();
120                     break;
121
122                 case "link":
123                     currentMode = Mode.LINK;
124                     scheduleTask();
125                     initLinkSet();
126                     sendLinkData();
127                     break;
128
129                 default:
130                     currentMode = Mode.IDLE;
131                     cancelTask();
132                     break;
133             }
134         }
135     }
136
137     private final class DisplayUpdateHandler extends RequestHandler {
138         public DisplayUpdateHandler() {
139             super(SAMPLE_TOPOV_DISPLAY_UPDATE);
140         }
141
142         @Override
143         public void process(long sid, ObjectNode payload) {
144             String id = string(payload, ID);
145             log.debug("Update Display: id [{}]", id);
146             if (!Strings.isNullOrEmpty(id)) {
147                 updateForMode(id);
148             } else {
149                 clearForMode();
150             }
151         }
152     }
153
154     private final class DisplayStopHandler extends RequestHandler {
155         public DisplayStopHandler() {
156             super(SAMPLE_TOPOV_DISPLAY_STOP);
157         }
158
159         @Override
160         public void process(long sid, ObjectNode payload) {
161             log.debug("Stop Display");
162             cancelTask();
163             clearState();
164             clearForMode();
165         }
166     }
167
168     // === ------------
169
170     private void clearState() {
171         currentMode = Mode.IDLE;
172         elementOfNote = null;
173         linkSet = EMPTY_LINK_SET;
174     }
175
176     private void updateForMode(String id) {
177         log.debug("host service: {}", hostService);
178         log.debug("device service: {}", deviceService);
179
180         try {
181             HostId hid = HostId.hostId(id);
182             log.debug("host id {}", hid);
183             elementOfNote = hostService.getHost(hid);
184             log.debug("host element {}", elementOfNote);
185
186         } catch (Exception e) {
187             try {
188                 DeviceId did = DeviceId.deviceId(id);
189                 log.debug("device id {}", did);
190                 elementOfNote = deviceService.getDevice(did);
191                 log.debug("device element {}", elementOfNote);
192
193             } catch (Exception e2) {
194                 log.debug("Unable to process ID [{}]", id);
195                 elementOfNote = null;
196             }
197         }
198
199         switch (currentMode) {
200             case MOUSE:
201                 sendMouseData();
202                 break;
203
204             case LINK:
205                 sendLinkData();
206                 break;
207
208             default:
209                 break;
210         }
211
212     }
213
214     private void clearForMode() {
215         sendHighlights(new Highlights());
216     }
217
218     private void sendHighlights(Highlights highlights) {
219         sendMessage(TopoJson.highlightsMessage(highlights));
220     }
221
222
223     private void sendMouseData() {
224         if (elementOfNote != null && elementOfNote instanceof Device) {
225             DeviceId devId = (DeviceId) elementOfNote.id();
226             Set<Link> links = linkService.getDeviceEgressLinks(devId);
227             sendHighlights(fromLinks(links, devId));
228         }
229         // Note: could also process Host, if available
230     }
231
232     private Highlights fromLinks(Set<Link> links, DeviceId devId) {
233         DemoLinkMap linkMap = new DemoLinkMap();
234         if (links != null) {
235             log.debug("Processing {} links", links.size());
236             links.forEach(linkMap::add);
237         } else {
238             log.debug("No egress links found for device {}", devId);
239         }
240
241         Highlights highlights = new Highlights();
242
243         for (DemoLink dlink : linkMap.biLinks()) {
244             dlink.makeImportant().setLabel("Yo!");
245             highlights.add(dlink.highlight(null));
246         }
247         return highlights;
248     }
249
250     private void initLinkSet() {
251         Set<Link> links = new HashSet<>();
252         for (Link link : linkService.getActiveLinks()) {
253             links.add(link);
254         }
255         linkSet = links.toArray(new Link[links.size()]);
256         linkIndex = 0;
257         log.debug("initialized link set to {}", linkSet.length);
258     }
259
260     private void sendLinkData() {
261         DemoLinkMap linkMap = new DemoLinkMap();
262         for (Link link : linkSet) {
263             linkMap.add(link);
264         }
265         DemoLink dl = linkMap.add(linkSet[linkIndex]);
266         dl.makeImportant().setLabel(Integer.toString(linkIndex));
267         log.debug("sending link data (index {})", linkIndex);
268
269         linkIndex += 1;
270         if (linkIndex >= linkSet.length) {
271             linkIndex = 0;
272         }
273
274         Highlights highlights = new Highlights();
275         for (DemoLink dlink : linkMap.biLinks()) {
276             highlights.add(dlink.highlight(null));
277         }
278
279         sendHighlights(highlights);
280     }
281
282     private synchronized void scheduleTask() {
283         if (demoTask == null) {
284             log.debug("Starting up demo task...");
285             demoTask = new DisplayUpdateTask();
286             timer.schedule(demoTask, UPDATE_PERIOD_MS, UPDATE_PERIOD_MS);
287         } else {
288             log.debug("(demo task already running");
289         }
290     }
291
292     private synchronized void cancelTask() {
293         if (demoTask != null) {
294             demoTask.cancel();
295             demoTask = null;
296         }
297     }
298
299
300     private class DisplayUpdateTask extends TimerTask {
301         @Override
302         public void run() {
303             try {
304                 switch (currentMode) {
305                     case LINK:
306                         sendLinkData();
307                         break;
308
309                     default:
310                         break;
311                 }
312             } catch (Exception e) {
313                 log.warn("Unable to process demo task: {}", e.getMessage());
314                 log.debug("Oops", e);
315             }
316         }
317     }
318
319 }