Remove superfulous class from neutron NB bundle.
[controller.git] / opendaylight / northbound / networkconfiguration / neutron / src / main / java / org / opendaylight / controller / networkconfig / neutron / northbound / NeutronRoutersNorthbound.java
1 /*\r
2  * Copyright IBM Corporation, 2013.  All rights reserved.\r
3  *\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
7  */\r
8 \r
9 package org.opendaylight.controller.networkconfig.neutron.northbound;\r
10 \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
25 \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
42 \r
43 \r
44 /**\r
45  * Open DOVE Northbound REST APIs.<br>\r
46  * This class provides REST APIs for managing the open DOVE\r
47  *\r
48  * <br>\r
49  * <br>\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
53  * <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
57  * More info :\r
58  * http://tomcat.apache.org/tomcat-7.0-doc/ssl-howto.html#Configuration\r
59  *\r
60  */\r
61 \r
62 @Path("/routers")\r
63 public class NeutronRoutersNorthbound {\r
64 \r
65     private NeutronRouter extractFields(NeutronRouter o, List<String> fields) {\r
66         return o.extractFields(fields);\r
67     }\r
68 \r
69     /**\r
70      * Returns a list of all Routers */\r
71 \r
72     @GET\r
73     @Produces({ MediaType.APPLICATION_JSON })\r
74     //@TypeHint(OpenStackRouters.class)\r
75     @StatusCodes({\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
80             // return fields\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
89             // pagination\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
94             ) {\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
99         }\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
113                 else\r
114                     ans.add(oSS);\r
115             }\r
116         }\r
117         //TODO: apply pagination to results\r
118         return Response.status(200).entity(\r
119                 new NeutronRouterRequest(ans)).build();\r
120     }\r
121 \r
122     /**\r
123      * Returns a specific Router */\r
124 \r
125     @Path("{routerUUID}")\r
126     @GET\r
127     @Produces({ MediaType.APPLICATION_JSON })\r
128     //@TypeHint(OpenStackRouters.class)\r
129     @StatusCodes({\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
137             // return fields\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
143         }\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
150         } else\r
151             return Response.status(200).entity(\r
152                     new NeutronRouterRequest(routerInterface.getRouter(routerUUID))).build();\r
153     }\r
154 \r
155     /**\r
156      * Creates new Routers */\r
157 \r
158     @POST\r
159     @Produces({ MediaType.APPLICATION_JSON })\r
160     @Consumes({ MediaType.APPLICATION_JSON })\r
161     //@TypeHint(OpenStackRouters.class)\r
162     @StatusCodes({\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
172         }\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
177         }\r
178         if (input.isSingleton()) {\r
179             NeutronRouter singleton = input.getSingleton();\r
180 \r
181             /*\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
185              */\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
195             }\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
203                 }\r
204             }\r
205 \r
206             /*\r
207              * add router to the cache\r
208              */\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
214                 }\r
215             }\r
216         } else {\r
217 \r
218             /*\r
219              * only singleton router creates supported\r
220              */\r
221             return Response.status(400).build();\r
222         }\r
223         return Response.status(201).entity(input).build();\r
224     }\r
225 \r
226     /**\r
227      * Updates a Router */\r
228 \r
229     @Path("{routerUUID}")\r
230     @PUT\r
231     @Produces({ MediaType.APPLICATION_JSON })\r
232     @Consumes({ MediaType.APPLICATION_JSON })\r
233     //@TypeHint(OpenStackRouters.class)\r
234     @StatusCodes({\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
243             ) {\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
248         }\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
253         }\r
254 \r
255         /*\r
256          * router has to exist and only a single delta can be supplied\r
257          */\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
264 \r
265         /*\r
266          * attribute changes blocked by Neutron\r
267          */\r
268         if (singleton.getID() != null || singleton.getTenantID() != null ||\r
269                 singleton.getStatus() != null)\r
270             return Response.status(400).build();\r
271 \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
279             }\r
280         }\r
281         /*\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
284          */\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
292         }\r
293 \r
294         /*\r
295          * update the router entry and return the modified object\r
296          */\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
303             }\r
304         }\r
305         return Response.status(200).entity(\r
306                 new NeutronRouterRequest(routerInterface.getRouter(routerUUID))).build();\r
307 \r
308     }\r
309 \r
310     /**\r
311      * Deletes a Router */\r
312 \r
313     @Path("{routerUUID}")\r
314     @DELETE\r
315     @StatusCodes({\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
327         }\r
328 \r
329         /*\r
330          * verify that the router exists and is not in use before removing it\r
331          */\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
344             }\r
345         }\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
351             }\r
352         }\r
353         return Response.status(204).build();\r
354     }\r
355 \r
356     /**\r
357      * Adds an interface to a router */\r
358 \r
359     @Path("{routerUUID}/add_router_interface")\r
360     @PUT\r
361     @Produces({ MediaType.APPLICATION_JSON })\r
362     @Consumes({ MediaType.APPLICATION_JSON })\r
363     //@TypeHint(OpenStackRouterInterfaces.class)\r
364     @StatusCodes({\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
374             ) {\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
379         }\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
384         }\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
389         }\r
390 \r
391         /*\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
394          */\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
401 \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
411 \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
417 \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
423             }\r
424         }\r
425 \r
426         //mark the port device id and device owner fields\r
427         targetPort.setDeviceOwner("network:router_interface");\r
428         targetPort.setDeviceID(routerUUID);\r
429 \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
435             }\r
436         }\r
437 \r
438         return Response.status(200).entity(input).build();\r
439     }\r
440 \r
441     /**\r
442      * Removes an interface to a router */\r
443 \r
444     @Path("{routerUUID}/remove_router_interface")\r
445     @PUT\r
446     @Produces({ MediaType.APPLICATION_JSON })\r
447     @Consumes({ MediaType.APPLICATION_JSON })\r
448     //@TypeHint(OpenStackRouterInterfaces.class)\r
449     @StatusCodes({\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
459             ) {\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
464         }\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
469         }\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
474         }\r
475 \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
480 \r
481         /*\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
484          */\r
485         if (input.getPortUUID() == null &&\r
486                 input.getSubnetUUID() != null) {\r
487             NeutronPort port = portInterface.getGatewayPort(input.getSubnetUUID());\r
488             if (port == null)\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
493 \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
499                 }\r
500             }\r
501 \r
502             // reset the port ownership\r
503             port.setDeviceID(null);\r
504             port.setDeviceOwner(null);\r
505 \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
511                 }\r
512             }\r
513             return Response.status(200).entity(input).build();\r
514         }\r
515 \r
516         /*\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
519          */\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
534             }\r
535             return Response.status(200).entity(input).build();\r
536         }\r
537 \r
538         /*\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
542          */\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
556                 }\r
557             }\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
564             }\r
565             return Response.status(200).entity(input).build();\r
566         }\r
567 \r
568         // have to specify either a port ID or a subnet ID\r
569         return Response.status(400).build();\r
570     }\r
571 }\r