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=1e88c4430548f6de805ee67c4441f49e6db89f3c;hb=c7df154d0ab6ab8222e46adefd82aea620b825aa;hp=e4ca83a260903d9fd808cae8901daaa2239820a7;hpb=29f7cfb54b580928c7feac63abce028a7014b0d5;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 e4ca83a260..1e88c44305 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 @@ -1,4 +1,3 @@ - /* * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved. * @@ -20,9 +19,10 @@ import javax.ws.rs.PUT; import javax.ws.rs.Path; import javax.ws.rs.PathParam; import javax.ws.rs.Produces; +import javax.ws.rs.core.Context; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; -import javax.xml.bind.JAXBElement; +import javax.ws.rs.core.SecurityContext; import org.codehaus.enunciate.jaxrs.ResponseCode; import org.codehaus.enunciate.jaxrs.StatusCodes; @@ -32,10 +32,14 @@ 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; +import org.opendaylight.controller.northbound.commons.utils.NorthboundUtils; +import org.opendaylight.controller.sal.authorization.Privilege; import org.opendaylight.controller.sal.core.Node; import org.opendaylight.controller.sal.utils.GlobalConstants; import org.opendaylight.controller.sal.utils.ServiceHelper; @@ -43,28 +47,38 @@ 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. * - *

+ *
+ *
* Authentication scheme : HTTP Basic
* 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("/") public class FlowProgrammerNorthbound { - private IForwardingRulesManager getForwardingRulesManagerService( - String containerName) { - IContainerManager containerManager = (IContainerManager) ServiceHelper - .getGlobalInstance(IContainerManager.class, this); + private String username; + + @Context + public void setSecurityContext(SecurityContext context) { + 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); if (containerManager == null) { - throw new ServiceUnavailableException("Container " - + RestMessages.SERVICEUNAVAILABLE.toString()); + throw new ServiceUnavailableException("Container " + RestMessages.SERVICEUNAVAILABLE.toString()); } boolean found = false; @@ -76,28 +90,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(); @@ -107,17 +117,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)) { @@ -130,19 +137,55 @@ 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 + * @param containerName + * Name of the Container (Eg. 'default') + * @return List of flows configured on a given container + * + *
+     *
+     * Example:
+     *
+     * RequestURL:
+     * http://localhost:8080/controller/nb/v2/flowprogrammer/default
+     *
+     * Response 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 in JSON:
+     * {"flowConfig":{"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}") @GET - @Produces( { MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }) + @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) { + @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); return new FlowConfigs(flowConfigs); } @@ -150,62 +193,128 @@ 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". - * @param nodeType Type of the node being programmed - * @param nodeId Node Identifier - * @return List of configured flows configured on a Node in a container + * @param containerName + * Name of the Container (Eg. 'default') + * @param nodeType + * Type of the node being programmed (Eg. 'OF') + * @param nodeId + * Node Identifier (Eg. '00:00:00:00:00:00:00:01') + * @return List of flows configured on a Node in a container + * + *
+     *
+     * Example:
+     *
+     * RequestURL:
+     * http://localhost:8080/controller/nb/v2/flowprogrammer/default/node/OF/00:00:00:00:00:00:00:01
+     *
+     * Response 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 in JSON:
+     * {"flowConfig":{"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}") + @Path("/{containerName}/node/{nodeType}/{nodeId}") @GET - @Produces( { MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }) + @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) { + @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); } /** - * Returns the flow configuration matching a human-readable name and nodeId on a - * given Container. - * - * @param containerName Name of the Container. The Container name - * for the base controller is "default". - * @param nodeType Type of the node being programmed - * @param nodeId Node Identifier - * @param name Human-readable name for the configured flow. + * Returns the flow configuration matching a human-readable name and nodeId + * on a given Container. + * + * @param containerName + * Name of the Container (Eg. 'default') + * @param nodeType + * Type of the node being programmed (Eg. 'OF') + * @param nodeId + * Node Identifier (Eg. '00:00:00:00:00:00:00:01') + * @param name + * Human-readable name for the configured flow (Eg. 'Flow1') * @return Flow configuration matching the name and nodeId on a Container + * + *
+     *
+     * Example:
+     *
+     * RequestURL:
+     * http://localhost:8080/controller/nb/v2/flowprogrammer/default/node/OF/00:00:00:00:00:00:00:01/staticFlow/flow1
+     *
+     * Response 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 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 }) + @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) { + @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); @@ -219,197 +328,264 @@ public class FlowProgrammerNorthbound { } /** - * Add a flow configuration - * - * @param containerName Name of the Container. The Container name - * for the base controller is "default". - * @param nodeType Type of the node being programmed - * @param nodeId Node Identifier - * @param name Name of the Static Flow configuration - * @param FlowConfig Flow Configuration in JSON or XML format + * Add a flow configuration. If a flow by the given name already exists, + * this method will respond with a non-successful status response. + * + * @param containerName + * Name of the Container (Eg. 'default') + * @param nodeType + * Type of the node being programmed (Eg. 'OF') + * @param nodeId + * Node Identifier (Eg. '00:00:00:00:00:00:00:01') + * @param name + * 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:
+     *
+     * RequestURL:
+     * http://localhost:8080/controller/nb/v2/flowprogrammer/default/node/OF/00:00:00:00:00:00:00:01/staticFlow/flow1
+     *
+     * Request 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 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 - @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) { + @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 = 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 addFlow(@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(nodeId, 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); FlowConfig staticFlow = frm.getStaticFlow(name, node); if (staticFlow != null) { - throw new ResourceConflictException(name + " already exists." - + RestMessages.RESOURCECONFLICT.toString()); + throw new ResourceConflictException(name + " already exists." + RestMessages.RESOURCECONFLICT.toString()); } - Status status = frm.addStaticFlow(flowConfig.getValue(), false); + Status status = frm.addStaticFlow(flowConfig); + if (status.isSuccess()) { - return Response.status(Response.Status.CREATED).build(); + NorthboundUtils.auditlog("Flow Entry", username, "added", + name + " on Node " + NorthboundUtils.getNodeDesc(node, containerName, this), containerName); + return Response.status(Response.Status.CREATED).entity("Success").build(); } - 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". - * @param nodeType Type of the node being programmed - * @param nodeId Node Identifier - * @param name Name of the Static Flow configuration + * @param containerName + * Name of the Container (Eg. 'default') + * @param nodeType + * Type of the node being programmed (Eg. 'OF') + * @param nodeId + * Node Identifier (Eg. '00:00:00:00:00:00:00:01') + * @param name + * 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, + @Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }) + @StatusCodes({ + @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); + } 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". - * @param nodeType Type of the node being programmed - * @param nodeId Node Identifier - * @param name Name of the Static Flow configuration + * @param containerName + * Name of the Container (Eg. 'default') + * @param nodeType + * Type of the node being programmed (Eg. 'OF') + * @param nodeId + * Node Identifier (Eg. '00:00:00:00:00:00:00:01') + * @param name + * 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 - @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, + @Path("/{containerName}/node/{nodeType}/{nodeId}/staticFlow/{name}") + @POST + @Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }) + @StatusCodes({ + @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); + } + 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.toggleStaticFlowStatus(new FlowConfig("", name, - node, "", "", "", "", "", "", "", "", "", "", "", "", "", "", - "", "", "", null)); + 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"); } }