diff --git a/README.txt b/README.txt index 20b8a9e591..9a7f6fba99 100644 --- a/README.txt +++ b/README.txt @@ -28,18 +28,19 @@ our dev version is 1.0-SNAPSHOT our compute api supports: ec2, gogrid, rackspace, rimuhosting, vcloud, trmk-ecloud, trmk-vcloudexpress, eucalyptus, bluelock-vclouddirector, - bluelock-vcloudexpress, ibmdev, slicehost + bluelock-vcloudexpress, slicehost, stub (in-memory) * note * the pom dependency org.jclouds/jclouds-allcompute gives you access to to all of these providers our blobstore api supports: s3, rackspace, azure, atmos online, att synaptic, - walrus, googlestorage, transient (in-memory) + walrus, googlestorage, transient (in-memory), filesystem (on-disk) * note * the pom dependency org.jclouds/jclouds-allblobstore gives you access to to all of these providers -we also have rest clients for: chef, opscodeplatform, pcs2 (mezeo), sdn (nirvanix), twitter +we also have rest clients for: chef, opscodeplatform, twitter, as well a number of features + in the sandbox If you want access to all jclouds components, include the maven dependency org.jclouds/jclouds-all diff --git a/all/pom.xml b/all/pom.xml index c29afbf3ab..8235fbb327 100644 --- a/all/pom.xml +++ b/all/pom.xml @@ -39,16 +39,6 @@ jclouds-allblobstore ${project.version} - - ${project.groupId} - jclouds-pcs2 - ${project.version} - - - ${project.groupId} - jclouds-sdn - ${project.version} - ${project.groupId} jclouds-twitter @@ -64,10 +54,5 @@ jclouds-opscodeplatform ${project.version} - - ${project.groupId} - jclouds-boxdotnet - ${project.version} - diff --git a/allcompute/pom.xml b/allcompute/pom.xml index 760cb00133..000e927a1f 100644 --- a/allcompute/pom.xml +++ b/allcompute/pom.xml @@ -64,11 +64,6 @@ jclouds-gogrid ${project.version} - - ${project.groupId} - jclouds-ibmdev - ${project.version} - ${project.groupId} jclouds-slicehost diff --git a/archetypes/compute-service-archetype/src/main/resources/archetype-resources/pom.xml b/archetypes/compute-service-archetype/src/main/resources/archetype-resources/pom.xml index 431a8b2600..74b8f2a1d7 100644 --- a/archetypes/compute-service-archetype/src/main/resources/archetype-resources/pom.xml +++ b/archetypes/compute-service-archetype/src/main/resources/archetype-resources/pom.xml @@ -54,7 +54,7 @@ jclouds-rimu-snapshots-nexus - http://jclouds.rimuhosting.com:8081/nexus/content/repositories/snapshots + https://oss.sonatype.org/content/repositories/snapshots true diff --git a/archetypes/json-client-archetype/src/main/resources/archetype-resources/pom.xml b/archetypes/json-client-archetype/src/main/resources/archetype-resources/pom.xml index 987c38e444..2efa11e0a5 100644 --- a/archetypes/json-client-archetype/src/main/resources/archetype-resources/pom.xml +++ b/archetypes/json-client-archetype/src/main/resources/archetype-resources/pom.xml @@ -54,7 +54,7 @@ jclouds-rimu-snapshots-nexus - http://jclouds.rimuhosting.com:8081/nexus/content/repositories/snapshots + https://oss.sonatype.org/content/repositories/snapshots true diff --git a/assemblies/src/main/resources/assemblies/package-descriptor.xml b/assemblies/src/main/resources/assemblies/package-descriptor.xml index 9afba8c97c..301cb16a0e 100644 --- a/assemblies/src/main/resources/assemblies/package-descriptor.xml +++ b/assemblies/src/main/resources/assemblies/package-descriptor.xml @@ -243,59 +243,32 @@ providers/azure - + - mezeo/pcs2/target + slicehost/target - jclouds-pcs2-${project.version}.jar + jclouds-slicehost-${project.version}.jar - providers/mezeo/lib + providers/slicehost/lib - mezeo/pcs2/target + slicehost/target - jclouds-pcs2-${project.version}-sources.jar + jclouds-slicehost-${project.version}-sources.jar - providers/mezeo/src + providers/slicehost/src - mezeo/pcs2/target/apidocs - providers/mezeo/docs + slicehost/target/apidocs + providers/slicehost/docs - mezeo/pcs2 + slicehost README.txt - providers/mezeo - - - - - nirvanix/sdn/target - - jclouds-sdn-${project.version}.jar - - providers/nirvanix/lib - - - nirvanix/sdn/target - - jclouds-sdn-${project.version}-sources.jar - - providers/nirvanix/src - - - nirvanix/sdn/target/apidocs - providers/nirvanix/docs - - - nirvanix/sdn - - README.txt - - providers/nirvanix - + providers/slicehost + @@ -324,6 +297,33 @@ providers/rackspace + + + gogrid/target + + jclouds-gogrid-${project.version}.jar + + providers/gogrid/lib + + + gogrid/target + + jclouds-gogrid-${project.version}-sources.jar + + providers/gogrid/src + + + gogrid/target/apidocs + providers/gogrid/docs + + + gogrid + + README.txt + + providers/gogrid + + rimuhosting/target @@ -351,7 +351,62 @@ providers/rimuhosting + + + vcloud/core/target + + jclouds-vcloud-${project.version}.jar + + providers/bluelock/lib + + + vcloud/core/target + + jclouds-vcloud-${project.version}-sources.jar + + providers/bluelock/src + + + vcloud/bluelock/target + + jclouds-bluelock-${project.version}.jar + + providers/bluelock/lib + + + vcloud/bluelock/target + + jclouds-bluelock-${project.version}-sources.jar + + providers/bluelock/src + + + vcloud/bluelock/target/apidocs + providers/bluelock/docs + + + vcloud/bluelock + + README.txt + + providers/bluelock + + + + vcloud/core/target + + jclouds-vcloud-${project.version}.jar + + providers/terremark/lib + + + vcloud/core/target + + jclouds-vcloud-${project.version}-sources.jar + + providers/terremark/src + vcloud/terremark/target @@ -378,6 +433,74 @@ providers/terremark + + + chef/target + + jclouds-chef-${project.version}.jar + + providers/chef/lib + + + chef/target + + jclouds-chef-${project.version}-sources.jar + + providers/chef/src + + + chef/target/apidocs + providers/chef/docs + + + chef + + README.txt + + providers/chef + + + + + chef/target + + jclouds-chef-${project.version}.jar + + providers/opscodeplatform/lib + + + chef/target + + jclouds-chef-${project.version}-sources.jar + + providers/opscodeplatform/src + + + opscodeplatform/target + + jclouds-opscodeplatform-${project.version}.jar + + providers/opscodeplatform/lib + + + opscodeplatform/target + + jclouds-opscodeplatform-${project.version}-sources.jar + + providers/opscodeplatform/src + + + opscodeplatform/target/apidocs + providers/opscodeplatform/docs + + + opscodeplatform + + README.txt + + providers/opscodeplatform + + twitter/target diff --git a/atmos/src/main/java/org/jclouds/atmosonline/saas/AtmosStorageAsyncClient.java b/atmos/src/main/java/org/jclouds/atmosonline/saas/AtmosStorageAsyncClient.java index 4c1e734f80..2ba7495fb2 100644 --- a/atmos/src/main/java/org/jclouds/atmosonline/saas/AtmosStorageAsyncClient.java +++ b/atmos/src/main/java/org/jclouds/atmosonline/saas/AtmosStorageAsyncClient.java @@ -70,6 +70,7 @@ import com.google.common.util.concurrent.ListenableFuture; */ @RequestFilters(SignRequest.class) @SkipEncoding('/') +@Path("/rest/namespace") public interface AtmosStorageAsyncClient { /** * Creates a default implementation of AtmosObject @@ -80,17 +81,16 @@ public interface AtmosStorageAsyncClient { * @see AtmosStorageClient#listDirectories */ @GET - @Path("/rest/namespace") + @Path("") @ResponseParser(ParseDirectoryListFromContentAndHeaders.class) @Consumes(MediaType.TEXT_XML) - ListenableFuture> listDirectories( - ListOptions... options); + ListenableFuture> listDirectories(ListOptions... options); /** * @see AtmosStorageClient#listDirectory */ @GET - @Path("/rest/namespace/{directoryName}/") + @Path("/{directoryName}/") @ResponseParser(ParseDirectoryListFromContentAndHeaders.class) @ExceptionParser(ThrowContainerNotFoundOn404.class) @Consumes(MediaType.TEXT_XML) @@ -101,7 +101,7 @@ public interface AtmosStorageAsyncClient { * @see AtmosStorageClient#createDirectory */ @POST - @Path("/rest/namespace/{directoryName}/") + @Path("/{directoryName}/") @ExceptionParser(ReturnEndpointIfAlreadyExists.class) @Consumes(MediaType.WILDCARD) ListenableFuture createDirectory(@PathParam("directoryName") String directoryName); @@ -110,7 +110,7 @@ public interface AtmosStorageAsyncClient { * @see AtmosStorageClient#createFile */ @POST - @Path("/rest/namespace/{parent}/{name}") + @Path("/{parent}/{name}") @Consumes(MediaType.WILDCARD) ListenableFuture createFile( @PathParam("parent") String parent, @@ -120,7 +120,7 @@ public interface AtmosStorageAsyncClient { * @see AtmosStorageClient#updateFile */ @PUT - @Path("/rest/namespace/{parent}/{name}") + @Path("/{parent}/{name}") @ExceptionParser(ThrowKeyNotFoundOn404.class) @Consumes(MediaType.WILDCARD) ListenableFuture updateFile( @@ -133,7 +133,7 @@ public interface AtmosStorageAsyncClient { @GET @ResponseParser(ParseObjectFromHeadersAndHttpContent.class) @ExceptionParser(ReturnNullOnNotFoundOr404.class) - @Path("/rest/namespace/{path}") + @Path("/{path}") @Consumes(MediaType.WILDCARD) ListenableFuture readFile(@PathParam("path") String path, GetOptions... options); @@ -143,7 +143,7 @@ public interface AtmosStorageAsyncClient { @HEAD @ResponseParser(ParseObjectFromHeadersAndHttpContent.class) @ExceptionParser(ReturnNullOnNotFoundOr404.class) - @Path("/rest/namespace/{path}") + @Path("/{path}") @Consumes(MediaType.WILDCARD) ListenableFuture headFile(@PathParam("path") String path); @@ -154,7 +154,7 @@ public interface AtmosStorageAsyncClient { @ResponseParser(ParseSystemMetadataFromHeaders.class) @ExceptionParser(ReturnNullOnNotFoundOr404.class) // currently throws 403 errors @QueryParams(keys = "metadata/system") - @Path("/rest/namespace/{path}") + @Path("/{path}") @Consumes(MediaType.WILDCARD) ListenableFuture getSystemMetadata(@PathParam("path") String path); @@ -164,7 +164,7 @@ public interface AtmosStorageAsyncClient { @HEAD @ResponseParser(ParseSystemMetadataFromHeaders.class) @ExceptionParser(ReturnNullOnNotFoundOr404.class) - @Path("/rest/namespace/{path}") + @Path("/{path}") @QueryParams(keys = "metadata/user") @Consumes(MediaType.WILDCARD) ListenableFuture getUserMetadata(@PathParam("path") String path); @@ -174,7 +174,7 @@ public interface AtmosStorageAsyncClient { */ @DELETE @ExceptionParser(ReturnVoidOnNotFoundOr404.class) - @Path("/rest/namespace/{path}") + @Path("/{path}") @Consumes(MediaType.WILDCARD) ListenableFuture deletePath(@PathParam("path") String path); @@ -183,7 +183,7 @@ public interface AtmosStorageAsyncClient { */ @HEAD @ExceptionParser(ReturnFalseOnNotFoundOr404.class) - @Path("/rest/namespace/{path}") + @Path("/{path}") @Consumes(MediaType.WILDCARD) ListenableFuture pathExists(@PathParam("path") String path); diff --git a/atmos/src/main/java/org/jclouds/atmosonline/saas/blobstore/AtmosBlobRequestSigner.java b/atmos/src/main/java/org/jclouds/atmosonline/saas/blobstore/AtmosBlobRequestSigner.java new file mode 100644 index 0000000000..ddbdfbc48a --- /dev/null +++ b/atmos/src/main/java/org/jclouds/atmosonline/saas/blobstore/AtmosBlobRequestSigner.java @@ -0,0 +1,81 @@ +/** + * + * Copyright (C) 2010 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.atmosonline.saas.blobstore; + +import static com.google.common.base.Preconditions.checkNotNull; +import static org.jclouds.blobstore.util.BlobStoreUtils.cleanRequest; + +import java.lang.reflect.Method; + +import javax.inject.Inject; +import javax.inject.Singleton; + +import org.jclouds.atmosonline.saas.AtmosStorageAsyncClient; +import org.jclouds.atmosonline.saas.blobstore.functions.BlobToObject; +import org.jclouds.atmosonline.saas.domain.AtmosObject; +import org.jclouds.blobstore.BlobRequestSigner; +import org.jclouds.blobstore.domain.Blob; +import org.jclouds.http.HttpRequest; +import org.jclouds.http.options.GetOptions; +import org.jclouds.rest.internal.RestAnnotationProcessor; + +/** + * + * @author Adrian Cole + */ +@Singleton +public class AtmosBlobRequestSigner implements BlobRequestSigner { + private final RestAnnotationProcessor processor; + private final BlobToObject blobToObject; + private final Method getMethod; + private final Method deleteMethod; + private final Method createMethod; + + @Inject + public AtmosBlobRequestSigner(RestAnnotationProcessor processor, BlobToObject blobToObject) + throws SecurityException, NoSuchMethodException { + this.processor = checkNotNull(processor, "processor"); + this.blobToObject = checkNotNull(blobToObject, "blobToObject"); + this.getMethod = AtmosStorageAsyncClient.class.getMethod("readFile", String.class, GetOptions[].class); + this.deleteMethod = AtmosStorageAsyncClient.class.getMethod("deletePath", String.class); + this.createMethod = AtmosStorageAsyncClient.class.getMethod("createFile", String.class, AtmosObject.class); + + } + + @Override + public HttpRequest signGetBlob(String container, String name) { + return cleanRequest(processor.createRequest(getMethod, getPath(container, name))); + } + + @Override + public HttpRequest signPutBlob(String container, Blob blob) { + return cleanRequest(processor.createRequest(createMethod, container, blobToObject.apply(blob))); + } + + @Override + public HttpRequest signRemoveBlob(String container, String name) { + return cleanRequest(processor.createRequest(deleteMethod, getPath(container, name))); + } + + private String getPath(String container, String name) { + return checkNotNull(container, "container") + "/" + checkNotNull(name, "name"); + } + +} \ No newline at end of file diff --git a/atmos/src/main/java/org/jclouds/atmosonline/saas/blobstore/config/AtmosBlobStoreContextModule.java b/atmos/src/main/java/org/jclouds/atmosonline/saas/blobstore/config/AtmosBlobStoreContextModule.java index b3c9786ae5..8183cdadd0 100755 --- a/atmos/src/main/java/org/jclouds/atmosonline/saas/blobstore/config/AtmosBlobStoreContextModule.java +++ b/atmos/src/main/java/org/jclouds/atmosonline/saas/blobstore/config/AtmosBlobStoreContextModule.java @@ -26,9 +26,11 @@ import javax.inject.Singleton; import org.jclouds.atmosonline.saas.AtmosStorageAsyncClient; import org.jclouds.atmosonline.saas.AtmosStorageClient; import org.jclouds.atmosonline.saas.blobstore.AtmosAsyncBlobStore; +import org.jclouds.atmosonline.saas.blobstore.AtmosBlobRequestSigner; import org.jclouds.atmosonline.saas.blobstore.AtmosBlobStore; import org.jclouds.atmosonline.saas.blobstore.strategy.FindMD5InUserMetadata; import org.jclouds.blobstore.AsyncBlobStore; +import org.jclouds.blobstore.BlobRequestSigner; import org.jclouds.blobstore.BlobStore; import org.jclouds.blobstore.BlobStoreContext; import org.jclouds.blobstore.attr.ConsistencyModel; @@ -65,6 +67,7 @@ public class AtmosBlobStoreContextModule extends AbstractModule { new TypeLiteral>() { }).in(Scopes.SINGLETON); bind(ContainsValueInListStrategy.class).to(FindMD5InUserMetadata.class); + bind(BlobRequestSigner.class).to(AtmosBlobRequestSigner.class); } @Provides diff --git a/atmos/src/test/java/org/jclouds/atmosonline/saas/AtmosStorageAsyncClientTest.java b/atmos/src/test/java/org/jclouds/atmosonline/saas/AtmosStorageAsyncClientTest.java index 7626e5103d..1636d957d5 100644 --- a/atmos/src/test/java/org/jclouds/atmosonline/saas/AtmosStorageAsyncClientTest.java +++ b/atmos/src/test/java/org/jclouds/atmosonline/saas/AtmosStorageAsyncClientTest.java @@ -72,7 +72,7 @@ public class AtmosStorageAsyncClientTest extends RestClientTest + * + * ==================================================================== + * 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.atmosonline.saas.blobstore; + +import static org.testng.Assert.assertEquals; + +import java.io.IOException; +import java.util.Properties; + +import org.jclouds.atmosonline.saas.AtmosStorageAsyncClient; +import org.jclouds.atmosonline.saas.config.AtmosStorageRestClientModule; +import org.jclouds.atmosonline.saas.filters.SignRequest; +import org.jclouds.blobstore.BlobRequestSigner; +import org.jclouds.blobstore.domain.Blob; +import org.jclouds.blobstore.domain.Blob.Factory; +import org.jclouds.date.TimeStamp; +import org.jclouds.http.HttpRequest; +import org.jclouds.http.RequiresHttp; +import org.jclouds.io.payloads.PhantomPayload; +import org.jclouds.rest.ConfiguresRestClient; +import org.jclouds.rest.RestClientTest; +import org.jclouds.rest.RestContextFactory; +import org.jclouds.rest.RestContextFactory.ContextSpec; +import org.jclouds.rest.internal.RestAnnotationProcessor; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.Test; + +import com.google.common.base.Supplier; +import com.google.inject.Module; +import com.google.inject.TypeLiteral; + +@Test(groups = "unit", testName = "emcsaas.AtmosBlobRequestSignerTest") +public class AtmosBlobRequestSignerTest extends RestClientTest { + + private BlobRequestSigner signer; + private Factory blobFactory; + + public void testSignGetBlob() throws ArrayIndexOutOfBoundsException, SecurityException, IllegalArgumentException, + NoSuchMethodException, IOException { + HttpRequest request = signer.signGetBlob("container", "name"); + + assertRequestLineEquals(request, "GET https://accesspoint.atmosonline.com/rest/namespace/container/name HTTP/1.1"); + assertNonPayloadHeadersEqual( + request, + "Accept: */*\nDate: Thu, 05 Jun 2008 16:38:19 GMT\nx-emc-signature: Mhe5tqaKv04BlMvEjreNKkHHxzk=\nx-emc-uid: identity\n"); + assertPayloadEquals(request, null, null, false); + + assertEquals(request.getFilters().size(), 0); + } + + public void testSignRemoveBlob() throws ArrayIndexOutOfBoundsException, SecurityException, IllegalArgumentException, + NoSuchMethodException, IOException { + HttpRequest request = signer.signRemoveBlob("container", "name"); + + assertRequestLineEquals(request, + "DELETE https://accesspoint.atmosonline.com/rest/namespace/container/name HTTP/1.1"); + assertNonPayloadHeadersEqual( + request, + "Accept: */*\nDate: Thu, 05 Jun 2008 16:38:19 GMT\nx-emc-signature: Q3zmO6KNAViNXquiCZSMx/0nuuc=\nx-emc-uid: identity\n"); + assertPayloadEquals(request, null, null, false); + + assertEquals(request.getFilters().size(), 0); + } + + public void testSignPutBlob() throws ArrayIndexOutOfBoundsException, SecurityException, IllegalArgumentException, + NoSuchMethodException, IOException { + Blob blob = blobFactory.create(null); + blob.getMetadata().setName("name"); + blob.setPayload(new PhantomPayload(2l, new byte[] { 0, 2, 4, 8 })); + blob.getPayload().setContentType("text/plain"); + + HttpRequest request = signer.signPutBlob("container", blob); + + assertRequestLineEquals(request, + "POST https://accesspoint.atmosonline.com/rest/namespace/container/name HTTP/1.1"); + assertNonPayloadHeadersEqual( + request, + "Accept: */*\nDate: Thu, 05 Jun 2008 16:38:19 GMT\nx-emc-signature: aLpB1oQaCA27AXT6Nzam7s0f0pI=\nx-emc-uid: identity\n"); + + assertContentHeadersEqual(request, "text/plain", (long) 2l, new byte[] { 0, 2, 4, 8 }); + + assertEquals(request.getFilters().size(), 0); + } + + @BeforeClass + protected void setupFactory() throws IOException { + super.setupFactory(); + this.blobFactory = injector.getInstance(Blob.Factory.class); + this.signer = injector.getInstance(BlobRequestSigner.class); + } + + @Override + protected void checkFilters(HttpRequest request) { + assertEquals(request.getFilters().size(), 1); + assertEquals(request.getFilters().get(0).getClass(), SignRequest.class); + } + + @Override + protected TypeLiteral> createTypeLiteral() { + return new TypeLiteral>() { + }; + } + + @Override + protected Module createModule() { + return new TestAtmosStorageRestClientModule(); + } + + @RequiresHttp + @ConfiguresRestClient + private static final class TestAtmosStorageRestClientModule extends AtmosStorageRestClientModule { + @Override + protected void configure() { + super.configure(); + } + + @Override + protected String provideTimeStamp(@TimeStamp Supplier cache) { + return "Thu, 05 Jun 2008 16:38:19 GMT"; + } + } + + @Override + public ContextSpec createContextSpec() { + return new RestContextFactory().createContextSpec("atmosonline", "identity", "credential", new Properties()); + } + +} \ No newline at end of file diff --git a/atmos/src/test/java/org/jclouds/atmosonline/saas/blobstore/integration/AtmosBlobSignerLiveTest.java b/atmos/src/test/java/org/jclouds/atmosonline/saas/blobstore/integration/AtmosBlobSignerLiveTest.java new file mode 100644 index 0000000000..44867392a4 --- /dev/null +++ b/atmos/src/test/java/org/jclouds/atmosonline/saas/blobstore/integration/AtmosBlobSignerLiveTest.java @@ -0,0 +1,32 @@ +/** + * + * Copyright (C) 2010 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.atmosonline.saas.blobstore.integration; + +import org.jclouds.blobstore.integration.internal.BaseBlobSignerLiveTest; +import org.testng.annotations.Test; + +/** + * + * @author Adrian Cole + */ +@Test(groups = { "live" }, testName = "emcsaas.AtmosBlobSignerLiveTest") +public class AtmosBlobSignerLiveTest extends BaseBlobSignerLiveTest { + +} \ No newline at end of file diff --git a/atmos/src/test/java/org/jclouds/atmosonline/saas/blobstore/integration/AtmosStorageTestInitializer.java b/atmos/src/test/java/org/jclouds/atmosonline/saas/blobstore/integration/AtmosStorageTestInitializer.java index 0c370d4402..e71b4899fe 100644 --- a/atmos/src/test/java/org/jclouds/atmosonline/saas/blobstore/integration/AtmosStorageTestInitializer.java +++ b/atmos/src/test/java/org/jclouds/atmosonline/saas/blobstore/integration/AtmosStorageTestInitializer.java @@ -39,7 +39,7 @@ public class AtmosStorageTestInitializer extends TransientBlobStoreTestInitializ @Override protected BlobStoreContext createLiveContext(Module configurationModule, String url, String app, String identity, String credential) throws IOException { - return new BlobStoreContextFactory().createContext("atmosonline", identity, credential, ImmutableSet + return new BlobStoreContextFactory().createContext("synaptic", identity, credential, ImmutableSet .of(configurationModule, new Log4JLoggingModule()), new Properties()); } diff --git a/aws/core/src/main/java/org/jclouds/aws/ec2/EC2PropertiesBuilder.java b/aws/core/src/main/java/org/jclouds/aws/ec2/EC2PropertiesBuilder.java index 0056a0d203..b8ad68742f 100644 --- a/aws/core/src/main/java/org/jclouds/aws/ec2/EC2PropertiesBuilder.java +++ b/aws/core/src/main/java/org/jclouds/aws/ec2/EC2PropertiesBuilder.java @@ -45,8 +45,8 @@ public class EC2PropertiesBuilder extends PropertiesBuilder { properties.setProperty(PROPERTY_ENDPOINT, "https://ec2.us-east-1.amazonaws.com"); properties.setProperty(PROPERTY_API_VERSION, EC2AsyncClient.VERSION); properties.setProperty(PROPERTY_ELB_ENDPOINT, "https://elasticloadbalancing.us-east-1.amazonaws.com"); - // alestic, canonical, and rightscale - properties.setProperty(PROPERTY_EC2_AMI_OWNERS, "063491364108,099720109477,411009282317"); + // amazon, alestic, canonical, and rightscale + properties.setProperty(PROPERTY_EC2_AMI_OWNERS, "137112412989,063491364108,099720109477,411009282317"); // amis that work with the cluster instances properties.setProperty(PROPERTY_EC2_CC_AMIs, "us-east-1/ami-7ea24a17"); // auth fail sometimes happens in EC2, as the rc.local script that injects the diff --git a/vcloud/bluelock/src/main/java/org/jclouds/vcloud/bluelock/BlueLockVCloudExpressPropertiesBuilder.java b/aws/core/src/main/java/org/jclouds/aws/ec2/NovaPropertiesBuilder.java similarity index 65% rename from vcloud/bluelock/src/main/java/org/jclouds/vcloud/bluelock/BlueLockVCloudExpressPropertiesBuilder.java rename to aws/core/src/main/java/org/jclouds/aws/ec2/NovaPropertiesBuilder.java index c8a5e99529..83b60f77a7 100644 --- a/vcloud/bluelock/src/main/java/org/jclouds/vcloud/bluelock/BlueLockVCloudExpressPropertiesBuilder.java +++ b/aws/core/src/main/java/org/jclouds/aws/ec2/NovaPropertiesBuilder.java @@ -17,30 +17,31 @@ * ==================================================================== */ -package org.jclouds.vcloud.bluelock; +package org.jclouds.aws.ec2; import static org.jclouds.Constants.PROPERTY_ENDPOINT; -import static org.jclouds.vcloud.reference.VCloudConstants.PROPERTY_VCLOUD_DEFAULT_NETWORK; +import static org.jclouds.aws.ec2.reference.EC2Constants.PROPERTY_EC2_AMI_OWNERS; +import static org.jclouds.aws.ec2.reference.EC2Constants.PROPERTY_EC2_CC_AMIs; import java.util.Properties; -import org.jclouds.vcloud.VCloudExpressPropertiesBuilder; - /** - * Builds properties used in bluelock VCloud Clients + * Builds properties used in Eucalyptus Clients * * @author Adrian Cole */ -public class BlueLockVCloudExpressPropertiesBuilder extends VCloudExpressPropertiesBuilder { +public class NovaPropertiesBuilder extends EC2PropertiesBuilder { @Override protected Properties defaultProperties() { Properties properties = super.defaultProperties(); - properties.setProperty(PROPERTY_ENDPOINT, "https://express.bluelock.com/api"); - properties.setProperty(PROPERTY_VCLOUD_DEFAULT_NETWORK, "Internal In and Out"); + properties.setProperty(PROPERTY_ENDPOINT, "YOU_MUST_SET_" + PROPERTY_ENDPOINT); + properties.setProperty(PROPERTY_EC2_AMI_OWNERS, "*"); + properties.setProperty(PROPERTY_EC2_CC_AMIs, ""); return properties; } - public BlueLockVCloudExpressPropertiesBuilder(Properties properties) { + public NovaPropertiesBuilder(Properties properties) { super(properties); } + } diff --git a/aws/core/src/main/java/org/jclouds/aws/ec2/compute/EC2ComputeService.java b/aws/core/src/main/java/org/jclouds/aws/ec2/compute/EC2ComputeService.java index 21f7acc751..e547b780a2 100644 --- a/aws/core/src/main/java/org/jclouds/aws/ec2/compute/EC2ComputeService.java +++ b/aws/core/src/main/java/org/jclouds/aws/ec2/compute/EC2ComputeService.java @@ -45,7 +45,7 @@ import org.jclouds.aws.ec2.domain.PlacementGroup.State; import org.jclouds.compute.ComputeServiceContext; import org.jclouds.compute.domain.Image; import org.jclouds.compute.domain.NodeMetadata; -import org.jclouds.compute.domain.Size; +import org.jclouds.compute.domain.Hardware; import org.jclouds.compute.domain.TemplateBuilder; import org.jclouds.compute.internal.BaseComputeService; import org.jclouds.compute.options.TemplateOptions; @@ -75,7 +75,7 @@ public class EC2ComputeService extends BaseComputeService { @Inject protected EC2ComputeService(ComputeServiceContext context, Supplier> images, - Supplier> sizes, Supplier> locations, + Supplier> sizes, Supplier> locations, ListNodesStrategy listNodesStrategy, GetNodeMetadataStrategy getNodeMetadataStrategy, RunNodesAndAddToSetStrategy runNodesAndAddToSetStrategy, RebootNodeStrategy rebootNodeStrategy, DestroyNodeStrategy destroyNodeStrategy, Provider templateBuilderProvider, diff --git a/aws/core/src/main/java/org/jclouds/aws/ec2/compute/config/EC2ComputeServiceContextModule.java b/aws/core/src/main/java/org/jclouds/aws/ec2/compute/config/EC2ComputeServiceContextModule.java index 283a1b6f92..e126db52c1 100755 --- a/aws/core/src/main/java/org/jclouds/aws/ec2/compute/config/EC2ComputeServiceContextModule.java +++ b/aws/core/src/main/java/org/jclouds/aws/ec2/compute/config/EC2ComputeServiceContextModule.java @@ -24,6 +24,7 @@ import static com.google.common.collect.Maps.newLinkedHashMap; import static org.jclouds.Constants.PROPERTY_SESSION_INTERVAL; import static org.jclouds.aws.ec2.reference.EC2Constants.PROPERTY_EC2_AMI_OWNERS; import static org.jclouds.aws.ec2.reference.EC2Constants.PROPERTY_EC2_CC_AMIs; +import static org.jclouds.compute.domain.OsFamily.AMZN_LINUX; import static org.jclouds.compute.domain.OsFamily.CENTOS; import static org.jclouds.compute.domain.OsFamily.UBUNTU; @@ -36,7 +37,6 @@ import java.util.concurrent.TimeUnit; import javax.inject.Named; import javax.inject.Singleton; -import org.jclouds.aws.Region; import org.jclouds.aws.ec2.EC2AsyncClient; import org.jclouds.aws.ec2.EC2Client; import org.jclouds.aws.ec2.compute.EC2ComputeService; @@ -54,13 +54,12 @@ import org.jclouds.aws.ec2.compute.strategy.EC2ListNodesStrategy; import org.jclouds.aws.ec2.compute.strategy.EC2LoadBalanceNodesStrategy; import org.jclouds.aws.ec2.compute.strategy.EC2RebootNodeStrategy; import org.jclouds.aws.ec2.compute.strategy.EC2RunNodesAndAddToSetStrategy; +import org.jclouds.aws.ec2.compute.suppliers.EC2HardwareSupplier; import org.jclouds.aws.ec2.compute.suppliers.EC2LocationSupplier; -import org.jclouds.aws.ec2.compute.suppliers.EC2SizeSupplier; import org.jclouds.aws.ec2.compute.suppliers.RegionAndNameToImageSupplier; import org.jclouds.aws.ec2.domain.KeyPair; import org.jclouds.aws.ec2.domain.PlacementGroup; import org.jclouds.aws.ec2.domain.RunningInstance; -import org.jclouds.aws.ec2.functions.RunningInstanceToStorageMappingUnix; import org.jclouds.aws.ec2.predicates.InstancePresent; import org.jclouds.aws.ec2.predicates.PlacementGroupAvailable; import org.jclouds.aws.ec2.predicates.PlacementGroupDeleted; @@ -69,8 +68,8 @@ import org.jclouds.compute.ComputeService; import org.jclouds.compute.ComputeServiceContext; import org.jclouds.compute.config.BaseComputeServiceContextModule; import org.jclouds.compute.config.ComputeServiceTimeoutsModule; +import org.jclouds.compute.domain.Hardware; import org.jclouds.compute.domain.Image; -import org.jclouds.compute.domain.Size; import org.jclouds.compute.domain.TemplateBuilder; import org.jclouds.compute.internal.ComputeServiceContextImpl; import org.jclouds.compute.options.TemplateOptions; @@ -84,6 +83,7 @@ import org.jclouds.compute.strategy.RunNodesAndAddToSetStrategy; import org.jclouds.domain.Location; import org.jclouds.predicates.RetryablePredicate; import org.jclouds.rest.RestContext; +import org.jclouds.rest.annotations.Provider; import org.jclouds.rest.internal.RestContextImpl; import org.jclouds.rest.suppliers.RetryOnTimeOutButNotOnAuthorizationExceptionSupplier; @@ -99,7 +99,6 @@ import com.google.inject.Key; import com.google.inject.Provides; import com.google.inject.Scopes; import com.google.inject.TypeLiteral; -import com.google.inject.name.Names; /** * Configures the {@link ComputeServiceContext}; requires {@link EC2ComputeService} bound. @@ -148,8 +147,6 @@ public class EC2ComputeServiceContextModule extends BaseComputeServiceContextMod bind(GetNodeMetadataStrategy.class).to(EC2GetNodeMetadataStrategy.class); bind(RebootNodeStrategy.class).to(EC2RebootNodeStrategy.class); bind(DestroyNodeStrategy.class).to(EC2DestroyNodeStrategy.class); - bind(new TypeLiteral>>() { - }).annotatedWith(Names.named("volumeMapping")).to(RunningInstanceToStorageMappingUnix.class).in(Scopes.SINGLETON); } @Provides @@ -168,9 +165,13 @@ public class EC2ComputeServiceContextModule extends BaseComputeServiceContextMod @Override protected TemplateBuilder provideTemplate(Injector injector, TemplateBuilder template) { - String region = injector.getInstance(Key.get(String.class, Region.class)); - return "Eucalyptus".equals(region) ? template.osFamily(CENTOS).smallest() : template.os64Bit(false).osFamily( - UBUNTU).osVersionMatches(".*10\\.?04.*").osDescriptionMatches("^ubuntu-images.*"); + String provider = injector.getInstance(Key.get(String.class, Provider.class)); + if ("eucalyptus".equals(provider)) + return template.osFamily(CENTOS); + else if ("nova".equals(provider)) + return template.osFamily(UBUNTU); + else + return template.osFamily(AMZN_LINUX).os64Bit(true); } @Provides @@ -255,8 +256,8 @@ public class EC2ComputeServiceContextModule extends BaseComputeServiceContextMod } @Override - protected Supplier> getSourceSizeSupplier(Injector injector) { - return injector.getInstance(EC2SizeSupplier.class); + protected Supplier> getSourceSizeSupplier(Injector injector) { + return injector.getInstance(EC2HardwareSupplier.class); } @Override diff --git a/aws/core/src/main/java/org/jclouds/aws/ec2/compute/domain/EC2Hardware.java b/aws/core/src/main/java/org/jclouds/aws/ec2/compute/domain/EC2Hardware.java new file mode 100644 index 0000000000..f96cc46414 --- /dev/null +++ b/aws/core/src/main/java/org/jclouds/aws/ec2/compute/domain/EC2Hardware.java @@ -0,0 +1,197 @@ +/** + * + * Copyright (C) 2010 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.compute.domain; + +import static com.google.common.base.Preconditions.checkNotNull; +import static com.google.common.base.Predicates.not; +import static org.jclouds.compute.predicates.ImagePredicates.any; +import static org.jclouds.compute.predicates.ImagePredicates.idIn; +import static org.jclouds.compute.predicates.ImagePredicates.is64Bit; + +import java.util.Arrays; + +import org.jclouds.aws.ec2.domain.InstanceType; +import org.jclouds.aws.ec2.domain.RootDeviceType; +import org.jclouds.compute.domain.Image; +import org.jclouds.compute.domain.Processor; +import org.jclouds.compute.domain.Volume; +import org.jclouds.compute.domain.internal.HardwareImpl; +import org.jclouds.compute.domain.internal.VolumeImpl; +import org.jclouds.domain.Location; + +import com.google.common.base.Predicate; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; + +/** + * + * @author Adrian Cole + * @see + */ +public class EC2Hardware extends HardwareImpl { + /** The serialVersionUID */ + private static final long serialVersionUID = 8605688733788974797L; + private final String instanceType; + + /** + * evaluates true if the Image has the following rootDeviceType + * + * @param type + * rootDeviceType of the image + * @return predicate + */ + public static Predicate hasRootDeviceType(final RootDeviceType type) { + checkNotNull(type, "type must be defined"); + return new Predicate() { + @Override + public boolean apply(Image image) { + return type.toString().equals(image.getUserMetadata().get("rootDeviceType")); + } + + @Override + public String toString() { + return "hasRootDeviceType(" + type + ")"; + } + }; + } + + EC2Hardware(String instanceType, Iterable processors, Integer ram, + Iterable volumes, RootDeviceType rootDeviceType) { + this(null, instanceType, processors, ram, volumes, hasRootDeviceType(rootDeviceType)); + } + + EC2Hardware(Location location, String instanceType, Iterable processors, Integer ram, + Iterable volumes, Predicate supportsImage) { + super(instanceType, instanceType, instanceType, location, null, ImmutableMap. of(), processors, + ram, volumes, supportsImage); + this.instanceType = instanceType; + } + + EC2Hardware(String instanceType, Iterable processors, Integer ram, + Iterable volumes, boolean is64Bit) { + this(null, instanceType, processors, ram, volumes, is64Bit ? is64Bit() : not(is64Bit())); + } + + public EC2Hardware(Location location, String instanceType, Iterable processors, Integer ram, + Iterable volumes, String[] ids) { + this(location, instanceType, processors, ram, volumes, (ids.length == 0 ? is64Bit() : idIn(Arrays.asList(ids)))); + } + + /** + * Returns the EC2 InstanceType associated with this size. + */ + public String getInstanceType() { + return instanceType; + } + + /** + * @see InstanceType#M1_SMALL + */ + public static final EC2Hardware M1_SMALL = new EC2Hardware(InstanceType.M1_SMALL, ImmutableList.of(new Processor( + 1.0, 1.0)), 1740, ImmutableList.of(new VolumeImpl(10.0f, "/dev/sda1", true, false), new VolumeImpl(150.0f, + "/dev/sda2", false, false)), false); + /** + * In Nova, m1.small can run 64bit images. + * + * @see InstanceType#M1_SMALL + */ + public static final EC2Hardware M1_SMALL_NOVA = new EC2Hardware(null, InstanceType.M1_SMALL, ImmutableList + .of(new Processor(1.0, 1.0)), 1740, ImmutableList.of(new VolumeImpl(10.0f, "/dev/sda1", true, false), + new VolumeImpl(150.0f, "/dev/sda2", false, false)), any()); + + /** + * @see InstanceType#T1_MICRO + */ + public static final EC2Hardware T1_MICRO = new EC2Hardware(InstanceType.T1_MICRO, ImmutableList.of(new Processor( + 1.0, 1.0)), 630, ImmutableList. of(), RootDeviceType.EBS); + /** + * @see InstanceType#M1_LARGE + */ + public static final EC2Hardware M1_LARGE = new EC2Hardware(InstanceType.M1_LARGE, ImmutableList.of(new Processor( + 2.0, 2.0)), 7680, ImmutableList.of(new VolumeImpl(10.0f, "/dev/sda1", true, false), new VolumeImpl(420.0f, + "/dev/sdb", false, false), new VolumeImpl(420.0f, "/dev/sdc", false, false)), true); + + /** + * @see InstanceType#M1_XLARGE + */ + public static final EC2Hardware M1_XLARGE = new EC2Hardware(InstanceType.M1_XLARGE, ImmutableList.of(new Processor( + 4.0, 2.0)), 15360, ImmutableList.of(new VolumeImpl(10.0f, "/dev/sda1", true, false), new VolumeImpl(420.0f, + "/dev/sdb", false, false), new VolumeImpl(420.0f, "/dev/sdc", false, false), new VolumeImpl(420.0f, + "/dev/sdd", false, false), new VolumeImpl(420.0f, "/dev/sde", false, false)), true); + /** + * @see InstanceType#M2_XLARGE + */ + public static final EC2Hardware M2_XLARGE = new EC2Hardware(InstanceType.M2_XLARGE, ImmutableList.of(new Processor( + 2.0, 3.25)), 17510, ImmutableList.of(new VolumeImpl(420.0f, "/dev/sda1", true, false)), true); + /** + * @see InstanceType#M2_2XLARGE + */ + public static final EC2Hardware M2_2XLARGE = new EC2Hardware(InstanceType.M2_2XLARGE, ImmutableList + .of(new Processor(4.0, 3.25)), 35020, ImmutableList.of(new VolumeImpl(10.0f, "/dev/sda1", true, false), + new VolumeImpl(840.0f, "/dev/sdb", false, false)), true); + /** + * @see InstanceType#M2_4XLARGE + */ + public static final EC2Hardware M2_4XLARGE = new EC2Hardware(InstanceType.M2_4XLARGE, ImmutableList + .of(new Processor(8.0, 3.25)), 70041, ImmutableList.of(new VolumeImpl(10.0f, "/dev/sda1", true, false), + new VolumeImpl(840.0f, "/dev/sdb", false, false), new VolumeImpl(840.0f, "/dev/sdc", false, false)), true); + /** + * @see InstanceType#C1_MEDIUM + */ + public static final EC2Hardware C1_MEDIUM = new EC2Hardware(InstanceType.C1_MEDIUM, ImmutableList.of(new Processor( + 2.0, 2.5)), 1740, ImmutableList.of(new VolumeImpl(10.0f, "/dev/sda1", true, false), new VolumeImpl(340.0f, + "/dev/sda2", false, false)), false); + + /** + * @see InstanceType#C1_XLARGE + */ + public static final EC2Hardware C1_XLARGE = new EC2Hardware(InstanceType.C1_XLARGE, ImmutableList.of(new Processor( + 8.0, 2.5)), 7168, ImmutableList.of(new VolumeImpl(10.0f, "/dev/sda1", true, false), new VolumeImpl(420.0f, + "/dev/sdb", false, false), new VolumeImpl(420.0f, "/dev/sdc", false, false), new VolumeImpl(420.0f, + "/dev/sdd", false, false), new VolumeImpl(420.0f, "/dev/sde", false, false)), true); + + @Override + public int hashCode() { + final int prime = 31; + int result = super.hashCode(); + result = prime * result + ((instanceType == null) ? 0 : instanceType.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (!super.equals(obj)) + return false; + if (getClass() != obj.getClass()) + return false; + EC2Hardware other = (EC2Hardware) obj; + if (instanceType == null) { + if (other.instanceType != null) + return false; + } else if (!instanceType.equals(other.instanceType)) + return false; + return true; + } + +} diff --git a/aws/core/src/main/java/org/jclouds/aws/ec2/compute/domain/EC2Size.java b/aws/core/src/main/java/org/jclouds/aws/ec2/compute/domain/EC2Size.java deleted file mode 100644 index 6b1b7957dc..0000000000 --- a/aws/core/src/main/java/org/jclouds/aws/ec2/compute/domain/EC2Size.java +++ /dev/null @@ -1,121 +0,0 @@ -/** - * - * Copyright (C) 2010 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.compute.domain; - -import static com.google.common.base.Predicates.not; -import static org.jclouds.compute.predicates.ImagePredicates.idIn; -import static org.jclouds.compute.predicates.ImagePredicates.is64Bit; - -import java.util.Arrays; - -import org.jclouds.aws.ec2.domain.InstanceType; -import org.jclouds.compute.domain.internal.SizeImpl; -import org.jclouds.domain.Location; - -import com.google.common.collect.ImmutableMap; - -/** - * - * @author Adrian Cole - */ -public class EC2Size extends SizeImpl { - /** The serialVersionUID */ - private static final long serialVersionUID = 8605688733788974797L; - private final String instanceType; - - EC2Size(String instanceType, Double cores, Integer ram, Integer disk, boolean is64Bit) { - super(instanceType, instanceType, instanceType, null, null, ImmutableMap. of(), cores, ram, disk, - is64Bit ? is64Bit() : not(is64Bit())); - this.instanceType = instanceType; - } - - public EC2Size(Location location, String instanceType, Double cores, Integer ram, Integer disk, String[] ids) { - super(instanceType, instanceType, instanceType, location, null, ImmutableMap. of(), cores, ram, - disk, (ids.length == 0 ? is64Bit() : idIn(Arrays.asList(ids)))); - this.instanceType = instanceType; - } - - /** - * Returns the EC2 InstanceType associated with this size. - */ - public String getInstanceType() { - return instanceType; - } - - /** - * @see InstanceType#M1_SMALL - */ - public static final EC2Size M1_SMALL = new EC2Size(InstanceType.M1_SMALL, 1.0, 1740, 160, false); - /** - * @see InstanceType#M1_LARGE - */ - public static final EC2Size M1_LARGE = new EC2Size(InstanceType.M1_LARGE, 4.0, 7680, 850, true); - /** - * @see InstanceType#M1_XLARGE - */ - public static final EC2Size M1_XLARGE = new EC2Size(InstanceType.M1_XLARGE, 8.0, 15360, 1690, true); - /** - * @see InstanceType#M2_XLARGE - */ - public static final EC2Size M2_XLARGE = new EC2Size(InstanceType.M2_XLARGE, 6.5, 17510, 420, true); - /** - * @see InstanceType#M2_2XLARGE - */ - public static final EC2Size M2_2XLARGE = new EC2Size(InstanceType.M2_2XLARGE, 13.0, 35020, 850, true); - /** - * @see InstanceType#M2_4XLARGE - */ - public static final EC2Size M2_4XLARGE = new EC2Size(InstanceType.M2_4XLARGE, 26.0, 70041, 1690, true); - /** - * @see InstanceType#C1_MEDIUM - */ - public static final EC2Size C1_MEDIUM = new EC2Size(InstanceType.C1_MEDIUM, 5.0, 1740, 350, false); - - /** - * @see InstanceType#C1_XLARGE - */ - public static final EC2Size C1_XLARGE = new EC2Size(InstanceType.C1_XLARGE, 20.0, 7168, 1690, true); - - @Override - public int hashCode() { - final int prime = 31; - int result = super.hashCode(); - result = prime * result + ((instanceType == null) ? 0 : instanceType.hashCode()); - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) - return true; - if (!super.equals(obj)) - return false; - if (getClass() != obj.getClass()) - return false; - EC2Size other = (EC2Size) obj; - if (instanceType == null) { - if (other.instanceType != null) - return false; - } else if (!instanceType.equals(other.instanceType)) - return false; - return true; - } - -} diff --git a/aws/core/src/main/java/org/jclouds/aws/ec2/compute/functions/CreateSecurityGroupIfNeeded.java b/aws/core/src/main/java/org/jclouds/aws/ec2/compute/functions/CreateSecurityGroupIfNeeded.java index 86b2ee7ef3..aac80ecade 100644 --- a/aws/core/src/main/java/org/jclouds/aws/ec2/compute/functions/CreateSecurityGroupIfNeeded.java +++ b/aws/core/src/main/java/org/jclouds/aws/ec2/compute/functions/CreateSecurityGroupIfNeeded.java @@ -26,7 +26,6 @@ import javax.inject.Inject; import javax.inject.Named; import javax.inject.Singleton; -import org.jclouds.aws.AWSResponseException; import org.jclouds.aws.ec2.EC2Client; import org.jclouds.aws.ec2.compute.domain.RegionNameAndIngressRules; import org.jclouds.aws.ec2.domain.IpProtocol; @@ -72,13 +71,8 @@ public class CreateSecurityGroupIfNeeded implements Function 0) { authorizeGroupToItself(region, name); } - } catch (AWSResponseException e) { - if (e.getError().getCode().equals("InvalidGroup.Duplicate") - || e.getError().getMessage().endsWith("already exists")) { - logger.debug("<< reused securityGroup(%s)", name); - } else { - throw e; - } + } catch (IllegalStateException e) { + logger.debug("<< reused securityGroup(%s)", name); } } diff --git a/aws/core/src/main/java/org/jclouds/aws/ec2/compute/functions/ImageParser.java b/aws/core/src/main/java/org/jclouds/aws/ec2/compute/functions/ImageParser.java index 5fb2d1103e..1c300d533e 100644 --- a/aws/core/src/main/java/org/jclouds/aws/ec2/compute/functions/ImageParser.java +++ b/aws/core/src/main/java/org/jclouds/aws/ec2/compute/functions/ImageParser.java @@ -46,6 +46,7 @@ import org.jclouds.domain.Location; import org.jclouds.domain.LocationScope; import org.jclouds.domain.internal.LocationImpl; import org.jclouds.logging.Logger; +import org.jclouds.rest.annotations.Provider; import com.google.common.base.Function; import com.google.common.base.Predicate; @@ -62,6 +63,17 @@ public class ImageParser implements Function> locations; private final Supplier defaultLocation; + private final String provider; @Inject ImageParser(PopulateDefaultLoginCredentialsForImageStrategy credentialProvider, - Supplier> locations, Supplier defaultLocation) { + Supplier> locations, Supplier defaultLocation, @Provider String provider) { this.credentialProvider = checkNotNull(credentialProvider, "credentialProvider"); this.locations = checkNotNull(locations, "locations"); this.defaultLocation = checkNotNull(defaultLocation, "defaultLocation"); - + this.provider = checkNotNull(provider, "provider"); } @Override public Image apply(final org.jclouds.aws.ec2.domain.Image from) { - if (from.getImageLocation().indexOf("test") != -1) { - logger.trace("skipping test image(%s)", from.getId()); - return null; - } if (from.getImageType() != ImageType.MACHINE) { logger.trace("skipping as not a machine image(%s)", from.getId()); return null; @@ -100,7 +109,7 @@ public class ImageParser implements Function of("owner", from.getImageOwnerId()), os, description, version, defaultCredentials); + . of("owner", from.getImageOwnerId(), "rootDeviceType", from.getRootDeviceType() + .toString()), os, description, version, defaultCredentials); } @@ -146,7 +163,8 @@ public class ImageParser implements Function credentialsMap; private final PopulateDefaultLoginCredentialsForImageStrategy credentialProvider; private final Supplier> locations; - private final Function> instanceToStorageMapping; + private final Supplier> hardware; private final ConcurrentMap imageMap; @Inject RunningInstanceToNodeMetadata(EC2Client client, Map credentialsMap, PopulateDefaultLoginCredentialsForImageStrategy credentialProvider, ConcurrentMap imageMap, Supplier> locations, - @Named("volumeMapping") Function> instanceToStorageMapping) { + Supplier> hardware) { this.client = checkNotNull(client, "client"); this.credentialsMap = checkNotNull(credentialsMap, "credentialsMap"); this.credentialProvider = checkNotNull(credentialProvider, "credentialProvider"); this.locations = checkNotNull(locations, "locations"); - this.instanceToStorageMapping = checkNotNull(instanceToStorageMapping, "instanceToStorageMapping"); + this.hardware = checkNotNull(hardware, "hardware"); this.imageMap = checkNotNull(imageMap, "imageMap"); } @@ -110,15 +116,47 @@ public class RunningInstanceToNodeMetadata implements Function publicAddresses = nullSafeSet(instance.getIpAddress()); Set privateAddresses = nullSafeSet(instance.getPrivateIpAddress()); - Map extra = getExtra(instance); + Hardware hardware = getHardwareForInstance(instance); - Location location = getLocationForAvailabilityZone(instance); + if (hardware != null) { + hardware = ComputeServiceUtils.replacesVolumes(hardware, addEBS(instance, hardware.getVolumes())); + } + + Location location = getLocationForAvailabilityZoneOrRegion(instance); Image image = resolveImageForInstanceInLocation(instance, location); return new NodeMetadataImpl(id, name, instance.getRegion() + "/" + instance.getId(), location, uri, userMetadata, - tag, instance.getRegion() + "/" + instance.getImageId(), image != null ? image.getOperatingSystem() - : null, state, publicAddresses, privateAddresses, extra, credentials); + tag, hardware, instance.getRegion() + "/" + instance.getImageId(), image != null ? image + .getOperatingSystem() : null, state, publicAddresses, privateAddresses, credentials); + } + + @VisibleForTesting + static Iterable addEBS(final RunningInstance instance, Iterable volumes) { + Iterable ebsVolumes = Iterables.transform(instance.getEbsBlockDevices().entrySet(), + new Function, Volume>() { + + @Override + public Volume apply(Entry from) { + return new VolumeImpl(from.getValue().getVolumeId(), Volume.Type.SAN, null, from.getKey(), + instance.getRootDeviceName() != null + && instance.getRootDeviceName().equals(from.getKey()), true); + } + }); + + if (instance.getRootDeviceType() == RootDeviceType.EBS) { + volumes = Iterables.filter(volumes, new Predicate() { + + @Override + public boolean apply(Volume input) { + return !input.isBootDevice(); + } + + }); + + } + return Iterables.concat(volumes, ebsVolumes); + } private Credentials getCredentialsForInstanceWithTag(final RunningInstance instance, String tag) { @@ -152,20 +190,48 @@ public class RunningInstanceToNodeMetadata implements Function() { - Location location = Iterables.find(locations.get(), new Predicate() { + @Override + public boolean apply(Hardware input) { + return input.getId().equals(instance.getInstanceType()); + } - @Override - public boolean apply(Location input) { - return input.getId().equals(locationId); - } + }); + } catch (NoSuchElementException e) { + logger.debug("couldn't match instance type %s in: %s", instance.getInstanceType(), hardware.get()); + return null; + } + } - }); + private Location getLocationForAvailabilityZoneOrRegion(final RunningInstance instance) { + Location location = findLocationWithId(instance.getAvailabilityZone()); + if (location == null) + location = findLocationWithId(instance.getRegion()); return location; } + private Location findLocationWithId(final String locationId) { + try { + Location location = Iterables.find(locations.get(), new Predicate() { + + @Override + public boolean apply(Location input) { + return input.getId().equals(locationId); + } + + }); + return location; + + } catch (NoSuchElementException e) { + logger.debug("couldn't match instance location %s in: %s", locationId, locations.get()); + return null; + } + } + @VisibleForTesting Image resolveImageForInstanceInLocation(final RunningInstance instance, final Location location) { Image image = null; @@ -174,34 +240,12 @@ public class RunningInstanceToNodeMetadata implements Function getExtra(RunningInstance instance) { - Map extra = Maps.newHashMap(); - extra.put("virtualizationType", instance.getVirtualizationType()); - if (instance.getPlacementGroup() != null) - extra.put("placementGroup", instance.getPlacementGroup()); - if (instance.getSubnetId() != null) - extra.put("subnetId", instance.getSubnetId()); - // put storage info - /* TODO: only valid for UNIX */ - extra.putAll(instanceToStorageMapping.apply(instance)); - - return extra; - } - @VisibleForTesting String getPrivateKeyOrNull(RunningInstance instance, String tag) { KeyPair keyPair = credentialsMap.get(new RegionAndName(instance.getRegion(), instance.getKeyName())); @@ -210,8 +254,13 @@ public class RunningInstanceToNodeMetadata implements Function> locations, Supplier> images, - Supplier> sizes, Supplier defaultLocation, + Supplier> sizes, Supplier defaultLocation, Provider optionsProvider, @Named("DEFAULT") Provider defaultTemplateProvider, ConcurrentMap imageMap) { @@ -91,6 +92,8 @@ public class EC2TemplateBuilderImpl extends TemplateBuilderImpl { return imageMap.get(key); } catch (NullPointerException nex) { throw new NoSuchElementException(String.format("image %s/%s not found", key.getRegion(), key.getName())); + } catch (ComputationException nex) { + throw new NoSuchElementException(String.format("image %s/%s not found", key.getRegion(), key.getName())); } } return null; @@ -103,7 +106,7 @@ public class EC2TemplateBuilderImpl extends TemplateBuilderImpl { * if the image is not found */ @Override - protected Image resolveImage(Size size, Iterable supportedImages) { + protected Image resolveImage(Hardware size, Iterable supportedImages) { try { return super.resolveImage(size, supportedImages); } catch (NoSuchElementException e) { diff --git a/aws/core/src/main/java/org/jclouds/aws/ec2/compute/strategy/CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptions.java b/aws/core/src/main/java/org/jclouds/aws/ec2/compute/strategy/CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptions.java index e8009ebec3..b18c854c2e 100644 --- a/aws/core/src/main/java/org/jclouds/aws/ec2/compute/strategy/CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptions.java +++ b/aws/core/src/main/java/org/jclouds/aws/ec2/compute/strategy/CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptions.java @@ -30,7 +30,7 @@ import javax.inject.Inject; import javax.inject.Named; import javax.inject.Singleton; -import org.jclouds.aws.ec2.compute.domain.EC2Size; +import org.jclouds.aws.ec2.compute.domain.EC2Hardware; import org.jclouds.aws.ec2.compute.domain.RegionAndName; import org.jclouds.aws.ec2.compute.domain.RegionNameAndIngressRules; import org.jclouds.aws.ec2.compute.functions.CreatePlacementGroupIfNeeded; @@ -79,9 +79,9 @@ public class CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptions } public RunInstancesOptions execute(String region, String tag, Template template) { - checkArgument(template.getSize() instanceof EC2Size, "unexpected image type. should be EC2Size, was: " - + template.getSize().getClass()); - EC2Size ec2Size = EC2Size.class.cast(template.getSize()); + checkArgument(template.getHardware() instanceof EC2Hardware, "unexpected image type. should be EC2Size, was: " + + template.getHardware().getClass()); + EC2Hardware ec2Size = EC2Hardware.class.cast(template.getHardware()); RunInstancesOptions instanceOptions = asType(ec2Size.getInstanceType()).withAdditionalInfo(tag); diff --git a/aws/core/src/main/java/org/jclouds/aws/ec2/compute/strategy/EC2PopulateDefaultLoginCredentialsForImageStrategy.java b/aws/core/src/main/java/org/jclouds/aws/ec2/compute/strategy/EC2PopulateDefaultLoginCredentialsForImageStrategy.java index 2e3d55e21c..6fda83850e 100644 --- a/aws/core/src/main/java/org/jclouds/aws/ec2/compute/strategy/EC2PopulateDefaultLoginCredentialsForImageStrategy.java +++ b/aws/core/src/main/java/org/jclouds/aws/ec2/compute/strategy/EC2PopulateDefaultLoginCredentialsForImageStrategy.java @@ -20,7 +20,6 @@ package org.jclouds.aws.ec2.compute.strategy; import static com.google.common.base.Preconditions.checkArgument; -import static com.google.common.base.Preconditions.checkNotNull; import javax.inject.Singleton; @@ -37,18 +36,18 @@ public class EC2PopulateDefaultLoginCredentialsForImageStrategy implements @Override public Credentials execute(Object resourceToAuthenticate) { - checkNotNull(resourceToAuthenticate); - checkArgument(resourceToAuthenticate instanceof Image, "Resource must be an image (for EC2)"); - Image image = (Image) resourceToAuthenticate; - - Credentials credentials; - - // canonical/alestic images use the ubuntu user to login - if (image.getImageOwnerId().matches("063491364108|099720109477")) - credentials = new Credentials("ubuntu", null); - else - credentials = new Credentials("root", null); - + Credentials credentials = new Credentials("root", null); + if (resourceToAuthenticate != null) { + checkArgument(resourceToAuthenticate instanceof Image, "Resource must be an image (for EC2)"); + Image image = (Image) resourceToAuthenticate; + // canonical/alestic images use the ubuntu user to login + if (image.getImageOwnerId().matches("063491364108|099720109477")) { + credentials = new Credentials("ubuntu", null); + // http://aws.typepad.com/aws/2010/09/introducing-amazon-linux-ami.html + } else if (image.getImageOwnerId().equals("137112412989")) { + credentials = new Credentials("ec2-user", null); + } + } return credentials; } } diff --git a/aws/core/src/main/java/org/jclouds/aws/ec2/compute/suppliers/EC2SizeSupplier.java b/aws/core/src/main/java/org/jclouds/aws/ec2/compute/suppliers/EC2HardwareSupplier.java similarity index 61% rename from aws/core/src/main/java/org/jclouds/aws/ec2/compute/suppliers/EC2SizeSupplier.java rename to aws/core/src/main/java/org/jclouds/aws/ec2/compute/suppliers/EC2HardwareSupplier.java index 68a43d5849..16c081ea4e 100644 --- a/aws/core/src/main/java/org/jclouds/aws/ec2/compute/suppliers/EC2SizeSupplier.java +++ b/aws/core/src/main/java/org/jclouds/aws/ec2/compute/suppliers/EC2HardwareSupplier.java @@ -30,16 +30,20 @@ import javax.inject.Inject; import javax.inject.Named; import javax.inject.Singleton; -import org.jclouds.aws.ec2.compute.domain.EC2Size; +import org.jclouds.aws.ec2.compute.domain.EC2Hardware; import org.jclouds.aws.ec2.domain.InstanceType; -import org.jclouds.compute.domain.Size; +import org.jclouds.compute.domain.Hardware; +import org.jclouds.compute.domain.Processor; +import org.jclouds.compute.domain.internal.VolumeImpl; import org.jclouds.compute.reference.ComputeServiceConstants; import org.jclouds.domain.Location; import org.jclouds.domain.LocationScope; import org.jclouds.logging.Logger; +import org.jclouds.rest.annotations.Provider; import com.google.common.base.Predicate; import com.google.common.base.Supplier; +import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableSet; /** @@ -47,22 +51,25 @@ import com.google.common.collect.ImmutableSet; * @author Adrian Cole */ @Singleton -public class EC2SizeSupplier implements Supplier> { +public class EC2HardwareSupplier implements Supplier> { @Resource @Named(ComputeServiceConstants.COMPUTE_LOGGER) protected Logger logger = Logger.NULL; private final Supplier> locations; private final String[] ccAmis; + private final String providerName; @Inject - EC2SizeSupplier(Supplier> locations, @Named(PROPERTY_EC2_CC_AMIs) String[] ccAmis) { + EC2HardwareSupplier(Supplier> locations, @Provider String providerName, + @Named(PROPERTY_EC2_CC_AMIs) String[] ccAmis) { this.locations = locations; this.ccAmis = ccAmis; + this.providerName = providerName; } @Override - public Set get() { - Set sizes = newHashSet(); + public Set get() { + Set sizes = newHashSet(); for (String ccAmi : ccAmis) { final String region = ccAmi.split("/")[0]; Location location = find(locations.get(), new Predicate() { @@ -73,10 +80,14 @@ public class EC2SizeSupplier implements Supplier> { } }); - sizes.add(new EC2Size(location, InstanceType.CC1_4XLARGE, 33.5, 23 * 1024, 1690, ccAmis)); + sizes.add(new EC2Hardware(location, InstanceType.CC1_4XLARGE, ImmutableList.of(new Processor(4.0, 4.0), + new Processor(4.0, 4.0)), 23 * 1024, ImmutableList.of( + new VolumeImpl(10.0f, "/dev/sda1", true, false), new VolumeImpl(840.0f, "/dev/sdb", false, false), + new VolumeImpl(840.0f, "/dev/sdc", false, false)), ccAmis)); } - sizes.addAll(ImmutableSet. of(EC2Size.C1_MEDIUM, EC2Size.C1_XLARGE, EC2Size.M1_LARGE, EC2Size.M1_SMALL, - EC2Size.M1_XLARGE, EC2Size.M2_XLARGE, EC2Size.M2_2XLARGE, EC2Size.M2_4XLARGE)); + sizes.addAll(ImmutableSet. of(EC2Hardware.T1_MICRO, EC2Hardware.C1_MEDIUM, EC2Hardware.C1_XLARGE, + EC2Hardware.M1_LARGE, "nova".equals(providerName) ? EC2Hardware.M1_SMALL_NOVA : EC2Hardware.M1_SMALL, + EC2Hardware.M1_XLARGE, EC2Hardware.M2_XLARGE, EC2Hardware.M2_2XLARGE, EC2Hardware.M2_4XLARGE)); return sizes; } } \ No newline at end of file diff --git a/aws/core/src/main/java/org/jclouds/aws/ec2/domain/InstanceType.java b/aws/core/src/main/java/org/jclouds/aws/ec2/domain/InstanceType.java index 40eecd2257..6c7e203e5c 100644 --- a/aws/core/src/main/java/org/jclouds/aws/ec2/domain/InstanceType.java +++ b/aws/core/src/main/java/org/jclouds/aws/ec2/domain/InstanceType.java @@ -32,6 +32,16 @@ import org.jclouds.aws.ec2.EC2AsyncClient; * */ public class InstanceType { + /** + * Micro Instance + *
    + *
  • 613 MB of memory
  • + *
  • up to 2 ECUs (for short periodic bursts)
  • + *
  • No instance storage (EBS storage only)
  • + *
  • 32-bit or 64-bit platform
  • + *
+ */ + public static final String T1_MICRO = "t1.micro"; /** * Small Instance *