X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=blobdiff_plain;f=opendaylight%2Fadsal%2Fnorthbound%2Fstatistics%2Fsrc%2Fmain%2Fjava%2Forg%2Fopendaylight%2Fcontroller%2Fstatistics%2Fnorthbound%2FStatisticsNorthbound.java;fp=opendaylight%2Fadsal%2Fnorthbound%2Fstatistics%2Fsrc%2Fmain%2Fjava%2Forg%2Fopendaylight%2Fcontroller%2Fstatistics%2Fnorthbound%2FStatisticsNorthbound.java;h=4175f1e3c49984c7d90ac03b2207df946c9f7e3a;hb=42c32160bfd41de57189bb246fec5ffb48ed8e9e;hp=0000000000000000000000000000000000000000;hpb=edf5bfcee83c750853253ccfd991ba7000f5f65b;p=controller.git diff --git a/opendaylight/adsal/northbound/statistics/src/main/java/org/opendaylight/controller/statistics/northbound/StatisticsNorthbound.java b/opendaylight/adsal/northbound/statistics/src/main/java/org/opendaylight/controller/statistics/northbound/StatisticsNorthbound.java new file mode 100644 index 0000000000..4175f1e3c4 --- /dev/null +++ b/opendaylight/adsal/northbound/statistics/src/main/java/org/opendaylight/controller/statistics/northbound/StatisticsNorthbound.java @@ -0,0 +1,1169 @@ +/* + * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ + +package org.opendaylight.controller.statistics.northbound; + +import java.util.ArrayList; +import java.util.List; + +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.SecurityContext; +import javax.ws.rs.ext.ContextResolver; + +import org.codehaus.enunciate.jaxrs.ResponseCode; +import org.codehaus.enunciate.jaxrs.StatusCodes; +import org.codehaus.enunciate.jaxrs.TypeHint; +import org.opendaylight.controller.containermanager.IContainerManager; +import org.opendaylight.controller.northbound.commons.RestMessages; +import org.opendaylight.controller.northbound.commons.exception.InternalServerErrorException; +import org.opendaylight.controller.northbound.commons.exception.ResourceConflictException; +import org.opendaylight.controller.northbound.commons.exception.ResourceNotFoundException; +import org.opendaylight.controller.northbound.commons.exception.ServiceUnavailableException; +import org.opendaylight.controller.northbound.commons.exception.UnauthorizedException; +import org.opendaylight.controller.northbound.commons.query.QueryContext; +import org.opendaylight.controller.northbound.commons.utils.NorthboundUtils; +import org.opendaylight.controller.sal.authorization.Privilege; +import org.opendaylight.controller.sal.core.Node; +import org.opendaylight.controller.sal.reader.FlowOnNode; +import org.opendaylight.controller.sal.reader.NodeConnectorStatistics; +import org.opendaylight.controller.sal.reader.NodeTableStatistics; +import org.opendaylight.controller.sal.utils.GlobalConstants; +import org.opendaylight.controller.sal.utils.ServiceHelper; +import org.opendaylight.controller.statisticsmanager.IStatisticsManager; +import org.opendaylight.controller.switchmanager.ISwitchManager; + +/** + * Northbound APIs that returns various Statistics exposed by the Southbound + * protocol plugins such as Openflow. + * + *
+ *
+ * Authentication scheme : HTTP Basic
+ * Authentication realm : opendaylight
+ * Transport : HTTP and HTTPS
+ *
+ * HTTPS Authentication is disabled by default. + * + */ +@Path("/") +public class StatisticsNorthbound { + + private String username; + private QueryContext queryContext; + + @Context + public void setQueryContext(ContextResolver queryCtxResolver) { + if (queryCtxResolver != null) { + queryContext = queryCtxResolver.getContext(QueryContext.class); + } + } + @Context + public void setSecurityContext(SecurityContext context) { + if (context != null && context.getUserPrincipal() != null) username = context.getUserPrincipal().getName(); + } + + protected String getUserName() { + return username; + } + + private IStatisticsManager getStatisticsService(String containerName) { + IContainerManager containerManager = (IContainerManager) ServiceHelper + .getGlobalInstance(IContainerManager.class, this); + if (containerManager == null) { + throw new ServiceUnavailableException("Container " + + RestMessages.SERVICEUNAVAILABLE.toString()); + } + + boolean found = false; + List containerNames = containerManager.getContainerNames(); + for (String cName : containerNames) { + if (cName.trim().equalsIgnoreCase(containerName.trim())) { + found = true; + } + } + + if (found == false) { + throw new ResourceNotFoundException(containerName + " " + + RestMessages.NOCONTAINER.toString()); + } + + IStatisticsManager statsManager = (IStatisticsManager) ServiceHelper + .getInstance(IStatisticsManager.class, containerName, this); + + if (statsManager == null) { + throw new ServiceUnavailableException("Statistics " + + RestMessages.SERVICEUNAVAILABLE.toString()); + } + + return statsManager; + } + + /** + * Returns a list of all Flow Statistics from all the Nodes. + * + * @param containerName + * Name of the Container. The Container name for the base + * controller is "default". + * @return List of FlowStatistics from all the Nodes + * + *
+     *
+     * Example:
+     *
+     * Request URL:
+     * http://localhost:8080/controller/nb/v2/statistics/default/flow
+     *
+     * Response body in JSON:
+     * {
+     *     "flowStatistics": [
+     *         {
+     *             "node": {
+     *                 "id":"00:00:00:00:00:00:00:02",
+     *                 "type":"OF"
+     *             },
+     *             "flowStatistic": [
+     *                 {
+     *                     "flow": {
+     *                         "match": {
+     *                             "matchField": [
+     *                                 {
+     *                                     "type": "DL_TYPE",
+     *                                     "value": "2048"
+     *                                 },
+     *                                 {
+     *                                     "mask": "255.255.255.255",
+     *                                     "type": "NW_DST",
+     *                                     "value": "1.1.1.1"
+     *                                 }
+     *                             ]
+     *                         },
+     *                         "actions": {
+     *                             "@type": "output",
+     *                             "port": {
+     *                                 "node":{
+     *                                     "id":"00:00:00:00:00:00:00:02",
+     *                                     "type":"OF"
+     *                                 },
+     *                                 "id":"3",
+     *                                 "type":"OF"
+     *                             }
+     *                         },
+     *                         "priority": "1",
+     *                         "idleTimeout": "0",
+     *                         "hardTimeout": "0",
+     *                         "id": "0"
+     *                     },
+     *                     "tableId": "0",
+     *                     "durationSeconds": "1828",
+     *                     "durationNanoseconds": "397000000",
+     *                     "packetCount": "0",
+     *                     "byteCount": "0"
+     *                 }
+     *             ]
+     *         },
+     *         {   flow statistics of another node
+     *             ............
+     *             ................
+     *             ......................
+     *         }
+     *
+     *     ]
+     * }
+     *
+     * Response body in XML:
+     * <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+     * <list>
+     *     <flowStatistics>
+     *         <node>
+     *             <id>00:00:00:00:00:00:00:02</id>
+     *             <type>OF</type>
+     *         </node>
+     *         <flowStatistic>
+     *             <flow>
+     *                 <match>
+     *                     <matchField>
+     *                         <type>DL_TYPE</type>
+     *                         <value>2048</value>
+     *                     </matchField>
+     *                     <matchField>
+     *                         <mask>255.255.255.255</mask>
+     *                         <type>NW_DST</type>
+     *                         <value>1.1.1.2</value>
+     *                     </matchField>
+     *                 </match>
+     *                 <actions
+     *                     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="output">
+     *                     <port>
+     *                         <node>
+     *                             <id>00:00:00:00:00:00:00:02</id>
+     *                             <type>OF</type>
+     *                         </node>
+     *                         <id>3</id>
+     *                         <type>OF</type>
+     *                     </port>
+     *                 </actions>
+     *                 <priority>1</priority>
+     *                 <idleTimeout>0</idleTimeout>
+     *                 <hardTimeout>0</hardTimeout>
+     *                 <id>0</id>
+     *             </flow>
+     *             <tableId>0</tableId>
+     *             <durationSeconds>337</durationSeconds>
+     *             <durationNanoseconds>149000000</durationNanoseconds>
+     *             <packetCount>0</packetCount>
+     *             <byteCount>0</byteCount>
+     *         </flowStatistic>
+     *     </flowStatistics>
+     *     <flowStatistics>
+     *          flow statistics for another node
+     *          ..........
+     *          ................
+     *          .....................
+     *     </flowStatistics>
+     * </list>
+     * 
+ */ + + @Path("/{containerName}/flow") + @GET + @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }) + @TypeHint(AllFlowStatistics.class) + @StatusCodes({ + @ResponseCode(code = 200, condition = "Operation successful"), + @ResponseCode(code = 404, condition = "The containerName is not found"), + @ResponseCode(code = 503, condition = "One or more of Controller Services are unavailable") }) + public AllFlowStatistics getFlowStatistics( + @PathParam("containerName") String containerName, + @QueryParam("_q") String queryString) { + if (!NorthboundUtils.isAuthorized( + getUserName(), containerName, Privilege.READ, this)) { + throw new UnauthorizedException( + "User is not authorized to perform this operation on container " + + containerName); + } + IStatisticsManager statisticsManager = getStatisticsService(containerName); + if (statisticsManager == null) { + throw new ServiceUnavailableException("Statistics " + + RestMessages.SERVICEUNAVAILABLE.toString()); + } + + ISwitchManager switchManager = (ISwitchManager) ServiceHelper + .getInstance(ISwitchManager.class, containerName, this); + if (switchManager == null) { + throw new ServiceUnavailableException("Switch manager " + + RestMessages.SERVICEUNAVAILABLE.toString()); + } + + List statistics = new ArrayList(); + for (Node node : switchManager.getNodes()) { + List flowStats = new ArrayList(); + + List flows = statisticsManager.getFlows(node); + for (FlowOnNode flowOnSwitch : flows) { + flowStats.add(flowOnSwitch); + } + FlowStatistics stat = new FlowStatistics(node, flowStats); + statistics.add(stat); + } + AllFlowStatistics result = new AllFlowStatistics(statistics); + if (queryString != null) { + queryContext.createQuery(queryString, AllFlowStatistics.class) + .filter(result, FlowStatistics.class); + } + return result; + } + + /** + * Returns a list of Flow Statistics for a given Node. + * + * @param containerName + * Name of the Container. The Container name for the base + * controller is "default". + * @param nodeType + * Node Type as specifid in {@link org.opendaylight.controller.sal.core.Node} class + * @param nodeId + * Node Identifier + * @return List of Flow Statistics for a given Node. * + * + *
+     *
+     * Example:
+     *
+     * Request URL:
+     * http://localhost:8080/controller/nb/v2/statistics/default/flow/node/OF/00:00:00:00:00:00:00:01
+     *
+     * Response body in JSON:
+     * {
+     *     "node": {
+     *         "id":"00:00:00:00:00:00:00:01",
+     *         "type":"OF"
+     *     },
+     *     "flowStatistic": [
+     *         {
+     *             "flow": {
+     *                 "match": {
+     *                     "matchField": [
+     *                         {
+     *                             "type": "DL_TYPE",
+     *                             "value": "2048"
+     *                         },
+     *                         {
+     *                             "mask": "255.255.255.255",
+     *                             "type": "NW_DST",
+     *                             "value": "1.1.1.2"
+     *                         }
+     *                     ]
+     *                 },
+     *                 "actions": [
+     *                     {
+     *                         "@type": "setDlDst",
+     *                         "address": "52d28b0f76ec"
+     *                     },
+     *                     {
+     *                         "@type": "output",
+     *                         "port":{
+     *                             "node":{
+     *                                 "id":"00:00:00:00:00:00:00:01",
+     *                                 "type":"OF"
+     *                              },
+     *                              "id":"5",
+     *                              "type":"OF"
+     *                         }
+     *                     }
+     *                 ],
+     *                 "priority": "1",
+     *                 "idleTimeout": "0",
+     *                 "hardTimeout": "0",
+     *                 "id": "0"
+     *             },
+     *             "tableId": "0",
+     *             "durationSeconds": "2089",
+     *             "durationNanoseconds": "538000000",
+     *             "packetCount": "0",
+     *             "byteCount": "0"
+     *         }
+     *     ]
+     * }
+     *
+     * Response body in XML:
+     * <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+     *     <nodeFlowStatistics>
+     *         <node>
+     *             <id>00:00:00:00:00:00:00:02</id>
+     *             <type>OF</type>
+     *         </node>
+     *         <flowStatistic>
+     *             <flow>
+     *                 <match>
+     *                     <matchField>
+     *                         <type>DL_TYPE</type>
+     *                         <value>2048</value>
+     *                     </matchField>
+     *                     <matchField>
+     *                         <mask>255.255.255.255</mask>
+     *                         <type>NW_DST</type>
+     *                         <value>1.1.1.2</value>
+     *                     </matchField>
+     *                 </match>
+     *                 <actions
+     *                     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="output">
+     *                     <port>
+     *                         <node>
+     *                             <id>00:00:00:00:00:00:00:02</id>
+     *                             <type>OF</type>
+     *                         </node>
+     *                         <id>3</id>
+     *                         <type>OF</type>
+     *                     </port>
+     *                 </actions>
+     *                 <priority>1</priority>
+     *                 <idleTimeout>0</idleTimeout>
+     *                 <hardTimeout>0</hardTimeout>
+     *                 <id>0</id>
+     *             </flow>
+     *             <tableId>0</tableId>
+     *             <durationSeconds>337</durationSeconds>
+     *             <durationNanoseconds>149000000</durationNanoseconds>
+     *             <packetCount>0</packetCount>
+     *             <byteCount>0</byteCount>
+     *         </flowStatistic>
+     *         <flowStatistic>
+     *             <flow>
+     *                 <match>
+     *                     <matchField>
+     *                         <type>DL_TYPE</type>
+     *                         <value>2048</value>
+     *                     </matchField>
+     *                     <matchField>
+     *                         <mask>255.255.255.255</mask>
+     *                         <type>NW_DST</type>
+     *                         <value>1.1.1.1</value>
+     *                     </matchField>
+     *                 </match>
+     *                 <actions
+     *                     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="output">
+     *                     <port>
+     *                         <node>
+     *                             <id>00:00:00:00:00:00:00:02</id>
+     *                             <type>OF</type>
+     *                         </node>
+     *                         <id>3</id>
+     *                         <type>OF</type>
+     *                     </port>
+     *                 </actions>
+     *                 <priority>1</priority>
+     *                 <idleTimeout>0</idleTimeout>
+     *                 <hardTimeout>0</hardTimeout>
+     *                 <id>0</id>
+     *             </flow>
+     *             <tableId>0</tableId>
+     *             <durationSeconds>337</durationSeconds>
+     *             <durationNanoseconds>208000000</durationNanoseconds>
+     *             <packetCount>0</packetCount>
+     *             <byteCount>0</byteCount>
+     *         </flowStatistic>
+     *     </nodeFlowStatistics>
+     * 
+ */ + @Path("/{containerName}/flow/node/{nodeType}/{nodeId}") + @GET + @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }) + @TypeHint(FlowStatistics.class) + @StatusCodes({ + @ResponseCode(code = 200, condition = "Operation successful"), + @ResponseCode(code = 404, condition = "The containerName is not found"), + @ResponseCode(code = 503, condition = "One or more of Controller Services are unavailable") }) + public FlowStatistics getFlowStatistics( + @PathParam("containerName") String containerName, + @PathParam("nodeType") String nodeType, + @PathParam("nodeId") String nodeId) { + if (!NorthboundUtils.isAuthorized( + getUserName(), containerName, Privilege.READ, this)) { + throw new UnauthorizedException( + "User is not authorized to perform this operation on container " + + containerName); + } + handleDefaultDisabled(containerName); + + IStatisticsManager statisticsManager = getStatisticsService(containerName); + if (statisticsManager == null) { + throw new ServiceUnavailableException("Statistics " + + RestMessages.SERVICEUNAVAILABLE.toString()); + } + + ISwitchManager switchManager = (ISwitchManager) ServiceHelper + .getInstance(ISwitchManager.class, containerName, this); + if (switchManager == null) { + throw new ServiceUnavailableException("Switch manager " + + RestMessages.SERVICEUNAVAILABLE.toString()); + } + + Node node = handleNodeAvailability(containerName, nodeType, nodeId); + return new FlowStatistics(node, statisticsManager.getFlows(node)); + } + + /** + * Returns a list of all the Port Statistics across all the NodeConnectors + * on all the Nodes. + * + * @param containerName + * Name of the Container. The Container name for the base + * controller is "default". + * @return List of all the Port Statistics across all the NodeConnectors on + * all the Nodes. + * + *
+     *
+     * Example:
+     *
+     * Request URL:
+     * http://localhost:8080/controller/nb/v2/statistics/default/port
+     *
+     * Response body in JSON:
+     * {
+     *     "portStatistics": [
+     *         {
+     *             "node": {
+     *                  "id":"00:00:00:00:00:00:00:02",
+     *                  "type":"OF"
+     *             },
+     *             "portStatistic": [
+     *                 {
+     *                     "nodeConnector":{
+     *                          "node":{
+     *                                 "id":"00:00:00:00:00:00:00:02",
+     *                                 "type":"OF"
+     *                           },
+     *                           "id":"3",
+     *                           "type":"OF"
+     *                     },
+     *                     "receivePackets": "182",
+     *                     "transmitPackets": "173",
+     *                     "receiveBytes": "12740",
+     *                     "transmitBytes": "12110",
+     *                     "receiveDrops": "0",
+     *                     "transmitDrops": "0",
+     *                     "receiveErrors": "0",
+     *                     "transmitErrors": "0",
+     *                     "receiveFrameError": "0",
+     *                     "receiveOverRunError": "0",
+     *                     "receiveCrcError": "0",
+     *                     "collisionCount": "0"
+     *                 },
+     *                 {
+     *                     "nodeConnector": {
+     *                          "node":{
+     *                                  "id":"00:00:00:00:00:00:00:02",
+     *                                  "type":"OF"
+     *                           },
+     *                           "id":"2",
+     *                           "type":"OF"
+     *                     },
+     *                     "receivePackets": "174",
+     *                     "transmitPackets": "181",
+     *                     "receiveBytes": "12180",
+     *                     "transmitBytes": "12670",
+     *                     "receiveDrops": "0",
+     *                     "transmitDrops": "0",
+     *                     "receiveErrors": "0",
+     *                     "transmitErrors": "0",
+     *                     "receiveFrameError": "0",
+     *                     "receiveOverRunError": "0",
+     *                     "receiveCrcError": "0",
+     *                     "collisionCount": "0"
+     *                 },
+     *
+     *             ]
+     *         },
+     *         {
+     *             "node": {
+     *                  "id":"00:00:00:00:00:00:00:03",
+     *                  "type":"OF"
+     *             },
+     *             "portStatistic": [
+     *                  ..................
+     *                  .......................
+     *                  ..........................
+     *             ]
+     *         }
+     *     ]
+     * }
+     *
+     * Response body in XML:
+     * <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+     * <list>
+     *     <portStatistics>
+     *          <node>
+     *             <id>00:00:00:00:00:00:00:02</id>
+     *             <type>OF</type>
+     *          </node>
+     *          <portStatistic>
+     *             <nodeConnector>
+     *                <node>
+     *                   <id>00:00:00:00:00:00:00:02</id>
+     *                   <type>OF</type>
+     *                </node>
+     *                <id>3</id>
+     *                <type>OF</type>
+     *             </nodeConnector>
+     *             <receivePackets>181</receivePackets>
+     *             <transmitPackets>172</transmitPackets>
+     *             <receiveBytes>12670</receiveBytes>
+     *             <transmitBytes>12040</transmitBytes>
+     *             <receiveDrops>0</receiveDrops>
+     *             <transmitDrops>0</transmitDrops>
+     *             <receiveErrors>0</receiveErrors>
+     *             <transmitErrors>0</transmitErrors>
+     *             <receiveFrameError>0</receiveFrameError>
+     *             <receiveOverRunError>0</receiveOverRunError>
+     *             <receiveCrcError>0</receiveCrcError>
+     *             <collisionCount>0</collisionCount>
+     *         </portStatistic>
+     *         <portStatistic>
+     *             <nodeConnector>
+     *                <node>
+     *                   <id>00:00:00:00:00:00:00:02</id>
+     *                   <type>OF</type>
+     *                </node>
+     *                <id>2</id>
+     *                <type>OF</type>
+     *             </nodeConnector>
+     *             <receivePackets>173</receivePackets>
+     *             <transmitPackets>180</transmitPackets>
+     *             <receiveBytes>12110</receiveBytes>
+     *             <transmitBytes>12600</transmitBytes>
+     *             <receiveDrops>0</receiveDrops>
+     *             <transmitDrops>0</transmitDrops>
+     *             <receiveErrors>0</receiveErrors>
+     *             <transmitErrors>0</transmitErrors>
+     *             <receiveFrameError>0</receiveFrameError>
+     *             <receiveOverRunError>0</receiveOverRunError>
+     *             <receiveCrcError>0</receiveCrcError>
+     *             <collisionCount>0</collisionCount>
+     *         </portStatistic>
+     *     </portStatistics>
+     * </list>
+     * 
+ */ + + @Path("/{containerName}/port") + @GET + @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }) + @TypeHint(AllPortStatistics.class) + @StatusCodes({ + @ResponseCode(code = 200, condition = "Operation successful"), + @ResponseCode(code = 404, condition = "The containerName is not found"), + @ResponseCode(code = 503, condition = "One or more of Controller Services are unavailable") }) + public AllPortStatistics getPortStatistics( + @PathParam("containerName") String containerName, + @QueryParam("_q") String queryString) { + + if (!NorthboundUtils.isAuthorized( + getUserName(), containerName, Privilege.READ, this)) { + throw new UnauthorizedException( + "User is not authorized to perform this operation on container " + + containerName); + } + IStatisticsManager statisticsManager = getStatisticsService(containerName); + if (statisticsManager == null) { + throw new ServiceUnavailableException("Statistics " + + RestMessages.SERVICEUNAVAILABLE.toString()); + } + + ISwitchManager switchManager = (ISwitchManager) ServiceHelper + .getInstance(ISwitchManager.class, containerName, this); + if (switchManager == null) { + throw new ServiceUnavailableException("Switch manager " + + RestMessages.SERVICEUNAVAILABLE.toString()); + } + + List statistics = new ArrayList(); + for (Node node : switchManager.getNodes()) { + List stat = statisticsManager + .getNodeConnectorStatistics(node); + PortStatistics portStat = new PortStatistics(node, stat); + statistics.add(portStat); + } + + AllPortStatistics result = new AllPortStatistics(statistics); + if (queryString != null) { + queryContext.createQuery(queryString, AllPortStatistics.class) + .filter(result, PortStatistics.class); + } + return result; + } + + /** + * Returns a list of all the Port Statistics across all the NodeConnectors + * in a given Node. + * + * @param containerName + * Name of the Container. The Container name for the base + * controller is "default". + * @param nodeType + * Node Type as specifid in {@link org.opendaylight.controller.sal.core.Node} class + * @param Node + * Identifier (e.g. MAC address) + * @return Returns a list of all the Port Statistics across all the + * NodeConnectors in a given Node. + * + *
+     *
+     * Example:
+     *
+     * Request URL:
+     * http://localhost:8080/controller/nb/v2/statistics/default/port/node/OF/00:00:00:00:00:00:00:01
+     *
+     * Response body in JSON:
+     * {
+     *     "node": {
+     *         "id":"00:00:00:00:00:00:00:01",
+     *         "type":"OF"
+     *     },
+     *     "portStatistic": [
+     *         {
+     *             "nodeConnector": {
+     *                 "node":{
+     *                     "id":"00:00:00:00:00:00:00:01",
+     *                     "type":"OF"
+     *                 },
+     *                 "id":"3",
+     *                 "type":"OF"
+     *             },
+     *             "receivePackets": "171",
+     *             "transmitPackets": "2451",
+     *             "receiveBytes": "11970",
+     *             "transmitBytes": "235186",
+     *             "receiveDrops": "0",
+     *             "transmitDrops": "0",
+     *             "receiveErrors": "0",
+     *             "transmitErrors": "0",
+     *             "receiveFrameError": "0",
+     *             "receiveOverRunError": "0",
+     *             "receiveCrcError": "0",
+     *             "collisionCount": "0"
+     *         },
+     *         {
+     *             "nodeConnector": {
+     *                 "node":{
+     *                     "id":"00:00:00:00:00:00:00:01",
+     *                     "type":"OF"
+     *                 },
+     *                 "id":"2",
+     *                 "type":"OF"
+     *             },
+     *             "receivePackets": "179",
+     *             "transmitPackets": "2443",
+     *             "receiveBytes": "12530",
+     *             "transmitBytes": "234626",
+     *             "receiveDrops": "0",
+     *             "transmitDrops": "0",
+     *             "receiveErrors": "0",
+     *             "transmitErrors": "0",
+     *             "receiveFrameError": "0",
+     *             "receiveOverRunError": "0",
+     *             "receiveCrcError": "0",
+     *             "collisionCount": "0"
+     *         }
+     *     ]
+     * }
+     *
+     * Response body in XML:
+     * <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+     * <nodePortStatistics>
+     *     <node>
+     *         <id>00:00:00:00:00:00:00:01</id>
+     *         <type>OF</type>
+     *     </node>
+     *     <portStatistic>
+     *         <nodeConnector>
+     *             <node>
+     *                 <id>00:00:00:00:00:00:00:01</id>
+     *                 <type>OF</type>
+     *             </node>
+     *             <id>2</id>
+     *             <type>OF</type>
+     *         </nodeConnector>
+     *         <receivePackets>180</receivePackets>
+     *         <transmitPackets>2594</transmitPackets>
+     *         <receiveBytes>12600</receiveBytes>
+     *         <transmitBytes>249396</transmitBytes>
+     *         <receiveDrops>0</receiveDrops>
+     *         <transmitDrops>0</transmitDrops>
+     *         <receiveErrors>0</receiveErrors>
+     *         <transmitErrors>0</transmitErrors>
+     *         <receiveFrameError>0</receiveFrameError>
+     *         <receiveOverRunError>0</receiveOverRunError>
+     *         <receiveCrcError>0</receiveCrcError>
+     *         <collisionCount>0</collisionCount>
+     *     </portStatistic>
+     *     <portStatistic>
+     *         <nodeConnector>
+     *             <node>
+     *                 <id>00:00:00:00:00:00:00:01</id>
+     *                 <type>OF</type>
+     *             </node>
+     *             <id>5</id>
+     *             <type>OF</type>
+     *         </nodeConnector>
+     *         <receivePackets>2542</receivePackets>
+     *         <transmitPackets>2719</transmitPackets>
+     *         <receiveBytes>243012</receiveBytes>
+     *         <transmitBytes>255374</transmitBytes>
+     *         <receiveDrops>0</receiveDrops>
+     *         <transmitDrops>0</transmitDrops>
+     *         <receiveErrors>0</receiveErrors>
+     *         <transmitErrors>0</transmitErrors>
+     *         <receiveFrameError>0</receiveFrameError>
+     *         <receiveOverRunError>0</receiveOverRunError>
+     *         <receiveCrcError>0</receiveCrcError>
+     *         <collisionCount>0</collisionCount>
+     *     </portStatistic>
+     * </nodePortStatistics>
+     * 
+ */ + @Path("/{containerName}/port/node/{nodeType}/{nodeId}") + @GET + @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }) + @TypeHint(PortStatistics.class) + @StatusCodes({ + @ResponseCode(code = 200, condition = "Operation successful"), + @ResponseCode(code = 404, condition = "The containerName is not found"), + @ResponseCode(code = 503, condition = "One or more of Controller Services are unavailable") }) + public PortStatistics getPortStatistics( + @PathParam("containerName") String containerName, + @PathParam("nodeType") String nodeType, + @PathParam("nodeId") String nodeId) { + + if (!NorthboundUtils.isAuthorized( + getUserName(), containerName, Privilege.READ, this)) { + throw new UnauthorizedException( + "User is not authorized to perform this operation on container " + + containerName); + } + handleDefaultDisabled(containerName); + + IStatisticsManager statisticsManager = getStatisticsService(containerName); + if (statisticsManager == null) { + throw new ServiceUnavailableException("Statistics " + + RestMessages.SERVICEUNAVAILABLE.toString()); + } + + ISwitchManager switchManager = (ISwitchManager) ServiceHelper + .getInstance(ISwitchManager.class, containerName, this); + if (switchManager == null) { + throw new ServiceUnavailableException("Switch manager " + + RestMessages.SERVICEUNAVAILABLE.toString()); + } + + Node node = handleNodeAvailability(containerName, nodeType, nodeId); + return new PortStatistics(node, + statisticsManager.getNodeConnectorStatistics(node)); + } + + /** + * Returns a list of all the Table Statistics on all Nodes. + * + * @param containerName + * Name of the Container. The Container name for the base + * controller is "default". + * + * @return Returns a list of all the Table Statistics in a given Node. + * + *
+     *
+     * Example:
+     *
+     * Request URL:
+     * http://localhost:8080/controller/nb/v2/statistics/default/table
+     *
+     * Response body in JSON:
+     * {
+     *     "tableStatistics": [
+     *         {
+     *             "node": {
+     *                 "id":"00:00:00:00:00:00:00:02",
+     *                 "type":"OF"
+     *             },
+     *             "tableStatistic": [
+     *                 {
+     *                     "nodeTable": {
+     *                        "node":{
+     *                           "id":"00:00:00:00:00:00:00:02",
+     *                           "type":"OF"
+     *                         },
+     *                         "id":"0"
+     *                     },
+     *                     "activeCount": "11",
+     *                     "lookupCount": "816",
+     *                     "matchedCount": "220",
+     *                     "maximumEntries": "1000"
+     *                 },
+     *                 {
+     *                     ...another table
+     *                     .....
+     *                     ........
+     *                 }
+     *
+     *             ]
+     *         }
+     *     ]
+     * }
+     *
+     *  Response body in XML:
+     *  <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+     *  <list>
+     *  <tableStatistics>
+     *      <node>
+     *          <id>00:00:00:00:00:00:00:01</id>
+     *          <type>OF</type>
+     *      </node>
+     *      <tableStatistic>
+     *          <nodeTable>
+     *              <node>
+     *                  <id>00:00:00:00:00:00:00:01</id>
+     *                  <type>OF</type>
+     *              </node>
+     *              <id>0</id>
+     *          </nodeTable>
+     *          <activeCount>12</activeCount>
+     *          <lookupCount>10935</lookupCount>
+     *          <matchedCount>10084</matchedCount>
+     *          <maximumEntries>1000</maximumEntries>
+     *      </tableStatistic>
+     *      <tableStatistic>
+     *          <nodeTable>
+     *              <node>
+     *                  <id>00:00:00:00:00:00:00:01</id>
+     *                  <type>OF</type>
+     *              </node>
+     *              <id>1</id>
+     *          </nodeTable>
+     *          <activeCount>0</activeCount>
+     *          <lookupCount>0</lookupCount>
+     *          <matchedCount>0</matchedCount>
+     *          <maximumEntries>0</maximumEntries>
+     *      </tableStatistic>
+     *      <tableStatistic>
+     *          <nodeTable>
+     *              <node>
+     *                  <id>00:00:00:00:00:00:00:01</id>
+     *                  <type>OF</type>
+     *              </node>
+     *              <id>2</id>
+     *          </nodeTable>
+     *          <activeCount>0</activeCount>
+     *          <lookupCount>0</lookupCount>
+     *          <matchedCount>0</matchedCount>
+     *          <maximumEntries>0</maximumEntries>
+     *      </tableStatistic>
+     *  </tableStatistics>
+     *  <tableStatistics>
+     *  ...
+     *  ......
+     *  ........
+     *  </tableStatistics>
+     *  </list>
+     *
+     * 
+ */ + @Path("/{containerName}/table") + @GET + @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }) + @TypeHint(AllTableStatistics.class) + @StatusCodes({ + @ResponseCode(code = 200, condition = "Operation successful"), + @ResponseCode(code = 404, condition = "The containerName is not found"), + @ResponseCode(code = 503, condition = "One or more of Controller Services are unavailable") }) + public AllTableStatistics getTableStatistics( + @PathParam("containerName") String containerName, + @QueryParam("_q") String queryString) { + + if (!NorthboundUtils.isAuthorized(getUserName(), containerName, Privilege.READ, this)) { + throw new UnauthorizedException("User is not authorized to perform this operation on container " + + containerName); + } + handleDefaultDisabled(containerName); + + IStatisticsManager statisticsManager = getStatisticsService(containerName); + if (statisticsManager == null) { + throw new ServiceUnavailableException("Statistics manager" + + RestMessages.SERVICEUNAVAILABLE.toString()); + } + + ISwitchManager switchManager = (ISwitchManager) ServiceHelper + .getInstance(ISwitchManager.class, containerName, this); + if (switchManager == null) { + throw new ServiceUnavailableException("Switch manager " + + RestMessages.SERVICEUNAVAILABLE.toString()); + } + + List statistics = new ArrayList(); + for (Node node : switchManager.getNodes()) { + List stat = statisticsManager + .getNodeTableStatistics(node); + TableStatistics tableStat = new TableStatistics(node, stat); + statistics.add(tableStat); + } + AllTableStatistics allstats = new AllTableStatistics(statistics); + if (queryString != null) { + queryContext.createQuery(queryString, AllTableStatistics.class) + .filter(allstats, TableStatistics.class); + } + return allstats; + } + + /** + * Returns a list of all the Table Statistics on a specific node. + * + * @param containerName + * Name of the Container. The Container name for the base + * controller is "default". + * @param nodeType + * Node Type as specified in {@link org.opendaylight.controller.sal.core.Node} class (e.g. OF for Openflow) + * @param Node + * Identifier (e.g. MAC address) + * @return Returns a list of all the Table Statistics in a given Node. + * + *
+     *
+     * Example:
+     *
+     * Request URL:
+     * http://localhost:8080/controller/nb/v2/statistics/default/table/node/OF/00:00:00:00:00:00:00:01
+     *
+     * Response body in JSON:
+     * {
+     *     "node": {
+     *         "id":"00:00:00:00:00:00:00:01",
+     *         "type":"OF"
+     *     },
+     *     "tableStatistic": [
+     *         {
+     *             "nodeTable": {
+     *                 "node":{
+     *                     "id":"00:00:00:00:00:00:00:01",
+     *                     "type":"OF"
+     *                 },
+     *                 "id":"0"
+     *             },
+     *             "activeCount": "12",
+     *             "lookupCount": "11382",
+     *             "matchedCount": "10524",
+     *             "maximumEntries": "1000"
+     *         },
+     *         {
+     *             "nodeTable": {
+     *                 "node":{
+     *                     "id":"00:00:00:00:00:00:00:01",
+     *                     "type":"OF"
+     *                 },
+     *                 "id":"1"
+     *             },
+     *             "activeCount": "0",
+     *             "lookupCount": "0",
+     *             "matchedCount": "0",
+     *             "maximumEntries": "0"
+     *         }
+     *    ]
+     * }
+     *
+     * Response body in XML:
+     * <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+     * <nodeTableStatistics>
+     *     <node>
+     *          <id>00:00:00:00:00:00:00:01</id>
+     *          <type>OF</type>
+     *     </node>
+     *     <tableStatistic>
+     *         <nodeTable>
+     *             <node>
+     *                 <id>00:00:00:00:00:00:00:01</id>
+     *                 <type>OF</type>
+     *             </node>
+     *             <id>0</id>
+     *         </nodeTable>
+     *         <activeCount>12</activeCount>
+     *         <lookupCount>10935</lookupCount>
+     *         <matchedCount>10084</matchedCount>
+     *         <maximumEntries>1000</maximumEntries>
+     *     </tableStatistic>
+     *     <tableStatistic>
+     *         <nodeTable>
+     *             <node>
+     *                 <id>00:00:00:00:00:00:00:01</id>
+     *                 <type>OF</type>
+     *             </node>
+     *             <id>1</id>
+     *         </nodeTable>
+     *         <activeCount>0</activeCount>
+     *         <lookupCount>0</lookupCount>
+     *         <matchedCount>0</matchedCount>
+     *         <maximumEntries>0</maximumEntries>
+     *     </tableStatistic>
+     *     <tableStatistic>
+     *         <nodeTable>
+     *             <node>
+     *                 <id>00:00:00:00:00:00:00:01</id>
+     *                 <type>OF</type>
+     *             </node>
+     *             <id>2</id>
+     *         </nodeTable>
+     *         <activeCount>0</activeCount>
+     *         <lookupCount>0</lookupCount>
+     *         <matchedCount>0</matchedCount>
+     *         <maximumEntries>0</maximumEntries>
+     *     </tableStatistic>
+     * </nodeTableStatistics>
+     *
+     * 
+ */ + @Path("/{containerName}/table/node/{nodeType}/{nodeId}") + @GET + @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }) + @TypeHint(TableStatistics.class) + @StatusCodes({ + @ResponseCode(code = 200, condition = "Operation successful"), + @ResponseCode(code = 404, condition = "The containerName is not found"), + @ResponseCode(code = 503, condition = "One or more of Controller Services are unavailable") }) + public TableStatistics getTableStatistics( + @PathParam("containerName") String containerName, + @PathParam("nodeType") String nodeType, + @PathParam("nodeId") String nodeId) { + + if (!NorthboundUtils.isAuthorized( + getUserName(), containerName, Privilege.READ, this)) { + throw new UnauthorizedException( + "User is not authorized to perform this operation on container " + + containerName); + } + handleDefaultDisabled(containerName); + + IStatisticsManager statisticsManager = getStatisticsService(containerName); + if (statisticsManager == null) { + throw new ServiceUnavailableException("Statistics " + + RestMessages.SERVICEUNAVAILABLE.toString()); + } + + ISwitchManager switchManager = (ISwitchManager) ServiceHelper + .getInstance(ISwitchManager.class, containerName, this); + if (switchManager == null) { + throw new ServiceUnavailableException("Switch manager " + + RestMessages.SERVICEUNAVAILABLE.toString()); + } + + Node node = handleNodeAvailability(containerName, nodeType, nodeId); + return new TableStatistics(node, + statisticsManager.getNodeTableStatistics(node)); + } + + private void handleDefaultDisabled(String containerName) { + IContainerManager containerManager = (IContainerManager) ServiceHelper + .getGlobalInstance(IContainerManager.class, this); + if (containerManager == null) { + throw new InternalServerErrorException( + RestMessages.INTERNALERROR.toString()); + } + if (containerName.equals(GlobalConstants.DEFAULT.toString()) + && containerManager.hasNonDefaultContainer()) { + throw new ResourceConflictException( + RestMessages.DEFAULTDISABLED.toString()); + } + } + + private Node handleNodeAvailability(String containerName, String nodeType, + String nodeId) { + + Node node = Node.fromString(nodeType, nodeId); + if (node == null) { + throw new ResourceNotFoundException(nodeId + " : " + + RestMessages.NONODE.toString()); + } + + ISwitchManager sm = (ISwitchManager) ServiceHelper.getInstance( + ISwitchManager.class, containerName, this); + + if (sm == null) { + throw new ServiceUnavailableException("Switch Manager " + + RestMessages.SERVICEUNAVAILABLE.toString()); + } + + if (!sm.getNodes().contains(node)) { + throw new ResourceNotFoundException(node.toString() + " : " + + RestMessages.NONODE.toString()); + } + return node; + } + +}