Merge "Fixed concurrency bug in DOMTransactionChainTest"
[controller.git] / opendaylight / northbound / staticrouting / src / main / java / org / opendaylight / controller / forwarding / staticrouting / northbound / StaticRoutingNorthbound.java
1
2 /*
3  * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
4  *
5  * This program and the accompanying materials are made available under the
6  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
7  * and is available at http://www.eclipse.org/legal/epl-v10.html
8  */
9
10 package org.opendaylight.controller.forwarding.staticrouting.northbound;
11
12 import java.util.ArrayList;
13 import java.util.List;
14
15 import javax.ws.rs.Consumes;
16 import javax.ws.rs.DELETE;
17 import javax.ws.rs.GET;
18 import javax.ws.rs.PUT;
19 import javax.ws.rs.Path;
20 import javax.ws.rs.PathParam;
21 import javax.ws.rs.Produces;
22 import javax.ws.rs.core.Context;
23 import javax.ws.rs.core.MediaType;
24 import javax.ws.rs.core.Response;
25 import javax.ws.rs.core.SecurityContext;
26 import javax.ws.rs.core.UriInfo;
27
28 import org.codehaus.enunciate.jaxrs.ResponseCode;
29 import org.codehaus.enunciate.jaxrs.StatusCodes;
30 import org.codehaus.enunciate.jaxrs.TypeHint;
31 import org.opendaylight.controller.containermanager.IContainerManager;
32 import org.opendaylight.controller.forwarding.staticrouting.IForwardingStaticRouting;
33 import org.opendaylight.controller.forwarding.staticrouting.StaticRouteConfig;
34 import org.opendaylight.controller.northbound.commons.RestMessages;
35 import org.opendaylight.controller.northbound.commons.exception.InternalServerErrorException;
36 import org.opendaylight.controller.northbound.commons.exception.NotAcceptableException;
37 import org.opendaylight.controller.northbound.commons.exception.ResourceConflictException;
38 import org.opendaylight.controller.northbound.commons.exception.ResourceNotFoundException;
39 import org.opendaylight.controller.northbound.commons.exception.UnauthorizedException;
40 import org.opendaylight.controller.northbound.commons.utils.NorthboundUtils;
41 import org.opendaylight.controller.sal.authorization.Privilege;
42 import org.opendaylight.controller.sal.utils.GlobalConstants;
43 import org.opendaylight.controller.sal.utils.ServiceHelper;
44 import org.opendaylight.controller.sal.utils.Status;
45
46 /**
47  * <p>Static Routing Northbound API allows for the management of the static
48  * routes.</p>
49  * </br>
50  * An example request/response for retrieving the static routes may look like this: </br>
51  * <pre>
52  * GET http://localhost:8080/controller/nb/v2/staticroute/default HTTP/1.1
53  * Accept: application/json
54  *
55  * HTTP/1.1 200 OK
56  * Content-Type: application/json
57  *
58  * { "staticRoute":[
59  *       "name":"route-1",
60  *       "prefix":"10.10.1.0/24",
61  *       "nextHop":"1.1.1.1"
62  *   ]
63  * }
64  *
65  * </pre>
66  *
67  * <br><br>
68  * Authentication scheme : <b>HTTP Basic</b><br>
69  * Authentication realm : <b>opendaylight</b><br>
70  * Transport : <b>HTTP and HTTPS</b><br>
71  * <br>
72  */
73 @Path("/")
74 public class StaticRoutingNorthbound {
75
76     private String username;
77
78     @Context
79     public void setSecurityContext(SecurityContext context) {
80         if (context != null && context.getUserPrincipal() != null) username = context.getUserPrincipal().getName();
81     }
82     protected String getUserName() {
83         return username;
84     }
85
86
87
88     private List<StaticRoute> getStaticRoutesInternal(String containerName) {
89
90         IForwardingStaticRouting staticRouting = (IForwardingStaticRouting) ServiceHelper
91                 .getInstance(IForwardingStaticRouting.class, containerName,
92                         this);
93
94         if (staticRouting == null) {
95             throw new ResourceNotFoundException(RestMessages.NOCONTAINER
96                     .toString());
97         }
98
99         List<StaticRoute> routes = new ArrayList<StaticRoute>();
100
101         for (StaticRouteConfig conf : staticRouting.getStaticRouteConfigs()
102                 .values()) {
103             StaticRoute route = new StaticRoute(conf.getName(), conf
104                     .getStaticRoute(), conf.getNextHop());
105             routes.add(route);
106         }
107         return routes;
108     }
109
110     /**
111      * Get a list of static routes present on the given container.
112      *
113      * @param containerName Name of the Container. The Container name for the base controller is "default".
114      * @return List of configured static routes on the given container
115      *
116      * <pre>
117      * Example:
118      *
119      * Request URL:
120      * http://localhost:8080/controller/nb/v2/staticroute/default/routes
121      *
122      * Response body in XML:
123      *  &lt;list&gt;
124      *   &lt;staticRoute&gt;
125      *     &lt;name&gt;route-1&lt;/name&gt;
126      *     &lt;prefix&gt;10.10.1.0/24&lt;/prefix&gt;
127      *     &lt;nextHop&gt;1.1.1.1&lt;/nextHop&gt;
128      *   &lt;/staticRoute&gt;
129      *  &lt;/list&gt;
130      *
131      * Response body in JSON:
132      * {
133      *    "staticRoute": [
134      *      {
135      *       "name": "route-1",
136      *       "prefix": "10.10.1.0/24",
137      *       "nextHop": "1.1.1.1"
138      *      }
139      *    ]
140      * }
141      * </pre>
142      */
143     @Path("/{containerName}/routes")
144     @GET
145     @Produces( { MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
146     @TypeHint(StaticRoutes.class)
147     @StatusCodes( {
148             @ResponseCode(code = 200, condition = "Operation successful"),
149             @ResponseCode(code = 404, condition = "The containerName passed was not found") })
150     public StaticRoutes getStaticRoutes(
151             @PathParam("containerName") String containerName) {
152
153         if(!NorthboundUtils.isAuthorized(getUserName(), containerName,
154                 Privilege.WRITE, this)){
155             throw new
156                 UnauthorizedException("User is not authorized to perform this operation on container "
157                             + containerName);
158         }
159         return new StaticRoutes(getStaticRoutesInternal(containerName));
160     }
161
162     /**
163      * Returns the static route for the provided configuration name on a given container
164      *
165      * @param containerName Name of the Container. The Container name for the base controller is "default".
166      * @param route Name of the Static Route configuration
167      * @return Static route configured with the supplied Name.
168      *
169      * <pre>
170      * Example:
171      *
172      * Request URL:
173      * http://localhost:8080/controller/nb/v2/staticroute/default/route/route-1
174      *
175      * Response body in XML:
176      *
177      *   &lt;staticRoute&gt;
178      *     &lt;name&gt;route-1&lt;/name&gt;
179      *     &lt;prefix&gt;10.10.1.0/24&lt;/prefix&gt;
180      *     &lt;nextHop&gt;1.1.1.1&lt;/nextHop&gt;
181      *   &lt;/staticRoute&gt;
182      *
183      * Response body in JSON:
184      * {
185      *    "name":"route-1",
186      *    "prefix":"10.10.1.0/24",
187      *    "nextHop":"1.1.1.1"
188      * }
189      *
190      * </pre>
191      */
192     @Path("/{containerName}/route/{route}")
193     @GET
194     @Produces( { MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
195     @TypeHint(StaticRoute.class)
196     @StatusCodes( {
197             @ResponseCode(code = 200, condition = "Operation successful"),
198             @ResponseCode(code = 404, condition = "The Container Name or Static Route Configuration name passed was not found") })
199     public StaticRoute getStaticRoute(
200             @PathParam("containerName") String containerName,
201             @PathParam("route") String route) {
202
203         if(!NorthboundUtils.isAuthorized(getUserName(), containerName,
204                 Privilege.WRITE, this)){
205             throw new
206                 UnauthorizedException("User is not authorized to perform this operation on container "
207                             + containerName);
208         }
209         List<StaticRoute> routes = this.getStaticRoutesInternal(containerName);
210         for (StaticRoute r : routes) {
211             if (r.getName().equalsIgnoreCase(route)) {
212                 return r;
213             }
214         }
215
216         throw new ResourceNotFoundException(RestMessages.NOSTATICROUTE
217                 .toString());
218     }
219
220     /**
221      *
222      * Add a new Static Route. If a route by the given name already exists, this
223      * method will return a non-successful status response.
224      *
225      * @param containerName Name of the Container. The Container name for the base controller is "default".
226      * @param route Name of the Static Route configuration
227      * @return Response as dictated by the HTTP Response code
228      *
229      * <pre>
230      * Example:
231      *
232      * Request URL:
233      * http://localhost:8080/controller/nb/v2/staticroute/default/route/route-1
234      *
235      * Request body in XML:
236      * &lt;staticRoute&gt;
237      *   &lt;name&gt;route-1&lt;/name&gt;
238      *   &lt;prefix>10.10.1.0/24&lt;/prefix&gt;
239      *   &lt;nextHop&gt;1.1.1.1&lt;/nextHop&gt;
240      *   &lt;/staticRoute&gt;
241      * Request body in JSON:
242      * {
243      *    "name":"route-1",
244      *    "prefix":"10.10.1.0/24",
245      *    "nextHop":"1.1.1.1"
246      * }
247      * </pre>
248      */
249     @Path("/{containerName}/route/{route}")
250     @PUT
251     @Consumes( { MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
252     @StatusCodes( {
253             @ResponseCode(code = 201, condition = "Created Static Route successfully"),
254             @ResponseCode(code = 404, condition = "The Container Name passed is not found"),
255             @ResponseCode(code = 406, condition = "Cannot operate on Default Container when other Containers are active"),
256             @ResponseCode(code = 409, condition = "Failed to create Static Route entry due to Conflicting Name or Prefix."), })
257     public Response addStaticRoute(
258             @Context UriInfo uriInfo,
259             @PathParam(value = "containerName") String containerName,
260             @PathParam(value = "route") String route,
261             @TypeHint(StaticRoute.class) StaticRoute staticRouteData) {
262
263
264         if(!NorthboundUtils.isAuthorized(getUserName(), containerName,
265                 Privilege.WRITE, this)){
266             throw new
267                 UnauthorizedException("User is not authorized to perform this operation on container "
268                             + containerName);
269         }
270         handleDefaultDisabled(containerName);
271
272         IForwardingStaticRouting staticRouting = (IForwardingStaticRouting) ServiceHelper
273                 .getInstance(IForwardingStaticRouting.class, containerName,
274                         this);
275
276         if (staticRouting == null) {
277             throw new ResourceNotFoundException(RestMessages.NOCONTAINER
278                     .toString());
279         }
280
281         StaticRoute sRoute = staticRouteData;
282         StaticRouteConfig cfgObject = new StaticRouteConfig(sRoute.getName(),
283                 sRoute.getPrefix(), sRoute.getNextHop());
284         Status response = staticRouting.addStaticRoute(cfgObject);
285         if (response.isSuccess()) {
286             NorthboundUtils.auditlog("Static Route", username, "added", route, containerName);
287             return Response.created(uriInfo.getRequestUri()).build();
288         }
289         throw new ResourceConflictException(response.getDescription());
290     }
291
292     /**
293      *
294      * Delete a Static Route
295      *
296      * @param containerName Name of the Container. The Container name for the base controller is "default".
297      * @param route Name of the Static Route configuration to be removed
298      *
299      * @return Response as dictated by the HTTP Response code
300      *
301      * <pre>
302      * Example:
303      *
304      * Request URL:
305      * DELETE http://localhost:8080/controller/nb/v2/staticroute/default/route/route-1
306      *
307      * </pre>
308      */
309     @Path("/{containerName}/route/{route}")
310     @DELETE
311     @StatusCodes( {
312             @ResponseCode(code = 204, condition = "Static route removed successfully"),
313             @ResponseCode(code = 404, condition = "Container Name or Configuration Name not found"),
314             @ResponseCode(code = 406, condition = "Cannot operate on Default Container when other Containers are active") })
315     public Response removeStaticRoute(
316             @PathParam(value = "containerName") String containerName,
317             @PathParam(value = "route") String route) {
318
319         if(!NorthboundUtils.isAuthorized(getUserName(), containerName,
320                 Privilege.WRITE, this)){
321             throw new
322                 UnauthorizedException("User is not authorized to perform this operation on container "
323                             + containerName);
324         }
325         handleDefaultDisabled(containerName);
326
327         IForwardingStaticRouting staticRouting = (IForwardingStaticRouting) ServiceHelper
328                 .getInstance(IForwardingStaticRouting.class, containerName,
329                         this);
330
331         if (staticRouting == null) {
332             throw new ResourceNotFoundException(RestMessages.NOCONTAINER
333                     .toString());
334         }
335
336         Status status = staticRouting.removeStaticRoute(route);
337         if (status.isSuccess()) {
338             NorthboundUtils.auditlog("Static Route", username, "removed", route, containerName);
339             return Response.noContent().build();
340         }
341         return NorthboundUtils.getResponse(status);
342     }
343
344     private void handleDefaultDisabled(String containerName) {
345         IContainerManager containerManager = (IContainerManager) ServiceHelper
346                 .getGlobalInstance(IContainerManager.class, this);
347         if (containerManager == null) {
348             throw new InternalServerErrorException(RestMessages.INTERNALERROR
349                     .toString());
350         }
351         if (containerName.equals(GlobalConstants.DEFAULT.toString())
352                 && containerManager.hasNonDefaultContainer()) {
353             throw new NotAcceptableException(RestMessages.DEFAULTDISABLED
354                     .toString());
355         }
356     }
357 }