Load Balancer ComputeService API

This commit is contained in:
Lili Nader 2010-05-20 18:38:23 -04:00
parent d3690c44f2
commit 0d1d28a972
10 changed files with 263 additions and 10 deletions

View File

@ -18,8 +18,11 @@
*/
package org.jclouds.aws.ec2.compute;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import static org.jclouds.util.Utils.checkNotEmpty;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.Map.Entry;
@ -44,15 +47,19 @@ import org.jclouds.compute.domain.Size;
import org.jclouds.compute.domain.TemplateBuilder;
import org.jclouds.compute.internal.BaseComputeService;
import org.jclouds.compute.options.TemplateOptions;
import org.jclouds.compute.predicates.NodePredicates;
import org.jclouds.compute.strategy.DestroyNodeStrategy;
import org.jclouds.compute.strategy.GetNodeMetadataStrategy;
import org.jclouds.compute.strategy.ListNodesStrategy;
import org.jclouds.compute.strategy.LoadBalancerStrategy;
import org.jclouds.compute.strategy.RebootNodeStrategy;
import org.jclouds.compute.strategy.RunNodesAndAddToSetStrategy;
import org.jclouds.compute.util.ComputeUtils;
import org.jclouds.domain.Location;
import com.google.common.base.Predicate;
import com.google.common.base.Predicates;
import com.google.common.collect.Iterables;
import com.google.common.collect.Maps;
/**
@ -72,6 +79,7 @@ public class EC2ComputeService extends BaseComputeService {
GetNodeMetadataStrategy getNodeMetadataStrategy,
RunNodesAndAddToSetStrategy runNodesAndAddToSetStrategy,
RebootNodeStrategy rebootNodeStrategy, DestroyNodeStrategy destroyNodeStrategy,
LoadBalancerStrategy loadBalancerStrategy,
Provider<TemplateBuilder> templateBuilderProvider,
Provider<TemplateOptions> templateOptionsProvider, ComputeUtils utils,
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService executor, EC2Client ec2Client,
@ -79,7 +87,7 @@ public class EC2ComputeService extends BaseComputeService {
Map<RegionAndName, KeyPair> credentialsMap, Map<RegionAndName, String> securityGroupMap) {
super(context, images, sizes, locations, listNodesStrategy, getNodeMetadataStrategy,
runNodesAndAddToSetStrategy, rebootNodeStrategy, destroyNodeStrategy,
templateBuilderProvider, templateOptionsProvider, utils, executor);
loadBalancerStrategy, templateBuilderProvider, templateOptionsProvider, utils, executor);
this.ec2Client = ec2Client;
this.getRegionFromLocation = getRegionFromLocation;
this.credentialsMap = credentialsMap;
@ -128,9 +136,57 @@ public class EC2ComputeService extends BaseComputeService {
deleteSecurityGroup(regionTag.getKey(), regionTag.getValue());
}
return deadOnes;
}
/**
}
@Override
public String loadBalanceNodesMatching(String loadBalancerName,
String protocol, Integer loadBalancerPort, Integer instancePort,
Predicate<NodeMetadata> filter)
{
checkNotNull(loadBalancerName, "loadBalancerName");
checkNotNull(protocol, "protocol");
checkArgument(protocol.toUpperCase().equals("HTTP")
|| protocol.toUpperCase().equals("TCP"),
"Acceptable values for protocol are HTTP or TCP");
checkNotNull(loadBalancerPort, "loadBalancerPort");
checkNotNull(instancePort, "instancePort");
Location location = null;
Set<String> ids = new HashSet<String>();
for (final NodeMetadata node : Iterables.filter(super
.listNodesDetailsMatching(NodePredicates.all()), Predicates
.and(filter, Predicates.not(NodePredicates.TERMINATED))))
{
ids.add(node.getId());
location = node.getLocation();
}
logger.debug(">> creating load balancer (%s)", loadBalancerName);
String dnsName = loadBalancerStrategy
.execute(location, loadBalancerName, protocol,
loadBalancerPort, instancePort, ids);
logger.debug("<< created load balancer (%s) DNS (%s)",
loadBalancerName, dnsName);
return dnsName;
}
@Override
public void deleteLoadBalancer(String loadBalancerName,
Predicate<NodeMetadata> filter)
{
Location location = Iterables.filter(
super.listNodesDetailsMatching(NodePredicates.all()),
Predicates.and(filter, Predicates
.not(NodePredicates.TERMINATED))).iterator().next()
.getLocation();
ec2Client.getElasticLoadBalancerServices().deleteLoadBalancer(
getRegionFromLocation.apply(location), loadBalancerName);
}
/**
* returns template options, except of type {@link EC2TemplateOptions}.
*/
@Override

View File

@ -55,6 +55,7 @@ import org.jclouds.aws.ec2.compute.functions.RunningInstanceToNodeMetadata;
import org.jclouds.aws.ec2.compute.internal.EC2TemplateBuilderImpl;
import org.jclouds.aws.ec2.compute.options.EC2TemplateOptions;
import org.jclouds.aws.ec2.compute.strategy.EC2DestroyNodeStrategy;
import org.jclouds.aws.ec2.compute.strategy.EC2LoadBalancerStrategy;
import org.jclouds.aws.ec2.compute.strategy.EC2RunNodesAndAddToSetStrategy;
import org.jclouds.aws.ec2.config.EC2ContextModule;
import org.jclouds.aws.ec2.domain.KeyPair;
@ -79,6 +80,7 @@ import org.jclouds.compute.reference.ComputeServiceConstants;
import org.jclouds.compute.strategy.DestroyNodeStrategy;
import org.jclouds.compute.strategy.GetNodeMetadataStrategy;
import org.jclouds.compute.strategy.ListNodesStrategy;
import org.jclouds.compute.strategy.LoadBalancerStrategy;
import org.jclouds.compute.strategy.RebootNodeStrategy;
import org.jclouds.compute.strategy.RunNodesAndAddToSetStrategy;
import org.jclouds.concurrent.ConcurrentUtils;
@ -129,6 +131,7 @@ public class EC2ComputeServiceContextModule extends EC2ContextModule {
bind(GetNodeMetadataStrategy.class).to(EC2GetNodeMetadataStrategy.class);
bind(RebootNodeStrategy.class).to(EC2RebootNodeStrategy.class);
bind(DestroyNodeStrategy.class).to(EC2DestroyNodeStrategy.class);
bind(LoadBalancerStrategy.class).to(EC2LoadBalancerStrategy.class);
bind(new TypeLiteral<Function<RunningInstance, Map<String, String>>>() {
}).annotatedWith(Jsr330.named("volumeMapping")).to(RunningInstanceToStorageMappingUnix.class)
.in(Scopes.SINGLETON);

View File

@ -19,6 +19,8 @@
package org.jclouds.aws.ec2.compute.strategy;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import javax.annotation.Resource;
@ -77,15 +79,31 @@ public class EC2LoadBalancerStrategy implements LoadBalancerStrategy
dnsName = elbClient.createLoadBalancer(region, name, protocol,
loadBalancerPort, instancePort, availabilityZone);
List<String> instanceIdlist = new ArrayList<String>(instanceIds);
String[] instanceIdArray = new String[instanceIdlist.size()];
for(int i=0; i<instanceIdlist.size(); i++)
{
instanceIdArray[i] = instanceIdlist.get(i);
}
Set<String> registeredInstanceIds = elbClient
.registerInstancesWithLoadBalancer(region, name,
(String[]) instanceIds.toArray());
instanceIdArray);
// deregister instances
boolean changed = registeredInstanceIds.removeAll(instanceIds);
if (changed)
elbClient.deregisterInstancesWithLoadBalancer(region, name,
(String[]) registeredInstanceIds.toArray());
{
List<String> list = new ArrayList<String>(registeredInstanceIds);
instanceIdArray = new String[list.size()];
for(int i=0; i<list.size(); i++)
{
instanceIdArray[i] = list.get(i);
}
if(instanceIdArray.length>0)
elbClient.deregisterInstancesWithLoadBalancer(region, name,
instanceIdArray);
}
return dnsName;
}

View File

@ -97,7 +97,7 @@ public interface ElasticLoadBalancerAsyncClient
*/
@POST
@Path("/")
@FormParams(keys = ACTION, values = "DeregisterInstancesWithLoadBalancer")
@FormParams(keys = ACTION, values = "DeregisterInstancesFromLoadBalancer")
ListenableFuture<Void> deregisterInstancesWithLoadBalancer(
@EndpointParam(parser = ELBRegionToEndpoint.class) @Nullable String region,
@FormParam("LoadBalancerName") String name,

View File

@ -30,6 +30,8 @@ public class RegisterInstancesWithLoadBalancerResponseHandler extends
{
if(qName.equals("InstanceId"))
instanceIds.add(currentText.toString().trim());
currentText = new StringBuilder();
}
@Override
public Set<String> getResult()

View File

@ -19,20 +19,26 @@
package org.jclouds.aws.ec2.compute;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNotNull;
import java.util.HashSet;
import java.util.Set;
import org.jclouds.aws.domain.Region;
import org.jclouds.aws.ec2.EC2Client;
import org.jclouds.aws.ec2.compute.options.EC2TemplateOptions;
import org.jclouds.aws.ec2.domain.ElasticLoadBalancer;
import org.jclouds.aws.ec2.domain.IpProtocol;
import org.jclouds.aws.ec2.domain.KeyPair;
import org.jclouds.aws.ec2.domain.RunningInstance;
import org.jclouds.aws.ec2.domain.SecurityGroup;
import org.jclouds.aws.ec2.services.ElasticLoadBalancerClient;
import org.jclouds.aws.ec2.services.InstanceClient;
import org.jclouds.aws.ec2.services.KeyPairClient;
import org.jclouds.aws.ec2.services.SecurityGroupClient;
import org.jclouds.compute.BaseComputeServiceLiveTest;
import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.domain.Template;
import org.jclouds.compute.options.TemplateOptions;
import org.jclouds.compute.predicates.NodePredicates;
import org.jclouds.domain.Credentials;
@ -172,6 +178,39 @@ public class EC2ComputeServiceLiveTest extends BaseComputeServiceLiveTest {
cleanupExtendedStuff(securityGroupClient, keyPairClient, tag);
}
}
@Test
public void testLoadBalanceNodesMatching() throws Exception{
ElasticLoadBalancerClient elbClient = EC2Client.class.cast(
context.getProviderSpecificContext().getApi())
.getElasticLoadBalancerServices();
String tag = "jcloudsElbTest";
Template template = client.templateBuilder().build();
Set<? extends NodeMetadata> nodes = client.runNodesWithTag(tag, 2,
template);
Set<String> instanceIds = new HashSet<String>();
for (NodeMetadata node : nodes)
{
instanceIds.add(node.getId());
}
// create load balancer
String dnsName = client.loadBalanceNodesMatching(tag, "HTTP", 80, 80,
NodePredicates.withTag(tag));
assertNotNull(dnsName);
Set<ElasticLoadBalancer> elbs = elbClient.describeLoadBalancers(
Region.US_EAST_1, tag);
assertNotNull(elbs);
ElasticLoadBalancer elb = elbs.iterator().next();
assertEquals(elb.getInstanceIds(), instanceIds);
elbClient.deleteLoadBalancer(Region.US_EAST_1, tag);
//finaly destroy nodes
client.destroyNodesMatching(NodePredicates.withTag(tag));
}
private RunningInstance getInstance(InstanceClient instanceClient, String id) {
RunningInstance instance = Iterables.getOnlyElement(Iterables.getOnlyElement(instanceClient

View File

@ -0,0 +1,70 @@
/**
*
* 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.Set;
import org.jclouds.aws.ec2.domain.ElasticLoadBalancer;
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.RegisterInstancesWithLoadBalancerResponseHandlerTest")
public class RegisterInstancesWithLoadBalancerResponseHandlerTest extends
BaseEC2HandlerTest
{
public void testParse()
{
InputStream is = getClass().getResourceAsStream(
"/ec2/register_instances_with_loadbalancer.xml");
Set<String> instanceIds = Sets.newHashSet();
instanceIds.add("i-6055fa09");
instanceIds.add("i-9055fa55");
Set<String> result = parseXML(is);
assertEquals(result, instanceIds);
}
private Set<String> parseXML(InputStream is)
{
RegisterInstancesWithLoadBalancerResponseHandler handler = injector
.getInstance(RegisterInstancesWithLoadBalancerResponseHandler.class);
Set<String> result = factory.create(handler).parse(is);
return result;
}
}

View File

@ -0,0 +1,8 @@
<RegisterInstancesWithLoadBalancerResult>
<Instances>
<member>
<InstanceId>i-6055fa09</InstanceId>
<InstanceId>i-9055fa55</InstanceId>
</member>
</Instances>
</RegisterInstancesWithLoadBalancerResult>

View File

@ -213,5 +213,33 @@ public interface ComputeService {
Map<? extends NodeMetadata, ExecResponse> runScriptOnNodesMatching(
Predicate<NodeMetadata> filter, byte[] runScript, RunScriptOptions options)
throws RunScriptOnNodesException;
/**
* @param loadBalancerName
* Load balancer name
* @param protocol
* LoadBalancer transport protocol to use for routing - TCP or
* HTTP. This property cannot be modified for the life of the
* LoadBalancer.
* @param loadBalancerPort
* The external TCP port of the LoadBalancer. Valid LoadBalancer
* ports are - 80, 443 and 1024 through 65535. This property
* cannot be modified for the life of the LoadBalancer.
* @param instancePort
* The InstancePort data type is simple type of type: integer. It
* is the TCP port on which the server on the instance is
* listening. Valid instance ports are one (1) through 65535.
* This property cannot be modified for the life of the
* LoadBalancer.
* @param filter
* Predicate-based filter to define on which nodes the script is
* to be executed
* @return DNS Name of the load balancer
*/
String loadBalanceNodesMatching(String loadBalancerName, String protocol,
Integer loadBalancerPort, Integer instancePort,
Predicate<NodeMetadata> filter);
void deleteLoadBalancer(String loadBalancerName, Predicate<NodeMetadata> filter);
}

View File

@ -58,6 +58,7 @@ import org.jclouds.compute.reference.ComputeServiceConstants;
import org.jclouds.compute.strategy.DestroyNodeStrategy;
import org.jclouds.compute.strategy.GetNodeMetadataStrategy;
import org.jclouds.compute.strategy.ListNodesStrategy;
import org.jclouds.compute.strategy.LoadBalancerStrategy;
import org.jclouds.compute.strategy.RebootNodeStrategy;
import org.jclouds.compute.strategy.RunNodesAndAddToSetStrategy;
import org.jclouds.compute.util.ComputeUtils;
@ -95,6 +96,7 @@ public class BaseComputeService implements ComputeService {
protected final RunNodesAndAddToSetStrategy runNodesAndAddToSetStrategy;
protected final RebootNodeStrategy rebootNodeStrategy;
protected final DestroyNodeStrategy destroyNodeStrategy;
protected final LoadBalancerStrategy loadBalancerStrategy;
protected final Provider<TemplateBuilder> templateBuilderProvider;
protected final Provider<TemplateOptions> templateOptionsProvider;
protected final ComputeUtils utils;
@ -107,7 +109,7 @@ public class BaseComputeService implements ComputeService {
GetNodeMetadataStrategy getNodeMetadataStrategy,
RunNodesAndAddToSetStrategy runNodesAndAddToSetStrategy,
RebootNodeStrategy rebootNodeStrategy, DestroyNodeStrategy destroyNodeStrategy,
Provider<TemplateBuilder> templateBuilderProvider,
LoadBalancerStrategy loadBalancerStrategy, Provider<TemplateBuilder> templateBuilderProvider,
Provider<TemplateOptions> templateOptionsProvider, ComputeUtils utils,
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService executor) {
this.context = checkNotNull(context, "context");
@ -121,6 +123,7 @@ public class BaseComputeService implements ComputeService {
"runNodesAndAddToSetStrategy");
this.rebootNodeStrategy = checkNotNull(rebootNodeStrategy, "rebootNodeStrategy");
this.destroyNodeStrategy = checkNotNull(destroyNodeStrategy, "destroyNodeStrategy");
this.loadBalancerStrategy = checkNotNull(loadBalancerStrategy, "loadBalancerStrategy");
this.templateBuilderProvider = checkNotNull(templateBuilderProvider,
"templateBuilderProvider");
this.templateOptionsProvider = checkNotNull(templateOptionsProvider,
@ -380,8 +383,12 @@ public class BaseComputeService implements ComputeService {
return execs;
}
private Iterable<? extends NodeMetadata> verifyParametersAndListNodes(
/**
* {@inheritDoc}
*/
private Iterable<? extends NodeMetadata> verifyParametersAndListNodes(
Predicate<NodeMetadata> filter, byte[] runScript, final RunScriptOptions options) {
checkNotNull(filter, "Filter must be provided");
checkNotNull(runScript,
@ -416,6 +423,28 @@ public class BaseComputeService implements ComputeService {
});
}
/**
* {@inheritDoc}
*/
public String loadBalanceNodesMatching(String loadBalancerName,
String protocol, Integer loadBalancerPort, Integer instancePort,
Predicate<NodeMetadata> filter)
{
return null;
}
/**
* {@inheritDoc}
*/
public void deleteLoadBalancer(String loadBalancerName,
Predicate<NodeMetadata> filter)
{
}
private Iterable<? extends NodeMetadata> detailsOnAllNodes() {
return listNodesStrategy.listDetailsOnNodesMatching(NodePredicates.all());
}