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=ea3f748dcc02e820c6b88aab5f2a10a73fef0cdf;hb=refs%2Fchanges%2F49%2F1149%2F2;hp=6bccc2d2e9ff25bde94925be51f4555f409c5e98;hpb=67a8679ab2eb3ad8d7914756e844243eac3cbd32;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 6bccc2d2e9..ea3f748dcc 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
@@ -33,6 +33,7 @@ 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;
@@ -47,7 +48,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 +56,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,7 +66,7 @@ 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() {
@@ -149,9 +146,39 @@ 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: + * + * 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 @@ -159,6 +186,7 @@ public class FlowProgrammerNorthbound { @TypeHint(FlowConfigs.class) @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( @@ -179,20 +207,51 @@ 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: + * + * 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 }) @TypeHint(FlowConfigs.class) @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( @@ -219,22 +278,51 @@ 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: + * + * 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 }) @TypeHint(FlowConfig.class) @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( @@ -265,30 +353,60 @@ public class FlowProgrammerNorthbound { } /** - * Add a flow configuration + * 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. 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: + * + * 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 + @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 = 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"), + @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( @@ -296,7 +414,7 @@ public class FlowProgrammerNorthbound { @PathParam(value = "name") String name, @PathParam("nodeType") String nodeType, @PathParam(value = "nodeId") String nodeId, - @TypeHint(FlowConfig.class) JAXBElement
+ * + * 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 = 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 = "Cannot operate on Default Container when other Containers are active"), + @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( @@ -388,33 +520,41 @@ public class FlowProgrammerNorthbound { Status status = frm.removeStaticFlow(name, node); if (status.isSuccess()) { NorthboundUtils.auditlog("Flow", username, "removed", name, containerName); - return Response.ok().build(); + 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 = 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 = "Cannot operate on Default Container when other Containers are active"), + @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( @@ -450,9 +590,8 @@ public class FlowProgrammerNorthbound { Status status = frm.toggleStaticFlowStatus(staticFlow); if (status.isSuccess()) { NorthboundUtils.auditlog("Flow", username, "toggled", name, containerName); - return Response.ok().build(); } - throw new InternalServerErrorException(status.getDescription()); + return NorthboundUtils.getResponse(status); } private Node handleNodeAvailability(String containerName, String nodeType, @@ -493,4 +632,10 @@ public class FlowProgrammerNorthbound { } } + private void handleResourceCongruence(String resource, String configured) { + if (!resource.equals(configured)) { + throw new MethodNotAllowedException("Path's resource name conflicts with payload's resource name"); + } + } + }