// // typica - A client library for Amazon Web Services // Copyright (C) 2007,2008,2009 Xerox Corporation // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // package com.xerox.amazonws.ec2; import java.io.IOException; import java.net.MalformedURLException; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import javax.xml.bind.JAXBException; import org.xml.sax.SAXException; import org.apache.http.HttpException; import org.apache.http.client.methods.HttpRequestBase; import org.apache.http.client.methods.HttpGet; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import com.xerox.amazonws.common.AWSException; import com.xerox.amazonws.common.AWSQueryConnection; import com.xerox.amazonws.typica.loadbalance.jaxb.EnableAvailabilityZonesForLoadBalancerResponse; import com.xerox.amazonws.typica.loadbalance.jaxb.ConfigureHealthCheckResponse; import com.xerox.amazonws.typica.loadbalance.jaxb.CreateLoadBalancerResponse; import com.xerox.amazonws.typica.loadbalance.jaxb.DeleteLoadBalancerResponse; import com.xerox.amazonws.typica.loadbalance.jaxb.DeregisterInstancesFromLoadBalancerResponse; import com.xerox.amazonws.typica.loadbalance.jaxb.DescribeLoadBalancersResponse; import com.xerox.amazonws.typica.loadbalance.jaxb.DescribeInstanceHealthResponse; import com.xerox.amazonws.typica.loadbalance.jaxb.RegisterInstancesWithLoadBalancerResponse; import com.xerox.amazonws.typica.loadbalance.jaxb.DisableAvailabilityZonesForLoadBalancerResponse; /** * A Java wrapper for the EC2 web services API */ public class LoadBalancing extends AWSQueryConnection { private static Log logger = LogFactory.getLog(LoadBalancing.class); /** * Initializes the ec2 service with your AWS login information. * * @param awsAccessId The your user key into AWS * @param awsSecretKey The secret string used to generate signatures for authentication. */ public LoadBalancing(String awsAccessId, String awsSecretKey) { this(awsAccessId, awsSecretKey, true); } /** * Initializes the ec2 service with your AWS login information. * * @param awsAccessId The your user key into AWS * @param awsSecretKey The secret string used to generate signatures for authentication. * @param isSecure True if the data should be encrypted on the wire on the way to or from EC2. */ public LoadBalancing(String awsAccessId, String awsSecretKey, boolean isSecure) { this(awsAccessId, awsSecretKey, isSecure, "elasticloadbalancing.amazonaws.com"); } /** * Initializes the ec2 service with your AWS login information. * * @param awsAccessId The your user key into AWS * @param awsSecretKey The secret string used to generate signatures for authentication. * @param isSecure True if the data should be encrypted on the wire on the way to or from EC2. * @param server Which host to connect to. Usually, this will be elasticloadbalancing.amazonaws.com */ public LoadBalancing(String awsAccessId, String awsSecretKey, boolean isSecure, String server) { this(awsAccessId, awsSecretKey, isSecure, server, isSecure ? 443 : 80); } /** * Initializes the ec2 service with your AWS login information. * * @param awsAccessId The your user key into AWS * @param awsSecretKey The secret string used to generate signatures for authentication. * @param isSecure True if the data should be encrypted on the wire on the way to or from EC2. * @param server Which host to connect to. Usually, this will be elasticloadbalancing.amazonaws.com * @param port Which port to use. */ public LoadBalancing(String awsAccessId, String awsSecretKey, boolean isSecure, String server, int port) { super(awsAccessId, awsSecretKey, isSecure, server, port); ArrayList<String> vals = new ArrayList<String>(); vals.add("2009-05-15"); super.headers.put("Version", vals); } /** * Add availability zones. * * @param loadBalancerName the name of the load balancer * @param availabilityZones a list of availability zones to add * @throws LoadBalancingException wraps checked exceptions */ public List<String> enableAvailabilityZonesForLoadBalancer(String loadBalancerName, List<String> availabilityZones) throws LoadBalancingException { Map<String, String> params = new HashMap<String, String>(); params.put("LoadBalancerName", loadBalancerName); int i=0; for (String zone : availabilityZones) { params.put("AvailabilityZones.member."+(i+1), zone); i++; } HttpGet method = new HttpGet(); EnableAvailabilityZonesForLoadBalancerResponse response = makeRequestInt(method, "EnableAvailabilityZonesForLoadBalancer", params, EnableAvailabilityZonesForLoadBalancerResponse.class); return response.getEnableAvailabilityZonesForLoadBalancerResult().getAvailabilityZones().getMembers(); } /** * Create load balancer. * * @param loadBalancerName the name of the load balancer * @param listeners the definition of protocol and ports * @param availabilityZones a list of availability zones * @return dns the DNS name for the load balancer * @throws LoadBalancingException wraps checked exceptions */ public String createLoadBalancer(String loadBalancerName, List<Listener> listeners, List<String> availabilityZones) throws LoadBalancingException { Map<String, String> params = new HashMap<String, String>(); params.put("LoadBalancerName", loadBalancerName); int i=1; for (Listener l : listeners) { params.put("Listeners.member."+i+".Protocol", l.getProtocol()); params.put("Listeners.member."+i+".LoadBalancerPort", ""+l.getLoadBalancerPort()); params.put("Listeners.member."+i+".InstancePort", ""+l.getInstancePort()); } i=1; for (String zone : availabilityZones) { params.put("AvailabilityZones.member."+i, zone); i++; } HttpGet method = new HttpGet(); CreateLoadBalancerResponse response = makeRequestInt(method, "CreateLoadBalancer", params, CreateLoadBalancerResponse.class); return response.getCreateLoadBalancerResult().getDNSName(); } /** * Configure health check. * * @param loadBalancerName the name of the load balancer * @param healthCheck the details of the healthcheck * @throws LoadBalancingException wraps checked exceptions */ public HealthCheck configureHealthCheck(String loadBalancerName, HealthCheck healthCheck) throws LoadBalancingException { Map<String, String> params = new HashMap<String, String>(); params.put("LoadBalancerName", loadBalancerName); params.put("HealthCheck.Target", ""+healthCheck.getTarget()); params.put("HealthCheck.Interval", ""+healthCheck.getInterval()); params.put("HealthCheck.Timeout", ""+healthCheck.getTimeout()); params.put("HealthCheck.UnhealthyThreshold", ""+healthCheck.getUnhealthyThreshold()); params.put("HealthCheck.HealthyThreshold", ""+healthCheck.getHealthyThreshold()); HttpGet method = new HttpGet(); ConfigureHealthCheckResponse response = makeRequestInt(method, "ConfigureHealthCheck", params, ConfigureHealthCheckResponse.class); com.xerox.amazonws.typica.loadbalance.jaxb.HealthCheck hc = response.getConfigureHealthCheckResult().getHealthCheck(); return new HealthCheck(hc.getTarget(), hc.getInterval().intValue(), hc.getTimeout().intValue(), hc.getUnhealthyThreshold().intValue(), hc.getHealthyThreshold().intValue()); } /** * Delete load balancer. * * @param loadBalancerName the name of the load balancer * @throws LoadBalancingException wraps checked exceptions */ public void deleteLoadBalancer(String loadBalancerName) throws LoadBalancingException { Map<String, String> params = new HashMap<String, String>(); params.put("LoadBalancerName", loadBalancerName); HttpGet method = new HttpGet(); // DeleteLoadBalancerResponse response = makeRequestInt(method, "DeleteLoadBalancer", params, DeleteLoadBalancerResponse.class); } /** * Deregister instances from load balancer. * * @param loadBalancerName the name of the load balancer * @param instances a list of instances to deregister from the load balancer * @return the updated list of instances registered with the load balancer * @throws LoadBalancingException wraps checked exceptions */ public List<String> deregisterInstancesFromLoadBalancer(String loadBalancerName, List<String> instances) throws LoadBalancingException { Map<String, String> params = new HashMap<String, String>(); params.put("LoadBalancerName", loadBalancerName); int i=1; for (String inst : instances) { params.put("Instances.member."+i+".InstanceId", inst); i++; } HttpGet method = new HttpGet(); DeregisterInstancesFromLoadBalancerResponse response = makeRequestInt(method, "DeregisterInstancesFromLoadBalancer", params, DeregisterInstancesFromLoadBalancerResponse.class); List<com.xerox.amazonws.typica.loadbalance.jaxb.Instance> instList = response.getDeregisterInstancesFromLoadBalancerResult().getInstances().getMembers(); List<String> ret = new ArrayList<String>(); for (com.xerox.amazonws.typica.loadbalance.jaxb.Instance inst : instList) { ret.add(inst.getInstanceId()); } return ret; } /** * Describe all load balancers. * * @throws LoadBalancingException wraps checked exceptions */ public List<LoadBalancer> describeLoadBalancers() throws LoadBalancingException { return describeLoadBalancers(null); } /** * Describe load balancers. * * @param loadBalancerNames a list of load balancers to describe * @throws LoadBalancingException wraps checked exceptions */ public List<LoadBalancer> describeLoadBalancers(List<String> loadBalancerNames) throws LoadBalancingException { Map<String, String> params = new HashMap<String, String>(); if (loadBalancerNames != null && loadBalancerNames.size() > 0) { int i = 0; for (String name : loadBalancerNames) { params.put("LoadBalancerNames.member."+(i+1), name); i++; } } HttpGet method = new HttpGet(); DescribeLoadBalancersResponse response = makeRequestInt(method, "DescribeLoadBalancers", params, DescribeLoadBalancersResponse.class); List<com.xerox.amazonws.typica.loadbalance.jaxb.LoadBalancerDescription> result = response.getDescribeLoadBalancersResult().getLoadBalancerDescriptions().getMembers(); List<LoadBalancer> ret = new ArrayList<LoadBalancer>(); for (com.xerox.amazonws.typica.loadbalance.jaxb.LoadBalancerDescription lb : result) { List<com.xerox.amazonws.typica.loadbalance.jaxb.Instance> instList = lb.getInstances().getMembers(); List<String> instances = new ArrayList<String>(); for (com.xerox.amazonws.typica.loadbalance.jaxb.Instance inst : instList) { instances.add(inst.getInstanceId()); } List<com.xerox.amazonws.typica.loadbalance.jaxb.Listener> listenerList = lb.getListeners().getMembers(); List<Listener> listeners = new ArrayList<Listener>(); for (com.xerox.amazonws.typica.loadbalance.jaxb.Listener listnr : listenerList) { listeners.add(new Listener(listnr.getProtocol(), listnr.getLoadBalancerPort().intValue(), listnr.getInstancePort().intValue())); } com.xerox.amazonws.typica.loadbalance.jaxb.HealthCheck hc = lb.getHealthCheck(); HealthCheck healthCheck = new HealthCheck(hc.getTarget(), hc.getInterval().intValue(), hc.getTimeout().intValue(), hc.getUnhealthyThreshold().intValue(), hc.getHealthyThreshold().intValue()); LoadBalancer newPoint = new LoadBalancer(lb.getLoadBalancerName(), lb.getDNSName(), listeners, lb.getAvailabilityZones().getMembers(), instances, healthCheck, lb.getCreatedTime().toGregorianCalendar()); ret.add(newPoint); } return ret; } /** * Describe the current state of the instances registered with the load balancer. * * @param loadBalancerName the name of the load balancer * @throws LoadBalancingException wraps checked exceptions */ public List<InstanceState> describeInstanceHealth(String loadBalancerName) throws LoadBalancingException { return describeInstanceHealth(loadBalancerName, null); } /** * Describe the current state of the instances specified * * @param loadBalancerName the name of the load balancer * @param instances a list of instances to describe (null for all) * @throws LoadBalancingException wraps checked exceptions */ public List<InstanceState> describeInstanceHealth(String loadBalancerName, List<String> instances) throws LoadBalancingException { Map<String, String> params = new HashMap<String, String>(); params.put("LoadBalancerName", loadBalancerName); if (instances != null && instances.size() > 0) { int i = 1; for (String name : instances) { params.put("Instances.member."+i+".InstanceId", name); i++; } } HttpGet method = new HttpGet(); DescribeInstanceHealthResponse response = makeRequestInt(method, "DescribeInstanceHealth", params, DescribeInstanceHealthResponse.class); List<com.xerox.amazonws.typica.loadbalance.jaxb.InstanceState> result = response.getDescribeInstanceHealthResult().getInstanceStates().getMembers(); List<InstanceState> ret = new ArrayList<InstanceState>(); for (com.xerox.amazonws.typica.loadbalance.jaxb.InstanceState state : result) { InstanceState newState = new InstanceState(state.getInstanceId(), state.getState(), state.getReasonCode(), state.getDescription()); ret.add(newState); } return ret; } /** * Register instance(s) with a load balancer. * * @param loadBalancerName the name of the load balancer * @param instances a list of instance IDs registered with the load balancer * @throws LoadBalancingException wraps checked exceptions */ public List<String> registerInstancesWithLoadBalancer(String loadBalancerName, List<String> instances) throws LoadBalancingException { Map<String, String> params = new HashMap<String, String>(); params.put("LoadBalancerName", loadBalancerName); int i=1; for (String inst : instances) { params.put("Instances.member."+i+".InstanceId", inst); i++; } HttpGet method = new HttpGet(); RegisterInstancesWithLoadBalancerResponse response = makeRequestInt(method, "RegisterInstancesWithLoadBalancer", params, RegisterInstancesWithLoadBalancerResponse.class); List<com.xerox.amazonws.typica.loadbalance.jaxb.Instance> instList = response.getRegisterInstancesWithLoadBalancerResult().getInstances().getMembers(); List<String> ret = new ArrayList<String>(); for (com.xerox.amazonws.typica.loadbalance.jaxb.Instance inst : instList) { ret.add(inst.getInstanceId()); } return ret; } /** * Disable availability zones. * * @param loadBalancerName the name of the load balancer * @param availabilityZones a list of availability zones to disable * @throws LoadBalancingException wraps checked exceptions */ public List<String> disableAvailabilityZonesForLoadBalancer(String loadBalancerName, List<String> availabilityZones) throws LoadBalancingException { Map<String, String> params = new HashMap<String, String>(); params.put("LoadBalancerName", loadBalancerName); int i=0; for (String zone : availabilityZones) { params.put("AvailabilityZones.member."+(i+1), zone); i++; } HttpGet method = new HttpGet(); DisableAvailabilityZonesForLoadBalancerResponse response = makeRequestInt(method, "DisableAvailabilityZonesForLoadBalancer", params, DisableAvailabilityZonesForLoadBalancerResponse.class); return response.getDisableAvailabilityZonesForLoadBalancerResult().getAvailabilityZones().getMembers(); } protected <T> T makeRequestInt(HttpRequestBase method, String action, Map<String, String> params, Class<T> respType) throws LoadBalancingException { try { return makeRequest(method, action, params, respType); } catch (AWSException ex) { throw new LoadBalancingException(ex); } catch (JAXBException ex) { throw new LoadBalancingException("Problem parsing returned message.", ex); } catch (SAXException ex) { throw new LoadBalancingException("Problem parsing returned message.", ex); } catch (MalformedURLException ex) { throw new LoadBalancingException(ex.getMessage(), ex); } catch (IOException ex) { throw new LoadBalancingException(ex.getMessage(), ex); } catch (HttpException ex) { throw new LoadBalancingException(ex.getMessage(), ex); } } }