Thomas Vachuska
Committed by Gerrit Code Review

GUI traffic visualization work on server-side.

Change-Id: I15564fc8484464858adf57fe22462f4951d09d09
...@@ -43,7 +43,6 @@ import org.onlab.onos.net.host.HostService; ...@@ -43,7 +43,6 @@ import org.onlab.onos.net.host.HostService;
43 import org.onlab.onos.net.intent.ConnectivityIntent; 43 import org.onlab.onos.net.intent.ConnectivityIntent;
44 import org.onlab.onos.net.intent.Intent; 44 import org.onlab.onos.net.intent.Intent;
45 import org.onlab.onos.net.intent.IntentService; 45 import org.onlab.onos.net.intent.IntentService;
46 -import org.onlab.onos.net.intent.IntentState;
47 import org.onlab.onos.net.intent.LinkCollectionIntent; 46 import org.onlab.onos.net.intent.LinkCollectionIntent;
48 import org.onlab.onos.net.intent.PathIntent; 47 import org.onlab.onos.net.intent.PathIntent;
49 import org.onlab.onos.net.link.LinkEvent; 48 import org.onlab.onos.net.link.LinkEvent;
...@@ -232,7 +231,7 @@ public abstract class TopologyMessages { ...@@ -232,7 +231,7 @@ public abstract class TopologyMessages {
232 ObjectNode payload = mapper.createObjectNode() 231 ObjectNode payload = mapper.createObjectNode()
233 .put("id", compactLinkString(link)) 232 .put("id", compactLinkString(link))
234 .put("type", link.type().toString().toLowerCase()) 233 .put("type", link.type().toString().toLowerCase())
235 - .put("online", true) // TODO: add link state field 234 + .put("online", true) // link.state()) TODO: add link state field
236 .put("linkWidth", 2) 235 .put("linkWidth", 2)
237 .put("src", link.src().deviceId().toString()) 236 .put("src", link.src().deviceId().toString())
238 .put("srcPort", link.src().port().toString()) 237 .put("srcPort", link.src().port().toString())
...@@ -370,18 +369,18 @@ public abstract class TopologyMessages { ...@@ -370,18 +369,18 @@ public abstract class TopologyMessages {
370 369
371 370
372 // Produces JSON message to trigger traffic visualization 371 // Produces JSON message to trigger traffic visualization
373 - protected ObjectNode trafficMessage(Set<Intent> intents, long sid) { 372 + protected ObjectNode trafficMessage(long sid, TrafficClass... trafficClasses) {
374 ObjectNode payload = mapper.createObjectNode(); 373 ObjectNode payload = mapper.createObjectNode();
375 ArrayNode paths = mapper.createArrayNode(); 374 ArrayNode paths = mapper.createArrayNode();
376 payload.set("paths", paths); 375 payload.set("paths", paths);
377 376
378 - for (Intent intent : intents) { 377 + for (TrafficClass trafficClass : trafficClasses) {
379 - List<Intent> installables = intentService.getInstallableIntents(intent.id()); 378 + for (Intent intent : trafficClass.intents) {
380 - IntentState state = intentService.getIntentState(intent.id()); 379 + List<Intent> installables = intentService.getInstallableIntents(intent.id());
381 - String type = state == IntentState.FAILED ? "inactive" : "active"; 380 + for (Intent installable : installables) {
382 - for (Intent installable : installables) { 381 + if (installable instanceof ConnectivityIntent) {
383 - if (installable instanceof ConnectivityIntent) { 382 + addPathTraffic(paths, trafficClass.type, (ConnectivityIntent) installable);
384 - addPathTraffic(paths, type, (ConnectivityIntent) installable); 383 + }
385 } 384 }
386 } 385 }
387 } 386 }
...@@ -452,4 +451,15 @@ public abstract class TopologyMessages { ...@@ -452,4 +451,15 @@ public abstract class TopologyMessages {
452 } 451 }
453 } 452 }
454 453
454 + // Auxiliary carrier of data for requesting traffic message.
455 + protected class TrafficClass {
456 + public final String type;
457 + public final Set<Intent> intents;
458 +
459 + TrafficClass(String type, Set<Intent> intents) {
460 + this.type = type;
461 + this.intents = intents;
462 + }
463 + }
464 +
455 } 465 }
......
...@@ -56,6 +56,7 @@ import java.util.Map; ...@@ -56,6 +56,7 @@ import java.util.Map;
56 import java.util.Set; 56 import java.util.Set;
57 import java.util.concurrent.ConcurrentHashMap; 57 import java.util.concurrent.ConcurrentHashMap;
58 58
59 +import static com.google.common.base.Strings.isNullOrEmpty;
59 import static org.onlab.onos.cluster.ClusterEvent.Type.INSTANCE_ADDED; 60 import static org.onlab.onos.cluster.ClusterEvent.Type.INSTANCE_ADDED;
60 import static org.onlab.onos.net.DeviceId.deviceId; 61 import static org.onlab.onos.net.DeviceId.deviceId;
61 import static org.onlab.onos.net.HostId.hostId; 62 import static org.onlab.onos.net.HostId.hostId;
...@@ -252,38 +253,44 @@ public class TopologyWebSocket ...@@ -252,38 +253,44 @@ public class TopologyWebSocket
252 private void requestTraffic(ObjectNode event) { 253 private void requestTraffic(ObjectNode event) {
253 ObjectNode payload = payload(event); 254 ObjectNode payload = payload(event);
254 long sid = number(event, "sid"); 255 long sid = number(event, "sid");
255 - Set<Intent> intents = findPathIntents(payload);
256 256
257 - // Add all those intents to the list of monitored intents & flows. 257 + // Get the set of selected hosts and their intents.
258 - intentsToMonitor.clear(); 258 + Set<Host> hosts = getHosts((ArrayNode) payload.path("ids"));
259 - for (Intent intent : intents) { 259 + Set<Intent> intents = findPathIntents(hosts);
260 - intentsToMonitor.put(intent, sid); 260 +
261 + // If there is a hover node, include it in the hosts and find intents.
262 + String hover = string(payload, "hover");
263 + Set<Intent> hoverIntents;
264 + if (!isNullOrEmpty(hover)) {
265 + addHost(hosts, hostId(hover));
266 + hoverIntents = findPathIntents(hosts);
267 + intents.removeAll(hoverIntents);
268 +
269 + // Send an initial message to highlight all links of all monitored intents.
270 + sendMessage(trafficMessage(sid,
271 + new TrafficClass("primary", hoverIntents),
272 + new TrafficClass("secondary", intents)));
273 +
274 + } else {
275 + // Send an initial message to highlight all links of all monitored intents.
276 + sendMessage(trafficMessage(sid, new TrafficClass("primary", intents)));
277 +
278 + // Add all those intents to the list of monitored intents & flows.
279 + intentsToMonitor.clear();
280 + for (Intent intent : intents) {
281 + intentsToMonitor.put(intent, sid);
282 + }
261 } 283 }
262 -
263 - // Send an initial message to highlight all links of all monitored intents.
264 - sendMessage(trafficMessage(intents, sid));
265 } 284 }
266 285
267 // Cancels sending traffic messages. 286 // Cancels sending traffic messages.
268 private void cancelTraffic(ObjectNode event) { 287 private void cancelTraffic(ObjectNode event) {
269 - ObjectNode payload = payload(event); 288 + sendMessage(trafficMessage(number(event, "sid")));
270 - long sid = number(event, "sid");
271 - Set<Intent> intents = findPathIntents(payload);
272 -
273 - // Remove all those intents from the list of monitored intents & flows.
274 - intentsToMonitor.clear(); // TODO: remove when ready
275 - for (Intent intent : intents) {
276 - intentsToMonitor.remove(intent.id());
277 - }
278 - sendMessage(trafficMessage(intents, sid));
279 } 289 }
280 290
281 // Finds all path (host-to-host or point-to-point) intents that pertains 291 // Finds all path (host-to-host or point-to-point) intents that pertains
282 - // to the hosts indicated in the given event payload. 292 + // to the given hosts.
283 - private Set<Intent> findPathIntents(ObjectNode payload) { 293 + private Set<Intent> findPathIntents(Set<Host> hosts) {
284 - // Get the list of selected hosts.
285 - Set<Host> hosts = getHosts((ArrayNode) payload.path("ids"));
286 -
287 // Derive from this the set of edge connect points. 294 // Derive from this the set of edge connect points.
288 Set<ConnectPoint> edgePoints = getEdgePoints(hosts); 295 Set<ConnectPoint> edgePoints = getEdgePoints(hosts);
289 296
...@@ -359,19 +366,25 @@ public class TopologyWebSocket ...@@ -359,19 +366,25 @@ public class TopologyWebSocket
359 // Produces a set of all host ids listed in the specified JSON array. 366 // Produces a set of all host ids listed in the specified JSON array.
360 private Set<Host> getHosts(ArrayNode array) { 367 private Set<Host> getHosts(ArrayNode array) {
361 Set<Host> hosts = new HashSet<>(); 368 Set<Host> hosts = new HashSet<>();
362 - for (JsonNode node : array) { 369 + if (array != null) {
363 - try { 370 + for (JsonNode node : array) {
364 - Host host = hostService.getHost(hostId(node.asText())); 371 + try {
365 - if (host != null) { 372 + addHost(hosts, hostId(node.asText()));
366 - hosts.add(host); 373 + } catch (IllegalArgumentException e) {
374 + log.debug("Skipping ID {}", node.asText());
367 } 375 }
368 - } catch (IllegalArgumentException e) {
369 - log.debug("Skipping ID {}", node.asText());
370 } 376 }
371 } 377 }
372 return hosts; 378 return hosts;
373 } 379 }
374 380
381 + private void addHost(Set<Host> hosts, HostId hostId) {
382 + Host host = hostService.getHost(hostId);
383 + if (host != null) {
384 + hosts.add(host);
385 + }
386 + }
387 +
375 // Produces a set of edge points from the specified set of hosts. 388 // Produces a set of edge points from the specified set of hosts.
376 private Set<ConnectPoint> getEdgePoints(Set<Host> hosts) { 389 private Set<ConnectPoint> getEdgePoints(Set<Host> hosts) {
377 Set<ConnectPoint> edgePoints = new HashSet<>(); 390 Set<ConnectPoint> edgePoints = new HashSet<>();
...@@ -460,7 +473,8 @@ public class TopologyWebSocket ...@@ -460,7 +473,8 @@ public class TopologyWebSocket
460 ObjectNode payload = pathMessage(path, "host") 473 ObjectNode payload = pathMessage(path, "host")
461 .put("intentId", intent.id().toString()); 474 .put("intentId", intent.id().toString());
462 sendMessage(envelope("showPath", sid, payload)); 475 sendMessage(envelope("showPath", sid, payload));
463 - sendMessage(trafficMessage(intentsToMonitor.keySet(), sid)); 476 + TrafficClass tc = new TrafficClass("animated", intentsToMonitor.keySet());
477 + sendMessage(trafficMessage(sid, tc));
464 } 478 }
465 } 479 }
466 } 480 }
......