Issue 27: added 'walrus' blobstore and 'eucalyptus' compute providers

This commit is contained in:
Adrian Cole 2010-06-15 15:22:32 -04:00
parent 55fa55a0dc
commit cba3f660fb
19 changed files with 939 additions and 395 deletions

View File

@ -0,0 +1,51 @@
/**
*
* Copyright (C) 2009 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;
import static org.jclouds.aws.ec2.reference.EC2Constants.PROPERTY_EC2_AMI_OWNERS;
import static org.jclouds.aws.ec2.reference.EC2Constants.PROPERTY_EC2_ENDPOINT;
import java.util.Properties;
/**
* Builds properties used in Eucalyptus Clients
*
* @author Adrian Cole
*/
public class EucalyptusPropertiesBuilder extends EC2PropertiesBuilder {
@Override
protected Properties defaultProperties() {
Properties properties = super.defaultProperties();
properties.setProperty(PROPERTY_EC2_ENDPOINT,
"http://173.205.188.130:8773/services/Eucalyptus");
// TODO
// properties.setProperty(PROPERTY_ELB_ENDPOINT,
// "https://elasticloadbalancing.us-east-1.amazonaws.com");
properties.setProperty(PROPERTY_EC2_AMI_OWNERS, "admin");
return properties;
}
public EucalyptusPropertiesBuilder(Properties properties) {
super(properties);
}
public EucalyptusPropertiesBuilder(String id, String secret) {
super(id, secret);
}
}

View File

@ -22,6 +22,7 @@ import static org.jclouds.aws.ec2.options.DescribeImagesOptions.Builder.ownedBy;
import static org.jclouds.aws.ec2.reference.EC2Constants.PROPERTY_EC2_AMI_OWNERS;
import static org.jclouds.aws.ec2.util.EC2Utils.getAllRunningInstancesInRegion;
import static org.jclouds.aws.ec2.util.EC2Utils.parseHandle;
import static org.jclouds.compute.domain.OsFamily.CENTOS;
import static org.jclouds.compute.domain.OsFamily.UBUNTU;
import static org.jclouds.concurrent.ConcurrentUtils.awaitCompletion;
@ -64,6 +65,7 @@ import org.jclouds.aws.ec2.domain.KeyPair;
import org.jclouds.aws.ec2.domain.RunningInstance;
import org.jclouds.aws.ec2.domain.Image.ImageType;
import org.jclouds.aws.ec2.functions.RunningInstanceToStorageMappingUnix;
import org.jclouds.aws.ec2.options.DescribeImagesOptions;
import org.jclouds.aws.ec2.predicates.InstancePresent;
import org.jclouds.aws.ec2.services.InstanceClient;
import org.jclouds.compute.ComputeService;
@ -127,10 +129,9 @@ public class EC2ComputeServiceContextModule extends EC2ContextModule {
@Named("PRESENT")
protected Predicate<RunningInstance> instancePresent(InstancePresent present) {
return new RetryablePredicate<RunningInstance>(present, 3000, 200,
TimeUnit.MILLISECONDS);
TimeUnit.MILLISECONDS);
}
@Override
protected void configure() {
super.configure();
@ -174,9 +175,12 @@ public class EC2ComputeServiceContextModule extends EC2ContextModule {
@Provides
@Named("DEFAULT")
protected TemplateBuilder provideTemplate(TemplateBuilder template) {
return template.architecture(Architecture.X86_32).osFamily(UBUNTU)
.imageNameMatches(".*10\\.?04.*").osDescriptionMatches("^ubuntu-images.*");
protected TemplateBuilder provideTemplate(@EC2 String region,
TemplateBuilder template) {
return "Eucalyptus".equals(region) ? template.osFamily(CENTOS).smallest()
: template.architecture(Architecture.X86_32).osFamily(UBUNTU)
.imageNameMatches(".*10\\.?04.*").osDescriptionMatches(
"^ubuntu-images.*");
}
// TODO make this more efficient for listNodes(); currently
@ -402,7 +406,11 @@ public class EC2ComputeServiceContextModule extends EC2ContextModule {
holder.logger.debug(">> providing images");
Map<String, ListenableFuture<?>> parallelResponses = Maps.newHashMap();
final DescribeImagesOptions options;
if (amiOwners.length == 1 && amiOwners[0].equals("*"))
options = new DescribeImagesOptions();
else
options = ownedBy(amiOwners);
for (final String region : regionMap.keySet()) {
parallelResponses.put(region, ConcurrentUtils.makeListenable(
executor.submit(new Callable<Void>() {
@ -410,7 +418,7 @@ public class EC2ComputeServiceContextModule extends EC2ContextModule {
public Void call() throws Exception {
for (final org.jclouds.aws.ec2.domain.Image from : sync
.getAMIServices().describeImagesInRegion(region,
ownedBy(amiOwners))) {
options)) {
Image image = parser.apply(from);
if (image != null)
images.put(new RegionAndName(region, image

View File

@ -19,8 +19,9 @@
package org.jclouds.aws.ec2.compute.functions;
import static com.google.common.base.Preconditions.checkNotNull;
import static org.jclouds.compute.util.ComputeUtils.parseOsFamilyOrNull;
import static org.jclouds.compute.util.ComputeUtils.parseVersionOrReturnEmptyString;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Set;
import java.util.regex.Matcher;
@ -53,26 +54,22 @@ import com.google.common.collect.Iterables;
* @author Adrian Cole
*/
@Singleton
public class ImageParser implements Function<org.jclouds.aws.ec2.domain.Image, Image> {
public class ImageParser implements
Function<org.jclouds.aws.ec2.domain.Image, Image> {
@Resource
@Named(ComputeServiceConstants.COMPUTE_LOGGER)
protected Logger logger = Logger.NULL;
public static final Pattern CANONICAL_PATTERN = Pattern
.compile(".*/([^-]*)-([^-]*)-.*-(.*)(\\.manifest.xml)?");
.compile(".*/([^-]*)-([^-]*)-.*-(.*)(\\.manifest.xml)?");
// ex rightscale-us-east/CentOS_5.4_x64_v4.4.10.manifest.xml
public static final Pattern RIGHTSCALE_PATTERN = Pattern
.compile("[^/]*/([^_]*)_([^_]*)_[^vV]*[vV](.*)(\\.manifest.xml)?");
.compile("[^/]*/([^_]*)_([^_]*)_[^vV]*[vV](.*)(\\.manifest.xml)?");
// ex 411009282317/RightImage_Ubuntu_9.10_x64_v4.5.3_EBS_Alpha
public static final Pattern RIGHTIMAGE_PATTERN = Pattern
.compile("[^/]*/RightImage_([^_]*)_([^_]*)_[^vV]*[vV](.*)(\\.manifest.xml)?");
public static final Map<String, String> NAME_VERSION_MAP = ImmutableMap
.<String, String> builder().put("hardy", "8.04").put("intrepid", "8.10").put("jaunty",
"9.04").put("karmic", "9.10").put("lucid", "10.04").put("maverick", "10.10")
.build();
.compile("[^/]*/RightImage_([^_]*)_([^_]*)_[^vV]*[vV](.*)(\\.manifest.xml)?");
private final PopulateDefaultLoginCredentialsForImageStrategy credentialProvider;
private final Set<? extends Location> locations;
@ -80,9 +77,11 @@ public class ImageParser implements Function<org.jclouds.aws.ec2.domain.Image, I
private final Location defaultLocation;
@Inject
ImageParser(PopulateDefaultLoginCredentialsForImageStrategy credentialProvider,
Set<? extends Location> locations, Location defaultLocation) {
this.credentialProvider = checkNotNull(credentialProvider, "credentialProvider");
ImageParser(
PopulateDefaultLoginCredentialsForImageStrategy credentialProvider,
Set<? extends Location> locations, Location defaultLocation) {
this.credentialProvider = checkNotNull(credentialProvider,
"credentialProvider");
this.locations = checkNotNull(locations, "locations");
this.defaultLocation = checkNotNull(defaultLocation, "defaultLocation");
@ -98,20 +97,17 @@ public class ImageParser implements Function<org.jclouds.aws.ec2.domain.Image, I
logger.trace("skipping as not a machine image(%s)", from.getId());
return null;
}
OsFamily os = null;
String name = "";
String description = from.getDescription() != null ? from.getDescription() : from
.getImageLocation();
OsFamily os = parseOsFamilyOrNull(from.getImageLocation());
String name = parseVersionOrReturnEmptyString(os, from.getImageLocation());
String description = from.getDescription() != null ? from
.getDescription() : from.getImageLocation();
String osDescription = from.getImageLocation();
String version = "";
try {
Matcher matcher = getMatcherAndFind(from.getImageLocation());
os = OsFamily.fromValue(matcher.group(1));
name = matcher.group(2);// TODO no field for os version
// normalize versions across ubuntu from alestic and canonical
if (NAME_VERSION_MAP.containsKey(name))
name = NAME_VERSION_MAP.get(name);
name = parseVersionOrReturnEmptyString(os, matcher.group(2));
version = matcher.group(3).replace(".manifest.xml", "");
} catch (IllegalArgumentException e) {
logger.debug("<< didn't match os(%s)", from.getImageLocation());
@ -132,24 +128,24 @@ public class ImageParser implements Function<org.jclouds.aws.ec2.domain.Image, I
});
} catch (NoSuchElementException e) {
System.err.printf("unknown region %s for image %s; not in %s", from.getRegion(), from
.getId(), locations);
location = new LocationImpl(LocationScope.REGION, from.getRegion(), from.getRegion(),
defaultLocation.getParent());
System.err.printf("unknown region %s for image %s; not in %s", from
.getRegion(), from.getId(), locations);
location = new LocationImpl(LocationScope.REGION, from.getRegion(),
from.getRegion(), defaultLocation.getParent());
}
return new ImageImpl(
from.getId(),
name,
from.getRegion() + "/" + from.getId(),
location,
null,
ImmutableMap.<String, String> of("owner", from.getImageOwnerId()),
description,
version,
os,
osDescription,
from.getArchitecture() == org.jclouds.aws.ec2.domain.Image.Architecture.I386 ? Architecture.X86_32
: Architecture.X86_64, defaultCredentials);
from.getId(),
name,
from.getRegion() + "/" + from.getId(),
location,
null,
ImmutableMap.<String, String> of("owner", from.getImageOwnerId()),
description,
version,
os,
osDescription,
from.getArchitecture() == org.jclouds.aws.ec2.domain.Image.Architecture.I386 ? Architecture.X86_32
: Architecture.X86_64, defaultCredentials);
}
@ -159,8 +155,8 @@ public class ImageParser implements Function<org.jclouds.aws.ec2.domain.Image, I
* if no configured matcher matches the manifest.
*/
private Matcher getMatcherAndFind(String manifest) {
for (Pattern pattern : new Pattern[] { CANONICAL_PATTERN, RIGHTIMAGE_PATTERN,
RIGHTSCALE_PATTERN }) {
for (Pattern pattern : new Pattern[] { CANONICAL_PATTERN,
RIGHTIMAGE_PATTERN, RIGHTSCALE_PATTERN }) {
Matcher matcher = pattern.matcher(manifest);
if (matcher.find())
return matcher;

View File

@ -36,91 +36,100 @@ import org.jclouds.concurrent.Timeout;
*
* @author Adrian Cole
*/
@Timeout(duration = 45, timeUnit = TimeUnit.SECONDS)
@Timeout(duration = 90, timeUnit = TimeUnit.SECONDS)
public interface InstanceClient {
/**
* Returns information about instances that you own.
* <p/>
*
* If you specify one or more instance IDs, Amazon EC2 returns information for those instances.
* If you do not specify instance IDs, Amazon EC2 returns information for all relevant instances.
* If you specify an invalid instance ID, a fault is returned. If you specify an instance that
* you do not own, it will not be included in the returned results.
* If you specify one or more instance IDs, Amazon EC2 returns information
* for those instances. If you do not specify instance IDs, Amazon EC2
* returns information for all relevant instances. If you specify an invalid
* instance ID, a fault is returned. If you specify an instance that you do
* not own, it will not be included in the returned results.
* <p/>
* Recently terminated instances might appear in the returned results.This interval is usually
* less than one hour.
* Recently terminated instances might appear in the returned results.This
* interval is usually less than one hour.
*
* @param region
* Instances are tied to Availability Zones. However, the instance ID is tied to the
* Region.
* Instances are tied to Availability Zones. However, the instance
* ID is tied to the Region.
*
* @see #runInstancesInRegion
* @see #terminateInstancesInRegion
* @see <a href="http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-DescribeInstances.html"
* />
*/
Set<Reservation> describeInstancesInRegion(@Nullable String region, String... instanceIds);
Set<Reservation> describeInstancesInRegion(@Nullable String region,
String... instanceIds);
/**
* Launches a specified number of instances of an AMI for which you have permissions.
* Launches a specified number of instances of an AMI for which you have
* permissions.
* <p/>
*
* If Amazon EC2 cannot launch the minimum number AMIs you request, no instances will be
* launched. If there is insufficient capacity to launch the maximum number of AMIs you request,
* Amazon EC2 launches the minimum number specified for each AMI and allocate the remaining
* available instances using round robin.
* If Amazon EC2 cannot launch the minimum number AMIs you request, no
* instances will be launched. If there is insufficient capacity to launch
* the maximum number of AMIs you request, Amazon EC2 launches the minimum
* number specified for each AMI and allocate the remaining available
* instances using round robin.
* <p/>
* <h4>Security Groups</h4>
* <b>Note:</b> Every instance is launched in a security group (created using the
* CreateSecurityGroup operation.
* <b>Note:</b> Every instance is launched in a security group (created using
* the CreateSecurityGroup operation.
* <h4>Key Pair</h4>
* You can provide an optional key pair ID for each image in the launch request (created using
* the CreateKeyPair operation). All instances that are created from images that use this key
* pair will have access to the associated public key at boot. You can use this key to provide
* secure access to an instance of an image on a per-instance basis. Amazon EC2 public images use
* this feature to provide secure access without passwords.
* You can provide an optional key pair ID for each image in the launch
* request (created using the CreateKeyPair operation). All instances that
* are created from images that use this key pair will have access to the
* associated public key at boot. You can use this key to provide secure
* access to an instance of an image on a per-instance basis. Amazon EC2
* public images use this feature to provide secure access without passwords.
* <p/>
* <b>Note:</b> Launching public images without a key pair ID will leave them inaccessible.
* <b>Note:</b> Launching public images without a key pair ID will leave them
* inaccessible.
* <p/>
* The public key material is made available to the instance at boot time by placing it in the
* openssh_id.pub file on a logical device that is exposed to the instance as /dev/sda2 (the
* instance store). The format of this file is suitable for use as an entry within
* ~/.ssh/authorized_keys (the OpenSSH format). This can be done at boot (e.g., as part of
* rc.local) allowing for secure access without passwords.
* The public key material is made available to the instance at boot time by
* placing it in the openssh_id.pub file on a logical device that is exposed
* to the instance as /dev/sda2 (the instance store). The format of this file
* is suitable for use as an entry within ~/.ssh/authorized_keys (the OpenSSH
* format). This can be done at boot (e.g., as part of rc.local) allowing for
* secure access without passwords.
* <h4>User Data</h4>
* Optional user data can be provided in the launch request. All instances that collectively
* comprise the launch request have access to this data. For more information, go the Amazon
* Elastic Compute Cloud Developer Guide.
* Optional user data can be provided in the launch request. All instances
* that collectively comprise the launch request have access to this data.
* For more information, go the Amazon Elastic Compute Cloud Developer Guide.
* <h4>Product Codes</h4>
*
* <b>Note:</b> If any of the AMIs have a product code attached for which the user has not
* subscribed, the RunInstances call will fail.
* <b>Note:</b> If any of the AMIs have a product code attached for which the
* user has not subscribed, the RunInstances call will fail.
* <h4>Kernel</h4>
*
* <b>Important:</b> We strongly recommend using the 2.6.18 Xen stock kernel with High-CPU and
* High-Memory instances. Although the default Amazon EC2 kernels will work, the new kernels
* provide greater stability and performance for these instance types. For more information about
* kernels, go the Amazon Elastic Compute Cloud Developer Guide.
* <b>Important:</b> We strongly recommend using the 2.6.18 Xen stock kernel
* with High-CPU and High-Memory instances. Although the default Amazon EC2
* kernels will work, the new kernels provide greater stability and
* performance for these instance types. For more information about kernels,
* go the Amazon Elastic Compute Cloud Developer Guide.
*
* @param region
* Instances are tied to Availability Zones. However, the instance ID is tied to the
* Region.
* Instances are tied to Availability Zones. However, the instance
* ID is tied to the Region.
* @param nullableAvailabilityZone
* Specifies the placement constraints (Availability Zones) for launching the
* instances. If null, Amazon will determine the best availability zone to place the
* instance.
* Specifies the placement constraints (Availability Zones) for
* launching the instances. If null, Amazon will determine the best
* availability zone to place the instance.
* @param imageId
* Unique ID of a machine image, returned by a call to
* @param minCount
* Minimum number of instances to launch. If the value is more than Amazon EC2 can
* launch, no instances a re launched at all. Constraints: Between 1 and the maximum
* number allowed for your account (default: 20).
* Minimum number of instances to launch. If the value is more than
* Amazon EC2 can launch, no instances a re launched at all.
* Constraints: Between 1 and the maximum number allowed for your
* account (default: 20).
* @param maxCount
* Maximum number of instances to launch. If the value is more than Amazon EC2 can
* launch, the largest possible number above minCount will be launched instead.
* Constraints: Between 1 and the maximum number allowed for your account (default:
* 20).
* Maximum number of instances to launch. If the value is more than
* Amazon EC2 can launch, the largest possible number above
* minCount will be launched instead. Constraints: Between 1 and
* the maximum number allowed for your account (default: 20).
* @see #describeInstancesInRegion
* @see #terminateInstancesInRegion
* @see #authorizeSecurityGroupIngressInRegion
@ -128,55 +137,58 @@ public interface InstanceClient {
* @see #describeSecurityGroupsInRegion
* @see #createSecurityGroupInRegion
* @see #createKeyPairInRegion
* @see <a href=
* "http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-RunInstances.html"
* @see <a href="http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-RunInstances.html"
* />
* @see RunInstancesOptions
*/
Reservation runInstancesInRegion(@Nullable String region,
@Nullable String nullableAvailabilityZone, String imageId, int minCount,
int maxCount, RunInstancesOptions... options);
@Nullable String nullableAvailabilityZone, String imageId,
int minCount, int maxCount, RunInstancesOptions... options);
/**
* Shuts down one or more instances. This operation is idempotent; if you terminate an instance
* more than once, each call will succeed.
* Shuts down one or more instances. This operation is idempotent; if you
* terminate an instance more than once, each call will succeed.
* <p/>
* Terminated instances will remain visible after termination (approximately one hour).
* Terminated instances will remain visible after termination (approximately
* one hour).
*
* @param region
* Instances are tied to Availability Zones. However, the instance ID is tied to the
* Region.
* Instances are tied to Availability Zones. However, the instance
* ID is tied to the Region.
* @param instanceIds
* Instance ID to terminate.
* @see #describeInstancesInRegion
* @see <a href="http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-TerminateInstances.html"
* />
*/
Set<InstanceStateChange> terminateInstancesInRegion(@Nullable String region, String... instanceIds);
Set<InstanceStateChange> terminateInstancesInRegion(@Nullable String region,
String... instanceIds);
/**
* Stops an instance that uses an Amazon EBS volume as its root device.
* <p/>
* Instances that use Amazon EBS volumes as their root devices can be quickly stopped and
* started. When an instance is stopped, the compute resources are released and you are not
* billed for hourly instance usage. However, your root partition Amazon EBS volume remains,
* continues to persist your data, and you are charged for Amazon EBS volume usage. You can
* restart your instance at any time.
* Instances that use Amazon EBS volumes as their root devices can be quickly
* stopped and started. When an instance is stopped, the compute resources
* are released and you are not billed for hourly instance usage. However,
* your root partition Amazon EBS volume remains, continues to persist your
* data, and you are charged for Amazon EBS volume usage. You can restart
* your instance at any time.
* <h3>Note</h3>
* Before stopping an instance, make sure it is in a state from which it can be restarted.
* Stopping an instance does not preserve data stored in RAM.
* Before stopping an instance, make sure it is in a state from which it can
* be restarted. Stopping an instance does not preserve data stored in RAM.
* <p/>
* Performing this operation on an instance that uses an instance store as its root device
* returns an error.
* Performing this operation on an instance that uses an instance store as
* its root device returns an error.
*
* @param region
* Instances are tied to Availability Zones. However, the instance ID is tied to the
* Region.
* Instances are tied to Availability Zones. However, the instance
* ID is tied to the Region.
* @param force
* Forces the instance to stop. The instance will not have an opportunity to flush file
* system caches nor file system meta data. If you use this option, you must perform
* file system check and repair procedures. This option is not recommended for Windows
* instances.
* Forces the instance to stop. The instance will not have an
* opportunity to flush file system caches nor file system meta
* data. If you use this option, you must perform file system check
* and repair procedures. This option is not recommended for
* Windows instances.
* @param instanceIds
* Instance ID to stop.
*
@ -184,23 +196,23 @@ public interface InstanceClient {
* @see #runInstancesInRegion
* @see #describeInstancesInRegion
* @see #terminateInstancesInRegion
* @see <a href=
* "http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-StopInstances.html"
* @see <a href="http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-StopInstances.html"
* />
*/
Set<InstanceStateChange> stopInstancesInRegion(@Nullable String region, boolean force,
String... instanceIds);
Set<InstanceStateChange> stopInstancesInRegion(@Nullable String region,
boolean force, String... instanceIds);
/**
* Requests a reboot of one or more instances. This operation is asynchronous; it only queues a
* request to reboot the specified instance(s). The operation will succeed if the instances are
* valid and belong to you. Requests to reboot terminated instances are ignored. <h3>Note</h3> If
* a Linux/UNIX instance does not cleanly shut down within four minutes, Amazon EC2 will perform
* a hard reboot.
* Requests a reboot of one or more instances. This operation is
* asynchronous; it only queues a request to reboot the specified
* instance(s). The operation will succeed if the instances are valid and
* belong to you. Requests to reboot terminated instances are ignored. <h3>
* Note</h3> If a Linux/UNIX instance does not cleanly shut down within four
* minutes, Amazon EC2 will perform a hard reboot.
*
* @param region
* Instances are tied to Availability Zones. However, the instance ID is tied to the
* Region.
* Instances are tied to Availability Zones. However, the instance
* ID is tied to the Region.
*
* @param instanceIds
* Instance ID to reboot.
@ -209,8 +221,7 @@ public interface InstanceClient {
* @see #runInstancesInRegion
* @see #describeInstancesInRegion
* @see #terminateInstancesInRegion
* @see <a href=
* "http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-StopInstances.html"
* @see <a href="http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-StopInstances.html"
* />
*/
void rebootInstancesInRegion(@Nullable String region, String... instanceIds);
@ -218,21 +229,22 @@ public interface InstanceClient {
/**
* Starts an instance that uses an Amazon EBS volume as its root device.
* <p/>
* Instances that use Amazon EBS volumes as their root devices can be quickly stopped and
* started. When an instance is stopped, the compute resources are released and you are not
* billed for hourly instance usage. However, your root partition Amazon EBS volume remains,
* continues to persist your data, and you are charged for Amazon EBS volume usage. You can
* restart your instance at any time.
* Instances that use Amazon EBS volumes as their root devices can be quickly
* stopped and started. When an instance is stopped, the compute resources
* are released and you are not billed for hourly instance usage. However,
* your root partition Amazon EBS volume remains, continues to persist your
* data, and you are charged for Amazon EBS volume usage. You can restart
* your instance at any time.
* <h3>Note</h3>
* Before stopping an instance, make sure it is in a state from which it can be restarted.
* Stopping an instance does not preserve data stored in RAM.
* Before stopping an instance, make sure it is in a state from which it can
* be restarted. Stopping an instance does not preserve data stored in RAM.
* <p/>
* Performing this operation on an instance that uses an instance store as its root device
* returns an error.
* Performing this operation on an instance that uses an instance store as
* its root device returns an error.
*
* @param region
* Instances are tied to Availability Zones. However, the instance ID is tied to the
* Region.
* Instances are tied to Availability Zones. However, the instance
* ID is tied to the Region.
* @param instanceIds
* Instance ID to start.
*
@ -243,129 +255,140 @@ public interface InstanceClient {
* @see <a href="http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-StartInstances.html"
* />
*/
Set<InstanceStateChange> startInstancesInRegion(@Nullable String region, String... instanceIds);
Set<InstanceStateChange> startInstancesInRegion(@Nullable String region,
String... instanceIds);
/**
*
* @param region
* Instances are tied to Availability Zones. However, the instance ID is tied to the
* Region.
* Instances are tied to Availability Zones. However, the instance
* ID is tied to the Region.
* @param instanceId
* which instance to describe the attribute of
* @return unencoded user data
*/
String getUserDataForInstanceInRegion(@Nullable String region, String instanceId);
String getUserDataForInstanceInRegion(@Nullable String region,
String instanceId);
/**
*
* @param region
* Instances are tied to Availability Zones. However, the instance ID is tied to the
* Region.
* Instances are tied to Availability Zones. However, the instance
* ID is tied to the Region.
* @param instanceId
* which instance to describe the attribute of
* @return The root device name (e.g., /dev/sda1).
*/
String getRootDeviceNameForInstanceInRegion(@Nullable String region, String instanceId);
String getRootDeviceNameForInstanceInRegion(@Nullable String region,
String instanceId);
/**
*
* @param region
* Instances are tied to Availability Zones. However, the instance ID is tied to the
* Region.
* Instances are tied to Availability Zones. However, the instance
* ID is tied to the Region.
* @param instanceId
* which instance to describe the attribute of
* @return the ID of the RAM disk associated with the AMI.
*/
String getRamdiskForInstanceInRegion(@Nullable String region, String instanceId);
String getRamdiskForInstanceInRegion(@Nullable String region,
String instanceId);
/**
*
* @param region
* Instances are tied to Availability Zones. However, the instance ID is tied to the
* Region.
* Instances are tied to Availability Zones. However, the instance
* ID is tied to the Region.
* @param instanceId
* which instance to describe the attribute of
* @return the ID of the kernel associated with the AMI.
*/
String getKernelForInstanceInRegion(@Nullable String region, String instanceId);
String getKernelForInstanceInRegion(@Nullable String region,
String instanceId);
/**
*
* @param region
* Instances are tied to Availability Zones. However, the instance ID is tied to the
* Region.
* Instances are tied to Availability Zones. However, the instance
* ID is tied to the Region.
* @param instanceId
* which instance to describe the attribute of
* @return Specifies whether the instance can be terminated using the APIs. You must modify this
* attribute before you can terminate any "locked" instances from the APIs.
* @return Specifies whether the instance can be terminated using the APIs.
* You must modify this attribute before you can terminate any
* "locked" instances from the APIs.
*/
boolean isApiTerminationDisabledForInstanceInRegion(@Nullable String region, String instanceId);
boolean isApiTerminationDisabledForInstanceInRegion(@Nullable String region,
String instanceId);
/**
*
* @param region
* Instances are tied to Availability Zones. However, the instance ID is tied to the
* Region.
* Instances are tied to Availability Zones. However, the instance
* ID is tied to the Region.
* @param instanceId
* which instance to describe the attribute of
* @return The instance type of the instance.
*/
String getInstanceTypeForInstanceInRegion(@Nullable String region, String instanceId);
String getInstanceTypeForInstanceInRegion(@Nullable String region,
String instanceId);
/**
*
* @param region
* Instances are tied to Availability Zones. However, the instance ID is tied to the
* Region.
* Instances are tied to Availability Zones. However, the instance
* ID is tied to the Region.
* @param instanceId
* which instance to describe the attribute of
* @return whether the instance's Amazon EBS volumes are stopped or terminated when the instance
* is shut down.
* @return whether the instance's Amazon EBS volumes are stopped or
* terminated when the instance is shut down.
*/
InstanceInitiatedShutdownBehavior getInstanceInitiatedShutdownBehaviorForInstanceInRegion(
String region, String instanceId);
String region, String instanceId);
/**
*
* @param region
* Instances are tied to Availability Zones. However, the instance ID is tied to the
* Region.
* Instances are tied to Availability Zones. However, the instance
* ID is tied to the Region.
* @param instanceId
* which instance to describe the attribute of
* @return Describes the mapping that defines native device names to use when exposing virtual
* devices.
* @return Describes the mapping that defines native device names to use when
* exposing virtual devices.
*/
Map<String, EbsBlockDevice> getBlockDeviceMappingForInstanceInRegion(@Nullable String region,
String instanceId);
Map<String, EbsBlockDevice> getBlockDeviceMappingForInstanceInRegion(
@Nullable String region, String instanceId);
/**
* Resets an attribute of an instance to its default value.
*
* @param region
* Instances are tied to Availability Zones. However, the instance ID is tied to the
* Region.
* Instances are tied to Availability Zones. However, the instance
* ID is tied to the Region.
* @param instanceId
* which instance to reset the attribute of
* @return the ID of the RAM disk associated with the AMI.
*/
String resetRamdiskForInstanceInRegion(@Nullable String region, String instanceId);
String resetRamdiskForInstanceInRegion(@Nullable String region,
String instanceId);
/**
* Resets an attribute of an instance to its default value.
*
* @param region
* Instances are tied to Availability Zones. However, the instance ID is tied to the
* Region.
* Instances are tied to Availability Zones. However, the instance
* ID is tied to the Region.
* @param instanceId
* which instance to reset the attribute of
* @return the ID of the kernel associated with the AMI.
*/
String resetKernelForInstanceInRegion(@Nullable String region, String instanceId);
String resetKernelForInstanceInRegion(@Nullable String region,
String instanceId);
/**
* Sets the userData used for starting the instance.
* <p/>
* The instance needs to be in a {@link InstanceState#STOPPED} state, which implies two things:
* The instance needs to be in a {@link InstanceState#STOPPED} state, which
* implies two things:
* <ol>
* <li>The instance was launched from an EBS-backed AMI so that it can stop</li>
* <li>You have stopped and waited for the instance to transition from
@ -373,8 +396,8 @@ public interface InstanceClient {
* </ol>
*
* @param region
* Instances are tied to Availability Zones. However, the instance ID is tied to the
* Region.
* Instances are tied to Availability Zones. However, the instance
* ID is tied to the Region.
* @param instanceId
* which instance to change the attribute of
* @param unencodedData
@ -382,12 +405,14 @@ public interface InstanceClient {
* @see <a href="http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-ModifyInstanceAttribute.html"
* />
*/
void setUserDataForInstanceInRegion(@Nullable String region, String instanceId, byte[] unencodedData);
void setUserDataForInstanceInRegion(@Nullable String region,
String instanceId, byte[] unencodedData);
/**
* Sets the ramdisk used for starting the instance.
* <p/>
* The instance needs to be in a {@link InstanceState#STOPPED} state, which implies two things:
* The instance needs to be in a {@link InstanceState#STOPPED} state, which
* implies two things:
* <ol>
* <li>The instance was launched from an EBS-backed AMI so that it can stop</li>
* <li>You have stopped and waited for the instance to transition from
@ -395,8 +420,8 @@ public interface InstanceClient {
* </ol>
*
* @param region
* Instances are tied to Availability Zones. However, the instance ID is tied to the
* Region.
* Instances are tied to Availability Zones. However, the instance
* ID is tied to the Region.
* @param instanceId
* which instance to change the attribute of
* @param ramdisk
@ -404,12 +429,14 @@ public interface InstanceClient {
* @see <a href="http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-ModifyInstanceAttribute.html"
* />
*/
void setRamdiskForInstanceInRegion(@Nullable String region, String instanceId, String ramdisk);
void setRamdiskForInstanceInRegion(@Nullable String region,
String instanceId, String ramdisk);
/**
* Sets the kernelId used for starting the instance.
* <p/>
* The instance needs to be in a {@link InstanceState#STOPPED} state, which implies two things:
* The instance needs to be in a {@link InstanceState#STOPPED} state, which
* implies two things:
* <ol>
* <li>The instance was launched from an EBS-backed AMI so that it can stop</li>
* <li>You have stopped and waited for the instance to transition from
@ -417,8 +444,8 @@ public interface InstanceClient {
* </ol>
*
* @param region
* Instances are tied to Availability Zones. However, the instance ID is tied to the
* Region.
* Instances are tied to Availability Zones. However, the instance
* ID is tied to the Region.
* @param instanceId
* which instance to change the attribute of
* @param kernel
@ -426,15 +453,16 @@ public interface InstanceClient {
* @see <a href="http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-ModifyInstanceAttribute.html"
* />
*/
void setKernelForInstanceInRegion(@Nullable String region, String instanceId, String kernel);
void setKernelForInstanceInRegion(@Nullable String region,
String instanceId, String kernel);
/**
* This command works while the instance is running and controls whether or not the api can be
* used to terminate the instance.
* This command works while the instance is running and controls whether or
* not the api can be used to terminate the instance.
*
* @param region
* Instances are tied to Availability Zones. However, the instance ID is tied to the
* Region.
* Instances are tied to Availability Zones. However, the instance
* ID is tied to the Region.
* @param instanceId
* which instance to reset the attribute of
* @param apiTerminationDisabled
@ -442,13 +470,14 @@ public interface InstanceClient {
* @see <a href="http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-ModifyInstanceAttribute.html"
* />
*/
void setApiTerminationDisabledForInstanceInRegion(@Nullable String region, String instanceId,
boolean apiTerminationDisabled);
void setApiTerminationDisabledForInstanceInRegion(@Nullable String region,
String instanceId, boolean apiTerminationDisabled);
/**
* Sets the instanceType used for starting the instance.
* <p/>
* The instance needs to be in a {@link InstanceState#STOPPED} state, which implies two things:
* The instance needs to be in a {@link InstanceState#STOPPED} state, which
* implies two things:
* <ol>
* <li>The instance was launched from an EBS-backed AMI so that it can stop</li>
* <li>You have stopped and waited for the instance to transition from
@ -456,8 +485,8 @@ public interface InstanceClient {
* </ol>
*
* @param region
* Instances are tied to Availability Zones. However, the instance ID is tied to the
* Region.
* Instances are tied to Availability Zones. However, the instance
* ID is tied to the Region.
* @param instanceId
* which instance to change the attribute of
* @param instanceType
@ -465,14 +494,15 @@ public interface InstanceClient {
* @see <a href="http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-ModifyInstanceAttribute.html"
* />
*/
void setInstanceTypeForInstanceInRegion(@Nullable String region, String instanceId,
String instanceType);
void setInstanceTypeForInstanceInRegion(@Nullable String region,
String instanceId, String instanceType);
/**
* Specifies whether the instance's Amazon EBS volumes are stopped or terminated when the
* instance is shut down.
* Specifies whether the instance's Amazon EBS volumes are stopped or
* terminated when the instance is shut down.
* <p/>
* The instance needs to be in a {@link InstanceState#STOPPED} state, which implies two things:
* The instance needs to be in a {@link InstanceState#STOPPED} state, which
* implies two things:
* <ol>
* <li>The instance was launched from an EBS-backed AMI so that it can stop</li>
* <li>You have stopped and waited for the instance to transition from
@ -480,56 +510,58 @@ public interface InstanceClient {
* </ol>
*
* @param region
* Instances are tied to Availability Zones. However, the instance ID is tied to the
* Region.
* Instances are tied to Availability Zones. However, the instance
* ID is tied to the Region.
* @param instanceId
* which instance to change the attribute of
* @param instanceInitiatedShutdownBehavior
* whether the instance's Amazon EBS volumes are stopped or terminated when the
* instance is shut down.
* whether the instance's Amazon EBS volumes are stopped or
* terminated when the instance is shut down.
* @see <a href="http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-ModifyInstanceAttribute.html"
* />
*/
void setInstanceInitiatedShutdownBehaviorForInstanceInRegion(@Nullable String region, String instanceId,
InstanceInitiatedShutdownBehavior instanceInitiatedShutdownBehavior);
void setInstanceInitiatedShutdownBehaviorForInstanceInRegion(
@Nullable String region, String instanceId,
InstanceInitiatedShutdownBehavior instanceInitiatedShutdownBehavior);
/**
* Sets the blockDeviceMapping used for an instance.
* <p/>
* The instance needs to be in a {@link InstanceState#STOPPED} state, which implies two things:
* The instance needs to be in a {@link InstanceState#STOPPED} state, which
* implies two things:
* <ol>
* <li>The instance was launched from an EBS-backed AMI so that it can stop</li>
* <li>You have stopped and waited for the instance to transition from
* {@link InstanceState#STOPPING} to {@link InstanceState#STOPPED}</li>
* </ol>
*
* To create the instances of {@link RunningInstance.EbsBlockDevice},
* the constructor can be used with the following parameters:
* {@link RunningInstance.EbsBlockDevice#EbsBlockDevice(String, String, boolean)},
* that are:
* To create the instances of {@link RunningInstance.EbsBlockDevice}, the
* constructor can be used with the following parameters:
* {@link RunningInstance.EbsBlockDevice#EbsBlockDevice(String, String, boolean)}
* , that are:
* <ol>
* <li>Volume id (required), for instance, "vol-blah"</li>
* <li>Device name (optional), for instance, "/dev/sda1". To find out more about
* device names, read the next paragraph.</li>
* <li>Delete on termination flag (optional), which defines whether the volume will be
* deleted upon instance's termination.</li>
* <li>Device name (optional), for instance, "/dev/sda1". To find out more
* about device names, read the next paragraph.</li>
* <li>Delete on termination flag (optional), which defines whether the
* volume will be deleted upon instance's termination.</li>
* </ol>
* <p/>
* Note that the device names between Linux and Windows differ. For Linux, ensure that your
* device name is in the form /dev/sd[a-z] . For example, /dev/sda , /dev/sdb and /dev/sdh are
* all valid device names.
* Note that the device names between Linux and Windows differ. For Linux,
* ensure that your device name is in the form /dev/sd[a-z] . For example,
* /dev/sda , /dev/sdb and /dev/sdh are all valid device names.
* <p/>
* For Windows, the root device is still referred to as /dev/sda1 . For other devices, ensure
* that they are in the form /xvd[c-p] . For example, /xvde , /xvdf and /xvdp are all valid
* Windows device names.
* For Windows, the root device is still referred to as /dev/sda1 . For other
* devices, ensure that they are in the form /xvd[c-p] . For example, /xvde ,
* /xvdf and /xvdp are all valid Windows device names.
* <p/>
* <b>NOTE</b>: As of now 02/20/2010, this command only works to change the
* DeleteOnTermination property of the device. The volume must be <i>attached</i> to a
* stopped instance.
* DeleteOnTermination property of the device. The volume must be
* <i>attached</i> to a stopped instance.
*
* @param region
* Instances are tied to Availability Zones. However, the instance ID is tied to the
* Region.
* Instances are tied to Availability Zones. However, the instance
* ID is tied to the Region.
* @param instanceId
* which instance to change the attribute of
* @param blockDeviceMapping
@ -537,6 +569,6 @@ public interface InstanceClient {
* @see <a href="http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-ModifyInstanceAttribute.html"
* />
*/
void setBlockDeviceMappingForInstanceInRegion(@Nullable String region, String instanceId,
BlockDeviceMapping blockDeviceMapping);
void setBlockDeviceMappingForInstanceInRegion(@Nullable String region,
String instanceId, BlockDeviceMapping blockDeviceMapping);
}

View File

@ -32,7 +32,8 @@ import com.google.common.collect.Maps;
*
* @author Adrian Cole
*/
public class DescribeRegionsResponseHandler extends ParseSax.HandlerWithResult<Map<String, URI>> {
public class DescribeRegionsResponseHandler extends
ParseSax.HandlerWithResult<Map<String, URI>> {
private StringBuilder currentText = new StringBuilder();
private Map<String, URI> regionEndpoints = Maps.newHashMap();
@ -47,10 +48,15 @@ public class DescribeRegionsResponseHandler extends ParseSax.HandlerWithResult<M
public void endElement(String uri, String name, String qName) {
if (qName.equals("regionName")) {
region = currentText.toString().trim();
String pending = currentText.toString().trim();
if (pending.indexOf("Walrus") == -1)
region = pending;
} else if (qName.equals("regionEndpoint")) {
regionEndpoint = URI.create(String.format("https://%s", currentText.toString().trim()));
} else if (qName.equals("item")) {
String pending = currentText.toString().trim();
if (pending.indexOf("Walrus") == -1)
regionEndpoint = URI.create(pending.startsWith("http") ? pending
: String.format("https://%s", pending));
} else if (qName.equals("item") && region != null) {
regionEndpoints.put(region, regionEndpoint);
this.region = null;
this.regionEndpoint = null;

View File

@ -72,6 +72,7 @@ public class ParseAWSErrorFromXmlContent implements HttpErrorHandler {
exception);
break;
case 401:
case 403:
exception = new AuthorizationException(command.getRequest(),
error != null ? error.getMessage() : response.getStatusLine());
break;

View File

@ -23,10 +23,7 @@ import static org.jclouds.Constants.PROPERTY_RELAX_HOSTNAME;
import static org.jclouds.aws.reference.AWSConstants.PROPERTY_AWS_ACCESSKEYID;
import static org.jclouds.aws.reference.AWSConstants.PROPERTY_AWS_SECRETACCESSKEY;
import static org.jclouds.aws.s3.reference.S3Constants.PROPERTY_S3_ENDPOINT;
import static org.jclouds.aws.s3.reference.S3Constants.PROPERTY_S3_ENDPOINT_AP_SOUTHEAST_1;
import static org.jclouds.aws.s3.reference.S3Constants.PROPERTY_S3_ENDPOINT_EU_WEST_1;
import static org.jclouds.aws.s3.reference.S3Constants.PROPERTY_S3_ENDPOINT_US_STANDARD;
import static org.jclouds.aws.s3.reference.S3Constants.PROPERTY_S3_ENDPOINT_US_WEST_1;
import static org.jclouds.aws.s3.reference.S3Constants.PROPERTY_S3_REGIONS;
import static org.jclouds.aws.s3.reference.S3Constants.PROPERTY_S3_SESSIONINTERVAL;
import static org.jclouds.blobstore.reference.BlobStoreConstants.DIRECTORY_SUFFIX_FOLDER;
import static org.jclouds.blobstore.reference.BlobStoreConstants.PROPERTY_BLOBSTORE_DIRECTORY_SUFFIX;
@ -36,8 +33,11 @@ import java.net.URI;
import java.util.Properties;
import org.jclouds.PropertiesBuilder;
import org.jclouds.aws.domain.Region;
import org.jclouds.aws.s3.reference.S3Constants;
import com.google.common.base.Joiner;
/**
* Builds properties used in S3 Connections
*
@ -49,14 +49,28 @@ public class S3PropertiesBuilder extends PropertiesBuilder {
Properties properties = super.defaultProperties();
properties.setProperty(PROPERTY_RELAX_HOSTNAME, "true");
properties.setProperty(PROPERTY_USER_METADATA_PREFIX, "x-amz-meta-");
properties.setProperty(PROPERTY_S3_ENDPOINT, "https://s3.amazonaws.com");
properties.setProperty(PROPERTY_S3_ENDPOINT_US_STANDARD, "https://s3.amazonaws.com");
properties.setProperty(PROPERTY_S3_ENDPOINT_US_WEST_1, "https://s3-us-west-1.amazonaws.com");
properties.setProperty(PROPERTY_S3_ENDPOINT_EU_WEST_1, "https://s3-eu-west-1.amazonaws.com");
properties.setProperty(PROPERTY_S3_ENDPOINT_AP_SOUTHEAST_1,
"https://s3-ap-southeast-1.amazonaws.com");
addEndpointProperties(properties);
properties.setProperty(PROPERTY_S3_SESSIONINTERVAL, "60");
properties.setProperty(PROPERTY_BLOBSTORE_DIRECTORY_SUFFIX, DIRECTORY_SUFFIX_FOLDER);
properties.setProperty(PROPERTY_BLOBSTORE_DIRECTORY_SUFFIX,
DIRECTORY_SUFFIX_FOLDER);
return properties;
}
protected Properties addEndpointProperties(Properties properties) {
properties.setProperty(PROPERTY_S3_REGIONS, Joiner.on(',').join(
Region.US_STANDARD, Region.US_WEST_1, Region.EU_WEST_1,
Region.AP_SOUTHEAST_1));
properties.setProperty(PROPERTY_S3_ENDPOINT, "https://s3.amazonaws.com");
properties.setProperty(PROPERTY_S3_ENDPOINT + "." + Region.US_STANDARD,
"https://s3.amazonaws.com");
properties.setProperty(PROPERTY_S3_ENDPOINT + "." + Region.US_WEST_1,
"https://s3-us-west-1.amazonaws.com");
properties.setProperty(PROPERTY_S3_ENDPOINT + "." + Region.EU_WEST_1,
"https://s3-eu-west-1.amazonaws.com");
properties.setProperty(
PROPERTY_S3_ENDPOINT + "." + Region.AP_SOUTHEAST_1,
"https://s3-ap-southeast-1.amazonaws.com");
return properties;
}
@ -71,15 +85,16 @@ public class S3PropertiesBuilder extends PropertiesBuilder {
@Override
public S3PropertiesBuilder withCredentials(String id, String secret) {
properties.setProperty(PROPERTY_AWS_ACCESSKEYID, checkNotNull(id, "awsAccessKeyId"));
properties.setProperty(PROPERTY_AWS_ACCESSKEYID, checkNotNull(id,
"awsAccessKeyId"));
properties.setProperty(PROPERTY_AWS_SECRETACCESSKEY, checkNotNull(secret,
"awsSecretAccessKey"));
"awsSecretAccessKey"));
return this;
}
public S3PropertiesBuilder withEndpoint(URI endpoint) {
properties.setProperty(S3Constants.PROPERTY_S3_ENDPOINT, checkNotNull(endpoint, "endpoint")
.toString());
properties.setProperty(S3Constants.PROPERTY_S3_ENDPOINT, checkNotNull(
endpoint, "endpoint").toString());
return this;
}

View File

@ -0,0 +1,31 @@
package org.jclouds.aws.s3;
import static org.jclouds.aws.s3.reference.S3Constants.PROPERTY_S3_ENDPOINT;
import static org.jclouds.aws.s3.reference.S3Constants.PROPERTY_S3_REGIONS;
import java.util.Properties;
/**
* Builds properties used in Walrus Clients
*
* @author Adrian Cole
*/
public class WalrusPropertiesBuilder extends S3PropertiesBuilder {
@Override
protected Properties addEndpointProperties(Properties properties) {
properties.setProperty(PROPERTY_S3_REGIONS, "Walrus");
properties.setProperty(PROPERTY_S3_ENDPOINT,
"http://173.205.188.130:8773/services/Walrus");
properties.setProperty(PROPERTY_S3_ENDPOINT + ".Walrus",
"http://173.205.188.130:8773/services/Walrus");
return properties;
}
public WalrusPropertiesBuilder(Properties properties) {
super(properties);
}
public WalrusPropertiesBuilder(String id, String secret) {
super(id, secret);
}
}

View File

@ -26,7 +26,6 @@ import java.util.concurrent.TimeUnit;
import javax.inject.Named;
import javax.inject.Singleton;
import org.jclouds.aws.domain.Region;
import org.jclouds.aws.handlers.AWSClientErrorRetryHandler;
import org.jclouds.aws.handlers.AWSRedirectionRetryHandler;
import org.jclouds.aws.handlers.ParseAWSErrorFromXmlContent;
@ -48,11 +47,15 @@ import org.jclouds.rest.ConfiguresRestClient;
import org.jclouds.rest.RequestSigner;
import org.jclouds.rest.config.RestClientModule;
import com.google.common.base.Splitter;
import com.google.common.base.Supplier;
import com.google.common.collect.ImmutableBiMap;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Maps;
import com.google.inject.Injector;
import com.google.inject.Key;
import com.google.inject.Provides;
import com.google.inject.Scopes;
import com.google.inject.name.Names;
/**
* Configures the S3 connection, including logging and http transport.
@ -61,7 +64,8 @@ import com.google.inject.Scopes;
*/
@ConfiguresRestClient
@RequiresHttp
public class S3RestClientModule extends RestClientModule<S3Client, S3AsyncClient> {
public class S3RestClientModule extends
RestClientModule<S3Client, S3AsyncClient> {
public S3RestClientModule() {
super(S3Client.class, S3AsyncClient.class);
}
@ -91,8 +95,8 @@ public class S3RestClientModule extends RestClientModule<S3Client, S3AsyncClient
@Provides
@TimeStamp
Supplier<String> provideTimeStampCache(
@Named(S3Constants.PROPERTY_S3_SESSIONINTERVAL) long seconds,
final DateService dateService) {
@Named(S3Constants.PROPERTY_S3_SESSIONINTERVAL) long seconds,
final DateService dateService) {
return new ExpirableSupplier<String>(new Supplier<String>() {
public String get() {
return dateService.rfc822DateFormat();
@ -104,13 +108,15 @@ public class S3RestClientModule extends RestClientModule<S3Client, S3AsyncClient
@Singleton
@S3
Map<String, URI> provideRegions(
@Named(S3Constants.PROPERTY_S3_ENDPOINT_US_STANDARD) String usstandard,
@Named(S3Constants.PROPERTY_S3_ENDPOINT_US_WEST_1) String uswest,
@Named(S3Constants.PROPERTY_S3_ENDPOINT_AP_SOUTHEAST_1) String southeast,
@Named(S3Constants.PROPERTY_S3_ENDPOINT_EU_WEST_1) String euwest) {
return ImmutableMap.<String, URI> of(Region.US_STANDARD, URI.create(usstandard),
Region.AP_SOUTHEAST_1, URI.create(southeast), Region.US_WEST_1, URI.create(uswest),
Region.EU_WEST_1, URI.create(euwest));
@Named(S3Constants.PROPERTY_S3_REGIONS) String regionString,
Injector injector) {
Map<String, URI> regions = Maps.newLinkedHashMap();
for (String region : Splitter.on(',').split(regionString)) {
regions.put(region, URI.create(injector.getInstance(Key.get(
String.class, Names.named(S3Constants.PROPERTY_S3_ENDPOINT + "."
+ region)))));
}
return regions;
}
@Provides
@ -123,7 +129,8 @@ public class S3RestClientModule extends RestClientModule<S3Client, S3AsyncClient
@Provides
@Singleton
@S3
protected URI provideS3URI(@Named(S3Constants.PROPERTY_S3_ENDPOINT) String endpoint) {
protected URI provideS3URI(
@Named(S3Constants.PROPERTY_S3_ENDPOINT) String endpoint) {
return URI.create(endpoint);
}
@ -131,24 +138,25 @@ public class S3RestClientModule extends RestClientModule<S3Client, S3AsyncClient
@Singleton
@S3
String getDefaultRegion(@S3 URI uri, @S3 Map<String, URI> map) {
return ImmutableBiMap.<String, URI> builder().putAll(map).build().inverse().get(uri);
return ImmutableBiMap.<String, URI> builder().putAll(map).build()
.inverse().get(uri);
}
@Override
protected void bindErrorHandlers() {
bind(HttpErrorHandler.class).annotatedWith(Redirection.class).to(
ParseAWSErrorFromXmlContent.class);
ParseAWSErrorFromXmlContent.class);
bind(HttpErrorHandler.class).annotatedWith(ClientError.class).to(
ParseAWSErrorFromXmlContent.class);
ParseAWSErrorFromXmlContent.class);
bind(HttpErrorHandler.class).annotatedWith(ServerError.class).to(
ParseAWSErrorFromXmlContent.class);
ParseAWSErrorFromXmlContent.class);
}
@Override
protected void bindRetryHandlers() {
bind(HttpRetryHandler.class).annotatedWith(Redirection.class).to(
AWSRedirectionRetryHandler.class);
AWSRedirectionRetryHandler.class);
bind(HttpRetryHandler.class).annotatedWith(ClientError.class).to(
AWSClientErrorRetryHandler.class);
AWSClientErrorRetryHandler.class);
}
}

View File

@ -36,14 +36,10 @@ public interface S3Constants extends AWSConstants, S3Headers {
public static final String MAX_KEYS = "max-keys";
public static final String DELIMITER = "delimiter";
public static final String PROPERTY_S3_ENDPOINT = "jclouds.s3.endpoint";
public static final String PROPERTY_S3_REGIONS = "jclouds.s3.regions";
/**
* how long do we wait before obtaining a new timestamp for requests.
*/
public static final String PROPERTY_S3_SESSIONINTERVAL = "jclouds.s3.sessioninterval";
public static final String PROPERTY_S3_ENDPOINT_EU_WEST_1 = "jclouds.s3.endpoint.eu_west_1";
public static final String PROPERTY_S3_ENDPOINT_US_STANDARD = "jclouds.s3.endpoint.us_standard";
public static final String PROPERTY_S3_ENDPOINT_US_WEST_1 = "jclouds.s3.endpoint.us_west_1";
public static final String PROPERTY_S3_ENDPOINT_AP_SOUTHEAST_1 = "jclouds.s3.endpoint.ap_southeast_1";
}

View File

@ -0,0 +1,36 @@
/**
*
* Copyright (C) 2009 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 org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
/**
*
* @author Adrian Cole
*/
@Test(groups = "live", sequential = true, testName = "ec2.EucalyptusComputeServiceLiveTest")
public class EucalyptusComputeServiceLiveTest extends EC2ComputeServiceLiveTest {
@BeforeClass
@Override
public void setServiceDefaults() {
service = "eucalyptus";
}
}

View File

@ -49,102 +49,111 @@ import com.google.common.collect.Iterables;
public class ImageParserTest extends BaseEC2HandlerTest {
public void testParseAlesticCanonicalImage() {
InputStream is = getClass().getResourceAsStream("/ec2/alestic_canonical.xml");
InputStream is = getClass().getResourceAsStream(
"/ec2/alestic_canonical.xml");
Set<Image> result = parseImages(is);
assertEquals(result.size(), 7);
ImageParser parser = new ImageParser(
new EC2PopulateDefaultLoginCredentialsForImageStrategy(), ImmutableSet
.<Location> of(defaultLocation), defaultLocation);
org.jclouds.compute.domain.Image ubuntuHardy = parser.apply(Iterables.get(result, 0));
new EC2PopulateDefaultLoginCredentialsForImageStrategy(),
ImmutableSet.<Location> of(defaultLocation), defaultLocation);
org.jclouds.compute.domain.Image ubuntuHardy = parser.apply(Iterables
.get(result, 0));
assertEquals(ubuntuHardy.getArchitecture(), org.jclouds.compute.domain.Architecture.X86_32);
assertEquals(ubuntuHardy.getArchitecture(),
org.jclouds.compute.domain.Architecture.X86_32);
assertEquals(ubuntuHardy.getDescription(),
"ubuntu-images-us/ubuntu-hardy-8.04-i386-server-20091130.manifest.xml");
"ubuntu-images-us/ubuntu-hardy-8.04-i386-server-20091130.manifest.xml");
assertEquals(ubuntuHardy.getProviderId(), "ami-7e28ca17");
assertEquals(ubuntuHardy.getLocation(), defaultLocation);
assertEquals(ubuntuHardy.getName(), "8.04");
assertEquals(ubuntuHardy.getOsDescription(),
"ubuntu-images-us/ubuntu-hardy-8.04-i386-server-20091130.manifest.xml");
"ubuntu-images-us/ubuntu-hardy-8.04-i386-server-20091130.manifest.xml");
assertEquals(ubuntuHardy.getOsFamily(), OsFamily.UBUNTU);
assertEquals(ubuntuHardy.getUserMetadata(), ImmutableMap.<String, String> of("owner",
"099720109477"));
assertEquals(ubuntuHardy.getUserMetadata(), ImmutableMap
.<String, String> of("owner", "099720109477"));
assertEquals(ubuntuHardy.getVersion(), "20091130");
org.jclouds.compute.domain.Image alesticKarmic = parser.apply(Iterables.get(result, 1));
org.jclouds.compute.domain.Image alesticKarmic = parser.apply(Iterables
.get(result, 1));
assertEquals(alesticKarmic.getArchitecture(), org.jclouds.compute.domain.Architecture.X86_32);
assertEquals(alesticKarmic.getArchitecture(),
org.jclouds.compute.domain.Architecture.X86_32);
assertEquals(alesticKarmic.getDescription(),
"alestic/ubuntu-9.10-karmic-base-20090623.manifest.xml");
"alestic/ubuntu-9.10-karmic-base-20090623.manifest.xml");
assertEquals(alesticKarmic.getProviderId(), "ami-19a34270");
assertEquals(alesticKarmic.getLocation(), defaultLocation);
assertEquals(alesticKarmic.getName(), "9.10");
assertEquals(alesticKarmic.getOsDescription(),
"alestic/ubuntu-9.10-karmic-base-20090623.manifest.xml");
"alestic/ubuntu-9.10-karmic-base-20090623.manifest.xml");
assertEquals(alesticKarmic.getOsFamily(), OsFamily.UBUNTU);
assertEquals(alesticKarmic.getUserMetadata(), ImmutableMap.<String, String> of("owner",
"063491364108"));
assertEquals(alesticKarmic.getUserMetadata(), ImmutableMap
.<String, String> of("owner", "063491364108"));
assertEquals(alesticKarmic.getVersion(), "20090623");
org.jclouds.compute.domain.Image ubuntuKarmic = parser.apply(Iterables
.get(result, 2));
org.jclouds.compute.domain.Image ubuntuKarmic = parser.apply(Iterables.get(result, 2));
assertEquals(ubuntuKarmic.getArchitecture(), org.jclouds.compute.domain.Architecture.X86_32);
assertEquals(ubuntuKarmic.getArchitecture(),
org.jclouds.compute.domain.Architecture.X86_32);
assertEquals(ubuntuKarmic.getDescription(),
"ubuntu-images-us/ubuntu-karmic-9.10-i386-server-20100121.manifest.xml");
"ubuntu-images-us/ubuntu-karmic-9.10-i386-server-20100121.manifest.xml");
assertEquals(ubuntuKarmic.getProviderId(), "ami-bb709dd2");
assertEquals(ubuntuKarmic.getLocation(), defaultLocation);
assertEquals(ubuntuKarmic.getName(), "9.10");
assertEquals(ubuntuKarmic.getOsDescription(),
"ubuntu-images-us/ubuntu-karmic-9.10-i386-server-20100121.manifest.xml");
"ubuntu-images-us/ubuntu-karmic-9.10-i386-server-20100121.manifest.xml");
assertEquals(ubuntuKarmic.getOsFamily(), OsFamily.UBUNTU);
assertEquals(ubuntuKarmic.getUserMetadata(), ImmutableMap.<String, String> of("owner",
"099720109477"));
assertEquals(ubuntuKarmic.getUserMetadata(), ImmutableMap
.<String, String> of("owner", "099720109477"));
assertEquals(ubuntuKarmic.getVersion(), "20100121");
// should skip testing image
assert parser.apply(Iterables.get(result, 3)) == null;
org.jclouds.compute.domain.Image alesticHardy = parser.apply(Iterables.get(result, 4));
org.jclouds.compute.domain.Image alesticHardy = parser.apply(Iterables
.get(result, 4));
assertEquals(alesticHardy.getArchitecture(), org.jclouds.compute.domain.Architecture.X86_32);
assertEquals(alesticHardy.getArchitecture(),
org.jclouds.compute.domain.Architecture.X86_32);
assertEquals(alesticHardy.getDescription(),
"alestic/ubuntu-8.04-hardy-base-20080905.manifest.xml");
"alestic/ubuntu-8.04-hardy-base-20080905.manifest.xml");
assertEquals(alesticHardy.getProviderId(), "ami-c0fa1ea9");
assertEquals(alesticHardy.getLocation(), defaultLocation);
assertEquals(alesticHardy.getName(), "8.04");
assertEquals(alesticHardy.getOsDescription(),
"alestic/ubuntu-8.04-hardy-base-20080905.manifest.xml");
"alestic/ubuntu-8.04-hardy-base-20080905.manifest.xml");
assertEquals(alesticHardy.getOsFamily(), OsFamily.UBUNTU);
assertEquals(alesticHardy.getUserMetadata(), ImmutableMap.<String, String> of("owner",
"063491364108"));
assertEquals(alesticHardy.getUserMetadata(), ImmutableMap
.<String, String> of("owner", "063491364108"));
assertEquals(alesticHardy.getVersion(), "20080905");
org.jclouds.compute.domain.Image ubuntuLucid = parser.apply(Iterables.get(result, 5));
org.jclouds.compute.domain.Image ubuntuLucid = parser.apply(Iterables
.get(result, 5));
assertEquals(ubuntuLucid.getArchitecture(), org.jclouds.compute.domain.Architecture.X86_32);
assertEquals(ubuntuLucid.getDescription(),
"ubuntu-images-us-west-1/ubuntu-lucid-10.04-i386-server-20100427.1.manifest.xml");
assertEquals(ubuntuLucid.getArchitecture(),
org.jclouds.compute.domain.Architecture.X86_32);
assertEquals(
ubuntuLucid.getDescription(),
"ubuntu-images-us-west-1/ubuntu-lucid-10.04-i386-server-20100427.1.manifest.xml");
assertEquals(ubuntuLucid.getProviderId(), "ami-c597c680");
assertEquals(ubuntuLucid.getLocation(), defaultLocation);
assertEquals(ubuntuLucid.getName(), "10.04");
assertEquals(ubuntuLucid.getOsDescription(),
"ubuntu-images-us-west-1/ubuntu-lucid-10.04-i386-server-20100427.1.manifest.xml");
assertEquals(
ubuntuLucid.getOsDescription(),
"ubuntu-images-us-west-1/ubuntu-lucid-10.04-i386-server-20100427.1.manifest.xml");
assertEquals(ubuntuLucid.getOsFamily(), OsFamily.UBUNTU);
assertEquals(ubuntuLucid.getUserMetadata(), ImmutableMap.<String, String> of("owner",
"099720109477"));
assertEquals(ubuntuLucid.getUserMetadata(), ImmutableMap
.<String, String> of("owner", "099720109477"));
assertEquals(ubuntuLucid.getVersion(), "20100427.1");
// should skip kernel
assert parser.apply(Iterables.get(result, 6)) == null;
}
private Location defaultLocation = new LocationImpl(LocationScope.REGION, "us-east-1",
"us-east-1", null);
private Location defaultLocation = new LocationImpl(LocationScope.REGION,
"us-east-1", "us-east-1", null);
public void testParseVostokImage() {
InputStream is = getClass().getResourceAsStream("/ec2/vostok.xml");
@ -152,68 +161,122 @@ public class ImageParserTest extends BaseEC2HandlerTest {
Set<Image> result = parseImages(is);
ImageParser parser = new ImageParser(
new EC2PopulateDefaultLoginCredentialsForImageStrategy(), ImmutableSet
.<Location> of(defaultLocation), defaultLocation);
new EC2PopulateDefaultLoginCredentialsForImageStrategy(),
ImmutableSet.<Location> of(defaultLocation), defaultLocation);
org.jclouds.compute.domain.Image image = parser.apply(Iterables.get(result, 0));
org.jclouds.compute.domain.Image image = parser.apply(Iterables.get(
result, 0));
assertEquals(image.getArchitecture(), org.jclouds.compute.domain.Architecture.X86_32);
assertEquals(image.getArchitecture(),
org.jclouds.compute.domain.Architecture.X86_32);
assertEquals(image.getDescription(),
"vostok-builds/vostok-0.95-5622/vostok-0.95-5622.manifest.xml");
"vostok-builds/vostok-0.95-5622/vostok-0.95-5622.manifest.xml");
assertEquals(image.getProviderId(), "ami-870de2ee");
assertEquals(image.getLocation(), defaultLocation);
assertEquals(image.getName(), "");
assertEquals(image.getOsDescription(),
"vostok-builds/vostok-0.95-5622/vostok-0.95-5622.manifest.xml");
"vostok-builds/vostok-0.95-5622/vostok-0.95-5622.manifest.xml");
assertEquals(image.getOsFamily(), null);
assertEquals(image.getUserMetadata(), ImmutableMap.<String, String> of("owner",
"133804938231"));
assertEquals(image.getUserMetadata(), ImmutableMap.<String, String> of(
"owner", "133804938231"));
assertEquals(image.getVersion(), "");
}
public void testParseRightScaleImage() {
InputStream is = getClass().getResourceAsStream("/ec2/rightscale_images.xml");
InputStream is = getClass().getResourceAsStream(
"/ec2/rightscale_images.xml");
Set<Image> result = parseImages(is);
ImageParser parser = new ImageParser(
new EC2PopulateDefaultLoginCredentialsForImageStrategy(), ImmutableSet
.<Location> of(defaultLocation), defaultLocation);
new EC2PopulateDefaultLoginCredentialsForImageStrategy(),
ImmutableSet.<Location> of(defaultLocation), defaultLocation);
org.jclouds.compute.domain.Image image = parser.apply(Iterables.get(result, 0));
org.jclouds.compute.domain.Image image = parser.apply(Iterables.get(
result, 0));
assertEquals(image.getArchitecture(), org.jclouds.compute.domain.Architecture.X86_64);
assertEquals(image.getDescription(), "rightscale-us-east/CentOS_5.4_x64_v4.4.10.manifest.xml");
assertEquals(image.getArchitecture(),
org.jclouds.compute.domain.Architecture.X86_64);
assertEquals(image.getDescription(),
"rightscale-us-east/CentOS_5.4_x64_v4.4.10.manifest.xml");
assertEquals(image.getProviderId(), "ami-ccb35ea5");
assertEquals(image.getLocation(), defaultLocation);
assertEquals(image.getName(), "5.4");
assertEquals(image.getOsDescription(),
"rightscale-us-east/CentOS_5.4_x64_v4.4.10.manifest.xml");
"rightscale-us-east/CentOS_5.4_x64_v4.4.10.manifest.xml");
assertEquals(image.getOsFamily(), OsFamily.CENTOS);
assertEquals(image.getUserMetadata(), ImmutableMap.<String, String> of("owner",
"411009282317"));
assertEquals(image.getUserMetadata(), ImmutableMap.<String, String> of(
"owner", "411009282317"));
assertEquals(image.getVersion(), "4.4.10");
image = parser.apply(Iterables.get(result, 1));
assertEquals(image.getArchitecture(), org.jclouds.compute.domain.Architecture.X86_64);
assertEquals(image.getDescription(), "RightImage_Ubuntu_9.10_x64_v4.5.3_EBS_Alpha");
assertEquals(image.getArchitecture(),
org.jclouds.compute.domain.Architecture.X86_64);
assertEquals(image.getDescription(),
"RightImage_Ubuntu_9.10_x64_v4.5.3_EBS_Alpha");
assertEquals(image.getProviderId(), "ami-c19db6b5");
assertEquals(image.getLocation(), defaultLocation);
assertEquals(image.getName(), "9.10");
assertEquals(image.getOsDescription(),
"411009282317/RightImage_Ubuntu_9.10_x64_v4.5.3_EBS_Alpha");
"411009282317/RightImage_Ubuntu_9.10_x64_v4.5.3_EBS_Alpha");
assertEquals(image.getOsFamily(), OsFamily.UBUNTU);
assertEquals(image.getUserMetadata(), ImmutableMap.<String, String> of("owner",
"411009282317"));
assertEquals(image.getUserMetadata(), ImmutableMap.<String, String> of(
"owner", "411009282317"));
assertEquals(image.getVersion(), "4.5.3_EBS_Alpha");
}
public void testParseEucalyptusImage() {
InputStream is = getClass().getResourceAsStream(
"/ec2/eucalyptus_images.xml");
Set<Image> result = parseImages(is);
assertEquals(result.size(), 11);
ImageParser parser = new ImageParser(
new EC2PopulateDefaultLoginCredentialsForImageStrategy(),
ImmutableSet.<Location> of(defaultLocation), defaultLocation);
org.jclouds.compute.domain.Image image = parser.apply(Iterables.get(
result, 0));
assertEquals(image.getArchitecture(),
org.jclouds.compute.domain.Architecture.X86_64);
assertEquals(image.getDescription(),
"centos-5.3-x86_64/centos.5-3.x86-64.img.manifest.xml");
assertEquals(image.getProviderId(), "emi-9ACB1363");
assertEquals(image.getLocation(), defaultLocation);
assertEquals(image.getName(), "5.3");
assertEquals(image.getOsDescription(),
"centos-5.3-x86_64/centos.5-3.x86-64.img.manifest.xml");
assertEquals(image.getOsFamily(), OsFamily.CENTOS);
assertEquals(image.getUserMetadata(), ImmutableMap.<String, String> of(
"owner", "admin"));
assertEquals(image.getVersion(), "");
image = parser.apply(Iterables.get(result, 6));
assertEquals(image.getDescription(),
"Lean/ubuntu.9-04.x86-64.img.manifest.xml");
assertEquals(image.getArchitecture(),
org.jclouds.compute.domain.Architecture.X86_64);
assertEquals(image.getDescription(),
"Lean/ubuntu.9-04.x86-64.img.manifest.xml");
assertEquals(image.getProviderId(), "emi-CBEA100C");
assertEquals(image.getLocation(), defaultLocation);
assertEquals(image.getName(), "9.04");
assertEquals(image.getOsDescription(),
"Lean/ubuntu.9-04.x86-64.img.manifest.xml");
assertEquals(image.getOsFamily(), OsFamily.UBUNTU);
assertEquals(image.getUserMetadata(), ImmutableMap.<String, String> of(
"owner", "mashaobing1"));
assertEquals(image.getVersion(), "");
}
private Set<Image> parseImages(InputStream is) {
DescribeImagesResponseHandler handler = injector
.getInstance(DescribeImagesResponseHandler.class);
.getInstance(DescribeImagesResponseHandler.class);
addDefaultRegionToHandler(handler);
Set<Image> result = factory.create(handler).parse(is);
return result;

View File

@ -29,6 +29,7 @@ import org.jclouds.aws.ec2.EC2;
import org.jclouds.http.functions.BaseHandlerTest;
import org.jclouds.http.functions.ParseSax;
import org.jclouds.http.functions.config.ParserModule;
import org.jclouds.util.Utils;
import org.testng.annotations.BeforeTest;
import org.testng.annotations.Test;
@ -50,7 +51,8 @@ public class DescribeRegionsResponseHandlerTest extends BaseHandlerTest {
@Override
protected void configure() {
bind(URI.class).annotatedWith(EC2.class).toInstance(URI.create("https://booya"));
bind(URI.class).annotatedWith(EC2.class).toInstance(
URI.create("https://booya"));
}
});
@ -60,31 +62,57 @@ public class DescribeRegionsResponseHandlerTest extends BaseHandlerTest {
public void testApplyInputStream() {
InputStream is = getClass().getResourceAsStream("/ec2/regionEndpoints.xml");
InputStream is = getClass().getResourceAsStream(
"/ec2/regionEndpoints.xml");
Map<String, URI> expected = ImmutableMap.<String, URI> of(Region.EU_WEST_1, URI
.create("https://ec2.eu-west-1.amazonaws.com"), Region.US_EAST_1, URI
.create("https://ec2.us-east-1.amazonaws.com"), Region.US_WEST_1, URI
.create("https://ec2.us-west-1.amazonaws.com"));
Map<String, URI> expected = ImmutableMap
.<String, URI> of(Region.EU_WEST_1, URI
.create("https://ec2.eu-west-1.amazonaws.com"),
Region.US_EAST_1, URI
.create("https://ec2.us-east-1.amazonaws.com"),
Region.US_WEST_1, URI
.create("https://ec2.us-west-1.amazonaws.com"));
Map<String, URI> result = factory.create(
injector.getInstance(DescribeRegionsResponseHandler.class)).parse(is);
injector.getInstance(DescribeRegionsResponseHandler.class)).parse(
is);
assertEquals(result, expected);
}
public void testEuc() {
InputStream is = Utils
.toInputStream("<DescribeRegionsResponse xmlns=\"http://ec2.amazonaws.com/doc/2009-11-30/\"><requestId>6a3b36f9-9ff4-47cf-87e3-285b08fbe5e5</requestId><regionInfo><item><regionName>Eucalyptus</regionName><regionEndpoint>http://173.205.188.130:8773/services/Eucalyptus</regionEndpoint></item><item><regionName>Walrus</regionName><regionEndpoint>http://173.205.188.130:8773/services/Walrus</regionEndpoint></item></regionInfo></DescribeRegionsResponse>");
Map<String, URI> expected = ImmutableMap.<String, URI> of("Eucalyptus",
URI.create("http://173.205.188.130:8773/services/Eucalyptus"));
Map<String, URI> result = factory.create(
injector.getInstance(DescribeRegionsResponseHandler.class)).parse(
is);
assertEquals(result, expected);
}
public void testUnsupportedAdditionalRegionDoesntBreak() {
InputStream is = getClass().getResourceAsStream("/ec2/regionEndpoints-additional.xml");
InputStream is = getClass().getResourceAsStream(
"/ec2/regionEndpoints-additional.xml");
Map<String, URI> expected = ImmutableMap.<String, URI> of("jp-west-1", URI
.create("https://ec2.jp-west-1.amazonaws.com"), Region.EU_WEST_1, URI
.create("https://ec2.eu-west-1.amazonaws.com"), Region.US_EAST_1, URI
.create("https://ec2.us-east-1.amazonaws.com"), Region.US_WEST_1, URI
.create("https://ec2.us-west-1.amazonaws.com"));
Map<String, URI> expected = ImmutableMap
.<String, URI> of("jp-west-1", URI
.create("https://ec2.jp-west-1.amazonaws.com"),
Region.EU_WEST_1, URI
.create("https://ec2.eu-west-1.amazonaws.com"),
Region.US_EAST_1, URI
.create("https://ec2.us-east-1.amazonaws.com"),
Region.US_WEST_1, URI
.create("https://ec2.us-west-1.amazonaws.com"));
Map<String, URI> result = factory.create(
injector.getInstance(DescribeRegionsResponseHandler.class)).parse(is);
injector.getInstance(DescribeRegionsResponseHandler.class)).parse(
is);
assertEquals(result, expected);
}

View File

@ -0,0 +1,189 @@
<DescribeImagesResponse xmlns="http://ec2.amazonaws.com/doc/2009-11-30/">
<requestId>7b893acf-7752-4e
2c-8c1a-3287a011b0df</requestId>
<imagesSet>
<item>
<imageId>emi-9ACB1363</imageId>
<imageLocation>centos-5.3-x86_64/centos.5-3.x86-64.img.manifest.xml
</imageLocation>
<imageState>available
</imageState>
<imageOwnerId>admin</imageOwnerId>
<isPublic>true</isPublic>
<productCodes />
<architecture>x86_64</architecture>
<imageType>
machine
</imageType>
<kernelId>eki-6CBD12F2</kernelId>
<ramdiskId>eri-A97113E4</ramdiskId>
<rootDeviceType>instance-store</rootDeviceType>
<rootDeviceName>/dev/sda1</rootDeviceName>
<blockDeviceMapping />
</item>
<item>
<imageId>emi-D2D610D1</imageId>
<imageLocation>martin_try1/martin_try1.manifest.xml</imageLocation>
<imageState>
available
</imageState>
<imageOwnerId>dominic</imageOwnerId>
<isPublic>true</isPublic>
<productCodes />
<architecture>x86_64</architecture>
<imageType>machine</imageType>
<kernelId>eki-6CBD12F2</kernelId>
<ramdiskId>eri-A97113E4</ramdiskId>
<rootDeviceType>instance-store</rootDeviceType>
<rootDeviceName>/dev/sda1</rootDeviceName>
<blockDeviceMapping />
</item>
<item>
<imageId>eri-A97113E4</imageId>
<imageLocation>initrd-64/initrd.img-2.6.28-11-generic.manifest.xml
</imageLocation>
<imageState>available</imageState>
<imageOwnerId>admin</imageOwnerId>
<isPublic>true</isPublic>
<productCodes />
<architecture>x86_64</architecture>
<imageType>ramdisk</imageType>
<rootDeviceType>
instance-store
</rootDeviceType>
<rootDeviceName>/dev/sda1</rootDeviceName>
<blockDeviceMapping />
</item>
<item>
<imageId>emi-B9A40FF6</imageId>
<imageLocation>ulteo4/ubuntu804-32-test.manifest.xml</imageLocation>
<imageState>available</imageState>
<imageOwnerId>gaelduval</imageOwnerId>
<isPublic>true</isPublic>
<productCodes />
<architecture>
i386
</architecture>
<imageType>machine</imageType>
<rootDeviceType>instance-store</rootDeviceType>
<rootDeviceName>/dev/sda1</rootDeviceName>
<blockDeviceMapping />
</item>
<item>
<imageId>
emi-D1991835
</imageId>
<imageLocation>jamestyj-test/Eucalyptus_Guest.x86_64-0.0.2.raw.manifest.xml
</imageLocation>
<imageState>available</imageState>
<imageOwnerId>jamestyj</imageOwnerId>
<isPublic>true</isPublic>
<productCodes />
<architecture>x86_64</architecture>
<imageType>machine</imageType>
<rootDeviceType>
instance-store
</rootDeviceType>
<rootDeviceName>/dev/sda1</rootDeviceName>
<blockDeviceMapping />
</item>
<item>
<imageId>emi-D8AB1044</imageId>
<imageLocation>test/ubuntu.9-04.x86-64.img.manifest.xml
</imageLocation>
<imageState>available</imageState>
<imageOwnerId>mymq0206</imageOwnerId>
<isPublic>true</isPublic>
<productCodes />
<architecture>
x86_64
</architecture>
<imageType>machine</imageType>
<rootDeviceType>instance-store</rootDeviceType>
<rootDeviceName>/dev/sda1</rootDeviceName>
<blockDeviceMapping />
</item>
<item>
<imageId>
emi-CBEA100C
</imageId>
<imageLocation>Lean/ubuntu.9-04.x86-64.img.manifest.xml
</imageLocation>
<imageState>available</imageState>
<imageOwnerId>
mashaobing1
</imageOwnerId>
<isPublic>true</isPublic>
<productCodes />
<architecture>x86_64</architecture>
<imageType>machine</imageType>
<kernelId>eki-6CBD12F2</kernelId>
<ramdiskId>eri-A97113E4</ramdiskId>
<rootDeviceType>instance-store</rootDeviceType>
<rootDeviceName>/dev/sda1</rootDeviceName>
<blockDeviceMapping />
</item>
<item>
<imageId>emi-D176182B</imageId>
<imageLocation>jamestyj-test/Eucalyptus_Guest.x86_64-0.0.3.raw.manifest.xml
</imageLocation>
<imageState>available</imageState>
<imageOwnerId>
jamestyj
</imageOwnerId>
<isPublic>true</isPublic>
<productCodes />
<architecture>x86_64</architecture>
<imageType>machine</imageType>
<rootDeviceType>instance-store</rootDeviceType>
<rootDeviceName>/dev/sda1</rootDeviceName>
<blockDeviceMapping />
</item>
<item>
<imageId>emi-D25E10CA</imageId>
<imageLocation>
biolinux/biolinux.qcow2.manifest.xml
</imageLocation>
<imageState>available</imageState>
<imageOwnerId>brainstorm</imageOwnerId>
<isPublic>true</isPublic>
<productCodes />
<architecture>x86_64</architecture>
<imageType>machine</imageType>
<rootDeviceType>instance-store</rootDeviceType>
<rootDeviceName>/dev/sda1</rootDeviceName>
<blockDeviceMapping />
</item>
<item>
<imageId>
eki-6CBD12F2
</imageId>
<imageLocation>kernel-64/vmlinuz-2.6.28-11-generic.manifest.xml
</imageLocation>
<imageState>available</imageState>
<imageOwnerId>admin</imageOwnerId>
<isPublic>true</isPublic>
<productCodes />
<architecture>x86_64</architecture>
<imageType>kernel</imageType>
<rootDeviceType>instance-store</rootDeviceType>
<rootDeviceName>/dev/sda1</rootDeviceName>
<blockDeviceMapping />
</item>
<item>
<imageId>emi-2EDC1606</imageId>
<imageLocation>
ulteo2/Ulteo-SM-Scalability-Test-19feb2010.manifest.xml
</imageLocation>
<imageState>available</imageState>
<imageOwnerId>gaelduval</imageOwnerId>
<isPublic>true</isPublic>
<productCodes />
<architecture>i386</architecture>
<imageType>machine</imageType>
<rootDeviceType>instance-store</rootDeviceType>
<rootDeviceName>/dev/sda1</rootDeviceName>
<blockDeviceMapping />
</item>
</imagesSet>
</DescribeImagesResponse>

View File

@ -82,6 +82,7 @@
</layout>
</appender>
<!-- A time/date based rolling appender -->
<appender name="COMPUTEFILE" class="org.apache.log4j.DailyRollingFileAppender">
<param name="File" value="target/test-data/jclouds-compute.log" />
@ -145,6 +146,12 @@
<appender-ref ref="ASYNCWIRE" />
</category>
<category name="jclouds.signature">
<priority value="DEBUG" />
<appender-ref ref="ASYNCWIRE" />
</category>
<!-- ======================= -->
<!-- Setup the Root category -->
<!-- ======================= -->

View File

@ -27,5 +27,7 @@ cloudfiles.contextbuilder=org.jclouds.rackspace.cloudfiles.CloudFilesContextBuil
cloudfiles.propertiesbuilder=org.jclouds.rackspace.cloudfiles.CloudFilesPropertiesBuilder
s3.contextbuilder=org.jclouds.aws.s3.S3ContextBuilder
s3.propertiesbuilder=org.jclouds.aws.s3.S3PropertiesBuilder
walrus.contextbuilder=org.jclouds.aws.s3.S3ContextBuilder
walrus.propertiesbuilder=org.jclouds.aws.s3.WalrusPropertiesBuilder
transient.contextbuilder=org.jclouds.blobstore.TransientBlobStoreContextBuilder
transient.propertiesbuilder=org.jclouds.blobstore.TransientBlobStorePropertiesBuilder

View File

@ -29,6 +29,7 @@ import java.util.Formatter;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Properties;
import java.util.Set;
import java.util.Map.Entry;
@ -42,12 +43,14 @@ import javax.annotation.Resource;
import javax.inject.Named;
import org.jclouds.Constants;
import org.jclouds.compute.domain.Architecture;
import org.jclouds.compute.domain.ComputeMetadata;
import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.domain.internal.NodeMetadataImpl;
import org.jclouds.compute.options.TemplateOptions;
import org.jclouds.compute.predicates.ScriptStatusReturnsZero.CommandUsingClient;
import org.jclouds.compute.reference.ComputeServiceConstants;
import org.jclouds.compute.reference.ComputeServiceConstants.Timeouts;
import org.jclouds.compute.strategy.GetNodeMetadataStrategy;
import org.jclouds.concurrent.ConcurrentUtils;
import org.jclouds.domain.Credentials;
@ -85,21 +88,73 @@ public class ComputeUtils {
private final ExecutorService executor;
protected final Predicate<NodeMetadata> nodeRunning;
private final GetNodeMetadataStrategy getNode;
private final Timeouts timeouts;
public static final Map<org.jclouds.compute.domain.OsFamily, Map<String, String>> NAME_VERSION_MAP = ImmutableMap
.<org.jclouds.compute.domain.OsFamily, Map<String, String>> of(
org.jclouds.compute.domain.OsFamily.CENTOS, ImmutableMap
.<String, String> builder().put("5.3", "5.3").put("5.4",
"5.4").put("5.5", "5.5").build(),
org.jclouds.compute.domain.OsFamily.RHEL, ImmutableMap
.<String, String> builder().put("5.3", "5.3").put("5.4",
"5.4").put("5.5", "5.5").build(),
org.jclouds.compute.domain.OsFamily.UBUNTU, ImmutableMap
.<String, String> builder().put("hardy", "8.04").put(
"intrepid", "8.10").put("jaunty", "9.04").put(
"karmic", "9.10").put("lucid", "10.04").put(
"maverick", "10.10").build());
@Inject
public ComputeUtils(
Predicate<IPSocket> socketTester,
@Named("SCRIPT_COMPLETE") Predicate<CommandUsingClient> runScriptNotRunning,
GetNodeMetadataStrategy getNode,
GetNodeMetadataStrategy getNode, Timeouts timeouts,
@Named("NODE_RUNNING") Predicate<NodeMetadata> nodeRunning,
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService executor) {
this.nodeRunning = nodeRunning;
this.timeouts = timeouts;
this.getNode = getNode;
this.socketTester = socketTester;
this.runScriptNotRunning = runScriptNotRunning;
this.executor = executor;
}
public static String parseVersionOrReturnEmptyString(
org.jclouds.compute.domain.OsFamily family, final String in) {
if (NAME_VERSION_MAP.containsKey(family)) {
CONTAINS_SUBSTRING contains = new CONTAINS_SUBSTRING(in.replace('-',
'.'));
try {
String key = Iterables.find(NAME_VERSION_MAP.get(family).keySet(),
contains);
return NAME_VERSION_MAP.get(family).get(key);
} catch (NoSuchElementException e) {
try {
return Iterables.find(NAME_VERSION_MAP.get(family).values(),
contains);
} catch (NoSuchElementException e1) {
}
}
}
return "";
}
public static org.jclouds.compute.domain.OsFamily parseOsFamilyOrNull(
String in) {
org.jclouds.compute.domain.OsFamily myOs = null;
for (org.jclouds.compute.domain.OsFamily os : org.jclouds.compute.domain.OsFamily
.values()) {
if (in.toLowerCase().replaceAll("\\s", "").indexOf(os.toString()) != -1) {
myOs = os;
}
}
return myOs;
}
public static Architecture parseArchitectureOrNull(String in) {
return in.indexOf("64") == -1 ? Architecture.X86_32 : Architecture.X86_64;
}
public static String createExecutionErrorMessage(
Map<?, Exception> executionExceptions) {
Formatter fmt = new Formatter().format("Execution failures:%n%n");
@ -179,7 +234,11 @@ public class ComputeUtils {
.getCredentials());
else
throw new IllegalStateException(
"node didn't achieve the state running: " + node);
String
.format(
"node didn't achieve the state running on node %s within %d seconds, final state: %s",
node.getId(), timeouts.nodeRunning / 1000, node
.getState()));
List<SshCallable<?>> callables = Lists.newArrayList();
if (options.getRunScript() != null) {
@ -331,6 +390,19 @@ public class ComputeUtils {
return actualResponses;
}
private static final class CONTAINS_SUBSTRING implements Predicate<String> {
private final String in;
private CONTAINS_SUBSTRING(String in) {
this.in = in;
}
@Override
public boolean apply(String input) {
return in.indexOf(input) != -1;
}
}
public static interface SshCallable<T> extends Callable<T> {
NodeMetadata getNode();

View File

@ -26,6 +26,8 @@ vcloud.contextbuilder=org.jclouds.vcloud.VCloudContextBuilder
vcloud.propertiesbuilder=org.jclouds.vcloud.VCloudPropertiesBuilder
ec2.contextbuilder=org.jclouds.aws.ec2.EC2ContextBuilder
ec2.propertiesbuilder=org.jclouds.aws.ec2.EC2PropertiesBuilder
eucalyptus.contextbuilder=org.jclouds.aws.ec2.EC2ContextBuilder
eucalyptus.propertiesbuilder=org.jclouds.aws.ec2.EucalyptusPropertiesBuilder
cloudservers.contextbuilder=org.jclouds.rackspace.cloudservers.CloudServersContextBuilder
cloudservers.propertiesbuilder=org.jclouds.rackspace.RackspacePropertiesBuilder
bluelock.contextbuilder=org.jclouds.vcloud.bluelock.BlueLockVCloudContextBuilder

View File

@ -36,6 +36,7 @@ import org.jclouds.compute.domain.OsFamily;
import org.jclouds.compute.domain.internal.ImageImpl;
import org.jclouds.compute.reference.ComputeServiceConstants;
import org.jclouds.compute.strategy.PopulateDefaultLoginCredentialsForImageStrategy;
import org.jclouds.compute.util.ComputeUtils;
import org.jclouds.concurrent.ConcurrentUtils;
import org.jclouds.domain.Location;
import org.jclouds.logging.Logger;
@ -66,10 +67,10 @@ public class VCloudImageProvider implements Provider<Set<? extends Image>> {
@Inject
protected VCloudImageProvider(
VCloudClient client,
FindLocationForResourceInVDC findLocationForResourceInVDC,
PopulateDefaultLoginCredentialsForImageStrategy populateDefaultLoginCredentialsForImageStrategy,
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService executor) {
VCloudClient client,
FindLocationForResourceInVDC findLocationForResourceInVDC,
PopulateDefaultLoginCredentialsForImageStrategy populateDefaultLoginCredentialsForImageStrategy,
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService executor) {
this.client = client;
this.findLocationForResourceInVDC = findLocationForResourceInVDC;
this.populateDefaultLoginCredentialsForImageStrategy = populateDefaultLoginCredentialsForImageStrategy;
@ -80,44 +81,44 @@ public class VCloudImageProvider implements Provider<Set<? extends Image>> {
public Set<? extends Image> get() {
final Set<Image> images = Sets.newHashSet();
logger.debug(">> providing vAppTemplates");
for (final NamedResource vDC : client.getDefaultOrganization().getVDCs().values()) {
Map<String, NamedResource> resources = client.getVDC(vDC.getId()).getResourceEntities();
for (final NamedResource vDC : client.getDefaultOrganization().getVDCs()
.values()) {
Map<String, NamedResource> resources = client.getVDC(vDC.getId())
.getResourceEntities();
Map<String, ListenableFuture<Void>> responses = Maps.newHashMap();
for (final NamedResource resource : resources.values()) {
if (resource.getType().equals(VCloudMediaType.VAPPTEMPLATE_XML)) {
responses.put(resource.getName(), ConcurrentUtils.makeListenable(executor
.submit(new Callable<Void>() {
@Override
public Void call() throws Exception {
OsFamily myOs = null;
for (OsFamily os : OsFamily.values()) {
if (resource.getName().toLowerCase().replaceAll("\\s", "")
.indexOf(os.toString()) != -1) {
myOs = os;
}
}
Architecture arch = resource.getName().indexOf("64") == -1 ? Architecture.X86_32
: Architecture.X86_64;
VAppTemplate template = client.getVAppTemplate(resource.getId());
responses.put(resource.getName(), ConcurrentUtils
.makeListenable(executor.submit(new Callable<Void>() {
@Override
public Void call() throws Exception {
OsFamily myOs = ComputeUtils
.parseOsFamilyOrNull(resource.getName());
Architecture arch = ComputeUtils
.parseArchitectureOrNull(resource.getName());
Location location = findLocationForResourceInVDC.apply(resource, vDC
.getId());
String name = getName(template.getName());
images.add(new ImageImpl(resource.getId(), name, resource.getId(),
location, template.getLocation(), ImmutableMap
.<String, String> of(), template.getDescription(),
"", myOs, name, arch,
populateDefaultLoginCredentialsForImageStrategy
.execute(template)));
return null;
}
}), executor));
VAppTemplate template = client
.getVAppTemplate(resource.getId());
Location location = findLocationForResourceInVDC
.apply(resource, vDC.getId());
String name = getName(template.getName());
images.add(new ImageImpl(resource.getId(), name,
resource.getId(), location, template
.getLocation(), ImmutableMap
.<String, String> of(), template
.getDescription(), "", myOs, name, arch,
populateDefaultLoginCredentialsForImageStrategy
.execute(template)));
return null;
}
}), executor));
}
}
ConcurrentUtils.awaitCompletion(responses, executor, null, logger, "vAppTemplates in "
+ vDC);
ConcurrentUtils.awaitCompletion(responses, executor, null, logger,
"vAppTemplates in " + vDC);
}
return images;
}