diff --git a/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/compute/AWSEC2TemplateOptions.java b/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/compute/AWSEC2TemplateOptions.java index 943a612980..760a0aa9b5 100644 --- a/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/compute/AWSEC2TemplateOptions.java +++ b/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/compute/AWSEC2TemplateOptions.java @@ -22,6 +22,8 @@ import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkState; import static com.google.common.base.Strings.emptyToNull; +import java.util.Calendar; +import java.util.Date; import java.util.Map; import java.util.Set; @@ -217,7 +219,10 @@ public class AWSEC2TemplateOptions extends EC2TemplateOptions implements Cloneab * Options for starting spot instances */ public AWSEC2TemplateOptions spotOptions(RequestSpotInstancesOptions spotOptions) { - this.spotOptions = spotOptions != null ? spotOptions : RequestSpotInstancesOptions.NONE; + Calendar cal = Calendar.getInstance(); + cal.setTime(new Date()); + cal.add(Calendar.MINUTE, 30); + this.spotOptions = spotOptions != null ? spotOptions : RequestSpotInstancesOptions.Builder.validUntil(cal.getTime()); return this; } diff --git a/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/domain/SpotInstanceRequest.java b/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/domain/SpotInstanceRequest.java index 58f5819cab..6ccf36ff96 100644 --- a/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/domain/SpotInstanceRequest.java +++ b/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/domain/SpotInstanceRequest.java @@ -21,12 +21,11 @@ import static com.google.common.base.Preconditions.checkNotNull; import java.util.Date; import java.util.Map; -import org.jclouds.javax.annotation.Nullable; - import com.google.common.base.CaseFormat; import com.google.common.base.Strings; import com.google.common.collect.ImmutableMap; import com.google.common.collect.Maps; +import org.jclouds.javax.annotation.Nullable; public class SpotInstanceRequest implements Comparable { public static Builder builder() { @@ -51,6 +50,9 @@ public class SpotInstanceRequest implements Comparable { private Type type; private Date validFrom; private Date validUntil; + private String statusCode; + private String statusMessage; + private Date statusUpdateTime; private Map tags = Maps.newLinkedHashMap(); public Builder clear() { @@ -71,6 +73,9 @@ public class SpotInstanceRequest implements Comparable { this.type = null; this.validFrom = null; this.validUntil = null; + this.statusCode = null; + this.statusMessage = null; + this.statusUpdateTime = null; tags = Maps.newLinkedHashMap(); return this; } @@ -170,10 +175,25 @@ public class SpotInstanceRequest implements Comparable { return this; } + public Builder statusCode(String statusCode) { + this.statusCode = statusCode; + return this; + } + + public Builder statusMessage(String statusMessage) { + this.statusMessage = statusMessage; + return this; + } + + public Builder statusUpdateTime(Date statusUpdateTime) { + this.statusUpdateTime = statusUpdateTime; + return this; + } + public SpotInstanceRequest build() { return new SpotInstanceRequest(region, availabilityZoneGroup, launchedAvailabilityZone, createTime, faultCode, faultMessage, instanceId, launchGroup, launchSpecification, productDescription, id, spotPrice, state, - rawState, type, validFrom, validUntil, tags); + rawState, type, validFrom, validUntil, statusCode, statusMessage, statusUpdateTime, tags); } } @@ -236,12 +256,16 @@ public class SpotInstanceRequest implements Comparable { private final Type type; private final Date validFrom; private final Date validUntil; + private final String statusCode; + private final String statusMessage; + private final Date statusUpdateTime; private final Map tags; public SpotInstanceRequest(String region, String availabilityZoneGroup, @Nullable String launchedAvailabilityZone, Date createTime, String faultCode, String faultMessage, String instanceId, String launchGroup, LaunchSpecification launchSpecification, String productDescription, String id, float spotPrice, - State state, String rawState, Type type, Date validFrom, Date validUntil, Map tags) { + State state, String rawState, Type type, Date validFrom, Date validUntil, String statusCode, + String statusMessage, Date statusUpdateTime, Map tags) { this.region = checkNotNull(region, "region"); this.availabilityZoneGroup = availabilityZoneGroup; this.launchedAvailabilityZone = launchedAvailabilityZone; @@ -259,6 +283,9 @@ public class SpotInstanceRequest implements Comparable { this.type = checkNotNull(type, "type"); this.validFrom = validFrom; this.validUntil = validUntil; + this.statusCode = statusCode; + this.statusMessage = statusMessage; + this.statusUpdateTime = statusUpdateTime; this.tags = ImmutableMap. copyOf(checkNotNull(tags, "tags")); } @@ -333,6 +360,18 @@ public class SpotInstanceRequest implements Comparable { return validUntil; } + public String getStatusCode() { + return statusCode; + } + + public String getStatusMessage() { + return statusMessage; + } + + public Date getStatusUpdateTime() { + return statusUpdateTime; + } + /** * tags that are present in the instance */ @@ -360,6 +399,9 @@ public class SpotInstanceRequest implements Comparable { result = prime * result + ((type == null) ? 0 : type.hashCode()); result = prime * result + ((validFrom == null) ? 0 : validFrom.hashCode()); result = prime * result + ((validUntil == null) ? 0 : validUntil.hashCode()); + result = prime * result + ((statusCode == null) ? 0 : statusCode.hashCode()); + result = prime * result + ((statusMessage == null) ? 0 : statusMessage.hashCode()); + result = prime * result + ((statusUpdateTime == null) ? 0 : statusUpdateTime.hashCode()); result = prime * result + ((tags == null) ? 0 : tags.hashCode()); return result; } @@ -444,6 +486,21 @@ public class SpotInstanceRequest implements Comparable { return false; } else if (!validUntil.equals(other.validUntil)) return false; + if (statusCode == null) { + if (other.statusCode != null) + return false; + } else if (!statusCode.equals(other.statusCode)) + return false; + if (statusMessage == null) { + if (other.statusMessage != null) + return false; + } else if (!statusMessage.equals(other.statusMessage)) + return false; + if (statusUpdateTime == null) { + if (other.statusUpdateTime != null) + return false; + } else if (!statusUpdateTime.equals(other.statusUpdateTime)) + return false; if (tags == null) { if (other.tags != null) return false; @@ -459,7 +516,8 @@ public class SpotInstanceRequest implements Comparable { + faultMessage + ", instanceId=" + instanceId + ", launchGroup=" + launchGroup + ", launchSpecification=" + launchSpecification + ", productDescription=" + productDescription + ", id=" + id + ", spotPrice=" + spotPrice + ", state=" + rawState + ", type=" + type + ", validFrom=" + validFrom + ", validUntil=" - + validUntil + ", tags=" + tags + "]"; + + validUntil + ", statusCode=" + statusCode + ", statusMessage=" + statusMessage + ", statusUpdateTime=" + + statusUpdateTime + ", tags=" + tags + "]"; } @Override diff --git a/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/xml/SpotInstanceHandler.java b/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/xml/SpotInstanceHandler.java index 2c940ec438..87ad3706d1 100644 --- a/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/xml/SpotInstanceHandler.java +++ b/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/xml/SpotInstanceHandler.java @@ -40,6 +40,8 @@ public class SpotInstanceHandler extends ParseSax.HandlerForGeneratedRequestWith protected final DateCodec dateCodec; protected final Supplier defaultRegion; protected final Builder builder; + protected boolean inFault; + protected boolean inStatus; protected boolean inLaunchSpecification; protected final LaunchSpecificationHandler launchSpecificationHandler; protected boolean inTagSet; @@ -73,6 +75,10 @@ public class SpotInstanceHandler extends ParseSax.HandlerForGeneratedRequestWith inLaunchSpecification = true; } else if (equalsOrSuffix(qName, "tagSet")) { inTagSet = true; + } else if (equalsOrSuffix(qName, "fault")) { + inFault = true; + } else if (equalsOrSuffix(qName, "status")) { + inStatus = true; } if (inLaunchSpecification) { launchSpecificationHandler.startElement(uri, name, qName, attrs); @@ -97,6 +103,14 @@ public class SpotInstanceHandler extends ParseSax.HandlerForGeneratedRequestWith launchSpecificationHandler.endElement(uri, name, qName); } + if (qName.equals("fault")) { + inFault = false; + } + + if (qName.equals("status")) { + inStatus = false; + } + if (qName.equals("spotInstanceRequestId")) { builder.id(currentOrNull(currentText)); } else if (qName.equals("instanceId")) { @@ -107,10 +121,6 @@ public class SpotInstanceHandler extends ParseSax.HandlerForGeneratedRequestWith builder.availabilityZoneGroup(currentOrNull(currentText)); } else if (qName.equals("launchGroup")) { builder.launchGroup(currentOrNull(currentText)); - } else if (qName.equals("code")) { - builder.faultCode(currentOrNull(currentText)); - } else if (qName.equals("message")) { - builder.faultMessage(currentOrNull(currentText)); } else if (qName.equals("spotPrice")) { String price = currentOrNull(currentText); if (price != null) @@ -131,6 +141,30 @@ public class SpotInstanceHandler extends ParseSax.HandlerForGeneratedRequestWith builder.createTime(dateCodec.toDate(createTime)); } else if (qName.equals("productDescription")) { builder.productDescription(currentOrNull(currentText)); + } else if (inFault) { + if (qName.equals("code")) { + builder.faultCode(currentOrNull(currentText)); + } else if (qName.equals("message")) { + builder.faultMessage(currentOrNull(currentText)); + } + } else if (inStatus) { + if (qName.equals("code")) { + builder.statusCode(currentOrNull(currentText)); + } else if (qName.equals("message")) { + builder.statusMessage(currentOrNull(currentText)); + } else if (qName.equals("updateTime")) { + String updateTime = currentOrNull(currentText); + if (updateTime != null) + builder.statusUpdateTime(dateCodec.toDate(updateTime)); + } + } else if (qName.equals("validFrom")) { + String validFrom = currentOrNull(currentText); + if (validFrom != null) + builder.validFrom(dateCodec.toDate(validFrom)); + } else if (qName.equals("validUntil")) { + String validUntil = currentOrNull(currentText); + if (validUntil != null) + builder.validUntil(dateCodec.toDate(validUntil)); } currentText.setLength(0); } diff --git a/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/xml/SpotInstanceHandlerTest.java b/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/xml/SpotInstanceHandlerTest.java index ff5f230c12..757b9f4a25 100644 --- a/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/xml/SpotInstanceHandlerTest.java +++ b/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/xml/SpotInstanceHandlerTest.java @@ -77,6 +77,11 @@ public class SpotInstanceHandlerTest extends BaseEC2HandlerTest { .type(Type.ONE_TIME) .state(State.OPEN) .rawState("open") + .statusCode("pending-fulfillment") + .statusMessage("Pending fulfillment") + .statusUpdateTime(new SimpleDateFormatDateService().iso8601DateParse("2011-03-08T03:30:36.000Z")) + .validFrom(new SimpleDateFormatDateService().iso8601DateParse("2011-03-08T03:30:36.000Z")) + .validUntil(new SimpleDateFormatDateService().iso8601DateParse("2011-03-08T03:30:36.000Z")) .launchSpecification( LaunchSpecification.builder().imageId("ami-595a0a1c").securityGroupIdToName("sg-83e1c4ea", "default") .instanceType("m1.large").mapNewVolumeToDevice("/dev/sda1", 1, true) @@ -110,6 +115,9 @@ public class SpotInstanceHandlerTest extends BaseEC2HandlerTest { .type(Type.ONE_TIME) .state(State.ACTIVE) .rawState("active") + .statusCode("fulfilled") + .statusMessage("Fulfilled") + .statusUpdateTime(new SimpleDateFormatDateService().iso8601DateParse("2011-07-29T05:27:39.000Z")) .launchedAvailabilityZone("us-east-1b") .launchSpecification( LaunchSpecification.builder().imageId("ami-8e1fece7") @@ -117,6 +125,8 @@ public class SpotInstanceHandlerTest extends BaseEC2HandlerTest { .instanceType("t1.micro").monitoringEnabled(false).keyName("jclouds#adriancole-ec2unssh") .build()) .createTime(new SimpleDateFormatDateService().iso8601DateParse("2011-07-29T05:27:39.000Z")) + .validFrom(new SimpleDateFormatDateService().iso8601DateParse("2011-07-29T05:27:39.000Z")) + .validUntil(new SimpleDateFormatDateService().iso8601DateParse("2011-07-29T05:27:39.000Z")) .productDescription("Linux/UNIX") .tag("Name", "ec2-o") .tag("Spot", "spot-value") diff --git a/providers/aws-ec2/src/test/resources/describe_spot_instance.xml b/providers/aws-ec2/src/test/resources/describe_spot_instance.xml index 964b246b81..c97f5657ab 100644 --- a/providers/aws-ec2/src/test/resources/describe_spot_instance.xml +++ b/providers/aws-ec2/src/test/resources/describe_spot_instance.xml @@ -23,7 +23,14 @@ i-ef308e8e + + fulfilled + Fulfilled + 2011-07-29T05:27:39.000Z + 2011-07-29T05:27:39.000Z + 2011-07-29T05:27:39.000Z + 2011-07-29T05:27:39.000Z Linux/UNIX diff --git a/providers/aws-ec2/src/test/resources/request_spot_instances-ebs.xml b/providers/aws-ec2/src/test/resources/request_spot_instances-ebs.xml index 7f64608823..5569f67c76 100644 --- a/providers/aws-ec2/src/test/resources/request_spot_instances-ebs.xml +++ b/providers/aws-ec2/src/test/resources/request_spot_instances-ebs.xml @@ -45,7 +45,14 @@ Webserver + + pending-fulfillment + Pending fulfillment + 2011-03-08T03:30:36.000Z + 2011-03-08T03:30:36.000Z + 2011-03-08T03:30:36.000Z + 2011-03-08T03:30:36.000Z Linux/UNIX