+/*\r
+ * Copyright IBM Corporation, 2013. All rights reserved.\r
+ *\r
+ * This program and the accompanying materials are made available under the\r
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,\r
+ * and is available at http://www.eclipse.org/legal/epl-v10.html\r
+ */\r
+\r
+package org.opendaylight.controller.networkconfig.neutron.northbound;\r
+\r
+import java.util.ArrayList;\r
+import java.util.Iterator;\r
+import java.util.List;\r
+import javax.ws.rs.Consumes;\r
+import javax.ws.rs.DELETE;\r
+import javax.ws.rs.GET;\r
+import javax.ws.rs.POST;\r
+import javax.ws.rs.PUT;\r
+import javax.ws.rs.Path;\r
+import javax.ws.rs.PathParam;\r
+import javax.ws.rs.Produces;\r
+import javax.ws.rs.QueryParam;\r
+import javax.ws.rs.core.MediaType;\r
+import javax.ws.rs.core.Response;\r
+\r
+import org.codehaus.enunciate.jaxrs.ResponseCode;\r
+import org.codehaus.enunciate.jaxrs.StatusCodes;\r
+import org.opendaylight.controller.networkconfig.neutron.INeutronNetworkCRUD;\r
+import org.opendaylight.controller.networkconfig.neutron.INeutronPortAware;\r
+import org.opendaylight.controller.networkconfig.neutron.INeutronPortCRUD;\r
+import org.opendaylight.controller.networkconfig.neutron.INeutronRouterAware;\r
+import org.opendaylight.controller.networkconfig.neutron.INeutronRouterCRUD;\r
+import org.opendaylight.controller.networkconfig.neutron.INeutronSubnetCRUD;\r
+import org.opendaylight.controller.networkconfig.neutron.NeutronNetwork;\r
+import org.opendaylight.controller.networkconfig.neutron.NeutronPort;\r
+import org.opendaylight.controller.networkconfig.neutron.NeutronRouter;\r
+import org.opendaylight.controller.networkconfig.neutron.NeutronRouter_Interface;\r
+import org.opendaylight.controller.networkconfig.neutron.NeutronSubnet;\r
+import org.opendaylight.controller.networkconfig.neutron.Neutron_IPs;\r
+import org.opendaylight.controller.northbound.commons.RestMessages;\r
+import org.opendaylight.controller.northbound.commons.exception.ServiceUnavailableException;\r
+import org.opendaylight.controller.sal.utils.ServiceHelper;\r
+\r
+\r
+/**\r
+ * Open DOVE Northbound REST APIs.<br>\r
+ * This class provides REST APIs for managing the open DOVE\r
+ *\r
+ * <br>\r
+ * <br>\r
+ * Authentication scheme : <b>HTTP Basic</b><br>\r
+ * Authentication realm : <b>opendaylight</b><br>\r
+ * Transport : <b>HTTP and HTTPS</b><br>\r
+ * <br>\r
+ * HTTPS Authentication is disabled by default. Administrator can enable it in\r
+ * tomcat-server.xml after adding a proper keystore / SSL certificate from a\r
+ * trusted authority.<br>\r
+ * More info :\r
+ * http://tomcat.apache.org/tomcat-7.0-doc/ssl-howto.html#Configuration\r
+ *\r
+ */\r
+\r
+@Path("/routers")\r
+public class NeutronRoutersNorthbound {\r
+\r
+ private NeutronRouter extractFields(NeutronRouter o, List<String> fields) {\r
+ return o.extractFields(fields);\r
+ }\r
+\r
+ /**\r
+ * Returns a list of all Routers */\r
+\r
+ @GET\r
+ @Produces({ MediaType.APPLICATION_JSON })\r
+ //@TypeHint(OpenStackRouters.class)\r
+ @StatusCodes({\r
+ @ResponseCode(code = 200, condition = "Operation successful"),\r
+ @ResponseCode(code = 401, condition = "Unauthorized"),\r
+ @ResponseCode(code = 501, condition = "Not Implemented") })\r
+ public Response listRouters(\r
+ // return fields\r
+ @QueryParam("fields") List<String> fields,\r
+ // note: openstack isn't clear about filtering on lists, so we aren't handling them\r
+ @QueryParam("id") String queryID,\r
+ @QueryParam("name") String queryName,\r
+ @QueryParam("admin_state_up") String queryAdminStateUp,\r
+ @QueryParam("status") String queryStatus,\r
+ @QueryParam("tenant_id") String queryTenantID,\r
+ @QueryParam("external_gateway_info") String queryExternalGatewayInfo,\r
+ // pagination\r
+ @QueryParam("limit") String limit,\r
+ @QueryParam("marker") String marker,\r
+ @QueryParam("page_reverse") String pageReverse\r
+ // sorting not supported\r
+ ) {\r
+ INeutronRouterCRUD routerInterface = NeutronNBInterfaces.getIfNBRouterCRUD("default",this);\r
+ if (routerInterface == null) {\r
+ throw new ServiceUnavailableException("Router CRUD Interface "\r
+ + RestMessages.SERVICEUNAVAILABLE.toString());\r
+ }\r
+ List<NeutronRouter> allRouters = routerInterface.getAllRouters();\r
+ List<NeutronRouter> ans = new ArrayList<NeutronRouter>();\r
+ Iterator<NeutronRouter> i = allRouters.iterator();\r
+ while (i.hasNext()) {\r
+ NeutronRouter oSS = i.next();\r
+ if ((queryID == null || queryID.equals(oSS.getID())) &&\r
+ (queryName == null || queryName.equals(oSS.getName())) &&\r
+ (queryAdminStateUp == null || queryAdminStateUp.equals(oSS.getAdminStateUp())) &&\r
+ (queryStatus == null || queryStatus.equals(oSS.getStatus())) &&\r
+ (queryExternalGatewayInfo == null || queryExternalGatewayInfo.equals(oSS.getExternalGatewayInfo())) &&\r
+ (queryTenantID == null || queryTenantID.equals(oSS.getTenantID()))) {\r
+ if (fields.size() > 0)\r
+ ans.add(extractFields(oSS,fields));\r
+ else\r
+ ans.add(oSS);\r
+ }\r
+ }\r
+ //TODO: apply pagination to results\r
+ return Response.status(200).entity(\r
+ new NeutronRouterRequest(ans)).build();\r
+ }\r
+\r
+ /**\r
+ * Returns a specific Router */\r
+\r
+ @Path("{routerUUID}")\r
+ @GET\r
+ @Produces({ MediaType.APPLICATION_JSON })\r
+ //@TypeHint(OpenStackRouters.class)\r
+ @StatusCodes({\r
+ @ResponseCode(code = 200, condition = "Operation successful"),\r
+ @ResponseCode(code = 401, condition = "Unauthorized"),\r
+ @ResponseCode(code = 403, condition = "Forbidden"),\r
+ @ResponseCode(code = 404, condition = "Not Found"),\r
+ @ResponseCode(code = 501, condition = "Not Implemented") })\r
+ public Response showRouter(\r
+ @PathParam("routerUUID") String routerUUID,\r
+ // return fields\r
+ @QueryParam("fields") List<String> fields) {\r
+ INeutronRouterCRUD routerInterface = NeutronNBInterfaces.getIfNBRouterCRUD("default",this);\r
+ if (routerInterface == null) {\r
+ throw new ServiceUnavailableException("Router CRUD Interface "\r
+ + RestMessages.SERVICEUNAVAILABLE.toString());\r
+ }\r
+ if (!routerInterface.routerExists(routerUUID))\r
+ return Response.status(404).build();\r
+ if (fields.size() > 0) {\r
+ NeutronRouter ans = routerInterface.getRouter(routerUUID);\r
+ return Response.status(200).entity(\r
+ new NeutronRouterRequest(extractFields(ans, fields))).build();\r
+ } else\r
+ return Response.status(200).entity(\r
+ new NeutronRouterRequest(routerInterface.getRouter(routerUUID))).build();\r
+ }\r
+\r
+ /**\r
+ * Creates new Routers */\r
+\r
+ @POST\r
+ @Produces({ MediaType.APPLICATION_JSON })\r
+ @Consumes({ MediaType.APPLICATION_JSON })\r
+ //@TypeHint(OpenStackRouters.class)\r
+ @StatusCodes({\r
+ @ResponseCode(code = 201, condition = "Created"),\r
+ @ResponseCode(code = 400, condition = "Bad Request"),\r
+ @ResponseCode(code = 401, condition = "Unauthorized"),\r
+ @ResponseCode(code = 501, condition = "Not Implemented") })\r
+ public Response createRouters(final NeutronRouterRequest input) {\r
+ INeutronRouterCRUD routerInterface = NeutronNBInterfaces.getIfNBRouterCRUD("default",this);\r
+ if (routerInterface == null) {\r
+ throw new ServiceUnavailableException("Router CRUD Interface "\r
+ + RestMessages.SERVICEUNAVAILABLE.toString());\r
+ }\r
+ INeutronNetworkCRUD networkInterface = NeutronNBInterfaces.getIfNBNetworkCRUD("default", this);\r
+ if (networkInterface == null) {\r
+ throw new ServiceUnavailableException("Network CRUD Interface "\r
+ + RestMessages.SERVICEUNAVAILABLE.toString());\r
+ }\r
+ if (input.isSingleton()) {\r
+ NeutronRouter singleton = input.getSingleton();\r
+\r
+ /*\r
+ * verify that the router doesn't already exist (issue: is deeper inspection necessary?)\r
+ * if there is external gateway information provided, verify that the specified network\r
+ * exists and has been designated as "router:external"\r
+ */\r
+ if (routerInterface.routerExists(singleton.getID()))\r
+ return Response.status(400).build();\r
+ if (singleton.getExternalGatewayInfo() != null) {\r
+ String externNetworkPtr = singleton.getExternalGatewayInfo().getNetworkID();\r
+ if (!networkInterface.networkExists(externNetworkPtr))\r
+ return Response.status(400).build();\r
+ NeutronNetwork externNetwork = networkInterface.getNetwork(externNetworkPtr);\r
+ if (!externNetwork.isRouterExternal())\r
+ return Response.status(400).build();\r
+ }\r
+ Object[] instances = ServiceHelper.getGlobalInstances(INeutronRouterAware.class, this, null);\r
+ if (instances != null) {\r
+ for (Object instance : instances) {\r
+ INeutronRouterAware service = (INeutronRouterAware) instance;\r
+ int status = service.canCreateRouter(singleton);\r
+ if (status < 200 || status > 299)\r
+ return Response.status(status).build();\r
+ }\r
+ }\r
+\r
+ /*\r
+ * add router to the cache\r
+ */\r
+ routerInterface.addRouter(singleton);\r
+ if (instances != null) {\r
+ for (Object instance : instances) {\r
+ INeutronRouterAware service = (INeutronRouterAware) instance;\r
+ service.neutronRouterCreated(singleton);\r
+ }\r
+ }\r
+ } else {\r
+\r
+ /*\r
+ * only singleton router creates supported\r
+ */\r
+ return Response.status(400).build();\r
+ }\r
+ return Response.status(201).entity(input).build();\r
+ }\r
+\r
+ /**\r
+ * Updates a Router */\r
+\r
+ @Path("{routerUUID}")\r
+ @PUT\r
+ @Produces({ MediaType.APPLICATION_JSON })\r
+ @Consumes({ MediaType.APPLICATION_JSON })\r
+ //@TypeHint(OpenStackRouters.class)\r
+ @StatusCodes({\r
+ @ResponseCode(code = 200, condition = "Operation successful"),\r
+ @ResponseCode(code = 400, condition = "Bad Request"),\r
+ @ResponseCode(code = 401, condition = "Unauthorized"),\r
+ @ResponseCode(code = 404, condition = "Not Found"),\r
+ @ResponseCode(code = 501, condition = "Not Implemented") })\r
+ public Response updateRouter(\r
+ @PathParam("routerUUID") String routerUUID,\r
+ NeutronRouterRequest input\r
+ ) {\r
+ INeutronRouterCRUD routerInterface = NeutronNBInterfaces.getIfNBRouterCRUD("default",this);\r
+ if (routerInterface == null) {\r
+ throw new ServiceUnavailableException("Router CRUD Interface "\r
+ + RestMessages.SERVICEUNAVAILABLE.toString());\r
+ }\r
+ INeutronNetworkCRUD networkInterface = NeutronNBInterfaces.getIfNBNetworkCRUD("default", this);\r
+ if (networkInterface == null) {\r
+ throw new ServiceUnavailableException("Network CRUD Interface "\r
+ + RestMessages.SERVICEUNAVAILABLE.toString());\r
+ }\r
+\r
+ /*\r
+ * router has to exist and only a single delta can be supplied\r
+ */\r
+ if (!routerInterface.routerExists(routerUUID))\r
+ return Response.status(404).build();\r
+ if (!input.isSingleton())\r
+ return Response.status(400).build();\r
+ NeutronRouter singleton = input.getSingleton();\r
+ NeutronRouter original = routerInterface.getRouter(routerUUID);\r
+\r
+ /*\r
+ * attribute changes blocked by Neutron\r
+ */\r
+ if (singleton.getID() != null || singleton.getTenantID() != null ||\r
+ singleton.getStatus() != null)\r
+ return Response.status(400).build();\r
+\r
+ Object[] instances = ServiceHelper.getGlobalInstances(INeutronRouterAware.class, this, null);\r
+ if (instances != null) {\r
+ for (Object instance : instances) {\r
+ INeutronRouterAware service = (INeutronRouterAware) instance;\r
+ int status = service.canUpdateRouter(singleton, original);\r
+ if (status < 200 || status > 299)\r
+ return Response.status(status).build();\r
+ }\r
+ }\r
+ /*\r
+ * if the external gateway info is being changed, verify that the new network\r
+ * exists and has been designated as an external network\r
+ */\r
+ if (singleton.getExternalGatewayInfo() != null) {\r
+ String externNetworkPtr = singleton.getExternalGatewayInfo().getNetworkID();\r
+ if (!networkInterface.networkExists(externNetworkPtr))\r
+ return Response.status(400).build();\r
+ NeutronNetwork externNetwork = networkInterface.getNetwork(externNetworkPtr);\r
+ if (!externNetwork.isRouterExternal())\r
+ return Response.status(400).build();\r
+ }\r
+\r
+ /*\r
+ * update the router entry and return the modified object\r
+ */\r
+ routerInterface.updateRouter(routerUUID, singleton);\r
+ NeutronRouter updatedRouter = routerInterface.getRouter(routerUUID);\r
+ if (instances != null) {\r
+ for (Object instance : instances) {\r
+ INeutronRouterAware service = (INeutronRouterAware) instance;\r
+ service.neutronRouterUpdated(updatedRouter);\r
+ }\r
+ }\r
+ return Response.status(200).entity(\r
+ new NeutronRouterRequest(routerInterface.getRouter(routerUUID))).build();\r
+\r
+ }\r
+\r
+ /**\r
+ * Deletes a Router */\r
+\r
+ @Path("{routerUUID}")\r
+ @DELETE\r
+ @StatusCodes({\r
+ @ResponseCode(code = 204, condition = "No Content"),\r
+ @ResponseCode(code = 401, condition = "Unauthorized"),\r
+ @ResponseCode(code = 404, condition = "Not Found"),\r
+ @ResponseCode(code = 409, condition = "Conflict"),\r
+ @ResponseCode(code = 501, condition = "Not Implemented") })\r
+ public Response deleteRouter(\r
+ @PathParam("routerUUID") String routerUUID) {\r
+ INeutronRouterCRUD routerInterface = NeutronNBInterfaces.getIfNBRouterCRUD("default",this);\r
+ if (routerInterface == null) {\r
+ throw new ServiceUnavailableException("Router CRUD Interface "\r
+ + RestMessages.SERVICEUNAVAILABLE.toString());\r
+ }\r
+\r
+ /*\r
+ * verify that the router exists and is not in use before removing it\r
+ */\r
+ if (!routerInterface.routerExists(routerUUID))\r
+ return Response.status(404).build();\r
+ if (routerInterface.routerInUse(routerUUID))\r
+ return Response.status(409).build();\r
+ NeutronRouter singleton = routerInterface.getRouter(routerUUID);\r
+ Object[] instances = ServiceHelper.getGlobalInstances(INeutronRouterAware.class, this, null);\r
+ if (instances != null) {\r
+ for (Object instance : instances) {\r
+ INeutronRouterAware service = (INeutronRouterAware) instance;\r
+ int status = service.canDeleteRouter(singleton);\r
+ if (status < 200 || status > 299)\r
+ return Response.status(status).build();\r
+ }\r
+ }\r
+ routerInterface.removeRouter(routerUUID);\r
+ if (instances != null) {\r
+ for (Object instance : instances) {\r
+ INeutronRouterAware service = (INeutronRouterAware) instance;\r
+ service.neutronRouterDeleted(singleton);\r
+ }\r
+ }\r
+ return Response.status(204).build();\r
+ }\r
+\r
+ /**\r
+ * Adds an interface to a router */\r
+\r
+ @Path("{routerUUID}/add_router_interface")\r
+ @PUT\r
+ @Produces({ MediaType.APPLICATION_JSON })\r
+ @Consumes({ MediaType.APPLICATION_JSON })\r
+ //@TypeHint(OpenStackRouterInterfaces.class)\r
+ @StatusCodes({\r
+ @ResponseCode(code = 200, condition = "Operation successful"),\r
+ @ResponseCode(code = 400, condition = "Bad Request"),\r
+ @ResponseCode(code = 401, condition = "Unauthorized"),\r
+ @ResponseCode(code = 404, condition = "Not Found"),\r
+ @ResponseCode(code = 409, condition = "Conflict"),\r
+ @ResponseCode(code = 501, condition = "Not Implemented") })\r
+ public Response addRouterInterface(\r
+ @PathParam("routerUUID") String routerUUID,\r
+ NeutronRouter_Interface input\r
+ ) {\r
+ INeutronRouterCRUD routerInterface = NeutronNBInterfaces.getIfNBRouterCRUD("default",this);\r
+ if (routerInterface == null) {\r
+ throw new ServiceUnavailableException("Router CRUD Interface "\r
+ + RestMessages.SERVICEUNAVAILABLE.toString());\r
+ }\r
+ INeutronPortCRUD portInterface = NeutronNBInterfaces.getIfNBPortCRUD("default",this);\r
+ if (portInterface == null) {\r
+ throw new ServiceUnavailableException("Port CRUD Interface "\r
+ + RestMessages.SERVICEUNAVAILABLE.toString());\r
+ }\r
+ INeutronSubnetCRUD subnetInterface = NeutronNBInterfaces.getIfNBSubnetCRUD("default",this);\r
+ if (subnetInterface == null) {\r
+ throw new ServiceUnavailableException("Subnet CRUD Interface "\r
+ + RestMessages.SERVICEUNAVAILABLE.toString());\r
+ }\r
+\r
+ /*\r
+ * While the Neutron specification says that the router has to exist and the input can only specify either a subnet id\r
+ * 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
+ */\r
+ if (!routerInterface.routerExists(routerUUID))\r
+ return Response.status(400).build();\r
+ NeutronRouter target = routerInterface.getRouter(routerUUID);\r
+ if (input.getSubnetUUID() == null ||\r
+ input.getPortUUID() == null)\r
+ return Response.status(400).build();\r
+\r
+ // check that the port is part of the subnet\r
+ NeutronSubnet targetSubnet = subnetInterface.getSubnet(input.getSubnetUUID());\r
+ if (targetSubnet == null)\r
+ return Response.status(400).build();\r
+ NeutronPort targetPort = portInterface.getPort(input.getPortUUID());\r
+ if (targetPort == null)\r
+ return Response.status(400).build();\r
+ if (!targetSubnet.getPortsInSubnet().contains(targetPort))\r
+ return Response.status(400).build();\r
+\r
+ if (targetPort.getFixedIPs().size() != 1)\r
+ return Response.status(400).build();\r
+ if (targetPort.getDeviceID() != null ||\r
+ targetPort.getDeviceOwner() != null)\r
+ return Response.status(409).build();\r
+\r
+ //mark the port device id and device owner fields\r
+ targetPort.setDeviceOwner("network:router_interface");\r
+ targetPort.setDeviceID(routerUUID);\r
+\r
+ target.addInterface(input.getPortUUID(), input);\r
+ Object[] instances = ServiceHelper.getGlobalInstances(INeutronRouterAware.class, this, null);\r
+ if (instances != null) {\r
+ for (Object instance : instances) {\r
+ INeutronRouterAware service = (INeutronRouterAware) instance;\r
+ service.neutronRouterInterfaceAttached(target, input);\r
+ }\r
+ }\r
+\r
+ return Response.status(200).entity(input).build();\r
+ }\r
+\r
+ /**\r
+ * Removes an interface to a router */\r
+\r
+ @Path("{routerUUID}/remove_router_interface")\r
+ @PUT\r
+ @Produces({ MediaType.APPLICATION_JSON })\r
+ @Consumes({ MediaType.APPLICATION_JSON })\r
+ //@TypeHint(OpenStackRouterInterfaces.class)\r
+ @StatusCodes({\r
+ @ResponseCode(code = 200, condition = "Operation successful"),\r
+ @ResponseCode(code = 400, condition = "Bad Request"),\r
+ @ResponseCode(code = 401, condition = "Unauthorized"),\r
+ @ResponseCode(code = 404, condition = "Not Found"),\r
+ @ResponseCode(code = 409, condition = "Conflict"),\r
+ @ResponseCode(code = 501, condition = "Not Implemented") })\r
+ public Response removeRouterInterface(\r
+ @PathParam("routerUUID") String routerUUID,\r
+ NeutronRouter_Interface input\r
+ ) {\r
+ INeutronRouterCRUD routerInterface = NeutronNBInterfaces.getIfNBRouterCRUD("default",this);\r
+ if (routerInterface == null) {\r
+ throw new ServiceUnavailableException("Router CRUD Interface "\r
+ + RestMessages.SERVICEUNAVAILABLE.toString());\r
+ }\r
+ INeutronPortCRUD portInterface = NeutronNBInterfaces.getIfNBPortCRUD("default",this);\r
+ if (portInterface == null) {\r
+ throw new ServiceUnavailableException("Port CRUD Interface "\r
+ + RestMessages.SERVICEUNAVAILABLE.toString());\r
+ }\r
+ INeutronSubnetCRUD subnetInterface = NeutronNBInterfaces.getIfNBSubnetCRUD("default",this);\r
+ if (subnetInterface == null) {\r
+ throw new ServiceUnavailableException("Subnet CRUD Interface "\r
+ + RestMessages.SERVICEUNAVAILABLE.toString());\r
+ }\r
+\r
+ // verify the router exists\r
+ if (!routerInterface.routerExists(routerUUID))\r
+ return Response.status(400).build();\r
+ NeutronRouter target = routerInterface.getRouter(routerUUID);\r
+\r
+ /*\r
+ * remove by subnet id. Collect information about the impacted router for the response and\r
+ * remove the port corresponding to the gateway IP address of the subnet\r
+ */\r
+ if (input.getPortUUID() == null &&\r
+ input.getSubnetUUID() != null) {\r
+ NeutronPort port = portInterface.getGatewayPort(input.getSubnetUUID());\r
+ if (port == null)\r
+ return Response.status(404).build();\r
+ input.setPortUUID(port.getID());\r
+ input.setID(target.getID());\r
+ input.setTenantID(target.getTenantID());\r
+\r
+ // reset the port ownership\r
+ port.setDeviceID(null);\r
+ port.setDeviceOwner(null);\r
+\r
+ target.removeInterface(input.getPortUUID());\r
+ Object[] instances = ServiceHelper.getGlobalInstances(INeutronRouterAware.class, this, null);\r
+ if (instances != null) {\r
+ for (Object instance : instances) {\r
+ INeutronRouterAware service = (INeutronRouterAware) instance;\r
+ service.neutronRouterInterfaceDetached(target, input);\r
+ }\r
+ }\r
+ return Response.status(200).entity(input).build();\r
+ }\r
+\r
+ /*\r
+ * remove by port id. collect information about the impacted router for the response\r
+ * remove the interface and reset the port ownership\r
+ */\r
+ if (input.getPortUUID() != null &&\r
+ input.getSubnetUUID() == null) {\r
+ NeutronRouter_Interface targetInterface = target.getInterfaces().get(input.getPortUUID());\r
+ input.setSubnetUUID(targetInterface.getSubnetUUID());\r
+ input.setID(target.getID());\r
+ input.setTenantID(target.getTenantID());\r
+ NeutronPort port = portInterface.getPort(input.getPortUUID());\r
+ port.setDeviceID(null);\r
+ port.setDeviceOwner(null);\r
+ target.removeInterface(input.getPortUUID());\r
+ Object[] instances = ServiceHelper.getGlobalInstances(INeutronRouterAware.class, this, null);\r
+ for (Object instance : instances) {\r
+ INeutronRouterAware service = (INeutronRouterAware) instance;\r
+ service.neutronRouterInterfaceDetached(target, input);\r
+ }\r
+ return Response.status(200).entity(input).build();\r
+ }\r
+\r
+ /*\r
+ * remove by both port and subnet ID. Verify that the first fixed IP of the port is a valid\r
+ * IP address for the subnet, and then remove the interface, collecting information about the\r
+ * impacted router for the response and reset port ownership\r
+ */\r
+ if (input.getPortUUID() != null &&\r
+ input.getSubnetUUID() != null) {\r
+ NeutronPort port = portInterface.getPort(input.getPortUUID());\r
+ NeutronSubnet subnet = subnetInterface.getSubnet(input.getSubnetUUID());\r
+ if (!subnet.isValidIP(port.getFixedIPs().get(0).getIpAddress()))\r
+ return Response.status(409).build();\r
+ input.setID(target.getID());\r
+ input.setTenantID(target.getTenantID());\r
+ port.setDeviceID(null);\r
+ port.setDeviceOwner(null);\r
+ target.removeInterface(input.getPortUUID());\r
+ Object[] instances = ServiceHelper.getGlobalInstances(INeutronRouterAware.class, this, null);\r
+ for (Object instance : instances) {\r
+ INeutronRouterAware service = (INeutronRouterAware) instance;\r
+ service.neutronRouterInterfaceDetached(target, input);\r
+ }\r
+ return Response.status(200).entity(input).build();\r
+ }\r
+\r
+ // have to specify either a port ID or a subnet ID\r
+ return Response.status(400).build();\r
+ }\r
+}\r