Add missing test methods to IRouterAware and clean up unused imports.
[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.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
41 \r
42 \r
43 /**\r
44  * Open DOVE Northbound REST APIs.<br>\r
45  * This class provides REST APIs for managing the open DOVE\r
46  *\r
47  * <br>\r
48  * <br>\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
52  * <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
56  * More info :\r
57  * http://tomcat.apache.org/tomcat-7.0-doc/ssl-howto.html#Configuration\r
58  *\r
59  */\r
60 \r
61 @Path("/routers")\r
62 public class NeutronRoutersNorthbound {\r
63 \r
64     private NeutronRouter extractFields(NeutronRouter o, List<String> fields) {\r
65         return o.extractFields(fields);\r
66     }\r
67 \r
68     /**\r
69      * Returns a list of all Routers */\r
70 \r
71     @GET\r
72     @Produces({ MediaType.APPLICATION_JSON })\r
73     //@TypeHint(OpenStackRouters.class)\r
74     @StatusCodes({\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
79             // return fields\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
88             // pagination\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
93             ) {\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
98         }\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
112                 else\r
113                     ans.add(oSS);\r
114             }\r
115         }\r
116         //TODO: apply pagination to results\r
117         return Response.status(200).entity(\r
118                 new NeutronRouterRequest(ans)).build();\r
119     }\r
120 \r
121     /**\r
122      * Returns a specific Router */\r
123 \r
124     @Path("{routerUUID}")\r
125     @GET\r
126     @Produces({ MediaType.APPLICATION_JSON })\r
127     //@TypeHint(OpenStackRouters.class)\r
128     @StatusCodes({\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
136             // return fields\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
142         }\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
149         } else\r
150             return Response.status(200).entity(\r
151                     new NeutronRouterRequest(routerInterface.getRouter(routerUUID))).build();\r
152     }\r
153 \r
154     /**\r
155      * Creates new Routers */\r
156 \r
157     @POST\r
158     @Produces({ MediaType.APPLICATION_JSON })\r
159     @Consumes({ MediaType.APPLICATION_JSON })\r
160     //@TypeHint(OpenStackRouters.class)\r
161     @StatusCodes({\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
171         }\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
176         }\r
177         if (input.isSingleton()) {\r
178             NeutronRouter singleton = input.getSingleton();\r
179 \r
180             /*\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
184              */\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
194             }\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
202                 }\r
203             }\r
204 \r
205             /*\r
206              * add router to the cache\r
207              */\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
213                 }\r
214             }\r
215         } else {\r
216 \r
217             /*\r
218              * only singleton router creates supported\r
219              */\r
220             return Response.status(400).build();\r
221         }\r
222         return Response.status(201).entity(input).build();\r
223     }\r
224 \r
225     /**\r
226      * Updates a Router */\r
227 \r
228     @Path("{routerUUID}")\r
229     @PUT\r
230     @Produces({ MediaType.APPLICATION_JSON })\r
231     @Consumes({ MediaType.APPLICATION_JSON })\r
232     //@TypeHint(OpenStackRouters.class)\r
233     @StatusCodes({\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
242             ) {\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
247         }\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
252         }\r
253 \r
254         /*\r
255          * router has to exist and only a single delta can be supplied\r
256          */\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
263 \r
264         /*\r
265          * attribute changes blocked by Neutron\r
266          */\r
267         if (singleton.getID() != null || singleton.getTenantID() != null ||\r
268                 singleton.getStatus() != null)\r
269             return Response.status(400).build();\r
270 \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
278             }\r
279         }\r
280         /*\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
283          */\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
291         }\r
292 \r
293         /*\r
294          * update the router entry and return the modified object\r
295          */\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
302             }\r
303         }\r
304         return Response.status(200).entity(\r
305                 new NeutronRouterRequest(routerInterface.getRouter(routerUUID))).build();\r
306 \r
307     }\r
308 \r
309     /**\r
310      * Deletes a Router */\r
311 \r
312     @Path("{routerUUID}")\r
313     @DELETE\r
314     @StatusCodes({\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
326         }\r
327 \r
328         /*\r
329          * verify that the router exists and is not in use before removing it\r
330          */\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
343             }\r
344         }\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
350             }\r
351         }\r
352         return Response.status(204).build();\r
353     }\r
354 \r
355     /**\r
356      * Adds an interface to a router */\r
357 \r
358     @Path("{routerUUID}/add_router_interface")\r
359     @PUT\r
360     @Produces({ MediaType.APPLICATION_JSON })\r
361     @Consumes({ MediaType.APPLICATION_JSON })\r
362     //@TypeHint(OpenStackRouterInterfaces.class)\r
363     @StatusCodes({\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
373             ) {\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
378         }\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
383         }\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
388         }\r
389 \r
390         /*\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
393          */\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
400 \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
410 \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
416 \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
422             }\r
423         }\r
424 \r
425         //mark the port device id and device owner fields\r
426         targetPort.setDeviceOwner("network:router_interface");\r
427         targetPort.setDeviceID(routerUUID);\r
428 \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
434             }\r
435         }\r
436 \r
437         return Response.status(200).entity(input).build();\r
438     }\r
439 \r
440     /**\r
441      * Removes an interface to a router */\r
442 \r
443     @Path("{routerUUID}/remove_router_interface")\r
444     @PUT\r
445     @Produces({ MediaType.APPLICATION_JSON })\r
446     @Consumes({ MediaType.APPLICATION_JSON })\r
447     //@TypeHint(OpenStackRouterInterfaces.class)\r
448     @StatusCodes({\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
458             ) {\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
463         }\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
468         }\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
473         }\r
474 \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
479 \r
480         /*\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
483          */\r
484         if (input.getPortUUID() == null &&\r
485                 input.getSubnetUUID() != null) {\r
486             NeutronPort port = portInterface.getGatewayPort(input.getSubnetUUID());\r
487             if (port == null)\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
492 \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
498                 }\r
499             }\r
500 \r
501             // reset the port ownership\r
502             port.setDeviceID(null);\r
503             port.setDeviceOwner(null);\r
504 \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
510                 }\r
511             }\r
512             return Response.status(200).entity(input).build();\r
513         }\r
514 \r
515         /*\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
518          */\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
533             }\r
534             return Response.status(200).entity(input).build();\r
535         }\r
536 \r
537         /*\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
541          */\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
555                 }\r
556             }\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
563             }\r
564             return Response.status(200).entity(input).build();\r
565         }\r
566 \r
567         // have to specify either a port ID or a subnet ID\r
568         return Response.status(400).build();\r
569     }\r
570 }\r