Adding multi-selection to the GUI and sketching out GUI/Server interactions.
Added persistent meta-data; including node coordinates.
Added ability to request path and return one.
Change-Id: I3edbdf44bbb8d8133a5e5a1fd0660a3fa5a2d6a1
diff --git a/web/gui/src/main/java/org/onlab/onos/gui/TopologyWebSocket.java b/web/gui/src/main/java/org/onlab/onos/gui/TopologyWebSocket.java
index e82303b..31c3f84 100644
--- a/web/gui/src/main/java/org/onlab/onos/gui/TopologyWebSocket.java
+++ b/web/gui/src/main/java/org/onlab/onos/gui/TopologyWebSocket.java
@@ -23,7 +23,9 @@
import org.onlab.onos.event.Event;
import org.onlab.onos.net.Annotations;
import org.onlab.onos.net.Device;
+import org.onlab.onos.net.DeviceId;
import org.onlab.onos.net.Link;
+import org.onlab.onos.net.Path;
import org.onlab.onos.net.device.DeviceEvent;
import org.onlab.onos.net.device.DeviceService;
import org.onlab.onos.net.link.LinkEvent;
@@ -37,7 +39,11 @@
import org.onlab.osgi.ServiceDirectory;
import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+import static org.onlab.onos.net.DeviceId.deviceId;
import static org.onlab.onos.net.device.DeviceEvent.Type.DEVICE_ADDED;
import static org.onlab.onos.net.device.DeviceEvent.Type.DEVICE_REMOVED;
import static org.onlab.onos.net.link.LinkEvent.Type.LINK_ADDED;
@@ -56,6 +62,12 @@
private Connection connection;
+ // TODO: extract into an external & durable state; good enough for now and demo
+ private static Map<String, ObjectNode> metaUi = new HashMap<>();
+
+ private static final String COMPACT = "%s/%s-%s/%s";
+
+
/**
* Creates a new web-socket for serving data to GUI topology view.
*
@@ -101,9 +113,56 @@
@Override
public void onMessage(String data) {
- System.out.println("Received: " + data);
+ try {
+ ObjectNode event = (ObjectNode) mapper.reader().readTree(data);
+ String type = event.path("event").asText("unknown");
+ ObjectNode payload = (ObjectNode) event.path("payload");
+
+ switch (type) {
+ case "updateMeta":
+ metaUi.put(payload.path("id").asText(), payload);
+ break;
+ case "requestPath":
+ findPath(deviceId(payload.path("one").asText()),
+ deviceId(payload.path("two").asText()));
+ default:
+ break;
+ }
+ } catch (IOException e) {
+ System.out.println("Received: " + data);
+ }
}
+ private void findPath(DeviceId one, DeviceId two) {
+ Set<Path> paths = topologyService.getPaths(topologyService.currentTopology(),
+ one, two);
+ if (!paths.isEmpty()) {
+ ObjectNode payload = mapper.createObjectNode();
+ ArrayNode links = mapper.createArrayNode();
+
+ Path path = paths.iterator().next();
+ for (Link link : path.links()) {
+ links.add(compactLinkString(link));
+ }
+
+ payload.set("links", links);
+ sendMessage(envelope("showPath", payload));
+ }
+ // TODO: when no path, send a message to the client
+ }
+
+ /**
+ * Returns a compact string representing the given link.
+ *
+ * @param link infrastructure link
+ * @return formatted link string
+ */
+ public static String compactLinkString(Link link) {
+ return String.format(COMPACT, link.src().deviceId(), link.src().port(),
+ link.dst().deviceId(), link.dst().port());
+ }
+
+
private void sendMessage(String data) {
try {
connection.sendMessage(data);
@@ -130,7 +189,11 @@
// Add labels, props and stuff the payload into envelope.
payload.set("labels", labels);
payload.set("props", props(device.annotations()));
- payload.set("metaUi", mapper.createObjectNode());
+
+ ObjectNode meta = metaUi.get(device.id().toString());
+ if (meta != null) {
+ payload.set("metaUi", meta);
+ }
String type = (event.type() == DEVICE_ADDED) ? "addDevice" :
((event.type() == DEVICE_REMOVED) ? "removeDevice" : "updateDevice");