/* * Copyright 2015-present Open Networking Laboratory * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.onosproject.rest.resources; import java.util.Spliterator; import java.util.Spliterators; import java.util.stream.StreamSupport; import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.PathParam; import javax.ws.rs.Produces; import javax.ws.rs.QueryParam; import javax.ws.rs.core.Context; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; import javax.ws.rs.core.UriBuilder; import javax.ws.rs.core.UriInfo; import org.onosproject.codec.JsonCodec; import org.onosproject.net.ConnectPoint; import org.onosproject.net.Device; import org.onosproject.net.DeviceId; import org.onosproject.net.Link; import org.onosproject.net.PortNumber; import org.onosproject.net.device.DeviceService; import org.onosproject.net.device.PortStatistics; import org.onosproject.net.flow.FlowRuleService; import org.onosproject.net.flow.TableStatisticsEntry; import org.onosproject.net.link.LinkService; import org.onosproject.net.statistic.Load; import org.onosproject.net.statistic.StatisticService; import org.onosproject.rest.AbstractWebResource; import com.fasterxml.jackson.databind.node.ArrayNode; import com.fasterxml.jackson.databind.node.ObjectNode; import static org.onosproject.net.DeviceId.deviceId; import static org.onosproject.net.PortNumber.portNumber; /** * Query flow statistics. */ @Path("statistics") public class StatisticsWebResource extends AbstractWebResource { @Context private UriInfo uriInfo; /** * Gets load statistics for all links or for a specific link. * * @onos.rsModel StatisticsFlowsLink * @param deviceId (optional) device ID for a specific link * @param port (optional) port number for a specified link * @return 200 OK with JSON encoded array of Load objects */ @GET @Path("flows/link") @Produces(MediaType.APPLICATION_JSON) public Response getLoads(@QueryParam("device") String deviceId, @QueryParam("port") String port) { Iterable<Link> links; if (deviceId == null || port == null) { links = get(LinkService.class).getLinks(); } else { ConnectPoint connectPoint = new ConnectPoint(deviceId(deviceId), portNumber(port)); links = get(LinkService.class).getLinks(connectPoint); } ObjectNode result = mapper().createObjectNode(); ArrayNode loads = mapper().createArrayNode(); JsonCodec<Load> loadCodec = codec(Load.class); StatisticService statsService = getService(StatisticService.class); StreamSupport.stream(Spliterators.spliteratorUnknownSize( links.iterator(), Spliterator.ORDERED), false) .forEach(link -> { ObjectNode loadNode = loadCodec.encode(statsService.load(link), this); UriBuilder locationBuilder = uriInfo.getBaseUriBuilder() .path("links") .queryParam("device", link.src().deviceId().toString()) .queryParam("port", link.src().port().toString()); loadNode.put("link", locationBuilder.build().toString()); loads.add(loadNode); }); result.set("loads", loads); return ok(result).build(); } /** * Gets table statistics for all tables of all devices. * * @onos.rsModel StatisticsFlowsTables * @return 200 OK with JSON encoded array of table statistics */ @GET @Path("flows/tables") @Produces(MediaType.APPLICATION_JSON) public Response getTableStatistics() { final FlowRuleService service = get(FlowRuleService.class); final Iterable<Device> devices = get(DeviceService.class).getDevices(); final ObjectNode root = mapper().createObjectNode(); final ArrayNode rootArrayNode = root.putArray("statistics"); for (final Device device : devices) { final ObjectNode deviceStatsNode = mapper().createObjectNode(); deviceStatsNode.put("device", device.id().toString()); final ArrayNode statisticsNode = deviceStatsNode.putArray("table"); final Iterable<TableStatisticsEntry> tableStatsEntries = service.getFlowTableStatistics(device.id()); if (tableStatsEntries != null) { for (final TableStatisticsEntry entry : tableStatsEntries) { statisticsNode.add(codec(TableStatisticsEntry.class).encode(entry, this)); } } rootArrayNode.add(deviceStatsNode); } return ok(root).build(); } /** * Gets table statistics for all tables of a specified device. * * @onos.rsModel StatisticsFlowsTables * @param deviceId device ID * @return 200 OK with JSON encoded array of table statistics */ @GET @Path("flows/tables/{deviceId}") @Produces(MediaType.APPLICATION_JSON) public Response getTableStatisticsByDeviceId(@PathParam("deviceId") String deviceId) { final FlowRuleService service = get(FlowRuleService.class); final Iterable<TableStatisticsEntry> tableStatisticsEntries = service.getFlowTableStatistics(DeviceId.deviceId(deviceId)); final ObjectNode root = mapper().createObjectNode(); final ArrayNode rootArrayNode = root.putArray("statistics"); final ObjectNode deviceStatsNode = mapper().createObjectNode(); deviceStatsNode.put("device", deviceId); final ArrayNode statisticsNode = deviceStatsNode.putArray("table"); for (final TableStatisticsEntry entry : tableStatisticsEntries) { statisticsNode.add(codec(TableStatisticsEntry.class).encode(entry, this)); } rootArrayNode.add(deviceStatsNode); return ok(root).build(); } /** * Gets port statistics of all devices. * @onos.rsModel StatisticsPorts * @return 200 OK with JSON encoded array of port statistics */ @GET @Path("ports") @Produces(MediaType.APPLICATION_JSON) public Response getPortStatistics() { final DeviceService service = get(DeviceService.class); final Iterable<Device> devices = service.getDevices(); final ObjectNode root = mapper().createObjectNode(); final ArrayNode rootArrayNode = root.putArray("statistics"); for (final Device device : devices) { final ObjectNode deviceStatsNode = mapper().createObjectNode(); deviceStatsNode.put("device", device.id().toString()); final ArrayNode statisticsNode = deviceStatsNode.putArray("ports"); final Iterable<PortStatistics> portStatsEntries = service.getPortStatistics(device.id()); if (portStatsEntries != null) { for (final PortStatistics entry : portStatsEntries) { statisticsNode.add(codec(PortStatistics.class).encode(entry, this)); } } rootArrayNode.add(deviceStatsNode); } return ok(root).build(); } /** * Gets port statistics of a specified devices. * @onos.rsModel StatisticsPorts * @param deviceId device ID * @return 200 OK with JSON encoded array of port statistics */ @GET @Path("ports/{deviceId}") @Produces(MediaType.APPLICATION_JSON) public Response getPortStatisticsByDeviceId(@PathParam("deviceId") String deviceId) { final DeviceService service = get(DeviceService.class); final Iterable<PortStatistics> portStatsEntries = service.getPortStatistics(DeviceId.deviceId(deviceId)); final ObjectNode root = mapper().createObjectNode(); final ArrayNode rootArrayNode = root.putArray("statistics"); final ObjectNode deviceStatsNode = mapper().createObjectNode(); deviceStatsNode.put("device", deviceId); final ArrayNode statisticsNode = deviceStatsNode.putArray("ports"); if (portStatsEntries != null) { for (final PortStatistics entry : portStatsEntries) { statisticsNode.add(codec(PortStatistics.class).encode(entry, this)); } } rootArrayNode.add(deviceStatsNode); return ok(root).build(); } /** * Gets port statistics of a specified device and port. * @onos.rsModel StatisticsPorts * @param deviceId device ID * @param port port * @return 200 OK with JSON encoded array of port statistics for the specified port */ @GET @Path("ports/{deviceId}/{port}") @Produces(MediaType.APPLICATION_JSON) public Response getPortStatisticsByDeviceIdAndPort(@PathParam("deviceId") String deviceId, @PathParam("port") String port) { final DeviceService service = get(DeviceService.class); final PortNumber portNumber = portNumber(port); final PortStatistics portStatsEntry = service.getStatisticsForPort(DeviceId.deviceId(deviceId), portNumber); final ObjectNode root = mapper().createObjectNode(); final ArrayNode rootArrayNode = root.putArray("statistics"); final ObjectNode deviceStatsNode = mapper().createObjectNode(); deviceStatsNode.put("device", deviceId); final ArrayNode statisticsNode = deviceStatsNode.putArray("ports"); if (portStatsEntry != null) { statisticsNode.add(codec(PortStatistics.class).encode(portStatsEntry, this)); } rootArrayNode.add(deviceStatsNode); return ok(root).build(); } /** * Gets port delta statistics of all devices. * @onos.rsModel StatisticsPorts * @return 200 OK with JSON encoded array of port delta statistics */ @GET @Path("delta/ports") @Produces(MediaType.APPLICATION_JSON) public Response getPortDeltaStatistics() { final DeviceService service = get(DeviceService.class); final Iterable<Device> devices = service.getDevices(); final ObjectNode root = mapper().createObjectNode(); final ArrayNode rootArrayNode = root.putArray("statistics"); for (final Device device : devices) { final ObjectNode deviceStatsNode = mapper().createObjectNode(); deviceStatsNode.put("device", device.id().toString()); final ArrayNode statisticsNode = deviceStatsNode.putArray("ports"); final Iterable<PortStatistics> portStatsEntries = service.getPortDeltaStatistics(device.id()); if (portStatsEntries != null) { for (final PortStatistics entry : portStatsEntries) { statisticsNode.add(codec(PortStatistics.class).encode(entry, this)); } } rootArrayNode.add(deviceStatsNode); } return ok(root).build(); } /** * Gets port delta statistics of a specified devices. * @onos.rsModel StatisticsPorts * @param deviceId device ID * @return 200 OK with JSON encoded array of port delta statistics */ @GET @Path("delta/ports/{deviceId}") @Produces(MediaType.APPLICATION_JSON) public Response getPortDeltaStatisticsByDeviceId(@PathParam("deviceId") String deviceId) { final DeviceService service = get(DeviceService.class); final Iterable<PortStatistics> portStatsEntries = service.getPortDeltaStatistics(DeviceId.deviceId(deviceId)); final ObjectNode root = mapper().createObjectNode(); final ArrayNode rootArrayNode = root.putArray("statistics"); final ObjectNode deviceStatsNode = mapper().createObjectNode(); deviceStatsNode.put("device", deviceId); final ArrayNode statisticsNode = deviceStatsNode.putArray("ports"); if (portStatsEntries != null) { for (final PortStatistics entry : portStatsEntries) { statisticsNode.add(codec(PortStatistics.class).encode(entry, this)); } } rootArrayNode.add(deviceStatsNode); return ok(root).build(); } /** * Gets port delta statistics of a specified device and port. * @onos.rsModel StatisticsPorts * @param deviceId device ID * @param port port * @return 200 OK with JSON encoded array of port delta statistics for the specified port */ @GET @Path("delta/ports/{deviceId}/{port}") @Produces(MediaType.APPLICATION_JSON) public Response getPortDeltaStatisticsByDeviceIdAndPort(@PathParam("deviceId") String deviceId, @PathParam("port") String port) { final DeviceService service = get(DeviceService.class); final PortNumber portNumber = portNumber(port); final PortStatistics portStatsEntry = service.getDeltaStatisticsForPort(DeviceId.deviceId(deviceId), portNumber); final ObjectNode root = mapper().createObjectNode(); final ArrayNode rootArrayNode = root.putArray("statistics"); final ObjectNode deviceStatsNode = mapper().createObjectNode(); deviceStatsNode.put("device", deviceId); final ArrayNode statisticsNode = deviceStatsNode.putArray("ports"); if (portStatsEntry != null) { statisticsNode.add(codec(PortStatistics.class).encode(portStatsEntry, this)); } rootArrayNode.add(deviceStatsNode); return ok(root).build(); } }