Issue 283 added

client.templateOptions().blockUntilRunning(false) and Issue 284: consolidated timeout properties into ComputeServiceConstants
This commit is contained in:
Adrian Cole 2010-06-14 23:51:11 -04:00
parent ffaea53022
commit aabaae2a51
68 changed files with 3348 additions and 2473 deletions

View File

@ -34,6 +34,7 @@ import ${package}.config.${providerName}ContextModule;
import org.jclouds.compute.ComputeServiceContext; import org.jclouds.compute.ComputeServiceContext;
import org.jclouds.compute.LoadBalancerService; import org.jclouds.compute.LoadBalancerService;
import org.jclouds.compute.config.ComputeServiceTimeoutsModule;
import org.jclouds.compute.domain.ComputeMetadata; import org.jclouds.compute.domain.ComputeMetadata;
import org.jclouds.compute.domain.Image; import org.jclouds.compute.domain.Image;
import org.jclouds.compute.domain.NodeMetadata; import org.jclouds.compute.domain.NodeMetadata;
@ -80,6 +81,7 @@ public class ${providerName}ComputeServiceContextModule extends ${providerName}C
@Override @Override
protected void configure() { protected void configure() {
super.configure(); super.configure();
install(new ComputeServiceTimeoutsModule());
bind(new TypeLiteral<ComputeServiceContext>() { bind(new TypeLiteral<ComputeServiceContext>() {
}) })
.to( .to(
@ -92,12 +94,6 @@ public class ${providerName}ComputeServiceContextModule extends ${providerName}C
bind(DestroyNodeStrategy.class).to(${providerName}DestroyNodeStrategy.class); bind(DestroyNodeStrategy.class).to(${providerName}DestroyNodeStrategy.class);
bind(LoadBalancerService.class).toProvider(Providers.<LoadBalancerService> of(null)); bind(LoadBalancerService.class).toProvider(Providers.<LoadBalancerService> of(null));
} }
@Provides
@Singleton
protected Predicate<IPSocket> socketTester(SocketOpen open) {
return new RetryablePredicate<IPSocket>(open, 130, 1, TimeUnit.SECONDS);
}
/** /**
* tested known configuration * tested known configuration
@ -204,14 +200,6 @@ public class ${providerName}ComputeServiceContextModule extends ${providerName}C
} }
} }
@Provides
@Singleton
@Named("NOT_RUNNING")
protected Predicate<CommandUsingClient> runScriptRunning(ScriptStatusReturnsZero stateRunning) {
return new RetryablePredicate<CommandUsingClient>(Predicates.not(stateRunning), 600, 3,
TimeUnit.SECONDS);
}
@Provides @Provides
@Singleton @Singleton

View File

@ -66,18 +66,27 @@ public class EC2ComputeService extends BaseComputeService {
@Inject @Inject
protected EC2ComputeService(ComputeServiceContext context, protected EC2ComputeService(ComputeServiceContext context,
Provider<Set<? extends Image>> images, Provider<Set<? extends Size>> sizes, Provider<Set<? extends Image>> images,
Provider<Set<? extends Location>> locations, ListNodesStrategy listNodesStrategy, Provider<Set<? extends Size>> sizes,
GetNodeMetadataStrategy getNodeMetadataStrategy, Provider<Set<? extends Location>> locations,
RunNodesAndAddToSetStrategy runNodesAndAddToSetStrategy, ListNodesStrategy listNodesStrategy,
RebootNodeStrategy rebootNodeStrategy, DestroyNodeStrategy destroyNodeStrategy, GetNodeMetadataStrategy getNodeMetadataStrategy,
Provider<TemplateBuilder> templateBuilderProvider, RunNodesAndAddToSetStrategy runNodesAndAddToSetStrategy,
Provider<TemplateOptions> templateOptionsProvider, ComputeUtils utils, RebootNodeStrategy rebootNodeStrategy,
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService executor, EC2Client ec2Client, DestroyNodeStrategy destroyNodeStrategy,
Map<RegionAndName, KeyPair> credentialsMap, Map<RegionAndName, String> securityGroupMap) { Provider<TemplateBuilder> templateBuilderProvider,
super(context, images, sizes, locations, listNodesStrategy, getNodeMetadataStrategy, Provider<TemplateOptions> templateOptionsProvider,
runNodesAndAddToSetStrategy, rebootNodeStrategy, destroyNodeStrategy, @Named("NODE_RUNNING") Predicate<NodeMetadata> nodeRunning,
templateBuilderProvider, templateOptionsProvider, utils, executor); @Named("NODE_TERMINATED") Predicate<NodeMetadata> nodeTerminated,
ComputeUtils utils,
@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, nodeRunning, nodeTerminated, utils,
executor);
this.ec2Client = ec2Client; this.ec2Client = ec2Client;
this.credentialsMap = credentialsMap; this.credentialsMap = credentialsMap;
this.securityGroupMap = securityGroupMap; this.securityGroupMap = securityGroupMap;
@ -86,38 +95,46 @@ public class EC2ComputeService extends BaseComputeService {
private void deleteSecurityGroup(String region, String tag) { private void deleteSecurityGroup(String region, String tag) {
checkNotEmpty(tag, "tag"); checkNotEmpty(tag, "tag");
String group = "jclouds#" + tag; String group = "jclouds#" + tag;
if (ec2Client.getSecurityGroupServices().describeSecurityGroupsInRegion(region, group).size() > 0) { if (ec2Client.getSecurityGroupServices().describeSecurityGroupsInRegion(
region, group).size() > 0) {
logger.debug(">> deleting securityGroup(%s)", group); logger.debug(">> deleting securityGroup(%s)", group);
ec2Client.getSecurityGroupServices().deleteSecurityGroupInRegion(region, group); ec2Client.getSecurityGroupServices().deleteSecurityGroupInRegion(
region, group);
// TODO: test this clear happens // TODO: test this clear happens
securityGroupMap.remove(new RegionNameAndIngressRules(region, tag, null, false)); securityGroupMap.remove(new RegionNameAndIngressRules(region, tag,
null, false));
logger.debug("<< deleted securityGroup(%s)", group); logger.debug("<< deleted securityGroup(%s)", group);
} }
} }
private void deleteKeyPair(String region, String tag) { private void deleteKeyPair(String region, String tag) {
for (KeyPair keyPair : ec2Client.getKeyPairServices().describeKeyPairsInRegion(region)) { for (KeyPair keyPair : ec2Client.getKeyPairServices()
.describeKeyPairsInRegion(region)) {
if (keyPair.getKeyName().matches("jclouds#" + tag + "-[0-9]+")) { if (keyPair.getKeyName().matches("jclouds#" + tag + "-[0-9]+")) {
logger.debug(">> deleting keyPair(%s)", keyPair.getKeyName()); logger.debug(">> deleting keyPair(%s)", keyPair.getKeyName());
ec2Client.getKeyPairServices().deleteKeyPairInRegion(region, keyPair.getKeyName()); ec2Client.getKeyPairServices().deleteKeyPairInRegion(region,
keyPair.getKeyName());
// TODO: test this clear happens // TODO: test this clear happens
credentialsMap.remove(new RegionAndName(region, keyPair.getKeyName())); credentialsMap.remove(new RegionAndName(region, keyPair
.getKeyName()));
logger.debug("<< deleted keyPair(%s)", keyPair.getKeyName()); logger.debug("<< deleted keyPair(%s)", keyPair.getKeyName());
} }
} }
} }
/** /**
* like {@link BaseComputeService#destroyNodesMatching} except that this will clean implicit * like {@link BaseComputeService#destroyNodesMatching} except that this will
* keypairs and security groups. * clean implicit keypairs and security groups.
*/ */
@Override @Override
public Set<? extends NodeMetadata> destroyNodesMatching(Predicate<NodeMetadata> filter) { public Set<? extends NodeMetadata> destroyNodesMatching(
Predicate<NodeMetadata> filter) {
Set<? extends NodeMetadata> deadOnes = super.destroyNodesMatching(filter); Set<? extends NodeMetadata> deadOnes = super.destroyNodesMatching(filter);
Map<String, String> regionTags = Maps.newHashMap(); Map<String, String> regionTags = Maps.newHashMap();
for (NodeMetadata nodeMetadata : deadOnes) { for (NodeMetadata nodeMetadata : deadOnes) {
if (nodeMetadata.getTag() != null) if (nodeMetadata.getTag() != null)
regionTags.put(parseHandle(nodeMetadata.getId())[0], nodeMetadata.getTag()); regionTags.put(parseHandle(nodeMetadata.getId())[0], nodeMetadata
.getTag());
} }
for (Entry<String, String> regionTag : regionTags.entrySet()) { for (Entry<String, String> regionTag : regionTags.entrySet()) {
deleteKeyPair(regionTag.getKey(), regionTag.getValue()); deleteKeyPair(regionTag.getKey(), regionTag.getValue());

View File

@ -64,9 +64,11 @@ import org.jclouds.aws.ec2.domain.KeyPair;
import org.jclouds.aws.ec2.domain.RunningInstance; import org.jclouds.aws.ec2.domain.RunningInstance;
import org.jclouds.aws.ec2.domain.Image.ImageType; import org.jclouds.aws.ec2.domain.Image.ImageType;
import org.jclouds.aws.ec2.functions.RunningInstanceToStorageMappingUnix; import org.jclouds.aws.ec2.functions.RunningInstanceToStorageMappingUnix;
import org.jclouds.aws.ec2.predicates.InstancePresent;
import org.jclouds.aws.ec2.services.InstanceClient; import org.jclouds.aws.ec2.services.InstanceClient;
import org.jclouds.compute.ComputeService; import org.jclouds.compute.ComputeService;
import org.jclouds.compute.ComputeServiceContext; import org.jclouds.compute.ComputeServiceContext;
import org.jclouds.compute.config.ComputeServiceTimeoutsModule;
import org.jclouds.compute.domain.Architecture; import org.jclouds.compute.domain.Architecture;
import org.jclouds.compute.domain.ComputeMetadata; import org.jclouds.compute.domain.ComputeMetadata;
import org.jclouds.compute.domain.Image; import org.jclouds.compute.domain.Image;
@ -76,8 +78,6 @@ import org.jclouds.compute.domain.TemplateBuilder;
import org.jclouds.compute.internal.ComputeServiceContextImpl; import org.jclouds.compute.internal.ComputeServiceContextImpl;
import org.jclouds.compute.options.TemplateOptions; import org.jclouds.compute.options.TemplateOptions;
import org.jclouds.compute.predicates.NodePredicates; 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.reference.ComputeServiceConstants;
import org.jclouds.compute.strategy.DestroyLoadBalancerStrategy; import org.jclouds.compute.strategy.DestroyLoadBalancerStrategy;
import org.jclouds.compute.strategy.DestroyNodeStrategy; import org.jclouds.compute.strategy.DestroyNodeStrategy;
@ -92,11 +92,9 @@ import org.jclouds.domain.LocationScope;
import org.jclouds.domain.internal.LocationImpl; import org.jclouds.domain.internal.LocationImpl;
import org.jclouds.logging.Logger; import org.jclouds.logging.Logger;
import org.jclouds.predicates.RetryablePredicate; import org.jclouds.predicates.RetryablePredicate;
import com.google.inject.name.Names;
import com.google.common.base.Function; import com.google.common.base.Function;
import com.google.common.base.Predicate; import com.google.common.base.Predicate;
import com.google.common.base.Predicates;
import com.google.common.base.Splitter; import com.google.common.base.Splitter;
import com.google.common.base.Supplier; import com.google.common.base.Supplier;
import com.google.common.collect.ImmutableSet; import com.google.common.collect.ImmutableSet;
@ -108,9 +106,11 @@ import com.google.common.util.concurrent.ListenableFuture;
import com.google.inject.Provides; import com.google.inject.Provides;
import com.google.inject.Scopes; import com.google.inject.Scopes;
import com.google.inject.TypeLiteral; import com.google.inject.TypeLiteral;
import com.google.inject.name.Names;
/** /**
* Configures the {@link ComputeServiceContext}; requires {@link EC2ComputeService} bound. * Configures the {@link ComputeServiceContext}; requires
* {@link EC2ComputeService} bound.
* *
* @author Adrian Cole * @author Adrian Cole
*/ */
@ -121,26 +121,41 @@ public class EC2ComputeServiceContextModule extends EC2ContextModule {
public EC2ComputeServiceContextModule(String providerName) { public EC2ComputeServiceContextModule(String providerName) {
this.providerName = providerName; this.providerName = providerName;
} }
@Provides
@Singleton
@Named("PRESENT")
protected Predicate<RunningInstance> instancePresent(InstancePresent present) {
return new RetryablePredicate<RunningInstance>(present, 3000, 200,
TimeUnit.MILLISECONDS);
}
@Override @Override
protected void configure() { protected void configure() {
super.configure(); super.configure();
install(new ComputeServiceTimeoutsModule());
bind(TemplateBuilder.class).to(EC2TemplateBuilderImpl.class); bind(TemplateBuilder.class).to(EC2TemplateBuilderImpl.class);
bind(TemplateOptions.class).to(EC2TemplateOptions.class); bind(TemplateOptions.class).to(EC2TemplateOptions.class);
bind(ComputeService.class).to(EC2ComputeService.class); bind(ComputeService.class).to(EC2ComputeService.class);
bind(new TypeLiteral<ComputeServiceContext>() { bind(new TypeLiteral<ComputeServiceContext>() {
}).to(new TypeLiteral<ComputeServiceContextImpl<EC2Client, EC2AsyncClient>>() { })
}).in(Scopes.SINGLETON); .to(
bind(LoadBalanceNodesStrategy.class).to(EC2LoadBalanceNodesStrategy.class); new TypeLiteral<ComputeServiceContextImpl<EC2Client, EC2AsyncClient>>() {
bind(DestroyLoadBalancerStrategy.class).to(EC2DestroyLoadBalancerStrategy.class); }).in(Scopes.SINGLETON);
bind(RunNodesAndAddToSetStrategy.class).to(EC2RunNodesAndAddToSetStrategy.class); 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(ListNodesStrategy.class).to(EC2ListNodesStrategy.class);
bind(GetNodeMetadataStrategy.class).to(EC2GetNodeMetadataStrategy.class); bind(GetNodeMetadataStrategy.class).to(EC2GetNodeMetadataStrategy.class);
bind(RebootNodeStrategy.class).to(EC2RebootNodeStrategy.class); bind(RebootNodeStrategy.class).to(EC2RebootNodeStrategy.class);
bind(DestroyNodeStrategy.class).to(EC2DestroyNodeStrategy.class); bind(DestroyNodeStrategy.class).to(EC2DestroyNodeStrategy.class);
bind(new TypeLiteral<Function<RunningInstance, Map<String, String>>>() { bind(new TypeLiteral<Function<RunningInstance, Map<String, String>>>() {
}).annotatedWith(Names.named("volumeMapping")).to(RunningInstanceToStorageMappingUnix.class) }).annotatedWith(Names.named("volumeMapping")).to(
.in(Scopes.SINGLETON); RunningInstanceToStorageMappingUnix.class).in(Scopes.SINGLETON);
} }
@Provides @Provides
@ -160,11 +175,12 @@ public class EC2ComputeServiceContextModule extends EC2ContextModule {
@Provides @Provides
@Named("DEFAULT") @Named("DEFAULT")
protected TemplateBuilder provideTemplate(TemplateBuilder template) { protected TemplateBuilder provideTemplate(TemplateBuilder template) {
return template.architecture(Architecture.X86_32).osFamily(UBUNTU).imageNameMatches( return template.architecture(Architecture.X86_32).osFamily(UBUNTU)
".*10\\.?04.*"); .imageNameMatches(".*10\\.?04.*").osDescriptionMatches("^ubuntu-images.*");
} }
// TODO make this more efficient for listNodes(); currently RunningInstanceToNodeMetadata is slow // TODO make this more efficient for listNodes(); currently
// RunningInstanceToNodeMetadata is slow
// due to image parsing; consider using MapMaker. computing map // due to image parsing; consider using MapMaker. computing map
@Singleton @Singleton
public static class EC2ListNodesStrategy implements ListNodesStrategy { public static class EC2ListNodesStrategy implements ListNodesStrategy {
@ -178,9 +194,10 @@ public class EC2ComputeServiceContextModule extends EC2ContextModule {
private final ExecutorService executor; private final ExecutorService executor;
@Inject @Inject
protected EC2ListNodesStrategy(EC2Client client, @EC2 Map<String, URI> regionMap, protected EC2ListNodesStrategy(EC2Client client,
RunningInstanceToNodeMetadata runningInstanceToNodeMetadata, @EC2 Map<String, URI> regionMap,
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService executor) { RunningInstanceToNodeMetadata runningInstanceToNodeMetadata,
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService executor) {
this.client = client; this.client = client;
this.regionMap = regionMap; this.regionMap = regionMap;
this.runningInstanceToNodeMetadata = runningInstanceToNodeMetadata; this.runningInstanceToNodeMetadata = runningInstanceToNodeMetadata;
@ -194,42 +211,44 @@ public class EC2ComputeServiceContextModule extends EC2ContextModule {
@Override @Override
public Iterable<? extends NodeMetadata> listDetailsOnNodesMatching( public Iterable<? extends NodeMetadata> listDetailsOnNodesMatching(
Predicate<ComputeMetadata> filter) { Predicate<ComputeMetadata> filter) {
final Set<NodeMetadata> nodes = Sets.newHashSet(); final Set<NodeMetadata> nodes = Sets.newHashSet();
Map<String, ListenableFuture<?>> parallelResponses = Maps.newHashMap(); Map<String, ListenableFuture<?>> parallelResponses = Maps.newHashMap();
for (final String region : regionMap.keySet()) { for (final String region : regionMap.keySet()) {
parallelResponses.put(region, ConcurrentUtils.makeListenable(executor parallelResponses.put(region, ConcurrentUtils.makeListenable(
.submit(new Callable<Void>() { executor.submit(new Callable<Void>() {
@Override @Override
public Void call() throws Exception { public Void call() throws Exception {
Iterables.addAll(nodes, Iterables.transform(Iterables.concat(client Iterables.addAll(nodes, Iterables.transform(Iterables
.getInstanceServices().describeInstancesInRegion(region)), .concat(client.getInstanceServices()
runningInstanceToNodeMetadata)); .describeInstancesInRegion(region)),
return null; runningInstanceToNodeMetadata));
} return null;
}), executor)); }
}), executor));
} }
Map<String, Exception> exceptions = awaitCompletion(parallelResponses, executor, null, Map<String, Exception> exceptions = awaitCompletion(parallelResponses,
logger, "nodes"); executor, null, logger, "nodes");
if (exceptions.size() > 0) if (exceptions.size() > 0)
throw new RuntimeException(String.format("error parsing nodes in regions: %s", throw new RuntimeException(String.format(
exceptions)); "error parsing nodes in regions: %s", exceptions));
return Iterables.filter(nodes, filter); return Iterables.filter(nodes, filter);
} }
} }
@Singleton @Singleton
public static class EC2GetNodeMetadataStrategy implements GetNodeMetadataStrategy { public static class EC2GetNodeMetadataStrategy implements
GetNodeMetadataStrategy {
private final EC2Client client; private final EC2Client client;
private final RunningInstanceToNodeMetadata runningInstanceToNodeMetadata; private final RunningInstanceToNodeMetadata runningInstanceToNodeMetadata;
@Inject @Inject
protected EC2GetNodeMetadataStrategy(EC2Client client, protected EC2GetNodeMetadataStrategy(EC2Client client,
RunningInstanceToNodeMetadata runningInstanceToNodeMetadata) { RunningInstanceToNodeMetadata runningInstanceToNodeMetadata) {
this.client = client; this.client = client;
this.runningInstanceToNodeMetadata = runningInstanceToNodeMetadata; this.runningInstanceToNodeMetadata = runningInstanceToNodeMetadata;
} }
@ -239,8 +258,9 @@ public class EC2ComputeServiceContextModule extends EC2ContextModule {
String[] parts = parseHandle(id); String[] parts = parseHandle(id);
String region = parts[0]; String region = parts[0];
String instanceId = parts[1]; String instanceId = parts[1];
RunningInstance runningInstance = Iterables.getOnlyElement(getAllRunningInstancesInRegion( RunningInstance runningInstance = Iterables
client.getInstanceServices(), region, instanceId)); .getOnlyElement(getAllRunningInstancesInRegion(client
.getInstanceServices(), region, instanceId));
return runningInstanceToNodeMetadata.apply(runningInstance); return runningInstanceToNodeMetadata.apply(runningInstance);
} }
@ -249,34 +269,30 @@ public class EC2ComputeServiceContextModule extends EC2ContextModule {
@Singleton @Singleton
public static class EC2RebootNodeStrategy implements RebootNodeStrategy { public static class EC2RebootNodeStrategy implements RebootNodeStrategy {
private final InstanceClient client; private final InstanceClient client;
private final GetNodeMetadataStrategy getNode;
@Inject @Inject
protected EC2RebootNodeStrategy(EC2Client client) { protected EC2RebootNodeStrategy(EC2Client client,
GetNodeMetadataStrategy getNode) {
this.client = client.getInstanceServices(); this.client = client.getInstanceServices();
this.getNode = getNode;
} }
@Override @Override
public boolean execute(String id) { public NodeMetadata execute(String id) {
String[] parts = parseHandle(id); String[] parts = parseHandle(id);
String region = parts[0]; String region = parts[0];
String instanceId = parts[1]; String instanceId = parts[1];
client.rebootInstancesInRegion(region, instanceId); client.rebootInstancesInRegion(region, instanceId);
return true; return getNode.execute(id);
} }
} }
@Provides @Provides
@Singleton @Singleton
@Named("NOT_RUNNING") protected final Map<RegionAndName, KeyPair> credentialsMap(
protected Predicate<CommandUsingClient> runScriptRunning(ScriptStatusReturnsZero stateRunning) { CreateUniqueKeyPair in) {
return new RetryablePredicate<CommandUsingClient>(Predicates.not(stateRunning), 600, 3,
TimeUnit.SECONDS);
}
@Provides
@Singleton
protected final Map<RegionAndName, KeyPair> credentialsMap(CreateUniqueKeyPair in) {
// doesn't seem to clear when someone issues remove(key) // doesn't seem to clear when someone issues remove(key)
// return new MapMaker().makeComputingMap(in); // return new MapMaker().makeComputingMap(in);
return Maps.newLinkedHashMap(); return Maps.newLinkedHashMap();
@ -284,7 +300,8 @@ public class EC2ComputeServiceContextModule extends EC2ContextModule {
@Provides @Provides
@Singleton @Singleton
protected final Map<RegionAndName, String> securityGroupMap(CreateSecurityGroupIfNeeded in) { protected final Map<RegionAndName, String> securityGroupMap(
CreateSecurityGroupIfNeeded in) {
// doesn't seem to clear when someone issues remove(key) // doesn't seem to clear when someone issues remove(key)
// return new MapMaker().makeComputingMap(in); // return new MapMaker().makeComputingMap(in);
return Maps.newLinkedHashMap(); return Maps.newLinkedHashMap();
@ -304,28 +321,33 @@ public class EC2ComputeServiceContextModule extends EC2ContextModule {
@Provides @Provides
@Singleton @Singleton
Set<? extends Size> provideSizes() { Set<? extends Size> provideSizes() {
return ImmutableSet.of(EC2Size.C1_MEDIUM, EC2Size.C1_XLARGE, EC2Size.M1_LARGE, return ImmutableSet.of(EC2Size.C1_MEDIUM, EC2Size.C1_XLARGE,
EC2Size.M1_SMALL, EC2Size.M1_XLARGE, EC2Size.M2_XLARGE, EC2Size.M2_2XLARGE, EC2Size.M1_LARGE, EC2Size.M1_SMALL, EC2Size.M1_XLARGE,
EC2Size.M2_4XLARGE); EC2Size.M2_XLARGE, EC2Size.M2_2XLARGE, EC2Size.M2_4XLARGE);
} }
@Provides @Provides
@Singleton @Singleton
Set<? extends Location> provideLocations(Map<String, String> availabilityZoneToRegionMap) { Set<? extends Location> provideLocations(
Location ec2 = new LocationImpl(LocationScope.PROVIDER, providerName, providerName, null); Map<String, String> availabilityZoneToRegionMap) {
Location ec2 = new LocationImpl(LocationScope.PROVIDER, providerName,
providerName, null);
Set<Location> locations = Sets.newLinkedHashSet(); Set<Location> locations = Sets.newLinkedHashSet();
for (String zone : availabilityZoneToRegionMap.keySet()) { for (String zone : availabilityZoneToRegionMap.keySet()) {
Location region = new LocationImpl(LocationScope.REGION, availabilityZoneToRegionMap Location region = new LocationImpl(LocationScope.REGION,
.get(zone), availabilityZoneToRegionMap.get(zone), ec2); availabilityZoneToRegionMap.get(zone),
availabilityZoneToRegionMap.get(zone), ec2);
locations.add(region); locations.add(region);
locations.add(new LocationImpl(LocationScope.ZONE, zone, zone, region)); locations
.add(new LocationImpl(LocationScope.ZONE, zone, zone, region));
} }
return locations; return locations;
} }
@Provides @Provides
@Singleton @Singleton
Location getDefaultLocation(@EC2 final String region, Set<? extends Location> set) { Location getDefaultLocation(@EC2 final String region,
Set<? extends Location> set) {
return Iterables.find(set, new Predicate<Location>() { return Iterables.find(set, new Predicate<Location>() {
@Override @Override
@ -352,26 +374,28 @@ public class EC2ComputeServiceContextModule extends EC2ContextModule {
} }
@Provides @Provides
protected Set<? extends Image> provideImages(Map<RegionAndName, ? extends Image> map) { protected Set<? extends Image> provideImages(
Map<RegionAndName, ? extends Image> map) {
return ImmutableSet.copyOf(map.values()); return ImmutableSet.copyOf(map.values());
} }
@Provides @Provides
@Singleton @Singleton
protected ConcurrentMap<RegionAndName, Image> provideImageMap( protected ConcurrentMap<RegionAndName, Image> provideImageMap(
RegionAndIdToImage regionAndIdToImage) { RegionAndIdToImage regionAndIdToImage) {
return new MapMaker().makeComputingMap(regionAndIdToImage); return new MapMaker().makeComputingMap(regionAndIdToImage);
} }
@Provides @Provides
@Singleton @Singleton
protected Map<RegionAndName, ? extends Image> provideImages(final EC2Client sync, protected Map<RegionAndName, ? extends Image> provideImages(
@EC2 Map<String, URI> regionMap, final LogHolder holder, final EC2Client sync, @EC2 Map<String, URI> regionMap,
Function<ComputeMetadata, String> indexer, final LogHolder holder, Function<ComputeMetadata, String> indexer,
@Named(PROPERTY_EC2_AMI_OWNERS) final String[] amiOwners, final ImageParser parser, @Named(PROPERTY_EC2_AMI_OWNERS) final String[] amiOwners,
final ConcurrentMap<RegionAndName, Image> images, final ImageParser parser,
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService executor) final ConcurrentMap<RegionAndName, Image> images,
throws InterruptedException, ExecutionException, TimeoutException { @Named(Constants.PROPERTY_USER_THREADS) ExecutorService executor)
throws InterruptedException, ExecutionException, TimeoutException {
if (amiOwners.length == 0) { if (amiOwners.length == 0) {
holder.logger.debug(">> no owners specified, skipping image parsing"); holder.logger.debug(">> no owners specified, skipping image parsing");
} else { } else {
@ -380,30 +404,31 @@ public class EC2ComputeServiceContextModule extends EC2ContextModule {
Map<String, ListenableFuture<?>> parallelResponses = Maps.newHashMap(); Map<String, ListenableFuture<?>> parallelResponses = Maps.newHashMap();
for (final String region : regionMap.keySet()) { for (final String region : regionMap.keySet()) {
parallelResponses.put(region, ConcurrentUtils.makeListenable(executor parallelResponses.put(region, ConcurrentUtils.makeListenable(
.submit(new Callable<Void>() { executor.submit(new Callable<Void>() {
@Override @Override
public Void call() throws Exception { public Void call() throws Exception {
for (final org.jclouds.aws.ec2.domain.Image from : sync.getAMIServices() for (final org.jclouds.aws.ec2.domain.Image from : sync
.describeImagesInRegion(region, ownedBy(amiOwners))) { .getAMIServices().describeImagesInRegion(region,
Image image = parser.apply(from); ownedBy(amiOwners))) {
if (image != null) Image image = parser.apply(from);
images if (image != null)
.put(new RegionAndName(region, image.getProviderId()), images.put(new RegionAndName(region, image
image); .getProviderId()), image);
else if (from.getImageType() == ImageType.MACHINE) else if (from.getImageType() == ImageType.MACHINE)
holder.logger.trace("<< image(%s) didn't parse", from.getId()); holder.logger.trace("<< image(%s) didn't parse",
} from.getId());
return null;
} }
}), executor)); return null;
}
}), executor));
} }
Map<String, Exception> exceptions = awaitCompletion(parallelResponses, executor, null, Map<String, Exception> exceptions = awaitCompletion(parallelResponses,
holder.logger, "images"); executor, null, holder.logger, "images");
if (exceptions.size() > 0) if (exceptions.size() > 0)
throw new RuntimeException(String.format("error parsing images in regions: %s", throw new RuntimeException(String.format(
exceptions)); "error parsing images in regions: %s", exceptions));
holder.logger.debug("<< images(%d)", images.size()); holder.logger.debug("<< images(%d)", images.size());
} }

View File

@ -27,15 +27,12 @@ import javax.inject.Named;
import javax.inject.Singleton; import javax.inject.Singleton;
import org.jclouds.aws.ec2.EC2Client; import org.jclouds.aws.ec2.EC2Client;
import org.jclouds.aws.ec2.domain.RunningInstance; import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.reference.ComputeServiceConstants; import org.jclouds.compute.reference.ComputeServiceConstants;
import org.jclouds.compute.strategy.DestroyNodeStrategy; import org.jclouds.compute.strategy.DestroyNodeStrategy;
import org.jclouds.compute.strategy.GetNodeMetadataStrategy; import org.jclouds.compute.strategy.GetNodeMetadataStrategy;
import org.jclouds.logging.Logger; import org.jclouds.logging.Logger;
import com.google.common.base.Predicate;
import com.google.common.collect.Iterables;
/** /**
* *
* @author Adrian Cole * @author Adrian Cole
@ -46,25 +43,22 @@ public class EC2DestroyNodeStrategy implements DestroyNodeStrategy {
@Named(ComputeServiceConstants.COMPUTE_LOGGER) @Named(ComputeServiceConstants.COMPUTE_LOGGER)
protected Logger logger = Logger.NULL; protected Logger logger = Logger.NULL;
protected final EC2Client ec2Client; protected final EC2Client ec2Client;
protected final Predicate<RunningInstance> instanceStateTerminated; protected final GetNodeMetadataStrategy getNode;
protected final GetNodeMetadataStrategy getNodeMetadataStrategy;
@Inject @Inject
protected EC2DestroyNodeStrategy(EC2Client ec2Client, protected EC2DestroyNodeStrategy(EC2Client ec2Client,
@Named("TERMINATED") Predicate<RunningInstance> instanceStateTerminated, GetNodeMetadataStrategy getNodeMetadataStrategy) {
GetNodeMetadataStrategy getNodeMetadataStrategy) {
this.ec2Client = ec2Client; this.ec2Client = ec2Client;
this.instanceStateTerminated = instanceStateTerminated; this.getNode = getNodeMetadataStrategy;
this.getNodeMetadataStrategy = getNodeMetadataStrategy;
} }
@Override @Override
public boolean execute(String id) { public NodeMetadata execute(String id) {
String[] parts = parseHandle(id); String[] parts = parseHandle(id);
String region = parts[0]; String region = parts[0];
String instanceId = parts[1]; String instanceId = parts[1];
ec2Client.getInstanceServices().terminateInstancesInRegion(region, instanceId); ec2Client.getInstanceServices().terminateInstancesInRegion(region,
return instanceStateTerminated.apply(Iterables.getOnlyElement(Iterables.concat(ec2Client instanceId);
.getInstanceServices().describeInstancesInRegion(region, instanceId)))); return getNode.execute(id);
} }
} }

View File

@ -20,8 +20,6 @@
package org.jclouds.aws.ec2.compute.strategy; package org.jclouds.aws.ec2.compute.strategy;
import static com.google.common.collect.Iterables.all; import static com.google.common.collect.Iterables.all;
import static com.google.common.collect.Iterables.concat;
import static com.google.common.collect.Iterables.toArray;
import static com.google.common.collect.Iterables.transform; import static com.google.common.collect.Iterables.transform;
import static org.jclouds.aws.ec2.compute.util.EC2ComputeUtils.getRegionFromLocationOrNull; import static org.jclouds.aws.ec2.compute.util.EC2ComputeUtils.getRegionFromLocationOrNull;
import static org.jclouds.aws.ec2.compute.util.EC2ComputeUtils.getZoneFromLocationOrNull; import static org.jclouds.aws.ec2.compute.util.EC2ComputeUtils.getZoneFromLocationOrNull;
@ -58,7 +56,8 @@ import com.google.common.util.concurrent.ListenableFuture;
* @author Adrian Cole * @author Adrian Cole
*/ */
@Singleton @Singleton
public class EC2RunNodesAndAddToSetStrategy implements RunNodesAndAddToSetStrategy { public class EC2RunNodesAndAddToSetStrategy implements
RunNodesAndAddToSetStrategy {
@Resource @Resource
@Named(ComputeServiceConstants.COMPUTE_LOGGER) @Named(ComputeServiceConstants.COMPUTE_LOGGER)
@ -69,76 +68,64 @@ public class EC2RunNodesAndAddToSetStrategy implements RunNodesAndAddToSetStrate
@VisibleForTesting @VisibleForTesting
final CreateKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions createKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions; final CreateKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions createKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions;
@VisibleForTesting @VisibleForTesting
final Predicate<RunningInstance> instanceStateRunning;
@VisibleForTesting
final RunningInstanceToNodeMetadata runningInstanceToNodeMetadata; final RunningInstanceToNodeMetadata runningInstanceToNodeMetadata;
@VisibleForTesting @VisibleForTesting
final ComputeUtils utils; final ComputeUtils utils;
final Predicate<RunningInstance> instancePresent;
@Inject @Inject
EC2RunNodesAndAddToSetStrategy( EC2RunNodesAndAddToSetStrategy(
EC2Client client, EC2Client client,
CreateKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions createKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions, CreateKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions createKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions,
@Named("RUNNING") Predicate<RunningInstance> instanceStateRunning, @Named("PRESENT") Predicate<RunningInstance> instancePresent,
RunningInstanceToNodeMetadata runningInstanceToNodeMetadata, ComputeUtils utils) { RunningInstanceToNodeMetadata runningInstanceToNodeMetadata,
ComputeUtils utils) {
this.client = client; this.client = client;
this.instancePresent = instancePresent;
this.createKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions = createKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions; this.createKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions = createKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions;
this.instanceStateRunning = instanceStateRunning;
this.runningInstanceToNodeMetadata = runningInstanceToNodeMetadata; this.runningInstanceToNodeMetadata = runningInstanceToNodeMetadata;
this.utils = utils; this.utils = utils;
} }
@Override @Override
public Map<?, ListenableFuture<Void>> execute(String tag, int count, Template template, public Map<?, ListenableFuture<Void>> execute(String tag, int count,
Set<NodeMetadata> goodNodes, Map<NodeMetadata, Exception> badNodes) { Template template, Set<NodeMetadata> goodNodes,
Map<NodeMetadata, Exception> badNodes) {
Reservation reservation = createKeyPairAndSecurityGroupsAsNeededThenRunInstances(tag, count, Reservation reservation = createKeyPairAndSecurityGroupsAsNeededThenRunInstances(
template); tag, count, template);
Iterable<NodeMetadata> runningNodes = blockUntilInstancesAreRunningAndConvertToNodes(reservation);
return utils.runOptionsOnNodesAndAddToGoodSetOrPutExceptionIntoBadMap(template.getOptions(),
runningNodes, goodNodes, badNodes);
}
@VisibleForTesting
Iterable<NodeMetadata> blockUntilInstancesAreRunningAndConvertToNodes(Reservation reservation) {
return transform(blockUntilInstancesAreRunning(reservation), runningInstanceToNodeMetadata);
}
@VisibleForTesting
Iterable<RunningInstance> blockUntilInstancesAreRunning(Reservation reservation) {
Iterable<String> ids = transform(reservation, instanceToId); Iterable<String> ids = transform(reservation, instanceToId);
String idsString = Joiner.on(',').join(ids); String idsString = Joiner.on(',').join(ids);
logger.debug("<< started instances(%s)", idsString);
all(reservation, instanceStateRunning);
logger.debug("<< running instances(%s)", idsString);
return getInstances(reservation.getRegion(), ids); logger.debug("<< started instances(%s)", idsString);
all(reservation, instancePresent);
logger.debug("<< present instances(%s)", idsString);
return utils.runOptionsOnNodesAndAddToGoodSetOrPutExceptionIntoBadMap(
template.getOptions(), transform(reservation,
runningInstanceToNodeMetadata), goodNodes, badNodes);
} }
@VisibleForTesting @VisibleForTesting
Reservation createKeyPairAndSecurityGroupsAsNeededThenRunInstances(String tag, int count, Reservation createKeyPairAndSecurityGroupsAsNeededThenRunInstances(
Template template) { String tag, int count, Template template) {
String region = getRegionFromLocationOrNull(template.getLocation()); String region = getRegionFromLocationOrNull(template.getLocation());
String zone = getZoneFromLocationOrNull(template.getLocation()); String zone = getZoneFromLocationOrNull(template.getLocation());
RunInstancesOptions instanceOptions = createKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions RunInstancesOptions instanceOptions = createKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions
.execute(region, tag, template); .execute(region, tag, template);
if (logger.isDebugEnabled()) if (logger.isDebugEnabled())
logger.debug(">> running %d instance region(%s) zone(%s) ami(%s) params(%s)", count, logger.debug(
region, zone, template.getImage().getProviderId(), instanceOptions ">> running %d instance region(%s) zone(%s) ami(%s) params(%s)",
.buildFormParameters()); count, region, zone, template.getImage().getProviderId(),
instanceOptions.buildFormParameters());
return client.getInstanceServices().runInstancesInRegion(region, zone, return client.getInstanceServices().runInstancesInRegion(region, zone,
template.getImage().getProviderId(), 1, count, instanceOptions); template.getImage().getProviderId(), 1, count, instanceOptions);
}
private Iterable<RunningInstance> getInstances(String region, Iterable<String> ids) {
return concat(client.getInstanceServices().describeInstancesInRegion(region,
toArray(ids, String.class)));
} }
} }

View File

@ -49,11 +49,11 @@ public class EC2ContextModule extends AbstractModule {
@Provides @Provides
@Singleton @Singleton
RestContext<EC2Client, EC2AsyncClient> provideContext(Closer closer, EC2AsyncClient defaultApi, RestContext<EC2Client, EC2AsyncClient> provideContext(Closer closer,
EC2Client synchApi, @EC2 URI endPoint, EC2AsyncClient defaultApi, EC2Client synchApi, @EC2 URI endPoint,
@Named(AWSConstants.PROPERTY_AWS_ACCESSKEYID) String account) { @Named(AWSConstants.PROPERTY_AWS_ACCESSKEYID) String account) {
return new RestContextImpl<EC2Client, EC2AsyncClient>(closer, defaultApi, synchApi, endPoint, return new RestContextImpl<EC2Client, EC2AsyncClient>(closer, defaultApi,
account); synchApi, endPoint, account);
} }
} }

View File

@ -21,7 +21,6 @@ package org.jclouds.aws.ec2.config;
import java.net.URI; import java.net.URI;
import java.util.Date; import java.util.Date;
import java.util.Map; import java.util.Map;
import java.util.concurrent.TimeUnit;
import javax.inject.Named; import javax.inject.Named;
import javax.inject.Singleton; import javax.inject.Singleton;
@ -32,9 +31,6 @@ import org.jclouds.aws.ec2.EC2AsyncClient;
import org.jclouds.aws.ec2.EC2Client; import org.jclouds.aws.ec2.EC2Client;
import org.jclouds.aws.ec2.ELB; import org.jclouds.aws.ec2.ELB;
import org.jclouds.aws.ec2.domain.AvailabilityZoneInfo; import org.jclouds.aws.ec2.domain.AvailabilityZoneInfo;
import org.jclouds.aws.ec2.domain.RunningInstance;
import org.jclouds.aws.ec2.predicates.InstanceStateRunning;
import org.jclouds.aws.ec2.predicates.InstanceStateTerminated;
import org.jclouds.aws.ec2.reference.EC2Constants; import org.jclouds.aws.ec2.reference.EC2Constants;
import org.jclouds.aws.ec2.services.AMIAsyncClient; import org.jclouds.aws.ec2.services.AMIAsyncClient;
import org.jclouds.aws.ec2.services.AMIClient; import org.jclouds.aws.ec2.services.AMIClient;
@ -66,14 +62,10 @@ import org.jclouds.http.RequiresHttp;
import org.jclouds.http.annotation.ClientError; import org.jclouds.http.annotation.ClientError;
import org.jclouds.http.annotation.Redirection; import org.jclouds.http.annotation.Redirection;
import org.jclouds.http.annotation.ServerError; import org.jclouds.http.annotation.ServerError;
import org.jclouds.net.IPSocket;
import org.jclouds.predicates.RetryablePredicate;
import org.jclouds.predicates.SocketOpen;
import org.jclouds.rest.ConfiguresRestClient; import org.jclouds.rest.ConfiguresRestClient;
import org.jclouds.rest.RequestSigner; import org.jclouds.rest.RequestSigner;
import org.jclouds.rest.config.RestClientModule; import org.jclouds.rest.config.RestClientModule;
import com.google.common.base.Predicate;
import com.google.common.collect.ImmutableBiMap; import com.google.common.collect.ImmutableBiMap;
import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Maps; import com.google.common.collect.Maps;
@ -86,50 +78,32 @@ import com.google.inject.Provides;
*/ */
@RequiresHttp @RequiresHttp
@ConfiguresRestClient @ConfiguresRestClient
public class EC2RestClientModule extends RestClientModule<EC2Client, EC2AsyncClient> { public class EC2RestClientModule extends
RestClientModule<EC2Client, EC2AsyncClient> {
public static final Map<Class<?>, Class<?>> DELEGATE_MAP = ImmutableMap public static final Map<Class<?>, Class<?>> DELEGATE_MAP = ImmutableMap
.<Class<?>, Class<?>> builder()// .<Class<?>, Class<?>> builder()//
.put(AMIClient.class, AMIAsyncClient.class)// .put(AMIClient.class, AMIAsyncClient.class)//
.put(ElasticIPAddressClient.class, ElasticIPAddressAsyncClient.class)// .put(ElasticIPAddressClient.class, ElasticIPAddressAsyncClient.class)//
.put(InstanceClient.class, InstanceAsyncClient.class)// .put(InstanceClient.class, InstanceAsyncClient.class)//
.put(KeyPairClient.class, KeyPairAsyncClient.class)// .put(KeyPairClient.class, KeyPairAsyncClient.class)//
.put(SecurityGroupClient.class, SecurityGroupAsyncClient.class)// .put(SecurityGroupClient.class, SecurityGroupAsyncClient.class)//
.put(MonitoringClient.class, MonitoringAsyncClient.class)// .put(MonitoringClient.class, MonitoringAsyncClient.class)//
.put(AvailabilityZoneAndRegionClient.class, AvailabilityZoneAndRegionAsyncClient.class)// .put(AvailabilityZoneAndRegionClient.class,
.put(ElasticBlockStoreClient.class, ElasticBlockStoreAsyncClient.class)// AvailabilityZoneAndRegionAsyncClient.class)//
.put(ElasticLoadBalancerClient.class, ElasticLoadBalancerAsyncClient.class)// .put(ElasticBlockStoreClient.class, ElasticBlockStoreAsyncClient.class)//
.build(); .put(ElasticLoadBalancerClient.class,
ElasticLoadBalancerAsyncClient.class)//
.build();
public EC2RestClientModule() { public EC2RestClientModule() {
super(EC2Client.class, EC2AsyncClient.class, DELEGATE_MAP); super(EC2Client.class, EC2AsyncClient.class, DELEGATE_MAP);
} }
@Provides
@Singleton
@Named("RUNNING")
protected Predicate<RunningInstance> instanceStateRunning(InstanceStateRunning stateRunning) {
return new RetryablePredicate<RunningInstance>(stateRunning, 600, 3, TimeUnit.SECONDS);
}
@Provides
@Singleton
@Named("TERMINATED")
protected Predicate<RunningInstance> instanceStateTerminated(
InstanceStateTerminated stateTerminated) {
return new RetryablePredicate<RunningInstance>(stateTerminated, 20000, 500,
TimeUnit.MILLISECONDS);
}
@Provides
@Singleton
protected Predicate<IPSocket> socketTester(SocketOpen open) {
return new RetryablePredicate<IPSocket>(open, 130, 1, TimeUnit.SECONDS);
}
@Provides @Provides
@Singleton @Singleton
@ELB @ELB
protected URI provideELBURI(@Named(EC2Constants.PROPERTY_ELB_ENDPOINT) String endpoint) { protected URI provideELBURI(
@Named(EC2Constants.PROPERTY_ELB_ENDPOINT) String endpoint) {
return URI.create(endpoint); return URI.create(endpoint);
} }
@ -137,21 +111,29 @@ public class EC2RestClientModule extends RestClientModule<EC2Client, EC2AsyncCli
@Singleton @Singleton
@ELB @ELB
Map<String, URI> provideELBRegions() { Map<String, URI> provideELBRegions() {
return ImmutableMap.<String, URI> of(Region.US_EAST_1, URI return ImmutableMap
.create("https://elasticloadbalancing.us-east-1.amazonaws.com"), Region.US_WEST_1, .<String, URI> of(
URI.create("https://elasticloadbalancing.us-west-1.amazonaws.com"), Region.US_EAST_1,
Region.EU_WEST_1, URI
URI.create("https://elasticloadbalancing.eu-west-1.amazonaws.com"), .create("https://elasticloadbalancing.us-east-1.amazonaws.com"),
Region.AP_SOUTHEAST_1, URI Region.US_WEST_1,
URI
.create("https://elasticloadbalancing.us-west-1.amazonaws.com"),
Region.EU_WEST_1,
URI
.create("https://elasticloadbalancing.eu-west-1.amazonaws.com"),
Region.AP_SOUTHEAST_1,
URI
.create("https://elasticloadbalancing.ap-southeast-1.amazonaws.com")); .create("https://elasticloadbalancing.ap-southeast-1.amazonaws.com"));
} }
@Provides @Provides
@Singleton @Singleton
@EC2 @EC2
String provideCurrentRegion(@EC2 Map<String, URI> regionMap, @EC2 URI currentUri) { String provideCurrentRegion(@EC2 Map<String, URI> regionMap,
ImmutableBiMap<URI, String> map = ImmutableBiMap.<String, URI> builder().putAll(regionMap) @EC2 URI currentUri) {
.build().inverse(); ImmutableBiMap<URI, String> map = ImmutableBiMap.<String, URI> builder()
.putAll(regionMap).build().inverse();
String region = map.get(currentUri); String region = map.get(currentUri);
assert region != null : currentUri + " not in " + map; assert region != null : currentUri + " not in " + map;
return region; return region;
@ -181,11 +163,12 @@ public class EC2RestClientModule extends RestClientModule<EC2Client, EC2AsyncCli
@Provides @Provides
@Singleton @Singleton
Map<String, String> provideAvailabilityZoneToRegions(EC2Client client, Map<String, String> provideAvailabilityZoneToRegions(EC2Client client,
@EC2 Map<String, URI> regions) { @EC2 Map<String, URI> regions) {
Map<String, String> map = Maps.newHashMap(); Map<String, String> map = Maps.newHashMap();
for (String region : regions.keySet()) { for (String region : regions.keySet()) {
for (AvailabilityZoneInfo zoneInfo : client.getAvailabilityZoneAndRegionServices() for (AvailabilityZoneInfo zoneInfo : client
.describeAvailabilityZonesInRegion(region)) { .getAvailabilityZoneAndRegionServices()
.describeAvailabilityZonesInRegion(region)) {
map.put(zoneInfo.getZone(), region); map.put(zoneInfo.getZone(), region);
} }
} }
@ -195,9 +178,9 @@ public class EC2RestClientModule extends RestClientModule<EC2Client, EC2AsyncCli
@Provides @Provides
@TimeStamp @TimeStamp
protected String provideTimeStamp(final DateService dateService, protected String provideTimeStamp(final DateService dateService,
@Named(EC2Constants.PROPERTY_AWS_EXPIREINTERVAL) final int expiration) { @Named(EC2Constants.PROPERTY_AWS_EXPIREINTERVAL) final int expiration) {
return dateService.iso8601DateFormat(new Date(System.currentTimeMillis() return dateService.iso8601DateFormat(new Date(System.currentTimeMillis()
+ (expiration * 1000))); + (expiration * 1000)));
} }
@Provides @Provides
@ -209,25 +192,26 @@ public class EC2RestClientModule extends RestClientModule<EC2Client, EC2AsyncCli
@Provides @Provides
@Singleton @Singleton
@EC2 @EC2
protected URI provideURI(@Named(EC2Constants.PROPERTY_EC2_ENDPOINT) String endpoint) { protected URI provideURI(
@Named(EC2Constants.PROPERTY_EC2_ENDPOINT) String endpoint) {
return URI.create(endpoint); return URI.create(endpoint);
} }
@Override @Override
protected void bindErrorHandlers() { protected void bindErrorHandlers() {
bind(HttpErrorHandler.class).annotatedWith(Redirection.class).to( bind(HttpErrorHandler.class).annotatedWith(Redirection.class).to(
ParseAWSErrorFromXmlContent.class); ParseAWSErrorFromXmlContent.class);
bind(HttpErrorHandler.class).annotatedWith(ClientError.class).to( bind(HttpErrorHandler.class).annotatedWith(ClientError.class).to(
ParseAWSErrorFromXmlContent.class); ParseAWSErrorFromXmlContent.class);
bind(HttpErrorHandler.class).annotatedWith(ServerError.class).to( bind(HttpErrorHandler.class).annotatedWith(ServerError.class).to(
ParseAWSErrorFromXmlContent.class); ParseAWSErrorFromXmlContent.class);
} }
@Override @Override
protected void bindRetryHandlers() { protected void bindRetryHandlers() {
bind(HttpRetryHandler.class).annotatedWith(Redirection.class).to( bind(HttpRetryHandler.class).annotatedWith(Redirection.class).to(
AWSRedirectionRetryHandler.class); AWSRedirectionRetryHandler.class);
bind(HttpRetryHandler.class).annotatedWith(ClientError.class).to( bind(HttpRetryHandler.class).annotatedWith(ClientError.class).to(
AWSClientErrorRetryHandler.class); AWSClientErrorRetryHandler.class);
} }
} }

View File

@ -0,0 +1,67 @@
/**
*
* 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.predicates;
import javax.annotation.Resource;
import javax.inject.Singleton;
import org.jclouds.aws.ec2.EC2Client;
import org.jclouds.aws.ec2.domain.RunningInstance;
import org.jclouds.logging.Logger;
import org.jclouds.rest.ResourceNotFoundException;
import com.google.common.base.Predicate;
import com.google.common.collect.Iterables;
import com.google.inject.Inject;
/**
*
* Tests to see if a task succeeds.
*
* @author Adrian Cole
*/
@Singleton
public class InstancePresent implements Predicate<RunningInstance> {
private final EC2Client client;
@Resource
protected Logger logger = Logger.NULL;
@Inject
public InstancePresent(EC2Client client) {
this.client = client;
}
public boolean apply(RunningInstance instance) {
logger.trace("looking for instance %s", instance);
try {
instance = refresh(instance);
return true;
} catch (ResourceNotFoundException e) {
return false;
}
}
private RunningInstance refresh(RunningInstance instance) {
return Iterables.getOnlyElement(Iterables.getOnlyElement(client
.getInstanceServices().describeInstancesInRegion(
instance.getRegion(), instance.getId())));
}
}

View File

@ -21,11 +21,11 @@ package org.jclouds.aws.ec2.predicates;
import javax.annotation.Resource; import javax.annotation.Resource;
import javax.inject.Singleton; import javax.inject.Singleton;
import org.jclouds.aws.AWSResponseException;
import org.jclouds.aws.ec2.EC2Client; import org.jclouds.aws.ec2.EC2Client;
import org.jclouds.aws.ec2.domain.InstanceState; import org.jclouds.aws.ec2.domain.InstanceState;
import org.jclouds.aws.ec2.domain.RunningInstance; import org.jclouds.aws.ec2.domain.RunningInstance;
import org.jclouds.logging.Logger; import org.jclouds.logging.Logger;
import org.jclouds.rest.ResourceNotFoundException;
import com.google.common.base.Predicate; import com.google.common.base.Predicate;
import com.google.common.collect.Iterables; import com.google.common.collect.Iterables;
@ -54,18 +54,18 @@ public class InstanceStateRunning implements Predicate<RunningInstance> {
logger.trace("looking for state on instance %s", instance); logger.trace("looking for state on instance %s", instance);
try { try {
instance = refresh(instance); instance = refresh(instance);
logger.trace("%s: looking for instance state %s: currently: %s", instance.getId(), logger.trace("%s: looking for instance state %s: currently: %s",
InstanceState.RUNNING, instance.getInstanceState()); instance.getId(), InstanceState.RUNNING, instance
.getInstanceState());
return instance.getInstanceState() == InstanceState.RUNNING; return instance.getInstanceState() == InstanceState.RUNNING;
} catch (AWSResponseException e) { } catch (ResourceNotFoundException e) {
if (e.getError().getCode().equals("InvalidInstanceID.NotFound")) return false;
return false;
throw e;
} }
} }
private RunningInstance refresh(RunningInstance instance) { private RunningInstance refresh(RunningInstance instance) {
return Iterables.getOnlyElement(Iterables.getOnlyElement(client.getInstanceServices() return Iterables.getOnlyElement(Iterables.getOnlyElement(client
.describeInstancesInRegion(instance.getRegion(), instance.getId()))); .getInstanceServices().describeInstancesInRegion(
instance.getRegion(), instance.getId())));
} }
} }

View File

@ -63,29 +63,31 @@ public class ParseAWSErrorFromXmlContent implements HttpErrorHandler {
Exception exception = new HttpResponseException(command, response); Exception exception = new HttpResponseException(command, response);
try { try {
AWSError error = parseErrorFromContentOrNull(command, response); AWSError error = parseErrorFromContentOrNull(command, response);
exception = error != null ? new AWSResponseException(command, response, error) : exception; exception = error != null ? new AWSResponseException(command,
response, error) : exception;
switch (response.getStatusCode()) { switch (response.getStatusCode()) {
case 400: case 400:
if (error.getCode().equals("InvalidAMIID.NotFound") if (error.getCode().endsWith(".NotFound"))
|| error.getCode().equals("InvalidAMIID.Malformed")) exception = new ResourceNotFoundException(error.getMessage(),
exception = new ResourceNotFoundException(error.getMessage(), exception); exception);
break; break;
case 401: case 401:
exception = new AuthorizationException(command.getRequest(), error != null ? error exception = new AuthorizationException(command.getRequest(),
.getMessage() : response.getStatusLine()); error != null ? error.getMessage() : response.getStatusLine());
break; break;
case 404: case 404:
if (!command.getRequest().getMethod().equals("DELETE")) { if (!command.getRequest().getMethod().equals("DELETE")) {
String message = error != null ? error.getMessage() : String.format("%s -> %s", String message = error != null ? error.getMessage() : String
command.getRequest().getRequestLine(), response.getStatusLine()); .format("%s -> %s", command.getRequest().getRequestLine(),
String container = command.getRequest().getEndpoint().getHost(); response.getStatusLine());
String key = command.getRequest().getEndpoint().getPath(); String container = command.getRequest().getEndpoint().getHost();
if (key == null || key.equals("/")) String key = command.getRequest().getEndpoint().getPath();
exception = new ContainerNotFoundException(container, message); if (key == null || key.equals("/"))
else exception = new ContainerNotFoundException(container, message);
exception = new KeyNotFoundException(container, key, message); else
} exception = new KeyNotFoundException(container, key, message);
break; }
break;
} }
} finally { } finally {
Closeables.closeQuietly(response.getContent()); Closeables.closeQuietly(response.getContent());
@ -93,12 +95,14 @@ public class ParseAWSErrorFromXmlContent implements HttpErrorHandler {
} }
} }
AWSError parseErrorFromContentOrNull(HttpCommand command, HttpResponse response) { AWSError parseErrorFromContentOrNull(HttpCommand command,
HttpResponse response) {
if (response.getContent() != null) { if (response.getContent() != null) {
try { try {
String content = Utils.toStringAndClose(response.getContent()); String content = Utils.toStringAndClose(response.getContent());
if (content != null && content.indexOf('<') >= 0) if (content != null && content.indexOf('<') >= 0)
return utils.parseAWSErrorFromContent(command, response, content); return utils
.parseAWSErrorFromContent(command, response, content);
} catch (IOException e) { } catch (IOException e) {
logger.warn(e, "exception reading error from response", response); logger.warn(e, "exception reading error from response", response);
} }

View File

@ -67,7 +67,8 @@ import com.google.inject.Injector;
/** /**
* Follows the book Cloud Application Architectures ISBN: 978-0-596-15636-7 * Follows the book Cloud Application Architectures ISBN: 978-0-596-15636-7
* <p/> * <p/>
* adds in functionality to boot a lamp instance: http://alestic.com/2009/06/ec2-user-data-scripts * adds in functionality to boot a lamp instance:
* http://alestic.com/2009/06/ec2-user-data-scripts
* <p/> * <p/>
* Generally disabled, as it incurs higher fees. * Generally disabled, as it incurs higher fees.
* *
@ -89,41 +90,50 @@ public class CloudApplicationArchitecturesEC2ClientLiveTest {
private RetryablePredicate<RunningInstance> runningTester; private RetryablePredicate<RunningInstance> runningTester;
@BeforeGroups(groups = { "live" }) @BeforeGroups(groups = { "live" })
public void setupClient() throws InterruptedException, ExecutionException, TimeoutException { public void setupClient() throws InterruptedException, ExecutionException,
String user = checkNotNull(System.getProperty("jclouds.test.user"), "jclouds.test.user"); TimeoutException {
String password = checkNotNull(System.getProperty("jclouds.test.key"), "jclouds.test.key"); String user = checkNotNull(System.getProperty("jclouds.test.user"),
Injector injector = new EC2ContextBuilder("ec2", new EC2PropertiesBuilder(user, password) "jclouds.test.user");
.build()).withModules(new Log4JLoggingModule(), new JschSshClientModule()) String password = checkNotNull(System.getProperty("jclouds.test.key"),
.buildInjector(); "jclouds.test.key");
Injector injector = new EC2ContextBuilder("ec2",
new EC2PropertiesBuilder(user, password).build()).withModules(
new Log4JLoggingModule(), new JschSshClientModule())
.buildInjector();
client = injector.getInstance(EC2Client.class); client = injector.getInstance(EC2Client.class);
sshFactory = injector.getInstance(SshClient.Factory.class); sshFactory = injector.getInstance(SshClient.Factory.class);
runningTester = new RetryablePredicate<RunningInstance>(new InstanceStateRunning(client), runningTester = new RetryablePredicate<RunningInstance>(
180, 5, TimeUnit.SECONDS); new InstanceStateRunning(client), 180, 5, TimeUnit.SECONDS);
hasIpTester = new RetryablePredicate<RunningInstance>(new InstanceHasIpAddress(client), 180, 5, TimeUnit.SECONDS); hasIpTester = new RetryablePredicate<RunningInstance>(
new InstanceHasIpAddress(client), 180, 5, TimeUnit.SECONDS);
SocketOpen socketOpen = injector.getInstance(SocketOpen.class); SocketOpen socketOpen = injector.getInstance(SocketOpen.class);
socketTester = new RetryablePredicate<IPSocket>(socketOpen, 180, 1, TimeUnit.SECONDS); socketTester = new RetryablePredicate<IPSocket>(socketOpen, 180, 1,
TimeUnit.SECONDS);
} }
@Test(enabled = false) @Test(enabled = false)
void testCreateSecurityGroupIngressCidr() throws InterruptedException, ExecutionException, void testCreateSecurityGroupIngressCidr() throws InterruptedException,
TimeoutException { ExecutionException, TimeoutException {
securityGroupName = instancePrefix + "ingress"; securityGroupName = instancePrefix + "ingress";
try { try {
client.getSecurityGroupServices().deleteSecurityGroupInRegion(null, securityGroupName); client.getSecurityGroupServices().deleteSecurityGroupInRegion(null,
securityGroupName);
} catch (Exception e) { } catch (Exception e) {
} }
client.getSecurityGroupServices().createSecurityGroupInRegion(null, securityGroupName, client.getSecurityGroupServices().createSecurityGroupInRegion(null,
securityGroupName); securityGroupName, securityGroupName);
for (int port : new int[] { 80, 443, 22 }) { for (int port : new int[] { 80, 443, 22 }) {
client.getSecurityGroupServices().authorizeSecurityGroupIngressInRegion(null, client.getSecurityGroupServices()
securityGroupName, IpProtocol.TCP, port, port, "0.0.0.0/0"); .authorizeSecurityGroupIngressInRegion(null, securityGroupName,
IpProtocol.TCP, port, port, "0.0.0.0/0");
} }
} }
@Test(enabled = false) @Test(enabled = false)
void testCreateKeyPair() throws InterruptedException, ExecutionException, TimeoutException { void testCreateKeyPair() throws InterruptedException, ExecutionException,
TimeoutException {
String keyName = instancePrefix + "1"; String keyName = instancePrefix + "1";
try { try {
client.getKeyPairServices().deleteKeyPairInRegion(null, keyName); client.getKeyPairServices().deleteKeyPairInRegion(null, keyName);
@ -132,7 +142,8 @@ public class CloudApplicationArchitecturesEC2ClientLiveTest {
} }
client.getKeyPairServices().deleteKeyPairInRegion(null, keyName); client.getKeyPairServices().deleteKeyPairInRegion(null, keyName);
keyPair = client.getKeyPairServices().createKeyPairInRegion(null, keyName); keyPair = client.getKeyPairServices()
.createKeyPairInRegion(null, keyName);
assertNotNull(keyPair); assertNotNull(keyPair);
assertNotNull(keyPair.getKeyMaterial()); assertNotNull(keyPair.getKeyMaterial());
assertNotNull(keyPair.getKeyFingerprint()); assertNotNull(keyPair.getKeyFingerprint());
@ -140,32 +151,40 @@ public class CloudApplicationArchitecturesEC2ClientLiveTest {
} }
@Test(enabled = false, dependsOnMethods = { "testCreateKeyPair", @Test(enabled = false, dependsOnMethods = { "testCreateKeyPair",
"testCreateSecurityGroupIngressCidr" }) "testCreateSecurityGroupIngressCidr" })
public void testCreateRunningInstance() throws Exception { public void testCreateRunningInstance() throws Exception {
String script = new ScriptBuilder() // lamp install script String script = new ScriptBuilder() // lamp install script
.addStatement(exec("runurl run.alestic.com/apt/upgrade"))// .addStatement(exec("runurl run.alestic.com/apt/upgrade"))//
.addStatement(exec("runurl run.alestic.com/install/lamp"))// .addStatement(exec("runurl run.alestic.com/install/lamp"))//
.build(OsFamily.UNIX); .build(OsFamily.UNIX);
RunningInstance instance = null; RunningInstance instance = null;
while (instance == null) { while (instance == null) {
try { try {
System.out.printf("%d: running instance%n", System.currentTimeMillis()); System.out.printf("%d: running instance%n", System
Reservation reservation = client.getInstanceServices().runInstancesInRegion(null, null, // allow .currentTimeMillis());
// ec2 Reservation reservation = client.getInstanceServices()
// to .runInstancesInRegion(null, null, // allow
// chose // ec2
// an // to
// availability // chose
// zone // an
"ami-ccf615a5", // alestic ami allows auto-invoke of user data scripts // availability
1, // minimum instances // zone
1, // maximum instances "ami-ccf615a5", // alestic ami allows auto-invoke of
asType(InstanceType.M1_SMALL) // smallest instance size // user data scripts
.withKeyName(keyPair.getKeyName()) // key I created above 1, // minimum instances
.withSecurityGroup(securityGroupName) // group I created above 1, // maximum instances
.withUserData(script.getBytes())); // script to run as root asType(InstanceType.M1_SMALL) // smallest instance size
.withKeyName(keyPair.getKeyName()) // key I
// created
// above
.withSecurityGroup(securityGroupName) // group I
// created
// above
.withUserData(script.getBytes())); // script to
// run as root
instance = Iterables.getOnlyElement(reservation); instance = Iterables.getOnlyElement(reservation);
@ -183,45 +202,51 @@ public class CloudApplicationArchitecturesEC2ClientLiveTest {
verifyInstanceProperties(script); verifyInstanceProperties(script);
tryToChangeStuff(); tryToChangeStuff();
sshPing(instance); sshPing(instance);
System.out.printf("%d: %s ssh connection made%n", System.currentTimeMillis(), instanceId); System.out.printf("%d: %s ssh connection made%n", System
.currentTimeMillis(), instanceId);
} }
private void verifyInstanceProperties(String script) { private void verifyInstanceProperties(String script) {
assertEquals(script, client.getInstanceServices().getUserDataForInstanceInRegion(null, assertEquals(script, client.getInstanceServices()
instanceId)); .getUserDataForInstanceInRegion(null, instanceId));
assertEquals(null, client.getInstanceServices().getRootDeviceNameForInstanceInRegion(null, assertEquals(null, client.getInstanceServices()
instanceId)); .getRootDeviceNameForInstanceInRegion(null, instanceId));
assert client.getInstanceServices().getRamdiskForInstanceInRegion(null, instanceId) assert client.getInstanceServices().getRamdiskForInstanceInRegion(null,
.startsWith("ari-"); instanceId).startsWith("ari-");
assertEquals(false, client.getInstanceServices().isApiTerminationDisabledForInstanceInRegion( assertEquals(false, client.getInstanceServices()
null, instanceId)); .isApiTerminationDisabledForInstanceInRegion(null, instanceId));
assert client.getInstanceServices().getKernelForInstanceInRegion(null, instanceId) assert client.getInstanceServices().getKernelForInstanceInRegion(null,
.startsWith("aki-"); instanceId).startsWith("aki-");
assertEquals(InstanceType.M1_SMALL, client.getInstanceServices() assertEquals(InstanceType.M1_SMALL, client.getInstanceServices()
.getInstanceTypeForInstanceInRegion(null, instanceId)); .getInstanceTypeForInstanceInRegion(null, instanceId));
assertEquals(InstanceInitiatedShutdownBehavior.TERMINATE, client.getInstanceServices() assertEquals(InstanceInitiatedShutdownBehavior.TERMINATE, client
.getInstanceInitiatedShutdownBehaviorForInstanceInRegion(null, instanceId)); .getInstanceServices()
.getInstanceInitiatedShutdownBehaviorForInstanceInRegion(null,
instanceId));
assertEquals(ImmutableMap.<String, EbsBlockDevice> of(), client.getInstanceServices() assertEquals(ImmutableMap.<String, EbsBlockDevice> of(), client
.getBlockDeviceMappingForInstanceInRegion(null, instanceId)); .getInstanceServices().getBlockDeviceMappingForInstanceInRegion(
null, instanceId));
} }
private void setApiTerminationDisabledForInstanceInRegion() { private void setApiTerminationDisabledForInstanceInRegion() {
client.getInstanceServices().setApiTerminationDisabledForInstanceInRegion(null, instanceId, client.getInstanceServices()
true); .setApiTerminationDisabledForInstanceInRegion(null, instanceId,
assertEquals(true, client.getInstanceServices().isApiTerminationDisabledForInstanceInRegion( true);
null, instanceId)); assertEquals(true, client.getInstanceServices()
client.getInstanceServices().setApiTerminationDisabledForInstanceInRegion(null, instanceId, .isApiTerminationDisabledForInstanceInRegion(null, instanceId));
false); client.getInstanceServices()
assertEquals(false, client.getInstanceServices().isApiTerminationDisabledForInstanceInRegion( .setApiTerminationDisabledForInstanceInRegion(null, instanceId,
null, instanceId)); false);
assertEquals(false, client.getInstanceServices()
.isApiTerminationDisabledForInstanceInRegion(null, instanceId));
} }
private void tryToChangeStuff() { private void tryToChangeStuff() {
@ -236,8 +261,8 @@ public class CloudApplicationArchitecturesEC2ClientLiveTest {
private void setUserDataForInstanceInRegion() { private void setUserDataForInstanceInRegion() {
try { try {
client.getInstanceServices().setUserDataForInstanceInRegion(null, instanceId, client.getInstanceServices().setUserDataForInstanceInRegion(null,
"test".getBytes()); instanceId, "test".getBytes());
assert false : "shouldn't be allowed, as instance needs to be stopped"; assert false : "shouldn't be allowed, as instance needs to be stopped";
} catch (AWSResponseException e) { } catch (AWSResponseException e) {
assertEquals("IncorrectInstanceState", e.getError().getCode()); assertEquals("IncorrectInstanceState", e.getError().getCode());
@ -246,9 +271,10 @@ public class CloudApplicationArchitecturesEC2ClientLiveTest {
private void setRamdiskForInstanceInRegion() { private void setRamdiskForInstanceInRegion() {
try { try {
String ramdisk = client.getInstanceServices().getRamdiskForInstanceInRegion(null, String ramdisk = client.getInstanceServices()
instanceId); .getRamdiskForInstanceInRegion(null, instanceId);
client.getInstanceServices().setRamdiskForInstanceInRegion(null, instanceId, ramdisk); client.getInstanceServices().setRamdiskForInstanceInRegion(null,
instanceId, ramdisk);
assert false : "shouldn't be allowed, as instance needs to be stopped"; assert false : "shouldn't be allowed, as instance needs to be stopped";
} catch (AWSResponseException e) { } catch (AWSResponseException e) {
assertEquals("IncorrectInstanceState", e.getError().getCode()); assertEquals("IncorrectInstanceState", e.getError().getCode());
@ -257,9 +283,10 @@ public class CloudApplicationArchitecturesEC2ClientLiveTest {
private void setKernelForInstanceInRegion() { private void setKernelForInstanceInRegion() {
try { try {
String oldKernel = client.getInstanceServices().getKernelForInstanceInRegion(null, String oldKernel = client.getInstanceServices()
instanceId); .getKernelForInstanceInRegion(null, instanceId);
client.getInstanceServices().setKernelForInstanceInRegion(null, instanceId, oldKernel); client.getInstanceServices().setKernelForInstanceInRegion(null,
instanceId, oldKernel);
assert false : "shouldn't be allowed, as instance needs to be stopped"; assert false : "shouldn't be allowed, as instance needs to be stopped";
} catch (AWSResponseException e) { } catch (AWSResponseException e) {
assertEquals("IncorrectInstanceState", e.getError().getCode()); assertEquals("IncorrectInstanceState", e.getError().getCode());
@ -268,8 +295,8 @@ public class CloudApplicationArchitecturesEC2ClientLiveTest {
private void setInstanceTypeForInstanceInRegion() { private void setInstanceTypeForInstanceInRegion() {
try { try {
client.getInstanceServices().setInstanceTypeForInstanceInRegion(null, instanceId, client.getInstanceServices().setInstanceTypeForInstanceInRegion(null,
InstanceType.C1_MEDIUM); instanceId, InstanceType.C1_MEDIUM);
assert false : "shouldn't be allowed, as instance needs to be stopped"; assert false : "shouldn't be allowed, as instance needs to be stopped";
} catch (AWSResponseException e) { } catch (AWSResponseException e) {
assertEquals("IncorrectInstanceState", e.getError().getCode()); assertEquals("IncorrectInstanceState", e.getError().getCode());
@ -279,8 +306,8 @@ public class CloudApplicationArchitecturesEC2ClientLiveTest {
private void setBlockDeviceMappingForInstanceInRegion() { private void setBlockDeviceMappingForInstanceInRegion() {
BlockDeviceMapping blockDeviceMapping = new BlockDeviceMapping(); BlockDeviceMapping blockDeviceMapping = new BlockDeviceMapping();
try { try {
client.getInstanceServices().setBlockDeviceMappingForInstanceInRegion(null, instanceId, client.getInstanceServices().setBlockDeviceMappingForInstanceInRegion(
blockDeviceMapping); null, instanceId, blockDeviceMapping);
assert false : "shouldn't be allowed, as instance needs to be ebs based-ami"; assert false : "shouldn't be allowed, as instance needs to be ebs based-ami";
} catch (AWSResponseException e) { } catch (AWSResponseException e) {
assertEquals("InvalidParameterCombination", e.getError().getCode()); assertEquals("InvalidParameterCombination", e.getError().getCode());
@ -289,8 +316,9 @@ public class CloudApplicationArchitecturesEC2ClientLiveTest {
private void setInstanceInitiatedShutdownBehaviorForInstanceInRegion() { private void setInstanceInitiatedShutdownBehaviorForInstanceInRegion() {
try { try {
client.getInstanceServices().setInstanceInitiatedShutdownBehaviorForInstanceInRegion(null, client.getInstanceServices()
instanceId, InstanceInitiatedShutdownBehavior.STOP); .setInstanceInitiatedShutdownBehaviorForInstanceInRegion(null,
instanceId, InstanceInitiatedShutdownBehavior.STOP);
assert false : "shouldn't be allowed, as instance needs to be ebs based-ami"; assert false : "shouldn't be allowed, as instance needs to be ebs based-ami";
} catch (AWSResponseException e) { } catch (AWSResponseException e) {
assertEquals("UnsupportedInstanceAttribute", e.getError().getCode()); assertEquals("UnsupportedInstanceAttribute", e.getError().getCode());
@ -298,19 +326,22 @@ public class CloudApplicationArchitecturesEC2ClientLiveTest {
} }
@Test(enabled = false, dependsOnMethods = "testCreateRunningInstance") @Test(enabled = false, dependsOnMethods = "testCreateRunningInstance")
void testReboot() throws InterruptedException, ExecutionException, TimeoutException, IOException { void testReboot() throws InterruptedException, ExecutionException,
TimeoutException, IOException {
RunningInstance instance = getInstance(instanceId); RunningInstance instance = getInstance(instanceId);
System.out.printf("%d: %s rebooting instance %n", System.currentTimeMillis(), instanceId); System.out.printf("%d: %s rebooting instance %n", System
.currentTimeMillis(), instanceId);
client.getInstanceServices().rebootInstancesInRegion(null, instanceId); client.getInstanceServices().rebootInstancesInRegion(null, instanceId);
Thread.sleep(1000); Thread.sleep(1000);
instance = getInstance(instanceId); instance = getInstance(instanceId);
blockUntilWeCanSshIntoInstance(instance); blockUntilWeCanSshIntoInstance(instance);
SshClient ssh = sshFactory.create(new IPSocket(instance.getIpAddress(), 22), "root", keyPair SshClient ssh = sshFactory.create(new IPSocket(instance.getIpAddress(),
.getKeyMaterial().getBytes()); 22), "root", keyPair.getKeyMaterial().getBytes());
try { try {
ssh.connect(); ssh.connect();
ExecResponse uptime = ssh.exec("uptime"); ExecResponse uptime = ssh.exec("uptime");
assert uptime.getOutput().indexOf("0 min") != -1 : "reboot didn't work: " + uptime; assert uptime.getOutput().indexOf("0 min") != -1 : "reboot didn't work: "
+ uptime;
} finally { } finally {
if (ssh != null) if (ssh != null)
ssh.disconnect(); ssh.disconnect();
@ -318,86 +349,95 @@ public class CloudApplicationArchitecturesEC2ClientLiveTest {
} }
@Test(enabled = false, dependsOnMethods = "testReboot") @Test(enabled = false, dependsOnMethods = "testReboot")
void testElasticIpAddress() throws InterruptedException, ExecutionException, TimeoutException, void testElasticIpAddress() throws InterruptedException, ExecutionException,
IOException { TimeoutException, IOException {
address = client.getElasticIPAddressServices().allocateAddressInRegion(null); address = client.getElasticIPAddressServices().allocateAddressInRegion(
null);
assertNotNull(address); assertNotNull(address);
PublicIpInstanceIdPair compare = Iterables.getLast(client.getElasticIPAddressServices() PublicIpInstanceIdPair compare = Iterables.getLast(client
.describeAddressesInRegion(null, address)); .getElasticIPAddressServices().describeAddressesInRegion(null,
address));
assertEquals(compare.getPublicIp(), address); assertEquals(compare.getPublicIp(), address);
assert compare.getInstanceId() == null; assert compare.getInstanceId() == null;
client.getElasticIPAddressServices().associateAddressInRegion(null, address, instanceId); client.getElasticIPAddressServices().associateAddressInRegion(null,
address, instanceId);
compare = Iterables.getLast(client.getElasticIPAddressServices().describeAddressesInRegion( compare = Iterables.getLast(client.getElasticIPAddressServices()
null, address)); .describeAddressesInRegion(null, address));
assertEquals(compare.getPublicIp(), address); assertEquals(compare.getPublicIp(), address);
assertEquals(compare.getInstanceId(), instanceId); assertEquals(compare.getInstanceId(), instanceId);
Reservation reservation = Iterables.getOnlyElement(client.getInstanceServices() Reservation reservation = Iterables.getOnlyElement(client
.describeInstancesInRegion(null, instanceId)); .getInstanceServices().describeInstancesInRegion(null, instanceId));
assertNotNull(Iterables.getOnlyElement(reservation).getIpAddress()); assertNotNull(Iterables.getOnlyElement(reservation).getIpAddress());
assertFalse(Iterables.getOnlyElement(reservation).getIpAddress().equals(address)); assertFalse(Iterables.getOnlyElement(reservation).getIpAddress().equals(
address));
doCheckKey(address); doCheckKey(address);
client.getElasticIPAddressServices().disassociateAddressInRegion(null, address); client.getElasticIPAddressServices().disassociateAddressInRegion(null,
address);
compare = Iterables.getLast(client.getElasticIPAddressServices().describeAddressesInRegion( compare = Iterables.getLast(client.getElasticIPAddressServices()
null, address)); .describeAddressesInRegion(null, address));
assertEquals(compare.getPublicIp(), address); assertEquals(compare.getPublicIp(), address);
assert compare.getInstanceId() == null; assert compare.getInstanceId() == null;
reservation = Iterables.getOnlyElement(client.getInstanceServices() reservation = Iterables.getOnlyElement(client.getInstanceServices()
.describeInstancesInRegion(null, instanceId)); .describeInstancesInRegion(null, instanceId));
// assert reservation.getRunningInstances().last().getIpAddress() == null; TODO // assert reservation.getRunningInstances().last().getIpAddress() == null;
// TODO
} }
private RunningInstance blockUntilWeCanSshIntoInstance(RunningInstance instance) private RunningInstance blockUntilWeCanSshIntoInstance(
throws UnknownHostException { RunningInstance instance) throws UnknownHostException {
System.out.printf("%d: %s awaiting instance to run %n", System.currentTimeMillis(), instance System.out.printf("%d: %s awaiting instance to run %n", System
.getId()); .currentTimeMillis(), instance.getId());
assert runningTester.apply(instance); assert runningTester.apply(instance);
instance = getInstance(instance.getId()); instance = getInstance(instance.getId());
System.out.printf("%d: %s awaiting instance to have ip assigned %n", System System.out.printf("%d: %s awaiting instance to have ip assigned %n",
.currentTimeMillis(), instance.getId()); System.currentTimeMillis(), instance.getId());
assert hasIpTester.apply(instance); assert hasIpTester.apply(instance);
System.out.printf("%d: %s awaiting ssh service to start%n", System.currentTimeMillis(), System.out.printf("%d: %s awaiting ssh service to start%n", System
instance.getIpAddress()); .currentTimeMillis(), instance.getIpAddress());
assert socketTester.apply(new IPSocket(instance.getIpAddress(), 22)); assert socketTester.apply(new IPSocket(instance.getIpAddress(), 22));
System.out.printf("%d: %s ssh service started%n", System.currentTimeMillis(), instance System.out.printf("%d: %s ssh service started%n", System
.getDnsName()); .currentTimeMillis(), instance.getDnsName());
sshPing(instance); sshPing(instance);
System.out.printf("%d: %s ssh connection made%n", System.currentTimeMillis(), instance System.out.printf("%d: %s ssh connection made%n", System
.getId()); .currentTimeMillis(), instance.getId());
System.out.printf("%d: %s awaiting http service to start%n", System.currentTimeMillis(), System.out.printf("%d: %s awaiting http service to start%n", System
instance.getIpAddress()); .currentTimeMillis(), instance.getIpAddress());
assert socketTester.apply(new IPSocket(instance.getIpAddress(), 80)); assert socketTester.apply(new IPSocket(instance.getIpAddress(), 80));
System.out.printf("%d: %s http service started%n", System.currentTimeMillis(), instance System.out.printf("%d: %s http service started%n", System
.getDnsName()); .currentTimeMillis(), instance.getDnsName());
return instance; return instance;
} }
private RunningInstance getInstance(String instanceId) { private RunningInstance getInstance(String instanceId) {
// search my account for the instance I just created // search my account for the instance I just created
Set<Reservation> reservations = client.getInstanceServices().describeInstancesInRegion(null, Set<Reservation> reservations = client.getInstanceServices()
instanceId); // last parameter (ids) narrows the search .describeInstancesInRegion(null, instanceId); // last parameter
// (ids) narrows the
// search
return Iterables.getOnlyElement(Iterables.getOnlyElement(reservations)); return Iterables.getOnlyElement(Iterables.getOnlyElement(reservations));
} }
/** /**
* this tests "personality" as the file looked up was sent during instance creation * this tests "personality" as the file looked up was sent during instance
* creation
* *
* @throws UnknownHostException * @throws UnknownHostException
*/ */
@ -413,13 +453,14 @@ public class CloudApplicationArchitecturesEC2ClientLiveTest {
} }
} }
private void doCheckKey(RunningInstance newDetails) throws UnknownHostException { private void doCheckKey(RunningInstance newDetails)
throws UnknownHostException {
doCheckKey(newDetails.getIpAddress()); doCheckKey(newDetails.getIpAddress());
} }
private void doCheckKey(String address) { private void doCheckKey(String address) {
SshClient ssh = sshFactory.create(new IPSocket(address, 22), "root", keyPair.getKeyMaterial() SshClient ssh = sshFactory.create(new IPSocket(address, 22), "root",
.getBytes()); keyPair.getKeyMaterial().getBytes());
try { try {
ssh.connect(); ssh.connect();
ExecResponse hello = ssh.exec("echo hello"); ExecResponse hello = ssh.exec("echo hello");
@ -431,15 +472,20 @@ public class CloudApplicationArchitecturesEC2ClientLiveTest {
} }
@AfterTest @AfterTest
void cleanup() throws InterruptedException, ExecutionException, TimeoutException { void cleanup() throws InterruptedException, ExecutionException,
TimeoutException {
if (address != null) if (address != null)
client.getElasticIPAddressServices().releaseAddressInRegion(null, address); client.getElasticIPAddressServices().releaseAddressInRegion(null,
address);
if (instanceId != null) if (instanceId != null)
client.getInstanceServices().terminateInstancesInRegion(null, instanceId); client.getInstanceServices().terminateInstancesInRegion(null,
instanceId);
if (keyPair != null) if (keyPair != null)
client.getKeyPairServices().deleteKeyPairInRegion(null, keyPair.getKeyName()); client.getKeyPairServices().deleteKeyPairInRegion(null,
keyPair.getKeyName());
if (securityGroupName != null) if (securityGroupName != null)
client.getSecurityGroupServices().deleteSecurityGroupInRegion(null, securityGroupName); client.getSecurityGroupServices().deleteSecurityGroupInRegion(null,
securityGroupName);
} }
} }

View File

@ -78,8 +78,8 @@ import com.google.inject.Injector;
import com.google.inject.internal.ImmutableMap; import com.google.inject.internal.ImmutableMap;
/** /**
* Adapted from the following sources: {@link http://gist.github.com/249915}, {@link http * Adapted from the following sources: {@link http://gist.github.com/249915},
* ://www.capsunlock.net/2009/12/create-ebs-boot-ami.html} * {@link http ://www.capsunlock.net/2009/12/create-ebs-boot-ami.html}
* <p/> * <p/>
* *
* Generally disabled, as it incurs higher fees. * Generally disabled, as it incurs higher fees.
@ -91,7 +91,9 @@ public class EBSBootEC2ClientLiveTest {
// don't need a lot of space. 2GB should be more than enough for testing // don't need a lot of space. 2GB should be more than enough for testing
private static final int VOLUME_SIZE = 2; private static final int VOLUME_SIZE = 2;
private static final String SCRIPT_END = "----COMPLETE----"; private static final String SCRIPT_END = "----COMPLETE----";
private static final String INSTANCE_PREFIX = System.getProperty("user.name") + ".ec2ebs"; private static final String INSTANCE_PREFIX = System
.getProperty("user.name")
+ ".ec2ebs";
private static final String IMAGE_ID = "ami-7e28ca17"; private static final String IMAGE_ID = "ami-7e28ca17";
private EC2Client client; private EC2Client client;
@ -117,58 +119,70 @@ public class EBSBootEC2ClientLiveTest {
@BeforeGroups(groups = { "live" }) @BeforeGroups(groups = { "live" })
public void setupClient() { public void setupClient() {
String user = checkNotNull(System.getProperty("jclouds.test.user"), "jclouds.test.user"); String user = checkNotNull(System.getProperty("jclouds.test.user"),
String password = checkNotNull(System.getProperty("jclouds.test.key"), "jclouds.test.key"); "jclouds.test.user");
Injector injector = new EC2ContextBuilder("ec2", new EC2PropertiesBuilder(user, password) String password = checkNotNull(System.getProperty("jclouds.test.key"),
.build()).withModules(new Log4JLoggingModule(), new JschSshClientModule()) "jclouds.test.key");
.buildInjector(); Injector injector = new EC2ContextBuilder("ec2",
new EC2PropertiesBuilder(user, password).build()).withModules(
new Log4JLoggingModule(), new JschSshClientModule())
.buildInjector();
client = injector.getInstance(EC2Client.class); client = injector.getInstance(EC2Client.class);
sshFactory = injector.getInstance(SshClient.Factory.class); sshFactory = injector.getInstance(SshClient.Factory.class);
SocketOpen socketOpen = injector.getInstance(SocketOpen.class); SocketOpen socketOpen = injector.getInstance(SocketOpen.class);
socketTester = new RetryablePredicate<IPSocket>(socketOpen, 120, 1, TimeUnit.SECONDS); socketTester = new RetryablePredicate<IPSocket>(socketOpen, 120, 1,
TimeUnit.SECONDS);
VolumeAvailable volumeAvailable = injector.getInstance(VolumeAvailable.class); VolumeAvailable volumeAvailable = injector
volumeTester = new RetryablePredicate<Volume>(volumeAvailable, 60, 1, TimeUnit.SECONDS); .getInstance(VolumeAvailable.class);
volumeTester = new RetryablePredicate<Volume>(volumeAvailable, 60, 1,
TimeUnit.SECONDS);
SnapshotCompleted snapshotCompleted = injector.getInstance(SnapshotCompleted.class); SnapshotCompleted snapshotCompleted = injector
snapshotTester = new RetryablePredicate<Snapshot>(snapshotCompleted, 120, 3, TimeUnit.SECONDS); .getInstance(SnapshotCompleted.class);
snapshotTester = new RetryablePredicate<Snapshot>(snapshotCompleted, 120,
3, TimeUnit.SECONDS);
VolumeAttached volumeAttached = injector.getInstance(VolumeAttached.class); VolumeAttached volumeAttached = injector
attachTester = new RetryablePredicate<Attachment>(volumeAttached, 60, 1, TimeUnit.SECONDS); .getInstance(VolumeAttached.class);
attachTester = new RetryablePredicate<Attachment>(volumeAttached, 60, 1,
TimeUnit.SECONDS);
runningTester = new RetryablePredicate<RunningInstance>(new InstanceStateRunning(client), runningTester = new RetryablePredicate<RunningInstance>(
180, 5, TimeUnit.SECONDS); new InstanceStateRunning(client), 180, 5, TimeUnit.SECONDS);
InstanceStateStopped instanceStateStopped = injector.getInstance(InstanceStateStopped.class); InstanceStateStopped instanceStateStopped = injector
stoppedTester = new RetryablePredicate<RunningInstance>(instanceStateStopped, 60, 1, .getInstance(InstanceStateStopped.class);
TimeUnit.SECONDS); stoppedTester = new RetryablePredicate<RunningInstance>(
instanceStateStopped, 60, 1, TimeUnit.SECONDS);
InstanceStateTerminated instanceStateTerminated = injector InstanceStateTerminated instanceStateTerminated = injector
.getInstance(InstanceStateTerminated.class); .getInstance(InstanceStateTerminated.class);
terminatedTester = new RetryablePredicate<RunningInstance>(instanceStateTerminated, 60, 1, terminatedTester = new RetryablePredicate<RunningInstance>(
TimeUnit.SECONDS); instanceStateTerminated, 60, 1, TimeUnit.SECONDS);
injector.injectMembers(socketOpen); // add logger injector.injectMembers(socketOpen); // add logger
} }
@Test(enabled = false) @Test(enabled = false)
void testCreateSecurityGroupIngressCidr() throws InterruptedException, ExecutionException, void testCreateSecurityGroupIngressCidr() throws InterruptedException,
TimeoutException { ExecutionException, TimeoutException {
securityGroupName = INSTANCE_PREFIX + "ingress"; securityGroupName = INSTANCE_PREFIX + "ingress";
try { try {
client.getSecurityGroupServices().deleteSecurityGroupInRegion(null, securityGroupName); client.getSecurityGroupServices().deleteSecurityGroupInRegion(null,
securityGroupName);
} catch (Exception e) { } catch (Exception e) {
} }
client.getSecurityGroupServices().createSecurityGroupInRegion(null, securityGroupName, client.getSecurityGroupServices().createSecurityGroupInRegion(null,
securityGroupName); securityGroupName, securityGroupName);
client.getSecurityGroupServices().authorizeSecurityGroupIngressInRegion(null, client.getSecurityGroupServices().authorizeSecurityGroupIngressInRegion(
securityGroupName, IpProtocol.TCP, 80, 80, "0.0.0.0/0"); null, securityGroupName, IpProtocol.TCP, 80, 80, "0.0.0.0/0");
client.getSecurityGroupServices().authorizeSecurityGroupIngressInRegion(null, client.getSecurityGroupServices().authorizeSecurityGroupIngressInRegion(
securityGroupName, IpProtocol.TCP, 443, 443, "0.0.0.0/0"); null, securityGroupName, IpProtocol.TCP, 443, 443, "0.0.0.0/0");
client.getSecurityGroupServices().authorizeSecurityGroupIngressInRegion(null, client.getSecurityGroupServices().authorizeSecurityGroupIngressInRegion(
securityGroupName, IpProtocol.TCP, 22, 22, "0.0.0.0/0"); null, securityGroupName, IpProtocol.TCP, 22, 22, "0.0.0.0/0");
} }
@Test(enabled = false) @Test(enabled = false)
@ -180,7 +194,8 @@ public class EBSBootEC2ClientLiveTest {
} }
keyPair = client.getKeyPairServices().createKeyPairInRegion(null, keyName); keyPair = client.getKeyPairServices()
.createKeyPairInRegion(null, keyName);
assertNotNull(keyPair); assertNotNull(keyPair);
assertNotNull(keyPair.getKeyMaterial()); assertNotNull(keyPair.getKeyMaterial());
assertNotNull(keyPair.getKeyFingerprint()); assertNotNull(keyPair.getKeyFingerprint());
@ -188,28 +203,34 @@ public class EBSBootEC2ClientLiveTest {
} }
@Test(enabled = false, dependsOnMethods = { "testCreateKeyPair", @Test(enabled = false, dependsOnMethods = { "testCreateKeyPair",
"testCreateSecurityGroupIngressCidr" }) "testCreateSecurityGroupIngressCidr" })
public void testCreateRunningInstance() throws Exception { public void testCreateRunningInstance() throws Exception {
instance = createInstance(IMAGE_ID); instance = createInstance(IMAGE_ID);
} }
private RunningInstance createInstance(String imageId) throws UnknownHostException { private RunningInstance createInstance(String imageId)
throws UnknownHostException {
RunningInstance instance = null; RunningInstance instance = null;
while (instance == null) { while (instance == null) {
try { try {
System.out.printf("%d: running instance%n", System.currentTimeMillis()); System.out.printf("%d: running instance%n", System
Reservation reservation = client.getInstanceServices().runInstancesInRegion(null, null, // allow .currentTimeMillis());
// ec2 Reservation reservation = client.getInstanceServices()
// to .runInstancesInRegion(null, null, // allow
// chose // ec2
// an // to
// availability // chose
// zone // an
imageId, 1, // minimum instances // availability
1, // maximum instances // zone
withKeyName(keyPair.getKeyName())// key I created above imageId, 1, // minimum instances
.asType(InstanceType.M1_SMALL)// smallest instance size 1, // maximum instances
.withSecurityGroup(securityGroupName));// group I created above withKeyName(keyPair.getKeyName())// key I created above
.asType(InstanceType.M1_SMALL)// smallest instance
// size
.withSecurityGroup(securityGroupName));// group I
// created
// above
instance = Iterables.getOnlyElement(reservation); instance = Iterables.getOnlyElement(reservation);
} catch (HttpResponseException htpe) { } catch (HttpResponseException htpe) {
if (htpe.getResponse().getStatusCode() == 400) if (htpe.getResponse().getStatusCode() == 400)
@ -225,55 +246,62 @@ public class EBSBootEC2ClientLiveTest {
@Test(enabled = false, dependsOnMethods = "testCreateRunningInstance") @Test(enabled = false, dependsOnMethods = "testCreateRunningInstance")
void testCreateAndAttachVolume() { void testCreateAndAttachVolume() {
volume = client.getElasticBlockStoreServices().createVolumeInAvailabilityZone( volume = client.getElasticBlockStoreServices()
instance.getAvailabilityZone(), VOLUME_SIZE); .createVolumeInAvailabilityZone(instance.getAvailabilityZone(),
System.out.printf("%d: %s awaiting volume to become available%n", System.currentTimeMillis(), VOLUME_SIZE);
volume.getId()); System.out.printf("%d: %s awaiting volume to become available%n", System
.currentTimeMillis(), volume.getId());
assert volumeTester.apply(volume); assert volumeTester.apply(volume);
Attachment attachment = client.getElasticBlockStoreServices().attachVolumeInRegion( Attachment attachment = client.getElasticBlockStoreServices()
instance.getRegion(), volume.getId(), instance.getId(), "/dev/sdh"); .attachVolumeInRegion(instance.getRegion(), volume.getId(),
instance.getId(), "/dev/sdh");
System.out.printf("%d: %s awaiting attachment to complete%n", System.currentTimeMillis(), System.out.printf("%d: %s awaiting attachment to complete%n", System
attachment.getId()); .currentTimeMillis(), attachment.getId());
assert attachTester.apply(attachment); assert attachTester.apply(attachment);
System.out.printf("%d: %s attachment complete%n", System.currentTimeMillis(), attachment System.out.printf("%d: %s attachment complete%n", System
.getId()); .currentTimeMillis(), attachment.getId());
} }
// TODO use userData to do this, and make initbuilder an example for something else. // TODO use userData to do this, and make initbuilder an example for
// something else.
@BeforeTest @BeforeTest
void makeScript() { void makeScript() {
mkEbsBoot = new InitBuilder( mkEbsBoot = new InitBuilder(
"mkebsboot",// name of the script "mkebsboot",// name of the script
"/tmp",// working directory "/tmp",// working directory
"/tmp/logs",// location of stdout.log and stderr.log "/tmp/logs",// location of stdout.log and stderr.log
ImmutableMap.of("imageDir", "/mnt/tmp", "ebsDevice", "/dev/sdh", "ebsMountPoint", ImmutableMap.of("imageDir", "/mnt/tmp", "ebsDevice", "/dev/sdh",
"/mnt/ebs"),// variables used inside of the script "ebsMountPoint", "/mnt/ebs"),// variables used inside of the
"echo creating a filesystem and mounting the ebs volume",// what to execute // script
"{md} {varl}IMAGE_DIR{varr} {varl}EBS_MOUNT_POINT{varr}", "echo creating a filesystem and mounting the ebs volume",// what to
"rm -rf {varl}IMAGE_DIR{varr}/*", // execute
"yes| mkfs -t ext3 {varl}EBS_DEVICE{varr} 2>&-", "{md} {varl}IMAGE_DIR{varr} {varl}EBS_MOUNT_POINT{varr}",
"mount {varl}EBS_DEVICE{varr} {varl}EBS_MOUNT_POINT{varr}", "rm -rf {varl}IMAGE_DIR{varr}/*",
"echo making a local working copy of the boot disk", "yes| mkfs -t ext3 {varl}EBS_DEVICE{varr} 2>&-",
"rsync -ax --exclude /ubuntu/.bash_history --exclude /home/*/.bash_history --exclude /etc/ssh/ssh_host_* --exclude /etc/ssh/moduli --exclude /etc/udev/rules.d/*persistent-net.rules --exclude /var/lib/ec2/* --exclude=/mnt/* --exclude=/proc/* --exclude=/tmp/* --exclude=/dev/log / {varl}IMAGE_DIR{varr}", "mount {varl}EBS_DEVICE{varr} {varl}EBS_MOUNT_POINT{varr}",
"echo preparing the local working copy", "echo making a local working copy of the boot disk",
"touch {varl}IMAGE_DIR{varr}/etc/init.d/ec2-init-user-data", "rsync -ax --exclude /ubuntu/.bash_history --exclude /home/*/.bash_history --exclude /etc/ssh/ssh_host_* --exclude /etc/ssh/moduli --exclude /etc/udev/rules.d/*persistent-net.rules --exclude /var/lib/ec2/* --exclude=/mnt/* --exclude=/proc/* --exclude=/tmp/* --exclude=/dev/log / {varl}IMAGE_DIR{varr}",
"echo copying the local working copy to the ebs mount", "echo preparing the local working copy",
"{cd} {varl}IMAGE_DIR{varr}", "touch {varl}IMAGE_DIR{varr}/etc/init.d/ec2-init-user-data",
"tar -cSf - * | tar xf - -C {varl}EBS_MOUNT_POINT{varr}", "echo size of ebs", "echo copying the local working copy to the ebs mount",
"du -sk {varl}EBS_MOUNT_POINT{varr}", "echo size of source", "{cd} {varl}IMAGE_DIR{varr}",
"du -sk {varl}IMAGE_DIR{varr}", "rm -rf {varl}IMAGE_DIR{varr}/*", "tar -cSf - * | tar xf - -C {varl}EBS_MOUNT_POINT{varr}",
"umount {varl}EBS_MOUNT_POINT{varr}", "echo " + SCRIPT_END).build(OsFamily.UNIX); "echo size of ebs", "du -sk {varl}EBS_MOUNT_POINT{varr}",
"echo size of source", "du -sk {varl}IMAGE_DIR{varr}",
"rm -rf {varl}IMAGE_DIR{varr}/*",
"umount {varl}EBS_MOUNT_POINT{varr}", "echo " + SCRIPT_END)
.build(OsFamily.UNIX);
} }
@Test(enabled = false, dependsOnMethods = "testCreateAndAttachVolume") @Test(enabled = false, dependsOnMethods = "testCreateAndAttachVolume")
void testBundleInstance() { void testBundleInstance() {
SshClient ssh = sshFactory.create(new IPSocket(instance.getIpAddress(), 22), "ubuntu", SshClient ssh = sshFactory.create(new IPSocket(instance.getIpAddress(),
keyPair.getKeyMaterial().getBytes()); 22), "ubuntu", keyPair.getKeyMaterial().getBytes());
try { try {
ssh.connect(); ssh.connect();
} catch (SshException e) {// try twice in case there is a network timeout } catch (SshException e) {// try twice in case there is a network timeout
@ -284,13 +312,13 @@ public class EBSBootEC2ClientLiveTest {
ssh.connect(); ssh.connect();
} }
try { try {
System.out.printf("%d: %s writing ebs script%n", System.currentTimeMillis(), instance System.out.printf("%d: %s writing ebs script%n", System
.getId()); .currentTimeMillis(), instance.getId());
String script = "/tmp/mkebsboot-init.sh"; String script = "/tmp/mkebsboot-init.sh";
ssh.put(script, new ByteArrayInputStream(mkEbsBoot.getBytes())); ssh.put(script, new ByteArrayInputStream(mkEbsBoot.getBytes()));
System.out.printf("%d: %s launching ebs script%n", System.currentTimeMillis(), instance System.out.printf("%d: %s launching ebs script%n", System
.getId()); .currentTimeMillis(), instance.getId());
ssh.exec("chmod 755 " + script); ssh.exec("chmod 755 " + script);
ssh.exec(script + " init"); ssh.exec(script + " init");
ExecResponse output = ssh.exec("sudo " + script + " start"); ExecResponse output = ssh.exec("sudo " + script + " start");
@ -299,8 +327,8 @@ public class EBSBootEC2ClientLiveTest {
assert !output.getOutput().trim().equals("") : output; assert !output.getOutput().trim().equals("") : output;
RetryablePredicate<String> scriptTester = new RetryablePredicate<String>(new ScriptTester( RetryablePredicate<String> scriptTester = new RetryablePredicate<String>(
ssh, SCRIPT_END), 600, 10, TimeUnit.SECONDS); new ScriptTester(ssh, SCRIPT_END), 600, 10, TimeUnit.SECONDS);
scriptTester.apply(script); scriptTester.apply(script);
} finally { } finally {
if (ssh != null) if (ssh != null)
@ -319,7 +347,8 @@ public class EBSBootEC2ClientLiveTest {
@Override @Override
public boolean apply(String script) { public boolean apply(String script) {
System.out.printf("%d: %s testing status%n", System.currentTimeMillis(), script); System.out.printf("%d: %s testing status%n", System
.currentTimeMillis(), script);
ExecResponse output = ssh.exec(script + " status"); ExecResponse output = ssh.exec(script + " status");
if (output.getOutput().trim().equals("")) { if (output.getOutput().trim().equals("")) {
output = ssh.exec(script + " tail"); output = ssh.exec(script + " tail");
@ -329,9 +358,11 @@ public class EBSBootEC2ClientLiveTest {
} else { } else {
output = ssh.exec(script + " tailerr"); output = ssh.exec(script + " tailerr");
String stderr = output.getOutput().trim(); String stderr = output.getOutput().trim();
throw new RuntimeException(String.format( throw new RuntimeException(
"script %s ended without token: stdout.log: [%s]; stderr.log: [%s]; ", String
script, stdout, stderr)); .format(
"script %s ended without token: stdout.log: [%s]; stderr.log: [%s]; ",
script, stdout, stderr));
} }
} }
return false; return false;
@ -342,45 +373,52 @@ public class EBSBootEC2ClientLiveTest {
@Test(enabled = false, dependsOnMethods = "testBundleInstance") @Test(enabled = false, dependsOnMethods = "testBundleInstance")
void testAMIFromBundle() { void testAMIFromBundle() {
volume = Iterables.getOnlyElement(client.getElasticBlockStoreServices() volume = Iterables.getOnlyElement(client.getElasticBlockStoreServices()
.describeVolumesInRegion(volume.getRegion(), volume.getId())); .describeVolumesInRegion(volume.getRegion(), volume.getId()));
if (volume.getAttachments().size() > 0) { if (volume.getAttachments().size() > 0) {
// should be cleanly unmounted, so force is not necessary. // should be cleanly unmounted, so force is not necessary.
client.getElasticBlockStoreServices().detachVolumeInRegion(instance.getRegion(), client.getElasticBlockStoreServices().detachVolumeInRegion(
volume.getId(), false); instance.getRegion(), volume.getId(), false);
System.out.printf("%d: %s awaiting detachment to complete%n", System.currentTimeMillis(), System.out.printf("%d: %s awaiting detachment to complete%n", System
volume.getId()); .currentTimeMillis(), volume.getId());
assert volumeTester.apply(volume); assert volumeTester.apply(volume);
} else { } else {
attachment = null; // protect test closer so that it doesn't try to detach attachment = null; // protect test closer so that it doesn't try to
// detach
} }
snapshot = client.getElasticBlockStoreServices().createSnapshotInRegion(volume.getRegion(), snapshot = client.getElasticBlockStoreServices().createSnapshotInRegion(
volume.getId(), withDescription("EBS Ubuntu Hardy")); volume.getRegion(), volume.getId(),
withDescription("EBS Ubuntu Hardy"));
System.out.printf("%d: %s awaiting snapshot to complete%n", System.currentTimeMillis(), System.out.printf("%d: %s awaiting snapshot to complete%n", System
snapshot.getId()); .currentTimeMillis(), snapshot.getId());
assert snapshotTester.apply(snapshot); assert snapshotTester.apply(snapshot);
Image image = Iterables.getOnlyElement(client.getAMIServices().describeImagesInRegion( Image image = Iterables.getOnlyElement(client.getAMIServices()
snapshot.getRegion(), imageIds(IMAGE_ID))); .describeImagesInRegion(snapshot.getRegion(), imageIds(IMAGE_ID)));
String description = image.getDescription() == null ? "jclouds" : image.getDescription(); String description = image.getDescription() == null ? "jclouds" : image
.getDescription();
System.out.printf("%d: %s creating ami from snapshot%n", System.currentTimeMillis(), snapshot System.out.printf("%d: %s creating ami from snapshot%n", System
.getId()); .currentTimeMillis(), snapshot.getId());
String amiId = client.getAMIServices().registerUnixImageBackedByEbsInRegion( String amiId = client.getAMIServices()
snapshot.getRegion(), .registerUnixImageBackedByEbsInRegion(
"ebsboot-" + image.getId(), snapshot.getRegion(),
snapshot.getId(), "ebsboot-" + image.getId(),
withKernelId(image.getKernelId()).withRamdisk(image.getRamdiskId()).withDescription( snapshot.getId(),
description).asArchitecture(Architecture.I386)); withKernelId(image.getKernelId()).withRamdisk(
image.getRamdiskId()).withDescription(description)
.asArchitecture(Architecture.I386));
try { try {
ebsImage = Iterables.getOnlyElement(client.getAMIServices().describeImagesInRegion( ebsImage = Iterables.getOnlyElement(client.getAMIServices()
snapshot.getRegion(), imageIds(amiId))); .describeImagesInRegion(snapshot.getRegion(), imageIds(amiId)));
} catch (AWSResponseException e) { } catch (AWSResponseException e) {
// TODO add a retry handler for this HTTP code 400 and the below error // TODO add a retry handler for this HTTP code 400 and the below error
if (e.getError().getClass().equals("InvalidAMIID.NotFound")) if (e.getError().getClass().equals("InvalidAMIID.NotFound"))
ebsImage = Iterables.getOnlyElement(client.getAMIServices().describeImagesInRegion( ebsImage = Iterables
snapshot.getRegion(), imageIds(amiId))); .getOnlyElement(client.getAMIServices()
.describeImagesInRegion(snapshot.getRegion(),
imageIds(amiId)));
else else
throw e; throw e;
} }
@ -389,22 +427,22 @@ public class EBSBootEC2ClientLiveTest {
@Test(enabled = false, dependsOnMethods = { "testAMIFromBundle" }) @Test(enabled = false, dependsOnMethods = { "testAMIFromBundle" })
public void testInstanceFromEBS() throws Exception { public void testInstanceFromEBS() throws Exception {
System.out.printf("%d: %s creating instance from ebs-backed ami%n", System System.out.printf("%d: %s creating instance from ebs-backed ami%n",
.currentTimeMillis(), ebsImage.getId()); System.currentTimeMillis(), ebsImage.getId());
ebsInstance = createInstance(ebsImage.getId()); ebsInstance = createInstance(ebsImage.getId());
client.getInstanceServices().stopInstancesInRegion(ebsInstance.getRegion(), true, client.getInstanceServices().stopInstancesInRegion(
ebsInstance.getId()); ebsInstance.getRegion(), true, ebsInstance.getId());
System.out.printf("%d: %s awaiting instance to stop %n", System.currentTimeMillis(), System.out.printf("%d: %s awaiting instance to stop %n", System
ebsInstance.getId()); .currentTimeMillis(), ebsInstance.getId());
stoppedTester.apply(ebsInstance); stoppedTester.apply(ebsInstance);
tryToChangeStuff(); tryToChangeStuff();
System.out.printf("%d: %s awaiting instance to start %n", System.currentTimeMillis(), System.out.printf("%d: %s awaiting instance to start %n", System
ebsInstance.getId()); .currentTimeMillis(), ebsInstance.getId());
client.getInstanceServices().startInstancesInRegion(ebsInstance.getRegion(), client.getInstanceServices().startInstancesInRegion(
ebsInstance.getId()); ebsInstance.getRegion(), ebsInstance.getId());
ebsInstance = blockUntilWeCanSshIntoInstance(ebsInstance); ebsInstance = blockUntilWeCanSshIntoInstance(ebsInstance);
} }
@ -412,8 +450,10 @@ public class EBSBootEC2ClientLiveTest {
assertEquals(ebsImage.getImageType(), ImageType.MACHINE); assertEquals(ebsImage.getImageType(), ImageType.MACHINE);
assertEquals(ebsImage.getRootDeviceType(), RootDeviceType.EBS); assertEquals(ebsImage.getRootDeviceType(), RootDeviceType.EBS);
assertEquals(ebsImage.getRootDeviceName(), "/dev/sda1"); assertEquals(ebsImage.getRootDeviceName(), "/dev/sda1");
assertEquals(ebsImage.getEbsBlockDevices().entrySet(), ImmutableMap.of("/dev/sda1", assertEquals(ebsImage.getEbsBlockDevices().entrySet(), ImmutableMap.of(
new Image.EbsBlockDevice(snapshot.getId(), VOLUME_SIZE, true)).entrySet()); "/dev/sda1",
new Image.EbsBlockDevice(snapshot.getId(), VOLUME_SIZE, true))
.entrySet());
} }
private void tryToChangeStuff() { private void tryToChangeStuff() {
@ -426,56 +466,59 @@ public class EBSBootEC2ClientLiveTest {
} }
private void setUserDataForInstanceInRegion() { private void setUserDataForInstanceInRegion() {
client.getInstanceServices().setUserDataForInstanceInRegion(null, ebsInstance.getId(), client.getInstanceServices().setUserDataForInstanceInRegion(null,
"test".getBytes()); ebsInstance.getId(), "test".getBytes());
assertEquals("test", client.getInstanceServices().getUserDataForInstanceInRegion(null, assertEquals("test", client.getInstanceServices()
ebsInstance.getId())); .getUserDataForInstanceInRegion(null, ebsInstance.getId()));
} }
private void setRamdiskForInstanceInRegion() { private void setRamdiskForInstanceInRegion() {
String ramdisk = client.getInstanceServices().getRamdiskForInstanceInRegion(null, String ramdisk = client.getInstanceServices()
ebsInstance.getId()); .getRamdiskForInstanceInRegion(null, ebsInstance.getId());
client.getInstanceServices() client.getInstanceServices().setRamdiskForInstanceInRegion(null,
.setRamdiskForInstanceInRegion(null, ebsInstance.getId(), ramdisk); ebsInstance.getId(), ramdisk);
assertEquals(ramdisk, client.getInstanceServices().getRamdiskForInstanceInRegion(null, assertEquals(ramdisk, client.getInstanceServices()
ebsInstance.getId())); .getRamdiskForInstanceInRegion(null, ebsInstance.getId()));
} }
private void setKernelForInstanceInRegion() { private void setKernelForInstanceInRegion() {
String oldKernel = client.getInstanceServices().getKernelForInstanceInRegion(null, String oldKernel = client.getInstanceServices()
ebsInstance.getId()); .getKernelForInstanceInRegion(null, ebsInstance.getId());
client.getInstanceServices().setKernelForInstanceInRegion(null, ebsInstance.getId(), client.getInstanceServices().setKernelForInstanceInRegion(null,
oldKernel); ebsInstance.getId(), oldKernel);
assertEquals(oldKernel, client.getInstanceServices().getKernelForInstanceInRegion(null, assertEquals(oldKernel, client.getInstanceServices()
ebsInstance.getId())); .getKernelForInstanceInRegion(null, ebsInstance.getId()));
} }
private void setInstanceTypeForInstanceInRegion() { private void setInstanceTypeForInstanceInRegion() {
client.getInstanceServices().setInstanceTypeForInstanceInRegion(null, ebsInstance.getId(), client.getInstanceServices().setInstanceTypeForInstanceInRegion(null,
InstanceType.C1_MEDIUM); ebsInstance.getId(), InstanceType.C1_MEDIUM);
assertEquals(InstanceType.C1_MEDIUM, client.getInstanceServices() assertEquals(InstanceType.C1_MEDIUM, client.getInstanceServices()
.getInstanceTypeForInstanceInRegion(null, ebsInstance.getId())); .getInstanceTypeForInstanceInRegion(null, ebsInstance.getId()));
client.getInstanceServices().setInstanceTypeForInstanceInRegion(null, ebsInstance.getId(), client.getInstanceServices().setInstanceTypeForInstanceInRegion(null,
InstanceType.M1_SMALL); ebsInstance.getId(), InstanceType.M1_SMALL);
assertEquals(InstanceType.M1_SMALL, client.getInstanceServices() assertEquals(InstanceType.M1_SMALL, client.getInstanceServices()
.getInstanceTypeForInstanceInRegion(null, ebsInstance.getId())); .getInstanceTypeForInstanceInRegion(null, ebsInstance.getId()));
} }
private void setBlockDeviceMappingForInstanceInRegion() { private void setBlockDeviceMappingForInstanceInRegion() {
String volumeId = ebsInstance.getEbsBlockDevices().get("/dev/sda1").getVolumeId(); String volumeId = ebsInstance.getEbsBlockDevices().get("/dev/sda1")
.getVolumeId();
BlockDeviceMapping blockDeviceMapping = new BlockDeviceMapping(); BlockDeviceMapping blockDeviceMapping = new BlockDeviceMapping();
blockDeviceMapping.addEbsBlockDevice("/dev/sda1", new RunningInstance.EbsBlockDevice( blockDeviceMapping.addEbsBlockDevice("/dev/sda1",
volumeId, false)); new RunningInstance.EbsBlockDevice(volumeId, false));
try { try {
client.getInstanceServices().setBlockDeviceMappingForInstanceInRegion(null, client.getInstanceServices().setBlockDeviceMappingForInstanceInRegion(
ebsInstance.getId(), blockDeviceMapping); null, ebsInstance.getId(), blockDeviceMapping);
Map<String, RunningInstance.EbsBlockDevice> devices = client.getInstanceServices() Map<String, RunningInstance.EbsBlockDevice> devices = client
.getBlockDeviceMappingForInstanceInRegion(null, ebsInstance.getId()); .getInstanceServices().getBlockDeviceMappingForInstanceInRegion(
null, ebsInstance.getId());
assertEquals(devices.size(), 1); assertEquals(devices.size(), 1);
String deviceName = Iterables.getOnlyElement(devices.keySet()); String deviceName = Iterables.getOnlyElement(devices.keySet());
RunningInstance.EbsBlockDevice device = Iterables.getOnlyElement(devices.values()); RunningInstance.EbsBlockDevice device = Iterables
.getOnlyElement(devices.values());
assertEquals(device.getVolumeId(), volumeId); assertEquals(device.getVolumeId(), volumeId);
assertEquals(deviceName, "/dev/sda1"); assertEquals(deviceName, "/dev/sda1");
@ -492,27 +535,36 @@ public class EBSBootEC2ClientLiveTest {
private void setInstanceInitiatedShutdownBehaviorForInstanceInRegion() { private void setInstanceInitiatedShutdownBehaviorForInstanceInRegion() {
try { try {
client.getInstanceServices().setInstanceInitiatedShutdownBehaviorForInstanceInRegion(null, client.getInstanceServices()
ebsInstance.getId(), InstanceInitiatedShutdownBehavior.STOP); .setInstanceInitiatedShutdownBehaviorForInstanceInRegion(null,
ebsInstance.getId(),
InstanceInitiatedShutdownBehavior.STOP);
assertEquals(InstanceInitiatedShutdownBehavior.STOP, client.getInstanceServices() assertEquals(InstanceInitiatedShutdownBehavior.STOP, client
.getInstanceInitiatedShutdownBehaviorForInstanceInRegion(null, .getInstanceServices()
ebsInstance.getId())); .getInstanceInitiatedShutdownBehaviorForInstanceInRegion(null,
client.getInstanceServices().setInstanceInitiatedShutdownBehaviorForInstanceInRegion(null, ebsInstance.getId()));
ebsInstance.getId(), InstanceInitiatedShutdownBehavior.TERMINATE); client.getInstanceServices()
.setInstanceInitiatedShutdownBehaviorForInstanceInRegion(null,
ebsInstance.getId(),
InstanceInitiatedShutdownBehavior.TERMINATE);
assertEquals(InstanceInitiatedShutdownBehavior.TERMINATE, client.getInstanceServices() assertEquals(InstanceInitiatedShutdownBehavior.TERMINATE, client
.getInstanceInitiatedShutdownBehaviorForInstanceInRegion(null, .getInstanceServices()
ebsInstance.getId())); .getInstanceInitiatedShutdownBehaviorForInstanceInRegion(null,
System.out.println("OK: setInstanceInitiatedShutdownBehaviorForInstanceInRegion"); ebsInstance.getId()));
System.out
.println("OK: setInstanceInitiatedShutdownBehaviorForInstanceInRegion");
} catch (Exception e) { } catch (Exception e) {
System.err.println("setInstanceInitiatedShutdownBehaviorForInstanceInRegion"); System.err
.println("setInstanceInitiatedShutdownBehaviorForInstanceInRegion");
e.printStackTrace(); e.printStackTrace();
} }
} }
/** /**
* this tests "personality" as the file looked up was sent during instance creation * this tests "personality" as the file looked up was sent during instance
* creation
* *
* @throws UnknownHostException * @throws UnknownHostException
*/ */
@ -528,13 +580,14 @@ public class EBSBootEC2ClientLiveTest {
} }
} }
private void doCheckKey(RunningInstance newDetails) throws UnknownHostException { private void doCheckKey(RunningInstance newDetails)
throws UnknownHostException {
doCheckKey(newDetails.getIpAddress()); doCheckKey(newDetails.getIpAddress());
} }
private void doCheckKey(String address) { private void doCheckKey(String address) {
SshClient ssh = sshFactory.create(new IPSocket(address, 22), "ubuntu", keyPair SshClient ssh = sshFactory.create(new IPSocket(address, 22), "ubuntu",
.getKeyMaterial().getBytes()); keyPair.getKeyMaterial().getBytes());
try { try {
ssh.connect(); ssh.connect();
ExecResponse hello = ssh.exec("echo hello"); ExecResponse hello = ssh.exec("echo hello");
@ -545,26 +598,32 @@ public class EBSBootEC2ClientLiveTest {
} }
} }
private RunningInstance blockUntilWeCanSshIntoInstance(RunningInstance instance) private RunningInstance blockUntilWeCanSshIntoInstance(
throws UnknownHostException { RunningInstance instance) throws UnknownHostException {
System.out.printf("%d: %s awaiting instance to run %n", System.currentTimeMillis(), instance System.out.printf("%d: %s awaiting instance to run %n", System
.getId()); .currentTimeMillis(), instance.getId());
assert runningTester.apply(instance); assert runningTester.apply(instance);
// search my account for the instance I just created // search my account for the instance I just created
Set<Reservation> reservations = client.getInstanceServices().describeInstancesInRegion( Set<Reservation> reservations = client.getInstanceServices()
instance.getRegion(), instance.getId()); // last parameter (ids) narrows the search .describeInstancesInRegion(instance.getRegion(), instance.getId()); // last
// parameter
// (ids)
// narrows
// the
// search
instance = Iterables.getOnlyElement(Iterables.getOnlyElement(reservations)); instance = Iterables.getOnlyElement(Iterables
.getOnlyElement(reservations));
System.out.printf("%d: %s awaiting ssh service to start%n", System.currentTimeMillis(), System.out.printf("%d: %s awaiting ssh service to start%n", System
instance.getIpAddress()); .currentTimeMillis(), instance.getIpAddress());
assert socketTester.apply(new IPSocket(instance.getIpAddress(), 22)); assert socketTester.apply(new IPSocket(instance.getIpAddress(), 22));
System.out.printf("%d: %s ssh service started%n", System.currentTimeMillis(), instance System.out.printf("%d: %s ssh service started%n", System
.getDnsName()); .currentTimeMillis(), instance.getDnsName());
sshPing(instance); sshPing(instance);
System.out.printf("%d: %s ssh connection made%n", System.currentTimeMillis(), instance System.out.printf("%d: %s ssh connection made%n", System
.getId()); .currentTimeMillis(), instance.getId());
return instance; return instance;
} }
@ -572,8 +631,8 @@ public class EBSBootEC2ClientLiveTest {
void cleanup() { void cleanup() {
if (ebsInstance != null) { if (ebsInstance != null) {
try { try {
client.getInstanceServices().terminateInstancesInRegion(ebsInstance.getRegion(), client.getInstanceServices().terminateInstancesInRegion(
ebsInstance.getId()); ebsInstance.getRegion(), ebsInstance.getId());
terminatedTester.apply(ebsInstance); terminatedTester.apply(ebsInstance);
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); e.printStackTrace();
@ -581,7 +640,8 @@ public class EBSBootEC2ClientLiveTest {
} }
if (ebsImage != null) { if (ebsImage != null) {
try { try {
client.getAMIServices().deregisterImageInRegion(ebsImage.getRegion(), ebsImage.getId()); client.getAMIServices().deregisterImageInRegion(
ebsImage.getRegion(), ebsImage.getId());
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); e.printStackTrace();
} }
@ -589,16 +649,16 @@ public class EBSBootEC2ClientLiveTest {
if (snapshot != null) { if (snapshot != null) {
try { try {
client.getElasticBlockStoreServices().deleteSnapshotInRegion(snapshot.getRegion(), client.getElasticBlockStoreServices().deleteSnapshotInRegion(
snapshot.getId()); snapshot.getRegion(), snapshot.getId());
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); e.printStackTrace();
} }
} }
if (attachment != null) { if (attachment != null) {
try { try {
client.getElasticBlockStoreServices().detachVolumeInRegion(volume.getRegion(), client.getElasticBlockStoreServices().detachVolumeInRegion(
volume.getId(), true); volume.getRegion(), volume.getId(), true);
assert volumeTester.apply(volume); assert volumeTester.apply(volume);
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); e.printStackTrace();
@ -606,8 +666,8 @@ public class EBSBootEC2ClientLiveTest {
} }
if (instance != null) { if (instance != null) {
try { try {
client.getInstanceServices().terminateInstancesInRegion(instance.getRegion(), client.getInstanceServices().terminateInstancesInRegion(
instance.getId()); instance.getRegion(), instance.getId());
terminatedTester.apply(instance); terminatedTester.apply(instance);
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); e.printStackTrace();
@ -615,23 +675,24 @@ public class EBSBootEC2ClientLiveTest {
} }
if (volume != null) { if (volume != null) {
try { try {
client.getElasticBlockStoreServices().deleteVolumeInRegion(volume.getRegion(), client.getElasticBlockStoreServices().deleteVolumeInRegion(
volume.getId()); volume.getRegion(), volume.getId());
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); e.printStackTrace();
} }
} }
if (keyPair != null) { if (keyPair != null) {
try { try {
client.getKeyPairServices().deleteKeyPairInRegion(keyPair.getRegion(), client.getKeyPairServices().deleteKeyPairInRegion(
keyPair.getKeyName()); keyPair.getRegion(), keyPair.getKeyName());
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); e.printStackTrace();
} }
} }
if (securityGroupName != null) { if (securityGroupName != null) {
try { try {
client.getSecurityGroupServices().deleteSecurityGroupInRegion(null, securityGroupName); client.getSecurityGroupServices().deleteSecurityGroupInRegion(null,
securityGroupName);
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); e.printStackTrace();
} }

View File

@ -63,13 +63,15 @@ public class EC2ComputeServiceLiveTest extends BaseComputeServiceLiveTest {
@Test(enabled = true, dependsOnMethods = "testCorrectAuthException") @Test(enabled = true, dependsOnMethods = "testCorrectAuthException")
public void testExtendedOptionsAndLogin() throws Exception { public void testExtendedOptionsAndLogin() throws Exception {
SecurityGroupClient securityGroupClient = EC2Client.class.cast( SecurityGroupClient securityGroupClient = EC2Client.class.cast(
context.getProviderSpecificContext().getApi()).getSecurityGroupServices(); context.getProviderSpecificContext().getApi())
.getSecurityGroupServices();
KeyPairClient keyPairClient = EC2Client.class.cast( KeyPairClient keyPairClient = EC2Client.class.cast(
context.getProviderSpecificContext().getApi()).getKeyPairServices(); context.getProviderSpecificContext().getApi()).getKeyPairServices();
InstanceClient instanceClient = EC2Client.class.cast( InstanceClient instanceClient = EC2Client.class.cast(
context.getProviderSpecificContext().getApi()).getInstanceServices(); context.getProviderSpecificContext().getApi())
.getInstanceServices();
String tag = this.tag + "optionsandlogin"; String tag = this.tag + "optionsandlogin";
@ -82,15 +84,17 @@ public class EC2ComputeServiceLiveTest extends BaseComputeServiceLiveTest {
try { try {
cleanupExtendedStuff(securityGroupClient, keyPairClient, tag); cleanupExtendedStuff(securityGroupClient, keyPairClient, tag);
// create a security group that allows ssh in so that our scripts later will work // create a security group that allows ssh in so that our scripts later
// will work
securityGroupClient.createSecurityGroupInRegion(null, tag, tag); securityGroupClient.createSecurityGroupInRegion(null, tag, tag);
securityGroupClient.authorizeSecurityGroupIngressInRegion(null, tag, IpProtocol.TCP, 22, securityGroupClient.authorizeSecurityGroupIngressInRegion(null, tag,
22, "0.0.0.0/0"); IpProtocol.TCP, 22, 22, "0.0.0.0/0");
// create a keypair to pass in as well // create a keypair to pass in as well
KeyPair result = keyPairClient.createKeyPairInRegion(null, tag); KeyPair result = keyPairClient.createKeyPairInRegion(null, tag);
Set<? extends NodeMetadata> nodes = client.runNodesWithTag(tag, 1, options); Set<? extends NodeMetadata> nodes = client.runNodesWithTag(tag, 1,
options);
NodeMetadata first = Iterables.get(nodes, 0); NodeMetadata first = Iterables.get(nodes, 0);
assert first.getCredentials() != null : first; assert first.getCredentials() != null : first;
assert first.getCredentials().account != null : first; assert first.getCredentials().account != null : first;
@ -102,23 +106,27 @@ public class EC2ComputeServiceLiveTest extends BaseComputeServiceLiveTest {
assertEquals(instance.getKeyName(), tag); assertEquals(instance.getKeyName(), tag);
// make sure we made our dummy group and also let in the user's group // make sure we made our dummy group and also let in the user's group
assertEquals(instance.getGroupIds(), ImmutableSet.<String> of(tag, "jclouds#" + tag)); assertEquals(instance.getGroupIds(), ImmutableSet.<String> of(tag,
"jclouds#" + tag));
// make sure our dummy group has no rules // make sure our dummy group has no rules
SecurityGroup group = Iterables.getOnlyElement(securityGroupClient SecurityGroup group = Iterables.getOnlyElement(securityGroupClient
.describeSecurityGroupsInRegion(null, "jclouds#" + tag)); .describeSecurityGroupsInRegion(null, "jclouds#" + tag));
assert group.getIpPermissions().size() == 0 : group; assert group.getIpPermissions().size() == 0 : group;
// try to run a script with the original keyPair // try to run a script with the original keyPair
runScriptWithCreds(tag, first.getImage().getOsFamily(), new Credentials(first runScriptWithCreds(tag, first.getImage().getOsFamily(),
.getCredentials().account, result.getKeyMaterial())); new Credentials(first.getCredentials().account, result
.getKeyMaterial()));
} finally { } finally {
client.destroyNodesMatching(NodePredicates.withTag(tag)); client.destroyNodesMatching(NodePredicates.withTag(tag));
if (startedId != null) { if (startedId != null) {
// ensure we didn't delete these resources! // ensure we didn't delete these resources!
assertEquals(keyPairClient.describeKeyPairsInRegion(null, tag).size(), 1); assertEquals(keyPairClient.describeKeyPairsInRegion(null, tag)
assertEquals(securityGroupClient.describeSecurityGroupsInRegion(null, tag).size(), 1); .size(), 1);
assertEquals(securityGroupClient.describeSecurityGroupsInRegion(
null, tag).size(), 1);
} }
cleanupExtendedStuff(securityGroupClient, keyPairClient, tag); cleanupExtendedStuff(securityGroupClient, keyPairClient, tag);
} }
@ -127,13 +135,15 @@ public class EC2ComputeServiceLiveTest extends BaseComputeServiceLiveTest {
@Test(enabled = true, dependsOnMethods = "testCorrectAuthException") @Test(enabled = true, dependsOnMethods = "testCorrectAuthException")
public void testExtendedOptionsNoKeyPair() throws Exception { public void testExtendedOptionsNoKeyPair() throws Exception {
SecurityGroupClient securityGroupClient = EC2Client.class.cast( SecurityGroupClient securityGroupClient = EC2Client.class.cast(
context.getProviderSpecificContext().getApi()).getSecurityGroupServices(); context.getProviderSpecificContext().getApi())
.getSecurityGroupServices();
KeyPairClient keyPairClient = EC2Client.class.cast( KeyPairClient keyPairClient = EC2Client.class.cast(
context.getProviderSpecificContext().getApi()).getKeyPairServices(); context.getProviderSpecificContext().getApi()).getKeyPairServices();
InstanceClient instanceClient = EC2Client.class.cast( InstanceClient instanceClient = EC2Client.class.cast(
context.getProviderSpecificContext().getApi()).getInstanceServices(); context.getProviderSpecificContext().getApi())
.getInstanceServices();
String tag = this.tag + "optionsnokey"; String tag = this.tag + "optionsnokey";
@ -149,7 +159,8 @@ public class EC2ComputeServiceLiveTest extends BaseComputeServiceLiveTest {
// create the security group // create the security group
securityGroupClient.createSecurityGroupInRegion(null, tag, tag); securityGroupClient.createSecurityGroupInRegion(null, tag, tag);
Set<? extends NodeMetadata> nodes = client.runNodesWithTag(tag, 1, options); Set<? extends NodeMetadata> nodes = client.runNodesWithTag(tag, 1,
options);
Credentials creds = nodes.iterator().next().getCredentials(); Credentials creds = nodes.iterator().next().getCredentials();
assert creds == null; assert creds == null;
@ -160,31 +171,34 @@ public class EC2ComputeServiceLiveTest extends BaseComputeServiceLiveTest {
assertEquals(instance.getKeyName(), null); assertEquals(instance.getKeyName(), null);
// make sure we made our dummy group and also let in the user's group // make sure we made our dummy group and also let in the user's group
assertEquals(instance.getGroupIds(), ImmutableSet.<String> of(tag, "jclouds#" + tag)); assertEquals(instance.getGroupIds(), ImmutableSet.<String> of(tag,
"jclouds#" + tag));
// make sure our dummy group has no rules // make sure our dummy group has no rules
SecurityGroup group = Iterables.getOnlyElement(securityGroupClient SecurityGroup group = Iterables.getOnlyElement(securityGroupClient
.describeSecurityGroupsInRegion(null, "jclouds#" + tag)); .describeSecurityGroupsInRegion(null, "jclouds#" + tag));
assert group.getIpPermissions().size() == 0 : group; assert group.getIpPermissions().size() == 0 : group;
} finally { } finally {
client.destroyNodesMatching(NodePredicates.withTag(tag)); client.destroyNodesMatching(NodePredicates.withTag(tag));
if (startedId != null) { if (startedId != null) {
// ensure we didn't delete these resources! // ensure we didn't delete these resources!
assertEquals(securityGroupClient.describeSecurityGroupsInRegion(null, tag).size(), 1); assertEquals(securityGroupClient.describeSecurityGroupsInRegion(
null, tag).size(), 1);
} }
cleanupExtendedStuff(securityGroupClient, keyPairClient, tag); cleanupExtendedStuff(securityGroupClient, keyPairClient, tag);
} }
} }
private RunningInstance getInstance(InstanceClient instanceClient, String id) { private RunningInstance getInstance(InstanceClient instanceClient, String id) {
RunningInstance instance = Iterables.getOnlyElement(Iterables.getOnlyElement(instanceClient RunningInstance instance = Iterables
.describeInstancesInRegion(null, id))); .getOnlyElement(Iterables.getOnlyElement(instanceClient
.describeInstancesInRegion(null, id)));
return instance; return instance;
} }
private void cleanupExtendedStuff(SecurityGroupClient securityGroupClient, private void cleanupExtendedStuff(SecurityGroupClient securityGroupClient,
KeyPairClient keyPairClient, String tag) { KeyPairClient keyPairClient, String tag) {
try { try {
securityGroupClient.deleteSecurityGroupInRegion(null, tag); securityGroupClient.deleteSecurityGroupInRegion(null, tag);
} catch (Exception e) { } catch (Exception e) {

View File

@ -52,7 +52,7 @@ public class ImageParserTest extends BaseEC2HandlerTest {
InputStream is = getClass().getResourceAsStream("/ec2/alestic_canonical.xml"); InputStream is = getClass().getResourceAsStream("/ec2/alestic_canonical.xml");
Set<Image> result = parseImages(is); Set<Image> result = parseImages(is);
assertEquals(result.size(), 6); assertEquals(result.size(), 7);
ImageParser parser = new ImageParser( ImageParser parser = new ImageParser(
new EC2PopulateDefaultLoginCredentialsForImageStrategy(), ImmutableSet new EC2PopulateDefaultLoginCredentialsForImageStrategy(), ImmutableSet
@ -87,6 +87,9 @@ public class ImageParserTest extends BaseEC2HandlerTest {
"063491364108")); "063491364108"));
assertEquals(alesticKarmic.getVersion(), "20090623"); assertEquals(alesticKarmic.getVersion(), "20090623");
org.jclouds.compute.domain.Image ubuntuKarmic = parser.apply(Iterables.get(result, 2)); org.jclouds.compute.domain.Image ubuntuKarmic = parser.apply(Iterables.get(result, 2));
assertEquals(ubuntuKarmic.getArchitecture(), org.jclouds.compute.domain.Architecture.X86_32); assertEquals(ubuntuKarmic.getArchitecture(), org.jclouds.compute.domain.Architecture.X86_32);
@ -120,8 +123,24 @@ public class ImageParserTest extends BaseEC2HandlerTest {
"063491364108")); "063491364108"));
assertEquals(alesticHardy.getVersion(), "20080905"); assertEquals(alesticHardy.getVersion(), "20080905");
org.jclouds.compute.domain.Image ubuntuLucid = parser.apply(Iterables.get(result, 5));
assertEquals(ubuntuLucid.getArchitecture(), org.jclouds.compute.domain.Architecture.X86_32);
assertEquals(ubuntuLucid.getDescription(),
"ubuntu-images-us-west-1/ubuntu-lucid-10.04-i386-server-20100427.1.manifest.xml");
assertEquals(ubuntuLucid.getProviderId(), "ami-c597c680");
assertEquals(ubuntuLucid.getLocation(), defaultLocation);
assertEquals(ubuntuLucid.getName(), "10.04");
assertEquals(ubuntuLucid.getOsDescription(),
"ubuntu-images-us-west-1/ubuntu-lucid-10.04-i386-server-20100427.1.manifest.xml");
assertEquals(ubuntuLucid.getOsFamily(), OsFamily.UBUNTU);
assertEquals(ubuntuLucid.getUserMetadata(), ImmutableMap.<String, String> of("owner",
"099720109477"));
assertEquals(ubuntuLucid.getVersion(), "20100427.1");
// should skip kernel // should skip kernel
assert parser.apply(Iterables.get(result, 5)) == null; assert parser.apply(Iterables.get(result, 6)) == null;
} }
private Location defaultLocation = new LocationImpl(LocationScope.REGION, "us-east-1", private Location defaultLocation = new LocationImpl(LocationScope.REGION, "us-east-1",

View File

@ -60,18 +60,20 @@ public class EC2RunNodesAndAddToSetStrategyTest {
@Test @Test
public void testZoneAsALocation() { public void testZoneAsALocation() {
assertRegionAndZoneForLocation(ZONE_AP_SOUTHEAST_1A, Region.AP_SOUTHEAST_1, assertRegionAndZoneForLocation(ZONE_AP_SOUTHEAST_1A,
AvailabilityZone.AP_SOUTHEAST_1A); Region.AP_SOUTHEAST_1, AvailabilityZone.AP_SOUTHEAST_1A);
} }
@Test @Test
public void testRegionAsALocation() { public void testRegionAsALocation() {
assertRegionAndZoneForLocation(REGION_AP_SOUTHEAST_1, Region.AP_SOUTHEAST_1, null); assertRegionAndZoneForLocation(REGION_AP_SOUTHEAST_1,
Region.AP_SOUTHEAST_1, null);
} }
// // fixtures // // fixtures
public static Iterable<NodeMetadata> containsNodeMetadata(final NodeMetadata in) { public static Iterable<NodeMetadata> containsNodeMetadata(
final NodeMetadata in) {
reportMatcher(new IArgumentMatcher() { reportMatcher(new IArgumentMatcher() {
@Override @Override
@ -90,7 +92,8 @@ public class EC2RunNodesAndAddToSetStrategyTest {
return null; return null;
} }
private void assertRegionAndZoneForLocation(Location location, String region, String zone) { private void assertRegionAndZoneForLocation(Location location,
String region, String zone) {
String imageId = "ami1"; String imageId = "ami1";
String instanceCreatedId = "instance1"; String instanceCreatedId = "instance1";
// setup mocks // setup mocks
@ -99,31 +102,37 @@ public class EC2RunNodesAndAddToSetStrategyTest {
InstanceClient instanceClient = createMock(InstanceClient.class); InstanceClient instanceClient = createMock(InstanceClient.class);
RunInstancesOptions ec2Options = createMock(RunInstancesOptions.class); RunInstancesOptions ec2Options = createMock(RunInstancesOptions.class);
RunningInstance instance = createMock(RunningInstance.class); RunningInstance instance = createMock(RunningInstance.class);
Reservation reservation = new Reservation(region, ImmutableSet.<String> of(), ImmutableSet Reservation reservation = new Reservation(region, ImmutableSet
.<RunningInstance> of(instance), "ownerId", "requesterId", "reservationId"); .<String> of(), ImmutableSet.<RunningInstance> of(instance),
"ownerId", "requesterId", "reservationId");
NodeMetadata nodeMetadata = createMock(NodeMetadata.class); NodeMetadata nodeMetadata = createMock(NodeMetadata.class);
// setup expectations // setup expectations
expect(strategy.client.getInstanceServices()).andReturn(instanceClient).atLeastOnce(); expect(strategy.client.getInstanceServices()).andReturn(instanceClient)
.atLeastOnce();
expect( expect(
strategy.createKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions.execute(region, strategy.createKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions
input.tag, input.template)).andReturn(ec2Options); .execute(region, input.tag, input.template)).andReturn(
expect(input.template.getLocation()).andReturn(input.location).atLeastOnce(); ec2Options);
expect(input.template.getLocation()).andReturn(input.location)
.atLeastOnce();
expect(input.template.getImage()).andReturn(input.image).atLeastOnce(); expect(input.template.getImage()).andReturn(input.image).atLeastOnce();
expect(input.image.getProviderId()).andReturn(imageId).atLeastOnce(); expect(input.image.getProviderId()).andReturn(imageId).atLeastOnce();
expect(instanceClient.runInstancesInRegion(region, zone, imageId, 1, input.count, ec2Options))
.andReturn(reservation);
expect(instance.getId()).andReturn(instanceCreatedId).atLeastOnce();
expect(strategy.instanceStateRunning.apply(instance)).andReturn(true);
expect(instanceClient.describeInstancesInRegion(region, instanceCreatedId)).andReturn(
ImmutableSet.of(reservation));
expect(input.template.getOptions()).andReturn(input.options).atLeastOnce();
expect(strategy.runningInstanceToNodeMetadata.apply(instance)).andReturn(nodeMetadata);
expect( expect(
strategy.utils.runOptionsOnNodesAndAddToGoodSetOrPutExceptionIntoBadMap( instanceClient.runInstancesInRegion(region, zone, imageId, 1,
eq(input.options), containsNodeMetadata(nodeMetadata), eq(input.nodes), input.count, ec2Options)).andReturn(reservation);
eq(input.badNodes))).andReturn(null); expect(instance.getId()).andReturn(instanceCreatedId).atLeastOnce();
expect(strategy.instancePresent.apply(instance)).andReturn(true);
expect(input.template.getOptions()).andReturn(input.options)
.atLeastOnce();
expect(strategy.runningInstanceToNodeMetadata.apply(instance)).andReturn(
nodeMetadata);
expect(
strategy.utils
.runOptionsOnNodesAndAddToGoodSetOrPutExceptionIntoBadMap(
eq(input.options), containsNodeMetadata(nodeMetadata),
eq(input.nodes), eq(input.badNodes))).andReturn(null);
// replay mocks // replay mocks
replay(instanceClient); replay(instanceClient);
@ -134,7 +143,8 @@ public class EC2RunNodesAndAddToSetStrategyTest {
replayStrategy(strategy); replayStrategy(strategy);
// run // run
strategy.execute(input.tag, input.count, input.template, input.nodes, input.badNodes); strategy.execute(input.tag, input.count, input.template, input.nodes,
input.badNodes);
// verify mocks // verify mocks
verify(instanceClient); verify(instanceClient);
@ -145,12 +155,12 @@ public class EC2RunNodesAndAddToSetStrategyTest {
verifyStrategy(strategy); verifyStrategy(strategy);
} }
private static final Location REGION_AP_SOUTHEAST_1 = new LocationImpl(LocationScope.REGION, private static final Location REGION_AP_SOUTHEAST_1 = new LocationImpl(
Region.AP_SOUTHEAST_1, Region.AP_SOUTHEAST_1, new LocationImpl(LocationScope.PROVIDER, LocationScope.REGION, Region.AP_SOUTHEAST_1, Region.AP_SOUTHEAST_1,
"ec2", "ec2", null)); new LocationImpl(LocationScope.PROVIDER, "ec2", "ec2", null));
private static final Location ZONE_AP_SOUTHEAST_1A = new LocationImpl(LocationScope.ZONE, private static final Location ZONE_AP_SOUTHEAST_1A = new LocationImpl(
AvailabilityZone.AP_SOUTHEAST_1A, AvailabilityZone.AP_SOUTHEAST_1A, LocationScope.ZONE, AvailabilityZone.AP_SOUTHEAST_1A,
REGION_AP_SOUTHEAST_1); AvailabilityZone.AP_SOUTHEAST_1A, REGION_AP_SOUTHEAST_1);
// ///////////////////////////////////////////////////////////////////// // /////////////////////////////////////////////////////////////////////
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
@ -191,7 +201,7 @@ public class EC2RunNodesAndAddToSetStrategyTest {
private void verifyStrategy(EC2RunNodesAndAddToSetStrategy strategy) { private void verifyStrategy(EC2RunNodesAndAddToSetStrategy strategy) {
verify(strategy.createKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions); verify(strategy.createKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions);
verify(strategy.client); verify(strategy.client);
verify(strategy.instanceStateRunning); verify(strategy.instancePresent);
verify(strategy.runningInstanceToNodeMetadata); verify(strategy.runningInstanceToNodeMetadata);
verify(strategy.utils); verify(strategy.utils);
} }
@ -204,14 +214,14 @@ public class EC2RunNodesAndAddToSetStrategyTest {
RunningInstanceToNodeMetadata runningInstanceToNodeMetadata = createMock(RunningInstanceToNodeMetadata.class); RunningInstanceToNodeMetadata runningInstanceToNodeMetadata = createMock(RunningInstanceToNodeMetadata.class);
ComputeUtils utils = createMock(ComputeUtils.class); ComputeUtils utils = createMock(ComputeUtils.class);
return new EC2RunNodesAndAddToSetStrategy(client, return new EC2RunNodesAndAddToSetStrategy(client,
createKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions, instanceStateRunning, createKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions,
runningInstanceToNodeMetadata, utils); instanceStateRunning, runningInstanceToNodeMetadata, utils);
} }
private void replayStrategy(EC2RunNodesAndAddToSetStrategy strategy) { private void replayStrategy(EC2RunNodesAndAddToSetStrategy strategy) {
replay(strategy.createKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions); replay(strategy.createKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions);
replay(strategy.client); replay(strategy.client);
replay(strategy.instanceStateRunning); replay(strategy.instancePresent);
replay(strategy.runningInstanceToNodeMetadata); replay(strategy.runningInstanceToNodeMetadata);
replay(strategy.utils); replay(strategy.utils);
} }

View File

@ -67,6 +67,19 @@
<rootDeviceType>instance-store</rootDeviceType> <rootDeviceType>instance-store</rootDeviceType>
<blockDeviceMapping /> <blockDeviceMapping />
</item> </item>
<item>
<imageId>ami-c597c680</imageId>
<imageLocation>ubuntu-images-us-west-1/ubuntu-lucid-10.04-i386-server-20100427.1.manifest.xml</imageLocation>
<imageState>available</imageState>
<imageOwnerId>099720109477</imageOwnerId>
<isPublic>true</isPublic>
<architecture>i386</architecture>
<imageType>machine</imageType>
<kernelId>aki-3197c674</kernelId>
<name>ubuntu-images/ubuntu-lucid-10.04-i386-server-20100427.1</name>
<rootDeviceType>instance-store</rootDeviceType>
<blockDeviceMapping/>
</item>
<item> <item>
<imageId>aki-fd15f694</imageId> <imageId>aki-fd15f694</imageId>
<imageLocation>ubuntu-kernels-us/ubuntu-karmic-amd64-linux-image-2.6.31-302-ec2-v-2.6.31-302.7-kernel.img.manifest.xml</imageLocation> <imageLocation>ubuntu-kernels-us/ubuntu-karmic-amd64-linux-image-2.6.31-302-ec2-v-2.6.31-302.7-kernel.img.manifest.xml</imageLocation>

View File

@ -0,0 +1,88 @@
/**
*
* 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.config;
import static com.google.common.base.Predicates.not;
import javax.inject.Named;
import javax.inject.Singleton;
import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.predicates.NodeRunning;
import org.jclouds.compute.predicates.NodeTerminated;
import org.jclouds.compute.predicates.ScriptStatusReturnsZero;
import org.jclouds.compute.predicates.ScriptStatusReturnsZero.CommandUsingClient;
import org.jclouds.compute.reference.ComputeServiceConstants.Timeouts;
import org.jclouds.net.IPSocket;
import org.jclouds.predicates.RetryablePredicate;
import org.jclouds.predicates.SocketOpen;
import com.google.common.base.Predicate;
import com.google.inject.AbstractModule;
import com.google.inject.Provides;
/**
*
* @author Adrian Cole
*
*/
public class ComputeServiceTimeoutsModule extends AbstractModule {
@Provides
@Singleton
@Named("NODE_RUNNING")
protected Predicate<NodeMetadata> nodeRunning(NodeRunning stateRunning,
Timeouts timeouts) {
return timeouts.nodeRunning == 0 ? stateRunning
: new RetryablePredicate<NodeMetadata>(stateRunning,
timeouts.nodeRunning);
}
@Provides
@Singleton
@Named("NODE_TERMINATED")
protected Predicate<NodeMetadata> serverTerminated(
NodeTerminated stateTerminated, Timeouts timeouts) {
return timeouts.nodeTerminated == 0 ? stateTerminated
: new RetryablePredicate<NodeMetadata>(stateTerminated,
timeouts.nodeTerminated);
}
@Provides
@Singleton
@Named("SCRIPT_COMPLETE")
protected Predicate<CommandUsingClient> runScriptRunning(
ScriptStatusReturnsZero stateRunning, Timeouts timeouts) {
return timeouts.scriptComplete == 0 ? not(stateRunning)
: new RetryablePredicate<CommandUsingClient>(not(stateRunning),
timeouts.scriptComplete);
}
@Provides
@Singleton
protected Predicate<IPSocket> socketTester(SocketOpen open, Timeouts timeouts) {
return timeouts.portOpen == 0 ? open : new RetryablePredicate<IPSocket>(
open, timeouts.portOpen);
}
@Override
protected void configure() {
}
}

View File

@ -32,8 +32,8 @@ import org.jclouds.domain.Credentials;
public interface NodeMetadata extends ComputeMetadata { public interface NodeMetadata extends ComputeMetadata {
/** /**
* Tag used for all resources that belong to the same logical group. run, destroy commands are * Tag used for all resources that belong to the same logical group. run,
* scoped to tag. * destroy commands are scoped to tag.
* *
* @return tag for this node, or null, if not a part of a group * @return tag for this node, or null, if not a part of a group
* *
@ -62,8 +62,8 @@ public interface NodeMetadata extends ComputeMetadata {
Set<String> getPrivateAddresses(); Set<String> getPrivateAddresses();
/** /**
* If possible, these are returned upon all detail requests. However, it is often the case that * If possible, these are returned upon all detail requests. However, it is
* credentials are only available at "run" time. * often the case that credentials are only available at "run" time.
*/ */
Credentials getCredentials(); Credentials getCredentials();

View File

@ -41,7 +41,8 @@ import com.google.common.collect.Sets;
* @author Adrian Cole * @author Adrian Cole
* @author Ivan Meredith * @author Ivan Meredith
*/ */
public class NodeMetadataImpl extends ComputeMetadataImpl implements NodeMetadata { public class NodeMetadataImpl extends ComputeMetadataImpl implements
NodeMetadata {
/** The serialVersionUID */ /** The serialVersionUID */
private static final long serialVersionUID = 7924307572338157887L; private static final long serialVersionUID = 7924307572338157887L;
@ -53,17 +54,19 @@ public class NodeMetadataImpl extends ComputeMetadataImpl implements NodeMetadat
private final String tag; private final String tag;
private final Image image; private final Image image;
public NodeMetadataImpl(String providerId, String name, String id, Location location, URI uri, public NodeMetadataImpl(String providerId, String name, String id,
Map<String, String> userMetadata, @Nullable String tag, @Nullable Image image, Location location, URI uri, Map<String, String> userMetadata,
NodeState state, Iterable<String> publicAddresses, @Nullable String tag, @Nullable Image image, NodeState state,
Iterable<String> privateAddresses, Map<String, String> extra, Iterable<String> publicAddresses, Iterable<String> privateAddresses,
@Nullable Credentials credentials) { Map<String, String> extra, @Nullable Credentials credentials) {
super(ComputeType.NODE, providerId, name, id, location, uri, userMetadata); super(ComputeType.NODE, providerId, name, id, location, uri, userMetadata);
this.tag = tag; this.tag = tag;
this.image = image; this.image = image;
this.state = checkNotNull(state, "state"); this.state = checkNotNull(state, "state");
Iterables.addAll(this.publicAddresses, checkNotNull(publicAddresses, "publicAddresses")); Iterables.addAll(this.publicAddresses, checkNotNull(publicAddresses,
Iterables.addAll(this.privateAddresses, checkNotNull(privateAddresses, "privateAddresses")); "publicAddresses"));
Iterables.addAll(this.privateAddresses, checkNotNull(privateAddresses,
"privateAddresses"));
this.extra.putAll(checkNotNull(extra, "extra")); this.extra.putAll(checkNotNull(extra, "extra"));
this.credentials = credentials; this.credentials = credentials;
} }
@ -127,19 +130,22 @@ public class NodeMetadataImpl extends ComputeMetadataImpl implements NodeMetadat
@Override @Override
public String toString() { public String toString() {
return "[id=" + getId() + ", providerId=" + getProviderId() + ", tag=" + getTag() + ", name=" return "[id=" + getId() + ", providerId=" + getProviderId() + ", tag="
+ getName() + ", location=" + getLocation() + ", uri=" + getUri() + ", image=" + getTag() + ", name=" + getName() + ", location=" + getLocation()
+ getImage() + ", userMetadata=" + getUserMetadata() + ", state=" + getState() + ", uri=" + getUri() + ", image=" + getImage() + ", userMetadata="
+ ", privateAddresses=" + privateAddresses + ", publicAddresses=" + publicAddresses + getUserMetadata() + ", state=" + getState()
+ ", extra=" + getExtra() + "]"; + ", privateAddresses=" + privateAddresses + ", publicAddresses="
+ publicAddresses + ", extra=" + getExtra() + "]";
} }
@Override @Override
public int hashCode() { public int hashCode() {
final int prime = 31; final int prime = 31;
int result = super.hashCode(); int result = super.hashCode();
result = prime * result + ((privateAddresses == null) ? 0 : privateAddresses.hashCode()); result = prime * result
result = prime * result + ((publicAddresses == null) ? 0 : publicAddresses.hashCode()); + ((privateAddresses == null) ? 0 : privateAddresses.hashCode());
result = prime * result
+ ((publicAddresses == null) ? 0 : publicAddresses.hashCode());
result = prime * result + ((tag == null) ? 0 : tag.hashCode()); result = prime * result + ((tag == null) ? 0 : tag.hashCode());
result = prime * result + ((image == null) ? 0 : image.hashCode()); result = prime * result + ((image == null) ? 0 : image.hashCode());
return result; return result;

View File

@ -97,34 +97,47 @@ public class BaseComputeService implements ComputeService {
protected final DestroyNodeStrategy destroyNodeStrategy; protected final DestroyNodeStrategy destroyNodeStrategy;
protected final Provider<TemplateBuilder> templateBuilderProvider; protected final Provider<TemplateBuilder> templateBuilderProvider;
protected final Provider<TemplateOptions> templateOptionsProvider; protected final Provider<TemplateOptions> templateOptionsProvider;
protected final Predicate<NodeMetadata> nodeRunning;
protected final Predicate<NodeMetadata> nodeTerminated;
protected final ComputeUtils utils; protected final ComputeUtils utils;
protected final ExecutorService executor; protected final ExecutorService executor;
@Inject @Inject
protected BaseComputeService(ComputeServiceContext context, protected BaseComputeService(ComputeServiceContext context,
Provider<Set<? extends Image>> images, Provider<Set<? extends Size>> sizes, Provider<Set<? extends Image>> images,
Provider<Set<? extends Location>> locations, ListNodesStrategy listNodesStrategy, Provider<Set<? extends Size>> sizes,
GetNodeMetadataStrategy getNodeMetadataStrategy, Provider<Set<? extends Location>> locations,
RunNodesAndAddToSetStrategy runNodesAndAddToSetStrategy, ListNodesStrategy listNodesStrategy,
RebootNodeStrategy rebootNodeStrategy, DestroyNodeStrategy destroyNodeStrategy, GetNodeMetadataStrategy getNodeMetadataStrategy,
Provider<TemplateBuilder> templateBuilderProvider, RunNodesAndAddToSetStrategy runNodesAndAddToSetStrategy,
Provider<TemplateOptions> templateOptionsProvider, ComputeUtils utils, RebootNodeStrategy rebootNodeStrategy,
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService executor) { DestroyNodeStrategy destroyNodeStrategy,
Provider<TemplateBuilder> templateBuilderProvider,
Provider<TemplateOptions> templateOptionsProvider,
@Named("NODE_RUNNING") Predicate<NodeMetadata> nodeRunning,
@Named("NODE_TERMINATED") Predicate<NodeMetadata> nodeTerminated,
ComputeUtils utils,
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService executor) {
this.context = checkNotNull(context, "context"); this.context = checkNotNull(context, "context");
this.images = checkNotNull(images, "images"); this.images = checkNotNull(images, "images");
this.sizes = checkNotNull(sizes, "sizes"); this.sizes = checkNotNull(sizes, "sizes");
this.locations = checkNotNull(locations, "locations"); this.locations = checkNotNull(locations, "locations");
this.listNodesStrategy = checkNotNull(listNodesStrategy, "listNodesStrategy"); this.listNodesStrategy = checkNotNull(listNodesStrategy,
"listNodesStrategy");
this.getNodeMetadataStrategy = checkNotNull(getNodeMetadataStrategy, this.getNodeMetadataStrategy = checkNotNull(getNodeMetadataStrategy,
"getNodeMetadataStrategy"); "getNodeMetadataStrategy");
this.runNodesAndAddToSetStrategy = checkNotNull(runNodesAndAddToSetStrategy, this.runNodesAndAddToSetStrategy = checkNotNull(
"runNodesAndAddToSetStrategy"); runNodesAndAddToSetStrategy, "runNodesAndAddToSetStrategy");
this.rebootNodeStrategy = checkNotNull(rebootNodeStrategy, "rebootNodeStrategy"); this.rebootNodeStrategy = checkNotNull(rebootNodeStrategy,
this.destroyNodeStrategy = checkNotNull(destroyNodeStrategy, "destroyNodeStrategy"); "rebootNodeStrategy");
this.destroyNodeStrategy = checkNotNull(destroyNodeStrategy,
"destroyNodeStrategy");
this.templateBuilderProvider = checkNotNull(templateBuilderProvider, this.templateBuilderProvider = checkNotNull(templateBuilderProvider,
"templateBuilderProvider"); "templateBuilderProvider");
this.templateOptionsProvider = checkNotNull(templateOptionsProvider, this.templateOptionsProvider = checkNotNull(templateOptionsProvider,
"templateOptionsProvider"); "templateOptionsProvider");
this.nodeRunning = checkNotNull(nodeRunning, "nodeRunning");
this.nodeTerminated = checkNotNull(nodeTerminated, "nodeTerminated");
this.utils = checkNotNull(utils, "utils"); this.utils = checkNotNull(utils, "utils");
this.executor = checkNotNull(executor, "executor"); this.executor = checkNotNull(executor, "executor");
} }
@ -141,22 +154,25 @@ public class BaseComputeService implements ComputeService {
* {@inheritDoc} * {@inheritDoc}
*/ */
@Override @Override
public Set<? extends NodeMetadata> runNodesWithTag(String tag, int count, Template template) public Set<? extends NodeMetadata> runNodesWithTag(String tag, int count,
throws RunNodesException { Template template) throws RunNodesException {
checkArgument(tag.indexOf('-') == -1, "tag cannot contain hyphens"); checkArgument(tag.indexOf('-') == -1, "tag cannot contain hyphens");
checkNotNull(template.getLocation(), "location"); checkNotNull(template.getLocation(), "location");
logger.debug(">> running %d node%s tag(%s) location(%s) image(%s) size(%s) options(%s)", logger
count, count > 1 ? "s" : "", tag, template.getLocation().getId(), template .debug(
.getImage().getProviderId(), template.getSize().getProviderId(), template ">> running %d node%s tag(%s) location(%s) image(%s) size(%s) options(%s)",
.getOptions()); count, count > 1 ? "s" : "", tag, template.getLocation()
.getId(), template.getImage().getProviderId(), template
.getSize().getProviderId(), template.getOptions());
Set<NodeMetadata> nodes = Sets.newHashSet(); Set<NodeMetadata> nodes = Sets.newHashSet();
Map<NodeMetadata, Exception> badNodes = Maps.newLinkedHashMap(); Map<NodeMetadata, Exception> badNodes = Maps.newLinkedHashMap();
Map<?, ListenableFuture<Void>> responses = runNodesAndAddToSetStrategy.execute(tag, count, Map<?, ListenableFuture<Void>> responses = runNodesAndAddToSetStrategy
template, nodes, badNodes); .execute(tag, count, template, nodes, badNodes);
Map<?, Exception> executionExceptions = awaitCompletion(responses, executor, null, logger, Map<?, Exception> executionExceptions = awaitCompletion(responses,
"starting nodes"); executor, null, logger, "starting nodes");
if (executionExceptions.size() > 0 || badNodes.size() > 0) { if (executionExceptions.size() > 0 || badNodes.size() > 0) {
throw new RunNodesException(tag, count, template, nodes, executionExceptions, badNodes); throw new RunNodesException(tag, count, template, nodes,
executionExceptions, badNodes);
} }
return nodes; return nodes;
} }
@ -166,8 +182,9 @@ public class BaseComputeService implements ComputeService {
*/ */
@Override @Override
public Set<? extends NodeMetadata> runNodesWithTag(String tag, int count, public Set<? extends NodeMetadata> runNodesWithTag(String tag, int count,
TemplateOptions templateOptions) throws RunNodesException { TemplateOptions templateOptions) throws RunNodesException {
return runNodesWithTag(tag, count, templateBuilder().any().options(templateOptions).build()); return runNodesWithTag(tag, count, templateBuilder().any().options(
templateOptions).build());
} }
/** /**
@ -175,7 +192,7 @@ public class BaseComputeService implements ComputeService {
*/ */
@Override @Override
public Set<? extends NodeMetadata> runNodesWithTag(String tag, int count) public Set<? extends NodeMetadata> runNodesWithTag(String tag, int count)
throws RunNodesException { throws RunNodesException {
return runNodesWithTag(tag, count, templateOptions()); return runNodesWithTag(tag, count, templateOptions());
} }
@ -186,7 +203,8 @@ public class BaseComputeService implements ComputeService {
public void destroyNode(String id) { public void destroyNode(String id) {
checkNotNull(id, "id"); checkNotNull(id, "id");
logger.debug(">> destroying node(%s)", id); logger.debug(">> destroying node(%s)", id);
boolean successful = destroyNodeStrategy.execute(id); NodeMetadata node = destroyNodeStrategy.execute(id);
boolean successful = node == null ? true : nodeTerminated.apply(node);
logger.debug("<< destroyed node(%s) success(%s)", id, successful); logger.debug("<< destroyed node(%s) success(%s)", id, successful);
} }
@ -194,19 +212,21 @@ public class BaseComputeService implements ComputeService {
* {@inheritDoc} * {@inheritDoc}
*/ */
@Override @Override
public Set<? extends NodeMetadata> destroyNodesMatching(Predicate<NodeMetadata> filter) { public Set<? extends NodeMetadata> destroyNodesMatching(
Predicate<NodeMetadata> filter) {
logger.debug(">> destroying nodes matching(%s)", filter); logger.debug(">> destroying nodes matching(%s)", filter);
Map<NodeMetadata, ListenableFuture<Void>> responses = Maps.newHashMap(); Map<NodeMetadata, ListenableFuture<Void>> responses = Maps.newHashMap();
final Set<NodeMetadata> destroyedNodes = Sets.newLinkedHashSet(); final Set<NodeMetadata> destroyedNodes = Sets.newLinkedHashSet();
for (final NodeMetadata node : nodesMatchingFilterAndNotTerminated(filter)) { for (final NodeMetadata node : nodesMatchingFilterAndNotTerminated(filter)) {
responses.put(node, makeListenable(executor.submit(new Callable<Void>() { responses.put(node, makeListenable(executor
@Override .submit(new Callable<Void>() {
public Void call() throws Exception { @Override
destroyNode(node.getId()); public Void call() throws Exception {
destroyedNodes.add(node); destroyNode(node.getId());
return null; destroyedNodes.add(node);
} return null;
}), executor)); }
}), executor));
} }
awaitCompletion(responses, executor, null, logger, "destroying nodes"); awaitCompletion(responses, executor, null, logger, "destroying nodes");
logger.debug("<< destroyed"); logger.debug("<< destroyed");
@ -214,9 +234,9 @@ public class BaseComputeService implements ComputeService {
} }
private Iterable<? extends NodeMetadata> nodesMatchingFilterAndNotTerminated( private Iterable<? extends NodeMetadata> nodesMatchingFilterAndNotTerminated(
Predicate<NodeMetadata> filter) { Predicate<NodeMetadata> filter) {
return Iterables.filter(detailsOnAllNodes(), Predicates.and(filter, Predicates return Iterables.filter(detailsOnAllNodes(), Predicates.and(filter,
.not(NodePredicates.TERMINATED))); Predicates.not(NodePredicates.TERMINATED)));
} }
/** /**
@ -225,7 +245,8 @@ public class BaseComputeService implements ComputeService {
@Override @Override
public Set<? extends ComputeMetadata> listNodes() { public Set<? extends ComputeMetadata> listNodes() {
logger.debug(">> listing nodes"); logger.debug(">> listing nodes");
Set<? extends ComputeMetadata> set = Sets.newLinkedHashSet(listNodesStrategy.list()); Set<? extends ComputeMetadata> set = Sets
.newLinkedHashSet(listNodesStrategy.list());
logger.debug("<< list(%d)", set.size()); logger.debug("<< list(%d)", set.size());
return set; return set;
} }
@ -234,11 +255,12 @@ public class BaseComputeService implements ComputeService {
* {@inheritDoc} * {@inheritDoc}
*/ */
@Override @Override
public Set<? extends NodeMetadata> listNodesDetailsMatching(Predicate<ComputeMetadata> filter) { public Set<? extends NodeMetadata> listNodesDetailsMatching(
Predicate<ComputeMetadata> filter) {
checkNotNull(filter, "filter"); checkNotNull(filter, "filter");
logger.debug(">> listing node details matching(%s)", filter); logger.debug(">> listing node details matching(%s)", filter);
Set<? extends NodeMetadata> set = Sets.newLinkedHashSet(listNodesStrategy Set<? extends NodeMetadata> set = Sets.newLinkedHashSet(listNodesStrategy
.listDetailsOnNodesMatching(filter)); .listDetailsOnNodesMatching(filter));
logger.debug("<< list(%d)", set.size()); logger.debug("<< list(%d)", set.size());
return set; return set;
} }
@ -291,7 +313,8 @@ public class BaseComputeService implements ComputeService {
public void rebootNode(String id) { public void rebootNode(String id) {
checkNotNull(id, "id"); checkNotNull(id, "id");
logger.debug(">> rebooting node(%s)", id); logger.debug(">> rebooting node(%s)", id);
boolean successful = rebootNodeStrategy.execute(id); NodeMetadata node = rebootNodeStrategy.execute(id);
boolean successful = nodeRunning.apply(node);
logger.debug("<< rebooted node(%s) success(%s)", id, successful); logger.debug("<< rebooted node(%s) success(%s)", id, successful);
} }
@ -304,13 +327,14 @@ public class BaseComputeService implements ComputeService {
Map<NodeMetadata, ListenableFuture<Void>> responses = Maps.newHashMap(); Map<NodeMetadata, ListenableFuture<Void>> responses = Maps.newHashMap();
for (final NodeMetadata node : nodesMatchingFilterAndNotTerminated(filter)) { for (final NodeMetadata node : nodesMatchingFilterAndNotTerminated(filter)) {
responses.put(node, makeListenable(executor.submit(new Callable<Void>() { responses.put(node, makeListenable(executor
@Override .submit(new Callable<Void>() {
public Void call() throws Exception { @Override
rebootNode(node.getId()); public Void call() throws Exception {
return null; rebootNode(node.getId());
} return null;
}), executor)); }
}), executor));
} }
awaitCompletion(responses, executor, null, logger, "rebooting nodes"); awaitCompletion(responses, executor, null, logger, "rebooting nodes");
logger.debug("<< rebooted"); logger.debug("<< rebooted");
@ -321,7 +345,8 @@ public class BaseComputeService implements ComputeService {
*/ */
@Override @Override
public Map<? extends NodeMetadata, ExecResponse> runScriptOnNodesMatching( public Map<? extends NodeMetadata, ExecResponse> runScriptOnNodesMatching(
Predicate<NodeMetadata> filter, byte[] runScript) throws RunScriptOnNodesException { Predicate<NodeMetadata> filter, byte[] runScript)
throws RunScriptOnNodesException {
return runScriptOnNodesMatching(filter, runScript, RunScriptOptions.NONE); return runScriptOnNodesMatching(filter, runScript, RunScriptOptions.NONE);
} }
@ -329,11 +354,13 @@ public class BaseComputeService implements ComputeService {
* {@inheritDoc} * {@inheritDoc}
*/ */
@Override @Override
public Map<NodeMetadata, ExecResponse> runScriptOnNodesMatching(Predicate<NodeMetadata> filter, public Map<NodeMetadata, ExecResponse> runScriptOnNodesMatching(
final byte[] runScript, @Nullable final RunScriptOptions options) Predicate<NodeMetadata> filter, final byte[] runScript,
throws RunScriptOnNodesException { @Nullable final RunScriptOptions options)
Iterable<? extends NodeMetadata> nodes = verifyParametersAndListNodes(filter, runScript, throws RunScriptOnNodesException {
(options != null) ? options : RunScriptOptions.NONE); Iterable<? extends NodeMetadata> nodes = verifyParametersAndListNodes(
filter, runScript, (options != null) ? options
: RunScriptOptions.NONE);
final Map<NodeMetadata, ExecResponse> execs = Maps.newHashMap(); final Map<NodeMetadata, ExecResponse> execs = Maps.newHashMap();
@ -343,75 +370,88 @@ public class BaseComputeService implements ComputeService {
for (final NodeMetadata node : nodes) { for (final NodeMetadata node : nodes) {
responses.put(node, makeListenable(executor.submit(new Callable<Void>() { responses.put(node, makeListenable(executor
@Override .submit(new Callable<Void>() {
public Void call() throws Exception { @Override
try { public Void call() throws Exception {
RunScriptOnNode callable; try {
if (options.isRunAsRoot()) RunScriptOnNode callable;
callable = utils.runScriptOnNode(node, "computeserv", runScript); if (options.isRunAsRoot())
else callable = utils.runScriptOnNode(node,
callable = utils.runScriptOnNodeAsDefaultUser(node, "computeserv", runScript); "computeserv", runScript);
SshClient ssh = utils.createSshClientOncePortIsListeningOnNode(node); else
try { callable = utils.runScriptOnNodeAsDefaultUser(node,
ssh.connect(); "computeserv", runScript);
callable.setConnection(ssh, logger); SshClient ssh = utils
execs.put(node, callable.call()); .createSshClientOncePortIsListeningOnNode(node);
} finally { try {
if (ssh != null) ssh.connect();
ssh.disconnect(); callable.setConnection(ssh, logger);
} execs.put(node, callable.call());
} catch (Exception e) { } finally {
badNodes.put(node, e); if (ssh != null)
ssh.disconnect();
}
} catch (Exception e) {
badNodes.put(node, e);
} }
return null; return null;
} }
}), executor)); }), executor));
} }
Map<?, Exception> exceptions = awaitCompletion(responses, executor, null, logger, Map<?, Exception> exceptions = awaitCompletion(responses, executor, null,
"starting nodes"); logger, "starting nodes");
if (exceptions.size() > 0 || badNodes.size() > 0) { if (exceptions.size() > 0 || badNodes.size() > 0) {
throw new RunScriptOnNodesException(runScript, options, execs, exceptions, badNodes); throw new RunScriptOnNodesException(runScript, options, execs,
exceptions, badNodes);
} }
return execs; return execs;
} }
private Iterable<? extends NodeMetadata> verifyParametersAndListNodes( private Iterable<? extends NodeMetadata> verifyParametersAndListNodes(
Predicate<NodeMetadata> filter, byte[] runScript, final RunScriptOptions options) { Predicate<NodeMetadata> filter, byte[] runScript,
final RunScriptOptions options) {
checkNotNull(filter, "Filter must be provided"); checkNotNull(filter, "Filter must be provided");
checkNotNull(runScript, checkNotNull(
"The script (represented by bytes array - use \"script\".getBytes() must be provided"); runScript,
"The script (represented by bytes array - use \"script\".getBytes() must be provided");
checkNotNull(options, "options"); checkNotNull(options, "options");
Iterable<? extends NodeMetadata> nodes = Iterables.filter(detailsOnAllNodes(), filter); Iterable<? extends NodeMetadata> nodes = Iterables.filter(
detailsOnAllNodes(), filter);
return Iterables.transform(nodes, new Function<NodeMetadata, NodeMetadata>() { return Iterables.transform(nodes,
new Function<NodeMetadata, NodeMetadata>() {
@Override @Override
public NodeMetadata apply(NodeMetadata node) { public NodeMetadata apply(NodeMetadata node) {
checkArgument(node.getPublicAddresses().size() > 0, "no public ip addresses on node: " checkArgument(node.getPublicAddresses().size() > 0,
+ node); "no public ip addresses on node: " + node);
if (options.getOverrideCredentials() != null) { if (options.getOverrideCredentials() != null) {
// override the credentials with provided to this method // override the credentials with provided to this
node = ComputeUtils.installNewCredentials(node, options.getOverrideCredentials()); // method
} else { node = ComputeUtils.installNewCredentials(node, options
// don't override .getOverrideCredentials());
checkNotNull(node.getCredentials(), } else {
"If the default credentials need to be used, they can't be null"); // don't override
checkNotNull(node.getCredentials().account, checkNotNull(node.getCredentials(),
"Account name for ssh authentication must be " "If the default credentials need to be used, they can't be null");
checkNotNull(
node.getCredentials().account,
"Account name for ssh authentication must be "
+ "specified. Try passing RunScriptOptions with new credentials"); + "specified. Try passing RunScriptOptions with new credentials");
checkNotNull(node.getCredentials().key, checkNotNull(
"Key or password for ssh authentication must be " node.getCredentials().key,
"Key or password for ssh authentication must be "
+ "specified. Try passing RunScriptOptions with new credentials"); + "specified. Try passing RunScriptOptions with new credentials");
} }
return node; return node;
} }
}); });
} }
private Iterable<? extends NodeMetadata> detailsOnAllNodes() { private Iterable<? extends NodeMetadata> detailsOnAllNodes() {

View File

@ -24,10 +24,11 @@ import static com.google.common.base.Preconditions.checkNotNull;
import java.util.Arrays; import java.util.Arrays;
/** /**
* Contains options supported in the {@code ComputeService#runNodesWithTag} operation. <h2> * Contains options supported in the {@code ComputeService#runNodesWithTag}
* Usage</h2> The recommended way to instantiate a TemplateOptions object is to statically import * operation. <h2>
* TemplateOptions.* and invoke a static creation method followed by an instance mutator (if * Usage</h2> The recommended way to instantiate a TemplateOptions object is to
* needed): * statically import TemplateOptions.* and invoke a static creation method
* followed by an instance mutator (if needed):
* <p/> * <p/>
* <code> * <code>
* import static org.jclouds.compute.options.TemplateOptions.Builder.*; * import static org.jclouds.compute.options.TemplateOptions.Builder.*;
@ -41,301 +42,350 @@ import java.util.Arrays;
*/ */
public class TemplateOptions { public class TemplateOptions {
public static final TemplateOptions NONE = new ImmutableTemplateOptions(new TemplateOptions()); public static final TemplateOptions NONE = new ImmutableTemplateOptions(
new TemplateOptions());
public static class ImmutableTemplateOptions extends TemplateOptions { public static class ImmutableTemplateOptions extends TemplateOptions {
private final TemplateOptions delegate; private final TemplateOptions delegate;
public ImmutableTemplateOptions(TemplateOptions delegate) { public ImmutableTemplateOptions(TemplateOptions delegate) {
this.delegate = delegate; this.delegate = delegate;
} }
@Override @Override
public String toString() { public String toString() {
return delegate.toString(); return delegate.toString();
} }
@Override @Override
public <T extends TemplateOptions> T as(Class<T> clazz) { public <T extends TemplateOptions> T as(Class<T> clazz) {
return delegate.as(clazz); return delegate.as(clazz);
} }
@Override @Override
public TemplateOptions authorizePublicKey(String publicKey) { public TemplateOptions authorizePublicKey(String publicKey) {
return delegate.authorizePublicKey(publicKey); throw new IllegalArgumentException(
} "authorizePublicKey is immutable");
}
@Override @Override
public TemplateOptions blockOnPort(int port, int seconds) { public TemplateOptions blockUntilRunning(boolean blockUntilRunning) {
throw new IllegalArgumentException("port, seconds are immutable"); throw new IllegalArgumentException("blockUntilRunning is immutable");
} }
@Override @Override
public int[] getInboundPorts() { public TemplateOptions blockOnPort(int port, int seconds) {
return delegate.getInboundPorts(); throw new IllegalArgumentException("port, seconds are immutable");
} }
@Override @Override
public int getPort() { public int[] getInboundPorts() {
return delegate.getPort(); return delegate.getInboundPorts();
} }
@Override @Override
public String getPrivateKey() { public int getPort() {
return delegate.getPrivateKey(); return delegate.getPort();
} }
@Override @Override
public String getPublicKey() { public String getPrivateKey() {
return delegate.getPublicKey(); return delegate.getPrivateKey();
} }
@Override @Override
public byte[] getRunScript() { public String getPublicKey() {
return delegate.getRunScript(); return delegate.getPublicKey();
} }
@Override @Override
public int getSeconds() { public byte[] getRunScript() {
return delegate.getSeconds(); return delegate.getRunScript();
} }
@Override @Override
public TemplateOptions inboundPorts(int... ports) { public int getSeconds() {
throw new IllegalArgumentException("ports is immutable"); return delegate.getSeconds();
} }
@Override @Override
public TemplateOptions installPrivateKey(String privateKey) { public boolean shouldBlockUntilRunning() {
throw new IllegalArgumentException("privateKey is immutable"); return delegate.shouldBlockUntilRunning();
} }
@Override @Override
public boolean isIncludeMetadata() { public TemplateOptions inboundPorts(int... ports) {
return delegate.isIncludeMetadata(); throw new IllegalArgumentException("ports is immutable");
} }
@Override @Override
public TemplateOptions runScript(byte[] script) { public TemplateOptions installPrivateKey(String privateKey) {
throw new IllegalArgumentException("withMetadata is immutable"); throw new IllegalArgumentException("privateKey is immutable");
} }
@Override @Override
public TemplateOptions withMetadata() { public boolean isIncludeMetadata() {
throw new IllegalArgumentException("withMetadata is immutable"); return delegate.isIncludeMetadata();
} }
} @Override
public TemplateOptions runScript(byte[] script) {
throw new IllegalArgumentException("withMetadata is immutable");
}
protected int[] inboundPorts = new int[] { 22 }; @Override
public TemplateOptions withMetadata() {
throw new IllegalArgumentException("withMetadata is immutable");
}
protected byte[] script; }
protected String privateKey; protected int[] inboundPorts = new int[] { 22 };
protected String publicKey; protected byte[] script;
protected int port = -1; protected String privateKey;
protected int seconds = -1; protected String publicKey;
protected boolean includeMetadata; protected int port = -1;
public int getPort() { protected int seconds = -1;
return port;
}
public int getSeconds() { protected boolean includeMetadata;
return seconds;
}
public int[] getInboundPorts() { protected boolean blockUntilRunning = true;
return inboundPorts;
}
public byte[] getRunScript() { public int getPort() {
return script; return port;
} }
public String getPrivateKey() { public int getSeconds() {
return privateKey; return seconds;
} }
public String getPublicKey() { public int[] getInboundPorts() {
return publicKey; return inboundPorts;
} }
public boolean isIncludeMetadata() { public byte[] getRunScript() {
return includeMetadata; return script;
} }
public <T extends TemplateOptions> T as(Class<T> clazz) { public String getPrivateKey() {
return clazz.cast(this); return privateKey;
} }
/** public String getPublicKey() {
* When the node is started, wait until the following port is active return publicKey;
*/ }
public TemplateOptions blockOnPort(int port, int seconds) {
checkArgument(port > 0 && port < 65536, "port must be a positive integer < 65535");
checkArgument(seconds > 0, "seconds must be a positive integer");
this.port = port;
this.seconds = seconds;
return this;
}
/** public boolean isIncludeMetadata() {
* This script will be executed as the root user upon system startup. This script gets a return includeMetadata;
* prologue, so no #!/bin/bash required, path set up, etc }
*/
public TemplateOptions runScript(byte[] script) {
checkArgument(checkNotNull(script, "script").length <= 16 * 1024,
"script cannot be larger than 16kb");
this.script = script;
return this;
}
/** public boolean shouldBlockUntilRunning() {
* replaces the rsa ssh key used at login. return blockUntilRunning;
*/ }
public TemplateOptions installPrivateKey(String privateKey) {
checkArgument(checkNotNull(privateKey, "privateKey").startsWith(
"-----BEGIN RSA PRIVATE KEY-----"),
"key should start with -----BEGIN RSA PRIVATE KEY-----");
this.privateKey = privateKey;
return this;
}
public TemplateOptions dontAuthorizePublicKey() { public <T extends TemplateOptions> T as(Class<T> clazz) {
this.publicKey = null; return clazz.cast(this);
return this; }
}
/** /**
* authorized an rsa ssh key. * When the node is started, wait until the following port is active
*/ */
public TemplateOptions authorizePublicKey(String publicKey) { public TemplateOptions blockOnPort(int port, int seconds) {
checkArgument(checkNotNull(publicKey, "publicKey").startsWith("ssh-rsa"), checkArgument(port > 0 && port < 65536,
"key should start with ssh-rsa"); "port must be a positive integer < 65535");
this.publicKey = publicKey; checkArgument(seconds > 0, "seconds must be a positive integer");
return this; this.port = port;
} this.seconds = seconds;
return this;
}
/** /**
* Opens the set of ports to public access. * This script will be executed as the root user upon system startup. This
*/ * script gets a prologue, so no #!/bin/bash required, path set up, etc
public TemplateOptions inboundPorts(int... ports) { */
for (int port : ports) public TemplateOptions runScript(byte[] script) {
checkArgument(port > 0 && port < 65536, "port must be a positive integer < 65535"); checkArgument(checkNotNull(script, "script").length <= 16 * 1024,
this.inboundPorts = ports; "script cannot be larger than 16kb");
return this; this.script = script;
} return this;
}
public TemplateOptions withMetadata() { /**
this.includeMetadata = true; * replaces the rsa ssh key used at login.
return this; */
} public TemplateOptions installPrivateKey(String privateKey) {
checkArgument(checkNotNull(privateKey, "privateKey").startsWith(
"-----BEGIN RSA PRIVATE KEY-----"),
"key should start with -----BEGIN RSA PRIVATE KEY-----");
this.privateKey = privateKey;
return this;
}
public static class Builder { public TemplateOptions dontAuthorizePublicKey() {
this.publicKey = null;
return this;
}
/** /**
* @see TemplateOptions#inboundPorts * if true, return when node(s) are NODE_RUNNING, if false, return as soon as the
*/ * server is provisioned.
public static TemplateOptions inboundPorts(int... ports) { * <p/>
TemplateOptions options = new TemplateOptions(); * default is true
return options.inboundPorts(ports); */
} public TemplateOptions blockUntilRunning(boolean blockUntilRunning) {
this.blockUntilRunning = blockUntilRunning;
if (!blockUntilRunning)
port = seconds = -1;
return this;
}
/** /**
* @see TemplateOptions#port * authorized an rsa ssh key.
*/ */
public static TemplateOptions blockOnPort(int port, int seconds) { public TemplateOptions authorizePublicKey(String publicKey) {
TemplateOptions options = new TemplateOptions(); checkArgument(checkNotNull(publicKey, "publicKey")
return options.blockOnPort(port, seconds); .startsWith("ssh-rsa"), "key should start with ssh-rsa");
} this.publicKey = publicKey;
return this;
}
/** /**
* @see TemplateOptions#runScript * Opens the set of ports to public access.
*/ */
public static TemplateOptions runScript(byte[] script) { public TemplateOptions inboundPorts(int... ports) {
TemplateOptions options = new TemplateOptions(); for (int port : ports)
return options.runScript(script); checkArgument(port > 0 && port < 65536,
} "port must be a positive integer < 65535");
this.inboundPorts = ports;
return this;
}
/** public TemplateOptions withMetadata() {
* @see TemplateOptions#installPrivateKey this.includeMetadata = true;
*/ return this;
public static TemplateOptions installPrivateKey(String rsaKey) { }
TemplateOptions options = new TemplateOptions();
return options.installPrivateKey(rsaKey);
}
/** public static class Builder {
* @see TemplateOptions#authorizePublicKey
*/
public static TemplateOptions authorizePublicKey(String rsaKey) {
TemplateOptions options = new TemplateOptions();
return options.authorizePublicKey(rsaKey);
}
public static TemplateOptions withDetails() { /**
TemplateOptions options = new TemplateOptions(); * @see TemplateOptions#inboundPorts
return options.withMetadata(); */
} public static TemplateOptions inboundPorts(int... ports) {
TemplateOptions options = new TemplateOptions();
return options.inboundPorts(ports);
}
} /**
* @see TemplateOptions#port
*/
public static TemplateOptions blockOnPort(int port, int seconds) {
TemplateOptions options = new TemplateOptions();
return options.blockOnPort(port, seconds);
}
@Override /**
public String toString() { * @see TemplateOptions#blockUntilRunning
return "TemplateOptions [inboundPorts=" + Arrays.toString(inboundPorts) + ", privateKey=" */
+ (privateKey != null) + ", publicKey=" + (publicKey != null) + ", runScript=" public static TemplateOptions blockUntilRunning(
+ (script != null) + ", port:seconds=" + port + ":" + seconds boolean blockUntilRunning) {
+ ", metadata/details: " + includeMetadata + "]"; TemplateOptions options = new TemplateOptions();
} return options.blockUntilRunning(blockUntilRunning);
}
@Override /**
public int hashCode() { * @see TemplateOptions#runScript
final int prime = 31; */
int result = 1; public static TemplateOptions runScript(byte[] script) {
result = prime * result + Arrays.hashCode(inboundPorts); TemplateOptions options = new TemplateOptions();
result = prime * result + (includeMetadata ? 1231 : 1237); return options.runScript(script);
result = prime * result + port; }
result = prime * result + ((privateKey == null) ? 0 : privateKey.hashCode());
result = prime * result + ((publicKey == null) ? 0 : publicKey.hashCode());
result = prime * result + Arrays.hashCode(script);
result = prime * result + seconds;
return result;
}
@Override /**
public boolean equals(Object obj) { * @see TemplateOptions#installPrivateKey
if (this == obj) */
return true; public static TemplateOptions installPrivateKey(String rsaKey) {
if (obj == null) TemplateOptions options = new TemplateOptions();
return false; return options.installPrivateKey(rsaKey);
if (getClass() != obj.getClass()) }
return false;
TemplateOptions other = (TemplateOptions) obj; /**
if (!Arrays.equals(inboundPorts, other.inboundPorts)) * @see TemplateOptions#authorizePublicKey
return false; */
if (includeMetadata != other.includeMetadata) public static TemplateOptions authorizePublicKey(String rsaKey) {
return false; TemplateOptions options = new TemplateOptions();
if (port != other.port) return options.authorizePublicKey(rsaKey);
return false; }
if (privateKey == null) {
if (other.privateKey != null) public static TemplateOptions withDetails() {
return false; TemplateOptions options = new TemplateOptions();
} else if (!privateKey.equals(other.privateKey)) return options.withMetadata();
return false; }
if (publicKey == null) {
if (other.publicKey != null) }
return false;
} else if (!publicKey.equals(other.publicKey)) @Override
return false; public String toString() {
if (!Arrays.equals(script, other.script)) return "TemplateOptions [inboundPorts=" + Arrays.toString(inboundPorts)
return false; + ", privateKey=" + (privateKey != null) + ", publicKey="
if (seconds != other.seconds) + (publicKey != null) + ", runScript=" + (script != null)
return false; + ", blockUntilRunning=" + blockUntilRunning
return true; + ", port:seconds=" + port + ":" + seconds
} + ", metadata/details: " + includeMetadata + "]";
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + (blockUntilRunning ? 1231 : 1237);
result = prime * result + Arrays.hashCode(inboundPorts);
result = prime * result + (includeMetadata ? 1231 : 1237);
result = prime * result + port;
result = prime * result
+ ((privateKey == null) ? 0 : privateKey.hashCode());
result = prime * result
+ ((publicKey == null) ? 0 : publicKey.hashCode());
result = prime * result + Arrays.hashCode(script);
result = prime * result + seconds;
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
TemplateOptions other = (TemplateOptions) obj;
if (blockUntilRunning != other.blockUntilRunning)
return false;
if (!Arrays.equals(inboundPorts, other.inboundPorts))
return false;
if (includeMetadata != other.includeMetadata)
return false;
if (port != other.port)
return false;
if (privateKey == null) {
if (other.privateKey != null)
return false;
} else if (!privateKey.equals(other.privateKey))
return false;
if (publicKey == null) {
if (other.publicKey != null)
return false;
} else if (!publicKey.equals(other.publicKey))
return false;
if (!Arrays.equals(script, other.script))
return false;
if (seconds != other.seconds)
return false;
return true;
}
} }

View File

@ -96,7 +96,7 @@ public class NodePredicates {
} }
/** /**
* Return nodes with specified tag that are in the RUNNING state. * Return nodes with specified tag that are in the NODE_RUNNING state.
* *
* @param tag * @param tag
* tag to match the items * tag to match the items
@ -121,7 +121,7 @@ public class NodePredicates {
/** /**
* Match nodes with State == RUNNING * Match nodes with State == RUNNING
*/ */
public static final Predicate<NodeMetadata> ACTIVE = new Predicate<NodeMetadata>() { public static final Predicate<NodeMetadata> RUNNING = new Predicate<NodeMetadata>() {
@Override @Override
public boolean apply(NodeMetadata nodeMetadata) { public boolean apply(NodeMetadata nodeMetadata) {
return nodeMetadata.getState() == NodeState.RUNNING; return nodeMetadata.getState() == NodeState.RUNNING;
@ -129,12 +129,12 @@ public class NodePredicates {
@Override @Override
public String toString() { public String toString() {
return "ACTIVE"; return "RUNNING";
} }
}; };
/** /**
* Match nodes with State == TERMINATED * Match nodes with State == NODE_TERMINATED
*/ */
public static final Predicate<NodeMetadata> TERMINATED = new Predicate<NodeMetadata>() { public static final Predicate<NodeMetadata> TERMINATED = new Predicate<NodeMetadata>() {
@Override @Override

View File

@ -0,0 +1,51 @@
package org.jclouds.compute.predicates;
import static com.google.common.base.Preconditions.checkNotNull;
import javax.annotation.Resource;
import javax.inject.Singleton;
import org.jclouds.compute.ComputeService;
import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.domain.NodeState;
import org.jclouds.logging.Logger;
import com.google.common.base.Predicate;
import com.google.inject.Inject;
/**
*
* Tests to see if a node is active.
*
* @author Adrian Cole
*/
@Singleton
public class NodeRunning implements Predicate<NodeMetadata> {
private final ComputeService client;
@Resource
protected Logger logger = Logger.NULL;
@Inject
public NodeRunning(ComputeService client) {
this.client = client;
}
public boolean apply(NodeMetadata node) {
logger.trace("looking for state on node %s", checkNotNull(node, "node"));
node = refresh(node);
if (node == null)
return false;
logger.trace("%s: looking for node state %s: currently: %s",
node.getId(), NodeState.RUNNING, node.getState());
if (node.getState() == NodeState.ERROR)
throw new IllegalStateException("node " + node.getId()
+ " in location " + node.getLocation() + " is in error state");
return node.getState() == NodeState.RUNNING;
}
private NodeMetadata refresh(NodeMetadata node) {
return client.getNodeMetadata(node.getId());
}
}

View File

@ -0,0 +1,48 @@
package org.jclouds.compute.predicates;
import static com.google.common.base.Preconditions.checkNotNull;
import javax.annotation.Resource;
import javax.inject.Singleton;
import org.jclouds.compute.ComputeService;
import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.domain.NodeState;
import org.jclouds.logging.Logger;
import com.google.common.base.Predicate;
import com.google.inject.Inject;
/**
*
* Tests to see if a node is deleted
*
* @author Adrian Cole
*/
@Singleton
public class NodeTerminated implements Predicate<NodeMetadata> {
private final ComputeService client;
@Resource
protected Logger logger = Logger.NULL;
@Inject
public NodeTerminated(ComputeService client) {
this.client = client;
}
public boolean apply(NodeMetadata node) {
logger.trace("looking for state on node %s", checkNotNull(node, "node"));
node = refresh(node);
if (node == null)
return true;
logger.trace("%s: looking for node state %s: currently: %s",
node.getId(), NodeState.TERMINATED, node.getState());
return node.getState() == NodeState.TERMINATED;
}
private NodeMetadata refresh(NodeMetadata node) {
return client.getNodeMetadata(node.getId());
}
}

View File

@ -18,6 +18,11 @@
*/ */
package org.jclouds.compute.reference; package org.jclouds.compute.reference;
import javax.inject.Named;
import javax.inject.Singleton;
import com.google.inject.Inject;
/** /**
* *
* @author Adrian Cole * @author Adrian Cole
@ -26,5 +31,28 @@ public interface ComputeServiceConstants {
public static final String COMPUTE_LOGGER = "jclouds.compute"; public static final String COMPUTE_LOGGER = "jclouds.compute";
public static final String LOCAL_PARTITION_GB_PATTERN = "disk_drive/%s/gb"; public static final String LOCAL_PARTITION_GB_PATTERN = "disk_drive/%s/gb";
public static final String PROPERTY_TIMEOUT_NODE_TERMINATED = "jclouds.compute.timeout.node-terminated";
public static final String PROPERTY_TIMEOUT_NODE_RUNNING = "jclouds.compute.timeout.node-running";
public static final String PROPERTY_TIMEOUT_SCRIPT_COMPLETE = "jclouds.compute.timeout.script-complete";
public static final String PROPERTY_TIMEOUT_PORT_OPEN = "jclouds.compute.timeout.port-open";
@Singleton
static class Timeouts {
@Inject(optional = true)
@Named(PROPERTY_TIMEOUT_NODE_TERMINATED)
public long nodeTerminated = 600 * 1000;
@Inject(optional = true)
@Named(PROPERTY_TIMEOUT_NODE_RUNNING)
public long nodeRunning = 600 * 1000;
@Inject(optional = true)
@Named(PROPERTY_TIMEOUT_SCRIPT_COMPLETE)
public long scriptComplete = 600 * 1000;
@Inject(optional = true)
@Named(PROPERTY_TIMEOUT_PORT_OPEN)
public long portOpen = 130 * 1000;
}
} }

View File

@ -19,15 +19,19 @@
package org.jclouds.compute.strategy; package org.jclouds.compute.strategy;
import org.jclouds.compute.domain.NodeMetadata;
/** /**
* terminates the node and blocks until it is no longer visible or in the state TERMINATED. If this * terminates the node
* is the last node in a tagset, incidental resources are also destroyed.
* *
* @author Adrian Cole * @author Adrian Cole
*/ */
public interface DestroyNodeStrategy { public interface DestroyNodeStrategy {
boolean execute(String id); /**
*
* @return null if the node wasn't found
*/
NodeMetadata execute(String id);
} }

View File

@ -19,14 +19,15 @@
package org.jclouds.compute.strategy; package org.jclouds.compute.strategy;
import org.jclouds.compute.domain.NodeMetadata;
/** /**
* Reboots a node unless it is in the state TERMINATED. * Reboots a node unless it is in the state NODE_TERMINATED.
* *
* @author Adrian Cole * @author Adrian Cole
*/ */
public interface RebootNodeStrategy { public interface RebootNodeStrategy {
boolean execute(String id); NodeMetadata execute(String id);
} }

View File

@ -55,7 +55,8 @@ import com.google.common.util.concurrent.ListenableFuture;
* @author Adrian Cole * @author Adrian Cole
*/ */
@Singleton @Singleton
public class EncodeTagIntoNameRunNodesAndAddToSetStrategy implements RunNodesAndAddToSetStrategy { public class EncodeTagIntoNameRunNodesAndAddToSetStrategy implements
RunNodesAndAddToSetStrategy {
@Resource @Resource
@Named(ComputeServiceConstants.COMPUTE_LOGGER) @Named(ComputeServiceConstants.COMPUTE_LOGGER)
protected Logger logger = Logger.NULL; protected Logger logger = Logger.NULL;
@ -67,9 +68,11 @@ public class EncodeTagIntoNameRunNodesAndAddToSetStrategy implements RunNodesAnd
@Inject @Inject
protected EncodeTagIntoNameRunNodesAndAddToSetStrategy( protected EncodeTagIntoNameRunNodesAndAddToSetStrategy(
AddNodeWithTagStrategy addNodeWithTagStrategy, ListNodesStrategy listNodesStrategy, AddNodeWithTagStrategy addNodeWithTagStrategy,
@Named("NAMING_CONVENTION") String nodeNamingConvention, ComputeUtils utils, ListNodesStrategy listNodesStrategy,
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService executor) { @Named("NAMING_CONVENTION") String nodeNamingConvention,
ComputeUtils utils,
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService executor) {
this.addNodeWithTagStrategy = addNodeWithTagStrategy; this.addNodeWithTagStrategy = addNodeWithTagStrategy;
this.listNodesStrategy = listNodesStrategy; this.listNodesStrategy = listNodesStrategy;
this.nodeNamingConvention = nodeNamingConvention; this.nodeNamingConvention = nodeNamingConvention;
@ -78,51 +81,51 @@ public class EncodeTagIntoNameRunNodesAndAddToSetStrategy implements RunNodesAnd
} }
/** /**
* This implementation gets a list of acceptable node names to encode the tag into, then it * This implementation gets a list of acceptable node names to encode the tag
* simultaneously runs the nodes and applies options to them. * into, then it simultaneously runs the nodes and applies options to them.
*/ */
@Override @Override
public Map<?, ListenableFuture<Void>> execute(final String tag, final int count, public Map<?, ListenableFuture<Void>> execute(final String tag,
final Template template, final Set<NodeMetadata> nodes, final int count, final Template template,
final Map<NodeMetadata, Exception> badNodes) { final Set<NodeMetadata> nodes,
final Map<NodeMetadata, Exception> badNodes) {
Map<String, ListenableFuture<Void>> responses = Maps.newHashMap(); Map<String, ListenableFuture<Void>> responses = Maps.newHashMap();
for (final String name : getNextNames(tag, template, count)) { for (final String name : getNextNames(tag, template, count)) {
responses.put(name, makeListenable(executor.submit(new Callable<Void>() { responses.put(name, makeListenable(executor
@Override .submit(new Callable<Void>() {
public Void call() throws Exception { @Override
NodeMetadata node = null; public Void call() throws Exception {
logger.debug(">> starting node(%s) tag(%s)", name, tag); NodeMetadata node = null;
node = addNodeWithTagStrategy.execute(tag, name, template); logger.debug(">> starting node(%s) tag(%s)", name, tag);
logger.debug("<< running node(%s)", node.getProviderId()); node = addNodeWithTagStrategy.execute(tag, name, template);
try { logger.debug("<< %s node(%s)", node.getState(), node
utils.runOptionsOnNode(node, template.getOptions()); .getId());
logger.debug("<< options applied node(%s)", node.getProviderId()); utils
nodes.add(node); .runOptionsOnNodeAndAddToGoodSetOrPutExceptionIntoBadMap(
} catch (Exception e) { node, badNodes, nodes, template.getOptions())
logger.error(e, "<< error applying options (%s) on node (%s)", template .call();
.getOptions(), node.getProviderId()); return null;
badNodes.put(node, e); }
} }), executor));
return null;
}
}), executor));
} }
return responses; return responses;
} }
/** /**
* Find the next node names that can be used. These will be derived from the tag and the * Find the next node names that can be used. These will be derived from the
* template. We will pre-allocate a specified quantity, and attempt to verify that there is no * tag and the template. We will pre-allocate a specified quantity, and
* name conflict with the current service. * attempt to verify that there is no name conflict with the current service.
* *
* @param tag * @param tag
* @param count * @param count
* @param template * @param template
* @return * @return
*/ */
protected Set<String> getNextNames(final String tag, final Template template, int count) { protected Set<String> getNextNames(final String tag,
final Template template, int count) {
Set<String> names = Sets.newHashSet(); Set<String> names = Sets.newHashSet();
Iterable<? extends ComputeMetadata> currentNodes = listNodesStrategy.list(); Iterable<? extends ComputeMetadata> currentNodes = listNodesStrategy
.list();
int maxTries = 100; int maxTries = 100;
int currentTries = 0; int currentTries = 0;
while (names.size() < count && currentTries++ < maxTries) { while (names.size() < count && currentTries++ < maxTries) {
@ -142,15 +145,16 @@ public class EncodeTagIntoNameRunNodesAndAddToSetStrategy implements RunNodesAnd
} }
/** /**
* Get a name using a random mechanism that still ties all nodes in a tag together. * Get a name using a random mechanism that still ties all nodes in a tag
* together.
* *
* This implementation will pass the tag and a hex formatted random number to the configured * This implementation will pass the tag and a hex formatted random number to
* naming convention. * the configured naming convention.
* *
*/ */
protected String getNextName(final String tag, final Template template) { protected String getNextName(final String tag, final Template template) {
return String.format(nodeNamingConvention, tag, Integer.toHexString(new SecureRandom() return String.format(nodeNamingConvention, tag, Integer
.nextInt(4095))); .toHexString(new SecureRandom().nextInt(4095)));
} }
} }

View File

@ -28,7 +28,7 @@ import java.util.Set;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap; import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.ExecutorService; import java.util.concurrent.ExecutorService;
import java.util.concurrent.TimeUnit; import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicInteger;
import javax.inject.Inject; import javax.inject.Inject;
@ -39,6 +39,7 @@ import javax.inject.Singleton;
import org.jclouds.Constants; import org.jclouds.Constants;
import org.jclouds.compute.ComputeServiceContext; import org.jclouds.compute.ComputeServiceContext;
import org.jclouds.compute.LoadBalancerService; import org.jclouds.compute.LoadBalancerService;
import org.jclouds.compute.config.ComputeServiceTimeoutsModule;
import org.jclouds.compute.domain.Architecture; import org.jclouds.compute.domain.Architecture;
import org.jclouds.compute.domain.ComputeMetadata; import org.jclouds.compute.domain.ComputeMetadata;
import org.jclouds.compute.domain.Image; import org.jclouds.compute.domain.Image;
@ -52,8 +53,6 @@ import org.jclouds.compute.domain.internal.ImageImpl;
import org.jclouds.compute.domain.internal.NodeMetadataImpl; import org.jclouds.compute.domain.internal.NodeMetadataImpl;
import org.jclouds.compute.internal.ComputeServiceContextImpl; import org.jclouds.compute.internal.ComputeServiceContextImpl;
import org.jclouds.compute.predicates.NodePredicates; import org.jclouds.compute.predicates.NodePredicates;
import org.jclouds.compute.predicates.ScriptStatusReturnsZero;
import org.jclouds.compute.predicates.ScriptStatusReturnsZero.CommandUsingClient;
import org.jclouds.compute.strategy.AddNodeWithTagStrategy; import org.jclouds.compute.strategy.AddNodeWithTagStrategy;
import org.jclouds.compute.strategy.DestroyNodeStrategy; import org.jclouds.compute.strategy.DestroyNodeStrategy;
import org.jclouds.compute.strategy.GetNodeMetadataStrategy; import org.jclouds.compute.strategy.GetNodeMetadataStrategy;
@ -66,14 +65,12 @@ import org.jclouds.domain.LocationScope;
import org.jclouds.domain.internal.LocationImpl; import org.jclouds.domain.internal.LocationImpl;
import org.jclouds.lifecycle.Closer; import org.jclouds.lifecycle.Closer;
import org.jclouds.net.IPSocket; import org.jclouds.net.IPSocket;
import org.jclouds.predicates.RetryablePredicate;
import org.jclouds.predicates.SocketOpen; import org.jclouds.predicates.SocketOpen;
import org.jclouds.rest.ResourceNotFoundException; import org.jclouds.rest.ResourceNotFoundException;
import org.jclouds.rest.RestContext; import org.jclouds.rest.RestContext;
import org.jclouds.rest.internal.RestContextImpl; import org.jclouds.rest.internal.RestContextImpl;
import com.google.common.base.Predicate; import com.google.common.base.Predicate;
import com.google.common.base.Predicates;
import com.google.common.base.Throwables; import com.google.common.base.Throwables;
import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet; import com.google.common.collect.ImmutableSet;
@ -140,7 +137,7 @@ public class StubComputeServiceContextModule extends AbstractModule {
@Inject @Inject
public StubSocketOpen(ConcurrentMap<Integer, StubNodeMetadata> nodes, public StubSocketOpen(ConcurrentMap<Integer, StubNodeMetadata> nodes,
@Named("PUBLIC_IP_PREFIX") String publicIpPrefix) { @Named("PUBLIC_IP_PREFIX") String publicIpPrefix) {
this.nodes = nodes; this.nodes = nodes;
this.publicIpPrefix = publicIpPrefix; this.publicIpPrefix = publicIpPrefix;
} }
@ -161,8 +158,8 @@ public class StubComputeServiceContextModule extends AbstractModule {
@Provides @Provides
@Singleton @Singleton
RestContext<ConcurrentMap, ConcurrentMap> provideRestContext(Closer closer) { RestContext<ConcurrentMap, ConcurrentMap> provideRestContext(Closer closer) {
return new RestContextImpl<ConcurrentMap, ConcurrentMap>(closer, nodes, nodes, URI return new RestContextImpl<ConcurrentMap, ConcurrentMap>(closer, nodes,
.create("http://stub"), System.getProperty("user.name")); nodes, URI.create("http://stub"), System.getProperty("user.name"));
} }
// NORMAL STUFF // NORMAL STUFF
@ -175,21 +172,19 @@ public class StubComputeServiceContextModule extends AbstractModule {
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
@Override @Override
protected void configure() { protected void configure() {
install(new ComputeServiceTimeoutsModule());
bind(new TypeLiteral<ComputeServiceContext>() { bind(new TypeLiteral<ComputeServiceContext>() {
}).to(new TypeLiteral<ComputeServiceContextImpl<ConcurrentMap, ConcurrentMap>>() { })
}).in(Scopes.SINGLETON); .to(
new TypeLiteral<ComputeServiceContextImpl<ConcurrentMap, ConcurrentMap>>() {
}).in(Scopes.SINGLETON);
bind(AddNodeWithTagStrategy.class).to(StubAddNodeWithTagStrategy.class); bind(AddNodeWithTagStrategy.class).to(StubAddNodeWithTagStrategy.class);
bind(ListNodesStrategy.class).to(StubListNodesStrategy.class); bind(ListNodesStrategy.class).to(StubListNodesStrategy.class);
bind(GetNodeMetadataStrategy.class).to(StubGetNodeMetadataStrategy.class); bind(GetNodeMetadataStrategy.class).to(StubGetNodeMetadataStrategy.class);
bind(RebootNodeStrategy.class).to(StubRebootNodeStrategy.class); bind(RebootNodeStrategy.class).to(StubRebootNodeStrategy.class);
bind(DestroyNodeStrategy.class).to(StubDestroyNodeStrategy.class); bind(DestroyNodeStrategy.class).to(StubDestroyNodeStrategy.class);
bind(LoadBalancerService.class).toProvider(Providers.<LoadBalancerService> of(null)); bind(LoadBalancerService.class).toProvider(
} Providers.<LoadBalancerService> of(null));
@Provides
@Singleton
protected Predicate<IPSocket> socketTester(SocketOpen open) {
return new RetryablePredicate<IPSocket>(open, 130, 10, TimeUnit.MILLISECONDS);
} }
@Provides @Provides
@ -205,12 +200,14 @@ public class StubComputeServiceContextModule extends AbstractModule {
private NodeState state; private NodeState state;
private final ExecutorService service; private final ExecutorService service;
public StubNodeMetadata(String providerId, String name, String id, Location location, public StubNodeMetadata(String providerId, String name, String id,
URI uri, Map<String, String> userMetadata, String tag, Image image, NodeState state, Location location, URI uri, Map<String, String> userMetadata,
Iterable<String> publicAddresses, Iterable<String> privateAddresses, String tag, Image image, NodeState state,
Map<String, String> extra, Credentials credentials, ExecutorService service) { Iterable<String> publicAddresses,
super(providerId, name, id, location, uri, userMetadata, tag, image, state, Iterable<String> privateAddresses, Map<String, String> extra,
publicAddresses, privateAddresses, extra, credentials); Credentials credentials, ExecutorService service) {
super(providerId, name, id, location, uri, userMetadata, tag, image,
state, publicAddresses, privateAddresses, extra, credentials);
this.setState(state, 0); this.setState(state, 0);
this.service = service; this.service = service;
} }
@ -242,7 +239,8 @@ public class StubComputeServiceContextModule extends AbstractModule {
} }
@Singleton @Singleton
public static class StubAddNodeWithTagStrategy implements AddNodeWithTagStrategy { public static class StubAddNodeWithTagStrategy implements
AddNodeWithTagStrategy {
private final Location location; private final Location location;
private final ExecutorService service; private final ExecutorService service;
private final ConcurrentMap<Integer, StubNodeMetadata> nodes; private final ConcurrentMap<Integer, StubNodeMetadata> nodes;
@ -252,15 +250,16 @@ public class StubComputeServiceContextModule extends AbstractModule {
private final String passwordPrefix; private final String passwordPrefix;
@Inject @Inject
public StubAddNodeWithTagStrategy(ConcurrentMap<Integer, StubNodeMetadata> nodes, public StubAddNodeWithTagStrategy(
Location location, @Named(Constants.PROPERTY_USER_THREADS) ExecutorService service, ConcurrentMap<Integer, StubNodeMetadata> nodes, Location location,
@Named("NODE_ID") Provider<Integer> idProvider, @Named(Constants.PROPERTY_USER_THREADS) ExecutorService service,
@Named("PUBLIC_IP_PREFIX") String publicIpPrefix, @Named("NODE_ID") Provider<Integer> idProvider,
@Named("PRIVATE_IP_PREFIX") String privateIpPrefix, @Named("PUBLIC_IP_PREFIX") String publicIpPrefix,
@Named("PASSWORD_PREFIX") String passwordPrefix) { @Named("PRIVATE_IP_PREFIX") String privateIpPrefix,
@Named("PASSWORD_PREFIX") String passwordPrefix) {
this.nodes = nodes; this.nodes = nodes;
this.location = location; this.location = location;
this.service = service; this.service = Executors.newCachedThreadPool();
this.idProvider = idProvider; this.idProvider = idProvider;
this.publicIpPrefix = publicIpPrefix; this.publicIpPrefix = publicIpPrefix;
this.privateIpPrefix = privateIpPrefix; this.privateIpPrefix = privateIpPrefix;
@ -269,27 +268,31 @@ public class StubComputeServiceContextModule extends AbstractModule {
@Override @Override
public NodeMetadata execute(String tag, String name, Template template) { public NodeMetadata execute(String tag, String name, Template template) {
checkArgument(location.equals(template.getLocation()), "invalid location: " checkArgument(location.equals(template.getLocation()),
+ template.getLocation()); "invalid location: " + template.getLocation());
int id = idProvider.get(); int id = idProvider.get();
StubNodeMetadata node = new StubNodeMetadata(id + "", name, id + "", location, null, StubNodeMetadata node = new StubNodeMetadata(id + "", name, id + "",
ImmutableMap.<String, String> of(), tag, template.getImage(), NodeState.PENDING, location, null, ImmutableMap.<String, String> of(), tag,
ImmutableSet.<String> of(publicIpPrefix + id), ImmutableSet template.getImage(), NodeState.PENDING, ImmutableSet
.<String> of(privateIpPrefix + id), ImmutableMap.<String, String> of(), .<String> of(publicIpPrefix + id), ImmutableSet
new Credentials("root", passwordPrefix + id), service); .<String> of(privateIpPrefix + id), ImmutableMap
node.setState(NodeState.RUNNING, 100); .<String, String> of(), new Credentials("root",
passwordPrefix + id), service);
nodes.put(id, node); nodes.put(id, node);
node.setState(NodeState.RUNNING, 100);
return node; return node;
} }
} }
@Singleton @Singleton
public static class StubGetNodeMetadataStrategy implements GetNodeMetadataStrategy { public static class StubGetNodeMetadataStrategy implements
GetNodeMetadataStrategy {
private final ConcurrentMap<Integer, StubNodeMetadata> nodes; private final ConcurrentMap<Integer, StubNodeMetadata> nodes;
@Inject @Inject
protected StubGetNodeMetadataStrategy(ConcurrentMap<Integer, StubNodeMetadata> nodes) { protected StubGetNodeMetadataStrategy(
ConcurrentMap<Integer, StubNodeMetadata> nodes) {
this.nodes = nodes; this.nodes = nodes;
} }
@ -304,7 +307,8 @@ public class StubComputeServiceContextModule extends AbstractModule {
private final ConcurrentMap<Integer, StubNodeMetadata> nodes; private final ConcurrentMap<Integer, StubNodeMetadata> nodes;
@Inject @Inject
protected StubListNodesStrategy(ConcurrentMap<Integer, StubNodeMetadata> nodes) { protected StubListNodesStrategy(
ConcurrentMap<Integer, StubNodeMetadata> nodes) {
this.nodes = nodes; this.nodes = nodes;
} }
@ -315,7 +319,7 @@ public class StubComputeServiceContextModule extends AbstractModule {
@Override @Override
public Iterable<? extends NodeMetadata> listDetailsOnNodesMatching( public Iterable<? extends NodeMetadata> listDetailsOnNodesMatching(
Predicate<ComputeMetadata> filter) { Predicate<ComputeMetadata> filter) {
return Iterables.filter(nodes.values(), filter); return Iterables.filter(nodes.values(), filter);
} }
} }
@ -325,18 +329,19 @@ public class StubComputeServiceContextModule extends AbstractModule {
private final ConcurrentMap<Integer, StubNodeMetadata> nodes; private final ConcurrentMap<Integer, StubNodeMetadata> nodes;
@Inject @Inject
protected StubRebootNodeStrategy(ConcurrentMap<Integer, StubNodeMetadata> nodes) { protected StubRebootNodeStrategy(
ConcurrentMap<Integer, StubNodeMetadata> nodes) {
this.nodes = nodes; this.nodes = nodes;
} }
@Override @Override
public boolean execute(String id) { public StubNodeMetadata execute(String id) {
StubNodeMetadata node = nodes.get(Integer.parseInt(id)); StubNodeMetadata node = nodes.get(Integer.parseInt(id));
if (node == null) if (node == null)
throw new ResourceNotFoundException("node not found: " + id); throw new ResourceNotFoundException("node not found: " + id);
node.setState(NodeState.PENDING, 0); node.setState(NodeState.PENDING, 0);
node.setState(NodeState.RUNNING, 50); node.setState(NodeState.RUNNING, 50);
return true; return node;
} }
} }
@ -346,18 +351,19 @@ public class StubComputeServiceContextModule extends AbstractModule {
private final ExecutorService service; private final ExecutorService service;
@Inject @Inject
protected StubDestroyNodeStrategy(ConcurrentMap<Integer, StubNodeMetadata> nodes, protected StubDestroyNodeStrategy(
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService service) { ConcurrentMap<Integer, StubNodeMetadata> nodes,
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService service) {
this.nodes = nodes; this.nodes = nodes;
this.service = service; this.service = service;
} }
@Override @Override
public boolean execute(String id) { public StubNodeMetadata execute(String id) {
final int nodeId = Integer.parseInt(id); final int nodeId = Integer.parseInt(id);
StubNodeMetadata node = nodes.get(nodeId); StubNodeMetadata node = nodes.get(nodeId);
if (node == null) if (node == null)
return true; return node;
node.setState(NodeState.PENDING, 0); node.setState(NodeState.PENDING, 0);
node.setState(NodeState.TERMINATED, 50); node.setState(NodeState.TERMINATED, 50);
service.execute(new Runnable() { service.execute(new Runnable() {
@ -374,7 +380,7 @@ public class StubComputeServiceContextModule extends AbstractModule {
} }
}); });
return true; return node;
} }
} }
@ -385,52 +391,49 @@ public class StubComputeServiceContextModule extends AbstractModule {
return "%s-%s"; return "%s-%s";
} }
@Provides
@Singleton
@Named("NOT_RUNNING")
protected Predicate<CommandUsingClient> runScriptRunning(ScriptStatusReturnsZero stateRunning) {
return new RetryablePredicate<CommandUsingClient>(Predicates.not(stateRunning), 600, 3,
TimeUnit.SECONDS);
}
@Provides @Provides
@Singleton @Singleton
protected Set<? extends Size> provideSizes() { protected Set<? extends Size> provideSizes() {
return ImmutableSet.of(new StubSize("small", 1, 1740, 160, ImmutableSet return ImmutableSet.of(new StubSize("small", 1, 1740, 160, ImmutableSet
.of(Architecture.X86_32)), new StubSize("medium", 4, 7680, 850, ImmutableSet .of(Architecture.X86_32)), new StubSize("medium", 4, 7680, 850,
.of(Architecture.X86_64)), new StubSize("large", 8, 15360, 1690, ImmutableSet ImmutableSet.of(Architecture.X86_64)), new StubSize("large", 8,
.of(Architecture.X86_64))); 15360, 1690, ImmutableSet.of(Architecture.X86_64)));
} }
private static class StubSize extends org.jclouds.compute.domain.internal.SizeImpl { private static class StubSize extends
org.jclouds.compute.domain.internal.SizeImpl {
/** The serialVersionUID */ /** The serialVersionUID */
private static final long serialVersionUID = -1842135761654973637L; private static final long serialVersionUID = -1842135761654973637L;
StubSize(String type, int cores, int ram, int disk, StubSize(String type, int cores, int ram, int disk,
Iterable<Architecture> supportedArchitectures) { Iterable<Architecture> supportedArchitectures) {
super(type, type, type, null, null, ImmutableMap.<String, String> of(), cores, ram, disk, super(type, type, type, null, null,
architectureIn(supportedArchitectures)); ImmutableMap.<String, String> of(), cores, ram, disk,
architectureIn(supportedArchitectures));
} }
} }
@Provides @Provides
@Singleton @Singleton
protected Set<? extends Image> provideImages(Location defaultLocation) { protected Set<? extends Image> provideImages(Location defaultLocation) {
return ImmutableSet.of(new ImageImpl("1", OsFamily.UBUNTU.name(), "1", defaultLocation, null, return ImmutableSet.of(new ImageImpl("1", OsFamily.UBUNTU.name(), "1",
ImmutableMap.<String, String> of(), "stub ubuntu 32", "", OsFamily.UBUNTU, defaultLocation, null, ImmutableMap.<String, String> of(),
"ubuntu 64", Architecture.X86_64, new Credentials("root", null)), new ImageImpl("2", "stub ubuntu 32", "", OsFamily.UBUNTU, "ubuntu 64",
OsFamily.UBUNTU.name(), "2", defaultLocation, null, ImmutableMap Architecture.X86_64, new Credentials("root", null)), new ImageImpl(
.<String, String> of(), "stub ubuntu 64", "", OsFamily.UBUNTU, "ubuntu 64", "2", OsFamily.UBUNTU.name(), "2", defaultLocation, null,
Architecture.X86_64, new Credentials("root", null)), new ImageImpl("3", ImmutableMap.<String, String> of(), "stub ubuntu 64", "",
OsFamily.CENTOS.name(), "3", defaultLocation, null, ImmutableMap OsFamily.UBUNTU, "ubuntu 64", Architecture.X86_64, new Credentials(
.<String, String> of(), "stub centos 64", "", OsFamily.CENTOS, "centos 64", "root", null)), new ImageImpl("3", OsFamily.CENTOS.name(),
Architecture.X86_64, new Credentials("root", null))); "3", defaultLocation, null, ImmutableMap.<String, String> of(),
"stub centos 64", "", OsFamily.CENTOS, "centos 64",
Architecture.X86_64, new Credentials("root", null)));
} }
@Provides @Provides
@Singleton @Singleton
Location getLocation() { Location getLocation() {
Location provider = new LocationImpl(LocationScope.PROVIDER, providerName, providerName, null); Location provider = new LocationImpl(LocationScope.PROVIDER,
providerName, providerName, null);
return new LocationImpl(LocationScope.ZONE, "memory", "memory", provider); return new LocationImpl(LocationScope.ZONE, "memory", "memory", provider);
} }

View File

@ -48,6 +48,7 @@ import org.jclouds.compute.domain.internal.NodeMetadataImpl;
import org.jclouds.compute.options.TemplateOptions; import org.jclouds.compute.options.TemplateOptions;
import org.jclouds.compute.predicates.ScriptStatusReturnsZero.CommandUsingClient; import org.jclouds.compute.predicates.ScriptStatusReturnsZero.CommandUsingClient;
import org.jclouds.compute.reference.ComputeServiceConstants; import org.jclouds.compute.reference.ComputeServiceConstants;
import org.jclouds.compute.strategy.GetNodeMetadataStrategy;
import org.jclouds.concurrent.ConcurrentUtils; import org.jclouds.concurrent.ConcurrentUtils;
import org.jclouds.domain.Credentials; import org.jclouds.domain.Credentials;
import org.jclouds.logging.Logger; import org.jclouds.logging.Logger;
@ -82,52 +83,61 @@ public class ComputeUtils {
protected final Predicate<CommandUsingClient> runScriptNotRunning; protected final Predicate<CommandUsingClient> runScriptNotRunning;
private final Predicate<IPSocket> socketTester; private final Predicate<IPSocket> socketTester;
private final ExecutorService executor; private final ExecutorService executor;
protected final Predicate<NodeMetadata> nodeRunning;
private final GetNodeMetadataStrategy getNode;
@Inject @Inject
public ComputeUtils(Predicate<IPSocket> socketTester, public ComputeUtils(
@Named("NOT_RUNNING") Predicate<CommandUsingClient> runScriptNotRunning, Predicate<IPSocket> socketTester,
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService executor) { @Named("SCRIPT_COMPLETE") Predicate<CommandUsingClient> runScriptNotRunning,
GetNodeMetadataStrategy getNode,
@Named("NODE_RUNNING") Predicate<NodeMetadata> nodeRunning,
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService executor) {
this.nodeRunning = nodeRunning;
this.getNode = getNode;
this.socketTester = socketTester; this.socketTester = socketTester;
this.runScriptNotRunning = runScriptNotRunning; this.runScriptNotRunning = runScriptNotRunning;
this.executor = executor; this.executor = executor;
} }
public static String createExecutionErrorMessage(Map<?, Exception> executionExceptions) { public static String createExecutionErrorMessage(
Map<?, Exception> executionExceptions) {
Formatter fmt = new Formatter().format("Execution failures:%n%n"); Formatter fmt = new Formatter().format("Execution failures:%n%n");
int index = 1; int index = 1;
for (Entry<?, Exception> errorMessage : executionExceptions.entrySet()) { for (Entry<?, Exception> errorMessage : executionExceptions.entrySet()) {
fmt.format("%s) %s on %s:%n%s%n%n", index++, errorMessage.getValue().getClass() fmt.format("%s) %s on %s:%n%s%n%n", index++, errorMessage.getValue()
.getSimpleName(), errorMessage.getKey(), Throwables .getClass().getSimpleName(), errorMessage.getKey(), Throwables
.getStackTraceAsString(errorMessage.getValue())); .getStackTraceAsString(errorMessage.getValue()));
} }
return fmt.format("%s error[s]", executionExceptions.size()).toString(); return fmt.format("%s error[s]", executionExceptions.size()).toString();
} }
public Map<?, ListenableFuture<Void>> runOptionsOnNodesAndAddToGoodSetOrPutExceptionIntoBadMap( public Map<?, ListenableFuture<Void>> runOptionsOnNodesAndAddToGoodSetOrPutExceptionIntoBadMap(
final TemplateOptions options, Iterable<NodeMetadata> runningNodes, final TemplateOptions options, Iterable<NodeMetadata> runningNodes,
final Set<NodeMetadata> goodNodes, final Map<NodeMetadata, Exception> badNodes) { final Set<NodeMetadata> goodNodes,
final Map<NodeMetadata, Exception> badNodes) {
Map<NodeMetadata, ListenableFuture<Void>> responses = Maps.newHashMap(); Map<NodeMetadata, ListenableFuture<Void>> responses = Maps.newHashMap();
for (final NodeMetadata node : runningNodes) { for (final NodeMetadata node : runningNodes) {
responses.put(node, makeListenable(executor responses.put(node, makeListenable(executor
.submit(runOptionsOnNodeAndAddToGoodSetOrPutExceptionIntoBadMap(node, badNodes, .submit(runOptionsOnNodeAndAddToGoodSetOrPutExceptionIntoBadMap(
goodNodes, options)), executor)); node, badNodes, goodNodes, options)), executor));
} }
return responses; return responses;
} }
public Callable<Void> runOptionsOnNodeAndAddToGoodSetOrPutExceptionIntoBadMap( public Callable<Void> runOptionsOnNodeAndAddToGoodSetOrPutExceptionIntoBadMap(
final NodeMetadata node, final Map<NodeMetadata, Exception> badNodes, final NodeMetadata node, final Map<NodeMetadata, Exception> badNodes,
final Set<NodeMetadata> goodNodes, final TemplateOptions options) { final Set<NodeMetadata> goodNodes, final TemplateOptions options) {
return new Callable<Void>() { return new Callable<Void>() {
@Override @Override
public Void call() throws Exception { public Void call() throws Exception {
try { try {
runOptionsOnNode(node, options); NodeMetadata node1 = runOptionsOnNode(node, options);
logger.debug("<< options applied node(%s)", node.getProviderId()); logger.debug("<< options applied node(%s)", node1.getId());
goodNodes.add(node); goodNodes.add(node1);
} catch (Exception e) { } catch (Exception e) {
logger.error(e, "<< problem applying options to node(%s): ", node.getProviderId(), logger.error(e, "<< problem applying options to node(%s): ",
Throwables.getRootCause(e).getMessage()); node.getId(), Throwables.getRootCause(e).getMessage());
badNodes.put(node, e); badNodes.put(node, e);
} }
return null; return null;
@ -136,19 +146,21 @@ public class ComputeUtils {
} }
public static String createNodeErrorMessage( public static String createNodeErrorMessage(
Map<? extends NodeMetadata, ? extends Throwable> failedNodes) { Map<? extends NodeMetadata, ? extends Throwable> failedNodes) {
Formatter fmt = new Formatter().format("Node failures:%n%n"); Formatter fmt = new Formatter().format("Node failures:%n%n");
int index = 1; int index = 1;
for (Entry<? extends NodeMetadata, ? extends Throwable> errorMessage : failedNodes.entrySet()) { for (Entry<? extends NodeMetadata, ? extends Throwable> errorMessage : failedNodes
fmt.format("%s) %s on node %s:%n%s%n%n", index++, errorMessage.getValue().getClass() .entrySet()) {
.getSimpleName(), errorMessage.getKey().getProviderId(), Throwables fmt.format("%s) %s on node %s:%n%s%n%n", index++, errorMessage
.getStackTraceAsString(errorMessage.getValue())); .getValue().getClass().getSimpleName(), errorMessage.getKey()
.getId(), Throwables.getStackTraceAsString(errorMessage
.getValue()));
} }
return fmt.format("%s error[s]", failedNodes.size()).toString(); return fmt.format("%s error[s]", failedNodes.size()).toString();
} }
public static Iterable<? extends ComputeMetadata> filterByName( public static Iterable<? extends ComputeMetadata> filterByName(
Iterable<? extends ComputeMetadata> nodes, final String name) { Iterable<? extends ComputeMetadata> nodes, final String name) {
return Iterables.filter(nodes, new Predicate<ComputeMetadata>() { return Iterables.filter(nodes, new Predicate<ComputeMetadata>() {
@Override @Override
public boolean apply(ComputeMetadata input) { public boolean apply(ComputeMetadata input) {
@ -157,67 +169,92 @@ public class ComputeUtils {
}); });
} }
public void runOptionsOnNode(NodeMetadata node, TemplateOptions options) { public NodeMetadata runOptionsOnNode(NodeMetadata node,
TemplateOptions options) {
if (!options.shouldBlockUntilRunning())
return node;
if (nodeRunning.apply(node))
node = installNewCredentials(getNode.execute(node.getId()), node
.getCredentials());
else
throw new IllegalStateException(
"node didn't achieve the state running: " + node);
List<SshCallable<?>> callables = Lists.newArrayList(); List<SshCallable<?>> callables = Lists.newArrayList();
if (options.getRunScript() != null) { if (options.getRunScript() != null) {
callables.add(runScriptOnNode(node, "runscript", options.getRunScript())); callables.add(runScriptOnNode(node, "runscript", options
.getRunScript()));
} }
if (options.getPublicKey() != null) { if (options.getPublicKey() != null) {
callables.add(authorizeKeyOnNode(node, options.getPublicKey())); callables.add(authorizeKeyOnNode(node, options.getPublicKey()));
} }
// changing the key "MUST" come last or else the other commands may fail. // changing the key "MUST" come last or else the other commands may
// fail.
if (callables.size() > 0 || options.getPrivateKey() != null) { if (callables.size() > 0 || options.getPrivateKey() != null) {
runCallablesOnNode(node, callables, options.getPrivateKey() != null ? installKeyOnNode( runCallablesOnNode(node, callables,
node, options.getPrivateKey()) : null); options.getPrivateKey() != null ? installKeyOnNode(node, options
.getPrivateKey()) : null);
} }
if (options.getPort() > 0) { if (options.getPort() > 0) {
checkNodeHasPublicIps(node); checkNodeHasPublicIps(node);
blockUntilPortIsListeningOnPublicIp(options.getPort(), options.getSeconds(), Iterables blockUntilPortIsListeningOnPublicIp(options.getPort(), options
.get(node.getPublicAddresses(), 0)); .getSeconds(), Iterables.get(node.getPublicAddresses(), 0));
} }
return node;
} }
private void checkNodeHasPublicIps(NodeMetadata node) { private void checkNodeHasPublicIps(NodeMetadata node) {
checkState(node.getPublicAddresses().size() > 0, checkState(node.getPublicAddresses().size() > 0,
"node does not have IP addresses configured: " + node); "node does not have IP addresses configured: " + node);
} }
private void blockUntilPortIsListeningOnPublicIp(int port, int seconds, String inetAddress) { private void blockUntilPortIsListeningOnPublicIp(int port, int seconds,
logger.debug(">> blocking on port %s:%d for %d seconds", inetAddress, port, seconds); String inetAddress) {
RetryablePredicate<IPSocket> tester = new RetryablePredicate<IPSocket>(socketTester, seconds, logger.debug(">> blocking on port %s:%d for %d seconds", inetAddress,
1, TimeUnit.SECONDS); port, seconds);
RetryablePredicate<IPSocket> tester = new RetryablePredicate<IPSocket>(
socketTester, seconds, 1, TimeUnit.SECONDS);
IPSocket socket = new IPSocket(inetAddress, port); IPSocket socket = new IPSocket(inetAddress, port);
boolean passed = tester.apply(socket); boolean passed = tester.apply(socket);
if (passed) if (passed)
logger.debug("<< port %s:%d opened", inetAddress, port); logger.debug("<< port %s:%d opened", inetAddress, port);
else else
logger.warn("<< port %s:%d didn't open after %d seconds", inetAddress, port, seconds); logger.warn("<< port %s:%d didn't open after %d seconds", inetAddress,
port, seconds);
} }
public InstallRSAPrivateKey installKeyOnNode(NodeMetadata node, String privateKey) { public InstallRSAPrivateKey installKeyOnNode(NodeMetadata node,
String privateKey) {
return new InstallRSAPrivateKey(node, privateKey); return new InstallRSAPrivateKey(node, privateKey);
} }
public AuthorizeRSAPublicKey authorizeKeyOnNode(NodeMetadata node, String publicKey) { public AuthorizeRSAPublicKey authorizeKeyOnNode(NodeMetadata node,
String publicKey) {
return new AuthorizeRSAPublicKey(node, publicKey); return new AuthorizeRSAPublicKey(node, publicKey);
} }
public RunScriptOnNode runScriptOnNode(NodeMetadata node, String scriptName, byte[] script) { public RunScriptOnNode runScriptOnNode(NodeMetadata node, String scriptName,
byte[] script) {
return new RunScriptOnNode(runScriptNotRunning, node, scriptName, script); return new RunScriptOnNode(runScriptNotRunning, node, scriptName, script);
} }
public RunScriptOnNode runScriptOnNodeAsDefaultUser(NodeMetadata node, String scriptName, public RunScriptOnNode runScriptOnNodeAsDefaultUser(NodeMetadata node,
byte[] script) { String scriptName, byte[] script) {
return new RunScriptOnNode(runScriptNotRunning, node, scriptName, script, false); return new RunScriptOnNode(runScriptNotRunning, node, scriptName, script,
false);
} }
public Map<SshCallable<?>, ?> runCallablesOnNode(NodeMetadata node, public Map<SshCallable<?>, ?> runCallablesOnNode(NodeMetadata node,
Iterable<? extends SshCallable<?>> parallel, @Nullable SshCallable<?> last) { Iterable<? extends SshCallable<?>> parallel,
checkState(this.sshFactory != null, "runScript requested, but no SshModule configured"); @Nullable SshCallable<?> last) {
checkState(this.sshFactory != null,
"runScript requested, but no SshModule configured");
checkNodeHasPublicIps(node); checkNodeHasPublicIps(node);
checkNotNull(node.getCredentials().key, "credentials.key for node " + node.getProviderId()); checkNotNull(node.getCredentials().key, "credentials.key for node "
+ node.getId());
SshClient ssh = createSshClientOncePortIsListeningOnNode(node); SshClient ssh = createSshClientOncePortIsListeningOnNode(node);
try { try {
ssh.connect(); ssh.connect();
@ -229,7 +266,8 @@ public class ComputeUtils {
} }
private Map<SshCallable<?>, ?> runTasksUsingSshClient( private Map<SshCallable<?>, ?> runTasksUsingSshClient(
Iterable<? extends SshCallable<?>> parallel, SshCallable<?> last, SshClient ssh) { Iterable<? extends SshCallable<?>> parallel, SshCallable<?> last,
SshClient ssh) {
Map<SshCallable<?>, Object> responses = Maps.newHashMap(); Map<SshCallable<?>, Object> responses = Maps.newHashMap();
if (Iterables.size(parallel) > 0) { if (Iterables.size(parallel) > 0) {
responses.putAll(runCallablesUsingSshClient(parallel, ssh)); responses.putAll(runCallablesUsingSshClient(parallel, ssh));
@ -246,37 +284,42 @@ public class ComputeUtils {
} }
public SshClient createSshClientOncePortIsListeningOnNode(NodeMetadata node) { public SshClient createSshClientOncePortIsListeningOnNode(NodeMetadata node) {
IPSocket socket = new IPSocket(Iterables.get(node.getPublicAddresses(), 0), 22); IPSocket socket = new IPSocket(Iterables
.get(node.getPublicAddresses(), 0), 22);
socketTester.apply(socket); socketTester.apply(socket);
SshClient ssh = isKeyAuth(node) ? sshFactory.create(socket, node.getCredentials().account, SshClient ssh = isKeyAuth(node) ? sshFactory.create(socket, node
node.getCredentials().key.getBytes()) : sshFactory.create(socket, node .getCredentials().account, node.getCredentials().key.getBytes())
.getCredentials().account, node.getCredentials().key); : sshFactory.create(socket, node.getCredentials().account, node
.getCredentials().key);
return ssh; return ssh;
} }
private Map<SshCallable<?>, Object> runCallablesUsingSshClient( private Map<SshCallable<?>, Object> runCallablesUsingSshClient(
Iterable<? extends SshCallable<?>> parallel, SshClient ssh) { Iterable<? extends SshCallable<?>> parallel, SshClient ssh) {
Map<SshCallable<?>, ListenableFuture<?>> parallelResponses = Maps.newHashMap(); Map<SshCallable<?>, ListenableFuture<?>> parallelResponses = Maps
.newHashMap();
for (SshCallable<?> callable : parallel) { for (SshCallable<?> callable : parallel) {
callable.setConnection(ssh, logger); callable.setConnection(ssh, logger);
parallelResponses.put(callable, ConcurrentUtils.makeListenable(executor.submit(callable), parallelResponses.put(callable, ConcurrentUtils.makeListenable(
executor)); executor.submit(callable), executor));
} }
Map<SshCallable<?>, Exception> exceptions = awaitCompletion(parallelResponses, executor, Map<SshCallable<?>, Exception> exceptions = awaitCompletion(
null, logger, "ssh"); parallelResponses, executor, null, logger, "ssh");
if (exceptions.size() > 0) if (exceptions.size() > 0)
throw new RuntimeException(String.format("error invoking callables on nodes: %s", throw new RuntimeException(String.format(
exceptions)); "error invoking callables on nodes: %s", exceptions));
Map<SshCallable<?>, Object> newresponses = transform(parallelResponses); Map<SshCallable<?>, Object> newresponses = transform(parallelResponses);
return newresponses; return newresponses;
} }
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public <T> Map<SshCallable<?>, T> transform(Map<SshCallable<?>, ListenableFuture<?>> responses) { public <T> Map<SshCallable<?>, T> transform(
Map<SshCallable<?>, ListenableFuture<?>> responses) {
Map<SshCallable<?>, T> actualResponses = Maps.newHashMap(); Map<SshCallable<?>, T> actualResponses = Maps.newHashMap();
for (Map.Entry<SshCallable<?>, ListenableFuture<?>> entry : responses.entrySet()) { for (Map.Entry<SshCallable<?>, ListenableFuture<?>> entry : responses
.entrySet()) {
try { try {
actualResponses.put(entry.getKey(), (T) entry.getValue().get()); actualResponses.put(entry.getKey(), (T) entry.getValue().get());
} catch (InterruptedException e) { } catch (InterruptedException e) {
@ -303,20 +346,24 @@ public class ComputeUtils {
private final boolean runAsRoot; private final boolean runAsRoot;
private Logger logger = Logger.NULL; private Logger logger = Logger.NULL;
RunScriptOnNode(@Named("NOT_RUNNING") Predicate<CommandUsingClient> runScriptNotRunning, RunScriptOnNode(
NodeMetadata node, String scriptName, byte[] script) { @Named("SCRIPT_COMPLETE") Predicate<CommandUsingClient> runScriptNotRunning,
NodeMetadata node, String scriptName, byte[] script) {
this(runScriptNotRunning, node, scriptName, script, true); this(runScriptNotRunning, node, scriptName, script, true);
} }
RunScriptOnNode(@Named("NOT_RUNNING") Predicate<CommandUsingClient> runScriptNotRunning, RunScriptOnNode(
NodeMetadata node, String scriptName, byte[] script, boolean runAsRoot) { @Named("SCRIPT_COMPLETE") Predicate<CommandUsingClient> runScriptNotRunning,
NodeMetadata node, String scriptName, byte[] script,
boolean runAsRoot) {
this.runScriptNotRunning = runScriptNotRunning; this.runScriptNotRunning = runScriptNotRunning;
this.node = checkNotNull(node, "node"); this.node = checkNotNull(node, "node");
this.scriptName = checkNotNull(scriptName, "scriptName"); this.scriptName = checkNotNull(scriptName, "scriptName");
this.script = new InitBuilder(scriptName, "/tmp/" + scriptName, "/tmp/" + scriptName, this.script = new InitBuilder(scriptName, "/tmp/" + scriptName,
ImmutableMap.<String, String> of(), Iterables.toArray(Splitter.on("\n").split( "/tmp/" + scriptName, ImmutableMap.<String, String> of(),
new String(checkNotNull(script, "script"))), String.class)).build( Iterables.toArray(Splitter.on("\n").split(
OsFamily.UNIX).getBytes(); new String(checkNotNull(script, "script"))), String.class))
.build(OsFamily.UNIX).getBytes();
this.runAsRoot = runAsRoot; this.runAsRoot = runAsRoot;
} }
@ -330,15 +377,18 @@ public class ComputeUtils {
returnVal = runScriptAsRoot(); returnVal = runScriptAsRoot();
else else
returnVal = runScriptAsDefaultUser(); returnVal = runScriptAsDefaultUser();
runScriptNotRunning.apply(new CommandUsingClient("./" + scriptName + " status", ssh)); runScriptNotRunning.apply(new CommandUsingClient("./" + scriptName
+ " status", ssh));
logger.debug("<< complete(%d)", returnVal.getExitCode()); logger.debug("<< complete(%d)", returnVal.getExitCode());
if (logger.isDebugEnabled() || returnVal.getExitCode() != 0) { if (logger.isDebugEnabled() || returnVal.getExitCode() != 0) {
logger.debug("<< stdout from %s as %s@%s\n%s", scriptName, logger.debug("<< stdout from %s as %s@%s\n%s", scriptName, node
node.getCredentials().account, Iterables.get(node.getPublicAddresses(), 0), .getCredentials().account, Iterables.get(node
ssh.exec("./" + scriptName + " tail").getOutput()); .getPublicAddresses(), 0), ssh.exec(
logger.debug("<< stderr from %s as %s@%s\n%s", scriptName, "./" + scriptName + " tail").getOutput());
node.getCredentials().account, Iterables.get(node.getPublicAddresses(), 0), logger.debug("<< stderr from %s as %s@%s\n%s", scriptName, node
ssh.exec("./" + scriptName + " tailerr").getOutput()); .getCredentials().account, Iterables.get(node
.getPublicAddresses(), 0), ssh.exec(
"./" + scriptName + " tailerr").getOutput());
} }
return returnVal; return returnVal;
} }
@ -351,24 +401,28 @@ public class ComputeUtils {
private ExecResponse runScriptAsRoot() { private ExecResponse runScriptAsRoot() {
if (node.getCredentials().account.equals("root")) { if (node.getCredentials().account.equals("root")) {
logger.debug(">> running %s as %s@%s", scriptName, node.getCredentials().account, logger.debug(">> running %s as %s@%s", scriptName, node
Iterables.get(node.getPublicAddresses(), 0)); .getCredentials().account, Iterables.get(node
.getPublicAddresses(), 0));
return ssh.exec("./" + scriptName + " start"); return ssh.exec("./" + scriptName + " start");
} else if (isKeyAuth(node)) { } else if (isKeyAuth(node)) {
logger.debug(">> running sudo %s as %s@%s", scriptName, node.getCredentials().account, logger.debug(">> running sudo %s as %s@%s", scriptName, node
Iterables.get(node.getPublicAddresses(), 0)); .getCredentials().account, Iterables.get(node
.getPublicAddresses(), 0));
return ssh.exec("sudo ./" + scriptName + " start"); return ssh.exec("sudo ./" + scriptName + " start");
} else { } else {
logger.debug(">> running sudo -S %s as %s@%s", scriptName, logger.debug(">> running sudo -S %s as %s@%s", scriptName, node
node.getCredentials().account, Iterables.get(node.getPublicAddresses(), 0)); .getCredentials().account, Iterables.get(node
return ssh.exec(String.format("echo '%s'|sudo -S ./%s", node.getCredentials().key, .getPublicAddresses(), 0));
scriptName + " start")); return ssh.exec(String.format("echo '%s'|sudo -S ./%s", node
.getCredentials().key, scriptName + " start"));
} }
} }
private ExecResponse runScriptAsDefaultUser() { private ExecResponse runScriptAsDefaultUser() {
logger.debug(">> running script %s as %s@%s", scriptName, node.getCredentials().account, logger.debug(">> running script %s as %s@%s", scriptName, node
Iterables.get(node.getPublicAddresses(), 0)); .getCredentials().account, Iterables.get(node
.getPublicAddresses(), 0));
return ssh.exec(String.format("./%s", scriptName + " start")); return ssh.exec(String.format("./%s", scriptName + " start"));
} }
@ -378,7 +432,8 @@ public class ComputeUtils {
} }
} }
public static class InstallRSAPrivateKey implements SshCallable<ExecResponse> { public static class InstallRSAPrivateKey implements
SshCallable<ExecResponse> {
private SshClient ssh; private SshClient ssh;
private final NodeMetadata node; private final NodeMetadata node;
private final String privateKey; private final String privateKey;
@ -393,9 +448,12 @@ public class ComputeUtils {
@Override @Override
public ExecResponse call() throws Exception { public ExecResponse call() throws Exception {
ssh.exec("mkdir .ssh"); ssh.exec("mkdir .ssh");
ssh.put(".ssh/id_rsa", new ByteArrayInputStream(privateKey.getBytes())); ssh
logger.debug(">> installing rsa key for %s@%s", node.getCredentials().account, Iterables .put(".ssh/id_rsa", new ByteArrayInputStream(privateKey
.get(node.getPublicAddresses(), 0)); .getBytes()));
logger.debug(">> installing rsa key for %s@%s",
node.getCredentials().account, Iterables.get(node
.getPublicAddresses(), 0));
return ssh.exec("chmod 600 .ssh/id_rsa"); return ssh.exec("chmod 600 .ssh/id_rsa");
} }
@ -411,7 +469,8 @@ public class ComputeUtils {
} }
} }
public static class AuthorizeRSAPublicKey implements SshCallable<ExecResponse> { public static class AuthorizeRSAPublicKey implements
SshCallable<ExecResponse> {
private SshClient ssh; private SshClient ssh;
private final NodeMetadata node; private final NodeMetadata node;
private final String publicKey; private final String publicKey;
@ -426,10 +485,13 @@ public class ComputeUtils {
@Override @Override
public ExecResponse call() throws Exception { public ExecResponse call() throws Exception {
ssh.exec("mkdir .ssh"); ssh.exec("mkdir .ssh");
ssh.put(".ssh/id_rsa.pub", new ByteArrayInputStream(publicKey.getBytes())); ssh.put(".ssh/id_rsa.pub", new ByteArrayInputStream(publicKey
logger.debug(">> authorizing rsa public key for %s@%s", node.getCredentials().account, .getBytes()));
Iterables.get(node.getPublicAddresses(), 0)); logger.debug(">> authorizing rsa public key for %s@%s", node
ExecResponse returnVal = ssh.exec("cat .ssh/id_rsa.pub >> .ssh/authorized_keys"); .getCredentials().account, Iterables.get(node
.getPublicAddresses(), 0));
ExecResponse returnVal = ssh
.exec("cat .ssh/id_rsa.pub >> .ssh/authorized_keys");
returnVal = ssh.exec("chmod 600 .ssh/authorized_keys"); returnVal = ssh.exec("chmod 600 .ssh/authorized_keys");
logger.debug("<< complete(%d)", returnVal.getExitCode()); logger.debug("<< complete(%d)", returnVal.getExitCode());
return returnVal; return returnVal;
@ -449,31 +511,36 @@ public class ComputeUtils {
public static boolean isKeyAuth(NodeMetadata createdNode) { public static boolean isKeyAuth(NodeMetadata createdNode) {
return createdNode.getCredentials().key != null return createdNode.getCredentials().key != null
&& createdNode.getCredentials().key.startsWith("-----BEGIN RSA PRIVATE KEY-----"); && createdNode.getCredentials().key
.startsWith("-----BEGIN RSA PRIVATE KEY-----");
} }
/** /**
* Given the instances of {@link NodeMetadata} (immutable) and {@link Credentials} (immutable), * Given the instances of {@link NodeMetadata} (immutable) and
* returns a new instance of {@link NodeMetadata} that has new credentials * {@link Credentials} (immutable), returns a new instance of
* {@link NodeMetadata} that has new credentials
*/ */
public static NodeMetadata installNewCredentials(NodeMetadata node, Credentials newCredentials) { public static NodeMetadata installNewCredentials(NodeMetadata node,
return new NodeMetadataImpl(node.getProviderId(), node.getName(), node.getId(), node Credentials newCredentials) {
.getLocation(), node.getUri(), node.getUserMetadata(), node.getTag(), node return new NodeMetadataImpl(node.getProviderId(), node.getName(), node
.getImage(), node.getState(), node.getPublicAddresses(), node.getPrivateAddresses(), .getId(), node.getLocation(), node.getUri(),
node.getExtra(), newCredentials); node.getUserMetadata(), node.getTag(), node.getImage(), node
.getState(), node.getPublicAddresses(), node
.getPrivateAddresses(), node.getExtra(), newCredentials);
} }
/** /**
* Gets a set of supported providers. Idea stolen from pallets (supported-clouds). Uses * Gets a set of supported providers. Idea stolen from pallets
* compute.properties to populate the set. * (supported-clouds). Uses compute.properties to populate the set.
* *
* XXX: Pass in extra properties to support ones that aren't in compute.properties * XXX: Pass in extra properties to support ones that aren't in
* compute.properties
*/ */
public static Set<String> getSupportedProviders() { public static Set<String> getSupportedProviders() {
Properties properties = new Properties(); Properties properties = new Properties();
try { try {
properties.load(Resources.newInputStreamSupplier( properties.load(Resources.newInputStreamSupplier(
Resources.getResource("compute.properties")).getInput()); Resources.getResource("compute.properties")).getInput());
} catch (IOException e) { } catch (IOException e) {
throw new RuntimeException(e); throw new RuntimeException(e);
} }
@ -484,7 +551,8 @@ public class ComputeUtils {
for (Object key : keys) { for (Object key : keys) {
String keyString = key.toString(); String keyString = key.toString();
if (keyString.endsWith(".contextbuilder")) { if (keyString.endsWith(".contextbuilder")) {
providers.add(keyString.substring(0, keyString.length() - ".contextbuilder".length())); providers.add(keyString.substring(0, keyString.length()
- ".contextbuilder".length()));
} }
} }
return providers; return providers;

View File

@ -99,8 +99,8 @@ public abstract class BaseComputeServiceLiveTest {
protected Map<String, String> keyPair; protected Map<String, String> keyPair;
@BeforeGroups(groups = { "integration", "live" }) @BeforeGroups(groups = { "integration", "live" })
public void setupClient() throws InterruptedException, ExecutionException, TimeoutException, public void setupClient() throws InterruptedException, ExecutionException,
IOException { TimeoutException, IOException {
if (tag == null) if (tag == null)
tag = checkNotNull(service, "service"); tag = checkNotNull(service, "service");
setupCredentials(); setupCredentials();
@ -110,28 +110,33 @@ public abstract class BaseComputeServiceLiveTest {
Injector injector = createSshClientInjector(); Injector injector = createSshClientInjector();
sshFactory = injector.getInstance(SshClient.Factory.class); sshFactory = injector.getInstance(SshClient.Factory.class);
SocketOpen socketOpen = injector.getInstance(SocketOpen.class); SocketOpen socketOpen = injector.getInstance(SocketOpen.class);
socketTester = new RetryablePredicate<IPSocket>(socketOpen, 60, 1, TimeUnit.SECONDS); socketTester = new RetryablePredicate<IPSocket>(socketOpen, 60, 1,
TimeUnit.SECONDS);
injector.injectMembers(socketOpen); // add logger injector.injectMembers(socketOpen); // add logger
} }
protected void setupKeyPair() throws FileNotFoundException, IOException { protected void setupKeyPair() throws FileNotFoundException, IOException {
String secretKeyFile; String secretKeyFile;
try { try {
secretKeyFile = checkNotNull(System.getProperty("jclouds.test.ssh.keyfile"), secretKeyFile = checkNotNull(System
"jclouds.test.ssh.keyfile"); .getProperty("jclouds.test.ssh.keyfile"),
"jclouds.test.ssh.keyfile");
} catch (NullPointerException e) { } catch (NullPointerException e) {
secretKeyFile = System.getProperty("user.home") + "/.ssh/id_rsa"; secretKeyFile = System.getProperty("user.home") + "/.ssh/id_rsa";
} }
checkSecretKeyFile(secretKeyFile); checkSecretKeyFile(secretKeyFile);
String secret = Files.toString(new File(secretKeyFile), Charsets.UTF_8); String secret = Files.toString(new File(secretKeyFile), Charsets.UTF_8);
assert secret.startsWith("-----BEGIN RSA PRIVATE KEY-----") : "invalid key:\n" + secret; assert secret.startsWith("-----BEGIN RSA PRIVATE KEY-----") : "invalid key:\n"
keyPair = ImmutableMap.<String, String> of("private", secret, "public", Files.toString( + secret;
new File(secretKeyFile + ".pub"), Charsets.UTF_8)); keyPair = ImmutableMap.<String, String> of("private", secret, "public",
Files.toString(new File(secretKeyFile + ".pub"), Charsets.UTF_8));
} }
protected void setupCredentials() { protected void setupCredentials() {
user = checkNotNull(System.getProperty("jclouds.test.user"), "jclouds.test.user"); user = checkNotNull(System.getProperty("jclouds.test.user"),
password = checkNotNull(System.getProperty("jclouds.test.key"), "jclouds.test.key"); "jclouds.test.user");
password = checkNotNull(System.getProperty("jclouds.test.key"),
"jclouds.test.key");
} }
protected Injector createSshClientInjector() { protected Injector createSshClientInjector() {
@ -141,16 +146,20 @@ public abstract class BaseComputeServiceLiveTest {
private void initializeContextAndClient() throws IOException { private void initializeContextAndClient() throws IOException {
if (context != null) if (context != null)
context.close(); context.close();
context = new ComputeServiceContextFactory().createContext(service, user, password, context = new ComputeServiceContextFactory()
ImmutableSet.of(new Log4JLoggingModule(), getSshModule())); .createContext(service, user, password, ImmutableSet.of(
new Log4JLoggingModule(), getSshModule()));
client = context.getComputeService(); client = context.getComputeService();
} }
private void checkSecretKeyFile(String secretKeyFile) throws FileNotFoundException { private void checkSecretKeyFile(String secretKeyFile)
Utils.checkNotEmpty(secretKeyFile, throws FileNotFoundException {
"System property: [jclouds.test.ssh.keyfile] set to an empty string"); Utils
.checkNotEmpty(secretKeyFile,
"System property: [jclouds.test.ssh.keyfile] set to an empty string");
if (!new File(secretKeyFile).exists()) { if (!new File(secretKeyFile).exists()) {
throw new FileNotFoundException("secretKeyFile not found at: " + secretKeyFile); throw new FileNotFoundException("secretKeyFile not found at: "
+ secretKeyFile);
} }
} }
@ -160,7 +169,7 @@ public abstract class BaseComputeServiceLiveTest {
@Test(enabled = true, expectedExceptions = AuthorizationException.class) @Test(enabled = true, expectedExceptions = AuthorizationException.class)
public void testCorrectAuthException() throws Exception { public void testCorrectAuthException() throws Exception {
new ComputeServiceContextFactory().createContext(service, "MOMMA", "MIA", new ComputeServiceContextFactory().createContext(service, "MOMMA", "MIA",
ImmutableSet.<Module> of(new Log4JLoggingModule())).close(); ImmutableSet.<Module> of(new Log4JLoggingModule())).close();
} }
@Test(enabled = true) @Test(enabled = true)
@ -172,10 +181,11 @@ public abstract class BaseComputeServiceLiveTest {
assert duration < 1000 : String.format("%dms to get images", duration); assert duration < 1000 : String.format("%dms to get images", duration);
} }
// since surefire and eclipse don't otherwise guarantee the order, we are // since surefire and eclipse don't otherwise guarantee the order, we are
// starting this one alphabetically before create2nodes.. // starting this one alphabetically before create2nodes..
@Test(enabled = true, dependsOnMethods = "testImagesCache") @Test(enabled = true, dependsOnMethods = "testImagesCache")
public void testAScriptExecutionAfterBootWithBasicTemplate() throws Exception { public void testAScriptExecutionAfterBootWithBasicTemplate()
throws Exception {
String tag = this.tag + "run"; String tag = this.tag + "run";
try { try {
client.destroyNodesMatching(NodePredicates.withTag(tag)); client.destroyNodesMatching(NodePredicates.withTag(tag));
@ -185,18 +195,21 @@ public abstract class BaseComputeServiceLiveTest {
TemplateOptions options = client.templateOptions().blockOnPort(22, 120); TemplateOptions options = client.templateOptions().blockOnPort(22, 120);
try { try {
Set<? extends NodeMetadata> nodes = client.runNodesWithTag(tag, 1, options); Set<? extends NodeMetadata> nodes = client.runNodesWithTag(tag, 1,
options);
Credentials good = nodes.iterator().next().getCredentials(); Credentials good = nodes.iterator().next().getCredentials();
assert good.account != null; assert good.account != null;
assert good.key != null; assert good.key != null;
Image image = Iterables.get(nodes, 0).getImage(); Image image = Iterables.get(nodes, 0).getImage();
try { try {
Map<? extends NodeMetadata, ExecResponse> responses = runScriptWithCreds(tag, image Map<? extends NodeMetadata, ExecResponse> responses = runScriptWithCreds(
.getOsFamily(), new Credentials(good.account, "romeo")); tag, image.getOsFamily(), new Credentials(good.account,
"romeo"));
assert false : "shouldn't pass with a bad password\n" + responses; assert false : "shouldn't pass with a bad password\n" + responses;
} catch (RunScriptOnNodesException e) { } catch (RunScriptOnNodesException e) {
assert Throwables.getRootCause(e).getMessage().contains("Auth fail") : e; assert Throwables.getRootCause(e).getMessage()
.contains("Auth fail") : e;
} }
runScriptWithCreds(tag, image.getOsFamily(), good); runScriptWithCreds(tag, image.getOsFamily(), good);
@ -211,7 +224,8 @@ public abstract class BaseComputeServiceLiveTest {
@Test(enabled = true, dependsOnMethods = "testImagesCache") @Test(enabled = true, dependsOnMethods = "testImagesCache")
public void testTemplateMatch() throws Exception { public void testTemplateMatch() throws Exception {
template = buildTemplate(client.templateBuilder()); template = buildTemplate(client.templateBuilder());
Template toMatch = client.templateBuilder().imageId(template.getImage().getId()).build(); Template toMatch = client.templateBuilder().imageId(
template.getImage().getId()).build();
assertEquals(toMatch.getImage(), template.getImage()); assertEquals(toMatch.getImage(), template.getImage());
} }
@ -226,14 +240,14 @@ public abstract class BaseComputeServiceLiveTest {
} }
template = buildTemplate(client.templateBuilder()); template = buildTemplate(client.templateBuilder());
template.getOptions().installPrivateKey(keyPair.get("private")).authorizePublicKey( template.getOptions().installPrivateKey(keyPair.get("private"))
keyPair.get("public")).runScript( .authorizePublicKey(keyPair.get("public")).runScript(
buildScript(template.getImage().getOsFamily()).getBytes()); buildScript(template.getImage().getOsFamily()).getBytes());
try { try {
nodes = Sets.newTreeSet(client.runNodesWithTag(tag, 2, template)); nodes = Sets.newTreeSet(client.runNodesWithTag(tag, 2, template));
} catch (RunNodesException e) { } catch (RunNodesException e) {
nodes = Sets.newTreeSet(Iterables.concat(e.getSuccessfulNodes(), e.getNodeErrors() nodes = Sets.newTreeSet(Iterables.concat(e.getSuccessfulNodes(), e
.keySet())); .getNodeErrors().keySet()));
throw e; throw e;
} }
assertEquals(nodes.size(), 2); assertEquals(nodes.size(), 2);
@ -260,9 +274,11 @@ public abstract class BaseComputeServiceLiveTest {
} }
@Test(enabled = true, dependsOnMethods = "testCreateTwoNodesWithRunScript") @Test(enabled = true, dependsOnMethods = "testCreateTwoNodesWithRunScript")
public void testCreateAnotherNodeWithANewContextToEnsureSharedMemIsntRequired() throws Exception { public void testCreateAnotherNodeWithANewContextToEnsureSharedMemIsntRequired()
throws Exception {
initializeContextAndClient(); initializeContextAndClient();
TreeSet<NodeMetadata> nodes = Sets.newTreeSet(client.runNodesWithTag(tag, 1, template)); TreeSet<NodeMetadata> nodes = Sets.newTreeSet(client.runNodesWithTag(tag,
1, template));
checkNodes(nodes, tag); checkNodes(nodes, tag);
NodeMetadata node = nodes.first(); NodeMetadata node = nodes.first();
this.nodes.add(node); this.nodes.add(node);
@ -271,28 +287,32 @@ public abstract class BaseComputeServiceLiveTest {
assertEquals(node.getImage(), template.getImage()); assertEquals(node.getImage(), template.getImage());
} }
protected Map<? extends NodeMetadata, ExecResponse> runScriptWithCreds(final String tag, protected Map<? extends NodeMetadata, ExecResponse> runScriptWithCreds(
OsFamily osFamily, Credentials creds) throws RunScriptOnNodesException { final String tag, OsFamily osFamily, Credentials creds)
throws RunScriptOnNodesException {
try { try {
return client.runScriptOnNodesMatching(NodePredicates.runningWithTag(tag), buildScript( return client.runScriptOnNodesMatching(NodePredicates
osFamily).getBytes(), RunScriptOptions.Builder.overrideCredentialsWith(creds)); .runningWithTag(tag), buildScript(osFamily).getBytes(),
RunScriptOptions.Builder.overrideCredentialsWith(creds));
} catch (SshException e) { } catch (SshException e) {
if (Throwables.getRootCause(e).getMessage().contains("Auth fail")) { if (Throwables.getRootCause(e).getMessage().contains("Auth fail")) {
// System.err.printf("bad credentials: %s:%s for %s%n", creds.account, creds.key, client // System.err.printf("bad credentials: %s:%s for %s%n",
// creds.account, creds.key, client
// .listNodesDetailsMatching(tag)); // .listNodesDetailsMatching(tag));
} }
throw e; throw e;
} }
} }
protected void checkNodes(Iterable<? extends NodeMetadata> nodes, String tag) throws IOException { protected void checkNodes(Iterable<? extends NodeMetadata> nodes, String tag)
throws IOException {
for (NodeMetadata node : nodes) { for (NodeMetadata node : nodes) {
assertNotNull(node.getProviderId()); assertNotNull(node.getProviderId());
assertNotNull(node.getTag()); assertNotNull(node.getTag());
assertEquals(node.getTag(), tag); assertEquals(node.getTag(), tag);
assertEquals(node.getState(), NodeState.RUNNING); assertEquals(node.getState(), NodeState.RUNNING);
assert node.getPublicAddresses().size() >= 1 || node.getPrivateAddresses().size() >= 1 : "no ips in" assert node.getPublicAddresses().size() >= 1
+ node; || node.getPrivateAddresses().size() >= 1 : "no ips in" + node;
assertNotNull(node.getCredentials()); assertNotNull(node.getCredentials());
if (node.getCredentials().account != null) { if (node.getCredentials().account != null) {
assertNotNull(node.getCredentials().account); assertNotNull(node.getCredentials().account);
@ -308,58 +328,70 @@ public abstract class BaseComputeServiceLiveTest {
protected String buildScript(OsFamily osFamily) { protected String buildScript(OsFamily osFamily) {
switch (osFamily) { switch (osFamily) {
case UBUNTU: case UBUNTU:
return new StringBuilder()// return new StringBuilder()//
.append("echo nameserver 208.67.222.222 >> /etc/resolv.conf\n")// .append("echo nameserver 208.67.222.222 >> /etc/resolv.conf\n")//
.append("cp /etc/apt/sources.list /etc/apt/sources.list.old\n")// .append("cp /etc/apt/sources.list /etc/apt/sources.list.old\n")//
.append( .append(
"sed 's~us.archive.ubuntu.com~mirror.anl.gov/pub~g' /etc/apt/sources.list.old >/etc/apt/sources.list\n")// "sed 's~us.archive.ubuntu.com~mirror.anl.gov/pub~g' /etc/apt/sources.list.old >/etc/apt/sources.list\n")//
.append("apt-get update\n")// .append("apt-get update\n")//
.append("apt-get install -f -y --force-yes openjdk-6-jdk\n")// .append("apt-get install -f -y --force-yes openjdk-6-jdk\n")//
.append("wget -qO/usr/bin/runurl run.alestic.com/runurl\n")// .append("wget -qO/usr/bin/runurl run.alestic.com/runurl\n")//
.append("chmod 755 /usr/bin/runurl\n")// .append("chmod 755 /usr/bin/runurl\n")//
.toString(); .toString();
case CENTOS: case CENTOS:
case RHEL: case RHEL:
return new StringBuilder() return new StringBuilder()
.append("echo nameserver 208.67.222.222 >> /etc/resolv.conf\n") .append("echo nameserver 208.67.222.222 >> /etc/resolv.conf\n")
.append("echo \"[jdkrepo]\" >> /etc/yum.repos.d/CentOS-Base.repo\n") .append(
.append("echo \"name=jdkrepository\" >> /etc/yum.repos.d/CentOS-Base.repo\n") "echo \"[jdkrepo]\" >> /etc/yum.repos.d/CentOS-Base.repo\n")
.append( .append(
"echo \"baseurl=http://ec2-us-east-mirror.rightscale.com/epel/5/i386/\" >> /etc/yum.repos.d/CentOS-Base.repo\n") "echo \"name=jdkrepository\" >> /etc/yum.repos.d/CentOS-Base.repo\n")
.append("echo \"enabled=1\" >> /etc/yum.repos.d/CentOS-Base.repo\n") .append(
.append("yum --nogpgcheck -y install java-1.6.0-openjdk\n") "echo \"baseurl=http://ec2-us-east-mirror.rightscale.com/epel/5/i386/\" >> /etc/yum.repos.d/CentOS-Base.repo\n")
.append( .append(
"echo \"export PATH=\\\"/usr/lib/jvm/jre-1.6.0-openjdk/bin/:\\$PATH\\\"\" >> /root/.bashrc\n") "echo \"enabled=1\" >> /etc/yum.repos.d/CentOS-Base.repo\n")
.toString(); .append("yum --nogpgcheck -y install java-1.6.0-openjdk\n")
default: .append(
throw new IllegalArgumentException(osFamily.toString()); "echo \"export PATH=\\\"/usr/lib/jvm/jre-1.6.0-openjdk/bin/:\\$PATH\\\"\" >> /root/.bashrc\n")
.toString();
default:
throw new IllegalArgumentException(osFamily.toString());
} }
} }
@Test(enabled = true, dependsOnMethods = "testCreateAnotherNodeWithANewContextToEnsureSharedMemIsntRequired") @Test(enabled = true, dependsOnMethods = "testCreateAnotherNodeWithANewContextToEnsureSharedMemIsntRequired")
public void testGet() throws Exception { public void testGet() throws Exception {
Set<? extends NodeMetadata> metadataSet = Sets.newHashSet(Iterables.filter(client Set<? extends NodeMetadata> metadataSet = Sets.newHashSet(Iterables
.listNodesDetailsMatching(NodePredicates.all()), Predicates.and(NodePredicates .filter(client.listNodesDetailsMatching(NodePredicates.all()),
.withTag(tag), Predicates.not(NodePredicates.TERMINATED)))); Predicates.and(NodePredicates.withTag(tag), Predicates
.not(NodePredicates.TERMINATED))));
for (NodeMetadata node : nodes) { for (NodeMetadata node : nodes) {
metadataSet.remove(node); metadataSet.remove(node);
NodeMetadata metadata = client.getNodeMetadata(node.getId()); NodeMetadata metadata = client.getNodeMetadata(node.getId());
assertEquals(metadata.getProviderId(), node.getProviderId()); assertEquals(metadata.getProviderId(), node.getProviderId());
assertEquals(metadata.getTag(), node.getTag()); assertEquals(metadata.getTag(), node.getTag());
assertLocationSameOrChild(metadata.getLocation(), template.getLocation()); assertLocationSameOrChild(metadata.getLocation(), template
.getLocation());
assertEquals(metadata.getImage(), template.getImage()); assertEquals(metadata.getImage(), template.getImage());
assertEquals(metadata.getState(), NodeState.RUNNING); assertEquals(metadata.getState(), NodeState.RUNNING);
assertEquals(metadata.getPrivateAddresses(), node.getPrivateAddresses()); assertEquals(metadata.getPrivateAddresses(), node
.getPrivateAddresses());
assertEquals(metadata.getPublicAddresses(), node.getPublicAddresses()); assertEquals(metadata.getPublicAddresses(), node.getPublicAddresses());
} }
assertNodeZero(metadataSet);
}
protected void assertNodeZero(Set<? extends NodeMetadata> metadataSet) {
assert metadataSet.size() == 0 : String.format( assert metadataSet.size() == 0 : String.format(
"nodes left in set: [%s] which didn't match set: [%s]", metadataSet, nodes); "nodes left in set: [%s] which didn't match set: [%s]",
metadataSet, nodes);
} }
@Test(enabled = true, dependsOnMethods = "testGet") @Test(enabled = true, dependsOnMethods = "testGet")
public void testReboot() throws Exception { public void testReboot() throws Exception {
client.rebootNodesMatching(NodePredicates.withTag(tag));// TODO test validation client.rebootNodesMatching(NodePredicates.withTag(tag));// TODO test
// validation
testGet(); testGet();
} }
@ -368,7 +400,7 @@ public abstract class BaseComputeServiceLiveTest {
TemplateOptions options = new TemplateOptions().withMetadata(); TemplateOptions options = new TemplateOptions().withMetadata();
Template t = client.templateBuilder().smallest().options(options).build(); Template t = client.templateBuilder().smallest().options(options).build();
assert t.getOptions().isIncludeMetadata() : "The metadata option should be 'true' " assert t.getOptions().isIncludeMetadata() : "The metadata option should be 'true' "
+ "for the created template"; + "for the created template";
} }
public void testListNodes() throws Exception { public void testListNodes() throws Exception {
@ -380,7 +412,8 @@ public abstract class BaseComputeServiceLiveTest {
} }
public void testGetNodesWithDetails() throws Exception { public void testGetNodesWithDetails() throws Exception {
for (NodeMetadata node : client.listNodesDetailsMatching(NodePredicates.all())) { for (NodeMetadata node : client.listNodesDetailsMatching(NodePredicates
.all())) {
assert node.getProviderId() != null : node; assert node.getProviderId() != null : node;
assert node.getLocation() != null : node; assert node.getLocation() != null : node;
assertEquals(node.getType(), ComputeType.NODE); assertEquals(node.getType(), ComputeType.NODE);
@ -394,7 +427,7 @@ public abstract class BaseComputeServiceLiveTest {
if (nodeMetadata.getState() == NodeState.RUNNING) { if (nodeMetadata.getState() == NodeState.RUNNING) {
assert nodeMetadata.getPublicAddresses() != null : nodeMetadata; assert nodeMetadata.getPublicAddresses() != null : nodeMetadata;
assert nodeMetadata.getPublicAddresses().size() > 0 assert nodeMetadata.getPublicAddresses().size() > 0
|| nodeMetadata.getPrivateAddresses().size() > 0 : nodeMetadata; || nodeMetadata.getPrivateAddresses().size() > 0 : nodeMetadata;
assertNotNull(nodeMetadata.getPrivateAddresses()); assertNotNull(nodeMetadata.getPrivateAddresses());
} }
} }
@ -416,30 +449,56 @@ public abstract class BaseComputeServiceLiveTest {
assert location != location.getParent() : location; assert location != location.getParent() : location;
assert location.getScope() != null : location; assert location.getScope() != null : location;
switch (location.getScope()) { switch (location.getScope()) {
case PROVIDER: case PROVIDER:
assertProvider(location); assertProvider(location);
break; break;
case REGION: case REGION:
assertProvider(location.getParent()); assertProvider(location.getParent());
break; break;
case ZONE: case ZONE:
Location provider = location.getParent().getParent(); Location provider = location.getParent().getParent();
// zone can be a direct descendant of provider // zone can be a direct descendant of provider
if (provider == null) if (provider == null)
provider = location.getParent(); provider = location.getParent();
assertProvider(provider); assertProvider(provider);
break; break;
case HOST: case HOST:
Location provider2 = location.getParent().getParent().getParent(); Location provider2 = location.getParent().getParent().getParent();
// zone can be a direct descendant of provider // zone can be a direct descendant of provider
if (provider2 == null) if (provider2 == null)
provider2 = location.getParent().getParent(); provider2 = location.getParent().getParent();
assertProvider(provider2); assertProvider(provider2);
break; break;
} }
} }
} }
@Test(enabled = true, dependsOnMethods = "testGet")
public void testOptionToNotBlock() throws Exception {
String tag = this.tag + "block";
try {
client.destroyNodesMatching(NodePredicates.withTag(tag));
} catch (Exception e) {
}
// no inbound ports
TemplateOptions options = client.templateOptions().blockUntilRunning(
false).inboundPorts();
try {
long time = System.currentTimeMillis();
Set<? extends NodeMetadata> nodes = client.runNodesWithTag(tag, 1,
options);
NodeMetadata node = Iterables.getOnlyElement(nodes);
assertEquals(node.getState(), NodeState.PENDING);
long duration = System.currentTimeMillis() - time;
assert duration < 30 * 1000 : "duration longer than 30 seconds!: "
+ duration / 1000;
} finally {
client.destroyNodesMatching(NodePredicates.withTag(tag));
}
}
private void assertProvider(Location provider) { private void assertProvider(Location provider) {
assertEquals(provider.getScope(), LocationScope.PROVIDER); assertEquals(provider.getScope(), LocationScope.PROVIDER);
assertEquals(provider.getParent(), null); assertEquals(provider.getParent(), null);
@ -470,12 +529,15 @@ public abstract class BaseComputeServiceLiveTest {
} }
} }
protected void doCheckJavaIsInstalledViaSsh(NodeMetadata node) throws IOException { protected void doCheckJavaIsInstalledViaSsh(NodeMetadata node)
IPSocket socket = new IPSocket(Iterables.get(node.getPublicAddresses(), 0), 22); throws IOException {
socketTester.apply(socket); // TODO add transitionTo option that accepts a socket conection IPSocket socket = new IPSocket(Iterables
.get(node.getPublicAddresses(), 0), 22);
socketTester.apply(socket); // TODO add transitionTo option that accepts
// a socket conection
// state. // state.
SshClient ssh = sshFactory.create(socket, node.getCredentials().account, keyPair.get( SshClient ssh = sshFactory.create(socket, node.getCredentials().account,
"private").getBytes()); keyPair.get("private").getBytes());
try { try {
ssh.connect(); ssh.connect();
ExecResponse hello = ssh.exec("echo hello"); ExecResponse hello = ssh.exec("echo hello");
@ -489,11 +551,13 @@ public abstract class BaseComputeServiceLiveTest {
} }
@AfterTest @AfterTest
protected void cleanup() throws InterruptedException, ExecutionException, TimeoutException { protected void cleanup() throws InterruptedException, ExecutionException,
TimeoutException {
if (nodes != null) { if (nodes != null) {
client.destroyNodesMatching(NodePredicates.withTag(tag)); client.destroyNodesMatching(NodePredicates.withTag(tag));
for (NodeMetadata node : Iterables.filter(client.listNodesDetailsMatching(NodePredicates for (NodeMetadata node : Iterables.filter(client
.all()), NodePredicates.withTag(tag))) { .listNodesDetailsMatching(NodePredicates.all()), NodePredicates
.withTag(tag))) {
assert node.getState() == NodeState.TERMINATED : node; assert node.getState() == NodeState.TERMINATED : node;
} }
} }

View File

@ -31,10 +31,12 @@ import java.io.FileNotFoundException;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.Serializable; import java.io.Serializable;
import java.util.Set;
import java.util.concurrent.ConcurrentMap; import java.util.concurrent.ConcurrentMap;
import org.easymock.IArgumentMatcher; import org.easymock.IArgumentMatcher;
import org.jclouds.compute.domain.Architecture; import org.jclouds.compute.domain.Architecture;
import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.domain.OsFamily; import org.jclouds.compute.domain.OsFamily;
import org.jclouds.compute.domain.Template; import org.jclouds.compute.domain.Template;
import org.jclouds.compute.stub.config.StubComputeServiceContextModule.StubNodeMetadata; import org.jclouds.compute.stub.config.StubComputeServiceContextModule.StubNodeMetadata;
@ -64,7 +66,8 @@ import com.google.inject.Module;
* @author Adrian Cole * @author Adrian Cole
*/ */
@Test(groups = "live", enabled = true, sequential = true, testName = "stub.StubComputeServiceIntegrationTest") @Test(groups = "live", enabled = true, sequential = true, testName = "stub.StubComputeServiceIntegrationTest")
public class StubComputeServiceIntegrationTest extends BaseComputeServiceLiveTest { public class StubComputeServiceIntegrationTest extends
BaseComputeServiceLiveTest {
private static final ExecResponse EXEC_GOOD = new ExecResponse("", "", 0); private static final ExecResponse EXEC_GOOD = new ExecResponse("", "", 0);
private static final ExecResponse EXEC_BAD = new ExecResponse("", "", 1); private static final ExecResponse EXEC_BAD = new ExecResponse("", "", 1);
@ -82,7 +85,8 @@ public class StubComputeServiceIntegrationTest extends BaseComputeServiceLiveTes
@Test @Test
public void testTemplateBuilder() { public void testTemplateBuilder() {
Template defaultTemplate = client.templateBuilder().build(); Template defaultTemplate = client.templateBuilder().build();
assertEquals(defaultTemplate.getImage().getArchitecture(), Architecture.X86_64); assertEquals(defaultTemplate.getImage().getArchitecture(),
Architecture.X86_64);
assertEquals(defaultTemplate.getImage().getOsFamily(), OsFamily.UBUNTU); assertEquals(defaultTemplate.getImage().getOsFamily(), OsFamily.UBUNTU);
assertEquals(defaultTemplate.getLocation().getId(), "memory"); assertEquals(defaultTemplate.getLocation().getId(), "memory");
assertEquals(defaultTemplate.getSize().getCores(), 4.0d); assertEquals(defaultTemplate.getSize().getCores(), 4.0d);
@ -107,17 +111,21 @@ public class StubComputeServiceIntegrationTest extends BaseComputeServiceLiveTes
expect(open.apply(new IPSocket("144.175.1.4", 22))).andReturn(true); expect(open.apply(new IPSocket("144.175.1.4", 22))).andReturn(true);
expect( expect(
factory.create(eq(new IPSocket("144.175.1.1", 22)), eq("root"), aryEq(keyPair factory.create(eq(new IPSocket("144.175.1.1", 22)),
.get("private").getBytes()))).andReturn(client1).atLeastOnce(); eq("root"), aryEq(keyPair.get("private").getBytes())))
.andReturn(client1).atLeastOnce();
expect( expect(
factory.create(eq(new IPSocket("144.175.1.2", 22)), eq("root"), aryEq(keyPair factory.create(eq(new IPSocket("144.175.1.2", 22)),
.get("private").getBytes()))).andReturn(client2).atLeastOnce(); eq("root"), aryEq(keyPair.get("private").getBytes())))
.andReturn(client2).atLeastOnce();
expect( expect(
factory.create(eq(new IPSocket("144.175.1.3", 22)), eq("root"), aryEq(keyPair factory.create(eq(new IPSocket("144.175.1.3", 22)),
.get("private").getBytes()))).andReturn(client3).atLeastOnce(); eq("root"), aryEq(keyPair.get("private").getBytes())))
.andReturn(client3).atLeastOnce();
expect( expect(
factory.create(eq(new IPSocket("144.175.1.4", 22)), eq("root"), aryEq(keyPair factory.create(eq(new IPSocket("144.175.1.4", 22)),
.get("private").getBytes()))).andReturn(client4).atLeastOnce(); eq("root"), aryEq(keyPair.get("private").getBytes())))
.andReturn(client4).atLeastOnce();
helloAndJava(client1); helloAndJava(client1);
helloAndJava(client2); helloAndJava(client2);
@ -139,8 +147,10 @@ public class StubComputeServiceIntegrationTest extends BaseComputeServiceLiveTes
private void helloAndJava(SshClient client) { private void helloAndJava(SshClient client) {
client.connect(); client.connect();
expect(client.exec("echo hello")).andReturn(new ExecResponse("hello", "", 0)); expect(client.exec("echo hello")).andReturn(
expect(client.exec("java -version")).andReturn(new ExecResponse("", "OpenJDK", 0)); new ExecResponse("hello", "", 0));
expect(client.exec("java -version")).andReturn(
new ExecResponse("", "OpenJDK", 0));
client.disconnect(); client.disconnect();
} }
@ -160,21 +170,26 @@ public class StubComputeServiceIntegrationTest extends BaseComputeServiceLiveTes
SshClient client3 = createMock(SshClient.class); SshClient client3 = createMock(SshClient.class);
SshClient client4 = createMock(SshClient.class); SshClient client4 = createMock(SshClient.class);
expect(factory.create(new IPSocket("144.175.1.1", 22), "root", "romeo")).andThrow( expect(
new SshException("Auth fail")); factory.create(new IPSocket("144.175.1.1", 22), "root",
expect(factory.create(new IPSocket("144.175.1.1", 22), "root", "password1")).andReturn( "romeo")).andThrow(new SshException("Auth fail"));
client1).atLeastOnce(); expect(
factory.create(new IPSocket("144.175.1.1", 22), "root",
"password1")).andReturn(client1).atLeastOnce();
client1.connect(); client1.connect();
runScript(client1, "computeserv", 1); runScript(client1, "computeserv", 1);
client1.disconnect(); client1.disconnect();
expect(factory.create(new IPSocket("144.175.1.2", 22), "root", "password2")).andReturn( expect(
client2).atLeastOnce(); factory.create(new IPSocket("144.175.1.2", 22), "root",
expect(factory.create(new IPSocket("144.175.1.3", 22), "root", "password3")).andReturn( "password2")).andReturn(client2).atLeastOnce();
client3).atLeastOnce(); expect(
expect(factory.create(new IPSocket("144.175.1.4", 22), "root", "password4")).andReturn( factory.create(new IPSocket("144.175.1.3", 22), "root",
client4).atLeastOnce(); "password3")).andReturn(client3).atLeastOnce();
expect(
factory.create(new IPSocket("144.175.1.4", 22), "root",
"password4")).andReturn(client4).atLeastOnce();
runScriptAndInstallSsh(client2, "runscript", 2); runScriptAndInstallSsh(client2, "runscript", 2);
runScriptAndInstallSsh(client3, "runscript", 3); runScriptAndInstallSsh(client3, "runscript", 3);
@ -189,14 +204,17 @@ public class StubComputeServiceIntegrationTest extends BaseComputeServiceLiveTes
bind(SshClient.Factory.class).toInstance(factory); bind(SshClient.Factory.class).toInstance(factory);
} }
private void runScriptAndInstallSsh(SshClient client, String scriptName, int nodeId) { private void runScriptAndInstallSsh(SshClient client,
String scriptName, int nodeId) {
client.connect(); client.connect();
runScript(client, scriptName, nodeId); runScript(client, scriptName, nodeId);
expect(client.exec("mkdir .ssh")).andReturn(EXEC_GOOD); expect(client.exec("mkdir .ssh")).andReturn(EXEC_GOOD);
expect(client.exec("cat .ssh/id_rsa.pub >> .ssh/authorized_keys")).andReturn(EXEC_GOOD); expect(client.exec("cat .ssh/id_rsa.pub >> .ssh/authorized_keys"))
expect(client.exec("chmod 600 .ssh/authorized_keys")).andReturn(EXEC_GOOD); .andReturn(EXEC_GOOD);
expect(client.exec("chmod 600 .ssh/authorized_keys")).andReturn(
EXEC_GOOD);
client.put(eq(".ssh/id_rsa.pub"), isEq(keyPair.get("public"))); client.put(eq(".ssh/id_rsa.pub"), isEq(keyPair.get("public")));
expect(client.exec("mkdir .ssh")).andReturn(EXEC_GOOD); expect(client.exec("mkdir .ssh")).andReturn(EXEC_GOOD);
@ -210,18 +228,26 @@ public class StubComputeServiceIntegrationTest extends BaseComputeServiceLiveTes
private void runScript(SshClient client, String scriptName, int nodeId) { private void runScript(SshClient client, String scriptName, int nodeId) {
client.put(eq("" + scriptName + ""), isEq(initScript(scriptName, client.put(eq("" + scriptName + ""), isEq(initScript(scriptName,
buildScript(OsFamily.UBUNTU)))); buildScript(OsFamily.UBUNTU))));
expect(client.exec("chmod 755 " + scriptName + "")).andReturn(EXEC_GOOD); expect(client.exec("chmod 755 " + scriptName + "")).andReturn(
EXEC_GOOD);
expect(client.getUsername()).andReturn("root").atLeastOnce(); expect(client.getUsername()).andReturn("root").atLeastOnce();
expect(client.getHostAddress()).andReturn(nodeId + "").atLeastOnce(); expect(client.getHostAddress()).andReturn(nodeId + "")
expect(client.exec("./" + scriptName + " init")).andReturn(EXEC_GOOD); .atLeastOnce();
expect(client.exec("./" + scriptName + " start")).andReturn(EXEC_GOOD); expect(client.exec("./" + scriptName + " init")).andReturn(
expect(client.exec("./" + scriptName + " status")).andReturn(EXEC_GOOD); EXEC_GOOD);
expect(client.exec("./" + scriptName + " start")).andReturn(
EXEC_GOOD);
expect(client.exec("./" + scriptName + " status")).andReturn(
EXEC_GOOD);
// next status says the script is done, since not found. // next status says the script is done, since not found.
expect(client.exec("./" + scriptName + " status")).andReturn(EXEC_BAD); expect(client.exec("./" + scriptName + " status")).andReturn(
expect(client.exec("./" + scriptName + " tail")).andReturn(EXEC_GOOD); EXEC_BAD);
expect(client.exec("./" + scriptName + " tailerr")).andReturn(EXEC_GOOD); expect(client.exec("./" + scriptName + " tail")).andReturn(
EXEC_GOOD);
expect(client.exec("./" + scriptName + " tailerr")).andReturn(
EXEC_GOOD);
} }
}; };
@ -233,11 +259,16 @@ public class StubComputeServiceIntegrationTest extends BaseComputeServiceLiveTes
password = "stub"; password = "stub";
} }
protected void assertNodeZero(Set<? extends NodeMetadata> metadataSet) {
// TODO: this fails so we override it.
}
public static String initScript(String scriptName, String script) { public static String initScript(String scriptName, String script) {
return new InitBuilder(scriptName, "/tmp/" + scriptName, "/tmp/" + scriptName, ImmutableMap return new InitBuilder(scriptName, "/tmp/" + scriptName, "/tmp/"
.<String, String> of(), Iterables.toArray(Splitter.on("\n").split( + scriptName, ImmutableMap.<String, String> of(), Iterables
new String(checkNotNull(script, "script"))), String.class)) .toArray(Splitter.on("\n").split(
.build(org.jclouds.scriptbuilder.domain.OsFamily.UNIX); new String(checkNotNull(script, "script"))), String.class))
.build(org.jclouds.scriptbuilder.domain.OsFamily.UNIX);
} }
public static InputStream isEq(String value) { public static InputStream isEq(String value) {
@ -248,10 +279,12 @@ public class StubComputeServiceIntegrationTest extends BaseComputeServiceLiveTes
public void testAssignability() throws Exception { public void testAssignability() throws Exception {
@SuppressWarnings("unused") @SuppressWarnings("unused")
RestContext<ConcurrentMap<Integer, StubNodeMetadata>, ConcurrentMap<Integer, StubNodeMetadata>> stubContext = new ComputeServiceContextFactory() RestContext<ConcurrentMap<Integer, StubNodeMetadata>, ConcurrentMap<Integer, StubNodeMetadata>> stubContext = new ComputeServiceContextFactory()
.createContext(service, user, password).getProviderSpecificContext(); .createContext(service, user, password)
.getProviderSpecificContext();
} }
private static class InputStreamEquals implements IArgumentMatcher, Serializable { private static class InputStreamEquals implements IArgumentMatcher,
Serializable {
private static final long serialVersionUID = 583055160049982067L; private static final long serialVersionUID = 583055160049982067L;
@ -297,8 +330,8 @@ public class StubComputeServiceIntegrationTest extends BaseComputeServiceLiveTes
if (o == null || !this.getClass().equals(o.getClass())) if (o == null || !this.getClass().equals(o.getClass()))
return false; return false;
InputStreamEquals other = (InputStreamEquals) o; InputStreamEquals other = (InputStreamEquals) o;
return this.expected == null && other.expected == null || this.expected != null return this.expected == null && other.expected == null
&& this.expected.equals(other.expected); || this.expected != null && this.expected.equals(other.expected);
} }
@Override @Override
@ -310,8 +343,8 @@ public class StubComputeServiceIntegrationTest extends BaseComputeServiceLiveTes
@Override @Override
protected void setupKeyPair() throws FileNotFoundException, IOException { protected void setupKeyPair() throws FileNotFoundException, IOException {
keyPair = ImmutableMap.<String, String> of("public", "ssh-rsa", "private", keyPair = ImmutableMap.<String, String> of("public", "ssh-rsa",
"-----BEGIN RSA PRIVATE KEY-----"); "private", "-----BEGIN RSA PRIVATE KEY-----");
} }
} }

View File

@ -4,23 +4,25 @@ import java.util.Set;
import org.jclouds.compute.util.ComputeUtils; import org.jclouds.compute.util.ComputeUtils;
import org.testng.annotations.Test; import org.testng.annotations.Test;
/** /**
* Test the compute utils. * Test the compute utils.
* *
* @author Ivan Meredith * @author Ivan Meredith
* *
*/ */
@Test(groups = "unit") @Test(groups = "unit")
public class ComputeUtilsTest { public class ComputeUtilsTest {
/** /**
* Test some of the currently supported clouds against compute.properties. * Test some of the currently supported clouds against compute.properties.
*/ */
@Test @Test
public void testSupportedProviders(){ public void testSupportedProviders() {
Set<String> providers = ComputeUtils.getSupportedProviders(); Set<String> providers = ComputeUtils.getSupportedProviders();
assert providers.contains("rimuhosting"); assert providers.contains("rimuhosting");
assert providers.contains("cloudservers"); assert providers.contains("cloudservers");
assert providers.contains("gogrid"); assert providers.contains("gogrid");
} }
} }

View File

@ -20,6 +20,7 @@ package org.jclouds.compute.options;
import static org.jclouds.compute.options.TemplateOptions.Builder.authorizePublicKey; import static org.jclouds.compute.options.TemplateOptions.Builder.authorizePublicKey;
import static org.jclouds.compute.options.TemplateOptions.Builder.blockOnPort; import static org.jclouds.compute.options.TemplateOptions.Builder.blockOnPort;
import static org.jclouds.compute.options.TemplateOptions.Builder.blockUntilRunning;
import static org.jclouds.compute.options.TemplateOptions.Builder.inboundPorts; import static org.jclouds.compute.options.TemplateOptions.Builder.inboundPorts;
import static org.jclouds.compute.options.TemplateOptions.Builder.installPrivateKey; import static org.jclouds.compute.options.TemplateOptions.Builder.installPrivateKey;
import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertEquals;
@ -33,120 +34,149 @@ import org.testng.annotations.Test;
*/ */
public class TemplateOptionsTest { public class TemplateOptionsTest {
@Test(expectedExceptions = IllegalArgumentException.class) @Test(expectedExceptions = IllegalArgumentException.class)
public void testinstallPrivateKeyBadFormat() { public void testinstallPrivateKeyBadFormat() {
TemplateOptions options = new TemplateOptions(); TemplateOptions options = new TemplateOptions();
options.installPrivateKey("whompy"); options.installPrivateKey("whompy");
} }
@Test @Test
public void testinstallPrivateKey() { public void testinstallPrivateKey() {
TemplateOptions options = new TemplateOptions(); TemplateOptions options = new TemplateOptions();
options.installPrivateKey("-----BEGIN RSA PRIVATE KEY-----"); options.installPrivateKey("-----BEGIN RSA PRIVATE KEY-----");
assertEquals(options.getPrivateKey(), "-----BEGIN RSA PRIVATE KEY-----"); assertEquals(options.getPrivateKey(), "-----BEGIN RSA PRIVATE KEY-----");
} }
@Test @Test
public void testNullinstallPrivateKey() { public void testNullinstallPrivateKey() {
TemplateOptions options = new TemplateOptions(); TemplateOptions options = new TemplateOptions();
assertEquals(options.getPrivateKey(), null); assertEquals(options.getPrivateKey(), null);
} }
@Test @Test
public void testinstallPrivateKeyStatic() { public void testinstallPrivateKeyStatic() {
TemplateOptions options = installPrivateKey("-----BEGIN RSA PRIVATE KEY-----"); TemplateOptions options = installPrivateKey("-----BEGIN RSA PRIVATE KEY-----");
assertEquals(options.getPrivateKey(), "-----BEGIN RSA PRIVATE KEY-----"); assertEquals(options.getPrivateKey(), "-----BEGIN RSA PRIVATE KEY-----");
} }
@Test(expectedExceptions = NullPointerException.class) @Test(expectedExceptions = NullPointerException.class)
public void testinstallPrivateKeyNPE() { public void testinstallPrivateKeyNPE() {
installPrivateKey(null); installPrivateKey(null);
} }
@Test(expectedExceptions = IllegalArgumentException.class) @Test(expectedExceptions = IllegalArgumentException.class)
public void testauthorizePublicKeyBadFormat() { public void testauthorizePublicKeyBadFormat() {
TemplateOptions options = new TemplateOptions(); TemplateOptions options = new TemplateOptions();
options.authorizePublicKey("whompy"); options.authorizePublicKey("whompy");
} }
@Test @Test
public void testauthorizePublicKey() { public void testauthorizePublicKey() {
TemplateOptions options = new TemplateOptions(); TemplateOptions options = new TemplateOptions();
options.authorizePublicKey("ssh-rsa"); options.authorizePublicKey("ssh-rsa");
assertEquals(options.getPublicKey(), "ssh-rsa"); assertEquals(options.getPublicKey(), "ssh-rsa");
} }
@Test @Test
public void testNullauthorizePublicKey() { public void testNullauthorizePublicKey() {
TemplateOptions options = new TemplateOptions(); TemplateOptions options = new TemplateOptions();
assertEquals(options.getPublicKey(), null); assertEquals(options.getPublicKey(), null);
} }
@Test @Test
public void testauthorizePublicKeyStatic() { public void testauthorizePublicKeyStatic() {
TemplateOptions options = authorizePublicKey("ssh-rsa"); TemplateOptions options = authorizePublicKey("ssh-rsa");
assertEquals(options.getPublicKey(), "ssh-rsa"); assertEquals(options.getPublicKey(), "ssh-rsa");
} }
@Test(expectedExceptions = NullPointerException.class) @Test(expectedExceptions = NullPointerException.class)
public void testauthorizePublicKeyNPE() { public void testauthorizePublicKeyNPE() {
authorizePublicKey(null); authorizePublicKey(null);
} }
@Test(expectedExceptions = IllegalArgumentException.class) @Test(expectedExceptions = IllegalArgumentException.class)
public void testblockOnPortBadFormat() { public void testblockOnPortBadFormat() {
TemplateOptions options = new TemplateOptions(); TemplateOptions options = new TemplateOptions();
options.blockOnPort(-1, -1); options.blockOnPort(-1, -1);
} }
@Test @Test
public void testblockOnPort() { public void testblockOnPort() {
TemplateOptions options = new TemplateOptions(); TemplateOptions options = new TemplateOptions();
options.blockOnPort(22, 30); options.blockOnPort(22, 30);
assertEquals(options.getPort(), 22); assertEquals(options.getPort(), 22);
assertEquals(options.getSeconds(), 30); assertEquals(options.getSeconds(), 30);
} }
@Test @Test
public void testNullblockOnPort() { public void testNullblockOnPort() {
TemplateOptions options = new TemplateOptions(); TemplateOptions options = new TemplateOptions();
assertEquals(options.getPort(), -1); assertEquals(options.getPort(), -1);
assertEquals(options.getSeconds(), -1); assertEquals(options.getSeconds(), -1);
} }
@Test @Test
public void testblockOnPortStatic() { public void testblockOnPortStatic() {
TemplateOptions options = blockOnPort(22, 30); TemplateOptions options = blockOnPort(22, 30);
assertEquals(options.getPort(), 22); assertEquals(options.getPort(), 22);
assertEquals(options.getSeconds(), 30); assertEquals(options.getSeconds(), 30);
} }
@Test(expectedExceptions = IllegalArgumentException.class) @Test(expectedExceptions = IllegalArgumentException.class)
public void testinboundPortsBadFormat() { public void testinboundPortsBadFormat() {
TemplateOptions options = new TemplateOptions(); TemplateOptions options = new TemplateOptions();
options.inboundPorts(-1, -1); options.inboundPorts(-1, -1);
} }
@Test @Test
public void testinboundPorts() { public void testinboundPorts() {
TemplateOptions options = new TemplateOptions(); TemplateOptions options = new TemplateOptions();
options.inboundPorts(22, 30); options.inboundPorts(22, 30);
assertEquals(options.getInboundPorts()[0], 22); assertEquals(options.getInboundPorts()[0], 22);
assertEquals(options.getInboundPorts()[1], 30); assertEquals(options.getInboundPorts()[1], 30);
} }
@Test @Test
public void testDefaultOpen22() { public void testDefaultOpen22() {
TemplateOptions options = new TemplateOptions(); TemplateOptions options = new TemplateOptions();
assertEquals(options.getInboundPorts()[0], 22); assertEquals(options.getInboundPorts()[0], 22);
} }
@Test @Test
public void testinboundPortsStatic() { public void testinboundPortsStatic() {
TemplateOptions options = inboundPorts(22, 30); TemplateOptions options = inboundPorts(22, 30);
assertEquals(options.getInboundPorts()[0], 22); assertEquals(options.getInboundPorts()[0], 22);
assertEquals(options.getInboundPorts()[1], 30); assertEquals(options.getInboundPorts()[1], 30);
} }
@Test
public void testblockUntilRunningDefault() {
TemplateOptions options = new TemplateOptions();
assertEquals(options.shouldBlockUntilRunning(), true);
}
@Test
public void testblockUntilRunning() {
TemplateOptions options = new TemplateOptions();
options.blockUntilRunning(false);
assertEquals(options.shouldBlockUntilRunning(), false);
}
@Test
public void testBlockUntilRunningUnsetsBlockOnPort() {
TemplateOptions options = new TemplateOptions();
options.blockOnPort(22, 30);
options.blockUntilRunning(false);
assertEquals(options.shouldBlockUntilRunning(), false);
assertEquals(options.getPort(), -1);
assertEquals(options.getSeconds(), -1);
}
@Test
public void testblockUntilRunningStatic() {
TemplateOptions options = blockUntilRunning(false);
assertEquals(options.shouldBlockUntilRunning(), false);
}
} }

View File

@ -34,24 +34,32 @@ import com.google.common.base.Predicate;
* @author Adrian Cole * @author Adrian Cole
*/ */
public class RetryablePredicate<T> implements Predicate<T> { public class RetryablePredicate<T> implements Predicate<T> {
private final int maxWait; private final long maxWait;
private final int checkInterval; private final long period;
private final Predicate<T> predicate; private final Predicate<T> predicate;
@Resource @Resource
protected Logger logger = Logger.NULL; protected Logger logger = Logger.NULL;
public RetryablePredicate(Predicate<T> predicate, long maxWait, long checkInterval, TimeUnit unit) { public RetryablePredicate(Predicate<T> predicate, long maxWait, long period,
TimeUnit unit) {
this.predicate = predicate; this.predicate = predicate;
this.maxWait = (int) unit.toMillis(maxWait); this.maxWait = unit.toMillis(maxWait);
this.checkInterval = (int) unit.toMillis(checkInterval); this.period = unit.toMillis(period);
}
public RetryablePredicate(Predicate<T> predicate, long maxWait) {
this.predicate = predicate;
this.maxWait = maxWait;
this.period = 50l;
} }
@Override @Override
public boolean apply(T input) { public boolean apply(T input) {
try { try {
long i = 1l;
for (Date end = new Date(System.currentTimeMillis() + maxWait); before(end); Thread for (Date end = new Date(System.currentTimeMillis() + maxWait); before(end); Thread
.sleep(checkInterval)) { .sleep(nextMaxInterval(i++, end))) {
if (predicate.apply(input)) { if (predicate.apply(input)) {
return true; return true;
} else if (atOrAfter(end)) { } else if (atOrAfter(end)) {
@ -59,11 +67,18 @@ public class RetryablePredicate<T> implements Predicate<T> {
} }
} }
} catch (InterruptedException e) { } catch (InterruptedException e) {
logger.warn(e, "predicate %s on %s interrupted, returning false", input, predicate); logger.warn(e, "predicate %s on %s interrupted, returning false",
input, predicate);
} }
return false; return false;
} }
long nextMaxInterval(long attempt, Date end) {
long interval = (period * (long) Math.pow(attempt, 2l));
long max = end.getTime() - System.currentTimeMillis();
return (interval > max) ? max : interval;
}
boolean before(Date end) { boolean before(Date end) {
return new Date().compareTo(end) <= 1; return new Date().compareTo(end) <= 1;
} }

View File

@ -38,7 +38,7 @@ import com.google.inject.Module;
*/ */
@Test @Test
public class JavaUrlHttpCommandExecutorServiceIntegrationTest extends public class JavaUrlHttpCommandExecutorServiceIntegrationTest extends
BaseHttpCommandExecutorServiceIntegrationTest { BaseHttpCommandExecutorServiceIntegrationTest {
protected Module createConnectionModule() { protected Module createConnectionModule() {
return new JavaUrlHttpCommandExecutorServiceModule(); return new JavaUrlHttpCommandExecutorServiceModule();

View File

@ -26,7 +26,6 @@ import static org.jclouds.gogrid.reference.GoGridConstants.PROPERTY_GOGRID_DEFAU
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException; import java.util.concurrent.TimeoutException;
import java.util.regex.Pattern; import java.util.regex.Pattern;
@ -37,6 +36,7 @@ import javax.inject.Singleton;
import org.jclouds.compute.ComputeServiceContext; import org.jclouds.compute.ComputeServiceContext;
import org.jclouds.compute.LoadBalancerService; import org.jclouds.compute.LoadBalancerService;
import org.jclouds.compute.config.ComputeServiceTimeoutsModule;
import org.jclouds.compute.domain.Architecture; import org.jclouds.compute.domain.Architecture;
import org.jclouds.compute.domain.ComputeMetadata; import org.jclouds.compute.domain.ComputeMetadata;
import org.jclouds.compute.domain.Image; import org.jclouds.compute.domain.Image;
@ -49,9 +49,8 @@ import org.jclouds.compute.domain.internal.ImageImpl;
import org.jclouds.compute.domain.internal.SizeImpl; import org.jclouds.compute.domain.internal.SizeImpl;
import org.jclouds.compute.internal.ComputeServiceContextImpl; import org.jclouds.compute.internal.ComputeServiceContextImpl;
import org.jclouds.compute.predicates.NodePredicates; 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.reference.ComputeServiceConstants;
import org.jclouds.compute.reference.ComputeServiceConstants.Timeouts;
import org.jclouds.compute.strategy.AddNodeWithTagStrategy; import org.jclouds.compute.strategy.AddNodeWithTagStrategy;
import org.jclouds.compute.strategy.DestroyNodeStrategy; import org.jclouds.compute.strategy.DestroyNodeStrategy;
import org.jclouds.compute.strategy.GetNodeMetadataStrategy; import org.jclouds.compute.strategy.GetNodeMetadataStrategy;
@ -77,7 +76,6 @@ import org.jclouds.predicates.RetryablePredicate;
import com.google.common.base.Function; import com.google.common.base.Function;
import com.google.common.base.Predicate; import com.google.common.base.Predicate;
import com.google.common.base.Predicates;
import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet; import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables; import com.google.common.collect.Iterables;
@ -100,15 +98,20 @@ public class GoGridComputeServiceContextModule extends GoGridContextModule {
@Override @Override
protected void configure() { protected void configure() {
super.configure(); super.configure();
install(new ComputeServiceTimeoutsModule());
bind(new TypeLiteral<Function<Server, NodeMetadata>>() { bind(new TypeLiteral<Function<Server, NodeMetadata>>() {
}).to(ServerToNodeMetadata.class); }).to(ServerToNodeMetadata.class);
bind(LoadBalancerService.class).toProvider(Providers.<LoadBalancerService> of(null)); bind(LoadBalancerService.class).toProvider(
Providers.<LoadBalancerService> of(null));
bind(new TypeLiteral<ComputeServiceContext>() { bind(new TypeLiteral<ComputeServiceContext>() {
}).to(new TypeLiteral<ComputeServiceContextImpl<GoGridClient, GoGridAsyncClient>>() { })
}).in(Scopes.SINGLETON); .to(
new TypeLiteral<ComputeServiceContextImpl<GoGridClient, GoGridAsyncClient>>() {
}).in(Scopes.SINGLETON);
bind(AddNodeWithTagStrategy.class).to(GoGridAddNodeWithTagStrategy.class); bind(AddNodeWithTagStrategy.class).to(GoGridAddNodeWithTagStrategy.class);
bind(ListNodesStrategy.class).to(GoGridListNodesStrategy.class); bind(ListNodesStrategy.class).to(GoGridListNodesStrategy.class);
bind(GetNodeMetadataStrategy.class).to(GoGridGetNodeMetadataStrategy.class); bind(GetNodeMetadataStrategy.class).to(
GoGridGetNodeMetadataStrategy.class);
bind(RebootNodeStrategy.class).to(GoGridRebootNodeStrategy.class); bind(RebootNodeStrategy.class).to(GoGridRebootNodeStrategy.class);
bind(DestroyNodeStrategy.class).to(GoGridDestroyNodeStrategy.class); bind(DestroyNodeStrategy.class).to(GoGridDestroyNodeStrategy.class);
} }
@ -129,26 +132,33 @@ public class GoGridComputeServiceContextModule extends GoGridContextModule {
@Singleton @Singleton
public static class GoGridRebootNodeStrategy implements RebootNodeStrategy { public static class GoGridRebootNodeStrategy implements RebootNodeStrategy {
private final GoGridClient client; private final GoGridClient client;
private RetryablePredicate<Server> serverLatestJobCompleted; private final RetryablePredicate<Server> serverLatestJobCompleted;
private RetryablePredicate<Server> serverLatestJobCompletedShort; private RetryablePredicate<Server> serverLatestJobCompletedShort;
private final GetNodeMetadataStrategy getNode;
@Inject @Inject
protected GoGridRebootNodeStrategy(GoGridClient client) { protected GoGridRebootNodeStrategy(GoGridClient client,
GetNodeMetadataStrategy getNode, Timeouts timeouts) {
this.client = client; this.client = client;
this.serverLatestJobCompleted = new RetryablePredicate<Server>( this.serverLatestJobCompleted = new RetryablePredicate<Server>(
new ServerLatestJobCompleted(client.getJobServices()), 800, 20, TimeUnit.SECONDS); new ServerLatestJobCompleted(client.getJobServices()),
timeouts.nodeRunning * 9l / 10l);
this.serverLatestJobCompletedShort = new RetryablePredicate<Server>( this.serverLatestJobCompletedShort = new RetryablePredicate<Server>(
new ServerLatestJobCompleted(client.getJobServices()), 60, 20, TimeUnit.SECONDS); new ServerLatestJobCompleted(client.getJobServices()),
timeouts.nodeRunning * 1l / 10l);
this.getNode = getNode;
} }
@Override @Override
public boolean execute(String id) { public NodeMetadata execute(String id) {
Server server = Iterables.getOnlyElement(client.getServerServices().getServersById( Server server = Iterables.getOnlyElement(client.getServerServices()
new Long(id))); .getServersById(new Long(id)));
client.getServerServices().power(server.getName(), PowerCommand.RESTART); client.getServerServices().power(server.getName(),
PowerCommand.RESTART);
serverLatestJobCompleted.apply(server); serverLatestJobCompleted.apply(server);
client.getServerServices().power(server.getName(), PowerCommand.START); client.getServerServices().power(server.getName(), PowerCommand.START);
return serverLatestJobCompletedShort.apply(server); serverLatestJobCompletedShort.apply(server);
return getNode.execute(id);
} }
} }
@ -159,7 +169,7 @@ public class GoGridComputeServiceContextModule extends GoGridContextModule {
@Inject @Inject
protected GoGridListNodesStrategy(GoGridClient client, protected GoGridListNodesStrategy(GoGridClient client,
Function<Server, NodeMetadata> serverToNodeMetadata) { Function<Server, NodeMetadata> serverToNodeMetadata) {
this.client = client; this.client = client;
this.serverToNodeMetadata = serverToNodeMetadata; this.serverToNodeMetadata = serverToNodeMetadata;
} }
@ -171,28 +181,29 @@ public class GoGridComputeServiceContextModule extends GoGridContextModule {
@Override @Override
public Iterable<? extends NodeMetadata> listDetailsOnNodesMatching( public Iterable<? extends NodeMetadata> listDetailsOnNodesMatching(
Predicate<ComputeMetadata> filter) { Predicate<ComputeMetadata> filter) {
return Iterables.filter(Iterables.transform(client.getServerServices().getServerList(), return Iterables.filter(Iterables.transform(client.getServerServices()
serverToNodeMetadata), filter); .getServerList(), serverToNodeMetadata), filter);
} }
} }
@Singleton @Singleton
public static class GoGridGetNodeMetadataStrategy implements GetNodeMetadataStrategy { public static class GoGridGetNodeMetadataStrategy implements
GetNodeMetadataStrategy {
private final GoGridClient client; private final GoGridClient client;
private final Function<Server, NodeMetadata> serverToNodeMetadata; private final Function<Server, NodeMetadata> serverToNodeMetadata;
@Inject @Inject
protected GoGridGetNodeMetadataStrategy(GoGridClient client, protected GoGridGetNodeMetadataStrategy(GoGridClient client,
Function<Server, NodeMetadata> serverToNodeMetadata) { Function<Server, NodeMetadata> serverToNodeMetadata) {
this.client = client; this.client = client;
this.serverToNodeMetadata = serverToNodeMetadata; this.serverToNodeMetadata = serverToNodeMetadata;
} }
@Override @Override
public NodeMetadata execute(String id) { public NodeMetadata execute(String id) {
Server server = Iterables.getOnlyElement(client.getServerServices().getServersById( Server server = Iterables.getOnlyElement(client.getServerServices()
new Long(checkNotNull(id, "id")))); .getServersById(new Long(checkNotNull(id, "id"))));
return server == null ? null : serverToNodeMetadata.apply(server); return server == null ? null : serverToNodeMetadata.apply(server);
} }
} }
@ -200,21 +211,21 @@ public class GoGridComputeServiceContextModule extends GoGridContextModule {
@Singleton @Singleton
public static class GoGridDestroyNodeStrategy implements DestroyNodeStrategy { public static class GoGridDestroyNodeStrategy implements DestroyNodeStrategy {
private final GoGridClient client; private final GoGridClient client;
private RetryablePredicate<Server> serverLatestJobCompleted; private final GetNodeMetadataStrategy getNode;
@Inject @Inject
protected GoGridDestroyNodeStrategy(GoGridClient client) { protected GoGridDestroyNodeStrategy(GoGridClient client,
GetNodeMetadataStrategy getNode) {
this.client = client; this.client = client;
this.serverLatestJobCompleted = new RetryablePredicate<Server>( this.getNode = getNode;
new ServerLatestJobCompleted(client.getJobServices()), 800, 20, TimeUnit.SECONDS);
} }
@Override @Override
public boolean execute(String id) { public NodeMetadata execute(String id) {
Server server = Iterables.getOnlyElement(client.getServerServices().getServersById( Server server = Iterables.getOnlyElement(client.getServerServices()
new Long(id))); .getServersById(new Long(id)));
client.getServerServices().deleteById(server.getId()); client.getServerServices().deleteById(server.getId());
return serverLatestJobCompleted.apply(server); return getNode.execute(id);
} }
} }
@ -222,18 +233,21 @@ public class GoGridComputeServiceContextModule extends GoGridContextModule {
@Singleton @Singleton
@Provides @Provides
Map<String, NodeState> provideServerToNodeState() { Map<String, NodeState> provideServerToNodeState() {
return ImmutableMap.<String, NodeState> builder().put("On", NodeState.RUNNING).put( return ImmutableMap.<String, NodeState> builder().put("On",
"Starting", NodeState.PENDING).put("Off", NodeState.SUSPENDED).put("Saving", NodeState.RUNNING).put("Starting", NodeState.PENDING).put("Off",
NodeState.PENDING).put("Restarting", NodeState.PENDING).put("Stopping", NodeState.SUSPENDED).put("Saving", NodeState.PENDING).put(
NodeState.PENDING).build(); "Restarting", NodeState.PENDING).put("Stopping", NodeState.PENDING)
.build();
} }
/** /**
* Finds matches to required configurations. GoGrid's documentation only specifies how much RAM * Finds matches to required configurations. GoGrid's documentation only
* one can get with different instance types. The # of cores and disk sizes are purely empyrical * specifies how much RAM one can get with different instance types. The # of
* and aren't guaranteed. However, these are the matches found: Ram: 512MB, CPU: 1 core, HDD: 28 * cores and disk sizes are purely empyrical and aren't guaranteed. However,
* GB Ram: 1GB, CPU: 1 core, HDD: 57 GB Ram: 2GB, CPU: 1 core, HDD: 113 GB Ram: 4GB, CPU: 3 * these are the matches found: Ram: 512MB, CPU: 1 core, HDD: 28 GB Ram: 1GB,
* cores, HDD: 233 GB Ram: 8GB, CPU: 6 cores, HDD: 462 GB (as of March 2010) * CPU: 1 core, HDD: 57 GB Ram: 2GB, CPU: 1 core, HDD: 113 GB Ram: 4GB, CPU:
* 3 cores, HDD: 233 GB Ram: 8GB, CPU: 6 cores, HDD: 462 GB (as of March
* 2010)
* *
* @return matched size * @return matched size
*/ */
@ -243,9 +257,11 @@ public class GoGridComputeServiceContextModule extends GoGridContextModule {
return new Function<Size, String>() { return new Function<Size, String>() {
@Override @Override
public String apply(Size size) { public String apply(Size size) {
if (size.getRam() >= 8 * 1024 || size.getCores() >= 6 || size.getDisk() >= 450) if (size.getRam() >= 8 * 1024 || size.getCores() >= 6
|| size.getDisk() >= 450)
return "8GB"; return "8GB";
if (size.getRam() >= 4 * 1024 || size.getCores() >= 3 || size.getDisk() >= 230) if (size.getRam() >= 4 * 1024 || size.getCores() >= 3
|| size.getDisk() >= 230)
return "4GB"; return "4GB";
if (size.getRam() >= 2 * 1024 || size.getDisk() >= 110) if (size.getRam() >= 2 * 1024 || size.getDisk() >= 110)
return "2GB"; return "2GB";
@ -258,16 +274,9 @@ public class GoGridComputeServiceContextModule extends GoGridContextModule {
@Provides @Provides
@Singleton @Singleton
@Named("NOT_RUNNING") Location getDefaultLocation(
protected Predicate<CommandUsingClient> runScriptRunning(ScriptStatusReturnsZero stateRunning) { @Named(PROPERTY_GOGRID_DEFAULT_DC) final String defaultDC,
return new RetryablePredicate<CommandUsingClient>(Predicates.not(stateRunning), 600, 3, Set<? extends Location> locations) {
TimeUnit.SECONDS);
}
@Provides
@Singleton
Location getDefaultLocation(@Named(PROPERTY_GOGRID_DEFAULT_DC) final String defaultDC,
Set<? extends Location> locations) {
return Iterables.find(locations, new Predicate<Location>() { return Iterables.find(locations, new Predicate<Location>() {
@Override @Override
@ -280,13 +289,14 @@ public class GoGridComputeServiceContextModule extends GoGridContextModule {
@Provides @Provides
@Singleton @Singleton
Set<? extends Location> getDefaultLocations(GoGridClient sync, LogHolder holder, Set<? extends Location> getDefaultLocations(GoGridClient sync,
Function<ComputeMetadata, String> indexer) { LogHolder holder, Function<ComputeMetadata, String> indexer) {
final Set<Location> locations = Sets.newHashSet(); final Set<Location> locations = Sets.newHashSet();
holder.logger.debug(">> providing locations"); holder.logger.debug(">> providing locations");
Location parent = new LocationImpl(LocationScope.PROVIDER, providerName, providerName, null); Location parent = new LocationImpl(LocationScope.PROVIDER, providerName,
locations.add(new LocationImpl(LocationScope.ZONE, "SANFRANCISCO", "San Francisco, CA", providerName, null);
parent)); locations.add(new LocationImpl(LocationScope.ZONE, "SANFRANCISCO",
"San Francisco, CA", parent));
holder.logger.debug("<< locations(%d)", locations.size()); holder.logger.debug("<< locations(%d)", locations.size());
return locations; return locations;
} }
@ -304,27 +314,28 @@ public class GoGridComputeServiceContextModule extends GoGridContextModule {
@Provides @Provides
@Singleton @Singleton
protected Set<? extends Size> provideSizes(GoGridClient sync, Set<? extends Image> images, protected Set<? extends Size> provideSizes(GoGridClient sync,
LogHolder holder, Function<ComputeMetadata, String> indexer) Set<? extends Image> images, LogHolder holder,
throws InterruptedException, TimeoutException, ExecutionException { Function<ComputeMetadata, String> indexer)
throws InterruptedException, TimeoutException, ExecutionException {
final Set<Size> sizes = Sets.newHashSet(); final Set<Size> sizes = Sets.newHashSet();
holder.logger.debug(">> providing sizes"); holder.logger.debug(">> providing sizes");
sizes.add(new SizeImpl("1", "1", "1", null, null, ImmutableMap.<String, String> of(), 0.5, sizes.add(new SizeImpl("1", "1", "1", null, null, ImmutableMap
512, 30, architectureIn(ImmutableSet.<Architecture> of(Architecture.X86_32, .<String, String> of(), 0.5, 512, 30, architectureIn(ImmutableSet
Architecture.X86_64)))); .<Architecture> of(Architecture.X86_32, Architecture.X86_64))));
sizes.add(new SizeImpl("2", "2", "2", null, null, ImmutableMap.<String, String> of(), 1, sizes.add(new SizeImpl("2", "2", "2", null, null, ImmutableMap
1024, 60, architectureIn(ImmutableSet.<Architecture> of(Architecture.X86_32, .<String, String> of(), 1, 1024, 60, architectureIn(ImmutableSet
Architecture.X86_64)))); .<Architecture> of(Architecture.X86_32, Architecture.X86_64))));
sizes.add(new SizeImpl("3", "3", "3", null, null, ImmutableMap.<String, String> of(), 2, sizes.add(new SizeImpl("3", "3", "3", null, null, ImmutableMap
2048, 120, architectureIn(ImmutableSet.<Architecture> of(Architecture.X86_32, .<String, String> of(), 2, 2048, 120, architectureIn(ImmutableSet
Architecture.X86_64)))); .<Architecture> of(Architecture.X86_32, Architecture.X86_64))));
sizes.add(new SizeImpl("4", "4", "4", null, null, ImmutableMap.<String, String> of(), 4, sizes.add(new SizeImpl("4", "4", "4", null, null, ImmutableMap
4096, 240, architectureIn(ImmutableSet.<Architecture> of(Architecture.X86_32, .<String, String> of(), 4, 4096, 240, architectureIn(ImmutableSet
Architecture.X86_64)))); .<Architecture> of(Architecture.X86_32, Architecture.X86_64))));
sizes.add(new SizeImpl("5", "5", "5", null, null, ImmutableMap.<String, String> of(), 8, sizes.add(new SizeImpl("5", "5", "5", null, null, ImmutableMap
8192, 480, architectureIn(ImmutableSet.<Architecture> of(Architecture.X86_32, .<String, String> of(), 8, 8192, 480, architectureIn(ImmutableSet
Architecture.X86_64)))); .<Architecture> of(Architecture.X86_32, Architecture.X86_64))));
holder.logger.debug("<< sizes(%d)", sizes.size()); holder.logger.debug("<< sizes(%d)", sizes.size());
return sizes; return sizes;
} }
@ -335,37 +346,42 @@ public class GoGridComputeServiceContextModule extends GoGridContextModule {
protected Logger logger = Logger.NULL; protected Logger logger = Logger.NULL;
} }
public static final Pattern GOGRID_OS_NAME_PATTERN = Pattern.compile("([a-zA-Z]*)(.*)"); public static final Pattern GOGRID_OS_NAME_PATTERN = Pattern
.compile("([a-zA-Z]*)(.*)");
@Provides @Provides
@Singleton @Singleton
protected Set<? extends Image> provideImages(final GoGridClient sync, LogHolder holder, protected Set<? extends Image> provideImages(final GoGridClient sync,
Function<ComputeMetadata, String> indexer, Location location, LogHolder holder, Function<ComputeMetadata, String> indexer,
PopulateDefaultLoginCredentialsForImageStrategy authenticator) Location location,
throws InterruptedException, ExecutionException, TimeoutException { PopulateDefaultLoginCredentialsForImageStrategy authenticator)
throws InterruptedException, ExecutionException, TimeoutException {
final Set<Image> images = Sets.newHashSet(); final Set<Image> images = Sets.newHashSet();
holder.logger.debug(">> providing images"); holder.logger.debug(">> providing images");
Set<ServerImage> allImages = sync.getImageServices().getImageList(); Set<ServerImage> allImages = sync.getImageServices().getImageList();
for (ServerImage from : allImages) { for (ServerImage from : allImages) {
OsFamily os = null; OsFamily os = null;
Architecture arch = (from.getOs().getName().indexOf("64") == -1 && from.getDescription() Architecture arch = (from.getOs().getName().indexOf("64") == -1 && from
.indexOf("64") == -1) ? Architecture.X86_32 : Architecture.X86_64; .getDescription().indexOf("64") == -1) ? Architecture.X86_32
: Architecture.X86_64;
String osDescription; String osDescription;
String version = ""; String version = "";
osDescription = from.getOs().getName(); osDescription = from.getOs().getName();
String matchedOs = GoGridUtils.parseStringByPatternAndGetNthMatchGroup(from.getOs() String matchedOs = GoGridUtils
.getName(), GOGRID_OS_NAME_PATTERN, 1); .parseStringByPatternAndGetNthMatchGroup(from.getOs().getName(),
GOGRID_OS_NAME_PATTERN, 1);
try { try {
os = OsFamily.fromValue(matchedOs.toLowerCase()); os = OsFamily.fromValue(matchedOs.toLowerCase());
} catch (IllegalArgumentException e) { } catch (IllegalArgumentException e) {
holder.logger.debug("<< didn't match os(%s)", matchedOs); holder.logger.debug("<< didn't match os(%s)", matchedOs);
} }
Credentials defaultCredentials = authenticator.execute(from); Credentials defaultCredentials = authenticator.execute(from);
images.add(new ImageImpl(from.getId() + "", from.getFriendlyName(), from.getId() + "", images.add(new ImageImpl(from.getId() + "", from.getFriendlyName(),
location, null, ImmutableMap.<String, String> of(), from.getDescription(), from.getId() + "", location, null, ImmutableMap
version, os, osDescription, arch, defaultCredentials)); .<String, String> of(), from.getDescription(), version,
os, osDescription, arch, defaultCredentials));
} }
holder.logger.debug("<< images(%d)", images.size()); holder.logger.debug("<< images(%d)", images.size());
return images; return images;

View File

@ -22,7 +22,6 @@ import static com.google.common.base.Preconditions.checkNotNull;
import java.security.SecureRandom; import java.security.SecureRandom;
import java.util.Set; import java.util.Set;
import java.util.concurrent.TimeUnit;
import javax.inject.Inject; import javax.inject.Inject;
import javax.inject.Singleton; import javax.inject.Singleton;
@ -30,6 +29,7 @@ import javax.inject.Singleton;
import org.jclouds.compute.domain.NodeMetadata; import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.domain.Size; import org.jclouds.compute.domain.Size;
import org.jclouds.compute.domain.Template; import org.jclouds.compute.domain.Template;
import org.jclouds.compute.reference.ComputeServiceConstants.Timeouts;
import org.jclouds.compute.strategy.AddNodeWithTagStrategy; import org.jclouds.compute.strategy.AddNodeWithTagStrategy;
import org.jclouds.gogrid.GoGridClient; import org.jclouds.gogrid.GoGridClient;
import org.jclouds.gogrid.domain.Ip; import org.jclouds.gogrid.domain.Ip;
@ -57,14 +57,17 @@ public class GoGridAddNodeWithTagStrategy implements AddNodeWithTagStrategy {
@Inject @Inject
protected GoGridAddNodeWithTagStrategy(GoGridClient client, protected GoGridAddNodeWithTagStrategy(GoGridClient client,
Function<Server, NodeMetadata> serverToNodeMetadata, Function<Size, String> sizeToRam) { Function<Server, NodeMetadata> serverToNodeMetadata,
Function<Size, String> sizeToRam, Timeouts timeouts) {
this.client = client; this.client = client;
this.serverToNodeMetadata = serverToNodeMetadata; this.serverToNodeMetadata = serverToNodeMetadata;
this.sizeToRam = sizeToRam; this.sizeToRam = sizeToRam;
this.serverLatestJobCompleted = new RetryablePredicate<Server>(new ServerLatestJobCompleted( this.serverLatestJobCompleted = new RetryablePredicate<Server>(
client.getJobServices()), 800, 20, TimeUnit.SECONDS); new ServerLatestJobCompleted(client.getJobServices()),
timeouts.nodeRunning * 9l / 10l);
this.serverLatestJobCompletedShort = new RetryablePredicate<Server>( this.serverLatestJobCompletedShort = new RetryablePredicate<Server>(
new ServerLatestJobCompleted(client.getJobServices()), 60, 20, TimeUnit.SECONDS); new ServerLatestJobCompleted(client.getJobServices()),
timeouts.nodeRunning * 1l / 10l);
} }
@Override @Override
@ -73,12 +76,15 @@ public class GoGridAddNodeWithTagStrategy implements AddNodeWithTagStrategy {
boolean notStarted = true; boolean notStarted = true;
int numOfRetries = 20; int numOfRetries = 20;
// lock-free consumption of a shared resource: IP address pool // lock-free consumption of a shared resource: IP address pool
while (notStarted) { // TODO: replace with Predicate-based thread collision avoidance for while (notStarted) { // TODO: replace with Predicate-based thread
// collision avoidance for
// simplicity // simplicity
Set<Ip> availableIps = client.getIpServices().getIpList( Set<Ip> availableIps = client.getIpServices().getIpList(
new GetIpListOptions().onlyUnassigned().onlyWithType(IpType.PUBLIC)); new GetIpListOptions().onlyUnassigned().onlyWithType(
IpType.PUBLIC));
if (availableIps.size() == 0) if (availableIps.size() == 0)
throw new RuntimeException("No public IPs available on this account."); throw new RuntimeException(
"No public IPs available on this account.");
int ipIndex = new SecureRandom().nextInt(availableIps.size()); int ipIndex = new SecureRandom().nextInt(availableIps.size());
Ip availableIp = Iterables.get(availableIps, ipIndex); Ip availableIp = Iterables.get(availableIps, ipIndex);
try { try {
@ -90,21 +96,22 @@ public class GoGridAddNodeWithTagStrategy implements AddNodeWithTagStrategy {
notStarted = true; notStarted = true;
} }
} }
serverLatestJobCompleted.apply(addedServer); if (template.getOptions().shouldBlockUntilRunning()) {
serverLatestJobCompleted.apply(addedServer);
client.getServerServices().power(addedServer.getName(), PowerCommand.START); client.getServerServices().power(addedServer.getName(),
serverLatestJobCompletedShort.apply(addedServer); PowerCommand.START);
serverLatestJobCompletedShort.apply(addedServer);
addedServer = Iterables.getOnlyElement(client.getServerServices().getServersByName( addedServer = Iterables.getOnlyElement(client.getServerServices()
addedServer.getName())); .getServersByName(addedServer.getName()));
}
return serverToNodeMetadata.apply(addedServer); return serverToNodeMetadata.apply(addedServer);
} }
private Server addServer(String name, Template template, Ip availableIp) { private Server addServer(String name, Template template, Ip availableIp) {
Server addedServer; Server addedServer;
addedServer = client.getServerServices().addServer(name, addedServer = client.getServerServices().addServer(name,
checkNotNull(template.getImage().getProviderId()), checkNotNull(template.getImage().getProviderId()),
sizeToRam.apply(template.getSize()), availableIp.getIp()); sizeToRam.apply(template.getSize()), availableIp.getIp());
return addedServer; return addedServer;
} }
} }

View File

@ -60,13 +60,9 @@ import org.jclouds.http.RequiresHttp;
import org.jclouds.http.annotation.ClientError; import org.jclouds.http.annotation.ClientError;
import org.jclouds.http.annotation.Redirection; import org.jclouds.http.annotation.Redirection;
import org.jclouds.http.annotation.ServerError; import org.jclouds.http.annotation.ServerError;
import org.jclouds.net.IPSocket;
import org.jclouds.predicates.RetryablePredicate;
import org.jclouds.predicates.SocketOpen;
import org.jclouds.rest.ConfiguresRestClient; import org.jclouds.rest.ConfiguresRestClient;
import org.jclouds.rest.config.RestClientModule; import org.jclouds.rest.config.RestClientModule;
import com.google.common.base.Predicate;
import com.google.common.base.Supplier; import com.google.common.base.Supplier;
import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Maps; import com.google.common.collect.Maps;
@ -80,15 +76,16 @@ import com.google.inject.Provides;
*/ */
@RequiresHttp @RequiresHttp
@ConfiguresRestClient @ConfiguresRestClient
public class GoGridRestClientModule extends RestClientModule<GoGridClient, GoGridAsyncClient> { public class GoGridRestClientModule extends
RestClientModule<GoGridClient, GoGridAsyncClient> {
public static final Map<Class<?>, Class<?>> DELEGATE_MAP = ImmutableMap public static final Map<Class<?>, Class<?>> DELEGATE_MAP = ImmutableMap
.<Class<?>, Class<?>> builder()// .<Class<?>, Class<?>> builder()//
.put(GridServerClient.class, GridServerAsyncClient.class)// .put(GridServerClient.class, GridServerAsyncClient.class)//
.put(GridJobClient.class, GridJobAsyncClient.class)// .put(GridJobClient.class, GridJobAsyncClient.class)//
.put(GridIpClient.class, GridIpAsyncClient.class)// .put(GridIpClient.class, GridIpAsyncClient.class)//
.put(GridLoadBalancerClient.class, GridLoadBalancerAsyncClient.class)// .put(GridLoadBalancerClient.class, GridLoadBalancerAsyncClient.class)//
.put(GridImageClient.class, GridImageAsyncClient.class)// .put(GridImageClient.class, GridImageAsyncClient.class)//
.build(); .build();
public GoGridRestClientModule() { public GoGridRestClientModule() {
super(GoGridClient.class, GoGridAsyncClient.class, DELEGATE_MAP); super(GoGridClient.class, GoGridAsyncClient.class, DELEGATE_MAP);
@ -97,7 +94,8 @@ public class GoGridRestClientModule extends RestClientModule<GoGridClient, GoGri
@Provides @Provides
@Singleton @Singleton
@GoGrid @GoGrid
protected URI provideURI(@Named(GoGridConstants.PROPERTY_GOGRID_ENDPOINT) String endpoint) { protected URI provideURI(
@Named(GoGridConstants.PROPERTY_GOGRID_ENDPOINT) String endpoint) {
return URI.create(endpoint); return URI.create(endpoint);
} }
@ -107,28 +105,28 @@ public class GoGridRestClientModule extends RestClientModule<GoGridClient, GoGri
return cache.get(); return cache.get();
} }
@Provides
@Singleton
protected Predicate<IPSocket> socketTester(SocketOpen open) {
return new RetryablePredicate<IPSocket>(open, 130, 1, TimeUnit.SECONDS);
}
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
@Provides @Provides
@Singleton @Singleton
@com.google.inject.name.Named(Constants.PROPERTY_GSON_ADAPTERS) @com.google.inject.name.Named(Constants.PROPERTY_GSON_ADAPTERS)
public Map<Class, Object> provideCustomAdapterBindings() { public Map<Class, Object> provideCustomAdapterBindings() {
Map<Class, Object> bindings = Maps.newHashMap(); Map<Class, Object> bindings = Maps.newHashMap();
bindings.put(ObjectType.class, new CustomDeserializers.ObjectTypeAdapter()); bindings.put(ObjectType.class,
bindings.put(LoadBalancerOs.class, new CustomDeserializers.LoadBalancerOsAdapter()); new CustomDeserializers.ObjectTypeAdapter());
bindings.put(LoadBalancerState.class, new CustomDeserializers.LoadBalancerStateAdapter()); bindings.put(LoadBalancerOs.class,
new CustomDeserializers.LoadBalancerOsAdapter());
bindings.put(LoadBalancerState.class,
new CustomDeserializers.LoadBalancerStateAdapter());
bindings.put(LoadBalancerPersistenceType.class, bindings.put(LoadBalancerPersistenceType.class,
new CustomDeserializers.LoadBalancerPersistenceTypeAdapter()); new CustomDeserializers.LoadBalancerPersistenceTypeAdapter());
bindings.put(LoadBalancerType.class, new CustomDeserializers.LoadBalancerTypeAdapter()); bindings.put(LoadBalancerType.class,
new CustomDeserializers.LoadBalancerTypeAdapter());
bindings.put(IpState.class, new CustomDeserializers.IpStateAdapter()); bindings.put(IpState.class, new CustomDeserializers.IpStateAdapter());
bindings.put(JobState.class, new CustomDeserializers.JobStateAdapter()); bindings.put(JobState.class, new CustomDeserializers.JobStateAdapter());
bindings.put(ServerImageState.class, new CustomDeserializers.ServerImageStateAdapter()); bindings.put(ServerImageState.class,
bindings.put(ServerImageType.class, new CustomDeserializers.ServerImageTypeAdapter()); new CustomDeserializers.ServerImageStateAdapter());
bindings.put(ServerImageType.class,
new CustomDeserializers.ServerImageTypeAdapter());
return bindings; return bindings;
} }
@ -137,7 +135,8 @@ public class GoGridRestClientModule extends RestClientModule<GoGridClient, GoGri
*/ */
@Provides @Provides
@TimeStamp @TimeStamp
Supplier<Long> provideTimeStampCache(@Named(PROPERTY_GOGRID_SESSIONINTERVAL) long seconds) { Supplier<Long> provideTimeStampCache(
@Named(PROPERTY_GOGRID_SESSIONINTERVAL) long seconds) {
return new ExpirableSupplier<Long>(new Supplier<Long>() { return new ExpirableSupplier<Long>(new Supplier<Long>() {
public Long get() { public Long get() {
return System.currentTimeMillis() / 1000; return System.currentTimeMillis() / 1000;
@ -147,9 +146,12 @@ public class GoGridRestClientModule extends RestClientModule<GoGridClient, GoGri
@Override @Override
protected void bindErrorHandlers() { protected void bindErrorHandlers() {
bind(HttpErrorHandler.class).annotatedWith(Redirection.class).to(GoGridErrorHandler.class); bind(HttpErrorHandler.class).annotatedWith(Redirection.class).to(
bind(HttpErrorHandler.class).annotatedWith(ClientError.class).to(GoGridErrorHandler.class); GoGridErrorHandler.class);
bind(HttpErrorHandler.class).annotatedWith(ServerError.class).to(GoGridErrorHandler.class); bind(HttpErrorHandler.class).annotatedWith(ClientError.class).to(
GoGridErrorHandler.class);
bind(HttpErrorHandler.class).annotatedWith(ServerError.class).to(
GoGridErrorHandler.class);
} }
} }

View File

@ -46,9 +46,9 @@ public class ServerToNodeMetadataTest {
expect(server.getId()).andReturn(1000l).atLeastOnce(); expect(server.getId()).andReturn(1000l).atLeastOnce();
expect(server.getName()).andReturn("tag-ff").atLeastOnce(); expect(server.getName()).andReturn("tag-ff").atLeastOnce();
expect(server.getState()).andReturn(new Option("RUNNING")).atLeastOnce(); expect(server.getState()).andReturn(new Option("NODE_RUNNING")).atLeastOnce();
expect(serverStateToNodeState.get("RUNNING")).andReturn(NodeState.RUNNING); expect(serverStateToNodeState.get("NODE_RUNNING")).andReturn(NodeState.RUNNING);
Location location = new LocationImpl(LocationScope.ZONE, "sanfran", "description", null); Location location = new LocationImpl(LocationScope.ZONE, "sanfran", "description", null);
Map<String, Credentials> credentialsMap = createMock(Map.class); Map<String, Credentials> credentialsMap = createMock(Map.class);

View File

@ -27,7 +27,6 @@ import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutorService; import java.util.concurrent.ExecutorService;
import java.util.concurrent.TimeUnit;
import javax.annotation.Resource; import javax.annotation.Resource;
import javax.inject.Inject; import javax.inject.Inject;
@ -37,6 +36,7 @@ import javax.inject.Singleton;
import org.jclouds.Constants; import org.jclouds.Constants;
import org.jclouds.compute.ComputeServiceContext; import org.jclouds.compute.ComputeServiceContext;
import org.jclouds.compute.LoadBalancerService; import org.jclouds.compute.LoadBalancerService;
import org.jclouds.compute.config.ComputeServiceTimeoutsModule;
import org.jclouds.compute.domain.Architecture; import org.jclouds.compute.domain.Architecture;
import org.jclouds.compute.domain.ComputeMetadata; import org.jclouds.compute.domain.ComputeMetadata;
import org.jclouds.compute.domain.Image; import org.jclouds.compute.domain.Image;
@ -50,8 +50,6 @@ import org.jclouds.compute.domain.internal.ImageImpl;
import org.jclouds.compute.domain.internal.SizeImpl; import org.jclouds.compute.domain.internal.SizeImpl;
import org.jclouds.compute.internal.ComputeServiceContextImpl; import org.jclouds.compute.internal.ComputeServiceContextImpl;
import org.jclouds.compute.predicates.NodePredicates; 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.reference.ComputeServiceConstants;
import org.jclouds.compute.strategy.AddNodeWithTagStrategy; import org.jclouds.compute.strategy.AddNodeWithTagStrategy;
import org.jclouds.compute.strategy.DestroyNodeStrategy; import org.jclouds.compute.strategy.DestroyNodeStrategy;
@ -71,13 +69,9 @@ import org.jclouds.ibmdev.config.IBMDeveloperCloudContextModule;
import org.jclouds.ibmdev.domain.Instance; import org.jclouds.ibmdev.domain.Instance;
import org.jclouds.ibmdev.reference.IBMDeveloperCloudConstants; import org.jclouds.ibmdev.reference.IBMDeveloperCloudConstants;
import org.jclouds.logging.Logger; import org.jclouds.logging.Logger;
import org.jclouds.net.IPSocket;
import org.jclouds.predicates.RetryablePredicate;
import org.jclouds.predicates.SocketOpen;
import com.google.common.base.Function; import com.google.common.base.Function;
import com.google.common.base.Predicate; import com.google.common.base.Predicate;
import com.google.common.base.Predicates;
import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Iterables; import com.google.common.collect.Iterables;
import com.google.common.collect.Maps; import com.google.common.collect.Maps;
@ -91,7 +85,8 @@ import com.google.inject.util.Providers;
/** /**
* @author Adrian Cole * @author Adrian Cole
*/ */
public class IBMDeveloperCloudComputeServiceContextModule extends IBMDeveloperCloudContextModule { public class IBMDeveloperCloudComputeServiceContextModule extends
IBMDeveloperCloudContextModule {
private final String providerName; private final String providerName;
@ -103,25 +98,26 @@ public class IBMDeveloperCloudComputeServiceContextModule extends IBMDeveloperCl
@Override @Override
protected void configure() { protected void configure() {
super.configure(); super.configure();
install(new ComputeServiceTimeoutsModule());
bind(new TypeLiteral<Function<Instance, NodeMetadata>>() { bind(new TypeLiteral<Function<Instance, NodeMetadata>>() {
}).to(InstanceToNodeMetadata.class); }).to(InstanceToNodeMetadata.class);
bind(new TypeLiteral<ComputeServiceContext>() { bind(new TypeLiteral<ComputeServiceContext>() {
}) })
.to( .to(
new TypeLiteral<ComputeServiceContextImpl<IBMDeveloperCloudClient, IBMDeveloperCloudAsyncClient>>() { new TypeLiteral<ComputeServiceContextImpl<IBMDeveloperCloudClient, IBMDeveloperCloudAsyncClient>>() {
}).in(Scopes.SINGLETON); }).in(Scopes.SINGLETON);
bind(AddNodeWithTagStrategy.class).to(IBMDeveloperCloudAddNodeWithTagStrategy.class); bind(AddNodeWithTagStrategy.class).to(
bind(ListNodesStrategy.class).to(IBMDeveloperCloudListNodesStrategy.class); IBMDeveloperCloudAddNodeWithTagStrategy.class);
bind(GetNodeMetadataStrategy.class).to(IBMDeveloperCloudGetNodeMetadataStrategy.class); bind(ListNodesStrategy.class)
bind(RebootNodeStrategy.class).to(IBMDeveloperCloudRebootNodeStrategy.class); .to(IBMDeveloperCloudListNodesStrategy.class);
bind(DestroyNodeStrategy.class).to(IBMDeveloperCloudDestroyNodeStrategy.class); bind(GetNodeMetadataStrategy.class).to(
bind(LoadBalancerService.class).toProvider(Providers.<LoadBalancerService> of(null)); IBMDeveloperCloudGetNodeMetadataStrategy.class);
} bind(RebootNodeStrategy.class).to(
IBMDeveloperCloudRebootNodeStrategy.class);
@Provides bind(DestroyNodeStrategy.class).to(
@Singleton IBMDeveloperCloudDestroyNodeStrategy.class);
protected Predicate<IPSocket> socketTester(SocketOpen open) { bind(LoadBalancerService.class).toProvider(
return new RetryablePredicate<IPSocket>(open, 130, 1, TimeUnit.SECONDS); Providers.<LoadBalancerService> of(null));
} }
/** /**
@ -149,25 +145,29 @@ public class IBMDeveloperCloudComputeServiceContextModule extends IBMDeveloperCl
@Singleton @Singleton
public static class CreateKeyPairEncodeTagIntoNameRunNodesAndAddToSet extends public static class CreateKeyPairEncodeTagIntoNameRunNodesAndAddToSet extends
EncodeTagIntoNameRunNodesAndAddToSetStrategy { EncodeTagIntoNameRunNodesAndAddToSetStrategy {
private final IBMDeveloperCloudClient client; private final IBMDeveloperCloudClient client;
private final Map<String, String> credentialsMap; private final Map<String, String> credentialsMap;
@Inject @Inject
protected CreateKeyPairEncodeTagIntoNameRunNodesAndAddToSet( protected CreateKeyPairEncodeTagIntoNameRunNodesAndAddToSet(
AddNodeWithTagStrategy addNodeWithTagStrategy, ListNodesStrategy listNodesStrategy, AddNodeWithTagStrategy addNodeWithTagStrategy,
@Named("NAMING_CONVENTION") String nodeNamingConvention, ComputeUtils utils, ListNodesStrategy listNodesStrategy,
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService executor, @Named("NAMING_CONVENTION") String nodeNamingConvention,
IBMDeveloperCloudClient client, ComputeUtils utils,
@Named("CREDENTIALS") Map<String, String> credentialsMap) { @Named(Constants.PROPERTY_USER_THREADS) ExecutorService executor,
super(addNodeWithTagStrategy, listNodesStrategy, nodeNamingConvention, utils, executor); IBMDeveloperCloudClient client,
@Named("CREDENTIALS") Map<String, String> credentialsMap) {
super(addNodeWithTagStrategy, listNodesStrategy, nodeNamingConvention,
utils, executor);
this.client = checkNotNull(client, "client"); this.client = checkNotNull(client, "client");
this.credentialsMap = checkNotNull(credentialsMap, "credentialsMap"); this.credentialsMap = checkNotNull(credentialsMap, "credentialsMap");
} }
@Override @Override
public Map<?, ListenableFuture<Void>> execute(String tag, int count, Template template, public Map<?, ListenableFuture<Void>> execute(String tag, int count,
Set<NodeMetadata> nodes, Map<NodeMetadata, Exception> badNodes) { Template template, Set<NodeMetadata> nodes,
Map<NodeMetadata, Exception> badNodes) {
String key = template.getOptions().getPublicKey(); String key = template.getOptions().getPublicKey();
if (key != null) { if (key != null) {
template.getOptions().dontAuthorizePublicKey(); template.getOptions().dontAuthorizePublicKey();
@ -178,7 +178,8 @@ public class IBMDeveloperCloudComputeServiceContextModule extends IBMDeveloperCl
client.updatePublicKey(tag, key); client.updatePublicKey(tag, key);
} }
} else { } else {
credentialsMap.put(tag, client.generateKeyPair(tag).getKeyMaterial()); credentialsMap.put(tag, client.generateKeyPair(tag)
.getKeyMaterial());
} }
return super.execute(tag, count, template, nodes, badNodes); return super.execute(tag, count, template, nodes, badNodes);
} }
@ -186,78 +187,81 @@ public class IBMDeveloperCloudComputeServiceContextModule extends IBMDeveloperCl
} }
@Singleton @Singleton
public static class IBMDeveloperCloudAddNodeWithTagStrategy implements AddNodeWithTagStrategy { public static class IBMDeveloperCloudAddNodeWithTagStrategy implements
AddNodeWithTagStrategy {
private final IBMDeveloperCloudClient client; private final IBMDeveloperCloudClient client;
private final Predicate<Instance> instanceActive;
private final Function<Instance, NodeMetadata> instanceToNodeMetadata; private final Function<Instance, NodeMetadata> instanceToNodeMetadata;
@Inject @Inject
protected IBMDeveloperCloudAddNodeWithTagStrategy(IBMDeveloperCloudClient client, protected IBMDeveloperCloudAddNodeWithTagStrategy(
@Named("ACTIVE") Predicate<Instance> instanceActive, IBMDeveloperCloudClient client,
Function<Instance, NodeMetadata> instanceToNodeMetadata) { Function<Instance, NodeMetadata> instanceToNodeMetadata) {
this.client = checkNotNull(client, "client"); this.client = checkNotNull(client, "client");
this.instanceActive = checkNotNull(instanceActive, "instanceActive");
this.instanceToNodeMetadata = checkNotNull(instanceToNodeMetadata, this.instanceToNodeMetadata = checkNotNull(instanceToNodeMetadata,
"instanceToNodeMetadata"); "instanceToNodeMetadata");
} }
@Override @Override
public NodeMetadata execute(String tag, String name, Template template) { public NodeMetadata execute(String tag, String name, Template template) {
Instance instance = client.createInstanceInLocation(template.getLocation().getId(), name, Instance instance = client.createInstanceInLocation(template
template.getImage().getProviderId(), template.getSize().getProviderId(), .getLocation().getId(), name, template.getImage()
authorizePublicKey(tag)); .getProviderId(), template.getSize().getProviderId(),
instanceActive.apply(instance); authorizePublicKey(tag));
return instanceToNodeMetadata.apply(client.getInstance(instance.getId())); return instanceToNodeMetadata.apply(client.getInstance(instance
.getId()));
} }
} }
@Singleton @Singleton
public static class IBMDeveloperCloudRebootNodeStrategy implements RebootNodeStrategy { public static class IBMDeveloperCloudRebootNodeStrategy implements
RebootNodeStrategy {
private final IBMDeveloperCloudClient client; private final IBMDeveloperCloudClient client;
private final Predicate<Instance> instanceActive; private final GetNodeMetadataStrategy getNode;
@Inject @Inject
protected IBMDeveloperCloudRebootNodeStrategy(IBMDeveloperCloudClient client, protected IBMDeveloperCloudRebootNodeStrategy(
@Named("ACTIVE") Predicate<Instance> instanceActive) { IBMDeveloperCloudClient client, GetNodeMetadataStrategy getNode) {
this.client = checkNotNull(client, "client"); this.client = checkNotNull(client, "client");
this.instanceActive = checkNotNull(instanceActive, "instanceActive"); this.getNode = checkNotNull(getNode, "getNode");
} }
@Override @Override
public boolean execute(String id) { public NodeMetadata execute(String id) {
client.restartInstance(id); client.restartInstance(id);
return instanceActive.apply(client.getInstance(id)); return getNode.execute(id);
} }
} }
@Singleton @Singleton
@Provides @Provides
Map<Instance.Status, NodeState> provideServerToNodeState() { Map<Instance.Status, NodeState> provideServerToNodeState() {
return ImmutableMap.<Instance.Status, NodeState> builder().put(Instance.Status.ACTIVE, return ImmutableMap.<Instance.Status, NodeState> builder().put(
NodeState.RUNNING)// Instance.Status.ACTIVE, NodeState.RUNNING)//
.put(Instance.Status.STOPPED, NodeState.SUSPENDED)// .put(Instance.Status.STOPPED, NodeState.SUSPENDED)//
.put(Instance.Status.REMOVED, NodeState.TERMINATED)// .put(Instance.Status.REMOVED, NodeState.TERMINATED)//
.put(Instance.Status.DEPROVISIONING, NodeState.PENDING)// .put(Instance.Status.DEPROVISIONING, NodeState.PENDING)//
.put(Instance.Status.FAILED, NodeState.ERROR)// .put(Instance.Status.FAILED, NodeState.ERROR)//
.put(Instance.Status.NEW, NodeState.PENDING)// .put(Instance.Status.NEW, NodeState.PENDING)//
.put(Instance.Status.PROVISIONING, NodeState.PENDING)// .put(Instance.Status.PROVISIONING, NodeState.PENDING)//
.put(Instance.Status.REJECTED, NodeState.ERROR)// .put(Instance.Status.REJECTED, NodeState.ERROR)//
.put(Instance.Status.RESTARTING, NodeState.PENDING)// .put(Instance.Status.RESTARTING, NodeState.PENDING)//
.put(Instance.Status.STARTING, NodeState.PENDING)// .put(Instance.Status.STARTING, NodeState.PENDING)//
.put(Instance.Status.STOPPING, NodeState.PENDING)// .put(Instance.Status.STOPPING, NodeState.PENDING)//
.put(Instance.Status.UNKNOWN, NodeState.UNKNOWN).build(); .put(Instance.Status.UNKNOWN, NodeState.UNKNOWN).build();
} }
@Singleton @Singleton
public static class IBMDeveloperCloudListNodesStrategy implements ListNodesStrategy { public static class IBMDeveloperCloudListNodesStrategy implements
ListNodesStrategy {
private final IBMDeveloperCloudClient client; private final IBMDeveloperCloudClient client;
private final Function<Instance, NodeMetadata> instanceToNodeMetadata; private final Function<Instance, NodeMetadata> instanceToNodeMetadata;
@Inject @Inject
protected IBMDeveloperCloudListNodesStrategy(IBMDeveloperCloudClient client, protected IBMDeveloperCloudListNodesStrategy(
Function<Instance, NodeMetadata> instanceToNodeMetadata) { IBMDeveloperCloudClient client,
Function<Instance, NodeMetadata> instanceToNodeMetadata) {
this.client = client; this.client = client;
this.instanceToNodeMetadata = instanceToNodeMetadata; this.instanceToNodeMetadata = instanceToNodeMetadata;
} }
@ -269,20 +273,22 @@ public class IBMDeveloperCloudComputeServiceContextModule extends IBMDeveloperCl
@Override @Override
public Iterable<? extends NodeMetadata> listDetailsOnNodesMatching( public Iterable<? extends NodeMetadata> listDetailsOnNodesMatching(
Predicate<ComputeMetadata> filter) { Predicate<ComputeMetadata> filter) {
return Iterables.filter(Iterables return Iterables.filter(Iterables.transform(client.listInstances(),
.transform(client.listInstances(), instanceToNodeMetadata), filter); instanceToNodeMetadata), filter);
} }
} }
@Singleton @Singleton
public static class IBMDeveloperCloudGetNodeMetadataStrategy implements GetNodeMetadataStrategy { public static class IBMDeveloperCloudGetNodeMetadataStrategy implements
GetNodeMetadataStrategy {
private final IBMDeveloperCloudClient client; private final IBMDeveloperCloudClient client;
private final Function<Instance, NodeMetadata> instanceToNodeMetadata; private final Function<Instance, NodeMetadata> instanceToNodeMetadata;
@Inject @Inject
protected IBMDeveloperCloudGetNodeMetadataStrategy(IBMDeveloperCloudClient client, protected IBMDeveloperCloudGetNodeMetadataStrategy(
Function<Instance, NodeMetadata> instanceToNodeMetadata) { IBMDeveloperCloudClient client,
Function<Instance, NodeMetadata> instanceToNodeMetadata) {
this.client = client; this.client = client;
this.instanceToNodeMetadata = instanceToNodeMetadata; this.instanceToNodeMetadata = instanceToNodeMetadata;
} }
@ -290,42 +296,36 @@ public class IBMDeveloperCloudComputeServiceContextModule extends IBMDeveloperCl
@Override @Override
public NodeMetadata execute(String id) { public NodeMetadata execute(String id) {
Instance instance = client.getInstance(checkNotNull(id, "id")); Instance instance = client.getInstance(checkNotNull(id, "id"));
return instance == null ? null : instanceToNodeMetadata.apply(instance); return instance == null ? null : instanceToNodeMetadata
.apply(instance);
} }
} }
@Singleton @Singleton
public static class IBMDeveloperCloudDestroyNodeStrategy implements DestroyNodeStrategy { public static class IBMDeveloperCloudDestroyNodeStrategy implements
DestroyNodeStrategy {
private final IBMDeveloperCloudClient client; private final IBMDeveloperCloudClient client;
private final Predicate<Instance> instanceRemoved; private final GetNodeMetadataStrategy getNode;
@Inject @Inject
protected IBMDeveloperCloudDestroyNodeStrategy(IBMDeveloperCloudClient client, protected IBMDeveloperCloudDestroyNodeStrategy(
@Named("REMOVED") Predicate<Instance> instanceRemoved) { IBMDeveloperCloudClient client, GetNodeMetadataStrategy getNode) {
this.client = checkNotNull(client, "client"); this.client = checkNotNull(client, "client");
this.instanceRemoved = checkNotNull(instanceRemoved, "instanceRemoved"); this.getNode = checkNotNull(getNode, "getNode");
} }
@Override @Override
public boolean execute(String id) { public NodeMetadata execute(String id) {
client.deleteInstance(id); client.deleteInstance(id);
return instanceRemoved.apply(client.getInstance(id)); return getNode.execute(id);
} }
} }
@Provides
@Singleton
@Named("NOT_RUNNING")
protected Predicate<CommandUsingClient> runScriptRunning(ScriptStatusReturnsZero stateRunning) {
return new RetryablePredicate<CommandUsingClient>(Predicates.not(stateRunning), 600, 3,
TimeUnit.SECONDS);
}
@Provides @Provides
@Singleton @Singleton
Location getDefaultLocation( Location getDefaultLocation(
@Named(PROPERTY_IBMDEVELOPERCLOUD_LOCATION) final String defaultLocation, @Named(PROPERTY_IBMDEVELOPERCLOUD_LOCATION) final String defaultLocation,
Set<? extends Location> locations) { Set<? extends Location> locations) {
return Iterables.find(locations, new Predicate<Location>() { return Iterables.find(locations, new Predicate<Location>() {
@Override @Override
@ -338,14 +338,16 @@ public class IBMDeveloperCloudComputeServiceContextModule extends IBMDeveloperCl
@Provides @Provides
@Singleton @Singleton
Set<? extends Location> getAssignableLocations(IBMDeveloperCloudClient sync, LogHolder holder) { Set<? extends Location> getAssignableLocations(IBMDeveloperCloudClient sync,
LogHolder holder) {
final Set<Location> assignableLocations = Sets.newHashSet(); final Set<Location> assignableLocations = Sets.newHashSet();
holder.logger.debug(">> providing locations"); holder.logger.debug(">> providing locations");
Location parent = new LocationImpl(LocationScope.PROVIDER, providerName, providerName, null); Location parent = new LocationImpl(LocationScope.PROVIDER, providerName,
providerName, null);
for (org.jclouds.ibmdev.domain.Location location : sync.listLocations()) for (org.jclouds.ibmdev.domain.Location location : sync.listLocations())
assignableLocations.add(new LocationImpl(LocationScope.ZONE, location.getId(), location assignableLocations.add(new LocationImpl(LocationScope.ZONE, location
.getName(), parent)); .getId(), location.getName(), parent));
holder.logger.debug("<< locations(%d)", assignableLocations.size()); holder.logger.debug("<< locations(%d)", assignableLocations.size());
return assignableLocations; return assignableLocations;
@ -353,45 +355,50 @@ public class IBMDeveloperCloudComputeServiceContextModule extends IBMDeveloperCl
@Provides @Provides
@Singleton @Singleton
protected Set<? extends Size> provideSizes(IBMDeveloperCloudClient sync, LogHolder holder, protected Set<? extends Size> provideSizes(IBMDeveloperCloudClient sync,
Map<String, ? extends Location> locations) { LogHolder holder, Map<String, ? extends Location> locations) {
final Set<Size> sizes = Sets.newHashSet(); final Set<Size> sizes = Sets.newHashSet();
holder.logger.debug(">> providing sizes"); holder.logger.debug(">> providing sizes");
for (org.jclouds.ibmdev.domain.Location location : sync.listLocations()) { for (org.jclouds.ibmdev.domain.Location location : sync.listLocations()) {
Location assignedLocation = locations.get(location.getId()); Location assignedLocation = locations.get(location.getId());
// TODO we cannot query actual size, yet, so lets make the multipliers work out // TODO we cannot query actual size, yet, so lets make the
// multipliers work out
int sizeMultiplier = 1; int sizeMultiplier = 1;
for (String i386 : location.getCapabilities().get( for (String i386 : location.getCapabilities().get(
IBMDeveloperCloudConstants.CAPABILITY_I386).keySet()) IBMDeveloperCloudConstants.CAPABILITY_I386).keySet())
sizes.add(buildSize(location, i386, assignedLocation, sizeMultiplier++)); sizes.add(buildSize(location, i386, assignedLocation,
sizeMultiplier++));
for (String x86_64 : location.getCapabilities().get( for (String x86_64 : location.getCapabilities().get(
IBMDeveloperCloudConstants.CAPABILITY_x86_64).keySet()) IBMDeveloperCloudConstants.CAPABILITY_x86_64).keySet())
sizes.add(buildSize(location, x86_64, assignedLocation, sizeMultiplier++)); sizes.add(buildSize(location, x86_64, assignedLocation,
sizeMultiplier++));
} }
holder.logger.debug("<< sizes(%d)", sizes.size()); holder.logger.debug("<< sizes(%d)", sizes.size());
return sizes; return sizes;
} }
private SizeImpl buildSize(org.jclouds.ibmdev.domain.Location location, final String id, private SizeImpl buildSize(org.jclouds.ibmdev.domain.Location location,
Location assignedLocation, int multiplier) { final String id, Location assignedLocation, int multiplier) {
return new SizeImpl(id, id, location.getId() + "/" + id, assignedLocation, null, ImmutableMap return new SizeImpl(id, id, location.getId() + "/" + id,
.<String, String> of(), multiplier, multiplier * 1024, multiplier * 10, assignedLocation, null, ImmutableMap.<String, String> of(),
new Predicate<Image>() { multiplier, multiplier * 1024, multiplier * 10,
@Override new Predicate<Image>() {
public boolean apply(Image input) { @Override
if (input instanceof IBMImage) public boolean apply(Image input) {
return IBMImage.class.cast(input).rawImage.getSupportedInstanceTypes() if (input instanceof IBMImage)
.contains(id); return IBMImage.class.cast(input).rawImage
return false; .getSupportedInstanceTypes().contains(id);
} return false;
}
}); });
} }
@Provides @Provides
@Singleton @Singleton
protected Map<String, ? extends Image> provideImageMap(Set<? extends Image> locations) { protected Map<String, ? extends Image> provideImageMap(
Set<? extends Image> locations) {
return Maps.uniqueIndex(locations, new Function<Image, String>() { return Maps.uniqueIndex(locations, new Function<Image, String>() {
@Override @Override
@ -404,7 +411,8 @@ public class IBMDeveloperCloudComputeServiceContextModule extends IBMDeveloperCl
@Provides @Provides
@Singleton @Singleton
protected Map<String, ? extends Location> provideLocationMap(Set<? extends Location> locations) { protected Map<String, ? extends Location> provideLocationMap(
Set<? extends Location> locations) {
return Maps.uniqueIndex(locations, new Function<Location, String>() { return Maps.uniqueIndex(locations, new Function<Location, String>() {
@Override @Override
@ -417,8 +425,9 @@ public class IBMDeveloperCloudComputeServiceContextModule extends IBMDeveloperCl
@Provides @Provides
@Singleton @Singleton
protected Set<? extends Image> provideImages(final IBMDeveloperCloudClient sync, protected Set<? extends Image> provideImages(
LogHolder holder, Map<String, ? extends Location> locations) { final IBMDeveloperCloudClient sync, LogHolder holder,
Map<String, ? extends Location> locations) {
final Set<Image> images = Sets.newHashSet(); final Set<Image> images = Sets.newHashSet();
holder.logger.debug(">> providing images"); holder.logger.debug(">> providing images");
@ -441,12 +450,14 @@ public class IBMDeveloperCloudComputeServiceContextModule extends IBMDeveloperCl
// TODO manifest fails to parse due to encoding issues in the path // TODO manifest fails to parse due to encoding issues in the path
// TODO get correct default credentials // TODO get correct default credentials
// http://www-180.ibm.com/cloud/enterprise/beta/ram/community/_rlvid.jsp.faces?_rap=pc_DiscussionForum.doDiscussionTopic&_rvip=/community/discussionForum.jsp&guid={DA689AEE-783C-6FE7-6F9F-DFEE9763F806}&v=1&submission=false&fid=1068&tid=1527 // http://www-180.ibm.com/cloud/enterprise/beta/ram/community/_rlvid.jsp.faces?_rap=pc_DiscussionForum.doDiscussionTopic&_rvip=/community/discussionForum.jsp&guid={DA689AEE-783C-6FE7-6F9F-DFEE9763F806}&v=1&submission=false&fid=1068&tid=1527
super(in.getId(), in.getName(), in.getId(), location, null, ImmutableMap super(in.getId(), in.getName(), in.getId(), location, null,
.<String, String> of(), in.getDescription(), in.getCreatedTime().getTime() + "", ImmutableMap.<String, String> of(), in.getDescription(), in
(in.getPlatform().indexOf("Redhat") != -1) ? OsFamily.RHEL : OsFamily.SUSE, in .getCreatedTime().getTime()
.getPlatform(), + "",
(in.getPlatform().indexOf("32") != -1) ? Architecture.X86_32 (in.getPlatform().indexOf("Redhat") != -1) ? OsFamily.RHEL
: Architecture.X86_64, new Credentials("idcuser", null)); : OsFamily.SUSE, in.getPlatform(), (in.getPlatform()
.indexOf("32") != -1) ? Architecture.X86_32
: Architecture.X86_64, new Credentials("idcuser", null));
this.rawImage = in; this.rawImage = in;
} }

View File

@ -20,7 +20,6 @@ package org.jclouds.ibmdev.config;
import java.io.UnsupportedEncodingException; import java.io.UnsupportedEncodingException;
import java.net.URI; import java.net.URI;
import java.util.concurrent.TimeUnit;
import javax.inject.Named; import javax.inject.Named;
import javax.inject.Singleton; import javax.inject.Singleton;
@ -35,16 +34,11 @@ import org.jclouds.http.filters.BasicAuthentication;
import org.jclouds.ibmdev.IBMDeveloperCloud; import org.jclouds.ibmdev.IBMDeveloperCloud;
import org.jclouds.ibmdev.IBMDeveloperCloudAsyncClient; import org.jclouds.ibmdev.IBMDeveloperCloudAsyncClient;
import org.jclouds.ibmdev.IBMDeveloperCloudClient; import org.jclouds.ibmdev.IBMDeveloperCloudClient;
import org.jclouds.ibmdev.domain.Instance;
import org.jclouds.ibmdev.handlers.IBMDeveloperCloudErrorHandler; import org.jclouds.ibmdev.handlers.IBMDeveloperCloudErrorHandler;
import org.jclouds.ibmdev.predicates.InstanceActive;
import org.jclouds.ibmdev.predicates.InstanceRemovedOrNotFound;
import org.jclouds.ibmdev.reference.IBMDeveloperCloudConstants; import org.jclouds.ibmdev.reference.IBMDeveloperCloudConstants;
import org.jclouds.predicates.RetryablePredicate;
import org.jclouds.rest.ConfiguresRestClient; import org.jclouds.rest.ConfiguresRestClient;
import org.jclouds.rest.config.RestClientModule; import org.jclouds.rest.config.RestClientModule;
import com.google.common.base.Predicate;
import com.google.inject.Provides; import com.google.inject.Provides;
/** /**
@ -55,19 +49,19 @@ import com.google.inject.Provides;
@RequiresHttp @RequiresHttp
@ConfiguresRestClient @ConfiguresRestClient
public class IBMDeveloperCloudRestClientModule extends public class IBMDeveloperCloudRestClientModule extends
RestClientModule<IBMDeveloperCloudClient, IBMDeveloperCloudAsyncClient> { RestClientModule<IBMDeveloperCloudClient, IBMDeveloperCloudAsyncClient> {
public IBMDeveloperCloudRestClientModule() { public IBMDeveloperCloudRestClientModule() {
super(IBMDeveloperCloudClient.class, IBMDeveloperCloudAsyncClient.class); super(IBMDeveloperCloudClient.class, IBMDeveloperCloudAsyncClient.class);
} }
@Provides @Provides
@Singleton @Singleton
public BasicAuthentication provideBasicAuthentication( public BasicAuthentication provideBasicAuthentication(
@Named(IBMDeveloperCloudConstants.PROPERTY_IBMDEVELOPERCLOUD_USER) String user, @Named(IBMDeveloperCloudConstants.PROPERTY_IBMDEVELOPERCLOUD_USER) String user,
@Named(IBMDeveloperCloudConstants.PROPERTY_IBMDEVELOPERCLOUD_PASSWORD) String password, @Named(IBMDeveloperCloudConstants.PROPERTY_IBMDEVELOPERCLOUD_PASSWORD) String password,
EncryptionService encryptionService) throws UnsupportedEncodingException { EncryptionService encryptionService)
throws UnsupportedEncodingException {
return new BasicAuthentication(user, password, encryptionService); return new BasicAuthentication(user, password, encryptionService);
} }
@ -75,18 +69,18 @@ public class IBMDeveloperCloudRestClientModule extends
@Singleton @Singleton
@IBMDeveloperCloud @IBMDeveloperCloud
protected URI provideURI( protected URI provideURI(
@Named(IBMDeveloperCloudConstants.PROPERTY_IBMDEVELOPERCLOUD_ENDPOINT) String endpoint) { @Named(IBMDeveloperCloudConstants.PROPERTY_IBMDEVELOPERCLOUD_ENDPOINT) String endpoint) {
return URI.create(endpoint); return URI.create(endpoint);
} }
@Override @Override
protected void bindErrorHandlers() { protected void bindErrorHandlers() {
bind(HttpErrorHandler.class).annotatedWith(Redirection.class).to( bind(HttpErrorHandler.class).annotatedWith(Redirection.class).to(
IBMDeveloperCloudErrorHandler.class); IBMDeveloperCloudErrorHandler.class);
bind(HttpErrorHandler.class).annotatedWith(ClientError.class).to( bind(HttpErrorHandler.class).annotatedWith(ClientError.class).to(
IBMDeveloperCloudErrorHandler.class); IBMDeveloperCloudErrorHandler.class);
bind(HttpErrorHandler.class).annotatedWith(ServerError.class).to( bind(HttpErrorHandler.class).annotatedWith(ServerError.class).to(
IBMDeveloperCloudErrorHandler.class); IBMDeveloperCloudErrorHandler.class);
} }
@Override @Override
@ -94,18 +88,4 @@ public class IBMDeveloperCloudRestClientModule extends
install(new IBMDeveloperCloudParserModule()); install(new IBMDeveloperCloudParserModule());
super.configure(); super.configure();
} }
@Provides
@Singleton
@Named("ACTIVE")
protected Predicate<Instance> instanceActive(InstanceActive instanceActive) {
return new RetryablePredicate<Instance>(instanceActive, 1200, 3, TimeUnit.SECONDS);
}
@Provides
@Singleton
@Named("REMOVED")
Predicate<Instance> instanceRemoved(InstanceRemovedOrNotFound instanceRemoved) {
return new RetryablePredicate<Instance>(instanceRemoved, 5000, 500, TimeUnit.MILLISECONDS);
}
} }

View File

@ -49,12 +49,15 @@ public class InstanceActive implements Predicate<Instance> {
public boolean apply(Instance instance) { public boolean apply(Instance instance) {
logger.trace("looking for state on instance %s", instance); logger.trace("looking for state on instance %s", instance);
instance = client.getInstance(instance.getId()); instance = client.getInstance(instance.getId());
if (instance == null || instance.getStatus() == Instance.Status.FAILED) if (instance == null)
return false; return false;
logger.trace("%s: looking for instance state %s: currently: %s", instance.getId(), logger.trace("%s: looking for instance state %s: currently: %s", instance
Instance.Status.ACTIVE, instance.getStatus()); .getId(), Instance.Status.ACTIVE, instance.getStatus());
if (instance.getStatus() == Instance.Status.FAILED)
throw new IllegalStateException("node " + instance.getId()
+ " in location " + instance.getLocation()
+ " is in a failed state");
return instance.getStatus() == Instance.Status.ACTIVE; return instance.getStatus() == Instance.Status.ACTIVE;
} }
} }

View File

@ -70,8 +70,8 @@ import com.google.common.io.Files;
@Test(groups = "live", testName = "ibmdevelopercloud.IBMDeveloperCloudClientLiveTest") @Test(groups = "live", testName = "ibmdevelopercloud.IBMDeveloperCloudClientLiveTest")
public class IBMDeveloperCloudClientLiveTest { public class IBMDeveloperCloudClientLiveTest {
private static final ImmutableSet<Software> SOFTWARE = ImmutableSet.<Software> of(new Software( private static final ImmutableSet<Software> SOFTWARE = ImmutableSet
"SUSE Linux Enterprise", "OS", "10 SP2")); .<Software> of(new Software("SUSE Linux Enterprise", "OS", "10 SP2"));
private static final String SIZE = "LARGE"; private static final String SIZE = "LARGE";
private IBMDeveloperCloudClient connection; private IBMDeveloperCloudClient connection;
private Location location; private Location location;
@ -87,11 +87,14 @@ public class IBMDeveloperCloudClientLiveTest {
@BeforeGroups(groups = { "live" }) @BeforeGroups(groups = { "live" })
public void setupClient() { public void setupClient() {
user = checkNotNull(System.getProperty("jclouds.test.user"), "jclouds.test.user"); user = checkNotNull(System.getProperty("jclouds.test.user"),
String password = checkNotNull(System.getProperty("jclouds.test.key"), "jclouds.test.key"); "jclouds.test.user");
String password = checkNotNull(System.getProperty("jclouds.test.key"),
"jclouds.test.key");
connection = (IBMDeveloperCloudClient) IBMDeveloperCloudContextFactory.createContext(user, connection = (IBMDeveloperCloudClient) IBMDeveloperCloudContextFactory
password, new Log4JLoggingModule()).getProviderSpecificContext().getApi(); .createContext(user, password, new Log4JLoggingModule())
.getProviderSpecificContext().getApi();
} }
@Test @Test
@ -118,7 +121,8 @@ public class IBMDeveloperCloudClientLiveTest {
@Test @Test
public void testListInstancesFromRequestReturnsNull() throws Exception { public void testListInstancesFromRequestReturnsNull() throws Exception {
Set<? extends Instance> response = connection.listInstancesFromRequest(Long.MAX_VALUE + ""); Set<? extends Instance> response = connection
.listInstancesFromRequest(Long.MAX_VALUE + "");
assertNull(response); assertNull(response);
} }
@ -128,7 +132,8 @@ public class IBMDeveloperCloudClientLiveTest {
assertNotNull(response); assertNotNull(response);
if (response.size() > 0) { if (response.size() > 0) {
Instance instance = Iterables.get(response, 0); Instance instance = Iterables.get(response, 0);
assertEquals(connection.getInstance(instance.getId()).getId(), instance.getId()); assertEquals(connection.getInstance(instance.getId()).getId(),
instance.getId());
} }
} }
@ -160,7 +165,8 @@ public class IBMDeveloperCloudClientLiveTest {
assertNotNull(response); assertNotNull(response);
if (response.size() > 0) { if (response.size() > 0) {
Volume image = Iterables.get(response, 0); Volume image = Iterables.get(response, 0);
assertEquals(connection.getVolume(image.getId()).getId(), image.getId()); assertEquals(connection.getVolume(image.getId()).getId(), image
.getId());
} }
} }
@ -176,7 +182,8 @@ public class IBMDeveloperCloudClientLiveTest {
assertNotNull(response); assertNotNull(response);
if (response.size() > 0) { if (response.size() > 0) {
location = Iterables.get(response, 0); location = Iterables.get(response, 0);
assertEquals(connection.getLocation(location.getId()).getId(), location.getId()); assertEquals(connection.getLocation(location.getId()).getId(),
location.getId());
} }
} }
@ -205,10 +212,11 @@ public class IBMDeveloperCloudClientLiveTest {
Instance instance = connection.getInstance(instanceId); Instance instance = connection.getInstance(instanceId);
System.out.println("deleting instance: " + instance); System.out.println("deleting instance: " + instance);
if (instance.getStatus() == Instance.Status.FAILED if (instance.getStatus() == Instance.Status.FAILED
|| instance.getStatus() == Instance.Status.ACTIVE) { || instance.getStatus() == Instance.Status.ACTIVE) {
connection.deleteInstance(instanceId); connection.deleteInstance(instanceId);
assert new RetryablePredicate<Instance>(new InstanceRemovedOrNotFound(connection), assert new RetryablePredicate<Instance>(
30, 2, TimeUnit.SECONDS).apply(instance) : instance; new InstanceRemovedOrNotFound(connection), 30, 2,
TimeUnit.SECONDS).apply(instance) : instance;
} }
} }
} }
@ -221,22 +229,25 @@ public class IBMDeveloperCloudClientLiveTest {
public void testAllocateIpAddress() throws Exception { public void testAllocateIpAddress() throws Exception {
try { try {
ip = connection.allocateAddressInLocation(location.getId()); ip = connection.allocateAddressInLocation(location.getId());
System.out.println(ip);
assertEquals(ip.getIp(), null); assertEquals(ip.getIp(), null);
// wait up to 30 seconds for this to become "free" // wait up to 30 seconds for this to become "free"
new RetryablePredicate<Address>(new AddressFree(connection), 30, 2, TimeUnit.SECONDS) new RetryablePredicate<Address>(new AddressFree(connection), 30, 2,
.apply(ip); TimeUnit.SECONDS).apply(ip);
refreshIpAndReturnAllAddresses(); refreshIpAndReturnAllAddresses();
assertEquals(ip.getInstanceId(), null); assertEquals(ip.getInstanceId(), null);
} catch (IllegalStateException e) { } catch (IllegalStateException e) {
if (HttpResponseException.class.cast(e.getCause()).getResponse().getStatusCode() == 409) { if (HttpResponseException.class.cast(e.getCause()).getResponse()
ip = Iterables.find(connection.listAddresses(), new Predicate<Address>() { .getStatusCode() == 409) {
ip = Iterables.find(connection.listAddresses(),
new Predicate<Address>() {
@Override @Override
public boolean apply(Address input) { public boolean apply(Address input) {
return input.getState() == Address.State.FREE; return input.getState() == Address.State.FREE;
} }
}); });
} else { } else {
throw e; throw e;
} }
@ -246,18 +257,21 @@ public class IBMDeveloperCloudClientLiveTest {
Set<? extends Address> allAddresses = refreshIpAndReturnAllAddresses(); Set<? extends Address> allAddresses = refreshIpAndReturnAllAddresses();
assert (allAddresses.contains(ip)) : String.format("ip %s not in %s", ip, allAddresses); assert (allAddresses.contains(ip)) : String.format("ip %s not in %s", ip,
allAddresses);
} }
@Test(enabled = false, dependsOnMethods = "testGetLocation") @Test(enabled = false, dependsOnMethods = "testGetLocation")
public void testCreateVolume() throws Exception { public void testCreateVolume() throws Exception {
try { try {
volume = connection.createVolumeInLocation(location.getId(), TAG, "EXT3", "SMALL"); volume = connection.createVolumeInLocation(location.getId(), TAG,
"EXT3", "SMALL");
// wait up to 5 minutes for this to become "unmounted" // wait up to 5 minutes for this to become "unmounted"
assert new RetryablePredicate<Volume>(new VolumeUnmounted(connection), 300, 5, assert new RetryablePredicate<Volume>(new VolumeUnmounted(connection),
TimeUnit.SECONDS).apply(volume); 300, 5, TimeUnit.SECONDS).apply(volume);
} catch (IllegalStateException e) { } catch (IllegalStateException e) {
if (HttpResponseException.class.cast(e.getCause()).getResponse().getStatusCode() == 409) { if (HttpResponseException.class.cast(e.getCause()).getResponse()
.getStatusCode() == 409) {
Set<? extends Volume> volumes = connection.listVolumes(); Set<? extends Volume> volumes = connection.listVolumes();
try { try {
volume = Iterables.find(volumes, new Predicate<Volume>() { volume = Iterables.find(volumes, new Predicate<Volume>() {
@ -269,7 +283,8 @@ public class IBMDeveloperCloudClientLiveTest {
}); });
} catch (NoSuchElementException ex) { } catch (NoSuchElementException ex) {
throw new RuntimeException("no unmounted volumes in: " + volumes, e); throw new RuntimeException(
"no unmounted volumes in: " + volumes, e);
} }
} else { } else {
throw e; throw e;
@ -291,18 +306,29 @@ public class IBMDeveloperCloudClientLiveTest {
}); });
assert (allVolumes.contains(volume)) : String.format("volume %s not in %s", volume, volume); assert (allVolumes.contains(volume)) : String.format(
"volume %s not in %s", volume, volume);
} }
private static final String IMAGE_ID = "11";// Rational Insight private static final String IMAGE_ID = "11";// Rational Insight
@Test(dependsOnMethods = "testAddPublicKey") @Test(dependsOnMethods = { "testAddPublicKey", "testAllocateIpAddress" })
public void testCreateInstance() throws Exception { public void testCreateInstance() throws Exception {
instance = connection.createInstanceInLocation(location.getId(), TAG, IMAGE_ID, SIZE, for (Instance instance : connection.listInstances()) {
configurationData( try {
ImmutableMap.of("insight_admin_password", "myPassword1", connection.deleteInstance(instance.getId());
"db2_admin_password", "myPassword2", "report_user_password", } catch (Exception e) {
"myPassword3")).authorizePublicKey(key.getName()));
}
}
System.err.println(connection.getImage(IMAGE_ID));
instance = connection.createInstanceInLocation(location.getId(), TAG,
IMAGE_ID, SIZE, configurationData(
ImmutableMap.of("insight_admin_password", "myPassword1",
"db2_admin_password", "myPassword2",
"report_user_password", "myPassword3"))
.authorizePublicKey(key.getName()).attachIp(ip.getId()));
try { try {
assertIpHostAndStatusNEW(instance); assertIpHostAndStatusNEW(instance);
assertConsistent(instance, TAG); assertConsistent(instance, TAG);
@ -313,12 +339,14 @@ public class IBMDeveloperCloudClientLiveTest {
System.err.println(instance); System.err.println(instance);
throw e; throw e;
} }
long start = System.currentTimeMillis();
assert new RetryablePredicate<Instance>(new InstanceActive(connection), 600, 2,
TimeUnit.SECONDS).apply(instance) : connection.getInstance(instance.getId());
System.out.println(((System.currentTimeMillis() - start) / 1000) + " seconds"); long start = System.currentTimeMillis();
assert new RetryablePredicate<Instance>(new InstanceActive(connection),
600, 2, TimeUnit.SECONDS).apply(instance) : connection
.getInstance(instance.getId());
System.out.println(((System.currentTimeMillis() - start) / 1000)
+ " seconds");
try { try {
assertIpHostAndStatusACTIVE(instance); assertIpHostAndStatusACTIVE(instance);
@ -364,18 +392,21 @@ public class IBMDeveloperCloudClientLiveTest {
/** /**
* cannot run an instance due to 500 errors: * cannot run an instance due to 500 errors:
* *
* http://www-180.ibm.com/cloud/enterprise/beta/ram/community/discussionTopic.faces?guid={ * http://www-180.ibm.com/cloud/enterprise/beta/ram/community/discussionTopic
* .faces?guid={
* DA689AEE-783C-6FE7-6F9F-DFEE9763F806}&v=1&fid=1068&tid=1523#topic * DA689AEE-783C-6FE7-6F9F-DFEE9763F806}&v=1&fid=1068&tid=1523#topic
*/ */
@Test(enabled = false, dependsOnMethods = { "testAddPublicKey", "testAllocateIpAddress", @Test(enabled = false, dependsOnMethods = { "testAddPublicKey",
"testCreateVolume" }) "testAllocateIpAddress", "testCreateVolume" })
public void testCreateInstanceWithVolume() throws Exception { public void testCreateInstanceWithVolume() throws Exception {
instance2 = connection.createInstanceInLocation(location.getId(), TAG, IMAGE_ID, SIZE, instance2 = connection.createInstanceInLocation(location.getId(), TAG,
attachIp(ip.getId()).authorizePublicKey(key.getName()).mountVolume(volume.getId(), IMAGE_ID, SIZE, attachIp(ip.getId()).authorizePublicKey(
"/mnt").configurationData( key.getName()).mountVolume(volume.getId(), "/mnt")
ImmutableMap.of("insight_admin_password", "myPassword1", .configurationData(
"db2_admin_password", "myPassword2", "report_user_password", ImmutableMap.of("insight_admin_password",
"myPassword3"))); "myPassword1", "db2_admin_password",
"myPassword2", "report_user_password",
"myPassword3")));
// //
volume = connection.getVolume(volume.getId()); volume = connection.getVolume(volume.getId());
@ -410,12 +441,14 @@ public class IBMDeveloperCloudClientLiveTest {
} catch (Exception e) { } catch (Exception e) {
} }
if (ip != null)
try {
connection.releaseAddress(ip.getId());
} catch (Exception e) {
} // resource contention on ip addresses... lets save it
// if (ip != null)
// try {
// connection.releaseAddress(ip.getId());
// } catch (Exception e) {
//
// }
if (key != null) if (key != null)
try { try {
connection.deleteKey(key.getName()); connection.deleteKey(key.getName());
@ -440,14 +473,16 @@ public class IBMDeveloperCloudClientLiveTest {
protected void setupKeyPair() throws FileNotFoundException, IOException { protected void setupKeyPair() throws FileNotFoundException, IOException {
String secretKeyFile; String secretKeyFile;
try { try {
secretKeyFile = checkNotNull(System.getProperty("jclouds.test.ssh.keyfile"), secretKeyFile = checkNotNull(System
"jclouds.test.ssh.keyfile"); .getProperty("jclouds.test.ssh.keyfile"),
"jclouds.test.ssh.keyfile");
} catch (NullPointerException e) { } catch (NullPointerException e) {
secretKeyFile = System.getProperty("user.home") + "/.ssh/id_rsa"; secretKeyFile = System.getProperty("user.home") + "/.ssh/id_rsa";
} }
String secret = Files.toString(new File(secretKeyFile), Charsets.UTF_8); String secret = Files.toString(new File(secretKeyFile), Charsets.UTF_8);
assert secret.startsWith("-----BEGIN RSA PRIVATE KEY-----") : "invalid key:\n" + secret; assert secret.startsWith("-----BEGIN RSA PRIVATE KEY-----") : "invalid key:\n"
keyPair = ImmutableMap.<String, String> of("private", secret, "public", Files.toString( + secret;
new File(secretKeyFile + ".pub"), Charsets.UTF_8)); keyPair = ImmutableMap.<String, String> of("private", secret, "public",
Files.toString(new File(secretKeyFile + ".pub"), Charsets.UTF_8));
} }
} }

View File

@ -25,7 +25,6 @@ import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService; import java.util.concurrent.ExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException; import java.util.concurrent.TimeoutException;
import java.util.regex.Matcher; import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
@ -38,6 +37,7 @@ import javax.inject.Singleton;
import org.jclouds.Constants; import org.jclouds.Constants;
import org.jclouds.compute.ComputeServiceContext; import org.jclouds.compute.ComputeServiceContext;
import org.jclouds.compute.LoadBalancerService; import org.jclouds.compute.LoadBalancerService;
import org.jclouds.compute.config.ComputeServiceTimeoutsModule;
import org.jclouds.compute.domain.Architecture; import org.jclouds.compute.domain.Architecture;
import org.jclouds.compute.domain.ComputeMetadata; import org.jclouds.compute.domain.ComputeMetadata;
import org.jclouds.compute.domain.Image; import org.jclouds.compute.domain.Image;
@ -54,8 +54,6 @@ import org.jclouds.compute.internal.BaseComputeService;
import org.jclouds.compute.internal.ComputeServiceContextImpl; import org.jclouds.compute.internal.ComputeServiceContextImpl;
import org.jclouds.compute.predicates.ImagePredicates; import org.jclouds.compute.predicates.ImagePredicates;
import org.jclouds.compute.predicates.NodePredicates; 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.reference.ComputeServiceConstants;
import org.jclouds.compute.strategy.AddNodeWithTagStrategy; import org.jclouds.compute.strategy.AddNodeWithTagStrategy;
import org.jclouds.compute.strategy.DestroyNodeStrategy; import org.jclouds.compute.strategy.DestroyNodeStrategy;
@ -67,7 +65,6 @@ import org.jclouds.domain.Location;
import org.jclouds.domain.LocationScope; import org.jclouds.domain.LocationScope;
import org.jclouds.domain.internal.LocationImpl; import org.jclouds.domain.internal.LocationImpl;
import org.jclouds.logging.Logger; import org.jclouds.logging.Logger;
import org.jclouds.predicates.RetryablePredicate;
import org.jclouds.rackspace.cloudservers.CloudServersAsyncClient; import org.jclouds.rackspace.cloudservers.CloudServersAsyncClient;
import org.jclouds.rackspace.cloudservers.CloudServersClient; import org.jclouds.rackspace.cloudservers.CloudServersClient;
import org.jclouds.rackspace.cloudservers.compute.functions.ServerToNodeMetadata; import org.jclouds.rackspace.cloudservers.compute.functions.ServerToNodeMetadata;
@ -82,7 +79,6 @@ import org.jclouds.rackspace.reference.RackspaceConstants;
import com.google.common.base.Function; import com.google.common.base.Function;
import com.google.common.base.Predicate; import com.google.common.base.Predicate;
import com.google.common.base.Predicates;
import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Iterables; import com.google.common.collect.Iterables;
import com.google.common.collect.Sets; import com.google.common.collect.Sets;
@ -92,12 +88,13 @@ import com.google.inject.TypeLiteral;
import com.google.inject.util.Providers; import com.google.inject.util.Providers;
/** /**
* Configures the {@link CloudServersComputeServiceContext}; requires {@link BaseComputeService} * Configures the {@link CloudServersComputeServiceContext}; requires
* bound. * {@link BaseComputeService} bound.
* *
* @author Adrian Cole * @author Adrian Cole
*/ */
public class CloudServersComputeServiceContextModule extends CloudServersContextModule { public class CloudServersComputeServiceContextModule extends
CloudServersContextModule {
private final String providerName; private final String providerName;
public CloudServersComputeServiceContextModule(String providerName) { public CloudServersComputeServiceContextModule(String providerName) {
@ -107,18 +104,22 @@ public class CloudServersComputeServiceContextModule extends CloudServersContext
@Override @Override
protected void configure() { protected void configure() {
super.configure(); super.configure();
install(new ComputeServiceTimeoutsModule());
install(new RackspaceLocationsModule(providerName)); install(new RackspaceLocationsModule(providerName));
bind(new TypeLiteral<Function<Server, NodeMetadata>>() { bind(new TypeLiteral<Function<Server, NodeMetadata>>() {
}).to(ServerToNodeMetadata.class); }).to(ServerToNodeMetadata.class);
bind(LoadBalancerService.class).toProvider(Providers.<LoadBalancerService> of(null)); bind(LoadBalancerService.class).toProvider(
Providers.<LoadBalancerService> of(null));
bind(new TypeLiteral<ComputeServiceContext>() { bind(new TypeLiteral<ComputeServiceContext>() {
}) })
.to( .to(
new TypeLiteral<ComputeServiceContextImpl<CloudServersClient, CloudServersAsyncClient>>() { new TypeLiteral<ComputeServiceContextImpl<CloudServersClient, CloudServersAsyncClient>>() {
}).in(Scopes.SINGLETON); }).in(Scopes.SINGLETON);
bind(AddNodeWithTagStrategy.class).to(CloudServersAddNodeWithTagStrategy.class); bind(AddNodeWithTagStrategy.class).to(
CloudServersAddNodeWithTagStrategy.class);
bind(ListNodesStrategy.class).to(CloudServersListNodesStrategy.class); bind(ListNodesStrategy.class).to(CloudServersListNodesStrategy.class);
bind(GetNodeMetadataStrategy.class).to(CloudServersGetNodeMetadataStrategy.class); bind(GetNodeMetadataStrategy.class).to(
CloudServersGetNodeMetadataStrategy.class);
bind(RebootNodeStrategy.class).to(CloudServersRebootNodeStrategy.class); bind(RebootNodeStrategy.class).to(CloudServersRebootNodeStrategy.class);
bind(DestroyNodeStrategy.class).to(CloudServersDestroyNodeStrategy.class); bind(DestroyNodeStrategy.class).to(CloudServersDestroyNodeStrategy.class);
} }
@ -132,93 +133,93 @@ public class CloudServersComputeServiceContextModule extends CloudServersContext
@Provides @Provides
@Named("NAMING_CONVENTION") @Named("NAMING_CONVENTION")
@Singleton @Singleton
String provideNamingConvention(@Named(RackspaceConstants.PROPERTY_RACKSPACE_USER) String account) { String provideNamingConvention(
@Named(RackspaceConstants.PROPERTY_RACKSPACE_USER) String account) {
return account + "-%s-%s"; return account + "-%s-%s";
} }
@Singleton @Singleton
public static class CloudServersRebootNodeStrategy implements RebootNodeStrategy { public static class CloudServersRebootNodeStrategy implements
RebootNodeStrategy {
private final CloudServersClient client; private final CloudServersClient client;
private final Predicate<Server> serverActive; private final GetNodeMetadataStrategy getNode;
@Inject @Inject
protected CloudServersRebootNodeStrategy(CloudServersClient client, protected CloudServersRebootNodeStrategy(CloudServersClient client,
@Named("ACTIVE") Predicate<Server> serverActive) { GetNodeMetadataStrategy getNode) {
this.client = client; this.client = client;
this.serverActive = serverActive; this.getNode = getNode;
} }
@Override @Override
public boolean execute(String id) { public NodeMetadata execute(String id) {
int serverId = Integer.parseInt(id); int serverId = Integer.parseInt(id);
// if false server wasn't around in the first place // if false server wasn't around in the first place
client.rebootServer(serverId, RebootType.HARD); client.rebootServer(serverId, RebootType.HARD);
Server server = client.getServer(serverId); return getNode.execute(id);
return server == null ? false : serverActive.apply(server);
} }
} }
@Singleton @Singleton
public static class CloudServersDestroyNodeStrategy implements DestroyNodeStrategy { public static class CloudServersDestroyNodeStrategy implements
DestroyNodeStrategy {
private final CloudServersClient client; private final CloudServersClient client;
private final Predicate<Server> serverDeleted; private final GetNodeMetadataStrategy getNode;
@Inject @Inject
protected CloudServersDestroyNodeStrategy(CloudServersClient client, protected CloudServersDestroyNodeStrategy(CloudServersClient client,
@Named("DELETED") Predicate<Server> serverDeleted) { GetNodeMetadataStrategy getNode) {
this.client = client; this.client = client;
this.serverDeleted = serverDeleted; this.getNode = getNode;
} }
@Override @Override
public boolean execute(String id) { public NodeMetadata execute(String id) {
int serverId = Integer.parseInt(id); int serverId = Integer.parseInt(id);
// if false server wasn't around in the first place // if false server wasn't around in the first place
if (!client.deleteServer(serverId)) client.deleteServer(serverId);
return false; return getNode.execute(id);
Server server = client.getServer(serverId);
return server == null ? false : serverDeleted.apply(server);
} }
} }
@Singleton @Singleton
public static class CloudServersAddNodeWithTagStrategy implements AddNodeWithTagStrategy { public static class CloudServersAddNodeWithTagStrategy implements
AddNodeWithTagStrategy {
private final CloudServersClient client; private final CloudServersClient client;
private final Predicate<Server> serverActive;
@Inject @Inject
protected CloudServersAddNodeWithTagStrategy(CloudServersClient client, protected CloudServersAddNodeWithTagStrategy(CloudServersClient client) {
@Named("ACTIVE") Predicate<Server> serverActive) {
this.client = checkNotNull(client, "client"); this.client = checkNotNull(client, "client");
this.serverActive = checkNotNull(serverActive, "serverActive");
} }
@Override @Override
public NodeMetadata execute(String tag, String name, Template template) { public NodeMetadata execute(String tag, String name, Template template) {
Server server = client.createServer(name, Integer.parseInt(template.getImage() Server server = client.createServer(name, Integer.parseInt(template
.getProviderId()), Integer.parseInt(template.getSize().getProviderId())); .getImage().getProviderId()), Integer.parseInt(template
serverActive.apply(server); .getSize().getProviderId()));
return new NodeMetadataImpl(server.getId() + "", name, server.getId() + "", return new NodeMetadataImpl(server.getId() + "", name, server.getId()
new LocationImpl(LocationScope.HOST, server.getHostId(), server.getHostId(), + "", new LocationImpl(LocationScope.HOST, server.getHostId(),
template.getLocation()), null, server.getMetadata(), tag, template server.getHostId(), template.getLocation()), null, server
.getImage(), NodeState.RUNNING, server.getAddresses() .getMetadata(), tag, template.getImage(), NodeState.PENDING,
.getPublicAddresses(), server.getAddresses().getPrivateAddresses(), server.getAddresses().getPublicAddresses(), server
ImmutableMap.<String, String> of(), .getAddresses().getPrivateAddresses(), ImmutableMap
new Credentials("root", server.getAdminPass())); .<String, String> of(), new Credentials("root", server
.getAdminPass()));
} }
} }
@Singleton @Singleton
public static class CloudServersListNodesStrategy implements ListNodesStrategy { public static class CloudServersListNodesStrategy implements
ListNodesStrategy {
private final CloudServersClient client; private final CloudServersClient client;
private final Function<Server, NodeMetadata> serverToNodeMetadata; private final Function<Server, NodeMetadata> serverToNodeMetadata;
@Inject @Inject
protected CloudServersListNodesStrategy(CloudServersClient client, protected CloudServersListNodesStrategy(CloudServersClient client,
Function<Server, NodeMetadata> serverToNodeMetadata) { Function<Server, NodeMetadata> serverToNodeMetadata) {
this.client = client; this.client = client;
this.serverToNodeMetadata = serverToNodeMetadata; this.serverToNodeMetadata = serverToNodeMetadata;
} }
@ -230,21 +231,23 @@ public class CloudServersComputeServiceContextModule extends CloudServersContext
@Override @Override
public Iterable<? extends NodeMetadata> listDetailsOnNodesMatching( public Iterable<? extends NodeMetadata> listDetailsOnNodesMatching(
Predicate<ComputeMetadata> filter) { Predicate<ComputeMetadata> filter) {
return Iterables.filter(Iterables.transform(client.listServers(ListOptions.Builder return Iterables.filter(Iterables.transform(client
.withDetails()), serverToNodeMetadata), filter); .listServers(ListOptions.Builder.withDetails()),
serverToNodeMetadata), filter);
} }
} }
@Singleton @Singleton
public static class CloudServersGetNodeMetadataStrategy implements GetNodeMetadataStrategy { public static class CloudServersGetNodeMetadataStrategy implements
GetNodeMetadataStrategy {
private final CloudServersClient client; private final CloudServersClient client;
private final Function<Server, NodeMetadata> serverToNodeMetadata; private final Function<Server, NodeMetadata> serverToNodeMetadata;
@Inject @Inject
protected CloudServersGetNodeMetadataStrategy(CloudServersClient client, protected CloudServersGetNodeMetadataStrategy(CloudServersClient client,
Function<Server, NodeMetadata> serverToNodeMetadata) { Function<Server, NodeMetadata> serverToNodeMetadata) {
this.client = client; this.client = client;
this.serverToNodeMetadata = serverToNodeMetadata; this.serverToNodeMetadata = serverToNodeMetadata;
} }
@ -260,38 +263,30 @@ public class CloudServersComputeServiceContextModule extends CloudServersContext
@Singleton @Singleton
@Provides @Provides
Map<ServerStatus, NodeState> provideServerToNodeState() { Map<ServerStatus, NodeState> provideServerToNodeState() {
return ImmutableMap.<ServerStatus, NodeState> builder().put(ServerStatus.ACTIVE, return ImmutableMap.<ServerStatus, NodeState> builder().put(
NodeState.RUNNING)// ServerStatus.ACTIVE, NodeState.RUNNING)//
.put(ServerStatus.SUSPENDED, NodeState.SUSPENDED)// .put(ServerStatus.SUSPENDED, NodeState.SUSPENDED)//
.put(ServerStatus.DELETED, NodeState.TERMINATED)// .put(ServerStatus.DELETED, NodeState.TERMINATED)//
.put(ServerStatus.QUEUE_RESIZE, NodeState.PENDING)// .put(ServerStatus.QUEUE_RESIZE, NodeState.PENDING)//
.put(ServerStatus.PREP_RESIZE, NodeState.PENDING)// .put(ServerStatus.PREP_RESIZE, NodeState.PENDING)//
.put(ServerStatus.RESIZE, NodeState.PENDING)// .put(ServerStatus.RESIZE, NodeState.PENDING)//
.put(ServerStatus.VERIFY_RESIZE, NodeState.PENDING)// .put(ServerStatus.VERIFY_RESIZE, NodeState.PENDING)//
.put(ServerStatus.QUEUE_MOVE, NodeState.PENDING)// .put(ServerStatus.QUEUE_MOVE, NodeState.PENDING)//
.put(ServerStatus.PREP_MOVE, NodeState.PENDING)// .put(ServerStatus.PREP_MOVE, NodeState.PENDING)//
.put(ServerStatus.MOVE, NodeState.PENDING)// .put(ServerStatus.MOVE, NodeState.PENDING)//
.put(ServerStatus.VERIFY_MOVE, NodeState.PENDING)// .put(ServerStatus.VERIFY_MOVE, NodeState.PENDING)//
.put(ServerStatus.RESCUE, NodeState.PENDING)// .put(ServerStatus.RESCUE, NodeState.PENDING)//
.put(ServerStatus.ERROR, NodeState.ERROR)// .put(ServerStatus.ERROR, NodeState.ERROR)//
.put(ServerStatus.BUILD, NodeState.PENDING)// .put(ServerStatus.BUILD, NodeState.PENDING)//
.put(ServerStatus.RESTORING, NodeState.PENDING)// .put(ServerStatus.RESTORING, NodeState.PENDING)//
.put(ServerStatus.PASSWORD, NodeState.PENDING)// .put(ServerStatus.PASSWORD, NodeState.PENDING)//
.put(ServerStatus.REBUILD, NodeState.PENDING)// .put(ServerStatus.REBUILD, NodeState.PENDING)//
.put(ServerStatus.DELETE_IP, NodeState.PENDING)// .put(ServerStatus.DELETE_IP, NodeState.PENDING)//
.put(ServerStatus.SHARE_IP_NO_CONFIG, NodeState.PENDING)// .put(ServerStatus.SHARE_IP_NO_CONFIG, NodeState.PENDING)//
.put(ServerStatus.SHARE_IP, NodeState.PENDING)// .put(ServerStatus.SHARE_IP, NodeState.PENDING)//
.put(ServerStatus.REBOOT, NodeState.PENDING)// .put(ServerStatus.REBOOT, NodeState.PENDING)//
.put(ServerStatus.HARD_REBOOT, NodeState.PENDING)// .put(ServerStatus.HARD_REBOOT, NodeState.PENDING)//
.put(ServerStatus.UNKNOWN, NodeState.UNKNOWN).build(); .put(ServerStatus.UNKNOWN, NodeState.UNKNOWN).build();
}
@Provides
@Singleton
@Named("NOT_RUNNING")
protected Predicate<CommandUsingClient> runScriptRunning(ScriptStatusReturnsZero stateRunning) {
return new RetryablePredicate<CommandUsingClient>(Predicates.not(stateRunning), 600, 3,
TimeUnit.SECONDS);
} }
@Provides @Provides
@ -307,17 +302,19 @@ public class CloudServersComputeServiceContextModule extends CloudServersContext
@Provides @Provides
@Singleton @Singleton
protected Set<? extends Size> provideSizes(CloudServersClient sync, Set<? extends Image> images, protected Set<? extends Size> provideSizes(CloudServersClient sync,
Location location, LogHolder holder, Set<? extends Image> images, Location location, LogHolder holder,
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService executor, @Named(Constants.PROPERTY_USER_THREADS) ExecutorService executor,
Function<ComputeMetadata, String> indexer) throws InterruptedException, Function<ComputeMetadata, String> indexer)
TimeoutException, ExecutionException { throws InterruptedException, TimeoutException, ExecutionException {
final Set<Size> sizes = Sets.newHashSet(); final Set<Size> sizes = Sets.newHashSet();
holder.logger.debug(">> providing sizes"); holder.logger.debug(">> providing sizes");
for (final Flavor from : sync.listFlavors(ListOptions.Builder.withDetails())) { for (final Flavor from : sync.listFlavors(ListOptions.Builder
sizes.add(new SizeImpl(from.getId() + "", from.getName(), from.getId() + "", location, .withDetails())) {
null, ImmutableMap.<String, String> of(), from.getDisk() / 10, from.getRam(), sizes.add(new SizeImpl(from.getId() + "", from.getName(), from.getId()
from.getDisk(), ImagePredicates.any())); + "", location, null, ImmutableMap.<String, String> of(), from
.getDisk() / 10, from.getRam(), from.getDisk(), ImagePredicates
.any()));
} }
holder.logger.debug("<< sizes(%d)", sizes.size()); holder.logger.debug("<< sizes(%d)", sizes.size());
return sizes; return sizes;
@ -329,17 +326,19 @@ public class CloudServersComputeServiceContextModule extends CloudServersContext
protected Logger logger = Logger.NULL; protected Logger logger = Logger.NULL;
} }
public static final Pattern RACKSPACE_PATTERN = Pattern.compile("(([^ ]*) .*)"); public static final Pattern RACKSPACE_PATTERN = Pattern
.compile("(([^ ]*) .*)");
@Provides @Provides
@Singleton @Singleton
protected Set<? extends Image> provideImages(final CloudServersClient sync, Location location, protected Set<? extends Image> provideImages(final CloudServersClient sync,
LogHolder holder, Function<ComputeMetadata, String> indexer) Location location, LogHolder holder,
throws InterruptedException, ExecutionException, TimeoutException { Function<ComputeMetadata, String> indexer)
throws InterruptedException, ExecutionException, TimeoutException {
final Set<Image> images = Sets.newHashSet(); final Set<Image> images = Sets.newHashSet();
holder.logger.debug(">> providing images"); holder.logger.debug(">> providing images");
for (final org.jclouds.rackspace.cloudservers.domain.Image from : sync for (final org.jclouds.rackspace.cloudservers.domain.Image from : sync
.listImages(ListOptions.Builder.withDetails())) { .listImages(ListOptions.Builder.withDetails())) {
OsFamily os = null; OsFamily os = null;
Architecture arch = Architecture.X86_64; Architecture arch = Architecture.X86_64;
String osDescription = ""; String osDescription = "";
@ -357,9 +356,11 @@ public class CloudServersComputeServiceContextModule extends CloudServersContext
holder.logger.debug("<< didn't match os(%s)", matcher.group(2)); holder.logger.debug("<< didn't match os(%s)", matcher.group(2));
} }
} }
images.add(new ImageImpl(from.getId() + "", from.getName(), from.getId() + "", location, images.add(new ImageImpl(from.getId() + "", from.getName(), from
null, ImmutableMap.<String, String> of(), from.getName(), version, os, .getId()
osDescription, arch, new Credentials("root", null))); + "", location, null, ImmutableMap.<String, String> of(), from
.getName(), version, os, osDescription, arch, new Credentials(
"root", null)));
} }
holder.logger.debug("<< images(%d)", images.size()); holder.logger.debug("<< images(%d)", images.size());
return images; return images;

View File

@ -18,31 +18,17 @@
*/ */
package org.jclouds.rackspace.cloudservers.config; package org.jclouds.rackspace.cloudservers.config;
import java.util.concurrent.TimeUnit;
import javax.inject.Named;
import javax.inject.Singleton;
import org.jclouds.http.HttpErrorHandler; import org.jclouds.http.HttpErrorHandler;
import org.jclouds.http.RequiresHttp; import org.jclouds.http.RequiresHttp;
import org.jclouds.http.annotation.ClientError; import org.jclouds.http.annotation.ClientError;
import org.jclouds.http.annotation.Redirection; import org.jclouds.http.annotation.Redirection;
import org.jclouds.http.annotation.ServerError; import org.jclouds.http.annotation.ServerError;
import org.jclouds.net.IPSocket;
import org.jclouds.predicates.RetryablePredicate;
import org.jclouds.predicates.SocketOpen;
import org.jclouds.rackspace.cloudservers.CloudServersAsyncClient; import org.jclouds.rackspace.cloudservers.CloudServersAsyncClient;
import org.jclouds.rackspace.cloudservers.CloudServersClient; import org.jclouds.rackspace.cloudservers.CloudServersClient;
import org.jclouds.rackspace.cloudservers.domain.Server;
import org.jclouds.rackspace.cloudservers.handlers.ParseCloudServersErrorFromHttpResponse; import org.jclouds.rackspace.cloudservers.handlers.ParseCloudServersErrorFromHttpResponse;
import org.jclouds.rackspace.cloudservers.predicates.ServerActive;
import org.jclouds.rackspace.cloudservers.predicates.ServerDeleted;
import org.jclouds.rest.ConfiguresRestClient; import org.jclouds.rest.ConfiguresRestClient;
import org.jclouds.rest.config.RestClientModule; import org.jclouds.rest.config.RestClientModule;
import com.google.common.base.Predicate;
import com.google.inject.Provides;
/** /**
* *
* @author Adrian Cole * @author Adrian Cole
@ -56,26 +42,6 @@ public class CloudServersRestClientModule extends
super(CloudServersClient.class, CloudServersAsyncClient.class); super(CloudServersClient.class, CloudServersAsyncClient.class);
} }
@Provides
@Singleton
@Named("ACTIVE")
protected Predicate<Server> serverRunning(ServerActive stateRunning) {
return new RetryablePredicate<Server>(stateRunning, 600, 1, TimeUnit.SECONDS);
}
@Provides
@Singleton
@Named("DELETED")
protected Predicate<Server> serverDeleted(ServerDeleted stateDeleted) {
return new RetryablePredicate<Server>(stateDeleted, 600, 50, TimeUnit.MILLISECONDS);
}
@Provides
@Singleton
protected Predicate<IPSocket> socketTester(SocketOpen open) {
return new RetryablePredicate<IPSocket>(open, 130, 1, TimeUnit.SECONDS);
}
@Override @Override
protected void bindErrorHandlers() { protected void bindErrorHandlers() {
bind(HttpErrorHandler.class).annotatedWith(Redirection.class).to( bind(HttpErrorHandler.class).annotatedWith(Redirection.class).to(

View File

@ -27,7 +27,6 @@ import java.util.NoSuchElementException;
import java.util.Set; import java.util.Set;
import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService; import java.util.concurrent.ExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException; import java.util.concurrent.TimeoutException;
import java.util.regex.Matcher; import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
@ -40,6 +39,7 @@ import javax.inject.Singleton;
import org.jclouds.Constants; import org.jclouds.Constants;
import org.jclouds.compute.ComputeServiceContext; import org.jclouds.compute.ComputeServiceContext;
import org.jclouds.compute.LoadBalancerService; import org.jclouds.compute.LoadBalancerService;
import org.jclouds.compute.config.ComputeServiceTimeoutsModule;
import org.jclouds.compute.domain.Architecture; import org.jclouds.compute.domain.Architecture;
import org.jclouds.compute.domain.ComputeMetadata; import org.jclouds.compute.domain.ComputeMetadata;
import org.jclouds.compute.domain.Image; import org.jclouds.compute.domain.Image;
@ -55,8 +55,6 @@ import org.jclouds.compute.domain.internal.SizeImpl;
import org.jclouds.compute.internal.ComputeServiceContextImpl; import org.jclouds.compute.internal.ComputeServiceContextImpl;
import org.jclouds.compute.predicates.ImagePredicates; import org.jclouds.compute.predicates.ImagePredicates;
import org.jclouds.compute.predicates.NodePredicates; 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.reference.ComputeServiceConstants;
import org.jclouds.compute.strategy.AddNodeWithTagStrategy; import org.jclouds.compute.strategy.AddNodeWithTagStrategy;
import org.jclouds.compute.strategy.DestroyNodeStrategy; import org.jclouds.compute.strategy.DestroyNodeStrategy;
@ -68,7 +66,6 @@ import org.jclouds.domain.Location;
import org.jclouds.domain.LocationScope; import org.jclouds.domain.LocationScope;
import org.jclouds.domain.internal.LocationImpl; import org.jclouds.domain.internal.LocationImpl;
import org.jclouds.logging.Logger; import org.jclouds.logging.Logger;
import org.jclouds.predicates.RetryablePredicate;
import org.jclouds.rimuhosting.miro.RimuHostingAsyncClient; import org.jclouds.rimuhosting.miro.RimuHostingAsyncClient;
import org.jclouds.rimuhosting.miro.RimuHostingClient; import org.jclouds.rimuhosting.miro.RimuHostingClient;
import org.jclouds.rimuhosting.miro.config.RimuHostingContextModule; import org.jclouds.rimuhosting.miro.config.RimuHostingContextModule;
@ -79,7 +76,6 @@ import org.jclouds.rimuhosting.miro.domain.internal.RunningState;
import com.google.common.base.Function; import com.google.common.base.Function;
import com.google.common.base.Predicate; import com.google.common.base.Predicate;
import com.google.common.base.Predicates;
import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet; import com.google.common.collect.ImmutableSet;
@ -96,7 +92,8 @@ import com.google.inject.util.Providers;
* *
* @author Adrian Cole * @author Adrian Cole
*/ */
public class RimuHostingComputeServiceContextModule extends RimuHostingContextModule { public class RimuHostingComputeServiceContextModule extends
RimuHostingContextModule {
private final String providerName; private final String providerName;
public RimuHostingComputeServiceContextModule(String providerName) { public RimuHostingComputeServiceContextModule(String providerName) {
@ -106,19 +103,23 @@ public class RimuHostingComputeServiceContextModule extends RimuHostingContextMo
@Override @Override
protected void configure() { protected void configure() {
super.configure(); super.configure();
install(new ComputeServiceTimeoutsModule());
bind(new TypeLiteral<Function<Server, NodeMetadata>>() { bind(new TypeLiteral<Function<Server, NodeMetadata>>() {
}).to(ServerToNodeMetadata.class); }).to(ServerToNodeMetadata.class);
bind(LoadBalancerService.class).toProvider(Providers.<LoadBalancerService> of(null)); bind(LoadBalancerService.class).toProvider(
Providers.<LoadBalancerService> of(null));
bind(new TypeLiteral<ComputeServiceContext>() { bind(new TypeLiteral<ComputeServiceContext>() {
}) })
.to( .to(
new TypeLiteral<ComputeServiceContextImpl<RimuHostingClient, RimuHostingAsyncClient>>() { new TypeLiteral<ComputeServiceContextImpl<RimuHostingClient, RimuHostingAsyncClient>>() {
}).in(Scopes.SINGLETON); }).in(Scopes.SINGLETON);
bind(new TypeLiteral<Function<Server, Iterable<String>>>() { bind(new TypeLiteral<Function<Server, Iterable<String>>>() {
}).to(ServerToPublicAddresses.class); }).to(ServerToPublicAddresses.class);
bind(AddNodeWithTagStrategy.class).to(RimuHostingAddNodeWithTagStrategy.class); bind(AddNodeWithTagStrategy.class).to(
RimuHostingAddNodeWithTagStrategy.class);
bind(ListNodesStrategy.class).to(RimuHostingListNodesStrategy.class); bind(ListNodesStrategy.class).to(RimuHostingListNodesStrategy.class);
bind(GetNodeMetadataStrategy.class).to(RimuHostingGetNodeMetadataStrategy.class); bind(GetNodeMetadataStrategy.class).to(
RimuHostingGetNodeMetadataStrategy.class);
bind(RebootNodeStrategy.class).to(RimuHostingRebootNodeStrategy.class); bind(RebootNodeStrategy.class).to(RimuHostingRebootNodeStrategy.class);
bind(DestroyNodeStrategy.class).to(RimuHostingDestroyNodeStrategy.class); bind(DestroyNodeStrategy.class).to(RimuHostingDestroyNodeStrategy.class);
} }
@ -126,8 +127,8 @@ public class RimuHostingComputeServiceContextModule extends RimuHostingContextMo
@Provides @Provides
@Named("DEFAULT") @Named("DEFAULT")
protected TemplateBuilder provideTemplate(TemplateBuilder template) { protected TemplateBuilder provideTemplate(TemplateBuilder template) {
return template.sizeId("MIRO1B").osFamily(UBUNTU).architecture(Architecture.X86_32) return template.sizeId("MIRO1B").osFamily(UBUNTU).architecture(
.imageNameMatches(".*10\\.?04.*"); Architecture.X86_32).imageNameMatches(".*10\\.?04.*");
} }
@Provides @Provides
@ -138,90 +139,94 @@ public class RimuHostingComputeServiceContextModule extends RimuHostingContextMo
} }
@Singleton @Singleton
public static class RimuHostingRebootNodeStrategy implements RebootNodeStrategy { public static class RimuHostingRebootNodeStrategy implements
RebootNodeStrategy {
private final RimuHostingClient client; private final RimuHostingClient client;
private final GetNodeMetadataStrategy getNode;
@Inject @Inject
protected RimuHostingRebootNodeStrategy(RimuHostingClient client) { protected RimuHostingRebootNodeStrategy(RimuHostingClient client,
GetNodeMetadataStrategy getNode) {
this.client = client; this.client = client;
this.getNode = getNode;
} }
@Override @Override
public boolean execute(String id) { public NodeMetadata execute(String id) {
Long serverId = Long.parseLong(id); Long serverId = Long.parseLong(id);
// if false server wasn't around in the first place // if false server wasn't around in the first place
return client.restartServer(serverId).getState() == RunningState.RUNNING; client.restartServer(serverId).getState();
return getNode.execute(id);
} }
} }
@Singleton @Singleton
public static class RimuHostingDestroyNodeStrategy implements DestroyNodeStrategy { public static class RimuHostingDestroyNodeStrategy implements
DestroyNodeStrategy {
private final RimuHostingClient client; private final RimuHostingClient client;
private final Predicate<Server> serverDestroyed; private final GetNodeMetadataStrategy getNode;
@Inject @Inject
protected RimuHostingDestroyNodeStrategy(RimuHostingClient client, protected RimuHostingDestroyNodeStrategy(RimuHostingClient client,
@Named("DESTROYED") Predicate<Server> serverDestroyed) { GetNodeMetadataStrategy getNode) {
this.client = client; this.client = client;
this.serverDestroyed = serverDestroyed; this.getNode = getNode;
} }
@Override @Override
public boolean execute(String id) { public NodeMetadata execute(String id) {
Long serverId = Long.parseLong(id); Long serverId = Long.parseLong(id);
client.destroyServer(serverId); client.destroyServer(serverId);
return serverDestroyed.apply(client.getServer(serverId)); return getNode.execute(id);
} }
} }
@Singleton @Singleton
public static class RimuHostingAddNodeWithTagStrategy implements AddNodeWithTagStrategy { public static class RimuHostingAddNodeWithTagStrategy implements
AddNodeWithTagStrategy {
private final RimuHostingClient client; private final RimuHostingClient client;
private final Predicate<Server> serverRunning;
private final Function<Server, Iterable<String>> getPublicAddresses; private final Function<Server, Iterable<String>> getPublicAddresses;
private final Map<RunningState, NodeState> runningStateToNodeState; private final Map<RunningState, NodeState> runningStateToNodeState;
@Inject @Inject
protected RimuHostingAddNodeWithTagStrategy(RimuHostingClient client, protected RimuHostingAddNodeWithTagStrategy(RimuHostingClient client,
@Named("RUNNING") Predicate<Server> serverRunning, Function<Server, Iterable<String>> getPublicAddresses,
Function<Server, Iterable<String>> getPublicAddresses, Map<RunningState, NodeState> runningStateToNodeState) {
Map<RunningState, NodeState> runningStateToNodeState) {
this.client = client; this.client = client;
this.serverRunning = serverRunning;
this.getPublicAddresses = getPublicAddresses; this.getPublicAddresses = getPublicAddresses;
this.runningStateToNodeState = runningStateToNodeState; this.runningStateToNodeState = runningStateToNodeState;
} }
@Override @Override
public NodeMetadata execute(String tag, String name, Template template) { public NodeMetadata execute(String tag, String name, Template template) {
NewServerResponse serverResponse = client.createServer(name, checkNotNull(template NewServerResponse serverResponse = client.createServer(name,
.getImage().getProviderId(), "imageId"), checkNotNull(template.getSize() checkNotNull(template.getImage().getProviderId(), "imageId"),
.getProviderId(), "sizeId")); checkNotNull(template.getSize().getProviderId(), "sizeId"));
serverRunning.apply(serverResponse.getServer());
Server server = client.getServer(serverResponse.getServer().getId()); Server server = client.getServer(serverResponse.getServer().getId());
// we have to lookup the new details in order to retrieve the currently assigned ip NodeMetadata node = new NodeMetadataImpl(server.getId().toString(),
// address. name, server.getId().toString(), template.getLocation(), null,
NodeMetadata node = new NodeMetadataImpl(server.getId().toString(), name, server.getId() ImmutableMap.<String, String> of(), tag, template.getImage(),
.toString(), template.getLocation(), null, ImmutableMap.<String, String> of(), runningStateToNodeState.get(server.getState()),
tag, template.getImage(), runningStateToNodeState.get(server.getState()), getPublicAddresses.apply(server), ImmutableList.<String> of(),
getPublicAddresses.apply(server), ImmutableList.<String> of(), ImmutableMap ImmutableMap.<String, String> of(), new Credentials("root",
.<String, String> of(), new Credentials("root", serverResponse serverResponse.getNewInstanceRequest().getCreateOptions()
.getNewInstanceRequest().getCreateOptions().getPassword())); .getPassword()));
return node; return node;
} }
} }
@Singleton @Singleton
public static class RimuHostingListNodesStrategy implements ListNodesStrategy { public static class RimuHostingListNodesStrategy implements
ListNodesStrategy {
private final RimuHostingClient client; private final RimuHostingClient client;
private final Function<Server, NodeMetadata> serverToNodeMetadata; private final Function<Server, NodeMetadata> serverToNodeMetadata;
@Inject @Inject
protected RimuHostingListNodesStrategy(RimuHostingClient client, protected RimuHostingListNodesStrategy(RimuHostingClient client,
Function<Server, NodeMetadata> serverToNodeMetadata) { Function<Server, NodeMetadata> serverToNodeMetadata) {
this.client = client; this.client = client;
this.serverToNodeMetadata = serverToNodeMetadata; this.serverToNodeMetadata = serverToNodeMetadata;
} }
@ -233,22 +238,23 @@ public class RimuHostingComputeServiceContextModule extends RimuHostingContextMo
@Override @Override
public Iterable<? extends NodeMetadata> listDetailsOnNodesMatching( public Iterable<? extends NodeMetadata> listDetailsOnNodesMatching(
Predicate<ComputeMetadata> filter) { Predicate<ComputeMetadata> filter) {
return Iterables.filter(Iterables.transform(client.getServerList(), serverToNodeMetadata), return Iterables.filter(Iterables.transform(client.getServerList(),
filter); serverToNodeMetadata), filter);
} }
} }
@Singleton @Singleton
public static class RimuHostingGetNodeMetadataStrategy implements GetNodeMetadataStrategy { public static class RimuHostingGetNodeMetadataStrategy implements
GetNodeMetadataStrategy {
private final RimuHostingClient client; private final RimuHostingClient client;
private final Function<Server, NodeMetadata> serverToNodeMetadata; private final Function<Server, NodeMetadata> serverToNodeMetadata;
@Inject @Inject
protected RimuHostingGetNodeMetadataStrategy(RimuHostingClient client, protected RimuHostingGetNodeMetadataStrategy(RimuHostingClient client,
Function<Server, NodeMetadata> serverToNodeMetadata) { Function<Server, NodeMetadata> serverToNodeMetadata) {
this.client = client; this.client = client;
this.serverToNodeMetadata = serverToNodeMetadata; this.serverToNodeMetadata = serverToNodeMetadata;
} }
@ -264,16 +270,17 @@ public class RimuHostingComputeServiceContextModule extends RimuHostingContextMo
@Singleton @Singleton
@Provides @Provides
Map<RunningState, NodeState> provideServerToNodeState() { Map<RunningState, NodeState> provideServerToNodeState() {
return ImmutableMap.<RunningState, NodeState> builder().put(RunningState.RUNNING, return ImmutableMap.<RunningState, NodeState> builder().put(
NodeState.RUNNING)// RunningState.RUNNING, NodeState.RUNNING)//
.put(RunningState.NOTRUNNING, NodeState.SUSPENDED)// .put(RunningState.NOTRUNNING, NodeState.SUSPENDED)//
.put(RunningState.POWERCYCLING, NodeState.PENDING)// .put(RunningState.POWERCYCLING, NodeState.PENDING)//
.put(RunningState.RESTARTING, NodeState.PENDING)// .put(RunningState.RESTARTING, NodeState.PENDING)//
.build(); .build();
} }
@Singleton @Singleton
private static class ServerToNodeMetadata implements Function<Server, NodeMetadata> { private static class ServerToNodeMetadata implements
Function<Server, NodeMetadata> {
@Resource @Resource
protected Logger logger = Logger.NULL; protected Logger logger = Logger.NULL;
@ -295,19 +302,22 @@ public class RimuHostingComputeServiceContextModule extends RimuHostingContextMo
@Override @Override
public boolean apply(Image input) { public boolean apply(Image input) {
return input.getProviderId().equals(instance.getImageId()) return input.getProviderId().equals(instance.getImageId())
&& (input.getLocation() == null || input.getLocation().equals(location) || input && (input.getLocation() == null
.getLocation().equals(location.getParent())); || input.getLocation().equals(location) || input
.getLocation().equals(location.getParent()));
} }
} }
@SuppressWarnings("unused") @SuppressWarnings("unused")
@Inject @Inject
ServerToNodeMetadata(Function<Server, Iterable<String>> getPublicAddresses, ServerToNodeMetadata(
Map<RunningState, NodeState> runningStateToNodeState, Set<? extends Image> images, Function<Server, Iterable<String>> getPublicAddresses,
Set<? extends Location> locations) { Map<RunningState, NodeState> runningStateToNodeState,
this.getPublicAddresses = checkNotNull(getPublicAddresses, "serverStateToNodeState"); Set<? extends Image> images, Set<? extends Location> locations) {
this.getPublicAddresses = checkNotNull(getPublicAddresses,
"serverStateToNodeState");
this.runningStateToNodeState = checkNotNull(runningStateToNodeState, this.runningStateToNodeState = checkNotNull(runningStateToNodeState,
"serverStateToNodeState"); "serverStateToNodeState");
this.images = checkNotNull(images, "images"); this.images = checkNotNull(images, "images");
this.locations = checkNotNull(locations, "locations"); this.locations = checkNotNull(locations, "locations");
} }
@ -315,49 +325,48 @@ public class RimuHostingComputeServiceContextModule extends RimuHostingContextMo
@Override @Override
public NodeMetadata apply(Server from) { public NodeMetadata apply(Server from) {
Location location = new LocationImpl(LocationScope.ZONE, from.getLocation().getId(), from Location location = new LocationImpl(LocationScope.ZONE, from
.getLocation().getName(), null); .getLocation().getId(), from.getLocation().getName(), null);
String tag = from.getName().replaceAll("-[0-9]+", ""); String tag = from.getName().replaceAll("-[0-9]+", "");
Credentials creds = null; Credentials creds = null;
Image image = null; Image image = null;
try { try {
image = Iterables.find(images, new FindImageForServer(location, from)); image = Iterables.find(images, new FindImageForServer(location,
from));
} catch (NoSuchElementException e) { } catch (NoSuchElementException e) {
logger.warn("could not find a matching image for server %s in location %s", from, logger
location); .warn(
"could not find a matching image for server %s in location %s",
from, location);
} }
NodeState state = runningStateToNodeState.get(from.getState()); NodeState state = runningStateToNodeState.get(from.getState());
return new NodeMetadataImpl(from.getId() + "", from.getName(), from.getId() + "", return new NodeMetadataImpl(from.getId() + "", from.getName(), from
location, null, ImmutableMap.<String, String> of(), tag, image, state, .getId()
getPublicAddresses.apply(from), ImmutableList.<String> of(), ImmutableMap + "", location, null, ImmutableMap.<String, String> of(), tag,
.<String, String> of(), creds); image, state, getPublicAddresses.apply(from), ImmutableList
.<String> of(), ImmutableMap.<String, String> of(), creds);
} }
} }
@Singleton @Singleton
private static class ServerToPublicAddresses implements Function<Server, Iterable<String>> { private static class ServerToPublicAddresses implements
Function<Server, Iterable<String>> {
@Override @Override
public Iterable<String> apply(Server server) { public Iterable<String> apply(Server server) {
return server.getIpAddresses() == null ? ImmutableSet.<String> of() : Iterables.concat( return server.getIpAddresses() == null ? ImmutableSet.<String> of()
ImmutableList.of(server.getIpAddresses().getPrimaryIp()), server.getIpAddresses() : Iterables.concat(ImmutableList.of(server.getIpAddresses()
.getSecondaryIps()); .getPrimaryIp()), server.getIpAddresses()
.getSecondaryIps());
} }
} }
@Provides @Provides
@Singleton @Singleton
@Named("NOT_RUNNING") Location getDefaultLocation(
protected Predicate<CommandUsingClient> runScriptRunning(ScriptStatusReturnsZero stateRunning) { @Named(PROPERTY_RIMUHOSTING_DEFAULT_DC) final String defaultDC,
return new RetryablePredicate<CommandUsingClient>(Predicates.not(stateRunning), 600, 3, Set<? extends Location> locations) {
TimeUnit.SECONDS);
}
@Provides
@Singleton
Location getDefaultLocation(@Named(PROPERTY_RIMUHOSTING_DEFAULT_DC) final String defaultDC,
Set<? extends Location> locations) {
return Iterables.find(locations, new Predicate<Location>() { return Iterables.find(locations, new Predicate<Location>() {
@Override @Override
@ -370,15 +379,17 @@ public class RimuHostingComputeServiceContextModule extends RimuHostingContextMo
@Provides @Provides
@Singleton @Singleton
Set<? extends Location> getDefaultLocations(RimuHostingClient sync, LogHolder holder, Set<? extends Location> getDefaultLocations(RimuHostingClient sync,
Function<ComputeMetadata, String> indexer) { LogHolder holder, Function<ComputeMetadata, String> indexer) {
final Set<Location> locations = Sets.newHashSet(); final Set<Location> locations = Sets.newHashSet();
holder.logger.debug(">> providing locations"); holder.logger.debug(">> providing locations");
Location provider = new LocationImpl(LocationScope.PROVIDER, providerName, providerName, null); Location provider = new LocationImpl(LocationScope.PROVIDER,
providerName, providerName, null);
for (final PricingPlan from : sync.getPricingPlanList()) { for (final PricingPlan from : sync.getPricingPlanList()) {
try { try {
locations.add(new LocationImpl(LocationScope.ZONE, from.getDataCenter().getId(), from locations.add(new LocationImpl(LocationScope.ZONE, from
.getDataCenter().getName(), provider)); .getDataCenter().getId(), from.getDataCenter().getName(),
provider));
} catch (NullPointerException e) { } catch (NullPointerException e) {
holder.logger.warn("datacenter not present in " + from.getId()); holder.logger.warn("datacenter not present in " + from.getId());
} }
@ -400,27 +411,30 @@ public class RimuHostingComputeServiceContextModule extends RimuHostingContextMo
@Provides @Provides
@Singleton @Singleton
protected Set<? extends Size> provideSizes(RimuHostingClient sync, Set<? extends Image> images, protected Set<? extends Size> provideSizes(RimuHostingClient sync,
Set<? extends Location> locations, LogHolder holder, Set<? extends Image> images, Set<? extends Location> locations,
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService userExecutor, LogHolder holder,
Function<ComputeMetadata, String> indexer) throws InterruptedException, @Named(Constants.PROPERTY_USER_THREADS) ExecutorService userExecutor,
TimeoutException, ExecutionException { Function<ComputeMetadata, String> indexer)
throws InterruptedException, TimeoutException, ExecutionException {
final Set<Size> sizes = Sets.newHashSet(); final Set<Size> sizes = Sets.newHashSet();
holder.logger.debug(">> providing sizes"); holder.logger.debug(">> providing sizes");
for (final PricingPlan from : sync.getPricingPlanList()) { for (final PricingPlan from : sync.getPricingPlanList()) {
try { try {
final Location location = Iterables.find(locations, new Predicate<Location>() { final Location location = Iterables.find(locations,
new Predicate<Location>() {
@Override @Override
public boolean apply(Location input) { public boolean apply(Location input) {
return input.getId().equals(from.getDataCenter().getId()); return input.getId().equals(
} from.getDataCenter().getId());
}
}); });
sizes.add(new SizeImpl(from.getId(), from.getId(), from.getId(), location, null, sizes.add(new SizeImpl(from.getId(), from.getId(), from.getId(),
ImmutableMap.<String, String> of(), 1, from.getRam(), from.getDiskSize(), location, null, ImmutableMap.<String, String> of(), 1, from
ImagePredicates.any())); .getRam(), from.getDiskSize(), ImagePredicates.any()));
} catch (NullPointerException e) { } catch (NullPointerException e) {
holder.logger.warn("datacenter not present in " + from.getId()); holder.logger.warn("datacenter not present in " + from.getId());
} }
@ -439,15 +453,16 @@ public class RimuHostingComputeServiceContextModule extends RimuHostingContextMo
@Provides @Provides
@Singleton @Singleton
protected Set<? extends Image> provideImages(final RimuHostingClient sync, LogHolder holder, protected Set<? extends Image> provideImages(final RimuHostingClient sync,
Function<ComputeMetadata, String> indexer) throws InterruptedException, LogHolder holder, Function<ComputeMetadata, String> indexer)
ExecutionException, TimeoutException { throws InterruptedException, ExecutionException, TimeoutException {
final Set<Image> images = Sets.newHashSet(); final Set<Image> images = Sets.newHashSet();
holder.logger.debug(">> providing images"); holder.logger.debug(">> providing images");
for (final org.jclouds.rimuhosting.miro.domain.Image from : sync.getImageList()) { for (final org.jclouds.rimuhosting.miro.domain.Image from : sync
.getImageList()) {
OsFamily os = null; OsFamily os = null;
Architecture arch = from.getId().indexOf("64") == -1 ? Architecture.X86_32 Architecture arch = from.getId().indexOf("64") == -1 ? Architecture.X86_32
: Architecture.X86_64; : Architecture.X86_64;
String osDescription = ""; String osDescription = "";
String version = ""; String version = "";
@ -462,9 +477,10 @@ public class RimuHostingComputeServiceContextModule extends RimuHostingContextMo
} }
} }
images.add(new ImageImpl(from.getId(), from.getDescription(), from.getId(), null, null, images.add(new ImageImpl(from.getId(), from.getDescription(), from
ImmutableMap.<String, String> of(), from.getDescription(), version, os, .getId(), null, null, ImmutableMap.<String, String> of(), from
osDescription, arch, new Credentials("root", null))); .getDescription(), version, os, osDescription, arch,
new Credentials("root", null)));
} }
holder.logger.debug("<< images(%d)", images.size()); holder.logger.debug("<< images(%d)", images.size());
return images; return images;

View File

@ -20,27 +20,19 @@ package org.jclouds.rimuhosting.miro.config;
import java.io.UnsupportedEncodingException; import java.io.UnsupportedEncodingException;
import java.net.URI; import java.net.URI;
import java.util.concurrent.TimeUnit;
import javax.inject.Named; import javax.inject.Named;
import javax.inject.Singleton; import javax.inject.Singleton;
import org.jclouds.http.RequiresHttp; import org.jclouds.http.RequiresHttp;
import org.jclouds.net.IPSocket;
import org.jclouds.predicates.RetryablePredicate;
import org.jclouds.predicates.SocketOpen;
import org.jclouds.rest.ConfiguresRestClient; import org.jclouds.rest.ConfiguresRestClient;
import org.jclouds.rest.config.RestClientModule; import org.jclouds.rest.config.RestClientModule;
import org.jclouds.rimuhosting.miro.RimuHosting; import org.jclouds.rimuhosting.miro.RimuHosting;
import org.jclouds.rimuhosting.miro.RimuHostingAsyncClient; import org.jclouds.rimuhosting.miro.RimuHostingAsyncClient;
import org.jclouds.rimuhosting.miro.RimuHostingClient; import org.jclouds.rimuhosting.miro.RimuHostingClient;
import org.jclouds.rimuhosting.miro.domain.Server;
import org.jclouds.rimuhosting.miro.filters.RimuHostingAuthentication; import org.jclouds.rimuhosting.miro.filters.RimuHostingAuthentication;
import org.jclouds.rimuhosting.miro.predicates.ServerDestroyed;
import org.jclouds.rimuhosting.miro.predicates.ServerRunning;
import org.jclouds.rimuhosting.miro.reference.RimuHostingConstants; import org.jclouds.rimuhosting.miro.reference.RimuHostingConstants;
import com.google.common.base.Predicate;
import com.google.inject.Provides; import com.google.inject.Provides;
/** /**
@ -51,37 +43,17 @@ import com.google.inject.Provides;
@RequiresHttp @RequiresHttp
@ConfiguresRestClient @ConfiguresRestClient
public class RimuHostingRestClientModule extends public class RimuHostingRestClientModule extends
RestClientModule<RimuHostingClient, RimuHostingAsyncClient> { RestClientModule<RimuHostingClient, RimuHostingAsyncClient> {
public RimuHostingRestClientModule() { public RimuHostingRestClientModule() {
super(RimuHostingClient.class, RimuHostingAsyncClient.class); super(RimuHostingClient.class, RimuHostingAsyncClient.class);
} }
@Provides
@Singleton
@Named("RUNNING")
protected Predicate<Server> serverRunning(ServerRunning stateRunning) {
return new RetryablePredicate<Server>(stateRunning, 600, 1, TimeUnit.SECONDS);
}
@Provides
@Singleton
@Named("DESTROYED")
protected Predicate<Server> serverDeleted(ServerDestroyed stateDeleted) {
return new RetryablePredicate<Server>(stateDeleted, 600, 50, TimeUnit.MILLISECONDS);
}
@Provides
@Singleton
protected Predicate<IPSocket> socketTester(SocketOpen open) {
return new RetryablePredicate<IPSocket>(open, 130, 1, TimeUnit.SECONDS);
}
@Provides @Provides
@Singleton @Singleton
public RimuHostingAuthentication provideRimuHostingAuthentication( public RimuHostingAuthentication provideRimuHostingAuthentication(
@Named(RimuHostingConstants.PROPERTY_RIMUHOSTING_APIKEY) String apikey) @Named(RimuHostingConstants.PROPERTY_RIMUHOSTING_APIKEY) String apikey)
throws UnsupportedEncodingException { throws UnsupportedEncodingException {
return new RimuHostingAuthentication(apikey); return new RimuHostingAuthentication(apikey);
} }
@ -89,7 +61,7 @@ public class RimuHostingRestClientModule extends
@Singleton @Singleton
@RimuHosting @RimuHosting
protected URI provideURI( protected URI provideURI(
@Named(RimuHostingConstants.PROPERTY_RIMUHOSTING_ENDPOINT) String endpoint) { @Named(RimuHostingConstants.PROPERTY_RIMUHOSTING_ENDPOINT) String endpoint) {
return URI.create(endpoint); return URI.create(endpoint);
} }

View File

@ -18,10 +18,9 @@
*/ */
package org.jclouds.rimuhosting.miro.domain.internal; package org.jclouds.rimuhosting.miro.domain.internal;
/** /**
* States an instance can be in. * States an instance can be in.
* *
* @author Ivan Meredith * @author Ivan Meredith
*/ */
public enum RunningState { public enum RunningState {

View File

@ -33,12 +33,13 @@ public class ServerRunning implements Predicate<Server> {
} }
public boolean apply(Server server) { public boolean apply(Server server) {
logger.trace("looking for state on server %s", checkNotNull(server, "server")); logger.trace("looking for state on server %s", checkNotNull(server,
"server"));
server = refresh(server); server = refresh(server);
if (server == null) if (server == null)
return false; return false;
logger.trace("%s: looking for server state %s: currently: %s", server.getId(), logger.trace("%s: looking for server state %s: currently: %s", server
RunningState.RUNNING, server.getState()); .getId(), RunningState.RUNNING, server.getState());
return server.getState() == RunningState.RUNNING; return server.getState() == RunningState.RUNNING;
} }

View File

@ -19,15 +19,22 @@
package org.jclouds.rimuhosting.miro; package org.jclouds.rimuhosting.miro;
import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkNotNull;
import org.jclouds.logging.log4j.config.Log4JLoggingModule; import static org.testng.Assert.assertEquals;
import org.jclouds.rimuhosting.miro.domain.*; import static org.testng.Assert.assertNotNull;
import org.jclouds.rimuhosting.miro.domain.internal.RunningState; import static org.testng.Assert.assertTrue;
import static org.testng.Assert.*;
import org.testng.annotations.BeforeGroups;
import org.testng.annotations.Test;
import java.util.SortedSet; import java.util.SortedSet;
import org.jclouds.logging.log4j.config.Log4JLoggingModule;
import org.jclouds.rimuhosting.miro.domain.Image;
import org.jclouds.rimuhosting.miro.domain.NewServerResponse;
import org.jclouds.rimuhosting.miro.domain.PricingPlan;
import org.jclouds.rimuhosting.miro.domain.Server;
import org.jclouds.rimuhosting.miro.domain.ServerInfo;
import org.jclouds.rimuhosting.miro.domain.internal.RunningState;
import org.testng.annotations.BeforeGroups;
import org.testng.annotations.Test;
/** /**
* Tests behavior of {@code RimuHostingClient} * Tests behavior of {@code RimuHostingClient}
* *
@ -40,10 +47,12 @@ public class RimuHostingClientLiveTest {
@BeforeGroups(groups = { "live" }) @BeforeGroups(groups = { "live" })
public void setupClient() { public void setupClient() {
String password = checkNotNull(System.getProperty("jclouds.test.key"), "jclouds.test.key"); String password = checkNotNull(System.getProperty("jclouds.test.key"),
"jclouds.test.key");
connection = (RimuHostingClient) RimuHostingContextFactory.createContext(password, new Log4JLoggingModule()) connection = (RimuHostingClient) RimuHostingContextFactory.createContext(
.getProviderSpecificContext().getApi(); password, new Log4JLoggingModule()).getProviderSpecificContext()
.getApi();
} }
@Test @Test
@ -73,8 +82,8 @@ public class RimuHostingClientLiveTest {
@Test @Test
public void testLifeCycle() { public void testLifeCycle() {
// Get the first image, we dont really care what it is in this test. // Get the first image, we dont really care what it is in this test.
NewServerResponse serverResponse = connection.createServer("test.ivan.api.com", "lenny", NewServerResponse serverResponse = connection.createServer(
"MIRO1B"); "test.ivan.api.com", "lenny", "MIRO1B");
Server server = serverResponse.getServer(); Server server = serverResponse.getServer();
// Now we have the server, lets restart it // Now we have the server, lets restart it
assertNotNull(server.getId()); assertNotNull(server.getId());

View File

@ -3,7 +3,6 @@ package org.jclouds.vcloud.bluelock.compute;
import java.util.Map; import java.util.Map;
import javax.inject.Inject; import javax.inject.Inject;
import javax.inject.Named;
import javax.inject.Singleton; import javax.inject.Singleton;
import org.jclouds.compute.domain.NodeState; import org.jclouds.compute.domain.NodeState;
@ -25,18 +24,20 @@ public class BlueLockVCloudComputeClient extends BaseVCloudComputeClient {
@Inject @Inject
protected BlueLockVCloudComputeClient( protected BlueLockVCloudComputeClient(
PopulateDefaultLoginCredentialsForImageStrategy credentialsProvider, PopulateDefaultLoginCredentialsForImageStrategy credentialsProvider,
VCloudClient client, Predicate<String> successTester, VCloudClient client, Predicate<String> successTester,
@Named("NOT_FOUND") Predicate<VApp> notFoundTester, Map<VAppStatus, NodeState> vAppStatusToNodeState) {
Map<VAppStatus, NodeState> vAppStatusToNodeState) { super(client, successTester, vAppStatusToNodeState);
super(client, successTester, notFoundTester, vAppStatusToNodeState);
this.credentialsProvider = credentialsProvider; this.credentialsProvider = credentialsProvider;
} }
@Override @Override
protected Map<String, String> parseAndValidateResponse(String templateId, VApp vAppResponse) { protected Map<String, String> parseAndValidateResponse(String templateId,
Credentials credentials = credentialsProvider.execute(client.getVAppTemplate(templateId)); VApp vAppResponse) {
Map<String, String> toReturn = super.parseResponse(templateId, vAppResponse); Credentials credentials = credentialsProvider.execute(client
.getVAppTemplate(templateId));
Map<String, String> toReturn = super.parseResponse(templateId,
vAppResponse);
toReturn.put("username", credentials.account); toReturn.put("username", credentials.account);
toReturn.put("password", credentials.key); toReturn.put("password", credentials.key);
return toReturn; return toReturn;

View File

@ -24,6 +24,7 @@ import static org.jclouds.vcloud.reference.VCloudConstants.PROPERTY_VCLOUD_DEFAU
import static org.jclouds.vcloud.reference.VCloudConstants.PROPERTY_VCLOUD_ENDPOINT; import static org.jclouds.vcloud.reference.VCloudConstants.PROPERTY_VCLOUD_ENDPOINT;
import static org.jclouds.vcloud.reference.VCloudConstants.PROPERTY_VCLOUD_KEY; import static org.jclouds.vcloud.reference.VCloudConstants.PROPERTY_VCLOUD_KEY;
import static org.jclouds.vcloud.reference.VCloudConstants.PROPERTY_VCLOUD_SESSIONINTERVAL; import static org.jclouds.vcloud.reference.VCloudConstants.PROPERTY_VCLOUD_SESSIONINTERVAL;
import static org.jclouds.vcloud.reference.VCloudConstants.PROPERTY_VCLOUD_TIMEOUT_TASK_COMPLETED;
import static org.jclouds.vcloud.reference.VCloudConstants.PROPERTY_VCLOUD_USER; import static org.jclouds.vcloud.reference.VCloudConstants.PROPERTY_VCLOUD_USER;
import static org.jclouds.vcloud.reference.VCloudConstants.PROPERTY_VCLOUD_VERSION; import static org.jclouds.vcloud.reference.VCloudConstants.PROPERTY_VCLOUD_VERSION;
import static org.jclouds.vcloud.reference.VCloudConstants.PROPERTY_VCLOUD_XML_NAMESPACE; import static org.jclouds.vcloud.reference.VCloudConstants.PROPERTY_VCLOUD_XML_NAMESPACE;
@ -47,11 +48,14 @@ public class VCloudPropertiesBuilder extends PropertiesBuilder {
properties.setProperty(PROPERTY_VCLOUD_VERSION, "0.8"); properties.setProperty(PROPERTY_VCLOUD_VERSION, "0.8");
properties.setProperty(PROPERTY_VCLOUD_SESSIONINTERVAL, 8 * 60 + ""); properties.setProperty(PROPERTY_VCLOUD_SESSIONINTERVAL, 8 * 60 + "");
properties.setProperty(PROPERTY_VCLOUD_XML_SCHEMA, properties.setProperty(PROPERTY_VCLOUD_XML_SCHEMA,
"http://vcloud.safesecureweb.com/ns/vcloud.xsd"); "http://vcloud.safesecureweb.com/ns/vcloud.xsd");
properties.setProperty(PROPERTY_VCLOUD_DEFAULT_DHCP_ENABLED, "false"); properties.setProperty(PROPERTY_VCLOUD_DEFAULT_DHCP_ENABLED, "false");
properties.setProperty(PROPERTY_VCLOUD_DEFAULT_FENCEMODE, FenceMode.ALLOW_IN_OUT.toString()); properties.setProperty(PROPERTY_VCLOUD_DEFAULT_FENCEMODE,
FenceMode.ALLOW_IN_OUT.toString());
properties.setProperty("jclouds.dns_name_length_min", "1"); properties.setProperty("jclouds.dns_name_length_min", "1");
properties.setProperty("jclouds.dns_name_length_max", "80"); properties.setProperty("jclouds.dns_name_length_max", "80");
properties.setProperty(PROPERTY_VCLOUD_TIMEOUT_TASK_COMPLETED,
180l * 1000l + "");
return properties; return properties;
} }
@ -62,8 +66,9 @@ public class VCloudPropertiesBuilder extends PropertiesBuilder {
private void setNs() { private void setNs() {
if (properties.getProperty(PROPERTY_VCLOUD_XML_NAMESPACE) == null) if (properties.getProperty(PROPERTY_VCLOUD_XML_NAMESPACE) == null)
properties.setProperty(PROPERTY_VCLOUD_XML_NAMESPACE, "http://www.vmware.com/vcloud/v" properties.setProperty(PROPERTY_VCLOUD_XML_NAMESPACE,
+ properties.getProperty(PROPERTY_VCLOUD_VERSION)); "http://www.vmware.com/vcloud/v"
+ properties.getProperty(PROPERTY_VCLOUD_VERSION));
} }
public VCloudPropertiesBuilder(URI endpoint, String id, String secret) { public VCloudPropertiesBuilder(URI endpoint, String id, String secret) {
@ -85,8 +90,8 @@ public class VCloudPropertiesBuilder extends PropertiesBuilder {
} }
public VCloudPropertiesBuilder withEndpoint(URI endpoint) { public VCloudPropertiesBuilder withEndpoint(URI endpoint) {
properties.setProperty(PROPERTY_VCLOUD_ENDPOINT, checkNotNull(endpoint, "endpoint") properties.setProperty(PROPERTY_VCLOUD_ENDPOINT, checkNotNull(endpoint,
.toString()); "endpoint").toString());
return this; return this;
} }
} }

View File

@ -54,58 +54,64 @@ public class BaseVCloudComputeClient implements VCloudComputeClient {
protected final VCloudClient client; protected final VCloudClient client;
protected final Predicate<String> taskTester; protected final Predicate<String> taskTester;
protected final Predicate<VApp> notFoundTester;
protected final Map<VAppStatus, NodeState> vAppStatusToNodeState; protected final Map<VAppStatus, NodeState> vAppStatusToNodeState;
@Inject @Inject
public BaseVCloudComputeClient(VCloudClient client, Predicate<String> successTester, public BaseVCloudComputeClient(VCloudClient client,
@Named("NOT_FOUND") Predicate<VApp> notFoundTester, Predicate<String> successTester,
Map<VAppStatus, NodeState> vAppStatusToNodeState) { Map<VAppStatus, NodeState> vAppStatusToNodeState) {
this.client = client; this.client = client;
this.taskTester = successTester; this.taskTester = successTester;
this.notFoundTester = notFoundTester;
this.vAppStatusToNodeState = vAppStatusToNodeState; this.vAppStatusToNodeState = vAppStatusToNodeState;
} }
@Override @Override
public Map<String, String> start(String vDCId, String name, String templateId, public Map<String, String> start(String vDCId, String name,
InstantiateVAppTemplateOptions options, int... portsToOpen) { String templateId, InstantiateVAppTemplateOptions options,
int... portsToOpen) {
checkNotNull(options, "options"); checkNotNull(options, "options");
logger.debug(">> instantiating vApp vDC(%s) name(%s) template(%s) options(%s) ", vDCId, name, logger.debug(
templateId, options); ">> instantiating vApp vDC(%s) name(%s) template(%s) options(%s) ",
vDCId, name, templateId, options);
VApp vAppResponse = client.instantiateVAppTemplateInVDC(vDCId, name, templateId, options); VApp vAppResponse = client.instantiateVAppTemplateInVDC(vDCId, name,
templateId, options);
logger.debug("<< instantiated VApp(%s)", vAppResponse.getId()); logger.debug("<< instantiated VApp(%s)", vAppResponse.getId());
logger.debug(">> deploying vApp(%s)", vAppResponse.getId()); logger.debug(">> deploying vApp(%s)", vAppResponse.getId());
Task task = client.deployVApp(vAppResponse.getId()); Task task = client.deployVApp(vAppResponse.getId());
if (!taskTester.apply(task.getId())) { if (options.shouldBlockOnDeploy()) {
throw new TaskException("deploy", vAppResponse, task); if (!taskTester.apply(task.getId())) {
} throw new TaskException("deploy", vAppResponse, task);
logger.debug("<< deployed vApp(%s)", vAppResponse.getId()); }
logger.debug("<< deployed vApp(%s)", vAppResponse.getId());
logger.debug(">> powering vApp(%s)", vAppResponse.getId()); logger.debug(">> powering vApp(%s)", vAppResponse.getId());
task = client.powerOnVApp(vAppResponse.getId()); task = client.powerOnVApp(vAppResponse.getId());
if (!taskTester.apply(task.getId())) { if (!taskTester.apply(task.getId())) {
throw new TaskException("powerOn", vAppResponse, task); throw new TaskException("powerOn", vAppResponse, task);
}
logger.debug("<< on vApp(%s)", vAppResponse.getId());
} }
logger.debug("<< on vApp(%s)", vAppResponse.getId());
return parseAndValidateResponse(templateId, vAppResponse); return parseAndValidateResponse(templateId, vAppResponse);
} }
protected Map<String, String> parseAndValidateResponse(String templateId, VApp vAppResponse) { protected Map<String, String> parseAndValidateResponse(String templateId,
VApp vAppResponse) {
Map<String, String> response = parseResponse(templateId, vAppResponse); Map<String, String> response = parseResponse(templateId, vAppResponse);
checkState(response.containsKey("id"), "bad configuration: [id] should be in response"); checkState(response.containsKey("id"),
"bad configuration: [id] should be in response");
checkState(response.containsKey("username"), checkState(response.containsKey("username"),
"bad configuration: [username] should be in response"); "bad configuration: [username] should be in response");
checkState(response.containsKey("password"), checkState(response.containsKey("password"),
"bad configuration: [password] should be in response"); "bad configuration: [password] should be in response");
return response; return response;
} }
protected Map<String, String> parseResponse(String templateId, VApp vAppResponse) { protected Map<String, String> parseResponse(String templateId,
VApp vAppResponse) {
Map<String, String> config = Maps.newLinkedHashMap();// Allows nulls Map<String, String> config = Maps.newLinkedHashMap();// Allows nulls
config.put("id", vAppResponse.getId()); config.put("id", vAppResponse.getId());
config.put("username", null); config.put("username", null);
@ -127,22 +133,19 @@ public class BaseVCloudComputeClient implements VCloudComputeClient {
VApp vApp = client.getVApp(id); VApp vApp = client.getVApp(id);
vApp = powerOffVAppIfDeployed(vApp); vApp = powerOffVAppIfDeployed(vApp);
vApp = undeployVAppIfDeployed(vApp); vApp = undeployVAppIfDeployed(vApp);
boolean successful = deleteVApp(vApp); deleteVApp(vApp);
logger.debug("<< deleted vApp(%s) completed(%s)", vApp.getId(), successful); logger.debug("<< deleted vApp(%s)", vApp.getId());
} }
private boolean deleteVApp(VApp vApp) { private void deleteVApp(VApp vApp) {
logger.debug(">> deleting vApp(%s)", vApp.getId()); logger.debug(">> deleting vApp(%s)", vApp.getId());
client.deleteVApp(vApp.getId()); client.deleteVApp(vApp.getId());
boolean successful = notFoundTester.apply(vApp);
return successful;
} }
private VApp undeployVAppIfDeployed(VApp vApp) { private VApp undeployVAppIfDeployed(VApp vApp) {
if (vApp.getStatus().compareTo(VAppStatus.RESOLVED) > 0) { if (vApp.getStatus().compareTo(VAppStatus.RESOLVED) > 0) {
logger logger.debug(">> undeploying vApp(%s), current status: %s", vApp
.debug(">> undeploying vApp(%s), current status: %s", vApp.getId(), vApp .getId(), vApp.getStatus());
.getStatus());
Task task = client.undeployVApp(vApp.getId()); Task task = client.undeployVApp(vApp.getId());
if (!taskTester.apply(task.getId())) { if (!taskTester.apply(task.getId())) {
throw new TaskException("undeploy", vApp, task); throw new TaskException("undeploy", vApp, task);
@ -155,8 +158,8 @@ public class BaseVCloudComputeClient implements VCloudComputeClient {
private VApp powerOffVAppIfDeployed(VApp vApp) { private VApp powerOffVAppIfDeployed(VApp vApp) {
if (vApp.getStatus().compareTo(VAppStatus.OFF) > 0) { if (vApp.getStatus().compareTo(VAppStatus.OFF) > 0) {
logger.debug(">> powering off vApp(%s), current status: %s", vApp.getId(), vApp logger.debug(">> powering off vApp(%s), current status: %s", vApp
.getStatus()); .getId(), vApp.getStatus());
Task task = client.powerOffVApp(vApp.getId()); Task task = client.powerOffVApp(vApp.getId());
if (!taskTester.apply(task.getId())) { if (!taskTester.apply(task.getId())) {
throw new TaskException("powerOff", vApp, task); throw new TaskException("powerOff", vApp, task);
@ -174,8 +177,10 @@ public class BaseVCloudComputeClient implements VCloudComputeClient {
private static final long serialVersionUID = 251801929573211256L; private static final long serialVersionUID = 251801929573211256L;
public TaskException(String type, VApp vApp, Task task) { public TaskException(String type, VApp vApp, Task task) {
super(String.format("failed to %s vApp %s status %s;task %s status %s", type, super(String.format(
vApp.getId(), vApp.getStatus(), task.getLocation(), task.getStatus()), vApp); "failed to %s vApp %s status %s;task %s status %s", type, vApp
.getId(), vApp.getStatus(), task.getLocation(), task
.getStatus()), vApp);
this.task = task; this.task = task;
} }

View File

@ -22,21 +22,19 @@ import static org.jclouds.compute.domain.OsFamily.UBUNTU;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.concurrent.TimeUnit;
import javax.inject.Named; import javax.inject.Named;
import javax.inject.Singleton; import javax.inject.Singleton;
import org.jclouds.compute.ComputeServiceContext; import org.jclouds.compute.ComputeServiceContext;
import org.jclouds.compute.LoadBalancerService; import org.jclouds.compute.LoadBalancerService;
import org.jclouds.compute.config.ComputeServiceTimeoutsModule;
import org.jclouds.compute.domain.ComputeMetadata; import org.jclouds.compute.domain.ComputeMetadata;
import org.jclouds.compute.domain.Image; import org.jclouds.compute.domain.Image;
import org.jclouds.compute.domain.NodeState; import org.jclouds.compute.domain.NodeState;
import org.jclouds.compute.domain.Size; import org.jclouds.compute.domain.Size;
import org.jclouds.compute.domain.TemplateBuilder; import org.jclouds.compute.domain.TemplateBuilder;
import org.jclouds.compute.internal.ComputeServiceContextImpl; import org.jclouds.compute.internal.ComputeServiceContextImpl;
import org.jclouds.compute.predicates.ScriptStatusReturnsZero;
import org.jclouds.compute.predicates.ScriptStatusReturnsZero.CommandUsingClient;
import org.jclouds.compute.strategy.AddNodeWithTagStrategy; import org.jclouds.compute.strategy.AddNodeWithTagStrategy;
import org.jclouds.compute.strategy.DestroyNodeStrategy; import org.jclouds.compute.strategy.DestroyNodeStrategy;
import org.jclouds.compute.strategy.GetNodeMetadataStrategy; import org.jclouds.compute.strategy.GetNodeMetadataStrategy;
@ -44,7 +42,6 @@ import org.jclouds.compute.strategy.ListNodesStrategy;
import org.jclouds.compute.strategy.RebootNodeStrategy; import org.jclouds.compute.strategy.RebootNodeStrategy;
import org.jclouds.compute.strategy.RunNodesAndAddToSetStrategy; import org.jclouds.compute.strategy.RunNodesAndAddToSetStrategy;
import org.jclouds.domain.Location; import org.jclouds.domain.Location;
import org.jclouds.predicates.RetryablePredicate;
import org.jclouds.vcloud.VCloudAsyncClient; import org.jclouds.vcloud.VCloudAsyncClient;
import org.jclouds.vcloud.VCloudClient; import org.jclouds.vcloud.VCloudClient;
import org.jclouds.vcloud.compute.BaseVCloudComputeClient; import org.jclouds.vcloud.compute.BaseVCloudComputeClient;
@ -63,7 +60,6 @@ import org.jclouds.vcloud.endpoints.VCloud;
import com.google.common.base.Function; import com.google.common.base.Function;
import com.google.common.base.Predicate; import com.google.common.base.Predicate;
import com.google.common.base.Predicates;
import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Iterables; import com.google.common.collect.Iterables;
import com.google.inject.Provides; import com.google.inject.Provides;
@ -103,6 +99,7 @@ public class VCloudComputeServiceContextModule extends VCloudContextModule {
@Override @Override
protected void configure() { protected void configure() {
super.configure(); super.configure();
install(new ComputeServiceTimeoutsModule());
bind(String.class).annotatedWith(VCloud.class).toInstance(providerName); bind(String.class).annotatedWith(VCloud.class).toInstance(providerName);
bind(AddNodeWithTagStrategy.class).to(VCloudAddNodeWithTagStrategy.class); bind(AddNodeWithTagStrategy.class).to(VCloudAddNodeWithTagStrategy.class);
bind(new TypeLiteral<ComputeServiceContext>() { bind(new TypeLiteral<ComputeServiceContext>() {
@ -127,14 +124,6 @@ public class VCloudComputeServiceContextModule extends VCloudContextModule {
return "%s-%s%s"; return "%s-%s%s";
} }
@Provides
@Singleton
@Named("NOT_RUNNING")
protected Predicate<CommandUsingClient> runScriptRunning(ScriptStatusReturnsZero stateRunning) {
return new RetryablePredicate<CommandUsingClient>(Predicates.not(stateRunning), 600, 3,
TimeUnit.SECONDS);
}
protected void bindLoadBalancer() { protected void bindLoadBalancer() {
bind(LoadBalancerService.class).toProvider(Providers.<LoadBalancerService> of(null)); bind(LoadBalancerService.class).toProvider(Providers.<LoadBalancerService> of(null));
} }

View File

@ -40,28 +40,32 @@ import com.google.common.base.Strings;
*/ */
@Singleton @Singleton
public class EncodeTemplateIdIntoNameRunNodesAndAddToSetStrategy extends public class EncodeTemplateIdIntoNameRunNodesAndAddToSetStrategy extends
EncodeTagIntoNameRunNodesAndAddToSetStrategy { EncodeTagIntoNameRunNodesAndAddToSetStrategy {
private final SecureRandom random; private final SecureRandom random;
@Inject @Inject
protected EncodeTemplateIdIntoNameRunNodesAndAddToSetStrategy( protected EncodeTemplateIdIntoNameRunNodesAndAddToSetStrategy(
AddNodeWithTagStrategy addNodeWithTagStrategy, ListNodesStrategy listNodesStrategy, AddNodeWithTagStrategy addNodeWithTagStrategy,
@Named("NAMING_CONVENTION") String nodeNamingConvention, ComputeUtils utils, ListNodesStrategy listNodesStrategy,
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService executor) { @Named("NAMING_CONVENTION") String nodeNamingConvention,
super(addNodeWithTagStrategy, listNodesStrategy, nodeNamingConvention, utils, executor); ComputeUtils utils,
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService executor) {
super(addNodeWithTagStrategy, listNodesStrategy, nodeNamingConvention,
utils, executor);
this.random = new SecureRandom(); this.random = new SecureRandom();
} }
/** /**
* Get a name corresponding to the tag-hex*5 where the first 3 hex correspond to the template id * Get a name corresponding to the tag-hex*5 where the first 3 hex correspond
* and the last a random number * to the template id and the last a random number
* *
*/ */
@Override @Override
protected String getNextName(final String tag, final Template template) { protected String getNextName(final String tag, final Template template) {
return String.format(nodeNamingConvention, tag, Strings.padStart(Integer.toHexString(Integer return String.format(nodeNamingConvention, tag, Strings.padStart(
.parseInt(template.getImage().getProviderId())), 3, '0'), Strings.padStart(Integer Integer.toHexString(Integer.parseInt(template.getImage()
.toHexString(random.nextInt(255)), 2, '0')); .getProviderId())), 3, '0'), Strings.padStart(Integer
.toHexString(random.nextInt(255)), 2, '0'));
} }
} }

View File

@ -49,8 +49,9 @@ public class VCloudAddNodeWithTagStrategy implements AddNodeWithTagStrategy {
protected final Map<VAppStatus, NodeState> vAppStatusToNodeState; protected final Map<VAppStatus, NodeState> vAppStatusToNodeState;
@Inject @Inject
protected VCloudAddNodeWithTagStrategy(VCloudClient client, VCloudComputeClient computeClient, protected VCloudAddNodeWithTagStrategy(VCloudClient client,
Map<VAppStatus, NodeState> vAppStatusToNodeState) { VCloudComputeClient computeClient,
Map<VAppStatus, NodeState> vAppStatusToNodeState) {
this.client = client; this.client = client;
this.computeClient = computeClient; this.computeClient = computeClient;
this.vAppStatusToNodeState = vAppStatusToNodeState; this.vAppStatusToNodeState = vAppStatusToNodeState;
@ -58,25 +59,29 @@ public class VCloudAddNodeWithTagStrategy implements AddNodeWithTagStrategy {
@Override @Override
public NodeMetadata execute(String tag, String name, Template template) { public NodeMetadata execute(String tag, String name, Template template) {
InstantiateVAppTemplateOptions options = processorCount( InstantiateVAppTemplateOptions options = processorCount(
Double.valueOf(template.getSize().getCores()).intValue()).memory( Double.valueOf(template.getSize().getCores()).intValue()).memory(
template.getSize().getRam()).disk(template.getSize().getDisk() * 1024 * 1024l); template.getSize().getRam()).disk(
Map<String, String> metaMap = computeClient.start(template.getLocation().getId(), name, template.getSize().getDisk() * 1024 * 1024l);
template.getImage().getProviderId(), options, template.getOptions() if (!template.getOptions().shouldBlockUntilRunning())
.getInboundPorts()); options.blockOnDeploy(false);
Map<String, String> metaMap = computeClient.start(template.getLocation()
.getId(), name, template.getImage().getProviderId(), options,
template.getOptions().getInboundPorts());
VApp vApp = client.getVApp(metaMap.get("id")); VApp vApp = client.getVApp(metaMap.get("id"));
return newCreateNodeResponse(tag, template, metaMap, vApp); return newCreateNodeResponse(tag, template, metaMap, vApp);
} }
protected NodeMetadata newCreateNodeResponse(String tag, Template template, protected NodeMetadata newCreateNodeResponse(String tag, Template template,
Map<String, String> metaMap, VApp vApp) { Map<String, String> metaMap, VApp vApp) {
return new NodeMetadataImpl(vApp.getId(), vApp.getName(), vApp.getId(), template return new NodeMetadataImpl(vApp.getId(), vApp.getName(), vApp.getId(),
.getLocation(), vApp.getLocation(), ImmutableMap.<String, String> of(), tag, template.getLocation(), vApp.getLocation(), ImmutableMap
template.getImage(), vAppStatusToNodeState.get(vApp.getStatus()), computeClient .<String, String> of(), tag, template.getImage(),
.getPublicAddresses(vApp.getId()), computeClient.getPrivateAddresses(vApp vAppStatusToNodeState.get(vApp.getStatus()), computeClient
.getId()), ImmutableMap.<String, String> of(), new Credentials(metaMap .getPublicAddresses(vApp.getId()), computeClient
.get("username"), metaMap.get("password"))); .getPrivateAddresses(vApp.getId()), ImmutableMap
.<String, String> of(), new Credentials(metaMap
.get("username"), metaMap.get("password")));
} }
} }

View File

@ -23,7 +23,9 @@ import static com.google.common.base.Preconditions.checkNotNull;
import javax.inject.Inject; import javax.inject.Inject;
import javax.inject.Singleton; import javax.inject.Singleton;
import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.strategy.DestroyNodeStrategy; import org.jclouds.compute.strategy.DestroyNodeStrategy;
import org.jclouds.compute.strategy.GetNodeMetadataStrategy;
import org.jclouds.vcloud.compute.VCloudComputeClient; import org.jclouds.vcloud.compute.VCloudComputeClient;
/** /**
@ -32,16 +34,20 @@ import org.jclouds.vcloud.compute.VCloudComputeClient;
@Singleton @Singleton
public class VCloudDestroyNodeStrategy implements DestroyNodeStrategy { public class VCloudDestroyNodeStrategy implements DestroyNodeStrategy {
protected final VCloudComputeClient computeClient; protected final VCloudComputeClient computeClient;
protected final GetNodeMetadataStrategy getNode;
@Inject @Inject
protected VCloudDestroyNodeStrategy(VCloudComputeClient computeClient) { protected VCloudDestroyNodeStrategy(VCloudComputeClient computeClient,
GetNodeMetadataStrategy getNode) {
this.computeClient = computeClient; this.computeClient = computeClient;
this.getNode = getNode;
} }
@Override @Override
public boolean execute(String id) { public NodeMetadata execute(String id) {
computeClient.stop(checkNotNull(id, "node.id")); computeClient.stop(checkNotNull(id, "node.id"));
return true; return getNode.execute(id);
} }
} }

View File

@ -23,6 +23,8 @@ import static com.google.common.base.Preconditions.checkNotNull;
import javax.inject.Inject; import javax.inject.Inject;
import javax.inject.Singleton; import javax.inject.Singleton;
import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.strategy.GetNodeMetadataStrategy;
import org.jclouds.compute.strategy.RebootNodeStrategy; import org.jclouds.compute.strategy.RebootNodeStrategy;
import org.jclouds.vcloud.VCloudClient; import org.jclouds.vcloud.VCloudClient;
import org.jclouds.vcloud.domain.Task; import org.jclouds.vcloud.domain.Task;
@ -36,17 +38,21 @@ import com.google.common.base.Predicate;
public class VCloudRebootNodeStrategy implements RebootNodeStrategy { public class VCloudRebootNodeStrategy implements RebootNodeStrategy {
private final VCloudClient client; private final VCloudClient client;
protected final Predicate<String> taskTester; protected final Predicate<String> taskTester;
protected final GetNodeMetadataStrategy getNode;
@Inject @Inject
protected VCloudRebootNodeStrategy(VCloudClient client, Predicate<String> taskTester) { protected VCloudRebootNodeStrategy(VCloudClient client,
Predicate<String> taskTester, GetNodeMetadataStrategy getNode) {
this.client = client; this.client = client;
this.taskTester = taskTester; this.taskTester = taskTester;
this.getNode = getNode;
} }
@Override @Override
public boolean execute(String id) { public NodeMetadata execute(String id) {
Task task = client.resetVApp(checkNotNull(id, "node.id")); Task task = client.resetVApp(checkNotNull(id, "node.id"));
return taskTester.apply(task.getId()); taskTester.apply(task.getId());
return getNode.execute(id);
} }
} }

View File

@ -24,6 +24,7 @@ import static org.jclouds.vcloud.reference.VCloudConstants.PROPERTY_VCLOUD_DEFAU
import static org.jclouds.vcloud.reference.VCloudConstants.PROPERTY_VCLOUD_ENDPOINT; import static org.jclouds.vcloud.reference.VCloudConstants.PROPERTY_VCLOUD_ENDPOINT;
import static org.jclouds.vcloud.reference.VCloudConstants.PROPERTY_VCLOUD_KEY; import static org.jclouds.vcloud.reference.VCloudConstants.PROPERTY_VCLOUD_KEY;
import static org.jclouds.vcloud.reference.VCloudConstants.PROPERTY_VCLOUD_SESSIONINTERVAL; import static org.jclouds.vcloud.reference.VCloudConstants.PROPERTY_VCLOUD_SESSIONINTERVAL;
import static org.jclouds.vcloud.reference.VCloudConstants.PROPERTY_VCLOUD_TIMEOUT_TASK_COMPLETED;
import static org.jclouds.vcloud.reference.VCloudConstants.PROPERTY_VCLOUD_USER; import static org.jclouds.vcloud.reference.VCloudConstants.PROPERTY_VCLOUD_USER;
import static org.jclouds.vcloud.reference.VCloudConstants.PROPERTY_VCLOUD_VERSION; import static org.jclouds.vcloud.reference.VCloudConstants.PROPERTY_VCLOUD_VERSION;
@ -49,9 +50,7 @@ import org.jclouds.http.annotation.Redirection;
import org.jclouds.http.annotation.ServerError; import org.jclouds.http.annotation.ServerError;
import org.jclouds.http.filters.BasicAuthentication; import org.jclouds.http.filters.BasicAuthentication;
import org.jclouds.logging.Logger; import org.jclouds.logging.Logger;
import org.jclouds.net.IPSocket;
import org.jclouds.predicates.RetryablePredicate; import org.jclouds.predicates.RetryablePredicate;
import org.jclouds.predicates.SocketOpen;
import org.jclouds.rest.AsyncClientFactory; import org.jclouds.rest.AsyncClientFactory;
import org.jclouds.rest.AuthorizationException; import org.jclouds.rest.AuthorizationException;
import org.jclouds.rest.ConfiguresRestClient; import org.jclouds.rest.ConfiguresRestClient;
@ -61,7 +60,6 @@ import org.jclouds.vcloud.VCloudClient;
import org.jclouds.vcloud.VCloudToken; import org.jclouds.vcloud.VCloudToken;
import org.jclouds.vcloud.domain.NamedResource; import org.jclouds.vcloud.domain.NamedResource;
import org.jclouds.vcloud.domain.Organization; import org.jclouds.vcloud.domain.Organization;
import org.jclouds.vcloud.domain.VApp;
import org.jclouds.vcloud.endpoints.Catalog; import org.jclouds.vcloud.endpoints.Catalog;
import org.jclouds.vcloud.endpoints.Network; import org.jclouds.vcloud.endpoints.Network;
import org.jclouds.vcloud.endpoints.Org; import org.jclouds.vcloud.endpoints.Org;
@ -78,7 +76,6 @@ import org.jclouds.vcloud.internal.VCloudLoginAsyncClient;
import org.jclouds.vcloud.internal.VCloudVersionsAsyncClient; import org.jclouds.vcloud.internal.VCloudVersionsAsyncClient;
import org.jclouds.vcloud.internal.VCloudLoginAsyncClient.VCloudSession; import org.jclouds.vcloud.internal.VCloudLoginAsyncClient.VCloudSession;
import org.jclouds.vcloud.predicates.TaskSuccess; import org.jclouds.vcloud.predicates.TaskSuccess;
import org.jclouds.vcloud.predicates.VAppNotFound;
import com.google.common.base.Predicate; import com.google.common.base.Predicate;
import com.google.common.base.Supplier; import com.google.common.base.Supplier;
@ -87,16 +84,18 @@ import com.google.common.collect.Iterables;
import com.google.inject.Provides; import com.google.inject.Provides;
/** /**
* Configures the VCloud authentication service connection, including logging and http transport. * Configures the VCloud authentication service connection, including logging
* and http transport.
* *
* @author Adrian Cole * @author Adrian Cole
*/ */
@RequiresHttp @RequiresHttp
@ConfiguresRestClient @ConfiguresRestClient
public abstract class BaseVCloudRestClientModule<S extends VCloudClient, A extends VCloudAsyncClient> public abstract class BaseVCloudRestClientModule<S extends VCloudClient, A extends VCloudAsyncClient>
extends RestClientModule<S, A> { extends RestClientModule<S, A> {
public BaseVCloudRestClientModule(Class<S> syncClientType, Class<A> asyncClientType) { public BaseVCloudRestClientModule(Class<S> syncClientType,
Class<A> asyncClientType) {
super(syncClientType, asyncClientType); super(syncClientType, asyncClientType);
} }
@ -111,35 +110,26 @@ public abstract class BaseVCloudRestClientModule<S extends VCloudClient, A exten
@Provides @Provides
@Singleton @Singleton
protected Predicate<IPSocket> socketTester(SocketOpen open) { protected Predicate<String> successTester(TaskSuccess success,
return new RetryablePredicate<IPSocket>(open, 130, 10, TimeUnit.SECONDS); @Named(PROPERTY_VCLOUD_TIMEOUT_TASK_COMPLETED) long completed) {
} return new RetryablePredicate<String>(success, completed);
@Provides
@Singleton
protected Predicate<String> successTester(TaskSuccess success) {
return new RetryablePredicate<String>(success, 60 * 30, 10, TimeUnit.SECONDS);
}
@Provides
@Singleton
@Named("NOT_FOUND")
protected Predicate<VApp> successTester(VAppNotFound notFound) {
return new RetryablePredicate<VApp>(notFound, 5, 1, TimeUnit.SECONDS);
} }
@VCloudToken @VCloudToken
@Provides @Provides
String provideVCloudToken(Supplier<VCloudSession> cache) { String provideVCloudToken(Supplier<VCloudSession> cache) {
return checkNotNull(cache.get().getVCloudToken(), "No token present in session"); return checkNotNull(cache.get().getVCloudToken(),
"No token present in session");
} }
@Provides @Provides
@Org @Org
@Singleton @Singleton
protected URI provideOrg(Supplier<VCloudSession> cache, @Named(PROPERTY_VCLOUD_USER) String user) { protected URI provideOrg(Supplier<VCloudSession> cache,
@Named(PROPERTY_VCLOUD_USER) String user) {
VCloudSession discovery = cache.get(); VCloudSession discovery = cache.get();
checkState(discovery.getOrgs().size() > 0, "No orgs present for user: " + user); checkState(discovery.getOrgs().size() > 0, "No orgs present for user: "
+ user);
return Iterables.getLast(discovery.getOrgs().values()).getLocation(); return Iterables.getLast(discovery.getOrgs().values()).getLocation();
} }
@ -158,30 +148,36 @@ public abstract class BaseVCloudRestClientModule<S extends VCloudClient, A exten
@Provides @Provides
@Singleton @Singleton
Supplier<VCloudSession> provideVCloudTokenCache( Supplier<VCloudSession> provideVCloudTokenCache(
@Named(PROPERTY_VCLOUD_SESSIONINTERVAL) long seconds, final VCloudLoginAsyncClient login) { @Named(PROPERTY_VCLOUD_SESSIONINTERVAL) long seconds,
final VCloudLoginAsyncClient login) {
return new ExpirableSupplier<VCloudSession>( return new ExpirableSupplier<VCloudSession>(
new RetryOnTimeOutExceptionSupplier<VCloudSession>(new Supplier<VCloudSession>() { new RetryOnTimeOutExceptionSupplier<VCloudSession>(
public VCloudSession get() { new Supplier<VCloudSession>() {
// http://code.google.com/p/google-guice/issues/detail?id=483 public VCloudSession get() {
// guice doesn't remember when singleton providers throw exceptions. // http://code.google.com/p/google-guice/issues/detail?id=483
// in this case, if describeRegions fails, it is called again for // guice doesn't remember when singleton providers throw
// each provider method that depends on it. To short-circuit this, // exceptions.
// we remember the last exception trusting that guice is single-threaded // in this case, if describeRegions fails, it is called
if (authException != null) // again for
throw authException; // each provider method that depends on it. To
try { // short-circuit this,
return login.login().get(10, TimeUnit.SECONDS); // we remember the last exception trusting that guice is
} catch (AuthorizationException e) { // single-threaded
BaseVCloudRestClientModule.this.authException = e; if (authException != null)
throw e; throw authException;
} catch (Exception e) { try {
Throwables.propagate(e); return login.login().get(10, TimeUnit.SECONDS);
assert false : e; } catch (AuthorizationException e) {
return null; BaseVCloudRestClientModule.this.authException = e;
throw e;
} catch (Exception e) {
Throwables.propagate(e);
assert false : e;
return null;
}
} }
}
}), seconds, TimeUnit.SECONDS); }), seconds, TimeUnit.SECONDS);
} }
@Provides @Provides
@ -194,34 +190,39 @@ public abstract class BaseVCloudRestClientModule<S extends VCloudClient, A exten
@Provides @Provides
@Singleton @Singleton
@org.jclouds.vcloud.endpoints.VCloudLogin @org.jclouds.vcloud.endpoints.VCloudLogin
protected URI provideAuthenticationURI(VCloudVersionsAsyncClient versionService, protected URI provideAuthenticationURI(
@Named(PROPERTY_VCLOUD_VERSION) String version) throws InterruptedException, VCloudVersionsAsyncClient versionService,
ExecutionException, TimeoutException { @Named(PROPERTY_VCLOUD_VERSION) String version)
SortedMap<String, URI> versions = versionService.getSupportedVersions().get(180, throws InterruptedException, ExecutionException, TimeoutException {
TimeUnit.SECONDS); SortedMap<String, URI> versions = versionService.getSupportedVersions()
.get(180, TimeUnit.SECONDS);
checkState(versions.size() > 0, "No versions present"); checkState(versions.size() > 0, "No versions present");
checkState(versions.containsKey(version), "version " + version + " not present in: " checkState(versions.containsKey(version), "version " + version
+ versions); + " not present in: " + versions);
return versions.get(version); return versions.get(version);
} }
@Provides @Provides
@Singleton @Singleton
protected VCloudLoginAsyncClient provideVCloudLogin(AsyncClientFactory factory) { protected VCloudLoginAsyncClient provideVCloudLogin(
AsyncClientFactory factory) {
return factory.create(VCloudLoginAsyncClient.class); return factory.create(VCloudLoginAsyncClient.class);
} }
@Provides @Provides
@Singleton @Singleton
protected VCloudVersionsAsyncClient provideVCloudVersions(AsyncClientFactory factory) { protected VCloudVersionsAsyncClient provideVCloudVersions(
AsyncClientFactory factory) {
return factory.create(VCloudVersionsAsyncClient.class); return factory.create(VCloudVersionsAsyncClient.class);
} }
@Provides @Provides
@Singleton @Singleton
public BasicAuthentication provideBasicAuthentication(@Named(PROPERTY_VCLOUD_USER) String user, public BasicAuthentication provideBasicAuthentication(
@Named(PROPERTY_VCLOUD_KEY) String key, EncryptionService encryptionService) @Named(PROPERTY_VCLOUD_USER) String user,
throws UnsupportedEncodingException { @Named(PROPERTY_VCLOUD_KEY) String key,
EncryptionService encryptionService)
throws UnsupportedEncodingException {
return new BasicAuthentication(user, key, encryptionService); return new BasicAuthentication(user, key, encryptionService);
} }
@ -248,8 +249,8 @@ public abstract class BaseVCloudRestClientModule<S extends VCloudClient, A exten
@Provides @Provides
@Singleton @Singleton
protected Organization provideOrganization(VCloudClient discovery) throws ExecutionException, protected Organization provideOrganization(VCloudClient discovery)
TimeoutException, InterruptedException { throws ExecutionException, TimeoutException, InterruptedException {
if (authException != null) if (authException != null)
throw authException; throw authException;
try { try {
@ -264,29 +265,33 @@ public abstract class BaseVCloudRestClientModule<S extends VCloudClient, A exten
@VDC @VDC
@Singleton @Singleton
protected URI provideDefaultVDC(Organization org) { protected URI provideDefaultVDC(Organization org) {
checkState(org.getVDCs().size() > 0, "No vdcs present in org: " + org.getName()); checkState(org.getVDCs().size() > 0, "No vdcs present in org: "
+ org.getName());
return Iterables.get(org.getVDCs().values(), 0).getLocation(); return Iterables.get(org.getVDCs().values(), 0).getLocation();
} }
@Provides @Provides
@Catalog @Catalog
@Singleton @Singleton
protected URI provideCatalog(Organization org, @Named(PROPERTY_VCLOUD_USER) String user) { protected URI provideCatalog(Organization org,
checkState(org.getCatalogs().size() > 0, "No catalogs present in org: " + org.getName()); @Named(PROPERTY_VCLOUD_USER) String user) {
checkState(org.getCatalogs().size() > 0, "No catalogs present in org: "
+ org.getName());
return Iterables.get(org.getCatalogs().values(), 0).getLocation(); return Iterables.get(org.getCatalogs().values(), 0).getLocation();
} }
@Provides @Provides
@Network @Network
@Singleton @Singleton
protected URI provideDefaultNetwork(VCloudClient client) throws InterruptedException, protected URI provideDefaultNetwork(VCloudClient client)
ExecutionException, TimeoutException { throws InterruptedException, ExecutionException, TimeoutException {
if (authException != null) if (authException != null)
throw authException; throw authException;
try { try {
org.jclouds.vcloud.domain.VDC vDC = client.getDefaultVDC(); org.jclouds.vcloud.domain.VDC vDC = client.getDefaultVDC();
Map<String, NamedResource> networks = vDC.getAvailableNetworks(); Map<String, NamedResource> networks = vDC.getAvailableNetworks();
checkState(networks.size() > 0, "No networks present in vDC: " + vDC.getName()); checkState(networks.size() > 0, "No networks present in vDC: "
+ vDC.getName());
return Iterables.get(networks.values(), 0).getLocation(); return Iterables.get(networks.values(), 0).getLocation();
} catch (AuthorizationException e) { } catch (AuthorizationException e) {
BaseVCloudRestClientModule.this.authException = e; BaseVCloudRestClientModule.this.authException = e;
@ -304,18 +309,19 @@ public abstract class BaseVCloudRestClientModule<S extends VCloudClient, A exten
@Override @Override
protected void bindErrorHandlers() { protected void bindErrorHandlers() {
bind(HttpErrorHandler.class).annotatedWith(Redirection.class).to( bind(HttpErrorHandler.class).annotatedWith(Redirection.class).to(
ParseVCloudErrorFromHttpResponse.class); ParseVCloudErrorFromHttpResponse.class);
bind(HttpErrorHandler.class).annotatedWith(ClientError.class).to( bind(HttpErrorHandler.class).annotatedWith(ClientError.class).to(
ParseVCloudErrorFromHttpResponse.class); ParseVCloudErrorFromHttpResponse.class);
bind(HttpErrorHandler.class).annotatedWith(ServerError.class).to( bind(HttpErrorHandler.class).annotatedWith(ServerError.class).to(
ParseVCloudErrorFromHttpResponse.class); ParseVCloudErrorFromHttpResponse.class);
} }
@Provides @Provides
@TasksList @TasksList
@Singleton @Singleton
protected URI provideDefaultTasksList(Organization org) { protected URI provideDefaultTasksList(Organization org) {
checkState(org.getTasksLists().size() > 0, "No tasks lists present in org: " + org.getName()); checkState(org.getTasksLists().size() > 0,
"No tasks lists present in org: " + org.getName());
return Iterables.get(org.getTasksLists().values(), 0).getLocation(); return Iterables.get(org.getTasksLists().values(), 0).getLocation();
} }
} }

View File

@ -42,14 +42,26 @@ public class InstantiateVAppTemplateOptions {
private String fenceMode; private String fenceMode;
private String dhcpEnabled; private String dhcpEnabled;
private String networkName; private String networkName;
private boolean blockOnDeploy = true;
private Map<String, String> properties = Maps.newTreeMap(); private Map<String, String> properties = Maps.newTreeMap();
public InstantiateVAppTemplateOptions productProperty(String key, String value) { public boolean shouldBlockOnDeploy() {
return blockOnDeploy;
}
public InstantiateVAppTemplateOptions blockOnDeploy(boolean blockOnDeploy) {
this.blockOnDeploy = blockOnDeploy;
return this;
}
public InstantiateVAppTemplateOptions productProperty(String key,
String value) {
properties.put(checkNotNull(key, "key"), checkNotNull(value, "value")); properties.put(checkNotNull(key, "key"), checkNotNull(value, "value"));
return this; return this;
} }
public InstantiateVAppTemplateOptions productProperties(Map<String, String> properties) { public InstantiateVAppTemplateOptions productProperties(
Map<String, String> properties) {
this.properties.putAll(checkNotNull(properties, "properties")); this.properties.putAll(checkNotNull(properties, "properties"));
return this; return this;
} }
@ -88,7 +100,8 @@ public class InstantiateVAppTemplateOptions {
} }
public InstantiateVAppTemplateOptions inNetwork(URI networkLocation) { public InstantiateVAppTemplateOptions inNetwork(URI networkLocation) {
this.network = checkNotNull(networkLocation, "networkLocation").toASCIIString(); this.network = checkNotNull(networkLocation, "networkLocation")
.toASCIIString();
return this; return this;
} }
@ -126,6 +139,15 @@ public class InstantiateVAppTemplateOptions {
public static class Builder { public static class Builder {
/**
* @see InstantiateVAppTemplateOptions#blockOnDeploy
*/
public static InstantiateVAppTemplateOptions blockOnDeploy(
boolean blockOnDeploy) {
InstantiateVAppTemplateOptions options = new InstantiateVAppTemplateOptions();
return options.blockOnDeploy(blockOnDeploy);
}
/** /**
* @see InstantiateVAppTemplateOptions#processorCount(int) * @see InstantiateVAppTemplateOptions#processorCount(int)
*/ */
@ -169,7 +191,8 @@ public class InstantiateVAppTemplateOptions {
/** /**
* @see InstantiateVAppTemplateOptions#dhcpEnabled(boolean) * @see InstantiateVAppTemplateOptions#dhcpEnabled(boolean)
*/ */
public static InstantiateVAppTemplateOptions dhcpEnabled(boolean dhcpEnabled) { public static InstantiateVAppTemplateOptions dhcpEnabled(
boolean dhcpEnabled) {
InstantiateVAppTemplateOptions options = new InstantiateVAppTemplateOptions(); InstantiateVAppTemplateOptions options = new InstantiateVAppTemplateOptions();
return options.dhcpEnabled(dhcpEnabled); return options.dhcpEnabled(dhcpEnabled);
} }
@ -177,7 +200,8 @@ public class InstantiateVAppTemplateOptions {
/** /**
* @see InstantiateVAppTemplateOptions#networkName(String) * @see InstantiateVAppTemplateOptions#networkName(String)
*/ */
public static InstantiateVAppTemplateOptions networkName(String networkName) { public static InstantiateVAppTemplateOptions networkName(
String networkName) {
InstantiateVAppTemplateOptions options = new InstantiateVAppTemplateOptions(); InstantiateVAppTemplateOptions options = new InstantiateVAppTemplateOptions();
return options.networkName(networkName); return options.networkName(networkName);
} }
@ -185,7 +209,8 @@ public class InstantiateVAppTemplateOptions {
/** /**
* @see InstantiateVAppTemplateOptions#productProperty(String,String) * @see InstantiateVAppTemplateOptions#productProperty(String,String)
*/ */
public static InstantiateVAppTemplateOptions productProperty(String key, String value) { public static InstantiateVAppTemplateOptions productProperty(String key,
String value) {
InstantiateVAppTemplateOptions options = new InstantiateVAppTemplateOptions(); InstantiateVAppTemplateOptions options = new InstantiateVAppTemplateOptions();
return options.productProperty(key, value); return options.productProperty(key, value);
} }
@ -193,7 +218,8 @@ public class InstantiateVAppTemplateOptions {
/** /**
* @see InstantiateVAppTemplateOptions#setProperties(Map<String, String>) * @see InstantiateVAppTemplateOptions#setProperties(Map<String, String>)
*/ */
public static InstantiateVAppTemplateOptions productProperties(Map<String, String> properties) { public static InstantiateVAppTemplateOptions productProperties(
Map<String, String> properties) {
InstantiateVAppTemplateOptions options = new InstantiateVAppTemplateOptions(); InstantiateVAppTemplateOptions options = new InstantiateVAppTemplateOptions();
return options.productProperties(properties); return options.productProperties(properties);
} }
@ -201,10 +227,12 @@ public class InstantiateVAppTemplateOptions {
@Override @Override
public String toString() { public String toString() {
return "InstantiateVAppTemplateOptions [cpuCount=" + cpuCount + ", memorySizeMegabytes=" return "InstantiateVAppTemplateOptions [cpuCount=" + cpuCount
+ memorySizeMegabytes + ", diskSizeKilobytes=" + diskSizeKilobytes + ", network=" + ", memorySizeMegabytes=" + memorySizeMegabytes
+ network + ", networkName=" + networkName + ", fenceMode=" + fenceMode + ", diskSizeKilobytes=" + diskSizeKilobytes + ", network="
+ ", dhcpEnabled=" + dhcpEnabled + ", properties=" + properties + "]"; + network + ", networkName=" + networkName + ", fenceMode="
+ fenceMode + ", dhcpEnabled=" + dhcpEnabled + ", properties="
+ properties + "]";
} }
@Override @Override
@ -212,14 +240,21 @@ public class InstantiateVAppTemplateOptions {
final int prime = 31; final int prime = 31;
int result = 1; int result = 1;
result = prime * result + ((cpuCount == null) ? 0 : cpuCount.hashCode()); result = prime * result + ((cpuCount == null) ? 0 : cpuCount.hashCode());
result = prime * result + ((dhcpEnabled == null) ? 0 : dhcpEnabled.hashCode());
result = prime * result + ((diskSizeKilobytes == null) ? 0 : diskSizeKilobytes.hashCode());
result = prime * result + ((fenceMode == null) ? 0 : fenceMode.hashCode());
result = prime * result result = prime * result
+ ((memorySizeMegabytes == null) ? 0 : memorySizeMegabytes.hashCode()); + ((dhcpEnabled == null) ? 0 : dhcpEnabled.hashCode());
result = prime * result
+ ((diskSizeKilobytes == null) ? 0 : diskSizeKilobytes.hashCode());
result = prime * result
+ ((fenceMode == null) ? 0 : fenceMode.hashCode());
result = prime
* result
+ ((memorySizeMegabytes == null) ? 0 : memorySizeMegabytes
.hashCode());
result = prime * result + ((network == null) ? 0 : network.hashCode()); result = prime * result + ((network == null) ? 0 : network.hashCode());
result = prime * result + ((networkName == null) ? 0 : networkName.hashCode()); result = prime * result
result = prime * result + ((properties == null) ? 0 : properties.hashCode()); + ((networkName == null) ? 0 : networkName.hashCode());
result = prime * result
+ ((properties == null) ? 0 : properties.hashCode());
return result; return result;
} }

View File

@ -18,6 +18,7 @@
*/ */
package org.jclouds.vcloud.reference; package org.jclouds.vcloud.reference;
/** /**
* Configuration properties and constants used in VCloud connections. * Configuration properties and constants used in VCloud connections.
* *
@ -51,4 +52,6 @@ public interface VCloudConstants {
public static final String PROPERTY_VCLOUD_XML_NAMESPACE = "jclouds.vcloud.xml.ns"; public static final String PROPERTY_VCLOUD_XML_NAMESPACE = "jclouds.vcloud.xml.ns";
public static final String PROPERTY_VCLOUD_XML_SCHEMA = "jclouds.vcloud.xml.schema"; public static final String PROPERTY_VCLOUD_XML_SCHEMA = "jclouds.vcloud.xml.schema";
public static final String PROPERTY_VCLOUD_TIMEOUT_TASK_COMPLETED = "jclouds.vcloud.timeout.task-complete";
} }

View File

@ -27,7 +27,7 @@ public class VCloudComputeServiceLiveTest extends BaseComputeServiceLiveTest {
@Override @Override
public void setServiceDefaults() { public void setServiceDefaults() {
System.setProperty("vcloud.endpoint", checkNotNull(System System.setProperty("vcloud.endpoint", checkNotNull(System
.getProperty("jclouds.test.endpoint"), "jclouds.test.endpoint")); .getProperty("jclouds.test.endpoint"), "jclouds.test.endpoint"));
service = "vcloud"; service = "vcloud";
} }
@ -39,7 +39,8 @@ public class VCloudComputeServiceLiveTest extends BaseComputeServiceLiveTest {
public void testAssignability() throws Exception { public void testAssignability() throws Exception {
@SuppressWarnings("unused") @SuppressWarnings("unused")
RestContext<VCloudClient, VCloudAsyncClient> tmContext = new ComputeServiceContextFactory() RestContext<VCloudClient, VCloudAsyncClient> tmContext = new ComputeServiceContextFactory()
.createContext(service, user, password).getProviderSpecificContext(); .createContext(service, user, password)
.getProviderSpecificContext();
} }
@Override @Override
@ -55,4 +56,5 @@ public class VCloudComputeServiceLiveTest extends BaseComputeServiceLiveTest {
System.out.println(allData.getExtra()); System.out.println(allData.getExtra());
} }
} }
} }

View File

@ -19,6 +19,7 @@
package org.jclouds.vcloud.hostingdotcom; package org.jclouds.vcloud.hostingdotcom;
import static org.jclouds.vcloud.reference.VCloudConstants.PROPERTY_VCLOUD_ENDPOINT; import static org.jclouds.vcloud.reference.VCloudConstants.PROPERTY_VCLOUD_ENDPOINT;
import static org.jclouds.vcloud.reference.VCloudConstants.PROPERTY_VCLOUD_TIMEOUT_TASK_COMPLETED;
import java.net.URI; import java.net.URI;
import java.util.Properties; import java.util.Properties;
@ -30,11 +31,15 @@ import org.jclouds.vcloud.VCloudPropertiesBuilder;
* *
* @author Adrian Cole * @author Adrian Cole
*/ */
public class HostingDotComVCloudPropertiesBuilder extends VCloudPropertiesBuilder { public class HostingDotComVCloudPropertiesBuilder extends
VCloudPropertiesBuilder {
@Override @Override
protected Properties defaultProperties() { protected Properties defaultProperties() {
Properties properties = super.defaultProperties(); Properties properties = super.defaultProperties();
properties.setProperty(PROPERTY_VCLOUD_ENDPOINT, "https://vcloud.safesecureweb.com/api"); properties.setProperty(PROPERTY_VCLOUD_ENDPOINT,
"https://vcloud.safesecureweb.com/api");
properties.setProperty(PROPERTY_VCLOUD_TIMEOUT_TASK_COMPLETED,
45 * 60 * 1000l + "");
return properties; return properties;
} }

View File

@ -3,7 +3,6 @@ package org.jclouds.vcloud.hostingdotcom.compute;
import java.util.Map; import java.util.Map;
import javax.inject.Inject; import javax.inject.Inject;
import javax.inject.Named;
import javax.inject.Singleton; import javax.inject.Singleton;
import org.jclouds.compute.domain.NodeState; import org.jclouds.compute.domain.NodeState;
@ -23,17 +22,18 @@ import com.google.common.collect.ImmutableMap;
public class HostingDotComVCloudComputeClient extends BaseVCloudComputeClient { public class HostingDotComVCloudComputeClient extends BaseVCloudComputeClient {
@Inject @Inject
protected HostingDotComVCloudComputeClient(VCloudClient client, Predicate<String> successTester, protected HostingDotComVCloudComputeClient(VCloudClient client,
@Named("NOT_FOUND") Predicate<VApp> notFoundTester, Predicate<String> successTester,
Map<VAppStatus, NodeState> vAppStatusToNodeState) { Map<VAppStatus, NodeState> vAppStatusToNodeState) {
super(client, successTester, notFoundTester, vAppStatusToNodeState); super(client, successTester, vAppStatusToNodeState);
} }
@Override @Override
protected Map<String, String> parseResponse(String templateId, VApp vAppResponse) { protected Map<String, String> parseResponse(String templateId,
VApp vAppResponse) {
HostingDotComVApp hVApp = HostingDotComVApp.class.cast(vAppResponse); HostingDotComVApp hVApp = HostingDotComVApp.class.cast(vAppResponse);
return ImmutableMap.<String, String> of("id", vAppResponse.getId(), "username", hVApp return ImmutableMap.<String, String> of("id", vAppResponse.getId(),
.getUsername(), "password", hVApp.getPassword()); "username", hVApp.getUsername(), "password", hVApp.getPassword());
} }
} }

View File

@ -19,40 +19,40 @@
package org.jclouds.vcloud.hostingdotcom.config; package org.jclouds.vcloud.hostingdotcom.config;
import java.net.URI; import java.net.URI;
import java.util.concurrent.TimeUnit;
import javax.inject.Singleton; import javax.inject.Singleton;
import org.jclouds.http.RequiresHttp; import org.jclouds.http.RequiresHttp;
import org.jclouds.predicates.RetryablePredicate;
import org.jclouds.rest.ConfiguresRestClient; import org.jclouds.rest.ConfiguresRestClient;
import org.jclouds.vcloud.VCloudAsyncClient; import org.jclouds.vcloud.VCloudAsyncClient;
import org.jclouds.vcloud.VCloudClient; import org.jclouds.vcloud.VCloudClient;
import org.jclouds.vcloud.config.BaseVCloudRestClientModule; import org.jclouds.vcloud.config.BaseVCloudRestClientModule;
import org.jclouds.vcloud.hostingdotcom.HostingDotComVCloudAsyncClient; import org.jclouds.vcloud.hostingdotcom.HostingDotComVCloudAsyncClient;
import org.jclouds.vcloud.hostingdotcom.HostingDotComVCloudClient; import org.jclouds.vcloud.hostingdotcom.HostingDotComVCloudClient;
import org.jclouds.vcloud.predicates.TaskSuccess;
import com.google.common.base.Predicate;
import com.google.inject.Provides; import com.google.inject.Provides;
/** /**
* Configures the VCloud authentication service connection, including logging and http transport. * Configures the VCloud authentication service connection, including logging
* and http transport.
* *
* @author Adrian Cole * @author Adrian Cole
*/ */
@RequiresHttp @RequiresHttp
@ConfiguresRestClient @ConfiguresRestClient
public class HostingDotComVCloudRestClientModule extends public class HostingDotComVCloudRestClientModule
BaseVCloudRestClientModule<HostingDotComVCloudClient, HostingDotComVCloudAsyncClient> { extends
BaseVCloudRestClientModule<HostingDotComVCloudClient, HostingDotComVCloudAsyncClient> {
public HostingDotComVCloudRestClientModule() { public HostingDotComVCloudRestClientModule() {
super(HostingDotComVCloudClient.class, HostingDotComVCloudAsyncClient.class); super(HostingDotComVCloudClient.class,
HostingDotComVCloudAsyncClient.class);
} }
@Provides @Provides
@Singleton @Singleton
protected VCloudAsyncClient provideVCloudAsyncClient(HostingDotComVCloudAsyncClient in) { protected VCloudAsyncClient provideVCloudAsyncClient(
HostingDotComVCloudAsyncClient in) {
return in; return in;
} }
@ -67,8 +67,4 @@ public class HostingDotComVCloudRestClientModule extends
return URI.create("https://vcloud.safesecureweb.com/network/1990"); return URI.create("https://vcloud.safesecureweb.com/network/1990");
} }
@Override
protected Predicate<String> successTester(TaskSuccess success) {
return new RetryablePredicate<String>(success, 45, 10, TimeUnit.MINUTES);
}
} }

View File

@ -60,37 +60,48 @@ public class TerremarkVCloudComputeClient extends BaseVCloudComputeClient {
@Inject @Inject
protected TerremarkVCloudComputeClient(TerremarkVCloudClient client, protected TerremarkVCloudComputeClient(TerremarkVCloudClient client,
PopulateDefaultLoginCredentialsForImageStrategy credentialsProvider, PopulateDefaultLoginCredentialsForImageStrategy credentialsProvider,
@Named("PASSWORD") Provider<String> passwordGenerator, Predicate<String> successTester, @Named("PASSWORD") Provider<String> passwordGenerator,
@Named("NOT_FOUND") Predicate<VApp> notFoundTester, Predicate<String> successTester,
Map<VAppStatus, NodeState> vAppStatusToNodeState) { Map<VAppStatus, NodeState> vAppStatusToNodeState) {
super(client, successTester, notFoundTester, vAppStatusToNodeState); super(client, successTester, vAppStatusToNodeState);
this.client = client; this.client = client;
this.credentialsProvider = credentialsProvider; this.credentialsProvider = credentialsProvider;
this.passwordGenerator = passwordGenerator; this.passwordGenerator = passwordGenerator;
} }
@Override @Override
protected Map<String, String> parseAndValidateResponse(String templateId, VApp vAppResponse) { protected Map<String, String> parseAndValidateResponse(String templateId,
Credentials credentials = credentialsProvider.execute(client.getVAppTemplate(templateId)); VApp vAppResponse) {
Map<String, String> toReturn = super.parseResponse(templateId, vAppResponse); Credentials credentials = credentialsProvider.execute(client
.getVAppTemplate(templateId));
Map<String, String> toReturn = super.parseResponse(templateId,
vAppResponse);
toReturn.put("username", credentials.account); toReturn.put("username", credentials.account);
toReturn.put("password", credentials.key); toReturn.put("password", credentials.key);
return toReturn; return toReturn;
} }
@Override @Override
public Map<String, String> start(String vDCId, String name, String templateId, public Map<String, String> start(String vDCId, String name,
InstantiateVAppTemplateOptions options, int... portsToOpen) { String templateId, InstantiateVAppTemplateOptions options,
int... portsToOpen) {
if (options.getDiskSizeKilobytes() != null) { if (options.getDiskSizeKilobytes() != null) {
logger.warn("trmk does not support resizing the primary disk; unsetting disk size"); logger
.warn("trmk does not support resizing the primary disk; unsetting disk size");
} }
// we only get IP addresses after "deploy"
if (portsToOpen.length > 0 && !options.shouldBlockOnDeploy())
throw new IllegalArgumentException(
"We cannot open ports on terremark unless we can deploy the vapp");
String password = null; String password = null;
if (client.getVAppTemplate(templateId).getDescription().indexOf("Windows") != -1) { if (client.getVAppTemplate(templateId).getDescription()
.indexOf("Windows") != -1) {
password = passwordGenerator.get(); password = passwordGenerator.get();
options.getProperties().put("password", password); options.getProperties().put("password", password);
} }
Map<String, String> response = super.start(vDCId, name, templateId, options, portsToOpen); Map<String, String> response = super.start(vDCId, name, templateId,
options, portsToOpen);
if (password != null) { if (password != null) {
response = new LinkedHashMap<String, String>(response); response = new LinkedHashMap<String, String>(response);
response.put("password", password); response.put("password", password);
@ -103,68 +114,77 @@ public class TerremarkVCloudComputeClient extends BaseVCloudComputeClient {
public String createPublicAddressMappedToPorts(String vAppId, int... ports) { public String createPublicAddressMappedToPorts(String vAppId, int... ports) {
VApp vApp = client.getVApp(vAppId); VApp vApp = client.getVApp(vAppId);
PublicIpAddress ip = null; PublicIpAddress ip = null;
String privateAddress = Iterables.getLast(vApp.getNetworkToAddresses().values()); String privateAddress = Iterables.getLast(vApp.getNetworkToAddresses()
.values());
for (int port : ports) { for (int port : ports) {
InternetService is = null; InternetService is = null;
Protocol protocol; Protocol protocol;
switch (port) { switch (port) {
case 22: case 22:
protocol = Protocol.TCP; protocol = Protocol.TCP;
break; break;
case 80: case 80:
case 8080: case 8080:
protocol = Protocol.HTTP; protocol = Protocol.HTTP;
break; break;
case 443: case 443:
protocol = Protocol.HTTPS; protocol = Protocol.HTTPS;
break; break;
default: default:
protocol = Protocol.HTTP; protocol = Protocol.HTTP;
break; break;
} }
if (ip == null) { if (ip == null) {
logger.debug(">> creating InternetService in vDC %s:%s:%d", vApp.getVDC().getId(), logger.debug(">> creating InternetService in vDC %s:%s:%d", vApp
protocol, port); .getVDC().getId(), protocol, port);
is = client.addInternetServiceToVDC(vApp.getVDC().getId(), vApp.getName() + "-" + port, is = client.addInternetServiceToVDC(vApp.getVDC().getId(), vApp
protocol, port, withDescription(String.format( .getName()
"port %d access to serverId: %s name: %s", port, vApp.getId(), vApp + "-" + port, protocol, port, withDescription(String.format(
.getName()))); "port %d access to serverId: %s name: %s", port,
vApp.getId(), vApp.getName())));
ip = is.getPublicIpAddress(); ip = is.getPublicIpAddress();
} else { } else {
logger.debug(">> adding InternetService %s:%s:%d", ip.getAddress(), protocol, port); logger.debug(">> adding InternetService %s:%s:%d", ip.getAddress(),
is = client.addInternetServiceToExistingIp(ip.getId(), vApp.getName() + "-" + port, protocol, port);
protocol, port, withDescription(String.format( is = client.addInternetServiceToExistingIp(ip.getId(), vApp
"port %d access to serverId: %s name: %s", port, vApp.getId(), vApp .getName()
.getName()))); + "-" + port, protocol, port, withDescription(String.format(
"port %d access to serverId: %s name: %s", port,
vApp.getId(), vApp.getName())));
} }
logger.debug("<< created InternetService(%s) %s:%s:%d", is.getId(), is logger.debug("<< created InternetService(%s) %s:%s:%d", is.getId(), is
.getPublicIpAddress().getAddress(), is.getProtocol(), is.getPort()); .getPublicIpAddress().getAddress(), is.getProtocol(), is
logger.debug(">> adding Node %s:%d -> %s:%d", is.getPublicIpAddress().getAddress(), is .getPort());
.getPort(), privateAddress, port); logger.debug(">> adding Node %s:%d -> %s:%d", is.getPublicIpAddress()
Node node = client.addNode(is.getId(), privateAddress, vApp.getName() + "-" + port, port); .getAddress(), is.getPort(), privateAddress, port);
Node node = client.addNode(is.getId(), privateAddress, vApp.getName()
+ "-" + port, port);
logger.debug("<< added Node(%s)", node.getId()); logger.debug("<< added Node(%s)", node.getId());
} }
return ip != null ? ip.getAddress() : null; return ip != null ? ip.getAddress() : null;
} }
private Set<PublicIpAddress> deleteInternetServicesAndNodesAssociatedWithVApp(VApp vApp) { private Set<PublicIpAddress> deleteInternetServicesAndNodesAssociatedWithVApp(
VApp vApp) {
Set<PublicIpAddress> ipAddresses = Sets.newHashSet(); Set<PublicIpAddress> ipAddresses = Sets.newHashSet();
SERVICE: for (InternetService service : client.getAllInternetServicesInVDC(vApp.getVDC() SERVICE: for (InternetService service : client
.getId())) { .getAllInternetServicesInVDC(vApp.getVDC().getId())) {
for (Node node : client.getNodes(service.getId())) { for (Node node : client.getNodes(service.getId())) {
if (vApp.getNetworkToAddresses().containsValue(node.getIpAddress())) { if (vApp.getNetworkToAddresses().containsValue(node.getIpAddress())) {
ipAddresses.add(service.getPublicIpAddress()); ipAddresses.add(service.getPublicIpAddress());
logger.debug(">> deleting Node(%s) %s:%d -> %s:%d", node.getId(), service logger.debug(">> deleting Node(%s) %s:%d -> %s:%d",
.getPublicIpAddress().getAddress(), service.getPort(), node.getIpAddress(), node.getId(), service.getPublicIpAddress().getAddress(),
node.getPort()); service.getPort(), node.getIpAddress(), node.getPort());
client.deleteNode(node.getId()); client.deleteNode(node.getId());
logger.debug("<< deleted Node(%s)", node.getId()); logger.debug("<< deleted Node(%s)", node.getId());
SortedSet<Node> nodes = client.getNodes(service.getId()); SortedSet<Node> nodes = client.getNodes(service.getId());
if (nodes.size() == 0) { if (nodes.size() == 0) {
logger.debug(">> deleting InternetService(%s) %s:%d", service.getId(), service logger.debug(">> deleting InternetService(%s) %s:%d", service
.getPublicIpAddress().getAddress(), service.getPort()); .getId(), service.getPublicIpAddress().getAddress(),
service.getPort());
client.deleteInternetService(service.getId()); client.deleteInternetService(service.getId());
logger.debug("<< deleted InternetService(%s)", service.getId()); logger.debug("<< deleted InternetService(%s)", service
.getId());
continue SERVICE; continue SERVICE;
} }
} }
@ -173,13 +193,14 @@ public class TerremarkVCloudComputeClient extends BaseVCloudComputeClient {
return ipAddresses; return ipAddresses;
} }
private void deletePublicIpAddressesWithNoServicesAttached(Set<PublicIpAddress> ipAddresses) { private void deletePublicIpAddressesWithNoServicesAttached(
Set<PublicIpAddress> ipAddresses) {
IPADDRESS: for (PublicIpAddress address : ipAddresses) { IPADDRESS: for (PublicIpAddress address : ipAddresses) {
SortedSet<InternetService> services = client SortedSet<InternetService> services = client
.getInternetServicesOnPublicIp(address.getId()); .getInternetServicesOnPublicIp(address.getId());
if (services.size() == 0) { if (services.size() == 0) {
logger.debug(">> deleting PublicIpAddress(%s) %s", address.getId(), address logger.debug(">> deleting PublicIpAddress(%s) %s", address.getId(),
.getAddress()); address.getAddress());
client.deletePublicIp(address.getId()); client.deletePublicIp(address.getId());
logger.debug("<< deleted PublicIpAddress(%s)", address.getId()); logger.debug("<< deleted PublicIpAddress(%s)", address.getId());
continue IPADDRESS; continue IPADDRESS;
@ -188,9 +209,10 @@ public class TerremarkVCloudComputeClient extends BaseVCloudComputeClient {
} }
/** /**
* deletes the internet service and nodes associated with the vapp. Deletes the IP address, if * deletes the internet service and nodes associated with the vapp. Deletes
* there are no others using it. Finally, it powers off and deletes the vapp. Note that we do not * the IP address, if there are no others using it. Finally, it powers off
* call undeploy, as terremark does not support the command. * and deletes the vapp. Note that we do not call undeploy, as terremark does
* not support the command.
*/ */
@Override @Override
public void stop(String id) { public void stop(String id) {
@ -198,8 +220,8 @@ public class TerremarkVCloudComputeClient extends BaseVCloudComputeClient {
Set<PublicIpAddress> ipAddresses = deleteInternetServicesAndNodesAssociatedWithVApp(vApp); Set<PublicIpAddress> ipAddresses = deleteInternetServicesAndNodesAssociatedWithVApp(vApp);
deletePublicIpAddressesWithNoServicesAttached(ipAddresses); deletePublicIpAddressesWithNoServicesAttached(ipAddresses);
if (vApp.getStatus() != VAppStatus.OFF) { if (vApp.getStatus() != VAppStatus.OFF) {
logger.debug(">> powering off vApp(%s), current status: %s", vApp.getId(), vApp logger.debug(">> powering off vApp(%s), current status: %s", vApp
.getStatus()); .getId(), vApp.getStatus());
Task task = client.powerOffVApp(vApp.getId()); Task task = client.powerOffVApp(vApp.getId());
if (!taskTester.apply(task.getId())) { if (!taskTester.apply(task.getId())) {
throw new TaskException("powerOff", vApp, task); throw new TaskException("powerOff", vApp, task);
@ -209,8 +231,7 @@ public class TerremarkVCloudComputeClient extends BaseVCloudComputeClient {
} }
logger.debug(">> deleting vApp(%s)", vApp.getId()); logger.debug(">> deleting vApp(%s)", vApp.getId());
client.deleteVApp(id); client.deleteVApp(id);
boolean successful = notFoundTester.apply(vApp); logger.debug("<< deleted vApp(%s))", vApp.getId());
logger.debug("<< deleted vApp(%s) completed(%s)", vApp.getId(), successful);
} }
@Override @Override
@ -223,7 +244,8 @@ public class TerremarkVCloudComputeClient extends BaseVCloudComputeClient {
public Set<String> getPublicAddresses(String id) { public Set<String> getPublicAddresses(String id) {
VApp vApp = client.getVApp(id); VApp vApp = client.getVApp(id);
Set<String> ipAddresses = Sets.newHashSet(); Set<String> ipAddresses = Sets.newHashSet();
for (InternetService service : client.getAllInternetServicesInVDC(vApp.getVDC().getId())) { for (InternetService service : client.getAllInternetServicesInVDC(vApp
.getVDC().getId())) {
for (Node node : client.getNodes(service.getId())) { for (Node node : client.getNodes(service.getId())) {
if (vApp.getNetworkToAddresses().containsValue(node.getIpAddress())) { if (vApp.getNetworkToAddresses().containsValue(node.getIpAddress())) {
ipAddresses.add(service.getPublicIpAddress().getAddress()); ipAddresses.add(service.getPublicIpAddress().getAddress());

View File

@ -51,7 +51,8 @@ public class TerremarkVCloudComputeClientTest {
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
@Test @Test
public void testStartWindows() throws IOException { public void testStartWindows() throws IOException {
InputStream is = getClass().getResourceAsStream("/terremark/windows_description.txt"); InputStream is = getClass().getResourceAsStream(
"/terremark/windows_description.txt");
String description = new String(ByteStreams.toByteArray(is)); String description = new String(ByteStreams.toByteArray(is));
VAppTemplate template = createMock(VAppTemplate.class); VAppTemplate template = createMock(VAppTemplate.class);
expect(template.getDescription()).andReturn(description).atLeastOnce(); expect(template.getDescription()).andReturn(description).atLeastOnce();
@ -60,9 +61,10 @@ public class TerremarkVCloudComputeClientTest {
VApp vApp = createMock(VApp.class); VApp vApp = createMock(VApp.class);
expect( expect(
client.instantiateVAppTemplateInVDC("vDCId", "name", "templateId", client.instantiateVAppTemplateInVDC("vDCId", "name", "templateId",
new TerremarkInstantiateVAppTemplateOptions().productProperty("password", new TerremarkInstantiateVAppTemplateOptions()
"password"))).andReturn(vApp); .productProperty("password", "password"))).andReturn(
vApp);
Task task = createMock(Task.class); Task task = createMock(Task.class);
expect(vApp.getId()).andReturn("1").atLeastOnce(); expect(vApp.getId()).andReturn("1").atLeastOnce();
@ -76,16 +78,17 @@ public class TerremarkVCloudComputeClientTest {
Predicate<VApp> notFoundTester = createMock(Predicate.class); Predicate<VApp> notFoundTester = createMock(Predicate.class);
Map<VAppStatus, NodeState> vAppStatusToNodeState = createMock(Map.class); Map<VAppStatus, NodeState> vAppStatusToNodeState = createMock(Map.class);
TerremarkVCloudComputeClient computeClient = new TerremarkVCloudComputeClient(client, TerremarkVCloudComputeClient computeClient = new TerremarkVCloudComputeClient(
new ParseVAppTemplateDescriptionToGetDefaultLoginCredentials(), client,
new Provider<String>() { new ParseVAppTemplateDescriptionToGetDefaultLoginCredentials(),
new Provider<String>() {
@Override @Override
public String get() { public String get() {
return "password"; return "password";
} }
}, successTester, notFoundTester, vAppStatusToNodeState); }, successTester, vAppStatusToNodeState);
replay(template); replay(template);
replay(vApp); replay(vApp);
@ -95,8 +98,8 @@ public class TerremarkVCloudComputeClientTest {
replay(notFoundTester); replay(notFoundTester);
replay(vAppStatusToNodeState); replay(vAppStatusToNodeState);
Map<String, String> response = computeClient.start("vDCId", "name", "templateId", Map<String, String> response = computeClient.start("vDCId", "name",
new TerremarkInstantiateVAppTemplateOptions()); "templateId", new TerremarkInstantiateVAppTemplateOptions());
assertEquals(response.get("id"), "1"); assertEquals(response.get("id"), "1");
assertEquals(response.get("username"), "Administrator"); assertEquals(response.get("username"), "Administrator");