/*
* 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.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.SecurityContext;
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.*;
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
* plugins such as Openflow.
*
*
*
* Authentication scheme : HTTP Basic
* Authentication realm : opendaylight
* Transport : HTTP and HTTPS
*
* HTTPS Authentication is disabled by default. Administrator can enable it in
* tomcat-server.xml after adding a proper keystore / SSL certificate from a
* trusted authority.
* More info :
* http://tomcat.apache.org/tomcat-7.0-doc/ssl-howto.html#Configuration
*
*/
@Path("/")
public class StatisticsNorthbound {
private String username;
@Context
public void setSecurityContext(SecurityContext context) {
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
*/
@Path("/{containerName}/flowstats")
@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) {
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);
}
return new AllFlowStatistics(statistics);
}
/**
* 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 by Node class
* @param nodeId
* Node Identifier
* @return List of Flow Statistics for a given Node.
*/
@Path("/{containerName}/flowstats/{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.
*/
@Path("/{containerName}/portstats")
@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) {
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);
}
return new AllPortStatistics(statistics);
}
/**
* 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 by Node class
* @param Node
* Identifier
* @return Returns a list of all the Port Statistics across all the
* NodeConnectors in a given Node.
*/
@Path("/{containerName}/portstats/{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.
*/
@Path("/{containerName}/tablestats")
@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 AllTableStatistics getTableStatistics(
@PathParam("containerName") String containerName) {
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());
}
List statistics = new ArrayList();
for (Node node : switchManager.getNodes()) {
List stat = statisticsManager
.getNodeTableStatistics(node);
TableStatistics tableStat = new TableStatistics(node, stat);
statistics.add(tableStat);
}
return new AllTableStatistics(statistics);
}
/**
* 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".
* @param nodeType
* Node Type as specifid by Node class
* @param Node
* Identifier
* @return Returns a list of all the Table Statistics in a given Node.
*/
@Path("/{containerName}/tablestats/{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;
}
}