diff --git a/README.txt b/README.txt index d5bc557537..6fbeb8f7de 100644 --- a/README.txt +++ b/README.txt @@ -26,7 +26,7 @@ two abstractions at the moment: compute and blobstore. compute helps you bootstrap machines in the cloud. blobstore helps you manage key-value data. -our current version is 1.0-beta-7 +our current version is 1.0-beta-8 our dev version is 1.0-SNAPSHOT our compute api supports: ec2, gogrid, cloudservers (rackspace), rimuhosting, vcloud, @@ -102,13 +102,13 @@ Compute Example (Clojure): (run-nodes "mycluster" 2)) Downloads: - * distribution zip: http://jclouds.googlecode.com/files/jclouds-1.0-beta-7.zip + * distribution zip: http://jclouds.googlecode.com/files/jclouds-1.0-beta-8.zip * maven repo: http://jclouds.googlecode.com/svn/repo * snapshot repo: http://jclouds.rimuhosting.com/maven2/snapshots Links: * project page: http://code.google.com/p/jclouds/ - * javadocs (1.0-beta-7): http://jclouds.rimuhosting.com/apidocs/ + * javadocs (1.0-beta-8): http://jclouds.rimuhosting.com/apidocs/ * javadocs (1.0-SNAPSHOT): http://jclouds.rimuhosting.com/apidocs-SNAPSHOT/ * community: http://code.google.com/p/jclouds/wiki/AppsThatUseJClouds * user group: http://groups.google.com/group/jclouds diff --git a/atmos/src/main/java/org/jclouds/atmosonline/saas/domain/AtmosObject.java b/atmos/src/main/java/org/jclouds/atmosonline/saas/domain/AtmosObject.java index 2580857ae4..00e942bd77 100644 --- a/atmos/src/main/java/org/jclouds/atmosonline/saas/domain/AtmosObject.java +++ b/atmos/src/main/java/org/jclouds/atmosonline/saas/domain/AtmosObject.java @@ -19,10 +19,11 @@ package org.jclouds.atmosonline.saas.domain; +import javax.annotation.Nullable; + import org.jclouds.io.PayloadEnclosing; import com.google.common.collect.Multimap; -import com.google.inject.internal.Nullable; /** * Amazon Atmos is designed to store objects. Objects are stored in buckets and consist of a 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 681b81acc3..c1ab245837 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 @@ -116,7 +116,7 @@ public class EC2ComputeService extends BaseComputeService { ec2Client.getPlacementGroupServices().deletePlacementGroupInRegion(region, group); checkState(placementGroupDeleted.apply(new PlacementGroup(region, group, "cluster", State.PENDING)), String.format("placementGroup region(%s) name(%s) failed to delete", region, group)); - placementGroupMap.remove(new RegionAndName(region, tag)); + placementGroupMap.remove(new RegionAndName(region, group)); logger.debug("<< deleted placementGroup(%s)", group); } catch (AWSResponseException e) { if (e.getError().getCode().equals("InvalidPlacementGroup.InUse")) { @@ -142,7 +142,7 @@ public class EC2ComputeService extends BaseComputeService { logger.debug(">> deleting securityGroup(%s)", group); ec2Client.getSecurityGroupServices().deleteSecurityGroupInRegion(region, group); // TODO: test this clear happens - securityGroupMap.remove(new RegionNameAndIngressRules(region, tag, null, false)); + securityGroupMap.remove(new RegionNameAndIngressRules(region, group, null, false)); logger.debug("<< deleted securityGroup(%s)", group); } } diff --git a/aws/core/src/main/java/org/jclouds/aws/ec2/compute/functions/RegionAndIdToImage.java b/aws/core/src/main/java/org/jclouds/aws/ec2/compute/functions/RegionAndIdToImage.java index 1414db2ae9..310b30f9ca 100644 --- a/aws/core/src/main/java/org/jclouds/aws/ec2/compute/functions/RegionAndIdToImage.java +++ b/aws/core/src/main/java/org/jclouds/aws/ec2/compute/functions/RegionAndIdToImage.java @@ -29,7 +29,6 @@ import org.jclouds.aws.ec2.EC2Client; import org.jclouds.aws.ec2.compute.domain.RegionAndName; import org.jclouds.compute.domain.Image; import org.jclouds.logging.Logger; -import org.jclouds.rest.ResourceNotFoundException; import com.google.common.base.Function; import com.google.common.collect.Iterables; @@ -55,11 +54,10 @@ public final class RegionAndIdToImage implements Function public Image apply(RegionAndName key) { try { org.jclouds.aws.ec2.domain.Image image = Iterables.getOnlyElement(sync.getAMIServices() - .describeImagesInRegion(key.getRegion(), imageIds(key.getName()))); + .describeImagesInRegion(key.getRegion(), imageIds(key.getName()))); return parser.apply(image); - } catch (ResourceNotFoundException e) { - logger.warn(e, "no image found for %s/%s: %s", key.getRegion(), key.getName(), e - .getMessage()); + } catch (Exception e) { + logger.warn(e, "could not find image %s/%s: %s", key.getRegion(), key.getName(), e.getMessage()); return null; } } diff --git a/aws/core/src/main/java/org/jclouds/aws/ec2/compute/functions/RunningInstanceToNodeMetadata.java b/aws/core/src/main/java/org/jclouds/aws/ec2/compute/functions/RunningInstanceToNodeMetadata.java index e73e225ddf..c3a9daaf15 100644 --- a/aws/core/src/main/java/org/jclouds/aws/ec2/compute/functions/RunningInstanceToNodeMetadata.java +++ b/aws/core/src/main/java/org/jclouds/aws/ec2/compute/functions/RunningInstanceToNodeMetadata.java @@ -101,9 +101,20 @@ public class RunningInstanceToNodeMetadata implements Function + * + * ==================================================================== + * 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.s3.blobstore; + +import java.util.List; +import java.util.Properties; + +import org.jclouds.aws.s3.S3ContextBuilder; +import org.jclouds.aws.s3.blobstore.config.ScaleUpCloudBlobStoreContextModule; + +import com.google.inject.Module; + +/** + * + * @author Adrian Cole + */ +public class ScaleUpCloudBlobStoreContextContextBuilder extends S3ContextBuilder { + + public ScaleUpCloudBlobStoreContextContextBuilder(Properties props) { + super(props); + } + + @Override + protected void addContextModule(List modules) { + modules.add(new ScaleUpCloudBlobStoreContextModule()); + } + +} \ No newline at end of file diff --git a/aws/core/src/main/java/org/jclouds/aws/s3/blobstore/config/S3BlobStoreContextModule.java b/aws/core/src/main/java/org/jclouds/aws/s3/blobstore/config/S3BlobStoreContextModule.java index 9ca1d87698..2a93fee09a 100755 --- a/aws/core/src/main/java/org/jclouds/aws/s3/blobstore/config/S3BlobStoreContextModule.java +++ b/aws/core/src/main/java/org/jclouds/aws/s3/blobstore/config/S3BlobStoreContextModule.java @@ -29,6 +29,8 @@ import org.jclouds.aws.s3.S3Client; import org.jclouds.aws.s3.blobstore.S3AsyncBlobStore; import org.jclouds.aws.s3.blobstore.S3BlobRequestSigner; import org.jclouds.aws.s3.blobstore.S3BlobStore; +import org.jclouds.aws.s3.blobstore.functions.LocationFromBucketLocation; +import org.jclouds.aws.s3.domain.BucketMetadata; import org.jclouds.aws.suppliers.DefaultLocationSupplier; import org.jclouds.blobstore.AsyncBlobStore; import org.jclouds.blobstore.BlobRequestSigner; @@ -43,6 +45,7 @@ import org.jclouds.domain.LocationScope; import org.jclouds.domain.internal.LocationImpl; import org.jclouds.rest.annotations.Provider; +import com.google.common.base.Function; import com.google.common.base.Supplier; import com.google.common.base.Suppliers; import com.google.common.collect.Sets; @@ -70,6 +73,12 @@ public class S3BlobStoreContextModule extends AbstractModule { bind(BlobStoreContext.class).to(new TypeLiteral>() { }).in(Scopes.SINGLETON); bind(BlobRequestSigner.class).to(S3BlobRequestSigner.class); + bindBucketLocationStrategy(); + } + + protected void bindBucketLocationStrategy() { + bind(new TypeLiteral>() { + }).to(LocationFromBucketLocation.class); } @Provides diff --git a/aws/core/src/main/java/org/jclouds/aws/s3/blobstore/config/ScaleUpCloudBlobStoreContextModule.java b/aws/core/src/main/java/org/jclouds/aws/s3/blobstore/config/ScaleUpCloudBlobStoreContextModule.java new file mode 100644 index 0000000000..771d3fbc2f --- /dev/null +++ b/aws/core/src/main/java/org/jclouds/aws/s3/blobstore/config/ScaleUpCloudBlobStoreContextModule.java @@ -0,0 +1,41 @@ +/** + * + * 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.s3.blobstore.config; + +import org.jclouds.aws.s3.domain.BucketMetadata; +import org.jclouds.domain.Location; + +import com.google.common.base.Function; +import com.google.common.base.Functions; +import com.google.inject.TypeLiteral; + +/** + * + * @author Adrian Cole + */ +public class ScaleUpCloudBlobStoreContextModule extends S3BlobStoreContextModule { + + @SuppressWarnings("rawtypes") + @Override + protected void bindBucketLocationStrategy() { + bind(new TypeLiteral>() { + }).toInstance((Function)Functions.constant(null)); + } +} diff --git a/aws/core/src/main/java/org/jclouds/aws/s3/blobstore/functions/BucketToResourceMetadata.java b/aws/core/src/main/java/org/jclouds/aws/s3/blobstore/functions/BucketToResourceMetadata.java index a1a891be0b..85b33c9219 100644 --- a/aws/core/src/main/java/org/jclouds/aws/s3/blobstore/functions/BucketToResourceMetadata.java +++ b/aws/core/src/main/java/org/jclouds/aws/s3/blobstore/functions/BucketToResourceMetadata.java @@ -19,80 +19,36 @@ package org.jclouds.aws.s3.blobstore.functions; -import java.util.NoSuchElementException; -import java.util.Set; -import javax.annotation.Resource; import javax.inject.Inject; import javax.inject.Singleton; -import org.jclouds.aws.s3.S3Client; import org.jclouds.aws.s3.domain.BucketMetadata; -import org.jclouds.blobstore.ContainerNotFoundException; import org.jclouds.blobstore.domain.MutableStorageMetadata; import org.jclouds.blobstore.domain.StorageMetadata; import org.jclouds.blobstore.domain.StorageType; import org.jclouds.blobstore.domain.internal.MutableStorageMetadataImpl; -import org.jclouds.collect.Memoized; import org.jclouds.domain.Location; -import org.jclouds.logging.Logger; import com.google.common.base.Function; -import com.google.common.base.Predicate; -import com.google.common.base.Supplier; -import com.google.common.collect.Iterables; /** * @author Adrian Cole */ @Singleton public class BucketToResourceMetadata implements Function { - private final S3Client client; - private final Location onlyLocation; - private final Supplier> locations; - - @Resource - protected Logger logger = Logger.NULL; + private final Function locationOfBucket; @Inject - BucketToResourceMetadata(S3Client client, @Memoized Supplier> locations) { - this.client = client; - this.onlyLocation = locations.get().size() == 1 ? Iterables.get(locations.get(), 0) : null; - this.locations = locations; + BucketToResourceMetadata(Function locationOfBucket) { + this.locationOfBucket = locationOfBucket; } public StorageMetadata apply(BucketMetadata from) { MutableStorageMetadata to = new MutableStorageMetadataImpl(); to.setName(from.getName()); to.setType(StorageType.CONTAINER); - to.setLocation(onlyLocation != null ? onlyLocation : getLocation(from)); + to.setLocation(locationOfBucket.apply(from)); return to; } - - private Location getLocation(BucketMetadata from) { - try { - Set locations = this.locations.get(); - final String region = client.getBucketLocation(from.getName()); - assert region != null : String.format("could not get region for %s", from.getName()); - if (region != null) { - try { - return Iterables.find(locations, new Predicate() { - - @Override - public boolean apply(Location input) { - return input.getId().equalsIgnoreCase(region.toString()); - } - - }); - } catch (NoSuchElementException e) { - logger.error("could not get location for region %s in %s", region, locations); - } - } else { - logger.error("could not get region for %s", from.getName()); - } - } catch (ContainerNotFoundException e) { - logger.error(e, "could not get region for %s, as service suggests the bucket doesn't exist", from.getName()); - } - return null; - } } \ No newline at end of file diff --git a/aws/core/src/main/java/org/jclouds/aws/s3/blobstore/functions/LocationFromBucketLocation.java b/aws/core/src/main/java/org/jclouds/aws/s3/blobstore/functions/LocationFromBucketLocation.java new file mode 100644 index 0000000000..3a3c62814f --- /dev/null +++ b/aws/core/src/main/java/org/jclouds/aws/s3/blobstore/functions/LocationFromBucketLocation.java @@ -0,0 +1,88 @@ +/** + * + * 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.s3.blobstore.functions; + +import java.util.NoSuchElementException; +import java.util.Set; + +import javax.annotation.Resource; +import javax.inject.Inject; +import javax.inject.Singleton; + +import org.jclouds.aws.s3.S3Client; +import org.jclouds.aws.s3.domain.BucketMetadata; +import org.jclouds.blobstore.ContainerNotFoundException; +import org.jclouds.collect.Memoized; +import org.jclouds.domain.Location; +import org.jclouds.logging.Logger; + +import com.google.common.base.Function; +import com.google.common.base.Predicate; +import com.google.common.base.Supplier; +import com.google.common.collect.Iterables; + +/** + * @author Adrian Cole + */ +@Singleton +public class LocationFromBucketLocation implements Function { + private final Location onlyLocation; + private final Supplier> locations; + private final S3Client client; + + @Resource + protected Logger logger = Logger.NULL; + + @Inject + LocationFromBucketLocation(S3Client client, @Memoized Supplier> locations) { + this.client = client; + this.onlyLocation = locations.get().size() == 1 ? Iterables.get(locations.get(), 0) : null; + this.locations = locations; + } + + public Location apply(BucketMetadata from) { + if (onlyLocation != null) + return onlyLocation; + try { + Set locations = this.locations.get(); + final String region = client.getBucketLocation(from.getName()); + assert region != null : String.format("could not get region for %s", from.getName()); + if (region != null) { + try { + return Iterables.find(locations, new Predicate() { + + @Override + public boolean apply(Location input) { + return input.getId().equalsIgnoreCase(region.toString()); + } + + }); + } catch (NoSuchElementException e) { + logger.error("could not get location for region %s in %s", region, locations); + } + } else { + logger.error("could not get region for %s", from.getName()); + } + } catch (ContainerNotFoundException e) { + logger.error(e, "could not get region for %s, as service suggests the bucket doesn't exist", from.getName()); + } + return null; + } +} \ No newline at end of file diff --git a/aws/core/src/main/java/org/jclouds/aws/s3/domain/S3Object.java b/aws/core/src/main/java/org/jclouds/aws/s3/domain/S3Object.java index da4478e78b..bf2c43695a 100644 --- a/aws/core/src/main/java/org/jclouds/aws/s3/domain/S3Object.java +++ b/aws/core/src/main/java/org/jclouds/aws/s3/domain/S3Object.java @@ -19,10 +19,11 @@ package org.jclouds.aws.s3.domain; +import javax.annotation.Nullable; + import org.jclouds.io.PayloadEnclosing; import com.google.common.collect.Multimap; -import com.google.inject.internal.Nullable; /** * Amazon S3 is designed to store objects. Objects are stored in buckets and consist of a diff --git a/aws/core/src/main/java/org/jclouds/aws/s3/functions/ReturnFalseIfBucketAlreadyOwnedByYou.java b/aws/core/src/main/java/org/jclouds/aws/s3/functions/ReturnFalseIfBucketAlreadyOwnedByYou.java index 2aa6a30213..a9512fd53e 100755 --- a/aws/core/src/main/java/org/jclouds/aws/s3/functions/ReturnFalseIfBucketAlreadyOwnedByYou.java +++ b/aws/core/src/main/java/org/jclouds/aws/s3/functions/ReturnFalseIfBucketAlreadyOwnedByYou.java @@ -19,8 +19,14 @@ package org.jclouds.aws.s3.functions; +import static com.google.common.base.Throwables.getCausalChain; +import static com.google.common.collect.Iterables.filter; +import static com.google.common.collect.Iterables.get; +import static com.google.common.collect.Iterables.size; import static org.jclouds.util.Utils.propagateOrNull; +import java.util.List; + import javax.inject.Singleton; import org.jclouds.aws.AWSResponseException; @@ -35,11 +41,12 @@ import com.google.common.base.Function; public class ReturnFalseIfBucketAlreadyOwnedByYou implements Function { public Boolean apply(Exception from) { - if (from instanceof AWSResponseException) { - AWSResponseException responseException = (AWSResponseException) from; - if ("BucketAlreadyOwnedByYou".equals(responseException.getError().getCode())) { + List throwables = getCausalChain(from); + + Iterable matchingAWSResponseException = filter(throwables, AWSResponseException.class); + if (size(matchingAWSResponseException) >= 1 && get(matchingAWSResponseException, 0).getError() != null) { + if (get(matchingAWSResponseException, 0).getError().getCode().equals("BucketAlreadyOwnedByYou")) return false; - } } return Boolean.class.cast(propagateOrNull(from)); } diff --git a/aws/core/src/test/java/org/jclouds/aws/ec2/compute/EC2ComputeServiceLiveTest.java b/aws/core/src/test/java/org/jclouds/aws/ec2/compute/EC2ComputeServiceLiveTest.java index 5465771925..496d7c0b7c 100644 --- a/aws/core/src/test/java/org/jclouds/aws/ec2/compute/EC2ComputeServiceLiveTest.java +++ b/aws/core/src/test/java/org/jclouds/aws/ec2/compute/EC2ComputeServiceLiveTest.java @@ -106,7 +106,7 @@ public class EC2ComputeServiceLiveTest extends BaseComputeServiceLiveTest { InstanceClient instanceClient = EC2Client.class.cast(context.getProviderSpecificContext().getApi()) .getInstanceServices(); - String tag = this.tag + "optionsandlogin"; + String tag = this.tag + "o"; TemplateOptions options = client.templateOptions(); @@ -190,7 +190,7 @@ public class EC2ComputeServiceLiveTest extends BaseComputeServiceLiveTest { InstanceClient instanceClient = EC2Client.class.cast(context.getProviderSpecificContext().getApi()) .getInstanceServices(); - String tag = this.tag + "optionsnokey"; + String tag = this.tag + "k"; TemplateOptions options = client.templateOptions(); @@ -250,7 +250,7 @@ public class EC2ComputeServiceLiveTest extends BaseComputeServiceLiveTest { InstanceClient instanceClient = EC2Client.class.cast(context.getProviderSpecificContext().getApi()) .getInstanceServices(); - String tag = this.tag + "optionswithsubnetid"; + String tag = this.tag + "g"; TemplateOptions options = client.templateOptions(); diff --git a/aws/core/src/test/java/org/jclouds/aws/ec2/compute/EucalyptusComputeServiceLiveTestDisabled.java b/aws/core/src/test/java/org/jclouds/aws/ec2/compute/EucalyptusComputeServiceLiveTestDisabled.java index a61b0659a3..c85cfe7bb0 100644 --- a/aws/core/src/test/java/org/jclouds/aws/ec2/compute/EucalyptusComputeServiceLiveTestDisabled.java +++ b/aws/core/src/test/java/org/jclouds/aws/ec2/compute/EucalyptusComputeServiceLiveTestDisabled.java @@ -43,7 +43,7 @@ public class EucalyptusComputeServiceLiveTestDisabled extends EC2ComputeServiceL @Override public void setServiceDefaults() { // security groups must be <30 characters - tag = "euc"; + tag = "eu"; } @Override diff --git a/aws/core/src/test/java/org/jclouds/aws/ec2/compute/TestCanRecreateTagLiveTest.java b/aws/core/src/test/java/org/jclouds/aws/ec2/compute/TestCanRecreateTagLiveTest.java new file mode 100644 index 0000000000..b706ccb0f3 --- /dev/null +++ b/aws/core/src/test/java/org/jclouds/aws/ec2/compute/TestCanRecreateTagLiveTest.java @@ -0,0 +1,106 @@ +/** + * + * 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; + +import static com.google.common.base.Preconditions.checkNotNull; + +import java.io.FileNotFoundException; +import java.io.IOException; +import java.util.Properties; + +import org.jclouds.Constants; +import org.jclouds.compute.ComputeServiceContext; +import org.jclouds.compute.ComputeServiceContextFactory; +import org.jclouds.compute.RunNodesException; +import org.jclouds.compute.predicates.NodePredicates; +import org.jclouds.logging.log4j.config.Log4JLoggingModule; +import org.jclouds.ssh.jsch.config.JschSshClientModule; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.BeforeGroups; +import org.testng.annotations.Test; + +import com.google.common.base.Throwables; +import com.google.common.collect.ImmutableSet; +import com.google.inject.Module; + +/** + * + * @author Adrian Cole + */ +@Test(groups = "live") +public class TestCanRecreateTagLiveTest { + + private ComputeServiceContext context; + protected String provider = "ec2"; + protected String identity; + protected String credential; + protected String endpoint; + protected String apiversion; + + @BeforeClass + protected void setupCredentials() { + identity = checkNotNull(System.getProperty("test." + provider + ".identity"), "test." + provider + ".identity"); + credential = System.getProperty("test." + provider + ".credential"); + endpoint = System.getProperty("test." + provider + ".endpoint"); + apiversion = System.getProperty("test." + provider + ".apiversion"); + } + + protected Properties setupProperties() { + Properties overrides = new Properties(); + overrides.setProperty(Constants.PROPERTY_TRUST_ALL_CERTS, "true"); + overrides.setProperty(Constants.PROPERTY_RELAX_HOSTNAME, "true"); + overrides.setProperty(provider + ".identity", identity); + if (credential != null) + overrides.setProperty(provider + ".credential", credential); + if (endpoint != null) + overrides.setProperty(provider + ".endpoint", endpoint); + if (apiversion != null) + overrides.setProperty(provider + ".apiversion", apiversion); + return overrides; + } + + @BeforeGroups(groups = { "live" }) + public void setupClient() throws FileNotFoundException, IOException { + setupCredentials(); + Properties overrides = setupProperties(); + context = new ComputeServiceContextFactory().createContext(provider, + ImmutableSet. of(new Log4JLoggingModule(), new JschSshClientModule()), overrides); + } + + public void testCanRecreateTag() throws Exception { + + String tag = PREFIX + "recreate"; + context.getComputeService().destroyNodesMatching(NodePredicates.withTag(tag)); + + try { + context.getComputeService().runNodesWithTag(tag, 1); + context.getComputeService().destroyNodesMatching(NodePredicates.withTag(tag)); + context.getComputeService().runNodesWithTag(tag, 1); + } catch (RunNodesException e) { + System.err.println(e.getNodeErrors().keySet()); + Throwables.propagate(e); + } finally { + context.getComputeService().destroyNodesMatching(NodePredicates.withTag(tag)); + } + } + + public static final String PREFIX = System.getProperty("user.name") + "ec2"; + +} diff --git a/aws/core/src/test/java/org/jclouds/aws/ec2/compute/functions/RegionAndIdToImageTest.java b/aws/core/src/test/java/org/jclouds/aws/ec2/compute/functions/RegionAndIdToImageTest.java index 1af311ef28..6b048fb308 100644 --- a/aws/core/src/test/java/org/jclouds/aws/ec2/compute/functions/RegionAndIdToImageTest.java +++ b/aws/core/src/test/java/org/jclouds/aws/ec2/compute/functions/RegionAndIdToImageTest.java @@ -27,6 +27,7 @@ import static org.easymock.classextension.EasyMock.verify; import static org.jclouds.aws.ec2.options.DescribeImagesOptions.Builder.imageIds; import static org.testng.Assert.assertEquals; +import java.util.NoSuchElementException; import java.util.Set; import org.jclouds.aws.ec2.EC2Client; @@ -44,7 +45,7 @@ import com.google.common.collect.ImmutableSet; @Test(groups = "unit", testName = "ec2.RegionAndIdToImageTest") public class RegionAndIdToImageTest { - @SuppressWarnings({ "unchecked"}) + @SuppressWarnings({ "unchecked" }) @Test public void testApply() { @@ -54,10 +55,10 @@ public class RegionAndIdToImageTest { org.jclouds.aws.ec2.domain.Image ec2Image = createMock(org.jclouds.aws.ec2.domain.Image.class); Image image = createNiceMock(Image.class); Set images = ImmutableSet - . of(ec2Image); + . of(ec2Image); expect(caller.getAMIServices()).andReturn(client).atLeastOnce(); - expect(client.describeImagesInRegion("region", imageIds("ami"))).andReturn((Set)images); + expect(client.describeImagesInRegion("region", imageIds("ami"))).andReturn((Set) images); expect(parser.apply(ec2Image)).andReturn(image); replay(caller); @@ -76,7 +77,7 @@ public class RegionAndIdToImageTest { } - @SuppressWarnings({ "unchecked"}) + @SuppressWarnings({ "unchecked" }) @Test public void testApplyNotFound() { @@ -86,10 +87,10 @@ public class RegionAndIdToImageTest { org.jclouds.aws.ec2.domain.Image ec2Image = createMock(org.jclouds.aws.ec2.domain.Image.class); Image image = createNiceMock(Image.class); Set images = ImmutableSet - . of(ec2Image); + . of(ec2Image); expect(caller.getAMIServices()).andReturn(client).atLeastOnce(); - expect(client.describeImagesInRegion("region", imageIds("ami"))).andReturn((Set)images); + expect(client.describeImagesInRegion("region", imageIds("ami"))).andReturn((Set) images); expect(parser.apply(ec2Image)).andThrow(new ResourceNotFoundException()); replay(caller); @@ -107,4 +108,36 @@ public class RegionAndIdToImageTest { verify(client); } + + @SuppressWarnings({ "unchecked" }) + @Test + public void testApplyNoSuchElementException() { + + ImageParser parser = createMock(ImageParser.class); + EC2Client caller = createMock(EC2Client.class); + AMIClient client = createMock(AMIClient.class); + org.jclouds.aws.ec2.domain.Image ec2Image = createMock(org.jclouds.aws.ec2.domain.Image.class); + Image image = createNiceMock(Image.class); + Set images = ImmutableSet + . of(ec2Image); + + expect(caller.getAMIServices()).andReturn(client).atLeastOnce(); + expect(client.describeImagesInRegion("region", imageIds("ami"))).andReturn((Set) images); + expect(parser.apply(ec2Image)).andThrow(new NoSuchElementException()); + + replay(caller); + replay(image); + replay(parser); + replay(client); + + RegionAndIdToImage function = new RegionAndIdToImage(parser, caller); + + assertEquals(function.apply(new RegionAndName("region", "ami")), null); + + verify(caller); + verify(image); + verify(parser); + verify(client); + + } } diff --git a/aws/core/src/test/java/org/jclouds/aws/ec2/compute/functions/RunningInstanceToNodeMetadataTest.java b/aws/core/src/test/java/org/jclouds/aws/ec2/compute/functions/RunningInstanceToNodeMetadataTest.java index 8b0b360879..a0044b6b73 100644 --- a/aws/core/src/test/java/org/jclouds/aws/ec2/compute/functions/RunningInstanceToNodeMetadataTest.java +++ b/aws/core/src/test/java/org/jclouds/aws/ec2/compute/functions/RunningInstanceToNodeMetadataTest.java @@ -51,6 +51,9 @@ import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; import com.google.common.collect.Iterables; import com.google.common.collect.Maps; +import com.google.common.collect.MapMaker; + +import javax.annotation.Nullable; /** * @author Adrian Cole @@ -140,15 +143,44 @@ public class RunningInstanceToNodeMetadataTest { "i-9slweygo").location(provider).build()); } + @Test + public void testHandleMissingAMIs() { + + // Handle the case when the installed AMI no longer can be found in AWS. + + // Create a null-returning function to simulate that the AMI can't be found. + Function nullReturningFunction = new Function() { + + @Override + public Image apply(@Nullable RegionAndName from) { + return null; + } + }; + Map instanceToImage = new MapMaker().makeComputingMap(nullReturningFunction); + + RunningInstanceToNodeMetadata parser = createNodeParser(ImmutableSet.of(m1_small().build()), ImmutableSet + .of(provider), ImmutableMap + .of(), EC2ComputeServiceDependenciesModule.instanceToNodeState, instanceToImage); + + RunningInstance server = firstInstanceFromResource("/ec2/describe_instances_nova.xml"); + + assertEquals(parser.apply(server), new NodeMetadataBuilder().state(NodeState.TERMINATED).privateAddresses( + ImmutableSet.of("10.128.207.5")).tag("NOTAG-i-9slweygo").imageId("us-east-1/ami-25CB1213").id( + "us-east-1/i-9slweygo").providerId("i-9slweygo").hardware(m1_small().build()).location( + provider).build()); + } + + protected RunningInstance firstInstanceFromResource(String resource) { RunningInstance server = Iterables.get(Iterables.get(DescribeInstancesResponseHandlerTest - .parseRunningInstances(resource), 0), 0); + .parseRunningInstances(resource), 0), 0); return server; } protected RunningInstanceToNodeMetadata createNodeParser(final ImmutableSet hardware, - final ImmutableSet locations, Set images, - Map credentialStore) { + final ImmutableSet locations, + Set images, + Map credentialStore) { Map instanceToNodeState = EC2ComputeServiceDependenciesModule.instanceToNodeState; Map instanceToImage = Maps.uniqueIndex(images, new Function() { @@ -159,6 +191,13 @@ public class RunningInstanceToNodeMetadataTest { } }); + + return createNodeParser(hardware, locations, credentialStore, instanceToNodeState, instanceToImage); + } + + private RunningInstanceToNodeMetadata createNodeParser(final ImmutableSet hardware, final + ImmutableSet locations, Map credentialStore, Map + instanceToNodeState, Map instanceToImage) { Supplier> locationSupplier = new Supplier>() { @Override diff --git a/aws/demos/googleappengine/pom.xml b/aws/demos/googleappengine/pom.xml index 65f5964ce1..c3a39338fa 100644 --- a/aws/demos/googleappengine/pom.xml +++ b/aws/demos/googleappengine/pom.xml @@ -52,7 +52,7 @@ com.google.code.guice guice-servlet - 2.1-r1201 + 3.0-snapshot-20101120 displaytag diff --git a/azure/src/main/java/org/jclouds/azure/storage/blob/domain/internal/BlobPropertiesImpl.java b/azure/src/main/java/org/jclouds/azure/storage/blob/domain/internal/BlobPropertiesImpl.java index 3233257cd6..e84ed48e84 100644 --- a/azure/src/main/java/org/jclouds/azure/storage/blob/domain/internal/BlobPropertiesImpl.java +++ b/azure/src/main/java/org/jclouds/azure/storage/blob/domain/internal/BlobPropertiesImpl.java @@ -26,6 +26,8 @@ import java.net.URI; import java.util.Date; import java.util.Map; +import javax.annotation.Nullable; + import org.jclouds.azure.storage.blob.domain.BlobProperties; import org.jclouds.azure.storage.blob.domain.BlobType; import org.jclouds.azure.storage.blob.domain.LeaseStatus; @@ -33,7 +35,6 @@ import org.jclouds.io.ContentMetadata; import org.jclouds.io.payloads.BaseImmutableContentMetadata; import com.google.common.collect.Maps; -import com.google.inject.internal.Nullable; /** * Allows you to manipulate metadata. diff --git a/blobstore/src/main/clojure/org/jclouds/blobstore.clj b/blobstore/src/main/clojure/org/jclouds/blobstore.clj index 3807697c1a..3081e91ace 100644 --- a/blobstore/src/main/clojure/org/jclouds/blobstore.clj +++ b/blobstore/src/main/clojure/org/jclouds/blobstore.clj @@ -299,7 +299,7 @@ Options can also be specified for extension modules ([container-name] (count-blobs container-name *blobstore*)) ([container-name blobstore] - (.countBlob blobstore container-name))) + (.countBlobs blobstore container-name))) (defn blobs "List the blobs in a container: diff --git a/blobstore/src/main/java/org/jclouds/blobstore/TransientAsyncBlobStore.java b/blobstore/src/main/java/org/jclouds/blobstore/TransientAsyncBlobStore.java index 5b2bae075b..f308d57d18 100755 --- a/blobstore/src/main/java/org/jclouds/blobstore/TransientAsyncBlobStore.java +++ b/blobstore/src/main/java/org/jclouds/blobstore/TransientAsyncBlobStore.java @@ -49,27 +49,28 @@ import java.util.Collections; import java.util.Date; import java.util.List; import java.util.Map; +import java.util.Map.Entry; import java.util.Set; import java.util.SortedSet; import java.util.TreeSet; -import java.util.Map.Entry; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; import java.util.concurrent.ExecutorService; +import javax.annotation.Nullable; import javax.inject.Inject; import javax.inject.Named; import javax.ws.rs.core.HttpHeaders; import org.jclouds.Constants; import org.jclouds.blobstore.domain.Blob; +import org.jclouds.blobstore.domain.Blob.Factory; import org.jclouds.blobstore.domain.BlobMetadata; import org.jclouds.blobstore.domain.MutableBlobMetadata; import org.jclouds.blobstore.domain.MutableStorageMetadata; import org.jclouds.blobstore.domain.PageSet; import org.jclouds.blobstore.domain.StorageMetadata; import org.jclouds.blobstore.domain.StorageType; -import org.jclouds.blobstore.domain.Blob.Factory; import org.jclouds.blobstore.domain.internal.MutableStorageMetadataImpl; import org.jclouds.blobstore.domain.internal.PageSetImpl; import org.jclouds.blobstore.functions.HttpGetOptionsListToGetOptions; @@ -103,7 +104,6 @@ import com.google.common.collect.Iterables; import com.google.common.collect.Multimaps; import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.ListenableFuture; -import com.google.inject.internal.Nullable; /** * Implementation of {@link BaseAsyncBlobStore} which keeps all data in a local Map object. diff --git a/blobstore/src/main/java/org/jclouds/blobstore/domain/Blob.java b/blobstore/src/main/java/org/jclouds/blobstore/domain/Blob.java index 51bc1d4351..e618c08ca4 100644 --- a/blobstore/src/main/java/org/jclouds/blobstore/domain/Blob.java +++ b/blobstore/src/main/java/org/jclouds/blobstore/domain/Blob.java @@ -19,10 +19,12 @@ package org.jclouds.blobstore.domain; +import javax.annotation.Nullable; + +import org.jclouds.io.Payload; import org.jclouds.io.PayloadEnclosing; import com.google.common.collect.Multimap; -import com.google.inject.internal.Nullable; /** * Value type for an HTTP Blob service. Blobs are stored in containers and consist of a diff --git a/blobstore/src/main/java/org/jclouds/blobstore/domain/internal/BlobMetadataImpl.java b/blobstore/src/main/java/org/jclouds/blobstore/domain/internal/BlobMetadataImpl.java index bcc8f4be3e..17659b73a6 100644 --- a/blobstore/src/main/java/org/jclouds/blobstore/domain/internal/BlobMetadataImpl.java +++ b/blobstore/src/main/java/org/jclouds/blobstore/domain/internal/BlobMetadataImpl.java @@ -26,14 +26,14 @@ import java.net.URI; import java.util.Date; import java.util.Map; +import javax.annotation.Nullable; + import org.jclouds.blobstore.domain.Blob; import org.jclouds.blobstore.domain.BlobMetadata; import org.jclouds.blobstore.domain.StorageType; import org.jclouds.domain.Location; import org.jclouds.io.ContentMetadata; -import com.google.inject.internal.Nullable; - /** * System and user Metadata for the {@link Blob}. * diff --git a/blobstore/src/main/java/org/jclouds/blobstore/domain/internal/StorageMetadataImpl.java b/blobstore/src/main/java/org/jclouds/blobstore/domain/internal/StorageMetadataImpl.java index 4e416806d9..7a347eaf46 100644 --- a/blobstore/src/main/java/org/jclouds/blobstore/domain/internal/StorageMetadataImpl.java +++ b/blobstore/src/main/java/org/jclouds/blobstore/domain/internal/StorageMetadataImpl.java @@ -26,13 +26,13 @@ import java.net.URI; import java.util.Date; import java.util.Map; +import javax.annotation.Nullable; + import org.jclouds.blobstore.domain.StorageMetadata; import org.jclouds.blobstore.domain.StorageType; import org.jclouds.domain.Location; import org.jclouds.domain.internal.ResourceMetadataImpl; -import com.google.inject.internal.Nullable; - /** * Idpayload of the object * diff --git a/blobstore/src/main/java/org/jclouds/blobstore/functions/ParseSystemAndUserMetadataFromHeaders.java b/blobstore/src/main/java/org/jclouds/blobstore/functions/ParseSystemAndUserMetadataFromHeaders.java index c8762ad605..9af2635e36 100755 --- a/blobstore/src/main/java/org/jclouds/blobstore/functions/ParseSystemAndUserMetadataFromHeaders.java +++ b/blobstore/src/main/java/org/jclouds/blobstore/functions/ParseSystemAndUserMetadataFromHeaders.java @@ -87,8 +87,11 @@ public class ParseSystemAndUserMetadataFromHeaders implements Function getTestDataSupplier() throws IOException { byte[] oneConstitution = ByteStreams.toByteArray(new GZIPInputStream(BaseJettyTest.class - .getResourceAsStream("/const.txt.gz"))); + .getResourceAsStream("/const.txt.gz"))); InputSupplier constitutionSupplier = ByteStreams.newInputStreamSupplier(oneConstitution); InputSupplier temp = ByteStreams.join(constitutionSupplier); @@ -120,24 +120,24 @@ public class BaseBlobIntegrationTest extends BaseBlobStoreIntegrationTest { Map> responses = Maps.newHashMap(); for (int i = 0; i < 10; i++) { - responses.put(i, Futures.compose(context.getAsyncBlobStore().getBlob(containerName, key), - new Function() { + responses.put(i, + Futures.compose(context.getAsyncBlobStore().getBlob(containerName, key), new Function() { - @Override - public Void apply(Blob from) { - try { - assertEquals(CryptoStreams.md5(from.getPayload()), oneHundredOneConstitutionsMD5); - checkContentDisposition(from, expectedContentDisposition); - } catch (IOException e) { - Throwables.propagate(e); - } - return null; + @Override + public Void apply(Blob from) { + try { + assertEquals(CryptoStreams.md5(from.getPayload()), oneHundredOneConstitutionsMD5); + checkContentDisposition(from, expectedContentDisposition); + } catch (IOException e) { + Throwables.propagate(e); } + return null; + } - }, this.exec)); + }, this.exec)); } Map exceptions = awaitCompletion(responses, exec, 30000l, Logger.CONSOLE, - "get constitution"); + "get constitution"); assert exceptions.size() == 0 : exceptions; } finally { @@ -156,7 +156,6 @@ public class BaseBlobIntegrationTest extends BaseBlobStoreIntegrationTest { context.getBlobStore().putBlob(containerName, sourceObject); } - @Test(groups = { "integration", "live" }) public void testGetIfModifiedSince() throws InterruptedException { String containerName = getContainerName(); @@ -365,15 +364,15 @@ public class BaseBlobIntegrationTest extends BaseBlobStoreIntegrationTest { @DataProvider(name = "delete") public Object[][] createData() { - return new Object[][] { { "normal" }, { "sp ace" }, { "qu?stion" }, { "unic₪de" }, { "path/foo" }, { "colon:" }, - { "asteri*k" }, { "quote\"" }, { "{greaten" }, { "p|pe" } }; + return new Object[][] { { "normal" }, { "sp ace" }, { "qu?stion" }, { "unic₪de" }, { "path/foo" }, + { "colon:" }, { "asteri*k" }, { "quote\"" }, { "{greaten" }, { "p|pe" } }; } @Test(groups = { "integration", "live" }, dataProvider = "delete") public void deleteObject(String key) throws InterruptedException { String containerName = getContainerName(); try { - addBlobToContainer(containerName, key); + addBlobToContainer(containerName, key, key, MediaType.TEXT_PLAIN); context.getBlobStore().removeBlob(containerName, key); assertContainerEmptyDeleting(containerName, key); } finally { @@ -383,17 +382,19 @@ public class BaseBlobIntegrationTest extends BaseBlobStoreIntegrationTest { private void assertContainerEmptyDeleting(String containerName, String key) { Iterable listing = Iterables.filter(context.getBlobStore().list(containerName), - new Predicate() { + new Predicate() { - @Override - public boolean apply(StorageMetadata input) { - return input.getType() == StorageType.BLOB; - } + @Override + public boolean apply(StorageMetadata input) { + return input.getType() == StorageType.BLOB; + } - }); - assertEquals(Iterables.size(listing), 0, String.format( - "deleting %s, we still have %s blobs left in container %s, using encoding %s", key, Iterables - .size(listing), containerName, LOCAL_ENCODING)); + }); + assertEquals( + Iterables.size(listing), + 0, + String.format("deleting %s, we still have %s blobs left in container %s, using encoding %s", key, + Iterables.size(listing), containerName, LOCAL_ENCODING)); } @Test(groups = { "integration", "live" }) @@ -413,13 +414,13 @@ public class BaseBlobIntegrationTest extends BaseBlobStoreIntegrationTest { String realObject = Utils.toStringAndClose(new FileInputStream("pom.xml")); return new Object[][] { { "file", "text/xml", new File("pom.xml"), realObject }, - { "string", "text/xml", realObject, realObject }, - { "bytes", "application/octet-stream", realObject.getBytes(), realObject } }; + { "string", "text/xml", realObject, realObject }, + { "bytes", "application/octet-stream", realObject.getBytes(), realObject } }; } @Test(groups = { "integration", "live" }, dataProvider = "putTests") public void testPutObject(String key, String type, Object content, Object realObject) throws InterruptedException, - IOException { + IOException { Blob blob = context.getBlobStore().newBlob(key); blob.setPayload(Payloads.newPayload(content)); blob.getMetadata().getContentMetadata().setContentType(type); @@ -486,32 +487,32 @@ public class BaseBlobIntegrationTest extends BaseBlobStoreIntegrationTest { protected void checkContentType(Blob blob, String contentType) { assert blob.getPayload().getContentMetadata().getContentType().startsWith(contentType) : blob.getPayload() - .getContentMetadata().getContentType(); + .getContentMetadata().getContentType(); assert blob.getMetadata().getContentMetadata().getContentType().startsWith(contentType) : blob.getMetadata() - .getContentMetadata().getContentType(); + .getContentMetadata().getContentType(); } protected void checkContentDisposition(Blob blob, String contentDisposition) { assert blob.getPayload().getContentMetadata().getContentDisposition().startsWith(contentDisposition) : blob - .getPayload().getContentMetadata().getContentDisposition(); + .getPayload().getContentMetadata().getContentDisposition(); assert blob.getMetadata().getContentMetadata().getContentDisposition().startsWith(contentDisposition) : blob - .getMetadata().getContentMetadata().getContentDisposition(); + .getMetadata().getContentMetadata().getContentDisposition(); } protected void checkContentEncoding(Blob blob, String contentEncoding) { assert blob.getPayload().getContentMetadata().getContentEncoding().startsWith(contentEncoding) : blob - .getPayload().getContentMetadata().getContentEncoding(); + .getPayload().getContentMetadata().getContentEncoding(); assert blob.getMetadata().getContentMetadata().getContentEncoding().startsWith(contentEncoding) : blob - .getMetadata().getContentMetadata().getContentEncoding(); + .getMetadata().getContentMetadata().getContentEncoding(); } protected void checkContentLanguage(Blob blob, String contentLanguage) { assert blob.getPayload().getContentMetadata().getContentLanguage().startsWith(contentLanguage) : blob - .getPayload().getContentMetadata().getContentLanguage(); + .getPayload().getContentMetadata().getContentLanguage(); assert blob.getMetadata().getContentMetadata().getContentLanguage().startsWith(contentLanguage) : blob - .getMetadata().getContentMetadata().getContentLanguage(); + .getMetadata().getContentMetadata().getContentLanguage(); } @@ -565,7 +566,7 @@ public class BaseBlobIntegrationTest extends BaseBlobStoreIntegrationTest { protected void validateMetadata(BlobMetadata metadata) throws IOException { assert metadata.getContentMetadata().getContentType().startsWith("text/plain") : metadata.getContentMetadata() - .getContentType(); + .getContentType(); assertEquals(metadata.getContentMetadata().getContentLength(), new Long(TEST_STRING.length())); assertEquals(metadata.getUserMetadata().get("adrian"), "powderpuff"); checkMD5(metadata); diff --git a/blobstore/src/test/java/org/jclouds/blobstore/integration/internal/BaseBlobStoreIntegrationTest.java b/blobstore/src/test/java/org/jclouds/blobstore/integration/internal/BaseBlobStoreIntegrationTest.java index 05fe4074e1..e928ea6840 100644 --- a/blobstore/src/test/java/org/jclouds/blobstore/integration/internal/BaseBlobStoreIntegrationTest.java +++ b/blobstore/src/test/java/org/jclouds/blobstore/integration/internal/BaseBlobStoreIntegrationTest.java @@ -25,8 +25,8 @@ import static org.testng.Assert.assertEquals; import java.io.IOException; import java.util.Map; -import java.util.Set; import java.util.Map.Entry; +import java.util.Set; import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.BlockingQueue; import java.util.concurrent.CancellationException; @@ -35,6 +35,8 @@ import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; +import javax.ws.rs.core.MediaType; + import org.jclouds.blobstore.BlobStoreContext; import org.jclouds.blobstore.attr.ConsistencyModel; import org.jclouds.blobstore.domain.Blob; @@ -60,13 +62,13 @@ public class BaseBlobStoreIntegrationTest { protected static final String TEST_STRING = String.format(XML_STRING_FORMAT, "apple"); protected Map fiveStrings = ImmutableMap.of("one", String.format(XML_STRING_FORMAT, "apple"), "two", - String.format(XML_STRING_FORMAT, "bear"), "three", String.format(XML_STRING_FORMAT, "candy"), "four", - String.format(XML_STRING_FORMAT, "dogma"), "five", String.format(XML_STRING_FORMAT, "emma")); + String.format(XML_STRING_FORMAT, "bear"), "three", String.format(XML_STRING_FORMAT, "candy"), "four", + String.format(XML_STRING_FORMAT, "dogma"), "five", String.format(XML_STRING_FORMAT, "emma")); - protected Map fiveStringsUnderPath = ImmutableMap.of("path/1", String.format(XML_STRING_FORMAT, - "apple"), "path/2", String.format(XML_STRING_FORMAT, "bear"), "path/3", String.format(XML_STRING_FORMAT, - "candy"), "path/4", String.format(XML_STRING_FORMAT, "dogma"), "path/5", String.format(XML_STRING_FORMAT, - "emma")); + protected Map fiveStringsUnderPath = ImmutableMap.of("path/1", + String.format(XML_STRING_FORMAT, "apple"), "path/2", String.format(XML_STRING_FORMAT, "bear"), "path/3", + String.format(XML_STRING_FORMAT, "candy"), "path/4", String.format(XML_STRING_FORMAT, "dogma"), "path/5", + String.format(XML_STRING_FORMAT, "emma")); public static long INCONSISTENCY_WINDOW = 10000; protected static volatile AtomicInteger containerIndex = new AtomicInteger(0); @@ -90,7 +92,7 @@ public class BaseBlobStoreIntegrationTest { @SuppressWarnings("unchecked") private BlobStoreContext getCloudResources(ITestContext testContext) throws ClassNotFoundException, - InstantiationException, IllegalAccessException, Exception { + InstantiationException, IllegalAccessException, Exception { String initializerClass = checkNotNull(System.getProperty("test.initializer"), "test.initializer"); Class clazz = (Class) Class.forName(initializerClass); BaseTestInitializer initializer = clazz.newInstance(); @@ -123,7 +125,7 @@ public class BaseBlobStoreIntegrationTest { private static volatile boolean initialized = false; protected void createContainersSharedByAllThreads(BlobStoreContext context, ITestContext testContext) - throws Exception { + throws Exception { while (!initialized) { synchronized (BaseBlobStoreIntegrationTest.class) { if (!initialized) { @@ -174,12 +176,12 @@ public class BaseBlobStoreIntegrationTest { try { for (int i = 0; i < 2; i++) { Iterable testContainers = Iterables.filter(context.getBlobStore().list(), - new Predicate() { - public boolean apply(StorageMetadata input) { - return (input.getType() == StorageType.CONTAINER || input.getType() == StorageType.FOLDER) - && input.getName().startsWith(CONTAINER_PREFIX.toLowerCase()); - } - }); + new Predicate() { + public boolean apply(StorageMetadata input) { + return (input.getType() == StorageType.CONTAINER || input.getType() == StorageType.FOLDER) + && input.getName().startsWith(CONTAINER_PREFIX.toLowerCase()); + } + }); for (StorageMetadata container : testContainers) { deleteContainerOrWarnIfUnable(context, container.getName()); } @@ -200,7 +202,7 @@ public class BaseBlobStoreIntegrationTest { * we will try up to the inconsistency window to see if the assertion completes. */ protected static void assertConsistencyAware(BlobStoreContext context, Runnable assertion) - throws InterruptedException { + throws InterruptedException { if (context.getConsistencyModel() == ConsistencyModel.STRICT) { assertion.run(); return; @@ -226,7 +228,7 @@ public class BaseBlobStoreIntegrationTest { } protected static void createContainerAndEnsureEmpty(BlobStoreContext context, final String containerName) - throws InterruptedException { + throws InterruptedException { context.getBlobStore().createContainerInLocation(null, containerName); if (context.getConsistencyModel() == ConsistencyModel.EVENTUAL) Thread.sleep(1000); @@ -238,9 +240,13 @@ public class BaseBlobStoreIntegrationTest { } protected String addBlobToContainer(String sourceContainer, String key) { + return addBlobToContainer(sourceContainer, key, TEST_STRING, MediaType.TEXT_XML); + } + + protected String addBlobToContainer(String sourceContainer, String key, String payload, String contentType) { Blob sourceObject = context.getBlobStore().newBlob(key); - sourceObject.setPayload(TEST_STRING); - sourceObject.getMetadata().getContentMetadata().setContentType("text/xml"); + sourceObject.setPayload(payload); + sourceObject.getMetadata().getContentMetadata().setContentType(contentType); return addBlobToContainer(sourceContainer, sourceObject); } @@ -270,19 +276,19 @@ public class BaseBlobStoreIntegrationTest { } protected void assertConsistencyAwareContainerSize(final String containerName, final int count) - throws InterruptedException { + throws InterruptedException { assertConsistencyAware(new Runnable() { public void run() { try { assert context.getBlobStore().countBlobs(containerName) == count : String.format( - "expected only %d values in %s: %s", count, containerName, Sets.newHashSet(Iterables.transform( - context.getBlobStore().list(containerName), new Function() { + "expected only %d values in %s: %s", count, containerName, Sets.newHashSet(Iterables.transform( + context.getBlobStore().list(containerName), new Function() { - public String apply(StorageMetadata from) { - return from.getName(); - } + public String apply(StorageMetadata from) { + return from.getName(); + } - }))); + }))); } catch (Exception e) { Throwables.propagateIfPossible(e); } diff --git a/compute/src/test/java/org/jclouds/compute/BaseComputeServiceLiveTest.java b/compute/src/test/java/org/jclouds/compute/BaseComputeServiceLiveTest.java index f967f6a063..d01e7d5244 100755 --- a/compute/src/test/java/org/jclouds/compute/BaseComputeServiceLiveTest.java +++ b/compute/src/test/java/org/jclouds/compute/BaseComputeServiceLiveTest.java @@ -200,7 +200,7 @@ public abstract class BaseComputeServiceLiveTest { // starting this one alphabetically before create2nodes.. @Test(enabled = true, dependsOnMethods = { "testCompareSizes" }) public void testAScriptExecutionAfterBootWithBasicTemplate() throws Exception { - String tag = this.tag + "run"; + String tag = this.tag + "r"; try { client.destroyNodesMatching(withTag(tag)); } catch (Exception e) { @@ -460,7 +460,7 @@ public abstract class BaseComputeServiceLiveTest { @Test(enabled = true) public void testCreateAndRunAService() throws Exception { - String tag = this.tag + "service"; + String tag = this.tag + "s"; try { client.destroyNodesMatching(withTag(tag)); } catch (Exception e) { diff --git a/core/pom.xml b/core/pom.xml index dae3ed8250..372ab3e87b 100644 --- a/core/pom.xml +++ b/core/pom.xml @@ -81,7 +81,7 @@ com.google.code.guice guice - 2.1-r1201 + 3.0-snapshot-20101120 javax.inject @@ -106,7 +106,7 @@ com.google.guava guava - r06 + r07 com.google.code.findbugs diff --git a/core/src/main/java/org/jclouds/domain/internal/ResourceMetadataImpl.java b/core/src/main/java/org/jclouds/domain/internal/ResourceMetadataImpl.java index fbc55edde7..38d6b6352f 100644 --- a/core/src/main/java/org/jclouds/domain/internal/ResourceMetadataImpl.java +++ b/core/src/main/java/org/jclouds/domain/internal/ResourceMetadataImpl.java @@ -25,11 +25,12 @@ import java.io.Serializable; import java.net.URI; import java.util.Map; +import javax.annotation.Nullable; + import org.jclouds.domain.Location; import org.jclouds.domain.ResourceMetadata; import com.google.common.collect.Maps; -import com.google.inject.internal.Nullable; /** * Idpayload of the object diff --git a/core/src/main/java/org/jclouds/http/HttpResponse.java b/core/src/main/java/org/jclouds/http/HttpResponse.java index ccb8fb8d72..a39cdeb995 100644 --- a/core/src/main/java/org/jclouds/http/HttpResponse.java +++ b/core/src/main/java/org/jclouds/http/HttpResponse.java @@ -19,10 +19,15 @@ package org.jclouds.http; +import static com.google.common.base.Preconditions.checkNotNull; + import javax.annotation.Nullable; import org.jclouds.io.Payload; +import com.google.common.collect.ImmutableMultimap; +import com.google.common.collect.Multimap; + /** * Represents a response produced from {@link HttpCommandExecutorService} * @@ -34,9 +39,14 @@ public class HttpResponse extends HttpMessage { private final String message; public HttpResponse(int statusCode, String message, @Nullable Payload payload) { + this(statusCode, message, payload, ImmutableMultimap. of()); + } + + public HttpResponse(int statusCode, String message, @Nullable Payload payload, Multimap headers) { super(payload); this.statusCode = statusCode; this.message = message; + this.headers.putAll(checkNotNull(headers)); } public int getStatusCode() { @@ -49,8 +59,8 @@ public class HttpResponse extends HttpMessage { @Override public String toString() { - return "[message=" + message + ", statusCode=" + statusCode + ", headers=" + headers - + ", payload=" + payload + "]"; + return "[message=" + message + ", statusCode=" + statusCode + ", headers=" + headers + ", payload=" + payload + + "]"; } public String getStatusLine() { diff --git a/core/src/main/java/org/jclouds/http/handlers/RedirectionRetryHandler.java b/core/src/main/java/org/jclouds/http/handlers/RedirectionRetryHandler.java index dd64967510..11d715e163 100644 --- a/core/src/main/java/org/jclouds/http/handlers/RedirectionRetryHandler.java +++ b/core/src/main/java/org/jclouds/http/handlers/RedirectionRetryHandler.java @@ -19,8 +19,8 @@ package org.jclouds.http.handlers; -import static org.jclouds.http.HttpUtils.changePathTo; -import static org.jclouds.http.HttpUtils.changeSchemeHostAndPortTo; +import static java.util.Collections.singletonList; +import static javax.ws.rs.core.HttpHeaders.HOST; import static org.jclouds.http.HttpUtils.closeClientButKeepContentStream; import java.net.URI; @@ -58,8 +58,7 @@ public class RedirectionRetryHandler implements HttpRetryHandler { protected final Provider uriBuilderProvider; @Inject - protected RedirectionRetryHandler(Provider uriBuilderProvider, - BackoffLimitedRetryHandler backoffHandler) { + protected RedirectionRetryHandler(Provider uriBuilderProvider, BackoffLimitedRetryHandler backoffHandler) { this.backoffHandler = backoffHandler; this.uriBuilderProvider = uriBuilderProvider; } @@ -67,25 +66,36 @@ public class RedirectionRetryHandler implements HttpRetryHandler { public boolean shouldRetryRequest(HttpCommand command, HttpResponse response) { closeClientButKeepContentStream(response); String hostHeader = response.getFirstHeaderOrNull(HttpHeaders.LOCATION); - if (hostHeader != null && command.incrementRedirectCount() < retryCountLimit) { - URI redirectionUrl = uriBuilderProvider.get().uri(URI.create(hostHeader)).build(); - if (redirectionUrl.getScheme().equals(command.getRequest().getEndpoint().getScheme()) - && redirectionUrl.getHost().equals(command.getRequest().getEndpoint().getHost()) - && redirectionUrl.getPort() == command.getRequest().getEndpoint().getPort()) { - if (!redirectionUrl.getPath().equals(command.getRequest().getEndpoint().getPath())) { - changePathTo(command.getRequest(), redirectionUrl.getPath(), uriBuilderProvider - .get()); - } else { - return backoffHandler.shouldRetryRequest(command, response); - } - } else { - changeSchemeHostAndPortTo(command.getRequest(), redirectionUrl.getScheme(), - redirectionUrl.getHost(), redirectionUrl.getPort(), uriBuilderProvider.get()); + if (command.incrementRedirectCount() < retryCountLimit && hostHeader != null) { + URI redirectionUrl = URI.create(hostHeader); + + // if you are sent the same uri, assume there's a transient problem and retry. + if (redirectionUrl.equals(command.getRequest().getEndpoint())) + return backoffHandler.shouldRetryRequest(command, response); + + UriBuilder builder = uriBuilderProvider.get().uri(command.getRequest().getEndpoint()); + assert redirectionUrl.getPath() != null : "no path in redirect header from: " + response; + builder.replacePath(redirectionUrl.getPath()); + + if (redirectionUrl.getScheme() != null) + builder.scheme(redirectionUrl.getScheme()); + + if (redirectionUrl.getHost() != null) { + builder.host(redirectionUrl.getHost()); + if (command.getRequest().getFirstHeaderOrNull(HOST) != null) + command.getRequest().getHeaders().replaceValues(HOST, singletonList(redirectionUrl.getHost())); } + if (redirectionUrl.getPort() != command.getRequest().getEndpoint().getPort()) + builder.port(redirectionUrl.getPort()); + + if (redirectionUrl.getQuery() != null) + builder.replaceQuery(redirectionUrl.getQuery()); + + command.getRequest().setEndpoint(builder.build()); return true; } else { return false; } } -} +} \ No newline at end of file diff --git a/core/src/main/java/org/jclouds/io/payloads/StringPayload.java b/core/src/main/java/org/jclouds/io/payloads/StringPayload.java index 34a06f9b40..ddd6795381 100644 --- a/core/src/main/java/org/jclouds/io/payloads/StringPayload.java +++ b/core/src/main/java/org/jclouds/io/payloads/StringPayload.java @@ -19,18 +19,27 @@ package org.jclouds.io.payloads; +import java.io.ByteArrayInputStream; import java.io.InputStream; -import org.jclouds.util.Utils; +import com.google.common.base.Charsets; /** + * This implementation converts the String to a byte array using UTF-8 encoding. If you wish to use + * a different encoding, please use {@link ByteArrayPayload}. + * * @author Adrian Cole */ public class StringPayload extends BasePayload { + private final byte[] bytes; + + // it is possible to discover length by walking the string and updating current length based on + // character code. However, this is process intense, and assumes an encoding type of UTF-8 public StringPayload(String content) { super(content); - getContentMetadata().setContentLength((long) content.length()); + this.bytes = content.getBytes(Charsets.UTF_8); + getContentMetadata().setContentLength(new Long(bytes.length)); } /** @@ -38,7 +47,7 @@ public class StringPayload extends BasePayload { */ @Override public InputStream getInput() { - return Utils.toInputStream(content); + return new ByteArrayInputStream(bytes); } } \ No newline at end of file diff --git a/core/src/main/java/org/jclouds/util/Utils.java b/core/src/main/java/org/jclouds/util/Utils.java index e439a5f561..fabf3de3e3 100644 --- a/core/src/main/java/org/jclouds/util/Utils.java +++ b/core/src/main/java/org/jclouds/util/Utils.java @@ -21,7 +21,9 @@ package org.jclouds.util; import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkNotNull; +import static com.google.common.base.Predicates.equalTo; import static com.google.common.base.Predicates.instanceOf; +import static com.google.common.base.Predicates.not; import static com.google.common.base.Predicates.notNull; import static com.google.common.base.Splitter.on; import static com.google.common.base.Throwables.getCausalChain; @@ -32,6 +34,7 @@ import static com.google.common.collect.Iterables.find; import static com.google.common.collect.Iterables.get; import static com.google.common.collect.Iterables.transform; import static com.google.common.collect.Lists.newArrayList; +import static com.google.common.collect.Maps.filterKeys; import static com.google.common.io.ByteStreams.toByteArray; import static com.google.common.io.Closeables.closeQuietly; import static org.jclouds.util.Patterns.CHAR_TO_PATTERN; @@ -47,10 +50,10 @@ import java.util.Comparator; import java.util.Iterator; import java.util.List; import java.util.Map; +import java.util.Map.Entry; import java.util.NoSuchElementException; import java.util.Properties; import java.util.Set; -import java.util.Map.Entry; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -70,6 +73,8 @@ import com.google.common.base.Predicate; import com.google.common.base.Splitter; import com.google.common.base.Supplier; import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableMap.Builder; import com.google.common.collect.ImmutableSet; import com.google.common.collect.Maps; import com.google.common.io.OutputSupplier; @@ -84,6 +89,32 @@ import com.google.inject.spi.Message; */ public class Utils { + /** + * If the supplied map contains the key {@code k1}, its value will be assigned to the key + * {@code k2}. Note that this doesn't modify the input map. + * + * @param + * type of value the map holds + * @param in + * the map you wish to make a copy of + * @param k1 + * old key + * @param k2 + * new key + * @return copy of the map with the value of the key re-routed, or the original, if it {@code k1} + * wasn't present. + */ + public static Map renameKey(Map in, String k1, String k2) { + if (in.containsKey(k1)) { + Builder builder = ImmutableMap.builder(); + builder.putAll(filterKeys(in, not(equalTo(k1)))); + V tags = in.get(k1); + builder.put(k2, tags); + in = builder.build(); + } + return in; + } + public static Supplier> composeMapSupplier(Iterable>> suppliers) { return new ListMapSupplier(suppliers); } diff --git a/core/src/main/resources/rest.properties b/core/src/main/resources/rest.properties index 9108d8ad63..65ce7ab602 100644 --- a/core/src/main/resources/rest.properties +++ b/core/src/main/resources/rest.properties @@ -89,6 +89,12 @@ bluelock-vcdirector.propertiesbuilder=org.jclouds.vcloud.bluelock.BlueLockVCloud gogrid.propertiesbuilder=org.jclouds.gogrid.GoGridPropertiesBuilder gogrid.contextbuilder=org.jclouds.gogrid.GoGridContextBuilder +elasticstack.propertiesbuilder=org.jclouds.elasticstack.ElasticStackPropertiesBuilder +elasticstack.contextbuilder=org.jclouds.elasticstack.ElasticStackContextBuilder + +cloudsigma.propertiesbuilder=org.jclouds.cloudsigma.CloudSigmaPropertiesBuilder +cloudsigma.contextbuilder=org.jclouds.cloudsigma.CloudSigmaContextBuilder + ibmdev.propertiesbuilder=org.jclouds.ibmdev.IBMDeveloperCloudPropertiesBuilder ibmdev.contextbuilder=org.jclouds.ibmdev.IBMDeveloperCloudContextBuilder @@ -119,6 +125,10 @@ walrus.propertiesbuilder=org.jclouds.aws.s3.WalrusPropertiesBuilder googlestorage.contextbuilder=org.jclouds.aws.s3.S3ContextBuilder googlestorage.propertiesbuilder=org.jclouds.aws.s3.GoogleStoragePropertiesBuilder +scaleup-storage.contextbuilder=org.jclouds.aws.s3.blobstore.ScaleUpCloudBlobStoreContextContextBuilder +scaleup-storage.propertiesbuilder=org.jclouds.aws.s3.S3PropertiesBuilder +scaleup-storage.endpoint=https://scs.scaleupstorage.com + transient.contextbuilder=org.jclouds.blobstore.TransientBlobStoreContextBuilder transient.propertiesbuilder=org.jclouds.blobstore.TransientBlobStorePropertiesBuilder diff --git a/core/src/test/java/org/jclouds/http/handlers/RedirectionRetryHandlerTest.java b/core/src/test/java/org/jclouds/http/handlers/RedirectionRetryHandlerTest.java new file mode 100644 index 0000000000..f7698718bd --- /dev/null +++ b/core/src/test/java/org/jclouds/http/handlers/RedirectionRetryHandlerTest.java @@ -0,0 +1,171 @@ +/** + * + * 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.http.handlers; + +import static org.easymock.EasyMock.expect; +import static org.easymock.classextension.EasyMock.createMock; +import static org.easymock.classextension.EasyMock.replay; +import static org.easymock.classextension.EasyMock.verify; +import static org.testng.Assert.assertEquals; + +import java.net.URI; + +import javax.ws.rs.core.HttpHeaders; + +import org.jclouds.http.HttpCommand; +import org.jclouds.http.HttpRequest; +import org.jclouds.http.HttpResponse; +import org.jclouds.rest.BaseRestClientTest.MockModule; +import org.jclouds.rest.config.RestModule; +import org.testng.annotations.Test; + +import com.google.common.collect.ImmutableMultimap; +import com.google.inject.Guice; + +/** + * Tests behavior of {@code RedirectionRetryHandler} + * + * @author Adrian Cole + */ +@Test(groups = "unit", testName = "http.RedirectionRetryHandlerTest") +public class RedirectionRetryHandlerTest { + + @Test + public void test302DoesNotRetry() { + + HttpCommand command = createMock(HttpCommand.class); + HttpResponse response = new HttpResponse(302, "HTTP/1.1 302 Found", null); + + expect(command.incrementRedirectCount()).andReturn(0); + + replay(command); + + RedirectionRetryHandler retry = Guice.createInjector(new MockModule(), new RestModule()).getInstance( + RedirectionRetryHandler.class); + + assert !retry.shouldRetryRequest(command, response); + + verify(command); + + } + + @Test + public void test302DoesNotRetryAfterLimit() { + + HttpCommand command = createMock(HttpCommand.class); + HttpResponse response = new HttpResponse(302, "HTTP/1.1 302 Found", null, ImmutableMultimap.of( + HttpHeaders.LOCATION, "/api/v0.8b-ext2.5/Error.aspx?aspxerrorpath=/api/v0.8b-ext2.5/org.svc/1906645")); + + expect(command.incrementRedirectCount()).andReturn(5); + + replay(command); + + RedirectionRetryHandler retry = Guice.createInjector(new MockModule(), new RestModule()).getInstance( + RedirectionRetryHandler.class); + + assert !retry.shouldRetryRequest(command, response); + + verify(command); + + } + + @Test + public void test302WithPathOnlyHeader() { + + verifyRedirectRoutes( + new HttpRequest("GET", + URI.create("https://services.enterprisecloud.terremark.com/api/v0.8b-ext2.5/org/1906645")), + new HttpResponse(302, "HTTP/1.1 302 Found", null, ImmutableMultimap.of(HttpHeaders.LOCATION, + "/api/v0.8b-ext2.5/Error.aspx?aspxerrorpath=/api/v0.8b-ext2.5/org.svc/1906645")), + new HttpRequest( + "GET", + URI.create("https://services.enterprisecloud.terremark.com/api/v0.8b-ext2.5/Error.aspx?aspxerrorpath=/api/v0.8b-ext2.5/org.svc/1906645"))); + + } + + @Test + public void test302ToHttps() { + + verifyRedirectRoutes( + new HttpRequest("GET", + URI.create("http://services.enterprisecloud.terremark.com/api/v0.8b-ext2.5/org/1906645")), + new HttpResponse(302, "HTTP/1.1 302 Found", null, ImmutableMultimap.of(HttpHeaders.LOCATION, + "https://services.enterprisecloud.terremark.com/api/v0.8b-ext2.5/org/1906645")),// + new HttpRequest("GET", URI + .create("https://services.enterprisecloud.terremark.com/api/v0.8b-ext2.5/org/1906645"))); + + } + + @Test + public void test302ToDifferentPort() { + + verifyRedirectRoutes( + new HttpRequest("GET", + URI.create("http://services.enterprisecloud.terremark.com/api/v0.8b-ext2.5/org/1906645")), + new HttpResponse(302, "HTTP/1.1 302 Found", null, ImmutableMultimap.of(HttpHeaders.LOCATION, + "http://services.enterprisecloud.terremark.com:3030/api/v0.8b-ext2.5/org/1906645")),// + new HttpRequest("GET", URI + .create("http://services.enterprisecloud.terremark.com:3030/api/v0.8b-ext2.5/org/1906645"))); + + } + + @Test + public void test302WithHeader() { + + verifyRedirectRoutes( + new HttpRequest("GET", + URI.create("https://services.enterprisecloud.terremark.com/api/v0.8b-ext2.5/org/1906645")), + new HttpResponse(302, "HTTP/1.1 302 Found", null, ImmutableMultimap.of(HttpHeaders.LOCATION, + "https://services1.enterprisecloud.terremark.com/api/v0.8b-ext2.5/org/1906645")), new HttpRequest( + "GET", URI.create("https://services1.enterprisecloud.terremark.com/api/v0.8b-ext2.5/org/1906645"))); + + } + + @Test + public void test302WithHeaderReplacesHostHeader() { + + verifyRedirectRoutes( + new HttpRequest("GET", + URI.create("https://services.enterprisecloud.terremark.com/api/v0.8b-ext2.5/org/1906645"), + ImmutableMultimap.of(HttpHeaders.HOST, "services.enterprisecloud.terremark.com")), + new HttpResponse(302, "HTTP/1.1 302 Found", null, ImmutableMultimap.of(HttpHeaders.LOCATION, + "https://services1.enterprisecloud.terremark.com/api/v0.8b-ext2.5/org/1906645")),// + new HttpRequest("GET", URI + .create("https://services1.enterprisecloud.terremark.com/api/v0.8b-ext2.5/org/1906645"), + ImmutableMultimap.of(HttpHeaders.HOST, "services1.enterprisecloud.terremark.com"))); + + } + + protected void verifyRedirectRoutes(HttpRequest request, HttpResponse response, HttpRequest expected) { + HttpCommand command = createMock(HttpCommand.class); + + expect(command.incrementRedirectCount()).andReturn(0); + expect(command.getRequest()).andReturn(request).atLeastOnce(); + + replay(command); + + RedirectionRetryHandler retry = Guice.createInjector(new MockModule(), new RestModule()).getInstance( + RedirectionRetryHandler.class); + + assert retry.shouldRetryRequest(command, response); + assertEquals(command.getRequest(), expected); + verify(command); + } +} diff --git a/core/src/test/java/org/jclouds/io/payloads/StringPayloadTest.java b/core/src/test/java/org/jclouds/io/payloads/StringPayloadTest.java new file mode 100644 index 0000000000..6a0fbfa7c8 --- /dev/null +++ b/core/src/test/java/org/jclouds/io/payloads/StringPayloadTest.java @@ -0,0 +1,40 @@ +/** + * + * 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.io.payloads; + +import static org.testng.Assert.assertEquals; + +import org.jclouds.io.Payload; +import org.testng.annotations.Test; + +import com.google.common.base.Charsets; + +/** + * + * @author Adrian Cole + */ +@Test +public class StringPayloadTest { + public void testLengthIsCorrectPerUTF8() { + Payload stringPayload = new StringPayload("unic₪de"); + assertEquals(stringPayload.getContentMetadata().getContentLength(), new Long( + "unic₪de".getBytes(Charsets.UTF_8).length)); + } +} diff --git a/core/src/test/java/org/jclouds/rest/BaseRestClientTest.java b/core/src/test/java/org/jclouds/rest/BaseRestClientTest.java index ee7abd1f37..df6dc40983 100644 --- a/core/src/test/java/org/jclouds/rest/BaseRestClientTest.java +++ b/core/src/test/java/org/jclouds/rest/BaseRestClientTest.java @@ -29,12 +29,13 @@ import static org.testng.Assert.assertNull; import java.io.IOException; import java.lang.reflect.Method; +import java.util.concurrent.ExecutorService; import javax.annotation.Nullable; +import org.jclouds.Constants; import org.jclouds.concurrent.MoreExecutors; import org.jclouds.concurrent.config.ConfiguresExecutorService; -import org.jclouds.concurrent.config.ExecutorServiceModule; import org.jclouds.crypto.Crypto; import org.jclouds.crypto.CryptoStreams; import org.jclouds.http.HttpRequest; @@ -47,6 +48,7 @@ import org.jclouds.rest.internal.RestAnnotationProcessor; import com.google.inject.AbstractModule; import com.google.inject.Injector; +import com.google.inject.name.Names; public abstract class BaseRestClientTest { @@ -69,7 +71,8 @@ public abstract class BaseRestClientTest { @Override protected void configure() { - install(new ExecutorServiceModule(MoreExecutors.sameThreadExecutor(), MoreExecutors.sameThreadExecutor())); + bind(ExecutorService.class).annotatedWith(Names.named(Constants.PROPERTY_USER_THREADS)).toInstance(MoreExecutors.sameThreadExecutor()); + bind(ExecutorService.class).annotatedWith(Names.named(Constants.PROPERTY_IO_WORKER_THREADS)).toInstance(MoreExecutors.sameThreadExecutor()); bind(TransformingHttpCommandExecutorService.class).toInstance(mock); } } diff --git a/core/src/test/java/org/jclouds/util/UtilsTest.java b/core/src/test/java/org/jclouds/util/UtilsTest.java index d17880b0db..8a5de24518 100644 --- a/core/src/test/java/org/jclouds/util/UtilsTest.java +++ b/core/src/test/java/org/jclouds/util/UtilsTest.java @@ -23,6 +23,7 @@ import static org.easymock.classextension.EasyMock.createMock; import static org.testng.Assert.assertEquals; import java.io.UnsupportedEncodingException; +import java.util.Map; import java.util.concurrent.TimeoutException; import org.jclouds.domain.Credentials; @@ -42,6 +43,15 @@ import com.google.inject.spi.Message; */ @Test(groups = "unit", testName = "jclouds.UtilsTest") public class UtilsTest { + public void testRenameKeyWhenNotFound() { + Map nothing = ImmutableMap.of(); + assertEquals(Utils.renameKey(nothing, "foo", "bar"), nothing); + } + + public void testRenameKeyWhenFound() { + Map nothing = ImmutableMap.of("foo", "bar"); + assertEquals(Utils.renameKey(nothing, "foo", "bar"), ImmutableMap.of("bar", "bar")); + } public void testOverridingCredentialsWhenOverridingIsNull() { Credentials defaultCredentials = new Credentials("foo", "bar"); @@ -69,7 +79,7 @@ public class UtilsTest { assertEquals(Utils.overrideCredentialsIfSupplied(defaultCredentials, overridingCredentials), new Credentials( "foo", "bar")); } - + public void testGetCause() { AuthorizationException aex = createMock(AuthorizationException.class); Message message = new Message(ImmutableList.of(), "test", aex); diff --git a/demos/gae-tweetstore/pom.xml b/demos/gae-tweetstore/pom.xml index 6b3063661a..7c716e5702 100644 --- a/demos/gae-tweetstore/pom.xml +++ b/demos/gae-tweetstore/pom.xml @@ -103,7 +103,7 @@ com.google.code.guice guice-servlet - 2.1-r1201 + 3.0-snapshot-20101120 displaytag diff --git a/filesystem/src/main/java/org/jclouds/filesystem/FilesystemAsyncBlobStore.java b/filesystem/src/main/java/org/jclouds/filesystem/FilesystemAsyncBlobStore.java index 3ffde30ddf..d8622888ac 100644 --- a/filesystem/src/main/java/org/jclouds/filesystem/FilesystemAsyncBlobStore.java +++ b/filesystem/src/main/java/org/jclouds/filesystem/FilesystemAsyncBlobStore.java @@ -49,12 +49,13 @@ import java.util.Collection; import java.util.Date; import java.util.List; import java.util.Map; +import java.util.Map.Entry; import java.util.Set; import java.util.SortedSet; import java.util.TreeSet; -import java.util.Map.Entry; import java.util.concurrent.ExecutorService; +import javax.annotation.Nullable; import javax.annotation.Resource; import javax.inject.Inject; import javax.inject.Named; @@ -66,13 +67,13 @@ import org.jclouds.blobstore.BlobStoreContext; import org.jclouds.blobstore.ContainerNotFoundException; import org.jclouds.blobstore.KeyNotFoundException; import org.jclouds.blobstore.domain.Blob; +import org.jclouds.blobstore.domain.Blob.Factory; import org.jclouds.blobstore.domain.BlobMetadata; import org.jclouds.blobstore.domain.MutableBlobMetadata; import org.jclouds.blobstore.domain.MutableStorageMetadata; import org.jclouds.blobstore.domain.PageSet; import org.jclouds.blobstore.domain.StorageMetadata; import org.jclouds.blobstore.domain.StorageType; -import org.jclouds.blobstore.domain.Blob.Factory; import org.jclouds.blobstore.domain.internal.MutableBlobMetadataImpl; import org.jclouds.blobstore.domain.internal.MutableStorageMetadataImpl; import org.jclouds.blobstore.domain.internal.PageSetImpl; @@ -107,7 +108,6 @@ import com.google.common.base.Throwables; import com.google.common.collect.Iterables; import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.ListenableFuture; -import com.google.inject.internal.Nullable; /** * diff --git a/filesystem/src/main/java/org/jclouds/filesystem/strategy/internal/FilesystemStorageStrategyImpl.java b/filesystem/src/main/java/org/jclouds/filesystem/strategy/internal/FilesystemStorageStrategyImpl.java index 038b4b0218..3955dc86f6 100644 --- a/filesystem/src/main/java/org/jclouds/filesystem/strategy/internal/FilesystemStorageStrategyImpl.java +++ b/filesystem/src/main/java/org/jclouds/filesystem/strategy/internal/FilesystemStorageStrategyImpl.java @@ -335,12 +335,12 @@ public class FilesystemStorageStrategyImpl implements FilesystemStorageStrategy * @return the resulting string */ protected String buildPathStartingFromBaseDir(String...pathTokens) { - String normalizedToken = removeFileSeparatorFromBorders(normalize(baseDirectory)); + String normalizedToken = removeFileSeparatorFromBorders(normalize(baseDirectory), true); StringBuilder completePath = new StringBuilder(normalizedToken); if(pathTokens!=null && pathTokens.length>0) { for(int i=0; i blobsExpected = TestUtils.createBlobsInContainer( + CONTAINER_NAME, + new String[] { + "bbb" + File.separator + "ccc" + File.separator + "ddd" + File.separator + "1234.jpg", + "4rrr.jpg", + "rrr" + File.separator + "sss" + File.separator + "788.jpg", + "rrr" + File.separator + "wert.kpg" } + ); + + //remove not expected values + blobsExpected.remove("bbb" + File.separator + "ccc" + File.separator + "ddd" + File.separator + "1234.jpg"); + blobsExpected.remove("4rrr.jpg"); + + checkForContainerContent(CONTAINER_NAME, "rrr", blobsExpected); + } + /** * TODO * Should throws an exception? @@ -809,12 +824,17 @@ public class FilesystemAsyncBlobStoreTest { * @param expectedBlobKeys */ private void checkForContainerContent(final String containerName, Set expectedBlobKeys) { + checkForContainerContent(containerName, null, expectedBlobKeys); + } + + private void checkForContainerContent(final String containerName, String inDirectory, Set expectedBlobKeys) { ListContainerOptions options = ListContainerOptions.Builder.recursive(); + if (null != inDirectory && !"".equals(inDirectory)) options.inDirectory(inDirectory); PageSet blobsRetrieved = blobStore.list(containerName, options); //nothing expected - if (null == expectedBlobKeys) { + if (null == expectedBlobKeys || 0 == expectedBlobKeys.size()) { assertTrue(blobsRetrieved.isEmpty(), "Wrong blob number retrieved in the containter [" + containerName + "]"); return; } diff --git a/filesystem/src/test/java/org/jclouds/filesystem/strategy/internal/FilesystemStorageStrategyImplTest.java b/filesystem/src/test/java/org/jclouds/filesystem/strategy/internal/FilesystemStorageStrategyImplTest.java index e1cfc40303..803bb85997 100644 --- a/filesystem/src/test/java/org/jclouds/filesystem/strategy/internal/FilesystemStorageStrategyImplTest.java +++ b/filesystem/src/test/java/org/jclouds/filesystem/strategy/internal/FilesystemStorageStrategyImplTest.java @@ -417,6 +417,38 @@ public class FilesystemStorageStrategyImplTest { } + public void testGetFileForBlobKey_AbsolutePath() + throws IOException { + String absoluteBasePath = (new File(getAbsoluteDirectory(), "basedir")).getAbsolutePath() + FS; + String absoluteContainerPath = absoluteBasePath + CONTAINER_NAME + FS; + + //create storageStrategy with an absolute path + FilesystemStorageStrategy storageStrategyAbsolute = new FilesystemStorageStrategyImpl( + new Blob.Factory() { + @Override + public Blob create(MutableBlobMetadata metadata) { + return new BlobImpl(metadata != null ? metadata : new MutableBlobMetadataImpl()); + } + }, + absoluteBasePath, + new FilesystemContainerNameValidatorImpl(), + new FilesystemBlobKeyValidatorImpl()); + TestUtils.cleanDirectoryContent(absoluteContainerPath); + + String blobKey; + File fileForPayload; + + blobKey = TestUtils.createRandomBlobKey("getFileForBlobKey-", ".img"); + fileForPayload = storageStrategyAbsolute.getFileForBlobKey(CONTAINER_NAME, blobKey); + assertNotNull(fileForPayload, "Result File object is null"); + assertEquals(fileForPayload.getAbsolutePath(), absoluteContainerPath + blobKey, "Wrong file path"); + + blobKey = TestUtils.createRandomBlobKey("asd" + FS + "vmad" + FS + "andsnf" + FS + "getFileForBlobKey-", ".img"); + fileForPayload = storageStrategyAbsolute.getFileForBlobKey(CONTAINER_NAME, blobKey); + assertEquals(fileForPayload.getAbsolutePath(), absoluteContainerPath + blobKey, "Wrong file path"); + } + + public void testBlobExists() throws IOException { String[] sourceBlobKeys = new String[]{ TestUtils.createRandomBlobKey("blobExists-", ".jpg"), @@ -530,5 +562,16 @@ public class FilesystemStorageStrategyImplTest { //---------------------------------------------------------- Private methods + /** + * Calculates an absolute directory path that depends on operative system + * @return + */ + private String getAbsoluteDirectory() throws IOException { + File tempFile = File.createTempFile("prefix", "suffix"); + String tempAbsolutePath = tempFile.getParent(); + + return tempAbsolutePath; + } + } diff --git a/gogrid/src/main/java/org/jclouds/gogrid/domain/ServerImage.java b/gogrid/src/main/java/org/jclouds/gogrid/domain/ServerImage.java index 17466febc4..b739f86ee9 100644 --- a/gogrid/src/main/java/org/jclouds/gogrid/domain/ServerImage.java +++ b/gogrid/src/main/java/org/jclouds/gogrid/domain/ServerImage.java @@ -89,6 +89,8 @@ public class ServerImage implements Comparable { } public String getDescription() { + if (description == null) + return ""; return description; } diff --git a/gogrid/src/main/java/org/jclouds/gogrid/functions/ParseServerNameToCredentialsMapFromJsonResponse.java b/gogrid/src/main/java/org/jclouds/gogrid/functions/ParseServerNameToCredentialsMapFromJsonResponse.java index 23199f6838..1525454d35 100644 --- a/gogrid/src/main/java/org/jclouds/gogrid/functions/ParseServerNameToCredentialsMapFromJsonResponse.java +++ b/gogrid/src/main/java/org/jclouds/gogrid/functions/ParseServerNameToCredentialsMapFromJsonResponse.java @@ -99,7 +99,8 @@ public class ParseServerNameToCredentialsMapFromJsonResponse implements @Override public int compareTo(Password o) { - return server.getName().compareTo(o.getServer().getName()); + if (null == o.getServer() || null == server) return -1; + return server.getName().compareTo(o.getServer().getName()); } } @@ -107,6 +108,7 @@ public class ParseServerNameToCredentialsMapFromJsonResponse implements public Map apply(HttpResponse arg0) { Map serverNameToCredentials = Maps.newHashMap(); for (Password password : json.apply(arg0).getList()) { + if( null != password.getServer()) serverNameToCredentials.put(password.getServer().getName(), new Credentials(password.getUserName(), password.getPassword())); } diff --git a/gogrid/src/test/java/org/jclouds/gogrid/functions/ParseCredentialsFromJsonResponseTest.java b/gogrid/src/test/java/org/jclouds/gogrid/functions/ParseCredentialsFromJsonResponseTest.java index 50503d1383..0ce6b8bd4a 100644 --- a/gogrid/src/test/java/org/jclouds/gogrid/functions/ParseCredentialsFromJsonResponseTest.java +++ b/gogrid/src/test/java/org/jclouds/gogrid/functions/ParseCredentialsFromJsonResponseTest.java @@ -71,7 +71,7 @@ public class ParseCredentialsFromJsonResponseTest { ParseCredentialsFromJsonResponse parser = i.getInstance(ParseCredentialsFromJsonResponse.class); Credentials creds = parser.apply(response); assertEquals(creds.identity, "root"); - assertEquals(creds.credential, "dig44sos"); + assertEquals(creds.credential, "zot40ced"); } diff --git a/gogrid/src/test/resources/test_credential.json b/gogrid/src/test/resources/test_credential.json index 924fbf5aa0..18bdec7887 100644 --- a/gogrid/src/test/resources/test_credential.json +++ b/gogrid/src/test/resources/test_credential.json @@ -1,103 +1,124 @@ { "list": [ - { - "password": "dig44sos", - "object": "password", - "username": "root", - "server": { - "object": "server", - "isSandbox": false, + { + "password": "zot40ced", + "object": "password", + "username": "root", + "server": { + "isSandbox": false, + "object": "server", + "type": { + "id": 1, + "description": "Web or Application Server", + "name": "Web Server", + "object": "option" + }, + "os": { + "id": 17, + "description": "CentOS 5.3 (64-bit)", + "name": "CentOS 5.3 (64-bit)", + "object": "option" + }, + "image": { "type": { - "object": "option", + "id": 1, "description": "Web or Application Server", "name": "Web Server", - "id": 1 + "object": "option" }, + "owner": { + "id": -1, + "name": "GoGrid", + "object": "customer" + }, + "updatedTime": 1257789076417, + "isActive": true, + "id": 1532, + "isPublic": true, + "name": "centos5.3_64_base", + "billingtokens": [ + { + "id": 47, + "price": 0, + "name": "CentOS 5.3 64bit", + "object": "billingtoken" + } + ], + "object": "serverimage", + "friendlyName": "CentOS 5.3 (64-bit) w/ None", "os": { - "object": "option", + "id": 17, "description": "CentOS 5.3 (64-bit)", "name": "CentOS 5.3 (64-bit)", - "id": 17 - }, - "image": { - "type": { - "object": "option", - "description": "Web or Application Server", - "name": "Web Server", - "id": 1 - }, - "owner": { - "object": "customer", - "name": "Gear6", - "id": 26443 - }, - "updatedTime": 1265675466171, - "isActive": true, - "id": 2500, - "createdTime": 1265412834154, - "isPublic": true, - "billingtokens": [ - { - "price": 0, - "name": "CentOS 5.3 64bit", - "id": 47 - }, - { - "price": 60, - "name": "Gear 6 Paid Version", - "id": 76 - } - ], - "object": "serverimage", - "friendlyName": "gear6-memcache-server-2.3.6.2-x86_64", - "os": { - "object": "option", - "description": "CentOS 5.3 (64-bit)", - "name": "CentOS 5.3 (64-bit)", - "id": 17 - }, - "price": 60, - "description": "Gear6 Memcache Server 2.3.6.2 (64 bit)", - "state": { - "object": "option", - "description": "Image is available for adds", - "name": "Available", - "id": 2 - }, - "location": "26443/GSI-7f498260-2b8a-43ef-aa77-5b403f8f739a.img", - "name": "GSI-7f498260-2b8a-43ef-aa77-5b403f8f739a" + "object": "option" }, + "price": 0, + "description": "CentOS 5.3 (64-bit) w/ None", "state": { - "object": "option", - "description": "Server is in active state.", - "name": "On", - "id": 1 + "id": 2, + "description": "Image is available for adds", + "name": "Available", + "object": "option" }, - "ram": { - "object": "option", - "description": "Server with 512MB RAM", - "name": "512MB", - "id": 1 - }, - "name": "gogrid-19", - "ip": { - "object": "ip", - "public": true, - "subnet": "204.51.240.176/255.255.255.240", - "state": { - "object": "option", - "description": "IP is reserved or in use", - "name": "Assigned", - "id": 2 - }, - "ip": "204.51.240.189", - "id": 1313090 - }, - "id": 77332 + "location": "gogrid/GSI-939ef909-84b8-4a2f-ad56-02ccd7da05ff.img", + "name": "bogus", + "architecture": { + "id": 2, + "description": "64 bit OS", + "name": "64-bit", + "object": "option" + } }, - "id": 82647, - "applicationtype": "os" - } + "state": { + "id": 1, + "description": "Server is in active state.", + "name": "On", + "object": "option" + }, + "ram": { + "id": 1, + "description": "Server with 512MB RAM", + "name": "512MB", + "object": "option" + }, + "name": "proxied-944", + "ip": { + "id": 1104200, + "subnet": "173.1.155.16/255.255.255.240", + "state": { + "id": 2, + "description": "IP is reserved or in use", + "name": "Assigned", + "object": "option" + }, + "datacenter": { + "id": 1, + "description": "US West 1 Datacenter", + "name": "US-West-1", + "object": "option" + }, + "object": "ip", + "public": true, + "ip": "173.1.155.19" + }, + "datacenter": { + "id": 1, + "description": "US West 1 Datacenter", + "name": "US-West-1", + "object": "option" + }, + "id": 134551 + }, + "id": 142243, + "applicationtype": "os" + }, + { + "id": 28000, + "username": "22290", + "applicationtype": "cloudstorage", + "object": "password", + "password": "200FMd2nDeomtfW." + } ], "summary": { "total": 6, @@ -107,4 +128,4 @@ }, "status": "success", "method": "/support/password/list" -} \ No newline at end of file +} diff --git a/rackspace/src/main/java/org/jclouds/rackspace/cloudfiles/domain/CFObject.java b/rackspace/src/main/java/org/jclouds/rackspace/cloudfiles/domain/CFObject.java index abefae7c34..182916521a 100644 --- a/rackspace/src/main/java/org/jclouds/rackspace/cloudfiles/domain/CFObject.java +++ b/rackspace/src/main/java/org/jclouds/rackspace/cloudfiles/domain/CFObject.java @@ -19,10 +19,11 @@ package org.jclouds.rackspace.cloudfiles.domain; +import javax.annotation.Nullable; + import org.jclouds.io.PayloadEnclosing; import com.google.common.collect.Multimap; -import com.google.inject.internal.Nullable; /** * diff --git a/rackspace/src/main/java/org/jclouds/rackspace/cloudservers/options/CreateSharedIpGroupOptions.java b/rackspace/src/main/java/org/jclouds/rackspace/cloudservers/options/CreateSharedIpGroupOptions.java index a69269654f..3b5af4042a 100644 --- a/rackspace/src/main/java/org/jclouds/rackspace/cloudservers/options/CreateSharedIpGroupOptions.java +++ b/rackspace/src/main/java/org/jclouds/rackspace/cloudservers/options/CreateSharedIpGroupOptions.java @@ -24,11 +24,12 @@ import static com.google.common.base.Preconditions.checkNotNull; import java.util.Map; +import javax.annotation.Nullable; + import org.jclouds.http.HttpRequest; import org.jclouds.rest.binders.BindToJsonPayload; import com.google.common.collect.ImmutableMap; -import com.google.inject.internal.Nullable; /** * diff --git a/sandbox/elasticstack/pom.xml b/sandbox/elasticstack/pom.xml new file mode 100644 index 0000000000..9e3d3d15dd --- /dev/null +++ b/sandbox/elasticstack/pom.xml @@ -0,0 +1,139 @@ + + + + 4.0.0 + + org.jclouds + jclouds-project + 1.0-SNAPSHOT + ../../project/pom.xml + + org.jclouds + jclouds-elasticstack + jclouds elasticstack core + jclouds components to access elasticstack + + + scm:svn:http://jclouds.googlecode.com/svn/trunk/elasticstack + scm:svn:https://jclouds.googlecode.com/svn/trunk/elasticstack + http://jclouds.googlecode.com/svn/trunk/elasticstack + + + + + + jclouds-googlecode-deploy + http://jclouds.googlecode.com/svn/repo + + + jclouds-rimu-snapshots-nexus + https://oss.sonatype.org/content/repositories/snapshots + + true + + + + + + + trmkrun-ccc,test.trmk-924 + https://api.cloudsigma.com + 1.0 + FIXME + FIXME + + + + ${project.groupId} + jclouds-core + ${project.version} + + + ${project.groupId} + jclouds-core + ${project.version} + test-jar + test + + + log4j + log4j + 1.2.14 + test + + + ${project.groupId} + jclouds-log4j + ${project.version} + test + + + + + live + + + + org.apache.maven.plugins + maven-surefire-plugin + + + integration + integration-test + + test + + + + + test.elasticstack.endpoint + ${test.elasticstack.endpoint} + + + test.elasticstack.apiversion + ${test.elasticstack.apiversion} + + + test.elasticstack.identity + ${test.elasticstack.identity} + + + test.elasticstack.credential + ${test.elasticstack.credential} + + + jclouds.compute.blacklist-nodes + ${jclouds.compute.blacklist-nodes} + + + + + + + + + + + diff --git a/sandbox/elasticstack/src/main/java/org/jclouds/cloudsigma/CloudSigmaAsyncClient.java b/sandbox/elasticstack/src/main/java/org/jclouds/cloudsigma/CloudSigmaAsyncClient.java new file mode 100644 index 0000000000..45d2c2dba4 --- /dev/null +++ b/sandbox/elasticstack/src/main/java/org/jclouds/cloudsigma/CloudSigmaAsyncClient.java @@ -0,0 +1,125 @@ +/** + * + * 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.cloudsigma; + +import java.util.Set; + +import javax.ws.rs.Consumes; +import javax.ws.rs.GET; +import javax.ws.rs.POST; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.core.MediaType; + +import org.jclouds.cloudsigma.domain.DriveInfo; +import org.jclouds.cloudsigma.functions.KeyValuesDelimitedByBlankLinesToDriveInfo; +import org.jclouds.cloudsigma.functions.ListOfKeyValuesDelimitedByBlankLinesToDriveInfoSet; +import org.jclouds.elasticstack.CommonElasticStackAsyncClient; +import org.jclouds.elasticstack.ElasticStackClient; +import org.jclouds.elasticstack.binders.BindCreateDriveRequestToPlainTextString; +import org.jclouds.elasticstack.binders.BindDriveDataToPlainTextString; +import org.jclouds.elasticstack.domain.CreateDriveRequest; +import org.jclouds.elasticstack.domain.DriveData; +import org.jclouds.elasticstack.functions.SplitNewlines; +import org.jclouds.http.filters.BasicAuthentication; +import org.jclouds.rest.annotations.BinderParam; +import org.jclouds.rest.annotations.ExceptionParser; +import org.jclouds.rest.annotations.RequestFilters; +import org.jclouds.rest.annotations.ResponseParser; +import org.jclouds.rest.functions.ReturnNullOnNotFoundOr404; + +import com.google.common.util.concurrent.ListenableFuture; + +/** + * Provides asynchronous access to CloudSigma via their REST API. + *

+ * + * @see ElasticStackClient + * @see + * @author Adrian Cole + */ +@RequestFilters(BasicAuthentication.class) +@Consumes(MediaType.TEXT_PLAIN) +public interface CloudSigmaAsyncClient extends CommonElasticStackAsyncClient { + + /** + * @see ElasticStackClient#listStandardDrives() + */ + @GET + @Path("/drives/standard/list") + @ResponseParser(SplitNewlines.class) + ListenableFuture> listStandardDrives(); + + /** + * @see ElasticStackClient#listStandardCds() + */ + @GET + @Path("/drives/standard/cd/list") + @ResponseParser(SplitNewlines.class) + ListenableFuture> listStandardCds(); + + /** + * @see ElasticStackClient#listStandardImages() + */ + @GET + @Path("/drives/standard/img/list") + @ResponseParser(SplitNewlines.class) + ListenableFuture> listStandardImages(); + + /** + * @see ElasticStackClient#listDriveInfo() + */ + @Override + @GET + @Path("/drives/info") + @ResponseParser(ListOfKeyValuesDelimitedByBlankLinesToDriveInfoSet.class) + ListenableFuture> listDriveInfo(); + + /** + * @see ElasticStackClient#getDriveInfo + */ + @Override + @GET + @ExceptionParser(ReturnNullOnNotFoundOr404.class) + @ResponseParser(KeyValuesDelimitedByBlankLinesToDriveInfo.class) + @Path("/drives/{uuid}/info") + ListenableFuture getDriveInfo(@PathParam("uuid") String uuid); + + /** + * @see ElasticStackClient#createDrive + */ + @Override + @POST + @ExceptionParser(ReturnNullOnNotFoundOr404.class) + @ResponseParser(KeyValuesDelimitedByBlankLinesToDriveInfo.class) + @Path("/drives/create") + ListenableFuture createDrive( + @BinderParam(BindCreateDriveRequestToPlainTextString.class) CreateDriveRequest createDrive); + + /** + * @see ElasticStackClient#setDriveData + */ + @POST + @ExceptionParser(ReturnNullOnNotFoundOr404.class) + @ResponseParser(KeyValuesDelimitedByBlankLinesToDriveInfo.class) + @Path("/drives/{uuid}/set") + ListenableFuture setDriveData(@PathParam("uuid") String uuid, + @BinderParam(BindDriveDataToPlainTextString.class) DriveData createDrive); +} diff --git a/sandbox/elasticstack/src/main/java/org/jclouds/cloudsigma/CloudSigmaClient.java b/sandbox/elasticstack/src/main/java/org/jclouds/cloudsigma/CloudSigmaClient.java new file mode 100644 index 0000000000..354ee916af --- /dev/null +++ b/sandbox/elasticstack/src/main/java/org/jclouds/cloudsigma/CloudSigmaClient.java @@ -0,0 +1,87 @@ +/** + * + * 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.cloudsigma; + +import java.util.Set; +import java.util.concurrent.TimeUnit; + +import org.jclouds.cloudsigma.domain.DriveInfo; +import org.jclouds.concurrent.Timeout; +import org.jclouds.elasticstack.CommonElasticStackClient; +import org.jclouds.elasticstack.domain.CreateDriveRequest; +import org.jclouds.elasticstack.domain.DriveData; + +/** + * Provides synchronous access to CloudSigma. + *

+ * + * @see CloudSigmaAsyncClient + * @see + * @author Adrian Cole + */ +@Timeout(duration = 60, timeUnit = TimeUnit.SECONDS) +public interface CloudSigmaClient extends CommonElasticStackClient { + + /** + * list of drive uuids that are in the library + * + * @return or empty set if no drives are found + */ + Set listStandardDrives(); + + /** + * list of cd uuids that are in the library + * + * @return or empty set if no cds are found + */ + Set listStandardCds(); + + /** + * list of image uuids that are in the library + * + * @return or empty set if no images are found + */ + Set listStandardImages(); + + /** + * {@inheritDoc} + */ + @Override + Set listDriveInfo(); + + /** + * {@inheritDoc} + */ + @Override + DriveInfo getDriveInfo(String uuid); + + /** + * {@inheritDoc} + */ + @Override + DriveInfo createDrive(CreateDriveRequest createDrive); + + /** + * {@inheritDoc} + */ + @Override + DriveInfo setDriveData(String uuid, DriveData driveData); + +} diff --git a/sandbox/elasticstack/src/main/java/org/jclouds/cloudsigma/CloudSigmaContextBuilder.java b/sandbox/elasticstack/src/main/java/org/jclouds/cloudsigma/CloudSigmaContextBuilder.java new file mode 100644 index 0000000000..d69dfc3874 --- /dev/null +++ b/sandbox/elasticstack/src/main/java/org/jclouds/cloudsigma/CloudSigmaContextBuilder.java @@ -0,0 +1,45 @@ +/** + * + * 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.cloudsigma; + +import java.util.List; +import java.util.Properties; + +import org.jclouds.cloudsigma.config.CloudSigmaRestClientModule; +import org.jclouds.rest.RestContextBuilder; + +import com.google.inject.Module; + +/** + * + * @author Adrian Cole + */ +public class CloudSigmaContextBuilder extends + RestContextBuilder { + + public CloudSigmaContextBuilder(Properties props) { + super(CloudSigmaClient.class, CloudSigmaAsyncClient.class, props); + } + + protected void addClientModule(List modules) { + modules.add(new CloudSigmaRestClientModule()); + } + +} diff --git a/sandbox/elasticstack/src/main/java/org/jclouds/cloudsigma/CloudSigmaPropertiesBuilder.java b/sandbox/elasticstack/src/main/java/org/jclouds/cloudsigma/CloudSigmaPropertiesBuilder.java new file mode 100644 index 0000000000..d1daf9bde5 --- /dev/null +++ b/sandbox/elasticstack/src/main/java/org/jclouds/cloudsigma/CloudSigmaPropertiesBuilder.java @@ -0,0 +1,47 @@ +/** + * + * 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.cloudsigma; + +import static org.jclouds.Constants.PROPERTY_API_VERSION; +import static org.jclouds.Constants.PROPERTY_ENDPOINT; + +import java.util.Properties; + +import org.jclouds.PropertiesBuilder; + +/** + * Builds properties used in CloudSigma Clients + * + * @author Adrian Cole + */ +public class CloudSigmaPropertiesBuilder extends PropertiesBuilder { + @Override + protected Properties defaultProperties() { + Properties properties = super.defaultProperties(); + properties.setProperty(PROPERTY_ENDPOINT, "https://api.cloudsigma.com"); + properties.setProperty(PROPERTY_API_VERSION, "1.0"); + return properties; + } + + public CloudSigmaPropertiesBuilder(Properties properties) { + super(properties); + } + +} diff --git a/sandbox/elasticstack/src/main/java/org/jclouds/cloudsigma/config/CloudSigmaRestClientModule.java b/sandbox/elasticstack/src/main/java/org/jclouds/cloudsigma/config/CloudSigmaRestClientModule.java new file mode 100644 index 0000000000..453362e8ae --- /dev/null +++ b/sandbox/elasticstack/src/main/java/org/jclouds/cloudsigma/config/CloudSigmaRestClientModule.java @@ -0,0 +1,76 @@ +/** + * + * 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.cloudsigma.config; + +import java.util.Map; + +import org.jclouds.cloudsigma.CloudSigmaAsyncClient; +import org.jclouds.cloudsigma.CloudSigmaClient; +import org.jclouds.cloudsigma.functions.CreateDriveRequestToMap; +import org.jclouds.cloudsigma.functions.DriveDataToMap; +import org.jclouds.elasticstack.domain.CreateDriveRequest; +import org.jclouds.elasticstack.domain.DriveData; +import org.jclouds.elasticstack.handlers.ElasticStackErrorHandler; +import org.jclouds.http.HttpErrorHandler; +import org.jclouds.http.RequiresHttp; +import org.jclouds.http.annotation.ClientError; +import org.jclouds.http.annotation.Redirection; +import org.jclouds.http.annotation.ServerError; +import org.jclouds.rest.ConfiguresRestClient; +import org.jclouds.rest.config.RestClientModule; + +import com.google.common.base.Function; +import com.google.inject.TypeLiteral; + +/** + * Configures the CloudSigma connection. + * + * @author Adrian Cole + */ +@RequiresHttp +@ConfiguresRestClient +public class CloudSigmaRestClientModule extends RestClientModule { + + public CloudSigmaRestClientModule() { + super(CloudSigmaClient.class, CloudSigmaAsyncClient.class); + } + + @Override + protected void bindErrorHandlers() { + bind(HttpErrorHandler.class).annotatedWith(Redirection.class).to(ElasticStackErrorHandler.class); + bind(HttpErrorHandler.class).annotatedWith(ClientError.class).to(ElasticStackErrorHandler.class); + bind(HttpErrorHandler.class).annotatedWith(ServerError.class).to(ElasticStackErrorHandler.class); + } + + @Override + protected void configure() { + super.configure(); + bind(new TypeLiteral>>() { + }).to(CreateDriveRequestToMap.class); + bind(new TypeLiteral>>() { + }).to(DriveDataToMap.class); + } + + @Override + protected void bindRetryHandlers() { + // TODO + } + +} diff --git a/sandbox/elasticstack/src/main/java/org/jclouds/cloudsigma/domain/DriveInfo.java b/sandbox/elasticstack/src/main/java/org/jclouds/cloudsigma/domain/DriveInfo.java new file mode 100644 index 0000000000..d549f4dee0 --- /dev/null +++ b/sandbox/elasticstack/src/main/java/org/jclouds/cloudsigma/domain/DriveInfo.java @@ -0,0 +1,415 @@ +/** + * + * 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.cloudsigma.domain; + +import static com.google.common.base.Preconditions.checkNotNull; + +import java.net.URI; +import java.util.Map; +import java.util.Set; + +import org.jclouds.elasticstack.domain.ClaimType; +import org.jclouds.elasticstack.domain.DriveStatus; + +import com.google.common.collect.ImmutableSet; + +/** + * + * @author Adrian Cole + */ +public class DriveInfo extends org.jclouds.elasticstack.domain.DriveInfo { + public static class Builder extends org.jclouds.elasticstack.domain.DriveInfo.Builder { + private Boolean autoexpanding; + private Integer bits; + private String description; + private Set driveType = ImmutableSet.of(); + private String encryptionKey; + private Boolean free; + private String installNotes; + private String os; + private DriveType type; + private URI url; + + public Builder autoexpanding(Boolean autoexpanding) { + this.autoexpanding = autoexpanding; + return this; + } + + public Builder bits(Integer bits) { + this.bits = bits; + return this; + } + + public Builder description(String description) { + this.description = description; + return this; + } + + public Builder driveType(Iterable driveType) { + this.driveType = ImmutableSet.copyOf(checkNotNull(driveType, "driveType")); + return this; + } + + public Builder encryptionKey(String encryptionKey) { + this.encryptionKey = encryptionKey; + return this; + } + + public Builder free(Boolean free) { + this.free = free; + return this; + } + + public Builder installNotes(String installNotes) { + this.installNotes = installNotes; + return this; + } + + public Builder os(String os) { + this.os = os; + return this; + } + + public Builder type(DriveType type) { + this.type = type; + return this; + } + + public Builder url(URI url) { + this.url = url; + return this; + } + + /** + * {@inheritDoc} + */ + @Override + public Builder status(DriveStatus status) { + return Builder.class.cast(super.status(status)); + } + + /** + * {@inheritDoc} + */ + @Override + public Builder user(String user) { + return Builder.class.cast(super.user(user)); + } + + /** + * {@inheritDoc} + */ + @Override + public Builder claimed(Iterable claimed) { + return Builder.class.cast(super.claimed(claimed)); + } + + /** + * {@inheritDoc} + */ + @Override + public Builder imaging(String imaging) { + return Builder.class.cast(super.imaging(imaging)); + } + + /** + * {@inheritDoc} + */ + @Override + public Builder readBytes(long readBytes) { + return Builder.class.cast(super.readBytes(readBytes)); + } + + /** + * {@inheritDoc} + */ + @Override + public Builder readRequests(long readRequests) { + return Builder.class.cast(super.readRequests(readRequests)); + } + + /** + * {@inheritDoc} + */ + @Override + public Builder writeBytes(long writeBytes) { + return Builder.class.cast(super.writeBytes(writeBytes)); + } + + /** + * {@inheritDoc} + */ + @Override + public Builder writeRequests(long writeRequests) { + return Builder.class.cast(super.writeRequests(writeRequests)); + } + + /** + * {@inheritDoc} + */ + @Override + public Builder encryptionCipher(String encryptionCipher) { + return Builder.class.cast(super.encryptionCipher(encryptionCipher)); + } + + /** + * {@inheritDoc} + */ + @Override + public Builder claimType(ClaimType claimType) { + return Builder.class.cast(super.claimType(claimType)); + } + + /** + * {@inheritDoc} + */ + @Override + public Builder readers(Iterable readers) { + return Builder.class.cast(super.readers(readers)); + } + + /** + * {@inheritDoc} + */ + @Override + public Builder size(long size) { + return Builder.class.cast(super.size(size)); + } + + /** + * {@inheritDoc} + */ + @Override + public Builder uuid(String uuid) { + return Builder.class.cast(super.uuid(uuid)); + } + + /** + * {@inheritDoc} + */ + @Override + public Builder name(String name) { + return Builder.class.cast(super.name(name)); + } + + /** + * {@inheritDoc} + */ + @Override + public Builder tags(Iterable tags) { + return Builder.class.cast(super.tags(tags)); + } + + /** + * {@inheritDoc} + */ + @Override + public Builder userMetadata(Map userMetadata) { + return Builder.class.cast(super.userMetadata(userMetadata)); + } + + public static Builder fromDriveInfo(org.jclouds.elasticstack.domain.DriveInfo driveInfo) { + return new Builder().uuid(driveInfo.getUuid()).name(driveInfo.getName()).size(driveInfo.getSize()) + .claimType(driveInfo.getClaimType()).readers(driveInfo.getReaders()).tags(driveInfo.getTags()) + .userMetadata(driveInfo.getUserMetadata()).status(driveInfo.getStatus()).user(driveInfo.getUser()) + .claimed(driveInfo.getClaimed()).encryptionCipher(driveInfo.getEncryptionCipher()) + .imaging(driveInfo.getImaging()).readBytes(driveInfo.getReadBytes()) + .readRequests(driveInfo.getReadRequests()).writeBytes(driveInfo.getWriteBytes()) + .writeRequests(driveInfo.getWriteRequests()); + } + + /** + * {@inheritDoc} + */ + @Override + public DriveInfo build() { + return new DriveInfo(uuid, name, size, claimType, readers, tags, userMetadata, status, user, claimed, + encryptionCipher, imaging, readBytes, readRequests, writeBytes, writeRequests, autoexpanding, bits, + description, driveType, encryptionKey, free, installNotes, os, type, url); + } + } + + private final Boolean autoexpanding; + private final Integer bits; + private final String description; + private final ImmutableSet driveType; + private final String encryptionKey; + private final Boolean free; + private final String installNotes; + private final String os; + private final DriveType type; + private final URI url; + + public DriveInfo(String uuid, String name, long size, ClaimType claimType, Iterable readers, + Iterable tags, Map userMetadata, DriveStatus status, String user, Set claimed, + String encryptionCipher, String imaging, long readBytes, long readRequests, long writeBytes, + long writeRequests, Boolean autoexpanding, Integer bits, String description, Iterable driveType, + String encryptionKey, Boolean free, String installNotes, String os, DriveType type, URI url) { + super(uuid, name, size, claimType, readers, tags, userMetadata, status, user, claimed, encryptionCipher, imaging, + readBytes, readRequests, writeBytes, writeRequests); + this.autoexpanding = autoexpanding; + this.bits = bits; + this.description = description; + this.driveType = ImmutableSet.copyOf(driveType); + this.encryptionKey = encryptionKey; + this.free = free; + this.installNotes = installNotes; + this.os = os; + this.type = type; + this.url = url; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = super.hashCode(); + result = prime * result + ((autoexpanding == null) ? 0 : autoexpanding.hashCode()); + result = prime * result + ((bits == null) ? 0 : bits.hashCode()); + result = prime * result + ((description == null) ? 0 : description.hashCode()); + result = prime * result + ((driveType == null) ? 0 : driveType.hashCode()); + result = prime * result + ((encryptionKey == null) ? 0 : encryptionKey.hashCode()); + result = prime * result + ((free == null) ? 0 : free.hashCode()); + result = prime * result + ((installNotes == null) ? 0 : installNotes.hashCode()); + result = prime * result + ((os == null) ? 0 : os.hashCode()); + result = prime * result + ((type == null) ? 0 : type.hashCode()); + result = prime * result + ((url == null) ? 0 : url.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; + DriveInfo other = (DriveInfo) obj; + if (autoexpanding == null) { + if (other.autoexpanding != null) + return false; + } else if (!autoexpanding.equals(other.autoexpanding)) + return false; + if (bits == null) { + if (other.bits != null) + return false; + } else if (!bits.equals(other.bits)) + return false; + if (description == null) { + if (other.description != null) + return false; + } else if (!description.equals(other.description)) + return false; + if (driveType == null) { + if (other.driveType != null) + return false; + } else if (!driveType.equals(other.driveType)) + return false; + if (encryptionKey == null) { + if (other.encryptionKey != null) + return false; + } else if (!encryptionKey.equals(other.encryptionKey)) + return false; + if (free == null) { + if (other.free != null) + return false; + } else if (!free.equals(other.free)) + return false; + if (installNotes == null) { + if (other.installNotes != null) + return false; + } else if (!installNotes.equals(other.installNotes)) + return false; + if (os == null) { + if (other.os != null) + return false; + } else if (!os.equals(other.os)) + return false; + if (type != other.type) + return false; + if (url == null) { + if (other.url != null) + return false; + } else if (!url.equals(other.url)) + return false; + return true; + } + + // TODO + public Boolean getAutoexpanding() { + return autoexpanding; + } + + // TODO + public Integer getBits() { + return bits; + } + + // TODO undocumented + public String getDescription() { + return description; + } + + // TODO + public Set getDriveType() { + return driveType; + } + + // TODO + public String getEncryptionKey() { + return encryptionKey; + } + + // TODO + public Boolean getFree() { + return free; + } + + // TODO + public String getInstallNotes() { + return installNotes; + } + + // TODO + public String getOs() { + return os; + } + + // TODO + public DriveType getType() { + return type; + } + + // TODO + + @Override + public String toString() { + return "[size=" + size + ", claimType=" + claimType + ", readers=" + readers + ", uuid=" + uuid + ", name=" + + name + ", tags=" + tags + ", userMetadata=" + userMetadata + ", autoexpanding=" + autoexpanding + + ", bits=" + bits + ", description=" + description + ", driveType=" + driveType + ", encryptionKey=" + + encryptionKey + ", free=" + free + ", installNotes=" + installNotes + ", os=" + os + ", type=" + type + + ", url=" + url + "]"; + } + + public URI getUrl() { + return url; + } + +} \ No newline at end of file diff --git a/sandbox/elasticstack/src/main/java/org/jclouds/cloudsigma/domain/DriveType.java b/sandbox/elasticstack/src/main/java/org/jclouds/cloudsigma/domain/DriveType.java new file mode 100644 index 0000000000..528320ddd7 --- /dev/null +++ b/sandbox/elasticstack/src/main/java/org/jclouds/cloudsigma/domain/DriveType.java @@ -0,0 +1,48 @@ +/** + * + * 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.cloudsigma.domain; + +import static com.google.common.base.Preconditions.checkNotNull; + +/** + * + * @author Adrian Cole + */ +public enum DriveType { + DISK, CDROM, SHARED, UNRECOGNIZED; + + public String value() { + return name().toLowerCase(); + } + + @Override + public String toString() { + return value(); + } + + public static DriveType fromValue(String type) { + try { + return valueOf(checkNotNull(type, "type").toUpperCase()); + } catch (IllegalArgumentException e) { + return UNRECOGNIZED; + } + } + +} \ No newline at end of file diff --git a/sandbox/elasticstack/src/main/java/org/jclouds/cloudsigma/functions/CreateDriveRequestToMap.java b/sandbox/elasticstack/src/main/java/org/jclouds/cloudsigma/functions/CreateDriveRequestToMap.java new file mode 100644 index 0000000000..dc8992a550 --- /dev/null +++ b/sandbox/elasticstack/src/main/java/org/jclouds/cloudsigma/functions/CreateDriveRequestToMap.java @@ -0,0 +1,58 @@ +/** + * + * 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.cloudsigma.functions; + +import static org.jclouds.util.Utils.renameKey; + +import java.util.Map; + +import javax.inject.Inject; +import javax.inject.Singleton; + +import org.jclouds.elasticstack.domain.CreateDriveRequest; + +import com.google.common.base.Function; +import com.google.common.collect.Maps; + +/** + * + * @author Adrian Cole + */ +@Singleton +public class CreateDriveRequestToMap implements Function> { + private final org.jclouds.elasticstack.functions.CreateDriveRequestToMap baseDriveToMap; + + @Inject + public CreateDriveRequestToMap(org.jclouds.elasticstack.functions.CreateDriveRequestToMap baseDriveToMap) { + this.baseDriveToMap = baseDriveToMap; + } + + @Override + public Map apply(CreateDriveRequest from) { + return Maps.transformEntries(renameKey(baseDriveToMap.apply(from), "tags", "use"), + new Maps.EntryTransformer() { + + @Override + public String transformEntry(String arg0, String arg1) { + return "use".equals(arg0) ? arg1.replace(' ', ',') : arg1; + } + + }); } +} \ No newline at end of file diff --git a/sandbox/elasticstack/src/main/java/org/jclouds/cloudsigma/functions/DriveDataToMap.java b/sandbox/elasticstack/src/main/java/org/jclouds/cloudsigma/functions/DriveDataToMap.java new file mode 100644 index 0000000000..715098e6b8 --- /dev/null +++ b/sandbox/elasticstack/src/main/java/org/jclouds/cloudsigma/functions/DriveDataToMap.java @@ -0,0 +1,59 @@ +/** + * + * 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.cloudsigma.functions; + +import static org.jclouds.util.Utils.renameKey; + +import java.util.Map; + +import javax.inject.Inject; +import javax.inject.Singleton; + +import org.jclouds.elasticstack.domain.DriveData; + +import com.google.common.base.Function; +import com.google.common.collect.Maps; + +/** + * + * @author Adrian Cole + */ +@Singleton +public class DriveDataToMap implements Function> { + private final org.jclouds.elasticstack.functions.DriveDataToMap baseDriveToMap; + + @Inject + public DriveDataToMap(org.jclouds.elasticstack.functions.DriveDataToMap baseDriveToMap) { + this.baseDriveToMap = baseDriveToMap; + } + + @Override + public Map apply(DriveData from) { + return Maps.transformEntries(renameKey(baseDriveToMap.apply(from), "tags", "use"), + new Maps.EntryTransformer() { + + @Override + public String transformEntry(String arg0, String arg1) { + return "use".equals(arg0) ? arg1.replace(' ', ',') : arg1; + } + + }); + } +} \ No newline at end of file diff --git a/sandbox/elasticstack/src/main/java/org/jclouds/cloudsigma/functions/KeyValuesDelimitedByBlankLinesToDriveInfo.java b/sandbox/elasticstack/src/main/java/org/jclouds/cloudsigma/functions/KeyValuesDelimitedByBlankLinesToDriveInfo.java new file mode 100644 index 0000000000..3f9cf3912c --- /dev/null +++ b/sandbox/elasticstack/src/main/java/org/jclouds/cloudsigma/functions/KeyValuesDelimitedByBlankLinesToDriveInfo.java @@ -0,0 +1,53 @@ +/** + * + * 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.cloudsigma.functions; + +import java.util.Set; + +import javax.inject.Inject; +import javax.inject.Singleton; + +import org.jclouds.cloudsigma.domain.DriveInfo; +import org.jclouds.http.HttpResponse; + +import com.google.common.base.Function; +import com.google.common.collect.Iterables; + +/** + * + * @author Adrian Cole + */ +@Singleton +public class KeyValuesDelimitedByBlankLinesToDriveInfo implements Function { + private final ListOfKeyValuesDelimitedByBlankLinesToDriveInfoSet setParser; + + @Inject + public KeyValuesDelimitedByBlankLinesToDriveInfo(ListOfKeyValuesDelimitedByBlankLinesToDriveInfoSet setParser) { + this.setParser = setParser; + } + + @Override + public DriveInfo apply(HttpResponse response) { + Set drives = setParser.apply(response); + if (drives.size() == 0) + return null; + return Iterables.get(drives, 0); + } +} \ No newline at end of file diff --git a/sandbox/elasticstack/src/main/java/org/jclouds/cloudsigma/functions/ListOfKeyValuesDelimitedByBlankLinesToDriveInfoSet.java b/sandbox/elasticstack/src/main/java/org/jclouds/cloudsigma/functions/ListOfKeyValuesDelimitedByBlankLinesToDriveInfoSet.java new file mode 100644 index 0000000000..3d7d1a3d53 --- /dev/null +++ b/sandbox/elasticstack/src/main/java/org/jclouds/cloudsigma/functions/ListOfKeyValuesDelimitedByBlankLinesToDriveInfoSet.java @@ -0,0 +1,61 @@ +/** + * + * 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.cloudsigma.functions; + +import java.util.Set; + +import javax.inject.Inject; +import javax.inject.Singleton; + +import org.jclouds.cloudsigma.domain.DriveInfo; +import org.jclouds.elasticstack.functions.ListOfKeyValuesDelimitedByBlankLinesToListOfMaps; +import org.jclouds.http.HttpResponse; +import org.jclouds.http.functions.ReturnStringIf2xx; + +import com.google.common.base.Function; +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Iterables; + +/** + * + * @author Adrian Cole + */ +@Singleton +public class ListOfKeyValuesDelimitedByBlankLinesToDriveInfoSet implements Function> { + private final ReturnStringIf2xx returnStringIf200; + private final ListOfKeyValuesDelimitedByBlankLinesToListOfMaps mapConverter; + private final MapToDriveInfo mapToDrive; + + @Inject + ListOfKeyValuesDelimitedByBlankLinesToDriveInfoSet(ReturnStringIf2xx returnStringIf200, + ListOfKeyValuesDelimitedByBlankLinesToListOfMaps mapConverter, MapToDriveInfo mapToDrive) { + this.returnStringIf200 = returnStringIf200; + this.mapConverter = mapConverter; + this.mapToDrive = mapToDrive; + } + + @Override + public Set apply(HttpResponse response) { + String text = returnStringIf200.apply(response); + if (text == null || text.trim().equals("")) + return ImmutableSet. of(); + return ImmutableSet.copyOf(Iterables.transform(mapConverter.apply(text), mapToDrive)); + } +} \ No newline at end of file diff --git a/sandbox/elasticstack/src/main/java/org/jclouds/cloudsigma/functions/MapToDriveInfo.java b/sandbox/elasticstack/src/main/java/org/jclouds/cloudsigma/functions/MapToDriveInfo.java new file mode 100644 index 0000000000..2910718e2a --- /dev/null +++ b/sandbox/elasticstack/src/main/java/org/jclouds/cloudsigma/functions/MapToDriveInfo.java @@ -0,0 +1,72 @@ +/** + * + * 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.cloudsigma.functions; + +import java.net.URI; +import java.util.Map; + +import javax.inject.Inject; +import javax.inject.Singleton; + +import org.jclouds.cloudsigma.domain.DriveInfo; +import org.jclouds.cloudsigma.domain.DriveType; + +import com.google.common.base.Function; +import com.google.common.base.Splitter; + +/** + * + * @author Adrian Cole + */ +@Singleton +public class MapToDriveInfo implements Function, DriveInfo> { + private final org.jclouds.elasticstack.functions.MapToDriveInfo mapToDriveInfo; + + @Inject + public MapToDriveInfo(org.jclouds.elasticstack.functions.MapToDriveInfo mapToDriveInfo) { + this.mapToDriveInfo = mapToDriveInfo; + } + + @Override + public DriveInfo apply(Map from) { + if (from.size() == 0) + return null; + DriveInfo.Builder builder = DriveInfo.Builder.fromDriveInfo(mapToDriveInfo.apply(from)); + if (from.containsKey("use")) + builder.tags(Splitter.on(',').split(from.get("use"))); + if (from.containsKey("bits")) + builder.bits(new Integer(from.get("bits"))); + if (from.containsKey("url")) + builder.url(URI.create(from.get("url"))); + builder.encryptionKey(from.get("encryption:key")); + builder.description(from.get("description")); + builder.installNotes(from.get("install_notes")); + builder.os(from.get("os")); + if (from.containsKey("drive_type")) + builder.driveType(Splitter.on(',').split(from.get("drive_type"))); + if (from.containsKey("autoexpanding")) + builder.autoexpanding(new Boolean(from.get("autoexpanding"))); + if (from.containsKey("free")) + builder.free(new Boolean(from.get("free"))); + if (from.containsKey("type")) + builder.type(DriveType.fromValue(from.get("type"))); + return builder.build(); + } +} \ No newline at end of file diff --git a/sandbox/elasticstack/src/main/java/org/jclouds/elasticstack/CommonElasticStackAsyncClient.java b/sandbox/elasticstack/src/main/java/org/jclouds/elasticstack/CommonElasticStackAsyncClient.java new file mode 100644 index 0000000000..193b155b72 --- /dev/null +++ b/sandbox/elasticstack/src/main/java/org/jclouds/elasticstack/CommonElasticStackAsyncClient.java @@ -0,0 +1,114 @@ +/** + * + * 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.elasticstack; + +import java.util.Set; + +import javax.ws.rs.Consumes; +import javax.ws.rs.GET; +import javax.ws.rs.POST; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.core.MediaType; + +import org.jclouds.elasticstack.binders.BindCreateDriveRequestToPlainTextString; +import org.jclouds.elasticstack.binders.BindDriveDataToPlainTextString; +import org.jclouds.elasticstack.domain.CreateDriveRequest; +import org.jclouds.elasticstack.domain.DriveData; +import org.jclouds.elasticstack.domain.DriveInfo; +import org.jclouds.elasticstack.functions.KeyValuesDelimitedByBlankLinesToDriveInfo; +import org.jclouds.elasticstack.functions.ListOfKeyValuesDelimitedByBlankLinesToDriveInfoSet; +import org.jclouds.elasticstack.functions.SplitNewlines; +import org.jclouds.http.filters.BasicAuthentication; +import org.jclouds.rest.annotations.BinderParam; +import org.jclouds.rest.annotations.ExceptionParser; +import org.jclouds.rest.annotations.RequestFilters; +import org.jclouds.rest.annotations.ResponseParser; +import org.jclouds.rest.functions.ReturnNullOnNotFoundOr404; +import org.jclouds.rest.functions.ReturnVoidOnNotFoundOr404; + +import com.google.common.util.concurrent.ListenableFuture; + +/** + * Provides asynchronous access to elasticstack via their REST API. + *

+ * + * @see ElasticStackClient + * @see + * @author Adrian Cole + */ +@RequestFilters(BasicAuthentication.class) +@Consumes(MediaType.TEXT_PLAIN) +public interface CommonElasticStackAsyncClient { + + /** + * @see ElasticStackClient#listDrives() + */ + @GET + @Path("/drives/list") + @ResponseParser(SplitNewlines.class) + ListenableFuture> listDrives(); + + /** + * @see ElasticStackClient#listDriveInfo() + */ + @GET + @Path("/drives/info") + @ResponseParser(ListOfKeyValuesDelimitedByBlankLinesToDriveInfoSet.class) + ListenableFuture> listDriveInfo(); + + /** + * @see ElasticStackClient#getDriveInfo + */ + @GET + @ExceptionParser(ReturnNullOnNotFoundOr404.class) + @ResponseParser(KeyValuesDelimitedByBlankLinesToDriveInfo.class) + @Path("/drives/{uuid}/info") + ListenableFuture getDriveInfo(@PathParam("uuid") String uuid); + + /** + * @see ElasticStackClient#createDrive + */ + @POST + @ExceptionParser(ReturnNullOnNotFoundOr404.class) + @ResponseParser(KeyValuesDelimitedByBlankLinesToDriveInfo.class) + @Path("/drives/create") + ListenableFuture createDrive( + @BinderParam(BindCreateDriveRequestToPlainTextString.class) CreateDriveRequest createDrive); + + /** + * @see ElasticStackClient#setDriveData + */ + @POST + @ExceptionParser(ReturnNullOnNotFoundOr404.class) + @ResponseParser(KeyValuesDelimitedByBlankLinesToDriveInfo.class) + @Path("/drives/{uuid}/set") + ListenableFuture setDriveData(@PathParam("uuid") String uuid, + @BinderParam(BindDriveDataToPlainTextString.class) DriveData createDrive); + + /** + * @see ElasticStackClient#destroyDrive + */ + @POST + @Path("/drives/{uuid}/destroy") + @ExceptionParser(ReturnVoidOnNotFoundOr404.class) + ListenableFuture destroyDrive(@PathParam("uuid") String uuid); + +} diff --git a/sandbox/elasticstack/src/main/java/org/jclouds/elasticstack/CommonElasticStackClient.java b/sandbox/elasticstack/src/main/java/org/jclouds/elasticstack/CommonElasticStackClient.java new file mode 100644 index 0000000000..0f0acad24f --- /dev/null +++ b/sandbox/elasticstack/src/main/java/org/jclouds/elasticstack/CommonElasticStackClient.java @@ -0,0 +1,90 @@ +/** + * + * 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.elasticstack; + +import java.util.Set; +import java.util.concurrent.TimeUnit; + +import org.jclouds.concurrent.Timeout; +import org.jclouds.elasticstack.domain.CreateDriveRequest; +import org.jclouds.elasticstack.domain.DriveData; +import org.jclouds.elasticstack.domain.DriveInfo; + +/** + * Provides synchronous access to elasticstack. + *

+ * + * @see ElasticStackAsyncClient + * @see + * @author Adrian Cole + */ +@Timeout(duration = 60, timeUnit = TimeUnit.SECONDS) +public interface CommonElasticStackClient { + /** + * list of drive uuids in your account + * + * @return or empty set if no drives are found + */ + Set listDrives(); + + /** + * Get all drives info + * + * @return or empty set if no drives are found + */ + Set listDriveInfo(); + + /** + * @param uuid + * what to get + * @return null, if not found + */ + DriveInfo getDriveInfo(String uuid); + + /** + * create a new drive + * + * @param createDrive + * required parameters: name, size + * @return newly created drive + */ + DriveInfo createDrive(CreateDriveRequest createDrive); + + /** + * set extra drive data + * + * @param uuid + * what drive to change + * @param driveData + * what values to change + * @return new data + */ + DriveInfo setDriveData(String uuid, DriveData driveData); + + /** + * Destroy a drive + * + * @param uuid + * what to delete + */ + void destroyDrive(String uuid); + + +} diff --git a/sandbox/elasticstack/src/main/java/org/jclouds/elasticstack/ElasticStackAsyncClient.java b/sandbox/elasticstack/src/main/java/org/jclouds/elasticstack/ElasticStackAsyncClient.java new file mode 100644 index 0000000000..4314cdfb24 --- /dev/null +++ b/sandbox/elasticstack/src/main/java/org/jclouds/elasticstack/ElasticStackAsyncClient.java @@ -0,0 +1,112 @@ +/** + * + * 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.elasticstack; + +import javax.ws.rs.Consumes; +import javax.ws.rs.GET; +import javax.ws.rs.POST; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.core.MediaType; + +import org.jclouds.elasticstack.binders.BindReadDriveOptionsToPath; +import org.jclouds.elasticstack.domain.ImageConversionType; +import org.jclouds.elasticstack.functions.ReturnPayload; +import org.jclouds.elasticstack.options.ReadDriveOptions; +import org.jclouds.http.filters.BasicAuthentication; +import org.jclouds.io.Payload; +import org.jclouds.rest.annotations.BinderParam; +import org.jclouds.rest.annotations.ExceptionParser; +import org.jclouds.rest.annotations.RequestFilters; +import org.jclouds.rest.annotations.ResponseParser; +import org.jclouds.rest.functions.ReturnNullOnNotFoundOr404; +import org.jclouds.rest.functions.ReturnVoidOnNotFoundOr404; + +import com.google.common.util.concurrent.ListenableFuture; + +/** + * Provides asynchronous access to elasticstack via their REST API. + *

+ * + * @see ElasticStackClient + * @see + * @author Adrian Cole + */ +@RequestFilters(BasicAuthentication.class) +@Consumes(MediaType.TEXT_PLAIN) +public interface ElasticStackAsyncClient extends CommonElasticStackAsyncClient { + + /** + * @see ElasticStackClient#imageDrive(String,String) + */ + @POST + @Path("/drives/{destination}/image/{source}") + @ExceptionParser(ReturnVoidOnNotFoundOr404.class) + ListenableFuture imageDrive(@PathParam("source") String source, @PathParam("destination") String destination); + + /** + * @see ElasticStackClient#imageDrive(String,String,ImageConversionType) + */ + @POST + @Path("/drives/{destination}/image/{source}/{conversion}") + @ExceptionParser(ReturnVoidOnNotFoundOr404.class) + ListenableFuture imageDrive(@PathParam("source") String source, @PathParam("destination") String destination, + @PathParam("conversion") ImageConversionType conversionType); + + /** + * @see ElasticStackClient#readDrive(String) + */ + @GET + @Consumes(MediaType.APPLICATION_OCTET_STREAM) + @Path("/drives/{uuid}/read") + @ResponseParser(ReturnPayload.class) + @ExceptionParser(ReturnNullOnNotFoundOr404.class) + ListenableFuture readDrive(@PathParam("uuid") String uuid); + + /** + * @see ElasticStackClient#readDrive(String,ReadDriveOptions) + */ + @POST + @Consumes(MediaType.APPLICATION_OCTET_STREAM) + @Path("/drives/{uuid}/read") + @ResponseParser(ReturnPayload.class) + @ExceptionParser(ReturnNullOnNotFoundOr404.class) + ListenableFuture readDrive(@PathParam("uuid") String uuid, + @BinderParam(BindReadDriveOptionsToPath.class) ReadDriveOptions options); + + /** + * @see ElasticStackClient#writeDrive(String, Payload) + */ + @POST + @Produces(MediaType.APPLICATION_OCTET_STREAM) + @Path("/drives/{uuid}/write") + @ExceptionParser(ReturnVoidOnNotFoundOr404.class) + ListenableFuture writeDrive(@PathParam("uuid") String uuid, Payload content); + + /** + * @see ElasticStackClient#writeDrive(String, Payload, long) + */ + @POST + @Produces(MediaType.APPLICATION_OCTET_STREAM) + @Path("/drives/{uuid}/write/{offset}") + @ExceptionParser(ReturnVoidOnNotFoundOr404.class) + ListenableFuture writeDrive(@PathParam("uuid") String uuid, Payload content, @PathParam("offset") long offset); +} diff --git a/sandbox/elasticstack/src/main/java/org/jclouds/elasticstack/ElasticStackClient.java b/sandbox/elasticstack/src/main/java/org/jclouds/elasticstack/ElasticStackClient.java new file mode 100644 index 0000000000..5d4998c366 --- /dev/null +++ b/sandbox/elasticstack/src/main/java/org/jclouds/elasticstack/ElasticStackClient.java @@ -0,0 +1,97 @@ +/** + * + * 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.elasticstack; + +import java.util.concurrent.TimeUnit; + +import org.jclouds.concurrent.Timeout; +import org.jclouds.elasticstack.domain.ImageConversionType; +import org.jclouds.elasticstack.options.ReadDriveOptions; +import org.jclouds.io.Payload; + +/** + * Provides synchronous access to elasticstack. + *

+ * + * @see ElasticStackAsyncClient + * @see + * @author Adrian Cole + */ +@Timeout(duration = 60, timeUnit = TimeUnit.SECONDS) +public interface ElasticStackClient extends CommonElasticStackClient { + + /** + * Image a drive from another drive. The actual imaging process is asynchronous, with progress + * reported via drive info. + * + * @param source + * drive to copy from + * @param destination + * drive to copy to + */ + void imageDrive(String source, String destination); + + /** + * @see #imageDrive(String, String) + * @param conversionType + * Supports 'gzip' or 'gunzip' conversions. + */ + void imageDrive(String source, String destination, ImageConversionType conversionType); + + /** + * Read binary data from a drive + * + * @param uuid + * drive to read + * @return binary content of the drive. + */ + Payload readDrive(String uuid); + + /** + * @see #readDrive(String) + * @param options + * controls offset and size of the request + */ + Payload readDrive(String uuid, ReadDriveOptions options); + + /** + * Write binary data to a drive + * + * @param uuid + * drive to write + * @param content + * what to write. + *

+ */ + void writeDrive(String uuid, Payload content); + + /** + * @see ElasticStackClient#writeDrive(String, Payload) + * @param offset + * the byte offset in the target drive at which to start writing, not an offset in the + * input stream. + */ + void writeDrive(String uuid, Payload content, long offset); + +} diff --git a/sandbox/elasticstack/src/main/java/org/jclouds/elasticstack/ElasticStackContextBuilder.java b/sandbox/elasticstack/src/main/java/org/jclouds/elasticstack/ElasticStackContextBuilder.java new file mode 100644 index 0000000000..9a072d3dac --- /dev/null +++ b/sandbox/elasticstack/src/main/java/org/jclouds/elasticstack/ElasticStackContextBuilder.java @@ -0,0 +1,45 @@ +/** + * + * 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.elasticstack; + +import java.util.List; +import java.util.Properties; + +import org.jclouds.elasticstack.config.ElasticStackRestClientModule; +import org.jclouds.rest.RestContextBuilder; + +import com.google.inject.Module; + +/** + * + * @author Adrian Cole + */ +public class ElasticStackContextBuilder extends + RestContextBuilder { + + public ElasticStackContextBuilder(Properties props) { + super(ElasticStackClient.class, ElasticStackAsyncClient.class, props); + } + + protected void addClientModule(List modules) { + modules.add(new ElasticStackRestClientModule()); + } + +} diff --git a/sandbox/elasticstack/src/main/java/org/jclouds/elasticstack/ElasticStackPropertiesBuilder.java b/sandbox/elasticstack/src/main/java/org/jclouds/elasticstack/ElasticStackPropertiesBuilder.java new file mode 100644 index 0000000000..4f1b2bd9ee --- /dev/null +++ b/sandbox/elasticstack/src/main/java/org/jclouds/elasticstack/ElasticStackPropertiesBuilder.java @@ -0,0 +1,45 @@ +/** + * + * 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.elasticstack; + +import static org.jclouds.Constants.PROPERTY_API_VERSION; + +import java.util.Properties; + +import org.jclouds.PropertiesBuilder; + +/** + * Builds properties used in elasticstack Clients + * + * @author Adrian Cole + */ +public class ElasticStackPropertiesBuilder extends PropertiesBuilder { + @Override + protected Properties defaultProperties() { + Properties properties = super.defaultProperties(); + properties.setProperty(PROPERTY_API_VERSION, "1.0"); + return properties; + } + + public ElasticStackPropertiesBuilder(Properties properties) { + super(properties); + } + +} diff --git a/sandbox/elasticstack/src/main/java/org/jclouds/elasticstack/binders/BindCreateDriveRequestToPlainTextString.java b/sandbox/elasticstack/src/main/java/org/jclouds/elasticstack/binders/BindCreateDriveRequestToPlainTextString.java new file mode 100644 index 0000000000..332cbd06ed --- /dev/null +++ b/sandbox/elasticstack/src/main/java/org/jclouds/elasticstack/binders/BindCreateDriveRequestToPlainTextString.java @@ -0,0 +1,61 @@ +/** + * + * 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.elasticstack.binders; + +import static com.google.common.base.Preconditions.checkArgument; + +import java.util.Map; + +import javax.inject.Inject; +import javax.inject.Singleton; +import javax.ws.rs.core.MediaType; + +import org.jclouds.elasticstack.domain.CreateDriveRequest; +import org.jclouds.elasticstack.functions.ListOfMapsToListOfKeyValuesDelimitedByBlankLines; +import org.jclouds.http.HttpRequest; +import org.jclouds.rest.Binder; + +import com.google.common.base.Function; +import com.google.common.collect.ImmutableSet; + +/** + * + * @author Adrian Cole + */ +@Singleton +public class BindCreateDriveRequestToPlainTextString implements Binder { + private final Function> createDriveRequestToMap; + private final ListOfMapsToListOfKeyValuesDelimitedByBlankLines listOfMapsToListOfKeyValuesDelimitedByBlankLines; + + @Inject + public BindCreateDriveRequestToPlainTextString(Function> createDriveRequestToMap, + ListOfMapsToListOfKeyValuesDelimitedByBlankLines listOfMapsToListOfKeyValuesDelimitedByBlankLines) { + this.createDriveRequestToMap = createDriveRequestToMap; + this.listOfMapsToListOfKeyValuesDelimitedByBlankLines = listOfMapsToListOfKeyValuesDelimitedByBlankLines; + } + + public void bindToRequest(HttpRequest request, Object payload) { + checkArgument(payload instanceof CreateDriveRequest, "this binder is only valid for CreateDriveRequest!"); + CreateDriveRequest create = CreateDriveRequest.class.cast(payload); + Map map = createDriveRequestToMap.apply(create); + request.setPayload(listOfMapsToListOfKeyValuesDelimitedByBlankLines.apply(ImmutableSet.of(map))); + request.getPayload().getContentMetadata().setContentType(MediaType.TEXT_PLAIN); + } +} diff --git a/sandbox/elasticstack/src/main/java/org/jclouds/elasticstack/binders/BindDriveDataToPlainTextString.java b/sandbox/elasticstack/src/main/java/org/jclouds/elasticstack/binders/BindDriveDataToPlainTextString.java new file mode 100644 index 0000000000..006565b8c6 --- /dev/null +++ b/sandbox/elasticstack/src/main/java/org/jclouds/elasticstack/binders/BindDriveDataToPlainTextString.java @@ -0,0 +1,61 @@ +/** + * + * 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.elasticstack.binders; + +import static com.google.common.base.Preconditions.checkArgument; + +import java.util.Map; + +import javax.inject.Inject; +import javax.inject.Singleton; +import javax.ws.rs.core.MediaType; + +import org.jclouds.elasticstack.domain.DriveData; +import org.jclouds.elasticstack.functions.ListOfMapsToListOfKeyValuesDelimitedByBlankLines; +import org.jclouds.http.HttpRequest; +import org.jclouds.rest.Binder; + +import com.google.common.base.Function; +import com.google.common.collect.ImmutableSet; + +/** + * + * @author Adrian Cole + */ +@Singleton +public class BindDriveDataToPlainTextString implements Binder { + private final Function> createDriveRequestToMap; + private final ListOfMapsToListOfKeyValuesDelimitedByBlankLines listOfMapsToListOfKeyValuesDelimitedByBlankLines; + + @Inject + public BindDriveDataToPlainTextString(Function> createDriveRequestToMap, + ListOfMapsToListOfKeyValuesDelimitedByBlankLines listOfMapsToListOfKeyValuesDelimitedByBlankLines) { + this.createDriveRequestToMap = createDriveRequestToMap; + this.listOfMapsToListOfKeyValuesDelimitedByBlankLines = listOfMapsToListOfKeyValuesDelimitedByBlankLines; + } + + public void bindToRequest(HttpRequest request, Object payload) { + checkArgument(payload instanceof DriveData, "this binder is only valid for DriveData!"); + DriveData create = DriveData.class.cast(payload); + Map map = createDriveRequestToMap.apply(create); + request.setPayload(listOfMapsToListOfKeyValuesDelimitedByBlankLines.apply(ImmutableSet.of(map))); + request.getPayload().getContentMetadata().setContentType(MediaType.TEXT_PLAIN); + } +} diff --git a/sandbox/elasticstack/src/main/java/org/jclouds/elasticstack/binders/BindReadDriveOptionsToPath.java b/sandbox/elasticstack/src/main/java/org/jclouds/elasticstack/binders/BindReadDriveOptionsToPath.java new file mode 100644 index 0000000000..878b4bca3a --- /dev/null +++ b/sandbox/elasticstack/src/main/java/org/jclouds/elasticstack/binders/BindReadDriveOptionsToPath.java @@ -0,0 +1,59 @@ +/** + * + * 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.elasticstack.binders; + +import static com.google.common.base.Preconditions.checkArgument; + +import javax.inject.Inject; +import javax.inject.Provider; +import javax.inject.Singleton; +import javax.ws.rs.core.UriBuilder; + +import org.jclouds.elasticstack.options.ReadDriveOptions; +import org.jclouds.http.HttpRequest; +import org.jclouds.rest.Binder; + +/** + * + * @author Adrian Cole + */ +@Singleton +public class BindReadDriveOptionsToPath implements Binder { + private final Provider uriBuilderProvider; + + @Inject + public BindReadDriveOptionsToPath(Provider uriBuilderProvider) { + this.uriBuilderProvider = uriBuilderProvider; + } + + public void bindToRequest(HttpRequest request, Object payload) { + checkArgument(payload instanceof ReadDriveOptions, "this binder is only valid for ReadDriveOptions!"); + ReadDriveOptions options = ReadDriveOptions.class.cast(payload); + if (options.getOffset() != null || options.getSize() != null){ + UriBuilder builder = uriBuilderProvider.get().uri(request.getEndpoint()); + if (options.getOffset() != null) + builder.path("/"+options.getOffset()); + if (options.getSize() != null) + builder.path("/"+options.getSize()); + request.setEndpoint(builder.build()); + } + + } +} diff --git a/sandbox/elasticstack/src/main/java/org/jclouds/elasticstack/config/ElasticStackRestClientModule.java b/sandbox/elasticstack/src/main/java/org/jclouds/elasticstack/config/ElasticStackRestClientModule.java new file mode 100644 index 0000000000..d8def53140 --- /dev/null +++ b/sandbox/elasticstack/src/main/java/org/jclouds/elasticstack/config/ElasticStackRestClientModule.java @@ -0,0 +1,76 @@ +/** + * + * 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.elasticstack.config; + +import java.util.Map; + +import org.jclouds.elasticstack.ElasticStackAsyncClient; +import org.jclouds.elasticstack.ElasticStackClient; +import org.jclouds.elasticstack.domain.CreateDriveRequest; +import org.jclouds.elasticstack.domain.DriveData; +import org.jclouds.elasticstack.functions.CreateDriveRequestToMap; +import org.jclouds.elasticstack.functions.DriveDataToMap; +import org.jclouds.elasticstack.handlers.ElasticStackErrorHandler; +import org.jclouds.http.HttpErrorHandler; +import org.jclouds.http.RequiresHttp; +import org.jclouds.http.annotation.ClientError; +import org.jclouds.http.annotation.Redirection; +import org.jclouds.http.annotation.ServerError; +import org.jclouds.rest.ConfiguresRestClient; +import org.jclouds.rest.config.RestClientModule; + +import com.google.common.base.Function; +import com.google.inject.TypeLiteral; + +/** + * Configures the elasticstack connection. + * + * @author Adrian Cole + */ +@RequiresHttp +@ConfiguresRestClient +public class ElasticStackRestClientModule extends RestClientModule { + + public ElasticStackRestClientModule() { + super(ElasticStackClient.class, ElasticStackAsyncClient.class); + } + + @Override + protected void configure() { + super.configure(); + bind(new TypeLiteral>>() { + }).to(CreateDriveRequestToMap.class); + bind(new TypeLiteral>>() { + }).to(DriveDataToMap.class); + } + + @Override + protected void bindErrorHandlers() { + bind(HttpErrorHandler.class).annotatedWith(Redirection.class).to(ElasticStackErrorHandler.class); + bind(HttpErrorHandler.class).annotatedWith(ClientError.class).to(ElasticStackErrorHandler.class); + bind(HttpErrorHandler.class).annotatedWith(ServerError.class).to(ElasticStackErrorHandler.class); + } + + @Override + protected void bindRetryHandlers() { + // TODO + } + +} diff --git a/sandbox/elasticstack/src/main/java/org/jclouds/elasticstack/domain/BlockDevice.java b/sandbox/elasticstack/src/main/java/org/jclouds/elasticstack/domain/BlockDevice.java new file mode 100644 index 0000000000..757732c2f3 --- /dev/null +++ b/sandbox/elasticstack/src/main/java/org/jclouds/elasticstack/domain/BlockDevice.java @@ -0,0 +1,73 @@ +/** + * + * 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.elasticstack.domain; + +import static com.google.common.base.Preconditions.checkArgument; + +/** + * + * @author Adrian Cole + */ +public class BlockDevice extends Device { + + private final char index; + + public BlockDevice(String driveUuid, MediaType mediaType, char index) { + super(driveUuid, mediaType); + checkArgument(index >= 0 && index < 8, "index must be between 0 and 7"); + this.index = index; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + index; + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + BlockDevice other = (BlockDevice) obj; + if (index != other.index) + return false; + return true; + } + + @Override + public String getId() { + return String.format("block:%d", index); + } + + public char getIndex() { + return index; + } + + @Override + public String toString() { + return "[id=" + getId() + ", driveUuid=" + driveUuid + ", mediaType=" + mediaType + "]"; + } +} \ No newline at end of file diff --git a/sandbox/elasticstack/src/main/java/org/jclouds/elasticstack/domain/ClaimType.java b/sandbox/elasticstack/src/main/java/org/jclouds/elasticstack/domain/ClaimType.java new file mode 100644 index 0000000000..b118acc5d1 --- /dev/null +++ b/sandbox/elasticstack/src/main/java/org/jclouds/elasticstack/domain/ClaimType.java @@ -0,0 +1,57 @@ +/** + * + * 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.elasticstack.domain; + +import static com.google.common.base.Preconditions.checkNotNull; + +/** + * either 'exclusive' (the default) or 'shared' to allow multiple servers to access a drive + * simultaneously + * + * @author Adrian Cole + */ +public enum ClaimType { + /** + * + */ + EXCLUSIVE, + /** + * allow multiple servers to access a drive simultaneously + */ + SHARED, UNRECOGNIZED; + + public String value() { + return name().toLowerCase(); + } + + @Override + public String toString() { + return value(); + } + + public static ClaimType fromValue(String claim) { + try { + return valueOf(checkNotNull(claim, "claim").toUpperCase()); + } catch (IllegalArgumentException e) { + return UNRECOGNIZED; + } + } + +} \ No newline at end of file diff --git a/sandbox/elasticstack/src/main/java/org/jclouds/elasticstack/domain/CreateDriveRequest.java b/sandbox/elasticstack/src/main/java/org/jclouds/elasticstack/domain/CreateDriveRequest.java new file mode 100644 index 0000000000..ad397d6dbb --- /dev/null +++ b/sandbox/elasticstack/src/main/java/org/jclouds/elasticstack/domain/CreateDriveRequest.java @@ -0,0 +1,176 @@ +/** + * + * 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.elasticstack.domain; + +import static com.google.common.base.Preconditions.checkNotNull; + +import java.util.Map; +import java.util.Set; + +import javax.annotation.Nullable; + +import org.jclouds.elasticstack.domain.internal.BaseDrive; + +import com.google.common.collect.ImmutableSet; + +/** + * + * @author Adrian Cole + */ +public class CreateDriveRequest extends BaseDrive { + public static class Builder extends BaseDrive.Builder { + + private Set avoid = ImmutableSet.of(); + + @Nullable + private String encryptionCipher; + + public Builder avoid(Iterable avoid) { + this.avoid = ImmutableSet.copyOf(checkNotNull(avoid, "avoid")); + return this; + } + + /** + * {@inheritDoc} + */ + @Override + public Builder claimType(ClaimType claimType) { + return Builder.class.cast(super.claimType(claimType)); + } + + public Builder encryptionCipher(String encryptionCipher) { + this.encryptionCipher = encryptionCipher; + return this; + } + + /** + * {@inheritDoc} + */ + @Override + public Builder name(String name) { + return Builder.class.cast(super.name(name)); + } + + /** + * {@inheritDoc} + */ + @Override + public Builder readers(Iterable readers) { + return Builder.class.cast(super.readers(readers)); + } + + /** + * {@inheritDoc} + */ + @Override + public Builder size(long size) { + return Builder.class.cast(super.size(size)); + } + + /** + * {@inheritDoc} + */ + @Override + public Builder tags(Iterable tags) { + return Builder.class.cast(super.tags(tags)); + } + + /** + * {@inheritDoc} + */ + @Override + public Builder userMetadata(Map userMetadata) { + return Builder.class.cast(super.userMetadata(userMetadata)); + } + + public CreateDriveRequest build() { + return new CreateDriveRequest(name, size, claimType, readers, tags, userMetadata, encryptionCipher, avoid); + } + } + + private final Set avoid; + @Nullable + private final String encryptionCipher; + + public CreateDriveRequest(String name, long size, @Nullable ClaimType claimType, Iterable readers, + Iterable tags, Map userMetadata, @Nullable String encryptionCipher, + Iterable avoid) { + super(null, name, size, claimType, readers, tags, userMetadata); + this.encryptionCipher = encryptionCipher; + this.avoid = ImmutableSet.copyOf(checkNotNull(avoid, "avoid")); + } + + /** + * + * @return list of existing drives to ensure this new drive is created on physical different + * hardware than those existing drives + */ + public Set getAvoid() { + return avoid; + } + + /** + * + * @return either 'none' or 'aes-xts-plain' (the default) + */ + @Nullable + public String getEncryptionCipher() { + return encryptionCipher; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = super.hashCode(); + result = prime * result + ((avoid == null) ? 0 : avoid.hashCode()); + result = prime * result + ((encryptionCipher == null) ? 0 : encryptionCipher.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; + CreateDriveRequest other = (CreateDriveRequest) obj; + if (avoid == null) { + if (other.avoid != null) + return false; + } else if (!avoid.equals(other.avoid)) + return false; + if (encryptionCipher == null) { + if (other.encryptionCipher != null) + return false; + } else if (!encryptionCipher.equals(other.encryptionCipher)) + return false; + return true; + } + + @Override + public String toString() { + return "[name=" + name + ", size=" + size + ", claimType=" + claimType + ", readers=" + readers + ", tags=" + + tags + ", userMetadata=" + userMetadata + ", avoid=" + avoid + ", encryptionCipher=" + encryptionCipher + + "]"; + } + +} \ No newline at end of file diff --git a/sandbox/elasticstack/src/main/java/org/jclouds/elasticstack/domain/Device.java b/sandbox/elasticstack/src/main/java/org/jclouds/elasticstack/domain/Device.java new file mode 100644 index 0000000000..3085647581 --- /dev/null +++ b/sandbox/elasticstack/src/main/java/org/jclouds/elasticstack/domain/Device.java @@ -0,0 +1,91 @@ +/** + * + * 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.elasticstack.domain; + +import static com.google.common.base.Preconditions.checkNotNull; + +/** + * + * @author Adrian Cole + */ +public abstract class Device { + protected final String driveUuid; + protected final MediaType mediaType; + + public Device(String driveUuid, MediaType mediaType) { + this.driveUuid = checkNotNull(driveUuid, "driveUuid"); + this.mediaType = checkNotNull(mediaType, "mediaType"); + } + + /** + * id generated based on the device bus, unit, and/or index numbers; + */ + public abstract String getId(); + + /** + * + * @return Drive UUID to connect as specified device. + */ + public String getDriveUuid() { + return driveUuid; + } + + /** + * + * @return set to 'cdrom' to simulate a cdrom, set to 'disk' or leave unset to simulate a hard + * disk. + */ + public MediaType getMediaType() { + return mediaType; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((driveUuid == null) ? 0 : driveUuid.hashCode()); + result = prime * result + ((mediaType == null) ? 0 : mediaType.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + Device other = (Device) obj; + if (driveUuid == null) { + if (other.driveUuid != null) + return false; + } else if (!driveUuid.equals(other.driveUuid)) + return false; + if (mediaType != other.mediaType) + return false; + return true; + } + + @Override + public String toString() { + return "[driveUuid=" + driveUuid + ", mediaType=" + mediaType + "]"; + } +} \ No newline at end of file diff --git a/sandbox/elasticstack/src/main/java/org/jclouds/elasticstack/domain/DriveData.java b/sandbox/elasticstack/src/main/java/org/jclouds/elasticstack/domain/DriveData.java new file mode 100644 index 0000000000..1b462e24b9 --- /dev/null +++ b/sandbox/elasticstack/src/main/java/org/jclouds/elasticstack/domain/DriveData.java @@ -0,0 +1,93 @@ +/** + * + * 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.elasticstack.domain; + +import java.util.Map; + +import javax.annotation.Nullable; + +import org.jclouds.elasticstack.domain.internal.BaseDrive; + +/** + * + * @author Adrian Cole + */ +public class DriveData extends BaseDrive { + public static class Builder extends BaseDrive.Builder { + + /** + * {@inheritDoc} + */ + @Override + public Builder claimType(ClaimType claimType) { + return Builder.class.cast(super.claimType(claimType)); + } + + + /** + * {@inheritDoc} + */ + @Override + public Builder name(String name) { + return Builder.class.cast(super.name(name)); + } + + /** + * {@inheritDoc} + */ + @Override + public Builder readers(Iterable readers) { + return Builder.class.cast(super.readers(readers)); + } + + /** + * {@inheritDoc} + */ + @Override + public Builder size(long size) { + return Builder.class.cast(super.size(size)); + } + + /** + * {@inheritDoc} + */ + @Override + public Builder tags(Iterable tags) { + return Builder.class.cast(super.tags(tags)); + } + + /** + * {@inheritDoc} + */ + @Override + public Builder userMetadata(Map userMetadata) { + return Builder.class.cast(super.userMetadata(userMetadata)); + } + + public DriveData build() { + return new DriveData(uuid, name, size, claimType, readers, tags, userMetadata); + } + } + + public DriveData(@Nullable String uuid, String name, long size, @Nullable ClaimType claimType, Iterable readers, + Iterable tags, Map userMetadata) { + super(uuid, name, size, claimType, readers, tags, userMetadata); + } +} \ No newline at end of file diff --git a/sandbox/elasticstack/src/main/java/org/jclouds/elasticstack/domain/DriveInfo.java b/sandbox/elasticstack/src/main/java/org/jclouds/elasticstack/domain/DriveInfo.java new file mode 100644 index 0000000000..abc81a5faf --- /dev/null +++ b/sandbox/elasticstack/src/main/java/org/jclouds/elasticstack/domain/DriveInfo.java @@ -0,0 +1,342 @@ +/** + * + * 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.elasticstack.domain; + +import static com.google.common.base.Preconditions.checkNotNull; + +import java.util.Map; +import java.util.Set; + +import javax.annotation.Nullable; + +import org.jclouds.elasticstack.domain.internal.BaseDrive; + +import com.google.common.collect.ImmutableSet; + +/** + * + * @author Adrian Cole + */ +public class DriveInfo extends BaseDrive { + public static class Builder extends BaseDrive.Builder { + + protected DriveStatus status; + protected String user; + protected Set claimed = ImmutableSet.of(); + @Nullable + protected String encryptionCipher; + @Nullable + protected String imaging; + protected long readBytes; + protected long readRequests; + protected long writeBytes; + protected long writeRequests; + + public Builder status(DriveStatus status) { + this.status = status; + return this; + } + + public Builder user(String user) { + this.user = user; + return this; + } + + public Builder claimed(Iterable claimed) { + this.claimed = ImmutableSet.copyOf(checkNotNull(claimed, "claimed")); + return this; + } + + public Builder imaging(String imaging) { + this.imaging = imaging; + return this; + } + + public Builder readBytes(long readBytes) { + this.readBytes = readBytes; + return this; + } + + public Builder readRequests(long readRequests) { + this.readRequests = readRequests; + return this; + } + + public Builder writeBytes(long writeBytes) { + this.writeBytes = writeBytes; + return this; + } + + public Builder writeRequests(long writeRequests) { + this.writeRequests = writeRequests; + return this; + } + + public Builder encryptionCipher(String encryptionCipher) { + this.encryptionCipher = encryptionCipher; + return this; + } + + /** + * {@inheritDoc} + */ + @Override + public Builder claimType(ClaimType claimType) { + return Builder.class.cast(super.claimType(claimType)); + } + + /** + * {@inheritDoc} + */ + @Override + public Builder readers(Iterable readers) { + return Builder.class.cast(super.readers(readers)); + } + + /** + * {@inheritDoc} + */ + @Override + public Builder size(long size) { + return Builder.class.cast(super.size(size)); + } + + /** + * {@inheritDoc} + */ + @Override + public Builder uuid(String uuid) { + return Builder.class.cast(super.uuid(uuid)); + } + + /** + * {@inheritDoc} + */ + @Override + public Builder name(String name) { + return Builder.class.cast(super.name(name)); + } + + /** + * {@inheritDoc} + */ + @Override + public Builder tags(Iterable tags) { + return Builder.class.cast(super.tags(tags)); + } + + /** + * {@inheritDoc} + */ + @Override + public Builder userMetadata(Map userMetadata) { + return Builder.class.cast(super.userMetadata(userMetadata)); + } + + public static Builder fromDriveInfo(DriveInfo driveInfo) { + return new Builder().uuid(driveInfo.getUuid()).name(driveInfo.getName()).size(driveInfo.getSize()) + .claimType(driveInfo.getClaimType()).readers(driveInfo.getReaders()).tags(driveInfo.getTags()) + .userMetadata(driveInfo.getUserMetadata()).status(driveInfo.getStatus()).user(driveInfo.getUser()) + .claimed(driveInfo.getClaimed()).encryptionCipher(driveInfo.getEncryptionCipher()) + .imaging(driveInfo.getImaging()).readBytes(driveInfo.getReadBytes()) + .readRequests(driveInfo.getReadRequests()).writeBytes(driveInfo.getWriteBytes()) + .writeRequests(driveInfo.getWriteRequests()); + } + + /** + * {@inheritDoc} + */ + @Override + public DriveInfo build() { + return new DriveInfo(uuid, name, size, claimType, readers, tags, userMetadata, status, user, claimed, + encryptionCipher, imaging, readBytes, readRequests, writeBytes, writeRequests); + } + + } + + protected final DriveStatus status; + protected final String user; + protected final Set claimed; + @Nullable + protected final String encryptionCipher; + @Nullable + protected final String imaging; + protected final long readBytes; + protected final long readRequests; + protected final long writeBytes; + protected final long writeRequests; + + public DriveInfo(String uuid, String name, long size, ClaimType claimType, Iterable readers, + Iterable tags, Map userMetadata, DriveStatus status, String user, Set claimed, + String encryptionCipher, String imaging, long readBytes, long readRequests, long writeBytes, long writeRequests) { + super(uuid, name, size, claimType, readers, tags, userMetadata); + this.status = status; + this.user = user; + this.claimed = ImmutableSet.copyOf(claimed); + this.encryptionCipher = encryptionCipher; + this.imaging = imaging; + this.readBytes = readBytes; + this.readRequests = readRequests; + this.writeBytes = writeBytes; + this.writeRequests = writeRequests; + } + + /** + * + * @return current status of the drive + */ + public DriveStatus getStatus() { + return status; + } + + /** + * + * @return owner of the drive + */ + public String getUser() { + return user; + } + + /** + * + * @return if drive is in use by a server, values are the server uuids + */ + public Set getClaimed() { + return claimed; + } + + /** + * + * @return either 'none' or 'aes-xts-plain' (the default) + */ + @Nullable + public String getEncryptionCipher() { + return encryptionCipher; + } + + /** + * + * @return percentage completed of drive imaging if this is underway, or 'queued' if waiting for + * another imaging operation to complete first + */ + public String getImaging() { + return imaging; + } + + /** + * + * @return Cumulative i/o byte/request count for each drive + */ + public long getReadBytes() { + return readBytes; + } + + /** + * + * @return Cumulative i/o byte/request count for each drive + */ + public long getReadRequests() { + return readRequests; + } + + /** + * + * @return Cumulative i/o byte/request count for each drive + */ + public long getWriteBytes() { + return writeBytes; + } + + /** + * + * @return Cumulative i/o byte/request count for each drive + */ + public long getWriteRequests() { + return writeRequests; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = super.hashCode(); + result = prime * result + ((claimed == null) ? 0 : claimed.hashCode()); + result = prime * result + ((encryptionCipher == null) ? 0 : encryptionCipher.hashCode()); + result = prime * result + ((imaging == null) ? 0 : imaging.hashCode()); + result = prime * result + (int) (readBytes ^ (readBytes >>> 32)); + result = prime * result + (int) (readRequests ^ (readRequests >>> 32)); + result = prime * result + ((status == null) ? 0 : status.hashCode()); + result = prime * result + ((user == null) ? 0 : user.hashCode()); + result = prime * result + (int) (writeBytes ^ (writeBytes >>> 32)); + result = prime * result + (int) (writeRequests ^ (writeRequests >>> 32)); + 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; + DriveInfo other = (DriveInfo) obj; + if (claimed == null) { + if (other.claimed != null) + return false; + } else if (!claimed.equals(other.claimed)) + return false; + if (encryptionCipher == null) { + if (other.encryptionCipher != null) + return false; + } else if (!encryptionCipher.equals(other.encryptionCipher)) + return false; + if (imaging == null) { + if (other.imaging != null) + return false; + } else if (!imaging.equals(other.imaging)) + return false; + if (readBytes != other.readBytes) + return false; + if (readRequests != other.readRequests) + return false; + if (status != other.status) + return false; + if (user == null) { + if (other.user != null) + return false; + } else if (!user.equals(other.user)) + return false; + if (writeBytes != other.writeBytes) + return false; + if (writeRequests != other.writeRequests) + return false; + return true; + } + + @Override + public String toString() { + return "[size=" + size + ", claimType=" + claimType + ", readers=" + readers + ", uuid=" + uuid + ", name=" + + name + ", tags=" + tags + ", userMetadata=" + userMetadata + ", status=" + status + ", user=" + user + + ", claimed=" + claimed + ", encryptionCipher=" + encryptionCipher + ", imaging=" + imaging + + ", readBytes=" + readBytes + ", readRequests=" + readRequests + ", writeBytes=" + writeBytes + + ", writeRequests=" + writeRequests + "]"; + } + +} \ No newline at end of file diff --git a/sandbox/elasticstack/src/main/java/org/jclouds/elasticstack/domain/DriveStatus.java b/sandbox/elasticstack/src/main/java/org/jclouds/elasticstack/domain/DriveStatus.java new file mode 100644 index 0000000000..1a1eb5365e --- /dev/null +++ b/sandbox/elasticstack/src/main/java/org/jclouds/elasticstack/domain/DriveStatus.java @@ -0,0 +1,48 @@ +/** + * + * 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.elasticstack.domain; + +import static com.google.common.base.Preconditions.checkNotNull; + +/** + * + * @author Adrian Cole + */ +public enum DriveStatus { + ACTIVE, INACTIVE, COPYING, IMAGING, UNRECOGNIZED; + + public String value() { + return name().toLowerCase(); + } + + @Override + public String toString() { + return value(); + } + + public static DriveStatus fromValue(String status) { + try { + return valueOf(checkNotNull(status, "status").toUpperCase()); + } catch (IllegalArgumentException e) { + return UNRECOGNIZED; + } + } + +} \ No newline at end of file diff --git a/sandbox/elasticstack/src/main/java/org/jclouds/elasticstack/domain/IDEDevice.java b/sandbox/elasticstack/src/main/java/org/jclouds/elasticstack/domain/IDEDevice.java new file mode 100644 index 0000000000..dda18b9f8b --- /dev/null +++ b/sandbox/elasticstack/src/main/java/org/jclouds/elasticstack/domain/IDEDevice.java @@ -0,0 +1,83 @@ +/** + * + * 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.elasticstack.domain; + +import static com.google.common.base.Preconditions.checkArgument; + +/** + * + * @author Adrian Cole + */ +public class IDEDevice extends Device { + + private final char bus; + private final char unit; + + public IDEDevice(String driveUuid, MediaType mediaType, char bus, char unit) { + super(driveUuid, mediaType); + checkArgument(bus == 0 || bus == 1, "bus must be 0 or 1"); + checkArgument(unit == 0 || unit == 1, "unit must be 0 or 1"); + this.bus = bus; + this.unit = unit; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + bus; + result = prime * result + unit; + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + IDEDevice other = (IDEDevice) obj; + if (bus != other.bus) + return false; + if (unit != other.unit) + return false; + return true; + } + + @Override + public String getId() { + return String.format("ide:%d:%d", bus, unit); + } + + public char getBus() { + return bus; + } + + public char getUnit() { + return unit; + } + + @Override + public String toString() { + return "[id=" + getId() + ", driveUuid=" + driveUuid + ", mediaType=" + mediaType + "]"; + } +} \ No newline at end of file diff --git a/sandbox/elasticstack/src/main/java/org/jclouds/elasticstack/domain/ImageConversionType.java b/sandbox/elasticstack/src/main/java/org/jclouds/elasticstack/domain/ImageConversionType.java new file mode 100644 index 0000000000..3a4984350f --- /dev/null +++ b/sandbox/elasticstack/src/main/java/org/jclouds/elasticstack/domain/ImageConversionType.java @@ -0,0 +1,48 @@ +/** + * + * 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.elasticstack.domain; + +import static com.google.common.base.Preconditions.checkNotNull; + +/** + * + * @author Adrian Cole + */ +public enum ImageConversionType { + GZIP, GUNZIP, UNRECOGNIZED; + + public String value() { + return name().toLowerCase(); + } + + @Override + public String toString() { + return value(); + } + + public static ImageConversionType fromValue(String type) { + try { + return valueOf(checkNotNull(type, "type").toUpperCase()); + } catch (IllegalArgumentException e) { + return UNRECOGNIZED; + } + } + +} \ No newline at end of file diff --git a/sandbox/elasticstack/src/main/java/org/jclouds/elasticstack/domain/Item.java b/sandbox/elasticstack/src/main/java/org/jclouds/elasticstack/domain/Item.java new file mode 100644 index 0000000000..b89b85a5c2 --- /dev/null +++ b/sandbox/elasticstack/src/main/java/org/jclouds/elasticstack/domain/Item.java @@ -0,0 +1,199 @@ +/** + * + * 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.elasticstack.domain; + +import static com.google.common.base.Preconditions.checkNotNull; + +import java.util.Map; +import java.util.Set; + +import javax.annotation.Nullable; + +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableSet; + +/** + * + * @author Adrian Cole + */ +public class Item { + public static class Builder { + protected String uuid; + protected String name; + protected Set tags = ImmutableSet.of(); + protected Map userMetadata = ImmutableMap.of(); + + public Builder uuid(String uuid) { + this.uuid = uuid; + return this; + } + + public Builder name(String name) { + this.name = name; + return this; + } + + public Builder tags(Iterable tags) { + this.tags = ImmutableSet.copyOf(checkNotNull(tags, "tags")); + return this; + } + + public Builder userMetadata(Map userMetadata) { + this.userMetadata = ImmutableMap.copyOf(checkNotNull(userMetadata, "userMetadata")); + return this; + } + + public Item build() { + return new Item(uuid, name, tags, userMetadata); + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((name == null) ? 0 : name.hashCode()); + result = prime * result + ((tags == null) ? 0 : tags.hashCode()); + result = prime * result + ((userMetadata == null) ? 0 : userMetadata.hashCode()); + result = prime * result + ((uuid == null) ? 0 : uuid.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + Builder other = (Builder) obj; + if (name == null) { + if (other.name != null) + return false; + } else if (!name.equals(other.name)) + return false; + if (tags == null) { + if (other.tags != null) + return false; + } else if (!tags.equals(other.tags)) + return false; + if (userMetadata == null) { + if (other.userMetadata != null) + return false; + } else if (!userMetadata.equals(other.userMetadata)) + return false; + if (uuid == null) { + if (other.uuid != null) + return false; + } else if (!uuid.equals(other.uuid)) + return false; + return true; + } + } + + @Nullable + protected final String uuid; + protected final String name; + protected final Set tags; + protected final Map userMetadata; + + public Item(@Nullable String uuid, String name, Iterable tags, Map userMetadata) { + this.uuid = uuid; + this.name = checkNotNull(name, "name"); + this.tags = ImmutableSet.copyOf(checkNotNull(tags, "tags")); + this.userMetadata = ImmutableMap.copyOf(checkNotNull(userMetadata, "userMetadata")); + } + + /** + * + * @return uuid of the item. + */ + @Nullable + public String getUuid() { + return uuid; + } + + /** + * + * @return name of the item + */ + public String getName() { + return name; + } + + /** + * + * @return list of tags + */ + public Set getTags() { + return tags; + } + + /** + * + * @return user-defined KEY VALUE pairs + */ + public Map getUserMetadata() { + return userMetadata; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((name == null) ? 0 : name.hashCode()); + result = prime * result + ((tags == null) ? 0 : tags.hashCode()); + result = prime * result + ((userMetadata == null) ? 0 : userMetadata.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + Item other = (Item) obj; + if (name == null) { + if (other.name != null) + return false; + } else if (!name.equals(other.name)) + return false; + if (tags == null) { + if (other.tags != null) + return false; + } else if (!tags.equals(other.tags)) + return false; + if (userMetadata == null) { + if (other.userMetadata != null) + return false; + } else if (!userMetadata.equals(other.userMetadata)) + return false; + return true; + } + + @Override + public String toString() { + return "[uuid=" + uuid + ", name=" + name + ", tags=" + tags + ", userMetadata=" + userMetadata + "]"; + } + +} \ No newline at end of file diff --git a/sandbox/elasticstack/src/main/java/org/jclouds/elasticstack/domain/MediaType.java b/sandbox/elasticstack/src/main/java/org/jclouds/elasticstack/domain/MediaType.java new file mode 100644 index 0000000000..6e55c7ae69 --- /dev/null +++ b/sandbox/elasticstack/src/main/java/org/jclouds/elasticstack/domain/MediaType.java @@ -0,0 +1,50 @@ +/** + * + * 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.elasticstack.domain; + +import static com.google.common.base.Preconditions.checkNotNull; + +/** + * Media type - set to 'cdrom' to simulate a cdrom, set to 'disk' or leave unset to simulate a hard + * disk. + * + * @author Adrian Cole + */ +public enum MediaType { + DISK, CDROM, UNRECOGNIZED; + + public String value() { + return name().toLowerCase(); + } + + @Override + public String toString() { + return value(); + } + + public static MediaType fromValue(String type) { + try { + return valueOf(checkNotNull(type, "type").toUpperCase()); + } catch (IllegalArgumentException e) { + return UNRECOGNIZED; + } + } + +} \ No newline at end of file diff --git a/sandbox/elasticstack/src/main/java/org/jclouds/elasticstack/domain/Model.java b/sandbox/elasticstack/src/main/java/org/jclouds/elasticstack/domain/Model.java new file mode 100644 index 0000000000..da5a5da26e --- /dev/null +++ b/sandbox/elasticstack/src/main/java/org/jclouds/elasticstack/domain/Model.java @@ -0,0 +1,47 @@ +/** + * + * 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.elasticstack.domain; + +import static com.google.common.base.Preconditions.checkNotNull; + +/** + * + * @author Adrian Cole + */ +public enum Model { + E1000, RTl8139, VIRTIO, UNRECOGNIZED; + + public String value() { + return name().toLowerCase(); + } + + @Override + public String toString() { + return value(); + } + + public static Model fromValue(String model) { + try { + return valueOf(checkNotNull(model, "model").toUpperCase()); + } catch (IllegalArgumentException e) { + return UNRECOGNIZED; + } + } +} \ No newline at end of file diff --git a/sandbox/elasticstack/src/main/java/org/jclouds/elasticstack/domain/NIC.java b/sandbox/elasticstack/src/main/java/org/jclouds/elasticstack/domain/NIC.java new file mode 100644 index 0000000000..b08625786c --- /dev/null +++ b/sandbox/elasticstack/src/main/java/org/jclouds/elasticstack/domain/NIC.java @@ -0,0 +1,122 @@ +/** + * + * 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.elasticstack.domain; + +import static com.google.common.base.Preconditions.checkNotNull; + +import javax.annotation.Nullable; + +/** + * + * @author Adrian Cole + */ +public class NIC { + private final String dhcp; + private final Model model; + private final String vlan; + private final String mac; + + public NIC(@Nullable String dhcp, Model model, @Nullable String vlan, @Nullable String mac) { + this.dhcp = dhcp; + this.model = checkNotNull(model, "model"); + this.vlan = vlan; + this.mac = mac; + } + + /** + * + * @return The IP address offered by DHCP to network interface 0. If unset, no address is + * offered. Set to 'auto' to allocate a temporary IP at boot. + */ + public String getDhcp() { + return dhcp; + } + + /** + * + * @return Create network interface with given type (use 'e1000' as default value; 'rtl8139' or + * 'virtio' are also available). + */ + public Model getModel() { + return model; + } + + /** + * + * @return The VLAN to which the network interface is attached. + */ + public String getVlan() { + return vlan; + } + + /** + * + * @return The MAC address of the network interface. If unset, a randomly generated address is + * used. If set, should be unique on the VLAN. + */ + public String getMac() { + return mac; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((dhcp == null) ? 0 : dhcp.hashCode()); + result = prime * result + ((mac == null) ? 0 : mac.hashCode()); + result = prime * result + ((model == null) ? 0 : model.hashCode()); + result = prime * result + ((vlan == null) ? 0 : vlan.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + NIC other = (NIC) obj; + if (dhcp == null) { + if (other.dhcp != null) + return false; + } else if (!dhcp.equals(other.dhcp)) + return false; + if (mac == null) { + if (other.mac != null) + return false; + } else if (!mac.equals(other.mac)) + return false; + if (model != other.model) + return false; + if (vlan == null) { + if (other.vlan != null) + return false; + } else if (!vlan.equals(other.vlan)) + return false; + return true; + } + + @Override + public String toString() { + return "[dhcp=" + dhcp + ", model=" + model + ", vlan=" + vlan + ", mac=" + mac + "]"; + } +} \ No newline at end of file diff --git a/sandbox/elasticstack/src/main/java/org/jclouds/elasticstack/domain/SCSIDevice.java b/sandbox/elasticstack/src/main/java/org/jclouds/elasticstack/domain/SCSIDevice.java new file mode 100644 index 0000000000..56bd535294 --- /dev/null +++ b/sandbox/elasticstack/src/main/java/org/jclouds/elasticstack/domain/SCSIDevice.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.elasticstack.domain; + +import static com.google.common.base.Preconditions.checkArgument; + +/** + * + * @author Adrian Cole + */ +public class SCSIDevice extends Device { + + private final char bus = 0; + private final char unit; + + public SCSIDevice(String driveUuid, MediaType mediaType, char unit) { + super(driveUuid, mediaType); + checkArgument(unit >= 0 && unit < 8, "unit must be between 0 and 7"); + this.unit = unit; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + bus; + result = prime * result + unit; + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + SCSIDevice other = (SCSIDevice) obj; + if (bus != other.bus) + return false; + if (unit != other.unit) + return false; + return true; + } + + public char getBus() { + return bus; + } + + public char getUnit() { + return unit; + } + + @Override + public String getId() { + return String.format("scsi:%d:%d", bus, unit); + } + + @Override + public String toString() { + return "[id=" + getId() + ", driveUuid=" + driveUuid + ", mediaType=" + mediaType + "]"; + } +} \ No newline at end of file diff --git a/sandbox/elasticstack/src/main/java/org/jclouds/elasticstack/domain/Server.java b/sandbox/elasticstack/src/main/java/org/jclouds/elasticstack/domain/Server.java new file mode 100644 index 0000000000..ad85f45e84 --- /dev/null +++ b/sandbox/elasticstack/src/main/java/org/jclouds/elasticstack/domain/Server.java @@ -0,0 +1,337 @@ +/** + * + * 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.elasticstack.domain; + +import static com.google.common.base.Preconditions.checkNotNull; + +import java.util.List; +import java.util.Map; +import java.util.Set; + +import javax.annotation.Nullable; + +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableSet; + +/** + * + * @author Adrian Cole + */ +public class Server extends Item { + // + // user UUID + // status active|stopped + // cpu CPU + // smp SMP + // mem MEM + // bootDeviceIds UUID + // description DESCRIPTION + // ide:0:0 UUID + // ide:0:1 UUID + // ide:1:0 UUID + // ide:1:1 UUID + // nic:0:model NIC_0_MODEL + // nic:0:dhcp NIC_0_DHCP + // nic:1:model NIC_1_MODEL + // nic:1:vlan NIC_1_VLAN + // vnc:ip VNC_IP + // vnc:password VNC_PASS + + public static class Builder extends Item.Builder { + protected int cpu; + protected Integer smp; + protected int mem; + protected boolean persistent; + protected Set devices = ImmutableSet.of(); + protected Set bootDeviceIds = ImmutableSet.of(); + protected List nics = ImmutableList.of(); + protected String user; + protected VNC vnc; + // TODO undocumented + protected String description; + + public Builder cpu(int cpu) { + this.cpu = cpu; + return this; + } + + public Builder smp(Integer smp) { + this.smp = smp; + return this; + } + + public Builder mem(int mem) { + this.mem = mem; + return this; + } + + public Builder persistent(boolean persistent) { + this.persistent = persistent; + return this; + } + + public Builder devices(Iterable devices) { + this.devices = ImmutableSet.copyOf(checkNotNull(devices, "devices")); + return this; + } + + public Builder bootDeviceIds(Iterable bootDeviceIds) { + this.bootDeviceIds = ImmutableSet.copyOf(checkNotNull(bootDeviceIds, "bootDeviceIds")); + return this; + } + + public Builder nics(Iterable nics) { + this.nics = ImmutableList.copyOf(checkNotNull(nics, "nics")); + return this; + } + + public Builder user(String user) { + this.user = user; + return this; + } + + public Builder vnc(VNC vnc) { + this.vnc = vnc; + return this; + } + + public Builder description(String description) { + this.description = description; + return this; + } + + /** + * {@inheritDoc} + */ + @Override + public Builder uuid(String uuid) { + return Builder.class.cast(super.uuid(uuid)); + } + + /** + * {@inheritDoc} + */ + @Override + public Builder name(String name) { + return Builder.class.cast(super.name(name)); + } + + /** + * {@inheritDoc} + */ + @Override + public Builder tags(Iterable tags) { + return Builder.class.cast(super.tags(tags)); + } + + /** + * {@inheritDoc} + */ + @Override + public Builder userMetadata(Map userMetadata) { + return Builder.class.cast(super.userMetadata(userMetadata)); + } + + public Server build() { + return new Server(uuid, name, cpu, smp, mem, persistent, devices, tags, bootDeviceIds, userMetadata, nics, + user, vnc, description); + } + } + + protected final int cpu; + protected final Integer smp; + protected final int mem; + protected final boolean persistent; + protected final Set devices; + protected final Set bootDeviceIds; + @Nullable + protected final String user; + protected final List nics; + protected final VNC vnc; + @Nullable + private final String description; + + public Server(@Nullable String uuid, String name, int cpu, @Nullable Integer smp, int mem, boolean persistent, + Iterable devices, Iterable bootDeviceIds, Iterable tags, + Map userMetadata, Iterable nics, @Nullable String user, VNC vnc, String description) { + super(uuid, name, tags, userMetadata); + this.cpu = cpu; + this.smp = smp; + this.mem = mem; + this.persistent = persistent; + this.devices = ImmutableSet.copyOf(checkNotNull(devices, "devices")); + this.bootDeviceIds = ImmutableSet.copyOf(checkNotNull(bootDeviceIds, "bootDeviceIds")); + this.nics = ImmutableList.copyOf(checkNotNull(nics, "nics")); + this.user = user; + this.vnc = checkNotNull(vnc, "vnc"); + this.description = description; + } + + /** + * + * @return CPU quota in core MHz. + */ + public int getCpu() { + return cpu; + } + + /** + * + * @return number of virtual processors or null if calculated based on cpu. + */ + public Integer getSmp() { + return smp; + } + + /** + * + * @return virtual memory size in MB. + */ + public int getMem() { + return mem; + } + + /** + * + * @return 'true' means that server will revert to a 'stopped' status on server stop or shutdown, + * rather than being destroyed automatically. + */ + public boolean isPersistent() { + return persistent; + } + + /** + * + * @return set of devices present + */ + public Set getDevices() { + return devices; + } + + /** + * + * @return ids of the devices to boot, e.g. ide:0:0 or ide:1:0 + * @see Device#getId() + */ + public Set getBootDeviceIds() { + return bootDeviceIds; + } + + public List getNics() { + return nics; + } + + // TODO undocumented + /** + * + * @return owner of the server. + */ + public String getUser() { + return user; + } + + public VNC getVnc() { + return vnc; + } + + // TODO undocumented + public String getDescription() { + return description; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = super.hashCode(); + result = prime * result + ((bootDeviceIds == null) ? 0 : bootDeviceIds.hashCode()); + result = prime * result + cpu; + result = prime * result + ((description == null) ? 0 : description.hashCode()); + result = prime * result + ((devices == null) ? 0 : devices.hashCode()); + result = prime * result + mem; + result = prime * result + ((nics == null) ? 0 : nics.hashCode()); + result = prime * result + (persistent ? 1231 : 1237); + result = prime * result + ((smp == null) ? 0 : smp.hashCode()); + result = prime * result + ((user == null) ? 0 : user.hashCode()); + result = prime * result + ((vnc == null) ? 0 : vnc.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; + Server other = (Server) obj; + if (bootDeviceIds == null) { + if (other.bootDeviceIds != null) + return false; + } else if (!bootDeviceIds.equals(other.bootDeviceIds)) + return false; + if (cpu != other.cpu) + return false; + if (description == null) { + if (other.description != null) + return false; + } else if (!description.equals(other.description)) + return false; + if (devices == null) { + if (other.devices != null) + return false; + } else if (!devices.equals(other.devices)) + return false; + if (mem != other.mem) + return false; + if (nics == null) { + if (other.nics != null) + return false; + } else if (!nics.equals(other.nics)) + return false; + if (persistent != other.persistent) + return false; + if (smp == null) { + if (other.smp != null) + return false; + } else if (!smp.equals(other.smp)) + return false; + if (user == null) { + if (other.user != null) + return false; + } else if (!user.equals(other.user)) + return false; + if (vnc == null) { + if (other.vnc != null) + return false; + } else if (!vnc.equals(other.vnc)) + return false; + return true; + } + + @Override + public String toString() { + return "[uuid=" + uuid + ", name=" + name + ", tags=" + tags + ", userMetadata=" + userMetadata + ", cpu=" + cpu + + ", smp=" + smp + ", mem=" + mem + ", persistent=" + persistent + ", devices=" + devices + + ", bootDeviceIds=" + bootDeviceIds + ", user=" + user + ", nics=" + nics + ", vnc=" + vnc + + ", description=" + description + "]"; + } + +} \ No newline at end of file diff --git a/sandbox/elasticstack/src/main/java/org/jclouds/elasticstack/domain/VNC.java b/sandbox/elasticstack/src/main/java/org/jclouds/elasticstack/domain/VNC.java new file mode 100644 index 0000000000..0fc89ebe83 --- /dev/null +++ b/sandbox/elasticstack/src/main/java/org/jclouds/elasticstack/domain/VNC.java @@ -0,0 +1,105 @@ +/** + * + * 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.elasticstack.domain; + +import javax.annotation.Nullable; + +/** + * + * @author Adrian Cole + */ +public class VNC { + @Nullable + private final String ip; + @Nullable + private final String password; + private final boolean tls; + + public VNC(String ip, String password, boolean tls) { + this.ip = ip; + this.password = password; + this.tls = tls; + } + + /** + * + * @return IP address for overlay VNC access on port 5900. Set to 'auto', to reuse nic:0:dhcp if + * available, or otherwise allocate a temporary IP at boot. + */ + public String getIp() { + return ip; + } + + /** + * + * @return Password for VNC access. If unset, VNC is disabled. + */ + public String getPassword() { + return password; + } + + /** + * + * @return Set to 'on' to require VeNCrypt-style TLS auth in addition to the password. If this is + * unset, only unencrypted VNC is available. + */ + public boolean isTls() { + return tls; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((ip == null) ? 0 : ip.hashCode()); + result = prime * result + ((password == null) ? 0 : password.hashCode()); + result = prime * result + (tls ? 1231 : 1237); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + VNC other = (VNC) obj; + if (ip == null) { + if (other.ip != null) + return false; + } else if (!ip.equals(other.ip)) + return false; + if (password == null) { + if (other.password != null) + return false; + } else if (!password.equals(other.password)) + return false; + if (tls != other.tls) + return false; + return true; + } + + @Override + public String toString() { + return "[ip=" + ip + ", password=" + password + ", tls=" + tls + "]"; + } +} \ No newline at end of file diff --git a/sandbox/elasticstack/src/main/java/org/jclouds/elasticstack/domain/internal/BaseDrive.java b/sandbox/elasticstack/src/main/java/org/jclouds/elasticstack/domain/internal/BaseDrive.java new file mode 100644 index 0000000000..e4dd523fce --- /dev/null +++ b/sandbox/elasticstack/src/main/java/org/jclouds/elasticstack/domain/internal/BaseDrive.java @@ -0,0 +1,221 @@ +/** + * + * 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.elasticstack.domain.internal; + +import static com.google.common.base.Preconditions.checkNotNull; + +import java.util.Map; +import java.util.Set; + +import javax.annotation.Nullable; + +import org.jclouds.elasticstack.domain.ClaimType; +import org.jclouds.elasticstack.domain.Item; + +import com.google.common.collect.ImmutableSet; + +/** + * + * @author Adrian Cole + */ +public class BaseDrive extends Item { + public static class Builder extends Item.Builder { + protected long size; + protected ClaimType claimType = ClaimType.EXCLUSIVE; + protected Set readers = ImmutableSet.of(); + + public Builder claimType(ClaimType claimType) { + this.claimType = claimType; + return this; + } + + public Builder readers(Iterable readers) { + this.readers = ImmutableSet.copyOf(checkNotNull(readers, "readers")); + return this; + } + + public Builder size(long size) { + this.size = size; + return this; + } + + /** + * {@inheritDoc} + */ + @Override + public Builder uuid(String uuid) { + return Builder.class.cast(super.uuid(uuid)); + } + + /** + * {@inheritDoc} + */ + @Override + public Builder name(String name) { + return Builder.class.cast(super.name(name)); + } + + /** + * {@inheritDoc} + */ + @Override + public Builder tags(Iterable tags) { + return Builder.class.cast(super.tags(tags)); + } + + /** + * {@inheritDoc} + */ + @Override + public Builder userMetadata(Map userMetadata) { + return Builder.class.cast(super.userMetadata(userMetadata)); + } + + public BaseDrive build() { + return new BaseDrive(uuid, name, size, claimType, readers, tags, userMetadata); + } + + @Override + public int hashCode() { + final int prime = 31; + int result = super.hashCode(); + result = prime * result + ((claimType == null) ? 0 : claimType.hashCode()); + result = prime * result + ((readers == null) ? 0 : readers.hashCode()); + result = prime * result + (int) (size ^ (size >>> 32)); + 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; + Builder other = (Builder) obj; + if (claimType != other.claimType) + return false; + if (readers == null) { + if (other.readers != null) + return false; + } else if (!readers.equals(other.readers)) + return false; + if (size != other.size) + return false; + return true; + } + } + + protected final long size; + protected final ClaimType claimType; + protected final Set readers; + + public BaseDrive(@Nullable String uuid, String name, long size, @Nullable ClaimType claimType, + Iterable readers, Iterable tags, Map userMetadata) { + super(uuid, name, tags, userMetadata); + this.size = size; + this.claimType = checkNotNull(claimType, "set claimType to exclusive, not null"); + this.readers = ImmutableSet.copyOf(checkNotNull(readers, "readers")); + } + + /** + * + * @return either 'exclusive' (the default) or 'shared' to allow multiple servers to access a + * drive simultaneously + */ + @Nullable + public ClaimType getClaimType() { + return claimType; + } + + /** + * + * @return list of users allowed to read from a drive or 'ffffffff-ffff-ffff-ffff-ffffffffffff' + * for all users + */ + public Set getReaders() { + return readers; + } + + /** + * + * @return size of drive in bytes + */ + public long getSize() { + return size; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((claimType == null) ? 0 : claimType.hashCode()); + result = prime * result + ((name == null) ? 0 : name.hashCode()); + result = prime * result + ((readers == null) ? 0 : readers.hashCode()); + result = prime * result + (int) (size ^ (size >>> 32)); + result = prime * result + ((tags == null) ? 0 : tags.hashCode()); + result = prime * result + ((userMetadata == null) ? 0 : userMetadata.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + BaseDrive other = (BaseDrive) obj; + if (claimType != other.claimType) + return false; + if (name == null) { + if (other.name != null) + return false; + } else if (!name.equals(other.name)) + return false; + if (readers == null) { + if (other.readers != null) + return false; + } else if (!readers.equals(other.readers)) + return false; + if (size != other.size) + return false; + if (tags == null) { + if (other.tags != null) + return false; + } else if (!tags.equals(other.tags)) + return false; + if (userMetadata == null) { + if (other.userMetadata != null) + return false; + } else if (!userMetadata.equals(other.userMetadata)) + return false; + return true; + } + + @Override + public String toString() { + return "[uuid=" + uuid + ", name=" + name + ", tags=" + tags + ", userMetadata=" + userMetadata + ", size=" + + size + ", claimType=" + claimType + ", readers=" + readers + "]"; + } + +} \ No newline at end of file diff --git a/sandbox/elasticstack/src/main/java/org/jclouds/elasticstack/functions/BaseDriveToMap.java b/sandbox/elasticstack/src/main/java/org/jclouds/elasticstack/functions/BaseDriveToMap.java new file mode 100644 index 0000000000..eca915aead --- /dev/null +++ b/sandbox/elasticstack/src/main/java/org/jclouds/elasticstack/functions/BaseDriveToMap.java @@ -0,0 +1,58 @@ +/** + * + * 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.elasticstack.functions; + +import static com.google.common.base.Preconditions.checkNotNull; + +import java.util.Map; +import java.util.Map.Entry; + +import javax.inject.Singleton; + +import org.jclouds.elasticstack.domain.ClaimType; +import org.jclouds.elasticstack.domain.internal.BaseDrive; + +import com.google.common.base.Function; +import com.google.common.base.Joiner; +import com.google.common.collect.ImmutableMap; + +/** + * + * @author Adrian Cole + */ +@Singleton +public class BaseDriveToMap implements Function> { + @Override + public Map apply(BaseDrive from) { + checkNotNull(from, "drive"); + ImmutableMap.Builder builder = ImmutableMap.builder(); + builder.put("name", from.getName()); + builder.put("size", from.getSize() + ""); + if (from.getClaimType() != ClaimType.EXCLUSIVE) + builder.put("claim:type", from.getClaimType().toString()); + if (from.getReaders().size() != 0) + builder.put("readers", Joiner.on(' ').join(from.getReaders())); + if (from.getTags().size() != 0) + builder.put("tags", Joiner.on(' ').join(from.getTags())); + for (Entry entry : from.getUserMetadata().entrySet()) + builder.put("user:" + entry.getKey(), entry.getValue()); + return builder.build(); + } +} \ No newline at end of file diff --git a/sandbox/elasticstack/src/main/java/org/jclouds/elasticstack/functions/CreateDriveRequestToMap.java b/sandbox/elasticstack/src/main/java/org/jclouds/elasticstack/functions/CreateDriveRequestToMap.java new file mode 100644 index 0000000000..a63c167d07 --- /dev/null +++ b/sandbox/elasticstack/src/main/java/org/jclouds/elasticstack/functions/CreateDriveRequestToMap.java @@ -0,0 +1,56 @@ +/** + * + * 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.elasticstack.functions; + +import java.util.Map; + +import javax.inject.Inject; +import javax.inject.Singleton; + +import org.jclouds.elasticstack.domain.CreateDriveRequest; + +import com.google.common.base.Function; +import com.google.common.base.Joiner; +import com.google.common.collect.ImmutableMap; + +/** + * + * @author Adrian Cole + */ +@Singleton +public class CreateDriveRequestToMap implements Function> { + private final BaseDriveToMap baseDriveToMap; + + @Inject + public CreateDriveRequestToMap(BaseDriveToMap baseDriveToMap) { + this.baseDriveToMap = baseDriveToMap; + } + + @Override + public Map apply(CreateDriveRequest from) { + ImmutableMap.Builder builder = ImmutableMap.builder(); + builder.putAll(baseDriveToMap.apply(from)); + if (from.getAvoid().size() != 0) + builder.put("avoid", Joiner.on(' ').join(from.getAvoid())); + if (from.getEncryptionCipher() != null) + builder.put("encryption:cipher", from.getEncryptionCipher()); + return builder.build(); + } +} \ No newline at end of file diff --git a/sandbox/elasticstack/src/main/java/org/jclouds/elasticstack/functions/DriveDataToMap.java b/sandbox/elasticstack/src/main/java/org/jclouds/elasticstack/functions/DriveDataToMap.java new file mode 100644 index 0000000000..a27792e00b --- /dev/null +++ b/sandbox/elasticstack/src/main/java/org/jclouds/elasticstack/functions/DriveDataToMap.java @@ -0,0 +1,51 @@ +/** + * + * 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.elasticstack.functions; + +import java.util.Map; + +import javax.inject.Inject; +import javax.inject.Singleton; + +import org.jclouds.elasticstack.domain.DriveData; + +import com.google.common.base.Function; +import com.google.common.collect.ImmutableMap; + +/** + * + * @author Adrian Cole + */ +@Singleton +public class DriveDataToMap implements Function> { + private final BaseDriveToMap baseDriveToMap; + + @Inject + public DriveDataToMap(BaseDriveToMap baseDriveToMap) { + this.baseDriveToMap = baseDriveToMap; + } + + @Override + public Map apply(DriveData from) { + ImmutableMap.Builder builder = ImmutableMap.builder(); + builder.putAll(baseDriveToMap.apply(from)); + return builder.build(); + } +} \ No newline at end of file diff --git a/sandbox/elasticstack/src/main/java/org/jclouds/elasticstack/functions/KeyValuesDelimitedByBlankLinesToDriveInfo.java b/sandbox/elasticstack/src/main/java/org/jclouds/elasticstack/functions/KeyValuesDelimitedByBlankLinesToDriveInfo.java new file mode 100644 index 0000000000..4cbc3db611 --- /dev/null +++ b/sandbox/elasticstack/src/main/java/org/jclouds/elasticstack/functions/KeyValuesDelimitedByBlankLinesToDriveInfo.java @@ -0,0 +1,53 @@ +/** + * + * 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.elasticstack.functions; + +import java.util.Set; + +import javax.inject.Inject; +import javax.inject.Singleton; + +import org.jclouds.elasticstack.domain.DriveInfo; +import org.jclouds.http.HttpResponse; + +import com.google.common.base.Function; +import com.google.common.collect.Iterables; + +/** + * + * @author Adrian Cole + */ +@Singleton +public class KeyValuesDelimitedByBlankLinesToDriveInfo implements Function { + private final ListOfKeyValuesDelimitedByBlankLinesToDriveInfoSet setParser; + + @Inject + public KeyValuesDelimitedByBlankLinesToDriveInfo(ListOfKeyValuesDelimitedByBlankLinesToDriveInfoSet setParser) { + this.setParser = setParser; + } + + @Override + public DriveInfo apply(HttpResponse response) { + Set drives = setParser.apply(response); + if (drives.size() == 0) + return null; + return Iterables.get(drives, 0); + } +} \ No newline at end of file diff --git a/sandbox/elasticstack/src/main/java/org/jclouds/elasticstack/functions/ListOfKeyValuesDelimitedByBlankLinesToDriveInfoSet.java b/sandbox/elasticstack/src/main/java/org/jclouds/elasticstack/functions/ListOfKeyValuesDelimitedByBlankLinesToDriveInfoSet.java new file mode 100644 index 0000000000..359b525d1c --- /dev/null +++ b/sandbox/elasticstack/src/main/java/org/jclouds/elasticstack/functions/ListOfKeyValuesDelimitedByBlankLinesToDriveInfoSet.java @@ -0,0 +1,60 @@ +/** + * + * 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.elasticstack.functions; + +import java.util.Set; + +import javax.inject.Inject; +import javax.inject.Singleton; + +import org.jclouds.elasticstack.domain.DriveInfo; +import org.jclouds.http.HttpResponse; +import org.jclouds.http.functions.ReturnStringIf2xx; + +import com.google.common.base.Function; +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Iterables; + +/** + * + * @author Adrian Cole + */ +@Singleton +public class ListOfKeyValuesDelimitedByBlankLinesToDriveInfoSet implements Function> { + private final ReturnStringIf2xx returnStringIf200; + private final ListOfKeyValuesDelimitedByBlankLinesToListOfMaps mapConverter; + private final MapToDriveInfo mapToDrive; + + @Inject + ListOfKeyValuesDelimitedByBlankLinesToDriveInfoSet(ReturnStringIf2xx returnStringIf200, + ListOfKeyValuesDelimitedByBlankLinesToListOfMaps mapConverter, MapToDriveInfo mapToDrive) { + this.returnStringIf200 = returnStringIf200; + this.mapConverter = mapConverter; + this.mapToDrive = mapToDrive; + } + + @Override + public Set apply(HttpResponse response) { + String text = returnStringIf200.apply(response); + if (text == null || text.trim().equals("")) + return ImmutableSet. of(); + return ImmutableSet.copyOf(Iterables.transform(mapConverter.apply(text), mapToDrive)); + } +} \ No newline at end of file diff --git a/sandbox/elasticstack/src/main/java/org/jclouds/elasticstack/functions/ListOfKeyValuesDelimitedByBlankLinesToListOfMaps.java b/sandbox/elasticstack/src/main/java/org/jclouds/elasticstack/functions/ListOfKeyValuesDelimitedByBlankLinesToListOfMaps.java new file mode 100644 index 0000000000..80f63906e6 --- /dev/null +++ b/sandbox/elasticstack/src/main/java/org/jclouds/elasticstack/functions/ListOfKeyValuesDelimitedByBlankLinesToListOfMaps.java @@ -0,0 +1,59 @@ +/** + * + * 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.elasticstack.functions; + +import java.util.List; +import java.util.Map; + +import javax.inject.Singleton; + +import com.google.common.base.Function; +import com.google.common.base.Splitter; +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; + +/** + * + * @author Adrian Cole + */ +@Singleton +public class ListOfKeyValuesDelimitedByBlankLinesToListOfMaps implements Function>> { + + @Override + public List> apply(String from) { + List> maps = Lists.newArrayList(); + for (String listOfKeyValues : Splitter.on("\n\n").split(from)) { + if (!"".equals(listOfKeyValues)) { + Map map = Maps.newLinkedHashMap(); + for (String keyValueLine : Splitter.on('\n').split(listOfKeyValues)) { + if (!"".equals(keyValueLine)) { + int firstIndex = keyValueLine.indexOf(' '); + String key = keyValueLine.substring(0, firstIndex); + String value = keyValueLine.substring(firstIndex + 1).replace("\\n", "\n"); + map.put(key, value); + } + } + if (map.size() != 0) + maps.add(map); + } + } + return maps; + } +} \ No newline at end of file diff --git a/sandbox/elasticstack/src/main/java/org/jclouds/elasticstack/functions/ListOfMapsToListOfKeyValuesDelimitedByBlankLines.java b/sandbox/elasticstack/src/main/java/org/jclouds/elasticstack/functions/ListOfMapsToListOfKeyValuesDelimitedByBlankLines.java new file mode 100644 index 0000000000..57a4e0302b --- /dev/null +++ b/sandbox/elasticstack/src/main/java/org/jclouds/elasticstack/functions/ListOfMapsToListOfKeyValuesDelimitedByBlankLines.java @@ -0,0 +1,58 @@ +/** + * + * 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.elasticstack.functions; + +import java.util.Map; + +import javax.inject.Singleton; + +import com.google.common.base.Function; +import com.google.common.base.Joiner; +import com.google.common.collect.Iterables; +import com.google.common.collect.Maps; + +/** + * + * @author Adrian Cole + */ +@Singleton +public class ListOfMapsToListOfKeyValuesDelimitedByBlankLines implements + Function>, String> { + + @Override + public String apply(Iterable> from) { + return Joiner.on("\n\n").join(Iterables.transform(from, new Function, String>() { + + @Override + public String apply(Map from) { + return Joiner.on('\n').withKeyValueSeparator(" ") + .join(Maps.transformValues(from, new Function() { + + @Override + public String apply(String from) { + return from.replace("\n", "\\n"); + } + + })); + } + + })); + } +} \ No newline at end of file diff --git a/sandbox/elasticstack/src/main/java/org/jclouds/elasticstack/functions/MapToDriveInfo.java b/sandbox/elasticstack/src/main/java/org/jclouds/elasticstack/functions/MapToDriveInfo.java new file mode 100644 index 0000000000..eb6282142f --- /dev/null +++ b/sandbox/elasticstack/src/main/java/org/jclouds/elasticstack/functions/MapToDriveInfo.java @@ -0,0 +1,78 @@ +/** + * + * 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.elasticstack.functions; + +import java.util.Map; +import java.util.Map.Entry; + +import javax.inject.Singleton; + +import org.jclouds.elasticstack.domain.ClaimType; +import org.jclouds.elasticstack.domain.DriveInfo; +import org.jclouds.elasticstack.domain.DriveStatus; + +import com.google.common.base.Function; +import com.google.common.base.Splitter; +import com.google.common.collect.Maps; + +/** + * + * @author Adrian Cole + */ +@Singleton +public class MapToDriveInfo implements Function, DriveInfo> { + @Override + public DriveInfo apply(Map from) { + if (from.size() == 0) + return null; + DriveInfo.Builder builder = new DriveInfo.Builder(); + builder.name(from.get("name")); + if (from.containsKey("tags")) + builder.tags(Splitter.on(' ').split(from.get("tags"))); + if (from.containsKey("status")) + builder.status(DriveStatus.fromValue(from.get("status"))); + if (from.containsKey("read:bytes")) + builder.readBytes(new Long(from.get("read:bytes"))); + if (from.containsKey("read:requests")) + builder.readRequests(new Long(from.get("read:requests"))); + builder.user(from.get("user")); + builder.encryptionCipher(from.get("encryption:cipher")); + builder.uuid(from.get("drive")); + if (from.containsKey("write:bytes")) + builder.writeBytes(new Long(from.get("write:bytes"))); + if (from.containsKey("write:requests")) + builder.writeRequests(new Long(from.get("write:requests"))); + if (from.containsKey("claim:type")) + builder.claimType(ClaimType.fromValue(from.get("claim:type"))); + if (from.containsKey("claimed")) + builder.claimed(Splitter.on(' ').split(from.get("claimed"))); + if (from.containsKey("readers")) + builder.readers(Splitter.on(' ').split(from.get("readers"))); + if (from.containsKey("size")) + builder.size(new Long(from.get("size"))); + Map metadata = Maps.newLinkedHashMap(); + for (Entry entry : from.entrySet()) { + if (entry.getKey().startsWith("user:")) + metadata.put(entry.getKey().substring(entry.getKey().indexOf(':') + 1), entry.getValue()); + } + builder.userMetadata(metadata); + return builder.build(); + } +} \ No newline at end of file diff --git a/sandbox/elasticstack/src/main/java/org/jclouds/elasticstack/functions/ReturnPayload.java b/sandbox/elasticstack/src/main/java/org/jclouds/elasticstack/functions/ReturnPayload.java new file mode 100644 index 0000000000..2cd168b7d1 --- /dev/null +++ b/sandbox/elasticstack/src/main/java/org/jclouds/elasticstack/functions/ReturnPayload.java @@ -0,0 +1,38 @@ +/** + * + * 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.elasticstack.functions; + +import javax.inject.Singleton; + +import org.jclouds.http.HttpResponse; +import org.jclouds.io.Payload; + +import com.google.common.base.Function; + +/** + * @author Adrian Cole + */ +@Singleton +public class ReturnPayload implements Function { + + public Payload apply(HttpResponse from) { + return from.getPayload(); + } +} \ No newline at end of file diff --git a/sandbox/elasticstack/src/main/java/org/jclouds/elasticstack/functions/SplitNewlines.java b/sandbox/elasticstack/src/main/java/org/jclouds/elasticstack/functions/SplitNewlines.java new file mode 100644 index 0000000000..7db34f2f04 --- /dev/null +++ b/sandbox/elasticstack/src/main/java/org/jclouds/elasticstack/functions/SplitNewlines.java @@ -0,0 +1,55 @@ +/** + * + * 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.elasticstack.functions; + +import static com.google.common.base.Predicates.equalTo; +import static com.google.common.base.Predicates.not; +import static com.google.common.collect.Iterables.filter; +import static com.google.common.collect.Sets.newTreeSet; + +import java.util.Set; + +import javax.inject.Inject; +import javax.inject.Singleton; + +import org.jclouds.http.HttpResponse; +import org.jclouds.http.functions.ReturnStringIf2xx; + +import com.google.common.base.Function; +import com.google.common.base.Splitter; + +/** + * + * @author Adrian Cole + */ +@Singleton +public class SplitNewlines implements Function> { + private final ReturnStringIf2xx returnStringIf200; + + @Inject + SplitNewlines(ReturnStringIf2xx returnStringIf200) { + this.returnStringIf200 = returnStringIf200; + } + + @Override + public Set apply(HttpResponse response) { + return newTreeSet(filter(Splitter.on('\n').split(returnStringIf200.apply(response)), not(equalTo("")))); + } +} \ No newline at end of file diff --git a/sandbox/elasticstack/src/main/java/org/jclouds/elasticstack/handlers/ElasticStackErrorHandler.java b/sandbox/elasticstack/src/main/java/org/jclouds/elasticstack/handlers/ElasticStackErrorHandler.java new file mode 100644 index 0000000000..cdc0c55e03 --- /dev/null +++ b/sandbox/elasticstack/src/main/java/org/jclouds/elasticstack/handlers/ElasticStackErrorHandler.java @@ -0,0 +1,106 @@ +/** + * + * 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.elasticstack.handlers; + +import java.io.IOException; + +import javax.annotation.Resource; +import javax.inject.Singleton; + +import org.jclouds.http.HttpCommand; +import org.jclouds.http.HttpErrorHandler; +import org.jclouds.http.HttpResponse; +import org.jclouds.http.HttpResponseException; +import org.jclouds.logging.Logger; +import org.jclouds.rest.AuthorizationException; +import org.jclouds.rest.ResourceNotFoundException; +import org.jclouds.util.Utils; + +import com.google.common.base.Throwables; +import com.google.common.io.Closeables; + +/** + * This will parse and set an appropriate exception on the command object. + * + *

+ * Errors are returned with an appropriate HTTP status code, an X-Elastic- Error header specifying + * the error type, and a text description in the HTTP body. + * + * @author Adrian Cole + * + */ +@Singleton +public class ElasticStackErrorHandler implements HttpErrorHandler { + @Resource + protected Logger logger = Logger.NULL; + + public void handleError(HttpCommand command, HttpResponse response) { + // it is important to always read fully and close streams + String message = parseMessage(response); + Exception exception = message != null ? new HttpResponseException(command, response, message) + : new HttpResponseException(command, response); + try { + message = message != null ? message : String.format("%s -> %s", command.getRequest().getRequestLine(), + response.getStatusLine()); + switch (response.getStatusCode()) { + case 400: + if (message != null && message.indexOf("could not be found") != -1) + exception = new ResourceNotFoundException(message, exception); + else + exception = new IllegalArgumentException(message, exception); + break; + case 401: + exception = new AuthorizationException(message, exception); + break; + case 404: + if (!command.getRequest().getMethod().equals("DELETE")) { + exception = new ResourceNotFoundException(message, exception); + } + break; + case 405: + exception = new IllegalArgumentException(message, exception); + break; + case 409: + exception = new IllegalStateException(message, exception); + break; + } + } finally { + if (response.getPayload() != null) + Closeables.closeQuietly(response.getPayload().getInput()); + command.setException(exception); + } + } + + public String parseMessage(HttpResponse response) { + if (response.getPayload() == null) + return null; + try { + return Utils.toStringAndClose(response.getPayload().getInput()); + } catch (IOException e) { + throw new RuntimeException(e); + } finally { + try { + response.getPayload().getInput().close(); + } catch (IOException e) { + Throwables.propagate(e); + } + } + } +} diff --git a/sandbox/elasticstack/src/main/java/org/jclouds/elasticstack/options/ReadDriveOptions.java b/sandbox/elasticstack/src/main/java/org/jclouds/elasticstack/options/ReadDriveOptions.java new file mode 100644 index 0000000000..cfbe4af50e --- /dev/null +++ b/sandbox/elasticstack/src/main/java/org/jclouds/elasticstack/options/ReadDriveOptions.java @@ -0,0 +1,91 @@ +/** + * + * 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.elasticstack.options; + +import static com.google.common.base.Preconditions.checkArgument; + +/** + * Contains options supported for read drive operations.

+ * Usage

The recommended way to instantiate a ReadDriveOptions object is to statically import + * ReadDriveOptions.Builder.* and invoke a static creation method followed by an instance mutator + * (if needed): + *

+ * + * import static org.jclouds.elasticstack.options.ReadDriveOptions.Builder.*; + * + * + * // this will get the first 1024 bytes starting at offset 2048 + * Payload payload = client.readDrive("drive-uuid",offset(2048l).size(1024l)); + * + * + * @author Adrian Cole + * + */ +public class ReadDriveOptions { + + private Long offset; + private Long size; + + /** + * start at the specified offset in bytes + */ + public ReadDriveOptions offset(long offset) { + checkArgument(offset >= 0, "start must be >= 0"); + this.offset = offset; + return this; + } + + /** + * download the specified size in bytes + */ + public ReadDriveOptions size(long size) { + checkArgument(size >= 0, "start must be >= 0"); + this.size = size; + return this; + } + + public static class Builder { + + /** + * @see ReadDriveOptions#offset + */ + public static ReadDriveOptions offset(long offset) { + ReadDriveOptions options = new ReadDriveOptions(); + return options.offset(offset); + } + + /** + * @see ReadDriveOptions#size + */ + public static ReadDriveOptions size(long size) { + ReadDriveOptions options = new ReadDriveOptions(); + return options.size(size); + } + + } + + public Long getOffset() { + return offset; + } + + public Long getSize() { + return size; + } +} diff --git a/sandbox/elasticstack/src/test/java/org/jclouds/cloudsigma/CloudSigmaAsyncClientTest.java b/sandbox/elasticstack/src/test/java/org/jclouds/cloudsigma/CloudSigmaAsyncClientTest.java new file mode 100644 index 0000000000..df788fd86e --- /dev/null +++ b/sandbox/elasticstack/src/test/java/org/jclouds/cloudsigma/CloudSigmaAsyncClientTest.java @@ -0,0 +1,180 @@ +/** + * + * 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.cloudsigma; + +import static org.testng.Assert.assertEquals; + +import java.io.IOException; +import java.lang.reflect.Method; +import java.util.Properties; + +import org.jclouds.cloudsigma.functions.KeyValuesDelimitedByBlankLinesToDriveInfo; +import org.jclouds.cloudsigma.functions.ListOfKeyValuesDelimitedByBlankLinesToDriveInfoSet; +import org.jclouds.elasticstack.domain.CreateDriveRequest; +import org.jclouds.elasticstack.domain.DriveData; +import org.jclouds.elasticstack.functions.SplitNewlines; +import org.jclouds.http.HttpRequest; +import org.jclouds.http.filters.BasicAuthentication; +import org.jclouds.rest.RestClientTest; +import org.jclouds.rest.RestContextFactory; +import org.jclouds.rest.RestContextSpec; +import org.jclouds.rest.functions.ReturnNullOnNotFoundOr404; +import org.jclouds.rest.internal.GeneratedHttpRequest; +import org.jclouds.rest.internal.RestAnnotationProcessor; +import org.testng.annotations.Test; + +import com.google.common.collect.ImmutableList; +import com.google.inject.TypeLiteral; + +/** + * Tests annotation parsing of {@code CloudSigmaAsyncClient} + * + * @author Adrian Cole + */ +@Test(groups = "unit", testName = "cloudsigma.CloudSigmaAsyncClientTest") +public class CloudSigmaAsyncClientTest extends RestClientTest { + + public void testListStandardDrives() throws SecurityException, NoSuchMethodException, IOException { + Method method = CloudSigmaAsyncClient.class.getMethod("listStandardDrives"); + GeneratedHttpRequest httpRequest = processor.createRequest(method); + + assertRequestLineEquals(httpRequest, "GET https://api.cloudsigma.com/drives/standard/list HTTP/1.1"); + assertNonPayloadHeadersEqual(httpRequest, "Accept: text/plain\n"); + assertPayloadEquals(httpRequest, null, null, false); + + assertResponseParserClassEquals(method, httpRequest, SplitNewlines.class); + assertSaxResponseParserClassEquals(method, null); + assertExceptionParserClassEquals(method, null); + + checkFilters(httpRequest); + } + + public void testListStandardCds() throws SecurityException, NoSuchMethodException, IOException { + Method method = CloudSigmaAsyncClient.class.getMethod("listStandardCds"); + GeneratedHttpRequest httpRequest = processor.createRequest(method); + + assertRequestLineEquals(httpRequest, "GET https://api.cloudsigma.com/drives/standard/cd/list HTTP/1.1"); + assertNonPayloadHeadersEqual(httpRequest, "Accept: text/plain\n"); + assertPayloadEquals(httpRequest, null, null, false); + + assertResponseParserClassEquals(method, httpRequest, SplitNewlines.class); + assertSaxResponseParserClassEquals(method, null); + assertExceptionParserClassEquals(method, null); + + checkFilters(httpRequest); + } + + public void testListStandardImages() throws SecurityException, NoSuchMethodException, IOException { + Method method = CloudSigmaAsyncClient.class.getMethod("listStandardImages"); + GeneratedHttpRequest httpRequest = processor.createRequest(method); + + assertRequestLineEquals(httpRequest, "GET https://api.cloudsigma.com/drives/standard/img/list HTTP/1.1"); + assertNonPayloadHeadersEqual(httpRequest, "Accept: text/plain\n"); + assertPayloadEquals(httpRequest, null, null, false); + + assertResponseParserClassEquals(method, httpRequest, SplitNewlines.class); + assertSaxResponseParserClassEquals(method, null); + assertExceptionParserClassEquals(method, null); + + checkFilters(httpRequest); + } + + public void testListDriveInfo() throws SecurityException, NoSuchMethodException, IOException { + Method method = CloudSigmaAsyncClient.class.getMethod("listDriveInfo"); + GeneratedHttpRequest httpRequest = processor.createRequest(method); + + assertRequestLineEquals(httpRequest, "GET https://api.cloudsigma.com/drives/info HTTP/1.1"); + assertNonPayloadHeadersEqual(httpRequest, "Accept: text/plain\n"); + assertPayloadEquals(httpRequest, null, null, false); + + assertResponseParserClassEquals(method, httpRequest, ListOfKeyValuesDelimitedByBlankLinesToDriveInfoSet.class); + assertSaxResponseParserClassEquals(method, null); + assertExceptionParserClassEquals(method, null); + + checkFilters(httpRequest); + } + + public void testGetDriveInfo() throws SecurityException, NoSuchMethodException, IOException { + Method method = CloudSigmaAsyncClient.class.getMethod("getDriveInfo", String.class); + GeneratedHttpRequest httpRequest = processor.createRequest(method, "uuid"); + + assertRequestLineEquals(httpRequest, "GET https://api.cloudsigma.com/drives/uuid/info HTTP/1.1"); + assertNonPayloadHeadersEqual(httpRequest, "Accept: text/plain\n"); + assertPayloadEquals(httpRequest, null, null, false); + + assertResponseParserClassEquals(method, httpRequest, KeyValuesDelimitedByBlankLinesToDriveInfo.class); + assertSaxResponseParserClassEquals(method, null); + assertExceptionParserClassEquals(method, ReturnNullOnNotFoundOr404.class); + + checkFilters(httpRequest); + + } + + public void testCreateDrive() throws SecurityException, NoSuchMethodException, IOException { + Method method = CloudSigmaAsyncClient.class.getMethod("createDrive", CreateDriveRequest.class); + GeneratedHttpRequest httpRequest = processor.createRequest(method, + new CreateDriveRequest.Builder().name("foo").tags(ImmutableList.of("production", "candy")).size(10000l).build()); + + assertRequestLineEquals(httpRequest, "POST https://api.cloudsigma.com/drives/create HTTP/1.1"); + assertNonPayloadHeadersEqual(httpRequest, "Accept: text/plain\n"); + assertPayloadEquals(httpRequest, "name foo\nsize 10000\nuse production,candy", "text/plain", false); + + assertResponseParserClassEquals(method, httpRequest, KeyValuesDelimitedByBlankLinesToDriveInfo.class); + assertSaxResponseParserClassEquals(method, null); + assertExceptionParserClassEquals(method, ReturnNullOnNotFoundOr404.class); + + checkFilters(httpRequest); + + } + + public void testSetDriveData() throws SecurityException, NoSuchMethodException, IOException { + Method method = CloudSigmaAsyncClient.class.getMethod("setDriveData", String.class, DriveData.class); + GeneratedHttpRequest httpRequest = processor.createRequest(method, "100", + new DriveData.Builder().name("foo").size(10000l).tags(ImmutableList.of("production", "candy")).build()); + + assertRequestLineEquals(httpRequest, "POST https://api.cloudsigma.com/drives/100/set HTTP/1.1"); + assertNonPayloadHeadersEqual(httpRequest, "Accept: text/plain\n"); + assertPayloadEquals(httpRequest, "name foo\nsize 10000\nuse production,candy", "text/plain", false); + + assertResponseParserClassEquals(method, httpRequest, KeyValuesDelimitedByBlankLinesToDriveInfo.class); + assertSaxResponseParserClassEquals(method, null); + assertExceptionParserClassEquals(method, ReturnNullOnNotFoundOr404.class); + + checkFilters(httpRequest); + + } + + @Override + protected void checkFilters(HttpRequest request) { + assertEquals(request.getFilters().size(), 1); + assertEquals(request.getFilters().get(0).getClass(), BasicAuthentication.class); + } + + @Override + protected TypeLiteral> createTypeLiteral() { + return new TypeLiteral>() { + }; + } + + @Override + public RestContextSpec createContextSpec() { + return new RestContextFactory().createContextSpec("cloudsigma", "foo", "bar", new Properties()); + } +} diff --git a/sandbox/elasticstack/src/test/java/org/jclouds/cloudsigma/CloudSigmaClientLiveTest.java b/sandbox/elasticstack/src/test/java/org/jclouds/cloudsigma/CloudSigmaClientLiveTest.java new file mode 100644 index 0000000000..223fa37d14 --- /dev/null +++ b/sandbox/elasticstack/src/test/java/org/jclouds/cloudsigma/CloudSigmaClientLiveTest.java @@ -0,0 +1,72 @@ +/** + * + * 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.cloudsigma; + +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertNotNull; + +import java.util.Set; + +import org.jclouds.cloudsigma.domain.DriveInfo; +import org.jclouds.cloudsigma.domain.DriveType; +import org.jclouds.elasticstack.CommonElasticStackClientLiveTest; +import org.testng.annotations.Test; + +/** + * Tests behavior of {@code CloudSigmaClient} + * + * @author Adrian Cole + */ +@Test(groups = "live", testName = "cloudsigma.CloudSigmaClientLiveTest") +public class CloudSigmaClientLiveTest extends CommonElasticStackClientLiveTest { + + public CloudSigmaClientLiveTest() { + provider = "cloudsigma"; + } + + @Test + public void testListStandardDrives() throws Exception { + Set drives = client.listStandardDrives(); + assertNotNull(drives); + } + + @Test + public void testListStandardCds() throws Exception { + Set drives = client.listStandardCds(); + assertNotNull(drives); + } + + @Test + public void testListStandardImages() throws Exception { + Set drives = client.listStandardImages(); + assertNotNull(drives); + } + @Override + protected void checkDriveMatchesGet(org.jclouds.elasticstack.domain.DriveInfo newInfo) { + super.checkDriveMatchesGet(newInfo); + assertEquals(DriveInfo.class.cast(newInfo).getType(), DriveType.DISK); + } + + @Override + protected void checkCreatedDrive() { + super.checkCreatedDrive(); + assertEquals(DriveInfo.class.cast(info).getType(), null); + } +} diff --git a/sandbox/elasticstack/src/test/java/org/jclouds/cloudsigma/ProvidersInPropertiesTest.java b/sandbox/elasticstack/src/test/java/org/jclouds/cloudsigma/ProvidersInPropertiesTest.java new file mode 100644 index 0000000000..6e9d0a1af3 --- /dev/null +++ b/sandbox/elasticstack/src/test/java/org/jclouds/cloudsigma/ProvidersInPropertiesTest.java @@ -0,0 +1,47 @@ +/** + * + * 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.cloudsigma; + +import org.jclouds.util.Utils; +import org.testng.annotations.Test; + +import com.google.common.collect.Iterables; + +/** + * + * @author Adrian Cole + * + */ +@Test(groups = "unit") +public class ProvidersInPropertiesTest { + + @Test + public void testSupportedProviders() { + Iterable providers = Utils.getSupportedProviders(); + assert Iterables.contains(providers, "cloudsigma") : providers; + } +// +// @Test +// public void testSupportedComputeServiceProviders() { +// Iterable providers = ComputeServiceUtils.getSupportedProviders(); +// assert Iterables.contains(providers, "cloudsigma") : providers; +// } + +} diff --git a/sandbox/elasticstack/src/test/java/org/jclouds/cloudsigma/functions/KeyValuesDelimitedByBlankLinesToDriveInfoTest.java b/sandbox/elasticstack/src/test/java/org/jclouds/cloudsigma/functions/KeyValuesDelimitedByBlankLinesToDriveInfoTest.java new file mode 100644 index 0000000000..8af9256de7 --- /dev/null +++ b/sandbox/elasticstack/src/test/java/org/jclouds/cloudsigma/functions/KeyValuesDelimitedByBlankLinesToDriveInfoTest.java @@ -0,0 +1,50 @@ +/** + * + * 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.cloudsigma.functions; + +import static org.testng.Assert.assertEquals; + +import org.jclouds.http.HttpResponse; +import org.jclouds.io.Payloads; +import org.testng.annotations.Test; + +import com.google.inject.Guice; + +/** + * + * @author Adrian Cole + */ +@Test(groups = { "unit" }) +public class KeyValuesDelimitedByBlankLinesToDriveInfoTest { + + private static final KeyValuesDelimitedByBlankLinesToDriveInfo FN = Guice.createInjector().getInstance( + KeyValuesDelimitedByBlankLinesToDriveInfo.class); + + public void testNone() { + assertEquals(FN.apply(new HttpResponse(200, "", Payloads.newStringPayload(""))), null); + assertEquals(FN.apply(new HttpResponse(200, "", Payloads.newStringPayload("\n\n"))), null); + assertEquals(FN.apply(new HttpResponse(200, "", null)), null); + } + + public void testOne() { + assertEquals(FN.apply(new HttpResponse(200, "", Payloads.newInputStreamPayload(MapToDriveInfoTest.class + .getResourceAsStream("/cloudsigma/drive.txt")))), MapToDriveInfoTest.ONE); + } +} \ No newline at end of file diff --git a/sandbox/elasticstack/src/test/java/org/jclouds/cloudsigma/functions/ListOfKeyValuesDelimitedByBlankLinesToDriveInfoSetTest.java b/sandbox/elasticstack/src/test/java/org/jclouds/cloudsigma/functions/ListOfKeyValuesDelimitedByBlankLinesToDriveInfoSetTest.java new file mode 100644 index 0000000000..82b5631e98 --- /dev/null +++ b/sandbox/elasticstack/src/test/java/org/jclouds/cloudsigma/functions/ListOfKeyValuesDelimitedByBlankLinesToDriveInfoSetTest.java @@ -0,0 +1,52 @@ +/** + * + * 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.cloudsigma.functions; + +import static org.testng.Assert.assertEquals; + +import org.jclouds.cloudsigma.domain.DriveInfo; +import org.jclouds.http.HttpResponse; +import org.jclouds.io.Payloads; +import org.testng.annotations.Test; + +import com.google.common.collect.ImmutableSet; +import com.google.inject.Guice; + +/** + * + * @author Adrian Cole + */ +@Test(groups = { "unit" }) +public class ListOfKeyValuesDelimitedByBlankLinesToDriveInfoSetTest { + + private static final ListOfKeyValuesDelimitedByBlankLinesToDriveInfoSet FN = Guice.createInjector().getInstance( + ListOfKeyValuesDelimitedByBlankLinesToDriveInfoSet.class); + + public void testNone() { + assertEquals(FN.apply(new HttpResponse(200, "", Payloads.newStringPayload(""))), ImmutableSet. of()); + assertEquals(FN.apply(new HttpResponse(200, "", Payloads.newStringPayload("\n\n"))), ImmutableSet. of()); + assertEquals(FN.apply(new HttpResponse(200, "", null)), ImmutableSet. of()); + } + + public void testOne() { + assertEquals(FN.apply(new HttpResponse(200, "", Payloads.newInputStreamPayload(MapToDriveInfoTest.class + .getResourceAsStream("/cloudsigma/drive.txt")))), ImmutableSet. of(MapToDriveInfoTest.ONE)); + } +} \ No newline at end of file diff --git a/sandbox/elasticstack/src/test/java/org/jclouds/cloudsigma/functions/MapToDriveInfoTest.java b/sandbox/elasticstack/src/test/java/org/jclouds/cloudsigma/functions/MapToDriveInfoTest.java new file mode 100644 index 0000000000..bcb2419a6c --- /dev/null +++ b/sandbox/elasticstack/src/test/java/org/jclouds/cloudsigma/functions/MapToDriveInfoTest.java @@ -0,0 +1,97 @@ +/** + * + * 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.cloudsigma.functions; + +import static org.testng.Assert.assertEquals; + +import java.io.IOException; +import java.net.URI; +import java.util.Map; + +import org.jclouds.cloudsigma.domain.DriveInfo; +import org.jclouds.cloudsigma.domain.DriveType; +import org.jclouds.elasticstack.domain.ClaimType; +import org.jclouds.elasticstack.domain.DriveStatus; +import org.jclouds.elasticstack.functions.ListOfKeyValuesDelimitedByBlankLinesToListOfMaps; +import org.jclouds.util.Utils; +import org.testng.annotations.Test; + +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableSet; + +/** + * + * @author Adrian Cole + */ +@Test(groups = { "unit" }) +public class MapToDriveInfoTest { + public static DriveInfo ONE = new DriveInfo.Builder() + .status(DriveStatus.ACTIVE) + .tags(ImmutableSet.of("networking", "security", "gateway")) + .name("Ubuntu 10.10 Server Edition Linux 64bit Preinstalled System") + .bits(64) + .url(URI.create("http://www.ubuntu.com")) + .readBytes(4096l) + .user("58ca3c1f-7629-4771-9b71-863f40153ba4") + .encryptionCipher("aes-xts-plain") + .encryptionKey("ba6c2a4897072e9f25920ed73bd522e9c10d89f30a215158cccf8d0f654ac643") + .description("The Ubuntu Linux distribution brings the spirit of Ubuntu to the software world.") + .uuid("b8171d28-755a-4271-b891-7998871a160e") + .installNotes("first line\n\n") + .os("linux") + .writeBytes(8589938688l) + .claimType(ClaimType.SHARED) + .claimed( + ImmutableSet.of( + "00109617-2c6b-424b-9cfa-5b572c17bafe:guest:692cd1c7-a863-4a22-8170-fc6e6feb68af:ide:0:0", + "00031836-a624-4b22-bc7d-41ff8977087b:guest:a1414360-7c24-4730-8c97-180bf7775a71:ide:0:0", + "0002c6df-a1d2-4d1d-96f0-f95405a28183:guest:386f1cc7-affc-49c1-82a5-2f8e412170e4:ide:0:0", + "00031836-a624-4b22-bc7d-41ff8977087b:guest:17b076be-430d-4a76-9df3-b9896fec82a5:ide:0:0", + "000663ee-9fb6-4461-90f6-01327a4aff07:guest:f83b519f-feab-42cf-859c-f61495681ada:ide:0:1"))// + .driveType(ImmutableSet.of("installcd", "livecd"))// + .autoexpanding(false).readers(ImmutableSet.of("ffffffff-ffff-ffff-ffff-ffffffffffff"))// + .readRequests(1l)// + .free(true)// + .type(DriveType.DISK)// + .writeRequests(2097153l)// + .size(8589934592l)// + .userMetadata(ImmutableMap.of("foo", "bar", "baz", "raz")).build(); + + private static final MapToDriveInfo MAP_TO_DRIVE = new MapToDriveInfo( + new org.jclouds.elasticstack.functions.MapToDriveInfo()); + + public void testEmptyMapReturnsNull() { + assertEquals(MAP_TO_DRIVE.apply(ImmutableMap. of()), null); + } + + public void testBasics() { + DriveInfo expects = new DriveInfo.Builder().name("foo").size(100l).build(); + assertEquals(MAP_TO_DRIVE.apply(ImmutableMap.of("name", "foo", "size", "100")), expects); + } + + public void testComplete() throws IOException { + + Map input = new ListOfKeyValuesDelimitedByBlankLinesToListOfMaps().apply( + Utils.toStringAndClose(MapToDriveInfoTest.class.getResourceAsStream("/cloudsigma/drive.txt"))).get(0); + + assertEquals(MAP_TO_DRIVE.apply(input), ONE); + + } +} \ No newline at end of file diff --git a/sandbox/elasticstack/src/test/java/org/jclouds/elasticstack/CommonElasticStackClientLiveTest.java b/sandbox/elasticstack/src/test/java/org/jclouds/elasticstack/CommonElasticStackClientLiveTest.java new file mode 100644 index 0000000000..28c8240a66 --- /dev/null +++ b/sandbox/elasticstack/src/test/java/org/jclouds/elasticstack/CommonElasticStackClientLiveTest.java @@ -0,0 +1,176 @@ +/** + * + * 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.elasticstack; + +import static com.google.common.base.Preconditions.checkNotNull; +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertNotNull; + +import java.util.Properties; +import java.util.Set; + +import org.jclouds.Constants; +import org.jclouds.elasticstack.domain.ClaimType; +import org.jclouds.elasticstack.domain.CreateDriveRequest; +import org.jclouds.elasticstack.domain.DriveData; +import org.jclouds.elasticstack.domain.DriveInfo; +import org.jclouds.elasticstack.domain.DriveStatus; +import org.jclouds.logging.log4j.config.Log4JLoggingModule; +import org.jclouds.rest.RestContext; +import org.jclouds.rest.RestContextFactory; +import org.testng.annotations.AfterGroups; +import org.testng.annotations.BeforeGroups; +import org.testng.annotations.Test; + +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableSet; +import com.google.inject.Module; + +/** + * Tests behavior of {@code CommonElasticStackClient} + * + * @author Adrian Cole + */ +@Test(groups = "live", sequential = true) +public abstract class CommonElasticStackClientLiveTest { + + protected S client; + protected RestContext context; + + protected String provider = "elasticstack"; + protected String identity; + protected String credential; + protected String endpoint; + protected String apiversion; + + protected void setupCredentials() { + identity = checkNotNull(System.getProperty("test." + provider + ".identity"), "test." + provider + ".identity"); + credential = System.getProperty("test." + provider + ".credential"); + endpoint = System.getProperty("test." + provider + ".endpoint"); + apiversion = System.getProperty("test." + provider + ".apiversion"); + } + + protected Properties setupProperties() { + Properties overrides = new Properties(); + overrides.setProperty(Constants.PROPERTY_TRUST_ALL_CERTS, "true"); + overrides.setProperty(Constants.PROPERTY_RELAX_HOSTNAME, "true"); + overrides.setProperty(provider + ".identity", identity); + if (credential != null) + overrides.setProperty(provider + ".credential", credential); + if (endpoint != null) + overrides.setProperty(provider + ".endpoint", endpoint); + if (apiversion != null) + overrides.setProperty(provider + ".apiversion", apiversion); + return overrides; + } + + @BeforeGroups(groups = "live") + public void setupClient() { + setupCredentials(); + Properties overrides = setupProperties(); + context = new RestContextFactory().createContext(provider, ImmutableSet. of(new Log4JLoggingModule()), + overrides); + + client = context.getApi(); + } + + @AfterGroups(groups = "live") + void tearDown() { + if (context != null) + context.close(); + } + + @Test + public void testListDrives() throws Exception { + Set drives = client.listDrives(); + assertNotNull(drives); + } + + @Test + public void testListDriveInfo() throws Exception { + Set drives = client.listDriveInfo(); + assertNotNull(drives); + } + + @Test + public void testGetDrive() throws Exception { + for (String driveUUID : client.listDrives()) { + assert !"".equals(driveUUID); + assertNotNull(client.getDriveInfo(driveUUID)); + } + } + + protected String prefix = System.getProperty("user.name") + ".test"; + protected DriveInfo info; + + @Test + public void testCreate() throws Exception { + info = client.createDrive(new CreateDriveRequest.Builder().name(prefix).size(4 * 1024 * 1024l).build()); + checkCreatedDrive(); + + DriveInfo newInfo = client.getDriveInfo(info.getUuid()); + checkDriveMatchesGet(newInfo); + + } + + protected void checkDriveMatchesGet(DriveInfo newInfo) { + assertEquals(newInfo.getUuid(), info.getUuid()); + } + + protected void checkCreatedDrive() { + assertNotNull(info.getUuid()); + assertNotNull(info.getUser()); + assertEquals(info.getName(), prefix); + assertEquals(info.getSize(), 4 * 1024 * 1024l); + assertEquals(info.getStatus(), DriveStatus.ACTIVE); + // for some reason, these occasionally return as 4096,1 + // assertEquals(info.getReadBytes(), 0l); + // assertEquals(info.getWriteBytes(), 0l); + // assertEquals(info.getReadRequests(), 0l); + // assertEquals(info.getWriteRequests(), 0l); + assertEquals(info.getEncryptionCipher(), "aes-xts-plain"); + } + + @Test(dependsOnMethods = "testCreate") + public void testSetDriveData() throws Exception { + + DriveInfo info2 = client.setDriveData( + info.getUuid(), + new DriveData.Builder().claimType(ClaimType.SHARED).name("rediculous") + .readers(ImmutableSet.of("ffffffff-ffff-ffff-ffff-ffffffffffff")) + .tags(ImmutableSet.of("networking", "security", "gateway")) + .userMetadata(ImmutableMap.of("foo", "bar")).build()); + + assertNotNull(info2.getUuid(), info.getUuid()); + assertEquals(info2.getName(), "rediculous"); + assertEquals(info2.getClaimType(), ClaimType.SHARED); + assertEquals(info2.getReaders(), ImmutableSet.of("ffffffff-ffff-ffff-ffff-ffffffffffff")); + assertEquals(info2.getTags(), ImmutableSet.of("networking", "security", "gateway")); + assertEquals(info2.getUserMetadata(), ImmutableMap.of("foo", "bar")); + info = info2; + } + + @Test(dependsOnMethods = "testSetDriveData") + public void testDestroyDrive() throws Exception { + client.destroyDrive(info.getUuid()); + assertEquals(client.getDriveInfo(info.getUuid()), null); + } + +} diff --git a/sandbox/elasticstack/src/test/java/org/jclouds/elasticstack/ElasticStackAsyncClientTest.java b/sandbox/elasticstack/src/test/java/org/jclouds/elasticstack/ElasticStackAsyncClientTest.java new file mode 100644 index 0000000000..0cd9ebf7bf --- /dev/null +++ b/sandbox/elasticstack/src/test/java/org/jclouds/elasticstack/ElasticStackAsyncClientTest.java @@ -0,0 +1,288 @@ +/** + * + * 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.elasticstack; + +import static org.testng.Assert.assertEquals; + +import java.io.IOException; +import java.lang.reflect.Method; +import java.util.Properties; + +import javax.ws.rs.core.MediaType; + +import org.jclouds.elasticstack.domain.CreateDriveRequest; +import org.jclouds.elasticstack.domain.DriveData; +import org.jclouds.elasticstack.domain.ImageConversionType; +import org.jclouds.elasticstack.functions.KeyValuesDelimitedByBlankLinesToDriveInfo; +import org.jclouds.elasticstack.functions.ListOfKeyValuesDelimitedByBlankLinesToDriveInfoSet; +import org.jclouds.elasticstack.functions.ReturnPayload; +import org.jclouds.elasticstack.functions.SplitNewlines; +import org.jclouds.elasticstack.options.ReadDriveOptions; +import org.jclouds.http.HttpRequest; +import org.jclouds.http.filters.BasicAuthentication; +import org.jclouds.http.functions.ReleasePayloadAndReturn; +import org.jclouds.io.Payload; +import org.jclouds.io.Payloads; +import org.jclouds.rest.RestClientTest; +import org.jclouds.rest.RestContextFactory; +import org.jclouds.rest.RestContextSpec; +import org.jclouds.rest.functions.ReturnNullOnNotFoundOr404; +import org.jclouds.rest.functions.ReturnVoidOnNotFoundOr404; +import org.jclouds.rest.internal.GeneratedHttpRequest; +import org.jclouds.rest.internal.RestAnnotationProcessor; +import org.testng.annotations.Test; + +import com.google.common.collect.ImmutableList; +import com.google.common.collect.Iterables; +import com.google.inject.TypeLiteral; + +/** + * Tests annotation parsing of {@code ElasticStackAsyncClient} + * + * @author Adrian Cole + */ +@Test(groups = "unit", testName = "elasticstack.ElasticStackAsyncClientTest") +public class ElasticStackAsyncClientTest extends RestClientTest { + + public void testListDrives() throws SecurityException, NoSuchMethodException, IOException { + Method method = ElasticStackAsyncClient.class.getMethod("listDrives"); + GeneratedHttpRequest httpRequest = processor.createRequest(method); + + assertRequestLineEquals(httpRequest, "GET https://api.elasticstack.com/drives/list HTTP/1.1"); + assertNonPayloadHeadersEqual(httpRequest, "Accept: text/plain\n"); + assertPayloadEquals(httpRequest, null, null, false); + + // now make sure request filters apply by replaying + Iterables.getOnlyElement(httpRequest.getFilters()).filter(httpRequest); + Iterables.getOnlyElement(httpRequest.getFilters()).filter(httpRequest); + + assertRequestLineEquals(httpRequest, "GET https://api.elasticstack.com/drives/list HTTP/1.1"); + // for example, using basic authentication, we should get "only one" + // header + assertNonPayloadHeadersEqual(httpRequest, + "Accept: text/plain\nAuthorization: Basic Zm9vOmJhcg==\n"); + assertPayloadEquals(httpRequest, null, null, false); + + // TODO: insert expected response class, which probably extends ParseJson + assertResponseParserClassEquals(method, httpRequest, SplitNewlines.class); + assertSaxResponseParserClassEquals(method, null); + assertExceptionParserClassEquals(method, null); + + checkFilters(httpRequest); + + } + + public void testListDriveInfo() throws SecurityException, NoSuchMethodException, IOException { + Method method = ElasticStackAsyncClient.class.getMethod("listDriveInfo"); + GeneratedHttpRequest httpRequest = processor.createRequest(method); + + assertRequestLineEquals(httpRequest, "GET https://api.elasticstack.com/drives/info HTTP/1.1"); + assertNonPayloadHeadersEqual(httpRequest, "Accept: text/plain\n"); + assertPayloadEquals(httpRequest, null, null, false); + + assertResponseParserClassEquals(method, httpRequest, ListOfKeyValuesDelimitedByBlankLinesToDriveInfoSet.class); + assertSaxResponseParserClassEquals(method, null); + assertExceptionParserClassEquals(method, null); + + checkFilters(httpRequest); + } + + public void testGetDriveInfo() throws SecurityException, NoSuchMethodException, IOException { + Method method = ElasticStackAsyncClient.class.getMethod("getDriveInfo", String.class); + GeneratedHttpRequest httpRequest = processor.createRequest(method, "uuid"); + + assertRequestLineEquals(httpRequest, "GET https://api.elasticstack.com/drives/uuid/info HTTP/1.1"); + assertNonPayloadHeadersEqual(httpRequest, "Accept: text/plain\n"); + assertPayloadEquals(httpRequest, null, null, false); + + assertResponseParserClassEquals(method, httpRequest, KeyValuesDelimitedByBlankLinesToDriveInfo.class); + assertSaxResponseParserClassEquals(method, null); + assertExceptionParserClassEquals(method, ReturnNullOnNotFoundOr404.class); + + checkFilters(httpRequest); + + } + + public void testCreateDrive() throws SecurityException, NoSuchMethodException, IOException { + Method method = ElasticStackAsyncClient.class.getMethod("createDrive", CreateDriveRequest.class); + GeneratedHttpRequest httpRequest = processor.createRequest(method, + new CreateDriveRequest.Builder().name("foo").size(10000l).build()); + + assertRequestLineEquals(httpRequest, "POST https://api.elasticstack.com/drives/create HTTP/1.1"); + assertNonPayloadHeadersEqual(httpRequest, "Accept: text/plain\n"); + assertPayloadEquals(httpRequest, "name foo\nsize 10000", "text/plain", false); + + assertResponseParserClassEquals(method, httpRequest, KeyValuesDelimitedByBlankLinesToDriveInfo.class); + assertSaxResponseParserClassEquals(method, null); + assertExceptionParserClassEquals(method, ReturnNullOnNotFoundOr404.class); + + checkFilters(httpRequest); + + } + + public void testSetDriveData() throws SecurityException, NoSuchMethodException, IOException { + Method method = ElasticStackAsyncClient.class.getMethod("setDriveData", String.class, DriveData.class); + GeneratedHttpRequest httpRequest = processor.createRequest(method, "100", + new DriveData.Builder().name("foo").size(10000l).tags(ImmutableList.of("production", "candy")).build()); + + assertRequestLineEquals(httpRequest, "POST https://api.elasticstack.com/drives/100/set HTTP/1.1"); + assertNonPayloadHeadersEqual(httpRequest, "Accept: text/plain\n"); + assertPayloadEquals(httpRequest, "name foo\nsize 10000\ntags production candy", "text/plain", false); + + assertResponseParserClassEquals(method, httpRequest, KeyValuesDelimitedByBlankLinesToDriveInfo.class); + assertSaxResponseParserClassEquals(method, null); + assertExceptionParserClassEquals(method, ReturnNullOnNotFoundOr404.class); + + checkFilters(httpRequest); + + } + + public void testImageDrive() throws SecurityException, NoSuchMethodException, IOException { + Method method = ElasticStackAsyncClient.class.getMethod("imageDrive", String.class, String.class); + GeneratedHttpRequest httpRequest = processor.createRequest(method, "100", "200"); + + assertRequestLineEquals(httpRequest, "POST https://api.elasticstack.com/drives/200/image/100 HTTP/1.1"); + assertNonPayloadHeadersEqual(httpRequest, "Accept: text/plain\n"); + assertPayloadEquals(httpRequest, null, null, false); + + assertResponseParserClassEquals(method, httpRequest, ReleasePayloadAndReturn.class); + assertSaxResponseParserClassEquals(method, null); + assertExceptionParserClassEquals(method, ReturnVoidOnNotFoundOr404.class); + + checkFilters(httpRequest); + + } + + public void testImageDriveWithConversion() throws SecurityException, NoSuchMethodException, IOException { + Method method = ElasticStackAsyncClient.class.getMethod("imageDrive", String.class, String.class, + ImageConversionType.class); + GeneratedHttpRequest httpRequest = processor.createRequest(method, "100", "200", + ImageConversionType.GUNZIP); + + assertRequestLineEquals(httpRequest, "POST https://api.elasticstack.com/drives/200/image/100/gunzip HTTP/1.1"); + assertNonPayloadHeadersEqual(httpRequest, "Accept: text/plain\n"); + assertPayloadEquals(httpRequest, null, null, false); + + assertResponseParserClassEquals(method, httpRequest, ReleasePayloadAndReturn.class); + assertSaxResponseParserClassEquals(method, null); + assertExceptionParserClassEquals(method, ReturnVoidOnNotFoundOr404.class); + + checkFilters(httpRequest); + + } + + public void testDestroyDrive() throws SecurityException, NoSuchMethodException, IOException { + Method method = ElasticStackAsyncClient.class.getMethod("destroyDrive", String.class); + GeneratedHttpRequest httpRequest = processor.createRequest(method, "uuid"); + + assertRequestLineEquals(httpRequest, "POST https://api.elasticstack.com/drives/uuid/destroy HTTP/1.1"); + assertNonPayloadHeadersEqual(httpRequest, "Accept: text/plain\n"); + assertPayloadEquals(httpRequest, null, null, false); + + assertResponseParserClassEquals(method, httpRequest, ReleasePayloadAndReturn.class); + assertSaxResponseParserClassEquals(method, null); + assertExceptionParserClassEquals(method, ReturnVoidOnNotFoundOr404.class); + + checkFilters(httpRequest); + + } + + public void testReadDrive() throws SecurityException, NoSuchMethodException, IOException { + Method method = ElasticStackAsyncClient.class.getMethod("readDrive", String.class); + GeneratedHttpRequest httpRequest = processor.createRequest(method, "100"); + + assertRequestLineEquals(httpRequest, "GET https://api.elasticstack.com/drives/100/read HTTP/1.1"); + assertNonPayloadHeadersEqual(httpRequest, "Accept: application/octet-stream\n"); + assertPayloadEquals(httpRequest, null, null, false); + + assertResponseParserClassEquals(method, httpRequest, ReturnPayload.class); + assertSaxResponseParserClassEquals(method, null); + assertExceptionParserClassEquals(method, ReturnNullOnNotFoundOr404.class); + + checkFilters(httpRequest); + } + + public void testReadDriveOptions() throws SecurityException, NoSuchMethodException, IOException { + Method method = ElasticStackAsyncClient.class.getMethod("readDrive", String.class, ReadDriveOptions.class); + GeneratedHttpRequest httpRequest = processor.createRequest(method, "100", + new ReadDriveOptions().offset(1024).size(2048)); + + assertRequestLineEquals(httpRequest, "POST https://api.elasticstack.com/drives/100/read/1024/2048 HTTP/1.1"); + assertNonPayloadHeadersEqual(httpRequest, "Accept: application/octet-stream\n"); + assertPayloadEquals(httpRequest, null, null, false); + + assertResponseParserClassEquals(method, httpRequest, ReturnPayload.class); + assertSaxResponseParserClassEquals(method, null); + assertExceptionParserClassEquals(method, ReturnNullOnNotFoundOr404.class); + + checkFilters(httpRequest); + } + + public void testWriteDrive() throws SecurityException, NoSuchMethodException, IOException { + Method method = ElasticStackAsyncClient.class.getMethod("writeDrive", String.class, Payload.class); + GeneratedHttpRequest httpRequest = processor.createRequest(method, "100", + Payloads.newStringPayload("foo")); + + assertRequestLineEquals(httpRequest, "POST https://api.elasticstack.com/drives/100/write HTTP/1.1"); + assertNonPayloadHeadersEqual(httpRequest, "Accept: text/plain\n"); + assertPayloadEquals(httpRequest, "", MediaType.APPLICATION_OCTET_STREAM, false); + + assertResponseParserClassEquals(method, httpRequest, ReleasePayloadAndReturn.class); + assertSaxResponseParserClassEquals(method, null); + assertExceptionParserClassEquals(method, ReturnVoidOnNotFoundOr404.class); + + checkFilters(httpRequest); + } + + public void testWriteDriveOffset() throws SecurityException, NoSuchMethodException, IOException { + Method method = ElasticStackAsyncClient.class.getMethod("writeDrive", String.class, Payload.class, long.class); + GeneratedHttpRequest httpRequest = processor.createRequest(method, "100", + Payloads.newStringPayload("foo"), 2048); + + assertRequestLineEquals(httpRequest, "POST https://api.elasticstack.com/drives/100/write/2048 HTTP/1.1"); + assertNonPayloadHeadersEqual(httpRequest, "Accept: text/plain\n"); + assertPayloadEquals(httpRequest, "", MediaType.APPLICATION_OCTET_STREAM, false); + + assertResponseParserClassEquals(method, httpRequest, ReleasePayloadAndReturn.class); + assertSaxResponseParserClassEquals(method, null); + assertExceptionParserClassEquals(method, ReturnVoidOnNotFoundOr404.class); + + checkFilters(httpRequest); + } + + @Override + protected void checkFilters(HttpRequest request) { + assertEquals(request.getFilters().size(), 1); + assertEquals(request.getFilters().get(0).getClass(), BasicAuthentication.class); + } + + @Override + protected TypeLiteral> createTypeLiteral() { + return new TypeLiteral>() { + }; + } + + @Override + public RestContextSpec createContextSpec() { + Properties props = new Properties(); + props.setProperty("elasticstack.endpoint", "https://api.elasticstack.com"); + return new RestContextFactory().createContextSpec("elasticstack", "foo", "bar", props); + } +} diff --git a/sandbox/elasticstack/src/test/java/org/jclouds/elasticstack/ElasticStackClientLiveTest.java b/sandbox/elasticstack/src/test/java/org/jclouds/elasticstack/ElasticStackClientLiveTest.java new file mode 100644 index 0000000000..f669ad7716 --- /dev/null +++ b/sandbox/elasticstack/src/test/java/org/jclouds/elasticstack/ElasticStackClientLiveTest.java @@ -0,0 +1,86 @@ +/** + * + * 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.elasticstack; + +import static org.testng.Assert.assertEquals; + +import java.io.IOException; + +import org.jclouds.elasticstack.domain.CreateDriveRequest; +import org.jclouds.elasticstack.domain.DriveInfo; +import org.jclouds.elasticstack.options.ReadDriveOptions; +import org.jclouds.io.Payloads; +import org.jclouds.util.Utils; +import org.testng.annotations.Test; + +/** + * Tests behavior of {@code ElasticStackClient} + * + * @author Adrian Cole + */ +@Test(groups = "live", testName = "elasticstack.ElasticStackClientLiveTest") +public class ElasticStackClientLiveTest extends + CommonElasticStackClientLiveTest { + private DriveInfo info2; + + @Override + public void testGetDrive() throws Exception { + super.testGetDrive(); + } + + @Override + public void testCreate() throws Exception { + super.testCreate(); + } + + @Override + public void testSetDriveData() throws Exception { + super.testSetDriveData(); + } + + @Override + public void testDestroyDrive() throws Exception { + super.testDestroyDrive(); + } + + @Test(dependsOnMethods = "testCreate") + public void testWeCanReadAndWriteToDrive() throws IOException { + client.writeDrive(info.getUuid(), Payloads.newStringPayload("foo")); + assertEquals(Utils.toStringAndClose(client.readDrive(info.getUuid(), ReadDriveOptions.Builder.offset(0).size(3)) + .getInput()), "foo"); + } + + @Test(dependsOnMethods = "testWeCanReadAndWriteToDrive") + public void testWeCopyADriveContentsViaGzip() throws IOException { + + try { + info2 = client.createDrive(new CreateDriveRequest.Builder().name(prefix + "2").size(4 * 1024 * 1024l).build()); + client.imageDrive(info.getUuid(), info2.getUuid()); + + // TODO block until complete + System.err.println("state " + client.getDriveInfo(info2.getUuid())); + assertEquals(Utils.toStringAndClose(client.readDrive(info2.getUuid()).getInput()), "foo"); + } finally { + client.destroyDrive(info2.getUuid()); + } + + } + +} diff --git a/sandbox/elasticstack/src/test/java/org/jclouds/elasticstack/ProvidersInPropertiesTest.java b/sandbox/elasticstack/src/test/java/org/jclouds/elasticstack/ProvidersInPropertiesTest.java new file mode 100644 index 0000000000..1ecf6df951 --- /dev/null +++ b/sandbox/elasticstack/src/test/java/org/jclouds/elasticstack/ProvidersInPropertiesTest.java @@ -0,0 +1,47 @@ +/** + * + * 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.elasticstack; + +import org.jclouds.util.Utils; +import org.testng.annotations.Test; + +import com.google.common.collect.Iterables; + +/** + * + * @author Adrian Cole + * + */ +@Test(groups = "unit") +public class ProvidersInPropertiesTest { + + @Test + public void testSupportedProviders() { + Iterable providers = Utils.getSupportedProviders(); + assert Iterables.contains(providers, "elasticstack") : providers; + } +// +// @Test +// public void testSupportedComputeServiceProviders() { +// Iterable providers = ComputeServiceUtils.getSupportedProviders(); +// assert Iterables.contains(providers, "cloudsigma") : providers; +// } + +} diff --git a/sandbox/elasticstack/src/test/java/org/jclouds/elasticstack/binders/BindCreateDriveRequestToPlainTextStringTest.java b/sandbox/elasticstack/src/test/java/org/jclouds/elasticstack/binders/BindCreateDriveRequestToPlainTextStringTest.java new file mode 100644 index 0000000000..3cc825f713 --- /dev/null +++ b/sandbox/elasticstack/src/test/java/org/jclouds/elasticstack/binders/BindCreateDriveRequestToPlainTextStringTest.java @@ -0,0 +1,91 @@ +/** + * + * 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.elasticstack.binders; + +import static org.testng.Assert.assertEquals; + +import java.io.IOException; +import java.net.URI; +import java.util.Map; + +import javax.ws.rs.core.MediaType; + +import org.jclouds.elasticstack.domain.ClaimType; +import org.jclouds.elasticstack.domain.CreateDriveRequest; +import org.jclouds.elasticstack.domain.DriveData; +import org.jclouds.elasticstack.functions.CreateDriveRequestToMap; +import org.jclouds.elasticstack.functions.DriveDataToMap; +import org.jclouds.http.HttpRequest; +import org.jclouds.util.Utils; +import org.testng.annotations.Test; + +import com.google.common.base.Function; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableSet; +import com.google.inject.AbstractModule; +import com.google.inject.Guice; +import com.google.inject.TypeLiteral; + +/** + * + * @author Adrian Cole + */ +@Test(groups = { "unit" }) +public class BindCreateDriveRequestToPlainTextStringTest { + + private static final BindCreateDriveRequestToPlainTextString FN = Guice.createInjector(new AbstractModule() { + + @Override + protected void configure() { + bind(new TypeLiteral>>() { + }).to(CreateDriveRequestToMap.class); + bind(new TypeLiteral>>() { + }).to(DriveDataToMap.class); + } + + }).getInstance(BindCreateDriveRequestToPlainTextString.class); + + public void testSimple() { + HttpRequest request = new HttpRequest("POST", URI.create("https://host/drives/create")); + FN.bindToRequest(request, new CreateDriveRequest.Builder().name("foo").size(100l).build()); + assertEquals(request.getPayload().getContentMetadata().getContentType(), MediaType.TEXT_PLAIN); + assertEquals(request.getPayload().getRawContent(), "name foo\nsize 100"); + } + + public void testComplete() throws IOException { + CreateDriveRequest input = new CreateDriveRequest.Builder() + .name("Ubuntu 10.10 Server Edition Linux 64bit Preinstalled System") + // + .size(8589934592l)// + .claimType(ClaimType.SHARED)// + .readers(ImmutableSet.of("ffffffff-ffff-ffff-ffff-ffffffffffff"))// + .tags(ImmutableSet.of("tag1", "tag2")).userMetadata(ImmutableMap.of("foo", "bar", "baz", "raz"))// + .encryptionCipher("aes-xts-plain").avoid(ImmutableSet.of("avoid1")).build(); + + HttpRequest request = new HttpRequest("POST", URI.create("https://host/drives/create")); + FN.bindToRequest(request, input); + assertEquals(request.getPayload().getContentMetadata().getContentType(), MediaType.TEXT_PLAIN); + assertEquals(request.getPayload().getRawContent(), + Utils.toStringAndClose(BindCreateDriveRequestToPlainTextStringTest.class + .getResourceAsStream("/create_drive.txt"))); + + } + +} \ No newline at end of file diff --git a/sandbox/elasticstack/src/test/java/org/jclouds/elasticstack/binders/BindDriveDataToPlainTextStringTest.java b/sandbox/elasticstack/src/test/java/org/jclouds/elasticstack/binders/BindDriveDataToPlainTextStringTest.java new file mode 100644 index 0000000000..0857dae2c2 --- /dev/null +++ b/sandbox/elasticstack/src/test/java/org/jclouds/elasticstack/binders/BindDriveDataToPlainTextStringTest.java @@ -0,0 +1,88 @@ +/** + * + * 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.elasticstack.binders; + +import static org.testng.Assert.assertEquals; + +import java.io.IOException; +import java.net.URI; +import java.util.Map; + +import javax.ws.rs.core.MediaType; + +import org.jclouds.elasticstack.domain.ClaimType; +import org.jclouds.elasticstack.domain.CreateDriveRequest; +import org.jclouds.elasticstack.domain.DriveData; +import org.jclouds.elasticstack.functions.CreateDriveRequestToMap; +import org.jclouds.elasticstack.functions.DriveDataToMap; +import org.jclouds.http.HttpRequest; +import org.jclouds.util.Utils; +import org.testng.annotations.Test; + +import com.google.common.base.Function; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableSet; +import com.google.inject.AbstractModule; +import com.google.inject.Guice; +import com.google.inject.TypeLiteral; + +/** + * + * @author Adrian Cole + */ +@Test(groups = { "unit" }) +public class BindDriveDataToPlainTextStringTest { + + private static final BindDriveDataToPlainTextString FN = Guice.createInjector(new AbstractModule() { + + @Override + protected void configure() { + bind(new TypeLiteral>>() { + }).to(CreateDriveRequestToMap.class); + bind(new TypeLiteral>>() { + }).to(DriveDataToMap.class); + } + + }).getInstance(BindDriveDataToPlainTextString.class); + + public void testSimple() { + HttpRequest request = new HttpRequest("POST", URI.create("https://host/drives/create")); + FN.bindToRequest(request, new DriveData.Builder().name("foo").size(100l).build()); + assertEquals(request.getPayload().getContentMetadata().getContentType(), MediaType.TEXT_PLAIN); + assertEquals(request.getPayload().getRawContent(), "name foo\nsize 100"); + } + + public void testComplete() throws IOException { + DriveData input = new DriveData.Builder().name("Ubuntu 10.10 Server Edition Linux 64bit Preinstalled System") + // + .size(8589934592l)// + .claimType(ClaimType.SHARED)// + .readers(ImmutableSet.of("ffffffff-ffff-ffff-ffff-ffffffffffff"))// + .tags(ImmutableSet.of("tag1", "tag2")).userMetadata(ImmutableMap.of("foo", "bar", "baz", "raz"))// + .build(); + + HttpRequest request = new HttpRequest("POST", URI.create("https://host/drives/create")); + FN.bindToRequest(request, input); + assertEquals(request.getPayload().getContentMetadata().getContentType(), MediaType.TEXT_PLAIN); + assertEquals(request.getPayload().getRawContent(), + Utils.toStringAndClose(BindDriveDataToPlainTextStringTest.class.getResourceAsStream("/drive_data.txt"))); + + } +} \ No newline at end of file diff --git a/sandbox/elasticstack/src/test/java/org/jclouds/elasticstack/binders/BindReadDriveOptionsToPathTest.java b/sandbox/elasticstack/src/test/java/org/jclouds/elasticstack/binders/BindReadDriveOptionsToPathTest.java new file mode 100644 index 0000000000..d7d9701b6c --- /dev/null +++ b/sandbox/elasticstack/src/test/java/org/jclouds/elasticstack/binders/BindReadDriveOptionsToPathTest.java @@ -0,0 +1,51 @@ +/** + * + * 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.elasticstack.binders; + +import static org.testng.Assert.assertEquals; + +import java.net.URI; + +import org.jclouds.elasticstack.options.ReadDriveOptions; +import org.jclouds.http.HttpRequest; +import org.jclouds.logging.config.NullLoggingModule; +import org.jclouds.rest.BaseRestClientTest.MockModule; +import org.jclouds.rest.config.RestModule; +import org.testng.annotations.Test; + +import com.google.inject.Guice; + +/** + * + * @author Adrian Cole + */ +@Test(groups = { "unit" }) +public class BindReadDriveOptionsToPathTest { + + private static final BindReadDriveOptionsToPath FN = Guice.createInjector(new RestModule(), new MockModule(), + new NullLoggingModule()).getInstance(BindReadDriveOptionsToPath.class); + + public void testSimple() { + HttpRequest request = new HttpRequest("POST", URI.create("https://drives/read")); + FN.bindToRequest(request, new ReadDriveOptions().offset(1024l).size(2048l)); + assertEquals(request.getEndpoint().getPath(), "/read/1024/2048"); + } + +} \ No newline at end of file diff --git a/sandbox/elasticstack/src/test/java/org/jclouds/elasticstack/functions/BaseDriveToMapTest.java b/sandbox/elasticstack/src/test/java/org/jclouds/elasticstack/functions/BaseDriveToMapTest.java new file mode 100644 index 0000000000..0bfd3de70c --- /dev/null +++ b/sandbox/elasticstack/src/test/java/org/jclouds/elasticstack/functions/BaseDriveToMapTest.java @@ -0,0 +1,65 @@ +/** + * + * 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.elasticstack.functions; + +import static org.testng.Assert.assertEquals; + +import java.io.IOException; + +import org.jclouds.elasticstack.domain.ClaimType; +import org.jclouds.elasticstack.domain.internal.BaseDrive; +import org.testng.annotations.Test; + +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableSet; + +/** + * + * @author Adrian Cole + */ +@Test(groups = { "unit" }) +public class BaseDriveToMapTest { + + private static final BaseDriveToMap BASEDRIVE_TO_MAP = new BaseDriveToMap(); + + public void testBasics() { + assertEquals(BASEDRIVE_TO_MAP.apply(new BaseDrive.Builder().name("foo").size(100l).build()), + ImmutableMap.of("name", "foo", "size", "100")); + } + + public void testComplete() throws IOException { + BaseDrive one = new BaseDrive.Builder().name("Ubuntu 10.10 Server Edition Linux 64bit Preinstalled System") + // + .size(8589934592l)// + .claimType(ClaimType.SHARED)// + .readers(ImmutableSet.of("ffffffff-ffff-ffff-ffff-ffffffffffff"))// + .tags(ImmutableSet.of("tag1", "tag2")).userMetadata(ImmutableMap.of("foo", "bar", "baz", "raz"))// + .build(); + assertEquals( + BASEDRIVE_TO_MAP.apply(one), + ImmutableMap.builder().put("name", "Ubuntu 10.10 Server Edition Linux 64bit Preinstalled System") + .put("size", "8589934592").put("claim:type", "shared") + .put("readers", "ffffffff-ffff-ffff-ffff-ffffffffffff").put("tags", "tag1 tag2") + .put("user:foo", "bar").put("user:baz", "raz").build() + + ); + + } +} \ No newline at end of file diff --git a/sandbox/elasticstack/src/test/java/org/jclouds/elasticstack/functions/CreateDriveRequestToMapTest.java b/sandbox/elasticstack/src/test/java/org/jclouds/elasticstack/functions/CreateDriveRequestToMapTest.java new file mode 100644 index 0000000000..1c40cb90e5 --- /dev/null +++ b/sandbox/elasticstack/src/test/java/org/jclouds/elasticstack/functions/CreateDriveRequestToMapTest.java @@ -0,0 +1,69 @@ +/** + * + * 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.elasticstack.functions; + +import static org.testng.Assert.assertEquals; + +import java.io.IOException; + +import org.jclouds.elasticstack.domain.ClaimType; +import org.jclouds.elasticstack.domain.CreateDriveRequest; +import org.testng.annotations.Test; + +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableSet; +import com.google.inject.Guice; + +/** + * + * @author Adrian Cole + */ +@Test(groups = { "unit" }) +public class CreateDriveRequestToMapTest { + + private static final CreateDriveRequestToMap BASEDRIVE_TO_MAP = Guice.createInjector().getInstance( + CreateDriveRequestToMap.class); + + public void testBasics() { + assertEquals(BASEDRIVE_TO_MAP.apply(new CreateDriveRequest.Builder().name("foo").size(100l).build()), + ImmutableMap.of("name", "foo", "size", "100")); + } + + public void testComplete() throws IOException { + CreateDriveRequest one = new CreateDriveRequest.Builder() + .name("Ubuntu 10.10 Server Edition Linux 64bit Preinstalled System") + // + .size(8589934592l)// + .claimType(ClaimType.SHARED)// + .readers(ImmutableSet.of("ffffffff-ffff-ffff-ffff-ffffffffffff"))// + .tags(ImmutableSet.of("tag1", "tag2")).userMetadata(ImmutableMap.of("foo", "bar", "baz", "raz"))// + .encryptionCipher("aes-xts-plain").avoid(ImmutableSet.of("avoid1")).build(); + assertEquals( + BASEDRIVE_TO_MAP.apply(one), + ImmutableMap.builder().put("name", "Ubuntu 10.10 Server Edition Linux 64bit Preinstalled System") + .put("size", "8589934592").put("claim:type", "shared") + .put("readers", "ffffffff-ffff-ffff-ffff-ffffffffffff").put("tags", "tag1 tag2") + .put("user:foo", "bar").put("user:baz", "raz").put("encryption:cipher", "aes-xts-plain") + .put("avoid", "avoid1").build() + + ); + + } +} \ No newline at end of file diff --git a/sandbox/elasticstack/src/test/java/org/jclouds/elasticstack/functions/DriveDataToMapTest.java b/sandbox/elasticstack/src/test/java/org/jclouds/elasticstack/functions/DriveDataToMapTest.java new file mode 100644 index 0000000000..041c2dd6d4 --- /dev/null +++ b/sandbox/elasticstack/src/test/java/org/jclouds/elasticstack/functions/DriveDataToMapTest.java @@ -0,0 +1,66 @@ +/** + * + * 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.elasticstack.functions; + +import static org.testng.Assert.assertEquals; + +import java.io.IOException; + +import org.jclouds.elasticstack.domain.ClaimType; +import org.jclouds.elasticstack.domain.DriveData; +import org.testng.annotations.Test; + +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableSet; +import com.google.inject.Guice; + +/** + * + * @author Adrian Cole + */ +@Test(groups = { "unit" }) +public class DriveDataToMapTest { + + private static final DriveDataToMap BASEDRIVE_TO_MAP = Guice.createInjector().getInstance(DriveDataToMap.class); + + public void testBasics() { + assertEquals(BASEDRIVE_TO_MAP.apply(new DriveData.Builder().name("foo").size(100l).build()), + ImmutableMap.of("name", "foo", "size", "100")); + } + + public void testComplete() throws IOException { + DriveData one = new DriveData.Builder().name("Ubuntu 10.10 Server Edition Linux 64bit Preinstalled System") + // + .size(8589934592l)// + .claimType(ClaimType.SHARED)// + .readers(ImmutableSet.of("ffffffff-ffff-ffff-ffff-ffffffffffff"))// + .tags(ImmutableSet.of("tag1", "tag2")).userMetadata(ImmutableMap.of("foo", "bar", "baz", "raz"))// + .build(); + assertEquals( + BASEDRIVE_TO_MAP.apply(one), + ImmutableMap.builder().put("name", "Ubuntu 10.10 Server Edition Linux 64bit Preinstalled System") + .put("size", "8589934592").put("claim:type", "shared") + .put("readers", "ffffffff-ffff-ffff-ffff-ffffffffffff").put("tags", "tag1 tag2") + .put("user:foo", "bar").put("user:baz", "raz").build() + + ); + + } +} \ No newline at end of file diff --git a/sandbox/elasticstack/src/test/java/org/jclouds/elasticstack/functions/KeyValuesDelimitedByBlankLinesToDriveInfoTest.java b/sandbox/elasticstack/src/test/java/org/jclouds/elasticstack/functions/KeyValuesDelimitedByBlankLinesToDriveInfoTest.java new file mode 100644 index 0000000000..2ad2cf5771 --- /dev/null +++ b/sandbox/elasticstack/src/test/java/org/jclouds/elasticstack/functions/KeyValuesDelimitedByBlankLinesToDriveInfoTest.java @@ -0,0 +1,50 @@ +/** + * + * 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.elasticstack.functions; + +import static org.testng.Assert.assertEquals; + +import org.jclouds.http.HttpResponse; +import org.jclouds.io.Payloads; +import org.testng.annotations.Test; + +import com.google.inject.Guice; + +/** + * + * @author Adrian Cole + */ +@Test(groups = { "unit" }) +public class KeyValuesDelimitedByBlankLinesToDriveInfoTest { + + private static final KeyValuesDelimitedByBlankLinesToDriveInfo FN = Guice.createInjector().getInstance( + KeyValuesDelimitedByBlankLinesToDriveInfo.class); + + public void testNone() { + assertEquals(FN.apply(new HttpResponse(200, "", Payloads.newStringPayload(""))), null); + assertEquals(FN.apply(new HttpResponse(200, "", Payloads.newStringPayload("\n\n"))), null); + assertEquals(FN.apply(new HttpResponse(200, "", null)), null); + } + + public void testOne() { + assertEquals(FN.apply(new HttpResponse(200, "", Payloads.newInputStreamPayload(MapToDriveInfoTest.class + .getResourceAsStream("/drive.txt")))), MapToDriveInfoTest.ONE); + } +} \ No newline at end of file diff --git a/sandbox/elasticstack/src/test/java/org/jclouds/elasticstack/functions/ListOfKeyValuesDelimitedByBlankLinesToDriveInfoSetTest.java b/sandbox/elasticstack/src/test/java/org/jclouds/elasticstack/functions/ListOfKeyValuesDelimitedByBlankLinesToDriveInfoSetTest.java new file mode 100644 index 0000000000..dd4b782953 --- /dev/null +++ b/sandbox/elasticstack/src/test/java/org/jclouds/elasticstack/functions/ListOfKeyValuesDelimitedByBlankLinesToDriveInfoSetTest.java @@ -0,0 +1,52 @@ +/** + * + * 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.elasticstack.functions; + +import static org.testng.Assert.assertEquals; + +import org.jclouds.elasticstack.domain.DriveInfo; +import org.jclouds.http.HttpResponse; +import org.jclouds.io.Payloads; +import org.testng.annotations.Test; + +import com.google.common.collect.ImmutableSet; +import com.google.inject.Guice; + +/** + * + * @author Adrian Cole + */ +@Test(groups = { "unit" }) +public class ListOfKeyValuesDelimitedByBlankLinesToDriveInfoSetTest { + + private static final ListOfKeyValuesDelimitedByBlankLinesToDriveInfoSet FN = Guice.createInjector().getInstance( + ListOfKeyValuesDelimitedByBlankLinesToDriveInfoSet.class); + + public void testNone() { + assertEquals(FN.apply(new HttpResponse(200, "", Payloads.newStringPayload(""))), ImmutableSet. of()); + assertEquals(FN.apply(new HttpResponse(200, "", Payloads.newStringPayload("\n\n"))), ImmutableSet. of()); + assertEquals(FN.apply(new HttpResponse(200, "", null)), ImmutableSet. of()); + } + + public void testOne() { + assertEquals(FN.apply(new HttpResponse(200, "", Payloads.newInputStreamPayload(MapToDriveInfoTest.class + .getResourceAsStream("/drive.txt")))), ImmutableSet. of(MapToDriveInfoTest.ONE)); + } +} \ No newline at end of file diff --git a/sandbox/elasticstack/src/test/java/org/jclouds/elasticstack/functions/ListOfKeyValuesDelimitedByBlankLinesToListOfMapsTest.java b/sandbox/elasticstack/src/test/java/org/jclouds/elasticstack/functions/ListOfKeyValuesDelimitedByBlankLinesToListOfMapsTest.java new file mode 100644 index 0000000000..62f9552ce3 --- /dev/null +++ b/sandbox/elasticstack/src/test/java/org/jclouds/elasticstack/functions/ListOfKeyValuesDelimitedByBlankLinesToListOfMapsTest.java @@ -0,0 +1,66 @@ +/** + * + * 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.elasticstack.functions; + +import static org.testng.Assert.assertEquals; + +import org.testng.annotations.Test; + +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.Lists; + +/** + * + * @author Adrian Cole + */ +@Test(groups = { "unit" }) +public class ListOfKeyValuesDelimitedByBlankLinesToListOfMapsTest { + + private static final ListOfKeyValuesDelimitedByBlankLinesToListOfMaps FN = new ListOfKeyValuesDelimitedByBlankLinesToListOfMaps(); + + public void testNone() { + assertEquals(FN.apply(""), Lists.newArrayList()); + assertEquals(FN.apply("\n\n\n"), Lists.newArrayList()); + } + + public void testOneMap() { + assertEquals(FN.apply("key1 value1\nkey2 value2"), + ImmutableList.of(ImmutableMap.of("key1", "value1", "key2", "value2"))); + assertEquals(FN.apply("key1 value1\nkey2 value2\n\n"), + ImmutableList.of(ImmutableMap.of("key1", "value1", "key2", "value2"))); + } + + public void testValueEncodesNewlines() { + assertEquals(FN.apply("key1 value1\\n\nkey2 value2"), + ImmutableList.of(ImmutableMap.of("key1", "value1\n", "key2", "value2"))); + } + + public void testTwoMaps() { + assertEquals( + FN.apply("key1 value1\nkey2 value2\n\nkey1 v1\nkey2 v2"), + ImmutableList.of(ImmutableMap.of("key1", "value1", "key2", "value2"), + ImmutableMap.of("key1", "v1", "key2", "v2"))); + assertEquals( + FN.apply("key1 value1\nkey2 value2\n\nkey1 v1\nkey2 v2\n\n"), + ImmutableList.of(ImmutableMap.of("key1", "value1", "key2", "value2"), + ImmutableMap.of("key1", "v1", "key2", "v2"))); + } +} \ No newline at end of file diff --git a/sandbox/elasticstack/src/test/java/org/jclouds/elasticstack/functions/ListOfMapsToListOfKeyValuesDelimitedByBlankLinesTest.java b/sandbox/elasticstack/src/test/java/org/jclouds/elasticstack/functions/ListOfMapsToListOfKeyValuesDelimitedByBlankLinesTest.java new file mode 100644 index 0000000000..8d001af41f --- /dev/null +++ b/sandbox/elasticstack/src/test/java/org/jclouds/elasticstack/functions/ListOfMapsToListOfKeyValuesDelimitedByBlankLinesTest.java @@ -0,0 +1,60 @@ +/** + * + * 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.elasticstack.functions; + +import static org.testng.Assert.assertEquals; + +import java.util.Map; + +import org.testng.annotations.Test; + +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; + +/** + * + * @author Adrian Cole + */ +@Test(groups = { "unit" }) +public class ListOfMapsToListOfKeyValuesDelimitedByBlankLinesTest { + + private static final ListOfMapsToListOfKeyValuesDelimitedByBlankLines FN = new ListOfMapsToListOfKeyValuesDelimitedByBlankLines(); + + public void testNone() { + assertEquals(FN.apply(ImmutableList.> of()), ""); + } + + public void testOneMap() { + assertEquals( + FN.apply(ImmutableList.> of(ImmutableMap.of("key1", "value1", "key2", "value2"))), + "key1 value1\nkey2 value2"); + } + + public void testValueEncodesNewlines() { + assertEquals( + FN.apply(ImmutableList.> of(ImmutableMap.of("key1", "value1\n", "key2", "value2"))), + "key1 value1\\n\nkey2 value2"); + } + + public void testTwoMaps() { + assertEquals(FN.apply(ImmutableList.> of(ImmutableMap.of("key1", "value1", "key2", "value2"), + ImmutableMap.of("key1", "v1", "key2", "v2"))), "key1 value1\nkey2 value2\n\nkey1 v1\nkey2 v2"); + } +} \ No newline at end of file diff --git a/sandbox/elasticstack/src/test/java/org/jclouds/elasticstack/functions/MapToDriveInfoTest.java b/sandbox/elasticstack/src/test/java/org/jclouds/elasticstack/functions/MapToDriveInfoTest.java new file mode 100644 index 0000000000..ef681199fe --- /dev/null +++ b/sandbox/elasticstack/src/test/java/org/jclouds/elasticstack/functions/MapToDriveInfoTest.java @@ -0,0 +1,83 @@ +/** + * + * 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.elasticstack.functions; + +import static org.testng.Assert.assertEquals; + +import java.io.IOException; +import java.util.Map; + +import org.jclouds.elasticstack.domain.ClaimType; +import org.jclouds.elasticstack.domain.DriveInfo; +import org.jclouds.elasticstack.domain.DriveStatus; +import org.jclouds.util.Utils; +import org.testng.annotations.Test; + +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableSet; + +/** + * + * @author Adrian Cole + */ +@Test(groups = { "unit" }) +public class MapToDriveInfoTest { + public static DriveInfo ONE = new DriveInfo.Builder() + .status(DriveStatus.ACTIVE) + .name("Ubuntu 10.10 Server Edition Linux 64bit Preinstalled System") + .readBytes(4096l) + .user("58ca3c1f-7629-4771-9b71-863f40153ba4") + .encryptionCipher("aes-xts-plain") + .uuid("b8171d28-755a-4271-b891-7998871a160e") + .writeBytes(8589938688l) + .claimType(ClaimType.SHARED) + .claimed( + ImmutableSet.of( + "00109617-2c6b-424b-9cfa-5b572c17bafe:guest:692cd1c7-a863-4a22-8170-fc6e6feb68af:ide:0:0", + "00031836-a624-4b22-bc7d-41ff8977087b:guest:a1414360-7c24-4730-8c97-180bf7775a71:ide:0:0", + "0002c6df-a1d2-4d1d-96f0-f95405a28183:guest:386f1cc7-affc-49c1-82a5-2f8e412170e4:ide:0:0", + "00031836-a624-4b22-bc7d-41ff8977087b:guest:17b076be-430d-4a76-9df3-b9896fec82a5:ide:0:0", + "000663ee-9fb6-4461-90f6-01327a4aff07:guest:f83b519f-feab-42cf-859c-f61495681ada:ide:0:1"))// + .readers(ImmutableSet.of("ffffffff-ffff-ffff-ffff-ffffffffffff"))// + .readRequests(1l)// + .writeRequests(2097153l)// + .size(8589934592l)// + .userMetadata(ImmutableMap.of("foo", "bar", "baz", "raz")).build(); + + private static final MapToDriveInfo MAP_TO_DRIVE = new MapToDriveInfo(); + + public void testEmptyMapReturnsNull() { + assertEquals(MAP_TO_DRIVE.apply(ImmutableMap. of()), null); + } + + public void testBasics() { + DriveInfo expects = new DriveInfo.Builder().name("foo").size(100l).build(); + assertEquals(MAP_TO_DRIVE.apply(ImmutableMap.of("name", "foo", "size", "100")), expects); + } + + public void testComplete() throws IOException { + + Map input = new ListOfKeyValuesDelimitedByBlankLinesToListOfMaps().apply( + Utils.toStringAndClose(MapToDriveInfoTest.class.getResourceAsStream("/drive.txt"))).get(0); + + assertEquals(MAP_TO_DRIVE.apply(input), ONE); + + } +} \ No newline at end of file diff --git a/sandbox/elasticstack/src/test/java/org/jclouds/elasticstack/functions/SplitNewlinesTest.java b/sandbox/elasticstack/src/test/java/org/jclouds/elasticstack/functions/SplitNewlinesTest.java new file mode 100644 index 0000000000..2afa9537b6 --- /dev/null +++ b/sandbox/elasticstack/src/test/java/org/jclouds/elasticstack/functions/SplitNewlinesTest.java @@ -0,0 +1,55 @@ +/** + * + * 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.elasticstack.functions; + +import static org.testng.Assert.assertEquals; + +import java.io.InputStream; +import java.util.Set; + +import org.jclouds.elasticstack.functions.SplitNewlines; +import org.jclouds.http.HttpResponse; +import org.jclouds.io.Payloads; +import org.testng.annotations.Test; + +import com.google.common.base.Function; +import com.google.common.collect.ImmutableSortedSet; +import com.google.inject.Guice; + +/** + * Tests behavior of {@code NewlineDelimitedStringHandler} + * + * @author Adrian Cole + */ +@Test(groups = "unit") +public class SplitNewlinesTest { + + static Function> createParser() { + return Guice.createInjector().getInstance(SplitNewlines.class); + } + + public void test() { + InputStream is = SplitNewlinesTest.class.getResourceAsStream("/uuids.txt"); + Set list = createParser().apply(new HttpResponse(200, "ok", Payloads.newInputStreamPayload(is))); + assertEquals(list, ImmutableSortedSet.of("7e8ab721-81c9-4cb9-a651-4cafbfe1501c", + "ea6a8fdb-dab3-4d06-86c2-41a5835e6ed9", "74744450-d338-4087-b3b8-59b505110a57")); + } + +} diff --git a/sandbox/elasticstack/src/test/java/org/jclouds/elasticstack/handlers/ElasticStackErrorHandlerTest.java b/sandbox/elasticstack/src/test/java/org/jclouds/elasticstack/handlers/ElasticStackErrorHandlerTest.java new file mode 100644 index 0000000000..0e23584cc0 --- /dev/null +++ b/sandbox/elasticstack/src/test/java/org/jclouds/elasticstack/handlers/ElasticStackErrorHandlerTest.java @@ -0,0 +1,130 @@ +/** + * + * 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.elasticstack.handlers; + +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.reportMatcher; +import static org.easymock.classextension.EasyMock.createMock; +import static org.easymock.classextension.EasyMock.replay; +import static org.easymock.classextension.EasyMock.verify; + +import java.net.URI; + +import org.easymock.IArgumentMatcher; +import org.jclouds.http.HttpCommand; +import org.jclouds.http.HttpRequest; +import org.jclouds.http.HttpResponse; +import org.jclouds.io.Payloads; +import org.jclouds.rest.AuthorizationException; +import org.jclouds.rest.ResourceNotFoundException; +import org.jclouds.util.Utils; +import org.testng.annotations.Test; + +import com.google.inject.Guice; + +/** + * + * @author Adrian Cole + */ +@Test(groups = { "unit" }) +public class ElasticStackErrorHandlerTest { + + @Test + public void test400MakesIllegalArgumentException() { + assertCodeMakes("GET", URI.create("https://elasticstack.com/foo"), 400, "", "Bad Request", + IllegalArgumentException.class); + } + + @Test + public void test400MakesResourceNotFoundExceptionOnMessageNotFound() { + assertCodeMakes("GET", URI.create("https://elasticstack.com/foo"), 400, "", "errors:system Drive 8f9b42b1-26de-49ad-a3fd-d4fa06524339 could not be found. Please re-validate your entry.", + ResourceNotFoundException.class); + } + + @Test + public void test401MakesAuthorizationException() { + assertCodeMakes("GET", URI.create("https://elasticstack.com/foo"), 401, "", "Unauthorized", + AuthorizationException.class); + } + + @Test + public void test404MakesResourceNotFoundException() { + assertCodeMakes("GET", URI.create("https://elasticstack.com/foo"), 404, "", "Not Found", + ResourceNotFoundException.class); + } + + @Test + public void test405MakesIllegalArgumentException() { + assertCodeMakes("GET", URI.create("https://elasticstack.com/foo"), 405, "", "Method Not Allowed", + IllegalArgumentException.class); + } + + @Test + public void test409MakesIllegalStateException() { + assertCodeMakes("GET", URI.create("https://elasticstack.com/foo"), 409, "", "Conflict", + IllegalStateException.class); + } + + private void assertCodeMakes(String method, URI uri, int statusCode, String message, String content, + Class expected) { + assertCodeMakes(method, uri, statusCode, message, "text/xml", content, expected); + } + + private void assertCodeMakes(String method, URI uri, int statusCode, String message, String contentType, + String content, Class expected) { + + ElasticStackErrorHandler function = Guice.createInjector().getInstance(ElasticStackErrorHandler.class); + + HttpCommand command = createMock(HttpCommand.class); + HttpRequest request = new HttpRequest(method, uri); + HttpResponse response = new HttpResponse(statusCode, message, Payloads.newInputStreamPayload(Utils + .toInputStream(content))); + response.getPayload().getContentMetadata().setContentType(contentType); + + expect(command.getRequest()).andReturn(request).atLeastOnce(); + command.setException(classEq(expected)); + + replay(command); + + function.handleError(command, response); + + verify(command); + } + + public static Exception classEq(final Class in) { + reportMatcher(new IArgumentMatcher() { + + @Override + public void appendTo(StringBuffer buffer) { + buffer.append("classEq("); + buffer.append(in); + buffer.append(")"); + } + + @Override + public boolean matches(Object arg) { + return arg.getClass() == in; + } + + }); + return null; + } + +} \ No newline at end of file diff --git a/sandbox/elasticstack/src/test/java/org/jclouds/elasticstack/options/ReadDriveOptionsTest.java b/sandbox/elasticstack/src/test/java/org/jclouds/elasticstack/options/ReadDriveOptionsTest.java new file mode 100644 index 0000000000..3e4e4a3a38 --- /dev/null +++ b/sandbox/elasticstack/src/test/java/org/jclouds/elasticstack/options/ReadDriveOptionsTest.java @@ -0,0 +1,83 @@ +/** + * + * 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.elasticstack.options; + +import static org.jclouds.elasticstack.options.ReadDriveOptions.Builder.offset; +import static org.jclouds.elasticstack.options.ReadDriveOptions.Builder.size; +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertNull; + +import org.testng.annotations.Test; + +/** + * Tests possible uses of ReadDriveOptions and ReadDriveOptions.Builder.* + * + * @author Adrian Cole + */ +@Test(groups = "unit") +public class ReadDriveOptionsTest { + + @Test + public void testNullOffset() { + ReadDriveOptions options = new ReadDriveOptions(); + assertNull(options.getOffset()); + } + + @Test + public void testOffset() { + ReadDriveOptions options = new ReadDriveOptions().offset(1024); + assertEquals(options.getOffset(), new Long(1024)); + } + + @Test + public void testOffsetStatic() { + ReadDriveOptions options = offset(1024); + assertEquals(options.getOffset(), new Long(1024)); + } + + @Test(expectedExceptions = IllegalArgumentException.class) + public void testOffsetNegative() { + offset(-1); + } + + @Test + public void testNullSize() { + ReadDriveOptions options = new ReadDriveOptions(); + assertNull(options.getSize()); + } + + @Test + public void testSize() { + ReadDriveOptions options = new ReadDriveOptions().size(1024); + assertEquals(options.getSize(), new Long(1024)); + } + + @Test + public void testSizeStatic() { + ReadDriveOptions options = size(1024); + assertEquals(options.getSize(), new Long(1024)); + } + + @Test(expectedExceptions = IllegalArgumentException.class) + public void testSizeNegative() { + size(-1); + } + +} diff --git a/sandbox/elasticstack/src/test/resources/cloudsigma/drive.txt b/sandbox/elasticstack/src/test/resources/cloudsigma/drive.txt new file mode 100644 index 0000000000..04372bb776 --- /dev/null +++ b/sandbox/elasticstack/src/test/resources/cloudsigma/drive.txt @@ -0,0 +1,26 @@ +status active +use networking,security,gateway +name Ubuntu 10.10 Server Edition Linux 64bit Preinstalled System +bits 64 +url http://www.ubuntu.com +read:bytes 4096 +user 58ca3c1f-7629-4771-9b71-863f40153ba4 +encryption:cipher aes-xts-plain +encryption:key ba6c2a4897072e9f25920ed73bd522e9c10d89f30a215158cccf8d0f654ac643 +description The Ubuntu Linux distribution brings the spirit of Ubuntu to the software world. +drive b8171d28-755a-4271-b891-7998871a160e +install_notes first line\n\n +os linux +write:bytes 8589938688 +claim:type shared +claimed 00109617-2c6b-424b-9cfa-5b572c17bafe:guest:692cd1c7-a863-4a22-8170-fc6e6feb68af:ide:0:0 00031836-a624-4b22-bc7d-41ff8977087b:guest:a1414360-7c24-4730-8c97-180bf7775a71:ide:0:0 0002c6df-a1d2-4d1d-96f0-f95405a28183:guest:386f1cc7-affc-49c1-82a5-2f8e412170e4:ide:0:0 00031836-a624-4b22-bc7d-41ff8977087b:guest:17b076be-430d-4a76-9df3-b9896fec82a5:ide:0:0 000663ee-9fb6-4461-90f6-01327a4aff07:guest:f83b519f-feab-42cf-859c-f61495681ada:ide:0:1 +drive_type installcd,livecd +autoexpanding false +readers ffffffff-ffff-ffff-ffff-ffffffffffff +read:requests 1 +free true +type disk +write:requests 2097153 +size 8589934592 +user:foo bar +user:baz raz \ No newline at end of file diff --git a/sandbox/elasticstack/src/test/resources/create_drive.txt b/sandbox/elasticstack/src/test/resources/create_drive.txt new file mode 100644 index 0000000000..be8919e1b3 --- /dev/null +++ b/sandbox/elasticstack/src/test/resources/create_drive.txt @@ -0,0 +1,9 @@ +name Ubuntu 10.10 Server Edition Linux 64bit Preinstalled System +size 8589934592 +claim:type shared +readers ffffffff-ffff-ffff-ffff-ffffffffffff +tags tag1 tag2 +user:foo bar +user:baz raz +avoid avoid1 +encryption:cipher aes-xts-plain \ No newline at end of file diff --git a/sandbox/elasticstack/src/test/resources/drive.txt b/sandbox/elasticstack/src/test/resources/drive.txt new file mode 100644 index 0000000000..a88daebbc0 --- /dev/null +++ b/sandbox/elasticstack/src/test/resources/drive.txt @@ -0,0 +1,15 @@ +status active +name Ubuntu 10.10 Server Edition Linux 64bit Preinstalled System +read:bytes 4096 +user 58ca3c1f-7629-4771-9b71-863f40153ba4 +encryption:cipher aes-xts-plain +drive b8171d28-755a-4271-b891-7998871a160e +write:bytes 8589938688 +claim:type shared +claimed 00109617-2c6b-424b-9cfa-5b572c17bafe:guest:692cd1c7-a863-4a22-8170-fc6e6feb68af:ide:0:0 00031836-a624-4b22-bc7d-41ff8977087b:guest:a1414360-7c24-4730-8c97-180bf7775a71:ide:0:0 0002c6df-a1d2-4d1d-96f0-f95405a28183:guest:386f1cc7-affc-49c1-82a5-2f8e412170e4:ide:0:0 00031836-a624-4b22-bc7d-41ff8977087b:guest:17b076be-430d-4a76-9df3-b9896fec82a5:ide:0:0 000663ee-9fb6-4461-90f6-01327a4aff07:guest:f83b519f-feab-42cf-859c-f61495681ada:ide:0:1 +readers ffffffff-ffff-ffff-ffff-ffffffffffff +read:requests 1 +write:requests 2097153 +size 8589934592 +user:foo bar +user:baz raz \ No newline at end of file diff --git a/sandbox/elasticstack/src/test/resources/drive_data.txt b/sandbox/elasticstack/src/test/resources/drive_data.txt new file mode 100644 index 0000000000..b96bc0afd3 --- /dev/null +++ b/sandbox/elasticstack/src/test/resources/drive_data.txt @@ -0,0 +1,7 @@ +name Ubuntu 10.10 Server Edition Linux 64bit Preinstalled System +size 8589934592 +claim:type shared +readers ffffffff-ffff-ffff-ffff-ffffffffffff +tags tag1 tag2 +user:foo bar +user:baz raz \ No newline at end of file diff --git a/sandbox/elasticstack/src/test/resources/log4j.xml b/sandbox/elasticstack/src/test/resources/log4j.xml new file mode 100644 index 0000000000..99fc6ca2a0 --- /dev/null +++ b/sandbox/elasticstack/src/test/resources/log4j.xml @@ -0,0 +1,110 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/sandbox/elasticstack/src/test/resources/uuids.txt b/sandbox/elasticstack/src/test/resources/uuids.txt new file mode 100644 index 0000000000..092a4f8d6d --- /dev/null +++ b/sandbox/elasticstack/src/test/resources/uuids.txt @@ -0,0 +1,3 @@ +7e8ab721-81c9-4cb9-a651-4cafbfe1501c +ea6a8fdb-dab3-4d06-86c2-41a5835e6ed9 +74744450-d338-4087-b3b8-59b505110a57 diff --git a/sandbox/ibmdev/src/main/java/org/jclouds/ibmdev/compute/config/IBMDeveloperCloudBindComputeStrategiesByClass.java b/sandbox/ibmdev/src/main/java/org/jclouds/ibmdev/compute/config/IBMDeveloperCloudBindComputeStrategiesByClass.java new file mode 100644 index 0000000000..1091eeac93 --- /dev/null +++ b/sandbox/ibmdev/src/main/java/org/jclouds/ibmdev/compute/config/IBMDeveloperCloudBindComputeStrategiesByClass.java @@ -0,0 +1,76 @@ +/** + * + * 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.ibmdev.compute.config; + +import org.jclouds.compute.config.BindComputeStrategiesByClass; +import org.jclouds.compute.strategy.AddNodeWithTagStrategy; +import org.jclouds.compute.strategy.DestroyNodeStrategy; +import org.jclouds.compute.strategy.GetNodeMetadataStrategy; +import org.jclouds.compute.strategy.ListNodesStrategy; +import org.jclouds.compute.strategy.RebootNodeStrategy; +import org.jclouds.compute.strategy.ResumeNodeStrategy; +import org.jclouds.compute.strategy.SuspendNodeStrategy; +import org.jclouds.ibmdev.compute.strategy.IBMDeveloperCloudAddNodeWithTagStrategy; +import org.jclouds.ibmdev.compute.strategy.IBMDeveloperCloudDestroyNodeStrategy; +import org.jclouds.ibmdev.compute.strategy.IBMDeveloperCloudGetNodeMetadataStrategy; +import org.jclouds.ibmdev.compute.strategy.IBMDeveloperCloudLifeCycleStrategy; +import org.jclouds.ibmdev.compute.strategy.IBMDeveloperCloudListNodesStrategy; + +/** + * @author Adrian Cole + */ +public class IBMDeveloperCloudBindComputeStrategiesByClass extends BindComputeStrategiesByClass { + + @Override + protected Class defineAddNodeWithTagStrategy() { + return IBMDeveloperCloudAddNodeWithTagStrategy.class; + } + + @Override + protected Class defineDestroyNodeStrategy() { + return IBMDeveloperCloudDestroyNodeStrategy.class; + } + + @Override + protected Class defineGetNodeMetadataStrategy() { + return IBMDeveloperCloudGetNodeMetadataStrategy.class; + } + + @Override + protected Class defineListNodesStrategy() { + return IBMDeveloperCloudListNodesStrategy.class; + } + + @Override + protected Class defineRebootNodeStrategy() { + return IBMDeveloperCloudLifeCycleStrategy.class; + } + + @Override + protected Class defineStartNodeStrategy() { + return IBMDeveloperCloudLifeCycleStrategy.class; + } + + @Override + protected Class defineStopNodeStrategy() { + return IBMDeveloperCloudLifeCycleStrategy.class; + } + +} \ No newline at end of file diff --git a/sandbox/ibmdev/src/main/java/org/jclouds/ibmdev/compute/config/IBMDeveloperCloudBindComputeSuppliersByClass.java b/sandbox/ibmdev/src/main/java/org/jclouds/ibmdev/compute/config/IBMDeveloperCloudBindComputeSuppliersByClass.java new file mode 100644 index 0000000000..aa2dc2f1f4 --- /dev/null +++ b/sandbox/ibmdev/src/main/java/org/jclouds/ibmdev/compute/config/IBMDeveloperCloudBindComputeSuppliersByClass.java @@ -0,0 +1,51 @@ +/** + * + * 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.ibmdev.compute.config; + +import java.util.Set; + +import org.jclouds.compute.config.BindComputeSuppliersByClass; +import org.jclouds.compute.domain.Hardware; +import org.jclouds.compute.domain.Image; +import org.jclouds.domain.Location; +import org.jclouds.ibmdev.compute.suppliers.IBMDeveloperCloudHardwareSupplier; +import org.jclouds.ibmdev.compute.suppliers.IBMDeveloperCloudImageSupplier; +import org.jclouds.ibmdev.compute.suppliers.IBMDeveloperCloudLocationSupplier; + +import com.google.common.base.Supplier; +/** + * @author Adrian Cole + */ +public class IBMDeveloperCloudBindComputeSuppliersByClass extends BindComputeSuppliersByClass { + @Override + protected Class>> defineHardwareSupplier() { + return IBMDeveloperCloudHardwareSupplier.class; + } + + @Override + protected Class>> defineImageSupplier() { + return IBMDeveloperCloudImageSupplier.class; + } + + @Override + protected Class>> defineLocationSupplier() { + return IBMDeveloperCloudLocationSupplier.class; + } +} \ No newline at end of file diff --git a/sandbox/ibmdev/src/main/java/org/jclouds/ibmdev/compute/config/IBMDeveloperCloudComputeServiceContextModule.java b/sandbox/ibmdev/src/main/java/org/jclouds/ibmdev/compute/config/IBMDeveloperCloudComputeServiceContextModule.java index 9e72066cfa..4395b09273 100644 --- a/sandbox/ibmdev/src/main/java/org/jclouds/ibmdev/compute/config/IBMDeveloperCloudComputeServiceContextModule.java +++ b/sandbox/ibmdev/src/main/java/org/jclouds/ibmdev/compute/config/IBMDeveloperCloudComputeServiceContextModule.java @@ -21,76 +21,26 @@ package org.jclouds.ibmdev.compute.config; import static org.jclouds.compute.domain.OsFamily.SUSE; -import java.util.Map; -import java.util.Set; -import java.util.concurrent.ConcurrentHashMap; - -import javax.inject.Named; -import javax.inject.Singleton; - -import org.jclouds.compute.ComputeServiceContext; -import org.jclouds.compute.LoadBalancerService; import org.jclouds.compute.config.BaseComputeServiceContextModule; -import org.jclouds.compute.config.ComputeServiceTimeoutsModule; -import org.jclouds.compute.domain.Image; -import org.jclouds.compute.domain.NodeMetadata; -import org.jclouds.compute.domain.NodeState; -import org.jclouds.compute.domain.Size; import org.jclouds.compute.domain.TemplateBuilder; -import org.jclouds.compute.internal.ComputeServiceContextImpl; -import org.jclouds.compute.strategy.AddNodeWithTagStrategy; -import org.jclouds.compute.strategy.DestroyNodeStrategy; -import org.jclouds.compute.strategy.GetNodeMetadataStrategy; -import org.jclouds.compute.strategy.ListNodesStrategy; -import org.jclouds.compute.strategy.RebootNodeStrategy; -import org.jclouds.domain.Location; -import org.jclouds.ibmdev.IBMDeveloperCloudAsyncClient; -import org.jclouds.ibmdev.IBMDeveloperCloudClient; -import org.jclouds.ibmdev.compute.functions.InstanceToNodeMetadata; -import org.jclouds.ibmdev.compute.strategy.IBMDeveloperCloudAddNodeWithTagStrategy; -import org.jclouds.ibmdev.compute.strategy.IBMDeveloperCloudDestroyNodeStrategy; -import org.jclouds.ibmdev.compute.strategy.IBMDeveloperCloudGetNodeMetadataStrategy; -import org.jclouds.ibmdev.compute.strategy.IBMDeveloperCloudListNodesStrategy; -import org.jclouds.ibmdev.compute.strategy.IBMDeveloperCloudRebootNodeStrategy; -import org.jclouds.ibmdev.compute.suppliers.IBMDeveloperCloudImageSupplier; -import org.jclouds.ibmdev.compute.suppliers.IBMDeveloperCloudLocationSupplier; -import org.jclouds.ibmdev.compute.suppliers.IBMDeveloperCloudSizeSupplier; -import org.jclouds.ibmdev.domain.Instance; -import org.jclouds.rest.RestContext; -import org.jclouds.rest.internal.RestContextImpl; +import org.jclouds.compute.internal.BaseComputeService; -import com.google.common.annotations.VisibleForTesting; -import com.google.common.base.Function; -import com.google.common.base.Supplier; -import com.google.common.collect.ImmutableMap; import com.google.inject.Injector; -import com.google.inject.Provides; -import com.google.inject.Scopes; -import com.google.inject.TypeLiteral; -import com.google.inject.util.Providers; /** + * Configures the {@link IBMDeveloperCloudComputeServiceContext}; requires + * {@link BaseComputeService} bound. + * * @author Adrian Cole */ public class IBMDeveloperCloudComputeServiceContextModule extends BaseComputeServiceContextModule { @Override protected void configure() { - install(new ComputeServiceTimeoutsModule()); - bind(new TypeLiteral>() { - }).to(InstanceToNodeMetadata.class); - bind(new TypeLiteral() { - }).to(new TypeLiteral>() { - }).in(Scopes.SINGLETON); - bind(new TypeLiteral>() { - }).to(new TypeLiteral>() { - }).in(Scopes.SINGLETON); - bind(AddNodeWithTagStrategy.class).to(IBMDeveloperCloudAddNodeWithTagStrategy.class); - bind(ListNodesStrategy.class).to(IBMDeveloperCloudListNodesStrategy.class); - bind(GetNodeMetadataStrategy.class).to(IBMDeveloperCloudGetNodeMetadataStrategy.class); - bind(RebootNodeStrategy.class).to(IBMDeveloperCloudRebootNodeStrategy.class); - bind(DestroyNodeStrategy.class).to(IBMDeveloperCloudDestroyNodeStrategy.class); - bind(LoadBalancerService.class).toProvider(Providers. of(null)); + install(new IBMDeveloperCloudComputeServiceDependenciesModule()); + install(new IBMDeveloperCloudBindComputeStrategiesByClass()); + install(new IBMDeveloperCloudBindComputeSuppliersByClass()); + super.configure(); } /** @@ -100,48 +50,4 @@ public class IBMDeveloperCloudComputeServiceContextModule extends BaseComputeSer protected TemplateBuilder provideTemplate(Injector injector, TemplateBuilder template) { return template.osFamily(SUSE); } - - @Provides - @Singleton - @Named("CREDENTIALS") - Map credentialsMap() { - return new ConcurrentHashMap(); - } - - @VisibleForTesting - static final Map instanceStatusToNodeState = ImmutableMap - . builder().put(Instance.Status.ACTIVE, NodeState.RUNNING)// - .put(Instance.Status.STOPPED, NodeState.SUSPENDED)// - .put(Instance.Status.REMOVED, NodeState.TERMINATED)// - .put(Instance.Status.DEPROVISIONING, NodeState.PENDING)// - .put(Instance.Status.FAILED, NodeState.ERROR)// - .put(Instance.Status.NEW, NodeState.PENDING)// - .put(Instance.Status.PROVISIONING, NodeState.PENDING)// - .put(Instance.Status.REJECTED, NodeState.ERROR)// - .put(Instance.Status.RESTARTING, NodeState.PENDING)// - .put(Instance.Status.STARTING, NodeState.PENDING)// - .put(Instance.Status.STOPPING, NodeState.PENDING)// - .put(Instance.Status.DEPROVISION_PENDING, NodeState.PENDING)// - .put(Instance.Status.UNKNOWN, NodeState.UNKNOWN).build(); - - @Singleton - @Provides - Map provideServerToNodeState() { - return instanceStatusToNodeState; - } - - @Override - protected Supplier> getSourceImageSupplier(Injector injector) { - return injector.getInstance(IBMDeveloperCloudImageSupplier.class); - } - - @Override - protected Supplier> getSourceSizeSupplier(Injector injector) { - return injector.getInstance(IBMDeveloperCloudSizeSupplier.class); - } - - @Override - protected Supplier> getSourceLocationSupplier(Injector injector) { - return injector.getInstance(IBMDeveloperCloudLocationSupplier.class); - } -} \ No newline at end of file +} diff --git a/sandbox/ibmdev/src/main/java/org/jclouds/ibmdev/compute/config/IBMDeveloperCloudComputeServiceDependenciesModule.java b/sandbox/ibmdev/src/main/java/org/jclouds/ibmdev/compute/config/IBMDeveloperCloudComputeServiceDependenciesModule.java new file mode 100644 index 0000000000..31826c046d --- /dev/null +++ b/sandbox/ibmdev/src/main/java/org/jclouds/ibmdev/compute/config/IBMDeveloperCloudComputeServiceDependenciesModule.java @@ -0,0 +1,92 @@ +/** + * + * 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.ibmdev.compute.config; + +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +import javax.inject.Named; +import javax.inject.Singleton; + +import org.jclouds.compute.ComputeServiceContext; +import org.jclouds.compute.domain.NodeMetadata; +import org.jclouds.compute.domain.NodeState; +import org.jclouds.compute.internal.ComputeServiceContextImpl; +import org.jclouds.ibmdev.IBMDeveloperCloudAsyncClient; +import org.jclouds.ibmdev.IBMDeveloperCloudClient; +import org.jclouds.ibmdev.compute.functions.InstanceToNodeMetadata; +import org.jclouds.ibmdev.domain.Instance; +import org.jclouds.rest.RestContext; +import org.jclouds.rest.internal.RestContextImpl; + +import com.google.common.annotations.VisibleForTesting; +import com.google.common.base.Function; +import com.google.common.collect.ImmutableMap; +import com.google.inject.AbstractModule; +import com.google.inject.Provides; +import com.google.inject.Scopes; +import com.google.inject.TypeLiteral; + +/** + * @author Adrian Cole + */ +public class IBMDeveloperCloudComputeServiceDependenciesModule extends AbstractModule { + + @Override + protected void configure() { + bind(new TypeLiteral>() { + }).to(InstanceToNodeMetadata.class); + bind(new TypeLiteral() { + }).to(new TypeLiteral>() { + }).in(Scopes.SINGLETON); + bind(new TypeLiteral>() { + }).to(new TypeLiteral>() { + }).in(Scopes.SINGLETON); + } + + @Provides + @Singleton + @Named("CREDENTIALS") + Map credentialsMap() { + return new ConcurrentHashMap(); + } + + @VisibleForTesting + static final Map instanceStatusToNodeState = ImmutableMap + . builder().put(Instance.Status.ACTIVE, NodeState.RUNNING)// + .put(Instance.Status.STOPPED, NodeState.SUSPENDED)// + .put(Instance.Status.REMOVED, NodeState.TERMINATED)// + .put(Instance.Status.DEPROVISIONING, NodeState.PENDING)// + .put(Instance.Status.FAILED, NodeState.ERROR)// + .put(Instance.Status.NEW, NodeState.PENDING)// + .put(Instance.Status.PROVISIONING, NodeState.PENDING)// + .put(Instance.Status.REJECTED, NodeState.ERROR)// + .put(Instance.Status.RESTARTING, NodeState.PENDING)// + .put(Instance.Status.STARTING, NodeState.PENDING)// + .put(Instance.Status.STOPPING, NodeState.PENDING)// + .put(Instance.Status.DEPROVISION_PENDING, NodeState.PENDING)// + .put(Instance.Status.UNKNOWN, NodeState.UNRECOGNIZED).build(); + + @Singleton + @Provides + Map provideServerToNodeState() { + return instanceStatusToNodeState; + } +} \ No newline at end of file diff --git a/sandbox/ibmdev/src/main/java/org/jclouds/ibmdev/compute/domain/IBMImage.java b/sandbox/ibmdev/src/main/java/org/jclouds/ibmdev/compute/domain/IBMImage.java deleted file mode 100644 index 9ab634d693..0000000000 --- a/sandbox/ibmdev/src/main/java/org/jclouds/ibmdev/compute/domain/IBMImage.java +++ /dev/null @@ -1,58 +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.ibmdev.compute.domain; - -import org.jclouds.compute.domain.OperatingSystem; -import org.jclouds.compute.domain.OsFamily; -import org.jclouds.compute.domain.internal.ImageImpl; -import org.jclouds.domain.Credentials; -import org.jclouds.domain.Location; - -import com.google.common.collect.ImmutableMap; - -/** - * @author Adrian Cole - */ -public class IBMImage extends ImageImpl { - - /** The serialVersionUID */ - private static final long serialVersionUID = -8520373150950058296L; - - private final org.jclouds.ibmdev.domain.Image rawImage; - - public IBMImage(org.jclouds.ibmdev.domain.Image in, Location location) { - // TODO parse correct OS - // TODO manifest fails to parse due to encoding issues in the path - // TODO get correct default credentials - // http://www-180.ibm.com/cloud/enterprise/beta/ram/community/_rlvid.jsp.faces?_rap=pc_DiscussionForum.doDiscussionTopic&_rvip=/community/discussionForum.jsp&guid={DA689AEE-783C-6FE7-6F9F-DFEE9763F806}&v=1&submission=false&fid=1068&tid=1527 - super(in.getId(), in.getName(), in.getId(), location, null, ImmutableMap. of(), - new OperatingSystem((in.getPlatform().indexOf("Red Hat") != -1) ? OsFamily.RHEL : OsFamily.SUSE, null, - null, null, in.getPlatform(), (in.getPlatform().indexOf("32") == -1)), in.getDescription(), in - .getCreatedTime().getTime() - + "", new Credentials("idcuser", null)); - - this.rawImage = in; - } - - public org.jclouds.ibmdev.domain.Image getRawImage() { - return rawImage; - } - -} \ No newline at end of file diff --git a/sandbox/ibmdev/src/main/java/org/jclouds/ibmdev/compute/domain/IBMSize.java b/sandbox/ibmdev/src/main/java/org/jclouds/ibmdev/compute/domain/IBMSize.java deleted file mode 100644 index 3d7dd64901..0000000000 --- a/sandbox/ibmdev/src/main/java/org/jclouds/ibmdev/compute/domain/IBMSize.java +++ /dev/null @@ -1,74 +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.ibmdev.compute.domain; - -import org.jclouds.compute.domain.Image; -import org.jclouds.compute.domain.internal.SizeImpl; -import org.jclouds.ibmdev.domain.InstanceType; - -import com.google.common.collect.ImmutableMap; - -/** - * @author Adrian Cole - */ -public class IBMSize extends SizeImpl { - - /** The serialVersionUID */ - private static final long serialVersionUID = -8520373150950058296L; - - private final IBMImage image; - - private final InstanceType instanceType; - - // until we can lookup cores by id, we are multiplying price *100 to get a positive integer we - // can compare against. - public IBMSize(IBMImage in, InstanceType instanceType) { - super(instanceType.getId(), instanceType.getLabel(), in.getId() + "/" + instanceType.getId(), in.getLocation(), - in.getRawImage().getManifest(), ImmutableMap. of(), (int) (instanceType.getPrice() - .getRate() * 100), (int) (instanceType.getPrice().getRate() * 1024d), (int) (instanceType - .getPrice().getRate() * 100d), null); - this.image = in; - this.instanceType = instanceType; - } - - public IBMImage getImage() { - return image; - } - - public InstanceType getInstanceType() { - return instanceType; - } - - /** - * {@inheritDoc} - */ - @Override - public boolean supportsImage(Image input) { - return image.getId().equals(input.getId()); - } - - @Override - public String toString() { - return "[id=" + getId() + ", providerId=" + getProviderId() + ", name=" + getName() + ", cores=" + getCores() - + ", ram=" + getRam() + ", disk=" + getDisk() + ", supportsImage=" + image.getId() + ", rate=" - + instanceType.getPrice().getRate() + "]"; - } - -} \ No newline at end of file diff --git a/sandbox/ibmdev/src/main/java/org/jclouds/ibmdev/compute/functions/InstanceToNodeMetadata.java b/sandbox/ibmdev/src/main/java/org/jclouds/ibmdev/compute/functions/InstanceToNodeMetadata.java index 46e5d5cf03..9507b5134b 100644 --- a/sandbox/ibmdev/src/main/java/org/jclouds/ibmdev/compute/functions/InstanceToNodeMetadata.java +++ b/sandbox/ibmdev/src/main/java/org/jclouds/ibmdev/compute/functions/InstanceToNodeMetadata.java @@ -32,16 +32,16 @@ import javax.inject.Singleton; import org.jclouds.compute.domain.Image; import org.jclouds.compute.domain.NodeMetadata; +import org.jclouds.compute.domain.NodeMetadataBuilder; import org.jclouds.compute.domain.NodeState; -import org.jclouds.compute.domain.internal.NodeMetadataImpl; import org.jclouds.domain.Credentials; import org.jclouds.domain.Location; import org.jclouds.ibmdev.domain.Instance; import org.jclouds.logging.Logger; +import com.google.common.annotations.VisibleForTesting; import com.google.common.base.Function; import com.google.common.base.Supplier; -import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; @@ -51,6 +51,21 @@ import com.google.common.collect.ImmutableSet; @Singleton public class InstanceToNodeMetadata implements Function { + @VisibleForTesting + public static final Map instanceStatusToNodeState = ImmutableMap + . builder().put(Instance.Status.ACTIVE, NodeState.RUNNING)// + .put(Instance.Status.STOPPED, NodeState.SUSPENDED)// + .put(Instance.Status.REMOVED, NodeState.TERMINATED)// + .put(Instance.Status.DEPROVISIONING, NodeState.PENDING)// + .put(Instance.Status.FAILED, NodeState.ERROR)// + .put(Instance.Status.NEW, NodeState.PENDING)// + .put(Instance.Status.PROVISIONING, NodeState.PENDING)// + .put(Instance.Status.REJECTED, NodeState.ERROR)// + .put(Instance.Status.RESTARTING, NodeState.PENDING)// + .put(Instance.Status.STARTING, NodeState.PENDING)// + .put(Instance.Status.STOPPING, NodeState.PENDING)// + .put(Instance.Status.DEPROVISION_PENDING, NodeState.PENDING)// + .put(Instance.Status.UNKNOWN, NodeState.UNRECOGNIZED).build(); @Resource protected Logger logger = Logger.NULL; private final Map instanceStateToNodeState; @@ -60,8 +75,8 @@ public class InstanceToNodeMetadata implements Function @Inject InstanceToNodeMetadata(Map instanceStateToNodeState, - Supplier> images, @Named("CREDENTIALS") Map credentialsMap, - Supplier> locations) { + Supplier> images, @Named("CREDENTIALS") Map credentialsMap, + Supplier> locations) { this.instanceStateToNodeState = checkNotNull(instanceStateToNodeState, "instanceStateToNodeState"); this.images = checkNotNull(images, "images"); this.credentialsMap = checkNotNull(credentialsMap, "credentialsMap"); @@ -70,14 +85,15 @@ public class InstanceToNodeMetadata implements Function @Override public NodeMetadata apply(Instance from) { + //TODO hardware String tag = parseTagFromName(from.getName()); Set ipSet = from.getIp() != null ? ImmutableSet.of(from.getIp()) : ImmutableSet. of(); - NodeState state = instanceStateToNodeState.get(from.getStatus()); Image image = images.get().get(from.getImageId()); String key = tag != null ? credentialsMap.get(tag) : null; - return new NodeMetadataImpl(from.getId() + "", from.getName(), from.getId() + "", locations.get().get( - image.getLocation()), null, ImmutableMap. of(), tag, from.getImageId(), - image != null ? image.getOperatingSystem() : null, state, ipSet, ImmutableList. of(), - ImmutableMap. of(), new Credentials(image.getDefaultCredentials().identity, key)); + return new NodeMetadataBuilder().ids(from.getId() + "").name(from.getName()) + .location(locations.get().get(image.getLocation())).tag(tag).imageId(from.getImageId()) + .state(instanceStateToNodeState.get(from.getStatus())) + .operatingSystem(image != null ? image.getOperatingSystem() : null).publicAddresses(ipSet) + .credentials(new Credentials(image.getDefaultCredentials().identity, key)).build(); } } \ No newline at end of file diff --git a/sandbox/ibmdev/src/main/java/org/jclouds/ibmdev/compute/strategy/CreateKeyPairEncodeTagIntoNameRunNodesAndAddToSet.java b/sandbox/ibmdev/src/main/java/org/jclouds/ibmdev/compute/strategy/CreateKeyPairEncodeTagIntoNameRunNodesAndAddToSet.java index 1f8f1b5322..131c69f59e 100644 --- a/sandbox/ibmdev/src/main/java/org/jclouds/ibmdev/compute/strategy/CreateKeyPairEncodeTagIntoNameRunNodesAndAddToSet.java +++ b/sandbox/ibmdev/src/main/java/org/jclouds/ibmdev/compute/strategy/CreateKeyPairEncodeTagIntoNameRunNodesAndAddToSet.java @@ -21,7 +21,6 @@ package org.jclouds.ibmdev.compute.strategy; import static com.google.common.base.Preconditions.checkNotNull; -import java.io.IOException; import java.util.Map; import java.util.Set; import java.util.concurrent.ExecutorService; @@ -39,8 +38,6 @@ import org.jclouds.compute.strategy.ListNodesStrategy; import org.jclouds.compute.strategy.impl.EncodeTagIntoNameRunNodesAndAddToSetStrategy; import org.jclouds.compute.util.ComputeUtils; import org.jclouds.ibmdev.IBMDeveloperCloudClient; -import org.jclouds.io.Payload; -import org.jclouds.util.Utils; /** * @author Adrian Cole @@ -52,9 +49,9 @@ public class CreateKeyPairEncodeTagIntoNameRunNodesAndAddToSet extends EncodeTag @Inject protected CreateKeyPairEncodeTagIntoNameRunNodesAndAddToSet(AddNodeWithTagStrategy addNodeWithTagStrategy, - ListNodesStrategy listNodesStrategy, @Named("NAMING_CONVENTION") String nodeNamingConvention, - ComputeUtils utils, @Named(Constants.PROPERTY_USER_THREADS) ExecutorService executor, - IBMDeveloperCloudClient client, @Named("CREDENTIALS") Map credentialsMap) { + ListNodesStrategy listNodesStrategy, @Named("NAMING_CONVENTION") String nodeNamingConvention, + ComputeUtils utils, @Named(Constants.PROPERTY_USER_THREADS) ExecutorService executor, + IBMDeveloperCloudClient client, @Named("CREDENTIALS") Map credentialsMap) { super(addNodeWithTagStrategy, listNodesStrategy, nodeNamingConvention, utils, executor); this.client = checkNotNull(client, "client"); this.credentialsMap = checkNotNull(credentialsMap, "credentialsMap"); @@ -62,15 +59,9 @@ public class CreateKeyPairEncodeTagIntoNameRunNodesAndAddToSet extends EncodeTag @Override public Map> execute(String tag, int count, Template template, Set nodes, - Map badNodes) { - Payload key = template.getOptions().getPublicKey(); - if (key != null) { - String keyAsText; - try { - keyAsText = Utils.toStringAndClose(key.getInput()); - } catch (IOException e1) { - throw new RuntimeException(e1); - } + Map badNodes) { + String keyAsText = template.getOptions().getPublicKey(); + if (keyAsText != null) { template.getOptions().dontAuthorizePublicKey(); try { client.addPublicKey(tag, keyAsText); diff --git a/sandbox/ibmdev/src/main/java/org/jclouds/ibmdev/compute/strategy/IBMDeveloperCloudAddNodeWithTagStrategy.java b/sandbox/ibmdev/src/main/java/org/jclouds/ibmdev/compute/strategy/IBMDeveloperCloudAddNodeWithTagStrategy.java index 92ef5fefcc..b7ddecac5b 100644 --- a/sandbox/ibmdev/src/main/java/org/jclouds/ibmdev/compute/strategy/IBMDeveloperCloudAddNodeWithTagStrategy.java +++ b/sandbox/ibmdev/src/main/java/org/jclouds/ibmdev/compute/strategy/IBMDeveloperCloudAddNodeWithTagStrategy.java @@ -29,8 +29,6 @@ import org.jclouds.compute.domain.NodeMetadata; import org.jclouds.compute.domain.Template; import org.jclouds.compute.strategy.AddNodeWithTagStrategy; import org.jclouds.ibmdev.IBMDeveloperCloudClient; -import org.jclouds.ibmdev.compute.domain.IBMImage; -import org.jclouds.ibmdev.compute.domain.IBMSize; import org.jclouds.ibmdev.domain.Instance; import com.google.common.base.Function; @@ -46,16 +44,15 @@ public class IBMDeveloperCloudAddNodeWithTagStrategy implements AddNodeWithTagSt @Inject protected IBMDeveloperCloudAddNodeWithTagStrategy(IBMDeveloperCloudClient client, - Function instanceToNodeMetadata) { + Function instanceToNodeMetadata) { this.client = checkNotNull(client, "client"); this.instanceToNodeMetadata = checkNotNull(instanceToNodeMetadata, "instanceToNodeMetadata"); } @Override - public NodeMetadata execute(String tag, String name, Template template) { - Instance instance = client.createInstanceInLocation(template.getLocation().getId(), name, IBMImage.class.cast( - template.getImage()).getRawImage().getId(), IBMSize.class.cast(template.getSize()).getInstanceType() - .getId(), authorizePublicKey(tag)); + public NodeMetadata addNodeWithTag(String tag, String name, Template template) { + Instance instance = client.createInstanceInLocation(template.getLocation().getId(), name, template.getImage() + .getProviderId(), template.getHardware().getProviderId(), authorizePublicKey(tag)); return instanceToNodeMetadata.apply(client.getInstance(instance.getId())); } } \ No newline at end of file diff --git a/sandbox/ibmdev/src/main/java/org/jclouds/ibmdev/compute/strategy/IBMDeveloperCloudDestroyNodeStrategy.java b/sandbox/ibmdev/src/main/java/org/jclouds/ibmdev/compute/strategy/IBMDeveloperCloudDestroyNodeStrategy.java index 721e04a4c3..d58189355f 100644 --- a/sandbox/ibmdev/src/main/java/org/jclouds/ibmdev/compute/strategy/IBMDeveloperCloudDestroyNodeStrategy.java +++ b/sandbox/ibmdev/src/main/java/org/jclouds/ibmdev/compute/strategy/IBMDeveloperCloudDestroyNodeStrategy.java @@ -44,8 +44,8 @@ public class IBMDeveloperCloudDestroyNodeStrategy implements DestroyNodeStrategy } @Override - public NodeMetadata execute(String id) { + public NodeMetadata destroyNode(String id) { client.deleteInstance(id); - return getNode.execute(id); + return getNode.getNode(id); } } \ No newline at end of file diff --git a/sandbox/ibmdev/src/main/java/org/jclouds/ibmdev/compute/strategy/IBMDeveloperCloudGetNodeMetadataStrategy.java b/sandbox/ibmdev/src/main/java/org/jclouds/ibmdev/compute/strategy/IBMDeveloperCloudGetNodeMetadataStrategy.java index 842a79a5f6..e550be76b5 100644 --- a/sandbox/ibmdev/src/main/java/org/jclouds/ibmdev/compute/strategy/IBMDeveloperCloudGetNodeMetadataStrategy.java +++ b/sandbox/ibmdev/src/main/java/org/jclouds/ibmdev/compute/strategy/IBMDeveloperCloudGetNodeMetadataStrategy.java @@ -47,7 +47,7 @@ public class IBMDeveloperCloudGetNodeMetadataStrategy implements GetNodeMetadata } @Override - public NodeMetadata execute(String id) { + public NodeMetadata getNode(String id) { Instance instance = client.getInstance(checkNotNull(id, "id")); return instance == null ? null : instanceToNodeMetadata.apply(instance); } diff --git a/sandbox/ibmdev/src/main/java/org/jclouds/ibmdev/compute/strategy/IBMDeveloperCloudRebootNodeStrategy.java b/sandbox/ibmdev/src/main/java/org/jclouds/ibmdev/compute/strategy/IBMDeveloperCloudLifeCycleStrategy.java similarity index 67% rename from sandbox/ibmdev/src/main/java/org/jclouds/ibmdev/compute/strategy/IBMDeveloperCloudRebootNodeStrategy.java rename to sandbox/ibmdev/src/main/java/org/jclouds/ibmdev/compute/strategy/IBMDeveloperCloudLifeCycleStrategy.java index a2d53ab83e..3660c04e5e 100644 --- a/sandbox/ibmdev/src/main/java/org/jclouds/ibmdev/compute/strategy/IBMDeveloperCloudRebootNodeStrategy.java +++ b/sandbox/ibmdev/src/main/java/org/jclouds/ibmdev/compute/strategy/IBMDeveloperCloudLifeCycleStrategy.java @@ -27,26 +27,38 @@ import javax.inject.Singleton; import org.jclouds.compute.domain.NodeMetadata; import org.jclouds.compute.strategy.GetNodeMetadataStrategy; import org.jclouds.compute.strategy.RebootNodeStrategy; +import org.jclouds.compute.strategy.ResumeNodeStrategy; +import org.jclouds.compute.strategy.SuspendNodeStrategy; import org.jclouds.ibmdev.IBMDeveloperCloudClient; /** * @author Adrian Cole */ @Singleton -public class IBMDeveloperCloudRebootNodeStrategy implements RebootNodeStrategy { +public class IBMDeveloperCloudLifeCycleStrategy implements RebootNodeStrategy, SuspendNodeStrategy, ResumeNodeStrategy { private final IBMDeveloperCloudClient client; private final GetNodeMetadataStrategy getNode; @Inject - protected IBMDeveloperCloudRebootNodeStrategy(IBMDeveloperCloudClient client, GetNodeMetadataStrategy getNode) { + protected IBMDeveloperCloudLifeCycleStrategy(IBMDeveloperCloudClient client, GetNodeMetadataStrategy getNode) { this.client = checkNotNull(client, "client"); this.getNode = checkNotNull(getNode, "getNode"); } @Override - public NodeMetadata execute(String id) { + public NodeMetadata rebootNode(String id) { client.restartInstance(id); - return getNode.execute(id); + return getNode.getNode(id); + } + + @Override + public NodeMetadata suspendNode(String id) { + throw new UnsupportedOperationException("suspend not supported"); + } + + @Override + public NodeMetadata resumeNode(String id) { + throw new UnsupportedOperationException("resume not supported"); } } \ No newline at end of file diff --git a/sandbox/ibmdev/src/main/java/org/jclouds/ibmdev/compute/strategy/IBMDeveloperCloudListNodesStrategy.java b/sandbox/ibmdev/src/main/java/org/jclouds/ibmdev/compute/strategy/IBMDeveloperCloudListNodesStrategy.java index ef2b3da814..5be45efa54 100644 --- a/sandbox/ibmdev/src/main/java/org/jclouds/ibmdev/compute/strategy/IBMDeveloperCloudListNodesStrategy.java +++ b/sandbox/ibmdev/src/main/java/org/jclouds/ibmdev/compute/strategy/IBMDeveloperCloudListNodesStrategy.java @@ -43,13 +43,13 @@ public class IBMDeveloperCloudListNodesStrategy implements ListNodesStrategy { @Inject protected IBMDeveloperCloudListNodesStrategy(IBMDeveloperCloudClient client, - Function instanceToNodeMetadata) { + Function instanceToNodeMetadata) { this.client = client; this.instanceToNodeMetadata = instanceToNodeMetadata; } @Override - public Iterable list() { + public Iterable listNodes() { return listDetailsOnNodesMatching(NodePredicates.all()); } diff --git a/sandbox/ibmdev/src/main/java/org/jclouds/ibmdev/compute/suppliers/IBMDeveloperCloudHardwareSupplier.java b/sandbox/ibmdev/src/main/java/org/jclouds/ibmdev/compute/suppliers/IBMDeveloperCloudHardwareSupplier.java new file mode 100644 index 0000000000..aca47417ab --- /dev/null +++ b/sandbox/ibmdev/src/main/java/org/jclouds/ibmdev/compute/suppliers/IBMDeveloperCloudHardwareSupplier.java @@ -0,0 +1,86 @@ +/** + * + * 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.ibmdev.compute.suppliers; + +import java.util.Map; +import java.util.Set; + +import javax.annotation.Resource; +import javax.inject.Inject; +import javax.inject.Named; +import javax.inject.Singleton; + +import org.jclouds.compute.domain.Hardware; +import org.jclouds.compute.domain.HardwareBuilder; +import org.jclouds.compute.domain.Processor; +import org.jclouds.compute.domain.Volume; +import org.jclouds.compute.domain.internal.VolumeImpl; +import org.jclouds.compute.reference.ComputeServiceConstants; +import org.jclouds.domain.Location; +import org.jclouds.ibmdev.IBMDeveloperCloudClient; +import org.jclouds.ibmdev.domain.InstanceType; +import org.jclouds.logging.Logger; + +import com.google.common.base.Supplier; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.Sets; + +/** + * @author Adrian Cole + */ +@Singleton +public class IBMDeveloperCloudHardwareSupplier implements Supplier> { + + @Resource + @Named(ComputeServiceConstants.COMPUTE_LOGGER) + protected Logger logger = Logger.NULL; + private final IBMDeveloperCloudClient sync; + private final Supplier> locations; + + @Inject + IBMDeveloperCloudHardwareSupplier(IBMDeveloperCloudClient sync, Supplier> locations) { + this.sync = sync; + this.locations = locations; + } + + @Override + public Set get() { + final Set hardware = Sets.newHashSet(); + logger.debug(">> providing hardware"); + for (org.jclouds.ibmdev.domain.Image image : sync.listImages()) { + for (InstanceType instanceType : image.getSupportedInstanceTypes()) { + hardware.add(new HardwareBuilder() + .id(image.getId() + "/" + instanceType.getId()) + .providerId(image.getId()) + .name(instanceType.getLabel()) + .location(locations.get().get(image.getLocation())) + .uri(image.getManifest()) + .processors(ImmutableList.of(new Processor((instanceType.getPrice().getRate() * 100), 1.0))) + .ram((int) instanceType.getPrice().getRate() * 1024) + .volumes( + ImmutableList. of(new VolumeImpl((float) (instanceType.getPrice().getRate() * 100d), + true, true))).build()); + + } + } + logger.debug("<< hardware(%d)", hardware.size()); + return hardware; + } +} \ No newline at end of file diff --git a/sandbox/ibmdev/src/main/java/org/jclouds/ibmdev/compute/suppliers/IBMDeveloperCloudImageSupplier.java b/sandbox/ibmdev/src/main/java/org/jclouds/ibmdev/compute/suppliers/IBMDeveloperCloudImageSupplier.java index a2dadc255a..0f023ec402 100644 --- a/sandbox/ibmdev/src/main/java/org/jclouds/ibmdev/compute/suppliers/IBMDeveloperCloudImageSupplier.java +++ b/sandbox/ibmdev/src/main/java/org/jclouds/ibmdev/compute/suppliers/IBMDeveloperCloudImageSupplier.java @@ -28,10 +28,13 @@ import javax.inject.Named; import javax.inject.Singleton; import org.jclouds.compute.domain.Image; +import org.jclouds.compute.domain.ImageBuilder; +import org.jclouds.compute.domain.OperatingSystemBuilder; +import org.jclouds.compute.domain.OsFamily; import org.jclouds.compute.reference.ComputeServiceConstants; +import org.jclouds.domain.Credentials; import org.jclouds.domain.Location; import org.jclouds.ibmdev.IBMDeveloperCloudClient; -import org.jclouds.ibmdev.compute.domain.IBMImage; import org.jclouds.logging.Logger; import com.google.common.base.Supplier; @@ -51,7 +54,7 @@ public class IBMDeveloperCloudImageSupplier implements Supplier> locations) { + Supplier> locations) { this.sync = sync; this.locations = locations; } @@ -61,11 +64,24 @@ public class IBMDeveloperCloudImageSupplier implements Supplier images = Sets.newHashSet(); logger.debug(">> providing images"); - for (org.jclouds.ibmdev.domain.Image image : sync.listImages()) - images.add(new IBMImage(image, locations.get().get(image.getLocation()))); + for (org.jclouds.ibmdev.domain.Image image : sync.listImages()) { + // TODO parse correct OS + // TODO manifest fails to parse due to encoding issues in the path + // TODO get correct default credentials + // http://www-180.ibm.com/cloud/enterprise/beta/ram/community/_rlvid.jsp.faces?_rap=pc_DiscussionForum.doDiscussionTopic&_rvip=/community/discussionForum.jsp&guid={DA689AEE-783C-6FE7-6F9F-DFEE9763F806}&v=1&submission=false&fid=1068&tid=1527 + images.add(new ImageBuilder() + .ids(image.getId()) + .name(image.getName()) + .location(locations.get().get(image.getLocation())) + .operatingSystem( + new OperatingSystemBuilder() + .family((image.getPlatform().indexOf("Red Hat") != -1) ? OsFamily.RHEL : OsFamily.SUSE) + .arch(image.getPlatform()).is64Bit(image.getPlatform().indexOf("32") == -1).build()) + .description(image.getDescription()).version(image.getCreatedTime().getTime() + "") + .defaultCredentials(new Credentials("idcuser", null)).build()); + } logger.debug("<< images(%d)", images.size()); return images; } - } \ No newline at end of file diff --git a/sandbox/ibmdev/src/main/java/org/jclouds/ibmdev/compute/suppliers/IBMDeveloperCloudSizeSupplier.java b/sandbox/ibmdev/src/main/java/org/jclouds/ibmdev/compute/suppliers/IBMDeveloperCloudSizeSupplier.java deleted file mode 100644 index a0132b6541..0000000000 --- a/sandbox/ibmdev/src/main/java/org/jclouds/ibmdev/compute/suppliers/IBMDeveloperCloudSizeSupplier.java +++ /dev/null @@ -1,68 +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.ibmdev.compute.suppliers; - -import java.util.Set; - -import javax.annotation.Resource; -import javax.inject.Inject; -import javax.inject.Named; -import javax.inject.Singleton; - -import org.jclouds.compute.domain.Image; -import org.jclouds.compute.domain.Size; -import org.jclouds.compute.reference.ComputeServiceConstants; -import org.jclouds.ibmdev.compute.domain.IBMImage; -import org.jclouds.ibmdev.compute.domain.IBMSize; -import org.jclouds.ibmdev.domain.InstanceType; -import org.jclouds.logging.Logger; - -import com.google.common.base.Supplier; -import com.google.common.collect.Sets; - -/** - * @author Adrian Cole - */ -@Singleton -public class IBMDeveloperCloudSizeSupplier implements Supplier> { - - @Resource - @Named(ComputeServiceConstants.COMPUTE_LOGGER) - protected Logger logger = Logger.NULL; - private final Supplier> images; - - @Inject - IBMDeveloperCloudSizeSupplier(Supplier> images) { - this.images = images; - } - - @Override - public Set get() { - final Set sizes = Sets.newHashSet(); - logger.debug(">> providing sizes"); - for (Image in : images.get()) { - IBMImage image = IBMImage.class.cast(in); - for (InstanceType instanceType : image.getRawImage().getSupportedInstanceTypes()) - sizes.add(new IBMSize(image, instanceType)); - } - logger.debug("<< sizes(%d)", sizes.size()); - return sizes; - } -} \ No newline at end of file diff --git a/sandbox/ibmdev/src/main/java/org/jclouds/ibmdev/handlers/IBMDeveloperCloudErrorHandler.java b/sandbox/ibmdev/src/main/java/org/jclouds/ibmdev/handlers/IBMDeveloperCloudErrorHandler.java index 076f227c2a..9a0f657723 100644 --- a/sandbox/ibmdev/src/main/java/org/jclouds/ibmdev/handlers/IBMDeveloperCloudErrorHandler.java +++ b/sandbox/ibmdev/src/main/java/org/jclouds/ibmdev/handlers/IBMDeveloperCloudErrorHandler.java @@ -56,8 +56,7 @@ public class IBMDeveloperCloudErrorHandler implements HttpErrorHandler { response.getStatusLine()); switch (response.getStatusCode()) { case 401: - exception = new AuthorizationException(command.getRequest(), message != null ? message : response - .getStatusLine()); + exception = new AuthorizationException(exception.getMessage(), exception); break; case 402: case 403: diff --git a/sandbox/ibmdev/src/test/java/org/jclouds/ibmdev/IBMDeveloperCloudAsyncClientTest.java b/sandbox/ibmdev/src/test/java/org/jclouds/ibmdev/IBMDeveloperCloudAsyncClientTest.java index 2758670dc5..e73691f7ad 100644 --- a/sandbox/ibmdev/src/test/java/org/jclouds/ibmdev/IBMDeveloperCloudAsyncClientTest.java +++ b/sandbox/ibmdev/src/test/java/org/jclouds/ibmdev/IBMDeveloperCloudAsyncClientTest.java @@ -50,7 +50,7 @@ import org.jclouds.ibmdev.xml.LocationHandler; import org.jclouds.ibmdev.xml.LocationsHandler; import org.jclouds.rest.RestClientTest; import org.jclouds.rest.RestContextFactory; -import org.jclouds.rest.RestContextFactory.ContextSpec; +import org.jclouds.rest.RestContextSpec; import org.jclouds.rest.functions.ReturnEmptySetOnNotFoundOr404; import org.jclouds.rest.functions.ReturnNullOnNotFoundOr404; import org.jclouds.rest.functions.ReturnVoidOnNotFoundOr404; @@ -660,7 +660,7 @@ public class IBMDeveloperCloudAsyncClientTest extends RestClientTest createContextSpec() { + public RestContextSpec createContextSpec() { return new RestContextFactory().createContextSpec("ibmdev", "identity", "credential", new Properties()); } } diff --git a/sandbox/ibmdev/src/test/java/org/jclouds/ibmdev/IBMDeveloperCloudClientLiveTest.java b/sandbox/ibmdev/src/test/java/org/jclouds/ibmdev/IBMDeveloperCloudClientLiveTest.java index 248b20713e..8c952e9237 100644 --- a/sandbox/ibmdev/src/test/java/org/jclouds/ibmdev/IBMDeveloperCloudClientLiveTest.java +++ b/sandbox/ibmdev/src/test/java/org/jclouds/ibmdev/IBMDeveloperCloudClientLiveTest.java @@ -41,14 +41,14 @@ import org.jclouds.http.handlers.BackoffLimitedRetryHandler; import org.jclouds.ibmdev.domain.Address; import org.jclouds.ibmdev.domain.Image; import org.jclouds.ibmdev.domain.Instance; +import org.jclouds.ibmdev.domain.Instance.Software; import org.jclouds.ibmdev.domain.InstanceType; import org.jclouds.ibmdev.domain.Key; import org.jclouds.ibmdev.domain.Location; import org.jclouds.ibmdev.domain.Offering; import org.jclouds.ibmdev.domain.StorageOffering; -import org.jclouds.ibmdev.domain.Volume; -import org.jclouds.ibmdev.domain.Instance.Software; import org.jclouds.ibmdev.domain.StorageOffering.Format; +import org.jclouds.ibmdev.domain.Volume; import org.jclouds.ibmdev.predicates.AddressFree; import org.jclouds.ibmdev.predicates.InstanceActive; import org.jclouds.ibmdev.predicates.InstanceActiveOrFailed; @@ -56,6 +56,7 @@ import org.jclouds.ibmdev.predicates.InstanceRemovedOrNotFound; import org.jclouds.ibmdev.predicates.VolumeUnmounted; import org.jclouds.logging.log4j.config.Log4JLoggingModule; import org.jclouds.net.IPSocket; +import org.jclouds.predicates.InetSocketAddressConnect; import org.jclouds.predicates.RetryablePredicate; import org.jclouds.rest.RestContext; import org.jclouds.rest.RestContextFactory; @@ -63,7 +64,6 @@ import org.jclouds.ssh.ExecResponse; import org.jclouds.ssh.SshClient; import org.jclouds.ssh.SshException; import org.jclouds.ssh.jsch.JschSshClient; -import org.jclouds.ssh.jsch.predicates.InetSocketAddressConnect; import org.testng.annotations.AfterTest; import org.testng.annotations.BeforeGroups; import org.testng.annotations.Test; diff --git a/sandbox/ibmdev/src/test/java/org/jclouds/ibmdev/compute/IBMDeveloperCloudComputeServiceLiveTestDisabled.java b/sandbox/ibmdev/src/test/java/org/jclouds/ibmdev/compute/IBMDeveloperCloudComputeServiceLiveTestDisabled.java index e1c519f1d2..f0eeefb72f 100644 --- a/sandbox/ibmdev/src/test/java/org/jclouds/ibmdev/compute/IBMDeveloperCloudComputeServiceLiveTestDisabled.java +++ b/sandbox/ibmdev/src/test/java/org/jclouds/ibmdev/compute/IBMDeveloperCloudComputeServiceLiveTestDisabled.java @@ -19,6 +19,7 @@ package org.jclouds.ibmdev.compute; +import static org.jclouds.compute.util.ComputeServiceUtils.getCores; import static org.testng.Assert.assertEquals; import org.jclouds.compute.BaseComputeServiceLiveTest; @@ -52,7 +53,7 @@ public class IBMDeveloperCloudComputeServiceLiveTestDisabled extends BaseCompute assertEquals(defaultTemplate.getImage().getOperatingSystem().is64Bit(), false); assertEquals(defaultTemplate.getImage().getOperatingSystem().getFamily(), OsFamily.SUSE); assertEquals(defaultTemplate.getLocation().getId(), "1"); - assertEquals(defaultTemplate.getSize().getCores(), 2.0d); + assertEquals(getCores(defaultTemplate.getHardware()), 2.0d); } @Override diff --git a/sandbox/ibmdev/src/test/java/org/jclouds/ibmdev/compute/IBMDeveloperCloudTemplateBuilderLiveTest.java b/sandbox/ibmdev/src/test/java/org/jclouds/ibmdev/compute/IBMDeveloperCloudTemplateBuilderLiveTest.java new file mode 100644 index 0000000000..d4681621ce --- /dev/null +++ b/sandbox/ibmdev/src/test/java/org/jclouds/ibmdev/compute/IBMDeveloperCloudTemplateBuilderLiveTest.java @@ -0,0 +1,34 @@ +package org.jclouds.ibmdev.compute; + +import org.jclouds.compute.BaseTemplateBuilderLiveTest; +import org.jclouds.compute.OsFamilyVersion64Bit; +import org.jclouds.compute.domain.OsFamily; +import org.testng.annotations.Test; + +import com.google.common.base.Predicate; + +/** + * + * @author Adrian Cole + */ +@Test(groups = "live", testName = "ibmdev.IBMDeveloperCloudTemplateBuilderLiveTest") +public class IBMDeveloperCloudTemplateBuilderLiveTest extends BaseTemplateBuilderLiveTest { + + public IBMDeveloperCloudTemplateBuilderLiveTest() { + provider = "ibmdev"; + } + + @Override + protected Predicate defineUnsupportedOperatingSystems() { + return new Predicate() { + + @Override + public boolean apply(OsFamilyVersion64Bit input) { + return input.family != OsFamily.RHEL && // + input.family != OsFamily.SUSE && // + input.family != OsFamily.WINDOWS; + } + + }; + } +} \ No newline at end of file diff --git a/sandbox/ibmdev/src/test/java/org/jclouds/ibmdev/compute/config/IBMDeveloperCloudComputeServiceContextModuleTest.java b/sandbox/ibmdev/src/test/java/org/jclouds/ibmdev/compute/config/IBMDeveloperCloudComputeServiceDependenciesModuleTest.java similarity index 83% rename from sandbox/ibmdev/src/test/java/org/jclouds/ibmdev/compute/config/IBMDeveloperCloudComputeServiceContextModuleTest.java rename to sandbox/ibmdev/src/test/java/org/jclouds/ibmdev/compute/config/IBMDeveloperCloudComputeServiceDependenciesModuleTest.java index 25040c356b..78fe281317 100644 --- a/sandbox/ibmdev/src/test/java/org/jclouds/ibmdev/compute/config/IBMDeveloperCloudComputeServiceContextModuleTest.java +++ b/sandbox/ibmdev/src/test/java/org/jclouds/ibmdev/compute/config/IBMDeveloperCloudComputeServiceDependenciesModuleTest.java @@ -25,13 +25,13 @@ import org.testng.annotations.Test; /** * @author Adrian Cole */ -@Test(groups = "unit", testName = "ibmdev.IBMDeveloperCloudComputeServiceContextModuleTest") -public class IBMDeveloperCloudComputeServiceContextModuleTest { +@Test(groups = "unit", testName = "ibmdev.IBMDeveloperCloudComputeServiceDependenciesModuleTest") +public class IBMDeveloperCloudComputeServiceDependenciesModuleTest { public void testAllStatusCovered() { for (Instance.Status state : Instance.Status.values()) { - assert IBMDeveloperCloudComputeServiceContextModule.instanceStatusToNodeState.containsKey(state) : state; + assert IBMDeveloperCloudComputeServiceDependenciesModule.instanceStatusToNodeState.containsKey(state) : state; } } diff --git a/sandbox/ning/pom.xml b/sandbox/ning/pom.xml index 0cd3b31c10..d24559668c 100644 --- a/sandbox/ning/pom.xml +++ b/sandbox/ning/pom.xml @@ -42,13 +42,7 @@ com.ning async-http-client - 1.3.1 - - - com.google.collections - google-collections - - + 1.4.0 org.mortbay.jetty diff --git a/sandbox/ning/src/main/java/org/jclouds/http/ning/NingHttpCommandExecutorService.java b/sandbox/ning/src/main/java/org/jclouds/http/ning/NingHttpCommandExecutorService.java index fef934692f..a99212590b 100644 --- a/sandbox/ning/src/main/java/org/jclouds/http/ning/NingHttpCommandExecutorService.java +++ b/sandbox/ning/src/main/java/org/jclouds/http/ning/NingHttpCommandExecutorService.java @@ -19,33 +19,6 @@ package org.jclouds.http.ning; -import static com.google.common.base.Preconditions.checkNotNull; -import static com.google.common.base.Throwables.propagate; - -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.util.List; -import java.util.Map.Entry; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.Future; - -import javax.inject.Singleton; -import javax.ws.rs.core.HttpHeaders; - -import org.jclouds.crypto.CryptoStreams; -import org.jclouds.http.HttpCommand; -import org.jclouds.http.HttpCommandExecutorService; -import org.jclouds.http.HttpRequest; -import org.jclouds.http.HttpRequestFilter; -import org.jclouds.http.HttpResponse; -import org.jclouds.http.HttpUtils; -import org.jclouds.http.handlers.DelegatingErrorHandler; -import org.jclouds.http.handlers.DelegatingRetryHandler; -import org.jclouds.http.internal.BaseHttpCommandExecutorService; -import org.jclouds.io.Payload; -import org.jclouds.io.Payloads; - import com.google.common.base.Function; import com.google.common.base.Throwables; import com.google.common.collect.LinkedHashMultimap; @@ -59,7 +32,31 @@ import com.ning.http.client.AsyncHttpClient; import com.ning.http.client.Request; import com.ning.http.client.RequestBuilder; import com.ning.http.client.Response; -import com.ning.http.client.Request.EntityWriter; +import org.jclouds.crypto.CryptoStreams; +import org.jclouds.http.HttpCommand; +import org.jclouds.http.HttpCommandExecutorService; +import org.jclouds.http.HttpRequest; +import org.jclouds.http.HttpRequestFilter; +import org.jclouds.http.HttpResponse; +import org.jclouds.http.HttpUtils; +import org.jclouds.http.handlers.DelegatingErrorHandler; +import org.jclouds.http.handlers.DelegatingRetryHandler; +import org.jclouds.http.internal.BaseHttpCommandExecutorService; +import org.jclouds.io.Payload; +import org.jclouds.io.Payloads; +import org.jclouds.io.payloads.FilePayload; + +import javax.inject.Singleton; +import javax.ws.rs.core.HttpHeaders; +import java.io.IOException; +import java.io.InputStream; +import java.util.List; +import java.util.Map.Entry; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.Future; + +import static com.google.common.base.Preconditions.checkNotNull; +import static com.google.common.base.Throwables.propagate; /** * Todo Write me @@ -128,21 +125,7 @@ public class NingHttpCommandExecutorService implements HttpCommandExecutorServic @Singleton public static class ConvertToNingRequest implements Function { - private static class PayloadEntityWriter implements EntityWriter { - private final Payload payload; - - public PayloadEntityWriter(Payload payload) { - this.payload = payload; - } - - @Override - public void writeEntity(OutputStream out) throws IOException { - payload.writeTo(out); - - } - } - - public Request apply(HttpRequest request) { + public Request apply(HttpRequest request) { for (HttpRequestFilter filter : request.getFilters()) { filter.filter(request); @@ -188,9 +171,13 @@ public class NingHttpCommandExecutorService implements HttpCommandExecutorServic return builder.build(); } - void setPayload(RequestBuilder requestBuilder, Payload payload) { - requestBuilder.setBody(new PayloadEntityWriter(payload)); - } + void setPayload(RequestBuilder requestBuilder, Payload payload) { + if (payload instanceof FilePayload) { + requestBuilder.setBody(((FilePayload) payload).getRawContent()); + } else { + requestBuilder.setBody(payload.getInput()); + } + } } @Singleton diff --git a/sandbox/ning/src/test/java/org/jclouds/http/ning/NingHttpCommandExecutorServiceTest.java b/sandbox/ning/src/test/java/org/jclouds/http/ning/NingHttpCommandExecutorServiceTest.java index 527c301cc7..7fe8eb1774 100644 --- a/sandbox/ning/src/test/java/org/jclouds/http/ning/NingHttpCommandExecutorServiceTest.java +++ b/sandbox/ning/src/test/java/org/jclouds/http/ning/NingHttpCommandExecutorServiceTest.java @@ -62,10 +62,4 @@ public class NingHttpCommandExecutorServiceTest extends BaseHttpCommandExecutorS props.setProperty(PROPERTY_IO_WORKER_THREADS, 3 + ""); props.setProperty(PROPERTY_USER_THREADS, 0 + ""); } - - // OOM - @Test(enabled = false, invocationCount = 1, timeOut = 5000) - public void testGetBigFile() throws ExecutionException, InterruptedException, TimeoutException, IOException { - } - -} \ No newline at end of file +} diff --git a/tools/antcontrib/samples/cargooverssh/build.xml b/tools/antcontrib/samples/cargooverssh/build.xml index c61ea8afe7..75fd1444f2 100644 --- a/tools/antcontrib/samples/cargooverssh/build.xml +++ b/tools/antcontrib/samples/cargooverssh/build.xml @@ -58,8 +58,8 @@ - - + + diff --git a/vcloud/core/src/main/java/org/jclouds/vcloud/compute/strategy/VCloudExpressListNodesStrategy.java b/vcloud/core/src/main/java/org/jclouds/vcloud/compute/strategy/VCloudExpressListNodesStrategy.java index 206ed9ff2d..7452357933 100644 --- a/vcloud/core/src/main/java/org/jclouds/vcloud/compute/strategy/VCloudExpressListNodesStrategy.java +++ b/vcloud/core/src/main/java/org/jclouds/vcloud/compute/strategy/VCloudExpressListNodesStrategy.java @@ -45,9 +45,9 @@ import com.google.common.annotations.VisibleForTesting; import com.google.common.base.Predicate; import com.google.common.base.Splitter; import com.google.common.base.Supplier; +import com.google.common.collect.ImmutableSet; import com.google.common.collect.Sets; import com.google.inject.Inject; -import com.google.inject.internal.util.ImmutableSet; /** * @author Adrian Cole diff --git a/vcloud/core/src/main/java/org/jclouds/vcloud/compute/strategy/VCloudListNodesStrategy.java b/vcloud/core/src/main/java/org/jclouds/vcloud/compute/strategy/VCloudListNodesStrategy.java index 6d5751ca4e..1963dbdbba 100644 --- a/vcloud/core/src/main/java/org/jclouds/vcloud/compute/strategy/VCloudListNodesStrategy.java +++ b/vcloud/core/src/main/java/org/jclouds/vcloud/compute/strategy/VCloudListNodesStrategy.java @@ -45,9 +45,9 @@ import com.google.common.annotations.VisibleForTesting; import com.google.common.base.Predicate; import com.google.common.base.Splitter; import com.google.common.base.Supplier; +import com.google.common.collect.ImmutableSet; import com.google.common.collect.Sets; import com.google.inject.Inject; -import com.google.inject.internal.util.ImmutableSet; /** * @author Adrian Cole diff --git a/vcloud/core/src/main/java/org/jclouds/vcloud/compute/util/VCloudComputeUtils.java b/vcloud/core/src/main/java/org/jclouds/vcloud/compute/util/VCloudComputeUtils.java index f737bb4f92..d2c195257e 100644 --- a/vcloud/core/src/main/java/org/jclouds/vcloud/compute/util/VCloudComputeUtils.java +++ b/vcloud/core/src/main/java/org/jclouds/vcloud/compute/util/VCloudComputeUtils.java @@ -37,7 +37,7 @@ import org.jclouds.vcloud.domain.ovf.ResourceType; import org.jclouds.vcloud.domain.ovf.VCloudNetworkAdapter; import com.google.common.collect.Iterables; -import com.google.inject.internal.util.Sets; +import com.google.common.collect.Sets; /** * diff --git a/vcloud/core/src/main/java/org/jclouds/vcloud/domain/internal/CatalogImpl.java b/vcloud/core/src/main/java/org/jclouds/vcloud/domain/internal/CatalogImpl.java index df2c8c4512..3314216f09 100644 --- a/vcloud/core/src/main/java/org/jclouds/vcloud/domain/internal/CatalogImpl.java +++ b/vcloud/core/src/main/java/org/jclouds/vcloud/domain/internal/CatalogImpl.java @@ -26,13 +26,14 @@ import java.util.LinkedHashMap; import java.util.List; import java.util.Map; +import javax.annotation.Nullable; + import org.jclouds.vcloud.domain.Catalog; import org.jclouds.vcloud.domain.ReferenceType; import org.jclouds.vcloud.domain.Task; import com.google.common.collect.Iterables; import com.google.common.collect.Lists; -import com.google.inject.internal.Nullable; /** * Locations of resources in vCloud diff --git a/vcloud/core/src/main/java/org/jclouds/vcloud/domain/internal/ErrorImpl.java b/vcloud/core/src/main/java/org/jclouds/vcloud/domain/internal/ErrorImpl.java index 1b25c3e9e7..f1d198a229 100644 --- a/vcloud/core/src/main/java/org/jclouds/vcloud/domain/internal/ErrorImpl.java +++ b/vcloud/core/src/main/java/org/jclouds/vcloud/domain/internal/ErrorImpl.java @@ -21,9 +21,9 @@ package org.jclouds.vcloud.domain.internal; import static com.google.common.base.Preconditions.checkNotNull; -import org.jclouds.vcloud.domain.VCloudError; +import javax.annotation.Nullable; -import com.google.inject.internal.Nullable; +import org.jclouds.vcloud.domain.VCloudError; /** * diff --git a/vcloud/core/src/main/java/org/jclouds/vcloud/domain/internal/TaskImpl.java b/vcloud/core/src/main/java/org/jclouds/vcloud/domain/internal/TaskImpl.java index 61a6fe4843..de1287459c 100644 --- a/vcloud/core/src/main/java/org/jclouds/vcloud/domain/internal/TaskImpl.java +++ b/vcloud/core/src/main/java/org/jclouds/vcloud/domain/internal/TaskImpl.java @@ -24,13 +24,13 @@ import static com.google.common.base.Preconditions.checkNotNull; import java.net.URI; import java.util.Date; +import javax.annotation.Nullable; + import org.jclouds.vcloud.VCloudMediaType; -import org.jclouds.vcloud.domain.VCloudError; import org.jclouds.vcloud.domain.ReferenceType; import org.jclouds.vcloud.domain.Task; import org.jclouds.vcloud.domain.TaskStatus; - -import com.google.inject.internal.Nullable; +import org.jclouds.vcloud.domain.VCloudError; /** * diff --git a/vcloud/core/src/main/java/org/jclouds/vcloud/domain/network/internal/VCloudExpressNetworkImpl.java b/vcloud/core/src/main/java/org/jclouds/vcloud/domain/network/internal/VCloudExpressNetworkImpl.java index 17f2023439..f0845b53f4 100644 --- a/vcloud/core/src/main/java/org/jclouds/vcloud/domain/network/internal/VCloudExpressNetworkImpl.java +++ b/vcloud/core/src/main/java/org/jclouds/vcloud/domain/network/internal/VCloudExpressNetworkImpl.java @@ -22,6 +22,8 @@ package org.jclouds.vcloud.domain.network.internal; import java.net.URI; import java.util.Set; +import javax.annotation.Nullable; + import org.jclouds.vcloud.domain.ReferenceType; import org.jclouds.vcloud.domain.internal.ReferenceTypeImpl; import org.jclouds.vcloud.domain.network.FenceMode; @@ -30,7 +32,6 @@ import org.jclouds.vcloud.domain.network.firewall.FirewallRule; import org.jclouds.vcloud.domain.network.nat.rules.PortForwardingRule; import com.google.common.collect.Sets; -import com.google.inject.internal.Nullable; /** * Locations of resources in vCloud diff --git a/vcloud/terremark/src/main/java/org/jclouds/vcloud/terremark/binders/TerremarkBindInstantiateVAppTemplateParamsToXmlPayload.java b/vcloud/terremark/src/main/java/org/jclouds/vcloud/terremark/binders/TerremarkBindInstantiateVAppTemplateParamsToXmlPayload.java index f5f316ae06..8e6dd54ca3 100644 --- a/vcloud/terremark/src/main/java/org/jclouds/vcloud/terremark/binders/TerremarkBindInstantiateVAppTemplateParamsToXmlPayload.java +++ b/vcloud/terremark/src/main/java/org/jclouds/vcloud/terremark/binders/TerremarkBindInstantiateVAppTemplateParamsToXmlPayload.java @@ -26,9 +26,10 @@ import static org.jclouds.vcloud.reference.VCloudConstants.PROPERTY_VCLOUD_XML_S import java.net.URI; import java.util.Map; -import java.util.SortedMap; import java.util.Map.Entry; +import java.util.SortedMap; +import javax.annotation.Nullable; import javax.inject.Inject; import javax.inject.Named; import javax.inject.Singleton; @@ -41,7 +42,6 @@ import org.jclouds.vcloud.endpoints.Network; import org.jclouds.vcloud.options.InstantiateVAppTemplateOptions; import org.jclouds.vcloud.terremark.options.TerremarkInstantiateVAppTemplateOptions; -import com.google.inject.internal.Nullable; import com.jamesmurty.utils.XMLBuilder; /** diff --git a/vcloud/terremark/src/main/java/org/jclouds/vcloud/terremark/options/TerremarkInstantiateVAppTemplateOptions.java b/vcloud/terremark/src/main/java/org/jclouds/vcloud/terremark/options/TerremarkInstantiateVAppTemplateOptions.java index a518b8c4b0..e58096bf5e 100644 --- a/vcloud/terremark/src/main/java/org/jclouds/vcloud/terremark/options/TerremarkInstantiateVAppTemplateOptions.java +++ b/vcloud/terremark/src/main/java/org/jclouds/vcloud/terremark/options/TerremarkInstantiateVAppTemplateOptions.java @@ -24,7 +24,7 @@ import java.util.Map; import org.jclouds.vcloud.domain.network.NetworkConfig; import org.jclouds.vcloud.options.InstantiateVAppTemplateOptions; -import com.google.inject.internal.util.Maps; +import com.google.common.collect.Maps; /** *