();
containerConfigs.add(containerManager.getContainerConfig(container));
return new ContainerConfigs(containerConfigs);
}
/**
* Create a container
*
* @param uriInfo
* @param container
* name of the Container (eg. yellow)
* @param containerConfig
* details of the container as specified by:
* {@link org.opendaylight.controller.containermanager.ContainerConfig}
* @return Response as dictated by the HTTP Response Status code
*
*
*
* Example:
*
* Request URL:
* http://localhost:8080/controller/nb/v2/containermanager/container/yellow
*
* Request body in XML:
* <containerConfig>
* <container>yellow</container>
* <staticVlan>10</staticVlan>
* <nodeConnectors></nodeConnectors>
* </containerConfig>
*
* Request body in JSON:
* {
* "container" : "yellow",
* "nodeConnectors" : [
* "OF|1@OF|00:00:00:00:00:00:00:01",
* "OF|23@OF|00:00:00:00:00:00:20:21"
* ],
* "staticVlan" : "10"
* }
*
*
*/
@Path("/container/{container}")
@PUT
@Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
@StatusCodes({ @ResponseCode(code = 201, condition = "Container created successfully"),
@ResponseCode(code = 400, condition = "Invalid Container configuration."),
@ResponseCode(code = 401, condition = "User not authorized to perform this operation"),
@ResponseCode(code = 403, condition = "Operation forbidden on default"),
@ResponseCode(code = 404, condition = "Container Name is not found"),
@ResponseCode(code = 409, condition = "Failed to create Container due to Conflicting Name"),
@ResponseCode(code = 500, condition = "Failure Reason included in HTTP Error response") })
public Response createContainer(@Context UriInfo uriInfo,
@PathParam(value = "container") String container,
@TypeHint(ContainerConfig.class) ContainerConfig containerConfig) {
handleAdminAuthorization(getUserName());
handleContainerExists(container);
handleNameMismatch(containerConfig.getContainerName(), container);
handleForbiddenOnDefault(container);
IContainerManager containerManager = getContainerManager();
Status status = containerManager.addContainer(containerConfig);
if (status.isSuccess()) {
NorthboundUtils.auditlog("Container", username, "added", container);
return Response.created(uriInfo.getRequestUri()).build();
}
return NorthboundUtils.getResponse(status);
}
/**
* Delete a container
*
* @param container
* name of the Container (eg. green)
* @return Response as dictated by the HTTP Response code
*
*
*
* Example:
*
* Request URL:
* http://localhost:8080/controller/nb/v2/containermanager/container/green
*
*
*/
@Path("/container/{container}")
@DELETE
@StatusCodes({
@ResponseCode(code = 204, condition = "Container deleted successfully"),
@ResponseCode(code = 401, condition = "User not authorized to perform this operation"),
@ResponseCode(code = 403, condition = "Operation forbidden on default"),
@ResponseCode(code = 404, condition = "The container is not found") })
public Response removeContainer(@PathParam(value = "container") String container) {
handleAdminAuthorization(getUserName());
handleForbiddenOnDefault(container);
handleContainerNotExists(container);
IContainerManager containerManager = getContainerManager();
Status status = containerManager.removeContainer(container);
if (status.isSuccess()) {
NorthboundUtils.auditlog("Container", username, "removed", container);
return Response.noContent().build();
}
return NorthboundUtils.getResponse(status);
}
/**
* Get flowspec within a given container
*
* @param container
* name of the Container (eg. green)
* @param name
* name of the flowspec (eg. ssh)
* @return flowspec detail as specified by:
* {@link org.opendaylight.controller.containermanager.ContainerFlowConfig}
*
*
*
* Example:
*
* Request URL:
* http://localhost:8080/controller/nb/v2/containermanager/container/green/flowspec/ssh
*
* Response body in XML:
* <flow-spec-config>
* <name>ssh</name>
* <dlVlan>52</dlVlan>
* <nwSrc>10.0.0.101</nwSrc>
* <nwDst>10.0.0.102</nwDst>
* <protocol>IPv4</protocol>
* <tpSrc>80</tpSrc>
* <tpDst>100</tpDst>
* </flow-spec-config>
*
* Response body in JSON:
* {
* "protocol" : "IPv4",
* "dlVlan" : "52",
* "nwDst" : "10.0.0.102",
* "name" : "ssh",
* "nwSrc" : "10.0.0.101",
* "tpSrc" : "80",
* "tpDst" : "100"
* }
*
*
*/
@Path("/container/{container}/flowspec/{flowspec}")
@GET
@Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
@TypeHint(ContainerFlowConfig.class)
@StatusCodes({ @ResponseCode(code = 200, condition = "Operation successful"),
@ResponseCode(code = 401, condition = "User not authorized to perform this operation"),
@ResponseCode(code = 404, condition = "The container is not found"),
@ResponseCode(code = 503, condition = "One or more of Controller Services are unavailable") })
public ContainerFlowConfig viewContainerFlowSpec(@PathParam(value = "container") String container,
@PathParam(value = "flowspec") String flowspec) {
handleContainerAuthorization(container, getUserName());
handleForbiddenOnDefault(container);
handleContainerNotExists(container);
IContainerManager containerManager = getContainerManager();
List flowSpecs = containerManager.getContainerFlows(container);
for (ContainerFlowConfig containerFlowConfig : flowSpecs) {
if (containerFlowConfig.equalsByName(flowspec)) {
return containerFlowConfig;
}
}
throw new ResourceNotFoundException("Flow Spec not found");
}
/**
* Get all the flowspec in a given container
*
* @param container
* name of the Container (eg. red)
* @return list of all flowspec configured for a container. Flowspec as
* specified by:
* {@link org.opendaylight.controller.containermanager.ContainerFlowConfig}
*
*
*
* Example:
*
* Request URL:
* http://localhost:8080/controller/nb/v2/containermanager/container/red/flowspec
*
* Response body in XML:
* <flow-spec-configs>
* <flow-spec-config>
* <name>ssh</name>
* <dlVlan>52</dlVlan>
* <nwSrc>10.0.0.101</nwSrc>
* <nwDst>10.0.0.102</nwDst>
* <protocol>IPv4</protocol>
* <tpSrc>23</tpSrc>
* <tpDst>100</tpDst>
* </flow-spec-config>
* <flow-spec-config>
* <name>http2</name>
* <dlVlan>123</dlVlan>
* <nwSrc>10.0.0.201</nwSrc>
* <nwDst>10.0.0.202</nwDst>
* <protocol></protocol>
* <tpSrc>80</tpSrc>
* <tpDst>100</tpDst>
* </flow-spec-config>
* </flow-spec-configs>
*
* Response body in JSON:
* {
* "flow-spec-config": [
* {
* "name": "http",
* "dlVlan" : "52",
* "nwSrc": "10.0.0.201",
* "nwDst": "10.0.0.202",
* "protocol": "",
* "tpSrc": "80",
* "tpDst": "100"
* },
* {
* "name": "ssh",
* "dlVlan" : "123",
* "nwSrc": "10.0.0.101",
* "nwDst": "10.0.0.102",
* "protocol": "IPv4",
* "tpSrc": "23",
* "tpDst": "100"
* }
* ]
* }
*
*
*/
@Path("/container/{container}/flowspecs")
@GET
@Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
@TypeHint(FlowSpecConfigs.class)
@StatusCodes({ @ResponseCode(code = 200, condition = "Operation successful"),
@ResponseCode(code = 404, condition = "The container is not found"),
@ResponseCode(code = 503, condition = "One or more of Controller Services are unavailable") })
public FlowSpecConfigs viewContainerFlowSpecs(@PathParam(value = "container") String container,
@QueryParam("_q") String queryString) {
handleContainerAuthorization(container, getUserName());
handleForbiddenOnDefault(container);
handleContainerNotExists(container);
IContainerManager containerManager = getContainerManager();
FlowSpecConfigs result = new FlowSpecConfigs(
containerManager.getContainerFlows(container));
if (queryString != null) {
queryContext.createQuery(queryString, FlowSpecConfigs.class)
.filter(result, ContainerFlowConfig.class);
}
return result;
}
/**
* Add flowspec to a container
*
* @param container
* name of the container (eg. purple)
* @param name
* name of the flowspec (eg. http)
* @param flowspec
* configuration as specified by:
* {@link org.opendaylight.controller.containermanager.ContainerFlowConfig}
*
* @return Response as dictated by the HTTP Response code
*
*
*
* Example:
*
* Request URL:
* http://localhost:8080/controller/nb/v2/containermanager/container/purple/flowspec/http
*
* Request body in XML:
* <flow-spec-config>
* <name>http</name>
* <dlVlan>25</dlVlan>
* <nwSrc>10.0.0.101</nwSrc>
* <nwDst>10.0.0.102</nwDst>
* <protocol></protocol>
* <tpSrc>80</tpSrc>
* <tpDst>100</tpDst>
* </flow-spec-config>
*
* Request body in JSON:
* {
* "name" : "http",
* "dlVlan" : "25",
* "nwSrc" : "10.0.0.101",
* "nwDst" : "10.0.0.102",
* "protocol" : "",
* "tpSrc" : "80",
* "tpDst" : "100"
* }
*
*
*/
@Path("/container/{container}/flowspec/{flowspec}")
@PUT
@Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
@StatusCodes({
@ResponseCode(code = 201, condition = "FlowSpec created successfully"),
@ResponseCode(code = 400, condition = "Invalid flowspec configuration"),
@ResponseCode(code = 404, condition = "The container is not found"),
@ResponseCode(code = 409, condition = "Container Entry already exists"),
@ResponseCode(code = 500, condition = "Failed to create Flow specifications. Failure Reason included in HTTP Error response") })
public Response createFlowSpec(@Context UriInfo uriInfo,
@PathParam(value = "container") String container,
@PathParam(value = "flowspec") String flowspec,
@TypeHint(ContainerFlowConfig.class) ContainerFlowConfig containerFlowConfig) {
handleAdminAuthorization(getUserName());
handleForbiddenOnDefault(container);
handleContainerNotExists(container);
handleNameMismatch(containerFlowConfig.getName(), flowspec);
IContainerManager containerManager = getContainerManager();
List list = new ArrayList();
list.add(containerFlowConfig);
Status status = containerManager.addContainerFlows(container, list);
if (status.isSuccess()) {
NorthboundUtils.auditlog("Flow Spec", username, "added", containerFlowConfig.getName());
return Response.created(uriInfo.getRequestUri()).build();
}
return NorthboundUtils.getResponse(status);
}
/**
* Remove flowspec from a container
*
* @param name
* name of the flowspec (eg. telnet)
* @param container
* name of the Container (eg. black)
* @return Response as dictated by the HTTP Response code
*
*
*
* Example:
*
* Request URL:
* http://localhost:8080/controller/nb/v2/containermanager/container/black/flowspec/telnet
*
*
*/
@Path("/container/{container}/flowspec/{flowspec}")
@DELETE
@StatusCodes({
@ResponseCode(code = 204, condition = "Flow Spec deleted successfully"),
@ResponseCode(code = 400, condition = "Invalid flowspec configuration"),
@ResponseCode(code = 404, condition = "Container or Container Entry not found"),
@ResponseCode(code = 406, condition = "Cannot operate on Default Container when other Containers are active"),
@ResponseCode(code = 500, condition = "Failed to delete Flowspec. Failure Reason included in HTTP Error response"),
@ResponseCode(code = 503, condition = "One or more of Controller service is unavailable") })
public Response removeFlowSpec(@PathParam(value = "container") String container,
@PathParam(value = "flowspec") String flowspec) {
handleAdminAuthorization(getUserName());
handleForbiddenOnDefault(container);
handleContainerNotExists(container);
IContainerManager containerManager = getContainerManager();
Set set = new HashSet();
set.add(flowspec);
Status status = containerManager.removeContainerFlows(container, set);
if (status.isSuccess()) {
NorthboundUtils.auditlog("Flow Spec", username, "added", flowspec);
return Response.noContent().build();
}
return NorthboundUtils.getResponse(status);
}
/**
* Add node connectors to a container
*
* @param container
* name of the container (eg. green)
* @param list
* The list of strings each representing a node connector in the form "|@|", as "OF|1@OF|00:00:00:ab:00:00:00:01"
* @return response as dictated by the HTTP Status code
*
*
*
* Example:
*
* Request URL:
* http://localhost:8080/controller/nb/v2/containermanager/container/green/nodeconnector
*
* Request body in XML:
* <nodeConnectors>
* <nodeConnectors>OF|1@OF|00:00:00:00:00:00:00:01</nodeConnectors>
* <nodeConnectors>OF|2@OF|00:00:00:00:00:00:00:01</nodeConnectors>
* <nodeConnectors>OF|3@OF|00:00:00:00:00:00:00:22</nodeConnectors>
* <nodeConnectors>OF|4@OF|00:00:00:00:00:00:00:22</nodeConnectors>
* </nodeConnectors>
*
* Request body in JSON:
* {
* "nodeConnectors" : [
* "OF|1@OF|00:00:00:00:00:00:00:01",
* "OF|2@OF|00:00:00:00:00:00:00:01",
* "OF|3@OF|00:00:00:00:00:00:00:22",
* "OF|4@OF|00:00:00:00:00:00:00:22"
* ]
* }
*
*
*/
@Path("/container/{container}/nodeconnector/")
@PUT
@Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
@TypeHint(Response.class)
@StatusCodes({
@ResponseCode(code = 200, condition = "NodeConnectors added successfully"),
@ResponseCode(code = 401, condition = "User not authorized to perform this operation"),
@ResponseCode(code = 403, condition = "Operation forbidden on default"),
@ResponseCode(code = 404, condition = "The Container is not found"),
@ResponseCode(code = 409, condition = "Container Entry already exists"),
@ResponseCode(code = 500, condition = "Failed to create nodeconnectors. Failure Reason included in HTTP Error response") })
public Response addNodeConnectors(@PathParam(value = "container") String container,
@TypeHint(StringList.class) StringList list) {
handleAdminAuthorization(getUserName());
handleForbiddenOnDefault(container);
handleContainerNotExists(container);
IContainerManager containerManager = getContainerManager();
Status status = containerManager.addContainerEntry(container, list.getList());
if (status.isSuccess()) {
NorthboundUtils.auditlog("Node ", username, "added", " Ports:" + list.getList());
}
return NorthboundUtils.getResponse(status);
}
/**
* Remove node connectors from a container
*
* @param container
* name of the container (eg. red)
* @param list
* The list of strings each representing a node connector in the form "|@|", as "OF|1@OF|00:00:00:ab:00:00:00:01"
* @return response as dictated by the HTTP Status code
*
*
*
* Example:
*
* Request URL:
* http://localhost:8080/controller/nb/v2/containermanager/container/red/nodeconnector
*
* Request body in XML:
* <nodeConnectors>
* <nodeConnectors>OF|1@OF|00:00:00:00:00:00:00:01</nodeConnectors>
* <nodeConnectors>OF|2@OF|00:00:00:00:00:00:00:01</nodeConnectors>
* <nodeConnectors>OF|3@OF|00:00:00:00:00:00:00:22</nodeConnectors>
* <nodeConnectors>OF|4@OF|00:00:00:00:00:00:00:22</nodeConnectors>
* </nodeConnectors>
*
* Request body in JSON:
* {
* "nodeConnectors" : [
* "OF|1@OF|00:00:00:00:00:00:00:01",
* "OF|2@OF|00:00:00:00:00:00:00:01",
* "OF|3@OF|00:00:00:00:00:00:00:22",
* "OF|4@OF|00:00:00:00:00:00:00:22"
* ]
* }
*
*
*/
@Path("/container/{container}/nodeconnector/")
@DELETE
@Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
@StatusCodes({
@ResponseCode(code = 204, condition = "Container Entry deleted successfully"),
@ResponseCode(code = 400, condition = "Invalid Container Entry configuration"),
@ResponseCode(code = 404, condition = "The Container is not found"),
@ResponseCode(code = 406, condition = "Cannot operate on Default Container when other Containers are active"),
@ResponseCode(code = 500, condition = "Failed to delete node connector. Failure Reason included in HTTP Error response") })
public Response removeNodeConnectors(@PathParam(value = "container") String container,
@TypeHint(StringList.class) StringList portList) {
handleAdminAuthorization(getUserName());
handleForbiddenOnDefault(container);
handleContainerNotExists(container);
IContainerManager containerManager = getContainerManager();
Status status = containerManager.removeContainerEntry(container, portList.getList());
if (status.isSuccess()) {
NorthboundUtils.auditlog("Node", username, "removed", " Ports:" + portList.getList());
return Response.noContent().build();
}
return NorthboundUtils.getResponse(status);
}
/*
* Check If the function is not allowed on default container, Throw a
* ResourceForbiddenException exception if forbidden
*/
private void handleForbiddenOnDefault(String container) {
if (container.equalsIgnoreCase(GlobalConstants.DEFAULT.toString())) {
throw new ResourceForbiddenException(RestMessages.NODEFAULT.toString() + ": " + container);
}
}
/*
* Check if container exists, Throw a ResourceNotFoundException exception if it
* does not exist
*/
private void handleContainerNotExists(String container) {
IContainerManager containerManager = getContainerManager();
if (!containerManager.doesContainerExist(container)) {
throw new ResourceNotFoundException(RestMessages.NOCONTAINER.toString() + ": " + container);
}
}
private void handleContainerExists(String container) {
IContainerManager containerManager = getContainerManager();
if (containerManager.doesContainerExist(container)) {
throw new ResourceConflictException(RestMessages.RESOURCECONFLICT.toString() + ": " + container);
}
}
private void handleAdminAuthorization(String userName) {
IUserManager usrMgr = (IUserManager) ServiceHelper.getGlobalInstance(IUserManager.class, this);
UserLevel level = usrMgr.getUserLevel(userName);
if (level.ordinal() <= UserLevel.NETWORKADMIN.ordinal()) {
return;
}
throw new UnauthorizedException("User is not authorized to perform this operation");
}
private void handleNetworkAuthorization(String userName) {
IUserManager usrMgr = (IUserManager) ServiceHelper.getGlobalInstance(IUserManager.class, this);
UserLevel level = usrMgr.getUserLevel(userName);
if (level.ordinal() <= UserLevel.NETWORKOPERATOR.ordinal()) {
return;
}
throw new UnauthorizedException("User is not authorized to perform this operation");
}
private void handleContainerAuthorization(String container, String userName) {
IContainerAuthorization auth = (IContainerAuthorization) ServiceHelper.getGlobalInstance(
IContainerAuthorization.class, this);
UserLevel level = auth.getUserLevel(userName);
if (level.ordinal() <= UserLevel.NETWORKOPERATOR.ordinal()) {
return;
}
Privilege current = (auth == null) ? Privilege.NONE : auth.getResourcePrivilege(userName, container);
if (current.ordinal() > Privilege.NONE.ordinal()) {
return;
}
throw new UnauthorizedException("User is not authorized to perform this operation");
}
}