Elastic Load Balancer

This commit is contained in:
Lili Nader 2010-05-20 01:16:57 -04:00
parent dfdbc44700
commit 596ca233e3
14 changed files with 1562 additions and 0 deletions

View File

@ -0,0 +1,39 @@
/**
*
* Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* 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 org.jclouds.aws.ec2;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import javax.inject.Qualifier;
/**
* Related to a ELB resource.
*
* @author Lili Nader
*
*/
@Retention(value = RetentionPolicy.RUNTIME)
@Target(value = { ElementType.FIELD, ElementType.PARAMETER, ElementType.METHOD })
@Qualifier
public @interface ELB {
}

View File

@ -0,0 +1,46 @@
/**
*
* Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* 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 org.jclouds.aws.ec2.binders;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import javax.inject.Singleton;
import org.jclouds.aws.ec2.util.EC2Utils;
import org.jclouds.http.HttpRequest;
import org.jclouds.rest.Binder;
import org.jclouds.rest.internal.GeneratedHttpRequest;
/**
* Binds the String [] to form parameters named with InstanceId.index
*
* @author Adrian Cole
*/
@Singleton
public class BindELBInstanceIdsToIndexedFormParams implements Binder {
@SuppressWarnings("unchecked")
public void bindToRequest(HttpRequest request, Object input) {
checkArgument(checkNotNull(request, "input") instanceof GeneratedHttpRequest,
"this binder is only valid for GeneratedHttpRequests!");
EC2Utils.indexStringArrayToFormValuesWithStringFormat((GeneratedHttpRequest<?>) request, "Instances.member.%s.InstanceId", input);
}
}

View File

@ -0,0 +1,92 @@
/**
*
* Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* 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 org.jclouds.aws.ec2.compute.strategy;
import java.util.Set;
import javax.annotation.Resource;
import javax.inject.Inject;
import javax.inject.Named;
import javax.inject.Singleton;
import org.jclouds.aws.ec2.EC2Client;
import org.jclouds.aws.ec2.compute.config.EC2ComputeServiceContextModule.GetRegionFromLocation;
import org.jclouds.aws.ec2.domain.AvailabilityZone;
import org.jclouds.aws.ec2.services.ElasticLoadBalancerClient;
import org.jclouds.compute.reference.ComputeServiceConstants;
import org.jclouds.compute.strategy.LoadBalancerStrategy;
import org.jclouds.domain.Location;
import org.jclouds.logging.Logger;
/**
*
* @author Adrian Cole
*/
@Singleton
public class EC2LoadBalancerStrategy implements LoadBalancerStrategy
{
@Resource
@Named(ComputeServiceConstants.COMPUTE_LOGGER)
protected Logger logger = Logger.NULL;
protected final EC2Client ec2Client;
protected final GetRegionFromLocation getRegionFromLocation;
@Inject
protected EC2LoadBalancerStrategy(EC2Client ec2Client, GetRegionFromLocation getRegionFromLocation)
{
this.ec2Client = ec2Client;
this.getRegionFromLocation = getRegionFromLocation;
}
@Override
public String execute(Location location, String name,
String protocol, Integer loadBalancerPort, Integer instancePort,
Set<String> instanceIds)
{
String region = getRegionFromLocation.apply(location);
String dnsName = new String();
// TODO: Fix temp hack
String availabilityZone = new String();
for (String az : AvailabilityZone.zones)
{
if (az.startsWith(region))
availabilityZone = az;
}
ElasticLoadBalancerClient elbClient = ec2Client
.getElasticLoadBalancerServices();
dnsName = elbClient.createLoadBalancer(region, name, protocol,
loadBalancerPort, instancePort, availabilityZone);
Set<String> registeredInstanceIds = elbClient
.registerInstancesWithLoadBalancer(region, name,
(String[]) instanceIds.toArray());
// deregister instances
boolean changed = registeredInstanceIds.removeAll(instanceIds);
if (changed)
elbClient.deregisterInstancesWithLoadBalancer(region, name,
(String[]) registeredInstanceIds.toArray());
return dnsName;
}
}

View File

@ -0,0 +1,525 @@
package org.jclouds.aws.ec2.domain;
import java.util.HashSet;
import java.util.Set;
public class ElasticLoadBalancer implements Comparable<ElasticLoadBalancer>
{
private String region;
private String name;
private Set<String> instanceIds;
private Set<String> availabilityZones;
private String dnsName;
private AppCookieStickinessPolicy appCookieStickinessPolicy;
private LBCookieStickinessPolicy lBCookieStickinessPolicy;
private Set<LoadBalancerListener> loadBalancerListeners;
public ElasticLoadBalancer()
{
super();
this.instanceIds = new HashSet<String>();
this.availabilityZones = new HashSet<String>();
this.loadBalancerListeners = new HashSet<LoadBalancerListener>();
}
public ElasticLoadBalancer(String region, String name,
Set<String> instanceIds, Set<String> availabilityZones,
String dnsName)
{
super();
this.region = region;
this.name = name;
this.instanceIds = instanceIds;
this.availabilityZones = availabilityZones;
this.dnsName = dnsName;
this.loadBalancerListeners = new HashSet<LoadBalancerListener>();
}
public void setRegion(String region)
{
this.region = region;
}
public void setName(String name)
{
this.name = name;
}
public void setInstanceIds(Set<String> instanceIds)
{
this.instanceIds = instanceIds;
}
public void setAvailabilityZones(Set<String> availabilityZones)
{
this.availabilityZones = availabilityZones;
}
public void setDnsName(String dnsName)
{
this.dnsName = dnsName;
}
public void setAppCookieStickinessPolicy(
AppCookieStickinessPolicy appCookieStickinessPolicy)
{
this.appCookieStickinessPolicy = appCookieStickinessPolicy;
}
public void setlBCookieStickinessPolicy(
LBCookieStickinessPolicy lBCookieStickinessPolicy)
{
this.lBCookieStickinessPolicy = lBCookieStickinessPolicy;
}
public void setLoadBalancerListeners(
Set<LoadBalancerListener> loadBalancerListeners)
{
this.loadBalancerListeners = loadBalancerListeners;
}
public String getName()
{
return name;
}
public Set<String> getInstanceIds()
{
return instanceIds;
}
public Set<String> getAvailabilityZones()
{
return availabilityZones;
}
public String getDnsName()
{
return dnsName;
}
public AppCookieStickinessPolicy getAppCookieStickinessPolicy()
{
return appCookieStickinessPolicy;
}
public LBCookieStickinessPolicy getlBCookieStickinessPolicy()
{
return lBCookieStickinessPolicy;
}
public Set<LoadBalancerListener> getLoadBalancerListeners()
{
return loadBalancerListeners;
}
public String getRegion()
{
return region;
}
@Override
public int compareTo(ElasticLoadBalancer that)
{
return name.compareTo(that.name);
}
@Override
public int hashCode()
{
final int prime = 31;
int result = 1;
result = prime
* result
+ ((appCookieStickinessPolicy == null) ? 0
: appCookieStickinessPolicy.hashCode());
result = prime
* result
+ ((availabilityZones == null) ? 0 : availabilityZones
.hashCode());
result = prime * result + ((dnsName == null) ? 0 : dnsName.hashCode());
result = prime * result
+ ((instanceIds == null) ? 0 : instanceIds.hashCode());
result = prime
* result
+ ((lBCookieStickinessPolicy == null) ? 0
: lBCookieStickinessPolicy.hashCode());
result = prime
* result
+ ((loadBalancerListeners == null) ? 0 : loadBalancerListeners
.hashCode());
result = prime * result + ((name == null) ? 0 : name.hashCode());
result = prime * result + ((region == null) ? 0 : region.hashCode());
return result;
}
@Override
public boolean equals(Object obj)
{
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
ElasticLoadBalancer other = (ElasticLoadBalancer) obj;
if (appCookieStickinessPolicy == null)
{
if (other.appCookieStickinessPolicy != null)
return false;
}
else if (!appCookieStickinessPolicy
.equals(other.appCookieStickinessPolicy))
return false;
if (availabilityZones == null)
{
if (other.availabilityZones != null)
return false;
}
else if (!availabilityZones.equals(other.availabilityZones))
return false;
if (dnsName == null)
{
if (other.dnsName != null)
return false;
}
else if (!dnsName.equals(other.dnsName))
return false;
if (instanceIds == null)
{
if (other.instanceIds != null)
return false;
}
else if (!instanceIds.equals(other.instanceIds))
return false;
if (lBCookieStickinessPolicy == null)
{
if (other.lBCookieStickinessPolicy != null)
return false;
}
else if (!lBCookieStickinessPolicy
.equals(other.lBCookieStickinessPolicy))
return false;
if (loadBalancerListeners == null)
{
if (other.loadBalancerListeners != null)
return false;
}
else if (!loadBalancerListeners.equals(other.loadBalancerListeners))
return false;
if (name == null)
{
if (other.name != null)
return false;
}
else if (!name.equals(other.name))
return false;
if (region == null)
{
if (other.region != null)
return false;
}
else if (!region.equals(other.region))
return false;
return true;
}
public static class AppCookieStickinessPolicy
{
private String policyName;
private String cookieName;
public AppCookieStickinessPolicy()
{
super();
}
public AppCookieStickinessPolicy(String policyName, String cookieName)
{
super();
this.policyName = policyName;
this.cookieName = cookieName;
}
public String getPolicyName()
{
return policyName;
}
public String getCookieName()
{
return cookieName;
}
public void setPolicyName(String policyName)
{
this.policyName = policyName;
}
public void setCookieName(String cookieName)
{
this.cookieName = cookieName;
}
@Override
public int hashCode()
{
final int prime = 31;
int result = 1;
result = prime * result
+ ((cookieName == null) ? 0 : cookieName.hashCode());
result = prime * result
+ ((policyName == null) ? 0 : policyName.hashCode());
return result;
}
@Override
public boolean equals(Object obj)
{
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
AppCookieStickinessPolicy other = (AppCookieStickinessPolicy) obj;
if (cookieName == null)
{
if (other.cookieName != null)
return false;
}
else if (!cookieName.equals(other.cookieName))
return false;
if (policyName == null)
{
if (other.policyName != null)
return false;
}
else if (!policyName.equals(other.policyName))
return false;
return true;
}
}
public static class LBCookieStickinessPolicy
{
private String policyName;
private Integer cookieExpirationPeriod;
public LBCookieStickinessPolicy()
{
super();
}
public LBCookieStickinessPolicy(String policyName,
Integer cookieExpirationPeriod)
{
super();
this.policyName = policyName;
this.cookieExpirationPeriod = cookieExpirationPeriod;
}
public String getPolicyName()
{
return policyName;
}
public Integer getCookieExpirationPeriod()
{
return cookieExpirationPeriod;
}
public void setPolicyName(String policyName)
{
this.policyName = policyName;
}
public void setCookieExpirationPeriod(Integer cookieExpirationPeriod)
{
this.cookieExpirationPeriod = cookieExpirationPeriod;
}
@Override
public int hashCode()
{
final int prime = 31;
int result = 1;
result = prime
* result
+ ((cookieExpirationPeriod == null) ? 0
: cookieExpirationPeriod.hashCode());
result = prime * result
+ ((policyName == null) ? 0 : policyName.hashCode());
return result;
}
@Override
public boolean equals(Object obj)
{
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
LBCookieStickinessPolicy other = (LBCookieStickinessPolicy) obj;
if (cookieExpirationPeriod == null)
{
if (other.cookieExpirationPeriod != null)
return false;
}
else if (!cookieExpirationPeriod
.equals(other.cookieExpirationPeriod))
return false;
if (policyName == null)
{
if (other.policyName != null)
return false;
}
else if (!policyName.equals(other.policyName))
return false;
return true;
}
}
public static class LoadBalancerListener
{
private Set<String> policyNames;
private Integer instancePort;
private Integer loadBalancerPort;
private String protocol;
public LoadBalancerListener(Set<String> policyNames,
Integer instancePort, Integer loadBalancerPort, String protocol)
{
super();
this.policyNames = policyNames;
this.instancePort = instancePort;
this.loadBalancerPort = loadBalancerPort;
this.protocol = protocol;
}
public LoadBalancerListener()
{
super();
}
public Set<String> getPolicyNames()
{
return policyNames;
}
public Integer getInstancePort()
{
return instancePort;
}
public Integer getLoadBalancerPort()
{
return loadBalancerPort;
}
public String getProtocol()
{
return protocol;
}
public void setPolicyNames(Set<String> policyNames)
{
this.policyNames = policyNames;
}
public void setInstancePort(Integer instancePort)
{
this.instancePort = instancePort;
}
public void setLoadBalancerPort(Integer loadBalancerPort)
{
this.loadBalancerPort = loadBalancerPort;
}
public void setProtocol(String protocol)
{
this.protocol = protocol;
}
@Override
public int hashCode()
{
final int prime = 31;
int result = 1;
result = prime * result
+ ((instancePort == null) ? 0 : instancePort.hashCode());
result = prime
* result
+ ((loadBalancerPort == null) ? 0 : loadBalancerPort
.hashCode());
result = prime * result
+ ((policyNames == null) ? 0 : policyNames.hashCode());
result = prime * result
+ ((protocol == null) ? 0 : protocol.hashCode());
return result;
}
@Override
public boolean equals(Object obj)
{
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
LoadBalancerListener other = (LoadBalancerListener) obj;
if (instancePort == null)
{
if (other.instancePort != null)
return false;
}
else if (!instancePort.equals(other.instancePort))
return false;
if (loadBalancerPort == null)
{
if (other.loadBalancerPort != null)
return false;
}
else if (!loadBalancerPort.equals(other.loadBalancerPort))
return false;
if (policyNames == null)
{
if (other.policyNames != null)
return false;
}
else if (!policyNames.equals(other.policyNames))
return false;
if (protocol == null)
{
if (other.protocol != null)
return false;
}
else if (!protocol.equals(other.protocol))
return false;
return true;
}
}
}

View File

@ -0,0 +1,50 @@
/**
*
* Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* 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 org.jclouds.aws.ec2.functions;
import java.net.URI;
import java.util.Map;
import javax.inject.Inject;
import javax.inject.Singleton;
import org.jclouds.aws.ec2.ELB;
import com.google.common.base.Function;
/**
*
* @author Adrian Cole
*/
@Singleton
public class ELBRegionToEndpoint implements Function<Object, URI> {
private final Map<String, URI> regionToEndpoint;
private final URI defaultUri;
@Inject
public ELBRegionToEndpoint(@ELB Map<String, URI> regionToEndpoint, @ELB URI defaultUri) {
this.regionToEndpoint = regionToEndpoint;
this.defaultUri = defaultUri;
}
public URI apply(Object from) {
return from == null ? defaultUri : regionToEndpoint.get(from);
}
}

View File

@ -0,0 +1,117 @@
/**
*
* Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* 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 org.jclouds.aws.ec2.services;
import static org.jclouds.aws.ec2.reference.EC2Parameters.ACTION;
import static org.jclouds.aws.ec2.reference.EC2Parameters.VERSION;
import java.util.Set;
import javax.annotation.Nullable;
import javax.ws.rs.FormParam;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import org.jclouds.aws.ec2.binders.BindELBInstanceIdsToIndexedFormParams;
import org.jclouds.aws.ec2.domain.ElasticLoadBalancer;
import org.jclouds.aws.ec2.functions.ELBRegionToEndpoint;
import org.jclouds.aws.ec2.xml.CreateLoadBalancerResponseHandler;
import org.jclouds.aws.ec2.xml.DescribeLoadBalancersResponseHandler;
import org.jclouds.aws.ec2.xml.RegisterInstancesWithLoadBalancerResponseHandler;
import org.jclouds.aws.filters.FormSigner;
import org.jclouds.rest.annotations.BinderParam;
import org.jclouds.rest.annotations.EndpointParam;
import org.jclouds.rest.annotations.FormParams;
import org.jclouds.rest.annotations.RequestFilters;
import org.jclouds.rest.annotations.VirtualHost;
import org.jclouds.rest.annotations.XMLResponseParser;
import com.google.common.util.concurrent.ListenableFuture;
/**
* Provides access to EC2 Elastic Load Balancer via REST API.
* <p/>
*
* @author Lili Nader
*/
@RequestFilters(FormSigner.class)
@FormParams(keys = VERSION, values = "2009-11-25")
@VirtualHost
public interface ElasticLoadBalancerAsyncClient
{
/**
* @see ElasticLoadBalancerClient#createLoadBalancer
*/
@POST
@Path("/")
@XMLResponseParser(CreateLoadBalancerResponseHandler.class)
@FormParams(keys = ACTION, values = "CreateLoadBalancer")
ListenableFuture<String> createLoadBalancer(
@EndpointParam(parser = ELBRegionToEndpoint.class) @Nullable String region,
@FormParam("LoadBalancerName") String name,
@FormParam("Listeners.member.1.Protocol") String protocol,
@FormParam("Listeners.member.1.LoadBalancerPort") Integer loadBalancerPort,
@FormParam("Listeners.member.1.InstancePort") Integer instancePort,
@FormParam("AvailabilityZones.member.1") String availabilityZone);
/**
* @see ElasticLoadBalancerClient#deleteLoadBalancer
*/
@POST
@Path("/")
@FormParams(keys = ACTION, values = "DeleteLoadBalancer")
ListenableFuture<Void> deleteLoadBalancer(
@EndpointParam(parser = ELBRegionToEndpoint.class) @Nullable String region,
@FormParam("LoadBalancerName") String name);
/**
* @see ElasticLoadBalancerClient#registerInstancesWithLoadBalancer
*/
@POST
@Path("/")
@XMLResponseParser(RegisterInstancesWithLoadBalancerResponseHandler.class)
@FormParams(keys = ACTION, values = "RegisterInstancesWithLoadBalancer")
ListenableFuture<? extends Set<String>> registerInstancesWithLoadBalancer(
@EndpointParam(parser = ELBRegionToEndpoint.class) @Nullable String region,
@FormParam("LoadBalancerName") String name,
@BinderParam(BindELBInstanceIdsToIndexedFormParams.class) String... instanceIds);
/**
* @see ElasticLoadBalancerClient#deregisterInstancesWithLoadBalancer
*/
@POST
@Path("/")
@FormParams(keys = ACTION, values = "DeregisterInstancesWithLoadBalancer")
ListenableFuture<Void> deregisterInstancesWithLoadBalancer(
@EndpointParam(parser = ELBRegionToEndpoint.class) @Nullable String region,
@FormParam("LoadBalancerName") String name,
@BinderParam(BindELBInstanceIdsToIndexedFormParams.class) String... instanceIds);
/**
* @see ElasticLoadBalancerClient#describeLoadBalancers
*/
@POST
@Path("/")
@XMLResponseParser(DescribeLoadBalancersResponseHandler.class)
@FormParams(keys = ACTION, values = "DescribeLoadBalancers")
ListenableFuture<? extends Set<ElasticLoadBalancer>> describeLoadBalancers(
@EndpointParam(parser = ELBRegionToEndpoint.class) @Nullable String region,
@FormParam("LoadBalancerName") @Nullable String name);
}

View File

@ -0,0 +1,81 @@
/**
*
* Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* 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 org.jclouds.aws.ec2.services;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import javax.annotation.Nullable;
import org.jclouds.aws.ec2.domain.ElasticLoadBalancer;
import org.jclouds.concurrent.Timeout;
/**
* Provides access to EC2 Elastic Load Balancer via their REST API.
* <p/>
*
* @author Lili Nader
*/
@Timeout(duration = 30, timeUnit = TimeUnit.SECONDS)
public interface ElasticLoadBalancerClient {
/**
* Creates a load balancer
*
* @param name Name of the load balancer
* @param loadBalancerPort Port for the load balancer to listen on
* @param instancePort Port to forward the request to
* @return dns the DNS name for the load balancer
* @see <a href="http://docs.amazonwebservices.com/ElasticLoadBalancing/latest/DeveloperGuide/"
*/
String createLoadBalancer(@Nullable String region, String name, String protocol, Integer loadBalancerPort, Integer instancePort, String availabilityZone);
/**
* Delete load balancer
*
* @param name Name of the load balancer
* @return
* @see <a href="http://docs.amazonwebservices.com/ElasticLoadBalancing/2009-05-15/DeveloperGuide/"
*/
void deleteLoadBalancer(@Nullable String region, String name);
/**
* Register instances with an existing load balancer
* @param name Load Balancer name
* @param instanceIds Set of instance Ids to register with load balancer
* @return instanceIds registered with load balancer
*
* @see <a href="http://docs.amazonwebservices.com/ElasticLoadBalancing/2009-05-15/DeveloperGuide/"
*/
Set<String> registerInstancesWithLoadBalancer(@Nullable String region, String name, String... instanceIds);
/**
* Deregister instances with an existing load balancer
* @param name Load Balancer name
* @param instanceIds Set of instance Ids to deregister with load balancer
* @return
*
* @see <a href="http://docs.amazonwebservices.com/ElasticLoadBalancing/2009-05-15/DeveloperGuide/"
*/
void deregisterInstancesWithLoadBalancer(@Nullable String region, String name, String... instanceIds);
Set<ElasticLoadBalancer> describeLoadBalancers(@Nullable String region, @Nullable String name);
}

View File

@ -0,0 +1,36 @@
package org.jclouds.aws.ec2.xml;
import javax.annotation.Resource;
import org.jclouds.http.functions.ParseSax.HandlerWithResult;
import org.jclouds.logging.Logger;
public class CreateLoadBalancerResponseHandler extends HandlerWithResult<String> {
@Resource
protected Logger logger = Logger.NULL;
private String dnsName;
private StringBuilder currentText = new StringBuilder();
protected String currentOrNull() {
String returnVal = currentText.toString().trim();
return returnVal.equals("") ? null : returnVal;
}
public void endElement(String uri, String name, String qName) {
if (qName.equals("DNSName")) {
dnsName = currentOrNull();
}
currentText = new StringBuilder();
}
public void characters(char ch[], int start, int length) {
currentText.append(ch, start, length);
}
@Override
public String getResult() {
return dnsName;
}
}

View File

@ -0,0 +1,241 @@
package org.jclouds.aws.ec2.xml;
import java.util.Set;
import javax.annotation.Resource;
import javax.inject.Inject;
import org.jclouds.aws.ec2.EC2;
import org.jclouds.aws.ec2.domain.ElasticLoadBalancer;
import org.jclouds.aws.ec2.domain.ElasticLoadBalancer.AppCookieStickinessPolicy;
import org.jclouds.aws.ec2.domain.ElasticLoadBalancer.LBCookieStickinessPolicy;
import org.jclouds.aws.ec2.domain.ElasticLoadBalancer.LoadBalancerListener;
import org.jclouds.aws.ec2.util.EC2Utils;
import org.jclouds.date.DateService;
import org.jclouds.http.functions.ParseSax;
import org.jclouds.logging.Logger;
import org.jclouds.rest.internal.GeneratedHttpRequest;
import org.xml.sax.Attributes;
import com.google.common.collect.Sets;
public class DescribeLoadBalancersResponseHandler extends
ParseSax.HandlerWithResult<Set<ElasticLoadBalancer>>
{
@Inject
public DescribeLoadBalancersResponseHandler(@EC2 String defaultRegion)
{
this.defaultRegion = defaultRegion;
this.listenerHandler = new LoadBalancerListenerHandler();
}
@Inject
protected DateService dateService;
@Resource
protected Logger logger = Logger.NULL;
private Set<ElasticLoadBalancer> contents = Sets
.newLinkedHashSet();
private StringBuilder currentText = new StringBuilder();
private final String defaultRegion;
private final LoadBalancerListenerHandler listenerHandler;
private boolean inListenerDescriptions = false;
private boolean inInstances = false;
private boolean inAppCookieStickinessPolicies = false;
private boolean inLBCookieStickinessPolicies = false;
private boolean inAvailabilityZones = false;
private boolean inLoadBalancerDescriptions = false;
private ElasticLoadBalancer elb;
private AppCookieStickinessPolicy appCookieStickinessPolicy;
private LBCookieStickinessPolicy lBCookieStickinessPolicy;
public void startElement(String uri, String localName, String qName,
Attributes attributes)
{
if (qName.equals("ListenerDescriptions") || inListenerDescriptions)
{
inListenerDescriptions = true;
}
else if (qName.equals("AppCookieStickinessPolicies"))
{
inAppCookieStickinessPolicies = true;
}
else if (qName.equals("LBCookieStickinessPolicies"))
{
inLBCookieStickinessPolicies = true;
}
else if (qName.equals("LoadBalancerDescriptions"))
{
inLoadBalancerDescriptions = true;
}
else if (qName.equals("Instances"))
{
inInstances = true;
}
else if (qName.equals("AvailabilityZones"))
{
inAvailabilityZones = true;
}
if (qName.equals("member"))
{
if (!(inListenerDescriptions || inAppCookieStickinessPolicies || inInstances
|| inLBCookieStickinessPolicies || inAvailabilityZones))
{
elb = new ElasticLoadBalancer();
}
}
}
public void endElement(String uri, String localName, String qName)
{
logger.info(qName);
//if end tag is one of below then set inXYZ to false
if (qName.equals("ListenerDescriptions"))
{
inListenerDescriptions = false;
}
else if (qName.equals("AppCookieStickinessPolicies"))
{
inAppCookieStickinessPolicies = false;
}
else if (qName.equals("LBCookieStickinessPolicies"))
{
inLBCookieStickinessPolicies = false;
}
else if (qName.equals("LoadBalancerDescriptions"))
{
inLoadBalancerDescriptions = false;
}
else if (qName.equals("Instances"))
{
inInstances = false;
}
else if (qName.equals("AvailabilityZones"))
{
inAvailabilityZones = false;
}
if (qName.equals("DNSName"))
{
elb.setDnsName(currentText.toString().trim());
}
else if (qName.equals("LoadBalancerName"))
{
elb.setName(currentText.toString().trim());
}
else if (qName.equals("InstanceId"))
{
elb.getInstanceIds().add(currentText.toString().trim());
}
else if (qName.equals("member"))
{
if (inAvailabilityZones)
{
elb.getAvailabilityZones().add(currentText.toString().trim());
}
else if (!(inListenerDescriptions || inAppCookieStickinessPolicies || inInstances
|| inLBCookieStickinessPolicies || inAvailabilityZones))
{
try
{
String region = EC2Utils.findRegionInArgsOrNull(request);
if (region == null)
region = defaultRegion;
elb.setRegion(region);
contents.add(elb);
}
catch (NullPointerException e)
{
logger.warn(e, "malformed load balancer: %s", localName);
}
this.elb = null;
}
}
currentText = new StringBuilder();
}
@Override
public Set<ElasticLoadBalancer> getResult()
{
return contents;
}
public void characters(char ch[], int start, int length)
{
currentText.append(ch, start, length);
}
@Override
public void setContext(GeneratedHttpRequest<?> request) {
listenerHandler.setContext(request);
super.setContext(request);
}
public class LoadBalancerListenerHandler extends
ParseSax.HandlerWithResult<Set<LoadBalancerListener>>
{
private Set<LoadBalancerListener> listeners = Sets.newHashSet();
private StringBuilder currentText = new StringBuilder();
private LoadBalancerListener listener;
public void startElement(String uri, String name, String qName,
Attributes attrs)
{
if (qName.equals("member"))
{
listener = new LoadBalancerListener();
}
}
public void endElement(String uri, String name, String qName)
{
if (qName.equals("Protocol"))
{
listener.setProtocol(currentText.toString().trim());
}
else if (qName.equals("LoadBalancerPort"))
{
listener.setLoadBalancerPort(Integer.parseInt(currentText
.toString().trim()));
}
else if (qName.equals("InstancePort"))
{
listener.setInstancePort(Integer.parseInt(currentText
.toString().trim()));
}
else if (qName.equals("member"))
{
listeners.add(listener);
}
currentText = new StringBuilder();
}
@Override
public Set<LoadBalancerListener> getResult()
{
return listeners;
}
public void characters(char ch[], int start, int length)
{
currentText.append(ch, start, length);
}
}
}

View File

@ -0,0 +1,44 @@
package org.jclouds.aws.ec2.xml;
import java.util.Set;
import javax.annotation.Resource;
import javax.inject.Inject;
import org.jclouds.http.functions.ParseSax;
import org.jclouds.logging.Logger;
import com.google.common.collect.Sets;
public class RegisterInstancesWithLoadBalancerResponseHandler extends
ParseSax.HandlerWithResult<Set<String>>
{
@Inject
public RegisterInstancesWithLoadBalancerResponseHandler()
{
}
@Resource
protected Logger logger = Logger.NULL;
private Set<String> instanceIds = Sets.newLinkedHashSet();
private StringBuilder currentText = new StringBuilder();
public void endElement(String uri, String localName, String qName)
{
if(qName.equals("InstanceId"))
instanceIds.add(currentText.toString().trim());
}
@Override
public Set<String> getResult()
{
return instanceIds;
}
public void characters(char ch[], int start, int length)
{
currentText.append(ch, start, length);
}
}

View File

@ -0,0 +1,109 @@
/**
*
* Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* 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 org.jclouds.aws.ec2.services;
import static com.google.common.base.Preconditions.checkNotNull;
import static org.testng.Assert.assertNotNull;
import java.util.Set;
import org.jclouds.aws.domain.Region;
import org.jclouds.aws.ec2.EC2AsyncClient;
import org.jclouds.aws.ec2.EC2Client;
import org.jclouds.aws.ec2.EC2ContextFactory;
import org.jclouds.aws.ec2.domain.AvailabilityZone;
import org.jclouds.aws.ec2.domain.ElasticLoadBalancer;
import org.jclouds.logging.log4j.config.Log4JLoggingModule;
import org.jclouds.rest.RestContext;
import org.testng.annotations.AfterTest;
import org.testng.annotations.BeforeGroups;
import org.testng.annotations.Test;
import com.google.common.collect.ImmutableSet;
/**
* Tests behavior of {@code ElasticIPAddressClient}
*
* @author Lili Nader
*/
@Test(groups = "live", sequential = true, testName = "ec2.ElasticLoadBalancerClientLiveTest")
public class ElasticLoadBalancerClientLiveTest
{
private ElasticLoadBalancerClient client;
private RestContext<EC2AsyncClient, EC2Client> context;
@BeforeGroups(groups = { "live" })
public void setupClient()
{
String user = checkNotNull(System.getProperty("jclouds.test.user"),
"jclouds.test.user");
String password = checkNotNull(System.getProperty("jclouds.test.key"),
"jclouds.test.key");
context = EC2ContextFactory.createContext(user, password,
new Log4JLoggingModule()).getProviderSpecificContext();
client = context.getApi().getElasticLoadBalancerServices();
}
@Test
void testCreateLoadBalancer()
{
String name = "TestLoadBalancer";
for (String region : ImmutableSet.of(Region.US_EAST_1))
{
String dnsName = client.createLoadBalancer(region, name, "http",
80, 80, AvailabilityZone.US_EAST_1A);
assertNotNull(dnsName);
assert (dnsName.startsWith(name));
}
}
@Test
void testDescribeLoadBalancers()
{
String name = "TestDescribeLoadBalancer";
for (String region : ImmutableSet.of(Region.US_EAST_1))
{
client.createLoadBalancer(region, name, "http",
80, 80, AvailabilityZone.US_EAST_1A);
Set<ElasticLoadBalancer> allResults = client.describeLoadBalancers(
region, name);
assertNotNull(allResults);
assert (allResults.size() >= 1);
client.deleteLoadBalancer(region, name);
}
}
@Test
void testDeleteLoadBalancer()
{
for (String region : ImmutableSet.of(Region.US_EAST_1))
{
client.deleteLoadBalancer(region, "TestLoadBalancer");
}
}
@AfterTest
public void shutdown()
{
context.close();
}
}

View File

@ -0,0 +1,81 @@
/**
*
* Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* 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 org.jclouds.aws.ec2.xml;
import static org.easymock.EasyMock.expect;
import static org.easymock.classextension.EasyMock.createMock;
import static org.easymock.classextension.EasyMock.replay;
import static org.testng.Assert.assertEquals;
import java.io.InputStream;
import java.util.Date;
import java.util.Set;
import org.jclouds.aws.domain.Region;
import org.jclouds.aws.ec2.domain.AvailabilityZone;
import org.jclouds.aws.ec2.domain.ElasticLoadBalancer;
import org.jclouds.aws.ec2.domain.Image;
import org.jclouds.aws.ec2.domain.ElasticLoadBalancer.AppCookieStickinessPolicy;
import org.jclouds.aws.ec2.domain.ElasticLoadBalancer.LBCookieStickinessPolicy;
import org.jclouds.aws.ec2.domain.ElasticLoadBalancer.LoadBalancerListener;
import org.jclouds.http.functions.ParseSax;
import org.jclouds.rest.internal.GeneratedHttpRequest;
import org.testng.annotations.Test;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Sets;
/**
* Tests behavior of {@code DescribeLoadBalancersResponseHandler}
*
* @author Adrian Cole
*/
@Test(groups = "unit", testName = "ec2.DescribeLoadBalancersResponseHandlerTest")
public class DescribeLoadBalancerResponseHandlerTest extends BaseEC2HandlerTest {
public void testParse() {
InputStream is = getClass().getResourceAsStream("/ec2/describe_loadbalancers.xml");
Set<ElasticLoadBalancer> contents = Sets.newHashSet();
ElasticLoadBalancer dummy = new ElasticLoadBalancer(defaultRegion, "my-load-balancer",
ImmutableSet.of("i-5b33e630", "i-8f26d7e4", "i-5933e632"), ImmutableSet.of("us-east-1a"),
"my-load-balancer-1400212309.us-east-1.elb.amazonaws.com");
contents.add(dummy);
Set<ElasticLoadBalancer> result = parseLoadBalancers(is);
assertEquals(result, contents);
}
private Set<ElasticLoadBalancer> parseLoadBalancers(InputStream is) {
DescribeLoadBalancersResponseHandler handler = injector
.getInstance(DescribeLoadBalancersResponseHandler.class);
addDefaultRegionToHandler(handler);
Set<ElasticLoadBalancer> result = factory.create(handler).parse(is);
return result;
}
private void addDefaultRegionToHandler(ParseSax.HandlerWithResult<?> handler) {
GeneratedHttpRequest<?> request = createMock(GeneratedHttpRequest.class);
expect(request.getArgs()).andReturn(new Object[] { null });
replay(request);
handler.setContext(request);
}
}

View File

@ -0,0 +1,63 @@
<DescribeLoadBalancersResponse
xmlns="http://elasticloadbalancing.amazonaws.com/doc/2009-11-25/">
<DescribeLoadBalancersResult>
<LoadBalancerDescriptions>
<member>
<LoadBalancerName>my-load-balancer</LoadBalancerName>
<CreatedTime>2010-03-03T20:54:45.110Z</CreatedTime>
<DNSName>my-load-balancer-1400212309.us-east-1.elb.amazonaws.com</DNSName>
<HealthCheck>
<Interval>300</Interval>
<Target>HTTP:80/index.html</Target>
<HealthyThreshold>3</HealthyThreshold>
<Timeout>30</Timeout>
<UnhealthyThreshold>5</UnhealthyThreshold>
</HealthCheck>
<ListenerDescriptions>
<member>
<PolicyNames />
<Listener>
<Protocol>HTTP</Protocol>
<LoadBalancerPort>80</LoadBalancerPort>
<InstancePort>80</InstancePort>
</Listener>
</member>
<member>
<PolicyNames />
<Listener>
<Protocol>TCP</Protocol>
<LoadBalancerPort>443</LoadBalancerPort>
<InstancePort>443</InstancePort>
</Listener>
</member>
</ListenerDescriptions>
<Instances>
<member>
<InstanceId>i-5b33e630</InstanceId>
</member>
<member>
<InstanceId>i-8f26d7e4</InstanceId>
</member>
<member>
<InstanceId>i-5933e632</InstanceId>
</member>
</Instances>
<Policies>
<AppCookieStickinessPolicies>
<member>
<CookieName>MyCookie</CookieName>
<PolicyName>MyLoadBalancerPolicy</PolicyName>
</member>
</AppCookieStickinessPolicies>
<LBCookieStickinessPolicies />
</Policies>
<AvailabilityZones>
<member>us-east-1a</member>
</AvailabilityZones>
</member>
</LoadBalancerDescriptions>
</DescribeLoadBalancersResult>
<ResponseMetadata>
<RequestId>10e2b9c9-3899-11df-a1e2-b5349194c035</RequestId>
</ResponseMetadata>
</DescribeLoadBalancersResponse>

View File

@ -0,0 +1,38 @@
/**
*
* Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* 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 org.jclouds.compute.strategy;
import java.util.Set;
import org.jclouds.domain.Location;
/**
* Creates a load balancer for nodes listed
*
* @author Lili Nader
*/
public interface LoadBalancerStrategy
{
String execute(Location loaction, String name, String protocol,
Integer loadBalancerPort, Integer instancePort,
Set<String> instanceIds);
}