Issue 260: fixed i/o threadpool to min=max; refactored session expiry logic. Issue 258 refactored load balancer code

This commit is contained in:
Adrian Cole 2010-05-23 15:39:49 -07:00
parent 5b300f87cc
commit a4bdd433f4
47 changed files with 1139 additions and 317 deletions

View File

@ -80,7 +80,7 @@ public class AtmosStorageUtils {
public static void deleteAndEnsureGone(final AtmosStorageClient sync, final String path) {
try {
if (!Utils.enventuallyTrue(new Supplier<Boolean>() {
if (!Utils.eventuallyTrue(new Supplier<Boolean>() {
public Boolean get() {
sync.deletePath(path);
return !sync.pathExists(path);

View File

@ -363,7 +363,7 @@ public class AtmosStorageClientLiveTest {
connection.deletePath(path);
} catch (KeyNotFoundException ex) {
}
assert Utils.enventuallyTrue(new Supplier<Boolean>() {
assert Utils.eventuallyTrue(new Supplier<Boolean>() {
public Boolean get() {
return !connection.pathExists(path);
}

View File

@ -18,13 +18,9 @@
*/
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.aws.ec2.util.EC2Utils.parseHandle;
import static org.jclouds.util.Utils.checkNotEmpty;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.Map.Entry;
@ -41,7 +37,6 @@ import org.jclouds.aws.ec2.compute.domain.RegionAndName;
import org.jclouds.aws.ec2.compute.domain.RegionNameAndIngressRules;
import org.jclouds.aws.ec2.compute.options.EC2TemplateOptions;
import org.jclouds.aws.ec2.domain.KeyPair;
import org.jclouds.aws.ec2.util.EC2Utils;
import org.jclouds.compute.ComputeServiceContext;
import org.jclouds.compute.domain.Image;
import org.jclouds.compute.domain.NodeMetadata;
@ -49,19 +44,15 @@ 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,7 +63,6 @@ public class EC2ComputeService extends BaseComputeService {
private final EC2Client ec2Client;
private final Map<RegionAndName, KeyPair> credentialsMap;
private final Map<RegionAndName, String> securityGroupMap;
private final LoadBalancerStrategy loadBalancerStrategy;
@Inject
protected EC2ComputeService(ComputeServiceContext context,
@ -83,13 +73,11 @@ public class EC2ComputeService extends BaseComputeService {
RebootNodeStrategy rebootNodeStrategy, DestroyNodeStrategy destroyNodeStrategy,
Provider<TemplateBuilder> templateBuilderProvider,
Provider<TemplateOptions> templateOptionsProvider, ComputeUtils utils,
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService executor,
LoadBalancerStrategy loadBalancerStrategy, EC2Client ec2Client,
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService executor, EC2Client ec2Client,
Map<RegionAndName, KeyPair> credentialsMap, Map<RegionAndName, String> securityGroupMap) {
super(context, images, sizes, locations, listNodesStrategy, getNodeMetadataStrategy,
runNodesAndAddToSetStrategy, rebootNodeStrategy, destroyNodeStrategy,
templateBuilderProvider, templateOptionsProvider, utils, executor);
this.loadBalancerStrategy = checkNotNull(loadBalancerStrategy, "loadBalancerStrategy");
this.ec2Client = ec2Client;
this.credentialsMap = credentialsMap;
this.securityGroupMap = securityGroupMap;
@ -146,47 +134,4 @@ public class EC2ComputeService extends BaseComputeService {
return EC2TemplateOptions.class.cast(super.templateOptions());
}
@Override
public Set<String> loadBalanceNodesMatching(Predicate<NodeMetadata> filter, String loadBalancerName,
String protocol, int loadBalancerPort, int instancePort) {
checkNotNull(loadBalancerName, "loadBalancerName");
checkNotNull(protocol, "protocol");
checkArgument(protocol.toUpperCase().equals("HTTP") || protocol.toUpperCase().equals("TCP"),
"Acceptable values for protocol are HTTP or TCP");
Map<Location, Set<String>> locationMap = new HashMap<Location, Set<String>>();
for (NodeMetadata node : Iterables.filter(super
.listNodesDetailsMatching(NodePredicates.all()), Predicates.and(filter, Predicates
.not(NodePredicates.TERMINATED)))) {
Set<String> ids = locationMap.get(node.getLocation());
if(ids == null)
ids = new HashSet<String>();
ids.add(node.getProviderId());
locationMap.put(node.getLocation(), ids);
}
Set<String> dnsNames = new HashSet<String>(0);
for(Location location: locationMap.keySet())
{
logger.debug(">> creating load balancer (%s)", loadBalancerName);
String dnsName = loadBalancerStrategy.execute(location, loadBalancerName, protocol,
loadBalancerPort, instancePort, locationMap.get(location));
dnsNames.add(dnsName);
logger.debug("<< created load balancer (%s) DNS (%s)", loadBalancerName, dnsName);
}
return dnsNames;
}
@Override
public void deleteLoadBalancer(String dnsName) {
Map<String, String> tuple = EC2Utils.getLoadBalancerNameAndRegionFromDnsName(dnsName);
//Only one load balancer per DNS name is expected
for(String key: tuple.keySet())
{
ec2Client.getElasticLoadBalancerServices().deleteLoadBalancerInRegion(key,
tuple.get(key));
}
}
}

View File

@ -55,8 +55,9 @@ import org.jclouds.aws.ec2.compute.functions.RegionAndIdToImage;
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.EC2DestroyLoadBalancerStrategy;
import org.jclouds.aws.ec2.compute.strategy.EC2DestroyNodeStrategy;
import org.jclouds.aws.ec2.compute.strategy.EC2LoadBalancerStrategy;
import org.jclouds.aws.ec2.compute.strategy.EC2LoadBalanceNodesStrategy;
import org.jclouds.aws.ec2.compute.strategy.EC2RunNodesAndAddToSetStrategy;
import org.jclouds.aws.ec2.config.EC2ContextModule;
import org.jclouds.aws.ec2.domain.KeyPair;
@ -78,10 +79,11 @@ import org.jclouds.compute.predicates.NodePredicates;
import org.jclouds.compute.predicates.ScriptStatusReturnsZero;
import org.jclouds.compute.predicates.ScriptStatusReturnsZero.CommandUsingClient;
import org.jclouds.compute.reference.ComputeServiceConstants;
import org.jclouds.compute.strategy.DestroyLoadBalancerStrategy;
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.LoadBalanceNodesStrategy;
import org.jclouds.compute.strategy.RebootNodeStrategy;
import org.jclouds.compute.strategy.RunNodesAndAddToSetStrategy;
import org.jclouds.concurrent.ConcurrentUtils;
@ -90,7 +92,6 @@ import org.jclouds.domain.LocationScope;
import org.jclouds.domain.internal.LocationImpl;
import org.jclouds.logging.Logger;
import org.jclouds.predicates.RetryablePredicate;
import org.jclouds.rest.RestContext;
import org.jclouds.util.Jsr330;
import com.google.common.base.Function;
@ -127,7 +128,11 @@ public class EC2ComputeServiceContextModule extends EC2ContextModule {
bind(TemplateBuilder.class).to(EC2TemplateBuilderImpl.class);
bind(TemplateOptions.class).to(EC2TemplateOptions.class);
bind(ComputeService.class).to(EC2ComputeService.class);
bind(LoadBalancerStrategy.class).to(EC2LoadBalancerStrategy.class);
bind(new TypeLiteral<ComputeServiceContext>() {
}).to(new TypeLiteral<ComputeServiceContextImpl<EC2AsyncClient, EC2Client>>() {
}).in(Scopes.SINGLETON);
bind(LoadBalanceNodesStrategy.class).to(EC2LoadBalanceNodesStrategy.class);
bind(DestroyLoadBalancerStrategy.class).to(EC2DestroyLoadBalancerStrategy.class);
bind(RunNodesAndAddToSetStrategy.class).to(EC2RunNodesAndAddToSetStrategy.class);
bind(ListNodesStrategy.class).to(EC2ListNodesStrategy.class);
bind(GetNodeMetadataStrategy.class).to(EC2GetNodeMetadataStrategy.class);
@ -284,13 +289,6 @@ public class EC2ComputeServiceContextModule extends EC2ContextModule {
return Maps.newLinkedHashMap();
}
@Provides
@Singleton
ComputeServiceContext provideContext(ComputeService computeService,
RestContext<EC2AsyncClient, EC2Client> context) {
return new ComputeServiceContextImpl<EC2AsyncClient, EC2Client>(computeService, context);
}
@Provides
@Singleton
Function<ComputeMetadata, String> indexer() {

View File

@ -28,9 +28,9 @@ public class EC2TemplateBuilderImpl extends TemplateBuilderImpl {
private final ConcurrentMap<RegionAndName, Image> imageMap;
@Inject
protected EC2TemplateBuilderImpl(Set<? extends Location> locations, Set<? extends Image> images,
Set<? extends Size> sizes, Location defaultLocation,
Provider<TemplateOptions> optionsProvider,
protected EC2TemplateBuilderImpl(Provider<Set<? extends Location>> locations,
Provider<Set<? extends Image>> images, Provider<Set<? extends Size>> sizes,
Location defaultLocation, Provider<TemplateOptions> optionsProvider,
@Named("DEFAULT") Provider<TemplateBuilder> defaultTemplateProvider,
ConcurrentMap<RegionAndName, Image> imageMap) {
super(locations, images, sizes, defaultLocation, optionsProvider, defaultTemplateProvider);

View File

@ -0,0 +1,65 @@
/**
*
* 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 static com.google.common.base.Preconditions.checkNotNull;
import java.net.InetAddress;
import java.util.Map;
import javax.annotation.Resource;
import javax.inject.Inject;
import javax.inject.Named;
import javax.inject.Singleton;
import org.jclouds.aws.ec2.services.ElasticLoadBalancerClient;
import org.jclouds.aws.ec2.util.EC2Utils;
import org.jclouds.compute.reference.ComputeServiceConstants;
import org.jclouds.compute.strategy.DestroyLoadBalancerStrategy;
import org.jclouds.logging.Logger;
/**
*
* @author Adrian Cole
*/
@Singleton
public class EC2DestroyLoadBalancerStrategy implements DestroyLoadBalancerStrategy {
@Resource
@Named(ComputeServiceConstants.COMPUTE_LOGGER)
protected Logger logger = Logger.NULL;
private final ElasticLoadBalancerClient elbClient;
@Inject
protected EC2DestroyLoadBalancerStrategy(ElasticLoadBalancerClient elbClient) {
this.elbClient = checkNotNull(elbClient, "elbClient");
}
@Override
public boolean execute(InetAddress loadBalancer) {
Map<String, String> tuple = EC2Utils.getLoadBalancerNameAndRegionFromDnsName(loadBalancer
.getCanonicalHostName());
// Only one load balancer per DNS name is expected
for (String key : tuple.keySet()) {
elbClient.deleteLoadBalancerInRegion(key, tuple.get(key));
}
return true;
}
}

View File

@ -33,7 +33,7 @@ import org.jclouds.aws.ec2.domain.AvailabilityZone;
import org.jclouds.aws.ec2.services.ElasticLoadBalancerClient;
import org.jclouds.aws.ec2.util.EC2Utils.GetRegionFromLocation;
import org.jclouds.compute.reference.ComputeServiceConstants;
import org.jclouds.compute.strategy.LoadBalancerStrategy;
import org.jclouds.compute.strategy.LoadBalanceNodesStrategy;
import org.jclouds.domain.Location;
import org.jclouds.logging.Logger;
@ -42,7 +42,7 @@ import org.jclouds.logging.Logger;
* @author Adrian Cole
*/
@Singleton
public class EC2LoadBalancerStrategy implements LoadBalancerStrategy {
public class EC2LoadBalanceNodesStrategy implements LoadBalanceNodesStrategy {
@Resource
@Named(ComputeServiceConstants.COMPUTE_LOGGER)
protected Logger logger = Logger.NULL;
@ -50,7 +50,7 @@ public class EC2LoadBalancerStrategy implements LoadBalancerStrategy {
protected final GetRegionFromLocation getRegionFromLocation;
@Inject
protected EC2LoadBalancerStrategy(EC2Client ec2Client,
protected EC2LoadBalanceNodesStrategy(EC2Client ec2Client,
GetRegionFromLocation getRegionFromLocation) {
this.ec2Client = ec2Client;
this.getRegionFromLocation = getRegionFromLocation;

View File

@ -167,7 +167,7 @@ public class S3BlobStore extends BaseBlobStore {
*/
public void clearAndDeleteContainer(final String container) {
try {
if (!Utils.enventuallyTrue(new Supplier<Boolean>() {
if (!Utils.eventuallyTrue(new Supplier<Boolean>() {
public Boolean get() {
clearContainer(container);
return sync.deleteBucketIfEmpty(container);

View File

@ -19,26 +19,20 @@
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;
@ -179,38 +173,6 @@ public class EC2ComputeServiceLiveTest extends BaseComputeServiceLiveTest {
}
}
@Test(enabled = true, dependsOnMethods = "testCorrectAuthException")
public void testLoadBalanceNodesMatching() throws Exception {
ElasticLoadBalancerClient elbClient = EC2Client.class.cast(
context.getProviderSpecificContext().getApi()).getElasticLoadBalancerServices();
String tag = "jcloudsElbTest";
Template template = client.templateBuilder().build();
try {
Set<? extends NodeMetadata> nodes = client.runNodesWithTag(tag, 2, template);
Set<String> instanceIds = new HashSet<String>();
for (NodeMetadata node : nodes) {
instanceIds.add(node.getProviderId());
}
// create load balancers
Set<String> dnsNames = client.loadBalanceNodesMatching(NodePredicates.withTag(tag), tag, "HTTP",
80, 80);
assertNotNull(dnsNames);
Set<ElasticLoadBalancer> elbs = elbClient.describeLoadBalancersInRegion(Region.US_EAST_1,
tag);
assertNotNull(elbs);
ElasticLoadBalancer elb = elbs.iterator().next();
assertEquals(elb.getInstanceIds(), instanceIds);
} finally {
elbClient.deleteLoadBalancerInRegion(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
.describeInstancesInRegion(null, id)));

View File

@ -29,12 +29,15 @@ import static org.easymock.EasyMock.expect;
import static org.easymock.classextension.EasyMock.createMock;
import static org.easymock.classextension.EasyMock.replay;
import java.util.Set;
import javax.inject.Provider;
import org.jclouds.aws.ec2.compute.domain.EC2Size;
import org.jclouds.compute.domain.Architecture;
import org.jclouds.compute.domain.ComputeMetadata;
import org.jclouds.compute.domain.Image;
import org.jclouds.compute.domain.Size;
import org.jclouds.compute.domain.Template;
import org.jclouds.compute.domain.TemplateBuilder;
import org.jclouds.compute.domain.internal.ImageImpl;
@ -49,6 +52,7 @@ import org.testng.annotations.Test;
import com.google.common.base.Function;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Maps;
import com.google.inject.util.Providers;
/**
* Tests compute service specifically to EC2.
@ -130,10 +134,18 @@ public class EC2ComputeServiceTest {
Architecture.X86_64, new Credentials("root", null));
replay(optionsProvider);
replay(templateBuilderProvider);
return new TemplateBuilderImpl(ImmutableSet.of(location), ImmutableSet.of(image),
ImmutableSet.of(EC2Size.C1_MEDIUM, EC2Size.C1_XLARGE, EC2Size.M1_LARGE,
EC2Size.M1_SMALL, EC2Size.M1_XLARGE, EC2Size.M2_XLARGE, EC2Size.M2_2XLARGE,
EC2Size.M2_4XLARGE), location, optionsProvider, templateBuilderProvider) {
Provider<Set<? extends Location>> locations = Providers
.<Set<? extends Location>> of(ImmutableSet.<Location> of(location));
Provider<Set<? extends Image>> images = Providers.<Set<? extends Image>> of(ImmutableSet
.<Image> of(image));
Provider<Set<? extends Size>> sizes = Providers.<Set<? extends Size>> of(ImmutableSet
.<Size> of(EC2Size.C1_MEDIUM, EC2Size.C1_XLARGE, EC2Size.M1_LARGE, EC2Size.M1_SMALL,
EC2Size.M1_XLARGE, EC2Size.M2_XLARGE, EC2Size.M2_2XLARGE,
EC2Size.M2_4XLARGE));
return new TemplateBuilderImpl(locations, images, sizes, location, optionsProvider,
templateBuilderProvider) {
};
}

View File

@ -0,0 +1,73 @@
/**
*
* 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;
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.domain.ElasticLoadBalancer;
import org.jclouds.aws.ec2.services.ElasticLoadBalancerClient;
import org.jclouds.compute.BaseLoadBalancerServiceLiveTest;
import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.ssh.jsch.config.JschSshClientModule;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
/**
*
* @author Lili Nadar
*/
@Test(groups = "live", sequential = true, testName = "ec2.EC2LoadBalancerServiceLiveTest")
public class EC2LoadBalancerServiceLiveTest extends BaseLoadBalancerServiceLiveTest {
@BeforeClass
@Override
public void setServiceDefaults() {
service = "ec2";
}
@Override
protected JschSshClientModule getSshModule() {
return new JschSshClientModule();
}
@Override
protected void validateNodesInLoadBalancer() {
// TODO create a LoadBalancer object and an appropriate list method so that this
// does not have to be EC2 specific code
ElasticLoadBalancerClient elbClient = EC2Client.class.cast(
context.getProviderSpecificContext().getApi()).getElasticLoadBalancerServices();
Set<String> instanceIds = new HashSet<String>();
for (NodeMetadata node : nodes) {
instanceIds.add(node.getProviderId());
}
Set<ElasticLoadBalancer> elbs = elbClient
.describeLoadBalancersInRegion(Region.US_EAST_1, tag);
assertNotNull(elbs);
ElasticLoadBalancer elb = elbs.iterator().next();
assertEquals(elb.getInstanceIds(), instanceIds);
}
}

View File

@ -51,6 +51,7 @@ import com.google.common.base.Function;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.MapMaker;
import com.google.inject.util.Providers;
/**
*
@ -77,8 +78,9 @@ public class EC2TemplateBuilderImplTest extends TemplateBuilderImplTest {
}
@Override
protected EC2TemplateBuilderImpl createTemplateBuilder(Set<Location> locations,
Set<Image> images, Set<Size> sizes, Location defaultLocation,
protected EC2TemplateBuilderImpl createTemplateBuilder(
Provider<Set<? extends Location>> locations, Provider<Set<? extends Image>> images,
Provider<Set<? extends Size>> sizes, Location defaultLocation,
Provider<TemplateOptions> optionsProvider,
Provider<TemplateBuilder> templateBuilderProvider) {
return new EC2TemplateBuilderImpl(locations, images, sizes, defaultLocation, optionsProvider,
@ -89,10 +91,15 @@ public class EC2TemplateBuilderImplTest extends TemplateBuilderImplTest {
@Test
public void testParseOnDemand() {
Location location = new LocationImpl(LocationScope.REGION, "region", "region", null);
Set<Location> locations = ImmutableSet.<Location> of(location);
Set<Image> images = ImmutableSet.<Image> of();
Set<Size> sizes = ImmutableSet.<Size> of(new SizeImpl("1", "1", "region/1", location, null,
ImmutableMap.<String, String> of(), 1, 1, 1, ImagePredicates.any()));
Provider<Set<? extends Location>> locations = Providers
.<Set<? extends Location>> of(ImmutableSet.<Location> of(location));
Provider<Set<? extends Image>> images = Providers.<Set<? extends Image>> of(ImmutableSet
.<Image> of());
Provider<Set<? extends Size>> sizes = Providers.<Set<? extends Size>> of(ImmutableSet
.<Size> of(new SizeImpl("1", "1", "region/1", location, null, ImmutableMap
.<String, String> of(), 1, 1, 1, ImagePredicates.any())));
Location defaultLocation = createMock(Location.class);
Provider<TemplateOptions> optionsProvider = createMock(Provider.class);
Provider<TemplateBuilder> templateBuilderProvider = createMock(Provider.class);
@ -125,10 +132,15 @@ public class EC2TemplateBuilderImplTest extends TemplateBuilderImplTest {
@Test(expectedExceptions = NoSuchElementException.class)
public void testParseOnDemandNotFound() {
Location location = new LocationImpl(LocationScope.REGION, "region", "region", null);
Set<Location> locations = ImmutableSet.<Location> of(location);
Set<Image> images = ImmutableSet.<Image> of();
Set<Size> sizes = ImmutableSet.<Size> of(new SizeImpl("1", "1", "region/1", location, null,
ImmutableMap.<String, String> of(), 1, 1, 1, ImagePredicates.any()));
Provider<Set<? extends Location>> locations = Providers
.<Set<? extends Location>> of(ImmutableSet.<Location> of(location));
Provider<Set<? extends Image>> images = Providers.<Set<? extends Image>> of(ImmutableSet
.<Image> of());
Provider<Set<? extends Size>> sizes = Providers.<Set<? extends Size>> of(ImmutableSet
.<Size> of(new SizeImpl("1", "1", "region/1", location, null, ImmutableMap
.<String, String> of(), 1, 1, 1, ImagePredicates.any())));
Location defaultLocation = createMock(Location.class);
Provider<TemplateOptions> optionsProvider = createMock(Provider.class);
Provider<TemplateBuilder> templateBuilderProvider = createMock(Provider.class);

View File

@ -252,7 +252,7 @@ public abstract class BaseAsyncBlobStore implements AsyncBlobStore {
protected void deleteAndEnsurePathGone(final String container) {
try {
if (!Utils.enventuallyTrue(new Supplier<Boolean>() {
if (!Utils.eventuallyTrue(new Supplier<Boolean>() {
public Boolean get() {
try {
clearContainer(container, recursive());

View File

@ -194,7 +194,7 @@ public abstract class BaseBlobStore implements BlobStore {
protected void clearAndDeleteContainer(final String container) {
try {
if (!Utils.enventuallyTrue(new Supplier<Boolean>() {
if (!Utils.eventuallyTrue(new Supplier<Boolean>() {
public Boolean get() {
try {
clearContainer(container, recursive());

View File

@ -33,7 +33,6 @@ import org.jclouds.compute.options.TemplateOptions;
import org.jclouds.domain.Location;
import org.jclouds.ssh.ExecResponse;
import com.google.common.annotations.Beta;
import com.google.common.base.Predicate;
import com.google.inject.ImplementedBy;
@ -146,8 +145,8 @@ public interface ComputeService {
Set<? extends NodeMetadata> runNodesWithTag(String tag, int count) throws RunNodesException;
/**
* destroy the node, given its id. If it is the only node in a tag set, the dependent
* resources will also be destroyed.
* destroy the node, given its id. If it is the only node in a tag set, the dependent resources
* will also be destroyed.
*/
void destroyNode(String id);
@ -215,30 +214,4 @@ public interface ComputeService {
Predicate<NodeMetadata> filter, byte[] runScript, RunScriptOptions options)
throws RunScriptOnNodesException;
/**
* @param filter
* Predicate-based filter to define which nodes to loadbalance
* @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.
*
* @return DNS Name of the load balancer
*/
@Beta
Set<String> loadBalanceNodesMatching(Predicate<NodeMetadata> filter, String loadBalancerName,
String protocol, int loadBalancerPort, int instancePort);
@Beta
void deleteLoadBalancer(String handle);
}

View File

@ -35,6 +35,12 @@ public interface ComputeServiceContext {
ComputeService getComputeService();
/**
*
* @return null, if the cloud does not support load balancer services
*/
LoadBalancerService getLoadBalancerService();
<A, S> RestContext<A, S> getProviderSpecificContext();
void close();

View File

@ -0,0 +1,71 @@
/**
*
* 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;
import java.net.InetAddress;
import java.util.Set;
import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.internal.BaseLoadBalancerService;
import com.google.common.annotations.Beta;
import com.google.common.base.Predicate;
import com.google.inject.ImplementedBy;
/**
* Provides portable access to load balancer services.
*
* @author Lili Nadar
*/
@Beta
@ImplementedBy(BaseLoadBalancerService.class)
public interface LoadBalancerService {
/**
* @return a reference to the context that created this LoadBalancerService.
*/
ComputeServiceContext getContext();
/**
* @param filter
* Predicate-based filter to define which nodes to loadbalance
* @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.
*
* @return DNS Name of the load balancer
*/
@Beta
Set<InetAddress> loadBalanceNodesMatching(Predicate<NodeMetadata> filter,
String loadBalancerName, String protocol, int loadBalancerPort, int instancePort);
@Beta
void destroyLoadBalancer(InetAddress handle);
}

View File

@ -422,16 +422,4 @@ public class BaseComputeService implements ComputeService {
public TemplateOptions templateOptions() {
return templateOptionsProvider.get();
}
@Override
public void deleteLoadBalancer(String handle) {
throw new UnsupportedOperationException("deleteLoadBalancer not supported in this cloud");
}
@Override
public Set<String> loadBalanceNodesMatching(Predicate<NodeMetadata> filter, String loadBalancerName,
String protocol, int loadBalancerPort, int instancePort) {
throw new UnsupportedOperationException(
"loadBalanceNodesMatching not supported in this cloud");
}
}

View File

@ -0,0 +1,142 @@
/**
*
* Copyright (C) 2009 Global Cloud Specialists, Inc. <info@globalcloudspecialists.com>
*
* ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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.internal;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.Map;
import java.util.Set;
import javax.annotation.Resource;
import javax.inject.Inject;
import javax.inject.Named;
import javax.inject.Singleton;
import org.jclouds.compute.ComputeServiceContext;
import org.jclouds.compute.LoadBalancerService;
import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.predicates.NodePredicates;
import org.jclouds.compute.reference.ComputeServiceConstants;
import org.jclouds.compute.strategy.DestroyLoadBalancerStrategy;
import org.jclouds.compute.strategy.LoadBalanceNodesStrategy;
import org.jclouds.domain.Location;
import org.jclouds.logging.Logger;
import com.google.common.base.Predicate;
import com.google.common.base.Predicates;
import com.google.common.base.Throwables;
import com.google.common.collect.Iterables;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
/**
*
* @author Lili Nadar
* @author Adrian Cole
*/
@Singleton
public class BaseLoadBalancerService implements LoadBalancerService {
@Resource
@Named(ComputeServiceConstants.COMPUTE_LOGGER)
protected Logger logger = Logger.NULL;
protected final ComputeServiceContext context;
protected final LoadBalanceNodesStrategy loadBalancerStrategy;
protected final DestroyLoadBalancerStrategy destroyLoadBalancerStrategy;
@Inject
protected BaseLoadBalancerService(ComputeServiceContext context,
LoadBalanceNodesStrategy loadBalancerStrategy,
DestroyLoadBalancerStrategy destroyLoadBalancerStrategy) {
this.context = checkNotNull(context, "context");
this.loadBalancerStrategy = checkNotNull(loadBalancerStrategy, "loadBalancerStrategy");
this.destroyLoadBalancerStrategy = checkNotNull(destroyLoadBalancerStrategy,
"destroyLoadBalancerStrategy");
}
/**
* {@inheritDoc}
*/
@Override
public ComputeServiceContext getContext() {
return context;
}
@Override
public Set<InetAddress> loadBalanceNodesMatching(Predicate<NodeMetadata> filter,
String loadBalancerName, String protocol, int loadBalancerPort, int instancePort) {
checkNotNull(loadBalancerName, "loadBalancerName");
checkNotNull(protocol, "protocol");
checkArgument(protocol.toUpperCase().equals("HTTP") || protocol.toUpperCase().equals("TCP"),
"Acceptable values for protocol are HTTP or TCP");
Map<Location, Set<String>> locationMap = Maps.newHashMap();
for (NodeMetadata node : Iterables.filter(context.getComputeService()
.listNodesDetailsMatching(NodePredicates.all()), Predicates.and(filter, Predicates
.not(NodePredicates.TERMINATED)))) {
Set<String> ids = locationMap.get(node.getLocation());
if (ids == null)
ids = Sets.newHashSet();
ids.add(node.getProviderId());
locationMap.put(node.getLocation(), ids);
}
Set<InetAddress> dnsNames = Sets.newHashSet();
for (Location location : locationMap.keySet()) {
logger.debug(">> creating load balancer (%s)", loadBalancerName);
String dnsName = loadBalancerStrategy.execute(location, loadBalancerName, protocol,
loadBalancerPort, instancePort, locationMap.get(location));
for (int i = 0; i < 3; i++) {
try {
dnsNames.add(InetAddress.getByName(dnsName));
} catch (UnknownHostException e) {
try {
Thread.sleep(1000);
} catch (InterruptedException e1) {
Throwables.propagate(e1);
}
continue;
}
}
logger.debug("<< created load balancer (%s) DNS (%s)", loadBalancerName, dnsName);
}
return dnsNames;
}
/**
* {@inheritDoc}
*/
@Override
public void destroyLoadBalancer(InetAddress loadBalancer) {
checkNotNull(loadBalancer, "loadBalancer");
logger.debug(">> destroying load balancer(%s)", loadBalancer);
boolean successful = destroyLoadBalancerStrategy.execute(loadBalancer);
logger.debug("<< destroyed load balancer(%s) success(%s)", loadBalancer, successful);
}
}

View File

@ -21,24 +21,32 @@ package org.jclouds.compute.internal;
import static com.google.common.base.Preconditions.checkNotNull;
import javax.annotation.Nullable;
import javax.inject.Inject;
import javax.inject.Singleton;
import org.jclouds.compute.ComputeService;
import org.jclouds.compute.ComputeServiceContext;
import org.jclouds.compute.LoadBalancerService;
import org.jclouds.rest.RestContext;
/**
* @author Adrian Cole
*/
@Singleton
public class ComputeServiceContextImpl<X, Y> implements ComputeServiceContext {
private final ComputeService computeService;
private final LoadBalancerService loadBalancerService;
private final RestContext<X, Y> providerSpecificContext;
@Inject
public ComputeServiceContextImpl(ComputeService computeService,
@Nullable LoadBalancerService loadBalancerService,
RestContext<X, Y> providerSpecificContext) {
this.computeService = checkNotNull(computeService, "computeService");
this.providerSpecificContext = checkNotNull(providerSpecificContext, "providerSpecificContext");;
this.loadBalancerService = loadBalancerService;
this.providerSpecificContext = checkNotNull(providerSpecificContext,
"providerSpecificContext");
}
public ComputeService getComputeService() {
@ -55,4 +63,9 @@ public class ComputeServiceContextImpl<X, Y> implements ComputeServiceContext {
public void close() {
providerSpecificContext.close();
}
@Override
public LoadBalancerService getLoadBalancerService() {
return loadBalancerService;
}
}

View File

@ -64,9 +64,9 @@ public class TemplateBuilderImpl implements TemplateBuilder {
@Named(ComputeServiceConstants.COMPUTE_LOGGER)
protected Logger logger = Logger.NULL;
private final Set<? extends Image> images;
private final Set<? extends Size> sizes;
private final Set<? extends Location> locations;
private final Provider<Set<? extends Image>> images;
private final Provider<Set<? extends Size>> sizes;
private final Provider<Set<? extends Location>> locations;
private final Provider<TemplateOptions> optionsProvider;
private final Provider<TemplateBuilder> defaultTemplateProvider;
private final Location defaultLocation;
@ -101,9 +101,9 @@ public class TemplateBuilderImpl implements TemplateBuilder {
protected TemplateOptions options;
@Inject
protected TemplateBuilderImpl(Set<? extends Location> locations, Set<? extends Image> images,
Set<? extends Size> sizes, Location defaultLocation,
Provider<TemplateOptions> optionsProvider,
protected TemplateBuilderImpl(Provider<Set<? extends Location>> locations,
Provider<Set<? extends Image>> images, Provider<Set<? extends Size>> sizes,
Location defaultLocation, Provider<TemplateOptions> optionsProvider,
@Named("DEFAULT") Provider<TemplateBuilder> defaultTemplateProvider) {
this.locations = locations;
this.images = images;
@ -413,7 +413,7 @@ public class TemplateBuilderImpl implements TemplateBuilder {
}
protected Location resolveLocation() {
Location location = Iterables.find(locations, new Predicate<Location>() {
Location location = Iterables.find(locations.get(), new Predicate<Location>() {
@Override
public boolean apply(Location input) {
@ -428,8 +428,8 @@ public class TemplateBuilderImpl implements TemplateBuilder {
protected Size resolveSize(Ordering<Size> sizeOrdering, final List<? extends Image> images) {
Size size;
try {
Iterable<? extends Size> sizesThatAreCompatibleWithOurImages = Iterables.filter(sizes,
new Predicate<Size>() {
Iterable<? extends Size> sizesThatAreCompatibleWithOurImages = Iterables.filter(sizes
.get(), new Predicate<Size>() {
@Override
public boolean apply(final Size size) {
boolean returnVal = false;
@ -471,7 +471,7 @@ public class TemplateBuilderImpl implements TemplateBuilder {
protected List<? extends Image> resolveImages() {
Predicate<Image> imagePredicate = buildImagePredicate();
try {
Iterable<? extends Image> matchingImages = Iterables.filter(images, imagePredicate);
Iterable<? extends Image> matchingImages = Iterables.filter(images.get(), imagePredicate);
if (logger.isTraceEnabled())
logger.trace("<< matched images(%s)", matchingImages);
List<? extends Image> maxImages = Utils.multiMax(DEFAULT_IMAGE_ORDERING, matchingImages);

View File

@ -0,0 +1,36 @@
/**
*
* 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.net.InetAddress;
import com.google.common.annotations.Beta;
/**
*
*
* @author Adrian Cole
*/
@Beta
public interface DestroyLoadBalancerStrategy {
boolean execute(InetAddress loadBalancer);
}

View File

@ -28,7 +28,7 @@ import org.jclouds.domain.Location;
*
* @author Lili Nader
*/
public interface LoadBalancerStrategy {
public interface LoadBalanceNodesStrategy {
String execute(Location loaction, String name, String protocol, int loadBalancerPort,
int instancePort, Set<String> instanceIds);

View File

@ -0,0 +1,155 @@
/**
*
* 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;
import static com.google.common.base.Preconditions.checkNotNull;
import static org.testng.Assert.assertNotNull;
import java.io.IOException;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.util.Map;
import java.util.Set;
import java.util.SortedSet;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.domain.NodeState;
import org.jclouds.compute.domain.Template;
import org.jclouds.compute.domain.TemplateBuilder;
import org.jclouds.compute.predicates.NodePredicates;
import org.jclouds.logging.log4j.config.Log4JLoggingModule;
import org.jclouds.predicates.RetryablePredicate;
import org.jclouds.predicates.SocketOpen;
import org.jclouds.ssh.SshClient;
import org.testng.annotations.AfterTest;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.BeforeGroups;
import org.testng.annotations.Test;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import com.google.common.collect.Sets;
import com.google.inject.Guice;
import com.google.inject.Injector;
import com.google.inject.Module;
/**
*
* @author Adrian Cole
*/
@Test(groups = "live", sequential = true, testName = "compute.BaseLoadBalancerServiceTest")
public abstract class BaseLoadBalancerServiceLiveTest {
@BeforeClass
abstract public void setServiceDefaults();
protected String service;
protected SshClient.Factory sshFactory;
protected String tag;
protected RetryablePredicate<InetSocketAddress> socketTester;
protected SortedSet<NodeMetadata> nodes;
protected ComputeServiceContext context;
protected ComputeService client;
protected LoadBalancerService lbClient;
protected String user;
protected String password;
protected Template template;
protected Map<String, String> keyPair;
protected Set<InetAddress> loadbalancers;
@BeforeGroups(groups = { "live" })
public void setupClient() throws InterruptedException, ExecutionException, TimeoutException,
IOException, RunNodesException {
if (tag == null)
tag = checkNotNull(service, "service") + "lb";
user = checkNotNull(System.getProperty("jclouds.test.user"), "jclouds.test.user");
password = checkNotNull(System.getProperty("jclouds.test.key"), "jclouds.test.key");
initializeContextAndClient();
Injector injector = Guice.createInjector(getSshModule());
sshFactory = injector.getInstance(SshClient.Factory.class);
SocketOpen socketOpen = injector.getInstance(SocketOpen.class);
socketTester = new RetryablePredicate<InetSocketAddress>(socketOpen, 60, 1, TimeUnit.SECONDS);
injector.injectMembers(socketOpen); // add logger
Template template = client.templateBuilder().build();
nodes = Sets.newTreeSet(client.runNodesWithTag(tag, 2, template));
}
private void initializeContextAndClient() throws IOException {
if (context != null)
context.close();
context = new ComputeServiceContextFactory().createContext(service, user, password,
ImmutableSet.of(new Log4JLoggingModule(), getSshModule()));
client = context.getComputeService();
lbClient = context.getLoadBalancerService();
}
abstract protected Module getSshModule();
protected Template buildTemplate(TemplateBuilder templateBuilder) {
return templateBuilder.build();
}
@Test(enabled = true)
public void testLoadBalanceNodesMatching() throws Exception {
// create load balancers
loadbalancers = lbClient.loadBalanceNodesMatching(NodePredicates.withTag(tag), tag, "HTTP",
80, 80);
assertNotNull(loadbalancers);
validateNodesInLoadBalancer();
}
// TODO create a LoadBalancerService method for this.
protected abstract void validateNodesInLoadBalancer();
@Test(enabled = true, dependsOnMethods = "testLoadBalanceNodesMatching")
public void testDestroyLoadBalancers() throws Exception {
for (InetAddress lb : loadbalancers) {
lbClient.destroyLoadBalancer(lb);
}
}
@AfterTest
protected void cleanup() throws InterruptedException, ExecutionException, TimeoutException {
if (nodes != null) {
client.destroyNodesMatching(NodePredicates.withTag(tag));
for (NodeMetadata node : Iterables.filter(client.listNodesDetailsMatching(NodePredicates
.all()), NodePredicates.withTag(tag))) {
assert node.getState() == NodeState.TERMINATED : node;
}
}
if (loadbalancers != null) {
client.destroyNodesMatching(NodePredicates.withTag(tag));
for (NodeMetadata node : Iterables.filter(client.listNodesDetailsMatching(NodePredicates
.all()), NodePredicates.withTag(tag))) {
assert node.getState() == NodeState.TERMINATED : node;
}
}
context.close();
}
}

View File

@ -42,6 +42,7 @@ import org.testng.annotations.Test;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.inject.util.Providers;
/**
*
@ -60,9 +61,12 @@ public class TemplateBuilderImplTest {
Size size = new SizeImpl("sizeId", null, "sizeId", defaultLocation, null, ImmutableMap
.<String, String> of(), 1.0, 0, 0, ImagePredicates.any());
Set<Location> locations = ImmutableSet.<Location> of(defaultLocation);
Set<Image> images = ImmutableSet.<Image> of(image, image2);
Set<Size> sizes = ImmutableSet.<Size> of(size);
Provider<Set<? extends Location>> locations = Providers
.<Set<? extends Location>> of(ImmutableSet.<Location> of(defaultLocation));
Provider<Set<? extends Image>> images = Providers.<Set<? extends Image>> of(ImmutableSet
.<Image> of(image, image2));
Provider<Set<? extends Size>> sizes = Providers.<Set<? extends Size>> of(ImmutableSet
.<Size> of(size));
Provider<TemplateOptions> optionsProvider = createMock(Provider.class);
Provider<TemplateBuilder> templateBuilderProvider = createMock(Provider.class);
TemplateBuilder defaultTemplate = createMock(TemplateBuilder.class);
@ -86,7 +90,7 @@ public class TemplateBuilderImplTest {
TemplateBuilderImpl template = createTemplateBuilder(locations, images, sizes,
defaultLocation, optionsProvider, templateBuilderProvider);
assertEquals(template.resolveImages(), images);
assertEquals(template.resolveImages(), images.get());
verify(image);
verify(image2);
@ -106,9 +110,12 @@ public class TemplateBuilderImplTest {
Size size = new SizeImpl("sizeId", null, "sizeId", defaultLocation, null, ImmutableMap
.<String, String> of(), 1.0, 0, 0, ImagePredicates.any());
Set<Location> locations = ImmutableSet.<Location> of(defaultLocation);
Set<Image> images = ImmutableSet.<Image> of(image, image2);
Set<Size> sizes = ImmutableSet.<Size> of(size);
Provider<Set<? extends Location>> locations = Providers
.<Set<? extends Location>> of(ImmutableSet.<Location> of(defaultLocation));
Provider<Set<? extends Image>> images = Providers.<Set<? extends Image>> of(ImmutableSet
.<Image> of(image, image2));
Provider<Set<? extends Size>> sizes = Providers.<Set<? extends Size>> of(ImmutableSet
.<Size> of(size));
Provider<TemplateOptions> optionsProvider = createMock(Provider.class);
Provider<TemplateBuilder> templateBuilderProvider = createMock(Provider.class);
TemplateBuilder defaultTemplate = createMock(TemplateBuilder.class);
@ -150,9 +157,12 @@ public class TemplateBuilderImplTest {
Size size = new SizeImpl("sizeId", null, "sizeId", defaultLocation, null, ImmutableMap
.<String, String> of(), 0, 0, 0, ImagePredicates.idEquals("imageId"));
Set<Location> locations = ImmutableSet.<Location> of(defaultLocation);
Set<Image> images = ImmutableSet.<Image> of(image);
Set<Size> sizes = ImmutableSet.<Size> of(size);
Provider<Set<? extends Location>> locations = Providers
.<Set<? extends Location>> of(ImmutableSet.<Location> of(defaultLocation));
Provider<Set<? extends Image>> images = Providers.<Set<? extends Image>> of(ImmutableSet
.<Image> of(image));
Provider<Set<? extends Size>> sizes = Providers.<Set<? extends Size>> of(ImmutableSet
.<Size> of(size));
Provider<TemplateOptions> optionsProvider = createMock(Provider.class);
Provider<TemplateBuilder> templateBuilderProvider = createMock(Provider.class);
TemplateBuilder defaultTemplate = createMock(TemplateBuilder.class);
@ -194,9 +204,12 @@ public class TemplateBuilderImplTest {
Size size = new SizeImpl("sizeId", null, "sizeId", defaultLocation, null, ImmutableMap
.<String, String> of(), 0, 0, 0, ImagePredicates.idEquals("imageId"));
Set<Location> locations = ImmutableSet.<Location> of(defaultLocation);
Set<Image> images = ImmutableSet.<Image> of(image);
Set<Size> sizes = ImmutableSet.<Size> of(size);
Provider<Set<? extends Location>> locations = Providers
.<Set<? extends Location>> of(ImmutableSet.<Location> of(defaultLocation));
Provider<Set<? extends Image>> images = Providers.<Set<? extends Image>> of(ImmutableSet
.<Image> of(image));
Provider<Set<? extends Size>> sizes = Providers.<Set<? extends Size>> of(ImmutableSet
.<Size> of(size));
Provider<TemplateOptions> optionsProvider = createMock(Provider.class);
Provider<TemplateBuilder> templateBuilderProvider = createMock(Provider.class);
TemplateBuilder defaultTemplate = createMock(TemplateBuilder.class);
@ -237,9 +250,12 @@ public class TemplateBuilderImplTest {
public void testOptionsUsesDefaultTemplateBuilder() {
TemplateOptions options = new TemplateOptions();
Set<Location> locations = ImmutableSet.<Location> of();
Set<Image> images = ImmutableSet.<Image> of();
Set<Size> sizes = ImmutableSet.<Size> of();
Provider<Set<? extends Location>> locations = Providers
.<Set<? extends Location>> of(ImmutableSet.<Location> of());
Provider<Set<? extends Image>> images = Providers.<Set<? extends Image>> of(ImmutableSet
.<Image> of());
Provider<Set<? extends Size>> sizes = Providers.<Set<? extends Size>> of(ImmutableSet
.<Size> of());
Location defaultLocation = createMock(Location.class);
Provider<TemplateOptions> optionsProvider = createMock(Provider.class);
Provider<TemplateBuilder> templateBuilderProvider = createMock(Provider.class);
@ -268,9 +284,14 @@ public class TemplateBuilderImplTest {
@SuppressWarnings("unchecked")
@Test
public void testNothingUsesDefaultTemplateBuilder() {
Set<Location> locations = ImmutableSet.<Location> of();
Set<Image> images = ImmutableSet.<Image> of();
Set<Size> sizes = ImmutableSet.<Size> of();
Provider<Set<? extends Location>> locations = Providers
.<Set<? extends Location>> of(ImmutableSet.<Location> of());
Provider<Set<? extends Image>> images = Providers.<Set<? extends Image>> of(ImmutableSet
.<Image> of());
Provider<Set<? extends Size>> sizes = Providers.<Set<? extends Size>> of(ImmutableSet
.<Size> of());
Location defaultLocation = createMock(Location.class);
Provider<TemplateOptions> optionsProvider = createMock(Provider.class);
Provider<TemplateBuilder> templateBuilderProvider = createMock(Provider.class);
@ -295,8 +316,9 @@ public class TemplateBuilderImplTest {
verify(templateBuilderProvider);
}
protected TemplateBuilderImpl createTemplateBuilder(Set<Location> locations, Set<Image> images,
Set<Size> sizes, Location defaultLocation, Provider<TemplateOptions> optionsProvider,
protected TemplateBuilderImpl createTemplateBuilder(Provider<Set<? extends Location>> locations,
Provider<Set<? extends Image>> images, Provider<Set<? extends Size>> sizes,
Location defaultLocation, Provider<TemplateOptions> optionsProvider,
Provider<TemplateBuilder> templateBuilderProvider) {
TemplateBuilderImpl template = new TemplateBuilderImpl(locations, images, sizes,
defaultLocation, optionsProvider, templateBuilderProvider);
@ -306,9 +328,12 @@ public class TemplateBuilderImplTest {
@SuppressWarnings("unchecked")
@Test
public void testSuppliedLocationWithNoOptions() {
Set<Location> locations = ImmutableSet.<Location> of();
Set<Image> images = ImmutableSet.<Image> of();
Set<Size> sizes = ImmutableSet.<Size> of();
Provider<Set<? extends Location>> locations = Providers
.<Set<? extends Location>> of(ImmutableSet.<Location> of());
Provider<Set<? extends Image>> images = Providers.<Set<? extends Image>> of(ImmutableSet
.<Image> of());
Provider<Set<? extends Size>> sizes = Providers.<Set<? extends Size>> of(ImmutableSet
.<Size> of());
Location defaultLocation = createMock(Location.class);
Provider<TemplateOptions> optionsProvider = createMock(Provider.class);
Provider<TemplateBuilder> templateBuilderProvider = createMock(Provider.class);
@ -340,9 +365,12 @@ public class TemplateBuilderImplTest {
@SuppressWarnings("unchecked")
@Test
public void testSuppliedLocationAndOptions() {
Set<Location> locations = ImmutableSet.<Location> of();
Set<Image> images = ImmutableSet.<Image> of();
Set<Size> sizes = ImmutableSet.<Size> of();
Provider<Set<? extends Location>> locations = Providers
.<Set<? extends Location>> of(ImmutableSet.<Location> of());
Provider<Set<? extends Image>> images = Providers.<Set<? extends Image>> of(ImmutableSet
.<Image> of());
Provider<Set<? extends Size>> sizes = Providers.<Set<? extends Size>> of(ImmutableSet
.<Size> of());
Location defaultLocation = createMock(Location.class);
Provider<TemplateOptions> optionsProvider = createMock(Provider.class);
Provider<TemplateBuilder> templateBuilderProvider = createMock(Provider.class);
@ -369,9 +397,12 @@ public class TemplateBuilderImplTest {
@SuppressWarnings("unchecked")
@Test
public void testDefaultLocationWithNoOptionsNoSuchElement() {
Set<Location> locations = ImmutableSet.<Location> of();
Set<Image> images = ImmutableSet.<Image> of();
Set<Size> sizes = ImmutableSet.<Size> of();
Provider<Set<? extends Location>> locations = Providers
.<Set<? extends Location>> of(ImmutableSet.<Location> of());
Provider<Set<? extends Image>> images = Providers.<Set<? extends Image>> of(ImmutableSet
.<Image> of());
Provider<Set<? extends Size>> sizes = Providers.<Set<? extends Size>> of(ImmutableSet
.<Size> of());
Location defaultLocation = createMock(Location.class);
Provider<TemplateOptions> optionsProvider = createMock(Provider.class);
Provider<TemplateBuilder> templateBuilderProvider = createMock(Provider.class);
@ -404,9 +435,12 @@ public class TemplateBuilderImplTest {
@SuppressWarnings("unchecked")
@Test
public void testDefaultLocationWithOptions() {
Set<Location> locations = ImmutableSet.<Location> of();
Set<Image> images = ImmutableSet.<Image> of();
Set<Size> sizes = ImmutableSet.<Size> of();
Provider<Set<? extends Location>> locations = Providers
.<Set<? extends Location>> of(ImmutableSet.<Location> of());
Provider<Set<? extends Image>> images = Providers.<Set<? extends Image>> of(ImmutableSet
.<Image> of());
Provider<Set<? extends Size>> sizes = Providers.<Set<? extends Size>> of(ImmutableSet
.<Size> of());
Location defaultLocation = createMock(Location.class);
Provider<TemplateOptions> optionsProvider = createMock(Provider.class);
Provider<TemplateBuilder> templateBuilderProvider = createMock(Provider.class);
@ -435,9 +469,12 @@ public class TemplateBuilderImplTest {
@SuppressWarnings("unchecked")
@Test
public void testImageIdNullsEverythingElse() {
Set<Location> locations = ImmutableSet.<Location> of();
Set<Image> images = ImmutableSet.<Image> of();
Set<Size> sizes = ImmutableSet.<Size> of();
Provider<Set<? extends Location>> locations = Providers
.<Set<? extends Location>> of(ImmutableSet.<Location> of());
Provider<Set<? extends Image>> images = Providers.<Set<? extends Image>> of(ImmutableSet
.<Image> of());
Provider<Set<? extends Size>> sizes = Providers.<Set<? extends Size>> of(ImmutableSet
.<Size> of());
Location defaultLocation = createMock(Location.class);
Provider<TemplateOptions> optionsProvider = createMock(Provider.class);
Provider<TemplateBuilder> templateBuilderProvider = createMock(Provider.class);

View File

@ -0,0 +1,60 @@
/**
*
* 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.concurrent;
import java.util.concurrent.TimeoutException;
import org.jclouds.util.Utils;
import com.google.common.base.Supplier;
import com.google.common.base.Throwables;
/**
*
* @author Adrian Cole
*/
public class RetryOnTimeOutExceptionSupplier<T> implements Supplier<T> {
private final Supplier<T> delegate;
public RetryOnTimeOutExceptionSupplier(Supplier<T> delegate) {
this.delegate = delegate;
}
@Override
public T get() {
TimeoutException ex = null;
for (int i = 0; i < 3; i++) {
try {
ex = null;
return delegate.get();
} catch (Exception e) {
if ((ex = Utils.getFirstThrowableOfType(e, TimeoutException.class)) != null)
continue;
Throwables.propagate(e);
assert false;
return null;
}
}
if (ex != null)
Throwables.propagate(ex);
assert false;
return null;
}
}

View File

@ -126,7 +126,7 @@ public class ExecutorServiceModule extends AbstractModule {
@VisibleForTesting
static ExecutorService newFixedThreadPoolNamed(String name, int maxCount) {
return new ThreadPoolExecutor(0, maxCount, 60L, TimeUnit.SECONDS,
return new ThreadPoolExecutor(maxCount, maxCount, 60L, TimeUnit.SECONDS,
new LinkedBlockingQueue<Runnable>(), new NamingThreadFactory(name));
}

View File

@ -27,12 +27,9 @@ import java.util.Set;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import javax.annotation.Resource;
import javax.inject.Inject;
import javax.inject.Singleton;
import org.jclouds.concurrent.Timeout;
import org.jclouds.logging.Logger;
import com.google.common.base.Throwables;
import com.google.common.collect.ImmutableSet;
@ -45,7 +42,6 @@ import com.google.common.util.concurrent.ListenableFuture;
* @author Adrian Cole
*/
@SuppressWarnings("deprecation")
@Singleton
public class SyncProxy implements InvocationHandler {
@SuppressWarnings("unchecked")
@ -55,8 +51,6 @@ public class SyncProxy implements InvocationHandler {
new SyncProxy(clazz, delegate));
}
@Resource
protected Logger logger = Logger.NULL;
private final Object delegate;
private final Class<?> declaring;
private final Map<Method, Method> methodMap;

View File

@ -195,6 +195,21 @@ public class HttpUtils {
}
}
/**
* Content stream may need to be read. However, we should always close the http stream.
*/
public static void consumeContent(HttpResponse response) {
if (response.getContent() != null) {
try {
ByteStreams.toByteArray(response.getContent());
} catch (IOException e) {
Throwables.propagate(e);
} finally {
Closeables.closeQuietly(response.getContent());
}
}
}
/**
* Content stream may need to be read. However, we should always close the http stream.
*/

View File

@ -32,6 +32,7 @@ import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Set;
import java.util.Map.Entry;
import java.util.regex.Matcher;
@ -42,9 +43,11 @@ import javax.annotation.Resource;
import org.jclouds.logging.Logger;
import com.google.common.base.Charsets;
import com.google.common.base.Predicates;
import com.google.common.base.Supplier;
import com.google.common.base.Throwables;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import com.google.common.io.ByteStreams;
import com.google.common.io.Closeables;
@ -95,6 +98,15 @@ public class Utils {
return null;
}
@SuppressWarnings("unchecked")
public static <T extends Throwable> T getFirstThrowableOfType(Throwable from, Class<T> clazz) {
try {
return (T) Iterables.find(Throwables.getCausalChain(from), Predicates.instanceOf(clazz));
} catch (NoSuchElementException e) {
return null;
}
}
public static Throwable firstRootCauseOrOriginalException(ProvisionException e) {
for (Message message : e.getErrorMessages()) {
Throwable cause = Throwables.getRootCause(message.getCause());
@ -145,7 +157,7 @@ public class Utils {
};
}
public static boolean enventuallyTrue(Supplier<Boolean> assertion, long inconsistencyMillis)
public static boolean eventuallyTrue(Supplier<Boolean> assertion, long inconsistencyMillis)
throws InterruptedException {
for (int i = 0; i < 30; i++) {

View File

@ -0,0 +1,127 @@
/**
*
* 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.concurrent;
import static com.google.common.util.concurrent.MoreExecutors.sameThreadExecutor;
import static org.easymock.EasyMock.expect;
import static org.easymock.classextension.EasyMock.createMock;
import static org.easymock.classextension.EasyMock.replay;
import static org.easymock.classextension.EasyMock.verify;
import static org.testng.Assert.assertEquals;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.TimeoutException;
import org.jclouds.rest.AuthorizationException;
import org.testng.annotations.Test;
import com.google.common.base.Supplier;
/**
* Tests behavior of RetryOnTimeOutExceptionSupplier
*
* @author Adrian Cole
*/
@Test(groups = "unit", testName = "concurrent.RetryOnTimeOutExceptionSupplierTest")
public class RetryOnTimeOutExceptionSupplierTest {
ExecutorService executorService = sameThreadExecutor();
@SuppressWarnings("unchecked")
@Test
public void testGetThrowsOriginalExceptionButRetriesOnTimeoutException() throws InterruptedException, ExecutionException {
Supplier<String> delegate = createMock(Supplier.class);
TimeoutException timeout = createMock(TimeoutException.class);
RuntimeException throwable = new RuntimeException(timeout);
expect(delegate.get()).andThrow(throwable);
expect(timeout.getCause()).andReturn(null).anyTimes();
expect(delegate.get()).andThrow(throwable);
expect(delegate.get()).andThrow(throwable);
replay(delegate);
replay(timeout);
RetryOnTimeOutExceptionSupplier<String> supplier = new RetryOnTimeOutExceptionSupplier<String>(
delegate);
try {
supplier.get();
assert false;
} catch (RuntimeException e) {
assertEquals(e.getCause(), timeout);
}
verify(delegate);
verify(timeout);
}
@SuppressWarnings("unchecked")
@Test
public void testGetAllowsTwoFailuresOnTimeoutException() throws InterruptedException, ExecutionException {
Supplier<String> delegate = createMock(Supplier.class);
TimeoutException timeout = createMock(TimeoutException.class);
RuntimeException throwable = new RuntimeException(timeout);
expect(delegate.get()).andThrow(throwable);
expect(timeout.getCause()).andReturn(null).anyTimes();
expect(delegate.get()).andThrow(throwable);
expect(delegate.get()).andReturn("foo");
replay(delegate);
replay(timeout);
RetryOnTimeOutExceptionSupplier<String> supplier = new RetryOnTimeOutExceptionSupplier<String>(
delegate);
assertEquals(supplier.get(), "foo");
verify(delegate);
verify(timeout);
}
@SuppressWarnings("unchecked")
@Test
public void testGetAllowsNoFailuresOnOtherExceptions() throws InterruptedException, ExecutionException {
Supplier<String> delegate = createMock(Supplier.class);
AuthorizationException auth = createMock(AuthorizationException.class);
RuntimeException throwable = new RuntimeException(auth);
expect(delegate.get()).andThrow(throwable);
expect(auth.getCause()).andReturn(null).anyTimes();
replay(delegate);
replay(auth);
RetryOnTimeOutExceptionSupplier<String> supplier = new RetryOnTimeOutExceptionSupplier<String>(
delegate);
try {
supplier.get();
assert false;
} catch (RuntimeException e) {
assertEquals(e.getCause(), auth);
}
verify(delegate);
verify(auth);
}
}

View File

@ -22,6 +22,7 @@ import static org.easymock.classextension.EasyMock.createMock;
import static org.testng.Assert.assertEquals;
import java.io.UnsupportedEncodingException;
import java.util.concurrent.TimeoutException;
import org.jclouds.rest.AuthorizationException;
import org.testng.annotations.Test;
@ -46,6 +47,25 @@ public class UtilsTest {
assertEquals(Utils.firstRootCauseOrOriginalException(pex), aex);
}
public void testGetFirstThrowableOfTypeOuter() {
AuthorizationException aex = createMock(AuthorizationException.class);
assertEquals(Utils.getFirstThrowableOfType(aex, AuthorizationException.class), aex);
}
public void testGetFirstThrowableOfTypeInner() {
AuthorizationException aex = createMock(AuthorizationException.class);
Message message = new Message(ImmutableList.of(), "test", aex);
ProvisionException pex = new ProvisionException(ImmutableSet.of(message));
assertEquals(Utils.getFirstThrowableOfType(pex, AuthorizationException.class), aex);
}
public void testGetFirstThrowableOfTypeFail() {
TimeoutException aex = createMock(TimeoutException.class);
Message message = new Message(ImmutableList.of(), "test", aex);
ProvisionException pex = new ProvisionException(ImmutableSet.of(message));
assertEquals(Utils.getFirstThrowableOfType(pex, AuthorizationException.class), null);
}
public void testReplaceTokens() throws UnsupportedEncodingException {
assertEquals(Utils.replaceTokens("hello {where}", ImmutableMap.of("where", "world")),
"hello world");

View File

@ -37,8 +37,8 @@ import javax.inject.Inject;
import javax.inject.Named;
import javax.inject.Singleton;
import org.jclouds.compute.ComputeService;
import org.jclouds.compute.ComputeServiceContext;
import org.jclouds.compute.LoadBalancerService;
import org.jclouds.compute.domain.Architecture;
import org.jclouds.compute.domain.ComputeMetadata;
import org.jclouds.compute.domain.Image;
@ -76,7 +76,6 @@ import org.jclouds.gogrid.predicates.ServerLatestJobCompleted;
import org.jclouds.gogrid.util.GoGridUtils;
import org.jclouds.logging.Logger;
import org.jclouds.predicates.RetryablePredicate;
import org.jclouds.rest.RestContext;
import com.google.common.base.Function;
import com.google.common.base.Predicate;
@ -86,7 +85,9 @@ import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import com.google.common.collect.Sets;
import com.google.inject.Provides;
import com.google.inject.Scopes;
import com.google.inject.TypeLiteral;
import com.google.inject.util.Providers;
/**
* @author Oleksiy Yarmula
@ -103,6 +104,10 @@ public class GoGridComputeServiceContextModule extends GoGridContextModule {
super.configure();
bind(new TypeLiteral<Function<Server, NodeMetadata>>() {
}).to(ServerToNodeMetadata.class);
bind(LoadBalancerService.class).toProvider(Providers.<LoadBalancerService> of(null));
bind(new TypeLiteral<ComputeServiceContext>() {
}).to(new TypeLiteral<ComputeServiceContextImpl<GoGridAsyncClient, GoGridClient>>() {
}).in(Scopes.SINGLETON);
bind(AddNodeWithTagStrategy.class).to(GoGridAddNodeWithTagStrategy.class);
bind(ListNodesStrategy.class).to(GoGridListNodesStrategy.class);
bind(GetNodeMetadataStrategy.class).to(GoGridGetNodeMetadataStrategy.class);
@ -269,13 +274,6 @@ public class GoGridComputeServiceContextModule extends GoGridContextModule {
};
}
@Provides
@Singleton
ComputeServiceContext provideContext(ComputeService computeService,
RestContext<GoGridAsyncClient, GoGridClient> context) {
return new ComputeServiceContextImpl<GoGridAsyncClient, GoGridClient>(computeService, context);
}
@Provides
@Singleton
@Named("NOT_RUNNING")

View File

@ -36,8 +36,8 @@ import javax.inject.Named;
import javax.inject.Singleton;
import org.jclouds.Constants;
import org.jclouds.compute.ComputeService;
import org.jclouds.compute.ComputeServiceContext;
import org.jclouds.compute.LoadBalancerService;
import org.jclouds.compute.domain.Architecture;
import org.jclouds.compute.domain.ComputeMetadata;
import org.jclouds.compute.domain.Image;
@ -79,7 +79,6 @@ import org.jclouds.rackspace.cloudservers.domain.ServerStatus;
import org.jclouds.rackspace.cloudservers.options.ListOptions;
import org.jclouds.rackspace.config.RackspaceLocationsModule;
import org.jclouds.rackspace.reference.RackspaceConstants;
import org.jclouds.rest.RestContext;
import com.google.common.base.Function;
import com.google.common.base.Predicate;
@ -88,7 +87,9 @@ import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Iterables;
import com.google.common.collect.Sets;
import com.google.inject.Provides;
import com.google.inject.Scopes;
import com.google.inject.TypeLiteral;
import com.google.inject.util.Providers;
/**
* Configures the {@link CloudServersComputeServiceContext}; requires {@link BaseComputeService}
@ -109,6 +110,12 @@ public class CloudServersComputeServiceContextModule extends CloudServersContext
install(new RackspaceLocationsModule(providerName));
bind(new TypeLiteral<Function<Server, NodeMetadata>>() {
}).to(ServerToNodeMetadata.class);
bind(LoadBalancerService.class).toProvider(Providers.<LoadBalancerService> of(null));
bind(new TypeLiteral<ComputeServiceContext>() {
})
.to(
new TypeLiteral<ComputeServiceContextImpl<CloudServersAsyncClient, CloudServersClient>>() {
}).in(Scopes.SINGLETON);
bind(AddNodeWithTagStrategy.class).to(CloudServersAddNodeWithTagStrategy.class);
bind(ListNodesStrategy.class).to(CloudServersListNodesStrategy.class);
bind(GetNodeMetadataStrategy.class).to(CloudServersGetNodeMetadataStrategy.class);
@ -279,14 +286,6 @@ public class CloudServersComputeServiceContextModule extends CloudServersContext
.put(ServerStatus.UNKNOWN, NodeState.UNKNOWN).build();
}
@Provides
@Singleton
ComputeServiceContext provideContext(ComputeService computeService,
RestContext<CloudServersAsyncClient, CloudServersClient> context) {
return new ComputeServiceContextImpl<CloudServersAsyncClient, CloudServersClient>(
computeService, context);
}
@Provides
@Singleton
@Named("NOT_RUNNING")

View File

@ -32,6 +32,7 @@ import javax.inject.Named;
import javax.inject.Singleton;
import org.jclouds.concurrent.ExpirableSupplier;
import org.jclouds.concurrent.RetryOnTimeOutExceptionSupplier;
import org.jclouds.date.TimeStamp;
import org.jclouds.http.RequiresHttp;
import org.jclouds.rackspace.Authentication;
@ -80,18 +81,22 @@ public class RackspaceAuthenticationRestModule extends AbstractModule {
Supplier<AuthenticationResponse> provideAuthenticationResponseCache(
final RestClientFactory factory, @Named(PROPERTY_RACKSPACE_USER) final String user,
@Named(PROPERTY_RACKSPACE_KEY) final String key) {
return new ExpirableSupplier<AuthenticationResponse>(new Supplier<AuthenticationResponse>() {
return new ExpirableSupplier<AuthenticationResponse>(
new RetryOnTimeOutExceptionSupplier<AuthenticationResponse>(
new Supplier<AuthenticationResponse>() {
public AuthenticationResponse get() {
try {
ListenableFuture<AuthenticationResponse> response = factory.create(
RackspaceAuthentication.class).authenticate(user, key);
ListenableFuture<AuthenticationResponse> response = factory
.create(RackspaceAuthentication.class).authenticate(user,
key);
return response.get(30, TimeUnit.SECONDS);
} catch (Exception e) {
Throwables.propagateIfPossible(e);
throw new RuntimeException("Error logging in", e);
Throwables.propagate(e);
assert false : e;
return null;
}
}
}, 23, TimeUnit.HOURS);
}), 23, TimeUnit.HOURS);
}
@Provides

View File

@ -40,8 +40,8 @@ import javax.inject.Named;
import javax.inject.Singleton;
import org.jclouds.Constants;
import org.jclouds.compute.ComputeService;
import org.jclouds.compute.ComputeServiceContext;
import org.jclouds.compute.LoadBalancerService;
import org.jclouds.compute.domain.Architecture;
import org.jclouds.compute.domain.ComputeMetadata;
import org.jclouds.compute.domain.Image;
@ -71,7 +71,6 @@ import org.jclouds.domain.LocationScope;
import org.jclouds.domain.internal.LocationImpl;
import org.jclouds.logging.Logger;
import org.jclouds.predicates.RetryablePredicate;
import org.jclouds.rest.RestContext;
import org.jclouds.rimuhosting.miro.RimuHostingAsyncClient;
import org.jclouds.rimuhosting.miro.RimuHostingClient;
import org.jclouds.rimuhosting.miro.config.RimuHostingContextModule;
@ -89,7 +88,9 @@ import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import com.google.common.collect.Sets;
import com.google.inject.Provides;
import com.google.inject.Scopes;
import com.google.inject.TypeLiteral;
import com.google.inject.util.Providers;
/**
* Configures the {@link RimuHostingComputeServiceContext}; requires
@ -109,6 +110,12 @@ public class RimuHostingComputeServiceContextModule extends RimuHostingContextMo
super.configure();
bind(new TypeLiteral<Function<Server, NodeMetadata>>() {
}).to(ServerToNodeMetadata.class);
bind(LoadBalancerService.class).toProvider(Providers.<LoadBalancerService> of(null));
bind(new TypeLiteral<ComputeServiceContext>() {
})
.to(
new TypeLiteral<ComputeServiceContextImpl<RimuHostingAsyncClient, RimuHostingClient>>() {
}).in(Scopes.SINGLETON);
bind(new TypeLiteral<Function<Server, Iterable<InetAddress>>>() {
}).to(ServerToPublicAddresses.class);
bind(AddNodeWithTagStrategy.class).to(RimuHostingAddNodeWithTagStrategy.class);
@ -352,14 +359,6 @@ public class RimuHostingComputeServiceContextModule extends RimuHostingContextMo
}
}
@Provides
@Singleton
ComputeServiceContext provideContext(ComputeService computeService,
RestContext<RimuHostingAsyncClient, RimuHostingClient> context) {
return new ComputeServiceContextImpl<RimuHostingAsyncClient, RimuHostingClient>(
computeService, context);
}
@Provides
@Singleton
@Named("NOT_RUNNING")

View File

@ -0,0 +1,61 @@
package org.jclouds.vcloud.bluelock;
import static com.google.common.base.Preconditions.checkNotNull;
import static org.jclouds.vcloud.reference.VCloudConstants.PROPERTY_VCLOUD_SESSIONINTERVAL;
import java.io.IOException;
import java.util.Properties;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeoutException;
import org.jclouds.compute.ComputeServiceContext;
import org.jclouds.compute.ComputeServiceContextFactory;
import org.jclouds.logging.log4j.config.Log4JLoggingModule;
import org.jclouds.vcloud.VCloudClient;
import org.testng.annotations.AfterTest;
import org.testng.annotations.BeforeGroups;
import org.testng.annotations.Test;
import com.google.common.collect.ImmutableSet;
import com.google.inject.Module;
/**
* Tests session refresh works
*
* @author Adrian Cole
*/
@Test(groups = "live", sequential = true, testName = "vcloud.VCloudSessionRefreshLiveTest")
public class VCloudSessionRefreshLiveTest {
private final static int timeOut = 40;
protected VCloudClient connection;
protected String account;
protected ComputeServiceContext context;
@Test
public void testSessionRefresh() throws Exception {
connection.getDefaultOrganization();
Thread.sleep(timeOut * 1000);
connection.getDefaultOrganization();
}
@BeforeGroups(groups = { "live" })
public void setupClient() throws IOException {
account = checkNotNull(System.getProperty("jclouds.test.user"), "jclouds.test.user");
String key = checkNotNull(System.getProperty("jclouds.test.key"), "jclouds.test.key");
Properties props = new Properties();
props.setProperty(PROPERTY_VCLOUD_SESSIONINTERVAL, 40 + "");
context = new ComputeServiceContextFactory().createContext("bluelock", account, key,
ImmutableSet.<Module> of(new Log4JLoggingModule()), props);
connection = VCloudClient.class.cast(context.getProviderSpecificContext().getApi());
}
@AfterTest
protected void cleanup() throws InterruptedException, ExecutionException, TimeoutException {
context.close();
}
}

View File

@ -27,8 +27,8 @@ import java.util.concurrent.TimeUnit;
import javax.inject.Named;
import javax.inject.Singleton;
import org.jclouds.compute.ComputeService;
import org.jclouds.compute.ComputeServiceContext;
import org.jclouds.compute.LoadBalancerService;
import org.jclouds.compute.domain.ComputeMetadata;
import org.jclouds.compute.domain.Image;
import org.jclouds.compute.domain.NodeState;
@ -45,7 +45,6 @@ import org.jclouds.compute.strategy.RebootNodeStrategy;
import org.jclouds.compute.strategy.RunNodesAndAddToSetStrategy;
import org.jclouds.domain.Location;
import org.jclouds.predicates.RetryablePredicate;
import org.jclouds.rest.RestContext;
import org.jclouds.vcloud.VCloudAsyncClient;
import org.jclouds.vcloud.VCloudClient;
import org.jclouds.vcloud.compute.BaseVCloudComputeClient;
@ -70,6 +69,7 @@ import com.google.common.collect.Iterables;
import com.google.inject.Provides;
import com.google.inject.Scopes;
import com.google.inject.TypeLiteral;
import com.google.inject.util.Providers;
/**
* Configures the {@link VCloudComputeServiceContext}; requires {@link BaseVCloudComputeClient}
@ -85,14 +85,13 @@ public class VCloudComputeServiceContextModule extends VCloudContextModule {
this.providerName = providerName;
}
@Singleton
@Provides
Map<VAppStatus, NodeState> provideVAppStatusToNodeState() {
return ImmutableMap.<VAppStatus, NodeState> builder().put(VAppStatus.OFF,
NodeState.SUSPENDED).put(VAppStatus.ON, NodeState.RUNNING).put(VAppStatus.RESOLVED,
NodeState.PENDING).put(VAppStatus.SUSPENDED, NodeState.SUSPENDED).put(
VAppStatus.UNRESOLVED, NodeState.PENDING).build();
return ImmutableMap.<VAppStatus, NodeState> builder()
.put(VAppStatus.OFF, NodeState.SUSPENDED).put(VAppStatus.ON, NodeState.RUNNING).put(
VAppStatus.RESOLVED, NodeState.PENDING).put(VAppStatus.SUSPENDED,
NodeState.SUSPENDED).put(VAppStatus.UNRESOLVED, NodeState.PENDING).build();
}
@Provides
@ -106,12 +105,16 @@ public class VCloudComputeServiceContextModule extends VCloudContextModule {
super.configure();
bind(String.class).annotatedWith(VCloud.class).toInstance(providerName);
bind(AddNodeWithTagStrategy.class).to(VCloudAddNodeWithTagStrategy.class);
bind(new TypeLiteral<ComputeServiceContext>() {
}).to(new TypeLiteral<ComputeServiceContextImpl<VCloudAsyncClient, VCloudClient>>() {
}).in(Scopes.SINGLETON);
bind(RunNodesAndAddToSetStrategy.class).to(
EncodeTemplateIdIntoNameRunNodesAndAddToSetStrategy.class);
bind(ListNodesStrategy.class).to(VCloudListNodesStrategy.class);
bind(GetNodeMetadataStrategy.class).to(VCloudGetNodeMetadataStrategy.class);
bind(RebootNodeStrategy.class).to(VCloudRebootNodeStrategy.class);
bind(DestroyNodeStrategy.class).to(VCloudDestroyNodeStrategy.class);
bindLoadBalancer();
bindSizes();
bindImages();
bindLocations();
@ -132,11 +135,8 @@ public class VCloudComputeServiceContextModule extends VCloudContextModule {
TimeUnit.SECONDS);
}
@Provides
@Singleton
protected ComputeServiceContext provideContext(ComputeService computeService,
RestContext<VCloudAsyncClient, VCloudClient> context) {
return new ComputeServiceContextImpl<VCloudAsyncClient, VCloudClient>(computeService, context);
protected void bindLoadBalancer() {
bind(LoadBalancerService.class).toProvider(Providers.<LoadBalancerService> of(null));
}
protected void bindImages() {

View File

@ -23,6 +23,7 @@ import java.util.Set;
import javax.annotation.Resource;
import javax.inject.Inject;
import javax.inject.Provider;
import javax.inject.Singleton;
import org.jclouds.domain.Location;
@ -43,11 +44,12 @@ public class FindLocationForResourceInVDC {
@Resource
protected Logger logger = Logger.NULL;
final Set<? extends Location> locations;
final Provider<Set<? extends Location>> locations;
final Location defaultLocation;
@Inject
public FindLocationForResourceInVDC(Set<? extends Location> locations, Location defaultLocation) {
public FindLocationForResourceInVDC(Provider<Set<? extends Location>> locations,
Location defaultLocation) {
this.locations = locations;
this.defaultLocation = defaultLocation;
}
@ -55,7 +57,7 @@ public class FindLocationForResourceInVDC {
public Location apply(NamedResource resource, final String vdcId) {
Location location = null;
try {
location = Iterables.find(locations, new Predicate<Location>() {
location = Iterables.find(locations.get(), new Predicate<Location>() {
@Override
public boolean apply(Location input) {

View File

@ -29,6 +29,7 @@ import java.util.regex.Pattern;
import javax.annotation.Resource;
import javax.inject.Inject;
import javax.inject.Named;
import javax.inject.Provider;
import javax.inject.Singleton;
import org.jclouds.compute.domain.Image;
@ -62,7 +63,7 @@ public class VCloudGetNodeMetadata {
public Logger logger = Logger.NULL;
protected final VCloudClient client;
protected final VCloudComputeClient computeClient;
protected final Set<? extends Image> images;
protected final Provider<Set<? extends Image>> images;
protected final FindLocationForResourceInVDC findLocationForResourceInVDC;
protected final GetExtra getExtra;
protected final Map<VAppStatus, NodeState> vAppStatusToNodeState;
@ -76,7 +77,8 @@ public class VCloudGetNodeMetadata {
@Inject
protected VCloudGetNodeMetadata(VCloudClient client, VCloudComputeClient computeClient,
Map<VAppStatus, NodeState> vAppStatusToNodeState, GetExtra getExtra,
FindLocationForResourceInVDC findLocationForResourceInVDC, Set<? extends Image> images) {
FindLocationForResourceInVDC findLocationForResourceInVDC,
Provider<Set<? extends Image>> images) {
this.client = checkNotNull(client, "client");
this.images = checkNotNull(images, "images");
this.getExtra = checkNotNull(getExtra, "getExtra");
@ -99,11 +101,12 @@ public class VCloudGetNodeMetadata {
String templateIdInHexWithoutLeadingZeros = matcher.group(2).replaceAll("^[0]+", "");
final String templateId = Integer.parseInt(templateIdInHexWithoutLeadingZeros, 16) + "";
try {
image = Iterables.find(images, new Predicate<Image>() {
image = Iterables.find(images.get(), new Predicate<Image>() {
@Override
public boolean apply(Image input) {
return input.getProviderId().equals(templateId) && input.getLocation().equals(location);
return input.getProviderId().equals(templateId)
&& input.getLocation().equals(location);
}
});

View File

@ -24,6 +24,7 @@ import java.util.Map;
import java.util.Set;
import javax.inject.Inject;
import javax.inject.Provider;
import javax.inject.Singleton;
import org.jclouds.compute.domain.Image;
@ -47,7 +48,8 @@ public class VCloudGetNodeMetadataStrategy extends VCloudGetNodeMetadata impleme
@Inject
protected VCloudGetNodeMetadataStrategy(VCloudClient client, VCloudComputeClient computeClient,
Map<VAppStatus, NodeState> vAppStatusToNodeState, GetExtra getExtra,
FindLocationForResourceInVDC findLocationForResourceInVDC, Set<? extends Image> images) {
FindLocationForResourceInVDC findLocationForResourceInVDC,
Provider<Set<? extends Image>> images) {
super(client, computeClient, vAppStatusToNodeState, getExtra, findLocationForResourceInVDC,
images);
}

View File

@ -24,6 +24,7 @@ import java.util.Set;
import javax.annotation.Resource;
import javax.inject.Inject;
import javax.inject.Named;
import javax.inject.Provider;
import javax.inject.Singleton;
import org.jclouds.compute.domain.ComputeMetadata;
@ -62,7 +63,8 @@ public class VCloudListNodesStrategy extends VCloudGetNodeMetadata implements Li
@Inject
protected VCloudListNodesStrategy(VCloudClient client, VCloudComputeClient computeClient,
Map<VAppStatus, NodeState> vAppStatusToNodeState, GetExtra getExtra,
FindLocationForResourceInVDC findLocationForResourceInVDC, Set<? extends Image> images) {
FindLocationForResourceInVDC findLocationForResourceInVDC,
Provider<Set<? extends Image>> images) {
super(client, computeClient, vAppStatusToNodeState, getExtra, findLocationForResourceInVDC,
images);
}

View File

@ -42,6 +42,7 @@ import javax.inject.Named;
import javax.inject.Singleton;
import org.jclouds.concurrent.ExpirableSupplier;
import org.jclouds.concurrent.RetryOnTimeOutExceptionSupplier;
import org.jclouds.concurrent.internal.SyncProxy;
import org.jclouds.encryption.EncryptionService;
import org.jclouds.http.HttpErrorHandler;
@ -158,17 +159,19 @@ public class VCloudRestClientModule extends AbstractModule {
@Singleton
Supplier<VCloudSession> provideVCloudTokenCache(
@Named(PROPERTY_VCLOUD_SESSIONINTERVAL) long seconds, final VCloudLoginAsyncClient login) {
return new ExpirableSupplier<VCloudSession>(new Supplier<VCloudSession>() {
return new ExpirableSupplier<VCloudSession>(
new RetryOnTimeOutExceptionSupplier<VCloudSession>(new Supplier<VCloudSession>() {
public VCloudSession get() {
try {
return login.login().get(180, TimeUnit.SECONDS);
return login.login().get(10, TimeUnit.SECONDS);
} catch (Exception e) {
Throwables.propagate(e);
assert false;
assert false : e;
return null;
}
}
}, seconds, TimeUnit.SECONDS);
}), seconds, TimeUnit.SECONDS);
}
@Provides

View File

@ -31,6 +31,7 @@ import javax.ws.rs.core.HttpHeaders;
import org.jclouds.http.HttpResponse;
import org.jclouds.http.HttpResponseException;
import org.jclouds.http.HttpUtils;
import org.jclouds.http.functions.ParseSax;
import org.jclouds.http.functions.ParseSax.Factory;
import org.jclouds.vcloud.VCloudToken;
@ -48,7 +49,7 @@ import com.google.common.base.Function;
*/
@Singleton
public class ParseLoginResponseFromHeaders implements Function<HttpResponse, VCloudSession> {
static final Pattern pattern = Pattern.compile("vcloud-token=(.*); [Pp]ath=.*");
static final Pattern pattern = Pattern.compile("vcloud-token=([^;]+);.*");
private final ParseSax.Factory factory;
private final Provider<OrgListHandler> orgHandlerProvider;
@ -87,6 +88,7 @@ public class ParseLoginResponseFromHeaders implements Function<HttpResponse, VCl
};
} else {
HttpUtils.consumeContent(from);
throw new HttpResponseException("vcloud token not found in response ", null, from);
}
}

View File

@ -33,6 +33,8 @@ import java.util.SortedSet;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeoutException;
import javax.inject.Provider;
import org.jclouds.compute.domain.Image;
import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.domain.NodeState;
@ -59,6 +61,7 @@ import com.google.common.collect.ImmutableSortedSet;
import com.google.common.collect.ListMultimap;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import com.google.inject.util.Providers;
/**
* @author Adrian Cole
@ -112,9 +115,10 @@ public class VCloudListNodesStrategyTest {
replay(computeClient);
Location vdcL = new LocationImpl(LocationScope.ZONE, "1", "1", null);
Set<? extends Location> locations = ImmutableSet.of(vdcL);
Set<? extends Image> images = ImmutableSet.of();
Provider<Set<? extends Location>> locations = Providers
.<Set<? extends Location>> of(ImmutableSet.of(vdcL));
Provider<Set<? extends Image>> images = Providers.<Set<? extends Image>> of(ImmutableSet
.<Image> of());
FindLocationForResourceInVDC findLocationForResourceInVDC = new FindLocationForResourceInVDC(
locations, null);
VCloudListNodesStrategy strategy = new VCloudListNodesStrategy(client, computeClient,

View File

@ -65,4 +65,23 @@ public class ParseLoginResponseFromHeadersTest extends BaseHandlerTest {
}
@Test
public void testApplyBlueLock() {
HttpResponse response = new HttpResponse();
response.setMessage("OK");
response.setStatusCode(200);
response.setContent(getClass().getResourceAsStream("/orglist.xml"));
response.getHeaders().put(HttpHeaders.SET_COOKIE,
"vcloud-token=c9f232506df9b65d7b7d97b7499eddd7; Domain=.bluelock.com; Path=/");
response.getHeaders().put(HttpHeaders.CONTENT_LENGTH, "307");
response.getHeaders().put(HttpHeaders.CONTENT_TYPE,
"Content-Type: application/xml; charset=utf-8");
VCloudSession reply = parser.apply(response);
assertEquals(reply.getVCloudToken(), "c9f232506df9b65d7b7d97b7499eddd7");
assertEquals(reply.getOrgs(), ImmutableMap.of("adrian@jclouds.org", new NamedResourceImpl("48",
"adrian@jclouds.org", VCloudMediaType.ORG_XML, URI
.create("https://services.vcloudexpress.terremark.com/api/v0.8/org/48"))));
}
}

View File

@ -57,9 +57,16 @@ public class TerremarkVCloudComputeServiceContextModule extends VCloudComputeSer
bind(VCloudComputeClient.class).to(TerremarkVCloudComputeClient.class);
bind(PopulateDefaultLoginCredentialsForImageStrategy.class).to(
ParseVAppTemplateDescriptionToGetDefaultLoginCredentials.class);
}
// TODO
// @Override
// protected void bindLoadBalancer() {
// bind(LoadBalanceNodesStrategy.class).to(TerremarkLoadBalanceNodesStrategy.class);
// bind(DestroyLoadBalancerStrategy.class).to(TerremarkDestroyLoadBalancerStrategy.class);
// }
//
@Named("PASSWORD")
@Provides
String providePassword() {