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