package com.urbancode.terraform.tasks.rackspace;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import org.apache.commons.httpclient.HttpStatus;
import org.apache.commons.httpclient.methods.DeleteMethod;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.methods.RequestEntity;
import org.apache.commons.httpclient.methods.StringRequestEntity;
import org.apache.log4j.Logger;
import org.codehaus.jettison.json.JSONArray;
import org.codehaus.jettison.json.JSONException;
import org.codehaus.jettison.json.JSONObject;
import com.urbancode.x2o.tasks.SubTask;
public class LoadBalancerTask extends SubTask {
//**********************************************************************************************
// CLASS
//**********************************************************************************************
static private final Logger log = Logger.getLogger(LoadBalancerTask.class);
//**********************************************************************************************
// INSTANCE
//**********************************************************************************************
private EnvironmentTaskRackspace env;
String id = null;
String name;
String region;
String protocol;
String port;
String algorithm = "RANDOM";
String ipType;//public or private
boolean autoDelete = true;
List<LoadBalancerNodeTask> nodes = new ArrayList<LoadBalancerNodeTask>();
//----------------------------------------------------------------------------------------------
public LoadBalancerTask(EnvironmentTaskRackspace env) {
super();
this.env = env;
}
//----------------------------------------------------------------------------------------------
public String getId() {
return id;
}
//----------------------------------------------------------------------------------------------
public String getName() {
return name;
}
//----------------------------------------------------------------------------------------------
public String getRegion() {
return region;
}
//----------------------------------------------------------------------------------------------
public String getProtocol() {
return protocol;
}
//----------------------------------------------------------------------------------------------
public String getPort() {
return port;
}
//----------------------------------------------------------------------------------------------
public String getAlgorithm() {
return algorithm;
}
//----------------------------------------------------------------------------------------------
public String getIpType() {
return ipType;
}
//----------------------------------------------------------------------------------------------
public List<LoadBalancerNodeTask> getNodeTasks(){
return nodes;
}
//----------------------------------------------------------------------------------------------
public void setId(String id) {
this.id = id;
}
//----------------------------------------------------------------------------------------------
public void setName(String name) {
this.name = name;
}
//----------------------------------------------------------------------------------------------
public void setRegion(String region) {
if(Region.containsIgnoreCase(region)) {
this.region = region.toLowerCase();
}
else {
log.warn("You did not enter a valid region for this load balancer.");
}
}
//----------------------------------------------------------------------------------------------
public void setProtocol(String protocol) {
this.protocol = protocol;
}
//----------------------------------------------------------------------------------------------
public void setPort(String port) {
this.port = port;
}
//----------------------------------------------------------------------------------------------
public void setAlgorithm(String algorithm) {
this.algorithm = algorithm;
}
//----------------------------------------------------------------------------------------------
public void setIpType(String ipType) {
this.ipType = ipType;
if (!ipType.equalsIgnoreCase("public") && !ipType.equalsIgnoreCase("private")) {
log.warn("Valid IP types for load balancers are \"public\" or \"private\"");
}
}
//----------------------------------------------------------------------------------------------
public LoadBalancerNodeTask createNode() {
LoadBalancerNodeTask node = new LoadBalancerNodeTask(env, ipType);
nodes.add(node);
return node;
}
//----------------------------------------------------------------------------------------------
private void createLBRestCall()
throws JSONException, IOException {
RackspaceRestClient client = env.fetchContext().client;
String uri = "https://" + client.encodePath(region) + ".loadbalancers.api.rackspacecloud.com/v1.0/" +
client.encodePath(client.getTenantID()) + "/loadbalancers";
JSONObject data = new JSONObject();
JSONObject loadBalancer = new JSONObject();
loadBalancer.put("name", name);
loadBalancer.put("port", port);
loadBalancer.put("protocol", protocol);
loadBalancer.put("algorithm", algorithm);
loadBalancer.put("nodes", generateNodeJSON());
JSONArray virtualIps = new JSONArray();
JSONObject virtualIp = new JSONObject();
if (ipType.equalsIgnoreCase("public")) {
virtualIp.put("type", "PUBLIC");
}
else if (ipType.equalsIgnoreCase("private") || ipType.equalsIgnoreCase("servicenet")) {
virtualIp.put("type", "SERVICENET");
}
virtualIps.put(virtualIp);
loadBalancer.put("virtualIps", virtualIps);
data.put("loadBalancer", loadBalancer);
log.debug("Sending body " + data.toString());
PostMethod method = new PostMethod(uri);
RequestEntity entity = new StringRequestEntity(data.toString(), "application/json", null);
method.setRequestEntity(entity);
method.setRequestHeader("X-Auth-Token", client.getAuthToken());
method.setRequestHeader("Content-Type", "application/json");
int status = client.invokeMethod(method);
String body = client.getBody(method);
method.releaseConnection();
if (200 <= status && status <= 202) {
log.info("Load balancer creation request succeeded.");
JSONObject resultJSON = new JSONObject(body);
id = resultJSON.getJSONObject("loadBalancer").getString("id");
}
else {
log.warn("Exception when creating load balancer.");
throw new IOException(String.format("%d %s %s",
status,
HttpStatus.getStatusText(status),
body));
}
}
//----------------------------------------------------------------------------------------------
private void deleteLBRestCall()
throws JSONException, IOException {
RackspaceRestClient client = env.fetchContext().client;
String uri = "https://" + client.encodePath(region) + ".loadbalancers.api.rackspacecloud.com/v1.0/" +
client.encodePath(client.getTenantID()) + "/loadbalancers/" + client.encodePath(id);
DeleteMethod method = new DeleteMethod(uri);
method.setRequestHeader("X-Auth-Token", client.getAuthToken());
int status = client.invokeMethod(method);
String body = client.getBody(method);
method.releaseConnection();
if (200 <= status && status <= 204) {
log.info("Load balancer deletion request succeeded.");
}
else {
log.warn("Exception when deleting load balancer.");
throw new IOException(String.format("%d %s %s",
status,
HttpStatus.getStatusText(status),
body));
}
}
//----------------------------------------------------------------------------------------------
private JSONArray generateNodeJSON()
throws JSONException {
JSONArray result = new JSONArray();
for (LoadBalancerNodeTask node : nodes) {
JSONObject nodeJSON = new JSONObject();
nodeJSON.put("address", node.getAddress());
nodeJSON.put("port", node.getPort());
nodeJSON.put("condition", node.getCondition());
result.put(nodeJSON);
}
return result;
}
//----------------------------------------------------------------------------------------------
@Override
public void create() throws Exception {
for (LoadBalancerNodeTask node : nodes) {
node.create();
}
try {
createLBRestCall();
}
catch(IOException e) {
log.error("A REST call failed while creating load balancer", e);
}
catch(JSONException e) {
log.error("Malformed JSON while creating load balancer", e);
}
}
//----------------------------------------------------------------------------------------------
@Override
public void destroy() throws Exception {
deleteLBRestCall();
}
}