mirror of https://github.com/apache/jclouds.git
Merge branch 'master' of git://github.com/jclouds/jclouds into large-blob
This commit is contained in:
commit
beb915424b
|
@ -21,6 +21,7 @@ package org.jclouds.ec2.binders;
|
||||||
|
|
||||||
import static com.google.common.base.Preconditions.checkArgument;
|
import static com.google.common.base.Preconditions.checkArgument;
|
||||||
|
|
||||||
|
import javax.inject.Inject;
|
||||||
import javax.inject.Singleton;
|
import javax.inject.Singleton;
|
||||||
|
|
||||||
import org.jclouds.http.HttpRequest;
|
import org.jclouds.http.HttpRequest;
|
||||||
|
@ -34,11 +35,22 @@ import org.jclouds.rest.Binder;
|
||||||
*/
|
*/
|
||||||
@Singleton
|
@Singleton
|
||||||
public class IfNotNullBindAvailabilityZoneToFormParam implements Binder {
|
public class IfNotNullBindAvailabilityZoneToFormParam implements Binder {
|
||||||
|
private final String param;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
protected IfNotNullBindAvailabilityZoneToFormParam() {
|
||||||
|
this("Placement.AvailabilityZone");
|
||||||
|
}
|
||||||
|
|
||||||
|
protected IfNotNullBindAvailabilityZoneToFormParam(String param) {
|
||||||
|
this.param = param;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <R extends HttpRequest> R bindToRequest(R request, Object input) {
|
public <R extends HttpRequest> R bindToRequest(R request, Object input) {
|
||||||
if (input != null) {
|
if (input != null) {
|
||||||
checkArgument(input instanceof String, "this binder is only valid for AvailabilityZone!");
|
checkArgument(input instanceof String, "this binder is only valid for String!");
|
||||||
return ModifyRequest.addFormParam(request, "Placement.AvailabilityZone", (String) input);
|
return ModifyRequest.addFormParam(request, param, (String) input);
|
||||||
}
|
}
|
||||||
return request;
|
return request;
|
||||||
}
|
}
|
||||||
|
|
|
@ -66,8 +66,8 @@ import com.google.common.annotations.VisibleForTesting;
|
||||||
import com.google.common.base.Function;
|
import com.google.common.base.Function;
|
||||||
import com.google.common.base.Predicate;
|
import com.google.common.base.Predicate;
|
||||||
import com.google.common.base.Supplier;
|
import com.google.common.base.Supplier;
|
||||||
import com.google.common.collect.ImmutableMap;
|
import com.google.common.collect.ImmutableMultimap;
|
||||||
import com.google.common.collect.ImmutableMap.Builder;
|
import com.google.common.collect.ImmutableMultimap.Builder;
|
||||||
import com.google.common.collect.ImmutableSet;
|
import com.google.common.collect.ImmutableSet;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -177,12 +177,12 @@ public class EC2ComputeService extends BaseComputeService {
|
||||||
@Override
|
@Override
|
||||||
public Set<? extends NodeMetadata> destroyNodesMatching(Predicate<NodeMetadata> filter) {
|
public Set<? extends NodeMetadata> destroyNodesMatching(Predicate<NodeMetadata> filter) {
|
||||||
Set<? extends NodeMetadata> deadOnes = super.destroyNodesMatching(filter);
|
Set<? extends NodeMetadata> deadOnes = super.destroyNodesMatching(filter);
|
||||||
Builder<String, String> regionGroups = ImmutableMap.<String, String> builder();
|
Builder<String, String> regionGroups = ImmutableMultimap.<String, String> builder();
|
||||||
for (NodeMetadata nodeMetadata : deadOnes) {
|
for (NodeMetadata nodeMetadata : deadOnes) {
|
||||||
if (nodeMetadata.getGroup() != null)
|
if (nodeMetadata.getGroup() != null)
|
||||||
regionGroups.put(AWSUtils.parseHandle(nodeMetadata.getId())[0], nodeMetadata.getGroup());
|
regionGroups.put(AWSUtils.parseHandle(nodeMetadata.getId())[0], nodeMetadata.getGroup());
|
||||||
}
|
}
|
||||||
for (Entry<String, String> regionGroup : regionGroups.build().entrySet()) {
|
for (Entry<String, String> regionGroup : regionGroups.build().entries()) {
|
||||||
cleanUpIncidentalResources(regionGroup);
|
cleanUpIncidentalResources(regionGroup);
|
||||||
}
|
}
|
||||||
return deadOnes;
|
return deadOnes;
|
||||||
|
|
|
@ -25,7 +25,6 @@ import static org.jclouds.ec2.reference.EC2Constants.PROPERTY_EC2_AMI_OWNERS;
|
||||||
|
|
||||||
import java.security.SecureRandom;
|
import java.security.SecureRandom;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
|
|
||||||
import javax.inject.Named;
|
import javax.inject.Named;
|
||||||
import javax.inject.Singleton;
|
import javax.inject.Singleton;
|
||||||
|
@ -54,13 +53,10 @@ import org.jclouds.ec2.compute.options.EC2TemplateOptions;
|
||||||
import org.jclouds.ec2.domain.InstanceState;
|
import org.jclouds.ec2.domain.InstanceState;
|
||||||
import org.jclouds.ec2.domain.KeyPair;
|
import org.jclouds.ec2.domain.KeyPair;
|
||||||
import org.jclouds.ec2.domain.RunningInstance;
|
import org.jclouds.ec2.domain.RunningInstance;
|
||||||
import org.jclouds.ec2.predicates.InstancePresent;
|
|
||||||
import org.jclouds.predicates.RetryablePredicate;
|
|
||||||
import org.jclouds.rest.RestContext;
|
import org.jclouds.rest.RestContext;
|
||||||
import org.jclouds.rest.internal.RestContextImpl;
|
import org.jclouds.rest.internal.RestContextImpl;
|
||||||
|
|
||||||
import com.google.common.base.Function;
|
import com.google.common.base.Function;
|
||||||
import com.google.common.base.Predicate;
|
|
||||||
import com.google.common.base.Splitter;
|
import com.google.common.base.Splitter;
|
||||||
import com.google.common.base.Supplier;
|
import com.google.common.base.Supplier;
|
||||||
import com.google.common.collect.ImmutableMap;
|
import com.google.common.collect.ImmutableMap;
|
||||||
|
@ -77,11 +73,11 @@ import com.google.inject.TypeLiteral;
|
||||||
public class EC2ComputeServiceDependenciesModule extends AbstractModule {
|
public class EC2ComputeServiceDependenciesModule extends AbstractModule {
|
||||||
|
|
||||||
public static final Map<InstanceState, NodeState> instanceToNodeState = ImmutableMap
|
public static final Map<InstanceState, NodeState> instanceToNodeState = ImmutableMap
|
||||||
.<InstanceState, NodeState> builder().put(InstanceState.PENDING, NodeState.PENDING)
|
.<InstanceState, NodeState> builder().put(InstanceState.PENDING, NodeState.PENDING).put(
|
||||||
.put(InstanceState.RUNNING, NodeState.RUNNING).put(InstanceState.SHUTTING_DOWN, NodeState.PENDING)
|
InstanceState.RUNNING, NodeState.RUNNING).put(InstanceState.SHUTTING_DOWN, NodeState.PENDING).put(
|
||||||
.put(InstanceState.TERMINATED, NodeState.TERMINATED).put(InstanceState.STOPPING, NodeState.PENDING)
|
InstanceState.TERMINATED, NodeState.TERMINATED).put(InstanceState.STOPPING, NodeState.PENDING)
|
||||||
.put(InstanceState.STOPPED, NodeState.SUSPENDED).put(InstanceState.UNRECOGNIZED, NodeState.UNRECOGNIZED)
|
.put(InstanceState.STOPPED, NodeState.SUSPENDED).put(InstanceState.UNRECOGNIZED, NodeState.UNRECOGNIZED)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
@Singleton
|
@Singleton
|
||||||
@Provides
|
@Provides
|
||||||
|
@ -89,13 +85,6 @@ public class EC2ComputeServiceDependenciesModule extends AbstractModule {
|
||||||
return instanceToNodeState;
|
return instanceToNodeState;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Provides
|
|
||||||
@Singleton
|
|
||||||
@Named("PRESENT")
|
|
||||||
protected Predicate<RunningInstance> instancePresent(InstancePresent present) {
|
|
||||||
return new RetryablePredicate<RunningInstance>(present, 5000, 200, TimeUnit.MILLISECONDS);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void configure() {
|
protected void configure() {
|
||||||
bind(TemplateBuilder.class).to(EC2TemplateBuilderImpl.class);
|
bind(TemplateBuilder.class).to(EC2TemplateBuilderImpl.class);
|
||||||
|
|
|
@ -73,7 +73,7 @@ public class RunningInstanceToNodeMetadata implements Function<RunningInstance,
|
||||||
protected final Map<InstanceState, NodeState> instanceToNodeState;
|
protected final Map<InstanceState, NodeState> instanceToNodeState;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
RunningInstanceToNodeMetadata(Map<InstanceState, NodeState> instanceToNodeState,
|
protected RunningInstanceToNodeMetadata(Map<InstanceState, NodeState> instanceToNodeState,
|
||||||
Map<String, Credentials> credentialStore, Map<RegionAndName, Image> instanceToImage,
|
Map<String, Credentials> credentialStore, Map<RegionAndName, Image> instanceToImage,
|
||||||
@Memoized Supplier<Set<? extends Location>> locations, @Memoized Supplier<Set<? extends Hardware>> hardware) {
|
@Memoized Supplier<Set<? extends Location>> locations, @Memoized Supplier<Set<? extends Hardware>> hardware) {
|
||||||
this.locations = checkNotNull(locations, "locations");
|
this.locations = checkNotNull(locations, "locations");
|
||||||
|
@ -85,13 +85,14 @@ public class RunningInstanceToNodeMetadata implements Function<RunningInstance,
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public NodeMetadata apply(RunningInstance instance) {
|
public NodeMetadata apply(RunningInstance instance) {
|
||||||
|
if (instance == null || instance.getId() == null)
|
||||||
|
return null;
|
||||||
NodeMetadataBuilder builder = new NodeMetadataBuilder();
|
NodeMetadataBuilder builder = new NodeMetadataBuilder();
|
||||||
String providerId = checkNotNull(instance, "instance").getId();
|
builder.providerId(instance.getId());
|
||||||
builder.providerId(providerId);
|
builder.id(instance.getRegion() + "/" + instance.getId());
|
||||||
builder.id(instance.getRegion() + "/" + providerId);
|
|
||||||
String group = getGroupForInstance(instance);
|
String group = getGroupForInstance(instance);
|
||||||
builder.group(group);
|
builder.group(group);
|
||||||
builder.credentials(credentialStore.get("node#" + instance.getRegion() + "/" + providerId));
|
addCredentialsForInstance(builder, instance);
|
||||||
builder.state(instanceToNodeState.get(instance.getInstanceState()));
|
builder.state(instanceToNodeState.get(instance.getInstanceState()));
|
||||||
builder.publicAddresses(NullSafeCollections.nullSafeSet(instance.getIpAddress()));
|
builder.publicAddresses(NullSafeCollections.nullSafeSet(instance.getIpAddress()));
|
||||||
builder.privateAddresses(NullSafeCollections.nullSafeSet(instance.getPrivateIpAddress()));
|
builder.privateAddresses(NullSafeCollections.nullSafeSet(instance.getPrivateIpAddress()));
|
||||||
|
@ -104,21 +105,25 @@ public class RunningInstanceToNodeMetadata implements Function<RunningInstance,
|
||||||
RegionAndName regionAndName = new RegionAndName(instance.getRegion(), instance.getImageId());
|
RegionAndName regionAndName = new RegionAndName(instance.getRegion(), instance.getImageId());
|
||||||
try {
|
try {
|
||||||
Image image = instanceToImage.get(regionAndName);
|
Image image = instanceToImage.get(regionAndName);
|
||||||
if (image != null)
|
if (image != null)
|
||||||
builder.operatingSystem(image.getOperatingSystem());
|
builder.operatingSystem(image.getOperatingSystem());
|
||||||
}
|
} catch (NullPointerException e) {
|
||||||
catch (NullPointerException e) {
|
// The instanceToImage Map may throw NullPointerException (actually subclass
|
||||||
// The instanceToImage Map may throw NullPointerException (actually subclass NullOutputException) if the
|
// NullOutputException) if the
|
||||||
// computing Function returns a null value.
|
// computing Function returns a null value.
|
||||||
//
|
//
|
||||||
// See the following for more information:
|
// See the following for more information:
|
||||||
// MapMaker.makeComputingMap()
|
// MapMaker.makeComputingMap()
|
||||||
// RegionAndIdToImage.apply()
|
// RegionAndIdToImage.apply()
|
||||||
}
|
}
|
||||||
|
|
||||||
return builder.build();
|
return builder.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected void addCredentialsForInstance(NodeMetadataBuilder builder, RunningInstance instance) {
|
||||||
|
builder.credentials(credentialStore.get("node#" + instance.getRegion() + "/" + instance.getId()));
|
||||||
|
}
|
||||||
|
|
||||||
protected Hardware parseHardware(final RunningInstance instance) {
|
protected Hardware parseHardware(final RunningInstance instance) {
|
||||||
Hardware hardware = getHardwareForInstance(instance);
|
Hardware hardware = getHardwareForInstance(instance);
|
||||||
|
|
||||||
|
@ -171,9 +176,8 @@ public class RunningInstanceToNodeMetadata implements Function<RunningInstance,
|
||||||
} catch (NoSuchElementException e) {
|
} catch (NoSuchElementException e) {
|
||||||
logger.debug("no group parsed from %s's security groups: %s", instance.getId(), instance.getGroupIds());
|
logger.debug("no group parsed from %s's security groups: %s", instance.getId(), instance.getGroupIds());
|
||||||
} catch (IllegalArgumentException e) {
|
} catch (IllegalArgumentException e) {
|
||||||
logger
|
logger.debug("too many groups match %s; %s's security groups: %s", "jclouds#", instance.getId(), instance
|
||||||
.debug("too many groups match %s; %s's security groups: %s", "jclouds#", instance.getId(), instance
|
.getGroupIds());
|
||||||
.getGroupIds());
|
|
||||||
}
|
}
|
||||||
return group;
|
return group;
|
||||||
}
|
}
|
||||||
|
@ -203,6 +207,8 @@ public class RunningInstanceToNodeMetadata implements Function<RunningInstance,
|
||||||
}
|
}
|
||||||
|
|
||||||
private Location findLocationWithId(final String locationId) {
|
private Location findLocationWithId(final String locationId) {
|
||||||
|
if (locationId == null)
|
||||||
|
return null;
|
||||||
try {
|
try {
|
||||||
Location location = Iterables.find(locations.get(), new Predicate<Location>() {
|
Location location = Iterables.find(locations.get(), new Predicate<Location>() {
|
||||||
|
|
||||||
|
|
|
@ -89,7 +89,7 @@ public class EC2TemplateOptions extends TemplateOptions implements Cloneable {
|
||||||
private String keyPair = null;
|
private String keyPair = null;
|
||||||
private boolean noKeyPair;
|
private boolean noKeyPair;
|
||||||
private byte[] userData;
|
private byte[] userData;
|
||||||
private Set<BlockDeviceMapping> blockDeviceMappings = ImmutableSet.of();
|
private ImmutableSet.Builder<BlockDeviceMapping> blockDeviceMappings = ImmutableSet.<BlockDeviceMapping> builder();
|
||||||
|
|
||||||
public static final EC2TemplateOptions NONE = new EC2TemplateOptions();
|
public static final EC2TemplateOptions NONE = new EC2TemplateOptions();
|
||||||
|
|
||||||
|
@ -142,80 +142,29 @@ public class EC2TemplateOptions extends TemplateOptions implements Cloneable {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Specifies the block device mappings to be used to run the instance
|
|
||||||
*/
|
|
||||||
public EC2TemplateOptions mapEBSSnapshotToDeviceName(String deviceName, String snapshotId,
|
public EC2TemplateOptions mapEBSSnapshotToDeviceName(String deviceName, String snapshotId,
|
||||||
@Nullable Integer sizeInGib, boolean deleteOnTermination) {
|
@Nullable Integer sizeInGib, boolean deleteOnTermination) {
|
||||||
checkNotNull(deviceName, "deviceName cannot be null");
|
blockDeviceMappings.add(new MapEBSSnapshotToDevice(deviceName, snapshotId, sizeInGib, deleteOnTermination));
|
||||||
Preconditions2.checkNotEmpty(deviceName, "deviceName must be non-empty");
|
|
||||||
checkNotNull(snapshotId, "snapshotId cannot be null");
|
|
||||||
Preconditions2.checkNotEmpty(snapshotId, "snapshotId must be non-empty");
|
|
||||||
com.google.common.collect.ImmutableSet.Builder<BlockDeviceMapping> mappings = ImmutableSet
|
|
||||||
.<BlockDeviceMapping> builder();
|
|
||||||
mappings.addAll(blockDeviceMappings);
|
|
||||||
MapEBSSnapshotToDevice mapping = new MapEBSSnapshotToDevice(deviceName, snapshotId, sizeInGib,
|
|
||||||
deleteOnTermination);
|
|
||||||
mappings.add(mapping);
|
|
||||||
blockDeviceMappings = mappings.build();
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Specifies the block device mappings to be used to run the instance
|
|
||||||
*/
|
|
||||||
public EC2TemplateOptions mapNewVolumeToDeviceName(String deviceName, int sizeInGib, boolean deleteOnTermination) {
|
public EC2TemplateOptions mapNewVolumeToDeviceName(String deviceName, int sizeInGib, boolean deleteOnTermination) {
|
||||||
checkNotNull(deviceName, "deviceName cannot be null");
|
blockDeviceMappings.add(new MapNewVolumeToDevice(deviceName, sizeInGib, deleteOnTermination));
|
||||||
Preconditions2.checkNotEmpty(deviceName, "deviceName must be non-empty");
|
|
||||||
|
|
||||||
com.google.common.collect.ImmutableSet.Builder<BlockDeviceMapping> mappings = ImmutableSet
|
|
||||||
.<BlockDeviceMapping> builder();
|
|
||||||
mappings.addAll(blockDeviceMappings);
|
|
||||||
MapNewVolumeToDevice mapping = new MapNewVolumeToDevice(deviceName, sizeInGib, deleteOnTermination);
|
|
||||||
mappings.add(mapping);
|
|
||||||
blockDeviceMappings = mappings.build();
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Specifies the block device mappings to be used to run the instance
|
|
||||||
*/
|
|
||||||
public EC2TemplateOptions mapEphemeralDeviceToDeviceName(String deviceName, String virtualName) {
|
public EC2TemplateOptions mapEphemeralDeviceToDeviceName(String deviceName, String virtualName) {
|
||||||
checkNotNull(deviceName, "deviceName cannot be null");
|
blockDeviceMappings.add(new MapEphemeralDeviceToDevice(deviceName, virtualName));
|
||||||
Preconditions2.checkNotEmpty(deviceName, "deviceName must be non-empty");
|
|
||||||
checkNotNull(virtualName, "virtualName cannot be null");
|
|
||||||
Preconditions2.checkNotEmpty(virtualName, "virtualName must be non-empty");
|
|
||||||
|
|
||||||
com.google.common.collect.ImmutableSet.Builder<BlockDeviceMapping> mappings = ImmutableSet
|
|
||||||
.<BlockDeviceMapping> builder();
|
|
||||||
mappings.addAll(blockDeviceMappings);
|
|
||||||
MapEphemeralDeviceToDevice mapping = new MapEphemeralDeviceToDevice(deviceName, virtualName);
|
|
||||||
mappings.add(mapping);
|
|
||||||
blockDeviceMappings = mappings.build();
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Specifies the block device mappings to be used to run the instance
|
|
||||||
*/
|
|
||||||
public EC2TemplateOptions unmapDeviceNamed(String deviceName) {
|
public EC2TemplateOptions unmapDeviceNamed(String deviceName) {
|
||||||
checkNotNull(deviceName, "deviceName cannot be null");
|
blockDeviceMappings.add(new UnmapDeviceNamed(deviceName));
|
||||||
Preconditions2.checkNotEmpty(deviceName, "deviceName must be non-empty");
|
|
||||||
|
|
||||||
com.google.common.collect.ImmutableSet.Builder<BlockDeviceMapping> mappings = ImmutableSet
|
|
||||||
.<BlockDeviceMapping> builder();
|
|
||||||
mappings.addAll(blockDeviceMappings);
|
|
||||||
UnmapDeviceNamed mapping = new UnmapDeviceNamed(deviceName);
|
|
||||||
mappings.add(mapping);
|
|
||||||
blockDeviceMappings = mappings.build();
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
public EC2TemplateOptions blockDeviceMappings(Iterable<? extends BlockDeviceMapping> blockDeviceMappings) {
|
||||||
* Specifies the block device mappings to be used to run the instance
|
this.blockDeviceMappings.addAll(checkNotNull(blockDeviceMappings, "blockDeviceMappings"));
|
||||||
*/
|
|
||||||
public EC2TemplateOptions blockDeviceMappings(Set<? extends BlockDeviceMapping> blockDeviceMappings) {
|
|
||||||
this.blockDeviceMappings = ImmutableSet.copyOf(checkNotNull(blockDeviceMappings, "blockDeviceMappings"));
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -511,7 +460,7 @@ public class EC2TemplateOptions extends TemplateOptions implements Cloneable {
|
||||||
* @return BlockDeviceMapping to use when running the instance or null.
|
* @return BlockDeviceMapping to use when running the instance or null.
|
||||||
*/
|
*/
|
||||||
public Set<BlockDeviceMapping> getBlockDeviceMappings() {
|
public Set<BlockDeviceMapping> getBlockDeviceMappings() {
|
||||||
return blockDeviceMappings;
|
return blockDeviceMappings.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -17,7 +17,9 @@
|
||||||
* ====================================================================
|
* ====================================================================
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.jclouds.ec2.predicates;
|
package org.jclouds.ec2.compute.predicates;
|
||||||
|
|
||||||
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
|
|
||||||
import java.util.NoSuchElementException;
|
import java.util.NoSuchElementException;
|
||||||
|
|
||||||
|
@ -25,7 +27,7 @@ import javax.annotation.Resource;
|
||||||
import javax.inject.Singleton;
|
import javax.inject.Singleton;
|
||||||
|
|
||||||
import org.jclouds.ec2.EC2Client;
|
import org.jclouds.ec2.EC2Client;
|
||||||
import org.jclouds.ec2.domain.RunningInstance;
|
import org.jclouds.ec2.compute.domain.RegionAndName;
|
||||||
import org.jclouds.logging.Logger;
|
import org.jclouds.logging.Logger;
|
||||||
import org.jclouds.rest.ResourceNotFoundException;
|
import org.jclouds.rest.ResourceNotFoundException;
|
||||||
|
|
||||||
|
@ -34,13 +36,11 @@ import com.google.common.collect.Iterables;
|
||||||
import com.google.inject.Inject;
|
import com.google.inject.Inject;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
|
||||||
* Tests to see if a task succeeds.
|
|
||||||
*
|
*
|
||||||
* @author Adrian Cole
|
* @author Adrian Cole
|
||||||
*/
|
*/
|
||||||
@Singleton
|
@Singleton
|
||||||
public class InstancePresent implements Predicate<RunningInstance> {
|
public class InstancePresent implements Predicate<RegionAndName> {
|
||||||
|
|
||||||
private final EC2Client client;
|
private final EC2Client client;
|
||||||
|
|
||||||
|
@ -49,13 +49,13 @@ public class InstancePresent implements Predicate<RunningInstance> {
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public InstancePresent(EC2Client client) {
|
public InstancePresent(EC2Client client) {
|
||||||
this.client = client;
|
this.client = checkNotNull(client, "client");
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean apply(RunningInstance instance) {
|
public boolean apply(RegionAndName instance) {
|
||||||
logger.trace("looking for instance %s", instance);
|
logger.trace("looking for instance %s/%s", instance.getRegion(), instance.getName());
|
||||||
try {
|
try {
|
||||||
instance = refresh(instance);
|
refresh(instance);
|
||||||
return true;
|
return true;
|
||||||
} catch (ResourceNotFoundException e) {
|
} catch (ResourceNotFoundException e) {
|
||||||
return false;
|
return false;
|
||||||
|
@ -64,8 +64,8 @@ public class InstancePresent implements Predicate<RunningInstance> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private RunningInstance refresh(RunningInstance instance) {
|
protected void refresh(RegionAndName instance) {
|
||||||
return Iterables.getOnlyElement(Iterables.getOnlyElement(client.getInstanceServices().describeInstancesInRegion(
|
Iterables.getOnlyElement(Iterables.getOnlyElement(client.getInstanceServices().describeInstancesInRegion(
|
||||||
instance.getRegion(), instance.getId())));
|
instance.getRegion(), instance.getName())));
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -19,10 +19,10 @@
|
||||||
|
|
||||||
package org.jclouds.ec2.compute.strategy;
|
package org.jclouds.ec2.compute.strategy;
|
||||||
|
|
||||||
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
import static com.google.common.collect.Iterables.all;
|
import static com.google.common.collect.Iterables.all;
|
||||||
import static com.google.common.collect.Iterables.transform;
|
import static com.google.common.collect.Iterables.transform;
|
||||||
import static org.jclouds.ec2.compute.util.EC2ComputeUtils.getZoneFromLocationOrNull;
|
import static org.jclouds.ec2.compute.util.EC2ComputeUtils.getZoneFromLocationOrNull;
|
||||||
import static org.jclouds.ec2.compute.util.EC2ComputeUtils.instanceToId;
|
|
||||||
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
@ -44,6 +44,8 @@ import org.jclouds.compute.strategy.CreateNodesInGroupThenAddToSet;
|
||||||
import org.jclouds.compute.util.ComputeUtils;
|
import org.jclouds.compute.util.ComputeUtils;
|
||||||
import org.jclouds.domain.Credentials;
|
import org.jclouds.domain.Credentials;
|
||||||
import org.jclouds.ec2.EC2Client;
|
import org.jclouds.ec2.EC2Client;
|
||||||
|
import org.jclouds.ec2.compute.domain.RegionAndName;
|
||||||
|
import org.jclouds.ec2.compute.predicates.InstancePresent;
|
||||||
import org.jclouds.ec2.domain.RunningInstance;
|
import org.jclouds.ec2.domain.RunningInstance;
|
||||||
import org.jclouds.ec2.options.RunInstancesOptions;
|
import org.jclouds.ec2.options.RunInstancesOptions;
|
||||||
import org.jclouds.logging.Logger;
|
import org.jclouds.logging.Logger;
|
||||||
|
@ -51,7 +53,6 @@ import org.jclouds.logging.Logger;
|
||||||
import com.google.common.annotations.VisibleForTesting;
|
import com.google.common.annotations.VisibleForTesting;
|
||||||
import com.google.common.base.Function;
|
import com.google.common.base.Function;
|
||||||
import com.google.common.base.Joiner;
|
import com.google.common.base.Joiner;
|
||||||
import com.google.common.base.Predicate;
|
|
||||||
import com.google.common.collect.ImmutableSet;
|
import com.google.common.collect.ImmutableSet;
|
||||||
import com.google.common.collect.Iterables;
|
import com.google.common.collect.Iterables;
|
||||||
import com.google.common.collect.Multimap;
|
import com.google.common.collect.Multimap;
|
||||||
|
@ -76,49 +77,58 @@ public class EC2CreateNodesInGroupThenAddToSet implements CreateNodesInGroupThen
|
||||||
final Function<RunningInstance, NodeMetadata> runningInstanceToNodeMetadata;
|
final Function<RunningInstance, NodeMetadata> runningInstanceToNodeMetadata;
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
final ComputeUtils utils;
|
final ComputeUtils utils;
|
||||||
final Predicate<RunningInstance> instancePresent;
|
final InstancePresent instancePresent;
|
||||||
final Function<RunningInstance, Credentials> instanceToCredentials;
|
final Function<RunningInstance, Credentials> instanceToCredentials;
|
||||||
final Map<String, Credentials> credentialStore;
|
final Map<String, Credentials> credentialStore;
|
||||||
final Provider<TemplateBuilder> templateBuilderProvider;
|
final Provider<TemplateBuilder> templateBuilderProvider;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
EC2CreateNodesInGroupThenAddToSet(
|
protected EC2CreateNodesInGroupThenAddToSet(
|
||||||
EC2Client client,
|
EC2Client client,
|
||||||
Provider<TemplateBuilder> templateBuilderProvider,
|
Provider<TemplateBuilder> templateBuilderProvider,
|
||||||
CreateKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions createKeyPairAndSecurityGroupsAsNeededAndReturncustomize,
|
CreateKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions createKeyPairAndSecurityGroupsAsNeededAndReturncustomize,
|
||||||
@Named("PRESENT") Predicate<RunningInstance> instancePresent,
|
InstancePresent instancePresent, Function<RunningInstance, NodeMetadata> runningInstanceToNodeMetadata,
|
||||||
Function<RunningInstance, NodeMetadata> runningInstanceToNodeMetadata,
|
Function<RunningInstance, Credentials> instanceToCredentials, Map<String, Credentials> credentialStore,
|
||||||
Function<RunningInstance, Credentials> instanceToCredentials, Map<String, Credentials> credentialStore,
|
ComputeUtils utils) {
|
||||||
ComputeUtils utils) {
|
this.client = checkNotNull(client, "client");
|
||||||
this.client = client;
|
this.templateBuilderProvider = checkNotNull(templateBuilderProvider, "templateBuilderProvider");
|
||||||
this.templateBuilderProvider = templateBuilderProvider;
|
this.instancePresent = checkNotNull(instancePresent, "instancePresent");
|
||||||
this.instancePresent = instancePresent;
|
this.createKeyPairAndSecurityGroupsAsNeededAndReturncustomize = checkNotNull(
|
||||||
this.createKeyPairAndSecurityGroupsAsNeededAndReturncustomize = createKeyPairAndSecurityGroupsAsNeededAndReturncustomize;
|
createKeyPairAndSecurityGroupsAsNeededAndReturncustomize,
|
||||||
this.runningInstanceToNodeMetadata = runningInstanceToNodeMetadata;
|
"createKeyPairAndSecurityGroupsAsNeededAndReturncustomize");
|
||||||
this.instanceToCredentials = instanceToCredentials;
|
this.runningInstanceToNodeMetadata = checkNotNull(runningInstanceToNodeMetadata, "runningInstanceToNodeMetadata");
|
||||||
this.credentialStore = credentialStore;
|
this.instanceToCredentials = checkNotNull(instanceToCredentials, "instanceToCredentials");
|
||||||
this.utils = utils;
|
this.credentialStore = checkNotNull(credentialStore, "credentialStore");
|
||||||
|
this.utils = checkNotNull(utils, "utils");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static Function<RunningInstance, RegionAndName> instanceToRegionAndName = new Function<RunningInstance, RegionAndName>() {
|
||||||
|
@Override
|
||||||
|
public RegionAndName apply(RunningInstance from) {
|
||||||
|
return new RegionAndName(from.getRegion(), from.getId());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Map<?, Future<Void>> execute(String group, int count, Template template, Set<NodeMetadata> goodNodes,
|
public Map<?, Future<Void>> execute(String group, int count, Template template, Set<NodeMetadata> goodNodes,
|
||||||
Map<NodeMetadata, Exception> badNodes, Multimap<NodeMetadata, CustomizationResponse> customizationResponses) {
|
Map<NodeMetadata, Exception> badNodes, Multimap<NodeMetadata, CustomizationResponse> customizationResponses) {
|
||||||
// ensure we don't mutate the input template
|
// ensure we don't mutate the input template
|
||||||
template = templateBuilderProvider.get().fromTemplate(template).build();
|
template = templateBuilderProvider.get().fromTemplate(template).build();
|
||||||
Iterable<? extends RunningInstance> started = createKeyPairAndSecurityGroupsAsNeededThenRunInstances(group,
|
Iterable<? extends RunningInstance> started = createKeyPairAndSecurityGroupsAsNeededThenRunInstances(group,
|
||||||
count, template);
|
count, template);
|
||||||
Iterable<String> ids = transform(started, instanceToId);
|
|
||||||
|
Iterable<RegionAndName> ids = transform(started, instanceToRegionAndName);
|
||||||
|
|
||||||
String idsString = Joiner.on(',').join(ids);
|
String idsString = Joiner.on(',').join(ids);
|
||||||
if (Iterables.size(ids) > 0) {
|
if (Iterables.size(ids) > 0) {
|
||||||
logger.debug("<< started instances(%s)", idsString);
|
logger.debug("<< started instances(%s)", idsString);
|
||||||
all(started, instancePresent);
|
all(ids, instancePresent);
|
||||||
logger.debug("<< present instances(%s)", idsString);
|
logger.debug("<< present instances(%s)", idsString);
|
||||||
populateCredentials(started);
|
populateCredentials(started);
|
||||||
}
|
}
|
||||||
|
|
||||||
return utils.customizeNodesAndAddToGoodMapOrPutExceptionIntoBadMap(template.getOptions(),
|
return utils.customizeNodesAndAddToGoodMapOrPutExceptionIntoBadMap(template.getOptions(), transform(started,
|
||||||
transform(started, runningInstanceToNodeMetadata), goodNodes, badNodes, customizationResponses);
|
runningInstanceToNodeMetadata), goodNodes, badNodes, customizationResponses);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void populateCredentials(Iterable<? extends RunningInstance> started) {
|
protected void populateCredentials(Iterable<? extends RunningInstance> started) {
|
||||||
|
@ -131,19 +141,20 @@ public class EC2CreateNodesInGroupThenAddToSet implements CreateNodesInGroupThen
|
||||||
if (credentials != null)
|
if (credentials != null)
|
||||||
for (RunningInstance instance : started)
|
for (RunningInstance instance : started)
|
||||||
credentialStore.put("node#" + instance.getRegion() + "/" + instance.getId(), credentials);
|
credentialStore.put("node#" + instance.getRegion() + "/" + instance.getId(), credentials);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO write test for this
|
// TODO write test for this
|
||||||
@VisibleForTesting
|
protected Iterable<? extends RunningInstance> createKeyPairAndSecurityGroupsAsNeededThenRunInstances(String group,
|
||||||
Iterable<? extends RunningInstance> createKeyPairAndSecurityGroupsAsNeededThenRunInstances(String group, int count,
|
int count, Template template) {
|
||||||
Template template) {
|
|
||||||
String region = AWSUtils.getRegionFromLocationOrNull(template.getLocation());
|
String region = AWSUtils.getRegionFromLocationOrNull(template.getLocation());
|
||||||
String zone = getZoneFromLocationOrNull(template.getLocation());
|
String zone = getZoneFromLocationOrNull(template.getLocation());
|
||||||
|
|
||||||
RunInstancesOptions instanceOptions = createKeyPairAndSecurityGroupsAsNeededAndReturncustomize.execute(region,
|
RunInstancesOptions instanceOptions = createKeyPairAndSecurityGroupsAsNeededAndReturncustomize.execute(region,
|
||||||
group, template);
|
group, template);
|
||||||
|
return createNodesInRegionAndZone(region, zone, count, template, instanceOptions);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Iterable<? extends RunningInstance> createNodesInRegionAndZone(String region, String zone, int count,
|
||||||
|
Template template, RunInstancesOptions instanceOptions) {
|
||||||
int countStarted = 0;
|
int countStarted = 0;
|
||||||
int tries = 0;
|
int tries = 0;
|
||||||
Iterable<? extends RunningInstance> started = ImmutableSet.<RunningInstance> of();
|
Iterable<? extends RunningInstance> started = ImmutableSet.<RunningInstance> of();
|
||||||
|
@ -151,12 +162,10 @@ public class EC2CreateNodesInGroupThenAddToSet implements CreateNodesInGroupThen
|
||||||
while (countStarted < count && tries++ < count) {
|
while (countStarted < count && tries++ < count) {
|
||||||
if (logger.isDebugEnabled())
|
if (logger.isDebugEnabled())
|
||||||
logger.debug(">> running %d instance region(%s) zone(%s) ami(%s) params(%s)", count - countStarted, region,
|
logger.debug(">> running %d instance region(%s) zone(%s) ami(%s) params(%s)", count - countStarted, region,
|
||||||
zone, template.getImage().getProviderId(), instanceOptions.buildFormParameters());
|
zone, template.getImage().getProviderId(), instanceOptions.buildFormParameters());
|
||||||
|
|
||||||
started = Iterables.concat(
|
started = Iterables.concat(started, client.getInstanceServices().runInstancesInRegion(region, zone,
|
||||||
started,
|
template.getImage().getProviderId(), 1, count - countStarted, instanceOptions));
|
||||||
client.getInstanceServices().runInstancesInRegion(region, zone, template.getImage().getProviderId(), 1,
|
|
||||||
count - countStarted, instanceOptions));
|
|
||||||
|
|
||||||
countStarted = Iterables.size(started);
|
countStarted = Iterables.size(started);
|
||||||
if (countStarted < count)
|
if (countStarted < count)
|
||||||
|
|
|
@ -19,6 +19,8 @@
|
||||||
|
|
||||||
package org.jclouds.ec2.compute.strategy;
|
package org.jclouds.ec2.compute.strategy;
|
||||||
|
|
||||||
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
import javax.inject.Named;
|
import javax.inject.Named;
|
||||||
|
@ -41,14 +43,13 @@ public class EC2DestroyNodeStrategy implements DestroyNodeStrategy {
|
||||||
@Resource
|
@Resource
|
||||||
@Named(ComputeServiceConstants.COMPUTE_LOGGER)
|
@Named(ComputeServiceConstants.COMPUTE_LOGGER)
|
||||||
protected Logger logger = Logger.NULL;
|
protected Logger logger = Logger.NULL;
|
||||||
protected final EC2Client ec2Client;
|
protected final EC2Client client;
|
||||||
protected final GetNodeMetadataStrategy getNode;
|
protected final GetNodeMetadataStrategy getNode;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
protected EC2DestroyNodeStrategy(EC2Client ec2Client,
|
protected EC2DestroyNodeStrategy(EC2Client client, GetNodeMetadataStrategy getNode) {
|
||||||
GetNodeMetadataStrategy getNodeMetadataStrategy) {
|
this.client = checkNotNull(client, "client");
|
||||||
this.ec2Client = ec2Client;
|
this.getNode = checkNotNull(getNode, "getNode");
|
||||||
this.getNode = getNodeMetadataStrategy;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -56,8 +57,11 @@ public class EC2DestroyNodeStrategy implements DestroyNodeStrategy {
|
||||||
String[] parts = AWSUtils.parseHandle(id);
|
String[] parts = AWSUtils.parseHandle(id);
|
||||||
String region = parts[0];
|
String region = parts[0];
|
||||||
String instanceId = parts[1];
|
String instanceId = parts[1];
|
||||||
ec2Client.getInstanceServices().terminateInstancesInRegion(region,
|
destroyInstanceInRegion(region, instanceId);
|
||||||
instanceId);
|
|
||||||
return getNode.getNode(id);
|
return getNode.getNode(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected void destroyInstanceInRegion(String region, String instanceId) {
|
||||||
|
client.getInstanceServices().terminateInstancesInRegion(region, instanceId);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
|
|
||||||
package org.jclouds.ec2.compute.strategy;
|
package org.jclouds.ec2.compute.strategy;
|
||||||
|
|
||||||
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
import static com.google.common.collect.Iterables.getOnlyElement;
|
import static com.google.common.collect.Iterables.getOnlyElement;
|
||||||
|
|
||||||
import java.util.NoSuchElementException;
|
import java.util.NoSuchElementException;
|
||||||
|
@ -31,7 +32,6 @@ import org.jclouds.compute.domain.NodeMetadata;
|
||||||
import org.jclouds.compute.strategy.GetNodeMetadataStrategy;
|
import org.jclouds.compute.strategy.GetNodeMetadataStrategy;
|
||||||
import org.jclouds.ec2.EC2Client;
|
import org.jclouds.ec2.EC2Client;
|
||||||
import org.jclouds.ec2.domain.RunningInstance;
|
import org.jclouds.ec2.domain.RunningInstance;
|
||||||
import org.jclouds.ec2.services.InstanceClient;
|
|
||||||
|
|
||||||
import com.google.common.base.Function;
|
import com.google.common.base.Function;
|
||||||
import com.google.common.collect.Iterables;
|
import com.google.common.collect.Iterables;
|
||||||
|
@ -48,28 +48,27 @@ public class EC2GetNodeMetadataStrategy implements GetNodeMetadataStrategy {
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
protected EC2GetNodeMetadataStrategy(EC2Client client,
|
protected EC2GetNodeMetadataStrategy(EC2Client client,
|
||||||
Function<RunningInstance, NodeMetadata> runningInstanceToNodeMetadata) {
|
Function<RunningInstance, NodeMetadata> runningInstanceToNodeMetadata) {
|
||||||
this.client = client;
|
this.client = checkNotNull(client, "client");
|
||||||
this.runningInstanceToNodeMetadata = runningInstanceToNodeMetadata;
|
this.runningInstanceToNodeMetadata = checkNotNull(runningInstanceToNodeMetadata, "runningInstanceToNodeMetadata");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public NodeMetadata getNode(String id) {
|
public NodeMetadata getNode(String id) {
|
||||||
|
checkNotNull(id, "id");
|
||||||
String[] parts = AWSUtils.parseHandle(id);
|
String[] parts = AWSUtils.parseHandle(id);
|
||||||
String region = parts[0];
|
String region = parts[0];
|
||||||
String instanceId = parts[1];
|
String instanceId = parts[1];
|
||||||
try {
|
try {
|
||||||
RunningInstance runningInstance = getOnlyElement(getAllRunningInstancesInRegion(client.getInstanceServices(),
|
RunningInstance runningInstance = getRunningInstanceInRegion(region, instanceId);
|
||||||
region, instanceId));
|
|
||||||
return runningInstanceToNodeMetadata.apply(runningInstance);
|
return runningInstanceToNodeMetadata.apply(runningInstance);
|
||||||
} catch (NoSuchElementException e) {
|
} catch (NoSuchElementException e) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Iterable<RunningInstance> getAllRunningInstancesInRegion(InstanceClient client, String region,
|
public RunningInstance getRunningInstanceInRegion(String region, String id) {
|
||||||
String id) {
|
return getOnlyElement(Iterables.concat(client.getInstanceServices().describeInstancesInRegion(region, id)));
|
||||||
return Iterables.concat(client.describeInstancesInRegion(region, id));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,10 +19,12 @@
|
||||||
|
|
||||||
package org.jclouds.ec2.compute.strategy;
|
package org.jclouds.ec2.compute.strategy;
|
||||||
|
|
||||||
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
|
import static com.google.common.base.Predicates.and;
|
||||||
|
import static com.google.common.base.Predicates.notNull;
|
||||||
import static com.google.common.collect.Iterables.concat;
|
import static com.google.common.collect.Iterables.concat;
|
||||||
import static com.google.common.collect.Iterables.filter;
|
import static com.google.common.collect.Iterables.filter;
|
||||||
import static com.google.common.collect.Iterables.transform;
|
import static com.google.common.collect.Iterables.transform;
|
||||||
import static com.google.common.collect.Sets.newLinkedHashSet;
|
|
||||||
import static org.jclouds.concurrent.FutureIterables.transformParallel;
|
import static org.jclouds.concurrent.FutureIterables.transformParallel;
|
||||||
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
@ -35,19 +37,20 @@ import javax.inject.Named;
|
||||||
import javax.inject.Singleton;
|
import javax.inject.Singleton;
|
||||||
|
|
||||||
import org.jclouds.Constants;
|
import org.jclouds.Constants;
|
||||||
import org.jclouds.ec2.EC2AsyncClient;
|
|
||||||
import org.jclouds.ec2.domain.Reservation;
|
|
||||||
import org.jclouds.ec2.domain.RunningInstance;
|
|
||||||
import org.jclouds.compute.domain.ComputeMetadata;
|
import org.jclouds.compute.domain.ComputeMetadata;
|
||||||
import org.jclouds.compute.domain.NodeMetadata;
|
import org.jclouds.compute.domain.NodeMetadata;
|
||||||
import org.jclouds.compute.predicates.NodePredicates;
|
import org.jclouds.compute.predicates.NodePredicates;
|
||||||
import org.jclouds.compute.reference.ComputeServiceConstants;
|
import org.jclouds.compute.reference.ComputeServiceConstants;
|
||||||
import org.jclouds.compute.strategy.ListNodesStrategy;
|
import org.jclouds.compute.strategy.ListNodesStrategy;
|
||||||
|
import org.jclouds.ec2.EC2AsyncClient;
|
||||||
|
import org.jclouds.ec2.domain.Reservation;
|
||||||
|
import org.jclouds.ec2.domain.RunningInstance;
|
||||||
import org.jclouds.location.Region;
|
import org.jclouds.location.Region;
|
||||||
import org.jclouds.logging.Logger;
|
import org.jclouds.logging.Logger;
|
||||||
|
|
||||||
import com.google.common.base.Function;
|
import com.google.common.base.Function;
|
||||||
import com.google.common.base.Predicate;
|
import com.google.common.base.Predicate;
|
||||||
|
import com.google.common.collect.ImmutableSet;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
|
@ -59,19 +62,19 @@ public class EC2ListNodesStrategy implements ListNodesStrategy {
|
||||||
@Named(ComputeServiceConstants.COMPUTE_LOGGER)
|
@Named(ComputeServiceConstants.COMPUTE_LOGGER)
|
||||||
protected Logger logger = Logger.NULL;
|
protected Logger logger = Logger.NULL;
|
||||||
|
|
||||||
private final EC2AsyncClient client;
|
protected final EC2AsyncClient client;
|
||||||
private final Set<String> regions;
|
protected final Set<String> regions;
|
||||||
private final Function<RunningInstance, NodeMetadata> runningInstanceToNodeMetadata;
|
protected final Function<RunningInstance, NodeMetadata> runningInstanceToNodeMetadata;
|
||||||
private final ExecutorService executor;
|
protected final ExecutorService executor;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
protected EC2ListNodesStrategy(EC2AsyncClient client, @Region Set<String> regions,
|
protected EC2ListNodesStrategy(EC2AsyncClient client, @Region Set<String> regions,
|
||||||
Function<RunningInstance, NodeMetadata> runningInstanceToNodeMetadata,
|
Function<RunningInstance, NodeMetadata> runningInstanceToNodeMetadata,
|
||||||
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService executor) {
|
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService executor) {
|
||||||
this.client = client;
|
this.client = checkNotNull(client, "client");
|
||||||
this.regions = regions;
|
this.regions = checkNotNull(regions, "regions");
|
||||||
this.runningInstanceToNodeMetadata = runningInstanceToNodeMetadata;
|
this.runningInstanceToNodeMetadata = checkNotNull(runningInstanceToNodeMetadata, "runningInstanceToNodeMetadata");
|
||||||
this.executor = executor;
|
this.executor = checkNotNull(executor, "executor");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -81,19 +84,25 @@ public class EC2ListNodesStrategy implements ListNodesStrategy {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Set<? extends NodeMetadata> listDetailsOnNodesMatching(Predicate<ComputeMetadata> filter) {
|
public Set<? extends NodeMetadata> listDetailsOnNodesMatching(Predicate<ComputeMetadata> filter) {
|
||||||
|
Iterable<? extends RunningInstance> instances = pollRunningInstances();
|
||||||
|
Iterable<? extends NodeMetadata> nodes = filter(transform(filter(instances, notNull()),
|
||||||
|
runningInstanceToNodeMetadata), and(notNull(), filter));
|
||||||
|
return ImmutableSet.copyOf(nodes);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Iterable<? extends RunningInstance> pollRunningInstances() {
|
||||||
Iterable<? extends Set<? extends Reservation<? extends RunningInstance>>> reservations = transformParallel(
|
Iterable<? extends Set<? extends Reservation<? extends RunningInstance>>> reservations = transformParallel(
|
||||||
regions, new Function<String, Future<Set<? extends Reservation<? extends RunningInstance>>>>() {
|
regions, new Function<String, Future<Set<? extends Reservation<? extends RunningInstance>>>>() {
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
@Override
|
@Override
|
||||||
public Future<Set<? extends Reservation<? extends RunningInstance>>> apply(String from) {
|
public Future<Set<? extends Reservation<? extends RunningInstance>>> apply(String from) {
|
||||||
return (Future<Set<? extends Reservation<? extends RunningInstance>>>) client.getInstanceServices().describeInstancesInRegion(from);
|
return (Future<Set<? extends Reservation<? extends RunningInstance>>>) client
|
||||||
}
|
.getInstanceServices().describeInstancesInRegion(from);
|
||||||
|
}
|
||||||
|
|
||||||
}, executor, null, logger, "reservations");
|
}, executor, null, logger, "reservations");
|
||||||
|
|
||||||
Iterable<? extends RunningInstance> instances = concat(concat(reservations));
|
return concat(concat(reservations));
|
||||||
Iterable<? extends NodeMetadata> nodes = filter(transform(instances, runningInstanceToNodeMetadata), filter);
|
|
||||||
return newLinkedHashSet(nodes);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,12 +21,9 @@ package org.jclouds.ec2.compute.util;
|
||||||
|
|
||||||
import javax.inject.Singleton;
|
import javax.inject.Singleton;
|
||||||
|
|
||||||
import org.jclouds.ec2.domain.RunningInstance;
|
|
||||||
import org.jclouds.domain.Location;
|
import org.jclouds.domain.Location;
|
||||||
import org.jclouds.domain.LocationScope;
|
import org.jclouds.domain.LocationScope;
|
||||||
|
|
||||||
import com.google.common.base.Function;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @author Adrian Cole
|
* @author Adrian Cole
|
||||||
|
@ -34,13 +31,6 @@ import com.google.common.base.Function;
|
||||||
@Singleton
|
@Singleton
|
||||||
public class EC2ComputeUtils {
|
public class EC2ComputeUtils {
|
||||||
|
|
||||||
public static Function<RunningInstance, String> instanceToId = new Function<RunningInstance, String>() {
|
|
||||||
@Override
|
|
||||||
public String apply(RunningInstance from) {
|
|
||||||
return from.getId();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
public static String getZoneFromLocationOrNull(Location location) {
|
public static String getZoneFromLocationOrNull(Location location) {
|
||||||
return location.getScope() == LocationScope.ZONE ? location.getId() : null;
|
return location.getScope() == LocationScope.ZONE ? location.getId() : null;
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,7 +30,64 @@ import org.jclouds.util.Preconditions2;
|
||||||
*
|
*
|
||||||
* @author Lili Nadar
|
* @author Lili Nadar
|
||||||
*/
|
*/
|
||||||
public class BlockDeviceMapping {
|
public class BlockDeviceMapping implements Comparable<BlockDeviceMapping>{
|
||||||
|
public static Builder builder() {
|
||||||
|
return new Builder();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Builder {
|
||||||
|
private String deviceName;
|
||||||
|
private String virtualName;
|
||||||
|
private String snapshotId;
|
||||||
|
private Integer sizeInGib;
|
||||||
|
private Boolean noDevice;
|
||||||
|
private Boolean deleteOnTermination;
|
||||||
|
|
||||||
|
public Builder deviceName(String deviceName) {
|
||||||
|
this.deviceName = deviceName;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder virtualName(String virtualName) {
|
||||||
|
this.virtualName = virtualName;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder snapshotId(String snapshotId) {
|
||||||
|
this.snapshotId = snapshotId;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder sizeInGib(Integer sizeInGib) {
|
||||||
|
this.sizeInGib = sizeInGib;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder noDevice(Boolean noDevice) {
|
||||||
|
this.noDevice = noDevice;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder deleteOnTermination(Boolean deleteOnTermination) {
|
||||||
|
this.deleteOnTermination = deleteOnTermination;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public BlockDeviceMapping build() {
|
||||||
|
return new BlockDeviceMapping(deviceName, virtualName, snapshotId, sizeInGib, noDevice, deleteOnTermination);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder clear() {
|
||||||
|
this.deviceName = null;
|
||||||
|
this.virtualName = null;
|
||||||
|
this.snapshotId = null;
|
||||||
|
this.sizeInGib = null;
|
||||||
|
this.noDevice = null;
|
||||||
|
this.deleteOnTermination = null;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private final String deviceName;
|
private final String deviceName;
|
||||||
private final String virtualName;
|
private final String virtualName;
|
||||||
private final String snapshotId;
|
private final String snapshotId;
|
||||||
|
@ -43,14 +100,14 @@ public class BlockDeviceMapping {
|
||||||
private static final Integer VOLUME_SIZE_MAX_VALUE = 1000;
|
private static final Integer VOLUME_SIZE_MAX_VALUE = 1000;
|
||||||
|
|
||||||
BlockDeviceMapping(String deviceName, @Nullable String virtualName, @Nullable String snapshotId,
|
BlockDeviceMapping(String deviceName, @Nullable String virtualName, @Nullable String snapshotId,
|
||||||
@Nullable Integer sizeInGib, @Nullable Boolean noDevice, @Nullable Boolean deleteOnTermination) {
|
@Nullable Integer sizeInGib, @Nullable Boolean noDevice, @Nullable Boolean deleteOnTermination) {
|
||||||
|
|
||||||
checkNotNull(deviceName, "deviceName cannot be null");
|
checkNotNull(deviceName, "deviceName cannot be null");
|
||||||
Preconditions2.checkNotEmpty(deviceName, "the deviceName must be non-empty");
|
Preconditions2.checkNotEmpty(deviceName, "the deviceName must be non-empty");
|
||||||
|
|
||||||
if (sizeInGib != null) {
|
if (sizeInGib != null) {
|
||||||
checkArgument((sizeInGib >= VOLUME_SIZE_MIN_VALUE && sizeInGib <= VOLUME_SIZE_MAX_VALUE), String.format(
|
checkArgument((sizeInGib >= VOLUME_SIZE_MIN_VALUE && sizeInGib <= VOLUME_SIZE_MAX_VALUE),
|
||||||
"Size in Gib must be between %s and %s GB", VOLUME_SIZE_MIN_VALUE, VOLUME_SIZE_MAX_VALUE));
|
String.format("Size in Gib must be between %s and %s GB", VOLUME_SIZE_MIN_VALUE, VOLUME_SIZE_MAX_VALUE));
|
||||||
}
|
}
|
||||||
this.deviceName = deviceName;
|
this.deviceName = deviceName;
|
||||||
this.virtualName = virtualName;
|
this.virtualName = virtualName;
|
||||||
|
@ -142,13 +199,13 @@ public class BlockDeviceMapping {
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "[deviceName=" + deviceName + ", virtualName=" + virtualName + ", snapshotId=" + snapshotId
|
return "[deviceName=" + deviceName + ", virtualName=" + virtualName + ", snapshotId=" + snapshotId
|
||||||
+ ", sizeInGib=" + sizeInGib + ", noDevice=" + noDevice + ", deleteOnTermination=" + deleteOnTermination
|
+ ", sizeInGib=" + sizeInGib + ", noDevice=" + noDevice + ", deleteOnTermination=" + deleteOnTermination
|
||||||
+ "]";
|
+ "]";
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class MapEBSSnapshotToDevice extends BlockDeviceMapping {
|
public static class MapEBSSnapshotToDevice extends BlockDeviceMapping {
|
||||||
public MapEBSSnapshotToDevice(String deviceName, String snapshotId, @Nullable Integer sizeInGib,
|
public MapEBSSnapshotToDevice(String deviceName, String snapshotId, @Nullable Integer sizeInGib,
|
||||||
@Nullable Boolean deleteOnTermination) {
|
@Nullable Boolean deleteOnTermination) {
|
||||||
super(deviceName, null, snapshotId, sizeInGib, null, deleteOnTermination);
|
super(deviceName, null, snapshotId, sizeInGib, null, deleteOnTermination);
|
||||||
checkNotNull(snapshotId, "snapshotId cannot be null");
|
checkNotNull(snapshotId, "snapshotId cannot be null");
|
||||||
Preconditions2.checkNotEmpty(snapshotId, "the snapshotId must be non-empty");
|
Preconditions2.checkNotEmpty(snapshotId, "the snapshotId must be non-empty");
|
||||||
|
@ -175,4 +232,9 @@ public class BlockDeviceMapping {
|
||||||
super(deviceName, null, null, null, true, null);
|
super(deviceName, null, null, null, true, null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int compareTo(BlockDeviceMapping arg0) {
|
||||||
|
return deviceName.compareTo(arg0.deviceName);
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -39,6 +39,9 @@ import com.google.common.collect.Sets;
|
||||||
* @author Adrian Cole
|
* @author Adrian Cole
|
||||||
*/
|
*/
|
||||||
public class RunningInstance implements Comparable<RunningInstance> {
|
public class RunningInstance implements Comparable<RunningInstance> {
|
||||||
|
public static Builder builder() {
|
||||||
|
return new Builder();
|
||||||
|
}
|
||||||
|
|
||||||
public static class Builder {
|
public static class Builder {
|
||||||
protected String region;
|
protected String region;
|
||||||
|
@ -265,8 +268,8 @@ public class RunningInstance implements Comparable<RunningInstance> {
|
||||||
this.ipAddress = ipAddress;
|
this.ipAddress = ipAddress;
|
||||||
this.kernelId = kernelId;
|
this.kernelId = kernelId;
|
||||||
this.keyName = keyName;
|
this.keyName = keyName;
|
||||||
this.launchTime = checkNotNull(launchTime, "launchTime");
|
this.launchTime = launchTime;// nullable on spot.
|
||||||
this.availabilityZone = checkNotNull(availabilityZone, "availabilityZone");
|
this.availabilityZone = availabilityZone;// nullable on spot.
|
||||||
this.virtualizationType = virtualizationType;
|
this.virtualizationType = virtualizationType;
|
||||||
this.platform = platform;
|
this.platform = platform;
|
||||||
this.privateDnsName = privateDnsName;// nullable on runinstances.
|
this.privateDnsName = privateDnsName;// nullable on runinstances.
|
||||||
|
|
|
@ -58,10 +58,6 @@ public class RunInstancesOptions extends BaseEC2RequestOptions {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
String getKeyName() {
|
|
||||||
return getFirstFormOrNull("KeyName");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Attach multiple security groups
|
* Attach multiple security groups
|
||||||
*/
|
*/
|
||||||
|
@ -88,10 +84,6 @@ public class RunInstancesOptions extends BaseEC2RequestOptions {
|
||||||
return withSecurityGroups(securityGroup);
|
return withSecurityGroups(securityGroup);
|
||||||
}
|
}
|
||||||
|
|
||||||
String getSecurityGroup() {
|
|
||||||
return getFirstFormOrNull("SecurityGroup.1");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Unencoded data
|
* Unencoded data
|
||||||
*/
|
*/
|
||||||
|
@ -103,10 +95,6 @@ public class RunInstancesOptions extends BaseEC2RequestOptions {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
String getUserData() {
|
|
||||||
return getFirstFormOrNull("UserData");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Specifies the instance type. default small;
|
* Specifies the instance type. default small;
|
||||||
*/
|
*/
|
||||||
|
@ -115,10 +103,6 @@ public class RunInstancesOptions extends BaseEC2RequestOptions {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
String getType() {
|
|
||||||
return getFirstFormOrNull("InstanceType");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The ID of the kernel with which to launch the instance.
|
* The ID of the kernel with which to launch the instance.
|
||||||
*/
|
*/
|
||||||
|
@ -127,10 +111,6 @@ public class RunInstancesOptions extends BaseEC2RequestOptions {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
String getKernelId() {
|
|
||||||
return getFirstFormOrNull("KernelId");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The ID of the RAM disk with which to launch the instance. Some kernels require additional
|
* The ID of the RAM disk with which to launch the instance. Some kernels require additional
|
||||||
* drivers at l aunch. Check the kernel requirements for information on whether you need to
|
* drivers at l aunch. Check the kernel requirements for information on whether you need to
|
||||||
|
@ -142,15 +122,10 @@ public class RunInstancesOptions extends BaseEC2RequestOptions {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
String getRamdiskId() {
|
|
||||||
return getFirstFormOrNull("RamdiskId");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Specifies the Block Device Mapping for the instance
|
* Specifies the Block Device Mapping for the instance
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public RunInstancesOptions withBlockDeviceMappings(Set<? extends BlockDeviceMapping> mappings) {
|
public RunInstancesOptions withBlockDeviceMappings(Set<? extends BlockDeviceMapping> mappings) {
|
||||||
int i = 1;
|
int i = 1;
|
||||||
for (BlockDeviceMapping mapping : checkNotNull(mappings, "mappings")) {
|
for (BlockDeviceMapping mapping : checkNotNull(mappings, "mappings")) {
|
||||||
|
@ -161,15 +136,14 @@ public class RunInstancesOptions extends BaseEC2RequestOptions {
|
||||||
if (mapping.getEbsSnapshotId() != null)
|
if (mapping.getEbsSnapshotId() != null)
|
||||||
formParameters.put(String.format("BlockDeviceMapping.%d.Ebs.SnapshotId", i), mapping.getEbsSnapshotId());
|
formParameters.put(String.format("BlockDeviceMapping.%d.Ebs.SnapshotId", i), mapping.getEbsSnapshotId());
|
||||||
if (mapping.getEbsVolumeSize() != null)
|
if (mapping.getEbsVolumeSize() != null)
|
||||||
formParameters.put(String.format("BlockDeviceMapping.%d.Ebs.VolumeSize", i), String.valueOf(mapping
|
formParameters.put(String.format("BlockDeviceMapping.%d.Ebs.VolumeSize", i),
|
||||||
.getEbsVolumeSize()));
|
String.valueOf(mapping.getEbsVolumeSize()));
|
||||||
if (mapping.getEbsNoDevice() != null)
|
if (mapping.getEbsNoDevice() != null)
|
||||||
formParameters.put(String.format("BlockDeviceMapping.%d.Ebs.NoDevice", i), String.valueOf(mapping
|
formParameters.put(String.format("BlockDeviceMapping.%d.Ebs.NoDevice", i),
|
||||||
.getEbsNoDevice()));
|
String.valueOf(mapping.getEbsNoDevice()));
|
||||||
if (mapping.getEbsDeleteOnTermination() != null)
|
if (mapping.getEbsDeleteOnTermination() != null)
|
||||||
formParameters.put(String.format("BlockDeviceMapping.%d.Ebs.DeleteOnTermination", i), String
|
formParameters.put(String.format("BlockDeviceMapping.%d.Ebs.DeleteOnTermination", i),
|
||||||
.valueOf(mapping.getEbsDeleteOnTermination()));
|
String.valueOf(mapping.getEbsDeleteOnTermination()));
|
||||||
|
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
return this;
|
return this;
|
||||||
|
|
|
@ -26,8 +26,9 @@ import java.util.Set;
|
||||||
import org.jclouds.http.options.BaseHttpRequestOptions;
|
import org.jclouds.http.options.BaseHttpRequestOptions;
|
||||||
|
|
||||||
import com.google.common.base.Predicate;
|
import com.google.common.base.Predicate;
|
||||||
|
import com.google.common.collect.ImmutableSet;
|
||||||
|
import com.google.common.collect.ImmutableSet.Builder;
|
||||||
import com.google.common.collect.Iterables;
|
import com.google.common.collect.Iterables;
|
||||||
import com.google.common.collect.Sets;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
|
@ -51,7 +52,7 @@ public class BaseEC2RequestOptions extends BaseHttpRequestOptions {
|
||||||
}
|
}
|
||||||
|
|
||||||
protected Set<String> getFormValuesWithKeysPrefixedBy(final String prefix) {
|
protected Set<String> getFormValuesWithKeysPrefixedBy(final String prefix) {
|
||||||
Set<String> values = Sets.newLinkedHashSet();
|
Builder<String> values = ImmutableSet.<String> builder();
|
||||||
for (String key : Iterables.filter(formParameters.keySet(), new Predicate<String>() {
|
for (String key : Iterables.filter(formParameters.keySet(), new Predicate<String>() {
|
||||||
|
|
||||||
public boolean apply(String input) {
|
public boolean apply(String input) {
|
||||||
|
@ -59,10 +60,9 @@ public class BaseEC2RequestOptions extends BaseHttpRequestOptions {
|
||||||
}
|
}
|
||||||
|
|
||||||
})) {
|
})) {
|
||||||
values.add(formParameters.get(key).iterator().next());
|
values.add(Iterables.get(formParameters.get(key), 0));
|
||||||
|
|
||||||
}
|
}
|
||||||
return values;
|
return values.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -42,8 +42,10 @@ import org.jclouds.domain.Location;
|
||||||
import org.jclouds.domain.LocationBuilder;
|
import org.jclouds.domain.LocationBuilder;
|
||||||
import org.jclouds.domain.LocationScope;
|
import org.jclouds.domain.LocationScope;
|
||||||
import org.jclouds.ec2.EC2Client;
|
import org.jclouds.ec2.EC2Client;
|
||||||
|
import org.jclouds.ec2.compute.domain.RegionAndName;
|
||||||
import org.jclouds.ec2.compute.functions.RunningInstanceToNodeMetadata;
|
import org.jclouds.ec2.compute.functions.RunningInstanceToNodeMetadata;
|
||||||
import org.jclouds.ec2.compute.options.EC2TemplateOptions;
|
import org.jclouds.ec2.compute.options.EC2TemplateOptions;
|
||||||
|
import org.jclouds.ec2.compute.predicates.InstancePresent;
|
||||||
import org.jclouds.ec2.domain.Reservation;
|
import org.jclouds.ec2.domain.Reservation;
|
||||||
import org.jclouds.ec2.domain.RunningInstance;
|
import org.jclouds.ec2.domain.RunningInstance;
|
||||||
import org.jclouds.ec2.options.RunInstancesOptions;
|
import org.jclouds.ec2.options.RunInstancesOptions;
|
||||||
|
@ -51,7 +53,6 @@ import org.jclouds.ec2.services.InstanceClient;
|
||||||
import org.testng.annotations.Test;
|
import org.testng.annotations.Test;
|
||||||
|
|
||||||
import com.google.common.base.Function;
|
import com.google.common.base.Function;
|
||||||
import com.google.common.base.Predicate;
|
|
||||||
import com.google.common.collect.ImmutableSet;
|
import com.google.common.collect.ImmutableSet;
|
||||||
import com.google.common.collect.Iterables;
|
import com.google.common.collect.Iterables;
|
||||||
import com.google.common.collect.Multimap;
|
import com.google.common.collect.Multimap;
|
||||||
|
@ -61,7 +62,7 @@ import com.google.inject.util.Providers;
|
||||||
* @author Adrian Cole
|
* @author Adrian Cole
|
||||||
*/
|
*/
|
||||||
@Test(groups = "unit")
|
@Test(groups = "unit")
|
||||||
public class EC2RunNodesAndAddToSetStrategyTest {
|
public class EC2CreateNodesInGroupThenAddToSetTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testZoneAsALocation() {
|
public void testZoneAsALocation() {
|
||||||
|
@ -126,10 +127,10 @@ public class EC2RunNodesAndAddToSetStrategyTest {
|
||||||
// simulate a lazy credentials fetch
|
// simulate a lazy credentials fetch
|
||||||
Credentials creds = new Credentials("foo", "bar");
|
Credentials creds = new Credentials("foo", "bar");
|
||||||
expect(strategy.instanceToCredentials.apply(instance)).andReturn(creds);
|
expect(strategy.instanceToCredentials.apply(instance)).andReturn(creds);
|
||||||
expect(instance.getRegion()).andReturn(region);
|
expect(instance.getRegion()).andReturn(region).atLeastOnce();
|
||||||
expect(strategy.credentialStore.put("node#" + region + "/" + instanceCreatedId, creds)).andReturn(null);
|
expect(strategy.credentialStore.put("node#" + region + "/" + instanceCreatedId, creds)).andReturn(null);
|
||||||
|
|
||||||
expect(strategy.instancePresent.apply(instance)).andReturn(true);
|
expect(strategy.instancePresent.apply(new RegionAndName(region, instanceCreatedId))).andReturn(true);
|
||||||
expect(input.template.getOptions()).andReturn(input.options).atLeastOnce();
|
expect(input.template.getOptions()).andReturn(input.options).atLeastOnce();
|
||||||
|
|
||||||
expect(strategy.runningInstanceToNodeMetadata.apply(instance)).andReturn(nodeMetadata);
|
expect(strategy.runningInstanceToNodeMetadata.apply(instance)).andReturn(nodeMetadata);
|
||||||
|
@ -220,13 +221,13 @@ public class EC2RunNodesAndAddToSetStrategyTest {
|
||||||
private EC2CreateNodesInGroupThenAddToSet setupStrategy(TemplateBuilder template) {
|
private EC2CreateNodesInGroupThenAddToSet setupStrategy(TemplateBuilder template) {
|
||||||
EC2Client client = createMock(EC2Client.class);
|
EC2Client client = createMock(EC2Client.class);
|
||||||
CreateKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions createKeyPairAndSecurityGroupsAsNeededAndReturncustomize = createMock(CreateKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions.class);
|
CreateKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions createKeyPairAndSecurityGroupsAsNeededAndReturncustomize = createMock(CreateKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions.class);
|
||||||
Predicate<RunningInstance> instanceStateRunning = createMock(Predicate.class);
|
InstancePresent instancePresent = createMock(InstancePresent.class);
|
||||||
RunningInstanceToNodeMetadata runningInstanceToNodeMetadata = createMock(RunningInstanceToNodeMetadata.class);
|
RunningInstanceToNodeMetadata runningInstanceToNodeMetadata = createMock(RunningInstanceToNodeMetadata.class);
|
||||||
Function<RunningInstance, Credentials> instanceToCredentials = createMock(Function.class);
|
Function<RunningInstance, Credentials> instanceToCredentials = createMock(Function.class);
|
||||||
Map<String, Credentials> credentialStore = createMock(Map.class);
|
Map<String, Credentials> credentialStore = createMock(Map.class);
|
||||||
ComputeUtils utils = createMock(ComputeUtils.class);
|
ComputeUtils utils = createMock(ComputeUtils.class);
|
||||||
return new EC2CreateNodesInGroupThenAddToSet(client, Providers.<TemplateBuilder> of(template),
|
return new EC2CreateNodesInGroupThenAddToSet(client, Providers.<TemplateBuilder> of(template),
|
||||||
createKeyPairAndSecurityGroupsAsNeededAndReturncustomize, instanceStateRunning,
|
createKeyPairAndSecurityGroupsAsNeededAndReturncustomize, instancePresent,
|
||||||
runningInstanceToNodeMetadata, instanceToCredentials, credentialStore, utils);
|
runningInstanceToNodeMetadata, instanceToCredentials, credentialStore, utils);
|
||||||
}
|
}
|
||||||
|
|
|
@ -65,6 +65,8 @@ public class NodePresentAndInIntendedState implements Predicate<NodeMetadata> {
|
||||||
}
|
}
|
||||||
|
|
||||||
private NodeMetadata refresh(NodeMetadata node) {
|
private NodeMetadata refresh(NodeMetadata node) {
|
||||||
|
if (node == null || node.getId() == null)
|
||||||
|
return null;
|
||||||
return client.getNodeMetadata(node.getId());
|
return client.getNodeMetadata(node.getId());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,6 +22,7 @@ package org.jclouds.compute.strategy;
|
||||||
import static com.google.common.base.Preconditions.checkNotNull;
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
import static com.google.common.base.Preconditions.checkState;
|
import static com.google.common.base.Preconditions.checkState;
|
||||||
import static com.google.common.base.Throwables.getRootCause;
|
import static com.google.common.base.Throwables.getRootCause;
|
||||||
|
import static java.lang.String.format;
|
||||||
import static org.jclouds.compute.util.ComputeServiceUtils.findReachableSocketOnNode;
|
import static org.jclouds.compute.util.ComputeServiceUtils.findReachableSocketOnNode;
|
||||||
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
@ -36,6 +37,7 @@ import org.jclouds.compute.callables.RunScriptOnNode;
|
||||||
import org.jclouds.compute.config.CustomizationResponse;
|
import org.jclouds.compute.config.CustomizationResponse;
|
||||||
import org.jclouds.compute.domain.ExecResponse;
|
import org.jclouds.compute.domain.ExecResponse;
|
||||||
import org.jclouds.compute.domain.NodeMetadata;
|
import org.jclouds.compute.domain.NodeMetadata;
|
||||||
|
import org.jclouds.compute.domain.NodeState;
|
||||||
import org.jclouds.compute.options.TemplateOptions;
|
import org.jclouds.compute.options.TemplateOptions;
|
||||||
import org.jclouds.compute.predicates.RetryIfSocketNotYetOpen;
|
import org.jclouds.compute.predicates.RetryIfSocketNotYetOpen;
|
||||||
import org.jclouds.compute.reference.ComputeServiceConstants;
|
import org.jclouds.compute.reference.ComputeServiceConstants;
|
||||||
|
@ -125,15 +127,24 @@ public class CustomizeNodeAndAddToGoodMapOrPutExceptionIntoBadMap implements Cal
|
||||||
public Void call() {
|
public Void call() {
|
||||||
checkState(!tainted, "this object is not designed to be reused: %s", toString());
|
checkState(!tainted, "this object is not designed to be reused: %s", toString());
|
||||||
tainted = true;
|
tainted = true;
|
||||||
|
String originalId = node.getId();
|
||||||
|
NodeMetadata originalNode = node;
|
||||||
try {
|
try {
|
||||||
if (options.shouldBlockUntilRunning()) {
|
if (options.shouldBlockUntilRunning()) {
|
||||||
if (nodeRunning.apply(node)) {
|
if (nodeRunning.apply(node)) {
|
||||||
node = getNode.getNode(node.getId());
|
node = getNode.getNode(originalId);
|
||||||
} else {
|
} else {
|
||||||
throw new IllegalStateException(String.format(
|
NodeMetadata nodeForState = getNode.getNode(originalId);
|
||||||
"node didn't achieve the state running on node %s within %d seconds, final state: %s", node
|
NodeState state = nodeForState == null ? NodeState.TERMINATED : nodeForState.getState();
|
||||||
.getId(), timeouts.nodeRunning / 1000, node.getState()));
|
if (state == NodeState.TERMINATED)
|
||||||
|
throw new IllegalStateException(format("node(%s) terminated before we could customize", originalId));
|
||||||
|
else
|
||||||
|
throw new IllegalStateException(format(
|
||||||
|
"node(%s) didn't achieve the state running within %d seconds, final state: %s", originalId,
|
||||||
|
timeouts.nodeRunning / 1000, state));
|
||||||
}
|
}
|
||||||
|
if (node == null)
|
||||||
|
throw new IllegalStateException(format("node %s terminated before applying options", originalId));
|
||||||
if (statement != null) {
|
if (statement != null) {
|
||||||
RunScriptOnNode runner = initScriptRunnerFactory.create(node, statement, options, badNodes).call();
|
RunScriptOnNode runner = initScriptRunnerFactory.create(node, statement, options, badNodes).call();
|
||||||
if (runner != null) {
|
if (runner != null) {
|
||||||
|
@ -145,11 +156,11 @@ public class CustomizeNodeAndAddToGoodMapOrPutExceptionIntoBadMap implements Cal
|
||||||
findReachableSocketOnNode(socketTester.seconds(options.getSeconds()), node, options.getPort());
|
findReachableSocketOnNode(socketTester.seconds(options.getSeconds()), node, options.getPort());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
logger.debug("<< options applied node(%s)", node.getId());
|
logger.debug("<< options applied node(%s)", originalId);
|
||||||
goodNodes.add(node);
|
goodNodes.add(node);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
logger.error(e, "<< problem applying options to node(%s): ", node.getId(), getRootCause(e).getMessage());
|
logger.error(e, "<< problem applying options to node(%s): ", originalId, getRootCause(e).getMessage());
|
||||||
badNodes.put(node, e);
|
badNodes.put(node == null ? originalNode : node, e);
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
|
@ -301,7 +301,7 @@ public class TemplateBuilderImplTest {
|
||||||
TemplateBuilder defaultTemplate = createMock(TemplateBuilder.class);
|
TemplateBuilder defaultTemplate = createMock(TemplateBuilder.class);
|
||||||
|
|
||||||
expect(templateBuilderProvider.get()).andReturn(defaultTemplate);
|
expect(templateBuilderProvider.get()).andReturn(defaultTemplate);
|
||||||
expect(defaultTemplate.options(options)).andReturn(defaultTemplate);
|
expect(defaultTemplate.options(from)).andReturn(defaultTemplate);
|
||||||
expect(defaultTemplate.build()).andReturn(null);
|
expect(defaultTemplate.build()).andReturn(null);
|
||||||
expect(optionsProvider.get()).andReturn(from).atLeastOnce();
|
expect(optionsProvider.get()).andReturn(from).atLeastOnce();
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,144 @@
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
|
||||||
|
*
|
||||||
|
* ====================================================================
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
* ====================================================================
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jclouds.compute.strategy;
|
||||||
|
|
||||||
|
import static org.easymock.EasyMock.expect;
|
||||||
|
import static org.easymock.classextension.EasyMock.createMock;
|
||||||
|
import static org.easymock.classextension.EasyMock.replay;
|
||||||
|
import static org.easymock.classextension.EasyMock.verify;
|
||||||
|
import static org.testng.Assert.assertEquals;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import org.jclouds.compute.config.CustomizationResponse;
|
||||||
|
import org.jclouds.compute.domain.NodeMetadata;
|
||||||
|
import org.jclouds.compute.domain.NodeMetadataBuilder;
|
||||||
|
import org.jclouds.compute.domain.NodeState;
|
||||||
|
import org.jclouds.compute.functions.TemplateOptionsToStatement;
|
||||||
|
import org.jclouds.compute.options.TemplateOptions;
|
||||||
|
import org.jclouds.compute.predicates.RetryIfSocketNotYetOpen;
|
||||||
|
import org.jclouds.compute.reference.ComputeServiceConstants.Timeouts;
|
||||||
|
import org.jclouds.scriptbuilder.domain.Statement;
|
||||||
|
import org.testng.annotations.Test;
|
||||||
|
|
||||||
|
import com.google.common.base.Function;
|
||||||
|
import com.google.common.base.Predicate;
|
||||||
|
import com.google.common.collect.ImmutableSet;
|
||||||
|
import com.google.common.collect.LinkedHashMultimap;
|
||||||
|
import com.google.common.collect.Maps;
|
||||||
|
import com.google.common.collect.Multimap;
|
||||||
|
import com.google.common.collect.Sets;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Adrian Cole
|
||||||
|
*/
|
||||||
|
@Test(groups = "unit")
|
||||||
|
public class CustomizeNodeAndAddToGoodMapOrPutExceptionIntoBadMapTest {
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public void testBreakWhenNodeStillPending() {
|
||||||
|
Predicate<NodeMetadata> nodeRunning = createMock(Predicate.class);
|
||||||
|
InitializeRunScriptOnNodeOrPlaceInBadMap.Factory initScriptRunnerFactory = createMock(InitializeRunScriptOnNodeOrPlaceInBadMap.Factory.class);
|
||||||
|
GetNodeMetadataStrategy getNode = createMock(GetNodeMetadataStrategy.class);
|
||||||
|
RetryIfSocketNotYetOpen socketTester = createMock(RetryIfSocketNotYetOpen.class);
|
||||||
|
Timeouts timeouts = new Timeouts();
|
||||||
|
Function<TemplateOptions, Statement> templateOptionsToStatement = new TemplateOptionsToStatement();
|
||||||
|
@SuppressWarnings("unused")
|
||||||
|
Statement statement = null;
|
||||||
|
TemplateOptions options = new TemplateOptions();
|
||||||
|
Set<NodeMetadata> goodNodes = Sets.newLinkedHashSet();
|
||||||
|
Map<NodeMetadata, Exception> badNodes = Maps.newLinkedHashMap();
|
||||||
|
Multimap<NodeMetadata, CustomizationResponse> customizationResponses = LinkedHashMultimap.create();
|
||||||
|
|
||||||
|
NodeMetadata node = new NodeMetadataBuilder().ids("id").state(NodeState.PENDING).build();
|
||||||
|
|
||||||
|
// node never reached running state
|
||||||
|
expect(nodeRunning.apply(node)).andReturn(false);
|
||||||
|
expect(getNode.getNode(node.getId())).andReturn(node);
|
||||||
|
|
||||||
|
// replay mocks
|
||||||
|
replay(nodeRunning);
|
||||||
|
replay(initScriptRunnerFactory);
|
||||||
|
replay(getNode);
|
||||||
|
replay(socketTester);
|
||||||
|
|
||||||
|
// run
|
||||||
|
new CustomizeNodeAndAddToGoodMapOrPutExceptionIntoBadMap(nodeRunning, getNode, socketTester, timeouts,
|
||||||
|
templateOptionsToStatement, initScriptRunnerFactory, options, node, goodNodes, badNodes,
|
||||||
|
customizationResponses).apply(node);
|
||||||
|
|
||||||
|
assertEquals(goodNodes.size(), 0);
|
||||||
|
assertEquals(badNodes.keySet(), ImmutableSet.of(node));
|
||||||
|
assertEquals(badNodes.get(node).getMessage(),
|
||||||
|
"node(id) didn't achieve the state running within 1200 seconds, final state: PENDING");
|
||||||
|
assertEquals(customizationResponses.size(), 0);
|
||||||
|
|
||||||
|
// verify mocks
|
||||||
|
verify(nodeRunning);
|
||||||
|
verify(initScriptRunnerFactory);
|
||||||
|
verify(getNode);
|
||||||
|
verify(socketTester);
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public void testBreakGraceFullyWhenNodeDied() {
|
||||||
|
Predicate<NodeMetadata> nodeRunning = createMock(Predicate.class);
|
||||||
|
InitializeRunScriptOnNodeOrPlaceInBadMap.Factory initScriptRunnerFactory = createMock(InitializeRunScriptOnNodeOrPlaceInBadMap.Factory.class);
|
||||||
|
GetNodeMetadataStrategy getNode = createMock(GetNodeMetadataStrategy.class);
|
||||||
|
RetryIfSocketNotYetOpen socketTester = createMock(RetryIfSocketNotYetOpen.class);
|
||||||
|
Timeouts timeouts = new Timeouts();
|
||||||
|
Function<TemplateOptions, Statement> templateOptionsToStatement = new TemplateOptionsToStatement();
|
||||||
|
@SuppressWarnings("unused")
|
||||||
|
Statement statement = null;
|
||||||
|
TemplateOptions options = new TemplateOptions();
|
||||||
|
Set<NodeMetadata> goodNodes = Sets.newLinkedHashSet();
|
||||||
|
Map<NodeMetadata, Exception> badNodes = Maps.newLinkedHashMap();
|
||||||
|
Multimap<NodeMetadata, CustomizationResponse> customizationResponses = LinkedHashMultimap.create();
|
||||||
|
|
||||||
|
NodeMetadata node = new NodeMetadataBuilder().ids("id").state(NodeState.PENDING).build();
|
||||||
|
|
||||||
|
// node never reached running state
|
||||||
|
expect(nodeRunning.apply(node)).andReturn(false);
|
||||||
|
expect(getNode.getNode(node.getId())).andReturn(null);
|
||||||
|
|
||||||
|
// replay mocks
|
||||||
|
replay(nodeRunning);
|
||||||
|
replay(initScriptRunnerFactory);
|
||||||
|
replay(getNode);
|
||||||
|
replay(socketTester);
|
||||||
|
|
||||||
|
// run
|
||||||
|
new CustomizeNodeAndAddToGoodMapOrPutExceptionIntoBadMap(nodeRunning, getNode, socketTester, timeouts,
|
||||||
|
templateOptionsToStatement, initScriptRunnerFactory, options, node, goodNodes, badNodes,
|
||||||
|
customizationResponses).apply(node);
|
||||||
|
|
||||||
|
assertEquals(goodNodes.size(), 0);
|
||||||
|
assertEquals(badNodes.keySet(), ImmutableSet.of(node));
|
||||||
|
assertEquals(badNodes.get(node).getMessage(), "node(id) terminated before we could customize");
|
||||||
|
assertEquals(customizationResponses.size(), 0);
|
||||||
|
|
||||||
|
// verify mocks
|
||||||
|
verify(nodeRunning);
|
||||||
|
verify(initScriptRunnerFactory);
|
||||||
|
verify(getNode);
|
||||||
|
verify(socketTester);
|
||||||
|
}
|
||||||
|
}
|
|
@ -19,14 +19,16 @@
|
||||||
|
|
||||||
package org.jclouds.predicates;
|
package org.jclouds.predicates;
|
||||||
|
|
||||||
|
import static org.jclouds.util.Throwables2.getFirstThrowableOfType;
|
||||||
|
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.concurrent.ExecutionException;
|
import java.util.concurrent.ExecutionException;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
import java.util.concurrent.TimeoutException;
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
|
|
||||||
import org.jclouds.logging.Logger;
|
import org.jclouds.logging.Logger;
|
||||||
import org.jclouds.util.Throwables2;
|
|
||||||
|
|
||||||
import com.google.common.base.Predicate;
|
import com.google.common.base.Predicate;
|
||||||
|
|
||||||
|
@ -75,10 +77,16 @@ public class RetryablePredicate<T> implements Predicate<T> {
|
||||||
} catch (InterruptedException e) {
|
} catch (InterruptedException e) {
|
||||||
logger.warn(e, "predicate %s on %s interrupted, returning false", input, predicate);
|
logger.warn(e, "predicate %s on %s interrupted, returning false", input, predicate);
|
||||||
} catch (RuntimeException e) {
|
} catch (RuntimeException e) {
|
||||||
ExecutionException exec = Throwables2.getFirstThrowableOfType(e, ExecutionException.class);
|
if (getFirstThrowableOfType(e, ExecutionException.class) != null) {
|
||||||
if (exec != null)
|
logger.warn(e, "predicate %s on %s errored [%s], returning false", input, predicate, e.getMessage());
|
||||||
logger.warn(exec, "predicate %s on %s error, returning false", input, predicate);
|
return false;
|
||||||
else
|
} else if (getFirstThrowableOfType(e, IllegalStateException.class) != null) {
|
||||||
|
logger.warn(e, "predicate %s on %s illegal state [%s], returning false", input, predicate, e.getMessage());
|
||||||
|
return false;
|
||||||
|
} else if (getFirstThrowableOfType(e, TimeoutException.class) != null) {
|
||||||
|
logger.warn(e, "predicate %s on %s timed out [%s], returning false", input, predicate, e.getMessage());
|
||||||
|
return false;
|
||||||
|
} else
|
||||||
throw e;
|
throw e;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -20,12 +20,15 @@
|
||||||
package org.jclouds.predicates;
|
package org.jclouds.predicates;
|
||||||
|
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
import java.util.concurrent.ExecutionException;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
import java.util.concurrent.TimeoutException;
|
||||||
|
|
||||||
import org.testng.annotations.Test;
|
import org.testng.annotations.Test;
|
||||||
|
|
||||||
import com.google.common.base.Predicate;
|
import com.google.common.base.Predicate;
|
||||||
import com.google.common.base.Predicates;
|
import com.google.common.base.Predicates;
|
||||||
|
import com.google.common.base.Supplier;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
|
@ -36,6 +39,56 @@ import com.google.common.base.Predicates;
|
||||||
public class RetryablePredicateTest {
|
public class RetryablePredicateTest {
|
||||||
public static int SLOW_BUILD_SERVER_GRACE = 50;
|
public static int SLOW_BUILD_SERVER_GRACE = 50;
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testFalseOnIllegalStateExeception() {
|
||||||
|
ensureImmediateReturnFor(new IllegalStateException());
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("serial")
|
||||||
|
@Test
|
||||||
|
void testFalseOnExecutionException() {
|
||||||
|
ensureImmediateReturnFor(new ExecutionException() {
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("serial")
|
||||||
|
@Test
|
||||||
|
void testFalseOnTimeoutException() {
|
||||||
|
ensureImmediateReturnFor(new TimeoutException() {
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("serial")
|
||||||
|
@Test(expectedExceptions = RuntimeException.class)
|
||||||
|
void testPropagateOnException() {
|
||||||
|
ensureImmediateReturnFor(new Exception() {
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ensureImmediateReturnFor(final Exception ex) {
|
||||||
|
RetryablePredicate<Supplier<String>> predicate = new RetryablePredicate<Supplier<String>>(
|
||||||
|
new Predicate<Supplier<String>>() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean apply(Supplier<String> input) {
|
||||||
|
return "goo".equals(input.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
}, 3, 1, TimeUnit.SECONDS);
|
||||||
|
Date startPlusThird = new Date(System.currentTimeMillis() + 1000);
|
||||||
|
assert !predicate.apply(new Supplier<String>() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String get() {
|
||||||
|
throw new RuntimeException(ex);
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
Date now = new Date();
|
||||||
|
assert now.compareTo(startPlusThird) < 0 : String.format("%s should be less than %s", now.getTime(),
|
||||||
|
startPlusThird.getTime());
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void testAlwaysTrue() {
|
void testAlwaysTrue() {
|
||||||
RetryablePredicate<String> predicate = new RetryablePredicate<String>(Predicates.<String> alwaysTrue(), 3, 1,
|
RetryablePredicate<String> predicate = new RetryablePredicate<String>(Predicates.<String> alwaysTrue(), 3, 1,
|
||||||
|
|
|
@ -24,6 +24,7 @@ import org.jclouds.aws.ec2.services.AWSInstanceAsyncClient;
|
||||||
import org.jclouds.aws.ec2.services.AWSKeyPairAsyncClient;
|
import org.jclouds.aws.ec2.services.AWSKeyPairAsyncClient;
|
||||||
import org.jclouds.aws.ec2.services.MonitoringAsyncClient;
|
import org.jclouds.aws.ec2.services.MonitoringAsyncClient;
|
||||||
import org.jclouds.aws.ec2.services.PlacementGroupAsyncClient;
|
import org.jclouds.aws.ec2.services.PlacementGroupAsyncClient;
|
||||||
|
import org.jclouds.aws.ec2.services.SpotInstanceAsyncClient;
|
||||||
import org.jclouds.ec2.EC2AsyncClient;
|
import org.jclouds.ec2.EC2AsyncClient;
|
||||||
import org.jclouds.rest.annotations.Delegate;
|
import org.jclouds.rest.annotations.Delegate;
|
||||||
|
|
||||||
|
@ -67,4 +68,10 @@ public interface AWSEC2AsyncClient extends EC2AsyncClient {
|
||||||
@Delegate
|
@Delegate
|
||||||
@Override
|
@Override
|
||||||
AWSKeyPairAsyncClient getKeyPairServices();
|
AWSKeyPairAsyncClient getKeyPairServices();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides asynchronous access to SpotInstance services.
|
||||||
|
*/
|
||||||
|
@Delegate
|
||||||
|
SpotInstanceAsyncClient getSpotInstanceServices();
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,6 +26,7 @@ import org.jclouds.aws.ec2.services.AWSInstanceClient;
|
||||||
import org.jclouds.aws.ec2.services.AWSKeyPairClient;
|
import org.jclouds.aws.ec2.services.AWSKeyPairClient;
|
||||||
import org.jclouds.aws.ec2.services.MonitoringClient;
|
import org.jclouds.aws.ec2.services.MonitoringClient;
|
||||||
import org.jclouds.aws.ec2.services.PlacementGroupClient;
|
import org.jclouds.aws.ec2.services.PlacementGroupClient;
|
||||||
|
import org.jclouds.aws.ec2.services.SpotInstanceClient;
|
||||||
import org.jclouds.concurrent.Timeout;
|
import org.jclouds.concurrent.Timeout;
|
||||||
import org.jclouds.ec2.EC2Client;
|
import org.jclouds.ec2.EC2Client;
|
||||||
import org.jclouds.rest.annotations.Delegate;
|
import org.jclouds.rest.annotations.Delegate;
|
||||||
|
@ -70,4 +71,10 @@ public interface AWSEC2Client extends EC2Client {
|
||||||
@Delegate
|
@Delegate
|
||||||
@Override
|
@Override
|
||||||
AWSKeyPairClient getKeyPairServices();
|
AWSKeyPairClient getKeyPairServices();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides synchronous access to SpotInstance services.
|
||||||
|
*/
|
||||||
|
@Delegate
|
||||||
|
SpotInstanceClient getSpotInstanceServices();
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,65 @@
|
||||||
|
package org.jclouds.aws.ec2.binders;
|
||||||
|
|
||||||
|
import static com.google.common.base.Preconditions.checkArgument;
|
||||||
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Map.Entry;
|
||||||
|
|
||||||
|
import javax.inject.Singleton;
|
||||||
|
|
||||||
|
import org.jclouds.aws.ec2.domain.LaunchSpecification;
|
||||||
|
import org.jclouds.aws.ec2.options.AWSRunInstancesOptions;
|
||||||
|
import org.jclouds.http.HttpRequest;
|
||||||
|
import org.jclouds.http.utils.ModifyRequest;
|
||||||
|
import org.jclouds.rest.Binder;
|
||||||
|
|
||||||
|
import com.google.common.base.Function;
|
||||||
|
import com.google.common.collect.ImmutableMap;
|
||||||
|
import com.google.common.collect.ImmutableMap.Builder;
|
||||||
|
import com.google.common.collect.Multimaps;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Adrian Cole
|
||||||
|
*/
|
||||||
|
@Singleton
|
||||||
|
public class BindLaunchSpecificationToFormParams implements Binder, Function<LaunchSpecification, Map<String, String>> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <R extends HttpRequest> R bindToRequest(R request, Object input) {
|
||||||
|
checkArgument(input instanceof LaunchSpecification, "this binder is only valid for LaunchSpecifications!");
|
||||||
|
LaunchSpecification launchSpec = LaunchSpecification.class.cast(input);
|
||||||
|
return ModifyRequest.putFormParams(request, Multimaps.forMap(apply(launchSpec)));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Map<String, String> apply(LaunchSpecification launchSpec) {
|
||||||
|
Builder<String, String> builder = ImmutableMap.<String, String> builder();
|
||||||
|
builder.put("LaunchSpecification.ImageId", checkNotNull(launchSpec.getImageId(), "imageId"));
|
||||||
|
if (launchSpec.getAvailabilityZone() != null)
|
||||||
|
builder.put("LaunchSpecification.Placement.AvailabilityZone", launchSpec.getAvailabilityZone());
|
||||||
|
|
||||||
|
AWSRunInstancesOptions options = new AWSRunInstancesOptions();
|
||||||
|
if (launchSpec.getBlockDeviceMappings().size() > 0)
|
||||||
|
options.withBlockDeviceMappings(launchSpec.getBlockDeviceMappings());
|
||||||
|
if (launchSpec.getGroupIds().size() > 0)
|
||||||
|
options.withSecurityGroups(launchSpec.getGroupIds());
|
||||||
|
options.asType(checkNotNull(launchSpec.getInstanceType(), "instanceType"));
|
||||||
|
if (launchSpec.getKernelId() != null)
|
||||||
|
options.withKernelId(launchSpec.getKernelId());
|
||||||
|
if (launchSpec.getKeyName() != null)
|
||||||
|
options.withKeyName(launchSpec.getKeyName());
|
||||||
|
if (launchSpec.getRamdiskId() != null)
|
||||||
|
options.withRamdisk(launchSpec.getRamdiskId());
|
||||||
|
if (Boolean.TRUE.equals(launchSpec.isMonitoringEnabled()))
|
||||||
|
options.enableMonitoring();
|
||||||
|
if (launchSpec.getUserData() != null)
|
||||||
|
options.withUserData(launchSpec.getUserData());
|
||||||
|
|
||||||
|
for (Entry<String, String> entry : options.buildFormParameters().entries()) {
|
||||||
|
builder.put("LaunchSpecification." + entry.getKey(), entry.getValue());
|
||||||
|
}
|
||||||
|
return builder.build();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,40 @@
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
|
||||||
|
*
|
||||||
|
* ====================================================================
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
* ====================================================================
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jclouds.aws.ec2.binders;
|
||||||
|
|
||||||
|
import javax.inject.Singleton;
|
||||||
|
|
||||||
|
import org.jclouds.aws.util.AWSUtils;
|
||||||
|
import org.jclouds.http.HttpRequest;
|
||||||
|
import org.jclouds.rest.Binder;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Binds the String [] to form parameters named with SpotInstanceRequestId.index
|
||||||
|
*
|
||||||
|
* @author Adrian Cole
|
||||||
|
*/
|
||||||
|
@Singleton
|
||||||
|
public class BindSpotInstanceRequestIdsToIndexedFormParams implements Binder {
|
||||||
|
@Override
|
||||||
|
public <R extends HttpRequest> R bindToRequest(R request, Object input) {
|
||||||
|
return AWSUtils.indexStringArrayToFormValuesWithPrefix(request, "SpotInstanceRequestId", input);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -27,6 +27,7 @@ import java.util.Set;
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
|
import org.jclouds.aws.ec2.options.RequestSpotInstancesOptions;
|
||||||
import org.jclouds.compute.options.TemplateOptions;
|
import org.jclouds.compute.options.TemplateOptions;
|
||||||
import org.jclouds.domain.Credentials;
|
import org.jclouds.domain.Credentials;
|
||||||
import org.jclouds.ec2.compute.options.EC2TemplateOptions;
|
import org.jclouds.ec2.compute.options.EC2TemplateOptions;
|
||||||
|
@ -73,6 +74,10 @@ public class AWSEC2TemplateOptions extends EC2TemplateOptions implements Cloneab
|
||||||
eTo.noPlacementGroup();
|
eTo.noPlacementGroup();
|
||||||
if (getPlacementGroup() != null)
|
if (getPlacementGroup() != null)
|
||||||
eTo.placementGroup(getPlacementGroup());
|
eTo.placementGroup(getPlacementGroup());
|
||||||
|
if (getSpotPrice() != null)
|
||||||
|
eTo.spotPrice(getSpotPrice());
|
||||||
|
if (getSpotOptions() != null)
|
||||||
|
eTo.spotOptions(getSpotOptions());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -80,6 +85,8 @@ public class AWSEC2TemplateOptions extends EC2TemplateOptions implements Cloneab
|
||||||
private String placementGroup = null;
|
private String placementGroup = null;
|
||||||
private boolean noPlacementGroup;
|
private boolean noPlacementGroup;
|
||||||
private String subnetId;
|
private String subnetId;
|
||||||
|
private Float spotPrice;
|
||||||
|
private RequestSpotInstancesOptions spotOptions = RequestSpotInstancesOptions.NONE;
|
||||||
|
|
||||||
public static final AWSEC2TemplateOptions NONE = new AWSEC2TemplateOptions();
|
public static final AWSEC2TemplateOptions NONE = new AWSEC2TemplateOptions();
|
||||||
|
|
||||||
|
@ -123,6 +130,22 @@ public class AWSEC2TemplateOptions extends EC2TemplateOptions implements Cloneab
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Specifies the maximum spot price to use
|
||||||
|
*/
|
||||||
|
public AWSEC2TemplateOptions spotPrice(Float spotPrice) {
|
||||||
|
this.spotPrice = spotPrice;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Options for starting spot instances
|
||||||
|
*/
|
||||||
|
public AWSEC2TemplateOptions spotOptions(RequestSpotInstancesOptions spotOptions) {
|
||||||
|
this.spotOptions = spotOptions != null ? spotOptions : RequestSpotInstancesOptions.NONE;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
public static class Builder {
|
public static class Builder {
|
||||||
/**
|
/**
|
||||||
* @see EC2TemplateOptions#blockDeviceMappings
|
* @see EC2TemplateOptions#blockDeviceMappings
|
||||||
|
@ -136,7 +159,7 @@ public class AWSEC2TemplateOptions extends EC2TemplateOptions implements Cloneab
|
||||||
* @see EC2TemplateOptions#mapEBSSnapshotToDeviceName
|
* @see EC2TemplateOptions#mapEBSSnapshotToDeviceName
|
||||||
*/
|
*/
|
||||||
public static AWSEC2TemplateOptions mapEBSSnapshotToDeviceName(String deviceName, String snapshotId,
|
public static AWSEC2TemplateOptions mapEBSSnapshotToDeviceName(String deviceName, String snapshotId,
|
||||||
@Nullable Integer sizeInGib, boolean deleteOnTermination) {
|
@Nullable Integer sizeInGib, boolean deleteOnTermination) {
|
||||||
AWSEC2TemplateOptions options = new AWSEC2TemplateOptions();
|
AWSEC2TemplateOptions options = new AWSEC2TemplateOptions();
|
||||||
return options.mapEBSSnapshotToDeviceName(deviceName, snapshotId, sizeInGib, deleteOnTermination);
|
return options.mapEBSSnapshotToDeviceName(deviceName, snapshotId, sizeInGib, deleteOnTermination);
|
||||||
}
|
}
|
||||||
|
@ -145,7 +168,7 @@ public class AWSEC2TemplateOptions extends EC2TemplateOptions implements Cloneab
|
||||||
* @see EC2TemplateOptions#mapNewVolumeToDeviceName
|
* @see EC2TemplateOptions#mapNewVolumeToDeviceName
|
||||||
*/
|
*/
|
||||||
public static AWSEC2TemplateOptions mapNewVolumeToDeviceName(String deviceName, int sizeInGib,
|
public static AWSEC2TemplateOptions mapNewVolumeToDeviceName(String deviceName, int sizeInGib,
|
||||||
boolean deleteOnTermination) {
|
boolean deleteOnTermination) {
|
||||||
AWSEC2TemplateOptions options = new AWSEC2TemplateOptions();
|
AWSEC2TemplateOptions options = new AWSEC2TemplateOptions();
|
||||||
return options.mapNewVolumeToDeviceName(deviceName, sizeInGib, deleteOnTermination);
|
return options.mapNewVolumeToDeviceName(deviceName, sizeInGib, deleteOnTermination);
|
||||||
}
|
}
|
||||||
|
@ -280,12 +303,28 @@ public class AWSEC2TemplateOptions extends EC2TemplateOptions implements Cloneab
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see TemplateOptions#withSubnetId
|
* @see TemplateOptions#spotPrice
|
||||||
*/
|
*/
|
||||||
public static AWSEC2TemplateOptions subnetId(String subnetId) {
|
public static AWSEC2TemplateOptions subnetId(String subnetId) {
|
||||||
AWSEC2TemplateOptions options = new AWSEC2TemplateOptions();
|
AWSEC2TemplateOptions options = new AWSEC2TemplateOptions();
|
||||||
return options.subnetId(subnetId);
|
return options.subnetId(subnetId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see TemplateOptions#spotPrice
|
||||||
|
*/
|
||||||
|
public static AWSEC2TemplateOptions spotPrice(Float spotPrice) {
|
||||||
|
AWSEC2TemplateOptions options = new AWSEC2TemplateOptions();
|
||||||
|
return options.spotPrice(spotPrice);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see TemplateOptions#spotOptions
|
||||||
|
*/
|
||||||
|
public static AWSEC2TemplateOptions spotOptions(RequestSpotInstancesOptions spotOptions) {
|
||||||
|
AWSEC2TemplateOptions options = new AWSEC2TemplateOptions();
|
||||||
|
return options.spotOptions(spotOptions);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// methods that only facilitate returning the correct object type
|
// methods that only facilitate returning the correct object type
|
||||||
|
@ -294,7 +333,7 @@ public class AWSEC2TemplateOptions extends EC2TemplateOptions implements Cloneab
|
||||||
* {@inheritDoc}
|
* {@inheritDoc}
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public AWSEC2TemplateOptions blockDeviceMappings(Set<? extends BlockDeviceMapping> blockDeviceMappings) {
|
public AWSEC2TemplateOptions blockDeviceMappings(Iterable<? extends BlockDeviceMapping> blockDeviceMappings) {
|
||||||
return AWSEC2TemplateOptions.class.cast(super.blockDeviceMappings(blockDeviceMappings));
|
return AWSEC2TemplateOptions.class.cast(super.blockDeviceMappings(blockDeviceMappings));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -312,9 +351,9 @@ public class AWSEC2TemplateOptions extends EC2TemplateOptions implements Cloneab
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public AWSEC2TemplateOptions mapEBSSnapshotToDeviceName(String deviceName, String snapshotId, Integer sizeInGib,
|
public AWSEC2TemplateOptions mapEBSSnapshotToDeviceName(String deviceName, String snapshotId, Integer sizeInGib,
|
||||||
boolean deleteOnTermination) {
|
boolean deleteOnTermination) {
|
||||||
return AWSEC2TemplateOptions.class.cast(super.mapEBSSnapshotToDeviceName(deviceName, snapshotId, sizeInGib,
|
return AWSEC2TemplateOptions.class.cast(super.mapEBSSnapshotToDeviceName(deviceName, snapshotId, sizeInGib,
|
||||||
deleteOnTermination));
|
deleteOnTermination));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -331,7 +370,7 @@ public class AWSEC2TemplateOptions extends EC2TemplateOptions implements Cloneab
|
||||||
@Override
|
@Override
|
||||||
public AWSEC2TemplateOptions mapNewVolumeToDeviceName(String deviceName, int sizeInGib, boolean deleteOnTermination) {
|
public AWSEC2TemplateOptions mapNewVolumeToDeviceName(String deviceName, int sizeInGib, boolean deleteOnTermination) {
|
||||||
return AWSEC2TemplateOptions.class.cast(super
|
return AWSEC2TemplateOptions.class.cast(super
|
||||||
.mapNewVolumeToDeviceName(deviceName, sizeInGib, deleteOnTermination));
|
.mapNewVolumeToDeviceName(deviceName, sizeInGib, deleteOnTermination));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -525,6 +564,20 @@ public class AWSEC2TemplateOptions extends EC2TemplateOptions implements Cloneab
|
||||||
return subnetId;
|
return subnetId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return maximum spot price or null.
|
||||||
|
*/
|
||||||
|
public Float getSpotPrice() {
|
||||||
|
return spotPrice;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return options for controlling spot instance requests.
|
||||||
|
*/
|
||||||
|
public RequestSpotInstancesOptions getSpotOptions() {
|
||||||
|
return spotOptions;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
final int prime = 31;
|
final int prime = 31;
|
||||||
|
@ -532,6 +585,8 @@ public class AWSEC2TemplateOptions extends EC2TemplateOptions implements Cloneab
|
||||||
result = prime * result + (monitoringEnabled ? 1231 : 1237);
|
result = prime * result + (monitoringEnabled ? 1231 : 1237);
|
||||||
result = prime * result + (noPlacementGroup ? 1231 : 1237);
|
result = prime * result + (noPlacementGroup ? 1231 : 1237);
|
||||||
result = prime * result + ((placementGroup == null) ? 0 : placementGroup.hashCode());
|
result = prime * result + ((placementGroup == null) ? 0 : placementGroup.hashCode());
|
||||||
|
result = prime * result + ((spotOptions == null) ? 0 : spotOptions.hashCode());
|
||||||
|
result = prime * result + ((spotPrice == null) ? 0 : spotPrice.hashCode());
|
||||||
result = prime * result + ((subnetId == null) ? 0 : subnetId.hashCode());
|
result = prime * result + ((subnetId == null) ? 0 : subnetId.hashCode());
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -554,6 +609,16 @@ public class AWSEC2TemplateOptions extends EC2TemplateOptions implements Cloneab
|
||||||
return false;
|
return false;
|
||||||
} else if (!placementGroup.equals(other.placementGroup))
|
} else if (!placementGroup.equals(other.placementGroup))
|
||||||
return false;
|
return false;
|
||||||
|
if (spotOptions == null) {
|
||||||
|
if (other.spotOptions != null)
|
||||||
|
return false;
|
||||||
|
} else if (!spotOptions.equals(other.spotOptions))
|
||||||
|
return false;
|
||||||
|
if (spotPrice == null) {
|
||||||
|
if (other.spotPrice != null)
|
||||||
|
return false;
|
||||||
|
} else if (!spotPrice.equals(other.spotPrice))
|
||||||
|
return false;
|
||||||
if (subnetId == null) {
|
if (subnetId == null) {
|
||||||
if (other.subnetId != null)
|
if (other.subnetId != null)
|
||||||
return false;
|
return false;
|
||||||
|
@ -566,9 +631,10 @@ public class AWSEC2TemplateOptions extends EC2TemplateOptions implements Cloneab
|
||||||
public String toString() {
|
public String toString() {
|
||||||
|
|
||||||
return "[groupIds=" + getGroupIds() + ", keyPair=" + getKeyPair() + ", noKeyPair="
|
return "[groupIds=" + getGroupIds() + ", keyPair=" + getKeyPair() + ", noKeyPair="
|
||||||
+ !shouldAutomaticallyCreateKeyPair() + ", monitoringEnabled=" + monitoringEnabled + ", placementGroup="
|
+ !shouldAutomaticallyCreateKeyPair() + ", monitoringEnabled=" + monitoringEnabled + ", placementGroup="
|
||||||
+ placementGroup + ", noPlacementGroup=" + noPlacementGroup + ", subnetId=" + subnetId + ", userData="
|
+ placementGroup + ", noPlacementGroup=" + noPlacementGroup + ", subnetId=" + subnetId + ", userData="
|
||||||
+ Arrays.toString(getUserData()) + ", blockDeviceMappings=" + getBlockDeviceMappings() + "]";
|
+ Arrays.toString(getUserData()) + ", blockDeviceMappings=" + getBlockDeviceMappings() + ", spotPrice="
|
||||||
|
+ spotPrice + ", spotOptions=" + spotOptions + "]";
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,14 +22,26 @@ package org.jclouds.aws.ec2.compute.config;
|
||||||
import static org.jclouds.compute.domain.OsFamily.AMZN_LINUX;
|
import static org.jclouds.compute.domain.OsFamily.AMZN_LINUX;
|
||||||
|
|
||||||
import org.jclouds.aws.ec2.compute.AWSEC2TemplateBuilderImpl;
|
import org.jclouds.aws.ec2.compute.AWSEC2TemplateBuilderImpl;
|
||||||
|
import org.jclouds.aws.ec2.compute.functions.AWSRunningInstanceToNodeMetadata;
|
||||||
|
import org.jclouds.aws.ec2.compute.predicates.AWSEC2InstancePresent;
|
||||||
|
import org.jclouds.aws.ec2.compute.strategy.AWSEC2CreateNodesInGroupThenAddToSet;
|
||||||
|
import org.jclouds.aws.ec2.compute.strategy.AWSEC2DestroyNodeStrategy;
|
||||||
|
import org.jclouds.aws.ec2.compute.strategy.AWSEC2GetNodeMetadataStrategy;
|
||||||
|
import org.jclouds.aws.ec2.compute.strategy.AWSEC2ListNodesStrategy;
|
||||||
import org.jclouds.aws.ec2.compute.strategy.AWSEC2ReviseParsedImage;
|
import org.jclouds.aws.ec2.compute.strategy.AWSEC2ReviseParsedImage;
|
||||||
import org.jclouds.aws.ec2.compute.strategy.CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptions;
|
import org.jclouds.aws.ec2.compute.strategy.CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptions;
|
||||||
import org.jclouds.aws.ec2.compute.suppliers.AWSEC2HardwareSupplier;
|
import org.jclouds.aws.ec2.compute.suppliers.AWSEC2HardwareSupplier;
|
||||||
import org.jclouds.aws.ec2.compute.suppliers.AWSRegionAndNameToImageSupplier;
|
import org.jclouds.aws.ec2.compute.suppliers.AWSRegionAndNameToImageSupplier;
|
||||||
import org.jclouds.compute.domain.TemplateBuilder;
|
import org.jclouds.compute.domain.TemplateBuilder;
|
||||||
import org.jclouds.ec2.compute.config.EC2ComputeServiceContextModule;
|
import org.jclouds.ec2.compute.config.EC2ComputeServiceContextModule;
|
||||||
|
import org.jclouds.ec2.compute.functions.RunningInstanceToNodeMetadata;
|
||||||
import org.jclouds.ec2.compute.internal.EC2TemplateBuilderImpl;
|
import org.jclouds.ec2.compute.internal.EC2TemplateBuilderImpl;
|
||||||
|
import org.jclouds.ec2.compute.predicates.InstancePresent;
|
||||||
import org.jclouds.ec2.compute.strategy.CreateKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions;
|
import org.jclouds.ec2.compute.strategy.CreateKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions;
|
||||||
|
import org.jclouds.ec2.compute.strategy.EC2CreateNodesInGroupThenAddToSet;
|
||||||
|
import org.jclouds.ec2.compute.strategy.EC2DestroyNodeStrategy;
|
||||||
|
import org.jclouds.ec2.compute.strategy.EC2GetNodeMetadataStrategy;
|
||||||
|
import org.jclouds.ec2.compute.strategy.EC2ListNodesStrategy;
|
||||||
import org.jclouds.ec2.compute.strategy.ReviseParsedImage;
|
import org.jclouds.ec2.compute.strategy.ReviseParsedImage;
|
||||||
import org.jclouds.ec2.compute.suppliers.EC2HardwareSupplier;
|
import org.jclouds.ec2.compute.suppliers.EC2HardwareSupplier;
|
||||||
import org.jclouds.ec2.compute.suppliers.RegionAndNameToImageSupplier;
|
import org.jclouds.ec2.compute.suppliers.RegionAndNameToImageSupplier;
|
||||||
|
@ -56,6 +68,12 @@ public class AWSEC2ComputeServiceContextModule extends EC2ComputeServiceContextM
|
||||||
bind(EC2HardwareSupplier.class).to(AWSEC2HardwareSupplier.class);
|
bind(EC2HardwareSupplier.class).to(AWSEC2HardwareSupplier.class);
|
||||||
bind(RegionAndNameToImageSupplier.class).to(AWSRegionAndNameToImageSupplier.class);
|
bind(RegionAndNameToImageSupplier.class).to(AWSRegionAndNameToImageSupplier.class);
|
||||||
bind(EC2TemplateBuilderImpl.class).to(AWSEC2TemplateBuilderImpl.class);
|
bind(EC2TemplateBuilderImpl.class).to(AWSEC2TemplateBuilderImpl.class);
|
||||||
|
bind(EC2GetNodeMetadataStrategy.class).to(AWSEC2GetNodeMetadataStrategy.class);
|
||||||
|
bind(EC2ListNodesStrategy.class).to(AWSEC2ListNodesStrategy.class);
|
||||||
|
bind(EC2DestroyNodeStrategy.class).to(AWSEC2DestroyNodeStrategy.class);
|
||||||
|
bind(InstancePresent.class).to(AWSEC2InstancePresent.class);
|
||||||
|
bind(EC2CreateNodesInGroupThenAddToSet.class).to(AWSEC2CreateNodesInGroupThenAddToSet.class);
|
||||||
|
bind(RunningInstanceToNodeMetadata.class).to(AWSRunningInstanceToNodeMetadata.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -0,0 +1,69 @@
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
|
||||||
|
*
|
||||||
|
* ====================================================================
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
* ====================================================================
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jclouds.aws.ec2.compute.functions;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import javax.inject.Inject;
|
||||||
|
import javax.inject.Singleton;
|
||||||
|
|
||||||
|
import org.jclouds.aws.ec2.domain.AWSRunningInstance;
|
||||||
|
import org.jclouds.collect.Memoized;
|
||||||
|
import org.jclouds.compute.domain.Hardware;
|
||||||
|
import org.jclouds.compute.domain.Image;
|
||||||
|
import org.jclouds.compute.domain.NodeMetadataBuilder;
|
||||||
|
import org.jclouds.compute.domain.NodeState;
|
||||||
|
import org.jclouds.domain.Credentials;
|
||||||
|
import org.jclouds.domain.Location;
|
||||||
|
import org.jclouds.ec2.compute.domain.RegionAndName;
|
||||||
|
import org.jclouds.ec2.compute.functions.RunningInstanceToNodeMetadata;
|
||||||
|
import org.jclouds.ec2.domain.InstanceState;
|
||||||
|
import org.jclouds.ec2.domain.RunningInstance;
|
||||||
|
|
||||||
|
import com.google.common.base.Supplier;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Adrian Cole
|
||||||
|
*/
|
||||||
|
@Singleton
|
||||||
|
public class AWSRunningInstanceToNodeMetadata extends RunningInstanceToNodeMetadata {
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
protected AWSRunningInstanceToNodeMetadata(Map<InstanceState, NodeState> instanceToNodeState,
|
||||||
|
Map<String, Credentials> credentialStore, Map<RegionAndName, Image> instanceToImage,
|
||||||
|
@Memoized Supplier<Set<? extends Location>> locations, @Memoized Supplier<Set<? extends Hardware>> hardware) {
|
||||||
|
super(instanceToNodeState, credentialStore, instanceToImage, locations, hardware);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void addCredentialsForInstance(NodeMetadataBuilder builder, RunningInstance instance) {
|
||||||
|
Credentials creds = credentialStore.get("node#" + instance.getRegion() + "/" + instance.getId());
|
||||||
|
String spotRequestId = AWSRunningInstance.class.cast(instance).getSpotInstanceRequestId();
|
||||||
|
if (creds == null && spotRequestId != null) {
|
||||||
|
creds = credentialStore.get("node#" + instance.getRegion() + "/" + spotRequestId);
|
||||||
|
if (creds != null)
|
||||||
|
credentialStore.put("node#" + instance.getRegion() + "/" + instance.getId(), creds);
|
||||||
|
}
|
||||||
|
if (creds != null)
|
||||||
|
builder.credentials(creds);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,56 @@
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
|
||||||
|
*
|
||||||
|
* ====================================================================
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
* ====================================================================
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jclouds.aws.ec2.compute.predicates;
|
||||||
|
|
||||||
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
|
|
||||||
|
import javax.inject.Singleton;
|
||||||
|
|
||||||
|
import org.jclouds.aws.ec2.AWSEC2Client;
|
||||||
|
import org.jclouds.ec2.compute.domain.RegionAndName;
|
||||||
|
import org.jclouds.ec2.compute.predicates.InstancePresent;
|
||||||
|
|
||||||
|
import com.google.common.collect.Iterables;
|
||||||
|
import com.google.inject.Inject;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Adrian Cole
|
||||||
|
*/
|
||||||
|
@Singleton
|
||||||
|
public class AWSEC2InstancePresent extends InstancePresent {
|
||||||
|
|
||||||
|
private final AWSEC2Client client;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
public AWSEC2InstancePresent(AWSEC2Client client) {
|
||||||
|
super(client);
|
||||||
|
this.client = checkNotNull(client, "client");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void refresh(RegionAndName instance) {
|
||||||
|
if (instance.getName().indexOf("sir-") != 0)
|
||||||
|
super.refresh(instance);
|
||||||
|
else
|
||||||
|
Iterables.getOnlyElement(client.getSpotInstanceServices().describeSpotInstanceRequestsInRegion(
|
||||||
|
instance.getRegion(), instance.getName()));
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,109 @@
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
|
||||||
|
*
|
||||||
|
* ====================================================================
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
* ====================================================================
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jclouds.aws.ec2.compute.strategy;
|
||||||
|
|
||||||
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
import javax.inject.Inject;
|
||||||
|
import javax.inject.Named;
|
||||||
|
import javax.inject.Provider;
|
||||||
|
import javax.inject.Singleton;
|
||||||
|
|
||||||
|
import org.jclouds.aws.ec2.AWSEC2Client;
|
||||||
|
import org.jclouds.aws.ec2.compute.AWSEC2TemplateOptions;
|
||||||
|
import org.jclouds.aws.ec2.compute.predicates.AWSEC2InstancePresent;
|
||||||
|
import org.jclouds.aws.ec2.domain.LaunchSpecification;
|
||||||
|
import org.jclouds.aws.ec2.functions.SpotInstanceRequestToAWSRunningInstance;
|
||||||
|
import org.jclouds.aws.ec2.options.AWSRunInstancesOptions;
|
||||||
|
import org.jclouds.aws.ec2.options.RequestSpotInstancesOptions;
|
||||||
|
import org.jclouds.compute.domain.NodeMetadata;
|
||||||
|
import org.jclouds.compute.domain.Template;
|
||||||
|
import org.jclouds.compute.domain.TemplateBuilder;
|
||||||
|
import org.jclouds.compute.options.TemplateOptions;
|
||||||
|
import org.jclouds.compute.reference.ComputeServiceConstants;
|
||||||
|
import org.jclouds.compute.util.ComputeUtils;
|
||||||
|
import org.jclouds.domain.Credentials;
|
||||||
|
import org.jclouds.ec2.compute.strategy.EC2CreateNodesInGroupThenAddToSet;
|
||||||
|
import org.jclouds.ec2.domain.RunningInstance;
|
||||||
|
import org.jclouds.ec2.options.RunInstancesOptions;
|
||||||
|
import org.jclouds.logging.Logger;
|
||||||
|
|
||||||
|
import com.google.common.annotations.VisibleForTesting;
|
||||||
|
import com.google.common.base.Function;
|
||||||
|
import com.google.common.collect.Iterables;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Adrian Cole
|
||||||
|
*/
|
||||||
|
@Singleton
|
||||||
|
public class AWSEC2CreateNodesInGroupThenAddToSet extends EC2CreateNodesInGroupThenAddToSet {
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
@Named(ComputeServiceConstants.COMPUTE_LOGGER)
|
||||||
|
protected Logger logger = Logger.NULL;
|
||||||
|
|
||||||
|
@VisibleForTesting
|
||||||
|
final AWSEC2Client client;
|
||||||
|
final SpotInstanceRequestToAWSRunningInstance spotConverter;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
protected AWSEC2CreateNodesInGroupThenAddToSet(
|
||||||
|
AWSEC2Client client,
|
||||||
|
Provider<TemplateBuilder> templateBuilderProvider,
|
||||||
|
CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptions createKeyPairAndSecurityGroupsAsNeededAndReturncustomize,
|
||||||
|
AWSEC2InstancePresent instancePresent,
|
||||||
|
Function<RunningInstance, NodeMetadata> runningInstanceToNodeMetadata,
|
||||||
|
Function<RunningInstance, Credentials> instanceToCredentials, Map<String, Credentials> credentialStore,
|
||||||
|
ComputeUtils utils, SpotInstanceRequestToAWSRunningInstance spotConverter) {
|
||||||
|
|
||||||
|
super(client, templateBuilderProvider, createKeyPairAndSecurityGroupsAsNeededAndReturncustomize, instancePresent,
|
||||||
|
runningInstanceToNodeMetadata, instanceToCredentials, credentialStore, utils);
|
||||||
|
this.client = checkNotNull(client, "client");
|
||||||
|
this.spotConverter = checkNotNull(spotConverter, "spotConverter");
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Iterable<? extends RunningInstance> createNodesInRegionAndZone(String region, String zone, int count,
|
||||||
|
Template template, RunInstancesOptions instanceOptions) {
|
||||||
|
Float spotPrice = getSpotPriceOrNull(template.getOptions());
|
||||||
|
if (spotPrice != null) {
|
||||||
|
LaunchSpecification spec = AWSRunInstancesOptions.class.cast(instanceOptions).getLaunchSpecificationBuilder()
|
||||||
|
.imageId(template.getImage().getProviderId()).availabilityZone(zone).build();
|
||||||
|
RequestSpotInstancesOptions options = AWSEC2TemplateOptions.class.cast(template.getOptions()).getSpotOptions();
|
||||||
|
if (logger.isDebugEnabled())
|
||||||
|
logger.debug(">> requesting %d spot instances region(%s) price(%f) spec(%s) options(%s)", count, region,
|
||||||
|
spotPrice, spec, options);
|
||||||
|
|
||||||
|
return Iterables.transform(client.getSpotInstanceServices().requestSpotInstancesInRegion(region, spotPrice,
|
||||||
|
count, spec, options), spotConverter);
|
||||||
|
} else {
|
||||||
|
return super.createNodesInRegionAndZone(zone, zone, count, template, instanceOptions);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private Float getSpotPriceOrNull(TemplateOptions options) {
|
||||||
|
return options instanceof AWSEC2TemplateOptions ? AWSEC2TemplateOptions.class.cast(options).getSpotPrice() : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,55 @@
|
||||||
|
package org.jclouds.aws.ec2.compute.strategy;
|
||||||
|
|
||||||
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
|
import static com.google.common.collect.Iterables.getOnlyElement;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.NoSuchElementException;
|
||||||
|
|
||||||
|
import javax.inject.Inject;
|
||||||
|
import javax.inject.Singleton;
|
||||||
|
|
||||||
|
import org.jclouds.aws.ec2.AWSEC2Client;
|
||||||
|
import org.jclouds.compute.strategy.GetNodeMetadataStrategy;
|
||||||
|
import org.jclouds.domain.Credentials;
|
||||||
|
import org.jclouds.ec2.compute.strategy.EC2DestroyNodeStrategy;
|
||||||
|
|
||||||
|
import com.google.common.collect.Iterables;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Adrian Cole
|
||||||
|
*/
|
||||||
|
@Singleton
|
||||||
|
public class AWSEC2DestroyNodeStrategy extends EC2DestroyNodeStrategy {
|
||||||
|
|
||||||
|
protected final AWSEC2Client client;
|
||||||
|
protected final Map<String, Credentials> credentialStore;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
protected AWSEC2DestroyNodeStrategy(AWSEC2Client client, GetNodeMetadataStrategy getNode,
|
||||||
|
Map<String, Credentials> credentialStore) {
|
||||||
|
super(client, getNode);
|
||||||
|
this.client = checkNotNull(client, "client");
|
||||||
|
this.credentialStore = checkNotNull(credentialStore, "credentialStore");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void destroyInstanceInRegion(String region, String id) {
|
||||||
|
String spotId = id;
|
||||||
|
if (id.indexOf("sir-") != 0) {
|
||||||
|
try {
|
||||||
|
spotId = getOnlyElement(
|
||||||
|
Iterables.concat(client.getInstanceServices().describeInstancesInRegion(region, id)))
|
||||||
|
.getSpotInstanceRequestId();
|
||||||
|
credentialStore.remove("node#" + region + "/" + spotId);
|
||||||
|
} catch (NoSuchElementException e) {
|
||||||
|
}
|
||||||
|
super.destroyInstanceInRegion(region, id);
|
||||||
|
} else {
|
||||||
|
client.getSpotInstanceServices().cancelSpotInstanceRequestsInRegion(region, spotId);
|
||||||
|
credentialStore.remove("node#" + region + "/" + id);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,68 @@
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
|
||||||
|
*
|
||||||
|
* ====================================================================
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
* ====================================================================
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jclouds.aws.ec2.compute.strategy;
|
||||||
|
|
||||||
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
|
import static com.google.common.collect.Iterables.getOnlyElement;
|
||||||
|
|
||||||
|
import javax.inject.Inject;
|
||||||
|
import javax.inject.Singleton;
|
||||||
|
|
||||||
|
import org.jclouds.aws.ec2.AWSEC2Client;
|
||||||
|
import org.jclouds.aws.ec2.domain.SpotInstanceRequest;
|
||||||
|
import org.jclouds.aws.ec2.functions.SpotInstanceRequestToAWSRunningInstance;
|
||||||
|
import org.jclouds.compute.domain.NodeMetadata;
|
||||||
|
import org.jclouds.ec2.compute.strategy.EC2GetNodeMetadataStrategy;
|
||||||
|
import org.jclouds.ec2.domain.RunningInstance;
|
||||||
|
|
||||||
|
import com.google.common.base.Function;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Adrian Cole
|
||||||
|
*/
|
||||||
|
@Singleton
|
||||||
|
public class AWSEC2GetNodeMetadataStrategy extends EC2GetNodeMetadataStrategy {
|
||||||
|
|
||||||
|
private final AWSEC2Client client;
|
||||||
|
private final SpotInstanceRequestToAWSRunningInstance spotConverter;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
protected AWSEC2GetNodeMetadataStrategy(AWSEC2Client client,
|
||||||
|
Function<RunningInstance, NodeMetadata> runningInstanceToNodeMetadata,
|
||||||
|
SpotInstanceRequestToAWSRunningInstance spotConverter) {
|
||||||
|
super(client, runningInstanceToNodeMetadata);
|
||||||
|
this.client = checkNotNull(client, "client");
|
||||||
|
this.spotConverter = checkNotNull(spotConverter, "spotConverter");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public RunningInstance getRunningInstanceInRegion(String region, String id) {
|
||||||
|
if (id.indexOf("sir-") != 0)
|
||||||
|
return super.getRunningInstanceInRegion(region, id);
|
||||||
|
SpotInstanceRequest spot = getOnlyElement(client.getSpotInstanceServices().describeSpotInstanceRequestsInRegion(
|
||||||
|
region, id));
|
||||||
|
if (spot.getState() == SpotInstanceRequest.State.ACTIVE)
|
||||||
|
return super.getRunningInstanceInRegion(region, spot.getInstanceId());
|
||||||
|
else
|
||||||
|
return spotConverter.apply(spot);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,85 @@
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
|
||||||
|
*
|
||||||
|
* ====================================================================
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
* ====================================================================
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jclouds.aws.ec2.compute.strategy;
|
||||||
|
|
||||||
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
|
import static com.google.common.base.Predicates.notNull;
|
||||||
|
import static com.google.common.collect.Iterables.concat;
|
||||||
|
import static com.google.common.collect.Iterables.filter;
|
||||||
|
import static com.google.common.collect.Iterables.transform;
|
||||||
|
import static org.jclouds.concurrent.FutureIterables.transformParallel;
|
||||||
|
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.concurrent.ExecutorService;
|
||||||
|
import java.util.concurrent.Future;
|
||||||
|
|
||||||
|
import javax.inject.Inject;
|
||||||
|
import javax.inject.Named;
|
||||||
|
import javax.inject.Singleton;
|
||||||
|
|
||||||
|
import org.jclouds.Constants;
|
||||||
|
import org.jclouds.aws.ec2.AWSEC2AsyncClient;
|
||||||
|
import org.jclouds.aws.ec2.domain.AWSRunningInstance;
|
||||||
|
import org.jclouds.aws.ec2.domain.SpotInstanceRequest;
|
||||||
|
import org.jclouds.aws.ec2.functions.SpotInstanceRequestToAWSRunningInstance;
|
||||||
|
import org.jclouds.compute.domain.NodeMetadata;
|
||||||
|
import org.jclouds.ec2.compute.strategy.EC2ListNodesStrategy;
|
||||||
|
import org.jclouds.ec2.domain.RunningInstance;
|
||||||
|
import org.jclouds.location.Region;
|
||||||
|
|
||||||
|
import com.google.common.base.Function;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Adrian Cole
|
||||||
|
*/
|
||||||
|
@Singleton
|
||||||
|
public class AWSEC2ListNodesStrategy extends EC2ListNodesStrategy {
|
||||||
|
|
||||||
|
protected final AWSEC2AsyncClient client;
|
||||||
|
protected final SpotInstanceRequestToAWSRunningInstance spotConverter;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
protected AWSEC2ListNodesStrategy(AWSEC2AsyncClient client, @Region Set<String> regions,
|
||||||
|
Function<RunningInstance, NodeMetadata> runningInstanceToNodeMetadata,
|
||||||
|
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService executor,
|
||||||
|
SpotInstanceRequestToAWSRunningInstance spotConverter) {
|
||||||
|
super(client, regions, runningInstanceToNodeMetadata, executor);
|
||||||
|
this.client = checkNotNull(client, "client");
|
||||||
|
this.spotConverter = checkNotNull(spotConverter, "spotConverter");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Iterable<? extends RunningInstance> pollRunningInstances() {
|
||||||
|
Iterable<? extends AWSRunningInstance> spots = filter(transform(concat(transformParallel(regions,
|
||||||
|
new Function<String, Future<Set<SpotInstanceRequest>>>() {
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
@Override
|
||||||
|
public Future<Set<SpotInstanceRequest>> apply(String from) {
|
||||||
|
return (Future<Set<SpotInstanceRequest>>) client.getSpotInstanceServices()
|
||||||
|
.describeSpotInstanceRequestsInRegion(from);
|
||||||
|
}
|
||||||
|
|
||||||
|
}, executor, null, logger, "reservations")), spotConverter), notNull());
|
||||||
|
|
||||||
|
return concat(super.pollRunningInstances(), spots);
|
||||||
|
}
|
||||||
|
}
|
|
@ -37,6 +37,8 @@ import org.jclouds.aws.ec2.services.MonitoringAsyncClient;
|
||||||
import org.jclouds.aws.ec2.services.MonitoringClient;
|
import org.jclouds.aws.ec2.services.MonitoringClient;
|
||||||
import org.jclouds.aws.ec2.services.PlacementGroupAsyncClient;
|
import org.jclouds.aws.ec2.services.PlacementGroupAsyncClient;
|
||||||
import org.jclouds.aws.ec2.services.PlacementGroupClient;
|
import org.jclouds.aws.ec2.services.PlacementGroupClient;
|
||||||
|
import org.jclouds.aws.ec2.services.SpotInstanceAsyncClient;
|
||||||
|
import org.jclouds.aws.ec2.services.SpotInstanceClient;
|
||||||
import org.jclouds.ec2.EC2AsyncClient;
|
import org.jclouds.ec2.EC2AsyncClient;
|
||||||
import org.jclouds.ec2.EC2Client;
|
import org.jclouds.ec2.EC2Client;
|
||||||
import org.jclouds.ec2.config.EC2RestClientModule;
|
import org.jclouds.ec2.config.EC2RestClientModule;
|
||||||
|
@ -82,6 +84,7 @@ public class AWSEC2RestClientModule extends EC2RestClientModule<AWSEC2Client, AW
|
||||||
.put(WindowsClient.class, WindowsAsyncClient.class)//
|
.put(WindowsClient.class, WindowsAsyncClient.class)//
|
||||||
.put(AvailabilityZoneAndRegionClient.class, AvailabilityZoneAndRegionAsyncClient.class)//
|
.put(AvailabilityZoneAndRegionClient.class, AvailabilityZoneAndRegionAsyncClient.class)//
|
||||||
.put(ElasticBlockStoreClient.class, ElasticBlockStoreAsyncClient.class)//
|
.put(ElasticBlockStoreClient.class, ElasticBlockStoreAsyncClient.class)//
|
||||||
|
.put(SpotInstanceClient.class, SpotInstanceAsyncClient.class)//
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
public AWSEC2RestClientModule() {
|
public AWSEC2RestClientModule() {
|
||||||
|
|
|
@ -42,6 +42,9 @@ import com.google.common.collect.Sets;
|
||||||
* @author Adrian Cole
|
* @author Adrian Cole
|
||||||
*/
|
*/
|
||||||
public class AWSRunningInstance extends RunningInstance {
|
public class AWSRunningInstance extends RunningInstance {
|
||||||
|
public static Builder builder() {
|
||||||
|
return new Builder();
|
||||||
|
}
|
||||||
|
|
||||||
public static class Builder extends org.jclouds.ec2.domain.RunningInstance.Builder {
|
public static class Builder extends org.jclouds.ec2.domain.RunningInstance.Builder {
|
||||||
private MonitoringState monitoringState;
|
private MonitoringState monitoringState;
|
||||||
|
|
|
@ -0,0 +1,350 @@
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Copyright (C) 2010 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.domain;
|
||||||
|
|
||||||
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
|
import org.jclouds.ec2.domain.BlockDeviceMapping;
|
||||||
|
import org.jclouds.ec2.domain.BlockDeviceMapping.MapEBSSnapshotToDevice;
|
||||||
|
import org.jclouds.ec2.domain.BlockDeviceMapping.MapEphemeralDeviceToDevice;
|
||||||
|
import org.jclouds.ec2.domain.BlockDeviceMapping.MapNewVolumeToDevice;
|
||||||
|
|
||||||
|
import com.google.common.collect.ImmutableSet;
|
||||||
|
import com.google.common.collect.ImmutableSortedSet;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @see <a href=
|
||||||
|
* "http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-RequestSpotInstances.html"
|
||||||
|
* />
|
||||||
|
* @author Adrian Cole
|
||||||
|
*/
|
||||||
|
public class LaunchSpecification {
|
||||||
|
|
||||||
|
public static Builder builder() {
|
||||||
|
return new Builder();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Builder {
|
||||||
|
protected ImmutableSet.Builder<String> groupIds = ImmutableSet.<String> builder();
|
||||||
|
protected String imageId;
|
||||||
|
protected String instanceType;
|
||||||
|
protected String kernelId;
|
||||||
|
protected String keyName;
|
||||||
|
protected String availabilityZone;
|
||||||
|
protected String ramdiskId;
|
||||||
|
protected Boolean monitoringEnabled;
|
||||||
|
protected ImmutableSet.Builder<BlockDeviceMapping> blockDeviceMappings = ImmutableSet
|
||||||
|
.<BlockDeviceMapping> builder();
|
||||||
|
protected byte[] userData;
|
||||||
|
|
||||||
|
public void clear() {
|
||||||
|
groupIds = ImmutableSet.<String> builder();
|
||||||
|
imageId = null;
|
||||||
|
instanceType = null;
|
||||||
|
kernelId = null;
|
||||||
|
keyName = null;
|
||||||
|
availabilityZone = null;
|
||||||
|
ramdiskId = null;
|
||||||
|
monitoringEnabled = false;
|
||||||
|
blockDeviceMappings = ImmutableSet.<BlockDeviceMapping> builder();
|
||||||
|
userData = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder groupIds(Iterable<String> groupIds) {
|
||||||
|
this.groupIds.addAll(checkNotNull(groupIds, "groupIds"));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder groupId(String groupId) {
|
||||||
|
if (groupId != null)
|
||||||
|
this.groupIds.add(groupId);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder imageId(String imageId) {
|
||||||
|
this.imageId = imageId;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder monitoringEnabled(Boolean monitoringEnabled) {
|
||||||
|
this.monitoringEnabled = monitoringEnabled;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder instanceType(String instanceType) {
|
||||||
|
this.instanceType = instanceType;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder kernelId(String kernelId) {
|
||||||
|
this.kernelId = kernelId;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder keyName(String keyName) {
|
||||||
|
this.keyName = keyName;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder availabilityZone(String availabilityZone) {
|
||||||
|
this.availabilityZone = availabilityZone;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder ramdiskId(String ramdiskId) {
|
||||||
|
this.ramdiskId = ramdiskId;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder mapEBSSnapshotToDevice(String deviceName, String snapshotId, @Nullable Integer sizeInGib,
|
||||||
|
boolean deleteOnTermination) {
|
||||||
|
blockDeviceMappings.add(new MapEBSSnapshotToDevice(deviceName, snapshotId, sizeInGib, deleteOnTermination));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder mapNewVolumeToDevice(String deviceName, int sizeInGib, boolean deleteOnTermination) {
|
||||||
|
blockDeviceMappings.add(new MapNewVolumeToDevice(deviceName, sizeInGib, deleteOnTermination));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder mapEphemeralDeviceToDevice(String deviceName, String virtualName) {
|
||||||
|
blockDeviceMappings.add(new MapEphemeralDeviceToDevice(deviceName, virtualName));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder blockDeviceMapping(BlockDeviceMapping blockDeviceMapping) {
|
||||||
|
this.blockDeviceMappings.add(checkNotNull(blockDeviceMapping, "blockDeviceMapping"));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder blockDeviceMappings(Iterable<? extends BlockDeviceMapping> blockDeviceMappings) {
|
||||||
|
this.blockDeviceMappings.addAll(checkNotNull(blockDeviceMappings, "blockDeviceMappings"));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder userData(byte[] userData) {
|
||||||
|
this.userData = userData;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public LaunchSpecification build() {
|
||||||
|
return new LaunchSpecification(instanceType, imageId, kernelId, ramdiskId, availabilityZone, keyName,
|
||||||
|
groupIds.build(), blockDeviceMappings.build(), monitoringEnabled, userData);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Builder fromLaunchSpecification(LaunchSpecification in) {
|
||||||
|
return new Builder().instanceType(in.getInstanceType()).imageId(in.getImageId()).kernelId(in.getKernelId())
|
||||||
|
.ramdiskId(in.getRamdiskId()).availabilityZone(in.getAvailabilityZone()).keyName(in.getKeyName())
|
||||||
|
.groupIds(in.getGroupIds()).blockDeviceMappings(in.getBlockDeviceMappings())
|
||||||
|
.monitoringEnabled(in.isMonitoringEnabled()).userData(in.getUserData());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected final String instanceType;
|
||||||
|
protected final String imageId;
|
||||||
|
protected final String kernelId;
|
||||||
|
protected final String ramdiskId;
|
||||||
|
protected final String availabilityZone;
|
||||||
|
protected final String keyName;
|
||||||
|
protected final Set<String> groupIds;
|
||||||
|
protected final Set<? extends BlockDeviceMapping> blockDeviceMappings;
|
||||||
|
protected final Boolean monitoringEnabled;
|
||||||
|
protected final byte[] userData;
|
||||||
|
|
||||||
|
public LaunchSpecification(String instanceType, String imageId, String kernelId, String ramdiskId,
|
||||||
|
String availabilityZone, String keyName, Iterable<String> groupIds,
|
||||||
|
Iterable<? extends BlockDeviceMapping> blockDeviceMappings, Boolean monitoringEnabled, byte[] userData) {
|
||||||
|
this.instanceType = checkNotNull(instanceType, "instanceType");
|
||||||
|
this.imageId = checkNotNull(imageId, "imageId");
|
||||||
|
this.kernelId = kernelId;
|
||||||
|
this.ramdiskId = ramdiskId;
|
||||||
|
this.availabilityZone = availabilityZone;
|
||||||
|
this.keyName = keyName;
|
||||||
|
this.groupIds = ImmutableSortedSet.copyOf(checkNotNull(groupIds, "groupIds"));
|
||||||
|
this.blockDeviceMappings = ImmutableSortedSet.copyOf(checkNotNull(blockDeviceMappings, "blockDeviceMappings"));
|
||||||
|
this.monitoringEnabled = monitoringEnabled;
|
||||||
|
this.userData = userData;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Image ID of the AMI used to launch the instance.
|
||||||
|
*/
|
||||||
|
public String getImageId() {
|
||||||
|
return imageId;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* CloudWatch support
|
||||||
|
*/
|
||||||
|
public Boolean isMonitoringEnabled() {
|
||||||
|
return monitoringEnabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The instance type.
|
||||||
|
*/
|
||||||
|
public String getInstanceType() {
|
||||||
|
return instanceType;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Optional. Kernel associated with this instance.
|
||||||
|
*/
|
||||||
|
public String getKernelId() {
|
||||||
|
return kernelId;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If this instance was launched with an associated key pair, this displays the key pair name.
|
||||||
|
*/
|
||||||
|
public String getKeyName() {
|
||||||
|
return keyName;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The location where the instance launched.
|
||||||
|
*/
|
||||||
|
public String getAvailabilityZone() {
|
||||||
|
return availabilityZone;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Optional. RAM disk associated with this instance.
|
||||||
|
*/
|
||||||
|
public String getRamdiskId() {
|
||||||
|
return ramdiskId;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* volumes mappings associated with the instance.
|
||||||
|
*/
|
||||||
|
public Set<? extends BlockDeviceMapping> getBlockDeviceMappings() {
|
||||||
|
return blockDeviceMappings;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Names of the security groups.
|
||||||
|
*/
|
||||||
|
public Set<String> getGroupIds() {
|
||||||
|
return groupIds;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* User Data
|
||||||
|
*/
|
||||||
|
public byte[] getUserData() {
|
||||||
|
return userData;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
final int prime = 31;
|
||||||
|
int result = 1;
|
||||||
|
result = prime * result + ((availabilityZone == null) ? 0 : availabilityZone.hashCode());
|
||||||
|
result = prime * result + ((blockDeviceMappings == null) ? 0 : blockDeviceMappings.hashCode());
|
||||||
|
result = prime * result + ((groupIds == null) ? 0 : groupIds.hashCode());
|
||||||
|
result = prime * result + ((imageId == null) ? 0 : imageId.hashCode());
|
||||||
|
result = prime * result + ((instanceType == null) ? 0 : instanceType.hashCode());
|
||||||
|
result = prime * result + ((kernelId == null) ? 0 : kernelId.hashCode());
|
||||||
|
result = prime * result + ((keyName == null) ? 0 : keyName.hashCode());
|
||||||
|
result = prime * result + ((monitoringEnabled == null) ? 0 : monitoringEnabled.hashCode());
|
||||||
|
result = prime * result + ((ramdiskId == null) ? 0 : ramdiskId.hashCode());
|
||||||
|
result = prime * result + Arrays.hashCode(userData);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object obj) {
|
||||||
|
if (this == obj)
|
||||||
|
return true;
|
||||||
|
if (obj == null)
|
||||||
|
return false;
|
||||||
|
if (getClass() != obj.getClass())
|
||||||
|
return false;
|
||||||
|
LaunchSpecification other = (LaunchSpecification) obj;
|
||||||
|
if (availabilityZone == null) {
|
||||||
|
if (other.availabilityZone != null)
|
||||||
|
return false;
|
||||||
|
} else if (!availabilityZone.equals(other.availabilityZone))
|
||||||
|
return false;
|
||||||
|
if (blockDeviceMappings == null) {
|
||||||
|
if (other.blockDeviceMappings != null)
|
||||||
|
return false;
|
||||||
|
} else if (!blockDeviceMappings.equals(other.blockDeviceMappings))
|
||||||
|
return false;
|
||||||
|
if (groupIds == null) {
|
||||||
|
if (other.groupIds != null)
|
||||||
|
return false;
|
||||||
|
} else if (!groupIds.equals(other.groupIds))
|
||||||
|
return false;
|
||||||
|
if (imageId == null) {
|
||||||
|
if (other.imageId != null)
|
||||||
|
return false;
|
||||||
|
} else if (!imageId.equals(other.imageId))
|
||||||
|
return false;
|
||||||
|
if (instanceType == null) {
|
||||||
|
if (other.instanceType != null)
|
||||||
|
return false;
|
||||||
|
} else if (!instanceType.equals(other.instanceType))
|
||||||
|
return false;
|
||||||
|
if (kernelId == null) {
|
||||||
|
if (other.kernelId != null)
|
||||||
|
return false;
|
||||||
|
} else if (!kernelId.equals(other.kernelId))
|
||||||
|
return false;
|
||||||
|
if (keyName == null) {
|
||||||
|
if (other.keyName != null)
|
||||||
|
return false;
|
||||||
|
} else if (!keyName.equals(other.keyName))
|
||||||
|
return false;
|
||||||
|
if (monitoringEnabled == null) {
|
||||||
|
if (other.monitoringEnabled != null)
|
||||||
|
return false;
|
||||||
|
} else if (!monitoringEnabled.equals(other.monitoringEnabled))
|
||||||
|
return false;
|
||||||
|
if (ramdiskId == null) {
|
||||||
|
if (other.ramdiskId != null)
|
||||||
|
return false;
|
||||||
|
} else if (!ramdiskId.equals(other.ramdiskId))
|
||||||
|
return false;
|
||||||
|
if (!Arrays.equals(userData, other.userData))
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder toBuilder() {
|
||||||
|
return Builder.fromLaunchSpecification(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "[instanceType=" + instanceType + ", imageId=" + imageId + ", kernelId=" + kernelId + ", ramdiskId="
|
||||||
|
+ ramdiskId + ", availabilityZone=" + availabilityZone + ", keyName=" + keyName + ", groupIds=" + groupIds
|
||||||
|
+ ", blockDeviceMappings=" + blockDeviceMappings + ", monitoringEnabled=" + monitoringEnabled
|
||||||
|
+ ", userData=" + (userData != null) + "]";
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,173 @@
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Copyright (C) 2010 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.domain;
|
||||||
|
|
||||||
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see <a href=
|
||||||
|
* "http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-DescribeSpotPriceHistory.html"
|
||||||
|
* />
|
||||||
|
* @author Adrian Cole
|
||||||
|
*/
|
||||||
|
public class Spot implements Comparable<Spot> {
|
||||||
|
public static Builder builder() {
|
||||||
|
return new Builder();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Builder {
|
||||||
|
private String region;
|
||||||
|
private String instanceType;
|
||||||
|
private String productDescription;
|
||||||
|
private float spotPrice;
|
||||||
|
private Date timestamp;
|
||||||
|
|
||||||
|
public void clear() {
|
||||||
|
this.region = null;
|
||||||
|
this.instanceType = null;
|
||||||
|
this.productDescription = null;
|
||||||
|
this.spotPrice = 0.0f;
|
||||||
|
this.timestamp = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder region(String region) {
|
||||||
|
this.region = region;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder instanceType(String instanceType) {
|
||||||
|
this.instanceType = instanceType;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder productDescription(String productDescription) {
|
||||||
|
this.productDescription = productDescription;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder spotPrice(float spotPrice) {
|
||||||
|
this.spotPrice = spotPrice;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder timestamp(Date timestamp) {
|
||||||
|
this.timestamp = timestamp;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Spot build() {
|
||||||
|
return new Spot(region, instanceType, productDescription, spotPrice, timestamp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private final String region;
|
||||||
|
private final String instanceType;
|
||||||
|
private final String productDescription;
|
||||||
|
private final float spotPrice;
|
||||||
|
private final Date timestamp;
|
||||||
|
|
||||||
|
public Spot(String region, String instanceType, String productDescription, float spotPrice, Date timestamp) {
|
||||||
|
this.region = checkNotNull(region, "region");
|
||||||
|
this.instanceType = checkNotNull(instanceType, "instanceType");
|
||||||
|
this.productDescription = checkNotNull(productDescription, "productDescription");
|
||||||
|
this.spotPrice = spotPrice;
|
||||||
|
this.timestamp = checkNotNull(timestamp, "timestamp");
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getRegion() {
|
||||||
|
return region;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getInstanceType() {
|
||||||
|
return instanceType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getProductDescription() {
|
||||||
|
return productDescription;
|
||||||
|
}
|
||||||
|
|
||||||
|
public float getSpotPrice() {
|
||||||
|
return spotPrice;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Date getTimestamp() {
|
||||||
|
return timestamp;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int compareTo(Spot o) {
|
||||||
|
return Float.compare(spotPrice, o.spotPrice);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
final int prime = 31;
|
||||||
|
int result = 1;
|
||||||
|
result = prime * result + ((instanceType == null) ? 0 : instanceType.hashCode());
|
||||||
|
result = prime * result + ((productDescription == null) ? 0 : productDescription.hashCode());
|
||||||
|
result = prime * result + ((region == null) ? 0 : region.hashCode());
|
||||||
|
result = prime * result + Float.floatToIntBits(spotPrice);
|
||||||
|
result = prime * result + ((timestamp == null) ? 0 : timestamp.hashCode());
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object obj) {
|
||||||
|
if (this == obj)
|
||||||
|
return true;
|
||||||
|
if (obj == null)
|
||||||
|
return false;
|
||||||
|
if (getClass() != obj.getClass())
|
||||||
|
return false;
|
||||||
|
Spot other = (Spot) obj;
|
||||||
|
if (instanceType == null) {
|
||||||
|
if (other.instanceType != null)
|
||||||
|
return false;
|
||||||
|
} else if (!instanceType.equals(other.instanceType))
|
||||||
|
return false;
|
||||||
|
if (productDescription == null) {
|
||||||
|
if (other.productDescription != null)
|
||||||
|
return false;
|
||||||
|
} else if (!productDescription.equals(other.productDescription))
|
||||||
|
return false;
|
||||||
|
if (region == null) {
|
||||||
|
if (other.region != null)
|
||||||
|
return false;
|
||||||
|
} else if (!region.equals(other.region))
|
||||||
|
return false;
|
||||||
|
if (Float.floatToIntBits(spotPrice) != Float.floatToIntBits(other.spotPrice))
|
||||||
|
return false;
|
||||||
|
if (timestamp == null) {
|
||||||
|
if (other.timestamp != null)
|
||||||
|
return false;
|
||||||
|
} else if (!timestamp.equals(other.timestamp))
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "[region=" + region + ", instanceType=" + instanceType + ", productDescription=" + productDescription
|
||||||
|
+ ", spotPrice=" + spotPrice + ", timestamp=" + timestamp + "]";
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,406 @@
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Copyright (C) 2010 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.domain;
|
||||||
|
|
||||||
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
import com.google.common.base.CaseFormat;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Adrian Cole
|
||||||
|
*/
|
||||||
|
public class SpotInstanceRequest implements Comparable<SpotInstanceRequest> {
|
||||||
|
public static Builder builder() {
|
||||||
|
return new Builder();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Builder {
|
||||||
|
private String region;
|
||||||
|
private String availabilityZoneGroup;
|
||||||
|
private Date createTime;
|
||||||
|
private String faultCode;
|
||||||
|
private String faultMessage;
|
||||||
|
private String instanceId;
|
||||||
|
private String launchGroup;
|
||||||
|
private LaunchSpecification launchSpecification;
|
||||||
|
private String productDescription;
|
||||||
|
private String id;
|
||||||
|
private float spotPrice;
|
||||||
|
private State state;
|
||||||
|
private Type type;
|
||||||
|
private Date validFrom;
|
||||||
|
private Date validUntil;
|
||||||
|
|
||||||
|
public Builder clear() {
|
||||||
|
this.region = null;
|
||||||
|
this.availabilityZoneGroup = null;
|
||||||
|
this.createTime = null;
|
||||||
|
this.faultCode = null;
|
||||||
|
this.faultMessage = null;
|
||||||
|
this.instanceId = null;
|
||||||
|
this.launchGroup = null;
|
||||||
|
this.launchSpecification = null;
|
||||||
|
this.productDescription = null;
|
||||||
|
this.id = null;
|
||||||
|
this.spotPrice = 0;
|
||||||
|
this.state = null;
|
||||||
|
this.type = null;
|
||||||
|
this.validFrom = null;
|
||||||
|
this.validUntil = null;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder region(String region) {
|
||||||
|
this.region = region;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder availabilityZoneGroup(String availabilityZoneGroup) {
|
||||||
|
this.availabilityZoneGroup = availabilityZoneGroup;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder createTime(Date createTime) {
|
||||||
|
this.createTime = createTime;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder faultCode(String faultCode) {
|
||||||
|
this.faultCode = faultCode;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder faultMessage(String faultMessage) {
|
||||||
|
this.faultMessage = faultMessage;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder instanceId(String instanceId) {
|
||||||
|
this.instanceId = instanceId;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder launchGroup(String launchGroup) {
|
||||||
|
this.launchGroup = launchGroup;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder launchSpecification(LaunchSpecification launchSpecification) {
|
||||||
|
this.launchSpecification = launchSpecification;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder productDescription(String productDescription) {
|
||||||
|
this.productDescription = productDescription;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder id(String id) {
|
||||||
|
this.id = id;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder spotPrice(float spotPrice) {
|
||||||
|
this.spotPrice = spotPrice;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder state(State state) {
|
||||||
|
this.state = state;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder type(Type type) {
|
||||||
|
this.type = type;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder validFrom(Date validFrom) {
|
||||||
|
this.validFrom = validFrom;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder validUntil(Date validUntil) {
|
||||||
|
this.validUntil = validUntil;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public SpotInstanceRequest build() {
|
||||||
|
return new SpotInstanceRequest(region, availabilityZoneGroup, createTime, faultCode, faultMessage, instanceId,
|
||||||
|
launchGroup, launchSpecification, productDescription, id, spotPrice, state, type, validFrom, validUntil);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum Type {
|
||||||
|
ONE_TIME, PERSISTENT, UNRECOGNIZED;
|
||||||
|
|
||||||
|
public String value() {
|
||||||
|
return (CaseFormat.UPPER_UNDERSCORE.to(CaseFormat.LOWER_HYPHEN, name()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return value();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Type fromValue(String type) {
|
||||||
|
try {
|
||||||
|
return valueOf(CaseFormat.LOWER_HYPHEN.to(CaseFormat.UPPER_UNDERSCORE, checkNotNull(type, "type")));
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
return UNRECOGNIZED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum State {
|
||||||
|
OPEN, ACTIVE, CANCELLED, CLOSED, UNRECOGNIZED;
|
||||||
|
|
||||||
|
public String value() {
|
||||||
|
return (CaseFormat.UPPER_UNDERSCORE.to(CaseFormat.LOWER_HYPHEN, name()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return value();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static State fromValue(String state) {
|
||||||
|
try {
|
||||||
|
return valueOf(CaseFormat.LOWER_HYPHEN.to(CaseFormat.UPPER_UNDERSCORE, checkNotNull(state, "type")));
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
return UNRECOGNIZED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private final String region;
|
||||||
|
private final String availabilityZoneGroup;
|
||||||
|
private final Date createTime;
|
||||||
|
private final String faultCode;
|
||||||
|
private final String faultMessage;
|
||||||
|
private final String instanceId;
|
||||||
|
private final String launchGroup;
|
||||||
|
private final LaunchSpecification launchSpecification;
|
||||||
|
private final String productDescription;
|
||||||
|
private final String id;
|
||||||
|
private final float spotPrice;
|
||||||
|
private final State state;
|
||||||
|
private final Type type;
|
||||||
|
private final Date validFrom;
|
||||||
|
private final Date validUntil;
|
||||||
|
|
||||||
|
public SpotInstanceRequest(String region, String availabilityZoneGroup, Date createTime, String faultCode,
|
||||||
|
String faultMessage, String instanceId, String launchGroup, LaunchSpecification launchSpecification,
|
||||||
|
String productDescription, String id, float spotPrice, State state, Type type, Date validFrom, Date validUntil) {
|
||||||
|
this.region = checkNotNull(region, "region");
|
||||||
|
this.availabilityZoneGroup = availabilityZoneGroup;
|
||||||
|
this.createTime = createTime;
|
||||||
|
this.faultCode = faultCode;
|
||||||
|
this.faultMessage = faultMessage;
|
||||||
|
this.instanceId = instanceId;
|
||||||
|
this.launchGroup = launchGroup;
|
||||||
|
this.launchSpecification = launchSpecification;
|
||||||
|
this.productDescription = productDescription;
|
||||||
|
this.id = checkNotNull(id, "id");
|
||||||
|
this.spotPrice = spotPrice;
|
||||||
|
this.state = checkNotNull(state, "state");
|
||||||
|
this.type = checkNotNull(type, "type");
|
||||||
|
this.validFrom = validFrom;
|
||||||
|
this.validUntil = validUntil;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return spot instance requests are in a region
|
||||||
|
*/
|
||||||
|
public String getRegion() {
|
||||||
|
return region;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getAvailabilityZoneGroup() {
|
||||||
|
return availabilityZoneGroup;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Date getCreateTime() {
|
||||||
|
return createTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getFaultCode() {
|
||||||
|
return faultCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getFaultMessage() {
|
||||||
|
return faultMessage;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getInstanceId() {
|
||||||
|
return instanceId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getLaunchGroup() {
|
||||||
|
return launchGroup;
|
||||||
|
}
|
||||||
|
|
||||||
|
public LaunchSpecification getLaunchSpecification() {
|
||||||
|
return launchSpecification;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getProductDescription() {
|
||||||
|
return productDescription;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public float getSpotPrice() {
|
||||||
|
return spotPrice;
|
||||||
|
}
|
||||||
|
|
||||||
|
public State getState() {
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Type getType() {
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Date getValidFrom() {
|
||||||
|
return validFrom;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Date getValidUntil() {
|
||||||
|
return validUntil;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
final int prime = 31;
|
||||||
|
int result = 1;
|
||||||
|
result = prime * result + ((availabilityZoneGroup == null) ? 0 : availabilityZoneGroup.hashCode());
|
||||||
|
result = prime * result + ((createTime == null) ? 0 : createTime.hashCode());
|
||||||
|
result = prime * result + ((faultCode == null) ? 0 : faultCode.hashCode());
|
||||||
|
result = prime * result + ((faultMessage == null) ? 0 : faultMessage.hashCode());
|
||||||
|
result = prime * result + ((id == null) ? 0 : id.hashCode());
|
||||||
|
result = prime * result + ((instanceId == null) ? 0 : instanceId.hashCode());
|
||||||
|
result = prime * result + ((launchGroup == null) ? 0 : launchGroup.hashCode());
|
||||||
|
result = prime * result + ((launchSpecification == null) ? 0 : launchSpecification.hashCode());
|
||||||
|
result = prime * result + ((productDescription == null) ? 0 : productDescription.hashCode());
|
||||||
|
result = prime * result + ((region == null) ? 0 : region.hashCode());
|
||||||
|
result = prime * result + Float.floatToIntBits(spotPrice);
|
||||||
|
result = prime * result + ((type == null) ? 0 : type.hashCode());
|
||||||
|
result = prime * result + ((validFrom == null) ? 0 : validFrom.hashCode());
|
||||||
|
result = prime * result + ((validUntil == null) ? 0 : validUntil.hashCode());
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object obj) {
|
||||||
|
if (this == obj)
|
||||||
|
return true;
|
||||||
|
if (obj == null)
|
||||||
|
return false;
|
||||||
|
if (getClass() != obj.getClass())
|
||||||
|
return false;
|
||||||
|
SpotInstanceRequest other = (SpotInstanceRequest) obj;
|
||||||
|
if (availabilityZoneGroup == null) {
|
||||||
|
if (other.availabilityZoneGroup != null)
|
||||||
|
return false;
|
||||||
|
} else if (!availabilityZoneGroup.equals(other.availabilityZoneGroup))
|
||||||
|
return false;
|
||||||
|
if (createTime == null) {
|
||||||
|
if (other.createTime != null)
|
||||||
|
return false;
|
||||||
|
} else if (!createTime.equals(other.createTime))
|
||||||
|
return false;
|
||||||
|
if (faultCode == null) {
|
||||||
|
if (other.faultCode != null)
|
||||||
|
return false;
|
||||||
|
} else if (!faultCode.equals(other.faultCode))
|
||||||
|
return false;
|
||||||
|
if (faultMessage == null) {
|
||||||
|
if (other.faultMessage != null)
|
||||||
|
return false;
|
||||||
|
} else if (!faultMessage.equals(other.faultMessage))
|
||||||
|
return false;
|
||||||
|
if (id == null) {
|
||||||
|
if (other.id != null)
|
||||||
|
return false;
|
||||||
|
} else if (!id.equals(other.id))
|
||||||
|
return false;
|
||||||
|
if (instanceId == null) {
|
||||||
|
if (other.instanceId != null)
|
||||||
|
return false;
|
||||||
|
} else if (!instanceId.equals(other.instanceId))
|
||||||
|
return false;
|
||||||
|
if (launchGroup == null) {
|
||||||
|
if (other.launchGroup != null)
|
||||||
|
return false;
|
||||||
|
} else if (!launchGroup.equals(other.launchGroup))
|
||||||
|
return false;
|
||||||
|
if (launchSpecification == null) {
|
||||||
|
if (other.launchSpecification != null)
|
||||||
|
return false;
|
||||||
|
} else if (!launchSpecification.equals(other.launchSpecification))
|
||||||
|
return false;
|
||||||
|
if (productDescription == null) {
|
||||||
|
if (other.productDescription != null)
|
||||||
|
return false;
|
||||||
|
} else if (!productDescription.equals(other.productDescription))
|
||||||
|
return false;
|
||||||
|
if (region == null) {
|
||||||
|
if (other.region != null)
|
||||||
|
return false;
|
||||||
|
} else if (!region.equals(other.region))
|
||||||
|
return false;
|
||||||
|
if (Float.floatToIntBits(spotPrice) != Float.floatToIntBits(other.spotPrice))
|
||||||
|
return false;
|
||||||
|
if (type != other.type)
|
||||||
|
return false;
|
||||||
|
if (validFrom == null) {
|
||||||
|
if (other.validFrom != null)
|
||||||
|
return false;
|
||||||
|
} else if (!validFrom.equals(other.validFrom))
|
||||||
|
return false;
|
||||||
|
if (validUntil == null) {
|
||||||
|
if (other.validUntil != null)
|
||||||
|
return false;
|
||||||
|
} else if (!validUntil.equals(other.validUntil))
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "[region=" + region + ", id=" + id + ", spotPrice=" + spotPrice + ", state=" + state
|
||||||
|
+ ", availabilityZoneGroup=" + availabilityZoneGroup + ", createTime=" + createTime + ", faultCode="
|
||||||
|
+ faultCode + ", type=" + type + ", instanceId=" + instanceId + ", launchGroup=" + launchGroup
|
||||||
|
+ ", launchSpecification=" + launchSpecification + ", productDescription=" + productDescription
|
||||||
|
+ ", validFrom=" + validFrom + ", validUntil=" + validUntil + "]";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int compareTo(SpotInstanceRequest arg0) {
|
||||||
|
return createTime.compareTo(arg0.createTime);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,64 @@
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
|
||||||
|
*
|
||||||
|
* ====================================================================
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
* ====================================================================
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jclouds.aws.ec2.functions;
|
||||||
|
|
||||||
|
import javax.inject.Singleton;
|
||||||
|
|
||||||
|
import org.jclouds.aws.ec2.domain.AWSRunningInstance;
|
||||||
|
import org.jclouds.aws.ec2.domain.LaunchSpecification;
|
||||||
|
import org.jclouds.aws.ec2.domain.MonitoringState;
|
||||||
|
import org.jclouds.aws.ec2.domain.SpotInstanceRequest;
|
||||||
|
import org.jclouds.ec2.domain.InstanceState;
|
||||||
|
|
||||||
|
import com.google.common.base.Function;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Adrian Cole
|
||||||
|
*/
|
||||||
|
@Singleton
|
||||||
|
public class SpotInstanceRequestToAWSRunningInstance implements Function<SpotInstanceRequest, AWSRunningInstance> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AWSRunningInstance apply(SpotInstanceRequest request) {
|
||||||
|
if (request == null)
|
||||||
|
return null;
|
||||||
|
if (request.getState() != SpotInstanceRequest.State.OPEN)
|
||||||
|
return null;
|
||||||
|
AWSRunningInstance.Builder builder = AWSRunningInstance.builder();
|
||||||
|
builder.spotInstanceRequestId(request.getId());
|
||||||
|
builder.instanceId(request.getId());
|
||||||
|
builder.instanceState(InstanceState.PENDING);
|
||||||
|
builder.region(request.getRegion());
|
||||||
|
LaunchSpecification spec = request.getLaunchSpecification();
|
||||||
|
builder.availabilityZone(spec.getAvailabilityZone());
|
||||||
|
// TODO convert
|
||||||
|
// builder.devices(spec.getBlockDeviceMappings());
|
||||||
|
builder.groupIds(spec.getGroupIds());
|
||||||
|
builder.imageId(spec.getImageId());
|
||||||
|
builder.instanceType(spec.getInstanceType());
|
||||||
|
builder.kernelId(spec.getKernelId());
|
||||||
|
builder.keyName(spec.getKeyName());
|
||||||
|
builder.ramdiskId(spec.getRamdiskId());
|
||||||
|
builder.monitoringState(Boolean.TRUE.equals(spec.isMonitoringEnabled()) ? MonitoringState.PENDING
|
||||||
|
: MonitoringState.DISABLED);
|
||||||
|
return builder.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -23,10 +23,13 @@ import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
|
import org.jclouds.aws.ec2.domain.LaunchSpecification;
|
||||||
import org.jclouds.ec2.domain.BlockDeviceMapping;
|
import org.jclouds.ec2.domain.BlockDeviceMapping;
|
||||||
import org.jclouds.ec2.domain.InstanceType;
|
import org.jclouds.ec2.domain.InstanceType;
|
||||||
import org.jclouds.ec2.options.RunInstancesOptions;
|
import org.jclouds.ec2.options.RunInstancesOptions;
|
||||||
|
|
||||||
|
import com.google.common.collect.ImmutableSet;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Contains options supported in the Form API for the RunInstances operation. <h2>
|
* Contains options supported in the Form API for the RunInstances operation. <h2>
|
||||||
* Usage</h2> The recommended way to instantiate a RunInstancesOptions object is to statically
|
* Usage</h2> The recommended way to instantiate a RunInstancesOptions object is to statically
|
||||||
|
@ -46,6 +49,7 @@ import org.jclouds.ec2.options.RunInstancesOptions;
|
||||||
* />
|
* />
|
||||||
*/
|
*/
|
||||||
public class AWSRunInstancesOptions extends RunInstancesOptions {
|
public class AWSRunInstancesOptions extends RunInstancesOptions {
|
||||||
|
private LaunchSpecification.Builder launchSpecificationBuilder = LaunchSpecification.builder();
|
||||||
public static final AWSRunInstancesOptions NONE = new AWSRunInstancesOptions();
|
public static final AWSRunInstancesOptions NONE = new AWSRunInstancesOptions();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -60,22 +64,15 @@ public class AWSRunInstancesOptions extends RunInstancesOptions {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
String getPlacementGroup() {
|
|
||||||
return getFirstFormOrNull("Placement.GroupName");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Enables monitoring for the instance.
|
* Enables monitoring for the instance.
|
||||||
*/
|
*/
|
||||||
public AWSRunInstancesOptions enableMonitoring() {
|
public AWSRunInstancesOptions enableMonitoring() {
|
||||||
formParameters.put("Monitoring.Enabled", "true");
|
formParameters.put("Monitoring.Enabled", "true");
|
||||||
|
launchSpecificationBuilder.monitoringEnabled(true);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
String getMonitoringEnabled() {
|
|
||||||
return getFirstFormOrNull("Monitoring.Enabled");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Specifies the subnet ID within which to launch the instance(s) for Amazon Virtual Private
|
* Specifies the subnet ID within which to launch the instance(s) for Amazon Virtual Private
|
||||||
* Cloud.
|
* Cloud.
|
||||||
|
@ -85,10 +82,6 @@ public class AWSRunInstancesOptions extends RunInstancesOptions {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
String getSubnetId() {
|
|
||||||
return getFirstFormOrNull("SubnetId");
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class Builder extends RunInstancesOptions.Builder {
|
public static class Builder extends RunInstancesOptions.Builder {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -175,46 +168,63 @@ public class AWSRunInstancesOptions extends RunInstancesOptions {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public AWSRunInstancesOptions withBlockDeviceMappings(Set<? extends BlockDeviceMapping> mappings) {
|
public AWSRunInstancesOptions withBlockDeviceMappings(Set<? extends BlockDeviceMapping> mappings) {
|
||||||
|
launchSpecificationBuilder.blockDeviceMappings(mappings);
|
||||||
return AWSRunInstancesOptions.class.cast(super.withBlockDeviceMappings(mappings));
|
return AWSRunInstancesOptions.class.cast(super.withBlockDeviceMappings(mappings));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public AWSRunInstancesOptions withKernelId(String kernelId) {
|
public AWSRunInstancesOptions withKernelId(String kernelId) {
|
||||||
|
launchSpecificationBuilder.kernelId(kernelId);
|
||||||
return AWSRunInstancesOptions.class.cast(super.withKernelId(kernelId));
|
return AWSRunInstancesOptions.class.cast(super.withKernelId(kernelId));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public AWSRunInstancesOptions withKeyName(String keyName) {
|
public AWSRunInstancesOptions withKeyName(String keyName) {
|
||||||
|
launchSpecificationBuilder.keyName(keyName);
|
||||||
return AWSRunInstancesOptions.class.cast(super.withKeyName(keyName));
|
return AWSRunInstancesOptions.class.cast(super.withKeyName(keyName));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public AWSRunInstancesOptions withRamdisk(String ramDiskId) {
|
public AWSRunInstancesOptions withRamdisk(String ramDiskId) {
|
||||||
|
launchSpecificationBuilder.ramdiskId(ramDiskId);
|
||||||
return AWSRunInstancesOptions.class.cast(super.withRamdisk(ramDiskId));
|
return AWSRunInstancesOptions.class.cast(super.withRamdisk(ramDiskId));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public AWSRunInstancesOptions withSecurityGroup(String securityGroup) {
|
public AWSRunInstancesOptions withSecurityGroup(String securityGroup) {
|
||||||
|
launchSpecificationBuilder.groupId(securityGroup);
|
||||||
return AWSRunInstancesOptions.class.cast(super.withSecurityGroup(securityGroup));
|
return AWSRunInstancesOptions.class.cast(super.withSecurityGroup(securityGroup));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public AWSRunInstancesOptions withSecurityGroups(Iterable<String> securityGroups) {
|
public AWSRunInstancesOptions withSecurityGroups(Iterable<String> securityGroups) {
|
||||||
|
launchSpecificationBuilder.groupIds(securityGroups);
|
||||||
return AWSRunInstancesOptions.class.cast(super.withSecurityGroups(securityGroups));
|
return AWSRunInstancesOptions.class.cast(super.withSecurityGroups(securityGroups));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public AWSRunInstancesOptions withSecurityGroups(String... securityGroups) {
|
public AWSRunInstancesOptions withSecurityGroups(String... securityGroups) {
|
||||||
|
launchSpecificationBuilder.groupIds(ImmutableSet.copyOf(securityGroups));
|
||||||
return AWSRunInstancesOptions.class.cast(super.withSecurityGroups(securityGroups));
|
return AWSRunInstancesOptions.class.cast(super.withSecurityGroups(securityGroups));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public AWSRunInstancesOptions withUserData(byte[] unencodedData) {
|
public AWSRunInstancesOptions withUserData(byte[] unencodedData) {
|
||||||
|
launchSpecificationBuilder.userData(unencodedData);
|
||||||
return AWSRunInstancesOptions.class.cast(super.withUserData(unencodedData));
|
return AWSRunInstancesOptions.class.cast(super.withUserData(unencodedData));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public AWSRunInstancesOptions asType(String type) {
|
public AWSRunInstancesOptions asType(String type) {
|
||||||
|
launchSpecificationBuilder.instanceType(type);
|
||||||
return AWSRunInstancesOptions.class.cast(super.asType(type));
|
return AWSRunInstancesOptions.class.cast(super.asType(type));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public synchronized LaunchSpecification.Builder getLaunchSpecificationBuilder() {
|
||||||
|
try {
|
||||||
|
return launchSpecificationBuilder.imageId("fake").build().toBuilder().imageId(null);
|
||||||
|
} finally {
|
||||||
|
launchSpecificationBuilder.imageId(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,119 @@
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Copyright (C) 2010 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.options;
|
||||||
|
|
||||||
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
import org.jclouds.date.DateService;
|
||||||
|
import org.jclouds.date.internal.SimpleDateFormatDateService;
|
||||||
|
import org.jclouds.ec2.domain.InstanceType;
|
||||||
|
import org.jclouds.ec2.options.internal.BaseEC2RequestOptions;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Contains options supported in the Form API for the DescribeSpotPriceHistory operation. <h2>
|
||||||
|
* Usage</h2> The recommended way to instantiate a DescribeSpotPriceHistoryOptions object is to
|
||||||
|
* statically import DescribeSpotPriceHistoryOptions.Builder.* and invoke a static creation method
|
||||||
|
* followed by an instance mutator (if needed):
|
||||||
|
* <p/>
|
||||||
|
* <code>
|
||||||
|
* import static org.jclouds.aws.ec2.options.DescribeSpotPriceHistoryOptions.Builder.*
|
||||||
|
* <p/>
|
||||||
|
* AWSEC2Client client = // get connection
|
||||||
|
* history = client.getSpotInstanceServices().describeSpotPriceHistoryInRegion(from(yesterday).instanceType("m1.small"));
|
||||||
|
* <code>
|
||||||
|
*
|
||||||
|
* @author Adrian Cole
|
||||||
|
* @see <a href=
|
||||||
|
* "http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/index.html?ApiReference-form-DescribeSpotPriceHistory.html"
|
||||||
|
* />
|
||||||
|
*/
|
||||||
|
public class DescribeSpotPriceHistoryOptions extends BaseEC2RequestOptions {
|
||||||
|
public static final DescribeSpotPriceHistoryOptions NONE = new DescribeSpotPriceHistoryOptions();
|
||||||
|
private static final DateService service = new SimpleDateFormatDateService();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Start date and time of the Spot Instance price history data.
|
||||||
|
*/
|
||||||
|
public DescribeSpotPriceHistoryOptions from(Date start) {
|
||||||
|
formParameters.put("StartTime", service.iso8601DateFormat(checkNotNull(start, "start")));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* End date and time of the Spot Instance price history data.
|
||||||
|
*/
|
||||||
|
public DescribeSpotPriceHistoryOptions to(Date end) {
|
||||||
|
formParameters.put("EndTime", service.iso8601DateFormat(checkNotNull(end, "end")));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Specifies the instance type to return.
|
||||||
|
*/
|
||||||
|
public DescribeSpotPriceHistoryOptions instanceType(String type) {
|
||||||
|
formParameters.put("InstanceType.1", checkNotNull(type, "type"));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The description of the AMI.
|
||||||
|
*/
|
||||||
|
public DescribeSpotPriceHistoryOptions productDescription(String description) {
|
||||||
|
formParameters.put("ProductDescription", checkNotNull(description, "description"));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Builder {
|
||||||
|
/**
|
||||||
|
* @see DescribeSpotPriceHistoryOptions#from
|
||||||
|
*/
|
||||||
|
public static DescribeSpotPriceHistoryOptions from(Date start) {
|
||||||
|
DescribeSpotPriceHistoryOptions options = new DescribeSpotPriceHistoryOptions();
|
||||||
|
return options.from(start);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see DescribeSpotPriceHistoryOptions#to
|
||||||
|
*/
|
||||||
|
public static DescribeSpotPriceHistoryOptions to(Date end) {
|
||||||
|
DescribeSpotPriceHistoryOptions options = new DescribeSpotPriceHistoryOptions();
|
||||||
|
return options.to(end);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see DescribeSpotPriceHistoryOptions#instanceType(InstanceType)
|
||||||
|
*/
|
||||||
|
public static DescribeSpotPriceHistoryOptions instanceType(String instanceType) {
|
||||||
|
DescribeSpotPriceHistoryOptions options = new DescribeSpotPriceHistoryOptions();
|
||||||
|
return options.instanceType(instanceType);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see DescribeSpotPriceHistoryOptions#productDescription(String)
|
||||||
|
*/
|
||||||
|
public static DescribeSpotPriceHistoryOptions productDescription(String description) {
|
||||||
|
DescribeSpotPriceHistoryOptions options = new DescribeSpotPriceHistoryOptions();
|
||||||
|
return options.productDescription(description);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,142 @@
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Copyright (C) 2010 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 validUntil 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.options;
|
||||||
|
|
||||||
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
import org.jclouds.aws.ec2.domain.SpotInstanceRequest;
|
||||||
|
import org.jclouds.date.DateService;
|
||||||
|
import org.jclouds.date.internal.SimpleDateFormatDateService;
|
||||||
|
import org.jclouds.ec2.options.internal.BaseEC2RequestOptions;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Contains options supported in the Form API for the RequestSpotInstances operation. <h2>
|
||||||
|
* Usage</h2> The recommended way validUntil instantiate a RequestSpotInstancesOptions object is
|
||||||
|
* validUntil statically import RequestSpotInstancesOptions.Builder.* and invoke a static creation
|
||||||
|
* method followed by an instance mutator (if needed):
|
||||||
|
* <p/>
|
||||||
|
* <code>
|
||||||
|
* import static org.jclouds.aws.ec2.options.RequestSpotInstancesOptions.Builder.*
|
||||||
|
* <p/>
|
||||||
|
* AWSEC2Client client = // get connection
|
||||||
|
* history = client.getSpotInstanceServices().requestSpotInstancesInRegion("us-east-1",validFrom(yesterday).type("m1.small"));
|
||||||
|
* <code>
|
||||||
|
*
|
||||||
|
* @author Adrian Cole
|
||||||
|
* @see <a href=
|
||||||
|
* "http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/index.html?ApiReference-form-RequestSpotInstances.html"
|
||||||
|
* />
|
||||||
|
*/
|
||||||
|
public class RequestSpotInstancesOptions extends BaseEC2RequestOptions {
|
||||||
|
public static final RequestSpotInstancesOptions NONE = new RequestSpotInstancesOptions();
|
||||||
|
private static final DateService service = new SimpleDateFormatDateService();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Start date of the request. If this is a one-time request, the request becomes active at this
|
||||||
|
* date and time and remains active until all instances launch, the request expires, or the
|
||||||
|
* request is canceled. If the request is persistent, the request becomes active at this date and
|
||||||
|
* time and remains active until it expires or is canceled.
|
||||||
|
*/
|
||||||
|
public RequestSpotInstancesOptions validFrom(Date start) {
|
||||||
|
formParameters.put("ValidFrom", service.iso8601DateFormat(checkNotNull(start, "start")));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* End date of the request. If this is a one-time request, the request remains active until all
|
||||||
|
* instances launch, the request is canceled, or this date is reached. If the request is
|
||||||
|
* persistent, it remains active until it is canceled or this date and time is reached.
|
||||||
|
*/
|
||||||
|
public RequestSpotInstancesOptions validUntil(Date end) {
|
||||||
|
formParameters.put("ValidUntil", service.iso8601DateFormat(checkNotNull(end, "end")));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Specifies the Spot Instance type.
|
||||||
|
*/
|
||||||
|
public RequestSpotInstancesOptions type(SpotInstanceRequest.Type type) {
|
||||||
|
formParameters.put("Type", checkNotNull(type, "type").toString());
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Specifies the instance launch group. Launch groups are Spot Instances that launch together and
|
||||||
|
* terminate together.
|
||||||
|
*/
|
||||||
|
public RequestSpotInstancesOptions launchGroup(String launchGroup) {
|
||||||
|
formParameters.put("LaunchGroup", checkNotNull(launchGroup, "launchGroup"));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Specifies the Availability Zone group. If you specify the same Availability Zone group for all
|
||||||
|
* Spot Instance requests, all Spot Instances are launched in the same Availability Zone.
|
||||||
|
*/
|
||||||
|
public RequestSpotInstancesOptions availabilityZoneGroup(String availabilityZoneGroup) {
|
||||||
|
formParameters.put("AvailabilityZoneGroup", checkNotNull(availabilityZoneGroup, "availabilityZoneGroup"));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Builder {
|
||||||
|
/**
|
||||||
|
* @see RequestSpotInstancesOptions#validFrom
|
||||||
|
*/
|
||||||
|
public static RequestSpotInstancesOptions validFrom(Date start) {
|
||||||
|
RequestSpotInstancesOptions options = new RequestSpotInstancesOptions();
|
||||||
|
return options.validFrom(start);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see RequestSpotInstancesOptions#validUntil
|
||||||
|
*/
|
||||||
|
public static RequestSpotInstancesOptions validUntil(Date end) {
|
||||||
|
RequestSpotInstancesOptions options = new RequestSpotInstancesOptions();
|
||||||
|
return options.validUntil(end);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see RequestSpotInstancesOptions#type
|
||||||
|
*/
|
||||||
|
public static RequestSpotInstancesOptions type(SpotInstanceRequest.Type type) {
|
||||||
|
RequestSpotInstancesOptions options = new RequestSpotInstancesOptions();
|
||||||
|
return options.type(type);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see RequestSpotInstancesOptions#launchGroup(String)
|
||||||
|
*/
|
||||||
|
public static RequestSpotInstancesOptions launchGroup(String launchGroup) {
|
||||||
|
RequestSpotInstancesOptions options = new RequestSpotInstancesOptions();
|
||||||
|
return options.launchGroup(launchGroup);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see RequestSpotInstancesOptions#availabilityZoneGroup
|
||||||
|
*/
|
||||||
|
public static RequestSpotInstancesOptions availabilityZoneGroup(String availabilityZoneGroup) {
|
||||||
|
RequestSpotInstancesOptions options = new RequestSpotInstancesOptions();
|
||||||
|
return options.availabilityZoneGroup(availabilityZoneGroup);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,78 @@
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Copyright (C) 2010 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 java.util.NoSuchElementException;
|
||||||
|
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
import javax.inject.Singleton;
|
||||||
|
|
||||||
|
import org.jclouds.aws.ec2.AWSEC2Client;
|
||||||
|
import org.jclouds.aws.ec2.domain.SpotInstanceRequest;
|
||||||
|
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;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @author Adrian Cole
|
||||||
|
*/
|
||||||
|
@Singleton
|
||||||
|
public class SpotInstanceRequestActive implements Predicate<SpotInstanceRequest> {
|
||||||
|
|
||||||
|
private final AWSEC2Client client;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
protected Logger logger = Logger.NULL;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
public SpotInstanceRequestActive(AWSEC2Client client) {
|
||||||
|
this.client = client;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean apply(SpotInstanceRequest spot) {
|
||||||
|
logger.trace("looking for state on spot %s", spot);
|
||||||
|
try {
|
||||||
|
spot = refresh(spot);
|
||||||
|
logger.trace("%s: looking for spot state %s: currently: %s", spot.getId(), SpotInstanceRequest.State.ACTIVE,
|
||||||
|
spot.getState());
|
||||||
|
if (spot.getState() == SpotInstanceRequest.State.CANCELLED
|
||||||
|
|| spot.getState() == SpotInstanceRequest.State.CLOSED)
|
||||||
|
throw new IllegalStateException(String.format("spot request %s %s", spot.getId(), spot.getState()));
|
||||||
|
if (spot.getFaultCode() != null)
|
||||||
|
throw new IllegalStateException(String.format("spot request %s fault code(%s) message(%s)", spot.getId(),
|
||||||
|
spot.getFaultCode(), spot.getFaultMessage()));
|
||||||
|
return spot.getState() == SpotInstanceRequest.State.ACTIVE;
|
||||||
|
} catch (ResourceNotFoundException e) {
|
||||||
|
return false;
|
||||||
|
} catch (NoSuchElementException e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private SpotInstanceRequest refresh(SpotInstanceRequest spot) {
|
||||||
|
return Iterables.getOnlyElement(client.getSpotInstanceServices().describeSpotInstanceRequestsInRegion(
|
||||||
|
spot.getRegion(), spot.getId()));
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,128 @@
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
|
||||||
|
*
|
||||||
|
* ====================================================================
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
* ====================================================================
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jclouds.aws.ec2.services;
|
||||||
|
|
||||||
|
import static org.jclouds.aws.reference.FormParameters.ACTION;
|
||||||
|
import static org.jclouds.aws.reference.FormParameters.VERSION;
|
||||||
|
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
import javax.ws.rs.FormParam;
|
||||||
|
import javax.ws.rs.POST;
|
||||||
|
import javax.ws.rs.Path;
|
||||||
|
|
||||||
|
import org.jclouds.aws.ec2.AWSEC2AsyncClient;
|
||||||
|
import org.jclouds.aws.ec2.binders.BindLaunchSpecificationToFormParams;
|
||||||
|
import org.jclouds.aws.ec2.binders.BindSpotInstanceRequestIdsToIndexedFormParams;
|
||||||
|
import org.jclouds.aws.ec2.domain.LaunchSpecification;
|
||||||
|
import org.jclouds.aws.ec2.domain.Spot;
|
||||||
|
import org.jclouds.aws.ec2.domain.SpotInstanceRequest;
|
||||||
|
import org.jclouds.aws.ec2.options.DescribeSpotPriceHistoryOptions;
|
||||||
|
import org.jclouds.aws.ec2.options.RequestSpotInstancesOptions;
|
||||||
|
import org.jclouds.aws.ec2.xml.DescribeSpotPriceHistoryResponseHandler;
|
||||||
|
import org.jclouds.aws.ec2.xml.SpotInstanceHandler;
|
||||||
|
import org.jclouds.aws.ec2.xml.SpotInstancesHandler;
|
||||||
|
import org.jclouds.aws.filters.FormSigner;
|
||||||
|
import org.jclouds.location.functions.RegionToEndpointOrProviderIfNull;
|
||||||
|
import org.jclouds.rest.annotations.BinderParam;
|
||||||
|
import org.jclouds.rest.annotations.EndpointParam;
|
||||||
|
import org.jclouds.rest.annotations.ExceptionParser;
|
||||||
|
import org.jclouds.rest.annotations.FormParams;
|
||||||
|
import org.jclouds.rest.annotations.RequestFilters;
|
||||||
|
import org.jclouds.rest.annotations.VirtualHost;
|
||||||
|
import org.jclouds.rest.annotations.XMLResponseParser;
|
||||||
|
import org.jclouds.rest.functions.ReturnEmptySetOnNotFoundOr404;
|
||||||
|
import org.jclouds.rest.functions.ReturnVoidOnNotFoundOr404;
|
||||||
|
|
||||||
|
import com.google.common.util.concurrent.ListenableFuture;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides access to EC2 Spot Instances via their REST API.
|
||||||
|
* <p/>
|
||||||
|
*
|
||||||
|
* @author Adrian Cole
|
||||||
|
*/
|
||||||
|
@RequestFilters(FormSigner.class)
|
||||||
|
@FormParams(keys = VERSION, values = AWSEC2AsyncClient.VERSION)
|
||||||
|
@VirtualHost
|
||||||
|
public interface SpotInstanceAsyncClient {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see SpotInstanceClient#describeSpotInstanceRequestsInRegion
|
||||||
|
*/
|
||||||
|
@POST
|
||||||
|
@Path("/")
|
||||||
|
@FormParams(keys = ACTION, values = "DescribeSpotInstanceRequests")
|
||||||
|
@ExceptionParser(ReturnEmptySetOnNotFoundOr404.class)
|
||||||
|
@XMLResponseParser(SpotInstancesHandler.class)
|
||||||
|
ListenableFuture<? extends Set<SpotInstanceRequest>> describeSpotInstanceRequestsInRegion(
|
||||||
|
@EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
|
||||||
|
@BinderParam(BindSpotInstanceRequestIdsToIndexedFormParams.class) String... requestIds);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see SpotInstanceClient#requestSpotInstanceInRegion
|
||||||
|
*/
|
||||||
|
@POST
|
||||||
|
@Path("/")
|
||||||
|
@FormParams(keys = ACTION, values = "RequestSpotInstances")
|
||||||
|
@XMLResponseParser(SpotInstanceHandler.class)
|
||||||
|
ListenableFuture<SpotInstanceRequest> requestSpotInstanceInRegion(
|
||||||
|
@EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
|
||||||
|
@FormParam("SpotPrice") float spotPrice, @FormParam("LaunchSpecification.ImageId") String imageId,
|
||||||
|
@FormParam("LaunchSpecification.InstanceType") String instanceType);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see SpotInstanceClient#requestSpotInstancesInRegion
|
||||||
|
*/
|
||||||
|
@POST
|
||||||
|
@Path("/")
|
||||||
|
@FormParams(keys = ACTION, values = "RequestSpotInstances")
|
||||||
|
@XMLResponseParser(SpotInstancesHandler.class)
|
||||||
|
ListenableFuture<? extends Set<SpotInstanceRequest>> requestSpotInstancesInRegion(
|
||||||
|
@EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
|
||||||
|
@FormParam("SpotPrice") float spotPrice, @FormParam("InstanceCount") int instanceCount,
|
||||||
|
@BinderParam(BindLaunchSpecificationToFormParams.class) LaunchSpecification launchSpec,
|
||||||
|
RequestSpotInstancesOptions... options);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see SpotInstanceClient#describeSpotPriceHistoryInRegion
|
||||||
|
*/
|
||||||
|
@POST
|
||||||
|
@Path("/")
|
||||||
|
@FormParams(keys = ACTION, values = "DescribeSpotPriceHistory")
|
||||||
|
@XMLResponseParser(DescribeSpotPriceHistoryResponseHandler.class)
|
||||||
|
@ExceptionParser(ReturnEmptySetOnNotFoundOr404.class)
|
||||||
|
ListenableFuture<? extends Set<Spot>> describeSpotPriceHistoryInRegion(
|
||||||
|
@EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
|
||||||
|
DescribeSpotPriceHistoryOptions... options);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see SpotInstanceClient#cancelSpotInstanceRequestsInRegion
|
||||||
|
*/
|
||||||
|
@POST
|
||||||
|
@Path("/")
|
||||||
|
@FormParams(keys = ACTION, values = "CancelSpotInstanceRequests")
|
||||||
|
@ExceptionParser(ReturnVoidOnNotFoundOr404.class)
|
||||||
|
ListenableFuture<Void> cancelSpotInstanceRequestsInRegion(
|
||||||
|
@EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
|
||||||
|
@BinderParam(BindSpotInstanceRequestIdsToIndexedFormParams.class) String... requestIds);
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,159 @@
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
|
||||||
|
*
|
||||||
|
* ====================================================================
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
* ====================================================================
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jclouds.aws.ec2.services;
|
||||||
|
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
|
import org.jclouds.aws.ec2.domain.LaunchSpecification;
|
||||||
|
import org.jclouds.aws.ec2.domain.Spot;
|
||||||
|
import org.jclouds.aws.ec2.domain.SpotInstanceRequest;
|
||||||
|
import org.jclouds.aws.ec2.options.DescribeSpotPriceHistoryOptions;
|
||||||
|
import org.jclouds.aws.ec2.options.RequestSpotInstancesOptions;
|
||||||
|
import org.jclouds.concurrent.Timeout;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides Spot Instance services for EC2. For more information, refer to the Amazon EC2 Developer
|
||||||
|
* Guide.
|
||||||
|
* <p/>
|
||||||
|
*
|
||||||
|
* @author Adrian Cole
|
||||||
|
*/
|
||||||
|
@Timeout(duration = 45, timeUnit = TimeUnit.SECONDS)
|
||||||
|
public interface SpotInstanceClient {
|
||||||
|
/**
|
||||||
|
* Describes Spot Instance requests. Spot Instances are instances that Amazon EC2 starts on your
|
||||||
|
* behalf when the maximum price that you specify exceeds the current Spot Price. Amazon EC2
|
||||||
|
* periodically sets the Spot Price based on available Spot Instance capacity and current spot
|
||||||
|
* instance requests. For conceptual information about Spot Instances, refer to the Amazon
|
||||||
|
* Elastic Compute Cloud Developer Guide or Amazon Elastic Compute Cloud User Guide.
|
||||||
|
*
|
||||||
|
* @param region
|
||||||
|
* Region where the spot instance service is running
|
||||||
|
* @param requestIds
|
||||||
|
* Specifies the ID of the Spot Instance request.
|
||||||
|
*
|
||||||
|
* @see #requestSpotInstancesInRegion
|
||||||
|
* @see #cancelSpotInstanceRequestsInRegion
|
||||||
|
* @see #describeSpotPriceHistoryInRegion
|
||||||
|
* @see <a href=
|
||||||
|
* "http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-DescribeSpotInstanceRequests.html"
|
||||||
|
* />
|
||||||
|
* @return TODO
|
||||||
|
*/
|
||||||
|
Set<SpotInstanceRequest> describeSpotInstanceRequestsInRegion(@Nullable String region, String... requestIds);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* request a single spot instance
|
||||||
|
*
|
||||||
|
* @param region
|
||||||
|
* Region where the spot instance service is running
|
||||||
|
* @param spotPrice
|
||||||
|
* Specifies the maximum hourly price for any Spot Instance launched to fulfill the
|
||||||
|
* request.
|
||||||
|
* @param imageId
|
||||||
|
* The AMI ID.
|
||||||
|
* @param instanceType
|
||||||
|
* The instance type (ex. m1.small)
|
||||||
|
* @return spot instance request
|
||||||
|
* @see #requestSpotInstancesInRegion
|
||||||
|
*/
|
||||||
|
SpotInstanceRequest requestSpotInstanceInRegion(@Nullable String region, float spotPrice, String imageId,
|
||||||
|
String instanceType);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a Spot Instance request. Spot Instances are instances that Amazon EC2 starts on your
|
||||||
|
* behalf when the maximum price that you specify exceeds the current Spot Price. Amazon EC2
|
||||||
|
* periodically sets the Spot Price based on available Spot Instance capacity and current spot
|
||||||
|
* instance requests. For conceptual information about Spot Instances, refer to the Amazon
|
||||||
|
* Elastic Compute Cloud Developer Guide or Amazon Elastic Compute Cloud User Guide.
|
||||||
|
*
|
||||||
|
* @param region
|
||||||
|
* Region where the spot instance service is running
|
||||||
|
* @param spotPrice
|
||||||
|
* Specifies the maximum hourly price for any Spot Instance launched to fulfill the
|
||||||
|
* request.
|
||||||
|
* @param instanceCount
|
||||||
|
* number of instances to request
|
||||||
|
* @param launchSpec
|
||||||
|
* includes at least The AMI ID and instance type (ex. m1.small)
|
||||||
|
* @param options
|
||||||
|
* options including expiration time or grouping
|
||||||
|
*
|
||||||
|
* @see #describeSpotInstanceRequestsInRegion
|
||||||
|
* @see #cancelSpotInstanceRequestsInRegion
|
||||||
|
* @see #describeSpotPriceHistoryInRegion
|
||||||
|
* @see <a href=
|
||||||
|
* "http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-RequestSpotInstances.html"
|
||||||
|
* />
|
||||||
|
* @return set of spot instance requests
|
||||||
|
*/
|
||||||
|
Set<SpotInstanceRequest> requestSpotInstancesInRegion(@Nullable String region, float spotPrice, int instanceCount,
|
||||||
|
LaunchSpecification launchSpec, RequestSpotInstancesOptions... options);
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Describes Spot Price history. Spot Instances are instances that Amazon EC2 starts on your
|
||||||
|
* behalf when the maximum price that you specify exceeds the current Spot Price. Amazon EC2
|
||||||
|
* periodically sets the Spot Price based on available Spot Instance capacity and current spot
|
||||||
|
* instance requests. For conceptual information about Spot Instances, refer to the Amazon
|
||||||
|
* Elastic Compute Cloud Developer Guide or Amazon Elastic Compute Cloud User Guide.
|
||||||
|
*
|
||||||
|
* @param region
|
||||||
|
* Region where the spot instance service is running
|
||||||
|
* @param options
|
||||||
|
* options to control the list
|
||||||
|
*
|
||||||
|
* @see #describeSpotInstanceRequestsInRegion
|
||||||
|
* @see #requestSpotInstancesInRegion
|
||||||
|
* @see #cancelSpotInstanceRequestsInRegion
|
||||||
|
* @see <a href=
|
||||||
|
* "http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-DescribeSpotInstanceRequests.html"
|
||||||
|
* />
|
||||||
|
* @return TODO
|
||||||
|
*/
|
||||||
|
@Timeout(duration = 2, timeUnit = TimeUnit.MINUTES)
|
||||||
|
Set<Spot> describeSpotPriceHistoryInRegion(@Nullable String region, DescribeSpotPriceHistoryOptions... options);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cancels one or more Spot Instance requests. Spot Instances are instances that Amazon EC2
|
||||||
|
* starts on your behalf when the maximum price that you specify exceeds the current Spot Price.
|
||||||
|
* Amazon EC2 periodically sets the Spot Price based on available Spot Instance capacity and
|
||||||
|
* current spot instance requests. For conceptual information about Spot Instances, refer to the
|
||||||
|
* Amazon Elastic Compute Cloud Developer Guide or Amazon Elastic Compute Cloud User Guide.
|
||||||
|
*
|
||||||
|
* @param region
|
||||||
|
* Region where the spot instance service is running
|
||||||
|
* @param requestIds
|
||||||
|
* Specifies the ID of the Spot Instance request.
|
||||||
|
*
|
||||||
|
* @see #describeSpotInstanceRequestsInRegion
|
||||||
|
* @see #requestSpotInstancesInRegion
|
||||||
|
* @see #describeSpotPriceHistoryInRegion
|
||||||
|
* @see <a href=
|
||||||
|
* "http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-CancelSpotInstanceRequests.html"
|
||||||
|
* />
|
||||||
|
* @return TODO
|
||||||
|
*/
|
||||||
|
String cancelSpotInstanceRequestsInRegion(@Nullable String region, String... requestIds);
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,79 @@
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
|
||||||
|
*
|
||||||
|
* ====================================================================
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
* ====================================================================
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jclouds.aws.ec2.xml;
|
||||||
|
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import javax.inject.Inject;
|
||||||
|
|
||||||
|
import org.jclouds.aws.ec2.domain.Spot;
|
||||||
|
import org.jclouds.http.HttpRequest;
|
||||||
|
import org.jclouds.http.functions.ParseSax;
|
||||||
|
import org.jclouds.http.functions.ParseSax.HandlerWithResult;
|
||||||
|
import org.xml.sax.Attributes;
|
||||||
|
import org.xml.sax.SAXException;
|
||||||
|
|
||||||
|
import com.google.common.collect.ImmutableSet;
|
||||||
|
import com.google.common.collect.ImmutableSet.Builder;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Adrian Cole
|
||||||
|
*/
|
||||||
|
public class DescribeSpotPriceHistoryResponseHandler extends
|
||||||
|
ParseSax.HandlerWithResult<Set<Spot>> {
|
||||||
|
|
||||||
|
private Builder<Spot> spots = ImmutableSet.<Spot>builder();
|
||||||
|
private final SpotHandler spotHandler;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
public DescribeSpotPriceHistoryResponseHandler(SpotHandler spotHandler) {
|
||||||
|
this.spotHandler = spotHandler;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Set<Spot> getResult() {
|
||||||
|
return spots.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public HandlerWithResult<Set<Spot>> setContext(HttpRequest request) {
|
||||||
|
spotHandler.setContext(request);
|
||||||
|
return super.setContext(request);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void startElement(String uri, String localName, String qName, Attributes attributes)
|
||||||
|
throws SAXException {
|
||||||
|
if (!qName.equals("item"))
|
||||||
|
spotHandler.startElement(uri, localName, qName, attributes);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void endElement(String uri, String localName, String qName) throws SAXException {
|
||||||
|
if (qName.equals("item")) {
|
||||||
|
spots.add(spotHandler.getResult());
|
||||||
|
}
|
||||||
|
spotHandler.endElement(uri, localName, qName);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void characters(char ch[], int start, int length) {
|
||||||
|
spotHandler.characters(ch, start, length);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,115 @@
|
||||||
|
package org.jclouds.aws.ec2.xml;
|
||||||
|
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
import javax.inject.Inject;
|
||||||
|
|
||||||
|
import org.jclouds.aws.ec2.domain.LaunchSpecification;
|
||||||
|
import org.jclouds.aws.ec2.domain.LaunchSpecification.Builder;
|
||||||
|
import org.jclouds.date.DateService;
|
||||||
|
import org.jclouds.ec2.domain.BlockDeviceMapping;
|
||||||
|
import org.jclouds.http.functions.ParseSax.HandlerForGeneratedRequestWithResult;
|
||||||
|
import org.jclouds.location.Region;
|
||||||
|
import org.jclouds.logging.Logger;
|
||||||
|
import org.xml.sax.Attributes;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Adrian Cole
|
||||||
|
*/
|
||||||
|
public class LaunchSpecificationHandler extends HandlerForGeneratedRequestWithResult<LaunchSpecification> {
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
protected Logger logger = Logger.NULL;
|
||||||
|
|
||||||
|
protected final DateService dateService;
|
||||||
|
protected final String defaultRegion;
|
||||||
|
protected final Builder builder;
|
||||||
|
protected final BlockDeviceMapping.Builder blockDeviceMappingBuilder;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
public LaunchSpecificationHandler(DateService dateService, @Region String defaultRegion,
|
||||||
|
LaunchSpecification.Builder builder, BlockDeviceMapping.Builder blockDeviceMappingBuilder) {
|
||||||
|
this.dateService = dateService;
|
||||||
|
this.defaultRegion = defaultRegion;
|
||||||
|
this.builder = builder;
|
||||||
|
this.blockDeviceMappingBuilder = blockDeviceMappingBuilder;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected String currentOrNull() {
|
||||||
|
String returnVal = currentText.toString().trim();
|
||||||
|
return returnVal.equals("") ? null : returnVal;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected StringBuilder currentText = new StringBuilder();
|
||||||
|
|
||||||
|
private boolean inBlockDeviceMapping;
|
||||||
|
|
||||||
|
public void startElement(String uri, String name, String qName, Attributes attrs) {
|
||||||
|
if (qName.equals("blockDeviceMapping")) {
|
||||||
|
inBlockDeviceMapping = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void endElement(String uri, String name, String qName) {
|
||||||
|
if (qName.equals("blockDeviceMapping")) {
|
||||||
|
inBlockDeviceMapping = false;
|
||||||
|
} else if (qName.equals("item") && inBlockDeviceMapping) {
|
||||||
|
try {
|
||||||
|
builder.blockDeviceMapping(blockDeviceMappingBuilder.build());
|
||||||
|
} finally {
|
||||||
|
blockDeviceMappingBuilder.clear();
|
||||||
|
}
|
||||||
|
} else if (qName.equals("deviceName")) {
|
||||||
|
blockDeviceMappingBuilder.deviceName(currentOrNull());
|
||||||
|
} else if (qName.equals("virtualName")) {
|
||||||
|
blockDeviceMappingBuilder.virtualName(currentOrNull());
|
||||||
|
} else if (qName.equals("snapshotId")) {
|
||||||
|
blockDeviceMappingBuilder.snapshotId(currentOrNull());
|
||||||
|
} else if (qName.equals("volumeSize")) {
|
||||||
|
String volumeSize = currentOrNull();
|
||||||
|
if (volumeSize != null)
|
||||||
|
blockDeviceMappingBuilder.sizeInGib(Integer.parseInt(volumeSize));
|
||||||
|
} else if (qName.equals("noDevice")) {
|
||||||
|
String noDevice = currentOrNull();
|
||||||
|
if (noDevice != null)
|
||||||
|
blockDeviceMappingBuilder.noDevice(Boolean.parseBoolean(noDevice));
|
||||||
|
} else if (qName.equals("deleteOnTermination")) {
|
||||||
|
String deleteOnTermination = currentOrNull();
|
||||||
|
if (deleteOnTermination != null)
|
||||||
|
blockDeviceMappingBuilder.deleteOnTermination(Boolean.parseBoolean(deleteOnTermination));
|
||||||
|
} else if (qName.equals("groupId")) {
|
||||||
|
builder.groupId(currentOrNull());
|
||||||
|
} else if (qName.equals("imageId")) {
|
||||||
|
builder.imageId(currentOrNull());
|
||||||
|
} else if (qName.equals("instanceType")) {
|
||||||
|
builder.instanceType(currentOrNull());
|
||||||
|
} else if (qName.equals("kernelId")) {
|
||||||
|
builder.kernelId(currentOrNull());
|
||||||
|
} else if (qName.equals("keyName")) {
|
||||||
|
builder.keyName(currentOrNull());
|
||||||
|
} else if (qName.equals("availabilityZone")) {
|
||||||
|
builder.availabilityZone(currentOrNull());
|
||||||
|
} else if (qName.equals("ramdiskId")) {
|
||||||
|
builder.ramdiskId(currentOrNull());
|
||||||
|
} else if (qName.equals("enabled")) {
|
||||||
|
String monitoringEnabled = currentOrNull();
|
||||||
|
if (monitoringEnabled != null)
|
||||||
|
builder.monitoringEnabled(new Boolean(monitoringEnabled));
|
||||||
|
}
|
||||||
|
currentText = new StringBuilder();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void characters(char ch[], int start, int length) {
|
||||||
|
currentText.append(ch, start, length);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public LaunchSpecification getResult() {
|
||||||
|
try {
|
||||||
|
return builder.build();
|
||||||
|
} finally {
|
||||||
|
builder.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -24,7 +24,6 @@ import javax.inject.Inject;
|
||||||
import org.jclouds.aws.ec2.domain.PlacementGroup;
|
import org.jclouds.aws.ec2.domain.PlacementGroup;
|
||||||
import org.jclouds.aws.ec2.domain.PlacementGroup.State;
|
import org.jclouds.aws.ec2.domain.PlacementGroup.State;
|
||||||
import org.jclouds.aws.util.AWSUtils;
|
import org.jclouds.aws.util.AWSUtils;
|
||||||
import org.jclouds.date.DateService;
|
|
||||||
import org.jclouds.http.functions.ParseSax;
|
import org.jclouds.http.functions.ParseSax;
|
||||||
import org.jclouds.location.Region;
|
import org.jclouds.location.Region;
|
||||||
|
|
||||||
|
@ -36,8 +35,6 @@ public class PlacementGroupHandler extends
|
||||||
ParseSax.HandlerForGeneratedRequestWithResult<PlacementGroup> {
|
ParseSax.HandlerForGeneratedRequestWithResult<PlacementGroup> {
|
||||||
private StringBuilder currentText = new StringBuilder();
|
private StringBuilder currentText = new StringBuilder();
|
||||||
|
|
||||||
@Inject
|
|
||||||
protected DateService dateService;
|
|
||||||
@Inject
|
@Inject
|
||||||
@Region
|
@Region
|
||||||
String defaultRegion;
|
String defaultRegion;
|
||||||
|
|
|
@ -0,0 +1,75 @@
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
|
||||||
|
*
|
||||||
|
* ====================================================================
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
* ====================================================================
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jclouds.aws.ec2.xml;
|
||||||
|
|
||||||
|
import javax.inject.Inject;
|
||||||
|
|
||||||
|
import org.jclouds.aws.ec2.domain.Spot;
|
||||||
|
import org.jclouds.aws.util.AWSUtils;
|
||||||
|
import org.jclouds.date.DateService;
|
||||||
|
import org.jclouds.http.functions.ParseSax;
|
||||||
|
import org.jclouds.location.Region;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Adrian Cole
|
||||||
|
*/
|
||||||
|
public class SpotHandler extends ParseSax.HandlerForGeneratedRequestWithResult<Spot> {
|
||||||
|
private StringBuilder currentText = new StringBuilder();
|
||||||
|
|
||||||
|
protected final DateService dateService;
|
||||||
|
protected final String defaultRegion;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
public SpotHandler(DateService dateService, @Region String defaultRegion) {
|
||||||
|
this.dateService = dateService;
|
||||||
|
this.defaultRegion = defaultRegion;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Spot.Builder builder = Spot.builder();
|
||||||
|
|
||||||
|
public Spot getResult() {
|
||||||
|
try {
|
||||||
|
String region = getRequest() == null ? null : AWSUtils.findRegionInArgsOrNull(getRequest());
|
||||||
|
if (region == null)
|
||||||
|
region = defaultRegion;
|
||||||
|
return builder.region(region).build();
|
||||||
|
} finally {
|
||||||
|
builder.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void endElement(String uri, String name, String qName) {
|
||||||
|
if (qName.equals("instanceType")) {
|
||||||
|
builder.instanceType(currentText.toString().trim());
|
||||||
|
} else if (qName.equals("productDescription")) {
|
||||||
|
builder.productDescription(currentText.toString().trim());
|
||||||
|
} else if (qName.equals("spotPrice")) {
|
||||||
|
builder.spotPrice(Float.parseFloat(currentText.toString().trim()));
|
||||||
|
} else if (qName.equals("timestamp")) {
|
||||||
|
builder.timestamp(dateService.iso8601DateParse(currentText.toString().trim()));
|
||||||
|
}
|
||||||
|
currentText = new StringBuilder();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void characters(char ch[], int start, int length) {
|
||||||
|
currentText.append(ch, start, length);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,125 @@
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
|
||||||
|
*
|
||||||
|
* ====================================================================
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
* ====================================================================
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jclouds.aws.ec2.xml;
|
||||||
|
|
||||||
|
import javax.inject.Inject;
|
||||||
|
|
||||||
|
import org.jclouds.aws.ec2.domain.SpotInstanceRequest;
|
||||||
|
import org.jclouds.aws.ec2.domain.SpotInstanceRequest.Builder;
|
||||||
|
import org.jclouds.aws.util.AWSUtils;
|
||||||
|
import org.jclouds.date.DateService;
|
||||||
|
import org.jclouds.http.functions.ParseSax;
|
||||||
|
import org.jclouds.location.Region;
|
||||||
|
import org.xml.sax.Attributes;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Adrian Cole
|
||||||
|
*/
|
||||||
|
public class SpotInstanceHandler extends ParseSax.HandlerForGeneratedRequestWithResult<SpotInstanceRequest> {
|
||||||
|
private StringBuilder currentText = new StringBuilder();
|
||||||
|
|
||||||
|
protected final DateService dateService;
|
||||||
|
protected final String defaultRegion;
|
||||||
|
protected final Builder builder;
|
||||||
|
protected boolean inLaunchSpecification;
|
||||||
|
protected final LaunchSpecificationHandler launchSpecificationHandler;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
public SpotInstanceHandler(DateService dateService, @Region String defaultRegion,
|
||||||
|
LaunchSpecificationHandler launchSpecificationHandler, SpotInstanceRequest.Builder builder) {
|
||||||
|
this.dateService = dateService;
|
||||||
|
this.defaultRegion = defaultRegion;
|
||||||
|
this.launchSpecificationHandler = launchSpecificationHandler;
|
||||||
|
this.builder = builder;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected String currentOrNull() {
|
||||||
|
String returnVal = currentText.toString().trim();
|
||||||
|
return returnVal.equals("") ? null : returnVal;
|
||||||
|
}
|
||||||
|
|
||||||
|
public SpotInstanceRequest getResult() {
|
||||||
|
try {
|
||||||
|
String region = getRequest() != null ? AWSUtils.findRegionInArgsOrNull(getRequest()) : null;
|
||||||
|
if (region == null)
|
||||||
|
region = defaultRegion;
|
||||||
|
return builder.region(region).build();
|
||||||
|
} finally {
|
||||||
|
builder.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void startElement(String uri, String name, String qName, Attributes attrs) {
|
||||||
|
if (qName.equals("launchSpecification")) {
|
||||||
|
inLaunchSpecification = true;
|
||||||
|
}
|
||||||
|
if (inLaunchSpecification)
|
||||||
|
launchSpecificationHandler.startElement(uri, name, qName, attrs);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void endElement(String uri, String name, String qName) {
|
||||||
|
if (qName.equals("launchSpecification")) {
|
||||||
|
inLaunchSpecification = false;
|
||||||
|
builder.launchSpecification(launchSpecificationHandler.getResult());
|
||||||
|
}
|
||||||
|
if (inLaunchSpecification) {
|
||||||
|
launchSpecificationHandler.endElement(uri, name, qName);
|
||||||
|
} else if (qName.equals("spotInstanceRequestId")) {
|
||||||
|
builder.id(currentOrNull());
|
||||||
|
} else if (qName.equals("instanceId")) {
|
||||||
|
builder.instanceId(currentOrNull());
|
||||||
|
} else if (qName.equals("availabilityZoneGroup")) {
|
||||||
|
builder.availabilityZoneGroup(currentOrNull());
|
||||||
|
} else if (qName.equals("launchGroup")) {
|
||||||
|
builder.launchGroup(currentOrNull());
|
||||||
|
} else if (qName.equals("code")) {
|
||||||
|
builder.faultCode(currentOrNull());
|
||||||
|
} else if (qName.equals("message")) {
|
||||||
|
builder.faultMessage(currentOrNull());
|
||||||
|
} else if (qName.equals("spotPrice")) {
|
||||||
|
String price = currentOrNull();
|
||||||
|
if (price != null)
|
||||||
|
builder.spotPrice(Float.parseFloat(price));
|
||||||
|
} else if (qName.equals("type")) {
|
||||||
|
String type = currentOrNull();
|
||||||
|
if (type != null)
|
||||||
|
builder.type(SpotInstanceRequest.Type.fromValue(type));
|
||||||
|
} else if (qName.equals("state")) {
|
||||||
|
String state = currentOrNull();
|
||||||
|
if (state != null)
|
||||||
|
builder.state(SpotInstanceRequest.State.fromValue(state));
|
||||||
|
} else if (qName.equals("createTime")) {
|
||||||
|
String createTime = currentOrNull();
|
||||||
|
if (createTime != null)
|
||||||
|
builder.createTime(dateService.iso8601DateParse(createTime));
|
||||||
|
} else if (qName.equals("productDescription")) {
|
||||||
|
builder.productDescription(currentOrNull());
|
||||||
|
}
|
||||||
|
currentText = new StringBuilder();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void characters(char ch[], int start, int length) {
|
||||||
|
if (inLaunchSpecification)
|
||||||
|
launchSpecificationHandler.characters(ch, start, length);
|
||||||
|
else
|
||||||
|
currentText.append(ch, start, length);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,84 @@
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
|
||||||
|
*
|
||||||
|
* ====================================================================
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
* ====================================================================
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jclouds.aws.ec2.xml;
|
||||||
|
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import javax.inject.Inject;
|
||||||
|
|
||||||
|
import org.jclouds.aws.ec2.domain.SpotInstanceRequest;
|
||||||
|
import org.jclouds.http.HttpRequest;
|
||||||
|
import org.jclouds.http.functions.ParseSax;
|
||||||
|
import org.jclouds.http.functions.ParseSax.HandlerWithResult;
|
||||||
|
import org.xml.sax.Attributes;
|
||||||
|
import org.xml.sax.SAXException;
|
||||||
|
|
||||||
|
import com.google.common.collect.ImmutableSet;
|
||||||
|
import com.google.common.collect.ImmutableSet.Builder;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Adrian Cole
|
||||||
|
*/
|
||||||
|
public class SpotInstancesHandler extends ParseSax.HandlerWithResult<Set<SpotInstanceRequest>> {
|
||||||
|
|
||||||
|
private final Builder<SpotInstanceRequest> spotRequests = ImmutableSet.<SpotInstanceRequest> builder();
|
||||||
|
private final SpotInstanceHandler spotRequestHandler;
|
||||||
|
private int itemDepth;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
public SpotInstancesHandler(SpotInstanceHandler spotRequestHandler) {
|
||||||
|
this.spotRequestHandler = spotRequestHandler;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Set<SpotInstanceRequest> getResult() {
|
||||||
|
return spotRequests.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public HandlerWithResult<Set<SpotInstanceRequest>> setContext(HttpRequest request) {
|
||||||
|
spotRequestHandler.setContext(request);
|
||||||
|
return super.setContext(request);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
|
||||||
|
if (qName.equals("item"))
|
||||||
|
itemDepth++;
|
||||||
|
if (itemDepth >= 1)
|
||||||
|
spotRequestHandler.startElement(uri, localName, qName, attributes);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void endElement(String uri, String localName, String qName) throws SAXException {
|
||||||
|
if (qName.equals("item") && itemDepth == 1) {
|
||||||
|
spotRequests.add(spotRequestHandler.getResult());
|
||||||
|
}
|
||||||
|
if (qName.equals("item"))
|
||||||
|
itemDepth--;
|
||||||
|
if (itemDepth >= 1)
|
||||||
|
spotRequestHandler.endElement(uri, localName, qName);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void characters(char ch[], int start, int length) {
|
||||||
|
if (itemDepth >= 1)
|
||||||
|
spotRequestHandler.characters(ch, start, length);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,60 @@
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
|
||||||
|
*
|
||||||
|
* ====================================================================
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
* ====================================================================
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jclouds.aws.ec2.binders;
|
||||||
|
|
||||||
|
import static org.testng.Assert.assertEquals;
|
||||||
|
|
||||||
|
import java.net.UnknownHostException;
|
||||||
|
|
||||||
|
import org.jclouds.aws.ec2.domain.LaunchSpecification;
|
||||||
|
import org.jclouds.ec2.domain.InstanceType;
|
||||||
|
import org.jclouds.encryption.internal.Base64;
|
||||||
|
import org.testng.annotations.Test;
|
||||||
|
|
||||||
|
import com.google.common.collect.ImmutableMap;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Adrian Cole
|
||||||
|
*/
|
||||||
|
@Test(groups = "unit")
|
||||||
|
public class BindLaunchSpecificationToFormParamsTest {
|
||||||
|
BindLaunchSpecificationToFormParams binder = new BindLaunchSpecificationToFormParams();
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testApplyWithBlockDeviceMappings() throws UnknownHostException {
|
||||||
|
LaunchSpecification spec = LaunchSpecification.builder().instanceType(InstanceType.T1_MICRO).imageId("ami-123")
|
||||||
|
.mapNewVolumeToDevice("/dev/sda1", 120, true).build();
|
||||||
|
|
||||||
|
assertEquals(binder.apply(spec), ImmutableMap.of("LaunchSpecification.InstanceType", "t1.micro",
|
||||||
|
"LaunchSpecification.ImageId", "ami-123", "LaunchSpecification.BlockDeviceMapping.1.DeviceName",
|
||||||
|
"/dev/sda1", "LaunchSpecification.BlockDeviceMapping.1.Ebs.VolumeSize", "120",
|
||||||
|
"LaunchSpecification.BlockDeviceMapping.1.Ebs.DeleteOnTermination", "true"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testApplyWithUserData() throws UnknownHostException {
|
||||||
|
LaunchSpecification spec = LaunchSpecification.builder().instanceType(InstanceType.T1_MICRO).imageId("ami-123")
|
||||||
|
.userData("hello".getBytes()).build();
|
||||||
|
|
||||||
|
assertEquals(binder.apply(spec), ImmutableMap.of("LaunchSpecification.InstanceType", "t1.micro",
|
||||||
|
"LaunchSpecification.ImageId", "ami-123", "LaunchSpecification.UserData",
|
||||||
|
Base64.encodeBytes("hello".getBytes())));
|
||||||
|
}
|
||||||
|
}
|
|
@ -59,13 +59,13 @@ public class AWSEC2ComputeServiceLiveTest extends EC2ComputeServiceLiveTest {
|
||||||
@Test(enabled = true, dependsOnMethods = "testCompareSizes")
|
@Test(enabled = true, dependsOnMethods = "testCompareSizes")
|
||||||
public void testExtendedOptionsAndLogin() throws Exception {
|
public void testExtendedOptionsAndLogin() throws Exception {
|
||||||
SecurityGroupClient securityGroupClient = EC2Client.class.cast(context.getProviderSpecificContext().getApi())
|
SecurityGroupClient securityGroupClient = EC2Client.class.cast(context.getProviderSpecificContext().getApi())
|
||||||
.getSecurityGroupServices();
|
.getSecurityGroupServices();
|
||||||
|
|
||||||
KeyPairClient keyPairClient = EC2Client.class.cast(context.getProviderSpecificContext().getApi())
|
KeyPairClient keyPairClient = EC2Client.class.cast(context.getProviderSpecificContext().getApi())
|
||||||
.getKeyPairServices();
|
.getKeyPairServices();
|
||||||
|
|
||||||
InstanceClient instanceClient = EC2Client.class.cast(context.getProviderSpecificContext().getApi())
|
InstanceClient instanceClient = EC2Client.class.cast(context.getProviderSpecificContext().getApi())
|
||||||
.getInstanceServices();
|
.getInstanceServices();
|
||||||
|
|
||||||
String group = this.group + "o";
|
String group = this.group + "o";
|
||||||
|
|
||||||
|
@ -76,6 +76,7 @@ public class AWSEC2ComputeServiceLiveTest extends EC2ComputeServiceLiveTest {
|
||||||
options.as(AWSEC2TemplateOptions.class).securityGroups(group);
|
options.as(AWSEC2TemplateOptions.class).securityGroups(group);
|
||||||
options.as(AWSEC2TemplateOptions.class).keyPair(group);
|
options.as(AWSEC2TemplateOptions.class).keyPair(group);
|
||||||
options.as(AWSEC2TemplateOptions.class).enableMonitoring();
|
options.as(AWSEC2TemplateOptions.class).enableMonitoring();
|
||||||
|
options.as(AWSEC2TemplateOptions.class).spotPrice(0.3f);
|
||||||
|
|
||||||
String startedId = null;
|
String startedId = null;
|
||||||
try {
|
try {
|
||||||
|
@ -117,17 +118,17 @@ public class AWSEC2ComputeServiceLiveTest extends EC2ComputeServiceLiveTest {
|
||||||
// }
|
// }
|
||||||
|
|
||||||
// make sure we made our dummy group and also let in the user's group
|
// make sure we made our dummy group and also let in the user's group
|
||||||
assertEquals(Sets.newTreeSet(instance.getGroupIds()),
|
assertEquals(Sets.newTreeSet(instance.getGroupIds()), ImmutableSortedSet.<String> of("jclouds#" + group + "#"
|
||||||
ImmutableSortedSet.<String> of("jclouds#" + group + "#" + instance.getRegion(), group));
|
+ instance.getRegion(), group));
|
||||||
|
|
||||||
// make sure our dummy group has no rules
|
// make sure our dummy group has no rules
|
||||||
SecurityGroup secgroup = Iterables.getOnlyElement(securityGroupClient.describeSecurityGroupsInRegion(null,
|
SecurityGroup secgroup = Iterables.getOnlyElement(securityGroupClient.describeSecurityGroupsInRegion(null,
|
||||||
"jclouds#" + group + "#" + instance.getRegion()));
|
"jclouds#" + group + "#" + instance.getRegion()));
|
||||||
assert secgroup.getIpPermissions().size() == 0 : secgroup;
|
assert secgroup.getIpPermissions().size() == 0 : secgroup;
|
||||||
|
|
||||||
// try to run a script with the original keyPair
|
// try to run a script with the original keyPair
|
||||||
runScriptWithCreds(group, first.getOperatingSystem(),
|
runScriptWithCreds(group, first.getOperatingSystem(), new Credentials(first.getCredentials().identity, result
|
||||||
new Credentials(first.getCredentials().identity, result.getKeyMaterial()));
|
.getKeyMaterial()));
|
||||||
|
|
||||||
} finally {
|
} finally {
|
||||||
client.destroyNodesMatching(NodePredicates.inGroup(group));
|
client.destroyNodesMatching(NodePredicates.inGroup(group));
|
||||||
|
@ -151,13 +152,13 @@ public class AWSEC2ComputeServiceLiveTest extends EC2ComputeServiceLiveTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
InstanceClient instanceClient = EC2Client.class.cast(context.getProviderSpecificContext().getApi())
|
InstanceClient instanceClient = EC2Client.class.cast(context.getProviderSpecificContext().getApi())
|
||||||
.getInstanceServices();
|
.getInstanceServices();
|
||||||
|
|
||||||
String group = this.group + "g";
|
String group = this.group + "g";
|
||||||
|
|
||||||
TemplateOptions options = client.templateOptions();
|
TemplateOptions options = client.templateOptions();
|
||||||
|
|
||||||
options.as(AWSEC2TemplateOptions.class).subnetId(subnetId);
|
options.as(AWSEC2TemplateOptions.class).subnetId(subnetId).spotPrice(0.3f);
|
||||||
|
|
||||||
String startedId = null;
|
String startedId = null;
|
||||||
String nodeId = null;
|
String nodeId = null;
|
||||||
|
|
|
@ -0,0 +1,74 @@
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Copyright (C) 2010 Cloud Conscious, LLC. .info@cloudconscious.com("
|
||||||
|
*
|
||||||
|
* ====================================================================
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
* ====================================================================
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jclouds.aws.ec2.functions;
|
||||||
|
|
||||||
|
import static org.testng.Assert.assertEquals;
|
||||||
|
|
||||||
|
import org.jclouds.aws.ec2.domain.AWSRunningInstance;
|
||||||
|
import org.jclouds.aws.ec2.domain.LaunchSpecification;
|
||||||
|
import org.jclouds.aws.ec2.domain.MonitoringState;
|
||||||
|
import org.jclouds.aws.ec2.domain.SpotInstanceRequest;
|
||||||
|
import org.jclouds.aws.ec2.functions.SpotInstanceRequestToAWSRunningInstance;
|
||||||
|
import org.jclouds.date.internal.SimpleDateFormatDateService;
|
||||||
|
import org.jclouds.ec2.domain.InstanceState;
|
||||||
|
import org.testng.annotations.Test;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests behavior of {@code SpotInstanceRequestToAWSRunningInstance}
|
||||||
|
*
|
||||||
|
* @author Adrian Cole
|
||||||
|
*/
|
||||||
|
// NOTE:without testName, this will not call @Before* and fail w/NPE during surefire
|
||||||
|
@Test(groups = "unit", testName = "SpotInstanceRequestToAWSRunningInstanceTest")
|
||||||
|
public class SpotInstanceRequestToAWSRunningInstanceTest {
|
||||||
|
|
||||||
|
public void testConvert() {
|
||||||
|
|
||||||
|
SpotInstanceRequest input = SpotInstanceRequest.builder().region("us-east-1").id("sir-228e6406")
|
||||||
|
.spotPrice(0.001f).type(SpotInstanceRequest.Type.ONE_TIME).state(SpotInstanceRequest.State.OPEN)
|
||||||
|
.launchSpecification(
|
||||||
|
LaunchSpecification.builder().imageId("ami-595a0a1c").groupId("default").instanceType(
|
||||||
|
"m1.large").mapNewVolumeToDevice("/dev/sda1", 1, true).mapEBSSnapshotToDevice(
|
||||||
|
"/dev/sda2", "snap-1ea27576", 1, true).mapEphemeralDeviceToDevice("/dev/sda3", "vre1")
|
||||||
|
.monitoringEnabled(false).build()).createTime(
|
||||||
|
new SimpleDateFormatDateService().iso8601DateParse("2011-03-08T03:30:36.000Z"))
|
||||||
|
.productDescription("Linux/UNIX").build();
|
||||||
|
|
||||||
|
assertEquals(new SpotInstanceRequestToAWSRunningInstance().apply(input), AWSRunningInstance.builder().region(
|
||||||
|
"us-east-1").instanceId("sir-228e6406").spotInstanceRequestId("sir-228e6406").instanceState(
|
||||||
|
InstanceState.PENDING).imageId("ami-595a0a1c").groupId("default").instanceType("m1.large")
|
||||||
|
.monitoringState(MonitoringState.PENDING).build());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testConvertWhenNotOpenReturnsNull() {
|
||||||
|
|
||||||
|
assertEquals(new SpotInstanceRequestToAWSRunningInstance().apply(SpotInstanceRequest.builder()
|
||||||
|
.region("us-east-1").id("sir-228e6406").type(SpotInstanceRequest.Type.ONE_TIME).state(
|
||||||
|
SpotInstanceRequest.State.ACTIVE).build()), null);
|
||||||
|
|
||||||
|
assertEquals(new SpotInstanceRequestToAWSRunningInstance().apply(SpotInstanceRequest.builder()
|
||||||
|
.region("us-east-1").id("sir-228e6406").type(SpotInstanceRequest.Type.ONE_TIME).state(
|
||||||
|
SpotInstanceRequest.State.CANCELLED).build()), null);
|
||||||
|
|
||||||
|
assertEquals(new SpotInstanceRequestToAWSRunningInstance().apply(SpotInstanceRequest.builder()
|
||||||
|
.region("us-east-1").id("sir-228e6406").type(SpotInstanceRequest.Type.ONE_TIME).state(
|
||||||
|
SpotInstanceRequest.State.UNRECOGNIZED).build()), null);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,122 @@
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Copyright (C) 2010 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.options;
|
||||||
|
|
||||||
|
import static org.jclouds.aws.ec2.options.DescribeSpotPriceHistoryOptions.Builder.from;
|
||||||
|
import static org.jclouds.aws.ec2.options.DescribeSpotPriceHistoryOptions.Builder.instanceType;
|
||||||
|
import static org.jclouds.aws.ec2.options.DescribeSpotPriceHistoryOptions.Builder.productDescription;
|
||||||
|
import static org.jclouds.aws.ec2.options.DescribeSpotPriceHistoryOptions.Builder.to;
|
||||||
|
import static org.testng.Assert.assertEquals;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
import org.jclouds.http.options.HttpRequestOptions;
|
||||||
|
import org.testng.annotations.Test;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests possible uses of DescribeSpotPriceHistoryOptions and
|
||||||
|
* DescribeSpotPriceHistoryOptions.Builder.*
|
||||||
|
*
|
||||||
|
* @author Adrian Cole
|
||||||
|
*/
|
||||||
|
public class DescribeSpotPriceHistoryOptionsTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testAssignability() {
|
||||||
|
assert HttpRequestOptions.class.isAssignableFrom(DescribeSpotPriceHistoryOptions.class);
|
||||||
|
assert !String.class.isAssignableFrom(DescribeSpotPriceHistoryOptions.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testDescription() {
|
||||||
|
DescribeSpotPriceHistoryOptions options = new DescribeSpotPriceHistoryOptions();
|
||||||
|
options.productDescription("test");
|
||||||
|
assertEquals(options.buildFormParameters().get("ProductDescription"), Collections.singletonList("test"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testDescriptionStatic() {
|
||||||
|
DescribeSpotPriceHistoryOptions options = productDescription("test");
|
||||||
|
assertEquals(options.buildFormParameters().get("ProductDescription"), Collections.singletonList("test"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expectedExceptions = NullPointerException.class)
|
||||||
|
public void testDescriptionNPE() {
|
||||||
|
productDescription(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testInstanceType() {
|
||||||
|
DescribeSpotPriceHistoryOptions options = new DescribeSpotPriceHistoryOptions();
|
||||||
|
options.instanceType("test");
|
||||||
|
assertEquals(options.buildFormParameters().get("InstanceType.1"), Collections.singletonList("test"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testInstanceTypeStatic() {
|
||||||
|
DescribeSpotPriceHistoryOptions options = instanceType("test");
|
||||||
|
assertEquals(options.buildFormParameters().get("InstanceType.1"), Collections.singletonList("test"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expectedExceptions = NullPointerException.class)
|
||||||
|
public void testInstanceTypeNPE() {
|
||||||
|
instanceType(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testFrom() {
|
||||||
|
DescribeSpotPriceHistoryOptions options = new DescribeSpotPriceHistoryOptions();
|
||||||
|
options.from(test);
|
||||||
|
assertEquals(options.buildFormParameters().get("StartTime"), Collections.singletonList("1970-05-23T21:21:18.910Z"));
|
||||||
|
}
|
||||||
|
|
||||||
|
Date test = new Date(12345678910l);
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testFromStatic() {
|
||||||
|
DescribeSpotPriceHistoryOptions options = from(test);
|
||||||
|
assertEquals(options.buildFormParameters().get("StartTime"), Collections.singletonList("1970-05-23T21:21:18.910Z"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expectedExceptions = NullPointerException.class)
|
||||||
|
public void testFromNPE() {
|
||||||
|
from(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testTo() {
|
||||||
|
DescribeSpotPriceHistoryOptions options = new DescribeSpotPriceHistoryOptions();
|
||||||
|
options.to(test);
|
||||||
|
assertEquals(options.buildFormParameters().get("EndTime"), Collections.singletonList("1970-05-23T21:21:18.910Z"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testToStatic() {
|
||||||
|
DescribeSpotPriceHistoryOptions options = to(test);
|
||||||
|
assertEquals(options.buildFormParameters().get("EndTime"), Collections.singletonList("1970-05-23T21:21:18.910Z"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expectedExceptions = NullPointerException.class)
|
||||||
|
public void testToNPE() {
|
||||||
|
to(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,145 @@
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Copyright (C) 2010 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 validUntil 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.options;
|
||||||
|
|
||||||
|
import static org.jclouds.aws.ec2.options.RequestSpotInstancesOptions.Builder.availabilityZoneGroup;
|
||||||
|
import static org.jclouds.aws.ec2.options.RequestSpotInstancesOptions.Builder.launchGroup;
|
||||||
|
import static org.jclouds.aws.ec2.options.RequestSpotInstancesOptions.Builder.type;
|
||||||
|
import static org.jclouds.aws.ec2.options.RequestSpotInstancesOptions.Builder.validFrom;
|
||||||
|
import static org.jclouds.aws.ec2.options.RequestSpotInstancesOptions.Builder.validUntil;
|
||||||
|
import static org.testng.Assert.assertEquals;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
import org.jclouds.aws.ec2.domain.SpotInstanceRequest;
|
||||||
|
import org.jclouds.http.options.HttpRequestOptions;
|
||||||
|
import org.testng.annotations.Test;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests possible uses of RequestSpotInstancesOptions and RequestSpotInstancesOptions.Builder.*
|
||||||
|
*
|
||||||
|
* @author Adrian Cole
|
||||||
|
*/
|
||||||
|
public class RequestSpotInstancesOptionsTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testAssignability() {
|
||||||
|
assert HttpRequestOptions.class.isAssignableFrom(RequestSpotInstancesOptions.class);
|
||||||
|
assert !String.class.isAssignableFrom(RequestSpotInstancesOptions.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testAvailabilityZoneGroup() {
|
||||||
|
RequestSpotInstancesOptions options = new RequestSpotInstancesOptions();
|
||||||
|
options.availabilityZoneGroup("test");
|
||||||
|
assertEquals(options.buildFormParameters().get("AvailabilityZoneGroup"), Collections.singletonList("test"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testAvailabilityZoneGroupStatic() {
|
||||||
|
RequestSpotInstancesOptions options = availabilityZoneGroup("test");
|
||||||
|
assertEquals(options.buildFormParameters().get("AvailabilityZoneGroup"), Collections.singletonList("test"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expectedExceptions = NullPointerException.class)
|
||||||
|
public void testAvailabilityZoneGroupNPE() {
|
||||||
|
availabilityZoneGroup(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testLaunchGroup() {
|
||||||
|
RequestSpotInstancesOptions options = new RequestSpotInstancesOptions();
|
||||||
|
options.launchGroup("test");
|
||||||
|
assertEquals(options.buildFormParameters().get("LaunchGroup"), Collections.singletonList("test"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testLaunchGroupStatic() {
|
||||||
|
RequestSpotInstancesOptions options = launchGroup("test");
|
||||||
|
assertEquals(options.buildFormParameters().get("LaunchGroup"), Collections.singletonList("test"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expectedExceptions = NullPointerException.class)
|
||||||
|
public void testLaunchGroupNPE() {
|
||||||
|
launchGroup(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testInstanceType() {
|
||||||
|
RequestSpotInstancesOptions options = new RequestSpotInstancesOptions();
|
||||||
|
options.type(SpotInstanceRequest.Type.PERSISTENT);
|
||||||
|
assertEquals(options.buildFormParameters().get("Type"), Collections.singletonList("persistent"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testInstanceTypeStatic() {
|
||||||
|
RequestSpotInstancesOptions options = type(SpotInstanceRequest.Type.PERSISTENT);
|
||||||
|
assertEquals(options.buildFormParameters().get("Type"), Collections.singletonList("persistent"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expectedExceptions = NullPointerException.class)
|
||||||
|
public void testInstanceTypeNPE() {
|
||||||
|
type(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testFrom() {
|
||||||
|
RequestSpotInstancesOptions options = new RequestSpotInstancesOptions();
|
||||||
|
options.validFrom(test);
|
||||||
|
assertEquals(options.buildFormParameters().get("ValidFrom"),
|
||||||
|
Collections.singletonList("1970-05-23T21:21:18.910Z"));
|
||||||
|
}
|
||||||
|
|
||||||
|
Date test = new Date(12345678910l);
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testFromStatic() {
|
||||||
|
RequestSpotInstancesOptions options = validFrom(test);
|
||||||
|
assertEquals(options.buildFormParameters().get("ValidFrom"),
|
||||||
|
Collections.singletonList("1970-05-23T21:21:18.910Z"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expectedExceptions = NullPointerException.class)
|
||||||
|
public void testFromNPE() {
|
||||||
|
validFrom(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testTo() {
|
||||||
|
RequestSpotInstancesOptions options = new RequestSpotInstancesOptions();
|
||||||
|
options.validUntil(test);
|
||||||
|
assertEquals(options.buildFormParameters().get("ValidUntil"),
|
||||||
|
Collections.singletonList("1970-05-23T21:21:18.910Z"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testToStatic() {
|
||||||
|
RequestSpotInstancesOptions options = validUntil(test);
|
||||||
|
assertEquals(options.buildFormParameters().get("ValidUntil"),
|
||||||
|
Collections.singletonList("1970-05-23T21:21:18.910Z"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expectedExceptions = NullPointerException.class)
|
||||||
|
public void testToNPE() {
|
||||||
|
validUntil(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -100,7 +100,7 @@ public class AMIClientLiveTest {
|
||||||
setupCredentials();
|
setupCredentials();
|
||||||
Properties overrides = setupProperties();
|
Properties overrides = setupProperties();
|
||||||
context = new ComputeServiceContextFactory().createContext(provider,
|
context = new ComputeServiceContextFactory().createContext(provider,
|
||||||
ImmutableSet.<Module> of(new Log4JLoggingModule()), overrides).getProviderSpecificContext();
|
ImmutableSet.<Module> of(new Log4JLoggingModule()), overrides).getProviderSpecificContext();
|
||||||
client = context.getApi().getAMIServices();
|
client = context.getApi().getAMIServices();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -135,7 +135,7 @@ public class AMIClientLiveTest {
|
||||||
String imageRegisteredId = client.registerImageFromManifestInRegion(null, "jcloudstest1", DEFAULT_MANIFEST);
|
String imageRegisteredId = client.registerImageFromManifestInRegion(null, "jcloudstest1", DEFAULT_MANIFEST);
|
||||||
imagesToDeregister.add(imageRegisteredId);
|
imagesToDeregister.add(imageRegisteredId);
|
||||||
Image imageRegisteredFromManifest = Iterables.getOnlyElement(client.describeImagesInRegion(null,
|
Image imageRegisteredFromManifest = Iterables.getOnlyElement(client.describeImagesInRegion(null,
|
||||||
imageIds(imageRegisteredId)));
|
imageIds(imageRegisteredId)));
|
||||||
assertEquals(imageRegisteredFromManifest.getName(), "jcloudstest1");
|
assertEquals(imageRegisteredFromManifest.getName(), "jcloudstest1");
|
||||||
assertEquals(imageRegisteredFromManifest.getImageLocation(), DEFAULT_MANIFEST);
|
assertEquals(imageRegisteredFromManifest.getImageLocation(), DEFAULT_MANIFEST);
|
||||||
assertEquals(imageRegisteredFromManifest.getImageType(), ImageType.MACHINE);
|
assertEquals(imageRegisteredFromManifest.getImageType(), ImageType.MACHINE);
|
||||||
|
@ -146,10 +146,10 @@ public class AMIClientLiveTest {
|
||||||
@Test(enabled = false)
|
@Test(enabled = false)
|
||||||
public void testRegisterImageFromManifestOptions() {
|
public void testRegisterImageFromManifestOptions() {
|
||||||
String imageRegisteredWithOptionsId = client.registerImageFromManifestInRegion(null, "jcloudstest2",
|
String imageRegisteredWithOptionsId = client.registerImageFromManifestInRegion(null, "jcloudstest2",
|
||||||
DEFAULT_MANIFEST, withDescription("adrian"));
|
DEFAULT_MANIFEST, withDescription("adrian"));
|
||||||
imagesToDeregister.add(imageRegisteredWithOptionsId);
|
imagesToDeregister.add(imageRegisteredWithOptionsId);
|
||||||
Image imageRegisteredFromManifestWithOptions = Iterables.getOnlyElement(client.describeImagesInRegion(null,
|
Image imageRegisteredFromManifestWithOptions = Iterables.getOnlyElement(client.describeImagesInRegion(null,
|
||||||
imageIds(imageRegisteredWithOptionsId)));
|
imageIds(imageRegisteredWithOptionsId)));
|
||||||
assertEquals(imageRegisteredFromManifestWithOptions.getName(), "jcloudstest2");
|
assertEquals(imageRegisteredFromManifestWithOptions.getName(), "jcloudstest2");
|
||||||
assertEquals(imageRegisteredFromManifestWithOptions.getImageLocation(), DEFAULT_MANIFEST);
|
assertEquals(imageRegisteredFromManifestWithOptions.getImageLocation(), DEFAULT_MANIFEST);
|
||||||
assertEquals(imageRegisteredFromManifestWithOptions.getImageType(), ImageType.MACHINE);
|
assertEquals(imageRegisteredFromManifestWithOptions.getImageType(), ImageType.MACHINE);
|
||||||
|
@ -164,7 +164,7 @@ public class AMIClientLiveTest {
|
||||||
String imageRegisteredId = client.registerUnixImageBackedByEbsInRegion(null, "jcloudstest1", DEFAULT_MANIFEST);
|
String imageRegisteredId = client.registerUnixImageBackedByEbsInRegion(null, "jcloudstest1", DEFAULT_MANIFEST);
|
||||||
imagesToDeregister.add(imageRegisteredId);
|
imagesToDeregister.add(imageRegisteredId);
|
||||||
Image imageRegistered = Iterables
|
Image imageRegistered = Iterables
|
||||||
.getOnlyElement(client.describeImagesInRegion(null, imageIds(imageRegisteredId)));
|
.getOnlyElement(client.describeImagesInRegion(null, imageIds(imageRegisteredId)));
|
||||||
assertEquals(imageRegistered.getName(), "jcloudstest1");
|
assertEquals(imageRegistered.getName(), "jcloudstest1");
|
||||||
assertEquals(imageRegistered.getImageType(), ImageType.MACHINE);
|
assertEquals(imageRegistered.getImageType(), ImageType.MACHINE);
|
||||||
assertEquals(imageRegistered.getRootDeviceType(), RootDeviceType.EBS);
|
assertEquals(imageRegistered.getRootDeviceType(), RootDeviceType.EBS);
|
||||||
|
@ -175,18 +175,19 @@ public class AMIClientLiveTest {
|
||||||
// awaiting EBS functionality to be added to jclouds
|
// awaiting EBS functionality to be added to jclouds
|
||||||
public void testRegisterImageBackedByEBSOptions() {
|
public void testRegisterImageBackedByEBSOptions() {
|
||||||
String imageRegisteredWithOptionsId = client.registerUnixImageBackedByEbsInRegion(null, "jcloudstest2",
|
String imageRegisteredWithOptionsId = client.registerUnixImageBackedByEbsInRegion(null, "jcloudstest2",
|
||||||
DEFAULT_SNAPSHOT, addNewBlockDevice("/dev/sda2", "myvirtual", 1).withDescription("adrian"));
|
DEFAULT_SNAPSHOT, addNewBlockDevice("/dev/sda2", "myvirtual", 1).withDescription("adrian"));
|
||||||
imagesToDeregister.add(imageRegisteredWithOptionsId);
|
imagesToDeregister.add(imageRegisteredWithOptionsId);
|
||||||
Image imageRegisteredWithOptions = Iterables.getOnlyElement(client.describeImagesInRegion(null,
|
Image imageRegisteredWithOptions = Iterables.getOnlyElement(client.describeImagesInRegion(null,
|
||||||
imageIds(imageRegisteredWithOptionsId)));
|
imageIds(imageRegisteredWithOptionsId)));
|
||||||
assertEquals(imageRegisteredWithOptions.getName(), "jcloudstest2");
|
assertEquals(imageRegisteredWithOptions.getName(), "jcloudstest2");
|
||||||
assertEquals(imageRegisteredWithOptions.getImageType(), ImageType.MACHINE);
|
assertEquals(imageRegisteredWithOptions.getImageType(), ImageType.MACHINE);
|
||||||
assertEquals(imageRegisteredWithOptions.getRootDeviceType(), RootDeviceType.EBS);
|
assertEquals(imageRegisteredWithOptions.getRootDeviceType(), RootDeviceType.EBS);
|
||||||
assertEquals(imageRegisteredWithOptions.getRootDeviceName(), "/dev/sda1");
|
assertEquals(imageRegisteredWithOptions.getRootDeviceName(), "/dev/sda1");
|
||||||
assertEquals(imageRegisteredWithOptions.getDescription(), "adrian");
|
assertEquals(imageRegisteredWithOptions.getDescription(), "adrian");
|
||||||
assertEquals(imageRegisteredWithOptions.getEbsBlockDevices().entrySet(), ImmutableMap.of("/dev/sda1",
|
assertEquals(
|
||||||
new Image.EbsBlockDevice("/dev/sda1", 30, true), "/dev/sda2",
|
imageRegisteredWithOptions.getEbsBlockDevices().entrySet(),
|
||||||
new Image.EbsBlockDevice("/dev/sda2", 1, true)).entrySet());
|
ImmutableMap.of("/dev/sda1", new Image.EbsBlockDevice("/dev/sda1", 30, true), "/dev/sda2",
|
||||||
|
new Image.EbsBlockDevice("/dev/sda2", 1, true)).entrySet());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(enabled = false)
|
@Test(enabled = false)
|
||||||
|
@ -216,6 +217,7 @@ public class AMIClientLiveTest {
|
||||||
// TODO client.resetLaunchPermissionsOnImageInRegion(null, imageId);
|
// TODO client.resetLaunchPermissionsOnImageInRegion(null, imageId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test(enabled = false)
|
||||||
public void testGetLaunchPermissionForImage() {
|
public void testGetLaunchPermissionForImage() {
|
||||||
System.out.println(client.getLaunchPermissionForImageInRegion(null, imageId));
|
System.out.println(client.getLaunchPermissionForImageInRegion(null, imageId));
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,6 +41,7 @@ import org.jclouds.Constants;
|
||||||
import org.jclouds.aws.domain.Region;
|
import org.jclouds.aws.domain.Region;
|
||||||
import org.jclouds.aws.ec2.AWSEC2AsyncClient;
|
import org.jclouds.aws.ec2.AWSEC2AsyncClient;
|
||||||
import org.jclouds.aws.ec2.AWSEC2Client;
|
import org.jclouds.aws.ec2.AWSEC2Client;
|
||||||
|
import org.jclouds.aws.ec2.compute.AWSEC2TemplateOptions;
|
||||||
import org.jclouds.aws.ec2.domain.AWSRunningInstance;
|
import org.jclouds.aws.ec2.domain.AWSRunningInstance;
|
||||||
import org.jclouds.compute.ComputeServiceContext;
|
import org.jclouds.compute.ComputeServiceContext;
|
||||||
import org.jclouds.compute.ComputeServiceContextFactory;
|
import org.jclouds.compute.ComputeServiceContextFactory;
|
||||||
|
@ -49,10 +50,7 @@ import org.jclouds.compute.domain.ExecResponse;
|
||||||
import org.jclouds.compute.domain.NodeMetadata;
|
import org.jclouds.compute.domain.NodeMetadata;
|
||||||
import org.jclouds.compute.options.TemplateOptions;
|
import org.jclouds.compute.options.TemplateOptions;
|
||||||
import org.jclouds.domain.Credentials;
|
import org.jclouds.domain.Credentials;
|
||||||
import org.jclouds.ec2.EC2Client;
|
|
||||||
import org.jclouds.ec2.domain.KeyPair;
|
import org.jclouds.ec2.domain.KeyPair;
|
||||||
import org.jclouds.ec2.domain.RunningInstance;
|
|
||||||
import org.jclouds.ec2.services.InstanceClient;
|
|
||||||
import org.jclouds.logging.log4j.config.Log4JLoggingModule;
|
import org.jclouds.logging.log4j.config.Log4JLoggingModule;
|
||||||
import org.jclouds.rest.RestContext;
|
import org.jclouds.rest.RestContext;
|
||||||
import org.jclouds.ssh.jsch.config.JschSshClientModule;
|
import org.jclouds.ssh.jsch.config.JschSshClientModule;
|
||||||
|
@ -84,7 +82,7 @@ public class AWSKeyPairClientLiveTest {
|
||||||
protected void setupCredentials() {
|
protected void setupCredentials() {
|
||||||
identity = checkNotNull(System.getProperty("test." + provider + ".identity"), "test." + provider + ".identity");
|
identity = checkNotNull(System.getProperty("test." + provider + ".identity"), "test." + provider + ".identity");
|
||||||
credential = checkNotNull(System.getProperty("test." + provider + ".credential"), "test." + provider
|
credential = checkNotNull(System.getProperty("test." + provider + ".credential"), "test." + provider
|
||||||
+ ".credential");
|
+ ".credential");
|
||||||
endpoint = System.getProperty("test." + provider + ".endpoint", null);
|
endpoint = System.getProperty("test." + provider + ".endpoint", null);
|
||||||
apiversion = System.getProperty("test." + provider + ".apiversion", null);
|
apiversion = System.getProperty("test." + provider + ".apiversion", null);
|
||||||
}
|
}
|
||||||
|
@ -106,8 +104,8 @@ public class AWSKeyPairClientLiveTest {
|
||||||
public void setupClient() {
|
public void setupClient() {
|
||||||
setupCredentials();
|
setupCredentials();
|
||||||
Properties overrides = setupProperties();
|
Properties overrides = setupProperties();
|
||||||
computeContext = new ComputeServiceContextFactory().createContext(provider,
|
computeContext = new ComputeServiceContextFactory().createContext(provider, ImmutableSet.<Module> of(
|
||||||
ImmutableSet.<Module> of(new Log4JLoggingModule(), new JschSshClientModule()), overrides);
|
new Log4JLoggingModule(), new JschSshClientModule()), overrides);
|
||||||
context = computeContext.getProviderSpecificContext();
|
context = computeContext.getProviderSpecificContext();
|
||||||
client = context.getApi().getKeyPairServices();
|
client = context.getApi().getKeyPairServices();
|
||||||
}
|
}
|
||||||
|
@ -116,19 +114,19 @@ public class AWSKeyPairClientLiveTest {
|
||||||
|
|
||||||
Map<String, String> keyPair = ComputeTestUtils.setupKeyPair();
|
Map<String, String> keyPair = ComputeTestUtils.setupKeyPair();
|
||||||
|
|
||||||
InstanceClient instanceClient = EC2Client.class.cast(context.getApi()).getInstanceServices();
|
AWSInstanceClient instanceClient = AWSEC2Client.class.cast(context.getApi()).getInstanceServices();
|
||||||
|
|
||||||
String group = PREFIX + "unssh";
|
String group = PREFIX + "unssh";
|
||||||
computeContext.getComputeService().destroyNodesMatching(inGroup(group));
|
computeContext.getComputeService().destroyNodesMatching(inGroup(group));
|
||||||
|
|
||||||
TemplateOptions options = computeContext.getComputeService().templateOptions();
|
TemplateOptions options = computeContext.getComputeService().templateOptions();
|
||||||
|
|
||||||
options.authorizePublicKey(keyPair.get("public"));
|
options.authorizePublicKey(keyPair.get("public")).as(AWSEC2TemplateOptions.class).spotPrice(0.3f);
|
||||||
|
|
||||||
ComputeServiceContext noSshContext = null;
|
ComputeServiceContext noSshContext = null;
|
||||||
try {
|
try {
|
||||||
noSshContext = new ComputeServiceContextFactory().createContext(provider,
|
noSshContext = new ComputeServiceContextFactory().createContext(provider, ImmutableSet
|
||||||
ImmutableSet.of(new Log4JLoggingModule()), setupProperties());
|
.of(new Log4JLoggingModule()), setupProperties());
|
||||||
|
|
||||||
Set<? extends NodeMetadata> nodes = noSshContext.getComputeService().createNodesInGroup(group, 1, options);
|
Set<? extends NodeMetadata> nodes = noSshContext.getComputeService().createNodesInGroup(group, 1, options);
|
||||||
|
|
||||||
|
@ -136,18 +134,19 @@ public class AWSKeyPairClientLiveTest {
|
||||||
assert first.getCredentials() != null : first;
|
assert first.getCredentials() != null : first;
|
||||||
assert first.getCredentials().identity != null : first;
|
assert first.getCredentials().identity != null : first;
|
||||||
|
|
||||||
AWSRunningInstance instance = AWSRunningInstance.class
|
AWSRunningInstance instance = getInstance(instanceClient, first.getProviderId());
|
||||||
.cast(getInstance(instanceClient, first.getProviderId()));
|
|
||||||
|
|
||||||
|
assert instance.getSpotInstanceRequestId() != null : instance;
|
||||||
assertEquals(instance.getKeyName(), "jclouds#" + group);
|
assertEquals(instance.getKeyName(), "jclouds#" + group);
|
||||||
assertEquals(first.getCredentials().credential, null);
|
assertEquals(first.getCredentials().credential, null);
|
||||||
|
|
||||||
Map<? extends NodeMetadata, ExecResponse> responses = computeContext.getComputeService()
|
Map<? extends NodeMetadata, ExecResponse> responses = computeContext.getComputeService()
|
||||||
.runScriptOnNodesMatching(
|
.runScriptOnNodesMatching(
|
||||||
runningInGroup(group),
|
runningInGroup(group),
|
||||||
exec("echo hello"),
|
exec("echo hello"),
|
||||||
overrideCredentialsWith(new Credentials(first.getCredentials().identity, keyPair.get("private")))
|
overrideCredentialsWith(
|
||||||
.wrapInInitScript(false).runAsRoot(false));
|
new Credentials(first.getCredentials().identity, keyPair.get("private")))
|
||||||
|
.wrapInInitScript(false).runAsRoot(false));
|
||||||
|
|
||||||
ExecResponse hello = getOnlyElement(responses.values());
|
ExecResponse hello = getOnlyElement(responses.values());
|
||||||
assertEquals(hello.getOutput().trim(), "hello");
|
assertEquals(hello.getOutput().trim(), "hello");
|
||||||
|
@ -235,9 +234,8 @@ public class AWSKeyPairClientLiveTest {
|
||||||
assertEquals(listPair.getKeyFingerprint(), keyPair.getKeyFingerprint());
|
assertEquals(listPair.getKeyFingerprint(), keyPair.getKeyFingerprint());
|
||||||
}
|
}
|
||||||
|
|
||||||
protected RunningInstance getInstance(InstanceClient instanceClient, String id) {
|
protected AWSRunningInstance getInstance(AWSInstanceClient instanceClient, String id) {
|
||||||
RunningInstance instance = getOnlyElement(getOnlyElement(instanceClient.describeInstancesInRegion(null, id)));
|
return getOnlyElement(getOnlyElement(instanceClient.describeInstancesInRegion(null, id)));
|
||||||
return instance;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@AfterTest
|
@AfterTest
|
||||||
|
|
|
@ -0,0 +1,190 @@
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
|
||||||
|
*
|
||||||
|
* ====================================================================
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
* ====================================================================
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jclouds.aws.ec2.services;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
import org.jclouds.aws.ec2.domain.LaunchSpecification;
|
||||||
|
import org.jclouds.aws.ec2.options.DescribeSpotPriceHistoryOptions;
|
||||||
|
import org.jclouds.aws.ec2.options.RequestSpotInstancesOptions;
|
||||||
|
import org.jclouds.aws.ec2.xml.DescribeSpotPriceHistoryResponseHandler;
|
||||||
|
import org.jclouds.aws.ec2.xml.SpotInstanceHandler;
|
||||||
|
import org.jclouds.aws.ec2.xml.SpotInstancesHandler;
|
||||||
|
import org.jclouds.http.HttpRequest;
|
||||||
|
import org.jclouds.http.functions.ParseSax;
|
||||||
|
import org.jclouds.http.functions.ReleasePayloadAndReturn;
|
||||||
|
import org.jclouds.rest.functions.ReturnEmptySetOnNotFoundOr404;
|
||||||
|
import org.jclouds.rest.functions.ReturnVoidOnNotFoundOr404;
|
||||||
|
import org.jclouds.rest.internal.RestAnnotationProcessor;
|
||||||
|
import org.testng.annotations.Test;
|
||||||
|
|
||||||
|
import com.google.inject.TypeLiteral;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests behavior of {@code SpotInstanceAsyncClient}
|
||||||
|
*
|
||||||
|
* @author Adrian Cole
|
||||||
|
*/
|
||||||
|
// NOTE:without testName, this will not call @Before* and fail w/NPE during surefire
|
||||||
|
@Test(groups = "unit", testName = "SpotInstanceAsyncClientTest")
|
||||||
|
public class SpotInstanceAsyncClientTest extends BaseAWSEC2AsyncClientTest<SpotInstanceAsyncClient> {
|
||||||
|
public void testRequestSpotInstance() throws SecurityException, NoSuchMethodException, IOException {
|
||||||
|
Method method = SpotInstanceAsyncClient.class.getMethod("requestSpotInstanceInRegion", String.class,
|
||||||
|
float.class, String.class, String.class);
|
||||||
|
HttpRequest request = processor.createRequest(method, null, 0.01f, "m1.small", "ami-voo");
|
||||||
|
|
||||||
|
assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
|
||||||
|
assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
|
||||||
|
assertPayloadEquals(
|
||||||
|
request,
|
||||||
|
"Version=2010-11-15&Action=RequestSpotInstances&LaunchSpecification.ImageId=m1.small&SpotPrice=0.01&LaunchSpecification.InstanceType=ami-voo",
|
||||||
|
"application/x-www-form-urlencoded", false);
|
||||||
|
|
||||||
|
assertResponseParserClassEquals(method, request, ParseSax.class);
|
||||||
|
assertSaxResponseParserClassEquals(method, SpotInstanceHandler.class);
|
||||||
|
assertExceptionParserClassEquals(method, null);
|
||||||
|
|
||||||
|
checkFilters(request);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testRequestSpotInstancesOptions() throws SecurityException, NoSuchMethodException, IOException {
|
||||||
|
Method method = SpotInstanceAsyncClient.class.getMethod("requestSpotInstancesInRegion", String.class,
|
||||||
|
float.class, int.class, LaunchSpecification.class, RequestSpotInstancesOptions[].class);
|
||||||
|
HttpRequest request = processor.createRequest(method, "eu-west-1", 0.01, 3,
|
||||||
|
LaunchSpecification.builder().instanceType("m1.small").imageId("ami-voo").availabilityZone("eu-west-1a")
|
||||||
|
.kernelId("kernelId").groupId("group1").build(), new RequestSpotInstancesOptions().validFrom(from)
|
||||||
|
.validUntil(to).availabilityZoneGroup("availabilityZoneGroup").launchGroup("launchGroup"));
|
||||||
|
|
||||||
|
assertRequestLineEquals(request, "POST https://ec2.eu-west-1.amazonaws.com/ HTTP/1.1");
|
||||||
|
assertNonPayloadHeadersEqual(request, "Host: ec2.eu-west-1.amazonaws.com\n");
|
||||||
|
assertPayloadEquals(
|
||||||
|
request,
|
||||||
|
"Version=2010-11-15&Action=RequestSpotInstances&InstanceCount=3&SpotPrice=0.01&ValidFrom=1970-05-23T21%3A21%3A18.910Z&ValidUntil=2009-02-13T23%3A31%3A31.011Z&AvailabilityZoneGroup=availabilityZoneGroup&LaunchGroup=launchGroup&LaunchSpecification.ImageId=ami-voo&LaunchSpecification.Placement.AvailabilityZone=eu-west-1a&LaunchSpecification.SecurityGroup.1=group1&LaunchSpecification.InstanceType=m1.small&LaunchSpecification.KernelId=kernelId",
|
||||||
|
"application/x-www-form-urlencoded", false);
|
||||||
|
|
||||||
|
assertResponseParserClassEquals(method, request, ParseSax.class);
|
||||||
|
assertSaxResponseParserClassEquals(method, SpotInstancesHandler.class);
|
||||||
|
assertExceptionParserClassEquals(method, null);
|
||||||
|
|
||||||
|
checkFilters(request);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testCancelSpotInstanceRequests() throws SecurityException, NoSuchMethodException, IOException {
|
||||||
|
Method method = SpotInstanceAsyncClient.class.getMethod("cancelSpotInstanceRequestsInRegion", String.class,
|
||||||
|
String[].class);
|
||||||
|
HttpRequest request = processor.createRequest(method, null, "id");
|
||||||
|
|
||||||
|
assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
|
||||||
|
assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
|
||||||
|
assertPayloadEquals(request, "Version=2010-11-15&Action=CancelSpotInstanceRequests&SpotInstanceRequestId.1=id",
|
||||||
|
"application/x-www-form-urlencoded", false);
|
||||||
|
|
||||||
|
assertResponseParserClassEquals(method, request, ReleasePayloadAndReturn.class);
|
||||||
|
assertSaxResponseParserClassEquals(method, null);
|
||||||
|
assertExceptionParserClassEquals(method, ReturnVoidOnNotFoundOr404.class);
|
||||||
|
|
||||||
|
checkFilters(request);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testDescribeSpotInstanceRequests() throws SecurityException, NoSuchMethodException, IOException {
|
||||||
|
Method method = SpotInstanceAsyncClient.class.getMethod("describeSpotInstanceRequestsInRegion", String.class,
|
||||||
|
String[].class);
|
||||||
|
HttpRequest request = processor.createRequest(method, (String) null);
|
||||||
|
|
||||||
|
assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
|
||||||
|
assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
|
||||||
|
assertPayloadEquals(request, "Version=2010-11-15&Action=DescribeSpotInstanceRequests",
|
||||||
|
"application/x-www-form-urlencoded", false);
|
||||||
|
|
||||||
|
assertResponseParserClassEquals(method, request, ParseSax.class);
|
||||||
|
assertSaxResponseParserClassEquals(method, SpotInstancesHandler.class);
|
||||||
|
assertExceptionParserClassEquals(method, ReturnEmptySetOnNotFoundOr404.class);
|
||||||
|
|
||||||
|
checkFilters(request);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testDescribeSpotInstanceRequestsArgs() throws SecurityException, NoSuchMethodException, IOException {
|
||||||
|
Method method = SpotInstanceAsyncClient.class.getMethod("describeSpotInstanceRequestsInRegion", String.class,
|
||||||
|
String[].class);
|
||||||
|
HttpRequest request = processor.createRequest(method, null, "1", "2");
|
||||||
|
|
||||||
|
assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
|
||||||
|
assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
|
||||||
|
assertPayloadEquals(
|
||||||
|
request,
|
||||||
|
"Version=2010-11-15&Action=DescribeSpotInstanceRequests&SpotInstanceRequestId.1=1&SpotInstanceRequestId.2=2",
|
||||||
|
"application/x-www-form-urlencoded", false);
|
||||||
|
|
||||||
|
assertResponseParserClassEquals(method, request, ParseSax.class);
|
||||||
|
assertSaxResponseParserClassEquals(method, SpotInstancesHandler.class);
|
||||||
|
assertExceptionParserClassEquals(method, ReturnEmptySetOnNotFoundOr404.class);
|
||||||
|
|
||||||
|
checkFilters(request);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testDescribeSpotPriceHistory() throws SecurityException, NoSuchMethodException, IOException {
|
||||||
|
Method method = SpotInstanceAsyncClient.class.getMethod("describeSpotPriceHistoryInRegion", String.class,
|
||||||
|
DescribeSpotPriceHistoryOptions[].class);
|
||||||
|
HttpRequest request = processor.createRequest(method, (String) null);
|
||||||
|
|
||||||
|
assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
|
||||||
|
assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
|
||||||
|
assertPayloadEquals(request, "Version=2010-11-15&Action=DescribeSpotPriceHistory",
|
||||||
|
"application/x-www-form-urlencoded", false);
|
||||||
|
|
||||||
|
assertResponseParserClassEquals(method, request, ParseSax.class);
|
||||||
|
assertSaxResponseParserClassEquals(method, DescribeSpotPriceHistoryResponseHandler.class);
|
||||||
|
assertExceptionParserClassEquals(method, ReturnEmptySetOnNotFoundOr404.class);
|
||||||
|
|
||||||
|
checkFilters(request);
|
||||||
|
}
|
||||||
|
|
||||||
|
Date from = new Date(12345678910l);
|
||||||
|
Date to = new Date(1234567891011l);
|
||||||
|
|
||||||
|
public void testDescribeSpotPriceHistoryArgs() throws SecurityException, NoSuchMethodException, IOException {
|
||||||
|
Method method = SpotInstanceAsyncClient.class.getMethod("describeSpotPriceHistoryInRegion", String.class,
|
||||||
|
DescribeSpotPriceHistoryOptions[].class);
|
||||||
|
HttpRequest request = processor.createRequest(method, null, DescribeSpotPriceHistoryOptions.Builder.from(from)
|
||||||
|
.to(to).productDescription("description").instanceType("m1.small"));
|
||||||
|
|
||||||
|
assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
|
||||||
|
assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
|
||||||
|
assertPayloadEquals(
|
||||||
|
request,
|
||||||
|
"Version=2010-11-15&Action=DescribeSpotPriceHistory&StartTime=1970-05-23T21%3A21%3A18.910Z&EndTime=2009-02-13T23%3A31%3A31.011Z&ProductDescription=description&InstanceType.1=m1.small",
|
||||||
|
"application/x-www-form-urlencoded", false);
|
||||||
|
|
||||||
|
assertResponseParserClassEquals(method, request, ParseSax.class);
|
||||||
|
assertSaxResponseParserClassEquals(method, DescribeSpotPriceHistoryResponseHandler.class);
|
||||||
|
assertExceptionParserClassEquals(method, ReturnEmptySetOnNotFoundOr404.class);
|
||||||
|
|
||||||
|
checkFilters(request);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected TypeLiteral<RestAnnotationProcessor<SpotInstanceAsyncClient>> createTypeLiteral() {
|
||||||
|
return new TypeLiteral<RestAnnotationProcessor<SpotInstanceAsyncClient>>() {
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,207 @@
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
|
||||||
|
*
|
||||||
|
* ====================================================================
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
* ====================================================================
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jclouds.aws.ec2.services;
|
||||||
|
|
||||||
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
|
import static com.google.common.base.Predicates.in;
|
||||||
|
import static com.google.common.collect.Iterables.getOnlyElement;
|
||||||
|
import static org.jclouds.aws.ec2.options.DescribeSpotPriceHistoryOptions.Builder.from;
|
||||||
|
import static org.jclouds.aws.ec2.options.RequestSpotInstancesOptions.Builder.launchGroup;
|
||||||
|
import static org.testng.Assert.assertEquals;
|
||||||
|
import static org.testng.Assert.assertNotNull;
|
||||||
|
|
||||||
|
import java.io.FileNotFoundException;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.Properties;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.SortedSet;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
import org.jclouds.Constants;
|
||||||
|
import org.jclouds.aws.domain.Region;
|
||||||
|
import org.jclouds.aws.ec2.AWSEC2Client;
|
||||||
|
import org.jclouds.aws.ec2.domain.AWSRunningInstance;
|
||||||
|
import org.jclouds.aws.ec2.domain.LaunchSpecification;
|
||||||
|
import org.jclouds.aws.ec2.domain.Spot;
|
||||||
|
import org.jclouds.aws.ec2.domain.SpotInstanceRequest;
|
||||||
|
import org.jclouds.aws.ec2.predicates.SpotInstanceRequestActive;
|
||||||
|
import org.jclouds.compute.ComputeServiceContext;
|
||||||
|
import org.jclouds.compute.ComputeServiceContextFactory;
|
||||||
|
import org.jclouds.ec2.domain.InstanceType;
|
||||||
|
import org.jclouds.logging.log4j.config.Log4JLoggingModule;
|
||||||
|
import org.jclouds.predicates.RetryablePredicate;
|
||||||
|
import org.jclouds.ssh.jsch.config.JschSshClientModule;
|
||||||
|
import org.testng.annotations.AfterTest;
|
||||||
|
import org.testng.annotations.BeforeClass;
|
||||||
|
import org.testng.annotations.BeforeGroups;
|
||||||
|
import org.testng.annotations.Test;
|
||||||
|
|
||||||
|
import com.google.common.collect.ImmutableSet;
|
||||||
|
import com.google.common.collect.ImmutableSortedSet;
|
||||||
|
import com.google.inject.Module;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests behavior of {@code SpotInstanceClient}
|
||||||
|
*
|
||||||
|
* @author Adrian Cole
|
||||||
|
*/
|
||||||
|
@Test(groups = "live", sequential = true)
|
||||||
|
public class SpotInstanceClientLiveTest {
|
||||||
|
|
||||||
|
private static final int SPOT_DELAY_SECONDS = 300;
|
||||||
|
private AWSEC2Client client;
|
||||||
|
private ComputeServiceContext context;
|
||||||
|
private RetryablePredicate<SpotInstanceRequest> activeTester;
|
||||||
|
private Set<SpotInstanceRequest> requests;
|
||||||
|
protected String provider = "aws-ec2";
|
||||||
|
protected String identity;
|
||||||
|
protected String credential;
|
||||||
|
protected String endpoint;
|
||||||
|
protected String apiversion;
|
||||||
|
private AWSRunningInstance instance;
|
||||||
|
private long start;
|
||||||
|
|
||||||
|
@BeforeClass
|
||||||
|
protected void setupCredentials() {
|
||||||
|
identity = checkNotNull(System.getProperty("test." + provider + ".identity"), "test." + provider + ".identity");
|
||||||
|
credential = System.getProperty("test." + provider + ".credential");
|
||||||
|
endpoint = System.getProperty("test." + provider + ".endpoint");
|
||||||
|
apiversion = System.getProperty("test." + provider + ".apiversion");
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Properties setupProperties() {
|
||||||
|
Properties overrides = new Properties();
|
||||||
|
overrides.setProperty(Constants.PROPERTY_TRUST_ALL_CERTS, "true");
|
||||||
|
overrides.setProperty(Constants.PROPERTY_RELAX_HOSTNAME, "true");
|
||||||
|
overrides.setProperty(provider + ".identity", identity);
|
||||||
|
if (credential != null)
|
||||||
|
overrides.setProperty(provider + ".credential", credential);
|
||||||
|
if (endpoint != null)
|
||||||
|
overrides.setProperty(provider + ".endpoint", endpoint);
|
||||||
|
if (apiversion != null)
|
||||||
|
overrides.setProperty(provider + ".apiversion", apiversion);
|
||||||
|
return overrides;
|
||||||
|
}
|
||||||
|
|
||||||
|
@BeforeGroups(groups = { "live" })
|
||||||
|
public void setupClient() throws FileNotFoundException, IOException {
|
||||||
|
setupCredentials();
|
||||||
|
Properties overrides = setupProperties();
|
||||||
|
context = new ComputeServiceContextFactory().createContext(provider,
|
||||||
|
ImmutableSet.<Module> of(new Log4JLoggingModule(), new JschSshClientModule()), overrides);
|
||||||
|
|
||||||
|
client = AWSEC2Client.class.cast(context.getProviderSpecificContext().getApi());
|
||||||
|
activeTester = new RetryablePredicate<SpotInstanceRequest>(new SpotInstanceRequestActive(client),
|
||||||
|
SPOT_DELAY_SECONDS, 1, 1, TimeUnit.SECONDS);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testDescribeSpotRequestsInRegion() {
|
||||||
|
for (String region : Region.DEFAULT_REGIONS) {
|
||||||
|
SortedSet<SpotInstanceRequest> allResults = ImmutableSortedSet.copyOf(client.getSpotInstanceServices()
|
||||||
|
.describeSpotInstanceRequestsInRegion(region));
|
||||||
|
assertNotNull(allResults);
|
||||||
|
if (allResults.size() >= 1) {
|
||||||
|
SpotInstanceRequest request = allResults.last();
|
||||||
|
SortedSet<SpotInstanceRequest> result = ImmutableSortedSet.copyOf(client.getSpotInstanceServices()
|
||||||
|
.describeSpotInstanceRequestsInRegion(region, request.getId()));
|
||||||
|
assertNotNull(result);
|
||||||
|
SpotInstanceRequest compare = result.last();
|
||||||
|
assertEquals(compare, request);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testDescribeSpotPriceHistoryInRegion() {
|
||||||
|
for (final String region : Region.DEFAULT_REGIONS) {
|
||||||
|
Set<Spot> spots = client.getSpotInstanceServices().describeSpotPriceHistoryInRegion(region, from(new Date()));
|
||||||
|
assertNotNull(spots);
|
||||||
|
assert spots.size() > 0;
|
||||||
|
for (Spot spot : spots) {
|
||||||
|
assert spot.getSpotPrice() > 0 : spots;
|
||||||
|
assertEquals(spot.getRegion(), region);
|
||||||
|
assert in(ImmutableSet.of("Linux/UNIX", "SUSE Linux", "Windows")).apply(spot.getProductDescription()) : spot;
|
||||||
|
assert in(
|
||||||
|
ImmutableSet.of("c1.medium", "c1.xlarge", "m1.large", "m1.small", "m1.xlarge", "m2.2xlarge",
|
||||||
|
"m2.4xlarge", "m2.xlarge", "t1.micro")).apply(spot.getInstanceType()) : spot;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(enabled = true)
|
||||||
|
void testCreateSpotInstance() {
|
||||||
|
String launchGroup = PREFIX + "1";
|
||||||
|
for (SpotInstanceRequest request : client.getSpotInstanceServices().describeSpotInstanceRequestsInRegion(
|
||||||
|
"us-west-1"))
|
||||||
|
if (launchGroup.equals(request.getLaunchGroup()))
|
||||||
|
client.getSpotInstanceServices().cancelSpotInstanceRequestsInRegion("us-west-1", request.getId());
|
||||||
|
start = System.currentTimeMillis();
|
||||||
|
|
||||||
|
requests = client.getSpotInstanceServices().requestSpotInstancesInRegion(
|
||||||
|
"us-west-1",
|
||||||
|
0.03f,
|
||||||
|
1,
|
||||||
|
LaunchSpecification.builder().imageId("ami-595a0a1c").instanceType(InstanceType.T1_MICRO).build(),
|
||||||
|
launchGroup(launchGroup).availabilityZoneGroup(launchGroup).validFrom(new Date())
|
||||||
|
.validUntil(new Date(System.currentTimeMillis() + TimeUnit.SECONDS.toMillis(SPOT_DELAY_SECONDS))));
|
||||||
|
assertNotNull(requests);
|
||||||
|
|
||||||
|
for (SpotInstanceRequest request : requests)
|
||||||
|
verifySpotInstance(request);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void verifySpotInstance(SpotInstanceRequest request) {
|
||||||
|
SpotInstanceRequest spot = refresh(request);
|
||||||
|
assertNotNull(spot);
|
||||||
|
assertEquals(spot, request);
|
||||||
|
assert activeTester.apply(request) : refresh(request);
|
||||||
|
System.out.println(System.currentTimeMillis() - start);
|
||||||
|
spot = refresh(request);
|
||||||
|
assert spot.getInstanceId() != null : spot;
|
||||||
|
instance = getOnlyElement(getOnlyElement(client.getInstanceServices().describeInstancesInRegion("us-west-1",
|
||||||
|
spot.getInstanceId())));
|
||||||
|
assertEquals(instance.getSpotInstanceRequestId(), spot.getId());
|
||||||
|
}
|
||||||
|
|
||||||
|
public SpotInstanceRequest refresh(SpotInstanceRequest request) {
|
||||||
|
return getOnlyElement(client.getSpotInstanceServices().describeSpotInstanceRequestsInRegion("us-west-1",
|
||||||
|
request.getId()));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final String PREFIX = System.getProperty("user.name") + "ec2";
|
||||||
|
|
||||||
|
@AfterTest
|
||||||
|
public void shutdown() {
|
||||||
|
if (requests != null) {
|
||||||
|
for (SpotInstanceRequest request : requests)
|
||||||
|
client.getSpotInstanceServices().cancelSpotInstanceRequestsInRegion(request.getRegion(), request.getId());
|
||||||
|
// assert deletedTester.apply(request) : request;
|
||||||
|
}
|
||||||
|
if (instance != null) {
|
||||||
|
client.getInstanceServices().terminateInstancesInRegion("us-west-1", instance.getId());
|
||||||
|
}
|
||||||
|
context.close();
|
||||||
|
}
|
||||||
|
}
|
|
@ -53,7 +53,7 @@ import com.google.inject.Guice;
|
||||||
*/
|
*/
|
||||||
// NOTE:without testName, this will not call @Before* and fail w/NPE during surefire
|
// NOTE:without testName, this will not call @Before* and fail w/NPE during surefire
|
||||||
@Test(groups = "unit", testName = "RunInstancesResponseHandlerTest")
|
@Test(groups = "unit", testName = "RunInstancesResponseHandlerTest")
|
||||||
public class RunInstancesResponseHandlerTest extends BaseEC2HandlerTest {
|
public class AWSRunInstancesResponseHandlerTest extends BaseEC2HandlerTest {
|
||||||
|
|
||||||
private DateService dateService;
|
private DateService dateService;
|
||||||
|
|
|
@ -0,0 +1,69 @@
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com("
|
||||||
|
*
|
||||||
|
* ====================================================================
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
* ====================================================================
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jclouds.aws.ec2.xml;
|
||||||
|
|
||||||
|
import static org.testng.Assert.assertEquals;
|
||||||
|
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import org.jclouds.aws.ec2.domain.Spot;
|
||||||
|
import org.jclouds.date.internal.SimpleDateFormatDateService;
|
||||||
|
import org.jclouds.http.functions.BaseHandlerTest;
|
||||||
|
import org.jclouds.location.Region;
|
||||||
|
import org.testng.annotations.Test;
|
||||||
|
|
||||||
|
import com.google.common.collect.ImmutableSet;
|
||||||
|
import com.google.inject.AbstractModule;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests behavior of {@code DescribeSpotPriceHistoryResponseHandler}
|
||||||
|
*
|
||||||
|
* @author Adrian Cole
|
||||||
|
*/
|
||||||
|
// NOTE:without testName, this will not call @Before* and fail w/NPE during surefire
|
||||||
|
@Test(groups = "unit", testName = "DescribeSpotPriceHistoryResponseHandlerTest")
|
||||||
|
public class DescribeSpotPriceHistoryResponseHandlerTest extends BaseHandlerTest {
|
||||||
|
public void testApplyInputStream() {
|
||||||
|
|
||||||
|
InputStream is = getClass().getResourceAsStream("/describe_spot_price_history.xml");
|
||||||
|
|
||||||
|
Set<Spot> expected = ImmutableSet.of(
|
||||||
|
Spot.builder().region("us-west-1").instanceType("t1.micro").productDescription("SUSE Linux").spotPrice(0.013f)
|
||||||
|
.timestamp(new SimpleDateFormatDateService().iso8601DateParse("2011-03-07T12:17:19.000Z")).build(),
|
||||||
|
Spot.builder().region("us-west-1").instanceType("m1.large").productDescription("Linux/UNIX").spotPrice(0.119f)
|
||||||
|
.timestamp(new SimpleDateFormatDateService().iso8601DateParse("2011-03-07T16:29:16.000Z")).build(),
|
||||||
|
Spot.builder().region("us-west-1").instanceType("t1.micro").productDescription("Windows").spotPrice(0.013f)
|
||||||
|
.timestamp(new SimpleDateFormatDateService().iso8601DateParse("2011-03-07T17:56:54.000Z")).build()
|
||||||
|
|
||||||
|
);
|
||||||
|
|
||||||
|
Set<Spot> result = factory.create(injector.createChildInjector(new AbstractModule(){
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void configure() {
|
||||||
|
bindConstant().annotatedWith(Region.class).to("us-west-1");
|
||||||
|
}
|
||||||
|
|
||||||
|
}).getInstance(DescribeSpotPriceHistoryResponseHandler.class)).parse(is);
|
||||||
|
|
||||||
|
assertEquals(result, expected);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,102 @@
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Copyright (C) 2010 Cloud Conscious, LLC. .info@cloudconscious.com("
|
||||||
|
*
|
||||||
|
* ====================================================================
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
* ====================================================================
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jclouds.aws.ec2.xml;
|
||||||
|
|
||||||
|
import static org.easymock.EasyMock.expect;
|
||||||
|
import static org.easymock.classextension.EasyMock.createMock;
|
||||||
|
import static org.easymock.classextension.EasyMock.replay;
|
||||||
|
import static org.testng.Assert.assertEquals;
|
||||||
|
|
||||||
|
import java.io.InputStream;
|
||||||
|
|
||||||
|
import org.jclouds.aws.ec2.domain.LaunchSpecification;
|
||||||
|
import org.jclouds.aws.ec2.domain.SpotInstanceRequest;
|
||||||
|
import org.jclouds.date.DateService;
|
||||||
|
import org.jclouds.date.internal.SimpleDateFormatDateService;
|
||||||
|
import org.jclouds.ec2.xml.BaseEC2HandlerTest;
|
||||||
|
import org.jclouds.http.functions.ParseSax;
|
||||||
|
import org.jclouds.http.functions.config.SaxParserModule;
|
||||||
|
import org.jclouds.location.Region;
|
||||||
|
import org.jclouds.rest.internal.GeneratedHttpRequest;
|
||||||
|
import org.testng.annotations.BeforeTest;
|
||||||
|
import org.testng.annotations.Test;
|
||||||
|
|
||||||
|
import com.google.common.collect.ImmutableList;
|
||||||
|
import com.google.inject.AbstractModule;
|
||||||
|
import com.google.inject.Guice;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests behavior of {@code SpotInstanceHandler}
|
||||||
|
*
|
||||||
|
* @author Adrian Cole
|
||||||
|
*/
|
||||||
|
// NOTE:without testName, this will not call @Before* and fail w/NPE during surefire
|
||||||
|
@Test(groups = "unit", testName = "SpotInstanceHandlerTest")
|
||||||
|
public class SpotInstanceHandlerTest extends BaseEC2HandlerTest {
|
||||||
|
|
||||||
|
private DateService dateService;
|
||||||
|
|
||||||
|
@BeforeTest
|
||||||
|
@Override
|
||||||
|
protected void setUpInjector() {
|
||||||
|
injector = Guice.createInjector(new SaxParserModule(), new AbstractModule() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void configure() {
|
||||||
|
bind(String.class).annotatedWith(Region.class).toInstance("us-east-1");
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
factory = injector.getInstance(ParseSax.Factory.class);
|
||||||
|
dateService = injector.getInstance(DateService.class);
|
||||||
|
assert dateService != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testApplyInputStream() {
|
||||||
|
|
||||||
|
InputStream is = getClass().getResourceAsStream("/request_spot_instances-ebs.xml");
|
||||||
|
|
||||||
|
SpotInstanceRequest expected = SpotInstanceRequest
|
||||||
|
.builder()
|
||||||
|
.region("us-east-1")
|
||||||
|
.id("sir-228e6406")
|
||||||
|
.spotPrice(0.001f)
|
||||||
|
.type(SpotInstanceRequest.Type.ONE_TIME)
|
||||||
|
.state(SpotInstanceRequest.State.OPEN)
|
||||||
|
.launchSpecification(
|
||||||
|
LaunchSpecification.builder().imageId("ami-595a0a1c").groupId("default").instanceType("m1.large")
|
||||||
|
.mapNewVolumeToDevice("/dev/sda1", 1, true)
|
||||||
|
.mapEBSSnapshotToDevice("/dev/sda2", "snap-1ea27576", 1, true)
|
||||||
|
.mapEphemeralDeviceToDevice("/dev/sda3", "vre1").monitoringEnabled(false).build())
|
||||||
|
.createTime(new SimpleDateFormatDateService().iso8601DateParse("2011-03-08T03:30:36.000Z"))
|
||||||
|
.productDescription("Linux/UNIX").build();
|
||||||
|
SpotInstanceHandler handler = injector.getInstance(SpotInstanceHandler.class);
|
||||||
|
addDefaultRegionToHandler(handler);
|
||||||
|
SpotInstanceRequest result = factory.create(handler).parse(is);
|
||||||
|
assertEquals(result, expected);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addDefaultRegionToHandler(ParseSax.HandlerWithResult<?> handler) {
|
||||||
|
GeneratedHttpRequest<?> request = createMock(GeneratedHttpRequest.class);
|
||||||
|
expect(request.getArgs()).andReturn(ImmutableList.<Object> of()).atLeastOnce();
|
||||||
|
replay(request);
|
||||||
|
handler.setContext(request);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,95 @@
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Copyright (C) 2010 Cloud Conscious, LLC. .info@cloudconscious.com("
|
||||||
|
*
|
||||||
|
* ====================================================================
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
* ====================================================================
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jclouds.aws.ec2.xml;
|
||||||
|
|
||||||
|
import static org.easymock.EasyMock.expect;
|
||||||
|
import static org.easymock.classextension.EasyMock.createMock;
|
||||||
|
import static org.easymock.classextension.EasyMock.replay;
|
||||||
|
import static org.testng.Assert.assertEquals;
|
||||||
|
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import org.jclouds.aws.ec2.domain.SpotInstanceRequest;
|
||||||
|
import org.jclouds.date.DateService;
|
||||||
|
import org.jclouds.ec2.xml.BaseEC2HandlerTest;
|
||||||
|
import org.jclouds.http.functions.ParseSax;
|
||||||
|
import org.jclouds.http.functions.config.SaxParserModule;
|
||||||
|
import org.jclouds.location.Region;
|
||||||
|
import org.jclouds.rest.internal.GeneratedHttpRequest;
|
||||||
|
import org.testng.annotations.BeforeTest;
|
||||||
|
import org.testng.annotations.Test;
|
||||||
|
|
||||||
|
import com.google.common.collect.ImmutableList;
|
||||||
|
import com.google.inject.AbstractModule;
|
||||||
|
import com.google.inject.Guice;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests behavior of {@code SpotInstancesHandler}
|
||||||
|
*
|
||||||
|
* @author Adrian Cole
|
||||||
|
*/
|
||||||
|
// NOTE:without testName, this will not call @Before* and fail w/NPE during surefire
|
||||||
|
@Test(groups = "unit", testName = "SpotInstancesHandlerTest")
|
||||||
|
public class SpotInstancesHandlerTest extends BaseEC2HandlerTest {
|
||||||
|
|
||||||
|
private DateService dateService;
|
||||||
|
|
||||||
|
@BeforeTest
|
||||||
|
@Override
|
||||||
|
protected void setUpInjector() {
|
||||||
|
injector = Guice.createInjector(new SaxParserModule(), new AbstractModule() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void configure() {
|
||||||
|
bind(String.class).annotatedWith(Region.class).toInstance("us-east-1");
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
factory = injector.getInstance(ParseSax.Factory.class);
|
||||||
|
dateService = injector.getInstance(DateService.class);
|
||||||
|
assert dateService != null;
|
||||||
|
}
|
||||||
|
public void testDescribe() {
|
||||||
|
|
||||||
|
InputStream is = getClass().getResourceAsStream("/describe_spot_instance_requests.xml");
|
||||||
|
SpotInstancesHandler handler = injector
|
||||||
|
.getInstance(SpotInstancesHandler.class);
|
||||||
|
addDefaultRegionToHandler(handler);
|
||||||
|
Set<SpotInstanceRequest> result = factory.create(handler).parse(is);
|
||||||
|
assertEquals(result.size(), 18);
|
||||||
|
}
|
||||||
|
public void testRequest() {
|
||||||
|
|
||||||
|
InputStream is = getClass().getResourceAsStream("/request_spot_instances.xml");
|
||||||
|
SpotInstancesHandler handler = injector
|
||||||
|
.getInstance(SpotInstancesHandler.class);
|
||||||
|
addDefaultRegionToHandler(handler);
|
||||||
|
Set<SpotInstanceRequest> result = factory.create(handler).parse(is);
|
||||||
|
assertEquals(result.size(), 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addDefaultRegionToHandler(ParseSax.HandlerWithResult<?> handler) {
|
||||||
|
GeneratedHttpRequest<?> request = createMock(GeneratedHttpRequest.class);
|
||||||
|
expect(request.getArgs()).andReturn(ImmutableList.<Object> of()).atLeastOnce();
|
||||||
|
replay(request);
|
||||||
|
handler.setContext(request);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,413 @@
|
||||||
|
<DescribeSpotInstanceRequestsResponse xmlns="http://ec2.amazonaws.com/doc/2010-11-15/">
|
||||||
|
<requestId>7c4dd2bd-106d-4cd3-987c-35ee819180a6</requestId>
|
||||||
|
<spotInstanceRequestSet>
|
||||||
|
<item>
|
||||||
|
<spotInstanceRequestId>sir-067a4805</spotInstanceRequestId>
|
||||||
|
<spotPrice>0.040000</spotPrice>
|
||||||
|
<type>one-time</type>
|
||||||
|
<state>cancelled</state>
|
||||||
|
<launchSpecification>
|
||||||
|
<imageId>ami-595a0a1c</imageId>
|
||||||
|
<groupSet>
|
||||||
|
<item>
|
||||||
|
<groupId>default</groupId>
|
||||||
|
</item>
|
||||||
|
</groupSet>
|
||||||
|
<instanceType>t1.micro</instanceType>
|
||||||
|
<blockDeviceMapping/>
|
||||||
|
<monitoring>
|
||||||
|
<enabled>false</enabled>
|
||||||
|
</monitoring>
|
||||||
|
</launchSpecification>
|
||||||
|
<createTime>2011-03-07T20:13:07.000Z</createTime>
|
||||||
|
<productDescription>Linux/UNIX</productDescription>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<spotInstanceRequestId>sir-aa67d410</spotInstanceRequestId>
|
||||||
|
<spotPrice>0.040000</spotPrice>
|
||||||
|
<type>one-time</type>
|
||||||
|
<state>cancelled</state>
|
||||||
|
<launchSpecification>
|
||||||
|
<imageId>ami-595a0a1c</imageId>
|
||||||
|
<groupSet>
|
||||||
|
<item>
|
||||||
|
<groupId>default</groupId>
|
||||||
|
</item>
|
||||||
|
</groupSet>
|
||||||
|
<instanceType>t1.micro</instanceType>
|
||||||
|
<blockDeviceMapping/>
|
||||||
|
<monitoring>
|
||||||
|
<enabled>false</enabled>
|
||||||
|
</monitoring>
|
||||||
|
</launchSpecification>
|
||||||
|
<createTime>2011-03-07T20:13:57.000Z</createTime>
|
||||||
|
<productDescription>Linux/UNIX</productDescription>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<spotInstanceRequestId>sir-32e32810</spotInstanceRequestId>
|
||||||
|
<spotPrice>0.010000</spotPrice>
|
||||||
|
<type>one-time</type>
|
||||||
|
<state>cancelled</state>
|
||||||
|
<launchSpecification>
|
||||||
|
<imageId>ami-595a0a1c</imageId>
|
||||||
|
<groupSet>
|
||||||
|
<item>
|
||||||
|
<groupId>default</groupId>
|
||||||
|
</item>
|
||||||
|
</groupSet>
|
||||||
|
<instanceType>t1.micro</instanceType>
|
||||||
|
<blockDeviceMapping/>
|
||||||
|
<monitoring>
|
||||||
|
<enabled>false</enabled>
|
||||||
|
</monitoring>
|
||||||
|
</launchSpecification>
|
||||||
|
<createTime>2011-03-07T20:15:52.000Z</createTime>
|
||||||
|
<productDescription>Linux/UNIX</productDescription>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<spotInstanceRequestId>sir-46a36210</spotInstanceRequestId>
|
||||||
|
<spotPrice>0.010000</spotPrice>
|
||||||
|
<type>one-time</type>
|
||||||
|
<state>cancelled</state>
|
||||||
|
<validUntil>2011-03-07T20:20:00.000Z</validUntil>
|
||||||
|
<launchGroup>foo</launchGroup>
|
||||||
|
<availabilityZoneGroup>azfoo</availabilityZoneGroup>
|
||||||
|
<launchSpecification>
|
||||||
|
<imageId>ami-595a0a1c</imageId>
|
||||||
|
<keyName>default</keyName>
|
||||||
|
<groupSet>
|
||||||
|
<item>
|
||||||
|
<groupId>quick-start-1</groupId>
|
||||||
|
</item>
|
||||||
|
</groupSet>
|
||||||
|
<instanceType>t1.micro</instanceType>
|
||||||
|
<blockDeviceMapping/>
|
||||||
|
<monitoring>
|
||||||
|
<enabled>true</enabled>
|
||||||
|
</monitoring>
|
||||||
|
</launchSpecification>
|
||||||
|
<createTime>2011-03-07T20:18:25.000Z</createTime>
|
||||||
|
<productDescription>Linux/UNIX</productDescription>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<spotInstanceRequestId>sir-91780010</spotInstanceRequestId>
|
||||||
|
<spotPrice>0.010000</spotPrice>
|
||||||
|
<type>one-time</type>
|
||||||
|
<state>cancelled</state>
|
||||||
|
<validUntil>2011-03-07T20:20:00.000Z</validUntil>
|
||||||
|
<launchGroup>foo</launchGroup>
|
||||||
|
<availabilityZoneGroup>azfoo</availabilityZoneGroup>
|
||||||
|
<launchSpecification>
|
||||||
|
<imageId>ami-595a0a1c</imageId>
|
||||||
|
<keyName>default</keyName>
|
||||||
|
<groupSet>
|
||||||
|
<item>
|
||||||
|
<groupId>quick-start-1</groupId>
|
||||||
|
</item>
|
||||||
|
</groupSet>
|
||||||
|
<instanceType>t1.micro</instanceType>
|
||||||
|
<blockDeviceMapping/>
|
||||||
|
<monitoring>
|
||||||
|
<enabled>true</enabled>
|
||||||
|
</monitoring>
|
||||||
|
</launchSpecification>
|
||||||
|
<createTime>2011-03-07T20:18:25.000Z</createTime>
|
||||||
|
<productDescription>Linux/UNIX</productDescription>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<spotInstanceRequestId>sir-6f1fa605</spotInstanceRequestId>
|
||||||
|
<spotPrice>0.001000</spotPrice>
|
||||||
|
<type>one-time</type>
|
||||||
|
<state>cancelled</state>
|
||||||
|
<launchSpecification>
|
||||||
|
<imageId>ami-595a0a1c</imageId>
|
||||||
|
<groupSet>
|
||||||
|
<item>
|
||||||
|
<groupId>default</groupId>
|
||||||
|
</item>
|
||||||
|
</groupSet>
|
||||||
|
<instanceType>t1.micro</instanceType>
|
||||||
|
<blockDeviceMapping/>
|
||||||
|
<monitoring>
|
||||||
|
<enabled>false</enabled>
|
||||||
|
</monitoring>
|
||||||
|
</launchSpecification>
|
||||||
|
<createTime>2011-03-07T20:19:27.000Z</createTime>
|
||||||
|
<productDescription>Linux/UNIX</productDescription>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<spotInstanceRequestId>sir-a33eee10</spotInstanceRequestId>
|
||||||
|
<spotPrice>0.001000</spotPrice>
|
||||||
|
<type>one-time</type>
|
||||||
|
<state>cancelled</state>
|
||||||
|
<launchSpecification>
|
||||||
|
<imageId>ami-595a0a1c</imageId>
|
||||||
|
<groupSet>
|
||||||
|
<item>
|
||||||
|
<groupId>default</groupId>
|
||||||
|
</item>
|
||||||
|
</groupSet>
|
||||||
|
<instanceType>t1.micro</instanceType>
|
||||||
|
<blockDeviceMapping/>
|
||||||
|
<monitoring>
|
||||||
|
<enabled>false</enabled>
|
||||||
|
</monitoring>
|
||||||
|
</launchSpecification>
|
||||||
|
<createTime>2011-03-07T20:21:16.000Z</createTime>
|
||||||
|
<productDescription>Linux/UNIX</productDescription>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<spotInstanceRequestId>sir-aa690410</spotInstanceRequestId>
|
||||||
|
<spotPrice>0.001000</spotPrice>
|
||||||
|
<type>one-time</type>
|
||||||
|
<state>cancelled</state>
|
||||||
|
<launchSpecification>
|
||||||
|
<imageId>ami-595a0a1c</imageId>
|
||||||
|
<groupSet>
|
||||||
|
<item>
|
||||||
|
<groupId>default</groupId>
|
||||||
|
</item>
|
||||||
|
</groupSet>
|
||||||
|
<instanceType>t1.micro</instanceType>
|
||||||
|
<blockDeviceMapping/>
|
||||||
|
<monitoring>
|
||||||
|
<enabled>false</enabled>
|
||||||
|
</monitoring>
|
||||||
|
</launchSpecification>
|
||||||
|
<createTime>2011-03-07T20:21:52.000Z</createTime>
|
||||||
|
<productDescription>Linux/UNIX</productDescription>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<spotInstanceRequestId>sir-99ba4e06</spotInstanceRequestId>
|
||||||
|
<spotPrice>0.010000</spotPrice>
|
||||||
|
<type>one-time</type>
|
||||||
|
<state>cancelled</state>
|
||||||
|
<validUntil>2011-03-07T20:26:00.000Z</validUntil>
|
||||||
|
<launchGroup>doo</launchGroup>
|
||||||
|
<availabilityZoneGroup>dooo</availabilityZoneGroup>
|
||||||
|
<launchSpecification>
|
||||||
|
<imageId>ami-595a0a1c</imageId>
|
||||||
|
<keyName>default</keyName>
|
||||||
|
<groupSet>
|
||||||
|
<item>
|
||||||
|
<groupId>quick-start-1</groupId>
|
||||||
|
</item>
|
||||||
|
</groupSet>
|
||||||
|
<instanceType>t1.micro</instanceType>
|
||||||
|
<blockDeviceMapping/>
|
||||||
|
<monitoring>
|
||||||
|
<enabled>true</enabled>
|
||||||
|
</monitoring>
|
||||||
|
</launchSpecification>
|
||||||
|
<createTime>2011-03-07T20:24:30.000Z</createTime>
|
||||||
|
<productDescription>Linux/UNIX</productDescription>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<spotInstanceRequestId>sir-a617c406</spotInstanceRequestId>
|
||||||
|
<spotPrice>0.010000</spotPrice>
|
||||||
|
<type>one-time</type>
|
||||||
|
<state>cancelled</state>
|
||||||
|
<validUntil>2011-03-07T20:26:00.000Z</validUntil>
|
||||||
|
<launchGroup>doo</launchGroup>
|
||||||
|
<availabilityZoneGroup>dooo</availabilityZoneGroup>
|
||||||
|
<launchSpecification>
|
||||||
|
<imageId>ami-595a0a1c</imageId>
|
||||||
|
<keyName>default</keyName>
|
||||||
|
<groupSet>
|
||||||
|
<item>
|
||||||
|
<groupId>quick-start-1</groupId>
|
||||||
|
</item>
|
||||||
|
</groupSet>
|
||||||
|
<instanceType>t1.micro</instanceType>
|
||||||
|
<blockDeviceMapping/>
|
||||||
|
<monitoring>
|
||||||
|
<enabled>true</enabled>
|
||||||
|
</monitoring>
|
||||||
|
</launchSpecification>
|
||||||
|
<createTime>2011-03-07T20:24:30.000Z</createTime>
|
||||||
|
<productDescription>Linux/UNIX</productDescription>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<spotInstanceRequestId>sir-2147a405</spotInstanceRequestId>
|
||||||
|
<spotPrice>0.001000</spotPrice>
|
||||||
|
<type>one-time</type>
|
||||||
|
<state>cancelled</state>
|
||||||
|
<launchSpecification>
|
||||||
|
<imageId>ami-595a0a1c</imageId>
|
||||||
|
<groupSet>
|
||||||
|
<item>
|
||||||
|
<groupId>default</groupId>
|
||||||
|
</item>
|
||||||
|
</groupSet>
|
||||||
|
<instanceType>t1.micro</instanceType>
|
||||||
|
<blockDeviceMapping/>
|
||||||
|
<monitoring>
|
||||||
|
<enabled>false</enabled>
|
||||||
|
</monitoring>
|
||||||
|
</launchSpecification>
|
||||||
|
<createTime>2011-03-07T20:25:19.000Z</createTime>
|
||||||
|
<productDescription>Linux/UNIX</productDescription>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<spotInstanceRequestId>sir-c441c805</spotInstanceRequestId>
|
||||||
|
<spotPrice>0.001000</spotPrice>
|
||||||
|
<type>one-time</type>
|
||||||
|
<state>cancelled</state>
|
||||||
|
<launchSpecification>
|
||||||
|
<imageId>ami-595a0a1c</imageId>
|
||||||
|
<groupSet>
|
||||||
|
<item>
|
||||||
|
<groupId>default</groupId>
|
||||||
|
</item>
|
||||||
|
</groupSet>
|
||||||
|
<instanceType>t1.micro</instanceType>
|
||||||
|
<blockDeviceMapping/>
|
||||||
|
<monitoring>
|
||||||
|
<enabled>false</enabled>
|
||||||
|
</monitoring>
|
||||||
|
</launchSpecification>
|
||||||
|
<createTime>2011-03-07T20:29:09.000Z</createTime>
|
||||||
|
<productDescription>Linux/UNIX</productDescription>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<spotInstanceRequestId>sir-4658fe10</spotInstanceRequestId>
|
||||||
|
<spotPrice>0.010000</spotPrice>
|
||||||
|
<type>one-time</type>
|
||||||
|
<state>cancelled</state>
|
||||||
|
<validUntil>2011-03-07T21:10:00.000Z</validUntil>
|
||||||
|
<launchGroup>check3</launchGroup>
|
||||||
|
<availabilityZoneGroup>check3</availabilityZoneGroup>
|
||||||
|
<launchSpecification>
|
||||||
|
<imageId>ami-595a0a1c</imageId>
|
||||||
|
<keyName>default</keyName>
|
||||||
|
<groupSet>
|
||||||
|
<item>
|
||||||
|
<groupId>quick-start-1</groupId>
|
||||||
|
</item>
|
||||||
|
</groupSet>
|
||||||
|
<instanceType>t1.micro</instanceType>
|
||||||
|
<blockDeviceMapping/>
|
||||||
|
<monitoring>
|
||||||
|
<enabled>false</enabled>
|
||||||
|
</monitoring>
|
||||||
|
</launchSpecification>
|
||||||
|
<createTime>2011-03-07T20:31:34.000Z</createTime>
|
||||||
|
<productDescription>Linux/UNIX</productDescription>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<spotInstanceRequestId>sir-49a3ce10</spotInstanceRequestId>
|
||||||
|
<spotPrice>0.010000</spotPrice>
|
||||||
|
<type>one-time</type>
|
||||||
|
<state>cancelled</state>
|
||||||
|
<validUntil>2011-03-07T21:10:00.000Z</validUntil>
|
||||||
|
<launchGroup>check3</launchGroup>
|
||||||
|
<availabilityZoneGroup>check3</availabilityZoneGroup>
|
||||||
|
<launchSpecification>
|
||||||
|
<imageId>ami-595a0a1c</imageId>
|
||||||
|
<keyName>default</keyName>
|
||||||
|
<groupSet>
|
||||||
|
<item>
|
||||||
|
<groupId>quick-start-1</groupId>
|
||||||
|
</item>
|
||||||
|
</groupSet>
|
||||||
|
<instanceType>t1.micro</instanceType>
|
||||||
|
<blockDeviceMapping/>
|
||||||
|
<monitoring>
|
||||||
|
<enabled>false</enabled>
|
||||||
|
</monitoring>
|
||||||
|
</launchSpecification>
|
||||||
|
<createTime>2011-03-07T20:31:34.000Z</createTime>
|
||||||
|
<productDescription>Linux/UNIX</productDescription>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<spotInstanceRequestId>sir-91b30610</spotInstanceRequestId>
|
||||||
|
<spotPrice>0.010000</spotPrice>
|
||||||
|
<type>one-time</type>
|
||||||
|
<state>cancelled</state>
|
||||||
|
<validUntil>2011-03-07T21:10:00.000Z</validUntil>
|
||||||
|
<launchGroup>check3</launchGroup>
|
||||||
|
<availabilityZoneGroup>check3</availabilityZoneGroup>
|
||||||
|
<launchSpecification>
|
||||||
|
<imageId>ami-595a0a1c</imageId>
|
||||||
|
<keyName>default</keyName>
|
||||||
|
<groupSet>
|
||||||
|
<item>
|
||||||
|
<groupId>quick-start-1</groupId>
|
||||||
|
</item>
|
||||||
|
</groupSet>
|
||||||
|
<instanceType>t1.micro</instanceType>
|
||||||
|
<blockDeviceMapping/>
|
||||||
|
<monitoring>
|
||||||
|
<enabled>false</enabled>
|
||||||
|
</monitoring>
|
||||||
|
</launchSpecification>
|
||||||
|
<createTime>2011-03-07T20:31:34.000Z</createTime>
|
||||||
|
<productDescription>Linux/UNIX</productDescription>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<spotInstanceRequestId>sir-d8561606</spotInstanceRequestId>
|
||||||
|
<spotPrice>0.001000</spotPrice>
|
||||||
|
<type>one-time</type>
|
||||||
|
<state>cancelled</state>
|
||||||
|
<launchSpecification>
|
||||||
|
<imageId>ami-595a0a1c</imageId>
|
||||||
|
<groupSet>
|
||||||
|
<item>
|
||||||
|
<groupId>default</groupId>
|
||||||
|
</item>
|
||||||
|
</groupSet>
|
||||||
|
<instanceType>t1.micro</instanceType>
|
||||||
|
<blockDeviceMapping/>
|
||||||
|
<monitoring>
|
||||||
|
<enabled>false</enabled>
|
||||||
|
</monitoring>
|
||||||
|
</launchSpecification>
|
||||||
|
<createTime>2011-03-07T20:34:10.000Z</createTime>
|
||||||
|
<productDescription>Linux/UNIX</productDescription>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<spotInstanceRequestId>sir-4cdaa406</spotInstanceRequestId>
|
||||||
|
<spotPrice>0.001000</spotPrice>
|
||||||
|
<type>persistent</type>
|
||||||
|
<state>cancelled</state>
|
||||||
|
<validUntil>2011-03-07T22:25:00.000Z</validUntil>
|
||||||
|
<launchSpecification>
|
||||||
|
<imageId>ami-595a0a1c</imageId>
|
||||||
|
<keyName>default</keyName>
|
||||||
|
<groupSet>
|
||||||
|
<item>
|
||||||
|
<groupId>quick-start-1</groupId>
|
||||||
|
</item>
|
||||||
|
</groupSet>
|
||||||
|
<instanceType>t1.micro</instanceType>
|
||||||
|
<blockDeviceMapping/>
|
||||||
|
<monitoring>
|
||||||
|
<enabled>false</enabled>
|
||||||
|
</monitoring>
|
||||||
|
</launchSpecification>
|
||||||
|
<createTime>2011-03-07T22:23:19.000Z</createTime>
|
||||||
|
<productDescription>Linux/UNIX</productDescription>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<spotInstanceRequestId>sir-e19f2206</spotInstanceRequestId>
|
||||||
|
<spotPrice>0.001000</spotPrice>
|
||||||
|
<type>one-time</type>
|
||||||
|
<state>open</state>
|
||||||
|
<launchSpecification>
|
||||||
|
<imageId>ami-595a0a1c</imageId>
|
||||||
|
<groupSet>
|
||||||
|
<item>
|
||||||
|
<groupId>default</groupId>
|
||||||
|
</item>
|
||||||
|
</groupSet>
|
||||||
|
<instanceType>t1.micro</instanceType>
|
||||||
|
<blockDeviceMapping/>
|
||||||
|
<monitoring>
|
||||||
|
<enabled>false</enabled>
|
||||||
|
</monitoring>
|
||||||
|
</launchSpecification>
|
||||||
|
<createTime>2011-03-07T22:32:50.000Z</createTime>
|
||||||
|
<productDescription>Linux/UNIX</productDescription>
|
||||||
|
</item>
|
||||||
|
</spotInstanceRequestSet>
|
||||||
|
</DescribeSpotInstanceRequestsResponse>
|
|
@ -0,0 +1,24 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<DescribeSpotPriceHistoryResponse xmlns="http://ec2.amazonaws.com/doc/2010-11-15/">
|
||||||
|
<requestId>99777a75-2a2b-4296-a305-650c442d2d63</requestId>
|
||||||
|
<spotPriceHistorySet>
|
||||||
|
<item>
|
||||||
|
<instanceType>t1.micro</instanceType>
|
||||||
|
<productDescription>SUSE Linux</productDescription>
|
||||||
|
<spotPrice>0.013000</spotPrice>
|
||||||
|
<timestamp>2011-03-07T12:17:19.000Z</timestamp>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<instanceType>m1.large</instanceType>
|
||||||
|
<productDescription>Linux/UNIX</productDescription>
|
||||||
|
<spotPrice>0.119000</spotPrice>
|
||||||
|
<timestamp>2011-03-07T16:29:16.000Z</timestamp>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<instanceType>t1.micro</instanceType>
|
||||||
|
<productDescription>Windows</productDescription>
|
||||||
|
<spotPrice>0.013000</spotPrice>
|
||||||
|
<timestamp>2011-03-07T17:56:54.000Z</timestamp>
|
||||||
|
</item>
|
||||||
|
</spotPriceHistorySet>
|
||||||
|
</DescribeSpotPriceHistoryResponse>
|
|
@ -0,0 +1,47 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<RequestSpotInstancesResponse xmlns="http://ec2.amazonaws.com/doc/2010-11-15/">
|
||||||
|
<requestId>02401e8e-a4f5-4285-8ea8-6d742fbaadd8</requestId>
|
||||||
|
<spotInstanceRequestSet>
|
||||||
|
<item>
|
||||||
|
<spotInstanceRequestId>sir-228e6406</spotInstanceRequestId>
|
||||||
|
<spotPrice>0.001000</spotPrice>
|
||||||
|
<type>one-time</type>
|
||||||
|
<state>open</state>
|
||||||
|
<launchSpecification>
|
||||||
|
<imageId>ami-595a0a1c</imageId>
|
||||||
|
<groupSet>
|
||||||
|
<item>
|
||||||
|
<groupId>default</groupId>
|
||||||
|
</item>
|
||||||
|
</groupSet>
|
||||||
|
<instanceType>m1.large</instanceType>
|
||||||
|
<blockDeviceMapping>
|
||||||
|
<item>
|
||||||
|
<deviceName>/dev/sda1</deviceName>
|
||||||
|
<ebs>
|
||||||
|
<volumeSize>1</volumeSize>
|
||||||
|
<deleteOnTermination>true</deleteOnTermination>
|
||||||
|
</ebs>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<deviceName>/dev/sda3</deviceName>
|
||||||
|
<virtualName>vre1</virtualName>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<deviceName>/dev/sda2</deviceName>
|
||||||
|
<ebs>
|
||||||
|
<snapshotId>snap-1ea27576</snapshotId>
|
||||||
|
<volumeSize>1</volumeSize>
|
||||||
|
<deleteOnTermination>true</deleteOnTermination>
|
||||||
|
</ebs>
|
||||||
|
</item>
|
||||||
|
</blockDeviceMapping>
|
||||||
|
<monitoring>
|
||||||
|
<enabled>false</enabled>
|
||||||
|
</monitoring>
|
||||||
|
</launchSpecification>
|
||||||
|
<createTime>2011-03-08T03:30:36.000Z</createTime>
|
||||||
|
<productDescription>Linux/UNIX</productDescription>
|
||||||
|
</item>
|
||||||
|
</spotInstanceRequestSet>
|
||||||
|
</RequestSpotInstancesResponse>
|
|
@ -0,0 +1,93 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<RequestSpotInstancesResponse xmlns="http://ec2.amazonaws.com/doc/2010-11-15/">
|
||||||
|
<requestId>2ffc645f-6835-4d23-bd18-f6f53c253067</requestId>
|
||||||
|
<spotInstanceRequestSet>
|
||||||
|
<item>
|
||||||
|
<spotInstanceRequestId>sir-7c74f805</spotInstanceRequestId>
|
||||||
|
<spotPrice>0.001000</spotPrice>
|
||||||
|
<type>one-time</type>
|
||||||
|
<state>open</state>
|
||||||
|
<launchSpecification>
|
||||||
|
<imageId>ami-595a0a1c</imageId>
|
||||||
|
<groupSet>
|
||||||
|
<item>
|
||||||
|
<groupId>default</groupId>
|
||||||
|
</item>
|
||||||
|
</groupSet>
|
||||||
|
<instanceType>t1.micro</instanceType>
|
||||||
|
<blockDeviceMapping>
|
||||||
|
<item>
|
||||||
|
<deviceName>/dev/sda1</deviceName>
|
||||||
|
<ebs>
|
||||||
|
<volumeSize>120</volumeSize>
|
||||||
|
<deleteOnTermination>true</deleteOnTermination>
|
||||||
|
</ebs>
|
||||||
|
</item>
|
||||||
|
</blockDeviceMapping>
|
||||||
|
<monitoring>
|
||||||
|
<enabled>false</enabled>
|
||||||
|
</monitoring>
|
||||||
|
</launchSpecification>
|
||||||
|
<createTime>2011-03-08T02:36:32.000Z</createTime>
|
||||||
|
<productDescription>Linux/UNIX</productDescription>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<spotInstanceRequestId>sir-78ca7605</spotInstanceRequestId>
|
||||||
|
<spotPrice>0.001000</spotPrice>
|
||||||
|
<type>one-time</type>
|
||||||
|
<state>open</state>
|
||||||
|
<launchSpecification>
|
||||||
|
<imageId>ami-595a0a1c</imageId>
|
||||||
|
<groupSet>
|
||||||
|
<item>
|
||||||
|
<groupId>default</groupId>
|
||||||
|
</item>
|
||||||
|
</groupSet>
|
||||||
|
<instanceType>t1.micro</instanceType>
|
||||||
|
<blockDeviceMapping>
|
||||||
|
<item>
|
||||||
|
<deviceName>/dev/sda1</deviceName>
|
||||||
|
<ebs>
|
||||||
|
<volumeSize>120</volumeSize>
|
||||||
|
<deleteOnTermination>true</deleteOnTermination>
|
||||||
|
</ebs>
|
||||||
|
</item>
|
||||||
|
</blockDeviceMapping>
|
||||||
|
<monitoring>
|
||||||
|
<enabled>false</enabled>
|
||||||
|
</monitoring>
|
||||||
|
</launchSpecification>
|
||||||
|
<createTime>2011-03-08T02:36:32.000Z</createTime>
|
||||||
|
<productDescription>Linux/UNIX</productDescription>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<spotInstanceRequestId>sir-7e0f6005</spotInstanceRequestId>
|
||||||
|
<spotPrice>0.001000</spotPrice>
|
||||||
|
<type>one-time</type>
|
||||||
|
<state>open</state>
|
||||||
|
<launchSpecification>
|
||||||
|
<imageId>ami-595a0a1c</imageId>
|
||||||
|
<groupSet>
|
||||||
|
<item>
|
||||||
|
<groupId>default</groupId>
|
||||||
|
</item>
|
||||||
|
</groupSet>
|
||||||
|
<instanceType>t1.micro</instanceType>
|
||||||
|
<blockDeviceMapping>
|
||||||
|
<item>
|
||||||
|
<deviceName>/dev/sda1</deviceName>
|
||||||
|
<ebs>
|
||||||
|
<volumeSize>120</volumeSize>
|
||||||
|
<deleteOnTermination>true</deleteOnTermination>
|
||||||
|
</ebs>
|
||||||
|
</item>
|
||||||
|
</blockDeviceMapping>
|
||||||
|
<monitoring>
|
||||||
|
<enabled>false</enabled>
|
||||||
|
</monitoring>
|
||||||
|
</launchSpecification>
|
||||||
|
<createTime>2011-03-08T02:36:32.000Z</createTime>
|
||||||
|
<productDescription>Linux/UNIX</productDescription>
|
||||||
|
</item>
|
||||||
|
</spotInstanceRequestSet>
|
||||||
|
</RequestSpotInstancesResponse>
|
|
@ -21,8 +21,6 @@ package org.jclouds.cloudstack.predicates;
|
||||||
|
|
||||||
import static com.google.common.base.Preconditions.checkNotNull;
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
|
|
||||||
import java.util.concurrent.ExecutionException;
|
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
import javax.inject.Singleton;
|
import javax.inject.Singleton;
|
||||||
|
|
||||||
|
@ -31,7 +29,6 @@ import org.jclouds.cloudstack.domain.AsyncJob;
|
||||||
import org.jclouds.logging.Logger;
|
import org.jclouds.logging.Logger;
|
||||||
|
|
||||||
import com.google.common.base.Predicate;
|
import com.google.common.base.Predicate;
|
||||||
import com.google.common.base.Throwables;
|
|
||||||
import com.google.inject.Inject;
|
import com.google.inject.Inject;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -60,10 +57,8 @@ public class JobComplete implements Predicate<Long> {
|
||||||
return false;
|
return false;
|
||||||
logger.trace("%s: looking for job status %s: currently: %s", job.getId(), 1, job.getStatus());
|
logger.trace("%s: looking for job status %s: currently: %s", job.getId(), 1, job.getStatus());
|
||||||
if (job.getError() != null)
|
if (job.getError() != null)
|
||||||
Throwables.propagate(new ExecutionException(String.format("job %s failed with exception %s", job.getId(), job
|
throw new IllegalStateException(String.format("job %s failed with exception %s", job.getId(), job.getError()
|
||||||
.getError().toString())) {
|
.toString()));
|
||||||
private static final long serialVersionUID = 4371112085613620239L;
|
|
||||||
});
|
|
||||||
return job.getStatus() > 0;
|
return job.getStatus() > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue