2 * Copyright (c) 2013, 2015 IBM Corporation and others. All rights reserved.
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
9 package org.opendaylight.neutron.northbound.api;
11 import java.net.HttpURLConnection;
13 import java.util.ArrayList;
14 import java.util.Iterator;
15 import java.util.List;
17 import javax.ws.rs.Consumes;
18 import javax.ws.rs.DELETE;
19 import javax.ws.rs.GET;
20 import javax.ws.rs.POST;
21 import javax.ws.rs.PUT;
22 import javax.ws.rs.Path;
23 import javax.ws.rs.PathParam;
24 import javax.ws.rs.Produces;
25 import javax.ws.rs.QueryParam;
26 import javax.ws.rs.core.MediaType;
27 import javax.ws.rs.core.Response;
29 import org.codehaus.enunciate.jaxrs.ResponseCode;
30 import org.codehaus.enunciate.jaxrs.StatusCodes;
31 import org.opendaylight.neutron.spi.INeutronNetworkCRUD;
32 import org.opendaylight.neutron.spi.INeutronPortCRUD;
33 import org.opendaylight.neutron.spi.INeutronRouterAware;
34 import org.opendaylight.neutron.spi.INeutronRouterCRUD;
35 import org.opendaylight.neutron.spi.INeutronSubnetCRUD;
36 import org.opendaylight.neutron.spi.NeutronCRUDInterfaces;
37 import org.opendaylight.neutron.spi.NeutronRouter;
38 import org.opendaylight.neutron.spi.NeutronRouter_Interface;
42 * Neutron Northbound REST APIs.<br>
43 * This class provides REST APIs for managing neutron routers
47 * Authentication scheme : <b>HTTP Basic</b><br>
48 * Authentication realm : <b>opendaylight</b><br>
49 * Transport : <b>HTTP and HTTPS</b><br>
51 * HTTPS Authentication is disabled by default. Administrator can enable it in
52 * tomcat-server.xml after adding a proper keystore / SSL certificate from a
53 * trusted authority.<br>
55 * http://tomcat.apache.org/tomcat-7.0-doc/ssl-howto.html#Configuration
60 public class NeutronRoutersNorthbound {
61 static final String ROUTER_INTERFACE_STR = "network:router_interface";
62 static final String ROUTER_GATEWAY_STR = "network:router_gateway";
63 private static final int HTTP_OK_BOTTOM = 200;
64 private static final int HTTP_OK_TOP = 299;
65 private static final String INTERFACE_NAME = "Router CRUD Interface";
66 private static final String UUID_NO_EXIST = "Router UUID does not exist.";
67 private static final String NO_PROVIDERS = "No providers registered. Please try again later";
68 private static final String NO_PROVIDER_LIST = "Couldn't get providers list. Please try again later";
70 private NeutronRouter extractFields(NeutronRouter o, List<String> fields) {
71 return o.extractFields(fields);
74 private NeutronCRUDInterfaces getNeutronInterfaces(boolean flag) {
75 NeutronCRUDInterfaces answer = new NeutronCRUDInterfaces().fetchINeutronRouterCRUD(this);
76 if (answer.getRouterInterface() == null) {
77 throw new ServiceUnavailableException(INTERFACE_NAME
78 + RestMessages.SERVICEUNAVAILABLE.toString());
81 answer = answer.fetchINeutronNetworkCRUD(this);
82 if (answer.getNetworkInterface() == null) {
83 throw new ServiceUnavailableException("Network CRUD Interface "
84 + RestMessages.SERVICEUNAVAILABLE.toString());
90 private NeutronCRUDInterfaces getAttachInterfaces() {
91 NeutronCRUDInterfaces answer = new NeutronCRUDInterfaces().fetchINeutronRouterCRUD(this);
92 if (answer.getRouterInterface() == null) {
93 throw new ServiceUnavailableException(INTERFACE_NAME
94 + RestMessages.SERVICEUNAVAILABLE.toString());
96 answer = answer.fetchINeutronPortCRUD(this).fetchINeutronSubnetCRUD(this);
97 if (answer.getPortInterface() == null) {
98 throw new ServiceUnavailableException("Port CRUD Interface "
99 + RestMessages.SERVICEUNAVAILABLE.toString());
101 if (answer.getSubnetInterface() == null) {
102 throw new ServiceUnavailableException("Subnet CRUD Interface "
103 + RestMessages.SERVICEUNAVAILABLE.toString());
109 * Returns a list of all Routers */
112 @Produces({ MediaType.APPLICATION_JSON })
113 //@TypeHint(OpenStackRouters.class)
115 @ResponseCode(code = HttpURLConnection.HTTP_OK, condition = "Operation successful"),
116 @ResponseCode(code = HttpURLConnection.HTTP_UNAUTHORIZED, condition = "Unauthorized"),
117 @ResponseCode(code = HttpURLConnection.HTTP_NOT_IMPLEMENTED, condition = "Not Implemented"),
118 @ResponseCode(code = HttpURLConnection.HTTP_UNAVAILABLE, condition = "No providers available") })
119 public Response listRouters(
121 @QueryParam("fields") List<String> fields,
122 // note: openstack isn't clear about filtering on lists, so we aren't handling them
123 @QueryParam("id") String queryID,
124 @QueryParam("name") String queryName,
125 @QueryParam("admin_state_up") String queryAdminStateUp,
126 @QueryParam("status") String queryStatus,
127 @QueryParam("tenant_id") String queryTenantID,
128 @QueryParam("external_gateway_info") String queryExternalGatewayInfo,
130 @QueryParam("limit") String limit,
131 @QueryParam("marker") String marker,
132 @QueryParam("page_reverse") String pageReverse
133 // sorting not supported
135 INeutronRouterCRUD routerInterface = getNeutronInterfaces(false).getRouterInterface();
136 if (routerInterface == null) {
137 throw new ServiceUnavailableException(INTERFACE_NAME
138 + RestMessages.SERVICEUNAVAILABLE.toString());
140 List<NeutronRouter> allRouters = routerInterface.getAllRouters();
141 List<NeutronRouter> ans = new ArrayList<NeutronRouter>();
142 Iterator<NeutronRouter> i = allRouters.iterator();
143 while (i.hasNext()) {
144 NeutronRouter oSS = i.next();
145 if ((queryID == null || queryID.equals(oSS.getID())) &&
146 (queryName == null || queryName.equals(oSS.getName())) &&
147 (queryAdminStateUp == null || queryAdminStateUp.equals(oSS.getAdminStateUp())) &&
148 (queryStatus == null || queryStatus.equals(oSS.getStatus())) &&
149 (queryExternalGatewayInfo == null || queryExternalGatewayInfo.equals(oSS.getExternalGatewayInfo())) &&
150 (queryTenantID == null || queryTenantID.equals(oSS.getTenantID()))) {
151 if (fields.size() > 0) {
152 ans.add(extractFields(oSS,fields));
158 //TODO: apply pagination to results
159 return Response.status(HttpURLConnection.HTTP_OK).entity(
160 new NeutronRouterRequest(ans)).build();
164 * Returns a specific Router */
166 @Path("{routerUUID}")
168 @Produces({ MediaType.APPLICATION_JSON })
169 //@TypeHint(OpenStackRouters.class)
171 @ResponseCode(code = HttpURLConnection.HTTP_OK, condition = "Operation successful"),
172 @ResponseCode(code = HttpURLConnection.HTTP_UNAUTHORIZED, condition = "Unauthorized"),
173 @ResponseCode(code = HttpURLConnection.HTTP_FORBIDDEN, condition = "Forbidden"),
174 @ResponseCode(code = HttpURLConnection.HTTP_NOT_FOUND, condition = "Not Found"),
175 @ResponseCode(code = HttpURLConnection.HTTP_NOT_IMPLEMENTED, condition = "Not Implemented"),
176 @ResponseCode(code = HttpURLConnection.HTTP_UNAVAILABLE, condition = "No providers available") })
177 public Response showRouter(
178 @PathParam("routerUUID") String routerUUID,
180 @QueryParam("fields") List<String> fields) {
181 INeutronRouterCRUD routerInterface = getNeutronInterfaces(false).getRouterInterface();
182 if (routerInterface == null) {
183 throw new ServiceUnavailableException(INTERFACE_NAME
184 + RestMessages.SERVICEUNAVAILABLE.toString());
186 if (!routerInterface.routerExists(routerUUID)) {
187 throw new ResourceNotFoundException(UUID_NO_EXIST);
189 if (fields.size() > 0) {
190 NeutronRouter ans = routerInterface.getRouter(routerUUID);
191 return Response.status(HttpURLConnection.HTTP_OK).entity(
192 new NeutronRouterRequest(extractFields(ans, fields))).build();
194 return Response.status(HttpURLConnection.HTTP_OK).entity(
195 new NeutronRouterRequest(routerInterface.getRouter(routerUUID))).build();
200 * Creates new Routers */
203 @Produces({ MediaType.APPLICATION_JSON })
204 @Consumes({ MediaType.APPLICATION_JSON })
205 //@TypeHint(OpenStackRouters.class)
207 @ResponseCode(code = HttpURLConnection.HTTP_CREATED, condition = "Created"),
208 @ResponseCode(code = HttpURLConnection.HTTP_UNAVAILABLE, condition = "No providers available") })
209 public Response createRouters(final NeutronRouterRequest input) {
210 NeutronCRUDInterfaces interfaces = getNeutronInterfaces(true);
211 INeutronRouterCRUD routerInterface = interfaces.getRouterInterface();
212 if (input.isSingleton()) {
213 NeutronRouter singleton = input.getSingleton();
215 Object[] instances = NeutronUtil.getInstances(INeutronRouterAware.class, this);
216 if (instances != null) {
217 if (instances.length > 0) {
218 for (Object instance : instances) {
219 INeutronRouterAware service = (INeutronRouterAware) instance;
220 int status = service.canCreateRouter(singleton);
221 if (status < HTTP_OK_BOTTOM || status > HTTP_OK_TOP) {
222 return Response.status(status).build();
226 throw new ServiceUnavailableException(NO_PROVIDERS);
229 throw new ServiceUnavailableException(NO_PROVIDER_LIST);
233 * add router to the cache
235 routerInterface.addRouter(singleton);
236 if (instances != null) {
237 for (Object instance : instances) {
238 INeutronRouterAware service = (INeutronRouterAware) instance;
239 service.neutronRouterCreated(singleton);
245 * only singleton router creates supported
247 throw new BadRequestException("Only singleton router creates supported");
249 return Response.status(HttpURLConnection.HTTP_CREATED).entity(input).build();
253 * Updates a Router */
255 @Path("{routerUUID}")
257 @Produces({ MediaType.APPLICATION_JSON })
258 @Consumes({ MediaType.APPLICATION_JSON })
259 //@TypeHint(OpenStackRouters.class)
261 @ResponseCode(code = HttpURLConnection.HTTP_OK, condition = "Operation successful"),
262 @ResponseCode(code = HttpURLConnection.HTTP_UNAVAILABLE, condition = "No providers available") })
263 public Response updateRouter(
264 @PathParam("routerUUID") String routerUUID,
265 NeutronRouterRequest input
267 NeutronCRUDInterfaces interfaces = getNeutronInterfaces(true);
268 INeutronRouterCRUD routerInterface = interfaces.getRouterInterface();
269 INeutronNetworkCRUD networkInterface = interfaces.getNetworkInterface();
271 NeutronRouter updatedRouter = input.getSingleton();
272 NeutronRouter original = routerInterface.getRouter(routerUUID);
273 updatedRouter.setID(routerUUID);
274 updatedRouter.setTenantID(original.getTenantID());
276 Object[] instances = NeutronUtil.getInstances(INeutronRouterAware.class, this);
277 if (instances != null) {
278 if (instances.length > 0) {
279 for (Object instance : instances) {
280 INeutronRouterAware service = (INeutronRouterAware) instance;
281 int status = service.canUpdateRouter(updatedRouter, original);
282 if (status < HTTP_OK_BOTTOM || status > HTTP_OK_TOP) {
283 return Response.status(status).build();
287 throw new ServiceUnavailableException(NO_PROVIDERS);
290 throw new ServiceUnavailableException(NO_PROVIDER_LIST);
294 * update the router entry and return the modified object
296 routerInterface.updateRouter(routerUUID, updatedRouter);
297 if (instances != null) {
298 for (Object instance : instances) {
299 INeutronRouterAware service = (INeutronRouterAware) instance;
300 service.neutronRouterUpdated(updatedRouter);
303 return Response.status(HttpURLConnection.HTTP_OK).entity(
304 new NeutronRouterRequest(routerInterface.getRouter(routerUUID))).build();
309 * Deletes a Router */
311 @Path("{routerUUID}")
314 @ResponseCode(code = HttpURLConnection.HTTP_NO_CONTENT, condition = "No Content"),
315 @ResponseCode(code = HttpURLConnection.HTTP_UNAVAILABLE, condition = "No providers available") })
316 public Response deleteRouter(
317 @PathParam("routerUUID") String routerUUID) {
318 INeutronRouterCRUD routerInterface = getNeutronInterfaces(false).getRouterInterface();
320 NeutronRouter singleton = routerInterface.getRouter(routerUUID);
321 Object[] instances = NeutronUtil.getInstances(INeutronRouterAware.class, this);
322 if (instances != null) {
323 if (instances.length > 0) {
324 for (Object instance : instances) {
325 INeutronRouterAware service = (INeutronRouterAware) instance;
326 int status = service.canDeleteRouter(singleton);
327 if (status < HTTP_OK_BOTTOM || status > HTTP_OK_TOP) {
328 return Response.status(status).build();
332 throw new ServiceUnavailableException(NO_PROVIDERS);
335 throw new ServiceUnavailableException(NO_PROVIDER_LIST);
337 routerInterface.removeRouter(routerUUID);
338 if (instances != null) {
339 for (Object instance : instances) {
340 INeutronRouterAware service = (INeutronRouterAware) instance;
341 service.neutronRouterDeleted(singleton);
344 return Response.status(HttpURLConnection.HTTP_NO_CONTENT).build();
348 * Adds an interface to a router */
350 @Path("{routerUUID}/add_router_interface")
352 @Produces({ MediaType.APPLICATION_JSON })
353 @Consumes({ MediaType.APPLICATION_JSON })
354 //@TypeHint(OpenStackRouterInterfaces.class)
356 @ResponseCode(code = HttpURLConnection.HTTP_OK, condition = "Operation successful"),
357 @ResponseCode(code = HttpURLConnection.HTTP_UNAVAILABLE, condition = "No providers available") })
358 public Response addRouterInterface(
359 @PathParam("routerUUID") String routerUUID,
360 NeutronRouter_Interface input
362 NeutronCRUDInterfaces interfaces = getAttachInterfaces();
363 INeutronRouterCRUD routerInterface = interfaces.getRouterInterface();
365 NeutronRouter target = routerInterface.getRouter(routerUUID);
366 Object[] instances = NeutronUtil.getInstances(INeutronRouterAware.class, this);
367 if (instances != null) {
368 if (instances.length > 0) {
369 for (Object instance : instances) {
370 INeutronRouterAware service = (INeutronRouterAware) instance;
371 int status = service.canAttachInterface(target, input);
372 if (status < HTTP_OK_BOTTOM || status > HTTP_OK_TOP) {
373 return Response.status(status).build();
377 throw new ServiceUnavailableException(NO_PROVIDERS);
380 throw new ServiceUnavailableException(NO_PROVIDER_LIST);
383 target.addInterface(input.getPortUUID(), input);
384 if (instances != null) {
385 for (Object instance : instances) {
386 INeutronRouterAware service = (INeutronRouterAware) instance;
387 service.neutronRouterInterfaceAttached(target, input);
391 return Response.status(HttpURLConnection.HTTP_OK).entity(input).build();
395 private int checkDownstreamDetach(NeutronRouter target, NeutronRouter_Interface input) {
396 Object[] instances = NeutronUtil.getInstances(INeutronRouterAware.class, this);
397 if (instances != null) {
398 if (instances.length > 0) {
399 for (Object instance : instances) {
400 INeutronRouterAware service = (INeutronRouterAware) instance;
401 int status = service.canDetachInterface(target, input);
402 if (status < HTTP_OK_BOTTOM || status > HTTP_OK_TOP) {
407 throw new ServiceUnavailableException(NO_PROVIDERS);
410 throw new ServiceUnavailableException(NO_PROVIDER_LIST);
412 return HTTP_OK_BOTTOM;
416 * Removes an interface to a router */
418 @Path("{routerUUID}/remove_router_interface")
420 @Produces({ MediaType.APPLICATION_JSON })
421 @Consumes({ MediaType.APPLICATION_JSON })
422 //@TypeHint(OpenStackRouterInterfaces.class)
424 @ResponseCode(code = HttpURLConnection.HTTP_OK, condition = "Operation successful"),
425 @ResponseCode(code = HttpURLConnection.HTTP_UNAVAILABLE, condition = "No providers available") })
426 public Response removeRouterInterface(
427 @PathParam("routerUUID") String routerUUID,
428 NeutronRouter_Interface input
430 NeutronCRUDInterfaces interfaces = getAttachInterfaces();
431 INeutronRouterCRUD routerInterface = interfaces.getRouterInterface();
432 Object[] instances = NeutronUtil.getInstances(INeutronRouterAware.class, this);
434 NeutronRouter target = routerInterface.getRouter(routerUUID);
435 input.setID(target.getID());
436 input.setTenantID(target.getTenantID());
437 int status = checkDownstreamDetach(target, input);
438 if (status != HTTP_OK_BOTTOM) {
439 return Response.status(status).build();
441 target.removeInterface(input.getPortUUID());
442 for (Object instance : instances) {
443 INeutronRouterAware service = (INeutronRouterAware) instance;
444 service.neutronRouterInterfaceDetached(target, input);
446 return Response.status(HttpURLConnection.HTTP_OK).entity(input).build();