blob: de7826c26ea204c73384f52f3b9ac05bfea000fe [file] [log] [blame]
Thomas Vachuskab4d3ff72015-12-01 09:53:51 -08001/*
2 * Copyright 2014,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.pathpainter;
17
18import com.fasterxml.jackson.databind.node.ObjectNode;
19import com.google.common.collect.ImmutableList;
20import com.google.common.collect.ImmutableSet;
Andrea Campanella8583e6b2015-12-01 21:24:45 -080021import com.google.common.collect.Sets;
Thomas Vachuskab4d3ff72015-12-01 09:53:51 -080022import org.onlab.osgi.ServiceDirectory;
23import org.onosproject.net.DeviceId;
Thomas Vachuska08bef152015-12-02 17:08:59 -080024import org.onosproject.net.DisjointPath;
Thomas Vachuskab4d3ff72015-12-01 09:53:51 -080025import org.onosproject.net.ElementId;
26import org.onosproject.net.HostId;
27import org.onosproject.net.Link;
28import org.onosproject.net.Path;
29import org.onosproject.net.topology.PathService;
30import org.onosproject.ui.RequestHandler;
31import org.onosproject.ui.UiConnection;
32import org.onosproject.ui.UiMessageHandler;
Andrea Campanella490e8392015-12-03 12:18:11 -080033import org.onosproject.ui.topo.DeviceHighlight;
Thomas Vachuskab4d3ff72015-12-01 09:53:51 -080034import org.onosproject.ui.topo.Highlights;
Andrea Campanella490e8392015-12-03 12:18:11 -080035import org.onosproject.ui.topo.HostHighlight;
36import org.onosproject.ui.topo.NodeBadge;
Thomas Vachuskab4d3ff72015-12-01 09:53:51 -080037import org.onosproject.ui.topo.TopoJson;
38import org.slf4j.Logger;
39import org.slf4j.LoggerFactory;
40
41import java.util.Collection;
42import java.util.List;
43import java.util.Set;
44
45/**
46 * Skeletal ONOS UI Topology-Overlay message handler.
47 */
48public class PathPainterTopovMessageHandler extends UiMessageHandler {
49
50 private static final String PAINTER_SET_SRC = "ppTopovSetSrc";
51 private static final String PAINTER_SET_DST = "ppTopovSetDst";
52 private static final String PAINTER_SWAP_SRC_DST = "ppTopovSwapSrcDst";
53 private static final String PAINTER_SET_MODE = "ppTopovSetMode";
54
55 private static final String PAINTER_NEXT_PATH = "ppTopovNextPath";
56 private static final String PAINTER_PREV_PATH = "ppTopovPrevPath";
57
58 private static final String ID = "id";
59 private static final String MODE = "mode";
Andrea Campanella490e8392015-12-03 12:18:11 -080060 private static final String TYPE = "type";
61 private static final String SWITCH = "switch";
62 private static final String ENDSTATION = "endstation";
63 public static final String DST = "Dst";
64 public static final String SRC = "Src";
Thomas Vachuskab4d3ff72015-12-01 09:53:51 -080065
66 private Set<Link> allPathLinks;
67
68 private enum Mode {
69 SHORTEST, DISJOINT, SRLG
70 }
71
72 private final Logger log = LoggerFactory.getLogger(getClass());
73
74 private PathService pathService;
75
Thomas Vachuskab4d3ff72015-12-01 09:53:51 -080076 private ElementId src, dst;
Andrea Campanella490e8392015-12-03 12:18:11 -080077 private String srcType, dstType;
Andrea Campanella8583e6b2015-12-01 21:24:45 -080078 private Mode currentMode = Mode.SHORTEST;
Thomas Vachuskab4d3ff72015-12-01 09:53:51 -080079 private List<Path> paths;
80 private int pathIndex;
81
82
83 // ===============-=-=-=-=-=-======================-=-=-=-=-=-=-================================
84
85
86 @Override
87 public void init(UiConnection connection, ServiceDirectory directory) {
88 super.init(connection, directory);
89 pathService = directory.get(PathService.class);
90 }
91
92 @Override
93 protected Collection<RequestHandler> createRequestHandlers() {
94 return ImmutableSet.of(
95 new SetSrcHandler(),
96 new SetDstHandler(),
Andrea Campanella0c17a0a2015-12-01 09:53:51 -080097 new SwapSrcDstHandler(),
Thomas Vachuskab4d3ff72015-12-01 09:53:51 -080098 new NextPathHandler(),
Andrea Campanella8583e6b2015-12-01 21:24:45 -080099 new PrevPathHandler(),
100 new SetModeHandler()
Thomas Vachuskab4d3ff72015-12-01 09:53:51 -0800101 );
102 }
103
104 // === -------------------------
105 // === Handler classes
106
107 private final class SetSrcHandler extends RequestHandler {
Andrea Campanella490e8392015-12-03 12:18:11 -0800108
Thomas Vachuskab4d3ff72015-12-01 09:53:51 -0800109 public SetSrcHandler() {
110 super(PAINTER_SET_SRC);
111 }
112
113 @Override
114 public void process(long sid, ObjectNode payload) {
115 String id = string(payload, ID);
116 src = elementId(id);
Andrea Campanella490e8392015-12-03 12:18:11 -0800117 srcType = string(payload, TYPE);
Thomas Vachuskab4d3ff72015-12-01 09:53:51 -0800118 if (src.equals(dst)) {
119 dst = null;
120 }
Andrea Campanella490e8392015-12-03 12:18:11 -0800121 sendMessage(TopoJson.highlightsMessage(addBadge(new Highlights(),
122 srcType,
123 src.toString(),
124 SRC)));
125 findAndSendPaths(currentMode);
Thomas Vachuskab4d3ff72015-12-01 09:53:51 -0800126 }
127 }
128
129 private final class SetDstHandler extends RequestHandler {
130 public SetDstHandler() {
131 super(PAINTER_SET_DST);
132 }
133
134 @Override
135 public void process(long sid, ObjectNode payload) {
136 String id = string(payload, ID);
137 dst = elementId(id);
Andrea Campanella490e8392015-12-03 12:18:11 -0800138 dstType = string(payload, TYPE);
Thomas Vachuskab4d3ff72015-12-01 09:53:51 -0800139 if (src.equals(dst)) {
140 src = null;
141 }
Andrea Campanella490e8392015-12-03 12:18:11 -0800142
143 sendMessage(TopoJson.highlightsMessage(addBadge(new Highlights(),
144 dstType,
145 dst.toString(),
146 DST)));
147 findAndSendPaths(currentMode);
Thomas Vachuskab4d3ff72015-12-01 09:53:51 -0800148 }
149 }
150
Andrea Campanella0c17a0a2015-12-01 09:53:51 -0800151 private final class SwapSrcDstHandler extends RequestHandler {
152 public SwapSrcDstHandler() {
153 super(PAINTER_SWAP_SRC_DST);
154 }
155
156 @Override
157 public void process(long sid, ObjectNode payload) {
158 ElementId temp = src;
159 src = dst;
160 dst = temp;
Andrea Campanella490e8392015-12-03 12:18:11 -0800161 String s = srcType;
162 srcType = dstType;
163 dstType = s;
164 findAndSendPaths(currentMode);
Andrea Campanella0c17a0a2015-12-01 09:53:51 -0800165 }
166 }
167
Thomas Vachuskab4d3ff72015-12-01 09:53:51 -0800168 private final class NextPathHandler extends RequestHandler {
169 public NextPathHandler() {
170 super(PAINTER_NEXT_PATH);
171 }
172
173 @Override
174 public void process(long sid, ObjectNode payload) {
175 pathIndex = (pathIndex >= paths.size() - 1 ? 0 : pathIndex + 1);
176 hilightAndSendPaths();
177 }
178 }
179
180 private final class PrevPathHandler extends RequestHandler {
181 public PrevPathHandler() {
182 super(PAINTER_PREV_PATH);
183 }
184
185 @Override
186 public void process(long sid, ObjectNode payload) {
187 pathIndex = (pathIndex <= 0 ? paths.size() - 1 : pathIndex - 1);
188 hilightAndSendPaths();
189 }
190 }
191
Andrea Campanella8583e6b2015-12-01 21:24:45 -0800192 private final class SetModeHandler extends RequestHandler {
193 public SetModeHandler() {
194 super(PAINTER_SET_MODE);
195 }
196
197 @Override
198 public void process(long sid, ObjectNode payload) {
199 String mode = string(payload, MODE);
200 currentMode = (mode.equals("shortest") ?
201 Mode.SHORTEST : (mode.equals("disjoint") ?
202 Mode.DISJOINT : Mode.SRLG));
203 //TODO: add support for SRLG
Andrea Campanella490e8392015-12-03 12:18:11 -0800204 findAndSendPaths(currentMode);
Andrea Campanella8583e6b2015-12-01 21:24:45 -0800205 }
206 }
207
Thomas Vachuskab4d3ff72015-12-01 09:53:51 -0800208 // === ------------
209
210 private ElementId elementId(String id) {
211 try {
212 return DeviceId.deviceId(id);
213 } catch (IllegalArgumentException e) {
214 return HostId.hostId(id);
215 }
216 }
217
Andrea Campanella490e8392015-12-03 12:18:11 -0800218 private void findAndSendPaths(Mode mode) {
Andrea Campanella8583e6b2015-12-01 21:24:45 -0800219 log.info("src={}; dst={}; mode={}", src, dst, currentMode);
220 if (src != null && dst != null) {
Andrea Campanella8583e6b2015-12-01 21:24:45 -0800221 pathIndex = 0;
Andrea Campanella8583e6b2015-12-01 21:24:45 -0800222 ImmutableSet.Builder<Link> builder = ImmutableSet.builder();
Andrea Campanella490e8392015-12-03 12:18:11 -0800223 if (mode.equals(Mode.SHORTEST)) {
224 paths = ImmutableList.copyOf(pathService.getPaths(src, dst));
225 allPathLinks = buildPaths(builder).build();
226 } else if (mode.equals(Mode.DISJOINT)) {
227 paths = ImmutableList.copyOf(pathService.getDisjointPaths(src, dst));
228 allPathLinks = buildDisjointPaths(builder).build();
229 } else {
230 log.info("Unsupported MODE");
231 }
Andrea Campanella8583e6b2015-12-01 21:24:45 -0800232 } else {
233 paths = ImmutableList.of();
234 allPathLinks = ImmutableSet.of();
235 }
236 hilightAndSendPaths();
Andrea Campanella490e8392015-12-03 12:18:11 -0800237
238 }
239
240 private ImmutableSet.Builder<Link> buildPaths(ImmutableSet.Builder<Link> pathBuilder) {
241 paths.forEach(path -> path.links().forEach(pathBuilder::add));
242 return pathBuilder;
243 }
244
245 private ImmutableSet.Builder<Link> buildDisjointPaths(ImmutableSet.Builder<Link> pathBuilder) {
246 paths.forEach(path -> {
247 DisjointPath dp = (DisjointPath) path;
248 pathBuilder.addAll(dp.primary().links());
249 pathBuilder.addAll(dp.backup().links());
250 });
251 return pathBuilder;
Andrea Campanella8583e6b2015-12-01 21:24:45 -0800252 }
253
Thomas Vachuskab4d3ff72015-12-01 09:53:51 -0800254 private void hilightAndSendPaths() {
255 PathLinkMap linkMap = new PathLinkMap();
256 allPathLinks.forEach(linkMap::add);
257
Thomas Vachuska08bef152015-12-02 17:08:59 -0800258 Set<Link> selectedPathLinks;
259
Thomas Vachuskab4d3ff72015-12-01 09:53:51 -0800260 // Prepare two working sets; one containing selected path links and
261 // the other containing all paths links.
Andrea Campanella8583e6b2015-12-01 21:24:45 -0800262 if (currentMode.equals(Mode.DISJOINT)) {
Andrea Campanella490e8392015-12-03 12:18:11 -0800263 DisjointPath dp = (DisjointPath) paths.get(pathIndex);
Andrea Campanella8583e6b2015-12-01 21:24:45 -0800264 selectedPathLinks = paths.isEmpty() ?
Andrea Campanella490e8392015-12-03 12:18:11 -0800265 ImmutableSet.of() : Sets.newHashSet(dp.primary().links());
Thomas Vachuska08bef152015-12-02 17:08:59 -0800266 selectedPathLinks.addAll(dp.backup().links());
Andrea Campanella8583e6b2015-12-01 21:24:45 -0800267 } else {
268 selectedPathLinks = paths.isEmpty() ?
Thomas Vachuska08bef152015-12-02 17:08:59 -0800269 ImmutableSet.of() : ImmutableSet.copyOf(paths.get(pathIndex).links());
Andrea Campanella8583e6b2015-12-01 21:24:45 -0800270 }
Thomas Vachuskab4d3ff72015-12-01 09:53:51 -0800271 Highlights highlights = new Highlights();
272 for (PathLink plink : linkMap.biLinks()) {
273 plink.computeHilight(selectedPathLinks, allPathLinks);
274 highlights.add(plink.highlight(null));
275 }
Andrea Campanella490e8392015-12-03 12:18:11 -0800276 if (src != null) {
277 highlights = addBadge(highlights, srcType, src.toString(), SRC);
278 }
279 if (dst != null) {
280 highlights = addBadge(highlights, dstType, dst.toString(), DST);
281 }
Thomas Vachuskab4d3ff72015-12-01 09:53:51 -0800282 sendMessage(TopoJson.highlightsMessage(highlights));
283 }
284
Andrea Campanella490e8392015-12-03 12:18:11 -0800285 private Highlights addBadge(Highlights highlights, String type, String elemId, String src) {
286 if (SWITCH.equals(type)) {
287 highlights = addDeviceBadge(highlights, elemId, src);
288 } else if (ENDSTATION.equals(type)) {
289 highlights = addHostBadge(highlights, elemId, src);
290 }
291 return highlights;
Thomas Vachuskab4d3ff72015-12-01 09:53:51 -0800292 }
293
Andrea Campanella490e8392015-12-03 12:18:11 -0800294 private Highlights addDeviceBadge(Highlights h, String elemId, String type) {
295 DeviceHighlight dh = new DeviceHighlight(elemId);
296 dh.setBadge(createBadge(type));
297 h.add(dh);
298 return h;
Thomas Vachuskab4d3ff72015-12-01 09:53:51 -0800299 }
Andrea Campanella490e8392015-12-03 12:18:11 -0800300
301 private Highlights addHostBadge(Highlights h, String elemId, String type) {
302 HostHighlight hh = new HostHighlight(elemId);
303 hh.setBadge(createBadge(type));
304 h.add(hh);
305 return h;
306 }
307
308 private NodeBadge createBadge(String type) {
309 return NodeBadge.text(type);
310 }
Thomas Vachuskab4d3ff72015-12-01 09:53:51 -0800311
312}