X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=blobdiff_plain;f=opendaylight%2Fnorthbound%2Fflowprogrammer%2Fsrc%2Fmain%2Fjava%2Forg%2Fopendaylight%2Fcontroller%2Fflowprogrammer%2Fnorthbound%2FFlowProgrammerNorthbound.java;h=4928ddef3b0296b8525531791dfe4272064dfaa1;hb=011123a270b7126d8c49191a88e48f15106bb4c8;hp=b419a9b29df1c25f5d044a279a085126457230f5;hpb=eb9e1983a0fce7e4a381eff33e40cae957cddf53;p=controller.git diff --git a/opendaylight/northbound/flowprogrammer/src/main/java/org/opendaylight/controller/flowprogrammer/northbound/FlowProgrammerNorthbound.java b/opendaylight/northbound/flowprogrammer/src/main/java/org/opendaylight/controller/flowprogrammer/northbound/FlowProgrammerNorthbound.java index b419a9b29d..4928ddef3b 100644 --- a/opendaylight/northbound/flowprogrammer/src/main/java/org/opendaylight/controller/flowprogrammer/northbound/FlowProgrammerNorthbound.java +++ b/opendaylight/northbound/flowprogrammer/src/main/java/org/opendaylight/controller/flowprogrammer/northbound/FlowProgrammerNorthbound.java @@ -23,7 +23,6 @@ import javax.ws.rs.core.Context; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; import javax.ws.rs.core.SecurityContext; -import javax.xml.bind.JAXBElement; import org.codehaus.enunciate.jaxrs.ResponseCode; import org.codehaus.enunciate.jaxrs.StatusCodes; @@ -33,8 +32,8 @@ import org.opendaylight.controller.forwardingrulesmanager.FlowConfig; import org.opendaylight.controller.forwardingrulesmanager.IForwardingRulesManager; import org.opendaylight.controller.northbound.commons.RestMessages; import org.opendaylight.controller.northbound.commons.exception.InternalServerErrorException; +import org.opendaylight.controller.northbound.commons.exception.MethodNotAllowedException; import org.opendaylight.controller.northbound.commons.exception.NotAcceptableException; -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.northbound.commons.exception.UnauthorizedException; @@ -47,7 +46,7 @@ import org.opendaylight.controller.sal.utils.Status; import org.opendaylight.controller.switchmanager.ISwitchManager; /** - * Flow Configuration Northbound API + * Flow Configuration Northbound API provides capabilities to program flows. * *
*
@@ -55,11 +54,7 @@ import org.opendaylight.controller.switchmanager.ISwitchManager; * Authentication realm : opendaylight
* Transport : HTTP and HTTPS
*
- * HTTPS Authentication is disabled by default. Administrator can enable it in - * tomcat-server.xml after adding a proper keystore / SSL certificate from a - * trusted authority.
- * More info : - * http://tomcat.apache.org/tomcat-7.0-doc/ssl-howto.html#Configuration + * HTTPS Authentication is disabled by default. * */ @Path("/") @@ -69,20 +64,20 @@ public class FlowProgrammerNorthbound { @Context public void setSecurityContext(SecurityContext context) { - username = context.getUserPrincipal().getName(); + if (context != null && context.getUserPrincipal() != null) { + username = context.getUserPrincipal().getName(); + } } protected String getUserName() { return username; } - private IForwardingRulesManager getForwardingRulesManagerService( - String containerName) { - IContainerManager containerManager = (IContainerManager) ServiceHelper - .getGlobalInstance(IContainerManager.class, this); + private IForwardingRulesManager getForwardingRulesManagerService(String containerName) { + IContainerManager containerManager = (IContainerManager) ServiceHelper.getGlobalInstance( + IContainerManager.class, this); if (containerManager == null) { - throw new ServiceUnavailableException("Container " - + RestMessages.SERVICEUNAVAILABLE.toString()); + throw new ServiceUnavailableException("Container " + RestMessages.SERVICEUNAVAILABLE.toString()); } boolean found = false; @@ -94,28 +89,24 @@ public class FlowProgrammerNorthbound { } if (found == false) { - throw new ResourceNotFoundException(containerName + " " - + RestMessages.NOCONTAINER.toString()); + throw new ResourceNotFoundException(containerName + " " + RestMessages.NOCONTAINER.toString()); } - IForwardingRulesManager frm = (IForwardingRulesManager) ServiceHelper - .getInstance(IForwardingRulesManager.class, containerName, this); + IForwardingRulesManager frm = (IForwardingRulesManager) ServiceHelper.getInstance( + IForwardingRulesManager.class, containerName, this); if (frm == null) { - throw new ServiceUnavailableException("Flow Programmer " - + RestMessages.SERVICEUNAVAILABLE.toString()); + throw new ServiceUnavailableException("Flow Programmer " + RestMessages.SERVICEUNAVAILABLE.toString()); } return frm; } - private List getStaticFlowsInternal(String containerName, - Node node) { + private List getStaticFlowsInternal(String containerName, Node node) { IForwardingRulesManager frm = getForwardingRulesManagerService(containerName); if (frm == null) { - throw new ServiceUnavailableException("Flow Programmer " - + RestMessages.SERVICEUNAVAILABLE.toString()); + throw new ServiceUnavailableException("Flow Programmer " + RestMessages.SERVICEUNAVAILABLE.toString()); } List flows = new ArrayList(); @@ -125,17 +116,14 @@ public class FlowProgrammerNorthbound { flows.add(flow); } } else { - ISwitchManager sm = (ISwitchManager) ServiceHelper.getInstance( - ISwitchManager.class, containerName, this); + ISwitchManager sm = (ISwitchManager) ServiceHelper.getInstance(ISwitchManager.class, containerName, this); if (sm == null) { - throw new ServiceUnavailableException("Switch Manager " - + RestMessages.SERVICEUNAVAILABLE.toString()); + throw new ServiceUnavailableException("Switch Manager " + RestMessages.SERVICEUNAVAILABLE.toString()); } if (!sm.getNodes().contains(node)) { - throw new ResourceNotFoundException(node.toString() + " : " - + RestMessages.NONODE.toString()); + throw new ResourceNotFoundException(node.toString() + " : " + RestMessages.NONODE.toString()); } for (FlowConfig flow : frm.getStaticFlows(node)) { @@ -149,29 +137,71 @@ public class FlowProgrammerNorthbound { * Returns a list of Flows configured on the given container * * @param containerName - * Name of the Container. The Container name for the base - * controller is "default". - * @return List of configured flows configured on a given container + * Name of the Container (Eg. 'default') + * @return List of flows configured on a given container + * + *
+     *
+     * Example:
+     *
+     * Request URL:
+     * http://localhost:8080/controller/nb/v2/flowprogrammer/default
+     *
+     * Response body in XML:
+     * <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+     * <list>
+     *        <flowConfig>
+     *               <installInHw>true</installInHw>
+     *               <name>flow1</name>
+     *               <node>
+     *                      <id>00:00:00:00:00:00:00:01</id>
+     *                      <type>OF</type>
+     *               </node>
+     *               <ingressPort>1</ingressPort>
+     *               <priority>500</priority>
+     *               <etherType>0x800</etherType>
+     *               <nwSrc>9.9.1.1</nwSrc>
+     *               <actions>OUTPUT=2</actions>
+     *        </flowConfig>
+     * </list>
+     *
+     * Response body in JSON:
+     * {
+     *   "flowConfig": [
+     *      {
+     *         "installInHw": "true",
+     *         "name": "flow1",
+     *         "node": {
+     *            "type": "OF",
+     *            "id": "00:00:00:00:00:00:00:01"
+     *         },
+     *         "ingressPort": "1",
+     *         "priority": "500",
+     *         "etherType": "0x800",
+     *         "nwSrc":"9.9.1.1",
+     *         "actions": [
+     *           "OUTPUT=2"
+     *         ]
+     *      }
+     *    ]
+     * }
+     * 
*/ @Path("/{containerName}") @GET @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }) @TypeHint(FlowConfigs.class) - @StatusCodes({ - @ResponseCode(code = 200, condition = "Operation successful"), - @ResponseCode(code = 404, condition = "The containerName is not found"), - @ResponseCode(code = 503, condition = "One or more of Controller Services are unavailable") }) - public FlowConfigs getStaticFlows( - @PathParam("containerName") String containerName) { - if (!NorthboundUtils.isAuthorized( - getUserName(), containerName, Privilege.READ, this)) { - throw new UnauthorizedException( - "User is not authorized to perform this operation on container " - + containerName); + @StatusCodes({ @ResponseCode(code = 200, condition = "Operation successful"), + @ResponseCode(code = 401, condition = "User not authorized to perform this operation"), + @ResponseCode(code = 404, condition = "The containerName is not found"), + @ResponseCode(code = 503, condition = "One or more of Controller Services are unavailable") }) + public FlowConfigs getStaticFlows(@PathParam("containerName") String containerName) { + if (!NorthboundUtils.isAuthorized(getUserName(), containerName, Privilege.READ, this)) { + throw new UnauthorizedException("User is not authorized to perform this operation on container " + + containerName); } - List flowConfigs = getStaticFlowsInternal(containerName, - null); + List flowConfigs = getStaticFlowsInternal(containerName, null); return new FlowConfigs(flowConfigs); } @@ -179,36 +209,77 @@ public class FlowProgrammerNorthbound { * Returns a list of Flows configured on a Node in a given container * * @param containerName - * Name of the Container. The Container name for the base - * controller is "default". + * Name of the Container (Eg. 'default') * @param nodeType - * Type of the node being programmed + * Type of the node being programmed (Eg. 'OF') * @param nodeId - * Node Identifier - * @return List of configured flows configured on a Node in a container + * Node Identifier (Eg. '00:00:00:00:00:00:00:01') + * @return List of flows configured on a Node in a container + * + *
+     *
+     * Example:
+     *
+     * Request URL:
+     * http://localhost:8080/controller/nb/v2/flowprogrammer/default/node/OF/00:00:00:00:00:00:00:01
+     *
+     * Response body in XML:
+     * <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+     * <list>
+     *        <flowConfig>
+     *               <installInHw>true</installInHw>
+     *               <name>flow1</name>
+     *               <node>
+     *                      <id>00:00:00:00:00:00:00:01</id>
+     *                      <type>OF</type>
+     *               </node>
+     *               <ingressPort>1</ingressPort>
+     *               <priority>500</priority>
+     *               <etherType>0x800</etherType>
+     *               <nwSrc>9.9.1.1</nwSrc>
+     *               <actions>OUTPUT=2</actions>
+     *        </flowConfig>
+     * </list>
+     *
+    * Response body in JSON:
+     * {
+     *   "flowConfig": [
+     *      {
+     *         "installInHw": "true",
+     *         "name": "flow1",
+     *         "node": {
+     *            "type": "OF",
+     *            "id": "00:00:00:00:00:00:00:01"
+     *         },
+     *         "ingressPort": "1",
+     *         "priority": "500",
+     *         "etherType": "0x800",
+     *         "nwSrc":"9.9.1.1",
+     *         "actions": [
+     *           "OUTPUT=2"
+     *         ]
+     *       }
+     *    ]
+     * }
+     * 
*/ - @Path("/{containerName}/{nodeType}/{nodeId}") + @Path("/{containerName}/node/{nodeType}/{nodeId}") @GET @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }) @TypeHint(FlowConfigs.class) - @StatusCodes({ - @ResponseCode(code = 200, condition = "Operation successful"), - @ResponseCode(code = 404, condition = "The containerName or nodeId is not found"), - @ResponseCode(code = 503, condition = "One or more of Controller Services are unavailable") }) - public FlowConfigs getStaticFlows( - @PathParam("containerName") String containerName, - @PathParam("nodeType") String nodeType, - @PathParam("nodeId") String nodeId) { - if (!NorthboundUtils.isAuthorized( - getUserName(), containerName, Privilege.READ, this)) { - throw new UnauthorizedException( - "User is not authorized to perform this operation on container " - + containerName); + @StatusCodes({ @ResponseCode(code = 200, condition = "Operation successful"), + @ResponseCode(code = 401, condition = "User not authorized to perform this operation"), + @ResponseCode(code = 404, condition = "The containerName or nodeId is not found"), + @ResponseCode(code = 503, condition = "One or more of Controller Services are unavailable") }) + public FlowConfigs getStaticFlows(@PathParam("containerName") String containerName, + @PathParam("nodeType") String nodeType, @PathParam("nodeId") String nodeId) { + if (!NorthboundUtils.isAuthorized(getUserName(), containerName, Privilege.READ, this)) { + throw new UnauthorizedException("User is not authorized to perform this operation on container " + + containerName); } Node node = Node.fromString(nodeType, nodeId); if (node == null) { - throw new ResourceNotFoundException(nodeId + " : " - + RestMessages.NONODE.toString()); + throw new ResourceNotFoundException(nodeId + " : " + RestMessages.NONODE.toString()); } List flows = getStaticFlowsInternal(containerName, node); return new FlowConfigs(flows); @@ -219,39 +290,75 @@ public class FlowProgrammerNorthbound { * on a given Container. * * @param containerName - * Name of the Container. The Container name for the base - * controller is "default". + * Name of the Container (Eg. 'default') * @param nodeType - * Type of the node being programmed + * Type of the node being programmed (Eg. 'OF') * @param nodeId - * Node Identifier + * Node Identifier (Eg. '00:00:00:00:00:00:00:01') * @param name - * Human-readable name for the configured flow. + * Human-readable name for the configured flow (Eg. 'Flow1') * @return Flow configuration matching the name and nodeId on a Container + * + *
+     *
+     * Example:
+     *
+     * Request URL:
+     * http://localhost:8080/controller/nb/v2/flowprogrammer/default/node/OF/00:00:00:00:00:00:00:01/staticFlow/flow1
+     *
+     * Response body in XML:
+     * <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+     * <flowConfig>
+     *        <installInHw>true</installInHw>
+     *        <name>flow1</name>
+     *        <node>
+     *               <id>00:00:00:00:00:00:00:01</id>
+     *               <type>OF</type>
+     *        </node>
+     *        <ingressPort>1</ingressPort>
+     *        <priority>500</priority>
+     *        <etherType>0x800</etherType>
+     *        <nwSrc>9.9.1.1</nwSrc>
+     *        <actions>OUTPUT=2</actions>
+     * </flowConfig>
+     *
+    * Response body in JSON:
+     * {
+     *    "installInHw":"true",
+     *    "name":"flow1",
+     *    "node":{
+     *       "id":"00:00:00:00:00:00:00:01",
+     *       "type":"OF"
+     *    },
+     *    "ingressPort":"1",
+     *    "priority":"500",
+     *    "etherType":"0x800",
+     *    "nwSrc":"9.9.1.1",
+     *    "actions":[
+     *       "OUTPUT=2"
+     *    ]
+     * }
+     *
+     * 
*/ - @Path("/{containerName}/{nodeType}/{nodeId}/{name}") + @Path("/{containerName}/node/{nodeType}/{nodeId}/staticFlow/{name}") @GET @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }) @TypeHint(FlowConfig.class) - @StatusCodes({ - @ResponseCode(code = 200, condition = "Operation successful"), - @ResponseCode(code = 404, condition = "The containerName or NodeId or Configuration name is not found"), - @ResponseCode(code = 503, condition = "One or more of Controller Services are unavailable") }) - public FlowConfig getStaticFlow( - @PathParam("containerName") String containerName, - @PathParam("nodeType") String nodeType, - @PathParam("nodeId") String nodeId, @PathParam("name") String name) { - if (!NorthboundUtils.isAuthorized( - getUserName(), containerName, Privilege.READ, this)) { - throw new UnauthorizedException( - "User is not authorized to perform this operation on container " - + containerName); + @StatusCodes({ @ResponseCode(code = 200, condition = "Operation successful"), + @ResponseCode(code = 401, condition = "User not authorized to perform this operation"), + @ResponseCode(code = 404, condition = "The containerName or NodeId or Configuration name is not found"), + @ResponseCode(code = 503, condition = "One or more of Controller Services are unavailable") }) + public FlowConfig getStaticFlow(@PathParam("containerName") String containerName, + @PathParam("nodeType") String nodeType, @PathParam("nodeId") String nodeId, @PathParam("name") String name) { + if (!NorthboundUtils.isAuthorized(getUserName(), containerName, Privilege.READ, this)) { + throw new UnauthorizedException("User is not authorized to perform this operation on container " + + containerName); } IForwardingRulesManager frm = getForwardingRulesManagerService(containerName); if (frm == null) { - throw new ServiceUnavailableException("Flow Programmer " - + RestMessages.SERVICEUNAVAILABLE.toString()); + throw new ServiceUnavailableException("Flow Programmer " + RestMessages.SERVICEUNAVAILABLE.toString()); } Node node = handleNodeAvailability(containerName, nodeType, nodeId); @@ -265,166 +372,224 @@ public class FlowProgrammerNorthbound { } /** - * Add a flow configuration + * Add or Modify a flow configuration. If the flow exists already, it will replace the current flow. * * @param containerName - * Name of the Container. The Container name for the base - * controller is "default". + * Name of the Container (Eg. 'default') * @param nodeType - * Type of the node being programmed + * Type of the node being programmed (Eg. 'OF') * @param nodeId - * Node Identifier + * Node Identifier (Eg. '00:00:00:00:00:00:00:01') * @param name - * Name of the Static Flow configuration + * Name of the Static Flow configuration (Eg. 'Flow2') * @param FlowConfig * Flow Configuration in JSON or XML format * @return Response as dictated by the HTTP Response Status code + * + *
+     *
+     * Example:
+     *
+     * Request URL:
+     * http://localhost:8080/controller/nb/v2/flowprogrammer/default/node/OF/00:00:00:00:00:00:00:01/staticFlow/flow1
+     *
+     * Request body in XML:
+     * <flowConfig>
+     *            <installInHw>true</installInHw>
+     *            <name>flow1</name>
+     *            <node>
+     *                   <id>00:00:00:00:00:00:00:01</id>
+     *                   <type>OF</type>
+     *            </node>
+     *            <ingressPort>1</ingressPort>
+     *            <priority>500</priority>
+     *            <etherType>0x800</etherType>
+     *            <nwSrc>9.9.1.1</nwSrc>
+     *            <actions>OUTPUT=2</actions>
+     * </flowConfig>
+     *
+     * Request body in JSON:
+      * {
+     *    "installInHw":"true",
+     *    "name":"flow1",
+     *    "node":{
+     *       "id":"00:00:00:00:00:00:00:01",
+     *       "type":"OF"
+     *    },
+     *    "ingressPort":"1",
+     *    "priority":"500",
+     *    "etherType":"0x800",
+     *    "nwSrc":"9.9.1.1",
+     *    "actions":[
+     *       "OUTPUT=2"
+     *    ]
+     * }
+     * 
*/ - @Path("/{containerName}/{nodeType}/{nodeId}/{name}") - @POST + @Path("/{containerName}/node/{nodeType}/{nodeId}/staticFlow/{name}") + @PUT @Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }) @StatusCodes({ - @ResponseCode(code = 201, condition = "Flow Config processed successfully"), - @ResponseCode(code = 404, condition = "The Container Name or nodeId or configuration name is not found"), - @ResponseCode(code = 406, condition = "Cannot operate on Default Container when other Containers are active"), - @ResponseCode(code = 409, condition = "Failed to create Static Flow entry due to Conflicting Name"), - @ResponseCode(code = 500, condition = "Failed to create Static Flow entry. Failure Reason included in HTTP Error response"), - @ResponseCode(code = 503, condition = "One or more of Controller services are unavailable") }) - public Response addFlow( - @PathParam(value = "containerName") String containerName, - @PathParam(value = "name") String name, - @PathParam("nodeType") String nodeType, - @PathParam(value = "nodeId") String nodeId, - @TypeHint(FlowConfig.class) JAXBElement flowConfig) { - - if (!NorthboundUtils.isAuthorized( - getUserName(), containerName, Privilege.WRITE, this)) { - throw new UnauthorizedException( - "User is not authorized to perform this operation on container " - + containerName); + @ResponseCode(code = 200, condition = "Static Flow modified successfully"), + @ResponseCode(code = 201, condition = "Flow Config processed successfully"), + @ResponseCode(code = 400, condition = "Failed to create Static Flow entry due to invalid flow configuration"), + @ResponseCode(code = 401, condition = "User not authorized to perform this operation"), + @ResponseCode(code = 404, condition = "The Container Name or nodeId is not found"), + @ResponseCode(code = 406, condition = "Cannot operate on Default Container when other Containers are active"), + @ResponseCode(code = 409, condition = "Failed to create Static Flow entry due to Conflicting Name or configuration"), + @ResponseCode(code = 500, condition = "Failed to create Static Flow entry. Failure Reason included in HTTP Error response"), + @ResponseCode(code = 503, condition = "One or more of Controller services are unavailable") }) + public Response addOrModifyFlow(@PathParam(value = "containerName") String containerName, + @PathParam(value = "name") String name, @PathParam("nodeType") String nodeType, + @PathParam(value = "nodeId") String nodeId, @TypeHint(FlowConfig.class) FlowConfig flowConfig) { + + if (!NorthboundUtils.isAuthorized(getUserName(), containerName, Privilege.WRITE, this)) { + throw new UnauthorizedException("User is not authorized to perform this operation on container " + + containerName); + } + + if (flowConfig.getNode() == null) { + return Response.status(Response.Status.BAD_REQUEST).entity("Invalid Configuration. Node is null or empty") + .build(); } + handleResourceCongruence(name, flowConfig.getName()); + handleResourceCongruence(nodeType, flowConfig.getNode().getType()); + handleResourceCongruence(nodeId, flowConfig.getNode().getID() == null ? null : flowConfig.getNode().getNodeIDString()); handleDefaultDisabled(containerName); IForwardingRulesManager frm = getForwardingRulesManagerService(containerName); if (frm == null) { - throw new ServiceUnavailableException("Flow Programmer " - + RestMessages.SERVICEUNAVAILABLE.toString()); + throw new ServiceUnavailableException("Flow Programmer " + RestMessages.SERVICEUNAVAILABLE.toString()); } Node node = handleNodeAvailability(containerName, nodeType, nodeId); + Status status; FlowConfig staticFlow = frm.getStaticFlow(name, node); - if (staticFlow != null) { - throw new ResourceConflictException(name + " already exists." - + RestMessages.RESOURCECONFLICT.toString()); - } - Status status = frm.addStaticFlow(flowConfig.getValue(), false); - if (status.isSuccess()) { - return Response.status(Response.Status.CREATED).build(); + if (staticFlow == null) { + status = frm.addStaticFlow(flowConfig); + if(status.isSuccess()){ + NorthboundUtils.auditlog("Flow Entry", username, "added", + name + " on Node " + NorthboundUtils.getNodeDesc(node, containerName, this), containerName); + return Response.status(Response.Status.CREATED).entity("Success").build(); + } + } else { + status = frm.modifyStaticFlow(flowConfig); + if(status.isSuccess()){ + NorthboundUtils.auditlog("Flow Entry", username, "updated", + name + " on Node " + NorthboundUtils.getNodeDesc(node, containerName, this), containerName); + return NorthboundUtils.getResponse(status); + } } - throw new InternalServerErrorException(status.getDescription()); + return NorthboundUtils.getResponse(status); } /** * Delete a Flow configuration * - * DELETE /flows/{containerName}/{nodeType}/{nodeId}/{name} - * * @param containerName - * Name of the Container. The Container name for the base - * controller is "default". + * Name of the Container (Eg. 'default') * @param nodeType - * Type of the node being programmed + * Type of the node being programmed (Eg. 'OF') * @param nodeId - * Node Identifier + * Node Identifier (Eg. '00:00:00:00:00:00:00:01') * @param name - * Name of the Static Flow configuration + * Name of the Static Flow configuration (Eg. 'Flow1') * @return Response as dictated by the HTTP Response code + * + *
+     *
+     * Example:
+     *
+     * RequestURL:
+     * http://localhost:8080/controller/nb/v2/flowprogrammer/default/node/OF/00:00:00:00:00:00:00:01/staticFlow/flow1
+     *
+     * 
*/ - @Path("/{containerName}/{nodeType}/{nodeId}/{name}") + @Path("/{containerName}/node/{nodeType}/{nodeId}/staticFlow/{name}") @DELETE - @Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }) @StatusCodes({ - @ResponseCode(code = 200, condition = "Flow Config deleted successfully"), - @ResponseCode(code = 404, condition = "The Container Name or Node-id or Flow Name passed is not found"), - @ResponseCode(code = 406, condition = "Cannot operate on Default Container when other Containers are active"), - @ResponseCode(code = 500, condition = "Failed to delete Flow config. Failure Reason included in HTTP Error response"), - @ResponseCode(code = 503, condition = "One or more of Controller service is unavailable") }) - public Response deleteFlow( - @PathParam(value = "containerName") String containerName, - @PathParam(value = "name") String name, - @PathParam("nodeType") String nodeType, + @ResponseCode(code = 204, condition = "Flow Config deleted successfully"), + @ResponseCode(code = 401, condition = "User not authorized to perform this operation"), + @ResponseCode(code = 404, condition = "The Container Name or Node-id or Flow Name passed is not found"), + @ResponseCode(code = 406, condition = "Failed to delete Flow config due to invalid operation. Failure details included in HTTP Error response"), + @ResponseCode(code = 500, condition = "Failed to delete Flow config. Failure Reason included in HTTP Error response"), + @ResponseCode(code = 503, condition = "One or more of Controller service is unavailable") }) + public Response deleteFlow(@PathParam(value = "containerName") String containerName, + @PathParam(value = "name") String name, @PathParam("nodeType") String nodeType, @PathParam(value = "nodeId") String nodeId) { - if (!NorthboundUtils.isAuthorized( - getUserName(), containerName, Privilege.WRITE, this)) { - throw new UnauthorizedException( - "User is not authorized to perform this operation on container " - + containerName); + if (!NorthboundUtils.isAuthorized(getUserName(), containerName, Privilege.WRITE, this)) { + throw new UnauthorizedException("User is not authorized to perform this operation on container " + + containerName); } handleDefaultDisabled(containerName); IForwardingRulesManager frm = getForwardingRulesManagerService(containerName); if (frm == null) { - throw new ServiceUnavailableException("Flow Programmer " - + RestMessages.SERVICEUNAVAILABLE.toString()); + throw new ServiceUnavailableException("Flow Programmer " + RestMessages.SERVICEUNAVAILABLE.toString()); } Node node = handleNodeAvailability(containerName, nodeType, nodeId); FlowConfig staticFlow = frm.getStaticFlow(name, node); if (staticFlow == null) { - throw new ResourceNotFoundException(name + " : " - + RestMessages.NOFLOW.toString()); + throw new ResourceNotFoundException(name + " : " + RestMessages.NOFLOW.toString()); } Status status = frm.removeStaticFlow(name, node); if (status.isSuccess()) { - return Response.ok().build(); + NorthboundUtils.auditlog("Flow Entry", username, "removed", + name + " from Node " + NorthboundUtils.getNodeDesc(node, containerName, this), containerName); + return Response.noContent().build(); } - throw new InternalServerErrorException(status.getDescription()); + return NorthboundUtils.getResponse(status); } /** * Toggle a Flow configuration * * @param containerName - * Name of the Container. The Container name for the base - * controller is "default". + * Name of the Container (Eg. 'default') * @param nodeType - * Type of the node being programmed + * Type of the node being programmed (Eg. 'OF') * @param nodeId - * Node Identifier + * Node Identifier (Eg. '00:00:00:00:00:00:00:01') * @param name - * Name of the Static Flow configuration + * Name of the Static Flow configuration (Eg. 'Flow1') * @return Response as dictated by the HTTP Response code + * + *
+     *
+     * Example:
+     *
+     * RequestURL:
+     * http://localhost:8080/controller/nb/v2/flowprogrammer/default/node/OF/00:00:00:00:00:00:00:01/staticFlow/flow1
+     *
+     * 
*/ - - @Path("/{containerName}/{nodeType}/{nodeId}/{name}") - @PUT + @Path("/{containerName}/node/{nodeType}/{nodeId}/staticFlow/{name}") + @POST @Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }) @StatusCodes({ - @ResponseCode(code = 200, condition = "Flow Config deleted successfully"), - @ResponseCode(code = 404, condition = "The Container Name or Node-id or Flow Name passed is not found"), - @ResponseCode(code = 406, condition = "Cannot operate on Default Container when other Containers are active"), - @ResponseCode(code = 500, condition = "Failed to delete Flow config. Failure Reason included in HTTP Error response"), - @ResponseCode(code = 503, condition = "One or more of Controller service is unavailable") }) - public Response toggleFlow( - @PathParam(value = "containerName") String containerName, - @PathParam("nodeType") String nodeType, - @PathParam(value = "nodeId") String nodeId, + @ResponseCode(code = 200, condition = "Flow Config processed successfully"), + @ResponseCode(code = 401, condition = "User not authorized to perform this operation"), + @ResponseCode(code = 404, condition = "The Container Name or Node-id or Flow Name passed is not found"), + @ResponseCode(code = 406, condition = "Failed to delete Flow config due to invalid operation. Failure details included in HTTP Error response"), + @ResponseCode(code = 500, condition = "Failed to delete Flow config. Failure Reason included in HTTP Error response"), + @ResponseCode(code = 503, condition = "One or more of Controller service is unavailable") }) + public Response toggleFlow(@PathParam(value = "containerName") String containerName, + @PathParam("nodeType") String nodeType, @PathParam(value = "nodeId") String nodeId, @PathParam(value = "name") String name) { - if (!NorthboundUtils.isAuthorized( - getUserName(), containerName, Privilege.WRITE, this)) { - throw new UnauthorizedException( - "User is not authorized to perform this operation on container " - + containerName); + if (!NorthboundUtils.isAuthorized(getUserName(), containerName, Privilege.WRITE, this)) { + throw new UnauthorizedException("User is not authorized to perform this operation on container " + + containerName); } handleDefaultDisabled(containerName); @@ -432,60 +597,57 @@ public class FlowProgrammerNorthbound { IForwardingRulesManager frm = getForwardingRulesManagerService(containerName); if (frm == null) { - throw new ServiceUnavailableException("Flow Programmer " - + RestMessages.SERVICEUNAVAILABLE.toString()); + throw new ServiceUnavailableException("Flow Programmer " + RestMessages.SERVICEUNAVAILABLE.toString()); } Node node = handleNodeAvailability(containerName, nodeType, nodeId); FlowConfig staticFlow = frm.getStaticFlow(name, node); if (staticFlow == null) { - throw new ResourceNotFoundException(name + " : " - + RestMessages.NOFLOW.toString()); + throw new ResourceNotFoundException(name + " : " + RestMessages.NOFLOW.toString()); } Status status = frm.toggleStaticFlowStatus(staticFlow); if (status.isSuccess()) { - return Response.ok().build(); + NorthboundUtils.auditlog("Flow Entry", username, "toggled", + name + " on Node " + NorthboundUtils.getNodeDesc(node, containerName, this), containerName); } - throw new InternalServerErrorException(status.getDescription()); + return NorthboundUtils.getResponse(status); } - private Node handleNodeAvailability(String containerName, String nodeType, - String nodeId) { + private Node handleNodeAvailability(String containerName, String nodeType, String nodeId) { Node node = Node.fromString(nodeType, nodeId); if (node == null) { - throw new ResourceNotFoundException(nodeId + " : " - + RestMessages.NONODE.toString()); + throw new ResourceNotFoundException(nodeId + " : " + RestMessages.NONODE.toString()); } - ISwitchManager sm = (ISwitchManager) ServiceHelper.getInstance( - ISwitchManager.class, containerName, this); + ISwitchManager sm = (ISwitchManager) ServiceHelper.getInstance(ISwitchManager.class, containerName, this); if (sm == null) { - throw new ServiceUnavailableException("Switch Manager " - + RestMessages.SERVICEUNAVAILABLE.toString()); + throw new ServiceUnavailableException("Switch Manager " + RestMessages.SERVICEUNAVAILABLE.toString()); } if (!sm.getNodes().contains(node)) { - throw new ResourceNotFoundException(node.toString() + " : " - + RestMessages.NONODE.toString()); + throw new ResourceNotFoundException(node.toString() + " : " + RestMessages.NONODE.toString()); } return node; } private void handleDefaultDisabled(String containerName) { - IContainerManager containerManager = (IContainerManager) ServiceHelper - .getGlobalInstance(IContainerManager.class, this); + IContainerManager containerManager = (IContainerManager) ServiceHelper.getGlobalInstance( + IContainerManager.class, this); if (containerManager == null) { - throw new InternalServerErrorException( - RestMessages.INTERNALERROR.toString()); + throw new InternalServerErrorException(RestMessages.INTERNALERROR.toString()); } - if (containerName.equals(GlobalConstants.DEFAULT.toString()) - && containerManager.hasNonDefaultContainer()) { - throw new NotAcceptableException( - RestMessages.DEFAULTDISABLED.toString()); + if (containerName.equals(GlobalConstants.DEFAULT.toString()) && containerManager.hasNonDefaultContainer()) { + throw new NotAcceptableException(RestMessages.DEFAULTDISABLED.toString()); + } + } + + private void handleResourceCongruence(String resource, String configured) { + if (!resource.equals(configured)) { + throw new MethodNotAllowedException("Path's resource name conflicts with payload's resource name"); } }