OpenDaylight Controller functional modules.
[controller.git] / opendaylight / northbound / statistics / src / main / java / org / opendaylight / controller / statistics / northbound / StatisticsNorthbound.java
1 /*
2  * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6  * and is available at http://www.eclipse.org/legal/epl-v10.html
7  */
8
9 package org.opendaylight.controller.statistics.northbound;
10
11 import java.util.ArrayList;
12 import java.util.List;
13
14 import javax.ws.rs.GET;
15 import javax.ws.rs.Path;
16 import javax.ws.rs.PathParam;
17 import javax.ws.rs.Produces;
18 import javax.ws.rs.core.MediaType;
19
20 import org.codehaus.enunciate.jaxrs.ResponseCode;
21 import org.codehaus.enunciate.jaxrs.StatusCodes;
22 import org.codehaus.enunciate.jaxrs.TypeHint;
23 import org.opendaylight.controller.containermanager.IContainerManager;
24
25 import org.opendaylight.controller.northbound.commons.RestMessages;
26 import org.opendaylight.controller.northbound.commons.exception.InternalServerErrorException;
27 import org.opendaylight.controller.northbound.commons.exception.ResourceConflictException;
28 import org.opendaylight.controller.northbound.commons.exception.ResourceNotFoundException;
29 import org.opendaylight.controller.northbound.commons.exception.ServiceUnavailableException;
30 import org.opendaylight.controller.sal.core.Node;
31 import org.opendaylight.controller.sal.reader.FlowOnNode;
32 import org.opendaylight.controller.sal.reader.NodeConnectorStatistics;
33 import org.opendaylight.controller.sal.utils.GlobalConstants;
34 import org.opendaylight.controller.sal.utils.ServiceHelper;
35 import org.opendaylight.controller.statisticsmanager.IStatisticsManager;
36 import org.opendaylight.controller.switchmanager.ISwitchManager;
37
38 /**
39  * Northbound APIs that returns various Statistics exposed by the Southbound plugins such as Openflow.
40  * 
41  * <br><br>
42  * Authentication scheme : <b>HTTP Basic</b><br>
43  * Authentication realm : <b>opendaylight</b><br>
44  * Transport : <b>HTTP and HTTPS</b><br>
45  * <br>
46  * HTTPS Authentication is disabled by default. Administrator can enable it in tomcat-server.xml after adding 
47  * a proper keystore / SSL certificate from a trusted authority.<br>
48  * More info : http://tomcat.apache.org/tomcat-7.0-doc/ssl-howto.html#Configuration
49  *
50  */
51 @Path("/")
52 public class StatisticsNorthbound {
53
54     private IStatisticsManager getStatisticsService(String containerName) {
55         IContainerManager containerManager = (IContainerManager) ServiceHelper
56                 .getGlobalInstance(IContainerManager.class, this);
57         if (containerManager == null) {
58             throw new ServiceUnavailableException("Container "
59                     + RestMessages.SERVICEUNAVAILABLE.toString());
60         }
61
62         boolean found = false;
63         List<String> containerNames = containerManager.getContainerNames();
64         for (String cName : containerNames) {
65             if (cName.trim().equalsIgnoreCase(containerName.trim())) {
66                 found = true;
67             }
68         }
69
70         if (found == false) {
71             throw new ResourceNotFoundException(containerName + " "
72                     + RestMessages.NOCONTAINER.toString());
73         }
74
75         IStatisticsManager statsManager = (IStatisticsManager) ServiceHelper
76                 .getInstance(IStatisticsManager.class, containerName, this);
77
78         if (statsManager == null) {
79             throw new ServiceUnavailableException("Statistics "
80                     + RestMessages.SERVICEUNAVAILABLE.toString());
81         }
82
83         return statsManager;
84     }
85
86     /**
87      * Returns a list of all Flow Statistics from all the Nodes.
88      *
89      * @param containerName Name of the Container. The Container name for the base controller is "default". 
90      * @return List of FlowStatistics from all the Nodes
91      */
92
93     @Path("/{containerName}/flowstats")
94     @GET
95     @Produces( { MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
96     @TypeHint(AllFlowStatistics.class)
97     @StatusCodes( {
98             @ResponseCode(code = 200, condition = "Operation successful"),
99             @ResponseCode(code = 404, condition = "The containerName is not found"),
100             @ResponseCode(code = 503, condition = "One or more of Controller Services are unavailable") })
101     public AllFlowStatistics getFlowStatistics(
102             @PathParam("containerName") String containerName) {
103         IStatisticsManager statisticsManager = getStatisticsService(containerName);
104         if (statisticsManager == null) {
105             throw new ServiceUnavailableException("Statistics "
106                     + RestMessages.SERVICEUNAVAILABLE.toString());
107         }
108
109         ISwitchManager switchManager = (ISwitchManager) ServiceHelper
110                 .getInstance(ISwitchManager.class, containerName, this);
111         if (switchManager == null) {
112             throw new ServiceUnavailableException("Switch manager "
113                     + RestMessages.SERVICEUNAVAILABLE.toString());
114         }
115
116         List<FlowStatistics> statistics = new ArrayList<FlowStatistics>();
117         for (Node node : switchManager.getNodes()) {
118             List<FlowOnNode> flowStats = new ArrayList<FlowOnNode>();
119
120             List<FlowOnNode> flows = statisticsManager.getFlows(node);
121             for (FlowOnNode flowOnSwitch : flows) {
122                 flowStats.add(flowOnSwitch);
123             }
124             FlowStatistics stat = new FlowStatistics(node,
125                                                      flowStats);
126             statistics.add(stat);
127         }
128         return new AllFlowStatistics(statistics);
129     }
130
131     /**
132      * Returns a list of Flow Statistics for a given Node.
133      *
134      * @param containerName Name of the Container. The Container name
135      * for the base controller is "default". 
136      * @param nodeType Node Type as specifid by Node class
137      * @param nodeId Node Identifier
138      * @return List of Flow Statistics for a given Node.
139      */
140     @Path("/{containerName}/flowstats/{nodeType}/{nodeId}")
141     @GET
142     @Produces( { MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
143     @TypeHint(FlowStatistics.class)
144     @StatusCodes( {
145             @ResponseCode(code = 200, condition = "Operation successful"),
146             @ResponseCode(code = 404, condition = "The containerName is not found"),
147             @ResponseCode(code = 503, condition = "One or more of Controller Services are unavailable") })
148     public FlowStatistics getFlowStatistics(
149             @PathParam("containerName") String containerName,
150             @PathParam("nodeType") String nodeType,
151             @PathParam("nodeId") String nodeId) {
152
153         handleDefaultDisabled(containerName);
154
155         IStatisticsManager statisticsManager = getStatisticsService(containerName);
156         if (statisticsManager == null) {
157             throw new ServiceUnavailableException("Statistics "
158                     + RestMessages.SERVICEUNAVAILABLE.toString());
159         }
160
161         ISwitchManager switchManager = (ISwitchManager) ServiceHelper
162                 .getInstance(ISwitchManager.class, containerName, this);
163         if (switchManager == null) {
164             throw new ServiceUnavailableException("Switch manager "
165                     + RestMessages.SERVICEUNAVAILABLE.toString());
166         }
167
168         Node node = handleNodeAvailability(containerName, nodeType, nodeId);
169         return new FlowStatistics(node, statisticsManager.getFlows(node));
170     }
171
172     /**
173      * Returns a list of all the Port Statistics across all the NodeConnectors on all the Nodes.
174      *
175      * @param containerName Name of the Container. The Container name for the base controller is "default". 
176      * @return List of all the Port Statistics across all the NodeConnectors on all the Nodes.
177      */
178
179     @Path("/{containerName}/portstats")
180     @GET
181     @Produces( { MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
182     @TypeHint(AllPortStatistics.class)
183     @StatusCodes( {
184             @ResponseCode(code = 200, condition = "Operation successful"),
185             @ResponseCode(code = 404, condition = "The containerName is not found"),
186             @ResponseCode(code = 503, condition = "One or more of Controller Services are unavailable") })
187     public AllPortStatistics getPortStatistics(
188             @PathParam("containerName") String containerName) {
189
190         IStatisticsManager statisticsManager = getStatisticsService(containerName);
191         if (statisticsManager == null) {
192             throw new ServiceUnavailableException("Statistics "
193                     + RestMessages.SERVICEUNAVAILABLE.toString());
194         }
195
196         ISwitchManager switchManager = (ISwitchManager) ServiceHelper
197                 .getInstance(ISwitchManager.class, containerName, this);
198         if (switchManager == null) {
199             throw new ServiceUnavailableException("Switch manager "
200                     + RestMessages.SERVICEUNAVAILABLE.toString());
201         }
202
203         List<PortStatistics> statistics = new ArrayList<PortStatistics>();
204         for (Node node : switchManager.getNodes()) {
205             List<NodeConnectorStatistics> stat = statisticsManager
206                     .getNodeConnectorStatistics(node);
207             PortStatistics portStat = new PortStatistics(node, stat);
208             statistics.add(portStat);
209         }
210         return new AllPortStatistics(statistics);
211     }
212
213     /**
214      * Returns a list of all the Port Statistics across all the NodeConnectors in a given Node.
215      *
216      * @param containerName Name of the Container. The Container name
217      * for the base controller is "default". 
218      * @param nodeType Node Type as specifid by Node class
219      * @param Node Identifier
220      * @return Returns a list of all the Port Statistics across all the NodeConnectors in a given Node.
221      */
222     @Path("/{containerName}/portstats/{nodeType}/{nodeId}")
223     @GET
224     @Produces( { MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
225     @TypeHint(PortStatistics.class)
226     @StatusCodes( {
227             @ResponseCode(code = 200, condition = "Operation successful"),
228             @ResponseCode(code = 404, condition = "The containerName is not found"),
229             @ResponseCode(code = 503, condition = "One or more of Controller Services are unavailable") })
230     public PortStatistics getPortStatistics(
231             @PathParam("containerName") String containerName,
232             @PathParam("nodeType") String nodeType,
233             @PathParam("nodeId") String nodeId) {
234
235         handleDefaultDisabled(containerName);
236
237         IStatisticsManager statisticsManager = getStatisticsService(containerName);
238         if (statisticsManager == null) {
239             throw new ServiceUnavailableException("Statistics "
240                     + RestMessages.SERVICEUNAVAILABLE.toString());
241         }
242
243         ISwitchManager switchManager = (ISwitchManager) ServiceHelper
244                 .getInstance(ISwitchManager.class, containerName, this);
245         if (switchManager == null) {
246             throw new ServiceUnavailableException("Switch manager "
247                     + RestMessages.SERVICEUNAVAILABLE.toString());
248         }
249
250         Node node = handleNodeAvailability(containerName,
251                                            nodeType, nodeId);
252         return new PortStatistics(node, statisticsManager
253                 .getNodeConnectorStatistics(node));
254     }
255
256     private void handleDefaultDisabled(String containerName) {
257         IContainerManager containerManager = (IContainerManager) ServiceHelper
258                 .getGlobalInstance(IContainerManager.class, this);
259         if (containerManager == null) {
260             throw new InternalServerErrorException(RestMessages.INTERNALERROR
261                     .toString());
262         }
263         if (containerName.equals(GlobalConstants.DEFAULT.toString())
264                 && containerManager.hasNonDefaultContainer()) {
265             throw new ResourceConflictException(RestMessages.DEFAULTDISABLED
266                     .toString());
267         }
268     }
269
270     private Node handleNodeAvailability(String containerName, String nodeType,
271                                         String nodeId) {
272
273         Node node = Node.fromString(nodeType, nodeId);
274         if (node == null) {
275             throw new ResourceNotFoundException(nodeId + " : "
276                     + RestMessages.NONODE.toString());
277         }
278
279         ISwitchManager sm = (ISwitchManager) ServiceHelper.getInstance(
280                 ISwitchManager.class, containerName, this);
281
282         if (sm == null) {
283             throw new ServiceUnavailableException("Switch Manager "
284                     + RestMessages.SERVICEUNAVAILABLE.toString());
285         }
286
287         if (!sm.getNodes().contains(node)) {
288             throw new ResourceNotFoundException(node.toString() + " : "
289                     + RestMessages.NONODE.toString());
290         }
291         return node;
292     }
293
294 }