();
if (node == null) {
for (FlowConfig flow : frm.getStaticFlows()) {
flows.add(flow);
}
} else {
ISwitchManager sm = (ISwitchManager) ServiceHelper.getInstance(ISwitchManager.class, containerName, this);
if (sm == null) {
throw new ServiceUnavailableException("Switch Manager " + RestMessages.SERVICEUNAVAILABLE.toString());
}
if (!sm.getNodes().contains(node)) {
throw new ResourceNotFoundException(node.toString() + " : " + RestMessages.NONODE.toString());
}
for (FlowConfig flow : frm.getStaticFlows(node)) {
flows.add(flow);
}
}
return flows;
}
/**
* Returns a list of Flows configured on the given container
*
* @param containerName
* 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 = 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"),
@ResponseCode(code = 400, condition = "Incorrect query syntex")})
public FlowConfigs getStaticFlows(@PathParam("containerName") String containerName,
@QueryParam("_q") String queryString) {
if (!NorthboundUtils.isAuthorized(getUserName(), containerName, Privilege.READ, this)) {
throw new UnauthorizedException("User is not authorized to perform this operation on container "
+ containerName);
}
FlowConfigs result = new FlowConfigs(getStaticFlowsInternal(containerName, null));
if (queryString != null) {
queryContext.createQuery(queryString, FlowConfigs.class)
.filter(result, FlowConfig.class);
}
return result;
}
/**
* Returns a list of Flows configured on a Node in 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')
* @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}/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(@PathParam("containerName") String containerName,
@PathParam("nodeType") String nodeType, @PathParam("nodeId") String nodeId,
@QueryParam("_q") String queryString) {
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());
}
FlowConfigs flows = new FlowConfigs(getStaticFlowsInternal(containerName, node));
if (queryString != null) {
queryContext.createQuery(queryString, FlowConfigs.class)
.filter(flows, FlowConfig.class);
}
return flows;
}
/**
* 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:
*
* 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}/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(@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());
}
Node node = handleNodeAvailability(containerName, nodeType, nodeId);
FlowConfig staticFlow = frm.getStaticFlow(name, node);
if (staticFlow == null) {
throw new ResourceNotFoundException(RestMessages.NOFLOW.toString());
}
return new FlowConfig(staticFlow);
}
/**
* Add or Modify a flow configuration. If the flow exists already, it will replace the current flow.
*
* @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:
*
* 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}/node/{nodeType}/{nodeId}/staticFlow/{name}")
@PUT
@Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
@StatusCodes({
@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());
}
Node node = handleNodeAvailability(containerName, nodeType, nodeId);
Status status;
FlowConfig staticFlow = frm.getStaticFlow(name, node);
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);
}
}
return NorthboundUtils.getResponse(status);
}
/**
* Delete a 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}/node/{nodeType}/{nodeId}/staticFlow/{name}")
@DELETE
@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());
}
Node node = handleNodeAvailability(containerName, nodeType, nodeId);
FlowConfig staticFlow = frm.getStaticFlow(name, node);
if (staticFlow == null) {
throw new ResourceNotFoundException(name + " : " + RestMessages.NOFLOW.toString());
}
Status status = frm.removeStaticFlow(name, node);
if (status.isSuccess()) {
NorthboundUtils.auditlog("Flow Entry", username, "removed",
name + " from Node " + NorthboundUtils.getNodeDesc(node, containerName, this), containerName);
return Response.noContent().build();
}
return NorthboundUtils.getResponse(status);
}
/**
* Toggle a 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}/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());
}
Node node = handleNodeAvailability(containerName, nodeType, nodeId);
FlowConfig staticFlow = frm.getStaticFlow(name, node);
if (staticFlow == null) {
throw new ResourceNotFoundException(name + " : " + RestMessages.NOFLOW.toString());
}
Status status = frm.toggleStaticFlowStatus(staticFlow);
if (status.isSuccess()) {
NorthboundUtils.auditlog("Flow Entry", username, "toggled",
name + " on Node " + NorthboundUtils.getNodeDesc(node, containerName, this), containerName);
}
return NorthboundUtils.getResponse(status);
}
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());
}
ISwitchManager sm = (ISwitchManager) ServiceHelper.getInstance(ISwitchManager.class, containerName, this);
if (sm == null) {
throw new ServiceUnavailableException("Switch Manager " + RestMessages.SERVICEUNAVAILABLE.toString());
}
if (!sm.getNodes().contains(node)) {
throw new ResourceNotFoundException(node.toString() + " : " + RestMessages.NONODE.toString());
}
return node;
}
private void handleDefaultDisabled(String containerName) {
IContainerManager containerManager = (IContainerManager) ServiceHelper.getGlobalInstance(
IContainerManager.class, this);
if (containerManager == null) {
throw new InternalServerErrorException(RestMessages.INTERNALERROR.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");
}
}
}