X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?p=controller.git;a=blobdiff_plain;f=opendaylight%2Fnorthbound%2Fnetworkconfiguration%2Fneutron%2Fsrc%2Fmain%2Fjava%2Forg%2Fopendaylight%2Fcontroller%2Fnetworkconfig%2Fneutron%2Fnorthbound%2FNeutronNetworksNorthbound.java;h=52c3337e40047fb844352fd9dcc0b6c596fcb8d0;hp=e8690aa889aee1d449601a3156757d298de9dd72;hb=b2d51144854503513151435f164510ef0dd47b1f;hpb=caee336f062eba4909ba53cbaccdde0714236134 diff --git a/opendaylight/northbound/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/northbound/NeutronNetworksNorthbound.java b/opendaylight/northbound/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/northbound/NeutronNetworksNorthbound.java index e8690aa889..52c3337e40 100644 --- a/opendaylight/northbound/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/northbound/NeutronNetworksNorthbound.java +++ b/opendaylight/northbound/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/northbound/NeutronNetworksNorthbound.java @@ -9,11 +9,15 @@ package org.opendaylight.controller.networkconfig.neutron.northbound; import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; 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,7 +25,9 @@ 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.UriInfo; import javax.ws.rs.core.Response; import org.codehaus.enunciate.jaxrs.ResponseCode; @@ -32,12 +38,15 @@ import org.opendaylight.controller.networkconfig.neutron.INeutronNetworkCRUD; import org.opendaylight.controller.networkconfig.neutron.NeutronCRUDInterfaces; import org.opendaylight.controller.networkconfig.neutron.NeutronNetwork; 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 for Network.
- * This class provides REST APIs for managing open DOVE internals related to Networks + * Neutron Northbound REST APIs for Network.
+ * This class provides REST APIs for managing neutron Networks * *
*
@@ -56,6 +65,9 @@ import org.opendaylight.controller.sal.utils.ServiceHelper; @Path("/networks") public class NeutronNetworksNorthbound { + @Context + UriInfo uriInfo; + private NeutronNetwork extractFields(NeutronNetwork o, List fields) { return o.extractFields(fields); } @@ -67,8 +79,8 @@ public class NeutronNetworksNorthbound { @Produces({ MediaType.APPLICATION_JSON }) //@TypeHint(OpenStackNetworks.class) @StatusCodes({ - @ResponseCode(code = 200, condition = "Operation successful"), - @ResponseCode(code = 401, condition = "Unauthorized") }) + @ResponseCode(code = 200, condition = "Operation successful"), + @ResponseCode(code = 401, condition = "Unauthorized")}) public Response listNetworks( // return fields @QueryParam("fields") List fields, @@ -84,11 +96,11 @@ public class NeutronNetworksNorthbound { @QueryParam("provider_physical_network") String queryProviderPhysicalNetwork, @QueryParam("provider_segmentation_id") String queryProviderSegmentationID, // pagination - @QueryParam("limit") String limit, + @QueryParam("limit") Integer limit, @QueryParam("marker") String marker, - @QueryParam("page_reverse") String pageReverse + @DefaultValue("false") @QueryParam("page_reverse") Boolean pageReverse // sorting not supported - ) { + ) { INeutronNetworkCRUD networkInterface = NeutronCRUDInterfaces.getINeutronNetworkCRUD( this); if (networkInterface == null) { throw new ServiceUnavailableException("Network CRUD Interface " @@ -103,12 +115,15 @@ public class NeutronNetworksNorthbound { Boolean bAdminStateUp = null; Boolean bShared = null; Boolean bRouterExternal = null; - if (queryAdminStateUp != null) + if (queryAdminStateUp != null) { bAdminStateUp = Boolean.valueOf(queryAdminStateUp); - if (queryShared != null) + } + if (queryShared != null) { bShared = Boolean.valueOf(queryShared); - if (queryRouterExternal != null) + } + if (queryRouterExternal != null) { bRouterExternal = Boolean.valueOf(queryRouterExternal); + } if ((queryID == null || queryID.equals(oSN.getID())) && (queryName == null || queryName.equals(oSN.getNetworkName())) && (bAdminStateUp == null || bAdminStateUp.booleanValue() == oSN.isAdminStateUp()) && @@ -116,15 +131,101 @@ public class NeutronNetworksNorthbound { (bShared == null || bShared.booleanValue() == oSN.isShared()) && (bRouterExternal == null || bRouterExternal.booleanValue() == oSN.isRouterExternal()) && (queryTenantID == null || queryTenantID.equals(oSN.getTenantID()))) { - if (fields.size() > 0) + if (fields.size() > 0) { ans.add(extractFields(oSN,fields)); - else + } else { ans.add(oSN); + } + } + } + + Comparator neutronNetworkComparator = new Comparator() { + @Override + public int compare(NeutronNetwork o1, NeutronNetwork o2) { + return o1.getID().compareTo(o2.getID()); + } + }; + + Collections.sort(ans, neutronNetworkComparator); + + if (limit != null && ans.size() > 1) { + List links = new ArrayList<>(); + Integer startPos = null; + String startMarker; + String endMarker; + Boolean firstPage = false; + Boolean lastPage = false; + + if (marker == null) { + startPos = 0; + } + + else { + + NeutronNetwork markerNetwork = new NeutronNetwork(); + markerNetwork.setNetworkUUID(marker); + + startPos = Collections.binarySearch(ans, markerNetwork, neutronNetworkComparator); + + if (!pageReverse){ + startPos = startPos + 1; + } + else { + startPos = startPos - limit; + } + + } + + if (startPos == null) { + throw new ResourceNotFoundException("UUID for marker:" + marker + " could not be found"); + } + + if (startPos == 0){ + firstPage = true; + } + + if (startPos + limit >= ans.size()) { + ans = ans.subList(startPos, ans.size()); + startMarker = ans.get(0).getID(); + endMarker = ans.get(ans.size() - 1).getID(); + lastPage = true; + } + else if (startPos < 0) { + if (startPos + limit > 0) { + ans = ans.subList(0, startPos + limit); + startMarker = ans.get(0).getID(); + endMarker = ans.get(ans.size() - 1).getID(); + firstPage = true; + } + else { + throw new BadRequestException("Requested page is out of bounds. Please check the supplied limit and marker"); + } } + else { + ans = ans.subList(startPos, startPos + limit); + startMarker = ans.get(0).getID(); + endMarker = ans.get(limit-1).getID(); + } + + if (!lastPage) { + NeutronPageLink next = new NeutronPageLink(); + next.setRef("next"); + next.setHref(uriInfo.getAbsolutePath().toString() + "?limit=" + limit.toString() + "&marker=" + endMarker); + links.add(next); + } + + if (!firstPage) { + NeutronPageLink previous = new NeutronPageLink(); + previous.setRef("previous"); + previous.setHref(uriInfo.getAbsolutePath().toString() + "?limit=" + limit.toString() + "&marker=" + startMarker + "&page_reverse=True"); + links.add(previous); + } + + return Response.status(200).entity(new PaginatedNeutronNetworkRequest(ans, links)).build(); } - //TODO: apply pagination to results - return Response.status(200).entity( - new NeutronNetworkRequest(ans)).build(); + + return Response.status(200).entity(new NeutronNetworkRequest(ans)).build(); + } /** @@ -135,9 +236,9 @@ public class NeutronNetworksNorthbound { @Produces({ MediaType.APPLICATION_JSON }) //@TypeHint(OpenStackNetworks.class) @StatusCodes({ - @ResponseCode(code = 200, condition = "Operation successful"), - @ResponseCode(code = 401, condition = "Unauthorized"), - @ResponseCode(code = 404, condition = "Not Found") }) + @ResponseCode(code = 200, condition = "Operation successful"), + @ResponseCode(code = 401, condition = "Unauthorized"), + @ResponseCode(code = 404, condition = "Not Found") }) public Response showNetwork( @PathParam("netUUID") String netUUID, // return fields @@ -148,15 +249,17 @@ public class NeutronNetworksNorthbound { throw new ServiceUnavailableException("Network CRUD Interface " + RestMessages.SERVICEUNAVAILABLE.toString()); } - if (!networkInterface.networkExists(netUUID)) - return Response.status(404).build(); + if (!networkInterface.networkExists(netUUID)) { + throw new ResourceNotFoundException("network UUID does not exist."); + } if (fields.size() > 0) { NeutronNetwork ans = networkInterface.getNetwork(netUUID); return Response.status(200).entity( new NeutronNetworkRequest(extractFields(ans, fields))).build(); - } else + } else { return Response.status(200).entity( new NeutronNetworkRequest(networkInterface.getNetwork(netUUID))).build(); + } } /** @@ -166,9 +269,9 @@ public class NeutronNetworksNorthbound { @Consumes({ MediaType.APPLICATION_JSON }) @TypeHint(NeutronNetwork.class) @StatusCodes({ - @ResponseCode(code = 201, condition = "Created"), - @ResponseCode(code = 400, condition = "Bad Request"), - @ResponseCode(code = 401, condition = "Unauthorized") }) + @ResponseCode(code = 201, condition = "Created"), + @ResponseCode(code = 400, condition = "Bad Request"), + @ResponseCode(code = 401, condition = "Unauthorized") }) public Response createNetworks(final NeutronNetworkRequest input) { INeutronNetworkCRUD networkInterface = NeutronCRUDInterfaces.getINeutronNetworkCRUD( this); if (networkInterface == null) { @@ -181,20 +284,23 @@ public class NeutronNetworksNorthbound { /* * network ID can't already exist */ - if (networkInterface.networkExists(singleton.getID())) - return Response.status(400).build(); + if (networkInterface.networkExists(singleton.getID())) { + throw new BadRequestException("network UUID already exists"); + } Object[] instances = ServiceHelper.getGlobalInstances(INeutronNetworkAware.class, this, null); if (instances != null) { for (Object instance : instances) { INeutronNetworkAware service = (INeutronNetworkAware) instance; int status = service.canCreateNetwork(singleton); - if (status < 200 || status > 299) + if (status < 200 || status > 299) { return Response.status(status).build(); + } } } // add network to cache + singleton.initDefaults(); networkInterface.addNetwork(singleton); if (instances != null) { for (Object instance : instances) { @@ -215,16 +321,19 @@ public class NeutronNetworksNorthbound { * network ID can't already exist, nor can there be an entry for this UUID * already in this bulk request */ - if (networkInterface.networkExists(test.getID())) - return Response.status(400).build(); - if (testMap.containsKey(test.getID())) - return Response.status(400).build(); + if (networkInterface.networkExists(test.getID())) { + throw new BadRequestException("network UUID already exists"); + } + if (testMap.containsKey(test.getID())) { + throw new BadRequestException("network UUID already exists"); + } if (instances != null) { for (Object instance: instances) { INeutronNetworkAware service = (INeutronNetworkAware) instance; int status = service.canCreateNetwork(test); - if (status < 200 || status > 299) + if (status < 200 || status > 299) { return Response.status(status).build(); + } } } testMap.put(test.getID(),test); @@ -255,10 +364,10 @@ public class NeutronNetworksNorthbound { @Consumes({ MediaType.APPLICATION_JSON }) //@TypeHint(OpenStackNetworks.class) @StatusCodes({ - @ResponseCode(code = 200, condition = "Operation successful"), - @ResponseCode(code = 400, condition = "Bad Request"), - @ResponseCode(code = 403, condition = "Forbidden"), - @ResponseCode(code = 404, condition = "Not Found"), }) + @ResponseCode(code = 200, condition = "Operation successful"), + @ResponseCode(code = 400, condition = "Bad Request"), + @ResponseCode(code = 403, condition = "Forbidden"), + @ResponseCode(code = 404, condition = "Not Found"), }) public Response updateNetwork( @PathParam("netUUID") String netUUID, final NeutronNetworkRequest input ) { @@ -271,18 +380,21 @@ public class NeutronNetworksNorthbound { /* * network has to exist and only a single delta is supported */ - if (!networkInterface.networkExists(netUUID)) - return Response.status(404).build(); - if (!input.isSingleton()) - return Response.status(400).build(); + if (!networkInterface.networkExists(netUUID)) { + throw new ResourceNotFoundException("network UUID does not exist."); + } + if (!input.isSingleton()) { + throw new BadRequestException("only singleton edits supported"); + } NeutronNetwork delta = input.getSingleton(); /* * transitions forbidden by Neutron */ if (delta.getID() != null || delta.getTenantID() != null || - delta.getStatus() != null) - return Response.status(400).build(); + delta.getStatus() != null) { + throw new BadRequestException("attribute edit blocked by Neutron"); + } Object[] instances = ServiceHelper.getGlobalInstances(INeutronNetworkAware.class, this, null); if (instances != null) { @@ -290,22 +402,23 @@ public class NeutronNetworksNorthbound { INeutronNetworkAware service = (INeutronNetworkAware) instance; NeutronNetwork original = networkInterface.getNetwork(netUUID); int status = service.canUpdateNetwork(delta, original); - if (status < 200 || status > 299) + if (status < 200 || status > 299) { return Response.status(status).build(); + } } } // update network object and return the modified object - networkInterface.updateNetwork(netUUID, delta); - NeutronNetwork updatedSingleton = networkInterface.getNetwork(netUUID); - if (instances != null) { - for (Object instance : instances) { - INeutronNetworkAware service = (INeutronNetworkAware) instance; - service.neutronNetworkUpdated(updatedSingleton); - } - } - return Response.status(200).entity( - new NeutronNetworkRequest(networkInterface.getNetwork(netUUID))).build(); + networkInterface.updateNetwork(netUUID, delta); + NeutronNetwork updatedSingleton = networkInterface.getNetwork(netUUID); + if (instances != null) { + for (Object instance : instances) { + INeutronNetworkAware service = (INeutronNetworkAware) instance; + service.neutronNetworkUpdated(updatedSingleton); + } + } + return Response.status(200).entity( + new NeutronNetworkRequest(networkInterface.getNetwork(netUUID))).build(); } /** @@ -314,10 +427,10 @@ public class NeutronNetworksNorthbound { @Path("{netUUID}") @DELETE @StatusCodes({ - @ResponseCode(code = 204, condition = "No Content"), - @ResponseCode(code = 401, condition = "Unauthorized"), - @ResponseCode(code = 404, condition = "Not Found"), - @ResponseCode(code = 409, condition = "Network In Use") }) + @ResponseCode(code = 204, condition = "No Content"), + @ResponseCode(code = 401, condition = "Unauthorized"), + @ResponseCode(code = 404, condition = "Not Found"), + @ResponseCode(code = 409, condition = "Network In Use") }) public Response deleteNetwork( @PathParam("netUUID") String netUUID) { INeutronNetworkCRUD networkInterface = NeutronCRUDInterfaces.getINeutronNetworkCRUD( this); @@ -329,10 +442,12 @@ public class NeutronNetworksNorthbound { /* * network has to exist and not be in use before it can be removed */ - if (!networkInterface.networkExists(netUUID)) - return Response.status(404).build(); - if (networkInterface.networkInUse(netUUID)) - return Response.status(409).build(); + if (!networkInterface.networkExists(netUUID)) { + throw new ResourceNotFoundException("network UUID does not exist."); + } + if (networkInterface.networkInUse(netUUID)) { + throw new ResourceConflictException("Network ID in use"); + } NeutronNetwork singleton = networkInterface.getNetwork(netUUID); Object[] instances = ServiceHelper.getGlobalInstances(INeutronNetworkAware.class, this, null); @@ -340,8 +455,9 @@ public class NeutronNetworksNorthbound { for (Object instance : instances) { INeutronNetworkAware service = (INeutronNetworkAware) instance; int status = service.canDeleteNetwork(singleton); - if (status < 200 || status > 299) + if (status < 200 || status > 299) { return Response.status(status).build(); + } } } networkInterface.removeNetwork(netUUID);