started code for ec2 spot instances

This commit is contained in:
Adrian Cole 2011-03-07 00:58:50 -05:00
parent ebd4d1e432
commit ab46268ca2
17 changed files with 1811 additions and 2 deletions

View File

@ -21,6 +21,7 @@ package org.jclouds.ec2.binders;
import static com.google.common.base.Preconditions.checkArgument;
import javax.inject.Inject;
import javax.inject.Singleton;
import org.jclouds.http.HttpRequest;
@ -34,11 +35,22 @@ import org.jclouds.rest.Binder;
*/
@Singleton
public class IfNotNullBindAvailabilityZoneToFormParam implements Binder {
private final String param;
@Inject
protected IfNotNullBindAvailabilityZoneToFormParam() {
this("Placement.AvailabilityZone");
}
protected IfNotNullBindAvailabilityZoneToFormParam(String param) {
this.param = param;
}
@Override
public <R extends HttpRequest> R bindToRequest(R request, Object input) {
if (input != null) {
checkArgument(input instanceof String, "this binder is only valid for AvailabilityZone!");
return ModifyRequest.addFormParam(request, "Placement.AvailabilityZone", (String) input);
checkArgument(input instanceof String, "this binder is only valid for String!");
return ModifyRequest.addFormParam(request, param, (String) input);
}
return request;
}

View File

@ -24,6 +24,7 @@ import org.jclouds.aws.ec2.services.AWSInstanceAsyncClient;
import org.jclouds.aws.ec2.services.AWSKeyPairAsyncClient;
import org.jclouds.aws.ec2.services.MonitoringAsyncClient;
import org.jclouds.aws.ec2.services.PlacementGroupAsyncClient;
import org.jclouds.aws.ec2.services.SpotInstanceAsyncClient;
import org.jclouds.ec2.EC2AsyncClient;
import org.jclouds.rest.annotations.Delegate;
@ -67,4 +68,10 @@ public interface AWSEC2AsyncClient extends EC2AsyncClient {
@Delegate
@Override
AWSKeyPairAsyncClient getKeyPairServices();
/**
* Provides asynchronous access to SpotInstance services.
*/
@Delegate
SpotInstanceAsyncClient getSpotInstanceServices();
}

View File

@ -26,6 +26,7 @@ import org.jclouds.aws.ec2.services.AWSInstanceClient;
import org.jclouds.aws.ec2.services.AWSKeyPairClient;
import org.jclouds.aws.ec2.services.MonitoringClient;
import org.jclouds.aws.ec2.services.PlacementGroupClient;
import org.jclouds.aws.ec2.services.SpotInstanceClient;
import org.jclouds.concurrent.Timeout;
import org.jclouds.ec2.EC2Client;
import org.jclouds.rest.annotations.Delegate;
@ -70,4 +71,10 @@ public interface AWSEC2Client extends EC2Client {
@Delegate
@Override
AWSKeyPairClient getKeyPairServices();
/**
* Provides synchronous access to SpotInstance services.
*/
@Delegate
SpotInstanceClient getSpotInstanceServices();
}

View File

@ -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);
}
}

View File

@ -0,0 +1,21 @@
package org.jclouds.aws.ec2.binders;
import javax.inject.Inject;
import javax.inject.Singleton;
import org.jclouds.ec2.binders.IfNotNullBindAvailabilityZoneToFormParam;
/**
* Binds the AvailabilityZone to a form parameter if set.
*
* @author Adrian Cole
*/
@Singleton
public class IfNotNullBindAvailabilityZoneToLaunchSpecificationFormParam extends IfNotNullBindAvailabilityZoneToFormParam {
@Inject
protected IfNotNullBindAvailabilityZoneToLaunchSpecificationFormParam() {
super("LaunchSpecification.Placement.AvailabilityZone");
}
}

View File

@ -37,6 +37,8 @@ import org.jclouds.aws.ec2.services.MonitoringAsyncClient;
import org.jclouds.aws.ec2.services.MonitoringClient;
import org.jclouds.aws.ec2.services.PlacementGroupAsyncClient;
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.EC2Client;
import org.jclouds.ec2.config.EC2RestClientModule;
@ -82,6 +84,7 @@ public class AWSEC2RestClientModule extends EC2RestClientModule<AWSEC2Client, AW
.put(WindowsClient.class, WindowsAsyncClient.class)//
.put(AvailabilityZoneAndRegionClient.class, AvailabilityZoneAndRegionAsyncClient.class)//
.put(ElasticBlockStoreClient.class, ElasticBlockStoreAsyncClient.class)//
.put(SpotInstanceClient.class, SpotInstanceAsyncClient.class)//
.build();
public AWSEC2RestClientModule() {

View File

@ -0,0 +1,348 @@
/**
*
* 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 fault;
private String instanceId;
private String launchGroup;
private String launchSpecification;
private String productDescription;
private String id;
private float spotPrice;
private String state;
private Type type;
private Date validFrom;
private Date validUntil;
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 fault(String fault) {
this.fault = fault;
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(String 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(String 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, fault, 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;
}
}
}
private final String region;
private final String availabilityZoneGroup;
private final Date createTime;
private final String fault;
private final String instanceId;
private final String launchGroup;
private final String launchSpecification;
private final String productDescription;
private final String id;
private final float spotPrice;
private final String state;
private final Type type;
private final Date validFrom;
private final Date validUntil;
public SpotInstanceRequest(String region, String availabilityZoneGroup, Date createTime, String fault,
String instanceId, String launchGroup, String launchSpecification, String productDescription, String id,
float spotPrice, String state, Type type, Date validFrom, Date validUntil) {
this.region = checkNotNull(region, "region");
this.availabilityZoneGroup = availabilityZoneGroup;
this.createTime = createTime;
this.fault = fault;
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 getFault() {
return fault;
}
public String getInstanceId() {
return instanceId;
}
public String getLaunchGroup() {
return launchGroup;
}
public String getLaunchSpecification() {
return launchSpecification;
}
public String getProductDescription() {
return productDescription;
}
public String getId() {
return id;
}
public float getSpotPrice() {
return spotPrice;
}
public String 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 + ((fault == null) ? 0 : fault.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 (fault == null) {
if (other.fault != null)
return false;
} else if (!fault.equals(other.fault))
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 + ", fault=" + fault
+ ", 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);
}
}

View File

@ -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);
}
}
}

View File

@ -0,0 +1,163 @@
/**
*
* 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 java.util.Map.Entry;
import org.jclouds.aws.ec2.domain.SpotInstanceRequest;
import org.jclouds.date.DateService;
import org.jclouds.date.internal.SimpleDateFormatDateService;
import org.jclouds.ec2.options.RunInstancesOptions;
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;
}
/**
* 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 launchSpecification(RunInstancesOptions launchSpecification) {
for (Entry<String, String> entry : checkNotNull(launchSpecification, "launchSpecification").buildFormParameters()
.entries()) {
formParameters.put("LaunchSpecification." + entry.getKey(), entry.getValue());
}
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);
}
/**
* @see RequestSpotInstancesOptions#launchSpecification
*/
public static RequestSpotInstancesOptions launchSpecification(RunInstancesOptions launchSpecification) {
RequestSpotInstancesOptions options = new RequestSpotInstancesOptions();
return options.launchSpecification(launchSpecification);
}
}
}

View File

@ -0,0 +1,98 @@
/**
*
* 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 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.BindSpotInstanceRequestIdsToIndexedFormParams;
import org.jclouds.aws.ec2.binders.IfNotNullBindAvailabilityZoneToLaunchSpecificationFormParam;
import org.jclouds.aws.ec2.options.DescribeSpotPriceHistoryOptions;
import org.jclouds.aws.ec2.options.RequestSpotInstancesOptions;
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.FormParams;
import org.jclouds.rest.annotations.RequestFilters;
import org.jclouds.rest.annotations.VirtualHost;
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")
ListenableFuture<String> describeSpotInstanceRequestsInRegion(
@EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
@BinderParam(BindSpotInstanceRequestIdsToIndexedFormParams.class) String... requestIds);
/**
* @see SpotInstanceClient#requestSpotInstancesInRegion
*/
@POST
@Path("/")
@FormParams(keys = ACTION, values = "RequestSpotInstances")
ListenableFuture<String> requestSpotInstancesInRegion(
@EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
@Nullable @BinderParam(IfNotNullBindAvailabilityZoneToLaunchSpecificationFormParam.class) String nullableAvailabilityZone,
@FormParam("LaunchSpecification.ImageId") String imageId,@FormParam("InstanceCount") int instanceCount, @FormParam("SpotPrice") float spotPrice,
RequestSpotInstancesOptions... options);
/**
* @see SpotInstanceClient#describeSpotPriceHistoryInRegion
*/
@POST
@Path("/")
@FormParams(keys = ACTION, values = "DescribeSpotPriceHistory")
ListenableFuture<String> describeSpotPriceHistoryInRegion(
@EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
DescribeSpotPriceHistoryOptions... options);
/**
* @see SpotInstanceClient#cancelSpotInstanceRequestsInRegion
*/
@POST
@Path("/")
@FormParams(keys = ACTION, values = "CancelSpotInstanceRequests")
ListenableFuture<String> cancelSpotInstanceRequestsInRegion(
@EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
@BinderParam(BindSpotInstanceRequestIdsToIndexedFormParams.class) String... requestIds);
}

View File

@ -0,0 +1,139 @@
/**
*
* 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.concurrent.TimeUnit;
import javax.annotation.Nullable;
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
*/
String describeSpotInstanceRequestsInRegion(@Nullable String region, String... requestIds);
/**
* 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 nullableAvailabilityZone
* The availability zone to launch the instances in, or null to let the system choose
* @param imageId
* The AMI ID.
* @param instanceCount
* The maximum number of Spot Instances to launch.
* @param spotPrice
* Specifies the maximum hourly price for any Spot Instance launched to fulfill the
* request.
* @param options
* control the duration of the request, grouping, and the size and parameters of the
* server to run
*
* @see #describeSpotInstanceRequestsInRegion
* @see #cancelSpotInstanceRequestsInRegion
* @see #describeSpotPriceHistoryInRegion
* @see <a href=
* "http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-RequestSpotInstances.html"
* />
* @return TODO
*/
String requestSpotInstancesInRegion(@Nullable String region, @Nullable String nullableAvailabilityZone,
String imageId, int instanceCount, float spotPrice, 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
*/
String 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);
}

View File

@ -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.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.Sets;
/**
* @author Adrian Cole
*/
//TODO finish
public class DescribeSpotInstanceRequestsResponseHandler extends
ParseSax.HandlerWithResult<Set<SpotInstanceRequest>> {
private Set<SpotInstanceRequest> spotRequests = Sets.newLinkedHashSet();
private final SpotInstanceRequestHandler spotRequestHandler;
@Inject
public DescribeSpotInstanceRequestsResponseHandler(SpotInstanceRequestHandler spotRequestHandler) {
this.spotRequestHandler = spotRequestHandler;
}
public Set<SpotInstanceRequest> getResult() {
return spotRequests;
}
@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"))
spotRequestHandler.startElement(uri, localName, qName, attributes);
}
@Override
public void endElement(String uri, String localName, String qName) throws SAXException {
if (qName.equals("item")) {
spotRequests.add(spotRequestHandler.getResult());
}
spotRequestHandler.endElement(uri, localName, qName);
}
public void characters(char ch[], int start, int length) {
spotRequestHandler.characters(ch, start, length);
}
}

View File

@ -0,0 +1,97 @@
/**
*
* 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.Date;
import javax.inject.Inject;
import org.jclouds.aws.ec2.domain.SpotInstanceRequest;
import org.jclouds.aws.ec2.domain.SpotInstanceRequest.Type;
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
*/
// TODO finish
public class SpotInstanceRequestHandler extends ParseSax.HandlerForGeneratedRequestWithResult<SpotInstanceRequest> {
private StringBuilder currentText = new StringBuilder();
@Inject
protected DateService dateService;
@Inject
@Region
private String defaultRegion;
private String availabilityZoneGroup;
private Date createTime;
private String fault;
private String instanceId;
private String launchGroup;
private String launchSpecification;
private String productDescription;
private String id;
private float spotPrice;
private String state;
private Type type;
private Date validFrom;
private Date validUntil;
public SpotInstanceRequest getResult() {
String region = AWSUtils.findRegionInArgsOrNull(getRequest());
if (region == null)
region = defaultRegion;
SpotInstanceRequest returnVal = new SpotInstanceRequest(region, availabilityZoneGroup, createTime, fault,
instanceId, launchGroup, launchSpecification, productDescription, id, spotPrice, state, type, validFrom,
validUntil);
this.availabilityZoneGroup = null;
this.createTime = null;
this.fault = null;
this.instanceId = null;
this.launchGroup = null;
this.launchSpecification = null;
this.productDescription = null;
this.id = null;
this.spotPrice = -1;
this.state = null;
this.type = null;
this.validFrom = null;
this.validUntil = null;
return returnVal;
}
public void endElement(String uri, String name, String qName) {
if (qName.equals("availabilityZoneGroup")) {
this.availabilityZoneGroup = currentText.toString().trim();
} else if (qName.equals("createTime")) {
createTime = this.dateService.iso8601DateParse(currentText.toString().trim());
} else if (qName.equals("type")) {
type = SpotInstanceRequest.Type.fromValue(currentText.toString().trim());
}
currentText = new StringBuilder();
}
public void characters(char ch[], int start, int length) {
currentText.append(ch, start, length);
}
}

View File

@ -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);
}
}

View File

@ -0,0 +1,179 @@
/**
*
* 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.launchSpecification;
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.ec2.domain.BlockDeviceMapping;
import org.jclouds.ec2.options.RunInstancesOptions;
import org.jclouds.http.options.HttpRequestOptions;
import org.testng.annotations.Test;
import com.google.common.collect.ImmutableSet;
/**
* 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);
}
RunInstancesOptions launchSpec = new RunInstancesOptions().withBlockDeviceMappings(ImmutableSet
.<BlockDeviceMapping> of(new BlockDeviceMapping.MapNewVolumeToDevice("/dev/sda1", 120, true)));
@Test
public void testLaunchSpecification() {
RequestSpotInstancesOptions options = new RequestSpotInstancesOptions();
options.launchSpecification(launchSpec);
verifyLaunchSpec(options);
}
protected void verifyLaunchSpec(RequestSpotInstancesOptions options) {
assertEquals(options.buildFormParameters().get("LaunchSpecification.BlockDeviceMapping.1.DeviceName"),
Collections.singletonList("/dev/sda1"));
assertEquals(options.buildFormParameters().get("LaunchSpecification.BlockDeviceMapping.1.Ebs.VolumeSize"),
Collections.singletonList("120"));
assertEquals(options.buildFormParameters()
.get("LaunchSpecification.BlockDeviceMapping.1.Ebs.DeleteOnTermination"), Collections.singletonList("true"));
}
@Test
public void testLaunchSpecificationStatic() {
RequestSpotInstancesOptions options = launchSpecification(launchSpec);
verifyLaunchSpec(options);
}
@Test(expectedExceptions = NullPointerException.class)
public void testLaunchSpecificationNPE() {
launchSpecification(null);
}
}

View File

@ -0,0 +1,194 @@
/**
*
* 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.options.DescribeSpotPriceHistoryOptions;
import org.jclouds.aws.ec2.options.RequestSpotInstancesOptions;
import org.jclouds.ec2.options.RunInstancesOptions;
import org.jclouds.http.HttpRequest;
import org.jclouds.http.functions.ReturnStringIf2xx;
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 testRequestSpotInstances() throws SecurityException, NoSuchMethodException, IOException {
Method method = SpotInstanceAsyncClient.class.getMethod("requestSpotInstancesInRegion", String.class,
String.class, String.class, int.class, float.class, RequestSpotInstancesOptions[].class);
HttpRequest request = processor.createRequest(method, null, null, "ami-voo", 1, 0.01);
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=ami-voo&InstanceCount=1&SpotPrice=0.01",
"application/x-www-form-urlencoded", false);
assertResponseParserClassEquals(method, request, ReturnStringIf2xx.class);
assertSaxResponseParserClassEquals(method, null);
assertExceptionParserClassEquals(method, null);
checkFilters(request);
}
public void testRequestSpotInstancesOptions() throws SecurityException, NoSuchMethodException, IOException {
Method method = SpotInstanceAsyncClient.class.getMethod("requestSpotInstancesInRegion", String.class,
String.class, String.class, int.class, float.class, RequestSpotInstancesOptions[].class);
HttpRequest request = processor.createRequest(
method,
"eu-west-1",
"eu-west-1a",
"ami-voo",
1,
0.01,
new RequestSpotInstancesOptions()
.validFrom(from)
.validUntil(to)
.availabilityZoneGroup("availabilityZoneGroup")
.launchGroup("launchGroup")
.launchSpecification(
RunInstancesOptions.Builder.withKernelId("kernelId").withSecurityGroups("group1", "group2")));
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&LaunchSpecification.ImageId=ami-voo&InstanceCount=1&SpotPrice=0.01&ValidFrom=1970-05-23T21%3A21%3A18.910Z&ValidUntil=2009-02-13T23%3A31%3A31.011Z&AvailabilityZoneGroup=availabilityZoneGroup&LaunchGroup=launchGroup&LaunchSpecification.KernelId=kernelId&LaunchSpecification.SecurityGroup.1=group1&LaunchSpecification.SecurityGroup.2=group2&LaunchSpecification.Placement.AvailabilityZone=eu-west-1a",
"application/x-www-form-urlencoded", false);
assertResponseParserClassEquals(method, request, ReturnStringIf2xx.class);
assertSaxResponseParserClassEquals(method, null);
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, ReturnStringIf2xx.class);
assertSaxResponseParserClassEquals(method, null);
assertExceptionParserClassEquals(method, null);
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, ReturnStringIf2xx.class);
assertSaxResponseParserClassEquals(method, null);
assertExceptionParserClassEquals(method, null);
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, ReturnStringIf2xx.class);
assertSaxResponseParserClassEquals(method, null);
assertExceptionParserClassEquals(method, null);
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, ReturnStringIf2xx.class);
assertSaxResponseParserClassEquals(method, null);
assertExceptionParserClassEquals(method, null);
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, ReturnStringIf2xx.class);
assertSaxResponseParserClassEquals(method, null);
assertExceptionParserClassEquals(method, null);
checkFilters(request);
}
@Override
protected TypeLiteral<RestAnnotationProcessor<SpotInstanceAsyncClient>> createTypeLiteral() {
return new TypeLiteral<RestAnnotationProcessor<SpotInstanceAsyncClient>>() {
};
}
}

View File

@ -0,0 +1,181 @@
/**
*
* 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 org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNotNull;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Properties;
import java.util.SortedSet;
import org.jclouds.Constants;
import org.jclouds.aws.domain.Region;
import org.jclouds.aws.ec2.AWSEC2Client;
import org.jclouds.aws.ec2.domain.SpotInstanceRequest;
import org.jclouds.aws.ec2.options.AWSRunInstancesOptions;
import org.jclouds.aws.ec2.options.RequestSpotInstancesOptions;
import org.jclouds.compute.ComputeServiceContext;
import org.jclouds.compute.ComputeServiceContextFactory;
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.common.collect.Iterables;
import com.google.inject.Module;
/**
* Tests behavior of {@code SpotInstanceClient}
*
* @author Adrian Cole
*/
@Test(groups = "live", sequential = true)
public class SpotInstanceClientLiveTest {
private AWSEC2Client client;
private ComputeServiceContext context;
private RetryablePredicate<SpotInstanceRequest> availableTester;
private RetryablePredicate<SpotInstanceRequest> deletedTester;
private SpotInstanceRequest request;
protected String provider = "aws-ec2";
protected String identity;
protected String credential;
protected String endpoint;
protected String apiversion;
@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());
// TODO
// availableTester = new RetryablePredicate<SpotInstanceRequest>(new
// SpotInstanceAvailable(client), 60, 1,
// TimeUnit.SECONDS);
//
// deletedTester = new RetryablePredicate<SpotInstanceRequest>(new
// SpotInstanceDeleted(client), 60, 1, TimeUnit.SECONDS);
}
@Test
void testDescribe() {
for (String region : Region.DEFAULT_REGIONS) {
String string = client.getSpotInstanceServices().describeSpotInstanceRequestsInRegion(region);
assertNotNull(string);// TODO
SortedSet<SpotInstanceRequest> allResults = ImmutableSortedSet.<SpotInstanceRequest>of(SpotInstanceRequest.builder().id("foo")
.build());
assertNotNull(allResults);
if (allResults.size() >= 1) {
SpotInstanceRequest request = allResults.last();
string = client.getSpotInstanceServices().describeSpotInstanceRequestsInRegion(region, request.getId());
assertNotNull(string);// TODO
SortedSet<SpotInstanceRequest> result = ImmutableSortedSet.of(SpotInstanceRequest.builder().id("foo")
.build());
assertNotNull(result);
SpotInstanceRequest compare = result.last();
assertEquals(compare, request);
}
}
for (String region : client.getAvailabilityZoneAndRegionServices().describeRegions().keySet()) {
if (!region.equals(Region.US_EAST_1))
try {
client.getSpotInstanceServices().describeSpotInstanceRequestsInRegion(region);
assert false : "should be unsupported";
} catch (UnsupportedOperationException e) {
}
}
}
@Test
void testCreateSpotInstance() {
String launchGroup = PREFIX + "1";
for (SpotInstanceRequest request : ImmutableSet.<SpotInstanceRequest> of())
// client.getSpotInstanceServices().describeSpotInstanceRequestsInRegion(null);
if (request.getLaunchGroup().equals(launchGroup))
client.getSpotInstanceServices().cancelSpotInstanceRequestsInRegion(null, request.getId());
String string = client.getSpotInstanceServices().requestSpotInstancesInRegion(
null,
null,
"TODO",
1,
0.01f,
RequestSpotInstancesOptions.Builder.launchSpecification(AWSRunInstancesOptions.Builder.asType("m1.small"))
.launchGroup(PREFIX));
assertNotNull(string);
verifySpotInstance(request);
}
private void verifySpotInstance(SpotInstanceRequest request) {
assert availableTester.apply(request) : request;
String string = client.getSpotInstanceServices().describeSpotInstanceRequestsInRegion(null, request.getId());
assertNotNull(string);// TODO
SpotInstanceRequest oneResult = Iterables.getOnlyElement(ImmutableSet.of(SpotInstanceRequest.builder().id("foo")
.build()));
assertNotNull(oneResult);
assertEquals(oneResult, request);
// TODO: more
}
public static final String PREFIX = System.getProperty("user.name") + "ec2";
@AfterTest
public void shutdown() {
if (request != null) {
client.getSpotInstanceServices().cancelSpotInstanceRequestsInRegion(request.getRegion(), request.getId());
assert deletedTester.apply(request) : request;
}
context.close();
}
}