X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=blobdiff_plain;f=opendaylight%2Fnorthbound%2Fnetworkconfiguration%2Fneutron%2Fsrc%2Fmain%2Fjava%2Forg%2Fopendaylight%2Fcontroller%2Fnetworkconfig%2Fneutron%2Fnorthbound%2FNeutronPortsNorthbound.java;h=5451fbf3e129e4be88addabcc7816e308c2cb2b7;hb=05861a85bc830af3fce638c301949da23c803ee4;hp=08e5dfbb364d6cf7c82b2c677cff3359f533a13b;hpb=d542617f3486541cf9937009fb6aa1e3f2c9f0e2;p=controller.git diff --git a/opendaylight/northbound/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/northbound/NeutronPortsNorthbound.java b/opendaylight/northbound/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/northbound/NeutronPortsNorthbound.java index 08e5dfbb36..5451fbf3e1 100644 --- a/opendaylight/northbound/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/northbound/NeutronPortsNorthbound.java +++ b/opendaylight/northbound/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/northbound/NeutronPortsNorthbound.java @@ -12,8 +12,10 @@ import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.List; + import javax.ws.rs.Consumes; import javax.ws.rs.DELETE; +import javax.ws.rs.DefaultValue; import javax.ws.rs.GET; import javax.ws.rs.POST; import javax.ws.rs.PUT; @@ -21,27 +23,31 @@ import javax.ws.rs.Path; import javax.ws.rs.PathParam; import javax.ws.rs.Produces; import javax.ws.rs.QueryParam; +import javax.ws.rs.core.Context; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; +import javax.ws.rs.core.UriInfo; import org.codehaus.enunciate.jaxrs.ResponseCode; import org.codehaus.enunciate.jaxrs.StatusCodes; import org.opendaylight.controller.networkconfig.neutron.INeutronNetworkCRUD; import org.opendaylight.controller.networkconfig.neutron.INeutronPortAware; import org.opendaylight.controller.networkconfig.neutron.INeutronPortCRUD; -import org.opendaylight.controller.networkconfig.neutron.INeutronSubnetAware; import org.opendaylight.controller.networkconfig.neutron.INeutronSubnetCRUD; import org.opendaylight.controller.networkconfig.neutron.NeutronCRUDInterfaces; import org.opendaylight.controller.networkconfig.neutron.NeutronPort; import org.opendaylight.controller.networkconfig.neutron.NeutronSubnet; import org.opendaylight.controller.networkconfig.neutron.Neutron_IPs; import org.opendaylight.controller.northbound.commons.RestMessages; +import org.opendaylight.controller.northbound.commons.exception.BadRequestException; +import org.opendaylight.controller.northbound.commons.exception.ResourceConflictException; +import org.opendaylight.controller.northbound.commons.exception.ResourceNotFoundException; import org.opendaylight.controller.northbound.commons.exception.ServiceUnavailableException; import org.opendaylight.controller.sal.utils.ServiceHelper; /** - * Open DOVE Northbound REST APIs.
- * This class provides REST APIs for managing the open DOVE + * Neutron Northbound REST APIs.
+ * This class provides REST APIs for managing neutron port objects * *
*
@@ -60,10 +66,15 @@ import org.opendaylight.controller.sal.utils.ServiceHelper; @Path("/ports") public class NeutronPortsNorthbound { + final String mac_regex="^([0-9A-Fa-f]{2}[:-]){5}([0-9A-Fa-f]{2})$"; + private NeutronPort extractFields(NeutronPort o, List fields) { return o.extractFields(fields); } + @Context + UriInfo uriInfo; + /** * Returns a list of all Ports */ @@ -71,9 +82,9 @@ public class NeutronPortsNorthbound { @Produces({ MediaType.APPLICATION_JSON }) //@TypeHint(OpenStackPorts.class) @StatusCodes({ - @ResponseCode(code = 200, condition = "Operation successful"), - @ResponseCode(code = 401, condition = "Unauthorized"), - @ResponseCode(code = 501, condition = "Not Implemented") }) + @ResponseCode(code = 200, condition = "Operation successful"), + @ResponseCode(code = 401, condition = "Unauthorized"), + @ResponseCode(code = 501, condition = "Not Implemented") }) public Response listPorts( // return fields @QueryParam("fields") List fields, @@ -87,10 +98,10 @@ public class NeutronPortsNorthbound { @QueryParam("device_id") String queryDeviceID, @QueryParam("device_owner") String queryDeviceOwner, @QueryParam("tenant_id") String queryTenantID, - // pagination - @QueryParam("limit") String limit, + // linkTitle + @QueryParam("limit") Integer limit, @QueryParam("marker") String marker, - @QueryParam("page_reverse") String pageReverse + @DefaultValue("false") @QueryParam("page_reverse") Boolean pageReverse // sorting not supported ) { INeutronPortCRUD portInterface = NeutronCRUDInterfaces.getINeutronPortCRUD(this); @@ -112,13 +123,21 @@ public class NeutronPortsNorthbound { (queryDeviceID == null || queryDeviceID.equals(oSS.getDeviceID())) && (queryDeviceOwner == null || queryDeviceOwner.equals(oSS.getDeviceOwner())) && (queryTenantID == null || queryTenantID.equals(oSS.getTenantID()))) { - if (fields.size() > 0) + if (fields.size() > 0) { ans.add(extractFields(oSS,fields)); - else + } else { ans.add(oSS); + } } } - //TODO: apply pagination to results + + if (limit != null && ans.size() > 1) { + // Return a paginated request + NeutronPortRequest request = (NeutronPortRequest) PaginatedRequestFactory.createRequest(limit, + marker, pageReverse, uriInfo, ans, NeutronPort.class); + return Response.status(200).entity(request).build(); + } + return Response.status(200).entity( new NeutronPortRequest(ans)).build(); } @@ -131,10 +150,10 @@ public class NeutronPortsNorthbound { @Produces({ MediaType.APPLICATION_JSON }) //@TypeHint(OpenStackPorts.class) @StatusCodes({ - @ResponseCode(code = 200, condition = "Operation successful"), - @ResponseCode(code = 401, condition = "Unauthorized"), - @ResponseCode(code = 404, condition = "Not Found"), - @ResponseCode(code = 501, condition = "Not Implemented") }) + @ResponseCode(code = 200, condition = "Operation successful"), + @ResponseCode(code = 401, condition = "Unauthorized"), + @ResponseCode(code = 404, condition = "Not Found"), + @ResponseCode(code = 501, condition = "Not Implemented") }) public Response showPort( @PathParam("portUUID") String portUUID, // return fields @@ -144,15 +163,17 @@ public class NeutronPortsNorthbound { throw new ServiceUnavailableException("Port CRUD Interface " + RestMessages.SERVICEUNAVAILABLE.toString()); } - if (!portInterface.portExists(portUUID)) - return Response.status(404).build(); + if (!portInterface.portExists(portUUID)) { + throw new ResourceNotFoundException("port UUID does not exist."); + } if (fields.size() > 0) { NeutronPort ans = portInterface.getPort(portUUID); return Response.status(200).entity( new NeutronPortRequest(extractFields(ans, fields))).build(); - } else + } else { return Response.status(200).entity( new NeutronPortRequest(portInterface.getPort(portUUID))).build(); + } } /** @@ -163,14 +184,14 @@ public class NeutronPortsNorthbound { @Consumes({ MediaType.APPLICATION_JSON }) //@TypeHint(OpenStackPorts.class) @StatusCodes({ - @ResponseCode(code = 201, condition = "Created"), - @ResponseCode(code = 400, condition = "Bad Request"), - @ResponseCode(code = 401, condition = "Unauthorized"), - @ResponseCode(code = 403, condition = "Forbidden"), - @ResponseCode(code = 404, condition = "Not Found"), - @ResponseCode(code = 409, condition = "Conflict"), - @ResponseCode(code = 501, condition = "Not Implemented"), - @ResponseCode(code = 503, condition = "MAC generation failure") }) + @ResponseCode(code = 201, condition = "Created"), + @ResponseCode(code = 400, condition = "Bad Request"), + @ResponseCode(code = 401, condition = "Unauthorized"), + @ResponseCode(code = 403, condition = "Forbidden"), + @ResponseCode(code = 404, condition = "Not Found"), + @ResponseCode(code = 409, condition = "Conflict"), + @ResponseCode(code = 501, condition = "Not Implemented"), + @ResponseCode(code = 503, condition = "MAC generation failure") }) public Response createPorts(final NeutronPortRequest input) { INeutronPortCRUD portInterface = NeutronCRUDInterfaces.getINeutronPortCRUD(this); if (portInterface == null) { @@ -194,25 +215,21 @@ public class NeutronPortsNorthbound { * the port must be part of an existing network, must not already exist, * have a valid MAC and the MAC not be in use */ - if (singleton.getNetworkUUID() == null) - return Response.status(400).build(); - if (portInterface.portExists(singleton.getID())) - return Response.status(400).build(); - if (!networkInterface.networkExists(singleton.getNetworkUUID())) - return Response.status(404).build(); + if (singleton.getNetworkUUID() == null) { + throw new BadRequestException("network UUID musy be specified"); + } + if (portInterface.portExists(singleton.getID())) { + throw new BadRequestException("port UUID already exists"); + } + if (!networkInterface.networkExists(singleton.getNetworkUUID())) { + throw new ResourceNotFoundException("network UUID does not exist."); + } if (singleton.getMacAddress() == null || - !singleton.getMacAddress().matches("^([0-9A-F]{2}[:-]){5}([0-9A-F]{2})$")) - return Response.status(400).build(); - if (portInterface.macInUse(singleton.getMacAddress())) - return Response.status(409).build(); - Object[] instances = ServiceHelper.getGlobalInstances(INeutronPortAware.class, this, null); - if (instances != null) { - for (Object instance : instances) { - INeutronPortAware service = (INeutronPortAware) instance; - int status = service.canCreatePort(singleton); - if (status < 200 || status > 299) - return Response.status(status).build(); - } + !singleton.getMacAddress().matches(mac_regex)) { + throw new BadRequestException("MAC address not properly formatted"); + } + if (portInterface.macInUse(singleton.getMacAddress())) { + throw new ResourceConflictException("MAC Address is in use."); } /* * if fixed IPs are specified, each one has to have an existing subnet ID @@ -225,22 +242,39 @@ public class NeutronPortsNorthbound { Iterator fixedIPIterator = fixedIPs.iterator(); while (fixedIPIterator.hasNext()) { Neutron_IPs ip = fixedIPIterator.next(); - if (ip.getSubnetUUID() == null) - return Response.status(400).build(); - if (!subnetInterface.subnetExists(ip.getSubnetUUID())) - return Response.status(400).build(); + if (ip.getSubnetUUID() == null) { + throw new BadRequestException("subnet UUID not specified"); + } + if (!subnetInterface.subnetExists(ip.getSubnetUUID())) { + throw new BadRequestException("subnet UUID must exists"); + } NeutronSubnet subnet = subnetInterface.getSubnet(ip.getSubnetUUID()); - if (!singleton.getNetworkUUID().equalsIgnoreCase(subnet.getNetworkUUID())) - return Response.status(400).build(); + if (!singleton.getNetworkUUID().equalsIgnoreCase(subnet.getNetworkUUID())) { + throw new BadRequestException("network UUID must match that of subnet"); + } if (ip.getIpAddress() != null) { - if (!subnet.isValidIP(ip.getIpAddress())) - return Response.status(400).build(); - if (subnet.isIPInUse(ip.getIpAddress())) - return Response.status(409).build(); + if (!subnet.isValidIP(ip.getIpAddress())) { + throw new BadRequestException("IP address is not valid"); + } + if (subnet.isIPInUse(ip.getIpAddress())) { + throw new ResourceConflictException("IP address is in use."); + } } } } + Object[] instances = ServiceHelper.getGlobalInstances(INeutronPortAware.class, this, null); + if (instances != null) { + for (Object instance : instances) { + INeutronPortAware service = (INeutronPortAware) instance; + int status = service.canCreatePort(singleton); + if (status < 200 || status > 299) { + return Response.status(status).build(); + } + } + } + + // add the port to the cache portInterface.addPort(singleton); if (instances != null) { @@ -253,7 +287,7 @@ public class NeutronPortsNorthbound { List bulk = input.getBulk(); Iterator i = bulk.iterator(); HashMap testMap = new HashMap(); - Object[] instances = ServiceHelper.getGlobalInstances(INeutronSubnetAware.class, this, null); + Object[] instances = ServiceHelper.getGlobalInstances(INeutronPortAware.class, this, null); while (i.hasNext()) { NeutronPort test = i.next(); @@ -262,35 +296,35 @@ public class NeutronPortsNorthbound { * have a valid MAC and the MAC not be in use. Further the bulk request * can't already contain a new port with the same UUID */ - if (portInterface.portExists(test.getID())) - return Response.status(400).build(); - if (testMap.containsKey(test.getID())) - return Response.status(400).build(); + if (portInterface.portExists(test.getID())) { + throw new BadRequestException("port UUID already exists"); + } + if (testMap.containsKey(test.getID())) { + throw new BadRequestException("port UUID already exists"); + } for (NeutronPort check : testMap.values()) { - if (test.getMacAddress().equalsIgnoreCase(check.getMacAddress())) - return Response.status(409).build(); + if (test.getMacAddress().equalsIgnoreCase(check.getMacAddress())) { + throw new ResourceConflictException("MAC address already allocated"); + } for (Neutron_IPs test_fixedIP : test.getFixedIPs()) { for (Neutron_IPs check_fixedIP : check.getFixedIPs()) { - if (test_fixedIP.getIpAddress().equals(check_fixedIP.getIpAddress())) - return Response.status(409).build(); + if (test_fixedIP.getIpAddress().equals(check_fixedIP.getIpAddress())) { + throw new ResourceConflictException("IP address already allocated"); + } } } } testMap.put(test.getID(), test); - if (!networkInterface.networkExists(test.getNetworkUUID())) - return Response.status(404).build(); - if (!test.getMacAddress().matches("^([0-9A-F]{2}[:-]){5}([0-9A-F]{2})$")) - return Response.status(400).build(); - if (portInterface.macInUse(test.getMacAddress())) - return Response.status(409).build(); - if (instances != null) { - for (Object instance : instances) { - INeutronPortAware service = (INeutronPortAware) instance; - int status = service.canCreatePort(test); - if (status < 200 || status > 299) - return Response.status(status).build(); - } + if (!networkInterface.networkExists(test.getNetworkUUID())) { + throw new ResourceNotFoundException("network UUID does not exist."); + } + if (!test.getMacAddress().matches(mac_regex)) { + throw new BadRequestException("MAC address not properly formatted"); + } + if (portInterface.macInUse(test.getMacAddress())) { + throw new ResourceConflictException("MAC address in use"); } + /* * if fixed IPs are specified, each one has to have an existing subnet ID * that is in the same scoping network as the port. In addition, if an IP @@ -302,20 +336,34 @@ public class NeutronPortsNorthbound { Iterator fixedIPIterator = fixedIPs.iterator(); while (fixedIPIterator.hasNext()) { Neutron_IPs ip = fixedIPIterator.next(); - if (ip.getSubnetUUID() == null) - return Response.status(400).build(); - if (!subnetInterface.subnetExists(ip.getSubnetUUID())) - return Response.status(400).build(); + if (ip.getSubnetUUID() == null) { + throw new BadRequestException("subnet UUID must be specified"); + } + if (!subnetInterface.subnetExists(ip.getSubnetUUID())) { + throw new BadRequestException("subnet UUID doesn't exists"); + } NeutronSubnet subnet = subnetInterface.getSubnet(ip.getSubnetUUID()); - if (!test.getNetworkUUID().equalsIgnoreCase(subnet.getNetworkUUID())) - return Response.status(400).build(); + if (!test.getNetworkUUID().equalsIgnoreCase(subnet.getNetworkUUID())) { + throw new BadRequestException("network UUID must match that of subnet"); + } if (ip.getIpAddress() != null) { - if (!subnet.isValidIP(ip.getIpAddress())) - return Response.status(400).build(); + if (!subnet.isValidIP(ip.getIpAddress())) { + throw new BadRequestException("ip address not valid"); + } //TODO: need to add consideration for a fixed IP being assigned the same address as a allocated IP in the //same bulk create - if (subnet.isIPInUse(ip.getIpAddress())) - return Response.status(409).build(); + if (subnet.isIPInUse(ip.getIpAddress())) { + throw new ResourceConflictException("IP address in use"); + } + } + } + } + if (instances != null) { + for (Object instance : instances) { + INeutronPortAware service = (INeutronPortAware) instance; + int status = service.canCreatePort(test); + if (status < 200 || status > 299) { + return Response.status(status).build(); } } } @@ -346,13 +394,13 @@ public class NeutronPortsNorthbound { @Consumes({ MediaType.APPLICATION_JSON }) //@TypeHint(OpenStackPorts.class) @StatusCodes({ - @ResponseCode(code = 200, condition = "Operation successful"), - @ResponseCode(code = 400, condition = "Bad Request"), - @ResponseCode(code = 401, condition = "Unauthorized"), - @ResponseCode(code = 403, condition = "Forbidden"), - @ResponseCode(code = 404, condition = "Not Found"), - @ResponseCode(code = 409, condition = "Conflict"), - @ResponseCode(code = 501, condition = "Not Implemented") }) + @ResponseCode(code = 200, condition = "Operation successful"), + @ResponseCode(code = 400, condition = "Bad Request"), + @ResponseCode(code = 401, condition = "Unauthorized"), + @ResponseCode(code = 403, condition = "Forbidden"), + @ResponseCode(code = 404, condition = "Not Found"), + @ResponseCode(code = 409, condition = "Conflict"), + @ResponseCode(code = 501, condition = "Not Implemented") }) public Response updatePort( @PathParam("portUUID") String portUUID, NeutronPortRequest input @@ -369,26 +417,30 @@ public class NeutronPortsNorthbound { } // port has to exist and only a single delta is supported - if (!portInterface.portExists(portUUID)) - return Response.status(404).build(); + if (!portInterface.portExists(portUUID)) { + throw new ResourceNotFoundException("port UUID does not exist."); + } NeutronPort target = portInterface.getPort(portUUID); - if (!input.isSingleton()) - return Response.status(400).build(); + if (!input.isSingleton()) { + throw new BadRequestException("only singleton edit suported"); + } NeutronPort singleton = input.getSingleton(); NeutronPort original = portInterface.getPort(portUUID); // deltas restricted by Neutron if (singleton.getID() != null || singleton.getTenantID() != null || - singleton.getStatus() != null) - return Response.status(400).build(); + singleton.getStatus() != null) { + throw new BadRequestException("attribute change blocked by Neutron"); + } Object[] instances = ServiceHelper.getGlobalInstances(INeutronPortAware.class, this, null); if (instances != null) { for (Object instance : instances) { INeutronPortAware service = (INeutronPortAware) instance; int status = service.canUpdatePort(singleton, original); - if (status < 200 || status > 299) + if (status < 200 || status > 299) { return Response.status(status).build(); + } } } @@ -398,23 +450,28 @@ public class NeutronPortsNorthbound { Iterator fixedIPIterator = fixedIPs.iterator(); while (fixedIPIterator.hasNext()) { Neutron_IPs ip = fixedIPIterator.next(); - if (ip.getSubnetUUID() == null) - return Response.status(400).build(); - if (!subnetInterface.subnetExists(ip.getSubnetUUID())) - return Response.status(400).build(); + if (ip.getSubnetUUID() == null) { + throw new BadRequestException("subnet UUID must be specified"); + } + if (!subnetInterface.subnetExists(ip.getSubnetUUID())) { + throw new BadRequestException("subnet UUID doesn't exist."); + } NeutronSubnet subnet = subnetInterface.getSubnet(ip.getSubnetUUID()); - if (!target.getNetworkUUID().equalsIgnoreCase(subnet.getNetworkUUID())) - return Response.status(400).build(); + if (!target.getNetworkUUID().equalsIgnoreCase(subnet.getNetworkUUID())) { + throw new BadRequestException("network UUID must match that of subnet"); + } if (ip.getIpAddress() != null) { - if (!subnet.isValidIP(ip.getIpAddress())) - return Response.status(400).build(); - if (subnet.isIPInUse(ip.getIpAddress())) - return Response.status(409).build(); + if (!subnet.isValidIP(ip.getIpAddress())) { + throw new BadRequestException("invalid IP address"); + } + if (subnet.isIPInUse(ip.getIpAddress())) { + throw new ResourceConflictException("IP address in use"); + } } } } -// TODO: Support change of security groups + // TODO: Support change of security groups // update the port and return the modified object portInterface.updatePort(portUUID, singleton); NeutronPort updatedPort = portInterface.getPort(portUUID); @@ -449,20 +506,23 @@ public class NeutronPortsNorthbound { } // port has to exist and not be owned by anyone. then it can be removed from the cache - if (!portInterface.portExists(portUUID)) - return Response.status(404).build(); + if (!portInterface.portExists(portUUID)) { + throw new ResourceNotFoundException("port UUID does not exist."); + } NeutronPort port = portInterface.getPort(portUUID); if (port.getDeviceID() != null || - port.getDeviceOwner() != null) + port.getDeviceOwner() != null) { Response.status(403).build(); + } NeutronPort singleton = portInterface.getPort(portUUID); Object[] instances = ServiceHelper.getGlobalInstances(INeutronPortAware.class, this, null); if (instances != null) { for (Object instance : instances) { INeutronPortAware service = (INeutronPortAware) instance; int status = service.canDeletePort(singleton); - if (status < 200 || status > 299) + if (status < 200 || status > 299) { return Response.status(status).build(); + } } } portInterface.removePort(portUUID);