From 7d27e70d59bb8e541819672f678b4802f92e5951 Mon Sep 17 00:00:00 2001 From: Adrian Cole Date: Sat, 17 Jul 2010 13:08:22 -0500 Subject: [PATCH] ec2: started work on reserved instances --- .../ec2/domain/ReservedInstancesOffering.java | 177 ++++++++++++++++++ .../aws/ec2/xml/BundleTaskHandler.java | 4 - ...ervedInstancesOfferingResponseHandler.java | 58 ++++++ .../xml/ReservedInstancesOfferingHandler.java | 90 +++++++++ ...dInstancesOfferingResponseHandlerTest.java | 62 ++++++ .../describe_reserved_instances_offerings.xml | 15 ++ 6 files changed, 402 insertions(+), 4 deletions(-) create mode 100644 aws/core/src/main/java/org/jclouds/aws/ec2/domain/ReservedInstancesOffering.java create mode 100644 aws/core/src/main/java/org/jclouds/aws/ec2/xml/DescribeReservedInstancesOfferingResponseHandler.java create mode 100644 aws/core/src/main/java/org/jclouds/aws/ec2/xml/ReservedInstancesOfferingHandler.java create mode 100644 aws/core/src/test/java/org/jclouds/aws/ec2/xml/DescribeReservedInstancesOfferingResponseHandlerTest.java create mode 100644 aws/core/src/test/resources/ec2/describe_reserved_instances_offerings.xml diff --git a/aws/core/src/main/java/org/jclouds/aws/ec2/domain/ReservedInstancesOffering.java b/aws/core/src/main/java/org/jclouds/aws/ec2/domain/ReservedInstancesOffering.java new file mode 100644 index 0000000000..686cce2901 --- /dev/null +++ b/aws/core/src/main/java/org/jclouds/aws/ec2/domain/ReservedInstancesOffering.java @@ -0,0 +1,177 @@ +/** + * + * Copyright (C) 2009 Cloud Conscious, LLC. + * + * ==================================================================== + * 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; + +/** + * + * @see + * @author Adrian Cole + */ +public class ReservedInstancesOffering implements Comparable { + private final String region; + private final String availabilityZone; + private final long duration; + private final float fixedPrice; + private final String instanceType; + private final String productDescription; + private final String id; + private final float usagePrice; + + public ReservedInstancesOffering(String region, String availabilityZone, long duration, float fixedPrice, String instanceType, + String productDescription, String reservedInstancesOfferingId, float usagePrice) { + this.region=region; + this.availabilityZone = availabilityZone; + this.duration = duration; + this.fixedPrice = fixedPrice; + this.instanceType = instanceType; + this.productDescription = productDescription; + this.id = reservedInstancesOfferingId; + this.usagePrice = usagePrice; + } + + public String getRegion() { + return region; + } + + /** + * @return The Availability Zone in which the Reserved Instance can be used. + */ + public String getAvailabilityZone() { + return availabilityZone; + } + + /** + * + * @return The duration of the Reserved Instance, in seconds + */ + public long getDuration() { + return duration; + } + + /** + * + * @return The purchase price of the Reserved Instance. + */ + public float getFixedPrice() { + return fixedPrice; + } + + /** + * + * @return The instance type on which the Reserved Instance can be used. + */ + public String getInstanceType() { + return instanceType; + } + + /** + * + * @return The Reserved Instance description. + */ + public String getProductDescription() { + return productDescription; + } + + /** + * @return The ID of the Reserved Instance offering. + */ + public String getId() { + return id; + } + + /** + * + * @return The usage price of the Reserved Instance, per hour. + */ + public float getUsagePrice() { + return usagePrice; + } + + @Override + public int compareTo(ReservedInstancesOffering o) { + return id.compareTo(o.id); + } + + @Override + public String toString() { + return "[availabilityZone=" + availabilityZone + ", duration=" + duration + + ", fixedPrice=" + fixedPrice + ", id=" + id + ", instanceType=" + instanceType + ", productDescription=" + + productDescription + ", region=" + region + ", usagePrice=" + usagePrice + "]"; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((availabilityZone == null) ? 0 : availabilityZone.hashCode()); + result = prime * result + (int) (duration ^ (duration >>> 32)); + result = prime * result + Float.floatToIntBits(fixedPrice); + result = prime * result + ((id == null) ? 0 : id.hashCode()); + 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(usagePrice); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + ReservedInstancesOffering other = (ReservedInstancesOffering) obj; + if (availabilityZone == null) { + if (other.availabilityZone != null) + return false; + } else if (!availabilityZone.equals(other.availabilityZone)) + return false; + if (duration != other.duration) + return false; + if (Float.floatToIntBits(fixedPrice) != Float.floatToIntBits(other.fixedPrice)) + return false; + if (id == null) { + if (other.id != null) + return false; + } else if (!id.equals(other.id)) + return false; + 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(usagePrice) != Float.floatToIntBits(other.usagePrice)) + return false; + return true; + } + +} diff --git a/aws/core/src/main/java/org/jclouds/aws/ec2/xml/BundleTaskHandler.java b/aws/core/src/main/java/org/jclouds/aws/ec2/xml/BundleTaskHandler.java index f17987e09c..e95bc2d318 100644 --- a/aws/core/src/main/java/org/jclouds/aws/ec2/xml/BundleTaskHandler.java +++ b/aws/core/src/main/java/org/jclouds/aws/ec2/xml/BundleTaskHandler.java @@ -20,7 +20,6 @@ package org.jclouds.aws.ec2.xml; import java.util.Date; -import javax.annotation.Resource; import javax.inject.Inject; import org.jclouds.aws.Region; @@ -28,7 +27,6 @@ import org.jclouds.aws.ec2.domain.BundleTask; import org.jclouds.aws.ec2.util.EC2Utils; import org.jclouds.date.DateService; import org.jclouds.http.functions.ParseSax; -import org.jclouds.logging.Logger; import org.jclouds.rest.internal.GeneratedHttpRequest; /** @@ -38,8 +36,6 @@ import org.jclouds.rest.internal.GeneratedHttpRequest; public class BundleTaskHandler extends ParseSax.HandlerForGeneratedRequestWithResult { private StringBuilder currentText = new StringBuilder(); - @Resource - protected Logger logger = Logger.NULL; @Inject protected DateService dateService; @Inject diff --git a/aws/core/src/main/java/org/jclouds/aws/ec2/xml/DescribeReservedInstancesOfferingResponseHandler.java b/aws/core/src/main/java/org/jclouds/aws/ec2/xml/DescribeReservedInstancesOfferingResponseHandler.java new file mode 100644 index 0000000000..fed6f80be6 --- /dev/null +++ b/aws/core/src/main/java/org/jclouds/aws/ec2/xml/DescribeReservedInstancesOfferingResponseHandler.java @@ -0,0 +1,58 @@ +package org.jclouds.aws.ec2.xml; + +import java.util.Set; + +import javax.inject.Inject; + +import org.jclouds.aws.ec2.domain.ReservedInstancesOffering; +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 + */ +public class DescribeReservedInstancesOfferingResponseHandler extends + ParseSax.HandlerWithResult> { + + private Set reservedInstancesOfferings = Sets.newLinkedHashSet(); + private final ReservedInstancesOfferingHandler reservedInstancesOffering; + + @Inject + public DescribeReservedInstancesOfferingResponseHandler(ReservedInstancesOfferingHandler reservedInstancesOffering) { + this.reservedInstancesOffering = reservedInstancesOffering; + } + + public Set getResult() { + return reservedInstancesOfferings; + } + + @Override + public HandlerWithResult> setContext(HttpRequest request) { + reservedInstancesOffering.setContext(request); + return super.setContext(request); + } + + @Override + public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { + if (!qName.equals("item")) + reservedInstancesOffering.startElement(uri, localName, qName, attributes); + } + + @Override + public void endElement(String uri, String localName, String qName) throws SAXException { + if (qName.equals("item")) { + reservedInstancesOfferings.add(reservedInstancesOffering.getResult()); + } + reservedInstancesOffering.endElement(uri, localName, qName); + } + + public void characters(char ch[], int start, int length) { + reservedInstancesOffering.characters(ch, start, length); + } + +} diff --git a/aws/core/src/main/java/org/jclouds/aws/ec2/xml/ReservedInstancesOfferingHandler.java b/aws/core/src/main/java/org/jclouds/aws/ec2/xml/ReservedInstancesOfferingHandler.java new file mode 100644 index 0000000000..f0c9759ca0 --- /dev/null +++ b/aws/core/src/main/java/org/jclouds/aws/ec2/xml/ReservedInstancesOfferingHandler.java @@ -0,0 +1,90 @@ +/** + * + * Copyright (C) 2009 Cloud Conscious, LLC. + * + * ==================================================================== + * 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.Region; +import org.jclouds.aws.ec2.domain.ReservedInstancesOffering; +import org.jclouds.aws.ec2.util.EC2Utils; +import org.jclouds.http.functions.ParseSax; +import org.jclouds.rest.internal.GeneratedHttpRequest; + +/** + * + * @see + * @author Adrian Cole + */ +public class ReservedInstancesOfferingHandler extends ParseSax.HandlerWithResult { + @Inject + @Region + String defaultRegion; + + private StringBuilder currentText = new StringBuilder(); + + private String availabilityZone; + private long duration = 0; + private float fixedPrice = 0; + private String instanceType; + private String productDescription; + private String id; + private float usagePrice = 0; + + public ReservedInstancesOffering getResult() { + String region = EC2Utils.findRegionInArgsOrNull((GeneratedHttpRequest) request); + if (region == null) + region = defaultRegion; + + ReservedInstancesOffering returnVal = new ReservedInstancesOffering(region, availabilityZone, duration, + fixedPrice, instanceType, productDescription, id, usagePrice); + this.availabilityZone = null; + this.duration = 0; + this.fixedPrice = 0; + this.instanceType = null; + this.productDescription = null; + this.id = null; + this.usagePrice = 0; + return returnVal; + } + + public void endElement(String uri, String name, String qName) { + + if (qName.equalsIgnoreCase("reservedInstancesOfferingId")) { + this.id = currentText.toString().trim(); + } else if (qName.equalsIgnoreCase("availabilityZone")) { + this.availabilityZone = currentText.toString().trim(); + } else if (qName.equalsIgnoreCase("duration")) { + this.duration = Long.parseLong(currentText.toString().trim()); + } else if (qName.equalsIgnoreCase("fixedPrice")) { + this.fixedPrice = Float.parseFloat(currentText.toString().trim()); + } else if (qName.equalsIgnoreCase("instanceType")) { + this.instanceType = currentText.toString().trim(); + } else if (qName.equalsIgnoreCase("productDescription")) { + this.productDescription = currentText.toString().trim(); + } else if (qName.equalsIgnoreCase("usagePrice")) { + this.usagePrice = Float.parseFloat(currentText.toString().trim()); + } + currentText = new StringBuilder(); + } + + public void characters(char ch[], int start, int length) { + currentText.append(ch, start, length); + } +} diff --git a/aws/core/src/test/java/org/jclouds/aws/ec2/xml/DescribeReservedInstancesOfferingResponseHandlerTest.java b/aws/core/src/test/java/org/jclouds/aws/ec2/xml/DescribeReservedInstancesOfferingResponseHandlerTest.java new file mode 100644 index 0000000000..9d4c072a3c --- /dev/null +++ b/aws/core/src/test/java/org/jclouds/aws/ec2/xml/DescribeReservedInstancesOfferingResponseHandlerTest.java @@ -0,0 +1,62 @@ +/** + * + * Copyright (C) 2009 Cloud Conscious, LLC. + * + * ==================================================================== + * 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.ReservedInstancesOffering; +import org.jclouds.http.functions.ParseSax; +import org.jclouds.rest.internal.GeneratedHttpRequest; +import org.testng.annotations.Test; + +import com.google.inject.internal.Iterables; + +/** + * Tests behavior of {@code DescribeReservedInstancesOfferingResponseHandler} + * + * @author Adrian Cole + */ +@Test(groups = "unit", testName = "ec2.DescribeReservedInstancesOfferingResponseHandlerTest") +public class DescribeReservedInstancesOfferingResponseHandlerTest extends BaseEC2HandlerTest { + public void testApplyInputStream() { + InputStream is = getClass().getResourceAsStream("/ec2/describe_reserved_instances_offerings.xml"); + + ReservedInstancesOffering expected = new ReservedInstancesOffering("us-east-1", "us-east-1a", 12, 0.0f, "m1.small", + "m1.small offering in us-east-1a", "4b2293b4-5813-4cc8-9ce3-1957fc1dcfc8", 0.0f); + + DescribeReservedInstancesOfferingResponseHandler handler = injector + .getInstance(DescribeReservedInstancesOfferingResponseHandler.class); + addDefaultRegionToHandler(handler); + ReservedInstancesOffering result = Iterables.getOnlyElement(factory.create(handler).parse(is)); + + assertEquals(result, expected); + } + + private void addDefaultRegionToHandler(ParseSax.HandlerWithResult handler) { + GeneratedHttpRequest request = createMock(GeneratedHttpRequest.class); + expect(request.getArgs()).andReturn(new Object[] { null }); + replay(request); + handler.setContext(request); + } +} \ No newline at end of file diff --git a/aws/core/src/test/resources/ec2/describe_reserved_instances_offerings.xml b/aws/core/src/test/resources/ec2/describe_reserved_instances_offerings.xml new file mode 100644 index 0000000000..d08a605d47 --- /dev/null +++ b/aws/core/src/test/resources/ec2/describe_reserved_instances_offerings.xml @@ -0,0 +1,15 @@ + + + + 4b2293b4-5813-4cc8-9ce3-1957fc1dcfc8 + + m1.small + us-east-1a + 12 + 0.00 + 0.00 + m1.small offering in us-east-1a + + + \ No newline at end of file