8ca29779d44cb074891d29e292ed2b0bd192f086
[affinity.git] / analytics / northbound / src / main / java / org / opendaylight / affinity / analytics / northbound / AnalyticsNorthbound.java
1 /*
2  * Copyright (c) 2013 Plexxi, 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.affinity.analytics.northbound;
10
11 import java.net.InetAddress;
12 import java.net.UnknownHostException;
13 import java.util.List;
14 import java.util.Set;
15
16 import javax.ws.rs.GET;
17 import javax.ws.rs.Path;
18 import javax.ws.rs.PathParam;
19 import javax.ws.rs.Produces;
20 import javax.ws.rs.core.Context;
21 import javax.ws.rs.core.MediaType;
22 import javax.ws.rs.core.SecurityContext;
23
24 import org.codehaus.enunciate.jaxrs.ResponseCode;
25 import org.codehaus.enunciate.jaxrs.StatusCodes;
26 import org.codehaus.enunciate.jaxrs.TypeHint;
27
28 import org.opendaylight.affinity.affinity.AffinityLink;
29 import org.opendaylight.affinity.affinity.IAffinityManager;
30 import org.opendaylight.affinity.analytics.IAnalyticsManager;
31 import org.opendaylight.controller.containermanager.IContainerManager;
32 import org.opendaylight.controller.hosttracker.IfIptoHost;
33 import org.opendaylight.controller.hosttracker.hostAware.HostNodeConnector;
34 import org.opendaylight.controller.northbound.commons.RestMessages;
35 import org.opendaylight.controller.northbound.commons.exception.*;
36 import org.opendaylight.controller.northbound.commons.utils.NorthboundUtils;
37 import org.opendaylight.controller.sal.authorization.Privilege;
38 import org.opendaylight.controller.sal.core.Host;
39 import org.opendaylight.controller.sal.utils.GlobalConstants;
40 import org.opendaylight.controller.sal.utils.ServiceHelper;
41 import org.opendaylight.controller.switchmanager.ISwitchManager;
42
43 /**
44  * Northbound APIs that returns various Analytics exposed by the Southbound
45  * plugins such as Openflow.
46  *
47  * <br>
48  * <br>
49  * Authentication scheme : <b>HTTP Basic</b><br>
50  * Authentication realm : <b>opendaylight</b><br>
51  * Transport : <b>HTTP and HTTPS</b><br>
52  * <br>
53  * HTTPS Authentication is disabled by default. Administrator can enable it in
54  * tomcat-server.xml after adding a proper keystore / SSL certificate from a
55  * trusted authority.<br>
56  * More info :
57  * http://tomcat.apache.org/tomcat-7.0-doc/ssl-howto.html#Configuration
58  *
59  */
60 @Path("/")
61 public class AnalyticsNorthbound {
62
63     private String username;
64
65     @Context
66     public void setSecurityContext(SecurityContext context) {
67         username = context.getUserPrincipal().getName();
68     }
69
70     protected String getUserName() {
71         return username;
72     }
73
74     private IAnalyticsManager getAnalyticsService(String containerName) {
75         IContainerManager containerManager = (IContainerManager) ServiceHelper.getGlobalInstance(IContainerManager.class, this);
76         if (containerManager == null) {
77             throw new ServiceUnavailableException("Container " + RestMessages.SERVICEUNAVAILABLE.toString());
78         }
79
80         boolean found = false;
81         List<String> containerNames = containerManager.getContainerNames();
82         for (String cName : containerNames) {
83             if (cName.trim().equalsIgnoreCase(containerName.trim())) {
84                 found = true;
85             }
86         }
87
88         if (found == false) {
89             throw new ResourceNotFoundException(containerName + " " + RestMessages.NOCONTAINER.toString());
90         }
91
92         IAnalyticsManager analyticsManager = (IAnalyticsManager) ServiceHelper.getInstance(IAnalyticsManager.class, containerName, this);
93         if (analyticsManager == null) {
94             throw new ServiceUnavailableException("Analytics " + RestMessages.SERVICEUNAVAILABLE.toString());
95         }
96         return analyticsManager;
97     }
98
99     /**
100      * Returns Host Statistics for a (src, dst) pair
101      *
102      * @param containerName
103      *            Name of the Container. The Container name for the base
104      *            controller is "default".
105      * @param dataLayerAddr
106      *            DataLayerAddress for the host
107      * @param networkAddr
108      *            NetworkAddress for the host
109      * @return Host Statistics for a given Node.
110      */
111     @Path("/{containerName}/hoststats/{srcNetworkAddr}/{dstNetworkAddr}")
112     @GET
113     @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
114     @TypeHint(HostStatistics.class)
115     @StatusCodes({
116         @ResponseCode(code = 200, condition = "Operation successful"),
117         @ResponseCode(code = 404, condition = "The containerName is not found"),
118         @ResponseCode(code = 503, condition = "One or more of Controller Services are unavailable") })
119     public HostStatistics getHostStatistics(
120         @PathParam("containerName") String containerName,
121         @PathParam("srcNetworkAddr") String srcNetworkAddr,
122         @PathParam("dstNetworkAddr") String dstNetworkAddr) {
123         if (!NorthboundUtils.isAuthorized(getUserName(), containerName, Privilege.READ, this)) {
124             throw new UnauthorizedException("User is not authorized to perform this operation on container " + containerName);
125         }
126         handleDefaultDisabled(containerName);
127
128         IAnalyticsManager analyticsManager = getAnalyticsService(containerName);
129         if (analyticsManager == null) {
130             throw new ServiceUnavailableException("Analytics " + RestMessages.SERVICEUNAVAILABLE.toString());
131         }
132
133         Host srcHost = handleHostAvailability(containerName, srcNetworkAddr);
134         Host dstHost = handleHostAvailability(containerName, dstNetworkAddr);
135         long byteCount = analyticsManager.getByteCountBetweenHosts(srcHost, dstHost);
136         double bitRate = analyticsManager.getBitRateBetweenHosts(srcHost, dstHost);
137
138         return new HostStatistics(srcHost, dstHost, byteCount, bitRate);
139     }
140
141     /**
142      * Returns the affinity link statistics for a given link.
143      *
144      * @param containerName
145      *            Name of the Container. The Container name for the base
146      *            controller is "default".
147      * @param linkName
148      *            AffinityLink name.
149      * @return List of Affinity Link Statistics for a given link.
150      */
151     @Path("/{containerName}/affinitylinkstats/{linkName}")
152     @GET
153     @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
154     @TypeHint(HostStatistics.class)
155     @StatusCodes({
156         @ResponseCode(code = 200, condition = "Operation successful"),
157         @ResponseCode(code = 404, condition = "The containerName is not found"),
158         @ResponseCode(code = 503, condition = "One or more of Controller Services are unavailable") })
159     public AffinityLinkStatistics getAffinityLinkStatistics(
160         @PathParam("containerName") String containerName,
161         @PathParam("linkName") String affinityLinkName) {
162         if (!NorthboundUtils.isAuthorized(getUserName(), containerName, Privilege.READ, this)) {
163             throw new UnauthorizedException("User is not authorized to perform this operation on container " + containerName);
164         }
165         handleDefaultDisabled(containerName);
166
167         IAnalyticsManager analyticsManager = getAnalyticsService(containerName);
168         if (analyticsManager == null) {
169             throw new ServiceUnavailableException("Analytics " + RestMessages.SERVICEUNAVAILABLE.toString());
170         }
171
172         AffinityLink al = handleAffinityLinkAvailability(containerName, affinityLinkName);
173         long byteCount = analyticsManager.getByteCountOnAffinityLink(al);
174         double bitRate = analyticsManager.getBitRateOnAffinityLink(al);
175
176         return new AffinityLinkStatistics(al, byteCount, bitRate);
177     }
178
179     private void handleDefaultDisabled(String containerName) {
180         IContainerManager containerManager = (IContainerManager) ServiceHelper.getGlobalInstance(IContainerManager.class, this);
181         if (containerManager == null) {
182             throw new InternalServerErrorException(RestMessages.INTERNALERROR.toString());
183         }
184
185         if (containerName.equals(GlobalConstants.DEFAULT.toString()) && containerManager.hasNonDefaultContainer()) {
186             throw new ResourceConflictException(RestMessages.DEFAULTDISABLED.toString());
187         }
188     }
189
190     private AffinityLink handleAffinityLinkAvailability(String containerName, String linkName) {
191
192         IAffinityManager affinityManager = (IAffinityManager) ServiceHelper.getInstance(IAffinityManager.class, containerName, this);
193         if (affinityManager == null) {
194             throw new ServiceUnavailableException("Affinity manager " + RestMessages.SERVICEUNAVAILABLE.toString());
195         }
196
197         AffinityLink al = affinityManager.getAffinityLink(linkName);
198         if (al == null) {
199             throw new ResourceNotFoundException(linkName + " : AffinityLink does not exist");
200         }
201
202         return al;
203     }
204
205
206     private Host handleHostAvailability(String containerName, String networkAddr) {
207
208         IfIptoHost hostTracker = (IfIptoHost) ServiceHelper.getInstance(IfIptoHost.class, containerName, this);
209         if (hostTracker == null) {
210             throw new ServiceUnavailableException("Host tracker " + RestMessages.SERVICEUNAVAILABLE.toString());
211         }
212
213         Set<HostNodeConnector> allHosts = hostTracker.getAllHosts();
214         if (allHosts == null) {
215             throw new ResourceNotFoundException(networkAddr + " : " + RestMessages.NOHOST.toString());
216         }
217
218         Host host = null;
219         try {
220             InetAddress networkAddress = InetAddress.getByName(networkAddr);
221             for (Host h : allHosts) {
222                 if (h.getNetworkAddress().equals(networkAddress)) {
223                     host = h;
224                     break;
225                 }
226             }
227         } catch (UnknownHostException e) {
228         }
229
230         if (host == null) {
231             throw new ResourceNotFoundException(networkAddr + " : " + RestMessages.NOHOST.toString());
232         }
233
234         return host;
235     }
236 }