diff --git a/aws/core/src/main/java/org/jclouds/aws/ec2/EC2AsyncClient.java b/aws/core/src/main/java/org/jclouds/aws/ec2/EC2AsyncClient.java index c07dbd686c..0c71531a27 100644 --- a/aws/core/src/main/java/org/jclouds/aws/ec2/EC2AsyncClient.java +++ b/aws/core/src/main/java/org/jclouds/aws/ec2/EC2AsyncClient.java @@ -26,6 +26,7 @@ package org.jclouds.aws.ec2; import org.jclouds.aws.ec2.internal.EC2AsyncClientImpl; import org.jclouds.aws.ec2.services.AMIAsyncClient; import org.jclouds.aws.ec2.services.AvailabilityZoneAndRegionAsyncClient; +import org.jclouds.aws.ec2.services.ElasticBlockStoreAsyncClient; import org.jclouds.aws.ec2.services.ElasticIPAddressAsyncClient; import org.jclouds.aws.ec2.services.InstanceAsyncClient; import org.jclouds.aws.ec2.services.KeyPairAsyncClient; @@ -75,4 +76,9 @@ public interface EC2AsyncClient { * Provides asynchronous access to Availability Zones and Regions services. */ AvailabilityZoneAndRegionAsyncClient getAvailabilityZoneAndRegionServices(); + + /** + * Provides asynchronous access to Elastic Block Store services. + */ + ElasticBlockStoreAsyncClient getElasticBlockStoreServices(); } diff --git a/aws/core/src/main/java/org/jclouds/aws/ec2/EC2Client.java b/aws/core/src/main/java/org/jclouds/aws/ec2/EC2Client.java index aed796060a..a7490bcfca 100644 --- a/aws/core/src/main/java/org/jclouds/aws/ec2/EC2Client.java +++ b/aws/core/src/main/java/org/jclouds/aws/ec2/EC2Client.java @@ -26,6 +26,7 @@ package org.jclouds.aws.ec2; import org.jclouds.aws.ec2.internal.EC2ClientImpl; import org.jclouds.aws.ec2.services.AMIClient; import org.jclouds.aws.ec2.services.AvailabilityZoneAndRegionClient; +import org.jclouds.aws.ec2.services.ElasticBlockStoreClient; import org.jclouds.aws.ec2.services.ElasticIPAddressClient; import org.jclouds.aws.ec2.services.InstanceClient; import org.jclouds.aws.ec2.services.KeyPairClient; @@ -75,4 +76,9 @@ public interface EC2Client { * Provides synchronous access to Availability Zones and Regions services. */ AvailabilityZoneAndRegionClient getAvailabilityZoneAndRegionServices(); + + /** + * Provides synchronous access to Elastic Block Store services. + */ + ElasticBlockStoreClient getElasticBlockStoreServices(); } diff --git a/aws/core/src/main/java/org/jclouds/aws/ec2/binders/BindVolumeIdsToIndexedFormParams.java b/aws/core/src/main/java/org/jclouds/aws/ec2/binders/BindVolumeIdsToIndexedFormParams.java new file mode 100644 index 0000000000..0fe46888b4 --- /dev/null +++ b/aws/core/src/main/java/org/jclouds/aws/ec2/binders/BindVolumeIdsToIndexedFormParams.java @@ -0,0 +1,49 @@ +/** + * + * Copyright (C) 2009 Cloud Conscious, LLC. + * + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * ==================================================================== + */ +package org.jclouds.aws.ec2.binders; + +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkNotNull; + +import org.jclouds.aws.ec2.util.EC2Utils; +import org.jclouds.http.HttpRequest; +import org.jclouds.rest.Binder; +import org.jclouds.rest.internal.GeneratedHttpRequest; + +/** + * Binds the String [] to form parameters named with VolumeId.index + * + * @author Adrian Cole + */ +public class BindVolumeIdsToIndexedFormParams implements Binder { + + @SuppressWarnings("unchecked") + public void bindToRequest(HttpRequest request, Object input) { + checkArgument(checkNotNull(request, "input") instanceof GeneratedHttpRequest, + "this binder is only valid for GeneratedHttpRequests!"); + EC2Utils.indexStringArrayToFormValuesWithPrefix((GeneratedHttpRequest) request, + "VolumeId", input); + } + +} \ No newline at end of file diff --git a/aws/core/src/main/java/org/jclouds/aws/ec2/config/EC2RestClientModule.java b/aws/core/src/main/java/org/jclouds/aws/ec2/config/EC2RestClientModule.java index 34b1b72128..da073057cf 100755 --- a/aws/core/src/main/java/org/jclouds/aws/ec2/config/EC2RestClientModule.java +++ b/aws/core/src/main/java/org/jclouds/aws/ec2/config/EC2RestClientModule.java @@ -41,6 +41,8 @@ import org.jclouds.aws.ec2.services.AMIAsyncClient; import org.jclouds.aws.ec2.services.AMIClient; import org.jclouds.aws.ec2.services.AvailabilityZoneAndRegionAsyncClient; import org.jclouds.aws.ec2.services.AvailabilityZoneAndRegionClient; +import org.jclouds.aws.ec2.services.ElasticBlockStoreAsyncClient; +import org.jclouds.aws.ec2.services.ElasticBlockStoreClient; import org.jclouds.aws.ec2.services.ElasticIPAddressAsyncClient; import org.jclouds.aws.ec2.services.ElasticIPAddressClient; import org.jclouds.aws.ec2.services.InstanceAsyncClient; @@ -206,6 +208,20 @@ public class EC2RestClientModule extends AbstractModule { return SyncProxy.create(AvailabilityZoneAndRegionClient.class, client); } + @Provides + @Singleton + protected ElasticBlockStoreAsyncClient provideElasticBlockStoreAsyncClient( + RestClientFactory factory) { + return factory.create(ElasticBlockStoreAsyncClient.class); + } + + @Provides + @Singleton + public ElasticBlockStoreClient provideElasticBlockStoreClient(ElasticBlockStoreAsyncClient client) + throws IllegalArgumentException, SecurityException, NoSuchMethodException { + return SyncProxy.create(ElasticBlockStoreClient.class, client); + } + @Provides @Singleton @EC2 diff --git a/aws/core/src/main/java/org/jclouds/aws/ec2/internal/EC2AsyncClientImpl.java b/aws/core/src/main/java/org/jclouds/aws/ec2/internal/EC2AsyncClientImpl.java index ab90bb2d15..ced48b34cb 100644 --- a/aws/core/src/main/java/org/jclouds/aws/ec2/internal/EC2AsyncClientImpl.java +++ b/aws/core/src/main/java/org/jclouds/aws/ec2/internal/EC2AsyncClientImpl.java @@ -31,6 +31,7 @@ import javax.inject.Singleton; import org.jclouds.aws.ec2.EC2AsyncClient; import org.jclouds.aws.ec2.services.AMIAsyncClient; import org.jclouds.aws.ec2.services.AvailabilityZoneAndRegionAsyncClient; +import org.jclouds.aws.ec2.services.ElasticBlockStoreAsyncClient; import org.jclouds.aws.ec2.services.ElasticIPAddressAsyncClient; import org.jclouds.aws.ec2.services.InstanceAsyncClient; import org.jclouds.aws.ec2.services.KeyPairAsyncClient; @@ -51,6 +52,7 @@ public class EC2AsyncClientImpl implements EC2AsyncClient { private final SecurityGroupAsyncClient securityGroupServices; private final MonitoringAsyncClient monitoringServices; private final AvailabilityZoneAndRegionAsyncClient availabilityZoneAndRegionServices; + private final ElasticBlockStoreAsyncClient elasticBlockStoreServices; @Inject public EC2AsyncClientImpl(AMIAsyncClient AMIServices, @@ -58,7 +60,8 @@ public class EC2AsyncClientImpl implements EC2AsyncClient { InstanceAsyncClient instanceServices, KeyPairAsyncClient keyPairServices, SecurityGroupAsyncClient securityGroupServices, MonitoringAsyncClient monitoringServices, - AvailabilityZoneAndRegionAsyncClient availabilityZoneAndRegionServices) { + AvailabilityZoneAndRegionAsyncClient availabilityZoneAndRegionServices, + ElasticBlockStoreAsyncClient elasticBlockStoreServices) { this.AMIServices = checkNotNull(AMIServices, "AMIServices"); this.elasticIPAddressServices = checkNotNull(elasticIPAddressServices, "elasticIPAddressServices"); @@ -68,6 +71,8 @@ public class EC2AsyncClientImpl implements EC2AsyncClient { this.monitoringServices = checkNotNull(monitoringServices, "monitoringServices"); this.availabilityZoneAndRegionServices = checkNotNull(availabilityZoneAndRegionServices, "availabilityZoneAndRegionServices"); + this.elasticBlockStoreServices = checkNotNull(elasticBlockStoreServices, + "elasticBlockStoreServices"); } /** @@ -119,4 +124,11 @@ public class EC2AsyncClientImpl implements EC2AsyncClient { return availabilityZoneAndRegionServices; } + /** + * {@inheritDoc} + */ + public ElasticBlockStoreAsyncClient getElasticBlockStoreServices() { + return elasticBlockStoreServices; + } + } diff --git a/aws/core/src/main/java/org/jclouds/aws/ec2/internal/EC2ClientImpl.java b/aws/core/src/main/java/org/jclouds/aws/ec2/internal/EC2ClientImpl.java index c384e197ad..511e605abe 100644 --- a/aws/core/src/main/java/org/jclouds/aws/ec2/internal/EC2ClientImpl.java +++ b/aws/core/src/main/java/org/jclouds/aws/ec2/internal/EC2ClientImpl.java @@ -31,6 +31,7 @@ import javax.inject.Singleton; import org.jclouds.aws.ec2.EC2Client; import org.jclouds.aws.ec2.services.AMIClient; import org.jclouds.aws.ec2.services.AvailabilityZoneAndRegionClient; +import org.jclouds.aws.ec2.services.ElasticBlockStoreClient; import org.jclouds.aws.ec2.services.ElasticIPAddressClient; import org.jclouds.aws.ec2.services.InstanceClient; import org.jclouds.aws.ec2.services.KeyPairClient; @@ -51,12 +52,14 @@ public class EC2ClientImpl implements EC2Client { private final SecurityGroupClient securityGroupServices; private final MonitoringClient monitoringServices; private final AvailabilityZoneAndRegionClient availabilityZoneAndRegionServices; + private final ElasticBlockStoreClient elasticBlockStoreServices; @Inject public EC2ClientImpl(AMIClient AMIServices, ElasticIPAddressClient elasticIPAddressServices, InstanceClient instanceServices, KeyPairClient keyPairServices, SecurityGroupClient securityGroupServices, MonitoringClient monitoringServices, - AvailabilityZoneAndRegionClient availabilityZoneAndRegionServices) { + AvailabilityZoneAndRegionClient availabilityZoneAndRegionServices, + ElasticBlockStoreClient elasticBlockStoreServices) { this.AMIServices = checkNotNull(AMIServices, "AMIServices"); this.elasticIPAddressServices = checkNotNull(elasticIPAddressServices, "elasticIPAddressServices"); @@ -66,6 +69,8 @@ public class EC2ClientImpl implements EC2Client { this.monitoringServices = checkNotNull(monitoringServices, "monitoringServices"); this.availabilityZoneAndRegionServices = checkNotNull(availabilityZoneAndRegionServices, "availabilityZoneAndRegionServices"); + this.elasticBlockStoreServices = checkNotNull(elasticBlockStoreServices, + "elasticBlockStoreServices"); } /** @@ -117,4 +122,11 @@ public class EC2ClientImpl implements EC2Client { return availabilityZoneAndRegionServices; } + /** + * {@inheritDoc} + */ + public ElasticBlockStoreClient getElasticBlockStoreServices() { + return elasticBlockStoreServices; + } + } diff --git a/aws/core/src/main/java/org/jclouds/aws/ec2/services/AMIAsyncClient.java b/aws/core/src/main/java/org/jclouds/aws/ec2/services/AMIAsyncClient.java index 1a04d5e4c0..af3a6323d5 100644 --- a/aws/core/src/main/java/org/jclouds/aws/ec2/services/AMIAsyncClient.java +++ b/aws/core/src/main/java/org/jclouds/aws/ec2/services/AMIAsyncClient.java @@ -34,7 +34,6 @@ import javax.ws.rs.FormParam; import javax.ws.rs.POST; import javax.ws.rs.Path; -import org.jclouds.aws.ec2.EC2; import org.jclouds.aws.ec2.binders.BindProductCodesToIndexedFormParams; import org.jclouds.aws.ec2.binders.BindUserGroupsToIndexedFormParams; import org.jclouds.aws.ec2.binders.BindUserIdsToIndexedFormParams; @@ -54,7 +53,6 @@ import org.jclouds.aws.ec2.xml.ImageIdHandler; import org.jclouds.aws.ec2.xml.LaunchPermissionHandler; import org.jclouds.aws.ec2.xml.ProductCodesHandler; import org.jclouds.rest.annotations.BinderParam; -import org.jclouds.rest.annotations.Endpoint; import org.jclouds.rest.annotations.EndpointParam; import org.jclouds.rest.annotations.FormParams; import org.jclouds.rest.annotations.RequestFilters; @@ -67,7 +65,6 @@ import org.jclouds.rest.annotations.XMLResponseParser; * * @author Adrian Cole */ -@Endpoint(EC2.class) @RequestFilters(FormSigner.class) @FormParams(keys = VERSION, values = "2009-11-30") @VirtualHost diff --git a/aws/core/src/main/java/org/jclouds/aws/ec2/services/ElasticBlockStoreAsyncClient.java b/aws/core/src/main/java/org/jclouds/aws/ec2/services/ElasticBlockStoreAsyncClient.java new file mode 100644 index 0000000000..33c4a2c112 --- /dev/null +++ b/aws/core/src/main/java/org/jclouds/aws/ec2/services/ElasticBlockStoreAsyncClient.java @@ -0,0 +1,103 @@ +/** + * + * Copyright (C) 2009 Cloud Conscious, LLC. + * + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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.ec2.reference.EC2Parameters.ACTION; +import static org.jclouds.aws.ec2.reference.EC2Parameters.VERSION; + +import java.util.concurrent.Future; + +import javax.ws.rs.FormParam; +import javax.ws.rs.POST; +import javax.ws.rs.Path; + +import org.jclouds.aws.ec2.EC2; +import org.jclouds.aws.ec2.binders.BindVolumeIdsToIndexedFormParams; +import org.jclouds.aws.ec2.domain.AvailabilityZone; +import org.jclouds.aws.ec2.domain.Region; +import org.jclouds.aws.ec2.filters.FormSigner; +import org.jclouds.aws.ec2.functions.RegionToEndpoint; +import org.jclouds.rest.annotations.BinderParam; +import org.jclouds.rest.annotations.Endpoint; +import org.jclouds.rest.annotations.EndpointParam; +import org.jclouds.rest.annotations.FormParams; +import org.jclouds.rest.annotations.RequestFilters; +import org.jclouds.rest.annotations.VirtualHost; + +/** + * Provides access to EC2 Elastic Block Store services via their REST API. + *

+ * + * @author Adrian Cole + */ +@RequestFilters(FormSigner.class) +@FormParams(keys = VERSION, values = "2009-11-30") +@VirtualHost +public interface ElasticBlockStoreAsyncClient { + + /** + * @see ElasticBlockStoreClient#createVolumeFromSnapshotInAvailabilityZone + */ + @POST + @Path("/") + @Endpoint(EC2.class) // TODO: remove + @FormParams(keys = ACTION, values = "CreateVolume") + // @XMLResponseParser(VolumeResponseHandler.class) + Future createVolumeFromSnapshotInAvailabilityZone( + @FormParam("AvailabilityZone") AvailabilityZone availabilityZone, + @FormParam("SnapshotId") String snapshotId); + + /** + * @see ElasticBlockStoreClient#createVolumeInAvailabilityZone + */ + @POST + @Path("/") + @Endpoint(EC2.class) // TODO: remove + @FormParams(keys = ACTION, values = "CreateVolume") + // @XMLResponseParser(VolumeResponseHandler.class) + Future createVolumeInAvailabilityZone( + @FormParam("AvailabilityZone") AvailabilityZone availabilityZone, + @FormParam("Size") int size); + + /** + * @see ElasticBlockStoreClient#describeVolumesInRegion + */ + @POST + @Path("/") + @FormParams(keys = ACTION, values = "DescribeVolumes") + // @XMLResponseParser(DescribeVolumesResponseHandler.class) + Future describeVolumesInRegion( + @EndpointParam(parser = RegionToEndpoint.class) Region region, + @BinderParam(BindVolumeIdsToIndexedFormParams.class) String... volumeIds); + + /** + * @see ElasticBlockStoreClient#deleteVolumeInRegion + */ + @POST + @Path("/") + @FormParams(keys = ACTION, values = "DeleteVolume") + Future deleteVolumeInRegion(@EndpointParam(parser = RegionToEndpoint.class) Region region, + @FormParam("VolumeId") String volumeId); + +} diff --git a/aws/core/src/main/java/org/jclouds/aws/ec2/services/ElasticBlockStoreClient.java b/aws/core/src/main/java/org/jclouds/aws/ec2/services/ElasticBlockStoreClient.java new file mode 100644 index 0000000000..360a0bfee3 --- /dev/null +++ b/aws/core/src/main/java/org/jclouds/aws/ec2/services/ElasticBlockStoreClient.java @@ -0,0 +1,129 @@ +/** + * + * Copyright (C) 2009 Cloud Conscious, LLC. + * + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.jclouds.aws.ec2.domain.AvailabilityZone; +import org.jclouds.aws.ec2.domain.Region; +import org.jclouds.concurrent.Timeout; + +/** + * Provides access to EC2 Elastic Block Store services. + *

+ * + * @author Adrian Cole + */ +@Timeout(duration = 30, timeUnit = TimeUnit.SECONDS) +public interface ElasticBlockStoreClient { + + /** + * Creates a new Amazon EBS volume to which any Amazon EC2 instance can attach within the same + * Availability Zone. For more information about Amazon EBS, go to the Amazon Elastic Compute + * Cloud Developer Guide or Amazon Elastic Compute Cloud User Guide. + * + * @param availabilityZone + * An Amazon EBS volume must be located within the same Availability Zone as the + * instance to which it attaches. + * @param snapshotId + * The snapshot from which to create the new volume. + * + * @see #describeVolumesInRegion + * @see #deleteVolumeInRegion + * @see #attachVolumeInRegion + * @see #detachVolumeInRegion + * @see AvailabilityZoneAndRegionClient#describeAvailabilityZonesInRegion + * + * + * @see + */ + String createVolumeFromSnapshotInAvailabilityZone(AvailabilityZone availabilityZone, + String snapshotId); + + /** + * Creates a new Amazon EBS volume to which any Amazon EC2 instance can attach within the same + * Availability Zone. For more information about Amazon EBS, go to the Amazon Elastic Compute + * Cloud Developer Guide or Amazon Elastic Compute Cloud User Guide. + * + * @param availabilityZone + * An Amazon EBS volume must be located within the same Availability Zone as the + * instance to which it attaches. + * @param size + * The size of the volume, in GiBs (1-1024). Required if you are not creating a volume + * from a snapshot. + * + * + * @see #describeVolumesInRegion + * @see #deleteVolumeInRegion + * @see #attachVolumeInRegion + * @see #detachVolumeInRegion + * @see AvailabilityZoneAndRegionClient#describeAvailabilityZonesInRegion + * @see + */ + String createVolumeInAvailabilityZone(AvailabilityZone availabilityZone, int size); + + /** + * Describes the specified Amazon EBS volumes that you own. If you do not specify one or more + * volume IDs, Amazon EBS describes all volumes that you own. For more information about Amazon + * EBS, go to the Amazon Elastic Compute Cloud Developer Guide or Amazon Elastic Compute Cloud + * User Guide. + * + * @param region + * region where the volume is defined + * @param volumeIds + * The ID of the volume to list. Defaults to describe all volumes that you own. + * + * @see #createSnapshotInRegion + * @see #describeSnapshotInRegion + * @see + */ + String describeVolumesInRegion(Region region, String... volumeIds); + + /** + * Deletes an Amazon EBS volume that you own. For more information about Amazon EBS, go to the + * Amazon Elastic Compute Cloud Developer Guide or Amazon Elastic Compute Cloud User Guide. + * + * @param region + * region where the volume is defined + * @param volumeId + * The ID of the volume to delete. The volume remains in the deleting state for several + * minutes after entering this command. + * + * @see #describeVolumes + * @see #createVolume + * @see #attachVolume + * @see #detachVolume + * + * @see + */ + void deleteVolumeInRegion(Region region, String volumeId); + +} diff --git a/aws/core/src/main/java/org/jclouds/aws/ec2/services/ElasticIPAddressAsyncClient.java b/aws/core/src/main/java/org/jclouds/aws/ec2/services/ElasticIPAddressAsyncClient.java index fa48a10635..f905b9564a 100644 --- a/aws/core/src/main/java/org/jclouds/aws/ec2/services/ElasticIPAddressAsyncClient.java +++ b/aws/core/src/main/java/org/jclouds/aws/ec2/services/ElasticIPAddressAsyncClient.java @@ -34,7 +34,6 @@ import javax.ws.rs.FormParam; import javax.ws.rs.POST; import javax.ws.rs.Path; -import org.jclouds.aws.ec2.EC2; import org.jclouds.aws.ec2.binders.BindInetAddressesToIndexedFormParams; import org.jclouds.aws.ec2.domain.PublicIpInstanceIdPair; import org.jclouds.aws.ec2.domain.Region; @@ -43,7 +42,6 @@ import org.jclouds.aws.ec2.functions.RegionToEndpoint; import org.jclouds.aws.ec2.xml.AllocateAddressResponseHandler; import org.jclouds.aws.ec2.xml.DescribeAddressesResponseHandler; import org.jclouds.rest.annotations.BinderParam; -import org.jclouds.rest.annotations.Endpoint; import org.jclouds.rest.annotations.EndpointParam; import org.jclouds.rest.annotations.FormParams; import org.jclouds.rest.annotations.ParamParser; @@ -58,7 +56,6 @@ import org.jclouds.rest.functions.InetAddressToHostAddress; * * @author Adrian Cole */ -@Endpoint(EC2.class) @RequestFilters(FormSigner.class) @FormParams(keys = VERSION, values = "2009-11-30") @VirtualHost diff --git a/aws/core/src/main/java/org/jclouds/aws/ec2/services/InstanceAsyncClient.java b/aws/core/src/main/java/org/jclouds/aws/ec2/services/InstanceAsyncClient.java index b94513cbe1..24ea010496 100644 --- a/aws/core/src/main/java/org/jclouds/aws/ec2/services/InstanceAsyncClient.java +++ b/aws/core/src/main/java/org/jclouds/aws/ec2/services/InstanceAsyncClient.java @@ -34,7 +34,6 @@ import javax.ws.rs.FormParam; import javax.ws.rs.POST; import javax.ws.rs.Path; -import org.jclouds.aws.ec2.EC2; import org.jclouds.aws.ec2.binders.BindInstanceIdsToIndexedFormParams; import org.jclouds.aws.ec2.binders.IfNotNullBindAvailabilityZoneToFormParam; import org.jclouds.aws.ec2.domain.AvailabilityZone; @@ -48,7 +47,6 @@ import org.jclouds.aws.ec2.xml.DescribeInstancesResponseHandler; import org.jclouds.aws.ec2.xml.RunInstancesResponseHandler; import org.jclouds.aws.ec2.xml.TerminateInstancesResponseHandler; import org.jclouds.rest.annotations.BinderParam; -import org.jclouds.rest.annotations.Endpoint; import org.jclouds.rest.annotations.EndpointParam; import org.jclouds.rest.annotations.FormParams; import org.jclouds.rest.annotations.RequestFilters; @@ -61,7 +59,6 @@ import org.jclouds.rest.annotations.XMLResponseParser; * * @author Adrian Cole */ -@Endpoint(EC2.class) @RequestFilters(FormSigner.class) @FormParams(keys = VERSION, values = "2009-11-30") @VirtualHost diff --git a/aws/core/src/main/java/org/jclouds/aws/ec2/services/KeyPairAsyncClient.java b/aws/core/src/main/java/org/jclouds/aws/ec2/services/KeyPairAsyncClient.java index 6d85fbd584..7f8710c15f 100644 --- a/aws/core/src/main/java/org/jclouds/aws/ec2/services/KeyPairAsyncClient.java +++ b/aws/core/src/main/java/org/jclouds/aws/ec2/services/KeyPairAsyncClient.java @@ -33,7 +33,6 @@ import javax.ws.rs.FormParam; import javax.ws.rs.POST; import javax.ws.rs.Path; -import org.jclouds.aws.ec2.EC2; import org.jclouds.aws.ec2.binders.BindKeyNameToIndexedFormParams; import org.jclouds.aws.ec2.domain.KeyPair; import org.jclouds.aws.ec2.domain.Region; @@ -42,7 +41,6 @@ import org.jclouds.aws.ec2.functions.RegionToEndpoint; import org.jclouds.aws.ec2.xml.DescribeKeyPairsResponseHandler; import org.jclouds.aws.ec2.xml.KeyPairResponseHandler; import org.jclouds.rest.annotations.BinderParam; -import org.jclouds.rest.annotations.Endpoint; import org.jclouds.rest.annotations.EndpointParam; import org.jclouds.rest.annotations.FormParams; import org.jclouds.rest.annotations.RequestFilters; @@ -55,7 +53,6 @@ import org.jclouds.rest.annotations.XMLResponseParser; * * @author Adrian Cole */ -@Endpoint(EC2.class) @RequestFilters(FormSigner.class) @FormParams(keys = VERSION, values = "2009-11-30") @VirtualHost diff --git a/aws/core/src/main/java/org/jclouds/aws/ec2/services/MonitoringAsyncClient.java b/aws/core/src/main/java/org/jclouds/aws/ec2/services/MonitoringAsyncClient.java index 3078ded69f..d0c812479e 100644 --- a/aws/core/src/main/java/org/jclouds/aws/ec2/services/MonitoringAsyncClient.java +++ b/aws/core/src/main/java/org/jclouds/aws/ec2/services/MonitoringAsyncClient.java @@ -33,7 +33,6 @@ import javax.ws.rs.FormParam; import javax.ws.rs.POST; import javax.ws.rs.Path; -import org.jclouds.aws.ec2.EC2; import org.jclouds.aws.ec2.binders.BindInstanceIdsToIndexedFormParams; import org.jclouds.aws.ec2.domain.MonitoringState; import org.jclouds.aws.ec2.domain.Region; @@ -41,7 +40,6 @@ import org.jclouds.aws.ec2.filters.FormSigner; import org.jclouds.aws.ec2.functions.RegionToEndpoint; import org.jclouds.aws.ec2.xml.MonitoringStateHandler; import org.jclouds.rest.annotations.BinderParam; -import org.jclouds.rest.annotations.Endpoint; import org.jclouds.rest.annotations.EndpointParam; import org.jclouds.rest.annotations.FormParams; import org.jclouds.rest.annotations.RequestFilters; @@ -54,7 +52,6 @@ import org.jclouds.rest.annotations.XMLResponseParser; * * @author Adrian Cole */ -@Endpoint(EC2.class) @RequestFilters(FormSigner.class) @FormParams(keys = VERSION, values = "2009-11-30") @VirtualHost diff --git a/aws/core/src/main/java/org/jclouds/aws/ec2/services/SecurityGroupAsyncClient.java b/aws/core/src/main/java/org/jclouds/aws/ec2/services/SecurityGroupAsyncClient.java index 0e025f2efd..a356e30602 100644 --- a/aws/core/src/main/java/org/jclouds/aws/ec2/services/SecurityGroupAsyncClient.java +++ b/aws/core/src/main/java/org/jclouds/aws/ec2/services/SecurityGroupAsyncClient.java @@ -33,7 +33,6 @@ import javax.ws.rs.FormParam; import javax.ws.rs.POST; import javax.ws.rs.Path; -import org.jclouds.aws.ec2.EC2; import org.jclouds.aws.ec2.binders.BindGroupNameToIndexedFormParams; import org.jclouds.aws.ec2.binders.BindUserIdGroupPairToSourceSecurityGroupFormParams; import org.jclouds.aws.ec2.domain.IpProtocol; @@ -45,7 +44,6 @@ import org.jclouds.aws.ec2.functions.RegionToEndpoint; import org.jclouds.aws.ec2.functions.ReturnVoidOnGroupNotFound; import org.jclouds.aws.ec2.xml.DescribeSecurityGroupsResponseHandler; import org.jclouds.rest.annotations.BinderParam; -import org.jclouds.rest.annotations.Endpoint; import org.jclouds.rest.annotations.EndpointParam; import org.jclouds.rest.annotations.ExceptionParser; import org.jclouds.rest.annotations.FormParams; @@ -59,7 +57,6 @@ import org.jclouds.rest.annotations.XMLResponseParser; * * @author Adrian Cole */ -@Endpoint(EC2.class) @RequestFilters(FormSigner.class) @FormParams(keys = VERSION, values = "2009-11-30") @VirtualHost diff --git a/aws/core/src/test/java/org/jclouds/aws/ec2/services/AMIAsyncClientTest.java b/aws/core/src/test/java/org/jclouds/aws/ec2/services/AMIAsyncClientTest.java index 041481d477..16e3dc0d5d 100644 --- a/aws/core/src/test/java/org/jclouds/aws/ec2/services/AMIAsyncClientTest.java +++ b/aws/core/src/test/java/org/jclouds/aws/ec2/services/AMIAsyncClientTest.java @@ -119,7 +119,8 @@ public class AMIAsyncClientTest extends RestClientTest { public void testDescribeImages() throws SecurityException, NoSuchMethodException, IOException { Method method = AMIAsyncClient.class.getMethod("describeImagesInRegion", Region.class, Array .newInstance(DescribeImagesOptions.class, 0).getClass()); - GeneratedHttpRequest httpMethod = processor.createRequest(method); + GeneratedHttpRequest httpMethod = processor.createRequest(method, + Region.DEFAULT); assertRequestLineEquals(httpMethod, "POST https://ec2.amazonaws.com/ HTTP/1.1"); assertHeadersEqual(httpMethod, diff --git a/aws/core/src/test/java/org/jclouds/aws/ec2/services/ElasticBlockStoreAsyncClientTest.java b/aws/core/src/test/java/org/jclouds/aws/ec2/services/ElasticBlockStoreAsyncClientTest.java new file mode 100644 index 0000000000..a1b6af7fe4 --- /dev/null +++ b/aws/core/src/test/java/org/jclouds/aws/ec2/services/ElasticBlockStoreAsyncClientTest.java @@ -0,0 +1,213 @@ +/** + * + * Copyright (C) 2009 Cloud Conscious, LLC. + * + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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.testng.Assert.assertEquals; + +import java.io.IOException; +import java.lang.reflect.Array; +import java.lang.reflect.Method; +import java.net.URI; +import java.util.Map; + +import javax.inject.Singleton; + +import org.jclouds.aws.ec2.EC2; +import org.jclouds.aws.ec2.domain.AvailabilityZone; +import org.jclouds.aws.ec2.domain.Region; +import org.jclouds.aws.ec2.filters.FormSigner; +import org.jclouds.aws.reference.AWSConstants; +import org.jclouds.date.TimeStamp; +import org.jclouds.http.functions.ReturnStringIf200; +import org.jclouds.http.functions.ReturnVoidIf2xx; +import org.jclouds.logging.Logger; +import org.jclouds.logging.Logger.LoggerFactory; +import org.jclouds.rest.RestClientTest; +import org.jclouds.rest.internal.GeneratedHttpRequest; +import org.jclouds.rest.internal.RestAnnotationProcessor; +import org.jclouds.util.Jsr330; +import org.testng.annotations.Test; + +import com.google.common.collect.ImmutableMap; +import com.google.inject.AbstractModule; +import com.google.inject.Module; +import com.google.inject.Provides; +import com.google.inject.TypeLiteral; + +/** + * Tests behavior of {@code ElasticBlockStoreAsyncClient} + * + * @author Adrian Cole + */ +@Test(groups = "unit", testName = "ec2.ElasticBlockStoreAsyncClientTest") +public class ElasticBlockStoreAsyncClientTest extends RestClientTest { + + public void testCreateVolume() throws SecurityException, NoSuchMethodException, IOException { + Method method = ElasticBlockStoreAsyncClient.class.getMethod( + "createVolumeInAvailabilityZone", AvailabilityZone.class, int.class); + GeneratedHttpRequest httpMethod = processor.createRequest( + method, AvailabilityZone.US_EAST_1A, 20); + + assertRequestLineEquals(httpMethod, "POST https://ec2.amazonaws.com/ HTTP/1.1"); + assertHeadersEqual(httpMethod, + "Content-Length: 74\nContent-Type: application/x-www-form-urlencoded\nHost: ec2.amazonaws.com\n"); + assertPayloadEquals(httpMethod, + "Version=2009-11-30&Action=CreateVolume&AvailabilityZone=us-east-1a&Size=20"); + + assertResponseParserClassEquals(method, httpMethod, ReturnStringIf200.class); + assertSaxResponseParserClassEquals(method, null); + assertExceptionParserClassEquals(method, null); + + checkFilters(httpMethod); + } + + public void testCreateVolumeFromSnapShot() throws SecurityException, NoSuchMethodException, + IOException { + Method method = ElasticBlockStoreAsyncClient.class.getMethod( + "createVolumeFromSnapshotInAvailabilityZone", AvailabilityZone.class, String.class); + GeneratedHttpRequest httpMethod = processor.createRequest( + method, AvailabilityZone.US_EAST_1A, "snapshotId"); + + assertRequestLineEquals(httpMethod, "POST https://ec2.amazonaws.com/ HTTP/1.1"); + assertHeadersEqual(httpMethod, + "Content-Length: 88\nContent-Type: application/x-www-form-urlencoded\nHost: ec2.amazonaws.com\n"); + assertPayloadEquals(httpMethod, + "Version=2009-11-30&Action=CreateVolume&AvailabilityZone=us-east-1a&SnapshotId=snapshotId"); + + assertResponseParserClassEquals(method, httpMethod, ReturnStringIf200.class); + assertSaxResponseParserClassEquals(method, null); + assertExceptionParserClassEquals(method, null); + + checkFilters(httpMethod); + } + + public void testDeleteVolume() throws SecurityException, NoSuchMethodException, IOException { + Method method = ElasticBlockStoreAsyncClient.class.getMethod("deleteVolumeInRegion", + Region.class, String.class); + GeneratedHttpRequest httpMethod = processor.createRequest( + method, Region.DEFAULT, "id"); + + assertRequestLineEquals(httpMethod, "POST https://ec2.amazonaws.com/ HTTP/1.1"); + assertHeadersEqual(httpMethod, + "Content-Length: 50\nContent-Type: application/x-www-form-urlencoded\nHost: ec2.amazonaws.com\n"); + assertPayloadEquals(httpMethod, "Version=2009-11-30&Action=DeleteVolume&VolumeId=id"); + + assertResponseParserClassEquals(method, httpMethod, ReturnVoidIf2xx.class); + assertSaxResponseParserClassEquals(method, null); + assertExceptionParserClassEquals(method, null); + + checkFilters(httpMethod); + } + + public void testDescribeVolumes() throws SecurityException, NoSuchMethodException, IOException { + Method method = ElasticBlockStoreAsyncClient.class.getMethod("describeVolumesInRegion", + Region.class, Array.newInstance(String.class, 0).getClass()); + GeneratedHttpRequest httpMethod = processor.createRequest( + method, Region.DEFAULT); + + assertRequestLineEquals(httpMethod, "POST https://ec2.amazonaws.com/ HTTP/1.1"); + assertHeadersEqual(httpMethod, + "Content-Length: 41\nContent-Type: application/x-www-form-urlencoded\nHost: ec2.amazonaws.com\n"); + assertPayloadEquals(httpMethod, "Version=2009-11-30&Action=DescribeVolumes"); + + assertResponseParserClassEquals(method, httpMethod, ReturnStringIf200.class); + assertSaxResponseParserClassEquals(method, null); + // assertResponseParserClassEquals(method, httpMethod, ParseSax.class); + // assertSaxResponseParserClassEquals(method, DescribeVolumesResponseHandler.class); + assertExceptionParserClassEquals(method, null); + + checkFilters(httpMethod); + } + + public void testDescribeVolumesArgs() throws SecurityException, NoSuchMethodException, + IOException { + Method method = ElasticBlockStoreAsyncClient.class.getMethod("describeVolumesInRegion", + Region.class, Array.newInstance(String.class, 0).getClass()); + GeneratedHttpRequest httpMethod = processor.createRequest( + method, Region.DEFAULT, "1", "2"); + + assertRequestLineEquals(httpMethod, "POST https://ec2.amazonaws.com/ HTTP/1.1"); + assertHeadersEqual(httpMethod, + "Content-Length: 41\nContent-Type: application/x-www-form-urlencoded\nHost: ec2.amazonaws.com\n"); + assertPayloadEquals(httpMethod, + "Version=2009-11-30&Action=DescribeVolumes&VolumeId.1=1&VolumeId.2=2"); + + assertResponseParserClassEquals(method, httpMethod, ReturnStringIf200.class); + assertSaxResponseParserClassEquals(method, null); + // assertResponseParserClassEquals(method, httpMethod, ParseSax.class); + // assertSaxResponseParserClassEquals(method, DescribeVolumesResponseHandler.class); + assertExceptionParserClassEquals(method, null); + + checkFilters(httpMethod); + } + + @Override + protected void checkFilters(GeneratedHttpRequest httpMethod) { + assertEquals(httpMethod.getFilters().size(), 1); + assertEquals(httpMethod.getFilters().get(0).getClass(), FormSigner.class); + } + + @Override + protected TypeLiteral> createTypeLiteral() { + return new TypeLiteral>() { + }; + } + + @Override + protected Module createModule() { + return new AbstractModule() { + @Override + protected void configure() { + bind(URI.class).annotatedWith(EC2.class).toInstance( + URI.create("https://ec2.amazonaws.com")); + bindConstant().annotatedWith(Jsr330.named(AWSConstants.PROPERTY_AWS_ACCESSKEYID)).to( + "user"); + bindConstant().annotatedWith(Jsr330.named(AWSConstants.PROPERTY_AWS_SECRETACCESSKEY)) + .to("key"); + bind(Logger.LoggerFactory.class).toInstance(new LoggerFactory() { + public Logger getLogger(String category) { + return Logger.NULL; + } + }); + } + + @SuppressWarnings("unused") + @Provides + @TimeStamp + String provide() { + return "2009-11-08T15:54:08.897Z"; + } + + @SuppressWarnings("unused") + @Singleton + @Provides + Map provideMap() { + return ImmutableMap. of(Region.DEFAULT, URI.create("https://booya"), + Region.EU_WEST_1, URI.create("https://ec2.eu-west-1.amazonaws.com"), + Region.US_EAST_1, URI.create("https://ec2.us-east-1.amazonaws.com"), + Region.US_WEST_1, URI.create("https://ec2.us-west-1.amazonaws.com")); + } + }; + } +} diff --git a/aws/core/src/test/java/org/jclouds/aws/ec2/services/ElasticBlockStoreClientLiveTest.java b/aws/core/src/test/java/org/jclouds/aws/ec2/services/ElasticBlockStoreClientLiveTest.java new file mode 100644 index 0000000000..6ba644ef78 --- /dev/null +++ b/aws/core/src/test/java/org/jclouds/aws/ec2/services/ElasticBlockStoreClientLiveTest.java @@ -0,0 +1,112 @@ +/** + * + * Copyright (C) 2009 Cloud Conscious, LLC. + * + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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.assertNotNull; + +import org.jclouds.aws.ec2.EC2AsyncClient; +import org.jclouds.aws.ec2.EC2Client; +import org.jclouds.aws.ec2.EC2ContextFactory; +import org.jclouds.aws.ec2.domain.AvailabilityZone; +import org.jclouds.aws.ec2.domain.Region; +import org.jclouds.logging.log4j.config.Log4JLoggingModule; +import org.jclouds.rest.RestContext; +import org.testng.annotations.AfterTest; +import org.testng.annotations.BeforeGroups; +import org.testng.annotations.Test; + +import com.google.common.collect.ImmutableSet; + +/** + * Tests behavior of {@code ElasticBlockStoreClient} + * + * @author Adrian Cole + */ +@Test(groups = "live", sequential = true, testName = "ec2.ElasticBlockStoreClientLiveTest") +public class ElasticBlockStoreClientLiveTest { + + private ElasticBlockStoreClient client; + private RestContext context; + + @BeforeGroups(groups = { "live" }) + public void setupClient() { + String user = checkNotNull(System.getProperty("jclouds.test.user"), "jclouds.test.user"); + String password = checkNotNull(System.getProperty("jclouds.test.key"), "jclouds.test.key"); + + context = EC2ContextFactory.createContext(user, password, new Log4JLoggingModule()); + client = context.getApi().getElasticBlockStoreServices(); + } + + @Test + void testDescribeVolumes() { + for (Region region : ImmutableSet.of(Region.DEFAULT, Region.EU_WEST_1, Region.US_EAST_1, + Region.US_WEST_1)) { + System.out.println(client.describeVolumesInRegion(region)); + // SortedSet allResults = Sets.newTreeSet(client.describeVolumesInRegion(region)); + // assertNotNull(allResults); + // if (allResults.size() >= 1) { + // Volume volume = allResults.last(); + // SortedSet result = Sets.newTreeSet(client.describeVolumesInRegion(region, + // volume.getKeyName())); + // assertNotNull(result); + // Volume compare = result.last(); + // assertEquals(compare, volume); + // } + } + } + + @Test(enabled = false)// pending functionality to delete + void testCreateVolumeInAvailabilityZone() { + String result = client.createVolumeInAvailabilityZone(AvailabilityZone.US_EAST_1A, 1); + assertNotNull(result); + System.out.println(result); + // + // SortedSet result = Sets.newTreeSet(client.describeVolumesInRegion( + // Region.DEFAULT, result.getId())); + // assertNotNull(result); + // assertEquals(result.size(), 1); + // Volume volume = result.iterator().next(); + // assertEquals(volume, result); + } + + @Test + void testCreateVolumeFromSnapshotInAvailabilityZone() { + // Volume result = + // client.createVolumeFromSnapshotInAvailabilityZone(AvailabilityZone.US_EAST_1A, snapshotId); + // assertNotNull(result); + // + // SortedSet result = Sets.newTreeSet(client.describeVolumesInRegion( + // Region.DEFAULT, result.getId())); + // assertNotNull(result); + // assertEquals(result.size(), 1); + // Volume volume = result.iterator().next(); + // assertEquals(volume, result); + } + + @AfterTest + public void shutdown() { + context.close(); + } +} diff --git a/aws/core/src/test/resources/ec2/created_volume.xml b/aws/core/src/test/resources/ec2/created_volume.xml new file mode 100644 index 0000000000..acca927183 --- /dev/null +++ b/aws/core/src/test/resources/ec2/created_volume.xml @@ -0,0 +1,9 @@ + + 0c67a4c9-d7ec-45ef-8016-bf7944668962 + vol-2a21e543 + 1 + + us-east-1a + creating + 2009-12-28T05:42:53.000Z + \ No newline at end of file diff --git a/aws/core/src/test/resources/ec2/describe_volumes.xml b/aws/core/src/test/resources/ec2/describe_volumes.xml new file mode 100644 index 0000000000..245fe49703 --- /dev/null +++ b/aws/core/src/test/resources/ec2/describe_volumes.xml @@ -0,0 +1,15 @@ + + + 31ab5542-e479-44cb-aa94-c340c2481e0b + + + vol-2a21e543 + 1 + + us-east-1a + available + 2009-12-28T05:42:53.000Z + + + + \ No newline at end of file