Added top-level location object per Simon/Paul spec.
Fixed an NPE in mastership when running optical demo. Change-Id: I038000d1237b4150db0c722fa96dd9541d83e44e
Showing
7 changed files
with
66 additions
and
9 deletions
... | @@ -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, | ... | ... |
-
Please register or login to post a comment