containerNames = containerManager.getContainerNames();
for (String cName : containerNames) {
if (cName.trim().equalsIgnoreCase(containerName.trim())) {
return;
}
}
throw new ResourceNotFoundException(containerName + " " + RestMessages.NOCONTAINER.toString());
}
private void handleNameMismatch(String name, String nameinURL) {
if (name == null || nameinURL == null) {
throw new BadRequestException(RestMessages.INVALIDDATA.toString() + " : Name is null");
}
if (name.equals(nameinURL)) {
return;
}
throw new ResourceConflictException(RestMessages.INVALIDDATA.toString()
+ " : Name in URL does not match the name in request body");
}
/**
* List all the subnets in a given container
*
* @param containerName
* container in which we want to query the subnets
*
* @return a List of SubnetConfig
*
*
* Example:
*
* Request URL: http://localhost:8080/controller/nb/v2/subnetservice/default/subnets
*
* Response in XML:
* <subnetConfig>
* <name>subnet1</name>
* <subnet>30.0.0.1/24</subnet>
* <nodePorts>1/1>/nodePorts>
* <nodePorts>1/2>/nodePorts>
* <nodePorts>1/3>/nodePorts>
* </subnetConfig>
* <subnetConfig>
* <name>subnet2</name>
* <subnet>20.0.0.1/24</subnet>
* <nodePorts>2/1>/nodePorts>
* <nodePorts>2/2>/nodePorts>
* <nodePorts>2/3>/nodePorts>
* </subnetConfig>
*
* Response in JSON:
* {
* "name":"subnet1",
* "subnet":"30.0.0.1/24",
* "nodePorts":["1/1","1/2","1/3"]
* }
* {
* "name":"subnet2",
* "subnet":"20.0.0.1/24",
* "nodePorts":["2/1","2/2","2/3"]
* }
*
*/
@Path("/{containerName}/subnets")
@GET
@Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
@StatusCodes({ @ResponseCode(code = 401, condition = "User not authorized to perform this operation"),
@ResponseCode(code = 404, condition = "The containerName passed was not found"),
@ResponseCode(code = 503, condition = "Service unavailable") })
@TypeHint(SubnetConfigs.class)
public SubnetConfigs listSubnets(@PathParam("containerName") String containerName) {
handleContainerDoesNotExist(containerName);
if (!NorthboundUtils.isAuthorized(getUserName(), containerName, Privilege.READ, this)) {
throw new UnauthorizedException("User is not authorized to perform this operation on container "
+ containerName);
}
ISwitchManager switchManager = (ISwitchManager) ServiceHelper.getInstance(ISwitchManager.class, containerName, this);
if (switchManager == null) {
throw new ServiceUnavailableException("SwitchManager " + RestMessages.SERVICEUNAVAILABLE.toString());
}
return new SubnetConfigs(switchManager.getSubnetsConfigList());
}
/**
* List the configuration of a subnet in a given container
*
* @param containerName
* container in which we want to query the subnet
* @param subnetName
* of the subnet being queried
*
* @return SubnetConfig
*
*
* Example:
*
* Request URL: http://localhost:8080/controller/nb/v2/subnetservice/default/subnet/subnet1
*
* Response in XML:
* <subnetConfig>
* <name>subnet1</name>
* <subnet>30.0.0.1/24</subnet>
* <nodePorts>1/1>/nodePorts>
* <nodePorts>1/2>/nodePorts>
* <nodePorts>1/3>/nodePorts>
* </subnetConfig>
*
* Response in JSON:
* {
* "name":"subnet1",
* "subnet":"30.0.0.1/24",
* "nodePorts":["1/1","1/2","1/3"]
* }
*
*/
@Path("/{containerName}/subnet/{subnetName}")
@GET
@Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
@StatusCodes({ @ResponseCode(code = 401, condition = "User not authorized to perform this operation"),
@ResponseCode(code = 404, condition = "The containerName or subnetName passed was not found"),
@ResponseCode(code = 503, condition = "Service unavailable") })
@TypeHint(SubnetConfig.class)
public SubnetConfig listSubnet(@PathParam("containerName") String containerName,
@PathParam("subnetName") String subnetName) {
handleContainerDoesNotExist(containerName);
if (!NorthboundUtils.isAuthorized(getUserName(), containerName, Privilege.READ, this)) {
throw new UnauthorizedException("User is not authorized to perform this operation on container "
+ containerName);
}
ISwitchManager switchManager = (ISwitchManager) ServiceHelper.getInstance(ISwitchManager.class, containerName, this);
if (switchManager == null) {
throw new ServiceUnavailableException("SwitchManager " + RestMessages.SERVICEUNAVAILABLE.toString());
}
SubnetConfig res = switchManager.getSubnetConfig(subnetName);
if (res == null) {
throw new ResourceNotFoundException(RestMessages.NOSUBNET.toString());
} else {
return res;
}
}
/**
* Add a subnet to a container. If a subnet by the given name already exists
* this method will return a non-successful response.
*
* @param containerName
* name of the container to which subnet needs to be added
* @param subnetName
* name of new subnet to be added
* @param subnetConfigData
* the {@link SubnetConfig} structure in request body
*
* @return Response as dictated by the HTTP Response Status code
*
*
* Example:
*
* Request URL: http://localhost:8080/controller/nb/v2/subnetservice/default/subnet/subnet1
*
* Request XML:
* <subnetConfig>
* <name>subnet1</name>
* <subnet>30.0.0.1/24</subnet>
* </subnetConfig>
*
* Request in JSON:
* {
* "name":"subnet1",
* "subnet":"30.0.0.1/24"
* }
*
*/
@Path("/{containerName}/subnet/{subnetName}")
@PUT
@StatusCodes({ @ResponseCode(code = 201, condition = "Subnet created successfully"),
@ResponseCode(code = 400, condition = "Invalid data passed"),
@ResponseCode(code = 401, condition = "User not authorized to perform this operation"),
@ResponseCode(code = 409, condition = "Subnet name in url conflicts with name in request body"),
@ResponseCode(code = 404, condition = "Container name passed was not found or subnet config is null"),
@ResponseCode(code = 500, condition = "Internal Server Error: Addition of subnet failed"),
@ResponseCode(code = 503, condition = "Service unavailable") })
public Response addSubnet(@PathParam("containerName") String containerName,
@PathParam("subnetName") String subnetName,
@TypeHint(SubnetConfig.class) SubnetConfig subnetConfigData) {
handleContainerDoesNotExist(containerName);
if (!NorthboundUtils.isAuthorized(getUserName(), containerName, Privilege.WRITE, this)) {
throw new UnauthorizedException("User is not authorized to perform this operation on container "
+ containerName);
}
SubnetConfig cfgObject = subnetConfigData;
handleNameMismatch(cfgObject.getName(), subnetName);
ISwitchManager switchManager = (ISwitchManager) ServiceHelper.getInstance(ISwitchManager.class, containerName, this);
if (switchManager == null) {
throw new ServiceUnavailableException("SwitchManager " + RestMessages.SERVICEUNAVAILABLE.toString());
}
Set ports = cfgObject.getNodePorts();
SubnetConfig subnetCfg = null;
if (ports == null) {
subnetCfg = new SubnetConfig(cfgObject.getName(), cfgObject.getSubnet(), new HashSet(0));
} else {
subnetCfg = cfgObject;
}
Status status = switchManager.addSubnet(subnetCfg);
if (status.isSuccess()) {
NorthboundUtils.auditlog("Subnet Gateway", username, "added", subnetName, containerName);
return Response.status(Response.Status.CREATED).build();
}
return NorthboundUtils.getResponse(status);
}
/**
* Delete a subnet from a container
*
* @param containerName
* name of the container from which subnet needs to be removed
* @param subnetName
* name of new subnet to be deleted
* @return Response as dictated by the HTTP Response Status code
*
*
* Example:
* Request URL: http://localhost:8080/controller/nb/v2/subnetservice/default/subnet/subnet1
*
*
*/
@Path("/{containerName}/subnet/{subnetName}")
@DELETE
@StatusCodes({ @ResponseCode(code = 204, condition = "No Content"),
@ResponseCode(code = 401, condition = "User not authorized to perform this operation"),
@ResponseCode(code = 404, condition = "The containerName passed was not found"),
@ResponseCode(code = 500, condition = "Internal Server Error : Removal of subnet failed"),
@ResponseCode(code = 503, condition = "Service unavailable") })
public Response removeSubnet(@PathParam("containerName") String containerName,
@PathParam("subnetName") String subnetName) {
handleContainerDoesNotExist(containerName);
if (!NorthboundUtils.isAuthorized(getUserName(), containerName, Privilege.WRITE, this)) {
throw new UnauthorizedException("User is not authorized to perform this operation on container "
+ containerName);
}
ISwitchManager switchManager = (ISwitchManager) ServiceHelper.getInstance(ISwitchManager.class, containerName, this);
if (switchManager == null) {
throw new ServiceUnavailableException("SwitchManager " + RestMessages.SERVICEUNAVAILABLE.toString());
}
Status status = switchManager.removeSubnet(subnetName);
if (status.isSuccess()) {
NorthboundUtils.auditlog("Subnet Gateway", username, "removed", subnetName, containerName);
return Response.status(Response.Status.NO_CONTENT).build();
}
return NorthboundUtils.getResponse(status);
}
/**
* Modify a subnet. For now only changing the port list is allowed.
*
* @param containerName
* Name of the Container
* @param subnetName
* Name of the SubnetConfig to be modified
* @param subnetConfigData
* the {@link SubnetConfig} structure in request body
* parameter
* @return If the operation is successful or not
*
*
* Example:
*
* Request URL: http://localhost:8080/controller/nb/v2/subnetservice/default/subnet/subnet1/nodePorts
*
* Request in XML:
* <subnetConfig>
* <name>subnet1</name>
* <subnet>30.0.0.1/24</subnet>
* <nodePorts>1/1</nodePorts>
* <nodePorts>1/2</nodePorts>
* <nodePorts>1/3</nodePorts>
* </subnetConfig>
*
* Request in JSON:
* {
* "name":"subnet1",
* "subnet":"30.0.0.1/24",
* "nodePorts":["1/1","1/2","1/3"]
* }
*
*/
@Path("/{containerName}/subnet/{subnetName}/nodePorts")
@POST
@Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
@StatusCodes({
@ResponseCode(code = 200, condition = "Ports replaced successfully"),
@ResponseCode(code = 400, condition = "Invalid request to change subnet name or invalid node ports passed"),
@ResponseCode(code = 401, condition = "User not authorized to perform this operation"),
@ResponseCode(code = 409, condition = "Subnet name in url conflicts with name in request body"),
@ResponseCode(code = 404, condition = "The containerName or subnetName is not found"),
@ResponseCode(code = 500, condition = "Internal server error: Modify ports failed"),
@ResponseCode(code = 503, condition = "Service unavailable") })
public Response modifySubnet(@PathParam("containerName") String containerName,
@PathParam("subnetName") String subnetName,
@TypeHint(SubnetConfig.class) SubnetConfig subnetConfigData) {
handleContainerDoesNotExist(containerName);
if (!NorthboundUtils.isAuthorized(getUserName(), containerName, Privilege.WRITE, this)) {
throw new UnauthorizedException("User is not authorized to perform this operation on container "
+ containerName);
}
handleNameMismatch(subnetConfigData.getName(), subnetName);
ISwitchManager switchManager = (ISwitchManager) ServiceHelper.getInstance(ISwitchManager.class, containerName,
this);
if (switchManager == null) {
throw new ServiceUnavailableException("SwitchManager " + RestMessages.SERVICEUNAVAILABLE.toString());
}
SubnetConfig subnetConf = subnetConfigData;
SubnetConfig existingConf = switchManager.getSubnetConfig(subnetName);
boolean successful = true;
// make sure that the name matches an existing subnet and we're not
// changing the name or subnet IP/mask
if (existingConf == null) {
// don't have a subnet by that name
return Response.status(Response.Status.NOT_FOUND).build();
} else if (!existingConf.getName().equals(subnetConf.getName())
|| !existingConf.getSubnet().equals(subnetConf.getSubnet())) {
// can't change the name of a subnet
Response.status(Response.Status.BAD_REQUEST).build();
} else {
// create a set for fast lookups
Set newPorts = new HashSet(subnetConf.getNodePorts());
// go through the current ports and (1) remove ports that aren't
// there anymore and (2) remove ports that are still there from the
// set of ports to add
for (String s : existingConf.getNodePorts()) {
if (newPorts.contains(s)) {
newPorts.remove(s);
} else {
Status st = switchManager.removePortsFromSubnet(subnetName, s);
successful = successful && st.isSuccess();
}
}
// add any remaining ports
for (String s : newPorts) {
Status st = switchManager.addPortsToSubnet(subnetName, s);
successful = successful && st.isSuccess();
if (successful) {
NorthboundUtils.auditlog("Subnet Gateway", username, "added", s + " to " + subnetName,
containerName);
}
}
}
if (successful) {
return Response.status(Response.Status.OK).build();
}
throw new InternalServerErrorException(RestMessages.INTERNALERROR.toString());
}
/**
* Add ports to a subnet in the container.
*
* @param containerName
* name of the container that has the subnet to which node ports
* need to be added
* @param subnetName
* name of subnet to which node ports need to be added
* @param SubnetConfig
* the {@link SubnetConfig} structure in request body
* @return Response as dictated by the HTTP Response Status code
*
*
* Example:
* Request URL: http://localhost:8080/controller/nb/v2/subnetservice/default/subnet/subnet1/nodePorts
*
* Request XML:
* <subnetConfig>
* <name>subnet1</name>
* <subnet>30.0.0.1/24</subnet>
* <nodePorts>1/1</nodePorts>
* <nodePorts>1/2</nodePorts>
* <nodePorts>1/3</nodePorts>
* </subnetConfig>
*
* Request in JSON:
* {
* "name":"subnet1",
* "subnet":"30.0.0.1/24",
* "nodePorts":["1/1","1/2","1/3"]
* }
*
*
*/
@Path("/{containerName}/subnet/{subnetName}/nodePorts")
@PUT
@Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
@StatusCodes({
@ResponseCode(code = 200, condition = "Added node ports to subnet successfully"),
@ResponseCode(code = 400, condition = "Invalid request to change subnet name or invalid node ports passed"),
@ResponseCode(code = 401, condition = "User not authorized to perform this operation"),
@ResponseCode(code = 404, condition = "The containerName or subnet is not found"),
@ResponseCode(code = 409, condition = "Subnet name in url conflicts with name in request body"),
@ResponseCode(code = 500, condition = "Internal server error : Port add failed"),
@ResponseCode(code = 503, condition = "Service unavailable") })
public Response addNodePorts(@PathParam("containerName") String containerName,
@PathParam("subnetName") String subnetName,
@TypeHint(SubnetConfig.class) SubnetConfig subnetConfigData) {
handleContainerDoesNotExist(containerName);
if (!NorthboundUtils.isAuthorized(getUserName(), containerName, Privilege.WRITE, this)) {
throw new UnauthorizedException("User is not authorized to perform this operation on container "
+ containerName);
}
handleNameMismatch(subnetConfigData.getName(), subnetName);
SubnetConfig subnetConf = subnetConfigData;
ISwitchManager switchManager = (ISwitchManager) ServiceHelper.getInstance(ISwitchManager.class, containerName,
this);
if (switchManager == null) {
throw new ServiceUnavailableException("SwitchManager " + RestMessages.SERVICEUNAVAILABLE.toString());
}
SubnetConfig existingConf = switchManager.getSubnetConfig(subnetName);
// make sure that the name matches an existing subnet and we're not
// changing the name or subnet IP/mask
if (existingConf == null) {
// don't have a subnet by that name
return Response.status(Response.Status.NOT_FOUND).build();
} else if (!existingConf.getName().equals(subnetConf.getName())
|| !existingConf.getSubnet().equals(subnetConf.getSubnet())) {
// can't change the name of a subnet
return Response.status(Response.Status.BAD_REQUEST).build();
}
Status st;
boolean successful = true;
Set ports = subnetConf.getNodePorts();
if (ports == null || ports.isEmpty()) {
throw new BadRequestException(RestMessages.INVALIDDATA.toString());
}
// add new ports only
if (existingConf.getNodePorts() != null) {
ports.removeAll(existingConf.getNodePorts());
}
for (String port : ports) {
st = switchManager.addPortsToSubnet(subnetName, port);
successful = successful && st.isSuccess();
if (successful) {
NorthboundUtils.auditlog("Subnet Gateway", username, "added", st + " to " + subnetName, containerName);
}
}
if (successful) {
return Response.status(Response.Status.OK).build();
}
throw new InternalServerErrorException(RestMessages.INTERNALERROR.toString());
}
/**
* Delete ports from a subnet in the container
*
* @param containerName
* name of the container that has the subnet from which node
* ports need to be deleted
* @param subnetName
* name of subnet from which node ports need to be deleted
* @param subnetConfigData
* SubnetConfig object to be deleted
* @return Response as dictated by the HTTP Response Status code
*
*
* Example:
* Request URL: http://localhost:8080/controller/nb/v2/subnetservice/default/subnet/subnet1/nodePorts
*
* Request XML:
* <subnetConfig>
* <name>subnet3</name>
* <subnet>30.0.0.1/24</subnet>
* <nodePorts>1/1,1/2,1/3</nodePorts>
* </subnetConfig>
*
* Request in JSON:
* { "name" : "subnet1",
* "subnet" : "30.0.0.1/24",
* nodePorts : ["1/1,1/2,1/3"]}
*
*
*/
@Path("/{containerName}/subnet/{subnetName}/nodePorts")
@DELETE
@Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
@StatusCodes({
@ResponseCode(code = 204, condition = "No content"),
@ResponseCode(code = 400, condition = "Invalid request to change subnet name or invalid node ports passed"),
@ResponseCode(code = 401, condition = "User not authorized to perform this operation"),
@ResponseCode(code = 404, condition = "The containerName or subnet is not found"),
@ResponseCode(code = 409, condition = "Subnet name in url conflicts with name in request body"),
@ResponseCode(code = 500, condition = "Internal server error : Delete node ports failed"),
@ResponseCode(code = 503, condition = "Service unavailable") })
public Response deleteNodePorts(@PathParam("containerName") String containerName,
@PathParam("subnetName") String subnetName,
@TypeHint(SubnetConfig.class) SubnetConfig subnetConfigData) {
handleContainerDoesNotExist(containerName);
if (!NorthboundUtils.isAuthorized(getUserName(), containerName, Privilege.WRITE, this)) {
throw new UnauthorizedException("User is not authorized to perform this operation on container "
+ containerName);
}
handleNameMismatch(subnetConfigData.getName(), subnetName);
SubnetConfig subnetConf = subnetConfigData;
if (subnetConf.getNodePorts() == null || subnetConf.getNodePorts().isEmpty()) {
throw new BadRequestException(RestMessages.INVALIDDATA.toString() + " : invalid node ports");
}
ISwitchManager switchManager = (ISwitchManager) ServiceHelper.getInstance(ISwitchManager.class, containerName,
this);
if (switchManager == null) {
throw new ServiceUnavailableException("SwitchManager " + RestMessages.SERVICEUNAVAILABLE.toString());
}
SubnetConfig existingConf = switchManager.getSubnetConfig(subnetName);
// make sure that the name matches an existing subnet and we're not
// changing the name or subnet IP/mask
if (existingConf == null) {
// don't have a subnet by that name
return Response.status(Response.Status.NOT_FOUND).build();
} else if (!existingConf.getName().equals(subnetConf.getName())
|| !existingConf.getSubnet().equals(subnetConf.getSubnet())) {
// can't change the name of a subnet
return Response.status(Response.Status.BAD_REQUEST).build();
}
Status st;
boolean successful = true;
Set ports = subnetConf.getNodePorts();
// delete existing ports
ports.retainAll(existingConf.getNodePorts());
for (String port : ports) {
st = switchManager.removePortsFromSubnet(subnetName, port);
successful = successful && st.isSuccess();
if (successful) {
NorthboundUtils.auditlog("Subnet Gateway", username, "removed", st + " from " + subnetName,
containerName);
}
}
if (successful) {
return Response.noContent().build();
}
throw new InternalServerErrorException(RestMessages.INTERNALERROR.toString());
}
}