2 * Copyright IBM Corporation, 2013. 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.util.ArrayList;
12 import java.util.Iterator;
13 import java.util.List;
15 import javax.ws.rs.Consumes;
16 import javax.ws.rs.DELETE;
17 import javax.ws.rs.GET;
18 import javax.ws.rs.POST;
19 import javax.ws.rs.PUT;
20 import javax.ws.rs.Path;
21 import javax.ws.rs.PathParam;
22 import javax.ws.rs.Produces;
23 import javax.ws.rs.QueryParam;
24 import javax.ws.rs.core.MediaType;
25 import javax.ws.rs.core.Response;
27 import org.codehaus.enunciate.jaxrs.ResponseCode;
28 import org.codehaus.enunciate.jaxrs.StatusCodes;
29 import org.opendaylight.neutron.spi.INeutronNetworkCRUD;
30 import org.opendaylight.neutron.spi.INeutronPortCRUD;
31 import org.opendaylight.neutron.spi.INeutronRouterAware;
32 import org.opendaylight.neutron.spi.INeutronRouterCRUD;
33 import org.opendaylight.neutron.spi.INeutronSubnetCRUD;
34 import org.opendaylight.neutron.spi.NeutronCRUDInterfaces;
35 import org.opendaylight.neutron.spi.NeutronNetwork;
36 import org.opendaylight.neutron.spi.NeutronPort;
37 import org.opendaylight.neutron.spi.NeutronRouter;
38 import org.opendaylight.neutron.spi.NeutronRouter_Interface;
39 import org.opendaylight.neutron.spi.NeutronSubnet;
43 * Neutron Northbound REST APIs.<br>
44 * This class provides REST APIs for managing neutron routers
48 * Authentication scheme : <b>HTTP Basic</b><br>
49 * Authentication realm : <b>opendaylight</b><br>
50 * Transport : <b>HTTP and HTTPS</b><br>
52 * HTTPS Authentication is disabled by default. Administrator can enable it in
53 * tomcat-server.xml after adding a proper keystore / SSL certificate from a
54 * trusted authority.<br>
56 * http://tomcat.apache.org/tomcat-7.0-doc/ssl-howto.html#Configuration
61 public class NeutronRoutersNorthbound {
62 static final String ROUTER_INTERFACE_STR = "network:router_interface";
63 static final String ROUTER_GATEWAY_STR = "network:router_gateway";
65 private NeutronRouter extractFields(NeutronRouter o, List<String> fields) {
66 return o.extractFields(fields);
70 * Returns a list of all Routers */
73 @Produces({ MediaType.APPLICATION_JSON })
74 //@TypeHint(OpenStackRouters.class)
76 @ResponseCode(code = 200, condition = "Operation successful"),
77 @ResponseCode(code = 401, condition = "Unauthorized"),
78 @ResponseCode(code = 501, condition = "Not Implemented"),
79 @ResponseCode(code = 503, condition = "No providers available") })
80 public Response listRouters(
82 @QueryParam("fields") List<String> fields,
83 // note: openstack isn't clear about filtering on lists, so we aren't handling them
84 @QueryParam("id") String queryID,
85 @QueryParam("name") String queryName,
86 @QueryParam("admin_state_up") String queryAdminStateUp,
87 @QueryParam("status") String queryStatus,
88 @QueryParam("tenant_id") String queryTenantID,
89 @QueryParam("external_gateway_info") String queryExternalGatewayInfo,
91 @QueryParam("limit") String limit,
92 @QueryParam("marker") String marker,
93 @QueryParam("page_reverse") String pageReverse
94 // sorting not supported
96 INeutronRouterCRUD routerInterface = NeutronCRUDInterfaces.getINeutronRouterCRUD(this);
97 if (routerInterface == null) {
98 throw new ServiceUnavailableException("Router CRUD Interface "
99 + RestMessages.SERVICEUNAVAILABLE.toString());
101 List<NeutronRouter> allRouters = routerInterface.getAllRouters();
102 List<NeutronRouter> ans = new ArrayList<NeutronRouter>();
103 Iterator<NeutronRouter> i = allRouters.iterator();
104 while (i.hasNext()) {
105 NeutronRouter oSS = i.next();
106 if ((queryID == null || queryID.equals(oSS.getID())) &&
107 (queryName == null || queryName.equals(oSS.getName())) &&
108 (queryAdminStateUp == null || queryAdminStateUp.equals(oSS.getAdminStateUp())) &&
109 (queryStatus == null || queryStatus.equals(oSS.getStatus())) &&
110 (queryExternalGatewayInfo == null || queryExternalGatewayInfo.equals(oSS.getExternalGatewayInfo())) &&
111 (queryTenantID == null || queryTenantID.equals(oSS.getTenantID()))) {
112 if (fields.size() > 0) {
113 ans.add(extractFields(oSS,fields));
119 //TODO: apply pagination to results
120 return Response.status(200).entity(
121 new NeutronRouterRequest(ans)).build();
125 * Returns a specific Router */
127 @Path("{routerUUID}")
129 @Produces({ MediaType.APPLICATION_JSON })
130 //@TypeHint(OpenStackRouters.class)
132 @ResponseCode(code = 200, condition = "Operation successful"),
133 @ResponseCode(code = 401, condition = "Unauthorized"),
134 @ResponseCode(code = 403, condition = "Forbidden"),
135 @ResponseCode(code = 404, condition = "Not Found"),
136 @ResponseCode(code = 501, condition = "Not Implemented"),
137 @ResponseCode(code = 503, condition = "No providers available") })
138 public Response showRouter(
139 @PathParam("routerUUID") String routerUUID,
141 @QueryParam("fields") List<String> fields) {
142 INeutronRouterCRUD routerInterface = NeutronCRUDInterfaces.getINeutronRouterCRUD(this);
143 if (routerInterface == null) {
144 throw new ServiceUnavailableException("Router CRUD Interface "
145 + RestMessages.SERVICEUNAVAILABLE.toString());
147 if (!routerInterface.routerExists(routerUUID)) {
148 throw new ResourceNotFoundException("Router UUID not found");
150 if (fields.size() > 0) {
151 NeutronRouter ans = routerInterface.getRouter(routerUUID);
152 return Response.status(200).entity(
153 new NeutronRouterRequest(extractFields(ans, fields))).build();
155 return Response.status(200).entity(
156 new NeutronRouterRequest(routerInterface.getRouter(routerUUID))).build();
160 * Creates new Routers */
163 @Produces({ MediaType.APPLICATION_JSON })
164 @Consumes({ MediaType.APPLICATION_JSON })
165 //@TypeHint(OpenStackRouters.class)
167 @ResponseCode(code = 201, condition = "Created"),
168 @ResponseCode(code = 400, condition = "Bad Request"),
169 @ResponseCode(code = 401, condition = "Unauthorized"),
170 @ResponseCode(code = 501, condition = "Not Implemented"),
171 @ResponseCode(code = 503, condition = "No providers available") })
172 public Response createRouters(final NeutronRouterRequest input) {
173 INeutronRouterCRUD routerInterface = NeutronCRUDInterfaces.getINeutronRouterCRUD(this);
174 if (routerInterface == null) {
175 throw new ServiceUnavailableException("Router CRUD Interface "
176 + RestMessages.SERVICEUNAVAILABLE.toString());
178 INeutronNetworkCRUD networkInterface = NeutronCRUDInterfaces.getINeutronNetworkCRUD( this);
179 if (networkInterface == null) {
180 throw new ServiceUnavailableException("Network CRUD Interface "
181 + RestMessages.SERVICEUNAVAILABLE.toString());
183 if (input.isSingleton()) {
184 NeutronRouter singleton = input.getSingleton();
187 * verify that the router doesn't already exist (issue: is deeper inspection necessary?)
188 * if there is external gateway information provided, verify that the specified network
189 * exists and has been designated as "router:external"
191 if (routerInterface.routerExists(singleton.getID())) {
192 throw new BadRequestException("router UUID already exists");
194 if (singleton.getExternalGatewayInfo() != null) {
195 String externNetworkPtr = singleton.getExternalGatewayInfo().getNetworkID();
196 if (!networkInterface.networkExists(externNetworkPtr)) {
197 throw new BadRequestException("External Network Pointer doesn't exist");
199 NeutronNetwork externNetwork = networkInterface.getNetwork(externNetworkPtr);
200 if (!externNetwork.isRouterExternal()) {
201 throw new BadRequestException("External Network Pointer isn't marked as router:external");
204 Object[] instances = NeutronUtil.getInstances(INeutronRouterAware.class, this);
205 if (instances != null) {
206 if (instances.length > 0) {
207 for (Object instance : instances) {
208 INeutronRouterAware service = (INeutronRouterAware) instance;
209 int status = service.canCreateRouter(singleton);
210 if (status < 200 || status > 299) {
211 return Response.status(status).build();
215 throw new ServiceUnavailableException("No providers registered. Please try again later");
218 throw new ServiceUnavailableException("Couldn't get providers list. Please try again later");
222 * add router to the cache
224 routerInterface.addRouter(singleton);
225 if (instances != null) {
226 for (Object instance : instances) {
227 INeutronRouterAware service = (INeutronRouterAware) instance;
228 service.neutronRouterCreated(singleton);
234 * only singleton router creates supported
236 throw new BadRequestException("Only singleton router creates supported");
238 return Response.status(201).entity(input).build();
242 * Updates a Router */
244 @Path("{routerUUID}")
246 @Produces({ MediaType.APPLICATION_JSON })
247 @Consumes({ MediaType.APPLICATION_JSON })
248 //@TypeHint(OpenStackRouters.class)
250 @ResponseCode(code = 200, condition = "Operation successful"),
251 @ResponseCode(code = 400, condition = "Bad Request"),
252 @ResponseCode(code = 401, condition = "Unauthorized"),
253 @ResponseCode(code = 404, condition = "Not Found"),
254 @ResponseCode(code = 501, condition = "Not Implemented"),
255 @ResponseCode(code = 503, condition = "No providers available") })
256 public Response updateRouter(
257 @PathParam("routerUUID") String routerUUID,
258 NeutronRouterRequest input
260 INeutronRouterCRUD routerInterface = NeutronCRUDInterfaces.getINeutronRouterCRUD(this);
261 if (routerInterface == null) {
262 throw new ServiceUnavailableException("Router CRUD Interface "
263 + RestMessages.SERVICEUNAVAILABLE.toString());
265 INeutronNetworkCRUD networkInterface = NeutronCRUDInterfaces.getINeutronNetworkCRUD( this);
266 if (networkInterface == null) {
267 throw new ServiceUnavailableException("Network CRUD Interface "
268 + RestMessages.SERVICEUNAVAILABLE.toString());
272 * router has to exist and only a single delta can be supplied
274 if (!routerInterface.routerExists(routerUUID)) {
275 throw new ResourceNotFoundException("Router UUID not found");
277 if (!input.isSingleton()) {
278 throw new BadRequestException("Only single router deltas supported");
280 NeutronRouter singleton = input.getSingleton();
281 NeutronRouter original = routerInterface.getRouter(routerUUID);
284 * attribute changes blocked by Neutron
286 if (singleton.getID() != null || singleton.getTenantID() != null ||
287 singleton.getStatus() != null) {
288 throw new BadRequestException("Request attribute change not allowed");
291 Object[] instances = NeutronUtil.getInstances(INeutronRouterAware.class, this);
292 if (instances != null) {
293 if (instances.length > 0) {
294 for (Object instance : instances) {
295 INeutronRouterAware service = (INeutronRouterAware) instance;
296 int status = service.canUpdateRouter(singleton, original);
297 if (status < 200 || status > 299) {
298 return Response.status(status).build();
302 throw new ServiceUnavailableException("No providers registered. Please try again later");
305 throw new ServiceUnavailableException("Couldn't get providers list. Please try again later");
308 * if the external gateway info is being changed, verify that the new network
309 * exists and has been designated as an external network
311 if (singleton.getExternalGatewayInfo() != null) {
312 String externNetworkPtr = singleton.getExternalGatewayInfo().getNetworkID();
313 if (!networkInterface.networkExists(externNetworkPtr)) {
314 throw new BadRequestException("External Network Pointer does not exist");
316 NeutronNetwork externNetwork = networkInterface.getNetwork(externNetworkPtr);
317 if (!externNetwork.isRouterExternal()) {
318 throw new BadRequestException("External Network Pointer isn't marked as router:external");
323 * update the router entry and return the modified object
325 routerInterface.updateRouter(routerUUID, singleton);
326 NeutronRouter updatedRouter = routerInterface.getRouter(routerUUID);
327 if (instances != null) {
328 for (Object instance : instances) {
329 INeutronRouterAware service = (INeutronRouterAware) instance;
330 service.neutronRouterUpdated(updatedRouter);
333 return Response.status(200).entity(
334 new NeutronRouterRequest(routerInterface.getRouter(routerUUID))).build();
339 * Deletes a Router */
341 @Path("{routerUUID}")
344 @ResponseCode(code = 204, condition = "No Content"),
345 @ResponseCode(code = 401, condition = "Unauthorized"),
346 @ResponseCode(code = 404, condition = "Not Found"),
347 @ResponseCode(code = 409, condition = "Conflict"),
348 @ResponseCode(code = 501, condition = "Not Implemented"),
349 @ResponseCode(code = 503, condition = "No providers available") })
350 public Response deleteRouter(
351 @PathParam("routerUUID") String routerUUID) {
352 INeutronRouterCRUD routerInterface = NeutronCRUDInterfaces.getINeutronRouterCRUD(this);
353 if (routerInterface == null) {
354 throw new ServiceUnavailableException("Router CRUD Interface "
355 + RestMessages.SERVICEUNAVAILABLE.toString());
359 * verify that the router exists and is not in use before removing it
361 if (!routerInterface.routerExists(routerUUID)) {
362 throw new ResourceNotFoundException("Router UUID not found");
364 if (routerInterface.routerInUse(routerUUID)) {
365 throw new ResourceConflictException("Router UUID in Use");
367 NeutronRouter singleton = routerInterface.getRouter(routerUUID);
368 Object[] instances = NeutronUtil.getInstances(INeutronRouterAware.class, this);
369 if (instances != null) {
370 if (instances.length > 0) {
371 for (Object instance : instances) {
372 INeutronRouterAware service = (INeutronRouterAware) instance;
373 int status = service.canDeleteRouter(singleton);
374 if (status < 200 || status > 299) {
375 return Response.status(status).build();
379 throw new ServiceUnavailableException("No providers registered. Please try again later");
382 throw new ServiceUnavailableException("Couldn't get providers list. Please try again later");
384 routerInterface.removeRouter(routerUUID);
385 if (instances != null) {
386 for (Object instance : instances) {
387 INeutronRouterAware service = (INeutronRouterAware) instance;
388 service.neutronRouterDeleted(singleton);
391 return Response.status(204).build();
395 * Adds an interface to a router */
397 @Path("{routerUUID}/add_router_interface")
399 @Produces({ MediaType.APPLICATION_JSON })
400 @Consumes({ MediaType.APPLICATION_JSON })
401 //@TypeHint(OpenStackRouterInterfaces.class)
403 @ResponseCode(code = 200, condition = "Operation successful"),
404 @ResponseCode(code = 400, condition = "Bad Request"),
405 @ResponseCode(code = 401, condition = "Unauthorized"),
406 @ResponseCode(code = 404, condition = "Not Found"),
407 @ResponseCode(code = 409, condition = "Conflict"),
408 @ResponseCode(code = 501, condition = "Not Implemented"),
409 @ResponseCode(code = 503, condition = "No providers available") })
410 public Response addRouterInterface(
411 @PathParam("routerUUID") String routerUUID,
412 NeutronRouter_Interface input
414 INeutronRouterCRUD routerInterface = NeutronCRUDInterfaces.getINeutronRouterCRUD(this);
415 if (routerInterface == null) {
416 throw new ServiceUnavailableException("Router CRUD Interface "
417 + RestMessages.SERVICEUNAVAILABLE.toString());
419 INeutronPortCRUD portInterface = NeutronCRUDInterfaces.getINeutronPortCRUD(this);
420 if (portInterface == null) {
421 throw new ServiceUnavailableException("Port CRUD Interface "
422 + RestMessages.SERVICEUNAVAILABLE.toString());
424 INeutronSubnetCRUD subnetInterface = NeutronCRUDInterfaces.getINeutronSubnetCRUD(this);
425 if (subnetInterface == null) {
426 throw new ServiceUnavailableException("Subnet CRUD Interface "
427 + RestMessages.SERVICEUNAVAILABLE.toString());
431 * While the Neutron specification says that the router has to exist and the input can only specify either a subnet id
432 * or a port id, but not both, this code assumes that the plugin has filled everything in for us and so both must be present
434 if (!routerInterface.routerExists(routerUUID)) {
435 throw new BadRequestException("Router UUID doesn't exist");
437 NeutronRouter target = routerInterface.getRouter(routerUUID);
438 if (input.getSubnetUUID() == null ||
439 input.getPortUUID() == null) {
440 throw new BadRequestException("Must specify at subnet id, port id or both");
443 // check that the port is part of the subnet
444 NeutronSubnet targetSubnet = subnetInterface.getSubnet(input.getSubnetUUID());
445 if (targetSubnet == null) {
446 throw new BadRequestException("Subnet id doesn't exist");
448 NeutronPort targetPort = portInterface.getPort(input.getPortUUID());
449 if (targetPort == null) {
450 throw new BadRequestException("Port id doesn't exist");
452 if (!targetSubnet.getPortsInSubnet().contains(targetPort)) {
453 throw new BadRequestException("Port id not part of subnet id");
456 if (targetPort.getFixedIPs().size() != 1) {
457 throw new BadRequestException("Port id must have a single fixedIP address");
459 if (targetPort.getDeviceID() != null && !targetPort.getDeviceID().equals(routerUUID)) {
460 throw new ResourceConflictException("Target Port already allocated to a different device id");
462 if (targetPort.getDeviceOwner() != null &&
463 !targetPort.getDeviceOwner().equalsIgnoreCase(ROUTER_INTERFACE_STR) &&
464 !targetPort.getDeviceOwner().equalsIgnoreCase(ROUTER_GATEWAY_STR)) {
465 throw new ResourceConflictException("Target Port already allocated to non-router interface");
467 Object[] instances = NeutronUtil.getInstances(INeutronRouterAware.class, this);
468 if (instances != null) {
469 if (instances.length > 0) {
470 for (Object instance : instances) {
471 INeutronRouterAware service = (INeutronRouterAware) instance;
472 int status = service.canAttachInterface(target, input);
473 if (status < 200 || status > 299) {
474 return Response.status(status).build();
478 throw new ServiceUnavailableException("No providers registered. Please try again later");
481 throw new ServiceUnavailableException("Couldn't get providers list. Please try again later");
484 //mark the port device id and device owner fields
485 if (targetPort.getDeviceOwner() == null || targetPort.getDeviceOwner().isEmpty()) {
486 targetPort.setDeviceOwner(ROUTER_INTERFACE_STR);
488 targetPort.setDeviceID(routerUUID);
490 target.addInterface(input.getPortUUID(), input);
491 if (instances != null) {
492 for (Object instance : instances) {
493 INeutronRouterAware service = (INeutronRouterAware) instance;
494 service.neutronRouterInterfaceAttached(target, input);
498 return Response.status(200).entity(input).build();
502 * Removes an interface to a router */
504 @Path("{routerUUID}/remove_router_interface")
506 @Produces({ MediaType.APPLICATION_JSON })
507 @Consumes({ MediaType.APPLICATION_JSON })
508 //@TypeHint(OpenStackRouterInterfaces.class)
510 @ResponseCode(code = 200, condition = "Operation successful"),
511 @ResponseCode(code = 400, condition = "Bad Request"),
512 @ResponseCode(code = 401, condition = "Unauthorized"),
513 @ResponseCode(code = 404, condition = "Not Found"),
514 @ResponseCode(code = 409, condition = "Conflict"),
515 @ResponseCode(code = 501, condition = "Not Implemented"),
516 @ResponseCode(code = 503, condition = "No providers available") })
517 public Response removeRouterInterface(
518 @PathParam("routerUUID") String routerUUID,
519 NeutronRouter_Interface input
521 INeutronRouterCRUD routerInterface = NeutronCRUDInterfaces.getINeutronRouterCRUD(this);
522 if (routerInterface == null) {
523 throw new ServiceUnavailableException("Router CRUD Interface "
524 + RestMessages.SERVICEUNAVAILABLE.toString());
526 INeutronPortCRUD portInterface = NeutronCRUDInterfaces.getINeutronPortCRUD(this);
527 if (portInterface == null) {
528 throw new ServiceUnavailableException("Port CRUD Interface "
529 + RestMessages.SERVICEUNAVAILABLE.toString());
531 INeutronSubnetCRUD subnetInterface = NeutronCRUDInterfaces.getINeutronSubnetCRUD(this);
532 if (subnetInterface == null) {
533 throw new ServiceUnavailableException("Subnet CRUD Interface "
534 + RestMessages.SERVICEUNAVAILABLE.toString());
537 // verify the router exists
538 if (!routerInterface.routerExists(routerUUID)) {
539 throw new BadRequestException("Router does not exist");
541 NeutronRouter target = routerInterface.getRouter(routerUUID);
544 * remove by subnet id. Collect information about the impacted router for the response and
545 * remove the port corresponding to the gateway IP address of the subnet
547 if (input.getPortUUID() == null &&
548 input.getSubnetUUID() != null) {
549 NeutronPort port = portInterface.getGatewayPort(input.getSubnetUUID());
551 throw new ResourceNotFoundException("Port UUID not found");
553 input.setPortUUID(port.getID());
554 input.setID(target.getID());
555 input.setTenantID(target.getTenantID());
557 Object[] instances = NeutronUtil.getInstances(INeutronRouterAware.class, this);
558 if (instances != null) {
559 if (instances.length > 0) {
560 for (Object instance : instances) {
561 INeutronRouterAware service = (INeutronRouterAware) instance;
562 int status = service.canDetachInterface(target, input);
563 if (status < 200 || status > 299) {
564 return Response.status(status).build();
568 throw new ServiceUnavailableException("No providers registered. Please try again later");
571 throw new ServiceUnavailableException("Couldn't get providers list. Please try again later");
574 // reset the port ownership
575 port.setDeviceID(null);
576 port.setDeviceOwner(null);
578 target.removeInterface(input.getPortUUID());
579 if (instances != null) {
580 for (Object instance : instances) {
581 INeutronRouterAware service = (INeutronRouterAware) instance;
582 service.neutronRouterInterfaceDetached(target, input);
585 return Response.status(200).entity(input).build();
589 * remove by port id. collect information about the impacted router for the response
590 * remove the interface and reset the port ownership
592 if (input.getPortUUID() != null &&
593 input.getSubnetUUID() == null) {
594 NeutronRouter_Interface targetInterface = target.getInterfaces().get(input.getPortUUID());
595 if (targetInterface == null) {
596 throw new ResourceNotFoundException("Router interface not found for given Port UUID");
598 input.setSubnetUUID(targetInterface.getSubnetUUID());
599 input.setID(target.getID());
600 input.setTenantID(target.getTenantID());
601 Object[] instances = NeutronUtil.getInstances(INeutronRouterAware.class, this);
602 if (instances != null) {
603 if (instances.length > 0) {
604 for (Object instance : instances) {
605 INeutronRouterAware service = (INeutronRouterAware) instance;
606 int status = service.canDetachInterface(target, input);
607 if (status < 200 || status > 299) {
608 return Response.status(status).build();
612 throw new ServiceUnavailableException("No providers registered. Please try again later");
615 throw new ServiceUnavailableException("Couldn't get providers list. Please try again later");
617 NeutronPort port = portInterface.getPort(input.getPortUUID());
618 port.setDeviceID(null);
619 port.setDeviceOwner(null);
620 target.removeInterface(input.getPortUUID());
621 for (Object instance : instances) {
622 INeutronRouterAware service = (INeutronRouterAware) instance;
623 service.neutronRouterInterfaceDetached(target, input);
625 return Response.status(200).entity(input).build();
629 * remove by both port and subnet ID. Verify that the first fixed IP of the port is a valid
630 * IP address for the subnet, and then remove the interface, collecting information about the
631 * impacted router for the response and reset port ownership
633 if (input.getPortUUID() != null &&
634 input.getSubnetUUID() != null) {
635 NeutronPort port = portInterface.getPort(input.getPortUUID());
637 throw new ResourceNotFoundException("Port UUID not found");
639 if (port.getFixedIPs() == null) {
640 throw new ResourceNotFoundException("Port UUID has no fixed IPs");
642 NeutronSubnet subnet = subnetInterface.getSubnet(input.getSubnetUUID());
643 if (subnet == null) {
644 throw new ResourceNotFoundException("Subnet UUID not found");
646 if (!subnet.isValidIP(port.getFixedIPs().get(0).getIpAddress())) {
647 throw new ResourceConflictException("Target Port IP not in Target Subnet");
649 Object[] instances = NeutronUtil.getInstances(INeutronRouterAware.class, this);
650 if (instances != null) {
651 if (instances.length > 0) {
652 for (Object instance : instances) {
653 INeutronRouterAware service = (INeutronRouterAware) instance;
654 int status = service.canDetachInterface(target, input);
655 if (status < 200 || status > 299) {
656 return Response.status(status).build();
660 throw new ServiceUnavailableException("No providers registered. Please try again later");
663 throw new ServiceUnavailableException("Couldn't get providers list. Please try again later");
665 input.setID(target.getID());
666 input.setTenantID(target.getTenantID());
667 port.setDeviceID(null);
668 port.setDeviceOwner(null);
669 target.removeInterface(input.getPortUUID());
670 if (instances != null) {
671 for (Object instance : instances) {
672 INeutronRouterAware service = (INeutronRouterAware) instance;
673 service.canDetachInterface(target, input);
675 } for (Object instance : instances) {
676 INeutronRouterAware service = (INeutronRouterAware) instance;
677 service.neutronRouterInterfaceDetached(target, input);
679 return Response.status(200).entity(input).build();
682 // have to specify either a port ID or a subnet ID
683 throw new BadRequestException("Must specify port id or subnet id or both");