Merge "Remove unused spring dependency and wrong version in web pom"
[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.INeutronPortAware;\r
30 import org.opendaylight.controller.networkconfig.neutron.INeutronPortCRUD;\r
31 import org.opendaylight.controller.networkconfig.neutron.INeutronRouterAware;\r
32 import org.opendaylight.controller.networkconfig.neutron.INeutronRouterCRUD;\r
33 import org.opendaylight.controller.networkconfig.neutron.INeutronSubnetCRUD;\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.networkconfig.neutron.Neutron_IPs;\r
40 import org.opendaylight.controller.northbound.commons.RestMessages;\r
41 import org.opendaylight.controller.northbound.commons.exception.ServiceUnavailableException;\r
42 import org.opendaylight.controller.sal.utils.ServiceHelper;\r
43 \r
44 \r
45 /**\r
46  * Open DOVE Northbound REST APIs.<br>\r
47  * This class provides REST APIs for managing the open DOVE\r
48  *\r
49  * <br>\r
50  * <br>\r
51  * Authentication scheme : <b>HTTP Basic</b><br>\r
52  * Authentication realm : <b>opendaylight</b><br>\r
53  * Transport : <b>HTTP and HTTPS</b><br>\r
54  * <br>\r
55  * HTTPS Authentication is disabled by default. Administrator can enable it in\r
56  * tomcat-server.xml after adding a proper keystore / SSL certificate from a\r
57  * trusted authority.<br>\r
58  * More info :\r
59  * http://tomcat.apache.org/tomcat-7.0-doc/ssl-howto.html#Configuration\r
60  *\r
61  */\r
62 \r
63 @Path("/routers")\r
64 public class NeutronRoutersNorthbound {\r
65 \r
66     private NeutronRouter extractFields(NeutronRouter o, List<String> fields) {\r
67         return o.extractFields(fields);\r
68     }\r
69 \r
70     /**\r
71      * Returns a list of all Routers */\r
72 \r
73     @GET\r
74     @Produces({ MediaType.APPLICATION_JSON })\r
75     //@TypeHint(OpenStackRouters.class)\r
76     @StatusCodes({\r
77             @ResponseCode(code = 200, condition = "Operation successful"),\r
78             @ResponseCode(code = 401, condition = "Unauthorized"),\r
79             @ResponseCode(code = 501, condition = "Not Implemented") })\r
80     public Response listRouters(\r
81             // return fields\r
82             @QueryParam("fields") List<String> fields,\r
83             // note: openstack isn't clear about filtering on lists, so we aren't handling them\r
84             @QueryParam("id") String queryID,\r
85             @QueryParam("name") String queryName,\r
86             @QueryParam("admin_state_up") String queryAdminStateUp,\r
87             @QueryParam("status") String queryStatus,\r
88             @QueryParam("tenant_id") String queryTenantID,\r
89             @QueryParam("external_gateway_info") String queryExternalGatewayInfo,\r
90             // pagination\r
91             @QueryParam("limit") String limit,\r
92             @QueryParam("marker") String marker,\r
93             @QueryParam("page_reverse") String pageReverse\r
94             // sorting not supported\r
95             ) {\r
96         INeutronRouterCRUD routerInterface = NeutronNBInterfaces.getIfNBRouterCRUD("default",this);\r
97         if (routerInterface == null) {\r
98             throw new ServiceUnavailableException("Router CRUD Interface "\r
99                     + RestMessages.SERVICEUNAVAILABLE.toString());\r
100         }\r
101         List<NeutronRouter> allRouters = routerInterface.getAllRouters();\r
102         List<NeutronRouter> ans = new ArrayList<NeutronRouter>();\r
103         Iterator<NeutronRouter> i = allRouters.iterator();\r
104         while (i.hasNext()) {\r
105             NeutronRouter oSS = i.next();\r
106             if ((queryID == null || queryID.equals(oSS.getID())) &&\r
107                     (queryName == null || queryName.equals(oSS.getName())) &&\r
108                     (queryAdminStateUp == null || queryAdminStateUp.equals(oSS.getAdminStateUp())) &&\r
109                     (queryStatus == null || queryStatus.equals(oSS.getStatus())) &&\r
110                     (queryExternalGatewayInfo == null || queryExternalGatewayInfo.equals(oSS.getExternalGatewayInfo())) &&\r
111                     (queryTenantID == null || queryTenantID.equals(oSS.getTenantID()))) {\r
112                 if (fields.size() > 0)\r
113                     ans.add(extractFields(oSS,fields));\r
114                 else\r
115                     ans.add(oSS);\r
116             }\r
117         }\r
118         //TODO: apply pagination to results\r
119         return Response.status(200).entity(\r
120                 new NeutronRouterRequest(ans)).build();\r
121     }\r
122 \r
123     /**\r
124      * Returns a specific Router */\r
125 \r
126     @Path("{routerUUID}")\r
127     @GET\r
128     @Produces({ MediaType.APPLICATION_JSON })\r
129     //@TypeHint(OpenStackRouters.class)\r
130     @StatusCodes({\r
131             @ResponseCode(code = 200, condition = "Operation successful"),\r
132             @ResponseCode(code = 401, condition = "Unauthorized"),\r
133             @ResponseCode(code = 403, condition = "Forbidden"),\r
134             @ResponseCode(code = 404, condition = "Not Found"),\r
135             @ResponseCode(code = 501, condition = "Not Implemented") })\r
136     public Response showRouter(\r
137             @PathParam("routerUUID") String routerUUID,\r
138             // return fields\r
139             @QueryParam("fields") List<String> fields) {\r
140         INeutronRouterCRUD routerInterface = NeutronNBInterfaces.getIfNBRouterCRUD("default",this);\r
141         if (routerInterface == null) {\r
142             throw new ServiceUnavailableException("Router CRUD Interface "\r
143                     + RestMessages.SERVICEUNAVAILABLE.toString());\r
144         }\r
145         if (!routerInterface.routerExists(routerUUID))\r
146             return Response.status(404).build();\r
147         if (fields.size() > 0) {\r
148             NeutronRouter ans = routerInterface.getRouter(routerUUID);\r
149             return Response.status(200).entity(\r
150                     new NeutronRouterRequest(extractFields(ans, fields))).build();\r
151         } else\r
152             return Response.status(200).entity(\r
153                     new NeutronRouterRequest(routerInterface.getRouter(routerUUID))).build();\r
154     }\r
155 \r
156     /**\r
157      * Creates new Routers */\r
158 \r
159     @POST\r
160     @Produces({ MediaType.APPLICATION_JSON })\r
161     @Consumes({ MediaType.APPLICATION_JSON })\r
162     //@TypeHint(OpenStackRouters.class)\r
163     @StatusCodes({\r
164             @ResponseCode(code = 201, condition = "Created"),\r
165             @ResponseCode(code = 400, condition = "Bad Request"),\r
166             @ResponseCode(code = 401, condition = "Unauthorized"),\r
167             @ResponseCode(code = 501, condition = "Not Implemented") })\r
168     public Response createRouters(final NeutronRouterRequest input) {\r
169         INeutronRouterCRUD routerInterface = NeutronNBInterfaces.getIfNBRouterCRUD("default",this);\r
170         if (routerInterface == null) {\r
171             throw new ServiceUnavailableException("Router CRUD Interface "\r
172                     + RestMessages.SERVICEUNAVAILABLE.toString());\r
173         }\r
174         INeutronNetworkCRUD networkInterface = NeutronNBInterfaces.getIfNBNetworkCRUD("default", this);\r
175         if (networkInterface == null) {\r
176             throw new ServiceUnavailableException("Network CRUD Interface "\r
177                     + RestMessages.SERVICEUNAVAILABLE.toString());\r
178         }\r
179         if (input.isSingleton()) {\r
180             NeutronRouter singleton = input.getSingleton();\r
181 \r
182             /*\r
183              * verify that the router doesn't already exist (issue: is deeper inspection necessary?)\r
184              * if there is external gateway information provided, verify that the specified network\r
185              * exists and has been designated as "router:external"\r
186              */\r
187             if (routerInterface.routerExists(singleton.getID()))\r
188                 return Response.status(400).build();\r
189             if (singleton.getExternalGatewayInfo() != null) {\r
190                 String externNetworkPtr = singleton.getExternalGatewayInfo().getNetworkID();\r
191                 if (!networkInterface.networkExists(externNetworkPtr))\r
192                     return Response.status(400).build();\r
193                 NeutronNetwork externNetwork = networkInterface.getNetwork(externNetworkPtr);\r
194                 if (!externNetwork.isRouterExternal())\r
195                     return Response.status(400).build();\r
196             }\r
197             Object[] instances = ServiceHelper.getGlobalInstances(INeutronRouterAware.class, this, null);\r
198             if (instances != null) {\r
199                 for (Object instance : instances) {\r
200                     INeutronRouterAware service = (INeutronRouterAware) instance;\r
201                     int status = service.canCreateRouter(singleton);\r
202                     if (status < 200 || status > 299)\r
203                         return Response.status(status).build();\r
204                 }\r
205             }\r
206 \r
207             /*\r
208              * add router to the cache\r
209              */\r
210             routerInterface.addRouter(singleton);\r
211             if (instances != null) {\r
212                 for (Object instance : instances) {\r
213                     INeutronRouterAware service = (INeutronRouterAware) instance;\r
214                     service.neutronRouterCreated(singleton);\r
215                 }\r
216             }\r
217         } else {\r
218 \r
219             /*\r
220              * only singleton router creates supported\r
221              */\r
222             return Response.status(400).build();\r
223         }\r
224         return Response.status(201).entity(input).build();\r
225     }\r
226 \r
227     /**\r
228      * Updates a Router */\r
229 \r
230     @Path("{routerUUID}")\r
231     @PUT\r
232     @Produces({ MediaType.APPLICATION_JSON })\r
233     @Consumes({ MediaType.APPLICATION_JSON })\r
234     //@TypeHint(OpenStackRouters.class)\r
235     @StatusCodes({\r
236             @ResponseCode(code = 200, condition = "Operation successful"),\r
237             @ResponseCode(code = 400, condition = "Bad Request"),\r
238             @ResponseCode(code = 401, condition = "Unauthorized"),\r
239             @ResponseCode(code = 404, condition = "Not Found"),\r
240             @ResponseCode(code = 501, condition = "Not Implemented") })\r
241     public Response updateRouter(\r
242             @PathParam("routerUUID") String routerUUID,\r
243             NeutronRouterRequest input\r
244             ) {\r
245         INeutronRouterCRUD routerInterface = NeutronNBInterfaces.getIfNBRouterCRUD("default",this);\r
246         if (routerInterface == null) {\r
247             throw new ServiceUnavailableException("Router CRUD Interface "\r
248                     + RestMessages.SERVICEUNAVAILABLE.toString());\r
249         }\r
250         INeutronNetworkCRUD networkInterface = NeutronNBInterfaces.getIfNBNetworkCRUD("default", this);\r
251         if (networkInterface == null) {\r
252             throw new ServiceUnavailableException("Network CRUD Interface "\r
253                     + RestMessages.SERVICEUNAVAILABLE.toString());\r
254         }\r
255 \r
256         /*\r
257          * router has to exist and only a single delta can be supplied\r
258          */\r
259         if (!routerInterface.routerExists(routerUUID))\r
260             return Response.status(404).build();\r
261         if (!input.isSingleton())\r
262             return Response.status(400).build();\r
263         NeutronRouter singleton = input.getSingleton();\r
264         NeutronRouter original = routerInterface.getRouter(routerUUID);\r
265 \r
266         /*\r
267          * attribute changes blocked by Neutron\r
268          */\r
269         if (singleton.getID() != null || singleton.getTenantID() != null ||\r
270                 singleton.getStatus() != null)\r
271             return Response.status(400).build();\r
272 \r
273         Object[] instances = ServiceHelper.getGlobalInstances(INeutronRouterAware.class, this, null);\r
274         if (instances != null) {\r
275             for (Object instance : instances) {\r
276                 INeutronRouterAware service = (INeutronRouterAware) instance;\r
277                 int status = service.canUpdateRouter(singleton, original);\r
278                 if (status < 200 || status > 299)\r
279                     return Response.status(status).build();\r
280             }\r
281         }\r
282         /*\r
283          * if the external gateway info is being changed, verify that the new network\r
284          * exists and has been designated as an external network\r
285          */\r
286         if (singleton.getExternalGatewayInfo() != null) {\r
287             String externNetworkPtr = singleton.getExternalGatewayInfo().getNetworkID();\r
288             if (!networkInterface.networkExists(externNetworkPtr))\r
289                 return Response.status(400).build();\r
290             NeutronNetwork externNetwork = networkInterface.getNetwork(externNetworkPtr);\r
291             if (!externNetwork.isRouterExternal())\r
292                 return Response.status(400).build();\r
293         }\r
294 \r
295         /*\r
296          * update the router entry and return the modified object\r
297          */\r
298         routerInterface.updateRouter(routerUUID, singleton);\r
299         NeutronRouter updatedRouter = routerInterface.getRouter(routerUUID);\r
300         if (instances != null) {\r
301             for (Object instance : instances) {\r
302                 INeutronRouterAware service = (INeutronRouterAware) instance;\r
303                 service.neutronRouterUpdated(updatedRouter);\r
304             }\r
305         }\r
306         return Response.status(200).entity(\r
307                 new NeutronRouterRequest(routerInterface.getRouter(routerUUID))).build();\r
308 \r
309     }\r
310 \r
311     /**\r
312      * Deletes a Router */\r
313 \r
314     @Path("{routerUUID}")\r
315     @DELETE\r
316     @StatusCodes({\r
317             @ResponseCode(code = 204, condition = "No Content"),\r
318             @ResponseCode(code = 401, condition = "Unauthorized"),\r
319             @ResponseCode(code = 404, condition = "Not Found"),\r
320             @ResponseCode(code = 409, condition = "Conflict"),\r
321             @ResponseCode(code = 501, condition = "Not Implemented") })\r
322     public Response deleteRouter(\r
323             @PathParam("routerUUID") String routerUUID) {\r
324         INeutronRouterCRUD routerInterface = NeutronNBInterfaces.getIfNBRouterCRUD("default",this);\r
325         if (routerInterface == null) {\r
326             throw new ServiceUnavailableException("Router CRUD Interface "\r
327                     + RestMessages.SERVICEUNAVAILABLE.toString());\r
328         }\r
329 \r
330         /*\r
331          * verify that the router exists and is not in use before removing it\r
332          */\r
333         if (!routerInterface.routerExists(routerUUID))\r
334             return Response.status(404).build();\r
335         if (routerInterface.routerInUse(routerUUID))\r
336             return Response.status(409).build();\r
337         NeutronRouter singleton = routerInterface.getRouter(routerUUID);\r
338         Object[] instances = ServiceHelper.getGlobalInstances(INeutronRouterAware.class, this, null);\r
339         if (instances != null) {\r
340             for (Object instance : instances) {\r
341                 INeutronRouterAware service = (INeutronRouterAware) instance;\r
342                 int status = service.canDeleteRouter(singleton);\r
343                 if (status < 200 || status > 299)\r
344                     return Response.status(status).build();\r
345             }\r
346         }\r
347         routerInterface.removeRouter(routerUUID);\r
348         if (instances != null) {\r
349             for (Object instance : instances) {\r
350                 INeutronRouterAware service = (INeutronRouterAware) instance;\r
351                 service.neutronRouterDeleted(singleton);\r
352             }\r
353         }\r
354         return Response.status(204).build();\r
355     }\r
356 \r
357     /**\r
358      * Adds an interface to a router */\r
359 \r
360     @Path("{routerUUID}/add_router_interface")\r
361     @PUT\r
362     @Produces({ MediaType.APPLICATION_JSON })\r
363     @Consumes({ MediaType.APPLICATION_JSON })\r
364     //@TypeHint(OpenStackRouterInterfaces.class)\r
365     @StatusCodes({\r
366             @ResponseCode(code = 200, condition = "Operation successful"),\r
367             @ResponseCode(code = 400, condition = "Bad Request"),\r
368             @ResponseCode(code = 401, condition = "Unauthorized"),\r
369             @ResponseCode(code = 404, condition = "Not Found"),\r
370             @ResponseCode(code = 409, condition = "Conflict"),\r
371             @ResponseCode(code = 501, condition = "Not Implemented") })\r
372     public Response addRouterInterface(\r
373             @PathParam("routerUUID") String routerUUID,\r
374             NeutronRouter_Interface input\r
375             ) {\r
376         INeutronRouterCRUD routerInterface = NeutronNBInterfaces.getIfNBRouterCRUD("default",this);\r
377         if (routerInterface == null) {\r
378             throw new ServiceUnavailableException("Router CRUD Interface "\r
379                     + RestMessages.SERVICEUNAVAILABLE.toString());\r
380         }\r
381         INeutronPortCRUD portInterface = NeutronNBInterfaces.getIfNBPortCRUD("default",this);\r
382         if (portInterface == null) {\r
383             throw new ServiceUnavailableException("Port CRUD Interface "\r
384                     + RestMessages.SERVICEUNAVAILABLE.toString());\r
385         }\r
386         INeutronSubnetCRUD subnetInterface = NeutronNBInterfaces.getIfNBSubnetCRUD("default",this);\r
387         if (subnetInterface == null) {\r
388             throw new ServiceUnavailableException("Subnet CRUD Interface "\r
389                     + RestMessages.SERVICEUNAVAILABLE.toString());\r
390         }\r
391 \r
392         /*\r
393          *  While the Neutron specification says that the router has to exist and the input can only specify either a subnet id\r
394          *  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          */\r
396         if (!routerInterface.routerExists(routerUUID))\r
397             return Response.status(400).build();\r
398         NeutronRouter target = routerInterface.getRouter(routerUUID);\r
399         if (input.getSubnetUUID() == null ||\r
400                     input.getPortUUID() == null)\r
401                 return Response.status(400).build();\r
402 \r
403         // check that the port is part of the subnet\r
404         NeutronSubnet targetSubnet = subnetInterface.getSubnet(input.getSubnetUUID());\r
405         if (targetSubnet == null)\r
406             return Response.status(400).build();\r
407         NeutronPort targetPort = portInterface.getPort(input.getPortUUID());\r
408         if (targetPort == null)\r
409             return Response.status(400).build();\r
410         if (!targetSubnet.getPortsInSubnet().contains(targetPort))\r
411             return Response.status(400).build();\r
412 \r
413         if (targetPort.getFixedIPs().size() != 1)\r
414             return Response.status(400).build();\r
415         if (targetPort.getDeviceID() != null ||\r
416                 targetPort.getDeviceOwner() != null)\r
417             return Response.status(409).build();\r
418 \r
419         //mark the port device id and device owner fields\r
420         targetPort.setDeviceOwner("network:router_interface");\r
421         targetPort.setDeviceID(routerUUID);\r
422 \r
423         target.addInterface(input.getPortUUID(), input);\r
424         Object[] instances = ServiceHelper.getGlobalInstances(INeutronRouterAware.class, this, null);\r
425         if (instances != null) {\r
426             for (Object instance : instances) {\r
427                 INeutronRouterAware service = (INeutronRouterAware) instance;\r
428                 service.neutronRouterInterfaceAttached(target, input);\r
429             }\r
430         }\r
431 \r
432         return Response.status(200).entity(input).build();\r
433     }\r
434 \r
435     /**\r
436      * Removes an interface to a router */\r
437 \r
438     @Path("{routerUUID}/remove_router_interface")\r
439     @PUT\r
440     @Produces({ MediaType.APPLICATION_JSON })\r
441     @Consumes({ MediaType.APPLICATION_JSON })\r
442     //@TypeHint(OpenStackRouterInterfaces.class)\r
443     @StatusCodes({\r
444             @ResponseCode(code = 200, condition = "Operation successful"),\r
445             @ResponseCode(code = 400, condition = "Bad Request"),\r
446             @ResponseCode(code = 401, condition = "Unauthorized"),\r
447             @ResponseCode(code = 404, condition = "Not Found"),\r
448             @ResponseCode(code = 409, condition = "Conflict"),\r
449             @ResponseCode(code = 501, condition = "Not Implemented") })\r
450     public Response removeRouterInterface(\r
451             @PathParam("routerUUID") String routerUUID,\r
452             NeutronRouter_Interface input\r
453             ) {\r
454         INeutronRouterCRUD routerInterface = NeutronNBInterfaces.getIfNBRouterCRUD("default",this);\r
455         if (routerInterface == null) {\r
456             throw new ServiceUnavailableException("Router CRUD Interface "\r
457                     + RestMessages.SERVICEUNAVAILABLE.toString());\r
458         }\r
459         INeutronPortCRUD portInterface = NeutronNBInterfaces.getIfNBPortCRUD("default",this);\r
460         if (portInterface == null) {\r
461             throw new ServiceUnavailableException("Port CRUD Interface "\r
462                     + RestMessages.SERVICEUNAVAILABLE.toString());\r
463         }\r
464         INeutronSubnetCRUD subnetInterface = NeutronNBInterfaces.getIfNBSubnetCRUD("default",this);\r
465         if (subnetInterface == null) {\r
466             throw new ServiceUnavailableException("Subnet CRUD Interface "\r
467                     + RestMessages.SERVICEUNAVAILABLE.toString());\r
468         }\r
469 \r
470         // verify the router exists\r
471         if (!routerInterface.routerExists(routerUUID))\r
472             return Response.status(400).build();\r
473         NeutronRouter target = routerInterface.getRouter(routerUUID);\r
474 \r
475         /*\r
476          * remove by subnet id.  Collect information about the impacted router for the response and\r
477          * remove the port corresponding to the gateway IP address of the subnet\r
478          */\r
479         if (input.getPortUUID() == null &&\r
480                 input.getSubnetUUID() != null) {\r
481             NeutronPort port = portInterface.getGatewayPort(input.getSubnetUUID());\r
482             if (port == null)\r
483                 return Response.status(404).build();\r
484             input.setPortUUID(port.getID());\r
485             input.setID(target.getID());\r
486             input.setTenantID(target.getTenantID());\r
487 \r
488             // reset the port ownership\r
489             port.setDeviceID(null);\r
490             port.setDeviceOwner(null);\r
491 \r
492             target.removeInterface(input.getPortUUID());\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.neutronRouterInterfaceDetached(target, input);\r
498                 }\r
499             }\r
500             return Response.status(200).entity(input).build();\r
501         }\r
502 \r
503         /*\r
504          * remove by port id. collect information about the impacted router for the response\r
505          * remove the interface and reset the port ownership\r
506          */\r
507         if (input.getPortUUID() != null &&\r
508                 input.getSubnetUUID() == null) {\r
509             NeutronRouter_Interface targetInterface = target.getInterfaces().get(input.getPortUUID());\r
510             input.setSubnetUUID(targetInterface.getSubnetUUID());\r
511             input.setID(target.getID());\r
512             input.setTenantID(target.getTenantID());\r
513             NeutronPort port = portInterface.getPort(input.getPortUUID());\r
514             port.setDeviceID(null);\r
515             port.setDeviceOwner(null);\r
516             target.removeInterface(input.getPortUUID());\r
517             Object[] instances = ServiceHelper.getGlobalInstances(INeutronRouterAware.class, this, null);\r
518             for (Object instance : instances) {\r
519                 INeutronRouterAware service = (INeutronRouterAware) instance;\r
520                 service.neutronRouterInterfaceDetached(target, input);\r
521             }\r
522             return Response.status(200).entity(input).build();\r
523         }\r
524 \r
525         /*\r
526          * remove by both port and subnet ID.  Verify that the first fixed IP of the port is a valid\r
527          * IP address for the subnet, and then remove the interface, collecting information about the\r
528          * impacted router for the response and reset port ownership\r
529          */\r
530         if (input.getPortUUID() != null &&\r
531                 input.getSubnetUUID() != null) {\r
532             NeutronPort port = portInterface.getPort(input.getPortUUID());\r
533             NeutronSubnet subnet = subnetInterface.getSubnet(input.getSubnetUUID());\r
534             if (!subnet.isValidIP(port.getFixedIPs().get(0).getIpAddress()))\r
535                 return Response.status(409).build();\r
536             input.setID(target.getID());\r
537             input.setTenantID(target.getTenantID());\r
538             port.setDeviceID(null);\r
539             port.setDeviceOwner(null);\r
540             target.removeInterface(input.getPortUUID());\r
541             Object[] instances = ServiceHelper.getGlobalInstances(INeutronRouterAware.class, this, null);\r
542             for (Object instance : instances) {\r
543                 INeutronRouterAware service = (INeutronRouterAware) instance;\r
544                 service.neutronRouterInterfaceDetached(target, input);\r
545             }\r
546             return Response.status(200).entity(input).build();\r
547         }\r
548 \r
549         // have to specify either a port ID or a subnet ID\r
550         return Response.status(400).build();\r
551     }\r
552 }\r