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.NeutronCRUDInterfaces;
\r
34 import org.opendaylight.controller.networkconfig.neutron.NeutronNetwork;
\r
35 import org.opendaylight.controller.networkconfig.neutron.NeutronPort;
\r
36 import org.opendaylight.controller.networkconfig.neutron.NeutronRouter;
\r
37 import org.opendaylight.controller.networkconfig.neutron.NeutronRouter_Interface;
\r
38 import org.opendaylight.controller.networkconfig.neutron.NeutronSubnet;
\r
39 import org.opendaylight.controller.northbound.commons.RestMessages;
\r
40 import org.opendaylight.controller.northbound.commons.exception.ServiceUnavailableException;
\r
41 import org.opendaylight.controller.sal.utils.ServiceHelper;
\r
45 * Open DOVE Northbound REST APIs.<br>
\r
46 * This class provides REST APIs for managing the open DOVE
\r
50 * Authentication scheme : <b>HTTP Basic</b><br>
\r
51 * Authentication realm : <b>opendaylight</b><br>
\r
52 * Transport : <b>HTTP and HTTPS</b><br>
\r
54 * HTTPS Authentication is disabled by default. Administrator can enable it in
\r
55 * tomcat-server.xml after adding a proper keystore / SSL certificate from a
\r
56 * trusted authority.<br>
\r
58 * http://tomcat.apache.org/tomcat-7.0-doc/ssl-howto.html#Configuration
\r
63 public class NeutronRoutersNorthbound {
\r
65 private NeutronRouter extractFields(NeutronRouter o, List<String> fields) {
\r
66 return o.extractFields(fields);
\r
70 * Returns a list of all Routers */
\r
73 @Produces({ MediaType.APPLICATION_JSON })
\r
74 //@TypeHint(OpenStackRouters.class)
\r
76 @ResponseCode(code = 200, condition = "Operation successful"),
\r
77 @ResponseCode(code = 401, condition = "Unauthorized"),
\r
78 @ResponseCode(code = 501, condition = "Not Implemented") })
\r
79 public Response listRouters(
\r
81 @QueryParam("fields") List<String> fields,
\r
82 // note: openstack isn't clear about filtering on lists, so we aren't handling them
\r
83 @QueryParam("id") String queryID,
\r
84 @QueryParam("name") String queryName,
\r
85 @QueryParam("admin_state_up") String queryAdminStateUp,
\r
86 @QueryParam("status") String queryStatus,
\r
87 @QueryParam("tenant_id") String queryTenantID,
\r
88 @QueryParam("external_gateway_info") String queryExternalGatewayInfo,
\r
90 @QueryParam("limit") String limit,
\r
91 @QueryParam("marker") String marker,
\r
92 @QueryParam("page_reverse") String pageReverse
\r
93 // sorting not supported
\r
95 INeutronRouterCRUD routerInterface = NeutronCRUDInterfaces.getINeutronRouterCRUD(this);
\r
96 if (routerInterface == null) {
\r
97 throw new ServiceUnavailableException("Router CRUD Interface "
\r
98 + RestMessages.SERVICEUNAVAILABLE.toString());
\r
100 List<NeutronRouter> allRouters = routerInterface.getAllRouters();
\r
101 List<NeutronRouter> ans = new ArrayList<NeutronRouter>();
\r
102 Iterator<NeutronRouter> i = allRouters.iterator();
\r
103 while (i.hasNext()) {
\r
104 NeutronRouter oSS = i.next();
\r
105 if ((queryID == null || queryID.equals(oSS.getID())) &&
\r
106 (queryName == null || queryName.equals(oSS.getName())) &&
\r
107 (queryAdminStateUp == null || queryAdminStateUp.equals(oSS.getAdminStateUp())) &&
\r
108 (queryStatus == null || queryStatus.equals(oSS.getStatus())) &&
\r
109 (queryExternalGatewayInfo == null || queryExternalGatewayInfo.equals(oSS.getExternalGatewayInfo())) &&
\r
110 (queryTenantID == null || queryTenantID.equals(oSS.getTenantID()))) {
\r
111 if (fields.size() > 0)
\r
112 ans.add(extractFields(oSS,fields));
\r
117 //TODO: apply pagination to results
\r
118 return Response.status(200).entity(
\r
119 new NeutronRouterRequest(ans)).build();
\r
123 * Returns a specific Router */
\r
125 @Path("{routerUUID}")
\r
127 @Produces({ MediaType.APPLICATION_JSON })
\r
128 //@TypeHint(OpenStackRouters.class)
\r
130 @ResponseCode(code = 200, condition = "Operation successful"),
\r
131 @ResponseCode(code = 401, condition = "Unauthorized"),
\r
132 @ResponseCode(code = 403, condition = "Forbidden"),
\r
133 @ResponseCode(code = 404, condition = "Not Found"),
\r
134 @ResponseCode(code = 501, condition = "Not Implemented") })
\r
135 public Response showRouter(
\r
136 @PathParam("routerUUID") String routerUUID,
\r
138 @QueryParam("fields") List<String> fields) {
\r
139 INeutronRouterCRUD routerInterface = NeutronCRUDInterfaces.getINeutronRouterCRUD(this);
\r
140 if (routerInterface == null) {
\r
141 throw new ServiceUnavailableException("Router CRUD Interface "
\r
142 + RestMessages.SERVICEUNAVAILABLE.toString());
\r
144 if (!routerInterface.routerExists(routerUUID))
\r
145 return Response.status(404).build();
\r
146 if (fields.size() > 0) {
\r
147 NeutronRouter ans = routerInterface.getRouter(routerUUID);
\r
148 return Response.status(200).entity(
\r
149 new NeutronRouterRequest(extractFields(ans, fields))).build();
\r
151 return Response.status(200).entity(
\r
152 new NeutronRouterRequest(routerInterface.getRouter(routerUUID))).build();
\r
156 * Creates new Routers */
\r
159 @Produces({ MediaType.APPLICATION_JSON })
\r
160 @Consumes({ MediaType.APPLICATION_JSON })
\r
161 //@TypeHint(OpenStackRouters.class)
\r
163 @ResponseCode(code = 201, condition = "Created"),
\r
164 @ResponseCode(code = 400, condition = "Bad Request"),
\r
165 @ResponseCode(code = 401, condition = "Unauthorized"),
\r
166 @ResponseCode(code = 501, condition = "Not Implemented") })
\r
167 public Response createRouters(final NeutronRouterRequest input) {
\r
168 INeutronRouterCRUD routerInterface = NeutronCRUDInterfaces.getINeutronRouterCRUD(this);
\r
169 if (routerInterface == null) {
\r
170 throw new ServiceUnavailableException("Router CRUD Interface "
\r
171 + RestMessages.SERVICEUNAVAILABLE.toString());
\r
173 INeutronNetworkCRUD networkInterface = NeutronCRUDInterfaces.getINeutronNetworkCRUD( this);
\r
174 if (networkInterface == null) {
\r
175 throw new ServiceUnavailableException("Network CRUD Interface "
\r
176 + RestMessages.SERVICEUNAVAILABLE.toString());
\r
178 if (input.isSingleton()) {
\r
179 NeutronRouter singleton = input.getSingleton();
\r
182 * verify that the router doesn't already exist (issue: is deeper inspection necessary?)
\r
183 * if there is external gateway information provided, verify that the specified network
\r
184 * exists and has been designated as "router:external"
\r
186 if (routerInterface.routerExists(singleton.getID()))
\r
187 return Response.status(400).build();
\r
188 if (singleton.getExternalGatewayInfo() != null) {
\r
189 String externNetworkPtr = singleton.getExternalGatewayInfo().getNetworkID();
\r
190 if (!networkInterface.networkExists(externNetworkPtr))
\r
191 return Response.status(400).build();
\r
192 NeutronNetwork externNetwork = networkInterface.getNetwork(externNetworkPtr);
\r
193 if (!externNetwork.isRouterExternal())
\r
194 return Response.status(400).build();
\r
196 Object[] instances = ServiceHelper.getGlobalInstances(INeutronRouterAware.class, this, null);
\r
197 if (instances != null) {
\r
198 for (Object instance : instances) {
\r
199 INeutronRouterAware service = (INeutronRouterAware) instance;
\r
200 int status = service.canCreateRouter(singleton);
\r
201 if (status < 200 || status > 299)
\r
202 return Response.status(status).build();
\r
207 * add router to the cache
\r
209 routerInterface.addRouter(singleton);
\r
210 if (instances != null) {
\r
211 for (Object instance : instances) {
\r
212 INeutronRouterAware service = (INeutronRouterAware) instance;
\r
213 service.neutronRouterCreated(singleton);
\r
219 * only singleton router creates supported
\r
221 return Response.status(400).build();
\r
223 return Response.status(201).entity(input).build();
\r
227 * Updates a Router */
\r
229 @Path("{routerUUID}")
\r
231 @Produces({ MediaType.APPLICATION_JSON })
\r
232 @Consumes({ MediaType.APPLICATION_JSON })
\r
233 //@TypeHint(OpenStackRouters.class)
\r
235 @ResponseCode(code = 200, condition = "Operation successful"),
\r
236 @ResponseCode(code = 400, condition = "Bad Request"),
\r
237 @ResponseCode(code = 401, condition = "Unauthorized"),
\r
238 @ResponseCode(code = 404, condition = "Not Found"),
\r
239 @ResponseCode(code = 501, condition = "Not Implemented") })
\r
240 public Response updateRouter(
\r
241 @PathParam("routerUUID") String routerUUID,
\r
242 NeutronRouterRequest input
\r
244 INeutronRouterCRUD routerInterface = NeutronCRUDInterfaces.getINeutronRouterCRUD(this);
\r
245 if (routerInterface == null) {
\r
246 throw new ServiceUnavailableException("Router CRUD Interface "
\r
247 + RestMessages.SERVICEUNAVAILABLE.toString());
\r
249 INeutronNetworkCRUD networkInterface = NeutronCRUDInterfaces.getINeutronNetworkCRUD( this);
\r
250 if (networkInterface == null) {
\r
251 throw new ServiceUnavailableException("Network CRUD Interface "
\r
252 + RestMessages.SERVICEUNAVAILABLE.toString());
\r
256 * router has to exist and only a single delta can be supplied
\r
258 if (!routerInterface.routerExists(routerUUID))
\r
259 return Response.status(404).build();
\r
260 if (!input.isSingleton())
\r
261 return Response.status(400).build();
\r
262 NeutronRouter singleton = input.getSingleton();
\r
263 NeutronRouter original = routerInterface.getRouter(routerUUID);
\r
266 * attribute changes blocked by Neutron
\r
268 if (singleton.getID() != null || singleton.getTenantID() != null ||
\r
269 singleton.getStatus() != null)
\r
270 return Response.status(400).build();
\r
272 Object[] instances = ServiceHelper.getGlobalInstances(INeutronRouterAware.class, this, null);
\r
273 if (instances != null) {
\r
274 for (Object instance : instances) {
\r
275 INeutronRouterAware service = (INeutronRouterAware) instance;
\r
276 int status = service.canUpdateRouter(singleton, original);
\r
277 if (status < 200 || status > 299)
\r
278 return Response.status(status).build();
\r
282 * if the external gateway info is being changed, verify that the new network
\r
283 * exists and has been designated as an external network
\r
285 if (singleton.getExternalGatewayInfo() != null) {
\r
286 String externNetworkPtr = singleton.getExternalGatewayInfo().getNetworkID();
\r
287 if (!networkInterface.networkExists(externNetworkPtr))
\r
288 return Response.status(400).build();
\r
289 NeutronNetwork externNetwork = networkInterface.getNetwork(externNetworkPtr);
\r
290 if (!externNetwork.isRouterExternal())
\r
291 return Response.status(400).build();
\r
295 * update the router entry and return the modified object
\r
297 routerInterface.updateRouter(routerUUID, singleton);
\r
298 NeutronRouter updatedRouter = routerInterface.getRouter(routerUUID);
\r
299 if (instances != null) {
\r
300 for (Object instance : instances) {
\r
301 INeutronRouterAware service = (INeutronRouterAware) instance;
\r
302 service.neutronRouterUpdated(updatedRouter);
\r
305 return Response.status(200).entity(
\r
306 new NeutronRouterRequest(routerInterface.getRouter(routerUUID))).build();
\r
311 * Deletes a Router */
\r
313 @Path("{routerUUID}")
\r
316 @ResponseCode(code = 204, condition = "No Content"),
\r
317 @ResponseCode(code = 401, condition = "Unauthorized"),
\r
318 @ResponseCode(code = 404, condition = "Not Found"),
\r
319 @ResponseCode(code = 409, condition = "Conflict"),
\r
320 @ResponseCode(code = 501, condition = "Not Implemented") })
\r
321 public Response deleteRouter(
\r
322 @PathParam("routerUUID") String routerUUID) {
\r
323 INeutronRouterCRUD routerInterface = NeutronCRUDInterfaces.getINeutronRouterCRUD(this);
\r
324 if (routerInterface == null) {
\r
325 throw new ServiceUnavailableException("Router CRUD Interface "
\r
326 + RestMessages.SERVICEUNAVAILABLE.toString());
\r
330 * verify that the router exists and is not in use before removing it
\r
332 if (!routerInterface.routerExists(routerUUID))
\r
333 return Response.status(404).build();
\r
334 if (routerInterface.routerInUse(routerUUID))
\r
335 return Response.status(409).build();
\r
336 NeutronRouter singleton = routerInterface.getRouter(routerUUID);
\r
337 Object[] instances = ServiceHelper.getGlobalInstances(INeutronRouterAware.class, this, null);
\r
338 if (instances != null) {
\r
339 for (Object instance : instances) {
\r
340 INeutronRouterAware service = (INeutronRouterAware) instance;
\r
341 int status = service.canDeleteRouter(singleton);
\r
342 if (status < 200 || status > 299)
\r
343 return Response.status(status).build();
\r
346 routerInterface.removeRouter(routerUUID);
\r
347 if (instances != null) {
\r
348 for (Object instance : instances) {
\r
349 INeutronRouterAware service = (INeutronRouterAware) instance;
\r
350 service.neutronRouterDeleted(singleton);
\r
353 return Response.status(204).build();
\r
357 * Adds an interface to a router */
\r
359 @Path("{routerUUID}/add_router_interface")
\r
361 @Produces({ MediaType.APPLICATION_JSON })
\r
362 @Consumes({ MediaType.APPLICATION_JSON })
\r
363 //@TypeHint(OpenStackRouterInterfaces.class)
\r
365 @ResponseCode(code = 200, condition = "Operation successful"),
\r
366 @ResponseCode(code = 400, condition = "Bad Request"),
\r
367 @ResponseCode(code = 401, condition = "Unauthorized"),
\r
368 @ResponseCode(code = 404, condition = "Not Found"),
\r
369 @ResponseCode(code = 409, condition = "Conflict"),
\r
370 @ResponseCode(code = 501, condition = "Not Implemented") })
\r
371 public Response addRouterInterface(
\r
372 @PathParam("routerUUID") String routerUUID,
\r
373 NeutronRouter_Interface input
\r
375 INeutronRouterCRUD routerInterface = NeutronCRUDInterfaces.getINeutronRouterCRUD(this);
\r
376 if (routerInterface == null) {
\r
377 throw new ServiceUnavailableException("Router CRUD Interface "
\r
378 + RestMessages.SERVICEUNAVAILABLE.toString());
\r
380 INeutronPortCRUD portInterface = NeutronCRUDInterfaces.getINeutronPortCRUD(this);
\r
381 if (portInterface == null) {
\r
382 throw new ServiceUnavailableException("Port CRUD Interface "
\r
383 + RestMessages.SERVICEUNAVAILABLE.toString());
\r
385 INeutronSubnetCRUD subnetInterface = NeutronCRUDInterfaces.getINeutronSubnetCRUD(this);
\r
386 if (subnetInterface == null) {
\r
387 throw new ServiceUnavailableException("Subnet CRUD Interface "
\r
388 + RestMessages.SERVICEUNAVAILABLE.toString());
\r
392 * While the Neutron specification says that the router has to exist and the input can only specify either a subnet id
\r
393 * 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
395 if (!routerInterface.routerExists(routerUUID))
\r
396 return Response.status(400).build();
\r
397 NeutronRouter target = routerInterface.getRouter(routerUUID);
\r
398 if (input.getSubnetUUID() == null ||
\r
399 input.getPortUUID() == null)
\r
400 return Response.status(400).build();
\r
402 // check that the port is part of the subnet
\r
403 NeutronSubnet targetSubnet = subnetInterface.getSubnet(input.getSubnetUUID());
\r
404 if (targetSubnet == null)
\r
405 return Response.status(400).build();
\r
406 NeutronPort targetPort = portInterface.getPort(input.getPortUUID());
\r
407 if (targetPort == null)
\r
408 return Response.status(400).build();
\r
409 if (!targetSubnet.getPortsInSubnet().contains(targetPort))
\r
410 return Response.status(400).build();
\r
412 if (targetPort.getFixedIPs().size() != 1)
\r
413 return Response.status(400).build();
\r
414 if (targetPort.getDeviceID() != null ||
\r
415 targetPort.getDeviceOwner() != null)
\r
416 return Response.status(409).build();
\r
418 Object[] instances = ServiceHelper.getGlobalInstances(INeutronRouterAware.class, this, null);
\r
419 if (instances != null) {
\r
420 for (Object instance : instances) {
\r
421 INeutronRouterAware service = (INeutronRouterAware) instance;
\r
422 service.canAttachInterface(target, input);
\r
426 //mark the port device id and device owner fields
\r
427 targetPort.setDeviceOwner("network:router_interface");
\r
428 targetPort.setDeviceID(routerUUID);
\r
430 target.addInterface(input.getPortUUID(), input);
\r
431 if (instances != null) {
\r
432 for (Object instance : instances) {
\r
433 INeutronRouterAware service = (INeutronRouterAware) instance;
\r
434 service.neutronRouterInterfaceAttached(target, input);
\r
438 return Response.status(200).entity(input).build();
\r
442 * Removes an interface to a router */
\r
444 @Path("{routerUUID}/remove_router_interface")
\r
446 @Produces({ MediaType.APPLICATION_JSON })
\r
447 @Consumes({ MediaType.APPLICATION_JSON })
\r
448 //@TypeHint(OpenStackRouterInterfaces.class)
\r
450 @ResponseCode(code = 200, condition = "Operation successful"),
\r
451 @ResponseCode(code = 400, condition = "Bad Request"),
\r
452 @ResponseCode(code = 401, condition = "Unauthorized"),
\r
453 @ResponseCode(code = 404, condition = "Not Found"),
\r
454 @ResponseCode(code = 409, condition = "Conflict"),
\r
455 @ResponseCode(code = 501, condition = "Not Implemented") })
\r
456 public Response removeRouterInterface(
\r
457 @PathParam("routerUUID") String routerUUID,
\r
458 NeutronRouter_Interface input
\r
460 INeutronRouterCRUD routerInterface = NeutronCRUDInterfaces.getINeutronRouterCRUD(this);
\r
461 if (routerInterface == null) {
\r
462 throw new ServiceUnavailableException("Router CRUD Interface "
\r
463 + RestMessages.SERVICEUNAVAILABLE.toString());
\r
465 INeutronPortCRUD portInterface = NeutronCRUDInterfaces.getINeutronPortCRUD(this);
\r
466 if (portInterface == null) {
\r
467 throw new ServiceUnavailableException("Port CRUD Interface "
\r
468 + RestMessages.SERVICEUNAVAILABLE.toString());
\r
470 INeutronSubnetCRUD subnetInterface = NeutronCRUDInterfaces.getINeutronSubnetCRUD(this);
\r
471 if (subnetInterface == null) {
\r
472 throw new ServiceUnavailableException("Subnet CRUD Interface "
\r
473 + RestMessages.SERVICEUNAVAILABLE.toString());
\r
476 // verify the router exists
\r
477 if (!routerInterface.routerExists(routerUUID))
\r
478 return Response.status(400).build();
\r
479 NeutronRouter target = routerInterface.getRouter(routerUUID);
\r
482 * remove by subnet id. Collect information about the impacted router for the response and
\r
483 * remove the port corresponding to the gateway IP address of the subnet
\r
485 if (input.getPortUUID() == null &&
\r
486 input.getSubnetUUID() != null) {
\r
487 NeutronPort port = portInterface.getGatewayPort(input.getSubnetUUID());
\r
489 return Response.status(404).build();
\r
490 input.setPortUUID(port.getID());
\r
491 input.setID(target.getID());
\r
492 input.setTenantID(target.getTenantID());
\r
494 Object[] instances = ServiceHelper.getGlobalInstances(INeutronRouterAware.class, this, null);
\r
495 if (instances != null) {
\r
496 for (Object instance : instances) {
\r
497 INeutronRouterAware service = (INeutronRouterAware) instance;
\r
498 service.canDetachInterface(target, input);
\r
502 // reset the port ownership
\r
503 port.setDeviceID(null);
\r
504 port.setDeviceOwner(null);
\r
506 target.removeInterface(input.getPortUUID());
\r
507 if (instances != null) {
\r
508 for (Object instance : instances) {
\r
509 INeutronRouterAware service = (INeutronRouterAware) instance;
\r
510 service.neutronRouterInterfaceDetached(target, input);
\r
513 return Response.status(200).entity(input).build();
\r
517 * remove by port id. collect information about the impacted router for the response
\r
518 * remove the interface and reset the port ownership
\r
520 if (input.getPortUUID() != null &&
\r
521 input.getSubnetUUID() == null) {
\r
522 NeutronRouter_Interface targetInterface = target.getInterfaces().get(input.getPortUUID());
\r
523 input.setSubnetUUID(targetInterface.getSubnetUUID());
\r
524 input.setID(target.getID());
\r
525 input.setTenantID(target.getTenantID());
\r
526 NeutronPort port = portInterface.getPort(input.getPortUUID());
\r
527 port.setDeviceID(null);
\r
528 port.setDeviceOwner(null);
\r
529 target.removeInterface(input.getPortUUID());
\r
530 Object[] instances = ServiceHelper.getGlobalInstances(INeutronRouterAware.class, this, null);
\r
531 for (Object instance : instances) {
\r
532 INeutronRouterAware service = (INeutronRouterAware) instance;
\r
533 service.neutronRouterInterfaceDetached(target, input);
\r
535 return Response.status(200).entity(input).build();
\r
539 * remove by both port and subnet ID. Verify that the first fixed IP of the port is a valid
\r
540 * IP address for the subnet, and then remove the interface, collecting information about the
\r
541 * impacted router for the response and reset port ownership
\r
543 if (input.getPortUUID() != null &&
\r
544 input.getSubnetUUID() != null) {
\r
545 NeutronPort port = portInterface.getPort(input.getPortUUID());
\r
546 NeutronSubnet subnet = subnetInterface.getSubnet(input.getSubnetUUID());
\r
547 if (!subnet.isValidIP(port.getFixedIPs().get(0).getIpAddress()))
\r
548 return Response.status(409).build();
\r
549 input.setID(target.getID());
\r
550 input.setTenantID(target.getTenantID());
\r
551 Object[] instances = ServiceHelper.getGlobalInstances(INeutronRouterAware.class, this, null);
\r
552 if (instances != null) {
\r
553 for (Object instance : instances) {
\r
554 INeutronRouterAware service = (INeutronRouterAware) instance;
\r
555 service.canDetachInterface(target, input);
\r
558 port.setDeviceID(null);
\r
559 port.setDeviceOwner(null);
\r
560 target.removeInterface(input.getPortUUID());
\r
561 for (Object instance : instances) {
\r
562 INeutronRouterAware service = (INeutronRouterAware) instance;
\r
563 service.neutronRouterInterfaceDetached(target, input);
\r
565 return Response.status(200).entity(input).build();
\r
568 // have to specify either a port ID or a subnet ID
\r
569 return Response.status(400).build();
\r