Merge branch 'master' of git://github.com/jclouds/jclouds

This commit is contained in:
unknown 2010-12-03 20:08:53 +01:00
commit 477466ca64
176 changed files with 8800 additions and 746 deletions

View File

@ -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 bootstrap machines in the cloud. blobstore helps you manage key-value
data. 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 dev version is 1.0-SNAPSHOT
our compute api supports: ec2, gogrid, cloudservers (rackspace), rimuhosting, vcloud, our compute api supports: ec2, gogrid, cloudservers (rackspace), rimuhosting, vcloud,
@ -102,13 +102,13 @@ Compute Example (Clojure):
(run-nodes "mycluster" 2)) (run-nodes "mycluster" 2))
Downloads: 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 * maven repo: http://jclouds.googlecode.com/svn/repo
* snapshot repo: http://jclouds.rimuhosting.com/maven2/snapshots * snapshot repo: http://jclouds.rimuhosting.com/maven2/snapshots
Links: Links:
* project page: http://code.google.com/p/jclouds/ * 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/ * javadocs (1.0-SNAPSHOT): http://jclouds.rimuhosting.com/apidocs-SNAPSHOT/
* community: http://code.google.com/p/jclouds/wiki/AppsThatUseJClouds * community: http://code.google.com/p/jclouds/wiki/AppsThatUseJClouds
* user group: http://groups.google.com/group/jclouds * user group: http://groups.google.com/group/jclouds

View File

@ -19,10 +19,11 @@
package org.jclouds.atmosonline.saas.domain; package org.jclouds.atmosonline.saas.domain;
import javax.annotation.Nullable;
import org.jclouds.io.PayloadEnclosing; import org.jclouds.io.PayloadEnclosing;
import com.google.common.collect.Multimap; 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 * Amazon Atmos is designed to store objects. Objects are stored in buckets and consist of a

View File

@ -116,7 +116,7 @@ public class EC2ComputeService extends BaseComputeService {
ec2Client.getPlacementGroupServices().deletePlacementGroupInRegion(region, group); ec2Client.getPlacementGroupServices().deletePlacementGroupInRegion(region, group);
checkState(placementGroupDeleted.apply(new PlacementGroup(region, group, "cluster", State.PENDING)), checkState(placementGroupDeleted.apply(new PlacementGroup(region, group, "cluster", State.PENDING)),
String.format("placementGroup region(%s) name(%s) failed to delete", region, group)); 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); logger.debug("<< deleted placementGroup(%s)", group);
} catch (AWSResponseException e) { } catch (AWSResponseException e) {
if (e.getError().getCode().equals("InvalidPlacementGroup.InUse")) { if (e.getError().getCode().equals("InvalidPlacementGroup.InUse")) {
@ -142,7 +142,7 @@ public class EC2ComputeService extends BaseComputeService {
logger.debug(">> deleting securityGroup(%s)", group); logger.debug(">> deleting securityGroup(%s)", group);
ec2Client.getSecurityGroupServices().deleteSecurityGroupInRegion(region, group); ec2Client.getSecurityGroupServices().deleteSecurityGroupInRegion(region, group);
// TODO: test this clear happens // 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); logger.debug("<< deleted securityGroup(%s)", group);
} }
} }

View File

@ -29,7 +29,6 @@ import org.jclouds.aws.ec2.EC2Client;
import org.jclouds.aws.ec2.compute.domain.RegionAndName; import org.jclouds.aws.ec2.compute.domain.RegionAndName;
import org.jclouds.compute.domain.Image; import org.jclouds.compute.domain.Image;
import org.jclouds.logging.Logger; import org.jclouds.logging.Logger;
import org.jclouds.rest.ResourceNotFoundException;
import com.google.common.base.Function; import com.google.common.base.Function;
import com.google.common.collect.Iterables; import com.google.common.collect.Iterables;
@ -57,9 +56,8 @@ public final class RegionAndIdToImage implements Function<RegionAndName, Image>
org.jclouds.aws.ec2.domain.Image image = Iterables.getOnlyElement(sync.getAMIServices() 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); return parser.apply(image);
} catch (ResourceNotFoundException e) { } catch (Exception e) {
logger.warn(e, "no image found for %s/%s: %s", key.getRegion(), key.getName(), e logger.warn(e, "could not find image %s/%s: %s", key.getRegion(), key.getName(), e.getMessage());
.getMessage());
return null; return null;
} }
} }

View File

@ -101,9 +101,20 @@ public class RunningInstanceToNodeMetadata implements Function<RunningInstance,
builder.imageId(instance.getRegion() + "/" + instance.getImageId()); builder.imageId(instance.getRegion() + "/" + instance.getImageId());
// extract the operating system from the image // extract the operating system from the image
Image image = instanceToImage.get(new RegionAndName(instance.getRegion(), instance.getImageId())); RegionAndName regionAndName = new RegionAndName(instance.getRegion(), instance.getImageId());
try {
Image image = instanceToImage.get(regionAndName);
if (image != null) if (image != null)
builder.operatingSystem(image.getOperatingSystem()); builder.operatingSystem(image.getOperatingSystem());
}
catch (NullPointerException e) {
// The instanceToImage Map may throw NullPointerException (actually subclass NullOutputException) if the
// computing Function returns a null value.
//
// See the following for more information:
// MapMaker.makeComputingMap()
// RegionAndIdToImage.apply()
}
return builder.build(); return builder.build();
} }

View File

@ -21,10 +21,11 @@ package org.jclouds.aws.ec2.domain;
import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkNotNull;
import javax.annotation.Nullable;
import com.google.common.collect.ImmutableMultimap; import com.google.common.collect.ImmutableMultimap;
import com.google.common.collect.LinkedHashMultimap; import com.google.common.collect.LinkedHashMultimap;
import com.google.common.collect.Multimap; import com.google.common.collect.Multimap;
import com.google.inject.internal.Nullable;
/** /**
* Defines the mapping of volumes for * Defines the mapping of volumes for

View File

@ -24,10 +24,11 @@ import static com.google.common.base.Preconditions.checkNotNull;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import javax.annotation.Nullable;
import com.google.common.collect.Iterables; import com.google.common.collect.Iterables;
import com.google.common.collect.Maps; import com.google.common.collect.Maps;
import com.google.common.collect.Sets; import com.google.common.collect.Sets;
import com.google.inject.internal.Nullable;
/** /**
* *

View File

@ -21,7 +21,7 @@ package org.jclouds.aws.ec2.domain;
import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkNotNull;
import com.google.inject.internal.Nullable; import javax.annotation.Nullable;
/** /**
* *

View File

@ -21,7 +21,7 @@ package org.jclouds.aws.ec2.domain;
import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkNotNull;
import com.google.inject.internal.Nullable; import javax.annotation.Nullable;
/** /**
* *

View File

@ -24,9 +24,10 @@ import static com.google.common.base.Preconditions.checkNotNull;
import java.util.LinkedHashSet; import java.util.LinkedHashSet;
import java.util.Set; import java.util.Set;
import javax.annotation.Nullable;
import com.google.common.collect.Iterables; import com.google.common.collect.Iterables;
import com.google.common.collect.Sets; import com.google.common.collect.Sets;
import com.google.inject.internal.Nullable;
/** /**
* *

View File

@ -25,12 +25,13 @@ import java.util.Date;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import javax.annotation.Nullable;
import org.jclouds.aws.ec2.domain.Attachment.Status; import org.jclouds.aws.ec2.domain.Attachment.Status;
import com.google.common.collect.Iterables; import com.google.common.collect.Iterables;
import com.google.common.collect.Maps; import com.google.common.collect.Maps;
import com.google.common.collect.Sets; import com.google.common.collect.Sets;
import com.google.inject.internal.Nullable;
/** /**
* *

View File

@ -35,10 +35,14 @@ import com.google.common.collect.Sets;
*/ */
public class BaseEC2RequestOptions extends BaseHttpRequestOptions { public class BaseEC2RequestOptions extends BaseHttpRequestOptions {
@Override
public String toString() {
return "[formParameters=" + formParameters + "]";
}
protected void indexFormValuesWithPrefix(String prefix, String... values) { protected void indexFormValuesWithPrefix(String prefix, String... values) {
for (int i = 0; i < values.length; i++) { for (int i = 0; i < values.length; i++) {
formParameters.put(prefix + "." + (i + 1), checkNotNull(values[i], prefix.toLowerCase() formParameters.put(prefix + "." + (i + 1), checkNotNull(values[i], prefix.toLowerCase() + "s[" + i + "]"));
+ "s[" + i + "]"));
} }
} }

View File

@ -94,7 +94,7 @@ public class ParseAWSErrorFromXmlContent implements HttpErrorHandler {
&& (error.getCode().endsWith(".NotFound") || error.getCode().endsWith(".Unknown"))) && (error.getCode().endsWith(".NotFound") || error.getCode().endsWith(".Unknown")))
exception = new ResourceNotFoundException(message, exception); exception = new ResourceNotFoundException(message, exception);
else if ((error != null && error.getCode() != null && (error.getCode().equals("IncorrectState") || error else if ((error != null && error.getCode() != null && (error.getCode().equals("IncorrectState") || error
.getCode().endsWith(".Duplicate"))) || (message != null && message.indexOf("already exists") != -1)) .getCode().endsWith(".Duplicate"))) || (message != null && (message.indexOf("already exists") != -1)))
exception = new IllegalStateException(message, exception); exception = new IllegalStateException(message, exception);
else if (error != null && error.getCode() != null && error.getCode().equals("AuthFailure")) else if (error != null && error.getCode() != null && error.getCode().equals("AuthFailure"))
exception = new AuthorizationException(exception.getMessage(), exception); exception = new AuthorizationException(exception.getMessage(), exception);

View File

@ -0,0 +1,45 @@
/**
*
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ====================================================================
*/
package org.jclouds.aws.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<Module> modules) {
modules.add(new ScaleUpCloudBlobStoreContextModule());
}
}

View File

@ -29,6 +29,8 @@ import org.jclouds.aws.s3.S3Client;
import org.jclouds.aws.s3.blobstore.S3AsyncBlobStore; import org.jclouds.aws.s3.blobstore.S3AsyncBlobStore;
import org.jclouds.aws.s3.blobstore.S3BlobRequestSigner; import org.jclouds.aws.s3.blobstore.S3BlobRequestSigner;
import org.jclouds.aws.s3.blobstore.S3BlobStore; 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.aws.suppliers.DefaultLocationSupplier;
import org.jclouds.blobstore.AsyncBlobStore; import org.jclouds.blobstore.AsyncBlobStore;
import org.jclouds.blobstore.BlobRequestSigner; import org.jclouds.blobstore.BlobRequestSigner;
@ -43,6 +45,7 @@ import org.jclouds.domain.LocationScope;
import org.jclouds.domain.internal.LocationImpl; import org.jclouds.domain.internal.LocationImpl;
import org.jclouds.rest.annotations.Provider; import org.jclouds.rest.annotations.Provider;
import com.google.common.base.Function;
import com.google.common.base.Supplier; import com.google.common.base.Supplier;
import com.google.common.base.Suppliers; import com.google.common.base.Suppliers;
import com.google.common.collect.Sets; import com.google.common.collect.Sets;
@ -70,6 +73,12 @@ public class S3BlobStoreContextModule extends AbstractModule {
bind(BlobStoreContext.class).to(new TypeLiteral<BlobStoreContextImpl<S3Client, S3AsyncClient>>() { bind(BlobStoreContext.class).to(new TypeLiteral<BlobStoreContextImpl<S3Client, S3AsyncClient>>() {
}).in(Scopes.SINGLETON); }).in(Scopes.SINGLETON);
bind(BlobRequestSigner.class).to(S3BlobRequestSigner.class); bind(BlobRequestSigner.class).to(S3BlobRequestSigner.class);
bindBucketLocationStrategy();
}
protected void bindBucketLocationStrategy() {
bind(new TypeLiteral<Function<BucketMetadata, Location>>() {
}).to(LocationFromBucketLocation.class);
} }
@Provides @Provides

View File

@ -0,0 +1,41 @@
/**
*
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ====================================================================
*/
package org.jclouds.aws.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<Function<BucketMetadata, Location>>() {
}).toInstance((Function)Functions.constant(null));
}
}

View File

@ -19,80 +19,36 @@
package org.jclouds.aws.s3.blobstore.functions; 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.Inject;
import javax.inject.Singleton; import javax.inject.Singleton;
import org.jclouds.aws.s3.S3Client;
import org.jclouds.aws.s3.domain.BucketMetadata; import org.jclouds.aws.s3.domain.BucketMetadata;
import org.jclouds.blobstore.ContainerNotFoundException;
import org.jclouds.blobstore.domain.MutableStorageMetadata; import org.jclouds.blobstore.domain.MutableStorageMetadata;
import org.jclouds.blobstore.domain.StorageMetadata; import org.jclouds.blobstore.domain.StorageMetadata;
import org.jclouds.blobstore.domain.StorageType; import org.jclouds.blobstore.domain.StorageType;
import org.jclouds.blobstore.domain.internal.MutableStorageMetadataImpl; import org.jclouds.blobstore.domain.internal.MutableStorageMetadataImpl;
import org.jclouds.collect.Memoized;
import org.jclouds.domain.Location; import org.jclouds.domain.Location;
import org.jclouds.logging.Logger;
import com.google.common.base.Function; 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 * @author Adrian Cole
*/ */
@Singleton @Singleton
public class BucketToResourceMetadata implements Function<BucketMetadata, StorageMetadata> { public class BucketToResourceMetadata implements Function<BucketMetadata, StorageMetadata> {
private final S3Client client; private final Function<BucketMetadata, Location> locationOfBucket;
private final Location onlyLocation;
private final Supplier<Set<? extends Location>> locations;
@Resource
protected Logger logger = Logger.NULL;
@Inject @Inject
BucketToResourceMetadata(S3Client client, @Memoized Supplier<Set<? extends Location>> locations) { BucketToResourceMetadata(Function<BucketMetadata, Location> locationOfBucket) {
this.client = client; this.locationOfBucket = locationOfBucket;
this.onlyLocation = locations.get().size() == 1 ? Iterables.get(locations.get(), 0) : null;
this.locations = locations;
} }
public StorageMetadata apply(BucketMetadata from) { public StorageMetadata apply(BucketMetadata from) {
MutableStorageMetadata to = new MutableStorageMetadataImpl(); MutableStorageMetadata to = new MutableStorageMetadataImpl();
to.setName(from.getName()); to.setName(from.getName());
to.setType(StorageType.CONTAINER); to.setType(StorageType.CONTAINER);
to.setLocation(onlyLocation != null ? onlyLocation : getLocation(from)); to.setLocation(locationOfBucket.apply(from));
return to; return to;
} }
private Location getLocation(BucketMetadata from) {
try {
Set<? extends Location> 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<Location>() {
@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;
}
} }

View File

@ -0,0 +1,88 @@
/**
*
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ====================================================================
*/
package org.jclouds.aws.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<BucketMetadata, Location> {
private final Location onlyLocation;
private final Supplier<Set<? extends Location>> locations;
private final S3Client client;
@Resource
protected Logger logger = Logger.NULL;
@Inject
LocationFromBucketLocation(S3Client client, @Memoized Supplier<Set<? extends Location>> 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<? extends Location> 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<Location>() {
@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;
}
}

View File

@ -19,10 +19,11 @@
package org.jclouds.aws.s3.domain; package org.jclouds.aws.s3.domain;
import javax.annotation.Nullable;
import org.jclouds.io.PayloadEnclosing; import org.jclouds.io.PayloadEnclosing;
import com.google.common.collect.Multimap; 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 * Amazon S3 is designed to store objects. Objects are stored in buckets and consist of a

View File

@ -19,8 +19,14 @@
package org.jclouds.aws.s3.functions; 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 static org.jclouds.util.Utils.propagateOrNull;
import java.util.List;
import javax.inject.Singleton; import javax.inject.Singleton;
import org.jclouds.aws.AWSResponseException; import org.jclouds.aws.AWSResponseException;
@ -35,12 +41,13 @@ import com.google.common.base.Function;
public class ReturnFalseIfBucketAlreadyOwnedByYou implements Function<Exception, Boolean> { public class ReturnFalseIfBucketAlreadyOwnedByYou implements Function<Exception, Boolean> {
public Boolean apply(Exception from) { public Boolean apply(Exception from) {
if (from instanceof AWSResponseException) { List<Throwable> throwables = getCausalChain(from);
AWSResponseException responseException = (AWSResponseException) from;
if ("BucketAlreadyOwnedByYou".equals(responseException.getError().getCode())) { Iterable<AWSResponseException> 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 false;
} }
}
return Boolean.class.cast(propagateOrNull(from)); return Boolean.class.cast(propagateOrNull(from));
} }
} }

View File

@ -106,7 +106,7 @@ public class EC2ComputeServiceLiveTest extends BaseComputeServiceLiveTest {
InstanceClient instanceClient = EC2Client.class.cast(context.getProviderSpecificContext().getApi()) InstanceClient instanceClient = EC2Client.class.cast(context.getProviderSpecificContext().getApi())
.getInstanceServices(); .getInstanceServices();
String tag = this.tag + "optionsandlogin"; String tag = this.tag + "o";
TemplateOptions options = client.templateOptions(); TemplateOptions options = client.templateOptions();
@ -190,7 +190,7 @@ public class EC2ComputeServiceLiveTest extends BaseComputeServiceLiveTest {
InstanceClient instanceClient = EC2Client.class.cast(context.getProviderSpecificContext().getApi()) InstanceClient instanceClient = EC2Client.class.cast(context.getProviderSpecificContext().getApi())
.getInstanceServices(); .getInstanceServices();
String tag = this.tag + "optionsnokey"; String tag = this.tag + "k";
TemplateOptions options = client.templateOptions(); TemplateOptions options = client.templateOptions();
@ -250,7 +250,7 @@ public class EC2ComputeServiceLiveTest extends BaseComputeServiceLiveTest {
InstanceClient instanceClient = EC2Client.class.cast(context.getProviderSpecificContext().getApi()) InstanceClient instanceClient = EC2Client.class.cast(context.getProviderSpecificContext().getApi())
.getInstanceServices(); .getInstanceServices();
String tag = this.tag + "optionswithsubnetid"; String tag = this.tag + "g";
TemplateOptions options = client.templateOptions(); TemplateOptions options = client.templateOptions();

View File

@ -43,7 +43,7 @@ public class EucalyptusComputeServiceLiveTestDisabled extends EC2ComputeServiceL
@Override @Override
public void setServiceDefaults() { public void setServiceDefaults() {
// security groups must be <30 characters // security groups must be <30 characters
tag = "euc"; tag = "eu";
} }
@Override @Override

View File

@ -0,0 +1,106 @@
/**
*
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ====================================================================
*/
package org.jclouds.aws.ec2.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.<Module> 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";
}

View File

@ -27,6 +27,7 @@ import static org.easymock.classextension.EasyMock.verify;
import static org.jclouds.aws.ec2.options.DescribeImagesOptions.Builder.imageIds; import static org.jclouds.aws.ec2.options.DescribeImagesOptions.Builder.imageIds;
import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertEquals;
import java.util.NoSuchElementException;
import java.util.Set; import java.util.Set;
import org.jclouds.aws.ec2.EC2Client; import org.jclouds.aws.ec2.EC2Client;
@ -107,4 +108,36 @@ public class RegionAndIdToImageTest {
verify(client); 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<? extends org.jclouds.aws.ec2.domain.Image> images = ImmutableSet
.<org.jclouds.aws.ec2.domain.Image> 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);
}
} }

View File

@ -51,6 +51,9 @@ import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet; import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables; import com.google.common.collect.Iterables;
import com.google.common.collect.Maps; import com.google.common.collect.Maps;
import com.google.common.collect.MapMaker;
import javax.annotation.Nullable;
/** /**
* @author Adrian Cole * @author Adrian Cole
@ -140,6 +143,34 @@ public class RunningInstanceToNodeMetadataTest {
"i-9slweygo").location(provider).build()); "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<RegionAndName, Image> nullReturningFunction = new Function<RegionAndName, Image>() {
@Override
public Image apply(@Nullable RegionAndName from) {
return null;
}
};
Map<RegionAndName, Image> instanceToImage = new MapMaker().makeComputingMap(nullReturningFunction);
RunningInstanceToNodeMetadata parser = createNodeParser(ImmutableSet.of(m1_small().build()), ImmutableSet
.of(provider), ImmutableMap
.<String, Credentials>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) { protected RunningInstance firstInstanceFromResource(String resource) {
RunningInstance server = Iterables.get(Iterables.get(DescribeInstancesResponseHandlerTest RunningInstance server = Iterables.get(Iterables.get(DescribeInstancesResponseHandlerTest
.parseRunningInstances(resource), 0), 0); .parseRunningInstances(resource), 0), 0);
@ -147,7 +178,8 @@ public class RunningInstanceToNodeMetadataTest {
} }
protected RunningInstanceToNodeMetadata createNodeParser(final ImmutableSet<Hardware> hardware, protected RunningInstanceToNodeMetadata createNodeParser(final ImmutableSet<Hardware> hardware,
final ImmutableSet<Location> locations, Set<org.jclouds.compute.domain.Image> images, final ImmutableSet<Location> locations,
Set<org.jclouds.compute.domain.Image> images,
Map<String, Credentials> credentialStore) { Map<String, Credentials> credentialStore) {
Map<InstanceState, NodeState> instanceToNodeState = EC2ComputeServiceDependenciesModule.instanceToNodeState; Map<InstanceState, NodeState> instanceToNodeState = EC2ComputeServiceDependenciesModule.instanceToNodeState;
@ -159,6 +191,13 @@ public class RunningInstanceToNodeMetadataTest {
} }
}); });
return createNodeParser(hardware, locations, credentialStore, instanceToNodeState, instanceToImage);
}
private RunningInstanceToNodeMetadata createNodeParser(final ImmutableSet<Hardware> hardware, final
ImmutableSet<Location> locations, Map<String, Credentials> credentialStore, Map<InstanceState, NodeState>
instanceToNodeState, Map<RegionAndName, Image> instanceToImage) {
Supplier<Set<? extends Location>> locationSupplier = new Supplier<Set<? extends Location>>() { Supplier<Set<? extends Location>> locationSupplier = new Supplier<Set<? extends Location>>() {
@Override @Override

View File

@ -52,7 +52,7 @@
<dependency> <dependency>
<groupId>com.google.code.guice</groupId> <groupId>com.google.code.guice</groupId>
<artifactId>guice-servlet</artifactId> <artifactId>guice-servlet</artifactId>
<version>2.1-r1201</version> <version>3.0-snapshot-20101120</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>displaytag</groupId> <groupId>displaytag</groupId>

View File

@ -26,6 +26,8 @@ import java.net.URI;
import java.util.Date; import java.util.Date;
import java.util.Map; import java.util.Map;
import javax.annotation.Nullable;
import org.jclouds.azure.storage.blob.domain.BlobProperties; import org.jclouds.azure.storage.blob.domain.BlobProperties;
import org.jclouds.azure.storage.blob.domain.BlobType; import org.jclouds.azure.storage.blob.domain.BlobType;
import org.jclouds.azure.storage.blob.domain.LeaseStatus; import org.jclouds.azure.storage.blob.domain.LeaseStatus;
@ -33,7 +35,6 @@ import org.jclouds.io.ContentMetadata;
import org.jclouds.io.payloads.BaseImmutableContentMetadata; import org.jclouds.io.payloads.BaseImmutableContentMetadata;
import com.google.common.collect.Maps; import com.google.common.collect.Maps;
import com.google.inject.internal.Nullable;
/** /**
* Allows you to manipulate metadata. * Allows you to manipulate metadata.

View File

@ -299,7 +299,7 @@ Options can also be specified for extension modules
([container-name] ([container-name]
(count-blobs container-name *blobstore*)) (count-blobs container-name *blobstore*))
([container-name blobstore] ([container-name blobstore]
(.countBlob blobstore container-name))) (.countBlobs blobstore container-name)))
(defn blobs (defn blobs
"List the blobs in a container: "List the blobs in a container:

View File

@ -49,27 +49,28 @@ import java.util.Collections;
import java.util.Date; import java.util.Date;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Map.Entry;
import java.util.Set; import java.util.Set;
import java.util.SortedSet; import java.util.SortedSet;
import java.util.TreeSet; import java.util.TreeSet;
import java.util.Map.Entry;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap; import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.ExecutorService; import java.util.concurrent.ExecutorService;
import javax.annotation.Nullable;
import javax.inject.Inject; import javax.inject.Inject;
import javax.inject.Named; import javax.inject.Named;
import javax.ws.rs.core.HttpHeaders; import javax.ws.rs.core.HttpHeaders;
import org.jclouds.Constants; import org.jclouds.Constants;
import org.jclouds.blobstore.domain.Blob; import org.jclouds.blobstore.domain.Blob;
import org.jclouds.blobstore.domain.Blob.Factory;
import org.jclouds.blobstore.domain.BlobMetadata; import org.jclouds.blobstore.domain.BlobMetadata;
import org.jclouds.blobstore.domain.MutableBlobMetadata; import org.jclouds.blobstore.domain.MutableBlobMetadata;
import org.jclouds.blobstore.domain.MutableStorageMetadata; import org.jclouds.blobstore.domain.MutableStorageMetadata;
import org.jclouds.blobstore.domain.PageSet; import org.jclouds.blobstore.domain.PageSet;
import org.jclouds.blobstore.domain.StorageMetadata; import org.jclouds.blobstore.domain.StorageMetadata;
import org.jclouds.blobstore.domain.StorageType; 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.MutableStorageMetadataImpl;
import org.jclouds.blobstore.domain.internal.PageSetImpl; import org.jclouds.blobstore.domain.internal.PageSetImpl;
import org.jclouds.blobstore.functions.HttpGetOptionsListToGetOptions; 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.collect.Multimaps;
import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture; 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. * Implementation of {@link BaseAsyncBlobStore} which keeps all data in a local Map object.

View File

@ -19,10 +19,12 @@
package org.jclouds.blobstore.domain; package org.jclouds.blobstore.domain;
import javax.annotation.Nullable;
import org.jclouds.io.Payload;
import org.jclouds.io.PayloadEnclosing; import org.jclouds.io.PayloadEnclosing;
import com.google.common.collect.Multimap; 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 * Value type for an HTTP Blob service. Blobs are stored in containers and consist of a

View File

@ -26,14 +26,14 @@ import java.net.URI;
import java.util.Date; import java.util.Date;
import java.util.Map; import java.util.Map;
import javax.annotation.Nullable;
import org.jclouds.blobstore.domain.Blob; import org.jclouds.blobstore.domain.Blob;
import org.jclouds.blobstore.domain.BlobMetadata; import org.jclouds.blobstore.domain.BlobMetadata;
import org.jclouds.blobstore.domain.StorageType; import org.jclouds.blobstore.domain.StorageType;
import org.jclouds.domain.Location; import org.jclouds.domain.Location;
import org.jclouds.io.ContentMetadata; import org.jclouds.io.ContentMetadata;
import com.google.inject.internal.Nullable;
/** /**
* System and user Metadata for the {@link Blob}. * System and user Metadata for the {@link Blob}.
* *

View File

@ -26,13 +26,13 @@ import java.net.URI;
import java.util.Date; import java.util.Date;
import java.util.Map; import java.util.Map;
import javax.annotation.Nullable;
import org.jclouds.blobstore.domain.StorageMetadata; import org.jclouds.blobstore.domain.StorageMetadata;
import org.jclouds.blobstore.domain.StorageType; import org.jclouds.blobstore.domain.StorageType;
import org.jclouds.domain.Location; import org.jclouds.domain.Location;
import org.jclouds.domain.internal.ResourceMetadataImpl; import org.jclouds.domain.internal.ResourceMetadataImpl;
import com.google.inject.internal.Nullable;
/** /**
* Idpayload of the object * Idpayload of the object
* *

View File

@ -87,8 +87,11 @@ public class ParseSystemAndUserMetadataFromHeaders implements Function<HttpRespo
@VisibleForTesting @VisibleForTesting
void parseLastModifiedOrThrowException(HttpResponse from, MutableBlobMetadata metadata) throws HttpException { void parseLastModifiedOrThrowException(HttpResponse from, MutableBlobMetadata metadata) throws HttpException {
String lastModified = from.getFirstHeaderOrNull(HttpHeaders.LAST_MODIFIED); String lastModified = from.getFirstHeaderOrNull(HttpHeaders.LAST_MODIFIED);
if (lastModified == null) if (lastModified == null) {
// scaleup-storage uses the wrong case for the last modified header
if ((lastModified = from.getFirstHeaderOrNull("Last-modified")) == null)
throw new HttpException(HttpHeaders.LAST_MODIFIED + " header not present in response: " + from.getStatusLine()); throw new HttpException(HttpHeaders.LAST_MODIFIED + " header not present in response: " + from.getStatusLine());
}
// Eucalyptus 1.6 returns iso8601 dates // Eucalyptus 1.6 returns iso8601 dates
if (apiVersion.indexOf("Walrus-1.6") != -1) { if (apiVersion.indexOf("Walrus-1.6") != -1) {
metadata.setLastModified(dateParser.iso8601DateParse(lastModified.replace("+0000", "Z"))); metadata.setLastModified(dateParser.iso8601DateParse(lastModified.replace("+0000", "Z")));

View File

@ -70,6 +70,7 @@
(is (= 1 (count (list-container "container" :max-results 1)))) (is (= 1 (count (list-container "container" :max-results 1))))
(create-directory "container" "dir") (create-directory "container" "dir")
(is (upload-blob "container" "dir/blob2" "blob2")) (is (upload-blob "container" "dir/blob2" "blob2"))
(is (= 3 (count-blobs "container")))
(is (= 3 (count (list-container "container")))) (is (= 3 (count (list-container "container"))))
(is (= 4 (count (list-container "container" :recursive true)))) (is (= 4 (count (list-container "container" :recursive true))))
(is (= 3 (count (list-container "container" :with-details true)))) (is (= 3 (count (list-container "container" :with-details true))))

View File

@ -120,8 +120,8 @@ public class BaseBlobIntegrationTest extends BaseBlobStoreIntegrationTest {
Map<Integer, Future<?>> responses = Maps.newHashMap(); Map<Integer, Future<?>> responses = Maps.newHashMap();
for (int i = 0; i < 10; i++) { for (int i = 0; i < 10; i++) {
responses.put(i, Futures.compose(context.getAsyncBlobStore().getBlob(containerName, key), responses.put(i,
new Function<Blob, Void>() { Futures.compose(context.getAsyncBlobStore().getBlob(containerName, key), new Function<Blob, Void>() {
@Override @Override
public Void apply(Blob from) { public Void apply(Blob from) {
@ -156,7 +156,6 @@ public class BaseBlobIntegrationTest extends BaseBlobStoreIntegrationTest {
context.getBlobStore().putBlob(containerName, sourceObject); context.getBlobStore().putBlob(containerName, sourceObject);
} }
@Test(groups = { "integration", "live" }) @Test(groups = { "integration", "live" })
public void testGetIfModifiedSince() throws InterruptedException { public void testGetIfModifiedSince() throws InterruptedException {
String containerName = getContainerName(); String containerName = getContainerName();
@ -365,15 +364,15 @@ public class BaseBlobIntegrationTest extends BaseBlobStoreIntegrationTest {
@DataProvider(name = "delete") @DataProvider(name = "delete")
public Object[][] createData() { public Object[][] createData() {
return new Object[][] { { "normal" }, { "sp ace" }, { "qu?stion" }, { "unic₪de" }, { "path/foo" }, { "colon:" }, return new Object[][] { { "normal" }, { "sp ace" }, { "qu?stion" }, { "unic₪de" }, { "path/foo" },
{ "asteri*k" }, { "quote\"" }, { "{great<r}" }, { "lesst>en" }, { "p|pe" } }; { "colon:" }, { "asteri*k" }, { "quote\"" }, { "{great<r}" }, { "lesst>en" }, { "p|pe" } };
} }
@Test(groups = { "integration", "live" }, dataProvider = "delete") @Test(groups = { "integration", "live" }, dataProvider = "delete")
public void deleteObject(String key) throws InterruptedException { public void deleteObject(String key) throws InterruptedException {
String containerName = getContainerName(); String containerName = getContainerName();
try { try {
addBlobToContainer(containerName, key); addBlobToContainer(containerName, key, key, MediaType.TEXT_PLAIN);
context.getBlobStore().removeBlob(containerName, key); context.getBlobStore().removeBlob(containerName, key);
assertContainerEmptyDeleting(containerName, key); assertContainerEmptyDeleting(containerName, key);
} finally { } finally {
@ -391,9 +390,11 @@ public class BaseBlobIntegrationTest extends BaseBlobStoreIntegrationTest {
} }
}); });
assertEquals(Iterables.size(listing), 0, String.format( assertEquals(
"deleting %s, we still have %s blobs left in container %s, using encoding %s", key, Iterables Iterables.size(listing),
.size(listing), containerName, LOCAL_ENCODING)); 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" }) @Test(groups = { "integration", "live" })

View File

@ -25,8 +25,8 @@ import static org.testng.Assert.assertEquals;
import java.io.IOException; import java.io.IOException;
import java.util.Map; import java.util.Map;
import java.util.Set;
import java.util.Map.Entry; import java.util.Map.Entry;
import java.util.Set;
import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue; import java.util.concurrent.BlockingQueue;
import java.util.concurrent.CancellationException; import java.util.concurrent.CancellationException;
@ -35,6 +35,8 @@ import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicInteger;
import javax.ws.rs.core.MediaType;
import org.jclouds.blobstore.BlobStoreContext; import org.jclouds.blobstore.BlobStoreContext;
import org.jclouds.blobstore.attr.ConsistencyModel; import org.jclouds.blobstore.attr.ConsistencyModel;
import org.jclouds.blobstore.domain.Blob; import org.jclouds.blobstore.domain.Blob;
@ -63,10 +65,10 @@ public class BaseBlobStoreIntegrationTest {
String.format(XML_STRING_FORMAT, "bear"), "three", String.format(XML_STRING_FORMAT, "candy"), "four", 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, "dogma"), "five", String.format(XML_STRING_FORMAT, "emma"));
protected Map<String, String> fiveStringsUnderPath = ImmutableMap.of("path/1", String.format(XML_STRING_FORMAT, protected Map<String, String> fiveStringsUnderPath = ImmutableMap.of("path/1",
"apple"), "path/2", String.format(XML_STRING_FORMAT, "bear"), "path/3", String.format(XML_STRING_FORMAT, String.format(XML_STRING_FORMAT, "apple"), "path/2", String.format(XML_STRING_FORMAT, "bear"), "path/3",
"candy"), "path/4", String.format(XML_STRING_FORMAT, "dogma"), "path/5", String.format(XML_STRING_FORMAT, String.format(XML_STRING_FORMAT, "candy"), "path/4", String.format(XML_STRING_FORMAT, "dogma"), "path/5",
"emma")); String.format(XML_STRING_FORMAT, "emma"));
public static long INCONSISTENCY_WINDOW = 10000; public static long INCONSISTENCY_WINDOW = 10000;
protected static volatile AtomicInteger containerIndex = new AtomicInteger(0); protected static volatile AtomicInteger containerIndex = new AtomicInteger(0);
@ -238,9 +240,13 @@ public class BaseBlobStoreIntegrationTest {
} }
protected String addBlobToContainer(String sourceContainer, String key) { 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); Blob sourceObject = context.getBlobStore().newBlob(key);
sourceObject.setPayload(TEST_STRING); sourceObject.setPayload(payload);
sourceObject.getMetadata().getContentMetadata().setContentType("text/xml"); sourceObject.getMetadata().getContentMetadata().setContentType(contentType);
return addBlobToContainer(sourceContainer, sourceObject); return addBlobToContainer(sourceContainer, sourceObject);
} }

View File

@ -200,7 +200,7 @@ public abstract class BaseComputeServiceLiveTest {
// starting this one alphabetically before create2nodes.. // starting this one alphabetically before create2nodes..
@Test(enabled = true, dependsOnMethods = { "testCompareSizes" }) @Test(enabled = true, dependsOnMethods = { "testCompareSizes" })
public void testAScriptExecutionAfterBootWithBasicTemplate() throws Exception { public void testAScriptExecutionAfterBootWithBasicTemplate() throws Exception {
String tag = this.tag + "run"; String tag = this.tag + "r";
try { try {
client.destroyNodesMatching(withTag(tag)); client.destroyNodesMatching(withTag(tag));
} catch (Exception e) { } catch (Exception e) {
@ -460,7 +460,7 @@ public abstract class BaseComputeServiceLiveTest {
@Test(enabled = true) @Test(enabled = true)
public void testCreateAndRunAService() throws Exception { public void testCreateAndRunAService() throws Exception {
String tag = this.tag + "service"; String tag = this.tag + "s";
try { try {
client.destroyNodesMatching(withTag(tag)); client.destroyNodesMatching(withTag(tag));
} catch (Exception e) { } catch (Exception e) {

View File

@ -81,7 +81,7 @@
<dependency> <dependency>
<groupId>com.google.code.guice</groupId> <groupId>com.google.code.guice</groupId>
<artifactId>guice</artifactId> <artifactId>guice</artifactId>
<version>2.1-r1201</version> <version>3.0-snapshot-20101120</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>javax.inject</groupId> <groupId>javax.inject</groupId>
@ -106,7 +106,7 @@
<dependency> <dependency>
<groupId>com.google.guava</groupId> <groupId>com.google.guava</groupId>
<artifactId>guava</artifactId> <artifactId>guava</artifactId>
<version>r06</version> <version>r07</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>com.google.code.findbugs</groupId> <groupId>com.google.code.findbugs</groupId>

View File

@ -25,11 +25,12 @@ import java.io.Serializable;
import java.net.URI; import java.net.URI;
import java.util.Map; import java.util.Map;
import javax.annotation.Nullable;
import org.jclouds.domain.Location; import org.jclouds.domain.Location;
import org.jclouds.domain.ResourceMetadata; import org.jclouds.domain.ResourceMetadata;
import com.google.common.collect.Maps; import com.google.common.collect.Maps;
import com.google.inject.internal.Nullable;
/** /**
* Idpayload of the object * Idpayload of the object

View File

@ -19,10 +19,15 @@
package org.jclouds.http; package org.jclouds.http;
import static com.google.common.base.Preconditions.checkNotNull;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import org.jclouds.io.Payload; import org.jclouds.io.Payload;
import com.google.common.collect.ImmutableMultimap;
import com.google.common.collect.Multimap;
/** /**
* Represents a response produced from {@link HttpCommandExecutorService} * Represents a response produced from {@link HttpCommandExecutorService}
* *
@ -34,9 +39,14 @@ public class HttpResponse extends HttpMessage {
private final String message; private final String message;
public HttpResponse(int statusCode, String message, @Nullable Payload payload) { public HttpResponse(int statusCode, String message, @Nullable Payload payload) {
this(statusCode, message, payload, ImmutableMultimap.<String, String> of());
}
public HttpResponse(int statusCode, String message, @Nullable Payload payload, Multimap<String, String> headers) {
super(payload); super(payload);
this.statusCode = statusCode; this.statusCode = statusCode;
this.message = message; this.message = message;
this.headers.putAll(checkNotNull(headers));
} }
public int getStatusCode() { public int getStatusCode() {
@ -49,8 +59,8 @@ public class HttpResponse extends HttpMessage {
@Override @Override
public String toString() { public String toString() {
return "[message=" + message + ", statusCode=" + statusCode + ", headers=" + headers return "[message=" + message + ", statusCode=" + statusCode + ", headers=" + headers + ", payload=" + payload
+ ", payload=" + payload + "]"; + "]";
} }
public String getStatusLine() { public String getStatusLine() {

View File

@ -19,8 +19,8 @@
package org.jclouds.http.handlers; package org.jclouds.http.handlers;
import static org.jclouds.http.HttpUtils.changePathTo; import static java.util.Collections.singletonList;
import static org.jclouds.http.HttpUtils.changeSchemeHostAndPortTo; import static javax.ws.rs.core.HttpHeaders.HOST;
import static org.jclouds.http.HttpUtils.closeClientButKeepContentStream; import static org.jclouds.http.HttpUtils.closeClientButKeepContentStream;
import java.net.URI; import java.net.URI;
@ -58,8 +58,7 @@ public class RedirectionRetryHandler implements HttpRetryHandler {
protected final Provider<UriBuilder> uriBuilderProvider; protected final Provider<UriBuilder> uriBuilderProvider;
@Inject @Inject
protected RedirectionRetryHandler(Provider<UriBuilder> uriBuilderProvider, protected RedirectionRetryHandler(Provider<UriBuilder> uriBuilderProvider, BackoffLimitedRetryHandler backoffHandler) {
BackoffLimitedRetryHandler backoffHandler) {
this.backoffHandler = backoffHandler; this.backoffHandler = backoffHandler;
this.uriBuilderProvider = uriBuilderProvider; this.uriBuilderProvider = uriBuilderProvider;
} }
@ -67,21 +66,32 @@ public class RedirectionRetryHandler implements HttpRetryHandler {
public boolean shouldRetryRequest(HttpCommand command, HttpResponse response) { public boolean shouldRetryRequest(HttpCommand command, HttpResponse response) {
closeClientButKeepContentStream(response); closeClientButKeepContentStream(response);
String hostHeader = response.getFirstHeaderOrNull(HttpHeaders.LOCATION); String hostHeader = response.getFirstHeaderOrNull(HttpHeaders.LOCATION);
if (hostHeader != null && command.incrementRedirectCount() < retryCountLimit) { if (command.incrementRedirectCount() < retryCountLimit && hostHeader != null) {
URI redirectionUrl = uriBuilderProvider.get().uri(URI.create(hostHeader)).build(); URI redirectionUrl = URI.create(hostHeader);
if (redirectionUrl.getScheme().equals(command.getRequest().getEndpoint().getScheme())
&& redirectionUrl.getHost().equals(command.getRequest().getEndpoint().getHost()) // if you are sent the same uri, assume there's a transient problem and retry.
&& redirectionUrl.getPort() == command.getRequest().getEndpoint().getPort()) { if (redirectionUrl.equals(command.getRequest().getEndpoint()))
if (!redirectionUrl.getPath().equals(command.getRequest().getEndpoint().getPath())) {
changePathTo(command.getRequest(), redirectionUrl.getPath(), uriBuilderProvider
.get());
} else {
return backoffHandler.shouldRetryRequest(command, response); 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()));
} }
} else { if (redirectionUrl.getPort() != command.getRequest().getEndpoint().getPort())
changeSchemeHostAndPortTo(command.getRequest(), redirectionUrl.getScheme(), builder.port(redirectionUrl.getPort());
redirectionUrl.getHost(), redirectionUrl.getPort(), uriBuilderProvider.get());
} if (redirectionUrl.getQuery() != null)
builder.replaceQuery(redirectionUrl.getQuery());
command.getRequest().setEndpoint(builder.build());
return true; return true;
} else { } else {
return false; return false;

View File

@ -19,18 +19,27 @@
package org.jclouds.io.payloads; package org.jclouds.io.payloads;
import java.io.ByteArrayInputStream;
import java.io.InputStream; 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 * @author Adrian Cole
*/ */
public class StringPayload extends BasePayload<String> { public class StringPayload extends BasePayload<String> {
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) { public StringPayload(String content) {
super(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<String> {
*/ */
@Override @Override
public InputStream getInput() { public InputStream getInput() {
return Utils.toInputStream(content); return new ByteArrayInputStream(bytes);
} }
} }

View File

@ -21,7 +21,9 @@ package org.jclouds.util;
import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull; 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.instanceOf;
import static com.google.common.base.Predicates.not;
import static com.google.common.base.Predicates.notNull; import static com.google.common.base.Predicates.notNull;
import static com.google.common.base.Splitter.on; import static com.google.common.base.Splitter.on;
import static com.google.common.base.Throwables.getCausalChain; 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.get;
import static com.google.common.collect.Iterables.transform; import static com.google.common.collect.Iterables.transform;
import static com.google.common.collect.Lists.newArrayList; 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.ByteStreams.toByteArray;
import static com.google.common.io.Closeables.closeQuietly; import static com.google.common.io.Closeables.closeQuietly;
import static org.jclouds.util.Patterns.CHAR_TO_PATTERN; import static org.jclouds.util.Patterns.CHAR_TO_PATTERN;
@ -47,10 +50,10 @@ import java.util.Comparator;
import java.util.Iterator; import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Map.Entry;
import java.util.NoSuchElementException; import java.util.NoSuchElementException;
import java.util.Properties; import java.util.Properties;
import java.util.Set; import java.util.Set;
import java.util.Map.Entry;
import java.util.regex.Matcher; import java.util.regex.Matcher;
import java.util.regex.Pattern; 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.Splitter;
import com.google.common.base.Supplier; import com.google.common.base.Supplier;
import com.google.common.collect.ImmutableList; 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.ImmutableSet;
import com.google.common.collect.Maps; import com.google.common.collect.Maps;
import com.google.common.io.OutputSupplier; import com.google.common.io.OutputSupplier;
@ -84,6 +89,32 @@ import com.google.inject.spi.Message;
*/ */
public class Utils { 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 <V>
* 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 <V> Map<String, V> renameKey(Map<String, V> in, String k1, String k2) {
if (in.containsKey(k1)) {
Builder<String, V> 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 <K, V> Supplier<Map<K, V>> composeMapSupplier(Iterable<Supplier<Map<K, V>>> suppliers) { public static <K, V> Supplier<Map<K, V>> composeMapSupplier(Iterable<Supplier<Map<K, V>>> suppliers) {
return new ListMapSupplier<K, V>(suppliers); return new ListMapSupplier<K, V>(suppliers);
} }

View File

@ -89,6 +89,12 @@ bluelock-vcdirector.propertiesbuilder=org.jclouds.vcloud.bluelock.BlueLockVCloud
gogrid.propertiesbuilder=org.jclouds.gogrid.GoGridPropertiesBuilder gogrid.propertiesbuilder=org.jclouds.gogrid.GoGridPropertiesBuilder
gogrid.contextbuilder=org.jclouds.gogrid.GoGridContextBuilder 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.propertiesbuilder=org.jclouds.ibmdev.IBMDeveloperCloudPropertiesBuilder
ibmdev.contextbuilder=org.jclouds.ibmdev.IBMDeveloperCloudContextBuilder 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.contextbuilder=org.jclouds.aws.s3.S3ContextBuilder
googlestorage.propertiesbuilder=org.jclouds.aws.s3.GoogleStoragePropertiesBuilder 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.contextbuilder=org.jclouds.blobstore.TransientBlobStoreContextBuilder
transient.propertiesbuilder=org.jclouds.blobstore.TransientBlobStorePropertiesBuilder transient.propertiesbuilder=org.jclouds.blobstore.TransientBlobStorePropertiesBuilder

View File

@ -0,0 +1,171 @@
/**
*
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ====================================================================
*/
package org.jclouds.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);
}
}

View File

@ -0,0 +1,40 @@
/**
*
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ====================================================================
*/
package org.jclouds.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));
}
}

View File

@ -29,12 +29,13 @@ import static org.testng.Assert.assertNull;
import java.io.IOException; import java.io.IOException;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.util.concurrent.ExecutorService;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import org.jclouds.Constants;
import org.jclouds.concurrent.MoreExecutors; import org.jclouds.concurrent.MoreExecutors;
import org.jclouds.concurrent.config.ConfiguresExecutorService; import org.jclouds.concurrent.config.ConfiguresExecutorService;
import org.jclouds.concurrent.config.ExecutorServiceModule;
import org.jclouds.crypto.Crypto; import org.jclouds.crypto.Crypto;
import org.jclouds.crypto.CryptoStreams; import org.jclouds.crypto.CryptoStreams;
import org.jclouds.http.HttpRequest; import org.jclouds.http.HttpRequest;
@ -47,6 +48,7 @@ import org.jclouds.rest.internal.RestAnnotationProcessor;
import com.google.inject.AbstractModule; import com.google.inject.AbstractModule;
import com.google.inject.Injector; import com.google.inject.Injector;
import com.google.inject.name.Names;
public abstract class BaseRestClientTest { public abstract class BaseRestClientTest {
@ -69,7 +71,8 @@ public abstract class BaseRestClientTest {
@Override @Override
protected void configure() { 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); bind(TransformingHttpCommandExecutorService.class).toInstance(mock);
} }
} }

View File

@ -23,6 +23,7 @@ import static org.easymock.classextension.EasyMock.createMock;
import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertEquals;
import java.io.UnsupportedEncodingException; import java.io.UnsupportedEncodingException;
import java.util.Map;
import java.util.concurrent.TimeoutException; import java.util.concurrent.TimeoutException;
import org.jclouds.domain.Credentials; import org.jclouds.domain.Credentials;
@ -42,6 +43,15 @@ import com.google.inject.spi.Message;
*/ */
@Test(groups = "unit", testName = "jclouds.UtilsTest") @Test(groups = "unit", testName = "jclouds.UtilsTest")
public class UtilsTest { public class UtilsTest {
public void testRenameKeyWhenNotFound() {
Map<String, String> nothing = ImmutableMap.of();
assertEquals(Utils.renameKey(nothing, "foo", "bar"), nothing);
}
public void testRenameKeyWhenFound() {
Map<String, String> nothing = ImmutableMap.of("foo", "bar");
assertEquals(Utils.renameKey(nothing, "foo", "bar"), ImmutableMap.of("bar", "bar"));
}
public void testOverridingCredentialsWhenOverridingIsNull() { public void testOverridingCredentialsWhenOverridingIsNull() {
Credentials defaultCredentials = new Credentials("foo", "bar"); Credentials defaultCredentials = new Credentials("foo", "bar");

View File

@ -103,7 +103,7 @@
<dependency> <dependency>
<groupId>com.google.code.guice</groupId> <groupId>com.google.code.guice</groupId>
<artifactId>guice-servlet</artifactId> <artifactId>guice-servlet</artifactId>
<version>2.1-r1201</version> <version>3.0-snapshot-20101120</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>displaytag</groupId> <groupId>displaytag</groupId>

View File

@ -49,12 +49,13 @@ import java.util.Collection;
import java.util.Date; import java.util.Date;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Map.Entry;
import java.util.Set; import java.util.Set;
import java.util.SortedSet; import java.util.SortedSet;
import java.util.TreeSet; import java.util.TreeSet;
import java.util.Map.Entry;
import java.util.concurrent.ExecutorService; import java.util.concurrent.ExecutorService;
import javax.annotation.Nullable;
import javax.annotation.Resource; import javax.annotation.Resource;
import javax.inject.Inject; import javax.inject.Inject;
import javax.inject.Named; import javax.inject.Named;
@ -66,13 +67,13 @@ import org.jclouds.blobstore.BlobStoreContext;
import org.jclouds.blobstore.ContainerNotFoundException; import org.jclouds.blobstore.ContainerNotFoundException;
import org.jclouds.blobstore.KeyNotFoundException; import org.jclouds.blobstore.KeyNotFoundException;
import org.jclouds.blobstore.domain.Blob; import org.jclouds.blobstore.domain.Blob;
import org.jclouds.blobstore.domain.Blob.Factory;
import org.jclouds.blobstore.domain.BlobMetadata; import org.jclouds.blobstore.domain.BlobMetadata;
import org.jclouds.blobstore.domain.MutableBlobMetadata; import org.jclouds.blobstore.domain.MutableBlobMetadata;
import org.jclouds.blobstore.domain.MutableStorageMetadata; import org.jclouds.blobstore.domain.MutableStorageMetadata;
import org.jclouds.blobstore.domain.PageSet; import org.jclouds.blobstore.domain.PageSet;
import org.jclouds.blobstore.domain.StorageMetadata; import org.jclouds.blobstore.domain.StorageMetadata;
import org.jclouds.blobstore.domain.StorageType; 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.MutableBlobMetadataImpl;
import org.jclouds.blobstore.domain.internal.MutableStorageMetadataImpl; import org.jclouds.blobstore.domain.internal.MutableStorageMetadataImpl;
import org.jclouds.blobstore.domain.internal.PageSetImpl; 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.collect.Iterables;
import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture; import com.google.common.util.concurrent.ListenableFuture;
import com.google.inject.internal.Nullable;
/** /**
* *

View File

@ -335,12 +335,12 @@ public class FilesystemStorageStrategyImpl implements FilesystemStorageStrategy
* @return the resulting string * @return the resulting string
*/ */
protected String buildPathStartingFromBaseDir(String...pathTokens) { protected String buildPathStartingFromBaseDir(String...pathTokens) {
String normalizedToken = removeFileSeparatorFromBorders(normalize(baseDirectory)); String normalizedToken = removeFileSeparatorFromBorders(normalize(baseDirectory), true);
StringBuilder completePath = new StringBuilder(normalizedToken); StringBuilder completePath = new StringBuilder(normalizedToken);
if(pathTokens!=null && pathTokens.length>0) { if(pathTokens!=null && pathTokens.length>0) {
for(int i=0; i<pathTokens.length; i++) { for(int i=0; i<pathTokens.length; i++) {
if(pathTokens[i]!=null) { if(pathTokens[i]!=null) {
normalizedToken = removeFileSeparatorFromBorders(normalize(pathTokens[i])); normalizedToken = removeFileSeparatorFromBorders(normalize(pathTokens[i]), false);
completePath.append(File.separator).append(normalizedToken); completePath.append(File.separator).append(normalizedToken);
} }
} }
@ -367,16 +367,19 @@ public class FilesystemStorageStrategyImpl implements FilesystemStorageStrategy
* Remove leading and trailing {@link File.separator} character from the * Remove leading and trailing {@link File.separator} character from the
* string. * string.
* @param pathToBeCleaned * @param pathToBeCleaned
* @param remove only trailing separator char from path
* @return * @return
*/ */
private String removeFileSeparatorFromBorders(String pathToBeCleaned) { private String removeFileSeparatorFromBorders(String pathToBeCleaned, boolean onlyTrailing) {
if (null == pathToBeCleaned || pathToBeCleaned.equals("")) return pathToBeCleaned; if (null == pathToBeCleaned || pathToBeCleaned.equals("")) return pathToBeCleaned;
int beginIndex = 0; int beginIndex = 0;
int endIndex = pathToBeCleaned.length(); int endIndex = pathToBeCleaned.length();
//search for separator chars //search for separator chars
if (!onlyTrailing) {
if (pathToBeCleaned.substring(0, 1).equals(File.separator)) beginIndex = 1; if (pathToBeCleaned.substring(0, 1).equals(File.separator)) beginIndex = 1;
}
if (pathToBeCleaned.substring(pathToBeCleaned.length() - 1).equals(File.separator)) endIndex--; if (pathToBeCleaned.substring(pathToBeCleaned.length() - 1).equals(File.separator)) endIndex--;
return pathToBeCleaned.substring(beginIndex, endIndex); return pathToBeCleaned.substring(beginIndex, endIndex);

View File

@ -185,16 +185,8 @@ public class FilesystemAsyncBlobStoreTest {
/** /**
* Test of list method, of class FilesystemAsyncBlobStore. * Test of list method, of class FilesystemAsyncBlobStore.
*/ */
public void testList_NoOptionSingleContainer() throws IOException { public void testList_NoOptionSingleContainer()
throws IOException {
// Testing list for a not existing container
try {
blobStore.list(CONTAINER_NAME);
fail("Found a not existing container");
} catch(ContainerNotFoundException e) {
}
blobStore.createContainerInLocation(null, CONTAINER_NAME); blobStore.createContainerInLocation(null, CONTAINER_NAME);
// Testing list for an empty container // Testing list for an empty container
checkForContainerContent(CONTAINER_NAME, null); checkForContainerContent(CONTAINER_NAME, null);
@ -268,6 +260,29 @@ public class FilesystemAsyncBlobStoreTest {
} }
public void testList_Subdirectory()
throws IOException {
blobStore.createContainerInLocation(null, CONTAINER_NAME);
// Testing list for an empty container
checkForContainerContent(CONTAINER_NAME, null);
//creates blobs in first container
Set<String> 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 * TODO
* Should throws an exception? * Should throws an exception?
@ -809,12 +824,17 @@ public class FilesystemAsyncBlobStoreTest {
* @param expectedBlobKeys * @param expectedBlobKeys
*/ */
private void checkForContainerContent(final String containerName, Set<String> expectedBlobKeys) { private void checkForContainerContent(final String containerName, Set<String> expectedBlobKeys) {
checkForContainerContent(containerName, null, expectedBlobKeys);
}
private void checkForContainerContent(final String containerName, String inDirectory, Set<String> expectedBlobKeys) {
ListContainerOptions options = ListContainerOptions.Builder.recursive(); ListContainerOptions options = ListContainerOptions.Builder.recursive();
if (null != inDirectory && !"".equals(inDirectory)) options.inDirectory(inDirectory);
PageSet<? extends StorageMetadata> blobsRetrieved = blobStore.list(containerName, options); PageSet<? extends StorageMetadata> blobsRetrieved = blobStore.list(containerName, options);
//nothing expected //nothing expected
if (null == expectedBlobKeys) { if (null == expectedBlobKeys || 0 == expectedBlobKeys.size()) {
assertTrue(blobsRetrieved.isEmpty(), "Wrong blob number retrieved in the containter [" + containerName + "]"); assertTrue(blobsRetrieved.isEmpty(), "Wrong blob number retrieved in the containter [" + containerName + "]");
return; return;
} }

View File

@ -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 { public void testBlobExists() throws IOException {
String[] sourceBlobKeys = new String[]{ String[] sourceBlobKeys = new String[]{
TestUtils.createRandomBlobKey("blobExists-", ".jpg"), TestUtils.createRandomBlobKey("blobExists-", ".jpg"),
@ -530,5 +562,16 @@ public class FilesystemStorageStrategyImplTest {
//---------------------------------------------------------- Private methods //---------------------------------------------------------- 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;
}
} }

View File

@ -89,6 +89,8 @@ public class ServerImage implements Comparable<ServerImage> {
} }
public String getDescription() { public String getDescription() {
if (description == null)
return "";
return description; return description;
} }

View File

@ -99,6 +99,7 @@ public class ParseServerNameToCredentialsMapFromJsonResponse implements
@Override @Override
public int compareTo(Password o) { public int compareTo(Password o) {
if (null == o.getServer() || null == server) return -1;
return server.getName().compareTo(o.getServer().getName()); return server.getName().compareTo(o.getServer().getName());
} }
} }
@ -107,6 +108,7 @@ public class ParseServerNameToCredentialsMapFromJsonResponse implements
public Map<String, Credentials> apply(HttpResponse arg0) { public Map<String, Credentials> apply(HttpResponse arg0) {
Map<String, Credentials> serverNameToCredentials = Maps.newHashMap(); Map<String, Credentials> serverNameToCredentials = Maps.newHashMap();
for (Password password : json.apply(arg0).getList()) { for (Password password : json.apply(arg0).getList()) {
if( null != password.getServer())
serverNameToCredentials.put(password.getServer().getName(), serverNameToCredentials.put(password.getServer().getName(),
new Credentials(password.getUserName(), password.getPassword())); new Credentials(password.getUserName(), password.getPassword()));
} }

View File

@ -71,7 +71,7 @@ public class ParseCredentialsFromJsonResponseTest {
ParseCredentialsFromJsonResponse parser = i.getInstance(ParseCredentialsFromJsonResponse.class); ParseCredentialsFromJsonResponse parser = i.getInstance(ParseCredentialsFromJsonResponse.class);
Credentials creds = parser.apply(response); Credentials creds = parser.apply(response);
assertEquals(creds.identity, "root"); assertEquals(creds.identity, "root");
assertEquals(creds.credential, "dig44sos"); assertEquals(creds.credential, "zot40ced");
} }

View File

@ -1,102 +1,123 @@
{ {
"list": [ "list": [
{ {
"password": "dig44sos", "password": "zot40ced",
"object": "password", "object": "password",
"username": "root", "username": "root",
"server": { "server": {
"object": "server",
"isSandbox": false, "isSandbox": false,
"object": "server",
"type": { "type": {
"object": "option", "id": 1,
"description": "Web or Application Server", "description": "Web or Application Server",
"name": "Web Server", "name": "Web Server",
"id": 1 "object": "option"
}, },
"os": { "os": {
"object": "option", "id": 17,
"description": "CentOS 5.3 (64-bit)", "description": "CentOS 5.3 (64-bit)",
"name": "CentOS 5.3 (64-bit)", "name": "CentOS 5.3 (64-bit)",
"id": 17 "object": "option"
}, },
"image": { "image": {
"type": { "type": {
"object": "option", "id": 1,
"description": "Web or Application Server", "description": "Web or Application Server",
"name": "Web Server", "name": "Web Server",
"id": 1 "object": "option"
}, },
"owner": { "owner": {
"object": "customer", "id": -1,
"name": "Gear6", "name": "GoGrid",
"id": 26443 "object": "customer"
}, },
"updatedTime": 1265675466171, "updatedTime": 1257789076417,
"isActive": true, "isActive": true,
"id": 2500, "id": 1532,
"createdTime": 1265412834154,
"isPublic": true, "isPublic": true,
"name": "centos5.3_64_base",
"billingtokens": [ "billingtokens": [
{ {
"id": 47,
"price": 0, "price": 0,
"name": "CentOS 5.3 64bit", "name": "CentOS 5.3 64bit",
"id": 47 "object": "billingtoken"
},
{
"price": 60,
"name": "Gear 6 Paid Version",
"id": 76
} }
], ],
"object": "serverimage", "object": "serverimage",
"friendlyName": "gear6-memcache-server-2.3.6.2-x86_64", "friendlyName": "CentOS 5.3 (64-bit) w/ None",
"os": { "os": {
"object": "option", "id": 17,
"description": "CentOS 5.3 (64-bit)", "description": "CentOS 5.3 (64-bit)",
"name": "CentOS 5.3 (64-bit)", "name": "CentOS 5.3 (64-bit)",
"id": 17 "object": "option"
}, },
"price": 60, "price": 0,
"description": "Gear6 Memcache Server 2.3.6.2 (64 bit)", "description": "CentOS 5.3 (64-bit) w/ None",
"state": { "state": {
"object": "option", "id": 2,
"description": "Image is available for adds", "description": "Image is available for adds",
"name": "Available", "name": "Available",
"id": 2 "object": "option"
}, },
"location": "26443/GSI-7f498260-2b8a-43ef-aa77-5b403f8f739a.img", "location": "gogrid/GSI-939ef909-84b8-4a2f-ad56-02ccd7da05ff.img",
"name": "GSI-7f498260-2b8a-43ef-aa77-5b403f8f739a" "name": "bogus",
"architecture": {
"id": 2,
"description": "64 bit OS",
"name": "64-bit",
"object": "option"
}
}, },
"state": { "state": {
"object": "option", "id": 1,
"description": "Server is in active state.", "description": "Server is in active state.",
"name": "On", "name": "On",
"id": 1 "object": "option"
}, },
"ram": { "ram": {
"object": "option", "id": 1,
"description": "Server with 512MB RAM", "description": "Server with 512MB RAM",
"name": "512MB", "name": "512MB",
"id": 1 "object": "option"
}, },
"name": "gogrid-19", "name": "proxied-944",
"ip": { "ip": {
"object": "ip", "id": 1104200,
"public": true, "subnet": "173.1.155.16/255.255.255.240",
"subnet": "204.51.240.176/255.255.255.240",
"state": { "state": {
"object": "option", "id": 2,
"description": "IP is reserved or in use", "description": "IP is reserved or in use",
"name": "Assigned", "name": "Assigned",
"id": 2 "object": "option"
}, },
"ip": "204.51.240.189", "datacenter": {
"id": 1313090 "id": 1,
"description": "US West 1 Datacenter",
"name": "US-West-1",
"object": "option"
}, },
"id": 77332 "object": "ip",
"public": true,
"ip": "173.1.155.19"
}, },
"id": 82647, "datacenter": {
"id": 1,
"description": "US West 1 Datacenter",
"name": "US-West-1",
"object": "option"
},
"id": 134551
},
"id": 142243,
"applicationtype": "os" "applicationtype": "os"
},
{
"id": 28000,
"username": "22290",
"applicationtype": "cloudstorage",
"object": "password",
"password": "200FMd2nDeomtfW."
} }
], ],
"summary": { "summary": {

View File

@ -19,10 +19,11 @@
package org.jclouds.rackspace.cloudfiles.domain; package org.jclouds.rackspace.cloudfiles.domain;
import javax.annotation.Nullable;
import org.jclouds.io.PayloadEnclosing; import org.jclouds.io.PayloadEnclosing;
import com.google.common.collect.Multimap; import com.google.common.collect.Multimap;
import com.google.inject.internal.Nullable;
/** /**
* *

View File

@ -24,11 +24,12 @@ import static com.google.common.base.Preconditions.checkNotNull;
import java.util.Map; import java.util.Map;
import javax.annotation.Nullable;
import org.jclouds.http.HttpRequest; import org.jclouds.http.HttpRequest;
import org.jclouds.rest.binders.BindToJsonPayload; import org.jclouds.rest.binders.BindToJsonPayload;
import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableMap;
import com.google.inject.internal.Nullable;
/** /**
* *

View File

@ -0,0 +1,139 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright (C) 2010 Cloud Conscious, LLC <info@cloudconscious.com>
====================================================================
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0.html
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.
====================================================================
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.jclouds</groupId>
<artifactId>jclouds-project</artifactId>
<version>1.0-SNAPSHOT</version>
<relativePath>../../project/pom.xml</relativePath>
</parent>
<groupId>org.jclouds</groupId>
<artifactId>jclouds-elasticstack</artifactId>
<name>jclouds elasticstack core</name>
<description>jclouds components to access elasticstack</description>
<scm>
<connection>scm:svn:http://jclouds.googlecode.com/svn/trunk/elasticstack</connection>
<developerConnection>scm:svn:https://jclouds.googlecode.com/svn/trunk/elasticstack</developerConnection>
<url>http://jclouds.googlecode.com/svn/trunk/elasticstack</url>
</scm>
<!-- bootstrapping: need to fetch the project POM -->
<repositories>
<repository>
<id>jclouds-googlecode-deploy</id>
<url>http://jclouds.googlecode.com/svn/repo</url>
</repository>
<repository>
<id>jclouds-rimu-snapshots-nexus</id>
<url>https://oss.sonatype.org/content/repositories/snapshots</url>
<snapshots>
<enabled>true</enabled>
</snapshots>
</repository>
</repositories>
<properties>
<!-- when instances are hung, open a ticket and add here -->
<jclouds.compute.blacklist-nodes>trmkrun-ccc,test.trmk-924</jclouds.compute.blacklist-nodes>
<test.elasticstack.endpoint>https://api.cloudsigma.com</test.elasticstack.endpoint>
<test.elasticstack.apiversion>1.0</test.elasticstack.apiversion>
<test.elasticstack.identity>FIXME</test.elasticstack.identity>
<test.elasticstack.credential>FIXME</test.elasticstack.credential>
</properties>
<dependencies>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>jclouds-core</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>jclouds-core</artifactId>
<version>${project.version}</version>
<type>test-jar</type>
<scope>test</scope>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.14</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>jclouds-log4j</artifactId>
<version>${project.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
<profiles>
<profile>
<id>live</id>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<executions>
<execution>
<id>integration</id>
<phase>integration-test</phase>
<goals>
<goal>test</goal>
</goals>
<configuration>
<systemProperties>
<property>
<name>test.elasticstack.endpoint</name>
<value>${test.elasticstack.endpoint}</value>
</property>
<property>
<name>test.elasticstack.apiversion</name>
<value>${test.elasticstack.apiversion}</value>
</property>
<property>
<name>test.elasticstack.identity</name>
<value>${test.elasticstack.identity}</value>
</property>
<property>
<name>test.elasticstack.credential</name>
<value>${test.elasticstack.credential}</value>
</property>
<property>
<name>jclouds.compute.blacklist-nodes</name>
<value>${jclouds.compute.blacklist-nodes}</value>
</property>
</systemProperties>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
</profiles>
</project>

View File

@ -0,0 +1,125 @@
/**
*
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ====================================================================
*/
package org.jclouds.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.
* <p/>
*
* @see ElasticStackClient
* @see <a href="TODO: insert URL of provider documentation" />
* @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<Set<String>> listStandardDrives();
/**
* @see ElasticStackClient#listStandardCds()
*/
@GET
@Path("/drives/standard/cd/list")
@ResponseParser(SplitNewlines.class)
ListenableFuture<Set<String>> listStandardCds();
/**
* @see ElasticStackClient#listStandardImages()
*/
@GET
@Path("/drives/standard/img/list")
@ResponseParser(SplitNewlines.class)
ListenableFuture<Set<String>> listStandardImages();
/**
* @see ElasticStackClient#listDriveInfo()
*/
@Override
@GET
@Path("/drives/info")
@ResponseParser(ListOfKeyValuesDelimitedByBlankLinesToDriveInfoSet.class)
ListenableFuture<Set<? extends org.jclouds.elasticstack.domain.DriveInfo>> listDriveInfo();
/**
* @see ElasticStackClient#getDriveInfo
*/
@Override
@GET
@ExceptionParser(ReturnNullOnNotFoundOr404.class)
@ResponseParser(KeyValuesDelimitedByBlankLinesToDriveInfo.class)
@Path("/drives/{uuid}/info")
ListenableFuture<? extends DriveInfo> getDriveInfo(@PathParam("uuid") String uuid);
/**
* @see ElasticStackClient#createDrive
*/
@Override
@POST
@ExceptionParser(ReturnNullOnNotFoundOr404.class)
@ResponseParser(KeyValuesDelimitedByBlankLinesToDriveInfo.class)
@Path("/drives/create")
ListenableFuture<? extends DriveInfo> createDrive(
@BinderParam(BindCreateDriveRequestToPlainTextString.class) CreateDriveRequest createDrive);
/**
* @see ElasticStackClient#setDriveData
*/
@POST
@ExceptionParser(ReturnNullOnNotFoundOr404.class)
@ResponseParser(KeyValuesDelimitedByBlankLinesToDriveInfo.class)
@Path("/drives/{uuid}/set")
ListenableFuture<? extends DriveInfo> setDriveData(@PathParam("uuid") String uuid,
@BinderParam(BindDriveDataToPlainTextString.class) DriveData createDrive);
}

View File

@ -0,0 +1,87 @@
/**
*
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ====================================================================
*/
package org.jclouds.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.
* <p/>
*
* @see CloudSigmaAsyncClient
* @see <a href="TODO: insert URL of elasticstack documentation" />
* @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<String> listStandardDrives();
/**
* list of cd uuids that are in the library
*
* @return or empty set if no cds are found
*/
Set<String> listStandardCds();
/**
* list of image uuids that are in the library
*
* @return or empty set if no images are found
*/
Set<String> listStandardImages();
/**
* {@inheritDoc}
*/
@Override
Set<? extends DriveInfo> listDriveInfo();
/**
* {@inheritDoc}
*/
@Override
DriveInfo getDriveInfo(String uuid);
/**
* {@inheritDoc}
*/
@Override
DriveInfo createDrive(CreateDriveRequest createDrive);
/**
* {@inheritDoc}
*/
@Override
DriveInfo setDriveData(String uuid, DriveData driveData);
}

View File

@ -0,0 +1,45 @@
/**
*
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ====================================================================
*/
package org.jclouds.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<CloudSigmaClient, CloudSigmaAsyncClient> {
public CloudSigmaContextBuilder(Properties props) {
super(CloudSigmaClient.class, CloudSigmaAsyncClient.class, props);
}
protected void addClientModule(List<Module> modules) {
modules.add(new CloudSigmaRestClientModule());
}
}

View File

@ -0,0 +1,47 @@
/**
*
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ====================================================================
*/
package org.jclouds.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);
}
}

View File

@ -0,0 +1,76 @@
/**
*
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ====================================================================
*/
package org.jclouds.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<CloudSigmaClient, CloudSigmaAsyncClient> {
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<Function<CreateDriveRequest, Map<String, String>>>() {
}).to(CreateDriveRequestToMap.class);
bind(new TypeLiteral<Function<DriveData, Map<String, String>>>() {
}).to(DriveDataToMap.class);
}
@Override
protected void bindRetryHandlers() {
// TODO
}
}

View File

@ -0,0 +1,415 @@
/**
*
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ====================================================================
*/
package org.jclouds.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<String> 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<String> 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<String> 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<String> 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<String> tags) {
return Builder.class.cast(super.tags(tags));
}
/**
* {@inheritDoc}
*/
@Override
public Builder userMetadata(Map<String, String> 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<String> 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<String> readers,
Iterable<String> tags, Map<String, String> userMetadata, DriveStatus status, String user, Set<String> claimed,
String encryptionCipher, String imaging, long readBytes, long readRequests, long writeBytes,
long writeRequests, Boolean autoexpanding, Integer bits, String description, Iterable<String> 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<String> 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;
}
}

View File

@ -0,0 +1,48 @@
/**
*
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ====================================================================
*/
package org.jclouds.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;
}
}
}

View File

@ -0,0 +1,58 @@
/**
*
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ====================================================================
*/
package org.jclouds.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<CreateDriveRequest, Map<String, String>> {
private final org.jclouds.elasticstack.functions.CreateDriveRequestToMap baseDriveToMap;
@Inject
public CreateDriveRequestToMap(org.jclouds.elasticstack.functions.CreateDriveRequestToMap baseDriveToMap) {
this.baseDriveToMap = baseDriveToMap;
}
@Override
public Map<String, String> apply(CreateDriveRequest from) {
return Maps.transformEntries(renameKey(baseDriveToMap.apply(from), "tags", "use"),
new Maps.EntryTransformer<String, String, String>() {
@Override
public String transformEntry(String arg0, String arg1) {
return "use".equals(arg0) ? arg1.replace(' ', ',') : arg1;
}
}); }
}

View File

@ -0,0 +1,59 @@
/**
*
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ====================================================================
*/
package org.jclouds.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<DriveData, Map<String, String>> {
private final org.jclouds.elasticstack.functions.DriveDataToMap baseDriveToMap;
@Inject
public DriveDataToMap(org.jclouds.elasticstack.functions.DriveDataToMap baseDriveToMap) {
this.baseDriveToMap = baseDriveToMap;
}
@Override
public Map<String, String> apply(DriveData from) {
return Maps.transformEntries(renameKey(baseDriveToMap.apply(from), "tags", "use"),
new Maps.EntryTransformer<String, String, String>() {
@Override
public String transformEntry(String arg0, String arg1) {
return "use".equals(arg0) ? arg1.replace(' ', ',') : arg1;
}
});
}
}

View File

@ -0,0 +1,53 @@
/**
*
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ====================================================================
*/
package org.jclouds.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<HttpResponse, DriveInfo> {
private final ListOfKeyValuesDelimitedByBlankLinesToDriveInfoSet setParser;
@Inject
public KeyValuesDelimitedByBlankLinesToDriveInfo(ListOfKeyValuesDelimitedByBlankLinesToDriveInfoSet setParser) {
this.setParser = setParser;
}
@Override
public DriveInfo apply(HttpResponse response) {
Set<DriveInfo> drives = setParser.apply(response);
if (drives.size() == 0)
return null;
return Iterables.get(drives, 0);
}
}

View File

@ -0,0 +1,61 @@
/**
*
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ====================================================================
*/
package org.jclouds.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<HttpResponse, Set<DriveInfo>> {
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<DriveInfo> apply(HttpResponse response) {
String text = returnStringIf200.apply(response);
if (text == null || text.trim().equals(""))
return ImmutableSet.<DriveInfo> of();
return ImmutableSet.copyOf(Iterables.transform(mapConverter.apply(text), mapToDrive));
}
}

View File

@ -0,0 +1,72 @@
/**
*
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ====================================================================
*/
package org.jclouds.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<Map<String, String>, 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<String, String> 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();
}
}

View File

@ -0,0 +1,114 @@
/**
*
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ====================================================================
*/
package org.jclouds.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.
* <p/>
*
* @see ElasticStackClient
* @see <a href="TODO: insert URL of provider documentation" />
* @author Adrian Cole
*/
@RequestFilters(BasicAuthentication.class)
@Consumes(MediaType.TEXT_PLAIN)
public interface CommonElasticStackAsyncClient {
/**
* @see ElasticStackClient#listDrives()
*/
@GET
@Path("/drives/list")
@ResponseParser(SplitNewlines.class)
ListenableFuture<Set<String>> listDrives();
/**
* @see ElasticStackClient#listDriveInfo()
*/
@GET
@Path("/drives/info")
@ResponseParser(ListOfKeyValuesDelimitedByBlankLinesToDriveInfoSet.class)
ListenableFuture<Set<? extends DriveInfo>> listDriveInfo();
/**
* @see ElasticStackClient#getDriveInfo
*/
@GET
@ExceptionParser(ReturnNullOnNotFoundOr404.class)
@ResponseParser(KeyValuesDelimitedByBlankLinesToDriveInfo.class)
@Path("/drives/{uuid}/info")
ListenableFuture<? extends DriveInfo> getDriveInfo(@PathParam("uuid") String uuid);
/**
* @see ElasticStackClient#createDrive
*/
@POST
@ExceptionParser(ReturnNullOnNotFoundOr404.class)
@ResponseParser(KeyValuesDelimitedByBlankLinesToDriveInfo.class)
@Path("/drives/create")
ListenableFuture<? extends DriveInfo> createDrive(
@BinderParam(BindCreateDriveRequestToPlainTextString.class) CreateDriveRequest createDrive);
/**
* @see ElasticStackClient#setDriveData
*/
@POST
@ExceptionParser(ReturnNullOnNotFoundOr404.class)
@ResponseParser(KeyValuesDelimitedByBlankLinesToDriveInfo.class)
@Path("/drives/{uuid}/set")
ListenableFuture<? extends DriveInfo> setDriveData(@PathParam("uuid") String uuid,
@BinderParam(BindDriveDataToPlainTextString.class) DriveData createDrive);
/**
* @see ElasticStackClient#destroyDrive
*/
@POST
@Path("/drives/{uuid}/destroy")
@ExceptionParser(ReturnVoidOnNotFoundOr404.class)
ListenableFuture<Void> destroyDrive(@PathParam("uuid") String uuid);
}

View File

@ -0,0 +1,90 @@
/**
*
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ====================================================================
*/
package org.jclouds.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.
* <p/>
*
* @see ElasticStackAsyncClient
* @see <a href="TODO: insert URL of elasticstack documentation" />
* @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<String> listDrives();
/**
* Get all drives info
*
* @return or empty set if no drives are found
*/
Set<? extends DriveInfo> 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);
}

View File

@ -0,0 +1,112 @@
/**
*
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ====================================================================
*/
package org.jclouds.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.
* <p/>
*
* @see ElasticStackClient
* @see <a href="TODO: insert URL of provider documentation" />
* @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<Void> 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<Void> 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<Payload> 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<Payload> 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<Void> 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<Void> writeDrive(@PathParam("uuid") String uuid, Payload content, @PathParam("offset") long offset);
}

View File

@ -0,0 +1,97 @@
/**
*
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ====================================================================
*/
package org.jclouds.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.
* <p/>
*
* @see ElasticStackAsyncClient
* @see <a href="TODO: insert URL of elasticstack documentation" />
* @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.
* <ul>
* <li>Binary data (Content-Type: application/octet-stream)</li>
* <li>Supports raw data or Content-Encoding: gzip</li>
* <li>Does not support Transfer-Encoding: chunked</li>
* </ul>
*/
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);
}

View File

@ -0,0 +1,45 @@
/**
*
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ====================================================================
*/
package org.jclouds.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<ElasticStackClient, ElasticStackAsyncClient> {
public ElasticStackContextBuilder(Properties props) {
super(ElasticStackClient.class, ElasticStackAsyncClient.class, props);
}
protected void addClientModule(List<Module> modules) {
modules.add(new ElasticStackRestClientModule());
}
}

View File

@ -0,0 +1,45 @@
/**
*
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ====================================================================
*/
package org.jclouds.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);
}
}

View File

@ -0,0 +1,61 @@
/**
*
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ====================================================================
*/
package org.jclouds.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<CreateDriveRequest, Map<String, String>> createDriveRequestToMap;
private final ListOfMapsToListOfKeyValuesDelimitedByBlankLines listOfMapsToListOfKeyValuesDelimitedByBlankLines;
@Inject
public BindCreateDriveRequestToPlainTextString(Function<CreateDriveRequest, Map<String, String>> 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<String, String> map = createDriveRequestToMap.apply(create);
request.setPayload(listOfMapsToListOfKeyValuesDelimitedByBlankLines.apply(ImmutableSet.of(map)));
request.getPayload().getContentMetadata().setContentType(MediaType.TEXT_PLAIN);
}
}

View File

@ -0,0 +1,61 @@
/**
*
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ====================================================================
*/
package org.jclouds.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<DriveData, Map<String, String>> createDriveRequestToMap;
private final ListOfMapsToListOfKeyValuesDelimitedByBlankLines listOfMapsToListOfKeyValuesDelimitedByBlankLines;
@Inject
public BindDriveDataToPlainTextString(Function<DriveData, Map<String, String>> 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<String, String> map = createDriveRequestToMap.apply(create);
request.setPayload(listOfMapsToListOfKeyValuesDelimitedByBlankLines.apply(ImmutableSet.of(map)));
request.getPayload().getContentMetadata().setContentType(MediaType.TEXT_PLAIN);
}
}

View File

@ -0,0 +1,59 @@
/**
*
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ====================================================================
*/
package org.jclouds.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<UriBuilder> uriBuilderProvider;
@Inject
public BindReadDriveOptionsToPath(Provider<UriBuilder> 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());
}
}
}

View File

@ -0,0 +1,76 @@
/**
*
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ====================================================================
*/
package org.jclouds.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<ElasticStackClient, ElasticStackAsyncClient> {
public ElasticStackRestClientModule() {
super(ElasticStackClient.class, ElasticStackAsyncClient.class);
}
@Override
protected void configure() {
super.configure();
bind(new TypeLiteral<Function<CreateDriveRequest, Map<String, String>>>() {
}).to(CreateDriveRequestToMap.class);
bind(new TypeLiteral<Function<DriveData, Map<String, String>>>() {
}).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
}
}

View File

@ -0,0 +1,73 @@
/**
*
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ====================================================================
*/
package org.jclouds.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 + "]";
}
}

View File

@ -0,0 +1,57 @@
/**
*
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ====================================================================
*/
package org.jclouds.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;
}
}
}

View File

@ -0,0 +1,176 @@
/**
*
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ====================================================================
*/
package org.jclouds.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<String> avoid = ImmutableSet.of();
@Nullable
private String encryptionCipher;
public Builder avoid(Iterable<String> 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<String> 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<String> tags) {
return Builder.class.cast(super.tags(tags));
}
/**
* {@inheritDoc}
*/
@Override
public Builder userMetadata(Map<String, String> 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<String> avoid;
@Nullable
private final String encryptionCipher;
public CreateDriveRequest(String name, long size, @Nullable ClaimType claimType, Iterable<String> readers,
Iterable<String> tags, Map<String, String> userMetadata, @Nullable String encryptionCipher,
Iterable<String> 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<String> 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
+ "]";
}
}

View File

@ -0,0 +1,91 @@
/**
*
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ====================================================================
*/
package org.jclouds.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 + "]";
}
}

View File

@ -0,0 +1,93 @@
/**
*
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ====================================================================
*/
package org.jclouds.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<String> 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<String> tags) {
return Builder.class.cast(super.tags(tags));
}
/**
* {@inheritDoc}
*/
@Override
public Builder userMetadata(Map<String, String> 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<String> readers,
Iterable<String> tags, Map<String, String> userMetadata) {
super(uuid, name, size, claimType, readers, tags, userMetadata);
}
}

View File

@ -0,0 +1,342 @@
/**
*
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ====================================================================
*/
package org.jclouds.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<String> 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<String> 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<String> 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<String> tags) {
return Builder.class.cast(super.tags(tags));
}
/**
* {@inheritDoc}
*/
@Override
public Builder userMetadata(Map<String, String> 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<String> 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<String> readers,
Iterable<String> tags, Map<String, String> userMetadata, DriveStatus status, String user, Set<String> 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<String> 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 + "]";
}
}

View File

@ -0,0 +1,48 @@
/**
*
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ====================================================================
*/
package org.jclouds.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;
}
}
}

View File

@ -0,0 +1,83 @@
/**
*
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ====================================================================
*/
package org.jclouds.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 + "]";
}
}

View File

@ -0,0 +1,48 @@
/**
*
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ====================================================================
*/
package org.jclouds.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;
}
}
}

View File

@ -0,0 +1,199 @@
/**
*
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ====================================================================
*/
package org.jclouds.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<String> tags = ImmutableSet.of();
protected Map<String, String> 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<String> tags) {
this.tags = ImmutableSet.copyOf(checkNotNull(tags, "tags"));
return this;
}
public Builder userMetadata(Map<String, String> 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<String> tags;
protected final Map<String, String> userMetadata;
public Item(@Nullable String uuid, String name, Iterable<String> tags, Map<String, String> 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<String> getTags() {
return tags;
}
/**
*
* @return user-defined KEY VALUE pairs
*/
public Map<String, String> 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 + "]";
}
}

View File

@ -0,0 +1,50 @@
/**
*
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ====================================================================
*/
package org.jclouds.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;
}
}
}

View File

@ -0,0 +1,47 @@
/**
*
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ====================================================================
*/
package org.jclouds.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;
}
}
}

View File

@ -0,0 +1,122 @@
/**
*
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ====================================================================
*/
package org.jclouds.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 + "]";
}
}

View File

@ -0,0 +1,81 @@
/**
*
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ====================================================================
*/
package org.jclouds.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 + "]";
}
}

View File

@ -0,0 +1,337 @@
/**
*
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ====================================================================
*/
package org.jclouds.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<? extends Device> devices = ImmutableSet.of();
protected Set<String> bootDeviceIds = ImmutableSet.of();
protected List<NIC> 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<? extends Device> devices) {
this.devices = ImmutableSet.copyOf(checkNotNull(devices, "devices"));
return this;
}
public Builder bootDeviceIds(Iterable<String> bootDeviceIds) {
this.bootDeviceIds = ImmutableSet.copyOf(checkNotNull(bootDeviceIds, "bootDeviceIds"));
return this;
}
public Builder nics(Iterable<NIC> 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<String> tags) {
return Builder.class.cast(super.tags(tags));
}
/**
* {@inheritDoc}
*/
@Override
public Builder userMetadata(Map<String, String> 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<? extends Device> devices;
protected final Set<String> bootDeviceIds;
@Nullable
protected final String user;
protected final List<NIC> 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<? extends Device> devices, Iterable<String> bootDeviceIds, Iterable<String> tags,
Map<String, String> userMetadata, Iterable<NIC> 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<? extends Device> getDevices() {
return devices;
}
/**
*
* @return ids of the devices to boot, e.g. ide:0:0 or ide:1:0
* @see Device#getId()
*/
public Set<String> getBootDeviceIds() {
return bootDeviceIds;
}
public List<NIC> 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 + "]";
}
}

View File

@ -0,0 +1,105 @@
/**
*
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ====================================================================
*/
package org.jclouds.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 + "]";
}
}

View File

@ -0,0 +1,221 @@
/**
*
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ====================================================================
*/
package org.jclouds.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<String> readers = ImmutableSet.of();
public Builder claimType(ClaimType claimType) {
this.claimType = claimType;
return this;
}
public Builder readers(Iterable<String> 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<String> tags) {
return Builder.class.cast(super.tags(tags));
}
/**
* {@inheritDoc}
*/
@Override
public Builder userMetadata(Map<String, String> 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<String> readers;
public BaseDrive(@Nullable String uuid, String name, long size, @Nullable ClaimType claimType,
Iterable<String> readers, Iterable<String> tags, Map<String, String> 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<String> 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 + "]";
}
}

View File

@ -0,0 +1,58 @@
/**
*
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ====================================================================
*/
package org.jclouds.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<BaseDrive, Map<String, String>> {
@Override
public Map<String, String> apply(BaseDrive from) {
checkNotNull(from, "drive");
ImmutableMap.Builder<String, String> 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<String, String> entry : from.getUserMetadata().entrySet())
builder.put("user:" + entry.getKey(), entry.getValue());
return builder.build();
}
}

Some files were not shown because too many files have changed in this diff Show More