blob: b15e80c57517772504b06889652410cbe4a1183a [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;
tom6a9986b2014-09-12 18:44:52 -07007import org.onlab.onos.net.Device;
tom8bb16062014-09-12 14:47:46 -07008import org.onlab.onos.net.ElementId;
9import org.onlab.onos.net.Link;
10import org.onlab.onos.net.device.DeviceService;
11import org.onlab.onos.net.host.HostService;
12import org.onlab.onos.net.link.LinkService;
13import org.onlab.onos.net.topology.Topology;
14import org.onlab.onos.net.topology.TopologyGraph;
15import org.onlab.onos.net.topology.TopologyService;
16import org.onlab.onos.net.topology.TopologyVertex;
17import org.onlab.rest.BaseResource;
18
19import javax.ws.rs.GET;
tom6a9986b2014-09-12 18:44:52 -070020import javax.ws.rs.PathParam;
tom8bb16062014-09-12 14:47:46 -070021import javax.ws.rs.Produces;
22import javax.ws.rs.core.Response;
23import java.util.HashMap;
24import java.util.HashSet;
25import java.util.Map;
26import java.util.Set;
27
tom6a9986b2014-09-12 18:44:52 -070028import static org.onlab.onos.net.DeviceId.deviceId;
29
tom8bb16062014-09-12 14:47:46 -070030/**
31 * Topology viewer resource.
32 */
tom6a9986b2014-09-12 18:44:52 -070033@javax.ws.rs.Path("topology")
tom8bb16062014-09-12 14:47:46 -070034public class TopologyResource extends BaseResource {
35
tom6a9986b2014-09-12 18:44:52 -070036 @javax.ws.rs.Path("/graph")
tom8bb16062014-09-12 14:47:46 -070037 @GET
38 @Produces("application/json")
39 public Response graph() {
40 ObjectMapper mapper = new ObjectMapper();
41
42 // Fetch the services we'll be using.
43 DeviceService deviceService = get(DeviceService.class);
44 HostService hostService = get(HostService.class);
45 TopologyService topologyService = get(TopologyService.class);
46
47 // Fetch the current topology and its graph that we'll use to render.
48 Topology topo = topologyService.currentTopology();
49 TopologyGraph graph = topologyService.getGraph(topo);
50
51 // Build all interior vertexes, i.e. no end-station hosts yet
52 ArrayNode vertexesNode = mapper.createArrayNode();
53 for (TopologyVertex vertex : graph.getVertexes()) {
54 vertexesNode.add(json(mapper, vertex.deviceId(), 2,
55 deviceService.isAvailable(vertex.deviceId())));
56 }
57
58 // Now scan all links and count number of them between the same devices
59 // using a normalized link key.
60 Map<String, AggLink> linkRecords = aggregateLinks();
61
62 // Now build all interior edges using the aggregated links.
63 ArrayNode edgesNode = mapper.createArrayNode();
64 for (AggLink lr : linkRecords.values()) {
65 edgesNode.add(json(mapper, lr.links.size(), lr.link.src(), lr.link.dst()));
66 }
67
68 // Merge the exterior and interior vertexes and inject host links as
69 // the exterior edges.
70// Iterator<Host> hosts = hostService.getHosts();
71// while (hosts.hasNext()) {
72// Host host = hosts.next();
73// vertexesNode.add(json(mapper, host.id().ip().toString(), 3, true));
74// edgesNode.add(json(mapper, 1, host.ip().toString(),
75// host.location().elementId().uri()));
76// }
77
78 // Now put the vertexes and edges into a root node and ship them off
79 ObjectNode rootNode = mapper.createObjectNode();
80 rootNode.put("vertexes", vertexesNode);
81 rootNode.put("edges", edgesNode);
82 return Response.ok(rootNode.toString()).build();
83 }
84
tom6a9986b2014-09-12 18:44:52 -070085
86
87 /**
88 * Returns a JSON array of all paths between the specified hosts.
89 *
90 * @param src source host id
91 * @param dst target host id
92 * @return JSON array of paths
93 */
94 @javax.ws.rs.Path("/paths/{src}/{dst}")
95 @GET
96 @Produces("application/json")
97 public Response paths(@PathParam("src") String src, @PathParam("dst") String dst) {
98 ObjectMapper mapper = new ObjectMapper();
99
100 DeviceService deviceService = get(DeviceService.class);
101 TopologyService topologyService = get(TopologyService.class);
102 Topology topology = topologyService.currentTopology();
103
104 ArrayNode pathsNode = mapper.createArrayNode();
105 Device srcDevice = deviceService.getDevice(deviceId(src));
106 Device dstDevice = deviceService.getDevice(deviceId(dst));
107
108// if (srcDevice != null && dstDevice != null) {
109// for (Path path : topologyService.getPaths(topology, srcDevice, dstDevice))
110// pathsNode.add(json(mapper, path));
111// }
112
113 // Now put the vertexes and edges into a root node and ship them off
114 ObjectNode rootNode = mapper.createObjectNode();
115 rootNode.put("paths", pathsNode);
116 return Response.ok(rootNode.toString()).build();
117 }
118
tom8bb16062014-09-12 14:47:46 -0700119 // Scan all links and counts number of them between the same devices
120 // using a normalized link key.
121 private Map<String, AggLink> aggregateLinks() {
122 Map<String, AggLink> aggLinks = new HashMap<>();
123 LinkService linkService = get(LinkService.class);
124 for (Link link : linkService.getLinks()) {
125 String key = key(link);
126 AggLink lr = aggLinks.get(key);
127 if (lr == null) {
128 lr = new AggLink(key);
129 aggLinks.put(key, lr);
130 }
131 lr.addLink(link);
132 }
133 return aggLinks;
134 }
135
tom6a9986b2014-09-12 18:44:52 -0700136
137
138
139
tom8bb16062014-09-12 14:47:46 -0700140 // Produces JSON for a graph vertex.
141 private ObjectNode json(ObjectMapper mapper, ElementId id, int group,
142 boolean isOnline) {
143 return mapper.createObjectNode()
tom4009d2c2014-09-12 15:53:42 -0700144 .put("name", id.uri().getSchemeSpecificPart())
tom8bb16062014-09-12 14:47:46 -0700145 .put("group", group)
146 .put("online", isOnline);
147 }
148
149 // Produces JSON for a graph edge.
150 private ObjectNode json(ObjectMapper mapper, int count,
151 ConnectPoint src, ConnectPoint dst) {
152 return json(mapper, count, id(src), id(dst));
153 }
154
155 // Produces JSON for a graph edge.
156 private ObjectNode json(ObjectMapper mapper, int count, String src, String dst) {
157 return mapper.createObjectNode()
158 .put("source", src).put("target", dst).put("value", count);
159 }
160
161 // Aggregate link of all links between the same devices regardless of
162 // their direction.
163 private class AggLink {
164 Link link; // representative links
165
166 final String key;
167 final Set<Link> links = new HashSet<>();
168
169 AggLink(String key) {
170 this.key = key;
171 }
172
173 void addLink(Link link) {
174 links.add(link);
175 if (this.link == null) {
176 this.link = link;
177 }
178 }
179 }
180
181 // Returns a canonical key for the specified link.
182 static String key(Link link) {
183 String s = id(link.src());
184 String d = id(link.dst());
185 return s.compareTo(d) > 0 ? d + s : s + d;
186 }
187
188 // Returns a formatted string for the element associated with the given
189 // connection point.
190 private static String id(ConnectPoint cp) {
tom4009d2c2014-09-12 15:53:42 -0700191 return cp.elementId().uri().getSchemeSpecificPart();
tom8bb16062014-09-12 14:47:46 -0700192 }
193
194}