package org.openstack.atlas.api.mgmt.resources;
import org.openstack.atlas.api.faults.HttpResponseBuilder;
import org.openstack.atlas.api.helpers.PaginationHelper;
import org.openstack.atlas.api.helpers.ResponseFactory;
import org.openstack.atlas.api.mapper.UsageMapper;
import org.openstack.atlas.api.mgmt.helpers.CheckQueryParams;
import org.openstack.atlas.api.mgmt.repository.ValidatorRepository;
import org.openstack.atlas.api.mgmt.resources.providers.ManagementDependencyProvider;
import org.openstack.atlas.api.mgmt.validation.contexts.ReassignHostContext;
import org.openstack.atlas.api.validation.results.ValidatorResult;
import org.openstack.atlas.docs.loadbalancers.api.management.v1.LoadBalancers;
import org.openstack.atlas.service.domain.entities.LoadBalancer;
import org.openstack.atlas.service.domain.entities.Usage;
import org.openstack.atlas.service.domain.exceptions.EntityNotFoundException;
import org.openstack.atlas.service.domain.management.operations.EsbRequest;
import org.openstack.atlas.service.domain.operations.Operation;
import org.openstack.atlas.util.common.exceptions.ConverterException;
import org.openstack.atlas.util.ip.IPUtils;
import org.w3.atom.Link;
import javax.ws.rs.*;
import javax.ws.rs.core.HttpHeaders;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
import static javax.ws.rs.core.MediaType.*;
import static org.openstack.atlas.util.converters.DateTimeConverters.isoTocal;
public class LoadBalancersResource extends ManagementDependencyProvider {
private LoadBalancerResource loadBalancerResource;
private AccountLimitsResource accountLimitsResource;
private SaveStateHistoryResource saveStateHistoryResource;
private int accountId;
private HttpHeaders requestHeaders;
@Path("{id: [1-9][0-9]*}")
public LoadBalancerResource getHostResource(@PathParam("id") int id) {
loadBalancerResource.setId(id);
return loadBalancerResource;
}
@Path("{id: [1-9][0-9]*}/lbstatehistory")
public SaveStateHistoryResource getSaveStateHistory(@PathParam("id") int id) {
saveStateHistoryResource.setId(id);
return saveStateHistoryResource;
}
@Path("absolutelimits")
public AccountLimitsResource getAccountLimitsResource() {
accountLimitsResource.setAccountId(accountId);
return accountLimitsResource;
}
@GET
@Path("usage")
public Response retrieveAllAccountUsage(@QueryParam("startTime") String startTimeParam, @QueryParam("endTime") String endTimeParam, @QueryParam("offset") Integer offset, @QueryParam("limit") Integer limit) {
if (!isUserInRole("cp,ops,support,billing")) {
return ResponseFactory.accessDenied();
}
Calendar startTime;
Calendar endTime;
List<Usage> rawLoadBalancerUsageList;
org.openstack.atlas.docs.loadbalancers.api.management.v1.LoadBalancerUsageRecords loadBalancerUsageRecords = new org.openstack.atlas.docs.loadbalancers.api.management.v1.LoadBalancerUsageRecords();
if (startTimeParam == null || endTimeParam == null) {
final String badRequestMessage = "'startTime' and 'endTime' query parameters are required";
return ResponseFactory.getResponseWithStatus(Response.Status.BAD_REQUEST, badRequestMessage);
} else {
try {
startTime = isoTocal(startTimeParam);
endTime = isoTocal(endTimeParam);
} catch (ConverterException ex) {
final String badRequestMessage = "Date parameters must follow ISO-8601 (yyyy-MM-dd'T'HH:mm:ss) format";
return ResponseFactory.getResponseWithStatus(Response.Status.BAD_REQUEST, badRequestMessage);
}
}
try {
limit = PaginationHelper.determinePageLimit(limit);
offset = PaginationHelper.determinePageOffset(offset);
rawLoadBalancerUsageList = usageRepository.getUsageRecords(startTime, endTime, offset, limit);
loadBalancerUsageRecords.getLoadBalancerUsageRecords().addAll(UsageMapper.toMgmtApiUsages(rawLoadBalancerUsageList));
if (loadBalancerUsageRecords.getLoadBalancerUsageRecords().size() > limit) {
String relativeUri = String.format("/management/loadbalancers/usage?startTime=%s&endTime=%s&offset=%d&limit=%d", startTimeParam, endTimeParam, PaginationHelper.calculateNextOffset(offset, limit), limit);
Link nextLink = PaginationHelper.createLink(PaginationHelper.NEXT, relativeUri);
loadBalancerUsageRecords.getLinks().add(nextLink);
loadBalancerUsageRecords.getLoadBalancerUsageRecords().remove(limit.intValue()); // Remove limit+1 item
}
if (offset > 0) {
String relativeUri = String.format("/management/loadbalancers/usage?startTime=%s&endTime=%s&offset=%d&limit=%d", startTimeParam, endTimeParam, PaginationHelper.calculatePreviousOffset(offset, limit), limit);
Link nextLink = PaginationHelper.createLink(PaginationHelper.PREVIOUS, relativeUri);
loadBalancerUsageRecords.getLinks().add(nextLink);
}
return Response.status(200).entity(loadBalancerUsageRecords).build();
} catch (Exception ex) {
return ResponseFactory.getErrorResponse(ex, null, null);
}
}
@PUT
@Path("reassignhosts")
@Consumes({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
public Response reAssignHosts(LoadBalancers lbs) {
if (!isUserInRole("cp,ops")) {
return ResponseFactory.accessDenied();
}
ValidatorResult res = ValidatorRepository.getValidatorFor(LoadBalancers.class).validate(lbs, ReassignHostContext.REASSIGN_HOST);
if (!res.passedValidation()) {
return Response.status(400).entity(HttpResponseBuilder.buildBadRequestResponse("Validation fault",
res.getValidationErrorMessages())).build();
}
try {
List<org.openstack.atlas.service.domain.entities.LoadBalancer> domainLoadBalancers = new ArrayList<LoadBalancer>();
for (org.openstack.atlas.docs.loadbalancers.api.management.v1.LoadBalancer lb : lbs.getLoadBalancers()) {
org.openstack.atlas.service.domain.entities.Host dHost = new org.openstack.atlas.service.domain.entities.Host();
org.openstack.atlas.service.domain.entities.LoadBalancer loadBalancer = new org.openstack.atlas.service.domain.entities.LoadBalancer();
if (lb.getHost() != null) {
dHost.setId(lb.getHost().getId());
}
loadBalancer.setId(lb.getId());
loadBalancer.setHost(dHost);
domainLoadBalancers.add(loadBalancer);
}
List<LoadBalancer> validLoadBalancers = loadBalancerService.reassignLoadBalancerHost(domainLoadBalancers);
EsbRequest req = new EsbRequest();
req.setLoadBalancers(validLoadBalancers);
getManagementAsyncService().callAsyncLoadBalancingOperation(Operation.REASSIGN_LOADBALANCER_HOST, req);
return Response.status(Response.Status.ACCEPTED).build();
} catch (Exception e) {
return ResponseFactory.getErrorResponse(e, null, null);
}
}
@DELETE
@Path("removeoldlimits")
public Response deleteRateLimitByExpiration() {
if (!isUserInRole("cp,ops")) {
return ResponseFactory.accessDenied();
}
try {
LoadBalancer domainLb = new LoadBalancer();
EsbRequest request = new EsbRequest();
request.setLoadBalancer(domainLb);
getManagementAsyncService().callAsyncLoadBalancingOperation(Operation.DELETE_OLD_RATE_LIMITS, request);
return Response.status(Response.Status.ACCEPTED).build();
} catch (Exception e) {
return ResponseFactory.getErrorResponse(e, null, null);
}
}
@GET
@Produces({APPLICATION_XML, APPLICATION_JSON, APPLICATION_ATOM_XML})
public Response retrieveLoadBalancers(@QueryParam("vipaddress") String address, @QueryParam("vipid") Integer vipId, @QueryParam("status") String status,
@QueryParam("offset") Integer offset, @QueryParam("limit") Integer limit, @QueryParam("marker") Integer marker,
@QueryParam("page") Integer page, @QueryParam("changes-since") Integer time, @QueryParam("nodeAddress") String nodeAddress) throws EntityNotFoundException {
if (!isUserInRole("cp,ops,support")) {
return ResponseFactory.accessDenied();
}
CheckQueryParams checkParams = new CheckQueryParams();
Response checkResponseParams = checkParams.checkParams(address, vipId);
if (checkResponseParams != null) {
return checkResponseParams;
} else if (address != null) {
try {
return retrieveLoadBalancers(address);
} catch (Exception ex) {
return ResponseFactory.getErrorResponse(ex, null, null);
}
}
List<org.openstack.atlas.service.domain.entities.LoadBalancer> domainLbs = new ArrayList<org.openstack.atlas.service.domain.entities.LoadBalancer>();
org.openstack.atlas.docs.loadbalancers.api.management.v1.LoadBalancers dataModelLbs = new org.openstack.atlas.docs.loadbalancers.api.management.v1.LoadBalancers();
// if (vipId != null && vipId >= 9000000) {
// domainLbs = virtualIpService.getLoadBalancerByVip6Id(vipId);
// } else {
// domainLbs = virtualIpService.getLoadBalancerByVipId(vipId);
// }
if (vipId != null) {
domainLbs = retrieveAllVipsById(vipId);
}
for (org.openstack.atlas.service.domain.entities.LoadBalancer domainLb : domainLbs) {
dataModelLbs.getLoadBalancers().add(dozerMapper.map(domainLb, org.openstack.atlas.docs.loadbalancers.api.management.v1.LoadBalancer.class, "SIMPLE_VIP_LB"));
}
return Response.status(200).entity(dataModelLbs).build();
}
private Response retrieveLoadBalancers(String address) {
List<org.openstack.atlas.service.domain.entities.LoadBalancer> domainLbs;
org.openstack.atlas.docs.loadbalancers.api.management.v1.LoadBalancers dataModelLbs = new org.openstack.atlas.docs.loadbalancers.api.management.v1.LoadBalancers();
try {
if (IPUtils.isValidIpv4String(address)) {
domainLbs = virtualIpService.getLoadBalancerByVipAddress(address);
} else if (IPUtils.isValidIpv6String(address)) {
domainLbs = virtualIpService.getLoadBalancerByVip6Address(address);
} else {
return Response.status(400).entity("Ip address is invalid").build();
}
for (org.openstack.atlas.service.domain.entities.LoadBalancer domainLb : domainLbs) {
dataModelLbs.getLoadBalancers().add(dozerMapper.map(domainLb, org.openstack.atlas.docs.loadbalancers.api.management.v1.LoadBalancer.class, "SIMPLE_VIP_LB"));
}
} catch (Exception ex) {
String msg = getExtendedStackTrace(ex);
return ResponseFactory.getErrorResponse(ex, null, null);
}
return Response.status(200).entity(dataModelLbs).build();
}
private List<org.openstack.atlas.service.domain.entities.LoadBalancer> retrieveAllVipsById(int vipId) {
List<org.openstack.atlas.service.domain.entities.LoadBalancer> domainLbs;
domainLbs = virtualIpService.getLoadBalancerByVip6Id(vipId);
domainLbs.addAll(virtualIpService.getLoadBalancerByVipId(vipId));
return domainLbs;
}
public void setLoadBalancerResource(LoadBalancerResource loadBalancerResource) {
this.loadBalancerResource = loadBalancerResource;
}
public void setAccountLimitsResource(AccountLimitsResource accountLimitsResource) {
this.accountLimitsResource = accountLimitsResource;
}
public void setSaveStateHistoryResource(SaveStateHistoryResource saveStateHistoryResource) {
this.saveStateHistoryResource = saveStateHistoryResource;
}
public int getAccountId() {
return accountId;
}
public void setAccountId(int accountId) {
this.accountId = accountId;
}
}