blob: 283b8fbf4488869a9545f13d558e00bf9360bb8d [file] [log] [blame]
tom8bb16062014-09-12 14:47:46 -07001package org.onlab.onos.tvue;
2
3import com.fasterxml.jackson.databind.ObjectMapper;
4import com.fasterxml.jackson.databind.node.ArrayNode;
5import com.fasterxml.jackson.databind.node.ObjectNode;
6import org.onlab.onos.net.ConnectPoint;
7import org.onlab.onos.net.ElementId;
8import org.onlab.onos.net.Link;
9import org.onlab.onos.net.device.DeviceService;
10import org.onlab.onos.net.host.HostService;
11import org.onlab.onos.net.link.LinkService;
12import org.onlab.onos.net.topology.Topology;
13import org.onlab.onos.net.topology.TopologyGraph;
14import org.onlab.onos.net.topology.TopologyService;
15import org.onlab.onos.net.topology.TopologyVertex;
16import org.onlab.rest.BaseResource;
17
18import javax.ws.rs.GET;
19import javax.ws.rs.Path;
20import javax.ws.rs.Produces;
21import javax.ws.rs.core.Response;
22import java.util.HashMap;
23import java.util.HashSet;
24import java.util.Map;
25import java.util.Set;
26
27/**
28 * Topology viewer resource.
29 */
30@Path("topology")
31public class TopologyResource extends BaseResource {
32
33 @Path("/graph")
34 @GET
35 @Produces("application/json")
36 public Response graph() {
37 ObjectMapper mapper = new ObjectMapper();
38
39 // Fetch the services we'll be using.
40 DeviceService deviceService = get(DeviceService.class);
41 HostService hostService = get(HostService.class);
42 TopologyService topologyService = get(TopologyService.class);
43
44 // Fetch the current topology and its graph that we'll use to render.
45 Topology topo = topologyService.currentTopology();
46 TopologyGraph graph = topologyService.getGraph(topo);
47
48 // Build all interior vertexes, i.e. no end-station hosts yet
49 ArrayNode vertexesNode = mapper.createArrayNode();
50 for (TopologyVertex vertex : graph.getVertexes()) {
51 vertexesNode.add(json(mapper, vertex.deviceId(), 2,
52 deviceService.isAvailable(vertex.deviceId())));
53 }
54
55 // Now scan all links and count number of them between the same devices
56 // using a normalized link key.
57 Map<String, AggLink> linkRecords = aggregateLinks();
58
59 // Now build all interior edges using the aggregated links.
60 ArrayNode edgesNode = mapper.createArrayNode();
61 for (AggLink lr : linkRecords.values()) {
62 edgesNode.add(json(mapper, lr.links.size(), lr.link.src(), lr.link.dst()));
63 }
64
65 // Merge the exterior and interior vertexes and inject host links as
66 // the exterior edges.
67// Iterator<Host> hosts = hostService.getHosts();
68// while (hosts.hasNext()) {
69// Host host = hosts.next();
70// vertexesNode.add(json(mapper, host.id().ip().toString(), 3, true));
71// edgesNode.add(json(mapper, 1, host.ip().toString(),
72// host.location().elementId().uri()));
73// }
74
75 // Now put the vertexes and edges into a root node and ship them off
76 ObjectNode rootNode = mapper.createObjectNode();
77 rootNode.put("vertexes", vertexesNode);
78 rootNode.put("edges", edgesNode);
79 return Response.ok(rootNode.toString()).build();
80 }
81
82 // Scan all links and counts number of them between the same devices
83 // using a normalized link key.
84 private Map<String, AggLink> aggregateLinks() {
85 Map<String, AggLink> aggLinks = new HashMap<>();
86 LinkService linkService = get(LinkService.class);
87 for (Link link : linkService.getLinks()) {
88 String key = key(link);
89 AggLink lr = aggLinks.get(key);
90 if (lr == null) {
91 lr = new AggLink(key);
92 aggLinks.put(key, lr);
93 }
94 lr.addLink(link);
95 }
96 return aggLinks;
97 }
98
99 // Produces JSON for a graph vertex.
100 private ObjectNode json(ObjectMapper mapper, ElementId id, int group,
101 boolean isOnline) {
102 return mapper.createObjectNode()
tom4009d2c2014-09-12 15:53:42 -0700103 .put("name", id.uri().getSchemeSpecificPart())
tom8bb16062014-09-12 14:47:46 -0700104 .put("group", group)
105 .put("online", isOnline);
106 }
107
108 // Produces JSON for a graph edge.
109 private ObjectNode json(ObjectMapper mapper, int count,
110 ConnectPoint src, ConnectPoint dst) {
111 return json(mapper, count, id(src), id(dst));
112 }
113
114 // Produces JSON for a graph edge.
115 private ObjectNode json(ObjectMapper mapper, int count, String src, String dst) {
116 return mapper.createObjectNode()
117 .put("source", src).put("target", dst).put("value", count);
118 }
119
120 // Aggregate link of all links between the same devices regardless of
121 // their direction.
122 private class AggLink {
123 Link link; // representative links
124
125 final String key;
126 final Set<Link> links = new HashSet<>();
127
128 AggLink(String key) {
129 this.key = key;
130 }
131
132 void addLink(Link link) {
133 links.add(link);
134 if (this.link == null) {
135 this.link = link;
136 }
137 }
138 }
139
140 // Returns a canonical key for the specified link.
141 static String key(Link link) {
142 String s = id(link.src());
143 String d = id(link.dst());
144 return s.compareTo(d) > 0 ? d + s : s + d;
145 }
146
147 // Returns a formatted string for the element associated with the given
148 // connection point.
149 private static String id(ConnectPoint cp) {
tom4009d2c2014-09-12 15:53:42 -0700150 return cp.elementId().uri().getSchemeSpecificPart();
tom8bb16062014-09-12 14:47:46 -0700151 }
152
153}