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.LoadBalancerService;
import org.jclouds.compute.config.ComputeServiceTimeoutsModule;
import org.jclouds.compute.domain.ComputeMetadata;
import org.jclouds.compute.domain.Image;
import org.jclouds.compute.domain.NodeMetadata;
@ -80,6 +81,7 @@ public class ${providerName}ComputeServiceContextModule extends ${providerName}C
@Override
protected void configure() {
super.configure();
install(new ComputeServiceTimeoutsModule());
bind(new TypeLiteral<ComputeServiceContext>() {
})
.to(
@ -93,12 +95,6 @@ public class ${providerName}ComputeServiceContextModule extends ${providerName}C
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
*/
@ -205,14 +201,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
@Singleton
Location getDefaultLocation(Set<? extends Location> locations) {

View File

@ -66,18 +66,27 @@ public class EC2ComputeService extends BaseComputeService {
@Inject
protected EC2ComputeService(ComputeServiceContext context,
Provider<Set<? extends Image>> images, Provider<Set<? extends Size>> sizes,
Provider<Set<? extends Location>> locations, ListNodesStrategy listNodesStrategy,
Provider<Set<? extends Image>> images,
Provider<Set<? extends Size>> sizes,
Provider<Set<? extends Location>> locations,
ListNodesStrategy listNodesStrategy,
GetNodeMetadataStrategy getNodeMetadataStrategy,
RunNodesAndAddToSetStrategy runNodesAndAddToSetStrategy,
RebootNodeStrategy rebootNodeStrategy, DestroyNodeStrategy destroyNodeStrategy,
RebootNodeStrategy rebootNodeStrategy,
DestroyNodeStrategy destroyNodeStrategy,
Provider<TemplateBuilder> templateBuilderProvider,
Provider<TemplateOptions> templateOptionsProvider, 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, utils, executor);
Provider<TemplateOptions> templateOptionsProvider,
@Named("NODE_RUNNING") Predicate<NodeMetadata> nodeRunning,
@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.credentialsMap = credentialsMap;
this.securityGroupMap = securityGroupMap;
@ -86,38 +95,46 @@ public class EC2ComputeService extends BaseComputeService {
private void deleteSecurityGroup(String region, String tag) {
checkNotEmpty(tag, "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);
ec2Client.getSecurityGroupServices().deleteSecurityGroupInRegion(region, group);
ec2Client.getSecurityGroupServices().deleteSecurityGroupInRegion(
region, group);
// 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);
}
}
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]+")) {
logger.debug(">> deleting keyPair(%s)", keyPair.getKeyName());
ec2Client.getKeyPairServices().deleteKeyPairInRegion(region, keyPair.getKeyName());
ec2Client.getKeyPairServices().deleteKeyPairInRegion(region,
keyPair.getKeyName());
// 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());
}
}
}
/**
* like {@link BaseComputeService#destroyNodesMatching} except that this will clean implicit
* keypairs and security groups.
* like {@link BaseComputeService#destroyNodesMatching} except that this will
* clean implicit keypairs and security groups.
*/
@Override
public Set<? extends NodeMetadata> destroyNodesMatching(Predicate<NodeMetadata> filter) {
public Set<? extends NodeMetadata> destroyNodesMatching(
Predicate<NodeMetadata> filter) {
Set<? extends NodeMetadata> deadOnes = super.destroyNodesMatching(filter);
Map<String, String> regionTags = Maps.newHashMap();
for (NodeMetadata nodeMetadata : deadOnes) {
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()) {
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.Image.ImageType;
import org.jclouds.aws.ec2.functions.RunningInstanceToStorageMappingUnix;
import org.jclouds.aws.ec2.predicates.InstancePresent;
import org.jclouds.aws.ec2.services.InstanceClient;
import org.jclouds.compute.ComputeService;
import org.jclouds.compute.ComputeServiceContext;
import org.jclouds.compute.config.ComputeServiceTimeoutsModule;
import org.jclouds.compute.domain.Architecture;
import org.jclouds.compute.domain.ComputeMetadata;
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.options.TemplateOptions;
import org.jclouds.compute.predicates.NodePredicates;
import org.jclouds.compute.predicates.ScriptStatusReturnsZero;
import org.jclouds.compute.predicates.ScriptStatusReturnsZero.CommandUsingClient;
import org.jclouds.compute.reference.ComputeServiceConstants;
import org.jclouds.compute.strategy.DestroyLoadBalancerStrategy;
import org.jclouds.compute.strategy.DestroyNodeStrategy;
@ -92,11 +92,9 @@ import org.jclouds.domain.LocationScope;
import org.jclouds.domain.internal.LocationImpl;
import org.jclouds.logging.Logger;
import org.jclouds.predicates.RetryablePredicate;
import com.google.inject.name.Names;
import com.google.common.base.Function;
import com.google.common.base.Predicate;
import com.google.common.base.Predicates;
import com.google.common.base.Splitter;
import com.google.common.base.Supplier;
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.Scopes;
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
*/
@ -122,25 +122,40 @@ public class EC2ComputeServiceContextModule extends EC2ContextModule {
this.providerName = providerName;
}
@Provides
@Singleton
@Named("PRESENT")
protected Predicate<RunningInstance> instancePresent(InstancePresent present) {
return new RetryablePredicate<RunningInstance>(present, 3000, 200,
TimeUnit.MILLISECONDS);
}
@Override
protected void configure() {
super.configure();
install(new ComputeServiceTimeoutsModule());
bind(TemplateBuilder.class).to(EC2TemplateBuilderImpl.class);
bind(TemplateOptions.class).to(EC2TemplateOptions.class);
bind(ComputeService.class).to(EC2ComputeService.class);
bind(new TypeLiteral<ComputeServiceContext>() {
}).to(new TypeLiteral<ComputeServiceContextImpl<EC2Client, EC2AsyncClient>>() {
})
.to(
new TypeLiteral<ComputeServiceContextImpl<EC2Client, EC2AsyncClient>>() {
}).in(Scopes.SINGLETON);
bind(LoadBalanceNodesStrategy.class).to(EC2LoadBalanceNodesStrategy.class);
bind(DestroyLoadBalancerStrategy.class).to(EC2DestroyLoadBalancerStrategy.class);
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(GetNodeMetadataStrategy.class).to(EC2GetNodeMetadataStrategy.class);
bind(RebootNodeStrategy.class).to(EC2RebootNodeStrategy.class);
bind(DestroyNodeStrategy.class).to(EC2DestroyNodeStrategy.class);
bind(new TypeLiteral<Function<RunningInstance, Map<String, String>>>() {
}).annotatedWith(Names.named("volumeMapping")).to(RunningInstanceToStorageMappingUnix.class)
.in(Scopes.SINGLETON);
}).annotatedWith(Names.named("volumeMapping")).to(
RunningInstanceToStorageMappingUnix.class).in(Scopes.SINGLETON);
}
@Provides
@ -160,11 +175,12 @@ public class EC2ComputeServiceContextModule extends EC2ContextModule {
@Provides
@Named("DEFAULT")
protected TemplateBuilder provideTemplate(TemplateBuilder template) {
return template.architecture(Architecture.X86_32).osFamily(UBUNTU).imageNameMatches(
".*10\\.?04.*");
return template.architecture(Architecture.X86_32).osFamily(UBUNTU)
.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
@Singleton
public static class EC2ListNodesStrategy implements ListNodesStrategy {
@ -178,7 +194,8 @@ public class EC2ComputeServiceContextModule extends EC2ContextModule {
private final ExecutorService executor;
@Inject
protected EC2ListNodesStrategy(EC2Client client, @EC2 Map<String, URI> regionMap,
protected EC2ListNodesStrategy(EC2Client client,
@EC2 Map<String, URI> regionMap,
RunningInstanceToNodeMetadata runningInstanceToNodeMetadata,
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService executor) {
this.client = client;
@ -200,29 +217,31 @@ public class EC2ComputeServiceContextModule extends EC2ContextModule {
Map<String, ListenableFuture<?>> parallelResponses = Maps.newHashMap();
for (final String region : regionMap.keySet()) {
parallelResponses.put(region, ConcurrentUtils.makeListenable(executor
.submit(new Callable<Void>() {
parallelResponses.put(region, ConcurrentUtils.makeListenable(
executor.submit(new Callable<Void>() {
@Override
public Void call() throws Exception {
Iterables.addAll(nodes, Iterables.transform(Iterables.concat(client
.getInstanceServices().describeInstancesInRegion(region)),
Iterables.addAll(nodes, Iterables.transform(Iterables
.concat(client.getInstanceServices()
.describeInstancesInRegion(region)),
runningInstanceToNodeMetadata));
return null;
}
}), executor));
}
Map<String, Exception> exceptions = awaitCompletion(parallelResponses, executor, null,
logger, "nodes");
Map<String, Exception> exceptions = awaitCompletion(parallelResponses,
executor, null, logger, "nodes");
if (exceptions.size() > 0)
throw new RuntimeException(String.format("error parsing nodes in regions: %s",
exceptions));
throw new RuntimeException(String.format(
"error parsing nodes in regions: %s", exceptions));
return Iterables.filter(nodes, filter);
}
}
@Singleton
public static class EC2GetNodeMetadataStrategy implements GetNodeMetadataStrategy {
public static class EC2GetNodeMetadataStrategy implements
GetNodeMetadataStrategy {
private final EC2Client client;
private final RunningInstanceToNodeMetadata runningInstanceToNodeMetadata;
@ -239,8 +258,9 @@ public class EC2ComputeServiceContextModule extends EC2ContextModule {
String[] parts = parseHandle(id);
String region = parts[0];
String instanceId = parts[1];
RunningInstance runningInstance = Iterables.getOnlyElement(getAllRunningInstancesInRegion(
client.getInstanceServices(), region, instanceId));
RunningInstance runningInstance = Iterables
.getOnlyElement(getAllRunningInstancesInRegion(client
.getInstanceServices(), region, instanceId));
return runningInstanceToNodeMetadata.apply(runningInstance);
}
@ -249,34 +269,30 @@ public class EC2ComputeServiceContextModule extends EC2ContextModule {
@Singleton
public static class EC2RebootNodeStrategy implements RebootNodeStrategy {
private final InstanceClient client;
private final GetNodeMetadataStrategy getNode;
@Inject
protected EC2RebootNodeStrategy(EC2Client client) {
protected EC2RebootNodeStrategy(EC2Client client,
GetNodeMetadataStrategy getNode) {
this.client = client.getInstanceServices();
this.getNode = getNode;
}
@Override
public boolean execute(String id) {
public NodeMetadata execute(String id) {
String[] parts = parseHandle(id);
String region = parts[0];
String instanceId = parts[1];
client.rebootInstancesInRegion(region, instanceId);
return true;
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
@Singleton
protected final Map<RegionAndName, KeyPair> credentialsMap(CreateUniqueKeyPair in) {
protected final Map<RegionAndName, KeyPair> credentialsMap(
CreateUniqueKeyPair in) {
// doesn't seem to clear when someone issues remove(key)
// return new MapMaker().makeComputingMap(in);
return Maps.newLinkedHashMap();
@ -284,7 +300,8 @@ public class EC2ComputeServiceContextModule extends EC2ContextModule {
@Provides
@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)
// return new MapMaker().makeComputingMap(in);
return Maps.newLinkedHashMap();
@ -304,28 +321,33 @@ public class EC2ComputeServiceContextModule extends EC2ContextModule {
@Provides
@Singleton
Set<? extends Size> provideSizes() {
return ImmutableSet.of(EC2Size.C1_MEDIUM, EC2Size.C1_XLARGE, EC2Size.M1_LARGE,
EC2Size.M1_SMALL, EC2Size.M1_XLARGE, EC2Size.M2_XLARGE, EC2Size.M2_2XLARGE,
EC2Size.M2_4XLARGE);
return ImmutableSet.of(EC2Size.C1_MEDIUM, EC2Size.C1_XLARGE,
EC2Size.M1_LARGE, EC2Size.M1_SMALL, EC2Size.M1_XLARGE,
EC2Size.M2_XLARGE, EC2Size.M2_2XLARGE, EC2Size.M2_4XLARGE);
}
@Provides
@Singleton
Set<? extends Location> provideLocations(Map<String, String> availabilityZoneToRegionMap) {
Location ec2 = new LocationImpl(LocationScope.PROVIDER, providerName, providerName, null);
Set<? extends Location> provideLocations(
Map<String, String> availabilityZoneToRegionMap) {
Location ec2 = new LocationImpl(LocationScope.PROVIDER, providerName,
providerName, null);
Set<Location> locations = Sets.newLinkedHashSet();
for (String zone : availabilityZoneToRegionMap.keySet()) {
Location region = new LocationImpl(LocationScope.REGION, availabilityZoneToRegionMap
.get(zone), availabilityZoneToRegionMap.get(zone), ec2);
Location region = new LocationImpl(LocationScope.REGION,
availabilityZoneToRegionMap.get(zone),
availabilityZoneToRegionMap.get(zone), ec2);
locations.add(region);
locations.add(new LocationImpl(LocationScope.ZONE, zone, zone, region));
locations
.add(new LocationImpl(LocationScope.ZONE, zone, zone, region));
}
return locations;
}
@Provides
@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>() {
@Override
@ -352,7 +374,8 @@ public class EC2ComputeServiceContextModule extends EC2ContextModule {
}
@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());
}
@ -365,10 +388,11 @@ public class EC2ComputeServiceContextModule extends EC2ContextModule {
@Provides
@Singleton
protected Map<RegionAndName, ? extends Image> provideImages(final EC2Client sync,
@EC2 Map<String, URI> regionMap, final LogHolder holder,
Function<ComputeMetadata, String> indexer,
@Named(PROPERTY_EC2_AMI_OWNERS) final String[] amiOwners, final ImageParser parser,
protected Map<RegionAndName, ? extends Image> provideImages(
final EC2Client sync, @EC2 Map<String, URI> regionMap,
final LogHolder holder, Function<ComputeMetadata, String> indexer,
@Named(PROPERTY_EC2_AMI_OWNERS) final String[] amiOwners,
final ImageParser parser,
final ConcurrentMap<RegionAndName, Image> images,
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService executor)
throws InterruptedException, ExecutionException, TimeoutException {
@ -380,30 +404,31 @@ public class EC2ComputeServiceContextModule extends EC2ContextModule {
Map<String, ListenableFuture<?>> parallelResponses = Maps.newHashMap();
for (final String region : regionMap.keySet()) {
parallelResponses.put(region, ConcurrentUtils.makeListenable(executor
.submit(new Callable<Void>() {
parallelResponses.put(region, ConcurrentUtils.makeListenable(
executor.submit(new Callable<Void>() {
@Override
public Void call() throws Exception {
for (final org.jclouds.aws.ec2.domain.Image from : sync.getAMIServices()
.describeImagesInRegion(region, ownedBy(amiOwners))) {
for (final org.jclouds.aws.ec2.domain.Image from : sync
.getAMIServices().describeImagesInRegion(region,
ownedBy(amiOwners))) {
Image image = parser.apply(from);
if (image != null)
images
.put(new RegionAndName(region, image.getProviderId()),
image);
images.put(new RegionAndName(region, image
.getProviderId()), image);
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));
}
Map<String, Exception> exceptions = awaitCompletion(parallelResponses, executor, null,
holder.logger, "images");
Map<String, Exception> exceptions = awaitCompletion(parallelResponses,
executor, null, holder.logger, "images");
if (exceptions.size() > 0)
throw new RuntimeException(String.format("error parsing images in regions: %s",
exceptions));
throw new RuntimeException(String.format(
"error parsing images in regions: %s", exceptions));
holder.logger.debug("<< images(%d)", images.size());
}

View File

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

View File

@ -20,8 +20,6 @@
package org.jclouds.aws.ec2.compute.strategy;
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 org.jclouds.aws.ec2.compute.util.EC2ComputeUtils.getRegionFromLocationOrNull;
import static org.jclouds.aws.ec2.compute.util.EC2ComputeUtils.getZoneFromLocationOrNull;
@ -58,7 +56,8 @@ import com.google.common.util.concurrent.ListenableFuture;
* @author Adrian Cole
*/
@Singleton
public class EC2RunNodesAndAddToSetStrategy implements RunNodesAndAddToSetStrategy {
public class EC2RunNodesAndAddToSetStrategy implements
RunNodesAndAddToSetStrategy {
@Resource
@Named(ComputeServiceConstants.COMPUTE_LOGGER)
@ -69,58 +68,50 @@ public class EC2RunNodesAndAddToSetStrategy implements RunNodesAndAddToSetStrate
@VisibleForTesting
final CreateKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions createKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions;
@VisibleForTesting
final Predicate<RunningInstance> instanceStateRunning;
@VisibleForTesting
final RunningInstanceToNodeMetadata runningInstanceToNodeMetadata;
@VisibleForTesting
final ComputeUtils utils;
final Predicate<RunningInstance> instancePresent;
@Inject
EC2RunNodesAndAddToSetStrategy(
EC2Client client,
CreateKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions createKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions,
@Named("RUNNING") Predicate<RunningInstance> instanceStateRunning,
RunningInstanceToNodeMetadata runningInstanceToNodeMetadata, ComputeUtils utils) {
@Named("PRESENT") Predicate<RunningInstance> instancePresent,
RunningInstanceToNodeMetadata runningInstanceToNodeMetadata,
ComputeUtils utils) {
this.client = client;
this.instancePresent = instancePresent;
this.createKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions = createKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions;
this.instanceStateRunning = instanceStateRunning;
this.runningInstanceToNodeMetadata = runningInstanceToNodeMetadata;
this.utils = utils;
}
@Override
public Map<?, ListenableFuture<Void>> execute(String tag, int count, Template template,
Set<NodeMetadata> goodNodes, Map<NodeMetadata, Exception> badNodes) {
public Map<?, ListenableFuture<Void>> execute(String tag, int count,
Template template, Set<NodeMetadata> goodNodes,
Map<NodeMetadata, Exception> badNodes) {
Reservation reservation = createKeyPairAndSecurityGroupsAsNeededThenRunInstances(tag, count,
template);
Reservation reservation = createKeyPairAndSecurityGroupsAsNeededThenRunInstances(
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);
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
Reservation createKeyPairAndSecurityGroupsAsNeededThenRunInstances(String tag, int count,
Template template) {
Reservation createKeyPairAndSecurityGroupsAsNeededThenRunInstances(
String tag, int count, Template template) {
String region = getRegionFromLocationOrNull(template.getLocation());
String zone = getZoneFromLocationOrNull(template.getLocation());
@ -128,17 +119,13 @@ public class EC2RunNodesAndAddToSetStrategy implements RunNodesAndAddToSetStrate
.execute(region, tag, template);
if (logger.isDebugEnabled())
logger.debug(">> running %d instance region(%s) zone(%s) ami(%s) params(%s)", count,
region, zone, template.getImage().getProviderId(), instanceOptions
.buildFormParameters());
logger.debug(
">> running %d instance region(%s) zone(%s) ami(%s) params(%s)",
count, region, zone, template.getImage().getProviderId(),
instanceOptions.buildFormParameters());
return client.getInstanceServices().runInstancesInRegion(region, zone,
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
@Singleton
RestContext<EC2Client, EC2AsyncClient> provideContext(Closer closer, EC2AsyncClient defaultApi,
EC2Client synchApi, @EC2 URI endPoint,
RestContext<EC2Client, EC2AsyncClient> provideContext(Closer closer,
EC2AsyncClient defaultApi, EC2Client synchApi, @EC2 URI endPoint,
@Named(AWSConstants.PROPERTY_AWS_ACCESSKEYID) String account) {
return new RestContextImpl<EC2Client, EC2AsyncClient>(closer, defaultApi, synchApi, endPoint,
account);
return new RestContextImpl<EC2Client, EC2AsyncClient>(closer, defaultApi,
synchApi, endPoint, account);
}
}

View File

@ -21,7 +21,6 @@ package org.jclouds.aws.ec2.config;
import java.net.URI;
import java.util.Date;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import javax.inject.Named;
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.ELB;
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.services.AMIAsyncClient;
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.Redirection;
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.RequestSigner;
import org.jclouds.rest.config.RestClientModule;
import com.google.common.base.Predicate;
import com.google.common.collect.ImmutableBiMap;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Maps;
@ -86,7 +78,8 @@ import com.google.inject.Provides;
*/
@RequiresHttp
@ConfiguresRestClient
public class EC2RestClientModule extends RestClientModule<EC2Client, EC2AsyncClient> {
public class EC2RestClientModule extends
RestClientModule<EC2Client, EC2AsyncClient> {
public static final Map<Class<?>, Class<?>> DELEGATE_MAP = ImmutableMap
.<Class<?>, Class<?>> builder()//
.put(AMIClient.class, AMIAsyncClient.class)//
@ -95,41 +88,22 @@ public class EC2RestClientModule extends RestClientModule<EC2Client, EC2AsyncCli
.put(KeyPairClient.class, KeyPairAsyncClient.class)//
.put(SecurityGroupClient.class, SecurityGroupAsyncClient.class)//
.put(MonitoringClient.class, MonitoringAsyncClient.class)//
.put(AvailabilityZoneAndRegionClient.class, AvailabilityZoneAndRegionAsyncClient.class)//
.put(AvailabilityZoneAndRegionClient.class,
AvailabilityZoneAndRegionAsyncClient.class)//
.put(ElasticBlockStoreClient.class, ElasticBlockStoreAsyncClient.class)//
.put(ElasticLoadBalancerClient.class, ElasticLoadBalancerAsyncClient.class)//
.put(ElasticLoadBalancerClient.class,
ElasticLoadBalancerAsyncClient.class)//
.build();
public EC2RestClientModule() {
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
@Singleton
@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);
}
@ -137,21 +111,29 @@ public class EC2RestClientModule extends RestClientModule<EC2Client, EC2AsyncCli
@Singleton
@ELB
Map<String, URI> provideELBRegions() {
return ImmutableMap.<String, URI> of(Region.US_EAST_1, URI
.create("https://elasticloadbalancing.us-east-1.amazonaws.com"), Region.US_WEST_1,
URI.create("https://elasticloadbalancing.us-west-1.amazonaws.com"),
return ImmutableMap
.<String, URI> of(
Region.US_EAST_1,
URI
.create("https://elasticloadbalancing.us-east-1.amazonaws.com"),
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
URI
.create("https://elasticloadbalancing.eu-west-1.amazonaws.com"),
Region.AP_SOUTHEAST_1,
URI
.create("https://elasticloadbalancing.ap-southeast-1.amazonaws.com"));
}
@Provides
@Singleton
@EC2
String provideCurrentRegion(@EC2 Map<String, URI> regionMap, @EC2 URI currentUri) {
ImmutableBiMap<URI, String> map = ImmutableBiMap.<String, URI> builder().putAll(regionMap)
.build().inverse();
String provideCurrentRegion(@EC2 Map<String, URI> regionMap,
@EC2 URI currentUri) {
ImmutableBiMap<URI, String> map = ImmutableBiMap.<String, URI> builder()
.putAll(regionMap).build().inverse();
String region = map.get(currentUri);
assert region != null : currentUri + " not in " + map;
return region;
@ -184,7 +166,8 @@ public class EC2RestClientModule extends RestClientModule<EC2Client, EC2AsyncCli
@EC2 Map<String, URI> regions) {
Map<String, String> map = Maps.newHashMap();
for (String region : regions.keySet()) {
for (AvailabilityZoneInfo zoneInfo : client.getAvailabilityZoneAndRegionServices()
for (AvailabilityZoneInfo zoneInfo : client
.getAvailabilityZoneAndRegionServices()
.describeAvailabilityZonesInRegion(region)) {
map.put(zoneInfo.getZone(), region);
}
@ -209,7 +192,8 @@ public class EC2RestClientModule extends RestClientModule<EC2Client, EC2AsyncCli
@Provides
@Singleton
@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);
}

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.inject.Singleton;
import org.jclouds.aws.AWSResponseException;
import org.jclouds.aws.ec2.EC2Client;
import org.jclouds.aws.ec2.domain.InstanceState;
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;
@ -54,18 +54,18 @@ public class InstanceStateRunning implements Predicate<RunningInstance> {
logger.trace("looking for state on instance %s", instance);
try {
instance = refresh(instance);
logger.trace("%s: looking for instance state %s: currently: %s", instance.getId(),
InstanceState.RUNNING, instance.getInstanceState());
logger.trace("%s: looking for instance state %s: currently: %s",
instance.getId(), InstanceState.RUNNING, instance
.getInstanceState());
return instance.getInstanceState() == InstanceState.RUNNING;
} catch (AWSResponseException e) {
if (e.getError().getCode().equals("InvalidInstanceID.NotFound"))
} catch (ResourceNotFoundException e) {
return false;
throw e;
}
}
private RunningInstance refresh(RunningInstance instance) {
return Iterables.getOnlyElement(Iterables.getOnlyElement(client.getInstanceServices()
.describeInstancesInRegion(instance.getRegion(), instance.getId())));
return Iterables.getOnlyElement(Iterables.getOnlyElement(client
.getInstanceServices().describeInstancesInRegion(
instance.getRegion(), instance.getId())));
}
}

View File

@ -63,21 +63,23 @@ public class ParseAWSErrorFromXmlContent implements HttpErrorHandler {
Exception exception = new HttpResponseException(command, response);
try {
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()) {
case 400:
if (error.getCode().equals("InvalidAMIID.NotFound")
|| error.getCode().equals("InvalidAMIID.Malformed"))
exception = new ResourceNotFoundException(error.getMessage(), exception);
if (error.getCode().endsWith(".NotFound"))
exception = new ResourceNotFoundException(error.getMessage(),
exception);
break;
case 401:
exception = new AuthorizationException(command.getRequest(), error != null ? error
.getMessage() : response.getStatusLine());
exception = new AuthorizationException(command.getRequest(),
error != null ? error.getMessage() : response.getStatusLine());
break;
case 404:
if (!command.getRequest().getMethod().equals("DELETE")) {
String message = error != null ? error.getMessage() : String.format("%s -> %s",
command.getRequest().getRequestLine(), response.getStatusLine());
String message = error != null ? error.getMessage() : String
.format("%s -> %s", command.getRequest().getRequestLine(),
response.getStatusLine());
String container = command.getRequest().getEndpoint().getHost();
String key = command.getRequest().getEndpoint().getPath();
if (key == null || key.equals("/"))
@ -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) {
try {
String content = Utils.toStringAndClose(response.getContent());
if (content != null && content.indexOf('<') >= 0)
return utils.parseAWSErrorFromContent(command, response, content);
return utils
.parseAWSErrorFromContent(command, response, content);
} catch (IOException e) {
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
* <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/>
* Generally disabled, as it incurs higher fees.
*
@ -89,41 +90,50 @@ public class CloudApplicationArchitecturesEC2ClientLiveTest {
private RetryablePredicate<RunningInstance> runningTester;
@BeforeGroups(groups = { "live" })
public void setupClient() throws InterruptedException, ExecutionException, TimeoutException {
String user = checkNotNull(System.getProperty("jclouds.test.user"), "jclouds.test.user");
String password = checkNotNull(System.getProperty("jclouds.test.key"), "jclouds.test.key");
Injector injector = new EC2ContextBuilder("ec2", new EC2PropertiesBuilder(user, password)
.build()).withModules(new Log4JLoggingModule(), new JschSshClientModule())
public void setupClient() throws InterruptedException, ExecutionException,
TimeoutException {
String user = checkNotNull(System.getProperty("jclouds.test.user"),
"jclouds.test.user");
String password = checkNotNull(System.getProperty("jclouds.test.key"),
"jclouds.test.key");
Injector injector = new EC2ContextBuilder("ec2",
new EC2PropertiesBuilder(user, password).build()).withModules(
new Log4JLoggingModule(), new JschSshClientModule())
.buildInjector();
client = injector.getInstance(EC2Client.class);
sshFactory = injector.getInstance(SshClient.Factory.class);
runningTester = new RetryablePredicate<RunningInstance>(new InstanceStateRunning(client),
180, 5, TimeUnit.SECONDS);
hasIpTester = new RetryablePredicate<RunningInstance>(new InstanceHasIpAddress(client), 180, 5, TimeUnit.SECONDS);
runningTester = new RetryablePredicate<RunningInstance>(
new InstanceStateRunning(client), 180, 5, TimeUnit.SECONDS);
hasIpTester = new RetryablePredicate<RunningInstance>(
new InstanceHasIpAddress(client), 180, 5, TimeUnit.SECONDS);
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)
void testCreateSecurityGroupIngressCidr() throws InterruptedException, ExecutionException,
TimeoutException {
void testCreateSecurityGroupIngressCidr() throws InterruptedException,
ExecutionException, TimeoutException {
securityGroupName = instancePrefix + "ingress";
try {
client.getSecurityGroupServices().deleteSecurityGroupInRegion(null, securityGroupName);
client.getSecurityGroupServices().deleteSecurityGroupInRegion(null,
securityGroupName);
} catch (Exception e) {
}
client.getSecurityGroupServices().createSecurityGroupInRegion(null, securityGroupName,
securityGroupName);
client.getSecurityGroupServices().createSecurityGroupInRegion(null,
securityGroupName, securityGroupName);
for (int port : new int[] { 80, 443, 22 }) {
client.getSecurityGroupServices().authorizeSecurityGroupIngressInRegion(null,
securityGroupName, IpProtocol.TCP, port, port, "0.0.0.0/0");
client.getSecurityGroupServices()
.authorizeSecurityGroupIngressInRegion(null, securityGroupName,
IpProtocol.TCP, port, port, "0.0.0.0/0");
}
}
@Test(enabled = false)
void testCreateKeyPair() throws InterruptedException, ExecutionException, TimeoutException {
void testCreateKeyPair() throws InterruptedException, ExecutionException,
TimeoutException {
String keyName = instancePrefix + "1";
try {
client.getKeyPairServices().deleteKeyPairInRegion(null, keyName);
@ -132,7 +142,8 @@ public class CloudApplicationArchitecturesEC2ClientLiveTest {
}
client.getKeyPairServices().deleteKeyPairInRegion(null, keyName);
keyPair = client.getKeyPairServices().createKeyPairInRegion(null, keyName);
keyPair = client.getKeyPairServices()
.createKeyPairInRegion(null, keyName);
assertNotNull(keyPair);
assertNotNull(keyPair.getKeyMaterial());
assertNotNull(keyPair.getKeyFingerprint());
@ -151,21 +162,29 @@ public class CloudApplicationArchitecturesEC2ClientLiveTest {
while (instance == null) {
try {
System.out.printf("%d: running instance%n", System.currentTimeMillis());
Reservation reservation = client.getInstanceServices().runInstancesInRegion(null, null, // allow
System.out.printf("%d: running instance%n", System
.currentTimeMillis());
Reservation reservation = client.getInstanceServices()
.runInstancesInRegion(null, null, // allow
// ec2
// to
// chose
// an
// availability
// zone
"ami-ccf615a5", // alestic ami allows auto-invoke of user data scripts
"ami-ccf615a5", // alestic ami allows auto-invoke of
// user data scripts
1, // minimum instances
1, // maximum instances
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
.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);
@ -183,45 +202,51 @@ public class CloudApplicationArchitecturesEC2ClientLiveTest {
verifyInstanceProperties(script);
tryToChangeStuff();
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) {
assertEquals(script, client.getInstanceServices().getUserDataForInstanceInRegion(null,
instanceId));
assertEquals(script, client.getInstanceServices()
.getUserDataForInstanceInRegion(null, instanceId));
assertEquals(null, client.getInstanceServices().getRootDeviceNameForInstanceInRegion(null,
instanceId));
assertEquals(null, client.getInstanceServices()
.getRootDeviceNameForInstanceInRegion(null, instanceId));
assert client.getInstanceServices().getRamdiskForInstanceInRegion(null, instanceId)
.startsWith("ari-");
assert client.getInstanceServices().getRamdiskForInstanceInRegion(null,
instanceId).startsWith("ari-");
assertEquals(false, client.getInstanceServices().isApiTerminationDisabledForInstanceInRegion(
null, instanceId));
assertEquals(false, client.getInstanceServices()
.isApiTerminationDisabledForInstanceInRegion(null, instanceId));
assert client.getInstanceServices().getKernelForInstanceInRegion(null, instanceId)
.startsWith("aki-");
assert client.getInstanceServices().getKernelForInstanceInRegion(null,
instanceId).startsWith("aki-");
assertEquals(InstanceType.M1_SMALL, client.getInstanceServices()
.getInstanceTypeForInstanceInRegion(null, instanceId));
assertEquals(InstanceInitiatedShutdownBehavior.TERMINATE, client.getInstanceServices()
.getInstanceInitiatedShutdownBehaviorForInstanceInRegion(null, instanceId));
assertEquals(InstanceInitiatedShutdownBehavior.TERMINATE, client
.getInstanceServices()
.getInstanceInitiatedShutdownBehaviorForInstanceInRegion(null,
instanceId));
assertEquals(ImmutableMap.<String, EbsBlockDevice> of(), client.getInstanceServices()
.getBlockDeviceMappingForInstanceInRegion(null, instanceId));
assertEquals(ImmutableMap.<String, EbsBlockDevice> of(), client
.getInstanceServices().getBlockDeviceMappingForInstanceInRegion(
null, instanceId));
}
private void setApiTerminationDisabledForInstanceInRegion() {
client.getInstanceServices().setApiTerminationDisabledForInstanceInRegion(null, instanceId,
client.getInstanceServices()
.setApiTerminationDisabledForInstanceInRegion(null, instanceId,
true);
assertEquals(true, client.getInstanceServices().isApiTerminationDisabledForInstanceInRegion(
null, instanceId));
client.getInstanceServices().setApiTerminationDisabledForInstanceInRegion(null, instanceId,
assertEquals(true, client.getInstanceServices()
.isApiTerminationDisabledForInstanceInRegion(null, instanceId));
client.getInstanceServices()
.setApiTerminationDisabledForInstanceInRegion(null, instanceId,
false);
assertEquals(false, client.getInstanceServices().isApiTerminationDisabledForInstanceInRegion(
null, instanceId));
assertEquals(false, client.getInstanceServices()
.isApiTerminationDisabledForInstanceInRegion(null, instanceId));
}
private void tryToChangeStuff() {
@ -236,8 +261,8 @@ public class CloudApplicationArchitecturesEC2ClientLiveTest {
private void setUserDataForInstanceInRegion() {
try {
client.getInstanceServices().setUserDataForInstanceInRegion(null, instanceId,
"test".getBytes());
client.getInstanceServices().setUserDataForInstanceInRegion(null,
instanceId, "test".getBytes());
assert false : "shouldn't be allowed, as instance needs to be stopped";
} catch (AWSResponseException e) {
assertEquals("IncorrectInstanceState", e.getError().getCode());
@ -246,9 +271,10 @@ public class CloudApplicationArchitecturesEC2ClientLiveTest {
private void setRamdiskForInstanceInRegion() {
try {
String ramdisk = client.getInstanceServices().getRamdiskForInstanceInRegion(null,
instanceId);
client.getInstanceServices().setRamdiskForInstanceInRegion(null, instanceId, ramdisk);
String ramdisk = client.getInstanceServices()
.getRamdiskForInstanceInRegion(null, instanceId);
client.getInstanceServices().setRamdiskForInstanceInRegion(null,
instanceId, ramdisk);
assert false : "shouldn't be allowed, as instance needs to be stopped";
} catch (AWSResponseException e) {
assertEquals("IncorrectInstanceState", e.getError().getCode());
@ -257,9 +283,10 @@ public class CloudApplicationArchitecturesEC2ClientLiveTest {
private void setKernelForInstanceInRegion() {
try {
String oldKernel = client.getInstanceServices().getKernelForInstanceInRegion(null,
instanceId);
client.getInstanceServices().setKernelForInstanceInRegion(null, instanceId, oldKernel);
String oldKernel = client.getInstanceServices()
.getKernelForInstanceInRegion(null, instanceId);
client.getInstanceServices().setKernelForInstanceInRegion(null,
instanceId, oldKernel);
assert false : "shouldn't be allowed, as instance needs to be stopped";
} catch (AWSResponseException e) {
assertEquals("IncorrectInstanceState", e.getError().getCode());
@ -268,8 +295,8 @@ public class CloudApplicationArchitecturesEC2ClientLiveTest {
private void setInstanceTypeForInstanceInRegion() {
try {
client.getInstanceServices().setInstanceTypeForInstanceInRegion(null, instanceId,
InstanceType.C1_MEDIUM);
client.getInstanceServices().setInstanceTypeForInstanceInRegion(null,
instanceId, InstanceType.C1_MEDIUM);
assert false : "shouldn't be allowed, as instance needs to be stopped";
} catch (AWSResponseException e) {
assertEquals("IncorrectInstanceState", e.getError().getCode());
@ -279,8 +306,8 @@ public class CloudApplicationArchitecturesEC2ClientLiveTest {
private void setBlockDeviceMappingForInstanceInRegion() {
BlockDeviceMapping blockDeviceMapping = new BlockDeviceMapping();
try {
client.getInstanceServices().setBlockDeviceMappingForInstanceInRegion(null, instanceId,
blockDeviceMapping);
client.getInstanceServices().setBlockDeviceMappingForInstanceInRegion(
null, instanceId, blockDeviceMapping);
assert false : "shouldn't be allowed, as instance needs to be ebs based-ami";
} catch (AWSResponseException e) {
assertEquals("InvalidParameterCombination", e.getError().getCode());
@ -289,7 +316,8 @@ public class CloudApplicationArchitecturesEC2ClientLiveTest {
private void setInstanceInitiatedShutdownBehaviorForInstanceInRegion() {
try {
client.getInstanceServices().setInstanceInitiatedShutdownBehaviorForInstanceInRegion(null,
client.getInstanceServices()
.setInstanceInitiatedShutdownBehaviorForInstanceInRegion(null,
instanceId, InstanceInitiatedShutdownBehavior.STOP);
assert false : "shouldn't be allowed, as instance needs to be ebs based-ami";
} catch (AWSResponseException e) {
@ -298,19 +326,22 @@ public class CloudApplicationArchitecturesEC2ClientLiveTest {
}
@Test(enabled = false, dependsOnMethods = "testCreateRunningInstance")
void testReboot() throws InterruptedException, ExecutionException, TimeoutException, IOException {
void testReboot() throws InterruptedException, ExecutionException,
TimeoutException, IOException {
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);
Thread.sleep(1000);
instance = getInstance(instanceId);
blockUntilWeCanSshIntoInstance(instance);
SshClient ssh = sshFactory.create(new IPSocket(instance.getIpAddress(), 22), "root", keyPair
.getKeyMaterial().getBytes());
SshClient ssh = sshFactory.create(new IPSocket(instance.getIpAddress(),
22), "root", keyPair.getKeyMaterial().getBytes());
try {
ssh.connect();
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 {
if (ssh != null)
ssh.disconnect();
@ -318,86 +349,95 @@ public class CloudApplicationArchitecturesEC2ClientLiveTest {
}
@Test(enabled = false, dependsOnMethods = "testReboot")
void testElasticIpAddress() throws InterruptedException, ExecutionException, TimeoutException,
IOException {
address = client.getElasticIPAddressServices().allocateAddressInRegion(null);
void testElasticIpAddress() throws InterruptedException, ExecutionException,
TimeoutException, IOException {
address = client.getElasticIPAddressServices().allocateAddressInRegion(
null);
assertNotNull(address);
PublicIpInstanceIdPair compare = Iterables.getLast(client.getElasticIPAddressServices()
.describeAddressesInRegion(null, address));
PublicIpInstanceIdPair compare = Iterables.getLast(client
.getElasticIPAddressServices().describeAddressesInRegion(null,
address));
assertEquals(compare.getPublicIp(), address);
assert compare.getInstanceId() == null;
client.getElasticIPAddressServices().associateAddressInRegion(null, address, instanceId);
client.getElasticIPAddressServices().associateAddressInRegion(null,
address, instanceId);
compare = Iterables.getLast(client.getElasticIPAddressServices().describeAddressesInRegion(
null, address));
compare = Iterables.getLast(client.getElasticIPAddressServices()
.describeAddressesInRegion(null, address));
assertEquals(compare.getPublicIp(), address);
assertEquals(compare.getInstanceId(), instanceId);
Reservation reservation = Iterables.getOnlyElement(client.getInstanceServices()
.describeInstancesInRegion(null, instanceId));
Reservation reservation = Iterables.getOnlyElement(client
.getInstanceServices().describeInstancesInRegion(null, instanceId));
assertNotNull(Iterables.getOnlyElement(reservation).getIpAddress());
assertFalse(Iterables.getOnlyElement(reservation).getIpAddress().equals(address));
assertFalse(Iterables.getOnlyElement(reservation).getIpAddress().equals(
address));
doCheckKey(address);
client.getElasticIPAddressServices().disassociateAddressInRegion(null, address);
client.getElasticIPAddressServices().disassociateAddressInRegion(null,
address);
compare = Iterables.getLast(client.getElasticIPAddressServices().describeAddressesInRegion(
null, address));
compare = Iterables.getLast(client.getElasticIPAddressServices()
.describeAddressesInRegion(null, address));
assertEquals(compare.getPublicIp(), address);
assert compare.getInstanceId() == null;
reservation = Iterables.getOnlyElement(client.getInstanceServices()
.describeInstancesInRegion(null, instanceId));
// assert reservation.getRunningInstances().last().getIpAddress() == null; TODO
// assert reservation.getRunningInstances().last().getIpAddress() == null;
// TODO
}
private RunningInstance blockUntilWeCanSshIntoInstance(RunningInstance instance)
throws UnknownHostException {
System.out.printf("%d: %s awaiting instance to run %n", System.currentTimeMillis(), instance
.getId());
private RunningInstance blockUntilWeCanSshIntoInstance(
RunningInstance instance) throws UnknownHostException {
System.out.printf("%d: %s awaiting instance to run %n", System
.currentTimeMillis(), instance.getId());
assert runningTester.apply(instance);
instance = getInstance(instance.getId());
System.out.printf("%d: %s awaiting instance to have ip assigned %n", System
.currentTimeMillis(), instance.getId());
System.out.printf("%d: %s awaiting instance to have ip assigned %n",
System.currentTimeMillis(), instance.getId());
assert hasIpTester.apply(instance);
System.out.printf("%d: %s awaiting ssh service to start%n", System.currentTimeMillis(),
instance.getIpAddress());
System.out.printf("%d: %s awaiting ssh service to start%n", System
.currentTimeMillis(), instance.getIpAddress());
assert socketTester.apply(new IPSocket(instance.getIpAddress(), 22));
System.out.printf("%d: %s ssh service started%n", System.currentTimeMillis(), instance
.getDnsName());
System.out.printf("%d: %s ssh service started%n", System
.currentTimeMillis(), instance.getDnsName());
sshPing(instance);
System.out.printf("%d: %s ssh connection made%n", System.currentTimeMillis(), instance
.getId());
System.out.printf("%d: %s ssh connection made%n", System
.currentTimeMillis(), instance.getId());
System.out.printf("%d: %s awaiting http service to start%n", System.currentTimeMillis(),
instance.getIpAddress());
System.out.printf("%d: %s awaiting http service to start%n", System
.currentTimeMillis(), instance.getIpAddress());
assert socketTester.apply(new IPSocket(instance.getIpAddress(), 80));
System.out.printf("%d: %s http service started%n", System.currentTimeMillis(), instance
.getDnsName());
System.out.printf("%d: %s http service started%n", System
.currentTimeMillis(), instance.getDnsName());
return instance;
}
private RunningInstance getInstance(String instanceId) {
// search my account for the instance I just created
Set<Reservation> reservations = client.getInstanceServices().describeInstancesInRegion(null,
instanceId); // last parameter (ids) narrows the search
Set<Reservation> reservations = client.getInstanceServices()
.describeInstancesInRegion(null, instanceId); // last parameter
// (ids) narrows the
// search
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
*/
@ -413,13 +453,14 @@ public class CloudApplicationArchitecturesEC2ClientLiveTest {
}
}
private void doCheckKey(RunningInstance newDetails) throws UnknownHostException {
private void doCheckKey(RunningInstance newDetails)
throws UnknownHostException {
doCheckKey(newDetails.getIpAddress());
}
private void doCheckKey(String address) {
SshClient ssh = sshFactory.create(new IPSocket(address, 22), "root", keyPair.getKeyMaterial()
.getBytes());
SshClient ssh = sshFactory.create(new IPSocket(address, 22), "root",
keyPair.getKeyMaterial().getBytes());
try {
ssh.connect();
ExecResponse hello = ssh.exec("echo hello");
@ -431,15 +472,20 @@ public class CloudApplicationArchitecturesEC2ClientLiveTest {
}
@AfterTest
void cleanup() throws InterruptedException, ExecutionException, TimeoutException {
void cleanup() throws InterruptedException, ExecutionException,
TimeoutException {
if (address != null)
client.getElasticIPAddressServices().releaseAddressInRegion(null, address);
client.getElasticIPAddressServices().releaseAddressInRegion(null,
address);
if (instanceId != null)
client.getInstanceServices().terminateInstancesInRegion(null, instanceId);
client.getInstanceServices().terminateInstancesInRegion(null,
instanceId);
if (keyPair != null)
client.getKeyPairServices().deleteKeyPairInRegion(null, keyPair.getKeyName());
client.getKeyPairServices().deleteKeyPairInRegion(null,
keyPair.getKeyName());
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;
/**
* Adapted from the following sources: {@link http://gist.github.com/249915}, {@link http
* ://www.capsunlock.net/2009/12/create-ebs-boot-ami.html}
* Adapted from the following sources: {@link http://gist.github.com/249915},
* {@link http ://www.capsunlock.net/2009/12/create-ebs-boot-ami.html}
* <p/>
*
* 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
private static final int VOLUME_SIZE = 2;
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 EC2Client client;
@ -117,58 +119,70 @@ public class EBSBootEC2ClientLiveTest {
@BeforeGroups(groups = { "live" })
public void setupClient() {
String user = checkNotNull(System.getProperty("jclouds.test.user"), "jclouds.test.user");
String password = checkNotNull(System.getProperty("jclouds.test.key"), "jclouds.test.key");
Injector injector = new EC2ContextBuilder("ec2", new EC2PropertiesBuilder(user, password)
.build()).withModules(new Log4JLoggingModule(), new JschSshClientModule())
String user = checkNotNull(System.getProperty("jclouds.test.user"),
"jclouds.test.user");
String password = checkNotNull(System.getProperty("jclouds.test.key"),
"jclouds.test.key");
Injector injector = new EC2ContextBuilder("ec2",
new EC2PropertiesBuilder(user, password).build()).withModules(
new Log4JLoggingModule(), new JschSshClientModule())
.buildInjector();
client = injector.getInstance(EC2Client.class);
sshFactory = injector.getInstance(SshClient.Factory.class);
SocketOpen socketOpen = injector.getInstance(SocketOpen.class);
socketTester = new RetryablePredicate<IPSocket>(socketOpen, 120, 1, TimeUnit.SECONDS);
VolumeAvailable volumeAvailable = injector.getInstance(VolumeAvailable.class);
volumeTester = new RetryablePredicate<Volume>(volumeAvailable, 60, 1, TimeUnit.SECONDS);
SnapshotCompleted snapshotCompleted = injector.getInstance(SnapshotCompleted.class);
snapshotTester = new RetryablePredicate<Snapshot>(snapshotCompleted, 120, 3, TimeUnit.SECONDS);
VolumeAttached volumeAttached = injector.getInstance(VolumeAttached.class);
attachTester = new RetryablePredicate<Attachment>(volumeAttached, 60, 1, TimeUnit.SECONDS);
runningTester = new RetryablePredicate<RunningInstance>(new InstanceStateRunning(client),
180, 5, TimeUnit.SECONDS);
InstanceStateStopped instanceStateStopped = injector.getInstance(InstanceStateStopped.class);
stoppedTester = new RetryablePredicate<RunningInstance>(instanceStateStopped, 60, 1,
socketTester = new RetryablePredicate<IPSocket>(socketOpen, 120, 1,
TimeUnit.SECONDS);
VolumeAvailable volumeAvailable = injector
.getInstance(VolumeAvailable.class);
volumeTester = new RetryablePredicate<Volume>(volumeAvailable, 60, 1,
TimeUnit.SECONDS);
SnapshotCompleted snapshotCompleted = injector
.getInstance(SnapshotCompleted.class);
snapshotTester = new RetryablePredicate<Snapshot>(snapshotCompleted, 120,
3, TimeUnit.SECONDS);
VolumeAttached volumeAttached = injector
.getInstance(VolumeAttached.class);
attachTester = new RetryablePredicate<Attachment>(volumeAttached, 60, 1,
TimeUnit.SECONDS);
runningTester = new RetryablePredicate<RunningInstance>(
new InstanceStateRunning(client), 180, 5, TimeUnit.SECONDS);
InstanceStateStopped instanceStateStopped = injector
.getInstance(InstanceStateStopped.class);
stoppedTester = new RetryablePredicate<RunningInstance>(
instanceStateStopped, 60, 1, TimeUnit.SECONDS);
InstanceStateTerminated instanceStateTerminated = injector
.getInstance(InstanceStateTerminated.class);
terminatedTester = new RetryablePredicate<RunningInstance>(instanceStateTerminated, 60, 1,
TimeUnit.SECONDS);
terminatedTester = new RetryablePredicate<RunningInstance>(
instanceStateTerminated, 60, 1, TimeUnit.SECONDS);
injector.injectMembers(socketOpen); // add logger
}
@Test(enabled = false)
void testCreateSecurityGroupIngressCidr() throws InterruptedException, ExecutionException,
TimeoutException {
void testCreateSecurityGroupIngressCidr() throws InterruptedException,
ExecutionException, TimeoutException {
securityGroupName = INSTANCE_PREFIX + "ingress";
try {
client.getSecurityGroupServices().deleteSecurityGroupInRegion(null, securityGroupName);
client.getSecurityGroupServices().deleteSecurityGroupInRegion(null,
securityGroupName);
} catch (Exception e) {
}
client.getSecurityGroupServices().createSecurityGroupInRegion(null, securityGroupName,
securityGroupName);
client.getSecurityGroupServices().authorizeSecurityGroupIngressInRegion(null,
securityGroupName, IpProtocol.TCP, 80, 80, "0.0.0.0/0");
client.getSecurityGroupServices().authorizeSecurityGroupIngressInRegion(null,
securityGroupName, IpProtocol.TCP, 443, 443, "0.0.0.0/0");
client.getSecurityGroupServices().authorizeSecurityGroupIngressInRegion(null,
securityGroupName, IpProtocol.TCP, 22, 22, "0.0.0.0/0");
client.getSecurityGroupServices().createSecurityGroupInRegion(null,
securityGroupName, securityGroupName);
client.getSecurityGroupServices().authorizeSecurityGroupIngressInRegion(
null, securityGroupName, IpProtocol.TCP, 80, 80, "0.0.0.0/0");
client.getSecurityGroupServices().authorizeSecurityGroupIngressInRegion(
null, securityGroupName, IpProtocol.TCP, 443, 443, "0.0.0.0/0");
client.getSecurityGroupServices().authorizeSecurityGroupIngressInRegion(
null, securityGroupName, IpProtocol.TCP, 22, 22, "0.0.0.0/0");
}
@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.getKeyMaterial());
assertNotNull(keyPair.getKeyFingerprint());
@ -193,12 +208,15 @@ public class EBSBootEC2ClientLiveTest {
instance = createInstance(IMAGE_ID);
}
private RunningInstance createInstance(String imageId) throws UnknownHostException {
private RunningInstance createInstance(String imageId)
throws UnknownHostException {
RunningInstance instance = null;
while (instance == null) {
try {
System.out.printf("%d: running instance%n", System.currentTimeMillis());
Reservation reservation = client.getInstanceServices().runInstancesInRegion(null, null, // allow
System.out.printf("%d: running instance%n", System
.currentTimeMillis());
Reservation reservation = client.getInstanceServices()
.runInstancesInRegion(null, null, // allow
// ec2
// to
// chose
@ -208,8 +226,11 @@ public class EBSBootEC2ClientLiveTest {
imageId, 1, // minimum instances
1, // maximum instances
withKeyName(keyPair.getKeyName())// key I created above
.asType(InstanceType.M1_SMALL)// smallest instance size
.withSecurityGroup(securityGroupName));// group I created above
.asType(InstanceType.M1_SMALL)// smallest instance
// size
.withSecurityGroup(securityGroupName));// group I
// created
// above
instance = Iterables.getOnlyElement(reservation);
} catch (HttpResponseException htpe) {
if (htpe.getResponse().getStatusCode() == 400)
@ -225,25 +246,28 @@ public class EBSBootEC2ClientLiveTest {
@Test(enabled = false, dependsOnMethods = "testCreateRunningInstance")
void testCreateAndAttachVolume() {
volume = client.getElasticBlockStoreServices().createVolumeInAvailabilityZone(
instance.getAvailabilityZone(), VOLUME_SIZE);
System.out.printf("%d: %s awaiting volume to become available%n", System.currentTimeMillis(),
volume.getId());
volume = client.getElasticBlockStoreServices()
.createVolumeInAvailabilityZone(instance.getAvailabilityZone(),
VOLUME_SIZE);
System.out.printf("%d: %s awaiting volume to become available%n", System
.currentTimeMillis(), volume.getId());
assert volumeTester.apply(volume);
Attachment attachment = client.getElasticBlockStoreServices().attachVolumeInRegion(
instance.getRegion(), volume.getId(), instance.getId(), "/dev/sdh");
Attachment attachment = client.getElasticBlockStoreServices()
.attachVolumeInRegion(instance.getRegion(), volume.getId(),
instance.getId(), "/dev/sdh");
System.out.printf("%d: %s awaiting attachment to complete%n", System.currentTimeMillis(),
attachment.getId());
System.out.printf("%d: %s awaiting attachment to complete%n", System
.currentTimeMillis(), attachment.getId());
assert attachTester.apply(attachment);
System.out.printf("%d: %s attachment complete%n", System.currentTimeMillis(), attachment
.getId());
System.out.printf("%d: %s attachment complete%n", System
.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
void makeScript() {
@ -251,9 +275,11 @@ public class EBSBootEC2ClientLiveTest {
"mkebsboot",// name of the script
"/tmp",// working directory
"/tmp/logs",// location of stdout.log and stderr.log
ImmutableMap.of("imageDir", "/mnt/tmp", "ebsDevice", "/dev/sdh", "ebsMountPoint",
"/mnt/ebs"),// variables used inside of the script
"echo creating a filesystem and mounting the ebs volume",// what to execute
ImmutableMap.of("imageDir", "/mnt/tmp", "ebsDevice", "/dev/sdh",
"ebsMountPoint", "/mnt/ebs"),// variables used inside of the
// script
"echo creating a filesystem and mounting the ebs volume",// what to
// execute
"{md} {varl}IMAGE_DIR{varr} {varl}EBS_MOUNT_POINT{varr}",
"rm -rf {varl}IMAGE_DIR{varr}/*",
"yes| mkfs -t ext3 {varl}EBS_DEVICE{varr} 2>&-",
@ -264,16 +290,18 @@ public class EBSBootEC2ClientLiveTest {
"touch {varl}IMAGE_DIR{varr}/etc/init.d/ec2-init-user-data",
"echo copying the local working copy to the ebs mount",
"{cd} {varl}IMAGE_DIR{varr}",
"tar -cSf - * | tar xf - -C {varl}EBS_MOUNT_POINT{varr}", "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);
"tar -cSf - * | tar xf - -C {varl}EBS_MOUNT_POINT{varr}",
"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")
void testBundleInstance() {
SshClient ssh = sshFactory.create(new IPSocket(instance.getIpAddress(), 22), "ubuntu",
keyPair.getKeyMaterial().getBytes());
SshClient ssh = sshFactory.create(new IPSocket(instance.getIpAddress(),
22), "ubuntu", keyPair.getKeyMaterial().getBytes());
try {
ssh.connect();
} catch (SshException e) {// try twice in case there is a network timeout
@ -284,13 +312,13 @@ public class EBSBootEC2ClientLiveTest {
ssh.connect();
}
try {
System.out.printf("%d: %s writing ebs script%n", System.currentTimeMillis(), instance
.getId());
System.out.printf("%d: %s writing ebs script%n", System
.currentTimeMillis(), instance.getId());
String script = "/tmp/mkebsboot-init.sh";
ssh.put(script, new ByteArrayInputStream(mkEbsBoot.getBytes()));
System.out.printf("%d: %s launching ebs script%n", System.currentTimeMillis(), instance
.getId());
System.out.printf("%d: %s launching ebs script%n", System
.currentTimeMillis(), instance.getId());
ssh.exec("chmod 755 " + script);
ssh.exec(script + " init");
ExecResponse output = ssh.exec("sudo " + script + " start");
@ -299,8 +327,8 @@ public class EBSBootEC2ClientLiveTest {
assert !output.getOutput().trim().equals("") : output;
RetryablePredicate<String> scriptTester = new RetryablePredicate<String>(new ScriptTester(
ssh, SCRIPT_END), 600, 10, TimeUnit.SECONDS);
RetryablePredicate<String> scriptTester = new RetryablePredicate<String>(
new ScriptTester(ssh, SCRIPT_END), 600, 10, TimeUnit.SECONDS);
scriptTester.apply(script);
} finally {
if (ssh != null)
@ -319,7 +347,8 @@ public class EBSBootEC2ClientLiveTest {
@Override
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");
if (output.getOutput().trim().equals("")) {
output = ssh.exec(script + " tail");
@ -329,7 +358,9 @@ public class EBSBootEC2ClientLiveTest {
} else {
output = ssh.exec(script + " tailerr");
String stderr = output.getOutput().trim();
throw new RuntimeException(String.format(
throw new RuntimeException(
String
.format(
"script %s ended without token: stdout.log: [%s]; stderr.log: [%s]; ",
script, stdout, stderr));
}
@ -345,42 +376,49 @@ public class EBSBootEC2ClientLiveTest {
.describeVolumesInRegion(volume.getRegion(), volume.getId()));
if (volume.getAttachments().size() > 0) {
// should be cleanly unmounted, so force is not necessary.
client.getElasticBlockStoreServices().detachVolumeInRegion(instance.getRegion(),
volume.getId(), false);
System.out.printf("%d: %s awaiting detachment to complete%n", System.currentTimeMillis(),
volume.getId());
client.getElasticBlockStoreServices().detachVolumeInRegion(
instance.getRegion(), volume.getId(), false);
System.out.printf("%d: %s awaiting detachment to complete%n", System
.currentTimeMillis(), volume.getId());
assert volumeTester.apply(volume);
} 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(),
volume.getId(), withDescription("EBS Ubuntu Hardy"));
snapshot = client.getElasticBlockStoreServices().createSnapshotInRegion(
volume.getRegion(), volume.getId(),
withDescription("EBS Ubuntu Hardy"));
System.out.printf("%d: %s awaiting snapshot to complete%n", System.currentTimeMillis(),
snapshot.getId());
System.out.printf("%d: %s awaiting snapshot to complete%n", System
.currentTimeMillis(), snapshot.getId());
assert snapshotTester.apply(snapshot);
Image image = Iterables.getOnlyElement(client.getAMIServices().describeImagesInRegion(
snapshot.getRegion(), imageIds(IMAGE_ID)));
String description = image.getDescription() == null ? "jclouds" : image.getDescription();
Image image = Iterables.getOnlyElement(client.getAMIServices()
.describeImagesInRegion(snapshot.getRegion(), imageIds(IMAGE_ID)));
String description = image.getDescription() == null ? "jclouds" : image
.getDescription();
System.out.printf("%d: %s creating ami from snapshot%n", System.currentTimeMillis(), snapshot
.getId());
System.out.printf("%d: %s creating ami from snapshot%n", System
.currentTimeMillis(), snapshot.getId());
String amiId = client.getAMIServices().registerUnixImageBackedByEbsInRegion(
String amiId = client.getAMIServices()
.registerUnixImageBackedByEbsInRegion(
snapshot.getRegion(),
"ebsboot-" + image.getId(),
snapshot.getId(),
withKernelId(image.getKernelId()).withRamdisk(image.getRamdiskId()).withDescription(
description).asArchitecture(Architecture.I386));
withKernelId(image.getKernelId()).withRamdisk(
image.getRamdiskId()).withDescription(description)
.asArchitecture(Architecture.I386));
try {
ebsImage = Iterables.getOnlyElement(client.getAMIServices().describeImagesInRegion(
snapshot.getRegion(), imageIds(amiId)));
ebsImage = Iterables.getOnlyElement(client.getAMIServices()
.describeImagesInRegion(snapshot.getRegion(), imageIds(amiId)));
} catch (AWSResponseException e) {
// TODO add a retry handler for this HTTP code 400 and the below error
if (e.getError().getClass().equals("InvalidAMIID.NotFound"))
ebsImage = Iterables.getOnlyElement(client.getAMIServices().describeImagesInRegion(
snapshot.getRegion(), imageIds(amiId)));
ebsImage = Iterables
.getOnlyElement(client.getAMIServices()
.describeImagesInRegion(snapshot.getRegion(),
imageIds(amiId)));
else
throw e;
}
@ -389,22 +427,22 @@ public class EBSBootEC2ClientLiveTest {
@Test(enabled = false, dependsOnMethods = { "testAMIFromBundle" })
public void testInstanceFromEBS() throws Exception {
System.out.printf("%d: %s creating instance from ebs-backed ami%n", System
.currentTimeMillis(), ebsImage.getId());
System.out.printf("%d: %s creating instance from ebs-backed ami%n",
System.currentTimeMillis(), ebsImage.getId());
ebsInstance = createInstance(ebsImage.getId());
client.getInstanceServices().stopInstancesInRegion(ebsInstance.getRegion(), true,
ebsInstance.getId());
client.getInstanceServices().stopInstancesInRegion(
ebsInstance.getRegion(), true, ebsInstance.getId());
System.out.printf("%d: %s awaiting instance to stop %n", System.currentTimeMillis(),
ebsInstance.getId());
System.out.printf("%d: %s awaiting instance to stop %n", System
.currentTimeMillis(), ebsInstance.getId());
stoppedTester.apply(ebsInstance);
tryToChangeStuff();
System.out.printf("%d: %s awaiting instance to start %n", System.currentTimeMillis(),
ebsInstance.getId());
client.getInstanceServices().startInstancesInRegion(ebsInstance.getRegion(),
ebsInstance.getId());
System.out.printf("%d: %s awaiting instance to start %n", System
.currentTimeMillis(), ebsInstance.getId());
client.getInstanceServices().startInstancesInRegion(
ebsInstance.getRegion(), ebsInstance.getId());
ebsInstance = blockUntilWeCanSshIntoInstance(ebsInstance);
}
@ -412,8 +450,10 @@ public class EBSBootEC2ClientLiveTest {
assertEquals(ebsImage.getImageType(), ImageType.MACHINE);
assertEquals(ebsImage.getRootDeviceType(), RootDeviceType.EBS);
assertEquals(ebsImage.getRootDeviceName(), "/dev/sda1");
assertEquals(ebsImage.getEbsBlockDevices().entrySet(), ImmutableMap.of("/dev/sda1",
new Image.EbsBlockDevice(snapshot.getId(), VOLUME_SIZE, true)).entrySet());
assertEquals(ebsImage.getEbsBlockDevices().entrySet(), ImmutableMap.of(
"/dev/sda1",
new Image.EbsBlockDevice(snapshot.getId(), VOLUME_SIZE, true))
.entrySet());
}
private void tryToChangeStuff() {
@ -426,56 +466,59 @@ public class EBSBootEC2ClientLiveTest {
}
private void setUserDataForInstanceInRegion() {
client.getInstanceServices().setUserDataForInstanceInRegion(null, ebsInstance.getId(),
"test".getBytes());
assertEquals("test", client.getInstanceServices().getUserDataForInstanceInRegion(null,
ebsInstance.getId()));
client.getInstanceServices().setUserDataForInstanceInRegion(null,
ebsInstance.getId(), "test".getBytes());
assertEquals("test", client.getInstanceServices()
.getUserDataForInstanceInRegion(null, ebsInstance.getId()));
}
private void setRamdiskForInstanceInRegion() {
String ramdisk = client.getInstanceServices().getRamdiskForInstanceInRegion(null,
ebsInstance.getId());
client.getInstanceServices()
.setRamdiskForInstanceInRegion(null, ebsInstance.getId(), ramdisk);
assertEquals(ramdisk, client.getInstanceServices().getRamdiskForInstanceInRegion(null,
ebsInstance.getId()));
String ramdisk = client.getInstanceServices()
.getRamdiskForInstanceInRegion(null, ebsInstance.getId());
client.getInstanceServices().setRamdiskForInstanceInRegion(null,
ebsInstance.getId(), ramdisk);
assertEquals(ramdisk, client.getInstanceServices()
.getRamdiskForInstanceInRegion(null, ebsInstance.getId()));
}
private void setKernelForInstanceInRegion() {
String oldKernel = client.getInstanceServices().getKernelForInstanceInRegion(null,
ebsInstance.getId());
client.getInstanceServices().setKernelForInstanceInRegion(null, ebsInstance.getId(),
oldKernel);
assertEquals(oldKernel, client.getInstanceServices().getKernelForInstanceInRegion(null,
ebsInstance.getId()));
String oldKernel = client.getInstanceServices()
.getKernelForInstanceInRegion(null, ebsInstance.getId());
client.getInstanceServices().setKernelForInstanceInRegion(null,
ebsInstance.getId(), oldKernel);
assertEquals(oldKernel, client.getInstanceServices()
.getKernelForInstanceInRegion(null, ebsInstance.getId()));
}
private void setInstanceTypeForInstanceInRegion() {
client.getInstanceServices().setInstanceTypeForInstanceInRegion(null, ebsInstance.getId(),
InstanceType.C1_MEDIUM);
client.getInstanceServices().setInstanceTypeForInstanceInRegion(null,
ebsInstance.getId(), InstanceType.C1_MEDIUM);
assertEquals(InstanceType.C1_MEDIUM, client.getInstanceServices()
.getInstanceTypeForInstanceInRegion(null, ebsInstance.getId()));
client.getInstanceServices().setInstanceTypeForInstanceInRegion(null, ebsInstance.getId(),
InstanceType.M1_SMALL);
client.getInstanceServices().setInstanceTypeForInstanceInRegion(null,
ebsInstance.getId(), InstanceType.M1_SMALL);
assertEquals(InstanceType.M1_SMALL, client.getInstanceServices()
.getInstanceTypeForInstanceInRegion(null, ebsInstance.getId()));
}
private void setBlockDeviceMappingForInstanceInRegion() {
String volumeId = ebsInstance.getEbsBlockDevices().get("/dev/sda1").getVolumeId();
String volumeId = ebsInstance.getEbsBlockDevices().get("/dev/sda1")
.getVolumeId();
BlockDeviceMapping blockDeviceMapping = new BlockDeviceMapping();
blockDeviceMapping.addEbsBlockDevice("/dev/sda1", new RunningInstance.EbsBlockDevice(
volumeId, false));
blockDeviceMapping.addEbsBlockDevice("/dev/sda1",
new RunningInstance.EbsBlockDevice(volumeId, false));
try {
client.getInstanceServices().setBlockDeviceMappingForInstanceInRegion(null,
ebsInstance.getId(), blockDeviceMapping);
client.getInstanceServices().setBlockDeviceMappingForInstanceInRegion(
null, ebsInstance.getId(), blockDeviceMapping);
Map<String, RunningInstance.EbsBlockDevice> devices = client.getInstanceServices()
.getBlockDeviceMappingForInstanceInRegion(null, ebsInstance.getId());
Map<String, RunningInstance.EbsBlockDevice> devices = client
.getInstanceServices().getBlockDeviceMappingForInstanceInRegion(
null, ebsInstance.getId());
assertEquals(devices.size(), 1);
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(deviceName, "/dev/sda1");
@ -492,27 +535,36 @@ public class EBSBootEC2ClientLiveTest {
private void setInstanceInitiatedShutdownBehaviorForInstanceInRegion() {
try {
client.getInstanceServices().setInstanceInitiatedShutdownBehaviorForInstanceInRegion(null,
ebsInstance.getId(), InstanceInitiatedShutdownBehavior.STOP);
client.getInstanceServices()
.setInstanceInitiatedShutdownBehaviorForInstanceInRegion(null,
ebsInstance.getId(),
InstanceInitiatedShutdownBehavior.STOP);
assertEquals(InstanceInitiatedShutdownBehavior.STOP, client.getInstanceServices()
assertEquals(InstanceInitiatedShutdownBehavior.STOP, client
.getInstanceServices()
.getInstanceInitiatedShutdownBehaviorForInstanceInRegion(null,
ebsInstance.getId()));
client.getInstanceServices().setInstanceInitiatedShutdownBehaviorForInstanceInRegion(null,
ebsInstance.getId(), InstanceInitiatedShutdownBehavior.TERMINATE);
client.getInstanceServices()
.setInstanceInitiatedShutdownBehaviorForInstanceInRegion(null,
ebsInstance.getId(),
InstanceInitiatedShutdownBehavior.TERMINATE);
assertEquals(InstanceInitiatedShutdownBehavior.TERMINATE, client.getInstanceServices()
assertEquals(InstanceInitiatedShutdownBehavior.TERMINATE, client
.getInstanceServices()
.getInstanceInitiatedShutdownBehaviorForInstanceInRegion(null,
ebsInstance.getId()));
System.out.println("OK: setInstanceInitiatedShutdownBehaviorForInstanceInRegion");
System.out
.println("OK: setInstanceInitiatedShutdownBehaviorForInstanceInRegion");
} catch (Exception e) {
System.err.println("setInstanceInitiatedShutdownBehaviorForInstanceInRegion");
System.err
.println("setInstanceInitiatedShutdownBehaviorForInstanceInRegion");
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
*/
@ -528,13 +580,14 @@ public class EBSBootEC2ClientLiveTest {
}
}
private void doCheckKey(RunningInstance newDetails) throws UnknownHostException {
private void doCheckKey(RunningInstance newDetails)
throws UnknownHostException {
doCheckKey(newDetails.getIpAddress());
}
private void doCheckKey(String address) {
SshClient ssh = sshFactory.create(new IPSocket(address, 22), "ubuntu", keyPair
.getKeyMaterial().getBytes());
SshClient ssh = sshFactory.create(new IPSocket(address, 22), "ubuntu",
keyPair.getKeyMaterial().getBytes());
try {
ssh.connect();
ExecResponse hello = ssh.exec("echo hello");
@ -545,26 +598,32 @@ public class EBSBootEC2ClientLiveTest {
}
}
private RunningInstance blockUntilWeCanSshIntoInstance(RunningInstance instance)
throws UnknownHostException {
System.out.printf("%d: %s awaiting instance to run %n", System.currentTimeMillis(), instance
.getId());
private RunningInstance blockUntilWeCanSshIntoInstance(
RunningInstance instance) throws UnknownHostException {
System.out.printf("%d: %s awaiting instance to run %n", System
.currentTimeMillis(), instance.getId());
assert runningTester.apply(instance);
// search my account for the instance I just created
Set<Reservation> reservations = client.getInstanceServices().describeInstancesInRegion(
instance.getRegion(), instance.getId()); // last parameter (ids) narrows the search
Set<Reservation> reservations = client.getInstanceServices()
.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(),
instance.getIpAddress());
System.out.printf("%d: %s awaiting ssh service to start%n", System
.currentTimeMillis(), instance.getIpAddress());
assert socketTester.apply(new IPSocket(instance.getIpAddress(), 22));
System.out.printf("%d: %s ssh service started%n", System.currentTimeMillis(), instance
.getDnsName());
System.out.printf("%d: %s ssh service started%n", System
.currentTimeMillis(), instance.getDnsName());
sshPing(instance);
System.out.printf("%d: %s ssh connection made%n", System.currentTimeMillis(), instance
.getId());
System.out.printf("%d: %s ssh connection made%n", System
.currentTimeMillis(), instance.getId());
return instance;
}
@ -572,8 +631,8 @@ public class EBSBootEC2ClientLiveTest {
void cleanup() {
if (ebsInstance != null) {
try {
client.getInstanceServices().terminateInstancesInRegion(ebsInstance.getRegion(),
ebsInstance.getId());
client.getInstanceServices().terminateInstancesInRegion(
ebsInstance.getRegion(), ebsInstance.getId());
terminatedTester.apply(ebsInstance);
} catch (Exception e) {
e.printStackTrace();
@ -581,7 +640,8 @@ public class EBSBootEC2ClientLiveTest {
}
if (ebsImage != null) {
try {
client.getAMIServices().deregisterImageInRegion(ebsImage.getRegion(), ebsImage.getId());
client.getAMIServices().deregisterImageInRegion(
ebsImage.getRegion(), ebsImage.getId());
} catch (Exception e) {
e.printStackTrace();
}
@ -589,16 +649,16 @@ public class EBSBootEC2ClientLiveTest {
if (snapshot != null) {
try {
client.getElasticBlockStoreServices().deleteSnapshotInRegion(snapshot.getRegion(),
snapshot.getId());
client.getElasticBlockStoreServices().deleteSnapshotInRegion(
snapshot.getRegion(), snapshot.getId());
} catch (Exception e) {
e.printStackTrace();
}
}
if (attachment != null) {
try {
client.getElasticBlockStoreServices().detachVolumeInRegion(volume.getRegion(),
volume.getId(), true);
client.getElasticBlockStoreServices().detachVolumeInRegion(
volume.getRegion(), volume.getId(), true);
assert volumeTester.apply(volume);
} catch (Exception e) {
e.printStackTrace();
@ -606,8 +666,8 @@ public class EBSBootEC2ClientLiveTest {
}
if (instance != null) {
try {
client.getInstanceServices().terminateInstancesInRegion(instance.getRegion(),
instance.getId());
client.getInstanceServices().terminateInstancesInRegion(
instance.getRegion(), instance.getId());
terminatedTester.apply(instance);
} catch (Exception e) {
e.printStackTrace();
@ -615,23 +675,24 @@ public class EBSBootEC2ClientLiveTest {
}
if (volume != null) {
try {
client.getElasticBlockStoreServices().deleteVolumeInRegion(volume.getRegion(),
volume.getId());
client.getElasticBlockStoreServices().deleteVolumeInRegion(
volume.getRegion(), volume.getId());
} catch (Exception e) {
e.printStackTrace();
}
}
if (keyPair != null) {
try {
client.getKeyPairServices().deleteKeyPairInRegion(keyPair.getRegion(),
keyPair.getKeyName());
client.getKeyPairServices().deleteKeyPairInRegion(
keyPair.getRegion(), keyPair.getKeyName());
} catch (Exception e) {
e.printStackTrace();
}
}
if (securityGroupName != null) {
try {
client.getSecurityGroupServices().deleteSecurityGroupInRegion(null, securityGroupName);
client.getSecurityGroupServices().deleteSecurityGroupInRegion(null,
securityGroupName);
} catch (Exception e) {
e.printStackTrace();
}

View File

@ -63,13 +63,15 @@ public class EC2ComputeServiceLiveTest extends BaseComputeServiceLiveTest {
@Test(enabled = true, dependsOnMethods = "testCorrectAuthException")
public void testExtendedOptionsAndLogin() throws Exception {
SecurityGroupClient securityGroupClient = EC2Client.class.cast(
context.getProviderSpecificContext().getApi()).getSecurityGroupServices();
context.getProviderSpecificContext().getApi())
.getSecurityGroupServices();
KeyPairClient keyPairClient = EC2Client.class.cast(
context.getProviderSpecificContext().getApi()).getKeyPairServices();
InstanceClient instanceClient = EC2Client.class.cast(
context.getProviderSpecificContext().getApi()).getInstanceServices();
context.getProviderSpecificContext().getApi())
.getInstanceServices();
String tag = this.tag + "optionsandlogin";
@ -82,15 +84,17 @@ public class EC2ComputeServiceLiveTest extends BaseComputeServiceLiveTest {
try {
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.authorizeSecurityGroupIngressInRegion(null, tag, IpProtocol.TCP, 22,
22, "0.0.0.0/0");
securityGroupClient.authorizeSecurityGroupIngressInRegion(null, tag,
IpProtocol.TCP, 22, 22, "0.0.0.0/0");
// create a keypair to pass in as well
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);
assert first.getCredentials() != null : first;
assert first.getCredentials().account != null : first;
@ -102,7 +106,8 @@ public class EC2ComputeServiceLiveTest extends BaseComputeServiceLiveTest {
assertEquals(instance.getKeyName(), tag);
// 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
SecurityGroup group = Iterables.getOnlyElement(securityGroupClient
@ -110,15 +115,18 @@ public class EC2ComputeServiceLiveTest extends BaseComputeServiceLiveTest {
assert group.getIpPermissions().size() == 0 : group;
// try to run a script with the original keyPair
runScriptWithCreds(tag, first.getImage().getOsFamily(), new Credentials(first
.getCredentials().account, result.getKeyMaterial()));
runScriptWithCreds(tag, first.getImage().getOsFamily(),
new Credentials(first.getCredentials().account, result
.getKeyMaterial()));
} finally {
client.destroyNodesMatching(NodePredicates.withTag(tag));
if (startedId != null) {
// ensure we didn't delete these resources!
assertEquals(keyPairClient.describeKeyPairsInRegion(null, tag).size(), 1);
assertEquals(securityGroupClient.describeSecurityGroupsInRegion(null, tag).size(), 1);
assertEquals(keyPairClient.describeKeyPairsInRegion(null, tag)
.size(), 1);
assertEquals(securityGroupClient.describeSecurityGroupsInRegion(
null, tag).size(), 1);
}
cleanupExtendedStuff(securityGroupClient, keyPairClient, tag);
}
@ -127,13 +135,15 @@ public class EC2ComputeServiceLiveTest extends BaseComputeServiceLiveTest {
@Test(enabled = true, dependsOnMethods = "testCorrectAuthException")
public void testExtendedOptionsNoKeyPair() throws Exception {
SecurityGroupClient securityGroupClient = EC2Client.class.cast(
context.getProviderSpecificContext().getApi()).getSecurityGroupServices();
context.getProviderSpecificContext().getApi())
.getSecurityGroupServices();
KeyPairClient keyPairClient = EC2Client.class.cast(
context.getProviderSpecificContext().getApi()).getKeyPairServices();
InstanceClient instanceClient = EC2Client.class.cast(
context.getProviderSpecificContext().getApi()).getInstanceServices();
context.getProviderSpecificContext().getApi())
.getInstanceServices();
String tag = this.tag + "optionsnokey";
@ -149,7 +159,8 @@ public class EC2ComputeServiceLiveTest extends BaseComputeServiceLiveTest {
// create the security group
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();
assert creds == null;
@ -160,7 +171,8 @@ public class EC2ComputeServiceLiveTest extends BaseComputeServiceLiveTest {
assertEquals(instance.getKeyName(), null);
// 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
SecurityGroup group = Iterables.getOnlyElement(securityGroupClient
@ -171,14 +183,16 @@ public class EC2ComputeServiceLiveTest extends BaseComputeServiceLiveTest {
client.destroyNodesMatching(NodePredicates.withTag(tag));
if (startedId != null) {
// 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);
}
}
private RunningInstance getInstance(InstanceClient instanceClient, String id) {
RunningInstance instance = Iterables.getOnlyElement(Iterables.getOnlyElement(instanceClient
RunningInstance instance = Iterables
.getOnlyElement(Iterables.getOnlyElement(instanceClient
.describeInstancesInRegion(null, id)));
return instance;
}

View File

@ -52,7 +52,7 @@ public class ImageParserTest extends BaseEC2HandlerTest {
InputStream is = getClass().getResourceAsStream("/ec2/alestic_canonical.xml");
Set<Image> result = parseImages(is);
assertEquals(result.size(), 6);
assertEquals(result.size(), 7);
ImageParser parser = new ImageParser(
new EC2PopulateDefaultLoginCredentialsForImageStrategy(), ImmutableSet
@ -87,6 +87,9 @@ public class ImageParserTest extends BaseEC2HandlerTest {
"063491364108"));
assertEquals(alesticKarmic.getVersion(), "20090623");
org.jclouds.compute.domain.Image ubuntuKarmic = parser.apply(Iterables.get(result, 2));
assertEquals(ubuntuKarmic.getArchitecture(), org.jclouds.compute.domain.Architecture.X86_32);
@ -120,8 +123,24 @@ public class ImageParserTest extends BaseEC2HandlerTest {
"063491364108"));
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
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",

View File

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

View File

@ -67,6 +67,19 @@
<rootDeviceType>instance-store</rootDeviceType>
<blockDeviceMapping />
</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>
<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>

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 {
/**
* Tag used for all resources that belong to the same logical group. run, destroy commands are
* scoped to tag.
* Tag used for all resources that belong to the same logical group. run,
* destroy commands are scoped to tag.
*
* @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();
/**
* If possible, these are returned upon all detail requests. However, it is often the case that
* credentials are only available at "run" time.
* If possible, these are returned upon all detail requests. However, it is
* often the case that credentials are only available at "run" time.
*/
Credentials getCredentials();

View File

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

View File

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

View File

@ -24,10 +24,11 @@ import static com.google.common.base.Preconditions.checkNotNull;
import java.util.Arrays;
/**
* Contains options supported in the {@code ComputeService#runNodesWithTag} operation. <h2>
* Usage</h2> The recommended way to instantiate a TemplateOptions object is to statically import
* TemplateOptions.* and invoke a static creation method followed by an instance mutator (if
* needed):
* Contains options supported in the {@code ComputeService#runNodesWithTag}
* operation. <h2>
* Usage</h2> The recommended way to instantiate a TemplateOptions object is to
* statically import TemplateOptions.* and invoke a static creation method
* followed by an instance mutator (if needed):
* <p/>
* <code>
* import static org.jclouds.compute.options.TemplateOptions.Builder.*;
@ -41,7 +42,8 @@ import java.util.Arrays;
*/
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 {
private final TemplateOptions delegate;
@ -62,7 +64,13 @@ public class TemplateOptions {
@Override
public TemplateOptions authorizePublicKey(String publicKey) {
return delegate.authorizePublicKey(publicKey);
throw new IllegalArgumentException(
"authorizePublicKey is immutable");
}
@Override
public TemplateOptions blockUntilRunning(boolean blockUntilRunning) {
throw new IllegalArgumentException("blockUntilRunning is immutable");
}
@Override
@ -100,6 +108,11 @@ public class TemplateOptions {
return delegate.getSeconds();
}
@Override
public boolean shouldBlockUntilRunning() {
return delegate.shouldBlockUntilRunning();
}
@Override
public TemplateOptions inboundPorts(int... ports) {
throw new IllegalArgumentException("ports is immutable");
@ -141,6 +154,8 @@ public class TemplateOptions {
protected boolean includeMetadata;
protected boolean blockUntilRunning = true;
public int getPort() {
return port;
}
@ -169,6 +184,10 @@ public class TemplateOptions {
return includeMetadata;
}
public boolean shouldBlockUntilRunning() {
return blockUntilRunning;
}
public <T extends TemplateOptions> T as(Class<T> clazz) {
return clazz.cast(this);
}
@ -177,7 +196,8 @@ public class TemplateOptions {
* When the node is started, wait until the following port is active
*/
public TemplateOptions blockOnPort(int port, int seconds) {
checkArgument(port > 0 && port < 65536, "port must be a positive integer < 65535");
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;
@ -185,8 +205,8 @@ public class TemplateOptions {
}
/**
* 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
* 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 runScript(byte[] script) {
checkArgument(checkNotNull(script, "script").length <= 16 * 1024,
@ -211,12 +231,25 @@ public class TemplateOptions {
return this;
}
/**
* if true, return when node(s) are NODE_RUNNING, if false, return as soon as the
* server is provisioned.
* <p/>
* default is true
*/
public TemplateOptions blockUntilRunning(boolean blockUntilRunning) {
this.blockUntilRunning = blockUntilRunning;
if (!blockUntilRunning)
port = seconds = -1;
return this;
}
/**
* authorized an rsa ssh key.
*/
public TemplateOptions authorizePublicKey(String publicKey) {
checkArgument(checkNotNull(publicKey, "publicKey").startsWith("ssh-rsa"),
"key should start with ssh-rsa");
checkArgument(checkNotNull(publicKey, "publicKey")
.startsWith("ssh-rsa"), "key should start with ssh-rsa");
this.publicKey = publicKey;
return this;
}
@ -226,7 +259,8 @@ public class TemplateOptions {
*/
public TemplateOptions inboundPorts(int... ports) {
for (int port : ports)
checkArgument(port > 0 && port < 65536, "port must be a positive integer < 65535");
checkArgument(port > 0 && port < 65536,
"port must be a positive integer < 65535");
this.inboundPorts = ports;
return this;
}
@ -254,6 +288,15 @@ public class TemplateOptions {
return options.blockOnPort(port, seconds);
}
/**
* @see TemplateOptions#blockUntilRunning
*/
public static TemplateOptions blockUntilRunning(
boolean blockUntilRunning) {
TemplateOptions options = new TemplateOptions();
return options.blockUntilRunning(blockUntilRunning);
}
/**
* @see TemplateOptions#runScript
*/
@ -287,9 +330,11 @@ public class TemplateOptions {
@Override
public String toString() {
return "TemplateOptions [inboundPorts=" + Arrays.toString(inboundPorts) + ", privateKey="
+ (privateKey != null) + ", publicKey=" + (publicKey != null) + ", runScript="
+ (script != null) + ", port:seconds=" + port + ":" + seconds
return "TemplateOptions [inboundPorts=" + Arrays.toString(inboundPorts)
+ ", privateKey=" + (privateKey != null) + ", publicKey="
+ (publicKey != null) + ", runScript=" + (script != null)
+ ", blockUntilRunning=" + blockUntilRunning
+ ", port:seconds=" + port + ":" + seconds
+ ", metadata/details: " + includeMetadata + "]";
}
@ -297,11 +342,14 @@ public class TemplateOptions {
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
+ ((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;
@ -316,6 +364,8 @@ public class TemplateOptions {
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)

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
* tag to match the items
@ -121,7 +121,7 @@ public class NodePredicates {
/**
* Match nodes with State == RUNNING
*/
public static final Predicate<NodeMetadata> ACTIVE = new Predicate<NodeMetadata>() {
public static final Predicate<NodeMetadata> RUNNING = new Predicate<NodeMetadata>() {
@Override
public boolean apply(NodeMetadata nodeMetadata) {
return nodeMetadata.getState() == NodeState.RUNNING;
@ -129,12 +129,12 @@ public class NodePredicates {
@Override
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>() {
@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;
import javax.inject.Named;
import javax.inject.Singleton;
import com.google.inject.Inject;
/**
*
* @author Adrian Cole
@ -26,5 +31,28 @@ public interface ComputeServiceConstants {
public static final String COMPUTE_LOGGER = "jclouds.compute";
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;
import org.jclouds.compute.domain.NodeMetadata;
/**
* terminates the node and blocks until it is no longer visible or in the state TERMINATED. If this
* is the last node in a tagset, incidental resources are also destroyed.
* terminates the node
*
* @author Adrian Cole
*/
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;
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
*/
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
*/
@Singleton
public class EncodeTagIntoNameRunNodesAndAddToSetStrategy implements RunNodesAndAddToSetStrategy {
public class EncodeTagIntoNameRunNodesAndAddToSetStrategy implements
RunNodesAndAddToSetStrategy {
@Resource
@Named(ComputeServiceConstants.COMPUTE_LOGGER)
protected Logger logger = Logger.NULL;
@ -67,8 +68,10 @@ public class EncodeTagIntoNameRunNodesAndAddToSetStrategy implements RunNodesAnd
@Inject
protected EncodeTagIntoNameRunNodesAndAddToSetStrategy(
AddNodeWithTagStrategy addNodeWithTagStrategy, ListNodesStrategy listNodesStrategy,
@Named("NAMING_CONVENTION") String nodeNamingConvention, ComputeUtils utils,
AddNodeWithTagStrategy addNodeWithTagStrategy,
ListNodesStrategy listNodesStrategy,
@Named("NAMING_CONVENTION") String nodeNamingConvention,
ComputeUtils utils,
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService executor) {
this.addNodeWithTagStrategy = addNodeWithTagStrategy;
this.listNodesStrategy = listNodesStrategy;
@ -78,31 +81,29 @@ public class EncodeTagIntoNameRunNodesAndAddToSetStrategy implements RunNodesAnd
}
/**
* This implementation gets a list of acceptable node names to encode the tag into, then it
* simultaneously runs the nodes and applies options to them.
* This implementation gets a list of acceptable node names to encode the tag
* into, then it simultaneously runs the nodes and applies options to them.
*/
@Override
public Map<?, ListenableFuture<Void>> execute(final String tag, final int count,
final Template template, final Set<NodeMetadata> nodes,
public Map<?, ListenableFuture<Void>> execute(final String tag,
final int count, final Template template,
final Set<NodeMetadata> nodes,
final Map<NodeMetadata, Exception> badNodes) {
Map<String, ListenableFuture<Void>> responses = Maps.newHashMap();
for (final String name : getNextNames(tag, template, count)) {
responses.put(name, makeListenable(executor.submit(new Callable<Void>() {
responses.put(name, makeListenable(executor
.submit(new Callable<Void>() {
@Override
public Void call() throws Exception {
NodeMetadata node = null;
logger.debug(">> starting node(%s) tag(%s)", name, tag);
node = addNodeWithTagStrategy.execute(tag, name, template);
logger.debug("<< running node(%s)", node.getProviderId());
try {
utils.runOptionsOnNode(node, template.getOptions());
logger.debug("<< options applied node(%s)", node.getProviderId());
nodes.add(node);
} catch (Exception e) {
logger.error(e, "<< error applying options (%s) on node (%s)", template
.getOptions(), node.getProviderId());
badNodes.put(node, e);
}
logger.debug("<< %s node(%s)", node.getState(), node
.getId());
utils
.runOptionsOnNodeAndAddToGoodSetOrPutExceptionIntoBadMap(
node, badNodes, nodes, template.getOptions())
.call();
return null;
}
}), executor));
@ -111,18 +112,20 @@ public class EncodeTagIntoNameRunNodesAndAddToSetStrategy implements RunNodesAnd
}
/**
* Find the next node names that can be used. These will be derived from the tag and the
* template. We will pre-allocate a specified quantity, and attempt to verify that there is no
* name conflict with the current service.
* Find the next node names that can be used. These will be derived from the
* tag and the template. We will pre-allocate a specified quantity, and
* attempt to verify that there is no name conflict with the current service.
*
* @param tag
* @param count
* @param template
* @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();
Iterable<? extends ComputeMetadata> currentNodes = listNodesStrategy.list();
Iterable<? extends ComputeMetadata> currentNodes = listNodesStrategy
.list();
int maxTries = 100;
int currentTries = 0;
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
* naming convention.
* This implementation will pass the tag and a hex formatted random number to
* the configured naming convention.
*
*/
protected String getNextName(final String tag, final Template template) {
return String.format(nodeNamingConvention, tag, Integer.toHexString(new SecureRandom()
.nextInt(4095)));
return String.format(nodeNamingConvention, tag, Integer
.toHexString(new SecureRandom().nextInt(4095)));
}
}

View File

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

View File

@ -48,6 +48,7 @@ import org.jclouds.compute.domain.internal.NodeMetadataImpl;
import org.jclouds.compute.options.TemplateOptions;
import org.jclouds.compute.predicates.ScriptStatusReturnsZero.CommandUsingClient;
import org.jclouds.compute.reference.ComputeServiceConstants;
import org.jclouds.compute.strategy.GetNodeMetadataStrategy;
import org.jclouds.concurrent.ConcurrentUtils;
import org.jclouds.domain.Credentials;
import org.jclouds.logging.Logger;
@ -82,22 +83,30 @@ public class ComputeUtils {
protected final Predicate<CommandUsingClient> runScriptNotRunning;
private final Predicate<IPSocket> socketTester;
private final ExecutorService executor;
protected final Predicate<NodeMetadata> nodeRunning;
private final GetNodeMetadataStrategy getNode;
@Inject
public ComputeUtils(Predicate<IPSocket> socketTester,
@Named("NOT_RUNNING") Predicate<CommandUsingClient> runScriptNotRunning,
public ComputeUtils(
Predicate<IPSocket> socketTester,
@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.runScriptNotRunning = runScriptNotRunning;
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");
int index = 1;
for (Entry<?, Exception> errorMessage : executionExceptions.entrySet()) {
fmt.format("%s) %s on %s:%n%s%n%n", index++, errorMessage.getValue().getClass()
.getSimpleName(), errorMessage.getKey(), Throwables
fmt.format("%s) %s on %s:%n%s%n%n", index++, errorMessage.getValue()
.getClass().getSimpleName(), errorMessage.getKey(), Throwables
.getStackTraceAsString(errorMessage.getValue()));
}
return fmt.format("%s error[s]", executionExceptions.size()).toString();
@ -105,12 +114,13 @@ public class ComputeUtils {
public Map<?, ListenableFuture<Void>> runOptionsOnNodesAndAddToGoodSetOrPutExceptionIntoBadMap(
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();
for (final NodeMetadata node : runningNodes) {
responses.put(node, makeListenable(executor
.submit(runOptionsOnNodeAndAddToGoodSetOrPutExceptionIntoBadMap(node, badNodes,
goodNodes, options)), executor));
.submit(runOptionsOnNodeAndAddToGoodSetOrPutExceptionIntoBadMap(
node, badNodes, goodNodes, options)), executor));
}
return responses;
}
@ -122,12 +132,12 @@ public class ComputeUtils {
@Override
public Void call() throws Exception {
try {
runOptionsOnNode(node, options);
logger.debug("<< options applied node(%s)", node.getProviderId());
goodNodes.add(node);
NodeMetadata node1 = runOptionsOnNode(node, options);
logger.debug("<< options applied node(%s)", node1.getId());
goodNodes.add(node1);
} catch (Exception e) {
logger.error(e, "<< problem applying options to node(%s): ", node.getProviderId(),
Throwables.getRootCause(e).getMessage());
logger.error(e, "<< problem applying options to node(%s): ",
node.getId(), Throwables.getRootCause(e).getMessage());
badNodes.put(node, e);
}
return null;
@ -139,10 +149,12 @@ public class ComputeUtils {
Map<? extends NodeMetadata, ? extends Throwable> failedNodes) {
Formatter fmt = new Formatter().format("Node failures:%n%n");
int index = 1;
for (Entry<? extends NodeMetadata, ? extends Throwable> errorMessage : failedNodes.entrySet()) {
fmt.format("%s) %s on node %s:%n%s%n%n", index++, errorMessage.getValue().getClass()
.getSimpleName(), errorMessage.getKey().getProviderId(), Throwables
.getStackTraceAsString(errorMessage.getValue()));
for (Entry<? extends NodeMetadata, ? extends Throwable> errorMessage : failedNodes
.entrySet()) {
fmt.format("%s) %s on node %s:%n%s%n%n", index++, errorMessage
.getValue().getClass().getSimpleName(), errorMessage.getKey()
.getId(), Throwables.getStackTraceAsString(errorMessage
.getValue()));
}
return fmt.format("%s error[s]", failedNodes.size()).toString();
}
@ -157,26 +169,41 @@ 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();
if (options.getRunScript() != null) {
callables.add(runScriptOnNode(node, "runscript", options.getRunScript()));
callables.add(runScriptOnNode(node, "runscript", options
.getRunScript()));
}
if (options.getPublicKey() != null) {
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) {
runCallablesOnNode(node, callables, options.getPrivateKey() != null ? installKeyOnNode(
node, options.getPrivateKey()) : null);
runCallablesOnNode(node, callables,
options.getPrivateKey() != null ? installKeyOnNode(node, options
.getPrivateKey()) : null);
}
if (options.getPort() > 0) {
checkNodeHasPublicIps(node);
blockUntilPortIsListeningOnPublicIp(options.getPort(), options.getSeconds(), Iterables
.get(node.getPublicAddresses(), 0));
blockUntilPortIsListeningOnPublicIp(options.getPort(), options
.getSeconds(), Iterables.get(node.getPublicAddresses(), 0));
}
return node;
}
private void checkNodeHasPublicIps(NodeMetadata node) {
@ -184,40 +211,50 @@ public class ComputeUtils {
"node does not have IP addresses configured: " + node);
}
private void blockUntilPortIsListeningOnPublicIp(int port, int seconds, String inetAddress) {
logger.debug(">> blocking on port %s:%d for %d seconds", inetAddress, port, seconds);
RetryablePredicate<IPSocket> tester = new RetryablePredicate<IPSocket>(socketTester, seconds,
1, TimeUnit.SECONDS);
private void blockUntilPortIsListeningOnPublicIp(int port, int seconds,
String inetAddress) {
logger.debug(">> blocking on port %s:%d for %d seconds", inetAddress,
port, seconds);
RetryablePredicate<IPSocket> tester = new RetryablePredicate<IPSocket>(
socketTester, seconds, 1, TimeUnit.SECONDS);
IPSocket socket = new IPSocket(inetAddress, port);
boolean passed = tester.apply(socket);
if (passed)
logger.debug("<< port %s:%d opened", inetAddress, port);
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);
}
public AuthorizeRSAPublicKey authorizeKeyOnNode(NodeMetadata node, String publicKey) {
public AuthorizeRSAPublicKey authorizeKeyOnNode(NodeMetadata node,
String 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);
}
public RunScriptOnNode runScriptOnNodeAsDefaultUser(NodeMetadata node, String scriptName,
byte[] script) {
return new RunScriptOnNode(runScriptNotRunning, node, scriptName, script, false);
public RunScriptOnNode runScriptOnNodeAsDefaultUser(NodeMetadata node,
String scriptName, byte[] script) {
return new RunScriptOnNode(runScriptNotRunning, node, scriptName, script,
false);
}
public Map<SshCallable<?>, ?> runCallablesOnNode(NodeMetadata node,
Iterable<? extends SshCallable<?>> parallel, @Nullable SshCallable<?> last) {
checkState(this.sshFactory != null, "runScript requested, but no SshModule configured");
Iterable<? extends SshCallable<?>> parallel,
@Nullable SshCallable<?> last) {
checkState(this.sshFactory != null,
"runScript requested, but no SshModule configured");
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);
try {
ssh.connect();
@ -229,7 +266,8 @@ public class ComputeUtils {
}
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();
if (Iterables.size(parallel) > 0) {
responses.putAll(runCallablesUsingSshClient(parallel, ssh));
@ -246,37 +284,42 @@ public class ComputeUtils {
}
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);
SshClient ssh = isKeyAuth(node) ? sshFactory.create(socket, node.getCredentials().account,
node.getCredentials().key.getBytes()) : sshFactory.create(socket, node
.getCredentials().account, node.getCredentials().key);
SshClient ssh = isKeyAuth(node) ? sshFactory.create(socket, node
.getCredentials().account, node.getCredentials().key.getBytes())
: sshFactory.create(socket, node.getCredentials().account, node
.getCredentials().key);
return ssh;
}
private Map<SshCallable<?>, Object> runCallablesUsingSshClient(
Iterable<? extends SshCallable<?>> parallel, SshClient ssh) {
Map<SshCallable<?>, ListenableFuture<?>> parallelResponses = Maps.newHashMap();
Map<SshCallable<?>, ListenableFuture<?>> parallelResponses = Maps
.newHashMap();
for (SshCallable<?> callable : parallel) {
callable.setConnection(ssh, logger);
parallelResponses.put(callable, ConcurrentUtils.makeListenable(executor.submit(callable),
executor));
parallelResponses.put(callable, ConcurrentUtils.makeListenable(
executor.submit(callable), executor));
}
Map<SshCallable<?>, Exception> exceptions = awaitCompletion(parallelResponses, executor,
null, logger, "ssh");
Map<SshCallable<?>, Exception> exceptions = awaitCompletion(
parallelResponses, executor, null, logger, "ssh");
if (exceptions.size() > 0)
throw new RuntimeException(String.format("error invoking callables on nodes: %s",
exceptions));
throw new RuntimeException(String.format(
"error invoking callables on nodes: %s", exceptions));
Map<SshCallable<?>, Object> newresponses = transform(parallelResponses);
return newresponses;
}
@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();
for (Map.Entry<SshCallable<?>, ListenableFuture<?>> entry : responses.entrySet()) {
for (Map.Entry<SshCallable<?>, ListenableFuture<?>> entry : responses
.entrySet()) {
try {
actualResponses.put(entry.getKey(), (T) entry.getValue().get());
} catch (InterruptedException e) {
@ -303,20 +346,24 @@ public class ComputeUtils {
private final boolean runAsRoot;
private Logger logger = Logger.NULL;
RunScriptOnNode(@Named("NOT_RUNNING") Predicate<CommandUsingClient> runScriptNotRunning,
RunScriptOnNode(
@Named("SCRIPT_COMPLETE") Predicate<CommandUsingClient> runScriptNotRunning,
NodeMetadata node, String scriptName, byte[] script) {
this(runScriptNotRunning, node, scriptName, script, true);
}
RunScriptOnNode(@Named("NOT_RUNNING") Predicate<CommandUsingClient> runScriptNotRunning,
NodeMetadata node, String scriptName, byte[] script, boolean runAsRoot) {
RunScriptOnNode(
@Named("SCRIPT_COMPLETE") Predicate<CommandUsingClient> runScriptNotRunning,
NodeMetadata node, String scriptName, byte[] script,
boolean runAsRoot) {
this.runScriptNotRunning = runScriptNotRunning;
this.node = checkNotNull(node, "node");
this.scriptName = checkNotNull(scriptName, "scriptName");
this.script = new InitBuilder(scriptName, "/tmp/" + scriptName, "/tmp/" + scriptName,
ImmutableMap.<String, String> of(), Iterables.toArray(Splitter.on("\n").split(
new String(checkNotNull(script, "script"))), String.class)).build(
OsFamily.UNIX).getBytes();
this.script = new InitBuilder(scriptName, "/tmp/" + scriptName,
"/tmp/" + scriptName, ImmutableMap.<String, String> of(),
Iterables.toArray(Splitter.on("\n").split(
new String(checkNotNull(script, "script"))), String.class))
.build(OsFamily.UNIX).getBytes();
this.runAsRoot = runAsRoot;
}
@ -330,15 +377,18 @@ public class ComputeUtils {
returnVal = runScriptAsRoot();
else
returnVal = runScriptAsDefaultUser();
runScriptNotRunning.apply(new CommandUsingClient("./" + scriptName + " status", ssh));
runScriptNotRunning.apply(new CommandUsingClient("./" + scriptName
+ " status", ssh));
logger.debug("<< complete(%d)", returnVal.getExitCode());
if (logger.isDebugEnabled() || returnVal.getExitCode() != 0) {
logger.debug("<< stdout from %s as %s@%s\n%s", scriptName,
node.getCredentials().account, Iterables.get(node.getPublicAddresses(), 0),
ssh.exec("./" + scriptName + " tail").getOutput());
logger.debug("<< stderr from %s as %s@%s\n%s", scriptName,
node.getCredentials().account, Iterables.get(node.getPublicAddresses(), 0),
ssh.exec("./" + scriptName + " tailerr").getOutput());
logger.debug("<< stdout from %s as %s@%s\n%s", scriptName, node
.getCredentials().account, Iterables.get(node
.getPublicAddresses(), 0), ssh.exec(
"./" + scriptName + " tail").getOutput());
logger.debug("<< stderr from %s as %s@%s\n%s", scriptName, node
.getCredentials().account, Iterables.get(node
.getPublicAddresses(), 0), ssh.exec(
"./" + scriptName + " tailerr").getOutput());
}
return returnVal;
}
@ -351,24 +401,28 @@ public class ComputeUtils {
private ExecResponse runScriptAsRoot() {
if (node.getCredentials().account.equals("root")) {
logger.debug(">> running %s as %s@%s", scriptName, node.getCredentials().account,
Iterables.get(node.getPublicAddresses(), 0));
logger.debug(">> running %s as %s@%s", scriptName, node
.getCredentials().account, Iterables.get(node
.getPublicAddresses(), 0));
return ssh.exec("./" + scriptName + " start");
} else if (isKeyAuth(node)) {
logger.debug(">> running sudo %s as %s@%s", scriptName, node.getCredentials().account,
Iterables.get(node.getPublicAddresses(), 0));
logger.debug(">> running sudo %s as %s@%s", scriptName, node
.getCredentials().account, Iterables.get(node
.getPublicAddresses(), 0));
return ssh.exec("sudo ./" + scriptName + " start");
} else {
logger.debug(">> running sudo -S %s as %s@%s", scriptName,
node.getCredentials().account, Iterables.get(node.getPublicAddresses(), 0));
return ssh.exec(String.format("echo '%s'|sudo -S ./%s", node.getCredentials().key,
scriptName + " start"));
logger.debug(">> running sudo -S %s as %s@%s", scriptName, node
.getCredentials().account, Iterables.get(node
.getPublicAddresses(), 0));
return ssh.exec(String.format("echo '%s'|sudo -S ./%s", node
.getCredentials().key, scriptName + " start"));
}
}
private ExecResponse runScriptAsDefaultUser() {
logger.debug(">> running script %s as %s@%s", scriptName, node.getCredentials().account,
Iterables.get(node.getPublicAddresses(), 0));
logger.debug(">> running script %s as %s@%s", scriptName, node
.getCredentials().account, Iterables.get(node
.getPublicAddresses(), 0));
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 final NodeMetadata node;
private final String privateKey;
@ -393,9 +448,12 @@ public class ComputeUtils {
@Override
public ExecResponse call() throws Exception {
ssh.exec("mkdir .ssh");
ssh.put(".ssh/id_rsa", new ByteArrayInputStream(privateKey.getBytes()));
logger.debug(">> installing rsa key for %s@%s", node.getCredentials().account, Iterables
.get(node.getPublicAddresses(), 0));
ssh
.put(".ssh/id_rsa", new ByteArrayInputStream(privateKey
.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");
}
@ -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 final NodeMetadata node;
private final String publicKey;
@ -426,10 +485,13 @@ public class ComputeUtils {
@Override
public ExecResponse call() throws Exception {
ssh.exec("mkdir .ssh");
ssh.put(".ssh/id_rsa.pub", new ByteArrayInputStream(publicKey.getBytes()));
logger.debug(">> authorizing rsa public key for %s@%s", node.getCredentials().account,
Iterables.get(node.getPublicAddresses(), 0));
ExecResponse returnVal = ssh.exec("cat .ssh/id_rsa.pub >> .ssh/authorized_keys");
ssh.put(".ssh/id_rsa.pub", new ByteArrayInputStream(publicKey
.getBytes()));
logger.debug(">> authorizing rsa public key for %s@%s", node
.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");
logger.debug("<< complete(%d)", returnVal.getExitCode());
return returnVal;
@ -449,25 +511,30 @@ public class ComputeUtils {
public static boolean isKeyAuth(NodeMetadata createdNode) {
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),
* returns a new instance of {@link NodeMetadata} that has new credentials
* Given the instances of {@link NodeMetadata} (immutable) and
* {@link Credentials} (immutable), returns a new instance of
* {@link NodeMetadata} that has new credentials
*/
public static NodeMetadata installNewCredentials(NodeMetadata node, Credentials newCredentials) {
return new NodeMetadataImpl(node.getProviderId(), node.getName(), node.getId(), node
.getLocation(), node.getUri(), node.getUserMetadata(), node.getTag(), node
.getImage(), node.getState(), node.getPublicAddresses(), node.getPrivateAddresses(),
node.getExtra(), newCredentials);
public static NodeMetadata installNewCredentials(NodeMetadata node,
Credentials newCredentials) {
return new NodeMetadataImpl(node.getProviderId(), node.getName(), node
.getId(), node.getLocation(), node.getUri(),
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
* compute.properties to populate the set.
* Gets a set of supported providers. Idea stolen from pallets
* (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() {
Properties properties = new Properties();
@ -484,7 +551,8 @@ public class ComputeUtils {
for (Object key : keys) {
String keyString = key.toString();
if (keyString.endsWith(".contextbuilder")) {
providers.add(keyString.substring(0, keyString.length() - ".contextbuilder".length()));
providers.add(keyString.substring(0, keyString.length()
- ".contextbuilder".length()));
}
}
return providers;

View File

@ -99,8 +99,8 @@ public abstract class BaseComputeServiceLiveTest {
protected Map<String, String> keyPair;
@BeforeGroups(groups = { "integration", "live" })
public void setupClient() throws InterruptedException, ExecutionException, TimeoutException,
IOException {
public void setupClient() throws InterruptedException, ExecutionException,
TimeoutException, IOException {
if (tag == null)
tag = checkNotNull(service, "service");
setupCredentials();
@ -110,28 +110,33 @@ public abstract class BaseComputeServiceLiveTest {
Injector injector = createSshClientInjector();
sshFactory = injector.getInstance(SshClient.Factory.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
}
protected void setupKeyPair() throws FileNotFoundException, IOException {
String secretKeyFile;
try {
secretKeyFile = checkNotNull(System.getProperty("jclouds.test.ssh.keyfile"),
secretKeyFile = checkNotNull(System
.getProperty("jclouds.test.ssh.keyfile"),
"jclouds.test.ssh.keyfile");
} catch (NullPointerException e) {
secretKeyFile = System.getProperty("user.home") + "/.ssh/id_rsa";
}
checkSecretKeyFile(secretKeyFile);
String secret = Files.toString(new File(secretKeyFile), Charsets.UTF_8);
assert secret.startsWith("-----BEGIN RSA PRIVATE KEY-----") : "invalid key:\n" + secret;
keyPair = ImmutableMap.<String, String> of("private", secret, "public", Files.toString(
new File(secretKeyFile + ".pub"), Charsets.UTF_8));
assert secret.startsWith("-----BEGIN RSA PRIVATE KEY-----") : "invalid key:\n"
+ secret;
keyPair = ImmutableMap.<String, String> of("private", secret, "public",
Files.toString(new File(secretKeyFile + ".pub"), Charsets.UTF_8));
}
protected void setupCredentials() {
user = checkNotNull(System.getProperty("jclouds.test.user"), "jclouds.test.user");
password = checkNotNull(System.getProperty("jclouds.test.key"), "jclouds.test.key");
user = checkNotNull(System.getProperty("jclouds.test.user"),
"jclouds.test.user");
password = checkNotNull(System.getProperty("jclouds.test.key"),
"jclouds.test.key");
}
protected Injector createSshClientInjector() {
@ -141,16 +146,20 @@ public abstract class BaseComputeServiceLiveTest {
private void initializeContextAndClient() throws IOException {
if (context != null)
context.close();
context = new ComputeServiceContextFactory().createContext(service, user, password,
ImmutableSet.of(new Log4JLoggingModule(), getSshModule()));
context = new ComputeServiceContextFactory()
.createContext(service, user, password, ImmutableSet.of(
new Log4JLoggingModule(), getSshModule()));
client = context.getComputeService();
}
private void checkSecretKeyFile(String secretKeyFile) throws FileNotFoundException {
Utils.checkNotEmpty(secretKeyFile,
private void checkSecretKeyFile(String secretKeyFile)
throws FileNotFoundException {
Utils
.checkNotEmpty(secretKeyFile,
"System property: [jclouds.test.ssh.keyfile] set to an empty string");
if (!new File(secretKeyFile).exists()) {
throw new FileNotFoundException("secretKeyFile not found at: " + secretKeyFile);
throw new FileNotFoundException("secretKeyFile not found at: "
+ secretKeyFile);
}
}
@ -175,7 +184,8 @@ public abstract class BaseComputeServiceLiveTest {
// since surefire and eclipse don't otherwise guarantee the order, we are
// starting this one alphabetically before create2nodes..
@Test(enabled = true, dependsOnMethods = "testImagesCache")
public void testAScriptExecutionAfterBootWithBasicTemplate() throws Exception {
public void testAScriptExecutionAfterBootWithBasicTemplate()
throws Exception {
String tag = this.tag + "run";
try {
client.destroyNodesMatching(NodePredicates.withTag(tag));
@ -185,18 +195,21 @@ public abstract class BaseComputeServiceLiveTest {
TemplateOptions options = client.templateOptions().blockOnPort(22, 120);
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();
assert good.account != null;
assert good.key != null;
Image image = Iterables.get(nodes, 0).getImage();
try {
Map<? extends NodeMetadata, ExecResponse> responses = runScriptWithCreds(tag, image
.getOsFamily(), new Credentials(good.account, "romeo"));
Map<? extends NodeMetadata, ExecResponse> responses = runScriptWithCreds(
tag, image.getOsFamily(), new Credentials(good.account,
"romeo"));
assert false : "shouldn't pass with a bad password\n" + responses;
} 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);
@ -211,7 +224,8 @@ public abstract class BaseComputeServiceLiveTest {
@Test(enabled = true, dependsOnMethods = "testImagesCache")
public void testTemplateMatch() throws Exception {
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());
}
@ -226,14 +240,14 @@ public abstract class BaseComputeServiceLiveTest {
}
template = buildTemplate(client.templateBuilder());
template.getOptions().installPrivateKey(keyPair.get("private")).authorizePublicKey(
keyPair.get("public")).runScript(
template.getOptions().installPrivateKey(keyPair.get("private"))
.authorizePublicKey(keyPair.get("public")).runScript(
buildScript(template.getImage().getOsFamily()).getBytes());
try {
nodes = Sets.newTreeSet(client.runNodesWithTag(tag, 2, template));
} catch (RunNodesException e) {
nodes = Sets.newTreeSet(Iterables.concat(e.getSuccessfulNodes(), e.getNodeErrors()
.keySet()));
nodes = Sets.newTreeSet(Iterables.concat(e.getSuccessfulNodes(), e
.getNodeErrors().keySet()));
throw e;
}
assertEquals(nodes.size(), 2);
@ -260,9 +274,11 @@ public abstract class BaseComputeServiceLiveTest {
}
@Test(enabled = true, dependsOnMethods = "testCreateTwoNodesWithRunScript")
public void testCreateAnotherNodeWithANewContextToEnsureSharedMemIsntRequired() throws Exception {
public void testCreateAnotherNodeWithANewContextToEnsureSharedMemIsntRequired()
throws Exception {
initializeContextAndClient();
TreeSet<NodeMetadata> nodes = Sets.newTreeSet(client.runNodesWithTag(tag, 1, template));
TreeSet<NodeMetadata> nodes = Sets.newTreeSet(client.runNodesWithTag(tag,
1, template));
checkNodes(nodes, tag);
NodeMetadata node = nodes.first();
this.nodes.add(node);
@ -271,28 +287,32 @@ public abstract class BaseComputeServiceLiveTest {
assertEquals(node.getImage(), template.getImage());
}
protected Map<? extends NodeMetadata, ExecResponse> runScriptWithCreds(final String tag,
OsFamily osFamily, Credentials creds) throws RunScriptOnNodesException {
protected Map<? extends NodeMetadata, ExecResponse> runScriptWithCreds(
final String tag, OsFamily osFamily, Credentials creds)
throws RunScriptOnNodesException {
try {
return client.runScriptOnNodesMatching(NodePredicates.runningWithTag(tag), buildScript(
osFamily).getBytes(), RunScriptOptions.Builder.overrideCredentialsWith(creds));
return client.runScriptOnNodesMatching(NodePredicates
.runningWithTag(tag), buildScript(osFamily).getBytes(),
RunScriptOptions.Builder.overrideCredentialsWith(creds));
} catch (SshException e) {
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));
}
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) {
assertNotNull(node.getProviderId());
assertNotNull(node.getTag());
assertEquals(node.getTag(), tag);
assertEquals(node.getState(), NodeState.RUNNING);
assert node.getPublicAddresses().size() >= 1 || node.getPrivateAddresses().size() >= 1 : "no ips in"
+ node;
assert node.getPublicAddresses().size() >= 1
|| node.getPrivateAddresses().size() >= 1 : "no ips in" + node;
assertNotNull(node.getCredentials());
if (node.getCredentials().account != null) {
assertNotNull(node.getCredentials().account);
@ -323,11 +343,14 @@ public abstract class BaseComputeServiceLiveTest {
case RHEL:
return new StringBuilder()
.append("echo nameserver 208.67.222.222 >> /etc/resolv.conf\n")
.append("echo \"[jdkrepo]\" >> /etc/yum.repos.d/CentOS-Base.repo\n")
.append("echo \"name=jdkrepository\" >> /etc/yum.repos.d/CentOS-Base.repo\n")
.append(
"echo \"[jdkrepo]\" >> /etc/yum.repos.d/CentOS-Base.repo\n")
.append(
"echo \"name=jdkrepository\" >> /etc/yum.repos.d/CentOS-Base.repo\n")
.append(
"echo \"baseurl=http://ec2-us-east-mirror.rightscale.com/epel/5/i386/\" >> /etc/yum.repos.d/CentOS-Base.repo\n")
.append("echo \"enabled=1\" >> /etc/yum.repos.d/CentOS-Base.repo\n")
.append(
"echo \"enabled=1\" >> /etc/yum.repos.d/CentOS-Base.repo\n")
.append("yum --nogpgcheck -y install java-1.6.0-openjdk\n")
.append(
"echo \"export PATH=\\\"/usr/lib/jvm/jre-1.6.0-openjdk/bin/:\\$PATH\\\"\" >> /root/.bashrc\n")
@ -339,27 +362,36 @@ public abstract class BaseComputeServiceLiveTest {
@Test(enabled = true, dependsOnMethods = "testCreateAnotherNodeWithANewContextToEnsureSharedMemIsntRequired")
public void testGet() throws Exception {
Set<? extends NodeMetadata> metadataSet = Sets.newHashSet(Iterables.filter(client
.listNodesDetailsMatching(NodePredicates.all()), Predicates.and(NodePredicates
.withTag(tag), Predicates.not(NodePredicates.TERMINATED))));
Set<? extends NodeMetadata> metadataSet = Sets.newHashSet(Iterables
.filter(client.listNodesDetailsMatching(NodePredicates.all()),
Predicates.and(NodePredicates.withTag(tag), Predicates
.not(NodePredicates.TERMINATED))));
for (NodeMetadata node : nodes) {
metadataSet.remove(node);
NodeMetadata metadata = client.getNodeMetadata(node.getId());
assertEquals(metadata.getProviderId(), node.getProviderId());
assertEquals(metadata.getTag(), node.getTag());
assertLocationSameOrChild(metadata.getLocation(), template.getLocation());
assertLocationSameOrChild(metadata.getLocation(), template
.getLocation());
assertEquals(metadata.getImage(), template.getImage());
assertEquals(metadata.getState(), NodeState.RUNNING);
assertEquals(metadata.getPrivateAddresses(), node.getPrivateAddresses());
assertEquals(metadata.getPrivateAddresses(), node
.getPrivateAddresses());
assertEquals(metadata.getPublicAddresses(), node.getPublicAddresses());
}
assertNodeZero(metadataSet);
}
protected void assertNodeZero(Set<? extends NodeMetadata> metadataSet) {
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")
public void testReboot() throws Exception {
client.rebootNodesMatching(NodePredicates.withTag(tag));// TODO test validation
client.rebootNodesMatching(NodePredicates.withTag(tag));// TODO test
// validation
testGet();
}
@ -380,7 +412,8 @@ public abstract class BaseComputeServiceLiveTest {
}
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.getLocation() != null : node;
assertEquals(node.getType(), ComputeType.NODE);
@ -440,6 +473,32 @@ public abstract class BaseComputeServiceLiveTest {
}
}
@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) {
assertEquals(provider.getScope(), LocationScope.PROVIDER);
assertEquals(provider.getParent(), null);
@ -470,12 +529,15 @@ public abstract class BaseComputeServiceLiveTest {
}
}
protected void doCheckJavaIsInstalledViaSsh(NodeMetadata node) throws IOException {
IPSocket socket = new IPSocket(Iterables.get(node.getPublicAddresses(), 0), 22);
socketTester.apply(socket); // TODO add transitionTo option that accepts a socket conection
protected void doCheckJavaIsInstalledViaSsh(NodeMetadata node)
throws IOException {
IPSocket socket = new IPSocket(Iterables
.get(node.getPublicAddresses(), 0), 22);
socketTester.apply(socket); // TODO add transitionTo option that accepts
// a socket conection
// state.
SshClient ssh = sshFactory.create(socket, node.getCredentials().account, keyPair.get(
"private").getBytes());
SshClient ssh = sshFactory.create(socket, node.getCredentials().account,
keyPair.get("private").getBytes());
try {
ssh.connect();
ExecResponse hello = ssh.exec("echo hello");
@ -489,11 +551,13 @@ public abstract class BaseComputeServiceLiveTest {
}
@AfterTest
protected void cleanup() throws InterruptedException, ExecutionException, TimeoutException {
protected void cleanup() throws InterruptedException, ExecutionException,
TimeoutException {
if (nodes != null) {
client.destroyNodesMatching(NodePredicates.withTag(tag));
for (NodeMetadata node : Iterables.filter(client.listNodesDetailsMatching(NodePredicates
.all()), NodePredicates.withTag(tag))) {
for (NodeMetadata node : Iterables.filter(client
.listNodesDetailsMatching(NodePredicates.all()), NodePredicates
.withTag(tag))) {
assert node.getState() == NodeState.TERMINATED : node;
}
}

View File

@ -31,10 +31,12 @@ import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.Serializable;
import java.util.Set;
import java.util.concurrent.ConcurrentMap;
import org.easymock.IArgumentMatcher;
import org.jclouds.compute.domain.Architecture;
import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.domain.OsFamily;
import org.jclouds.compute.domain.Template;
import org.jclouds.compute.stub.config.StubComputeServiceContextModule.StubNodeMetadata;
@ -64,7 +66,8 @@ import com.google.inject.Module;
* @author Adrian Cole
*/
@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_BAD = new ExecResponse("", "", 1);
@ -82,7 +85,8 @@ public class StubComputeServiceIntegrationTest extends BaseComputeServiceLiveTes
@Test
public void testTemplateBuilder() {
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.getLocation().getId(), "memory");
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(
factory.create(eq(new IPSocket("144.175.1.1", 22)), eq("root"), aryEq(keyPair
.get("private").getBytes()))).andReturn(client1).atLeastOnce();
factory.create(eq(new IPSocket("144.175.1.1", 22)),
eq("root"), aryEq(keyPair.get("private").getBytes())))
.andReturn(client1).atLeastOnce();
expect(
factory.create(eq(new IPSocket("144.175.1.2", 22)), eq("root"), aryEq(keyPair
.get("private").getBytes()))).andReturn(client2).atLeastOnce();
factory.create(eq(new IPSocket("144.175.1.2", 22)),
eq("root"), aryEq(keyPair.get("private").getBytes())))
.andReturn(client2).atLeastOnce();
expect(
factory.create(eq(new IPSocket("144.175.1.3", 22)), eq("root"), aryEq(keyPair
.get("private").getBytes()))).andReturn(client3).atLeastOnce();
factory.create(eq(new IPSocket("144.175.1.3", 22)),
eq("root"), aryEq(keyPair.get("private").getBytes())))
.andReturn(client3).atLeastOnce();
expect(
factory.create(eq(new IPSocket("144.175.1.4", 22)), eq("root"), aryEq(keyPair
.get("private").getBytes()))).andReturn(client4).atLeastOnce();
factory.create(eq(new IPSocket("144.175.1.4", 22)),
eq("root"), aryEq(keyPair.get("private").getBytes())))
.andReturn(client4).atLeastOnce();
helloAndJava(client1);
helloAndJava(client2);
@ -139,8 +147,10 @@ public class StubComputeServiceIntegrationTest extends BaseComputeServiceLiveTes
private void helloAndJava(SshClient client) {
client.connect();
expect(client.exec("echo hello")).andReturn(new ExecResponse("hello", "", 0));
expect(client.exec("java -version")).andReturn(new ExecResponse("", "OpenJDK", 0));
expect(client.exec("echo hello")).andReturn(
new ExecResponse("hello", "", 0));
expect(client.exec("java -version")).andReturn(
new ExecResponse("", "OpenJDK", 0));
client.disconnect();
}
@ -160,21 +170,26 @@ public class StubComputeServiceIntegrationTest extends BaseComputeServiceLiveTes
SshClient client3 = createMock(SshClient.class);
SshClient client4 = createMock(SshClient.class);
expect(factory.create(new IPSocket("144.175.1.1", 22), "root", "romeo")).andThrow(
new SshException("Auth fail"));
expect(factory.create(new IPSocket("144.175.1.1", 22), "root", "password1")).andReturn(
client1).atLeastOnce();
expect(
factory.create(new IPSocket("144.175.1.1", 22), "root",
"romeo")).andThrow(new SshException("Auth fail"));
expect(
factory.create(new IPSocket("144.175.1.1", 22), "root",
"password1")).andReturn(client1).atLeastOnce();
client1.connect();
runScript(client1, "computeserv", 1);
client1.disconnect();
expect(factory.create(new IPSocket("144.175.1.2", 22), "root", "password2")).andReturn(
client2).atLeastOnce();
expect(factory.create(new IPSocket("144.175.1.3", 22), "root", "password3")).andReturn(
client3).atLeastOnce();
expect(factory.create(new IPSocket("144.175.1.4", 22), "root", "password4")).andReturn(
client4).atLeastOnce();
expect(
factory.create(new IPSocket("144.175.1.2", 22), "root",
"password2")).andReturn(client2).atLeastOnce();
expect(
factory.create(new IPSocket("144.175.1.3", 22), "root",
"password3")).andReturn(client3).atLeastOnce();
expect(
factory.create(new IPSocket("144.175.1.4", 22), "root",
"password4")).andReturn(client4).atLeastOnce();
runScriptAndInstallSsh(client2, "runscript", 2);
runScriptAndInstallSsh(client3, "runscript", 3);
@ -189,14 +204,17 @@ public class StubComputeServiceIntegrationTest extends BaseComputeServiceLiveTes
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();
runScript(client, scriptName, nodeId);
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("chmod 600 .ssh/authorized_keys")).andReturn(EXEC_GOOD);
expect(client.exec("cat .ssh/id_rsa.pub >> .ssh/authorized_keys"))
.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")));
expect(client.exec("mkdir .ssh")).andReturn(EXEC_GOOD);
@ -212,16 +230,24 @@ public class StubComputeServiceIntegrationTest extends BaseComputeServiceLiveTes
client.put(eq("" + scriptName + ""), isEq(initScript(scriptName,
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.getHostAddress()).andReturn(nodeId + "").atLeastOnce();
expect(client.exec("./" + scriptName + " init")).andReturn(EXEC_GOOD);
expect(client.exec("./" + scriptName + " start")).andReturn(EXEC_GOOD);
expect(client.exec("./" + scriptName + " status")).andReturn(EXEC_GOOD);
expect(client.getHostAddress()).andReturn(nodeId + "")
.atLeastOnce();
expect(client.exec("./" + scriptName + " init")).andReturn(
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.
expect(client.exec("./" + scriptName + " status")).andReturn(EXEC_BAD);
expect(client.exec("./" + scriptName + " tail")).andReturn(EXEC_GOOD);
expect(client.exec("./" + scriptName + " tailerr")).andReturn(EXEC_GOOD);
expect(client.exec("./" + scriptName + " status")).andReturn(
EXEC_BAD);
expect(client.exec("./" + scriptName + " tail")).andReturn(
EXEC_GOOD);
expect(client.exec("./" + scriptName + " tailerr")).andReturn(
EXEC_GOOD);
}
};
@ -233,9 +259,14 @@ public class StubComputeServiceIntegrationTest extends BaseComputeServiceLiveTes
password = "stub";
}
protected void assertNodeZero(Set<? extends NodeMetadata> metadataSet) {
// TODO: this fails so we override it.
}
public static String initScript(String scriptName, String script) {
return new InitBuilder(scriptName, "/tmp/" + scriptName, "/tmp/" + scriptName, ImmutableMap
.<String, String> of(), Iterables.toArray(Splitter.on("\n").split(
return new InitBuilder(scriptName, "/tmp/" + scriptName, "/tmp/"
+ scriptName, ImmutableMap.<String, String> of(), Iterables
.toArray(Splitter.on("\n").split(
new String(checkNotNull(script, "script"))), String.class))
.build(org.jclouds.scriptbuilder.domain.OsFamily.UNIX);
}
@ -248,10 +279,12 @@ public class StubComputeServiceIntegrationTest extends BaseComputeServiceLiveTes
public void testAssignability() throws Exception {
@SuppressWarnings("unused")
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;
@ -297,8 +330,8 @@ public class StubComputeServiceIntegrationTest extends BaseComputeServiceLiveTes
if (o == null || !this.getClass().equals(o.getClass()))
return false;
InputStreamEquals other = (InputStreamEquals) o;
return this.expected == null && other.expected == null || this.expected != null
&& this.expected.equals(other.expected);
return this.expected == null && other.expected == null
|| this.expected != null && this.expected.equals(other.expected);
}
@Override
@ -310,8 +343,8 @@ public class StubComputeServiceIntegrationTest extends BaseComputeServiceLiveTes
@Override
protected void setupKeyPair() throws FileNotFoundException, IOException {
keyPair = ImmutableMap.<String, String> of("public", "ssh-rsa", "private",
"-----BEGIN RSA PRIVATE KEY-----");
keyPair = ImmutableMap.<String, String> of("public", "ssh-rsa",
"private", "-----BEGIN RSA PRIVATE KEY-----");
}
}

View File

@ -4,6 +4,7 @@ import java.util.Set;
import org.jclouds.compute.util.ComputeUtils;
import org.testng.annotations.Test;
/**
* Test the compute utils.
*
@ -17,10 +18,11 @@ public class ComputeUtilsTest {
* Test some of the currently supported clouds against compute.properties.
*/
@Test
public void testSupportedProviders(){
public void testSupportedProviders() {
Set<String> providers = ComputeUtils.getSupportedProviders();
assert providers.contains("rimuhosting");
assert providers.contains("cloudservers");
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.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.installPrivateKey;
import static org.testng.Assert.assertEquals;
@ -149,4 +150,33 @@ public class TemplateOptionsTest {
assertEquals(options.getInboundPorts()[0], 22);
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
*/
public class RetryablePredicate<T> implements Predicate<T> {
private final int maxWait;
private final int checkInterval;
private final long maxWait;
private final long period;
private final Predicate<T> predicate;
@Resource
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.maxWait = (int) unit.toMillis(maxWait);
this.checkInterval = (int) unit.toMillis(checkInterval);
this.maxWait = unit.toMillis(maxWait);
this.period = unit.toMillis(period);
}
public RetryablePredicate(Predicate<T> predicate, long maxWait) {
this.predicate = predicate;
this.maxWait = maxWait;
this.period = 50l;
}
@Override
public boolean apply(T input) {
try {
long i = 1l;
for (Date end = new Date(System.currentTimeMillis() + maxWait); before(end); Thread
.sleep(checkInterval)) {
.sleep(nextMaxInterval(i++, end))) {
if (predicate.apply(input)) {
return true;
} else if (atOrAfter(end)) {
@ -59,11 +67,18 @@ public class RetryablePredicate<T> implements Predicate<T> {
}
}
} 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;
}
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) {
return new Date().compareTo(end) <= 1;
}

View File

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

View File

@ -22,7 +22,6 @@ import static com.google.common.base.Preconditions.checkNotNull;
import java.security.SecureRandom;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import javax.inject.Inject;
import javax.inject.Singleton;
@ -30,6 +29,7 @@ import javax.inject.Singleton;
import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.domain.Size;
import org.jclouds.compute.domain.Template;
import org.jclouds.compute.reference.ComputeServiceConstants.Timeouts;
import org.jclouds.compute.strategy.AddNodeWithTagStrategy;
import org.jclouds.gogrid.GoGridClient;
import org.jclouds.gogrid.domain.Ip;
@ -57,14 +57,17 @@ public class GoGridAddNodeWithTagStrategy implements AddNodeWithTagStrategy {
@Inject
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.serverToNodeMetadata = serverToNodeMetadata;
this.sizeToRam = sizeToRam;
this.serverLatestJobCompleted = new RetryablePredicate<Server>(new ServerLatestJobCompleted(
client.getJobServices()), 800, 20, TimeUnit.SECONDS);
this.serverLatestJobCompleted = new RetryablePredicate<Server>(
new ServerLatestJobCompleted(client.getJobServices()),
timeouts.nodeRunning * 9l / 10l);
this.serverLatestJobCompletedShort = new RetryablePredicate<Server>(
new ServerLatestJobCompleted(client.getJobServices()), 60, 20, TimeUnit.SECONDS);
new ServerLatestJobCompleted(client.getJobServices()),
timeouts.nodeRunning * 1l / 10l);
}
@Override
@ -73,12 +76,15 @@ public class GoGridAddNodeWithTagStrategy implements AddNodeWithTagStrategy {
boolean notStarted = true;
int numOfRetries = 20;
// 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
Set<Ip> availableIps = client.getIpServices().getIpList(
new GetIpListOptions().onlyUnassigned().onlyWithType(IpType.PUBLIC));
new GetIpListOptions().onlyUnassigned().onlyWithType(
IpType.PUBLIC));
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());
Ip availableIp = Iterables.get(availableIps, ipIndex);
try {
@ -90,13 +96,14 @@ public class GoGridAddNodeWithTagStrategy implements AddNodeWithTagStrategy {
notStarted = true;
}
}
if (template.getOptions().shouldBlockUntilRunning()) {
serverLatestJobCompleted.apply(addedServer);
client.getServerServices().power(addedServer.getName(), PowerCommand.START);
client.getServerServices().power(addedServer.getName(),
PowerCommand.START);
serverLatestJobCompletedShort.apply(addedServer);
addedServer = Iterables.getOnlyElement(client.getServerServices().getServersByName(
addedServer.getName()));
addedServer = Iterables.getOnlyElement(client.getServerServices()
.getServersByName(addedServer.getName()));
}
return serverToNodeMetadata.apply(addedServer);
}

View File

@ -60,13 +60,9 @@ import org.jclouds.http.RequiresHttp;
import org.jclouds.http.annotation.ClientError;
import org.jclouds.http.annotation.Redirection;
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.config.RestClientModule;
import com.google.common.base.Predicate;
import com.google.common.base.Supplier;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Maps;
@ -80,7 +76,8 @@ import com.google.inject.Provides;
*/
@RequiresHttp
@ConfiguresRestClient
public class GoGridRestClientModule extends RestClientModule<GoGridClient, GoGridAsyncClient> {
public class GoGridRestClientModule extends
RestClientModule<GoGridClient, GoGridAsyncClient> {
public static final Map<Class<?>, Class<?>> DELEGATE_MAP = ImmutableMap
.<Class<?>, Class<?>> builder()//
.put(GridServerClient.class, GridServerAsyncClient.class)//
@ -97,7 +94,8 @@ public class GoGridRestClientModule extends RestClientModule<GoGridClient, GoGri
@Provides
@Singleton
@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);
}
@ -107,28 +105,28 @@ public class GoGridRestClientModule extends RestClientModule<GoGridClient, GoGri
return cache.get();
}
@Provides
@Singleton
protected Predicate<IPSocket> socketTester(SocketOpen open) {
return new RetryablePredicate<IPSocket>(open, 130, 1, TimeUnit.SECONDS);
}
@SuppressWarnings("unchecked")
@Provides
@Singleton
@com.google.inject.name.Named(Constants.PROPERTY_GSON_ADAPTERS)
public Map<Class, Object> provideCustomAdapterBindings() {
Map<Class, Object> bindings = Maps.newHashMap();
bindings.put(ObjectType.class, new CustomDeserializers.ObjectTypeAdapter());
bindings.put(LoadBalancerOs.class, new CustomDeserializers.LoadBalancerOsAdapter());
bindings.put(LoadBalancerState.class, new CustomDeserializers.LoadBalancerStateAdapter());
bindings.put(ObjectType.class,
new CustomDeserializers.ObjectTypeAdapter());
bindings.put(LoadBalancerOs.class,
new CustomDeserializers.LoadBalancerOsAdapter());
bindings.put(LoadBalancerState.class,
new CustomDeserializers.LoadBalancerStateAdapter());
bindings.put(LoadBalancerPersistenceType.class,
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(JobState.class, new CustomDeserializers.JobStateAdapter());
bindings.put(ServerImageState.class, new CustomDeserializers.ServerImageStateAdapter());
bindings.put(ServerImageType.class, new CustomDeserializers.ServerImageTypeAdapter());
bindings.put(ServerImageState.class,
new CustomDeserializers.ServerImageStateAdapter());
bindings.put(ServerImageType.class,
new CustomDeserializers.ServerImageTypeAdapter());
return bindings;
}
@ -137,7 +135,8 @@ public class GoGridRestClientModule extends RestClientModule<GoGridClient, GoGri
*/
@Provides
@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>() {
public Long get() {
return System.currentTimeMillis() / 1000;
@ -147,9 +146,12 @@ public class GoGridRestClientModule extends RestClientModule<GoGridClient, GoGri
@Override
protected void bindErrorHandlers() {
bind(HttpErrorHandler.class).annotatedWith(Redirection.class).to(GoGridErrorHandler.class);
bind(HttpErrorHandler.class).annotatedWith(ClientError.class).to(GoGridErrorHandler.class);
bind(HttpErrorHandler.class).annotatedWith(ServerError.class).to(GoGridErrorHandler.class);
bind(HttpErrorHandler.class).annotatedWith(Redirection.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.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);
Map<String, Credentials> credentialsMap = createMock(Map.class);

View File

@ -27,7 +27,6 @@ import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.TimeUnit;
import javax.annotation.Resource;
import javax.inject.Inject;
@ -37,6 +36,7 @@ import javax.inject.Singleton;
import org.jclouds.Constants;
import org.jclouds.compute.ComputeServiceContext;
import org.jclouds.compute.LoadBalancerService;
import org.jclouds.compute.config.ComputeServiceTimeoutsModule;
import org.jclouds.compute.domain.Architecture;
import org.jclouds.compute.domain.ComputeMetadata;
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.internal.ComputeServiceContextImpl;
import org.jclouds.compute.predicates.NodePredicates;
import org.jclouds.compute.predicates.ScriptStatusReturnsZero;
import org.jclouds.compute.predicates.ScriptStatusReturnsZero.CommandUsingClient;
import org.jclouds.compute.reference.ComputeServiceConstants;
import org.jclouds.compute.strategy.AddNodeWithTagStrategy;
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.reference.IBMDeveloperCloudConstants;
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.Predicate;
import com.google.common.base.Predicates;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Iterables;
import com.google.common.collect.Maps;
@ -91,7 +85,8 @@ import com.google.inject.util.Providers;
/**
* @author Adrian Cole
*/
public class IBMDeveloperCloudComputeServiceContextModule extends IBMDeveloperCloudContextModule {
public class IBMDeveloperCloudComputeServiceContextModule extends
IBMDeveloperCloudContextModule {
private final String providerName;
@ -103,6 +98,7 @@ public class IBMDeveloperCloudComputeServiceContextModule extends IBMDeveloperCl
@Override
protected void configure() {
super.configure();
install(new ComputeServiceTimeoutsModule());
bind(new TypeLiteral<Function<Instance, NodeMetadata>>() {
}).to(InstanceToNodeMetadata.class);
bind(new TypeLiteral<ComputeServiceContext>() {
@ -110,18 +106,18 @@ public class IBMDeveloperCloudComputeServiceContextModule extends IBMDeveloperCl
.to(
new TypeLiteral<ComputeServiceContextImpl<IBMDeveloperCloudClient, IBMDeveloperCloudAsyncClient>>() {
}).in(Scopes.SINGLETON);
bind(AddNodeWithTagStrategy.class).to(IBMDeveloperCloudAddNodeWithTagStrategy.class);
bind(ListNodesStrategy.class).to(IBMDeveloperCloudListNodesStrategy.class);
bind(GetNodeMetadataStrategy.class).to(IBMDeveloperCloudGetNodeMetadataStrategy.class);
bind(RebootNodeStrategy.class).to(IBMDeveloperCloudRebootNodeStrategy.class);
bind(DestroyNodeStrategy.class).to(IBMDeveloperCloudDestroyNodeStrategy.class);
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);
bind(AddNodeWithTagStrategy.class).to(
IBMDeveloperCloudAddNodeWithTagStrategy.class);
bind(ListNodesStrategy.class)
.to(IBMDeveloperCloudListNodesStrategy.class);
bind(GetNodeMetadataStrategy.class).to(
IBMDeveloperCloudGetNodeMetadataStrategy.class);
bind(RebootNodeStrategy.class).to(
IBMDeveloperCloudRebootNodeStrategy.class);
bind(DestroyNodeStrategy.class).to(
IBMDeveloperCloudDestroyNodeStrategy.class);
bind(LoadBalancerService.class).toProvider(
Providers.<LoadBalancerService> of(null));
}
/**
@ -155,19 +151,23 @@ public class IBMDeveloperCloudComputeServiceContextModule extends IBMDeveloperCl
@Inject
protected CreateKeyPairEncodeTagIntoNameRunNodesAndAddToSet(
AddNodeWithTagStrategy addNodeWithTagStrategy, ListNodesStrategy listNodesStrategy,
@Named("NAMING_CONVENTION") String nodeNamingConvention, ComputeUtils utils,
AddNodeWithTagStrategy addNodeWithTagStrategy,
ListNodesStrategy listNodesStrategy,
@Named("NAMING_CONVENTION") String nodeNamingConvention,
ComputeUtils utils,
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService executor,
IBMDeveloperCloudClient client,
@Named("CREDENTIALS") Map<String, String> credentialsMap) {
super(addNodeWithTagStrategy, listNodesStrategy, nodeNamingConvention, utils, executor);
super(addNodeWithTagStrategy, listNodesStrategy, nodeNamingConvention,
utils, executor);
this.client = checkNotNull(client, "client");
this.credentialsMap = checkNotNull(credentialsMap, "credentialsMap");
}
@Override
public Map<?, ListenableFuture<Void>> execute(String tag, int count, Template template,
Set<NodeMetadata> nodes, Map<NodeMetadata, Exception> badNodes) {
public Map<?, ListenableFuture<Void>> execute(String tag, int count,
Template template, Set<NodeMetadata> nodes,
Map<NodeMetadata, Exception> badNodes) {
String key = template.getOptions().getPublicKey();
if (key != null) {
template.getOptions().dontAuthorizePublicKey();
@ -178,7 +178,8 @@ public class IBMDeveloperCloudComputeServiceContextModule extends IBMDeveloperCl
client.updatePublicKey(tag, key);
}
} else {
credentialsMap.put(tag, client.generateKeyPair(tag).getKeyMaterial());
credentialsMap.put(tag, client.generateKeyPair(tag)
.getKeyMaterial());
}
return super.execute(tag, count, template, nodes, badNodes);
}
@ -186,57 +187,58 @@ public class IBMDeveloperCloudComputeServiceContextModule extends IBMDeveloperCl
}
@Singleton
public static class IBMDeveloperCloudAddNodeWithTagStrategy implements AddNodeWithTagStrategy {
public static class IBMDeveloperCloudAddNodeWithTagStrategy implements
AddNodeWithTagStrategy {
private final IBMDeveloperCloudClient client;
private final Predicate<Instance> instanceActive;
private final Function<Instance, NodeMetadata> instanceToNodeMetadata;
@Inject
protected IBMDeveloperCloudAddNodeWithTagStrategy(IBMDeveloperCloudClient client,
@Named("ACTIVE") Predicate<Instance> instanceActive,
protected IBMDeveloperCloudAddNodeWithTagStrategy(
IBMDeveloperCloudClient client,
Function<Instance, NodeMetadata> instanceToNodeMetadata) {
this.client = checkNotNull(client, "client");
this.instanceActive = checkNotNull(instanceActive, "instanceActive");
this.instanceToNodeMetadata = checkNotNull(instanceToNodeMetadata,
"instanceToNodeMetadata");
}
@Override
public NodeMetadata execute(String tag, String name, Template template) {
Instance instance = client.createInstanceInLocation(template.getLocation().getId(), name,
template.getImage().getProviderId(), template.getSize().getProviderId(),
Instance instance = client.createInstanceInLocation(template
.getLocation().getId(), name, template.getImage()
.getProviderId(), template.getSize().getProviderId(),
authorizePublicKey(tag));
instanceActive.apply(instance);
return instanceToNodeMetadata.apply(client.getInstance(instance.getId()));
return instanceToNodeMetadata.apply(client.getInstance(instance
.getId()));
}
}
@Singleton
public static class IBMDeveloperCloudRebootNodeStrategy implements RebootNodeStrategy {
public static class IBMDeveloperCloudRebootNodeStrategy implements
RebootNodeStrategy {
private final IBMDeveloperCloudClient client;
private final Predicate<Instance> instanceActive;
private final GetNodeMetadataStrategy getNode;
@Inject
protected IBMDeveloperCloudRebootNodeStrategy(IBMDeveloperCloudClient client,
@Named("ACTIVE") Predicate<Instance> instanceActive) {
protected IBMDeveloperCloudRebootNodeStrategy(
IBMDeveloperCloudClient client, GetNodeMetadataStrategy getNode) {
this.client = checkNotNull(client, "client");
this.instanceActive = checkNotNull(instanceActive, "instanceActive");
this.getNode = checkNotNull(getNode, "getNode");
}
@Override
public boolean execute(String id) {
public NodeMetadata execute(String id) {
client.restartInstance(id);
return instanceActive.apply(client.getInstance(id));
return getNode.execute(id);
}
}
@Singleton
@Provides
Map<Instance.Status, NodeState> provideServerToNodeState() {
return ImmutableMap.<Instance.Status, NodeState> builder().put(Instance.Status.ACTIVE,
NodeState.RUNNING)//
return ImmutableMap.<Instance.Status, NodeState> builder().put(
Instance.Status.ACTIVE, NodeState.RUNNING)//
.put(Instance.Status.STOPPED, NodeState.SUSPENDED)//
.put(Instance.Status.REMOVED, NodeState.TERMINATED)//
.put(Instance.Status.DEPROVISIONING, NodeState.PENDING)//
@ -251,12 +253,14 @@ public class IBMDeveloperCloudComputeServiceContextModule extends IBMDeveloperCl
}
@Singleton
public static class IBMDeveloperCloudListNodesStrategy implements ListNodesStrategy {
public static class IBMDeveloperCloudListNodesStrategy implements
ListNodesStrategy {
private final IBMDeveloperCloudClient client;
private final Function<Instance, NodeMetadata> instanceToNodeMetadata;
@Inject
protected IBMDeveloperCloudListNodesStrategy(IBMDeveloperCloudClient client,
protected IBMDeveloperCloudListNodesStrategy(
IBMDeveloperCloudClient client,
Function<Instance, NodeMetadata> instanceToNodeMetadata) {
this.client = client;
this.instanceToNodeMetadata = instanceToNodeMetadata;
@ -270,18 +274,20 @@ public class IBMDeveloperCloudComputeServiceContextModule extends IBMDeveloperCl
@Override
public Iterable<? extends NodeMetadata> listDetailsOnNodesMatching(
Predicate<ComputeMetadata> filter) {
return Iterables.filter(Iterables
.transform(client.listInstances(), instanceToNodeMetadata), filter);
return Iterables.filter(Iterables.transform(client.listInstances(),
instanceToNodeMetadata), filter);
}
}
@Singleton
public static class IBMDeveloperCloudGetNodeMetadataStrategy implements GetNodeMetadataStrategy {
public static class IBMDeveloperCloudGetNodeMetadataStrategy implements
GetNodeMetadataStrategy {
private final IBMDeveloperCloudClient client;
private final Function<Instance, NodeMetadata> instanceToNodeMetadata;
@Inject
protected IBMDeveloperCloudGetNodeMetadataStrategy(IBMDeveloperCloudClient client,
protected IBMDeveloperCloudGetNodeMetadataStrategy(
IBMDeveloperCloudClient client,
Function<Instance, NodeMetadata> instanceToNodeMetadata) {
this.client = client;
this.instanceToNodeMetadata = instanceToNodeMetadata;
@ -290,37 +296,31 @@ public class IBMDeveloperCloudComputeServiceContextModule extends IBMDeveloperCl
@Override
public NodeMetadata execute(String id) {
Instance instance = client.getInstance(checkNotNull(id, "id"));
return instance == null ? null : instanceToNodeMetadata.apply(instance);
return instance == null ? null : instanceToNodeMetadata
.apply(instance);
}
}
@Singleton
public static class IBMDeveloperCloudDestroyNodeStrategy implements DestroyNodeStrategy {
public static class IBMDeveloperCloudDestroyNodeStrategy implements
DestroyNodeStrategy {
private final IBMDeveloperCloudClient client;
private final Predicate<Instance> instanceRemoved;
private final GetNodeMetadataStrategy getNode;
@Inject
protected IBMDeveloperCloudDestroyNodeStrategy(IBMDeveloperCloudClient client,
@Named("REMOVED") Predicate<Instance> instanceRemoved) {
protected IBMDeveloperCloudDestroyNodeStrategy(
IBMDeveloperCloudClient client, GetNodeMetadataStrategy getNode) {
this.client = checkNotNull(client, "client");
this.instanceRemoved = checkNotNull(instanceRemoved, "instanceRemoved");
this.getNode = checkNotNull(getNode, "getNode");
}
@Override
public boolean execute(String id) {
public NodeMetadata execute(String 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
@Singleton
Location getDefaultLocation(
@ -338,14 +338,16 @@ public class IBMDeveloperCloudComputeServiceContextModule extends IBMDeveloperCl
@Provides
@Singleton
Set<? extends Location> getAssignableLocations(IBMDeveloperCloudClient sync, LogHolder holder) {
Set<? extends Location> getAssignableLocations(IBMDeveloperCloudClient sync,
LogHolder holder) {
final Set<Location> assignableLocations = Sets.newHashSet();
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())
assignableLocations.add(new LocationImpl(LocationScope.ZONE, location.getId(), location
.getName(), parent));
assignableLocations.add(new LocationImpl(LocationScope.ZONE, location
.getId(), location.getName(), parent));
holder.logger.debug("<< locations(%d)", assignableLocations.size());
return assignableLocations;
@ -353,36 +355,40 @@ public class IBMDeveloperCloudComputeServiceContextModule extends IBMDeveloperCl
@Provides
@Singleton
protected Set<? extends Size> provideSizes(IBMDeveloperCloudClient sync, LogHolder holder,
Map<String, ? extends Location> locations) {
protected Set<? extends Size> provideSizes(IBMDeveloperCloudClient sync,
LogHolder holder, Map<String, ? extends Location> locations) {
final Set<Size> sizes = Sets.newHashSet();
holder.logger.debug(">> providing sizes");
for (org.jclouds.ibmdev.domain.Location location : sync.listLocations()) {
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;
for (String i386 : location.getCapabilities().get(
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(
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());
return sizes;
}
private SizeImpl buildSize(org.jclouds.ibmdev.domain.Location location, final String id,
Location assignedLocation, int multiplier) {
return new SizeImpl(id, id, location.getId() + "/" + id, assignedLocation, null, ImmutableMap
.<String, String> of(), multiplier, multiplier * 1024, multiplier * 10,
private SizeImpl buildSize(org.jclouds.ibmdev.domain.Location location,
final String id, Location assignedLocation, int multiplier) {
return new SizeImpl(id, id, location.getId() + "/" + id,
assignedLocation, null, ImmutableMap.<String, String> of(),
multiplier, multiplier * 1024, multiplier * 10,
new Predicate<Image>() {
@Override
public boolean apply(Image input) {
if (input instanceof IBMImage)
return IBMImage.class.cast(input).rawImage.getSupportedInstanceTypes()
.contains(id);
return IBMImage.class.cast(input).rawImage
.getSupportedInstanceTypes().contains(id);
return false;
}
@ -391,7 +397,8 @@ public class IBMDeveloperCloudComputeServiceContextModule extends IBMDeveloperCl
@Provides
@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>() {
@Override
@ -404,7 +411,8 @@ public class IBMDeveloperCloudComputeServiceContextModule extends IBMDeveloperCl
@Provides
@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>() {
@Override
@ -417,8 +425,9 @@ public class IBMDeveloperCloudComputeServiceContextModule extends IBMDeveloperCl
@Provides
@Singleton
protected Set<? extends Image> provideImages(final IBMDeveloperCloudClient sync,
LogHolder holder, Map<String, ? extends Location> locations) {
protected Set<? extends Image> provideImages(
final IBMDeveloperCloudClient sync, LogHolder holder,
Map<String, ? extends Location> locations) {
final Set<Image> images = Sets.newHashSet();
holder.logger.debug(">> providing images");
@ -441,11 +450,13 @@ public class IBMDeveloperCloudComputeServiceContextModule extends IBMDeveloperCl
// TODO manifest fails to parse due to encoding issues in the path
// 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
super(in.getId(), in.getName(), in.getId(), location, null, ImmutableMap
.<String, String> of(), in.getDescription(), in.getCreatedTime().getTime() + "",
(in.getPlatform().indexOf("Redhat") != -1) ? OsFamily.RHEL : OsFamily.SUSE, in
.getPlatform(),
(in.getPlatform().indexOf("32") != -1) ? Architecture.X86_32
super(in.getId(), in.getName(), in.getId(), location, null,
ImmutableMap.<String, String> of(), in.getDescription(), in
.getCreatedTime().getTime()
+ "",
(in.getPlatform().indexOf("Redhat") != -1) ? OsFamily.RHEL
: OsFamily.SUSE, in.getPlatform(), (in.getPlatform()
.indexOf("32") != -1) ? Architecture.X86_32
: Architecture.X86_64, new Credentials("idcuser", null));
this.rawImage = in;
}

View File

@ -20,7 +20,6 @@ package org.jclouds.ibmdev.config;
import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.util.concurrent.TimeUnit;
import javax.inject.Named;
import javax.inject.Singleton;
@ -35,16 +34,11 @@ import org.jclouds.http.filters.BasicAuthentication;
import org.jclouds.ibmdev.IBMDeveloperCloud;
import org.jclouds.ibmdev.IBMDeveloperCloudAsyncClient;
import org.jclouds.ibmdev.IBMDeveloperCloudClient;
import org.jclouds.ibmdev.domain.Instance;
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.predicates.RetryablePredicate;
import org.jclouds.rest.ConfiguresRestClient;
import org.jclouds.rest.config.RestClientModule;
import com.google.common.base.Predicate;
import com.google.inject.Provides;
/**
@ -61,13 +55,13 @@ public class IBMDeveloperCloudRestClientModule extends
super(IBMDeveloperCloudClient.class, IBMDeveloperCloudAsyncClient.class);
}
@Provides
@Singleton
public BasicAuthentication provideBasicAuthentication(
@Named(IBMDeveloperCloudConstants.PROPERTY_IBMDEVELOPERCLOUD_USER) String user,
@Named(IBMDeveloperCloudConstants.PROPERTY_IBMDEVELOPERCLOUD_PASSWORD) String password,
EncryptionService encryptionService) throws UnsupportedEncodingException {
EncryptionService encryptionService)
throws UnsupportedEncodingException {
return new BasicAuthentication(user, password, encryptionService);
}
@ -94,18 +88,4 @@ public class IBMDeveloperCloudRestClientModule extends
install(new IBMDeveloperCloudParserModule());
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) {
logger.trace("looking for state on instance %s", instance);
instance = client.getInstance(instance.getId());
if (instance == null || instance.getStatus() == Instance.Status.FAILED)
if (instance == null)
return false;
logger.trace("%s: looking for instance state %s: currently: %s", instance.getId(),
Instance.Status.ACTIVE, instance.getStatus());
logger.trace("%s: looking for instance state %s: currently: %s", instance
.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;
}
}

View File

@ -70,8 +70,8 @@ import com.google.common.io.Files;
@Test(groups = "live", testName = "ibmdevelopercloud.IBMDeveloperCloudClientLiveTest")
public class IBMDeveloperCloudClientLiveTest {
private static final ImmutableSet<Software> SOFTWARE = ImmutableSet.<Software> of(new Software(
"SUSE Linux Enterprise", "OS", "10 SP2"));
private static final ImmutableSet<Software> SOFTWARE = ImmutableSet
.<Software> of(new Software("SUSE Linux Enterprise", "OS", "10 SP2"));
private static final String SIZE = "LARGE";
private IBMDeveloperCloudClient connection;
private Location location;
@ -87,11 +87,14 @@ public class IBMDeveloperCloudClientLiveTest {
@BeforeGroups(groups = { "live" })
public void setupClient() {
user = checkNotNull(System.getProperty("jclouds.test.user"), "jclouds.test.user");
String password = checkNotNull(System.getProperty("jclouds.test.key"), "jclouds.test.key");
user = checkNotNull(System.getProperty("jclouds.test.user"),
"jclouds.test.user");
String password = checkNotNull(System.getProperty("jclouds.test.key"),
"jclouds.test.key");
connection = (IBMDeveloperCloudClient) IBMDeveloperCloudContextFactory.createContext(user,
password, new Log4JLoggingModule()).getProviderSpecificContext().getApi();
connection = (IBMDeveloperCloudClient) IBMDeveloperCloudContextFactory
.createContext(user, password, new Log4JLoggingModule())
.getProviderSpecificContext().getApi();
}
@Test
@ -118,7 +121,8 @@ public class IBMDeveloperCloudClientLiveTest {
@Test
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);
}
@ -128,7 +132,8 @@ public class IBMDeveloperCloudClientLiveTest {
assertNotNull(response);
if (response.size() > 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);
if (response.size() > 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);
if (response.size() > 0) {
location = Iterables.get(response, 0);
assertEquals(connection.getLocation(location.getId()).getId(), location.getId());
assertEquals(connection.getLocation(location.getId()).getId(),
location.getId());
}
}
@ -207,8 +214,9 @@ public class IBMDeveloperCloudClientLiveTest {
if (instance.getStatus() == Instance.Status.FAILED
|| instance.getStatus() == Instance.Status.ACTIVE) {
connection.deleteInstance(instanceId);
assert new RetryablePredicate<Instance>(new InstanceRemovedOrNotFound(connection),
30, 2, TimeUnit.SECONDS).apply(instance) : instance;
assert new RetryablePredicate<Instance>(
new InstanceRemovedOrNotFound(connection), 30, 2,
TimeUnit.SECONDS).apply(instance) : instance;
}
}
}
@ -221,15 +229,18 @@ public class IBMDeveloperCloudClientLiveTest {
public void testAllocateIpAddress() throws Exception {
try {
ip = connection.allocateAddressInLocation(location.getId());
System.out.println(ip);
assertEquals(ip.getIp(), null);
// wait up to 30 seconds for this to become "free"
new RetryablePredicate<Address>(new AddressFree(connection), 30, 2, TimeUnit.SECONDS)
.apply(ip);
new RetryablePredicate<Address>(new AddressFree(connection), 30, 2,
TimeUnit.SECONDS).apply(ip);
refreshIpAndReturnAllAddresses();
assertEquals(ip.getInstanceId(), null);
} catch (IllegalStateException e) {
if (HttpResponseException.class.cast(e.getCause()).getResponse().getStatusCode() == 409) {
ip = Iterables.find(connection.listAddresses(), new Predicate<Address>() {
if (HttpResponseException.class.cast(e.getCause()).getResponse()
.getStatusCode() == 409) {
ip = Iterables.find(connection.listAddresses(),
new Predicate<Address>() {
@Override
public boolean apply(Address input) {
@ -246,18 +257,21 @@ public class IBMDeveloperCloudClientLiveTest {
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")
public void testCreateVolume() throws Exception {
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"
assert new RetryablePredicate<Volume>(new VolumeUnmounted(connection), 300, 5,
TimeUnit.SECONDS).apply(volume);
assert new RetryablePredicate<Volume>(new VolumeUnmounted(connection),
300, 5, TimeUnit.SECONDS).apply(volume);
} 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();
try {
volume = Iterables.find(volumes, new Predicate<Volume>() {
@ -269,7 +283,8 @@ public class IBMDeveloperCloudClientLiveTest {
});
} catch (NoSuchElementException ex) {
throw new RuntimeException("no unmounted volumes in: " + volumes, e);
throw new RuntimeException(
"no unmounted volumes in: " + volumes, e);
}
} else {
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
@Test(dependsOnMethods = "testAddPublicKey")
@Test(dependsOnMethods = { "testAddPublicKey", "testAllocateIpAddress" })
public void testCreateInstance() throws Exception {
instance = connection.createInstanceInLocation(location.getId(), TAG, IMAGE_ID, SIZE,
configurationData(
for (Instance instance : connection.listInstances()) {
try {
connection.deleteInstance(instance.getId());
} catch (Exception e) {
}
}
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()));
"db2_admin_password", "myPassword2",
"report_user_password", "myPassword3"))
.authorizePublicKey(key.getName()).attachIp(ip.getId()));
try {
assertIpHostAndStatusNEW(instance);
assertConsistent(instance, TAG);
@ -315,10 +341,12 @@ public class IBMDeveloperCloudClientLiveTest {
}
long start = System.currentTimeMillis();
assert new RetryablePredicate<Instance>(new InstanceActive(connection), 600, 2,
TimeUnit.SECONDS).apply(instance) : connection.getInstance(instance.getId());
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");
System.out.println(((System.currentTimeMillis() - start) / 1000)
+ " seconds");
try {
assertIpHostAndStatusACTIVE(instance);
@ -364,17 +392,20 @@ public class IBMDeveloperCloudClientLiveTest {
/**
* 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
*/
@Test(enabled = false, dependsOnMethods = { "testAddPublicKey", "testAllocateIpAddress",
"testCreateVolume" })
@Test(enabled = false, dependsOnMethods = { "testAddPublicKey",
"testAllocateIpAddress", "testCreateVolume" })
public void testCreateInstanceWithVolume() throws Exception {
instance2 = connection.createInstanceInLocation(location.getId(), TAG, IMAGE_ID, SIZE,
attachIp(ip.getId()).authorizePublicKey(key.getName()).mountVolume(volume.getId(),
"/mnt").configurationData(
ImmutableMap.of("insight_admin_password", "myPassword1",
"db2_admin_password", "myPassword2", "report_user_password",
instance2 = connection.createInstanceInLocation(location.getId(), TAG,
IMAGE_ID, SIZE, attachIp(ip.getId()).authorizePublicKey(
key.getName()).mountVolume(volume.getId(), "/mnt")
.configurationData(
ImmutableMap.of("insight_admin_password",
"myPassword1", "db2_admin_password",
"myPassword2", "report_user_password",
"myPassword3")));
//
@ -410,12 +441,14 @@ public class IBMDeveloperCloudClientLiveTest {
} 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)
try {
connection.deleteKey(key.getName());
@ -440,14 +473,16 @@ public class IBMDeveloperCloudClientLiveTest {
protected void setupKeyPair() throws FileNotFoundException, IOException {
String secretKeyFile;
try {
secretKeyFile = checkNotNull(System.getProperty("jclouds.test.ssh.keyfile"),
secretKeyFile = checkNotNull(System
.getProperty("jclouds.test.ssh.keyfile"),
"jclouds.test.ssh.keyfile");
} catch (NullPointerException e) {
secretKeyFile = System.getProperty("user.home") + "/.ssh/id_rsa";
}
String secret = Files.toString(new File(secretKeyFile), Charsets.UTF_8);
assert secret.startsWith("-----BEGIN RSA PRIVATE KEY-----") : "invalid key:\n" + secret;
keyPair = ImmutableMap.<String, String> of("private", secret, "public", Files.toString(
new File(secretKeyFile + ".pub"), Charsets.UTF_8));
assert secret.startsWith("-----BEGIN RSA PRIVATE KEY-----") : "invalid key:\n"
+ secret;
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.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@ -38,6 +37,7 @@ import javax.inject.Singleton;
import org.jclouds.Constants;
import org.jclouds.compute.ComputeServiceContext;
import org.jclouds.compute.LoadBalancerService;
import org.jclouds.compute.config.ComputeServiceTimeoutsModule;
import org.jclouds.compute.domain.Architecture;
import org.jclouds.compute.domain.ComputeMetadata;
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.predicates.ImagePredicates;
import org.jclouds.compute.predicates.NodePredicates;
import org.jclouds.compute.predicates.ScriptStatusReturnsZero;
import org.jclouds.compute.predicates.ScriptStatusReturnsZero.CommandUsingClient;
import org.jclouds.compute.reference.ComputeServiceConstants;
import org.jclouds.compute.strategy.AddNodeWithTagStrategy;
import org.jclouds.compute.strategy.DestroyNodeStrategy;
@ -67,7 +65,6 @@ import org.jclouds.domain.Location;
import org.jclouds.domain.LocationScope;
import org.jclouds.domain.internal.LocationImpl;
import org.jclouds.logging.Logger;
import org.jclouds.predicates.RetryablePredicate;
import org.jclouds.rackspace.cloudservers.CloudServersAsyncClient;
import org.jclouds.rackspace.cloudservers.CloudServersClient;
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.Predicate;
import com.google.common.base.Predicates;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Iterables;
import com.google.common.collect.Sets;
@ -92,12 +88,13 @@ import com.google.inject.TypeLiteral;
import com.google.inject.util.Providers;
/**
* Configures the {@link CloudServersComputeServiceContext}; requires {@link BaseComputeService}
* bound.
* Configures the {@link CloudServersComputeServiceContext}; requires
* {@link BaseComputeService} bound.
*
* @author Adrian Cole
*/
public class CloudServersComputeServiceContextModule extends CloudServersContextModule {
public class CloudServersComputeServiceContextModule extends
CloudServersContextModule {
private final String providerName;
public CloudServersComputeServiceContextModule(String providerName) {
@ -107,18 +104,22 @@ public class CloudServersComputeServiceContextModule extends CloudServersContext
@Override
protected void configure() {
super.configure();
install(new ComputeServiceTimeoutsModule());
install(new RackspaceLocationsModule(providerName));
bind(new TypeLiteral<Function<Server, NodeMetadata>>() {
}).to(ServerToNodeMetadata.class);
bind(LoadBalancerService.class).toProvider(Providers.<LoadBalancerService> of(null));
bind(LoadBalancerService.class).toProvider(
Providers.<LoadBalancerService> of(null));
bind(new TypeLiteral<ComputeServiceContext>() {
})
.to(
new TypeLiteral<ComputeServiceContextImpl<CloudServersClient, CloudServersAsyncClient>>() {
}).in(Scopes.SINGLETON);
bind(AddNodeWithTagStrategy.class).to(CloudServersAddNodeWithTagStrategy.class);
bind(AddNodeWithTagStrategy.class).to(
CloudServersAddNodeWithTagStrategy.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(DestroyNodeStrategy.class).to(CloudServersDestroyNodeStrategy.class);
}
@ -132,87 +133,87 @@ public class CloudServersComputeServiceContextModule extends CloudServersContext
@Provides
@Named("NAMING_CONVENTION")
@Singleton
String provideNamingConvention(@Named(RackspaceConstants.PROPERTY_RACKSPACE_USER) String account) {
String provideNamingConvention(
@Named(RackspaceConstants.PROPERTY_RACKSPACE_USER) String account) {
return account + "-%s-%s";
}
@Singleton
public static class CloudServersRebootNodeStrategy implements RebootNodeStrategy {
public static class CloudServersRebootNodeStrategy implements
RebootNodeStrategy {
private final CloudServersClient client;
private final Predicate<Server> serverActive;
private final GetNodeMetadataStrategy getNode;
@Inject
protected CloudServersRebootNodeStrategy(CloudServersClient client,
@Named("ACTIVE") Predicate<Server> serverActive) {
GetNodeMetadataStrategy getNode) {
this.client = client;
this.serverActive = serverActive;
this.getNode = getNode;
}
@Override
public boolean execute(String id) {
public NodeMetadata execute(String id) {
int serverId = Integer.parseInt(id);
// if false server wasn't around in the first place
client.rebootServer(serverId, RebootType.HARD);
Server server = client.getServer(serverId);
return server == null ? false : serverActive.apply(server);
return getNode.execute(id);
}
}
@Singleton
public static class CloudServersDestroyNodeStrategy implements DestroyNodeStrategy {
public static class CloudServersDestroyNodeStrategy implements
DestroyNodeStrategy {
private final CloudServersClient client;
private final Predicate<Server> serverDeleted;
private final GetNodeMetadataStrategy getNode;
@Inject
protected CloudServersDestroyNodeStrategy(CloudServersClient client,
@Named("DELETED") Predicate<Server> serverDeleted) {
GetNodeMetadataStrategy getNode) {
this.client = client;
this.serverDeleted = serverDeleted;
this.getNode = getNode;
}
@Override
public boolean execute(String id) {
public NodeMetadata execute(String id) {
int serverId = Integer.parseInt(id);
// if false server wasn't around in the first place
if (!client.deleteServer(serverId))
return false;
Server server = client.getServer(serverId);
return server == null ? false : serverDeleted.apply(server);
client.deleteServer(serverId);
return getNode.execute(id);
}
}
@Singleton
public static class CloudServersAddNodeWithTagStrategy implements AddNodeWithTagStrategy {
public static class CloudServersAddNodeWithTagStrategy implements
AddNodeWithTagStrategy {
private final CloudServersClient client;
private final Predicate<Server> serverActive;
@Inject
protected CloudServersAddNodeWithTagStrategy(CloudServersClient client,
@Named("ACTIVE") Predicate<Server> serverActive) {
protected CloudServersAddNodeWithTagStrategy(CloudServersClient client) {
this.client = checkNotNull(client, "client");
this.serverActive = checkNotNull(serverActive, "serverActive");
}
@Override
public NodeMetadata execute(String tag, String name, Template template) {
Server server = client.createServer(name, Integer.parseInt(template.getImage()
.getProviderId()), Integer.parseInt(template.getSize().getProviderId()));
serverActive.apply(server);
return new NodeMetadataImpl(server.getId() + "", name, server.getId() + "",
new LocationImpl(LocationScope.HOST, server.getHostId(), server.getHostId(),
template.getLocation()), null, server.getMetadata(), tag, template
.getImage(), NodeState.RUNNING, server.getAddresses()
.getPublicAddresses(), server.getAddresses().getPrivateAddresses(),
ImmutableMap.<String, String> of(),
new Credentials("root", server.getAdminPass()));
Server server = client.createServer(name, Integer.parseInt(template
.getImage().getProviderId()), Integer.parseInt(template
.getSize().getProviderId()));
return new NodeMetadataImpl(server.getId() + "", name, server.getId()
+ "", new LocationImpl(LocationScope.HOST, server.getHostId(),
server.getHostId(), template.getLocation()), null, server
.getMetadata(), tag, template.getImage(), NodeState.PENDING,
server.getAddresses().getPublicAddresses(), server
.getAddresses().getPrivateAddresses(), ImmutableMap
.<String, String> of(), new Credentials("root", server
.getAdminPass()));
}
}
@Singleton
public static class CloudServersListNodesStrategy implements ListNodesStrategy {
public static class CloudServersListNodesStrategy implements
ListNodesStrategy {
private final CloudServersClient client;
private final Function<Server, NodeMetadata> serverToNodeMetadata;
@ -231,13 +232,15 @@ public class CloudServersComputeServiceContextModule extends CloudServersContext
@Override
public Iterable<? extends NodeMetadata> listDetailsOnNodesMatching(
Predicate<ComputeMetadata> filter) {
return Iterables.filter(Iterables.transform(client.listServers(ListOptions.Builder
.withDetails()), serverToNodeMetadata), filter);
return Iterables.filter(Iterables.transform(client
.listServers(ListOptions.Builder.withDetails()),
serverToNodeMetadata), filter);
}
}
@Singleton
public static class CloudServersGetNodeMetadataStrategy implements GetNodeMetadataStrategy {
public static class CloudServersGetNodeMetadataStrategy implements
GetNodeMetadataStrategy {
private final CloudServersClient client;
private final Function<Server, NodeMetadata> serverToNodeMetadata;
@ -260,8 +263,8 @@ public class CloudServersComputeServiceContextModule extends CloudServersContext
@Singleton
@Provides
Map<ServerStatus, NodeState> provideServerToNodeState() {
return ImmutableMap.<ServerStatus, NodeState> builder().put(ServerStatus.ACTIVE,
NodeState.RUNNING)//
return ImmutableMap.<ServerStatus, NodeState> builder().put(
ServerStatus.ACTIVE, NodeState.RUNNING)//
.put(ServerStatus.SUSPENDED, NodeState.SUSPENDED)//
.put(ServerStatus.DELETED, NodeState.TERMINATED)//
.put(ServerStatus.QUEUE_RESIZE, NodeState.PENDING)//
@ -286,14 +289,6 @@ public class CloudServersComputeServiceContextModule extends CloudServersContext
.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
@Singleton
protected Function<ComputeMetadata, String> indexer() {
@ -307,17 +302,19 @@ public class CloudServersComputeServiceContextModule extends CloudServersContext
@Provides
@Singleton
protected Set<? extends Size> provideSizes(CloudServersClient sync, Set<? extends Image> images,
Location location, LogHolder holder,
protected Set<? extends Size> provideSizes(CloudServersClient sync,
Set<? extends Image> images, Location location, LogHolder holder,
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService executor,
Function<ComputeMetadata, String> indexer) throws InterruptedException,
TimeoutException, ExecutionException {
Function<ComputeMetadata, String> indexer)
throws InterruptedException, TimeoutException, ExecutionException {
final Set<Size> sizes = Sets.newHashSet();
holder.logger.debug(">> providing sizes");
for (final Flavor from : sync.listFlavors(ListOptions.Builder.withDetails())) {
sizes.add(new SizeImpl(from.getId() + "", from.getName(), from.getId() + "", location,
null, ImmutableMap.<String, String> of(), from.getDisk() / 10, from.getRam(),
from.getDisk(), ImagePredicates.any()));
for (final Flavor from : sync.listFlavors(ListOptions.Builder
.withDetails())) {
sizes.add(new SizeImpl(from.getId() + "", from.getName(), from.getId()
+ "", location, null, ImmutableMap.<String, String> of(), from
.getDisk() / 10, from.getRam(), from.getDisk(), ImagePredicates
.any()));
}
holder.logger.debug("<< sizes(%d)", sizes.size());
return sizes;
@ -329,12 +326,14 @@ public class CloudServersComputeServiceContextModule extends CloudServersContext
protected Logger logger = Logger.NULL;
}
public static final Pattern RACKSPACE_PATTERN = Pattern.compile("(([^ ]*) .*)");
public static final Pattern RACKSPACE_PATTERN = Pattern
.compile("(([^ ]*) .*)");
@Provides
@Singleton
protected Set<? extends Image> provideImages(final CloudServersClient sync, Location location,
LogHolder holder, Function<ComputeMetadata, String> indexer)
protected Set<? extends Image> provideImages(final CloudServersClient sync,
Location location, LogHolder holder,
Function<ComputeMetadata, String> indexer)
throws InterruptedException, ExecutionException, TimeoutException {
final Set<Image> images = Sets.newHashSet();
holder.logger.debug(">> providing images");
@ -357,9 +356,11 @@ public class CloudServersComputeServiceContextModule extends CloudServersContext
holder.logger.debug("<< didn't match os(%s)", matcher.group(2));
}
}
images.add(new ImageImpl(from.getId() + "", from.getName(), from.getId() + "", location,
null, ImmutableMap.<String, String> of(), from.getName(), version, os,
osDescription, arch, new Credentials("root", null)));
images.add(new ImageImpl(from.getId() + "", from.getName(), from
.getId()
+ "", location, null, ImmutableMap.<String, String> of(), from
.getName(), version, os, osDescription, arch, new Credentials(
"root", null)));
}
holder.logger.debug("<< images(%d)", images.size());
return images;

View File

@ -18,31 +18,17 @@
*/
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.RequiresHttp;
import org.jclouds.http.annotation.ClientError;
import org.jclouds.http.annotation.Redirection;
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.CloudServersClient;
import org.jclouds.rackspace.cloudservers.domain.Server;
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.config.RestClientModule;
import com.google.common.base.Predicate;
import com.google.inject.Provides;
/**
*
* @author Adrian Cole
@ -56,26 +42,6 @@ public class CloudServersRestClientModule extends
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
protected void bindErrorHandlers() {
bind(HttpErrorHandler.class).annotatedWith(Redirection.class).to(

View File

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

View File

@ -20,27 +20,19 @@ package org.jclouds.rimuhosting.miro.config;
import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.util.concurrent.TimeUnit;
import javax.inject.Named;
import javax.inject.Singleton;
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.config.RestClientModule;
import org.jclouds.rimuhosting.miro.RimuHosting;
import org.jclouds.rimuhosting.miro.RimuHostingAsyncClient;
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.predicates.ServerDestroyed;
import org.jclouds.rimuhosting.miro.predicates.ServerRunning;
import org.jclouds.rimuhosting.miro.reference.RimuHostingConstants;
import com.google.common.base.Predicate;
import com.google.inject.Provides;
/**
@ -57,26 +49,6 @@ public class RimuHostingRestClientModule extends
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
@Singleton
public RimuHostingAuthentication provideRimuHostingAuthentication(

View File

@ -18,7 +18,6 @@
*/
package org.jclouds.rimuhosting.miro.domain.internal;
/**
* States an instance can be in.
*

View File

@ -33,12 +33,13 @@ public class ServerRunning implements Predicate<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);
if (server == null)
return false;
logger.trace("%s: looking for server state %s: currently: %s", server.getId(),
RunningState.RUNNING, server.getState());
logger.trace("%s: looking for server state %s: currently: %s", server
.getId(), RunningState.RUNNING, server.getState());
return server.getState() == RunningState.RUNNING;
}

View File

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

View File

@ -3,7 +3,6 @@ package org.jclouds.vcloud.bluelock.compute;
import java.util.Map;
import javax.inject.Inject;
import javax.inject.Named;
import javax.inject.Singleton;
import org.jclouds.compute.domain.NodeState;
@ -27,16 +26,18 @@ public class BlueLockVCloudComputeClient extends BaseVCloudComputeClient {
protected BlueLockVCloudComputeClient(
PopulateDefaultLoginCredentialsForImageStrategy credentialsProvider,
VCloudClient client, Predicate<String> successTester,
@Named("NOT_FOUND") Predicate<VApp> notFoundTester,
Map<VAppStatus, NodeState> vAppStatusToNodeState) {
super(client, successTester, notFoundTester, vAppStatusToNodeState);
super(client, successTester, vAppStatusToNodeState);
this.credentialsProvider = credentialsProvider;
}
@Override
protected Map<String, String> parseAndValidateResponse(String templateId, VApp vAppResponse) {
Credentials credentials = credentialsProvider.execute(client.getVAppTemplate(templateId));
Map<String, String> toReturn = super.parseResponse(templateId, vAppResponse);
protected Map<String, String> parseAndValidateResponse(String templateId,
VApp vAppResponse) {
Credentials credentials = credentialsProvider.execute(client
.getVAppTemplate(templateId));
Map<String, String> toReturn = super.parseResponse(templateId,
vAppResponse);
toReturn.put("username", credentials.account);
toReturn.put("password", credentials.key);
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_KEY;
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_VERSION;
import static org.jclouds.vcloud.reference.VCloudConstants.PROPERTY_VCLOUD_XML_NAMESPACE;
@ -49,9 +50,12 @@ public class VCloudPropertiesBuilder extends PropertiesBuilder {
properties.setProperty(PROPERTY_VCLOUD_XML_SCHEMA,
"http://vcloud.safesecureweb.com/ns/vcloud.xsd");
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_max", "80");
properties.setProperty(PROPERTY_VCLOUD_TIMEOUT_TASK_COMPLETED,
180l * 1000l + "");
return properties;
}
@ -62,7 +66,8 @@ public class VCloudPropertiesBuilder extends PropertiesBuilder {
private void setNs() {
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,
"http://www.vmware.com/vcloud/v"
+ properties.getProperty(PROPERTY_VCLOUD_VERSION));
}
@ -85,8 +90,8 @@ public class VCloudPropertiesBuilder extends PropertiesBuilder {
}
public VCloudPropertiesBuilder withEndpoint(URI endpoint) {
properties.setProperty(PROPERTY_VCLOUD_ENDPOINT, checkNotNull(endpoint, "endpoint")
.toString());
properties.setProperty(PROPERTY_VCLOUD_ENDPOINT, checkNotNull(endpoint,
"endpoint").toString());
return this;
}
}

View File

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

View File

@ -22,21 +22,19 @@ import static org.jclouds.compute.domain.OsFamily.UBUNTU;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import javax.inject.Named;
import javax.inject.Singleton;
import org.jclouds.compute.ComputeServiceContext;
import org.jclouds.compute.LoadBalancerService;
import org.jclouds.compute.config.ComputeServiceTimeoutsModule;
import org.jclouds.compute.domain.ComputeMetadata;
import org.jclouds.compute.domain.Image;
import org.jclouds.compute.domain.NodeState;
import org.jclouds.compute.domain.Size;
import org.jclouds.compute.domain.TemplateBuilder;
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.DestroyNodeStrategy;
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.RunNodesAndAddToSetStrategy;
import org.jclouds.domain.Location;
import org.jclouds.predicates.RetryablePredicate;
import org.jclouds.vcloud.VCloudAsyncClient;
import org.jclouds.vcloud.VCloudClient;
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.Predicate;
import com.google.common.base.Predicates;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Iterables;
import com.google.inject.Provides;
@ -103,6 +99,7 @@ public class VCloudComputeServiceContextModule extends VCloudContextModule {
@Override
protected void configure() {
super.configure();
install(new ComputeServiceTimeoutsModule());
bind(String.class).annotatedWith(VCloud.class).toInstance(providerName);
bind(AddNodeWithTagStrategy.class).to(VCloudAddNodeWithTagStrategy.class);
bind(new TypeLiteral<ComputeServiceContext>() {
@ -127,14 +124,6 @@ public class VCloudComputeServiceContextModule extends VCloudContextModule {
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() {
bind(LoadBalancerService.class).toProvider(Providers.<LoadBalancerService> of(null));
}

View File

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

View File

@ -49,7 +49,8 @@ public class VCloudAddNodeWithTagStrategy implements AddNodeWithTagStrategy {
protected final Map<VAppStatus, NodeState> vAppStatusToNodeState;
@Inject
protected VCloudAddNodeWithTagStrategy(VCloudClient client, VCloudComputeClient computeClient,
protected VCloudAddNodeWithTagStrategy(VCloudClient client,
VCloudComputeClient computeClient,
Map<VAppStatus, NodeState> vAppStatusToNodeState) {
this.client = client;
this.computeClient = computeClient;
@ -58,24 +59,28 @@ public class VCloudAddNodeWithTagStrategy implements AddNodeWithTagStrategy {
@Override
public NodeMetadata execute(String tag, String name, Template template) {
InstantiateVAppTemplateOptions options = processorCount(
Double.valueOf(template.getSize().getCores()).intValue()).memory(
template.getSize().getRam()).disk(template.getSize().getDisk() * 1024 * 1024l);
Map<String, String> metaMap = computeClient.start(template.getLocation().getId(), name,
template.getImage().getProviderId(), options, template.getOptions()
.getInboundPorts());
template.getSize().getRam()).disk(
template.getSize().getDisk() * 1024 * 1024l);
if (!template.getOptions().shouldBlockUntilRunning())
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"));
return newCreateNodeResponse(tag, template, metaMap, vApp);
}
protected NodeMetadata newCreateNodeResponse(String tag, Template template,
Map<String, String> metaMap, VApp vApp) {
return new NodeMetadataImpl(vApp.getId(), vApp.getName(), vApp.getId(), template
.getLocation(), vApp.getLocation(), ImmutableMap.<String, String> of(), tag,
template.getImage(), vAppStatusToNodeState.get(vApp.getStatus()), computeClient
.getPublicAddresses(vApp.getId()), computeClient.getPrivateAddresses(vApp
.getId()), ImmutableMap.<String, String> of(), new Credentials(metaMap
return new NodeMetadataImpl(vApp.getId(), vApp.getName(), vApp.getId(),
template.getLocation(), vApp.getLocation(), ImmutableMap
.<String, String> of(), tag, template.getImage(),
vAppStatusToNodeState.get(vApp.getStatus()), computeClient
.getPublicAddresses(vApp.getId()), computeClient
.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.Singleton;
import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.strategy.DestroyNodeStrategy;
import org.jclouds.compute.strategy.GetNodeMetadataStrategy;
import org.jclouds.vcloud.compute.VCloudComputeClient;
/**
@ -32,16 +34,20 @@ import org.jclouds.vcloud.compute.VCloudComputeClient;
@Singleton
public class VCloudDestroyNodeStrategy implements DestroyNodeStrategy {
protected final VCloudComputeClient computeClient;
protected final GetNodeMetadataStrategy getNode;
@Inject
protected VCloudDestroyNodeStrategy(VCloudComputeClient computeClient) {
protected VCloudDestroyNodeStrategy(VCloudComputeClient computeClient,
GetNodeMetadataStrategy getNode) {
this.computeClient = computeClient;
this.getNode = getNode;
}
@Override
public boolean execute(String id) {
public NodeMetadata execute(String 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.Singleton;
import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.strategy.GetNodeMetadataStrategy;
import org.jclouds.compute.strategy.RebootNodeStrategy;
import org.jclouds.vcloud.VCloudClient;
import org.jclouds.vcloud.domain.Task;
@ -36,17 +38,21 @@ import com.google.common.base.Predicate;
public class VCloudRebootNodeStrategy implements RebootNodeStrategy {
private final VCloudClient client;
protected final Predicate<String> taskTester;
protected final GetNodeMetadataStrategy getNode;
@Inject
protected VCloudRebootNodeStrategy(VCloudClient client, Predicate<String> taskTester) {
protected VCloudRebootNodeStrategy(VCloudClient client,
Predicate<String> taskTester, GetNodeMetadataStrategy getNode) {
this.client = client;
this.taskTester = taskTester;
this.getNode = getNode;
}
@Override
public boolean execute(String id) {
public NodeMetadata execute(String 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_KEY;
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_VERSION;
@ -49,9 +50,7 @@ import org.jclouds.http.annotation.Redirection;
import org.jclouds.http.annotation.ServerError;
import org.jclouds.http.filters.BasicAuthentication;
import org.jclouds.logging.Logger;
import org.jclouds.net.IPSocket;
import org.jclouds.predicates.RetryablePredicate;
import org.jclouds.predicates.SocketOpen;
import org.jclouds.rest.AsyncClientFactory;
import org.jclouds.rest.AuthorizationException;
import org.jclouds.rest.ConfiguresRestClient;
@ -61,7 +60,6 @@ import org.jclouds.vcloud.VCloudClient;
import org.jclouds.vcloud.VCloudToken;
import org.jclouds.vcloud.domain.NamedResource;
import org.jclouds.vcloud.domain.Organization;
import org.jclouds.vcloud.domain.VApp;
import org.jclouds.vcloud.endpoints.Catalog;
import org.jclouds.vcloud.endpoints.Network;
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.VCloudLoginAsyncClient.VCloudSession;
import org.jclouds.vcloud.predicates.TaskSuccess;
import org.jclouds.vcloud.predicates.VAppNotFound;
import com.google.common.base.Predicate;
import com.google.common.base.Supplier;
@ -87,7 +84,8 @@ import com.google.common.collect.Iterables;
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
*/
@ -96,7 +94,8 @@ import com.google.inject.Provides;
public abstract class BaseVCloudRestClientModule<S extends VCloudClient, A extends VCloudAsyncClient>
extends RestClientModule<S, A> {
public BaseVCloudRestClientModule(Class<S> syncClientType, Class<A> asyncClientType) {
public BaseVCloudRestClientModule(Class<S> syncClientType,
Class<A> asyncClientType) {
super(syncClientType, asyncClientType);
}
@ -111,35 +110,26 @@ public abstract class BaseVCloudRestClientModule<S extends VCloudClient, A exten
@Provides
@Singleton
protected Predicate<IPSocket> socketTester(SocketOpen open) {
return new RetryablePredicate<IPSocket>(open, 130, 10, TimeUnit.SECONDS);
}
@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);
protected Predicate<String> successTester(TaskSuccess success,
@Named(PROPERTY_VCLOUD_TIMEOUT_TASK_COMPLETED) long completed) {
return new RetryablePredicate<String>(success, completed);
}
@VCloudToken
@Provides
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
@Org
@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();
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();
}
@ -158,15 +148,21 @@ public abstract class BaseVCloudRestClientModule<S extends VCloudClient, A exten
@Provides
@Singleton
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>(
new RetryOnTimeOutExceptionSupplier<VCloudSession>(new Supplier<VCloudSession>() {
new RetryOnTimeOutExceptionSupplier<VCloudSession>(
new Supplier<VCloudSession>() {
public VCloudSession get() {
// http://code.google.com/p/google-guice/issues/detail?id=483
// guice doesn't remember when singleton providers throw exceptions.
// in this case, if describeRegions fails, it is called again for
// each provider method that depends on it. To short-circuit this,
// we remember the last exception trusting that guice is single-threaded
// guice doesn't remember when singleton providers throw
// exceptions.
// in this case, if describeRegions fails, it is called
// again for
// each provider method that depends on it. To
// short-circuit this,
// we remember the last exception trusting that guice is
// single-threaded
if (authException != null)
throw authException;
try {
@ -194,33 +190,38 @@ public abstract class BaseVCloudRestClientModule<S extends VCloudClient, A exten
@Provides
@Singleton
@org.jclouds.vcloud.endpoints.VCloudLogin
protected URI provideAuthenticationURI(VCloudVersionsAsyncClient versionService,
@Named(PROPERTY_VCLOUD_VERSION) String version) throws InterruptedException,
ExecutionException, TimeoutException {
SortedMap<String, URI> versions = versionService.getSupportedVersions().get(180,
TimeUnit.SECONDS);
protected URI provideAuthenticationURI(
VCloudVersionsAsyncClient versionService,
@Named(PROPERTY_VCLOUD_VERSION) String version)
throws InterruptedException, ExecutionException, TimeoutException {
SortedMap<String, URI> versions = versionService.getSupportedVersions()
.get(180, TimeUnit.SECONDS);
checkState(versions.size() > 0, "No versions present");
checkState(versions.containsKey(version), "version " + version + " not present in: "
+ versions);
checkState(versions.containsKey(version), "version " + version
+ " not present in: " + versions);
return versions.get(version);
}
@Provides
@Singleton
protected VCloudLoginAsyncClient provideVCloudLogin(AsyncClientFactory factory) {
protected VCloudLoginAsyncClient provideVCloudLogin(
AsyncClientFactory factory) {
return factory.create(VCloudLoginAsyncClient.class);
}
@Provides
@Singleton
protected VCloudVersionsAsyncClient provideVCloudVersions(AsyncClientFactory factory) {
protected VCloudVersionsAsyncClient provideVCloudVersions(
AsyncClientFactory factory) {
return factory.create(VCloudVersionsAsyncClient.class);
}
@Provides
@Singleton
public BasicAuthentication provideBasicAuthentication(@Named(PROPERTY_VCLOUD_USER) String user,
@Named(PROPERTY_VCLOUD_KEY) String key, EncryptionService encryptionService)
public BasicAuthentication provideBasicAuthentication(
@Named(PROPERTY_VCLOUD_USER) String user,
@Named(PROPERTY_VCLOUD_KEY) String key,
EncryptionService encryptionService)
throws UnsupportedEncodingException {
return new BasicAuthentication(user, key, encryptionService);
}
@ -248,8 +249,8 @@ public abstract class BaseVCloudRestClientModule<S extends VCloudClient, A exten
@Provides
@Singleton
protected Organization provideOrganization(VCloudClient discovery) throws ExecutionException,
TimeoutException, InterruptedException {
protected Organization provideOrganization(VCloudClient discovery)
throws ExecutionException, TimeoutException, InterruptedException {
if (authException != null)
throw authException;
try {
@ -264,29 +265,33 @@ public abstract class BaseVCloudRestClientModule<S extends VCloudClient, A exten
@VDC
@Singleton
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();
}
@Provides
@Catalog
@Singleton
protected URI provideCatalog(Organization org, @Named(PROPERTY_VCLOUD_USER) String user) {
checkState(org.getCatalogs().size() > 0, "No catalogs present in org: " + org.getName());
protected URI provideCatalog(Organization org,
@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();
}
@Provides
@Network
@Singleton
protected URI provideDefaultNetwork(VCloudClient client) throws InterruptedException,
ExecutionException, TimeoutException {
protected URI provideDefaultNetwork(VCloudClient client)
throws InterruptedException, ExecutionException, TimeoutException {
if (authException != null)
throw authException;
try {
org.jclouds.vcloud.domain.VDC vDC = client.getDefaultVDC();
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();
} catch (AuthorizationException e) {
BaseVCloudRestClientModule.this.authException = e;
@ -315,7 +320,8 @@ public abstract class BaseVCloudRestClientModule<S extends VCloudClient, A exten
@TasksList
@Singleton
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();
}
}

View File

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

View File

@ -18,6 +18,7 @@
*/
package org.jclouds.vcloud.reference;
/**
* 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_SCHEMA = "jclouds.vcloud.xml.schema";
public static final String PROPERTY_VCLOUD_TIMEOUT_TASK_COMPLETED = "jclouds.vcloud.timeout.task-complete";
}

View File

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

View File

@ -19,6 +19,7 @@
package org.jclouds.vcloud.hostingdotcom;
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.util.Properties;
@ -30,11 +31,15 @@ import org.jclouds.vcloud.VCloudPropertiesBuilder;
*
* @author Adrian Cole
*/
public class HostingDotComVCloudPropertiesBuilder extends VCloudPropertiesBuilder {
public class HostingDotComVCloudPropertiesBuilder extends
VCloudPropertiesBuilder {
@Override
protected Properties 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;
}

View File

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

View File

@ -19,40 +19,40 @@
package org.jclouds.vcloud.hostingdotcom.config;
import java.net.URI;
import java.util.concurrent.TimeUnit;
import javax.inject.Singleton;
import org.jclouds.http.RequiresHttp;
import org.jclouds.predicates.RetryablePredicate;
import org.jclouds.rest.ConfiguresRestClient;
import org.jclouds.vcloud.VCloudAsyncClient;
import org.jclouds.vcloud.VCloudClient;
import org.jclouds.vcloud.config.BaseVCloudRestClientModule;
import org.jclouds.vcloud.hostingdotcom.HostingDotComVCloudAsyncClient;
import org.jclouds.vcloud.hostingdotcom.HostingDotComVCloudClient;
import org.jclouds.vcloud.predicates.TaskSuccess;
import com.google.common.base.Predicate;
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
*/
@RequiresHttp
@ConfiguresRestClient
public class HostingDotComVCloudRestClientModule extends
public class HostingDotComVCloudRestClientModule
extends
BaseVCloudRestClientModule<HostingDotComVCloudClient, HostingDotComVCloudAsyncClient> {
public HostingDotComVCloudRestClientModule() {
super(HostingDotComVCloudClient.class, HostingDotComVCloudAsyncClient.class);
super(HostingDotComVCloudClient.class,
HostingDotComVCloudAsyncClient.class);
}
@Provides
@Singleton
protected VCloudAsyncClient provideVCloudAsyncClient(HostingDotComVCloudAsyncClient in) {
protected VCloudAsyncClient provideVCloudAsyncClient(
HostingDotComVCloudAsyncClient in) {
return in;
}
@ -67,8 +67,4 @@ public class HostingDotComVCloudRestClientModule extends
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

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

View File

@ -51,7 +51,8 @@ public class TerremarkVCloudComputeClientTest {
@SuppressWarnings("unchecked")
@Test
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));
VAppTemplate template = createMock(VAppTemplate.class);
expect(template.getDescription()).andReturn(description).atLeastOnce();
@ -61,8 +62,9 @@ public class TerremarkVCloudComputeClientTest {
expect(
client.instantiateVAppTemplateInVDC("vDCId", "name", "templateId",
new TerremarkInstantiateVAppTemplateOptions().productProperty("password",
"password"))).andReturn(vApp);
new TerremarkInstantiateVAppTemplateOptions()
.productProperty("password", "password"))).andReturn(
vApp);
Task task = createMock(Task.class);
expect(vApp.getId()).andReturn("1").atLeastOnce();
@ -76,7 +78,8 @@ public class TerremarkVCloudComputeClientTest {
Predicate<VApp> notFoundTester = createMock(Predicate.class);
Map<VAppStatus, NodeState> vAppStatusToNodeState = createMock(Map.class);
TerremarkVCloudComputeClient computeClient = new TerremarkVCloudComputeClient(client,
TerremarkVCloudComputeClient computeClient = new TerremarkVCloudComputeClient(
client,
new ParseVAppTemplateDescriptionToGetDefaultLoginCredentials(),
new Provider<String>() {
@ -85,7 +88,7 @@ public class TerremarkVCloudComputeClientTest {
return "password";
}
}, successTester, notFoundTester, vAppStatusToNodeState);
}, successTester, vAppStatusToNodeState);
replay(template);
replay(vApp);
@ -95,8 +98,8 @@ public class TerremarkVCloudComputeClientTest {
replay(notFoundTester);
replay(vAppStatusToNodeState);
Map<String, String> response = computeClient.start("vDCId", "name", "templateId",
new TerremarkInstantiateVAppTemplateOptions());
Map<String, String> response = computeClient.start("vDCId", "name",
"templateId", new TerremarkInstantiateVAppTemplateOptions());
assertEquals(response.get("id"), "1");
assertEquals(response.get("username"), "Administrator");