Thomas Vachuska

Added top-level location object per Simon/Paul spec.

Fixed an NPE in mastership when running optical demo.

Change-Id: I038000d1237b4150db0c722fa96dd9541d83e44e
...@@ -24,6 +24,7 @@ import org.onlab.onos.cluster.ClusterService; ...@@ -24,6 +24,7 @@ import org.onlab.onos.cluster.ClusterService;
24 import org.onlab.onos.cluster.ControllerNode; 24 import org.onlab.onos.cluster.ControllerNode;
25 import org.onlab.onos.cluster.NodeId; 25 import org.onlab.onos.cluster.NodeId;
26 import org.onlab.onos.mastership.MastershipService; 26 import org.onlab.onos.mastership.MastershipService;
27 +import org.onlab.onos.net.Annotated;
27 import org.onlab.onos.net.Annotations; 28 import org.onlab.onos.net.Annotations;
28 import org.onlab.onos.net.ConnectPoint; 29 import org.onlab.onos.net.ConnectPoint;
29 import org.onlab.onos.net.DefaultEdgeLink; 30 import org.onlab.onos.net.DefaultEdgeLink;
...@@ -45,6 +46,8 @@ import org.onlab.onos.net.link.LinkService; ...@@ -45,6 +46,8 @@ import org.onlab.onos.net.link.LinkService;
45 import org.onlab.onos.net.provider.ProviderId; 46 import org.onlab.onos.net.provider.ProviderId;
46 import org.onlab.osgi.ServiceDirectory; 47 import org.onlab.osgi.ServiceDirectory;
47 import org.onlab.packet.IpAddress; 48 import org.onlab.packet.IpAddress;
49 +import org.slf4j.Logger;
50 +import org.slf4j.LoggerFactory;
48 51
49 import java.util.Iterator; 52 import java.util.Iterator;
50 import java.util.Map; 53 import java.util.Map;
...@@ -68,6 +71,8 @@ import static org.onlab.onos.net.link.LinkEvent.Type.LINK_REMOVED; ...@@ -68,6 +71,8 @@ import static org.onlab.onos.net.link.LinkEvent.Type.LINK_REMOVED;
68 */ 71 */
69 public abstract class TopologyMessages { 72 public abstract class TopologyMessages {
70 73
74 + protected static final Logger log = LoggerFactory.getLogger(TopologyMessages.class);
75 +
71 private static final ProviderId PID = new ProviderId("core", "org.onlab.onos.core", true); 76 private static final ProviderId PID = new ProviderId("core", "org.onlab.onos.core", true);
72 private static final String COMPACT = "%s/%s-%s/%s"; 77 private static final String COMPACT = "%s/%s-%s/%s";
73 78
...@@ -195,7 +200,7 @@ public abstract class TopologyMessages { ...@@ -195,7 +200,7 @@ public abstract class TopologyMessages {
195 .put("id", device.id().toString()) 200 .put("id", device.id().toString())
196 .put("type", device.type().toString().toLowerCase()) 201 .put("type", device.type().toString().toLowerCase())
197 .put("online", deviceService.isAvailable(device.id())) 202 .put("online", deviceService.isAvailable(device.id()))
198 - .put("master", mastershipService.getMasterFor(device.id()).toString()); 203 + .put("master", master(device.id()));
199 204
200 // Generate labels: id, chassis id, no-label, optional-name 205 // Generate labels: id, chassis id, no-label, optional-name
201 ArrayNode labels = mapper.createArrayNode(); 206 ArrayNode labels = mapper.createArrayNode();
...@@ -207,6 +212,7 @@ public abstract class TopologyMessages { ...@@ -207,6 +212,7 @@ public abstract class TopologyMessages {
207 // Add labels, props and stuff the payload into envelope. 212 // Add labels, props and stuff the payload into envelope.
208 payload.set("labels", labels); 213 payload.set("labels", labels);
209 payload.set("props", props(device.annotations())); 214 payload.set("props", props(device.annotations()));
215 + addGeoLocation(device, payload);
210 addMetaUi(device.id().toString(), payload); 216 addMetaUi(device.id().toString(), payload);
211 217
212 String type = (event.type() == DEVICE_ADDED) ? "addDevice" : 218 String type = (event.type() == DEVICE_ADDED) ? "addDevice" :
...@@ -220,6 +226,7 @@ public abstract class TopologyMessages { ...@@ -220,6 +226,7 @@ public abstract class TopologyMessages {
220 ObjectNode payload = mapper.createObjectNode() 226 ObjectNode payload = mapper.createObjectNode()
221 .put("id", compactLinkString(link)) 227 .put("id", compactLinkString(link))
222 .put("type", link.type().toString().toLowerCase()) 228 .put("type", link.type().toString().toLowerCase())
229 + .put("online", true) // TODO: add link state field
223 .put("linkWidth", 2) 230 .put("linkWidth", 2)
224 .put("src", link.src().deviceId().toString()) 231 .put("src", link.src().deviceId().toString())
225 .put("srcPort", link.src().port().toString()) 232 .put("srcPort", link.src().port().toString())
...@@ -237,10 +244,11 @@ public abstract class TopologyMessages { ...@@ -237,10 +244,11 @@ public abstract class TopologyMessages {
237 .put("id", host.id().toString()) 244 .put("id", host.id().toString())
238 .put("ingress", compactLinkString(edgeLink(host, true))) 245 .put("ingress", compactLinkString(edgeLink(host, true)))
239 .put("egress", compactLinkString(edgeLink(host, false))); 246 .put("egress", compactLinkString(edgeLink(host, false)));
240 - payload.set("cp", location(mapper, host.location())); 247 + payload.set("cp", hostConnect(mapper, host.location()));
241 payload.set("labels", labels(mapper, ip(host.ipAddresses()), 248 payload.set("labels", labels(mapper, ip(host.ipAddresses()),
242 host.mac().toString())); 249 host.mac().toString()));
243 payload.set("props", props(host.annotations())); 250 payload.set("props", props(host.annotations()));
251 + addGeoLocation(host, payload);
244 addMetaUi(host.id().toString(), payload); 252 addMetaUi(host.id().toString(), payload);
245 253
246 String type = (event.type() == HOST_ADDED) ? "addHost" : 254 String type = (event.type() == HOST_ADDED) ? "addHost" :
...@@ -249,7 +257,7 @@ public abstract class TopologyMessages { ...@@ -249,7 +257,7 @@ public abstract class TopologyMessages {
249 } 257 }
250 258
251 // Encodes the specified host location into a JSON object. 259 // Encodes the specified host location into a JSON object.
252 - private ObjectNode location(ObjectMapper mapper, HostLocation location) { 260 + private ObjectNode hostConnect(ObjectMapper mapper, HostLocation location) {
253 return mapper.createObjectNode() 261 return mapper.createObjectNode()
254 .put("device", location.deviceId().toString()) 262 .put("device", location.deviceId().toString())
255 .put("port", location.port().toLong()); 263 .put("port", location.port().toLong());
...@@ -264,6 +272,12 @@ public abstract class TopologyMessages { ...@@ -264,6 +272,12 @@ public abstract class TopologyMessages {
264 return json; 272 return json;
265 } 273 }
266 274
275 + // Returns the name of the master node for the specified device id.
276 + private String master(DeviceId deviceId) {
277 + NodeId master = mastershipService.getMasterFor(deviceId);
278 + return master != null ? master.toString() : "";
279 + }
280 +
267 // Generates an edge link from the specified host location. 281 // Generates an edge link from the specified host location.
268 private EdgeLink edgeLink(Host host, boolean ingress) { 282 private EdgeLink edgeLink(Host host, boolean ingress) {
269 return new DefaultEdgeLink(PID, new ConnectPoint(host.id(), portNumber(0)), 283 return new DefaultEdgeLink(PID, new ConnectPoint(host.id(), portNumber(0)),
...@@ -278,6 +292,24 @@ public abstract class TopologyMessages { ...@@ -278,6 +292,24 @@ public abstract class TopologyMessages {
278 } 292 }
279 } 293 }
280 294
295 + // Adds a geo location JSON to the specified payload object.
296 + private void addGeoLocation(Annotated annotated, ObjectNode payload) {
297 + Annotations annotations = annotated.annotations();
298 + String slat = annotations.value("latitude");
299 + String slng = annotations.value("longitude");
300 + try {
301 + if (slat != null && slng != null && !slat.isEmpty() && !slng.isEmpty()) {
302 + double lat = Double.parseDouble(slat);
303 + double lng = Double.parseDouble(slng);
304 + ObjectNode loc = mapper.createObjectNode()
305 + .put("type", "latlng").put("lat", lat).put("lng", lng);
306 + payload.set("location", loc);
307 + }
308 + } catch (NumberFormatException e) {
309 + log.warn("Invalid geo data latitude={}; longiture={}", slat, slng);
310 + }
311 + }
312 +
281 // Updates meta UI information for the specified object. 313 // Updates meta UI information for the specified object.
282 protected void updateMetaUi(ObjectNode event) { 314 protected void updateMetaUi(ObjectNode event) {
283 ObjectNode payload = payload(event); 315 ObjectNode payload = payload(event);
...@@ -289,7 +321,6 @@ public abstract class TopologyMessages { ...@@ -289,7 +321,6 @@ public abstract class TopologyMessages {
289 Device device = deviceService.getDevice(deviceId); 321 Device device = deviceService.getDevice(deviceId);
290 Annotations annot = device.annotations(); 322 Annotations annot = device.annotations();
291 int portCount = deviceService.getPorts(deviceId).size(); 323 int portCount = deviceService.getPorts(deviceId).size();
292 - NodeId master = mastershipService.getMasterFor(device.id());
293 return envelope("showDetails", sid, 324 return envelope("showDetails", sid,
294 json(deviceId.toString(), 325 json(deviceId.toString(),
295 device.type().toString().toLowerCase(), 326 device.type().toString().toLowerCase(),
...@@ -303,7 +334,7 @@ public abstract class TopologyMessages { ...@@ -303,7 +334,7 @@ public abstract class TopologyMessages {
303 new Prop("Longitude", annot.value("longitude")), 334 new Prop("Longitude", annot.value("longitude")),
304 new Prop("Ports", Integer.toString(portCount)), 335 new Prop("Ports", Integer.toString(portCount)),
305 new Separator(), 336 new Separator(),
306 - new Prop("Master", master.toString()))); 337 + new Prop("Master", master(deviceId))));
307 } 338 }
308 339
309 // Returns host details response. 340 // Returns host details response.
...@@ -321,14 +352,14 @@ public abstract class TopologyMessages { ...@@ -321,14 +352,14 @@ public abstract class TopologyMessages {
321 352
322 353
323 // Produces a path message to the client. 354 // Produces a path message to the client.
324 - protected ObjectNode pathMessage(Path path) { 355 + protected ObjectNode pathMessage(Path path, String type) {
325 ObjectNode payload = mapper.createObjectNode(); 356 ObjectNode payload = mapper.createObjectNode();
326 ArrayNode links = mapper.createArrayNode(); 357 ArrayNode links = mapper.createArrayNode();
327 for (Link link : path.links()) { 358 for (Link link : path.links()) {
328 links.add(compactLinkString(link)); 359 links.add(compactLinkString(link));
329 } 360 }
330 361
331 - payload.set("links", links); 362 + payload.put("type", type).set("links", links);
332 return payload; 363 return payload;
333 } 364 }
334 365
......
...@@ -122,7 +122,7 @@ public class TopologyWebSocket ...@@ -122,7 +122,7 @@ public class TopologyWebSocket
122 cancelTraffic(event); 122 cancelTraffic(event);
123 } 123 }
124 } catch (Exception e) { 124 } catch (Exception e) {
125 - System.out.println("WTF?! " + data); 125 + log.warn("Unable to parse GUI request {} due to {}", data, e);
126 e.printStackTrace(); 126 e.printStackTrace();
127 } 127 }
128 } 128 }
...@@ -282,7 +282,8 @@ public class TopologyWebSocket ...@@ -282,7 +282,8 @@ public class TopologyWebSocket
282 if (installable != null && !installable.isEmpty()) { 282 if (installable != null && !installable.isEmpty()) {
283 PathIntent pathIntent = (PathIntent) installable.iterator().next(); 283 PathIntent pathIntent = (PathIntent) installable.iterator().next();
284 Path path = pathIntent.path(); 284 Path path = pathIntent.path();
285 - ObjectNode payload = pathMessage(path).put("intentId", intent.id().toString()); 285 + ObjectNode payload = pathMessage(path, "host")
286 + .put("intentId", intent.id().toString());
286 sendMessage(envelope("showPath", sid, payload)); 287 sendMessage(envelope("showPath", sid, payload));
287 } 288 }
288 } 289 }
......
...@@ -4,6 +4,11 @@ ...@@ -4,6 +4,11 @@
4 "id": "of:0000ffffffff0008", 4 "id": "of:0000ffffffff0008",
5 "type": "switch", 5 "type": "switch",
6 "online": false, 6 "online": false,
7 + "location": {
8 + "type": "latlng",
9 + "lat": 37.6,
10 + "lng": 122.3
11 + },
7 "labels": [ 12 "labels": [
8 "0000ffffffff0008", 13 "0000ffffffff0008",
9 "FF:FF:FF:FF:00:08", 14 "FF:FF:FF:FF:00:08",
......
...@@ -3,6 +3,11 @@ ...@@ -3,6 +3,11 @@
3 "id": "of:0000000000000001", 3 "id": "of:0000000000000001",
4 "type": "roadm", 4 "type": "roadm",
5 "propOrder": [ "name", "type", "-", "dpid", "latitude", "longitude", "allowed" ], 5 "propOrder": [ "name", "type", "-", "dpid", "latitude", "longitude", "allowed" ],
6 + "location": {
7 + "type": "latlng",
8 + "lat": 37.6,
9 + "lng": 122.3
10 + },
6 "props": { 11 "props": {
7 "allowed": true, 12 "allowed": true,
8 "latitude": 37.6, 13 "latitude": 37.6,
......
...@@ -3,6 +3,11 @@ ...@@ -3,6 +3,11 @@
3 "id": "of:0000000000000002", 3 "id": "of:0000000000000002",
4 "type": "switch", 4 "type": "switch",
5 "propOrder": [ "name", "type", "dpid", "latitude", "longitude", "allowed" ], 5 "propOrder": [ "name", "type", "dpid", "latitude", "longitude", "allowed" ],
6 + "location": {
7 + "type": "latlng",
8 + "lat": 37.6,
9 + "lng": 122.3
10 + },
6 "props": { 11 "props": {
7 "allowed": true, 12 "allowed": true,
8 "latitude": 37.3, 13 "latitude": 37.3,
......
...@@ -3,6 +3,11 @@ ...@@ -3,6 +3,11 @@
3 "id": "of:0000000000000003", 3 "id": "of:0000000000000003",
4 "type": "switch", 4 "type": "switch",
5 "propOrder": [ "name", "type", "dpid", "latitude", "longitude", "allowed" ], 5 "propOrder": [ "name", "type", "dpid", "latitude", "longitude", "allowed" ],
6 + "location": {
7 + "type": "latlng",
8 + "lat": 33.9,
9 + "lng": 118.4
10 + },
6 "props": { 11 "props": {
7 "allowed": true, 12 "allowed": true,
8 "latitude": 33.9, 13 "latitude": 33.9,
......
...@@ -3,6 +3,11 @@ ...@@ -3,6 +3,11 @@
3 "id": "of:0000000000000004", 3 "id": "of:0000000000000004",
4 "type": "switch", 4 "type": "switch",
5 "propOrder": [ "name", "type", "dpid", "latitude", "longitude", "allowed" ], 5 "propOrder": [ "name", "type", "dpid", "latitude", "longitude", "allowed" ],
6 + "location": {
7 + "type": "latlng",
8 + "lat": 32.8,
9 + "lng": 117.1
10 + },
6 "props": { 11 "props": {
7 "allowed": true, 12 "allowed": true,
8 "latitude": 32.8, 13 "latitude": 32.8,
......