2 * Copyright IBM Corporation, 2013. All rights reserved.
\r
4 * This program and the accompanying materials are made available under the
\r
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
\r
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
\r
9 package org.opendaylight.controller.networkconfig.neutron.northbound;
\r
11 import java.util.ArrayList;
\r
12 import java.util.Iterator;
\r
13 import java.util.List;
\r
14 import javax.ws.rs.Consumes;
\r
15 import javax.ws.rs.DELETE;
\r
16 import javax.ws.rs.GET;
\r
17 import javax.ws.rs.POST;
\r
18 import javax.ws.rs.PUT;
\r
19 import javax.ws.rs.Path;
\r
20 import javax.ws.rs.PathParam;
\r
21 import javax.ws.rs.Produces;
\r
22 import javax.ws.rs.QueryParam;
\r
23 import javax.ws.rs.core.MediaType;
\r
24 import javax.ws.rs.core.Response;
\r
26 import org.codehaus.enunciate.jaxrs.ResponseCode;
\r
27 import org.codehaus.enunciate.jaxrs.StatusCodes;
\r
28 import org.opendaylight.controller.networkconfig.neutron.INeutronNetworkCRUD;
\r
29 import org.opendaylight.controller.networkconfig.neutron.INeutronPortCRUD;
\r
30 import org.opendaylight.controller.networkconfig.neutron.INeutronRouterAware;
\r
31 import org.opendaylight.controller.networkconfig.neutron.INeutronRouterCRUD;
\r
32 import org.opendaylight.controller.networkconfig.neutron.INeutronSubnetCRUD;
\r
33 import org.opendaylight.controller.networkconfig.neutron.NeutronNetwork;
\r
34 import org.opendaylight.controller.networkconfig.neutron.NeutronPort;
\r
35 import org.opendaylight.controller.networkconfig.neutron.NeutronRouter;
\r
36 import org.opendaylight.controller.networkconfig.neutron.NeutronRouter_Interface;
\r
37 import org.opendaylight.controller.networkconfig.neutron.NeutronSubnet;
\r
38 import org.opendaylight.controller.northbound.commons.RestMessages;
\r
39 import org.opendaylight.controller.northbound.commons.exception.ServiceUnavailableException;
\r
40 import org.opendaylight.controller.sal.utils.ServiceHelper;
\r
44 * Open DOVE Northbound REST APIs.<br>
\r
45 * This class provides REST APIs for managing the open DOVE
\r
49 * Authentication scheme : <b>HTTP Basic</b><br>
\r
50 * Authentication realm : <b>opendaylight</b><br>
\r
51 * Transport : <b>HTTP and HTTPS</b><br>
\r
53 * HTTPS Authentication is disabled by default. Administrator can enable it in
\r
54 * tomcat-server.xml after adding a proper keystore / SSL certificate from a
\r
55 * trusted authority.<br>
\r
57 * http://tomcat.apache.org/tomcat-7.0-doc/ssl-howto.html#Configuration
\r
62 public class NeutronRoutersNorthbound {
\r
64 private NeutronRouter extractFields(NeutronRouter o, List<String> fields) {
\r
65 return o.extractFields(fields);
\r
69 * Returns a list of all Routers */
\r
72 @Produces({ MediaType.APPLICATION_JSON })
\r
73 //@TypeHint(OpenStackRouters.class)
\r
75 @ResponseCode(code = 200, condition = "Operation successful"),
\r
76 @ResponseCode(code = 401, condition = "Unauthorized"),
\r
77 @ResponseCode(code = 501, condition = "Not Implemented") })
\r
78 public Response listRouters(
\r
80 @QueryParam("fields") List<String> fields,
\r
81 // note: openstack isn't clear about filtering on lists, so we aren't handling them
\r
82 @QueryParam("id") String queryID,
\r
83 @QueryParam("name") String queryName,
\r
84 @QueryParam("admin_state_up") String queryAdminStateUp,
\r
85 @QueryParam("status") String queryStatus,
\r
86 @QueryParam("tenant_id") String queryTenantID,
\r
87 @QueryParam("external_gateway_info") String queryExternalGatewayInfo,
\r
89 @QueryParam("limit") String limit,
\r
90 @QueryParam("marker") String marker,
\r
91 @QueryParam("page_reverse") String pageReverse
\r
92 // sorting not supported
\r
94 INeutronRouterCRUD routerInterface = NeutronNBInterfaces.getIfNBRouterCRUD("default",this);
\r
95 if (routerInterface == null) {
\r
96 throw new ServiceUnavailableException("Router CRUD Interface "
\r
97 + RestMessages.SERVICEUNAVAILABLE.toString());
\r
99 List<NeutronRouter> allRouters = routerInterface.getAllRouters();
\r
100 List<NeutronRouter> ans = new ArrayList<NeutronRouter>();
\r
101 Iterator<NeutronRouter> i = allRouters.iterator();
\r
102 while (i.hasNext()) {
\r
103 NeutronRouter oSS = i.next();
\r
104 if ((queryID == null || queryID.equals(oSS.getID())) &&
\r
105 (queryName == null || queryName.equals(oSS.getName())) &&
\r
106 (queryAdminStateUp == null || queryAdminStateUp.equals(oSS.getAdminStateUp())) &&
\r
107 (queryStatus == null || queryStatus.equals(oSS.getStatus())) &&
\r
108 (queryExternalGatewayInfo == null || queryExternalGatewayInfo.equals(oSS.getExternalGatewayInfo())) &&
\r
109 (queryTenantID == null || queryTenantID.equals(oSS.getTenantID()))) {
\r
110 if (fields.size() > 0)
\r
111 ans.add(extractFields(oSS,fields));
\r
116 //TODO: apply pagination to results
\r
117 return Response.status(200).entity(
\r
118 new NeutronRouterRequest(ans)).build();
\r
122 * Returns a specific Router */
\r
124 @Path("{routerUUID}")
\r
126 @Produces({ MediaType.APPLICATION_JSON })
\r
127 //@TypeHint(OpenStackRouters.class)
\r
129 @ResponseCode(code = 200, condition = "Operation successful"),
\r
130 @ResponseCode(code = 401, condition = "Unauthorized"),
\r
131 @ResponseCode(code = 403, condition = "Forbidden"),
\r
132 @ResponseCode(code = 404, condition = "Not Found"),
\r
133 @ResponseCode(code = 501, condition = "Not Implemented") })
\r
134 public Response showRouter(
\r
135 @PathParam("routerUUID") String routerUUID,
\r
137 @QueryParam("fields") List<String> fields) {
\r
138 INeutronRouterCRUD routerInterface = NeutronNBInterfaces.getIfNBRouterCRUD("default",this);
\r
139 if (routerInterface == null) {
\r
140 throw new ServiceUnavailableException("Router CRUD Interface "
\r
141 + RestMessages.SERVICEUNAVAILABLE.toString());
\r
143 if (!routerInterface.routerExists(routerUUID))
\r
144 return Response.status(404).build();
\r
145 if (fields.size() > 0) {
\r
146 NeutronRouter ans = routerInterface.getRouter(routerUUID);
\r
147 return Response.status(200).entity(
\r
148 new NeutronRouterRequest(extractFields(ans, fields))).build();
\r
150 return Response.status(200).entity(
\r
151 new NeutronRouterRequest(routerInterface.getRouter(routerUUID))).build();
\r
155 * Creates new Routers */
\r
158 @Produces({ MediaType.APPLICATION_JSON })
\r
159 @Consumes({ MediaType.APPLICATION_JSON })
\r
160 //@TypeHint(OpenStackRouters.class)
\r
162 @ResponseCode(code = 201, condition = "Created"),
\r
163 @ResponseCode(code = 400, condition = "Bad Request"),
\r
164 @ResponseCode(code = 401, condition = "Unauthorized"),
\r
165 @ResponseCode(code = 501, condition = "Not Implemented") })
\r
166 public Response createRouters(final NeutronRouterRequest input) {
\r
167 INeutronRouterCRUD routerInterface = NeutronNBInterfaces.getIfNBRouterCRUD("default",this);
\r
168 if (routerInterface == null) {
\r
169 throw new ServiceUnavailableException("Router CRUD Interface "
\r
170 + RestMessages.SERVICEUNAVAILABLE.toString());
\r
172 INeutronNetworkCRUD networkInterface = NeutronNBInterfaces.getIfNBNetworkCRUD("default", this);
\r
173 if (networkInterface == null) {
\r
174 throw new ServiceUnavailableException("Network CRUD Interface "
\r
175 + RestMessages.SERVICEUNAVAILABLE.toString());
\r
177 if (input.isSingleton()) {
\r
178 NeutronRouter singleton = input.getSingleton();
\r
181 * verify that the router doesn't already exist (issue: is deeper inspection necessary?)
\r
182 * if there is external gateway information provided, verify that the specified network
\r
183 * exists and has been designated as "router:external"
\r
185 if (routerInterface.routerExists(singleton.getID()))
\r
186 return Response.status(400).build();
\r
187 if (singleton.getExternalGatewayInfo() != null) {
\r
188 String externNetworkPtr = singleton.getExternalGatewayInfo().getNetworkID();
\r
189 if (!networkInterface.networkExists(externNetworkPtr))
\r
190 return Response.status(400).build();
\r
191 NeutronNetwork externNetwork = networkInterface.getNetwork(externNetworkPtr);
\r
192 if (!externNetwork.isRouterExternal())
\r
193 return Response.status(400).build();
\r
195 Object[] instances = ServiceHelper.getGlobalInstances(INeutronRouterAware.class, this, null);
\r
196 if (instances != null) {
\r
197 for (Object instance : instances) {
\r
198 INeutronRouterAware service = (INeutronRouterAware) instance;
\r
199 int status = service.canCreateRouter(singleton);
\r
200 if (status < 200 || status > 299)
\r
201 return Response.status(status).build();
\r
206 * add router to the cache
\r
208 routerInterface.addRouter(singleton);
\r
209 if (instances != null) {
\r
210 for (Object instance : instances) {
\r
211 INeutronRouterAware service = (INeutronRouterAware) instance;
\r
212 service.neutronRouterCreated(singleton);
\r
218 * only singleton router creates supported
\r
220 return Response.status(400).build();
\r
222 return Response.status(201).entity(input).build();
\r
226 * Updates a Router */
\r
228 @Path("{routerUUID}")
\r
230 @Produces({ MediaType.APPLICATION_JSON })
\r
231 @Consumes({ MediaType.APPLICATION_JSON })
\r
232 //@TypeHint(OpenStackRouters.class)
\r
234 @ResponseCode(code = 200, condition = "Operation successful"),
\r
235 @ResponseCode(code = 400, condition = "Bad Request"),
\r
236 @ResponseCode(code = 401, condition = "Unauthorized"),
\r
237 @ResponseCode(code = 404, condition = "Not Found"),
\r
238 @ResponseCode(code = 501, condition = "Not Implemented") })
\r
239 public Response updateRouter(
\r
240 @PathParam("routerUUID") String routerUUID,
\r
241 NeutronRouterRequest input
\r
243 INeutronRouterCRUD routerInterface = NeutronNBInterfaces.getIfNBRouterCRUD("default",this);
\r
244 if (routerInterface == null) {
\r
245 throw new ServiceUnavailableException("Router CRUD Interface "
\r
246 + RestMessages.SERVICEUNAVAILABLE.toString());
\r
248 INeutronNetworkCRUD networkInterface = NeutronNBInterfaces.getIfNBNetworkCRUD("default", this);
\r
249 if (networkInterface == null) {
\r
250 throw new ServiceUnavailableException("Network CRUD Interface "
\r
251 + RestMessages.SERVICEUNAVAILABLE.toString());
\r
255 * router has to exist and only a single delta can be supplied
\r
257 if (!routerInterface.routerExists(routerUUID))
\r
258 return Response.status(404).build();
\r
259 if (!input.isSingleton())
\r
260 return Response.status(400).build();
\r
261 NeutronRouter singleton = input.getSingleton();
\r
262 NeutronRouter original = routerInterface.getRouter(routerUUID);
\r
265 * attribute changes blocked by Neutron
\r
267 if (singleton.getID() != null || singleton.getTenantID() != null ||
\r
268 singleton.getStatus() != null)
\r
269 return Response.status(400).build();
\r
271 Object[] instances = ServiceHelper.getGlobalInstances(INeutronRouterAware.class, this, null);
\r
272 if (instances != null) {
\r
273 for (Object instance : instances) {
\r
274 INeutronRouterAware service = (INeutronRouterAware) instance;
\r
275 int status = service.canUpdateRouter(singleton, original);
\r
276 if (status < 200 || status > 299)
\r
277 return Response.status(status).build();
\r
281 * if the external gateway info is being changed, verify that the new network
\r
282 * exists and has been designated as an external network
\r
284 if (singleton.getExternalGatewayInfo() != null) {
\r
285 String externNetworkPtr = singleton.getExternalGatewayInfo().getNetworkID();
\r
286 if (!networkInterface.networkExists(externNetworkPtr))
\r
287 return Response.status(400).build();
\r
288 NeutronNetwork externNetwork = networkInterface.getNetwork(externNetworkPtr);
\r
289 if (!externNetwork.isRouterExternal())
\r
290 return Response.status(400).build();
\r
294 * update the router entry and return the modified object
\r
296 routerInterface.updateRouter(routerUUID, singleton);
\r
297 NeutronRouter updatedRouter = routerInterface.getRouter(routerUUID);
\r
298 if (instances != null) {
\r
299 for (Object instance : instances) {
\r
300 INeutronRouterAware service = (INeutronRouterAware) instance;
\r
301 service.neutronRouterUpdated(updatedRouter);
\r
304 return Response.status(200).entity(
\r
305 new NeutronRouterRequest(routerInterface.getRouter(routerUUID))).build();
\r
310 * Deletes a Router */
\r
312 @Path("{routerUUID}")
\r
315 @ResponseCode(code = 204, condition = "No Content"),
\r
316 @ResponseCode(code = 401, condition = "Unauthorized"),
\r
317 @ResponseCode(code = 404, condition = "Not Found"),
\r
318 @ResponseCode(code = 409, condition = "Conflict"),
\r
319 @ResponseCode(code = 501, condition = "Not Implemented") })
\r
320 public Response deleteRouter(
\r
321 @PathParam("routerUUID") String routerUUID) {
\r
322 INeutronRouterCRUD routerInterface = NeutronNBInterfaces.getIfNBRouterCRUD("default",this);
\r
323 if (routerInterface == null) {
\r
324 throw new ServiceUnavailableException("Router CRUD Interface "
\r
325 + RestMessages.SERVICEUNAVAILABLE.toString());
\r
329 * verify that the router exists and is not in use before removing it
\r
331 if (!routerInterface.routerExists(routerUUID))
\r
332 return Response.status(404).build();
\r
333 if (routerInterface.routerInUse(routerUUID))
\r
334 return Response.status(409).build();
\r
335 NeutronRouter singleton = routerInterface.getRouter(routerUUID);
\r
336 Object[] instances = ServiceHelper.getGlobalInstances(INeutronRouterAware.class, this, null);
\r
337 if (instances != null) {
\r
338 for (Object instance : instances) {
\r
339 INeutronRouterAware service = (INeutronRouterAware) instance;
\r
340 int status = service.canDeleteRouter(singleton);
\r
341 if (status < 200 || status > 299)
\r
342 return Response.status(status).build();
\r
345 routerInterface.removeRouter(routerUUID);
\r
346 if (instances != null) {
\r
347 for (Object instance : instances) {
\r
348 INeutronRouterAware service = (INeutronRouterAware) instance;
\r
349 service.neutronRouterDeleted(singleton);
\r
352 return Response.status(204).build();
\r
356 * Adds an interface to a router */
\r
358 @Path("{routerUUID}/add_router_interface")
\r
360 @Produces({ MediaType.APPLICATION_JSON })
\r
361 @Consumes({ MediaType.APPLICATION_JSON })
\r
362 //@TypeHint(OpenStackRouterInterfaces.class)
\r
364 @ResponseCode(code = 200, condition = "Operation successful"),
\r
365 @ResponseCode(code = 400, condition = "Bad Request"),
\r
366 @ResponseCode(code = 401, condition = "Unauthorized"),
\r
367 @ResponseCode(code = 404, condition = "Not Found"),
\r
368 @ResponseCode(code = 409, condition = "Conflict"),
\r
369 @ResponseCode(code = 501, condition = "Not Implemented") })
\r
370 public Response addRouterInterface(
\r
371 @PathParam("routerUUID") String routerUUID,
\r
372 NeutronRouter_Interface input
\r
374 INeutronRouterCRUD routerInterface = NeutronNBInterfaces.getIfNBRouterCRUD("default",this);
\r
375 if (routerInterface == null) {
\r
376 throw new ServiceUnavailableException("Router CRUD Interface "
\r
377 + RestMessages.SERVICEUNAVAILABLE.toString());
\r
379 INeutronPortCRUD portInterface = NeutronNBInterfaces.getIfNBPortCRUD("default",this);
\r
380 if (portInterface == null) {
\r
381 throw new ServiceUnavailableException("Port CRUD Interface "
\r
382 + RestMessages.SERVICEUNAVAILABLE.toString());
\r
384 INeutronSubnetCRUD subnetInterface = NeutronNBInterfaces.getIfNBSubnetCRUD("default",this);
\r
385 if (subnetInterface == null) {
\r
386 throw new ServiceUnavailableException("Subnet CRUD Interface "
\r
387 + RestMessages.SERVICEUNAVAILABLE.toString());
\r
391 * While the Neutron specification says that the router has to exist and the input can only specify either a subnet id
\r
392 * 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
\r
394 if (!routerInterface.routerExists(routerUUID))
\r
395 return Response.status(400).build();
\r
396 NeutronRouter target = routerInterface.getRouter(routerUUID);
\r
397 if (input.getSubnetUUID() == null ||
\r
398 input.getPortUUID() == null)
\r
399 return Response.status(400).build();
\r
401 // check that the port is part of the subnet
\r
402 NeutronSubnet targetSubnet = subnetInterface.getSubnet(input.getSubnetUUID());
\r
403 if (targetSubnet == null)
\r
404 return Response.status(400).build();
\r
405 NeutronPort targetPort = portInterface.getPort(input.getPortUUID());
\r
406 if (targetPort == null)
\r
407 return Response.status(400).build();
\r
408 if (!targetSubnet.getPortsInSubnet().contains(targetPort))
\r
409 return Response.status(400).build();
\r
411 if (targetPort.getFixedIPs().size() != 1)
\r
412 return Response.status(400).build();
\r
413 if (targetPort.getDeviceID() != null ||
\r
414 targetPort.getDeviceOwner() != null)
\r
415 return Response.status(409).build();
\r
417 Object[] instances = ServiceHelper.getGlobalInstances(INeutronRouterAware.class, this, null);
\r
418 if (instances != null) {
\r
419 for (Object instance : instances) {
\r
420 INeutronRouterAware service = (INeutronRouterAware) instance;
\r
421 service.canAttachInterface(target, input);
\r
425 //mark the port device id and device owner fields
\r
426 targetPort.setDeviceOwner("network:router_interface");
\r
427 targetPort.setDeviceID(routerUUID);
\r
429 target.addInterface(input.getPortUUID(), input);
\r
430 if (instances != null) {
\r
431 for (Object instance : instances) {
\r
432 INeutronRouterAware service = (INeutronRouterAware) instance;
\r
433 service.neutronRouterInterfaceAttached(target, input);
\r
437 return Response.status(200).entity(input).build();
\r
441 * Removes an interface to a router */
\r
443 @Path("{routerUUID}/remove_router_interface")
\r
445 @Produces({ MediaType.APPLICATION_JSON })
\r
446 @Consumes({ MediaType.APPLICATION_JSON })
\r
447 //@TypeHint(OpenStackRouterInterfaces.class)
\r
449 @ResponseCode(code = 200, condition = "Operation successful"),
\r
450 @ResponseCode(code = 400, condition = "Bad Request"),
\r
451 @ResponseCode(code = 401, condition = "Unauthorized"),
\r
452 @ResponseCode(code = 404, condition = "Not Found"),
\r
453 @ResponseCode(code = 409, condition = "Conflict"),
\r
454 @ResponseCode(code = 501, condition = "Not Implemented") })
\r
455 public Response removeRouterInterface(
\r
456 @PathParam("routerUUID") String routerUUID,
\r
457 NeutronRouter_Interface input
\r
459 INeutronRouterCRUD routerInterface = NeutronNBInterfaces.getIfNBRouterCRUD("default",this);
\r
460 if (routerInterface == null) {
\r
461 throw new ServiceUnavailableException("Router CRUD Interface "
\r
462 + RestMessages.SERVICEUNAVAILABLE.toString());
\r
464 INeutronPortCRUD portInterface = NeutronNBInterfaces.getIfNBPortCRUD("default",this);
\r
465 if (portInterface == null) {
\r
466 throw new ServiceUnavailableException("Port CRUD Interface "
\r
467 + RestMessages.SERVICEUNAVAILABLE.toString());
\r
469 INeutronSubnetCRUD subnetInterface = NeutronNBInterfaces.getIfNBSubnetCRUD("default",this);
\r
470 if (subnetInterface == null) {
\r
471 throw new ServiceUnavailableException("Subnet CRUD Interface "
\r
472 + RestMessages.SERVICEUNAVAILABLE.toString());
\r
475 // verify the router exists
\r
476 if (!routerInterface.routerExists(routerUUID))
\r
477 return Response.status(400).build();
\r
478 NeutronRouter target = routerInterface.getRouter(routerUUID);
\r
481 * remove by subnet id. Collect information about the impacted router for the response and
\r
482 * remove the port corresponding to the gateway IP address of the subnet
\r
484 if (input.getPortUUID() == null &&
\r
485 input.getSubnetUUID() != null) {
\r
486 NeutronPort port = portInterface.getGatewayPort(input.getSubnetUUID());
\r
488 return Response.status(404).build();
\r
489 input.setPortUUID(port.getID());
\r
490 input.setID(target.getID());
\r
491 input.setTenantID(target.getTenantID());
\r
493 Object[] instances = ServiceHelper.getGlobalInstances(INeutronRouterAware.class, this, null);
\r
494 if (instances != null) {
\r
495 for (Object instance : instances) {
\r
496 INeutronRouterAware service = (INeutronRouterAware) instance;
\r
497 service.canDetachInterface(target, input);
\r
501 // reset the port ownership
\r
502 port.setDeviceID(null);
\r
503 port.setDeviceOwner(null);
\r
505 target.removeInterface(input.getPortUUID());
\r
506 if (instances != null) {
\r
507 for (Object instance : instances) {
\r
508 INeutronRouterAware service = (INeutronRouterAware) instance;
\r
509 service.neutronRouterInterfaceDetached(target, input);
\r
512 return Response.status(200).entity(input).build();
\r
516 * remove by port id. collect information about the impacted router for the response
\r
517 * remove the interface and reset the port ownership
\r
519 if (input.getPortUUID() != null &&
\r
520 input.getSubnetUUID() == null) {
\r
521 NeutronRouter_Interface targetInterface = target.getInterfaces().get(input.getPortUUID());
\r
522 input.setSubnetUUID(targetInterface.getSubnetUUID());
\r
523 input.setID(target.getID());
\r
524 input.setTenantID(target.getTenantID());
\r
525 NeutronPort port = portInterface.getPort(input.getPortUUID());
\r
526 port.setDeviceID(null);
\r
527 port.setDeviceOwner(null);
\r
528 target.removeInterface(input.getPortUUID());
\r
529 Object[] instances = ServiceHelper.getGlobalInstances(INeutronRouterAware.class, this, null);
\r
530 for (Object instance : instances) {
\r
531 INeutronRouterAware service = (INeutronRouterAware) instance;
\r
532 service.neutronRouterInterfaceDetached(target, input);
\r
534 return Response.status(200).entity(input).build();
\r
538 * remove by both port and subnet ID. Verify that the first fixed IP of the port is a valid
\r
539 * IP address for the subnet, and then remove the interface, collecting information about the
\r
540 * impacted router for the response and reset port ownership
\r
542 if (input.getPortUUID() != null &&
\r
543 input.getSubnetUUID() != null) {
\r
544 NeutronPort port = portInterface.getPort(input.getPortUUID());
\r
545 NeutronSubnet subnet = subnetInterface.getSubnet(input.getSubnetUUID());
\r
546 if (!subnet.isValidIP(port.getFixedIPs().get(0).getIpAddress()))
\r
547 return Response.status(409).build();
\r
548 input.setID(target.getID());
\r
549 input.setTenantID(target.getTenantID());
\r
550 Object[] instances = ServiceHelper.getGlobalInstances(INeutronRouterAware.class, this, null);
\r
551 if (instances != null) {
\r
552 for (Object instance : instances) {
\r
553 INeutronRouterAware service = (INeutronRouterAware) instance;
\r
554 service.canDetachInterface(target, input);
\r
557 port.setDeviceID(null);
\r
558 port.setDeviceOwner(null);
\r
559 target.removeInterface(input.getPortUUID());
\r
560 for (Object instance : instances) {
\r
561 INeutronRouterAware service = (INeutronRouterAware) instance;
\r
562 service.neutronRouterInterfaceDetached(target, input);
\r
564 return Response.status(200).entity(input).build();
\r
567 // have to specify either a port ID or a subnet ID
\r
568 return Response.status(400).build();
\r