Issue 130: fleshed out compute abstraction and hardened TemplateBuilder design

git-svn-id: http://jclouds.googlecode.com/svn/trunk@2718 3d8758e0-26b5-11de-8745-db77d3ebf521
This commit is contained in:
adrian.f.cole 2010-01-22 09:35:39 +00:00
parent a17da70588
commit 28aadccb49
39 changed files with 1188 additions and 735 deletions

View File

@ -38,7 +38,7 @@ public class EC2PropertiesBuilder extends HttpPropertiesBuilder {
@Override
protected Properties defaultProperties() {
Properties properties = super.defaultProperties();
properties.setProperty(PROPERTY_EC2_ENDPOINT, "https://ec2.amazonaws.com");
properties.setProperty(PROPERTY_EC2_ENDPOINT, "https://ec2.us-east-1.amazonaws.com");
properties.setProperty(PROPERTY_AWS_EXPIREINTERVAL, "60");
return properties;
}

View File

@ -26,7 +26,6 @@ import java.net.InetAddress;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Set;
import java.util.SortedSet;
import javax.annotation.Resource;
import javax.inject.Inject;
@ -43,15 +42,16 @@ import org.jclouds.aws.ec2.domain.KeyPair;
import org.jclouds.aws.ec2.domain.RunningInstance;
import org.jclouds.aws.ec2.options.RunInstancesOptions;
import org.jclouds.compute.ComputeService;
import org.jclouds.compute.domain.Architecture;
import org.jclouds.compute.domain.ComputeMetadata;
import org.jclouds.compute.domain.ComputeType;
import org.jclouds.compute.domain.CreateNodeResponse;
import org.jclouds.compute.domain.Image;
import org.jclouds.compute.domain.LoginType;
import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.domain.NodeState;
import org.jclouds.compute.domain.OperatingSystem;
import org.jclouds.compute.domain.Size;
import org.jclouds.compute.domain.Template;
import org.jclouds.compute.domain.TemplateBuilder;
import org.jclouds.compute.domain.internal.ComputeMetadataImpl;
import org.jclouds.compute.domain.internal.CreateNodeResponseImpl;
import org.jclouds.compute.domain.internal.NodeMetadataImpl;
@ -76,22 +76,21 @@ public class EC2ComputeService implements ComputeService {
@Named(ComputeServiceConstants.COMPUTE_LOGGER)
protected Logger logger = Logger.NULL;
private final EC2Client ec2Client;
private final SortedSet<EC2Size> sizes;
private final Provider<Set<EC2Template>> templates;
protected final Provider<Set<? extends Image>> images;
protected final Provider<Set<? extends Size>> sizes;
protected final Provider<TemplateBuilder> templateBuilderProvider;
private final Predicate<RunningInstance> instanceStateRunning;
private final RunningInstanceToNodeMetadata runningInstanceToNodeMetadata;
private final Map<Architecture, Map<OperatingSystem, Map<Region, String>>> imageAmiIdMap;
@Inject
public EC2ComputeService(EC2Client client, SortedSet<EC2Size> sizes,
Provider<Set<EC2Template>> templates,
Map<Architecture, Map<OperatingSystem, Map<Region, String>>> imageAmiIdMap,
public EC2ComputeService(EC2Client client, Provider<TemplateBuilder> templateBuilderProvider,
Provider<Set<? extends Image>> images, Provider<Set<? extends Size>> sizes,
Predicate<RunningInstance> instanceStateRunning,
RunningInstanceToNodeMetadata runningInstanceToNodeMetadata) {
this.ec2Client = client;
this.images = images;
this.sizes = sizes;
this.templates = templates; // delayed intentionally, as generation is slow
this.imageAmiIdMap = imageAmiIdMap;
this.templateBuilderProvider = templateBuilderProvider;
this.instanceStateRunning = instanceStateRunning;
this.runningInstanceToNodeMetadata = runningInstanceToNodeMetadata;
}
@ -108,20 +107,23 @@ public class EC2ComputeService implements ComputeService {
@Override
public CreateNodeResponse runNode(String name, Template template, RunNodeOptions options) {
checkArgument(template instanceof EC2Template,
"unexpected template type. should be EC2Template, was: " + template.getClass());
EC2Template ec2Template = (EC2Template) template;
checkArgument(template.getImage() instanceof EC2Image,
"unexpected image type. should be EC2Image, was: " + template.getImage().getClass());
checkArgument(template.getSize() instanceof EC2Size,
"unexpected image type. should be EC2Size, was: " + template.getSize().getClass());
EC2Image ec2Image = EC2Image.class.cast(template.getImage());
EC2Size ec2Size = EC2Size.class.cast(template.getSize());
KeyPair keyPair = createKeyPairInRegion(ec2Template.getRegion(), name);
Region region = ec2Image.getImage().getRegion();
KeyPair keyPair = createKeyPairInRegion(region, name);
String securityGroupName = name;
createSecurityGroupInRegion(ec2Template.getRegion(), securityGroupName, options
.getOpenPorts());
createSecurityGroupInRegion(region, securityGroupName, options.getOpenPorts());
logger.debug(">> running instance region(%s) ami(%s) type(%s) keyPair(%s) securityGroup(%s)",
ec2Template.getRegion(), ec2Template.getImage().getId(), ec2Template.getSize()
.getInstanceType(), keyPair.getKeyName(), securityGroupName);
region, ec2Image.getId(), ec2Size.getInstanceType(), keyPair.getKeyName(),
securityGroupName);
RunInstancesOptions instanceOptions = withKeyName(keyPair.getKeyName())// key
.asType(ec2Template.getSize().getInstanceType())// instance size
.asType(ec2Size.getInstanceType())// instance size
.withSecurityGroup(securityGroupName)// group I created above
.withAdditionalInfo(name);
@ -129,36 +131,24 @@ public class EC2ComputeService implements ComputeService {
instanceOptions.withUserData(options.getRunScript());
RunningInstance runningInstance = Iterables.getOnlyElement(ec2Client.getInstanceServices()
.runInstancesInRegion(ec2Template.getRegion(), null, ec2Template.getImage().getId(),
1, 1, instanceOptions));
.runInstancesInRegion(region, null, ec2Image.getId(), 1, 1, instanceOptions));
logger.debug("<< started instance(%s)", runningInstance.getId());
instanceStateRunning.apply(runningInstance);
logger.debug("<< running instance(%s)", runningInstance.getId());
// refresh to get IP address
runningInstance = getOnlyRunningInstanceInRegion(ec2Template.getRegion(), runningInstance
.getId());
runningInstance = getOnlyRunningInstanceInRegion(region, runningInstance.getId());
Set<InetAddress> publicAddresses = runningInstance.getIpAddress() == null ? ImmutableSet
.<InetAddress> of() : ImmutableSet.<InetAddress> of(runningInstance.getIpAddress());
Set<InetAddress> privateAddresses = runningInstance.getPrivateIpAddress() == null ? ImmutableSet
.<InetAddress> of()
: ImmutableSet.<InetAddress> of(runningInstance.getPrivateIpAddress());
return new CreateNodeResponseImpl(
runningInstance.getId(),
name,
runningInstance.getRegion().toString(),
null,
ImmutableMap.<String, String> of(),
instanceToNodeState.get(runningInstance.getInstanceState()),
publicAddresses,
privateAddresses,
22,
return new CreateNodeResponseImpl(runningInstance.getId(), name, runningInstance.getRegion()
.toString(), null, ImmutableMap.<String, String> of(), instanceToNodeState
.get(runningInstance.getInstanceState()), publicAddresses, privateAddresses, 22,
LoginType.SSH,
new Credentials(
ec2Template.getImage().getOperatingSystem() == OperatingSystem.UBUNTU ? "ubuntu"
: "root", keyPair.getKeyMaterial()), ImmutableMap
.<String, String> of());
new Credentials("root", keyPair.getKeyMaterial()), ImmutableMap.<String, String> of());
}
private KeyPair createKeyPairInRegion(Region region, String name) {
@ -316,17 +306,18 @@ public class EC2ComputeService implements ComputeService {
}
@Override
public SortedSet<EC2Size> listSizes() {
return sizes;
public Set<? extends Size> listSizes() {
return sizes.get();
}
@Override
public Set<EC2Template> listTemplates() {
return templates.get();
public Set<? extends Image> listImages() {
return images.get();
}
@Override
public Template createTemplateInLocation(String location) {
return new EC2Template(ec2Client, imageAmiIdMap, location);
public TemplateBuilder templateBuilder() {
return templateBuilderProvider.get();
}
}

View File

@ -0,0 +1,139 @@
/**
*
* Copyright (C) 2009 Global Cloud Specialists, Inc. <info@globalcloudspecialists.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
*
* 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.jclouds.compute.domain.Architecture;
import org.jclouds.compute.domain.Image;
import org.jclouds.compute.domain.OperatingSystem;
/**
*
* @author Adrian Cole
*/
public class EC2Image implements Image {
private final org.jclouds.aws.ec2.domain.Image image;
private final OperatingSystem os;
private final String osVersion;
private final String version;
public EC2Image(org.jclouds.aws.ec2.domain.Image image, OperatingSystem os, String osVersion,
String version) {
this.image = image;
this.os = os;
this.osVersion = osVersion;
this.version = version;
}
@Override
public Architecture getArchitecture() {
return getImage().getArchitecture() == org.jclouds.aws.ec2.domain.Image.Architecture.I386 ? Architecture.X86_32
: Architecture.X86_64;
}
@Override
public String getDescription() {
return getImage().getDescription();
}
@Override
public String getId() {
return getImage().getId();
}
@Override
public String getLocation() {
return getImage().getRegion().toString();
}
@Override
public OperatingSystem getOperatingSystem() {
return os;
}
@Override
public String getOperatingSystemVersion() {
return osVersion;
}
@Override
public String getVersion() {
return version;
}
public org.jclouds.aws.ec2.domain.Image getImage() {
return image;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((image == null) ? 0 : image.hashCode());
result = prime * result + ((os == null) ? 0 : os.hashCode());
result = prime * result + ((osVersion == null) ? 0 : osVersion.hashCode());
result = prime * result + ((version == null) ? 0 : version.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;
EC2Image other = (EC2Image) obj;
if (image == null) {
if (other.image != null)
return false;
} else if (!image.equals(other.image))
return false;
if (os == null) {
if (other.os != null)
return false;
} else if (!os.equals(other.os))
return false;
if (osVersion == null) {
if (other.osVersion != null)
return false;
} else if (!osVersion.equals(other.osVersion))
return false;
if (version == null) {
if (other.version != null)
return false;
} else if (!version.equals(other.version))
return false;
return true;
}
@Override
public String toString() {
return "[id=" + getId() + ", version=" + version + ", location=" + getLocation()
+ ", architecture=" + getArchitecture() + ", operatingSystem="
+ getOperatingSystem() + ", operatingSystemVersion=" + getOperatingSystemVersion()
+ ", description=" + getDescription() + "]";
}
}

View File

@ -38,7 +38,7 @@ public class EC2Size extends SizeImpl {
EC2Size(InstanceType instanceType, Integer cores, Integer ram, Integer disk,
Iterable<Architecture> supportedArchitectures) {
super(cores, ram, disk, supportedArchitectures);
super(instanceType.toString(), cores, ram, disk, supportedArchitectures);
this.instanceType = instanceType;
}
@ -85,4 +85,29 @@ public class EC2Size extends SizeImpl {
public static final EC2Size C1_XLARGE = new EC2Size(InstanceType.C1_XLARGE, 20, 7168, 1690,
ImmutableSet.of(Architecture.X86_64));
@Override
public int hashCode() {
final int prime = 31;
int result = super.hashCode();
result = prime * result + ((instanceType == null) ? 0 : instanceType.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (!super.equals(obj))
return false;
if (getClass() != obj.getClass())
return false;
EC2Size other = (EC2Size) obj;
if (instanceType == null) {
if (other.instanceType != null)
return false;
} else if (!instanceType.equals(other.instanceType))
return false;
return true;
}
}

View File

@ -1,233 +0,0 @@
/**
*
* Copyright (C) 2009 Global Cloud Specialists, Inc. <info@globalcloudspecialists.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
*
* 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.util.Map;
import javax.annotation.Nullable;
import org.jclouds.aws.domain.Region;
import org.jclouds.aws.ec2.EC2Client;
import org.jclouds.aws.ec2.util.EC2Utils;
import org.jclouds.compute.domain.Architecture;
import org.jclouds.compute.domain.Image;
import org.jclouds.compute.domain.OperatingSystem;
import org.jclouds.compute.domain.Template;
import com.google.common.annotations.VisibleForTesting;
/**
*
* @author Adrian Cole
*/
public class EC2Template implements Template {
private final EC2Client client;
private final Map<Architecture, Map<OperatingSystem, Map<Region, String>>> imageAmiIdMap;
private EC2Size size;
private OperatingSystem operatingSystem;
private Region region;
private transient Image image;
public EC2Template(EC2Client client,
Map<Architecture, Map<OperatingSystem, Map<Region, String>>> imageAmiIdMap,
EC2Size size, OperatingSystem operatingSystem, Region region, @Nullable Image image) {
this.client = client;
this.size = size;
this.operatingSystem = operatingSystem;
this.region = region;
this.imageAmiIdMap = imageAmiIdMap;
this.image = image != null ? image : resolveImage();
}
EC2Template(EC2Client client,
Map<Architecture, Map<OperatingSystem, Map<Region, String>>> imageAmiIdMap,
String location) {
this(client, imageAmiIdMap, EC2Size.M1_SMALL, OperatingSystem.UBUNTU, Region
.fromValue(location), null);
}
/**
* {@inheritDoc}
*/
@Override
public EC2Size getSize() {
return size;
}
/**
* {@inheritDoc}
*/
@Override
public Image getImage() {
return image;
}
@VisibleForTesting
Image resolveImage() {
Architecture architecture = size.supportsArchitecture(Architecture.X86_64) ? Architecture.X86_64
: Architecture.X86_32;
String ami = checkNotNull(
checkNotNull(
checkNotNull(
imageAmiIdMap.get(architecture),
String.format(
"architecture %s not supported. Valid choices %s: ",
architecture, imageAmiIdMap.keySet())).get(
operatingSystem),
String
.format(
"operatingSystem %s not supported for architecture %s. Valid choices %s: ",
operatingSystem, architecture, imageAmiIdMap.get(
architecture).keySet())).get(region),
String
.format(
"region %s not supported for operatingSystem %s, architecture %s. Valid choices %s: ",
region, operatingSystem, architecture, imageAmiIdMap.get(
architecture).get(operatingSystem).keySet()));
return EC2Utils.newImage(client, region, operatingSystem, architecture, ami);
}
public Template asSize(EC2Size size) {
this.size = size;
this.image = resolveImage();
return this;
}
/**
* {@inheritDoc}
*/
@Override
public Template smallest() {
return asSize(EC2Size.M1_SMALL);
}
/**
* {@inheritDoc}
*/
@Override
public Template biggest() {
return asSize(EC2Size.M2_4XLARGE);
}
/**
* {@inheritDoc}
*/
@Override
public Template fastest() {
return asSize(EC2Size.C1_XLARGE);
}
/**
* {@inheritDoc}
*/
@Override
public Template inLocation(String location) {
this.region = Region.fromValue(location);
this.image = resolveImage();
return this;
}
/**
* {@inheritDoc}
*/
@Override
public Template os(OperatingSystem os) {
this.operatingSystem = os;
this.image = resolveImage();
return this;
}
/**
* {@inheritDoc}
*/
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((image == null) ? 0 : image.hashCode());
result = prime * result + ((operatingSystem == null) ? 0 : operatingSystem.hashCode());
result = prime * result + ((region == null) ? 0 : region.hashCode());
result = prime * result + ((size == null) ? 0 : size.hashCode());
return result;
}
/**
* {@inheritDoc}
*/
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
EC2Template other = (EC2Template) obj;
if (image == null) {
if (other.image != null)
return false;
} else if (!image.equals(other.image))
return false;
if (operatingSystem == null) {
if (other.operatingSystem != null)
return false;
} else if (!operatingSystem.equals(other.operatingSystem))
return false;
if (region == null) {
if (other.region != null)
return false;
} else if (!region.equals(other.region))
return false;
if (size == null) {
if (other.size != null)
return false;
} else if (!size.equals(other.size))
return false;
return true;
}
/**
* {@inheritDoc}
*/
@Override
public String toString() {
return "EC2Template [image=" + image + ", operatingSystem=" + operatingSystem + ", region="
+ region + ", size=" + size + "]";
}
/**
* {@inheritDoc}
*/
@Override
protected Object clone() throws CloneNotSupportedException {
return new EC2Template(client, imageAmiIdMap, size, operatingSystem, region, image);
}
public Region getRegion() {
return region;
}
}

View File

@ -18,33 +18,40 @@
*/
package org.jclouds.aws.ec2.compute.config;
import static org.jclouds.aws.ec2.options.DescribeImagesOptions.Builder.ownedBy;
import java.net.URI;
import java.util.Map;
import java.util.Set;
import java.util.SortedSet;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeoutException;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.annotation.Resource;
import javax.inject.Named;
import javax.inject.Singleton;
import org.jclouds.aws.domain.Region;
import org.jclouds.aws.ec2.EC2;
import org.jclouds.aws.ec2.EC2AsyncClient;
import org.jclouds.aws.ec2.EC2Client;
import org.jclouds.aws.ec2.compute.EC2ComputeService;
import org.jclouds.aws.ec2.compute.EC2Image;
import org.jclouds.aws.ec2.compute.EC2Size;
import org.jclouds.aws.ec2.compute.EC2Template;
import org.jclouds.aws.ec2.config.EC2ContextModule;
import org.jclouds.aws.ec2.util.EC2Utils;
import org.jclouds.compute.ComputeService;
import org.jclouds.compute.ComputeServiceContext;
import org.jclouds.compute.domain.Architecture;
import org.jclouds.compute.domain.Image;
import org.jclouds.compute.domain.OperatingSystem;
import org.jclouds.compute.domain.Size;
import org.jclouds.compute.internal.ComputeServiceContextImpl;
import org.jclouds.compute.reference.ComputeServiceConstants;
import org.jclouds.domain.ResourceLocation;
import org.jclouds.logging.Logger;
import org.jclouds.rest.RestContext;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSortedSet;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Sets;
import com.google.inject.Provides;
@ -70,61 +77,55 @@ public class EC2ComputeServiceContextModule extends EC2ContextModule {
@Provides
@Singleton
SortedSet<EC2Size> provideSizes() {
return ImmutableSortedSet.of(EC2Size.C1_MEDIUM, EC2Size.C1_XLARGE, EC2Size.M1_LARGE,
Set<? extends Size> provideSizes() {
return ImmutableSet.of(EC2Size.C1_MEDIUM, EC2Size.C1_XLARGE, EC2Size.M1_LARGE,
EC2Size.M1_SMALL, EC2Size.M1_XLARGE, EC2Size.M2_2XLARGE, EC2Size.M2_4XLARGE);
}
@Provides
@Singleton
@ResourceLocation
String getRegion(@EC2 Region region) {
return region.value();
}
private static class LogHolder {
@Resource
@Named(ComputeServiceConstants.COMPUTE_LOGGER)
protected Logger logger = Logger.NULL;
}
@Provides
@Singleton
Set<EC2Template> provideTemplates(EC2Client client, SortedSet<EC2Size> sizes,
Map<Architecture, Map<OperatingSystem, Map<Region, String>>> imageAmiIdMap,
LogHolder holder) {
Set<EC2Template> templates = Sets.newHashSet();
holder.logger.debug(">> generating templates");
for (EC2Size size : sizes) {
for (Architecture architecture : imageAmiIdMap.keySet()) {
if (size.supportsArchitecture(architecture)) {
for (OperatingSystem operatingSystem : imageAmiIdMap.get(architecture).keySet()) {
for (Region region : imageAmiIdMap.get(architecture).get(operatingSystem)
.keySet()) {
String ami = imageAmiIdMap.get(architecture).get(operatingSystem).get(region);
templates.add(new EC2Template(client, imageAmiIdMap, size, operatingSystem,
region, EC2Utils.newImage(client, region, operatingSystem,
architecture, ami)));
}
}
}
}
}
holder.logger.debug("<< templates(%d)", templates.size());
return templates;
}
// alestic-32-eu-west-1/debian-4.0-etch-base-20081130.manifest.xml
public static final Pattern ALESTIC_PATTERN = Pattern
.compile(".*/([^-]*)-([^-]*)-.*-(.*)\\.manifest\\.xml");
@Provides
@Singleton
Map<Architecture, Map<OperatingSystem, Map<Region, String>>> provideimageAmiIdMap() {
return ImmutableMap.<Architecture, Map<OperatingSystem, Map<Region, String>>> of(
Architecture.X86_32,//
ImmutableMap.<OperatingSystem, Map<Region, String>> builder().put(
OperatingSystem.UBUNTU,
ImmutableMap.of(Region.DEFAULT, "ami-1515f67c", Region.US_EAST_1,
"ami-1515f67c", Region.US_WEST_1, "ami-7d3c6d38",
Region.EU_WEST_1, "ami-a62a01d2")).put(
OperatingSystem.RHEL,
ImmutableMap.of(Region.DEFAULT, "ami-368b685f", Region.US_EAST_1,
"ami-368b685f")).build(),//
Architecture.X86_64,//
ImmutableMap.<OperatingSystem, Map<Region, String>> builder().put(
OperatingSystem.UBUNTU,
ImmutableMap.of(Region.DEFAULT, "ami-ab15f6c2", Region.US_EAST_1,
"ami-ab15f6c2", Region.US_WEST_1, "ami-7b3c6d3e",
Region.EU_WEST_1, "ami-9a2a01ee")).build());// todo ami
protected Set<? extends Image> provideImages(final EC2Client sync, Map<Region, URI> regionMap,
LogHolder holder) throws InterruptedException, ExecutionException, TimeoutException {
final Set<Image> images = Sets.newHashSet();
holder.logger.debug(">> providing images");
for (final Region region : regionMap.keySet()) {
for (final org.jclouds.aws.ec2.domain.Image from : sync.getAMIServices()
.describeImagesInRegion(region, ownedBy("063491364108"))) {
OperatingSystem os = null;
String osVersion = "";
String version = "";
Matcher matcher = ALESTIC_PATTERN.matcher(from.getImageLocation());
if (matcher.find()) {
try {
os = OperatingSystem.fromValue(matcher.group(1));
osVersion = matcher.group(2);
version = matcher.group(3);
} catch (IllegalArgumentException e) {
holder.logger.debug("<< didn't match os(%s)", matcher.group(1));
}
}
images.add(new EC2Image(from, os, osVersion, version));
}
}
holder.logger.debug("<< images(%d)", images.size());
return images;
}
}

View File

@ -68,6 +68,7 @@ import org.jclouds.rest.ConfiguresRestClient;
import org.jclouds.rest.RestClientFactory;
import com.google.common.base.Predicate;
import com.google.common.collect.ImmutableBiMap;
import com.google.common.collect.Maps;
import com.google.inject.AbstractModule;
import com.google.inject.Provides;
@ -92,6 +93,16 @@ public class EC2RestClientModule extends AbstractModule {
bindRetryHandlers();
}
@Provides
@Singleton
@EC2
Region provideCurrentRegion(Map<Region, URI> regionMap, @EC2 URI currentUri) {
ImmutableBiMap<URI, Region> map = ImmutableBiMap.copyOf(regionMap).inverse();
Region region = map.get(currentUri);
assert region != null : currentUri + " not in " + map;
return region;
}
@Provides
@Singleton
Map<Region, URI> provideRegions(AvailabilityZoneAndRegionClient client) {

View File

@ -41,7 +41,7 @@ import org.jclouds.concurrent.Timeout;
*
* @author Adrian Cole
*/
@Timeout(duration = 30, timeUnit = TimeUnit.SECONDS)
@Timeout(duration = 45, timeUnit = TimeUnit.SECONDS)
public interface InstanceClient {
/**

View File

@ -20,30 +20,16 @@ package org.jclouds.aws.ec2.util;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import static org.jclouds.aws.ec2.options.DescribeImagesOptions.Builder.imageIds;
import org.jclouds.aws.domain.Region;
import org.jclouds.aws.ec2.EC2Client;
import org.jclouds.aws.ec2.domain.AvailabilityZone;
import org.jclouds.compute.domain.Architecture;
import org.jclouds.compute.domain.Image;
import org.jclouds.compute.domain.OperatingSystem;
import org.jclouds.compute.domain.internal.ImageImpl;
import org.jclouds.rest.internal.GeneratedHttpRequest;
import com.google.inject.internal.Iterables;
/**
*
* @author Adrian Cole
*/
public class EC2Utils {
public static Image newImage(EC2Client client, Region region, OperatingSystem os,
Architecture architecture, String ami) {
org.jclouds.aws.ec2.domain.Image image = Iterables.getOnlyElement(client.getAMIServices()
.describeImagesInRegion(region, imageIds(ami)));
return new ImageImpl(ami, image.getDescription(), os, null, region.toString(), architecture);
}
public static void indexStringArrayToFormValuesWithPrefix(GeneratedHttpRequest<?> request,
String prefix, Object input) {

View File

@ -46,7 +46,6 @@ public class QueueHandler extends ParseSax.HandlerWithResult<Queue> {
@Inject
QueueHandler(Map<Region, URI> regionMap) {
this.regionBiMap = ImmutableBiMap.copyOf(regionMap);
}
public Queue getResult() {

View File

@ -49,7 +49,7 @@ public class EC2ContextBuilderTest {
public void testNewBuilder() {
EC2ContextBuilder builder = newBuilder();
assertEquals(builder.getProperties().getProperty(EC2Constants.PROPERTY_EC2_ENDPOINT),
"https://ec2.amazonaws.com");
"https://ec2.us-east-1.amazonaws.com");
assertEquals(builder.getProperties().getProperty(PROPERTY_AWS_ACCESSKEYID), "id");
assertEquals(builder.getProperties().getProperty(PROPERTY_AWS_SECRETACCESSKEY), "secret");
}
@ -58,7 +58,7 @@ public class EC2ContextBuilderTest {
RestContext<EC2AsyncClient, EC2Client> context = newBuilder().buildContext();
assertEquals(context.getClass(), RestContextImpl.class);
assertEquals(context.getAccount(), "id");
assertEquals(context.getEndPoint(), URI.create("https://ec2.amazonaws.com"));
assertEquals(context.getEndPoint(), URI.create("https://ec2.us-east-1.amazonaws.com"));
}
public void testBuildInjector() {

View File

@ -21,6 +21,8 @@ package org.jclouds.aws.ec2.compute;
import static org.jclouds.compute.domain.OperatingSystem.UBUNTU;
import org.jclouds.compute.BaseComputeServiceLiveTest;
import org.jclouds.compute.domain.Template;
import org.jclouds.compute.domain.TemplateBuilder;
import org.jclouds.ssh.jsch.config.JschSshClientModule;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
@ -37,7 +39,10 @@ public class EC2ComputeServiceLiveTest extends BaseComputeServiceLiveTest {
@Override
public void setServiceDefaults() {
service = "ec2";
testOS = UBUNTU;
}
protected Template buildTemplate(TemplateBuilder templateBuilder) {
return templateBuilder.os(UBUNTU).smallest().build();
}
@Override

View File

@ -19,13 +19,14 @@
package org.jclouds.compute;
import java.util.Set;
import java.util.SortedSet;
import org.jclouds.compute.domain.ComputeMetadata;
import org.jclouds.compute.domain.CreateNodeResponse;
import org.jclouds.compute.domain.Image;
import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.domain.Size;
import org.jclouds.compute.domain.Template;
import org.jclouds.compute.domain.TemplateBuilder;
import org.jclouds.compute.options.RunNodeOptions;
/**
@ -36,27 +37,19 @@ import org.jclouds.compute.options.RunNodeOptions;
*/
public interface ComputeService {
/**
* Creates a new template in the specified location.
*
* @param location
* where the template is valid for
* Makes a new template builder for this service
*/
Template createTemplateInLocation(String location);
TemplateBuilder templateBuilder();
/**
* List all sizes available to the current user
*/
SortedSet<? extends Size> listSizes();
Set<? extends Size> listSizes();
/**
* List all images available to the current user
*/
// Set<? extends Image> listImages();
/**
* List all templates available to the current user
*/
Set<? extends Template> listTemplates();
Set<? extends Image> listImages();
/**
* List all nodes available to the current user
@ -68,6 +61,7 @@ public interface ComputeService {
*
*/
CreateNodeResponse runNode(String name, Template template);
CreateNodeResponse runNode(String name, Template template, RunNodeOptions options);
/**

View File

@ -46,6 +46,11 @@ public interface Image {
*/
OperatingSystem getOperatingSystem();
/**
* Version of the operating system
*/
String getOperatingSystemVersion();
/**
* Version of the image
*/

View File

@ -23,11 +23,28 @@
*/
package org.jclouds.compute.domain;
import static com.google.common.base.Preconditions.checkNotNull;
import com.google.common.base.CaseFormat;
/**
* Running Operating system
*
* @author Adrian Cole
*/
public enum OperatingSystem {
CENTOS, RHEL, UBUNTU, JEOS, WINDOWS, UNKNOWN;
CENTOS, RHEL, FEDORA, DEBIAN, UBUNTU, JEOS, WINDOWS;
public String value() {
return CaseFormat.UPPER_UNDERSCORE.to(CaseFormat.LOWER_HYPHEN, name());
}
@Override
public String toString() {
return value();
}
public static OperatingSystem fromValue(String operatingSystem) {
return valueOf(CaseFormat.LOWER_HYPHEN.to(CaseFormat.UPPER_UNDERSCORE, checkNotNull(
operatingSystem, "region")));
}
}

View File

@ -23,13 +23,23 @@
*/
package org.jclouds.compute.domain;
import org.jclouds.compute.domain.internal.SizeImpl;
import com.google.inject.ImplementedBy;
/**
* Size of a node.
*
* @author Adrian Cole
*/
@ImplementedBy(SizeImpl.class)
public interface Size extends Comparable<Size> {
/**
* unique identifier of this configuration.
*/
String getId();
/**
* Amount of virtual or physical cores provided
*/

View File

@ -24,32 +24,6 @@ package org.jclouds.compute.domain;
* @author Adrian Cole
*/
public interface Template extends Cloneable {
/**
* configure this template to the smallest size.
*/
Template smallest();
/**
* configure this template to the fastest size.
*/
Template fastest();
/**
* configure this template to the largest size.
*/
Template biggest();
/**
* Configure this template to use a specific operating system image.
*/
Template os(OperatingSystem os);
/**
* Configure this template to start in a specific location
*/
Template inLocation(String location);
/**
* Image that suits the requirements.
*

View File

@ -0,0 +1,124 @@
/**
*
* Copyright (C) 2009 Global Cloud Specialists, Inc. <info@globalcloudspecialists.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
*
* 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.compute.domain;
import org.jclouds.compute.internal.TemplateBuilderImpl;
import com.google.inject.ImplementedBy;
/**
* Creates a customized template based on requirements.
*
* @author Adrian Cole
*/
@ImplementedBy(TemplateBuilderImpl.class)
public interface TemplateBuilder {
/**
* Configure this template to require the minimum size of the parameter.
*/
TemplateBuilder fromSize(Size size);
/**
* Configure this template to fuzzy-match on the image parameter
*/
TemplateBuilder fromImage(Image image);
/**
* Configure this template to match the resources of the template parameter.
*/
TemplateBuilder fromTemplate(Template image);
/**
* configure this template to the smallest size.
*/
TemplateBuilder smallest();
/**
* configure this template to the fastest size.
*/
TemplateBuilder fastest();
/**
* configure this template to the largest size.
*/
TemplateBuilder biggest();
/**
* Configure this template to use a specific operating system image.
*/
TemplateBuilder os(OperatingSystem os);
/**
* Configure this template to start in a specific location
*/
TemplateBuilder location(String location);
/**
* Configure this template to require a specific architecture
*/
TemplateBuilder architecture(Architecture architecture);
/**
* Configure this template to require a specific imageId.
* <p/>
* Note that image Ids are often scoped to {@code location}
*/
TemplateBuilder imageId(String imageId);
/**
* Configure this template to require a specific sizeId.
*/
TemplateBuilder sizeId(String sizeId);
/**
* Configure this template to have an operating system version that matches the regular
* expression
*/
TemplateBuilder osVersionMatches(String osVersionRegex);
/**
* Configure this template to have an image version that matches the regular expression
*/
TemplateBuilder imageVersionMatches(String imageVersionRegex);
/**
* Configure this template to have a description that matches the regular expression
*/
TemplateBuilder imageDescriptionMatches(String descriptionRegex);
/**
* Configure this template to require the minimum cores below
*/
TemplateBuilder minCores(int minCores);
/**
* Configure this template to require the minimum ram in megabytes below
*/
TemplateBuilder minRam(int megabytes);
/**
* Generate an immutable template from the current builder.
*/
Template build();
}

View File

@ -34,21 +34,12 @@ public class ImageImpl implements Image {
private final String id;
private final String description;
private final OperatingSystem operatingSystem;
private final String version;
private final OperatingSystem operatingSystem;
private final String operatingSystemVersion;
private final String location;
private final Architecture architecture;
public ImageImpl(String id, String description, OperatingSystem operatingSystem, String version,
String location, Architecture architecture) {
this.id = id;
this.description = description;
this.operatingSystem = operatingSystem;
this.version = version;
this.location = location;
this.architecture = architecture;
}
/**
* {@inheritDoc}
*/
@ -65,6 +56,17 @@ public class ImageImpl implements Image {
return result;
}
public ImageImpl(String id, String description, String version, OperatingSystem operatingSystem,
String operatingSystemVersion, String location, Architecture architecture) {
this.id = id;
this.description = description;
this.version = version;
this.operatingSystem = operatingSystem;
this.operatingSystemVersion = operatingSystemVersion;
this.location = location;
this.architecture = architecture;
}
/**
* {@inheritDoc}
*/
@ -110,14 +112,12 @@ public class ImageImpl implements Image {
return true;
}
/**
* {@inheritDoc}
*/
@Override
public String toString() {
return "ImageImpl [architecture=" + architecture + ", description=" + description + ", id="
+ id + ", location=" + location + ", operatingSystem=" + operatingSystem
+ ", version=" + version + "]";
return "[id=" + id + ", version=" + version + ", location=" + location + ", architecture="
+ architecture + ", operatingSystem=" + operatingSystem
+ ", operatingSystemVersion=" + operatingSystemVersion + ", description="
+ description + "]";
}
/**
@ -168,4 +168,12 @@ public class ImageImpl implements Image {
return architecture;
}
/**
* {@inheritDoc}
*/
@Override
public String getOperatingSystemVersion() {
return operatingSystemVersion;
}
}

View File

@ -31,13 +31,15 @@ import com.google.common.collect.Sets;
* @author Adrian Cole
*/
public class SizeImpl implements Size {
private String id;
private final int cores;
private final int ram;
private final int disk;
private final Set<Architecture> supportedArchitectures = Sets.newHashSet();
public SizeImpl(int cores, int ram, int disk, Iterable<Architecture> supportedArchitectures) {
public SizeImpl(String id, int cores, int ram, int disk,
Iterable<Architecture> supportedArchitectures) {
this.id = id;
this.cores = cores;
this.ram = ram;
this.disk = disk;
@ -74,6 +76,7 @@ public class SizeImpl implements Size {
int result = 1;
result = prime * result + cores;
result = prime * result + disk;
result = prime * result + ((id == null) ? 0 : id.hashCode());
result = prime * result + ram;
result = prime * result
+ ((supportedArchitectures == null) ? 0 : supportedArchitectures.hashCode());
@ -93,6 +96,11 @@ public class SizeImpl implements Size {
return false;
if (disk != other.disk)
return false;
if (id == null) {
if (other.id != null)
return false;
} else if (!id.equals(other.id))
return false;
if (ram != other.ram)
return false;
if (supportedArchitectures == null) {
@ -108,12 +116,10 @@ public class SizeImpl implements Size {
this.getRam(), that.getRam()).compare(this.getDisk(), that.getDisk()).result();
}
/**
* {@inheritDoc}
*/
@Override
public String toString() {
return "Size [cores=" + cores + ", disk=" + disk + ", ram=" + ram + "]";
return "[id=" + id + ", cores=" + cores + ", ram=" + ram + ", disk=" + disk
+ ", supportedArchitectures=" + supportedArchitectures + "]";
}
/**
@ -123,4 +129,12 @@ public class SizeImpl implements Size {
public boolean supportsArchitecture(Architecture architecture) {
return supportedArchitectures.contains(architecture);
}
/**
* {@inheritDoc}
*/
@Override
public String getId() {
return id;
}
}

View File

@ -0,0 +1,103 @@
/**
*
* Copyright (C) 2009 Global Cloud Specialists, Inc. <info@globalcloudspecialists.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
*
* 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.compute.domain.internal;
import org.jclouds.compute.domain.Image;
import org.jclouds.compute.domain.Size;
import org.jclouds.compute.domain.Template;
/**
*
* @author Adrian Cole
*/
public class TemplateImpl implements Template {
private final Image image;
private final Size size;
protected TemplateImpl(Image image, Size size) {
this.image = image;
this.size = size;
}
/**
* {@inheritDoc}
*/
@Override
public Image getImage() {
return image;
}
/**
* {@inheritDoc}
*/
@Override
public Size getSize() {
return size;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((image == null) ? 0 : image.hashCode());
result = prime * result + ((size == null) ? 0 : size.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;
TemplateImpl other = (TemplateImpl) obj;
if (image == null) {
if (other.image != null)
return false;
} else if (!image.equals(other.image))
return false;
if (size == null) {
if (other.size != null)
return false;
} else if (!size.equals(other.size))
return false;
return true;
}
@Override
public String toString() {
return "TemplateImpl [image=" + image + ", size=" + size + "]";
}
/**
* {@inheritDoc}
*/
@Override
protected Object clone() throws CloneNotSupportedException {
return new TemplateImpl(image, size);
}
}

View File

@ -0,0 +1,413 @@
package org.jclouds.compute.internal;
import java.util.NoSuchElementException;
import java.util.Set;
import javax.annotation.Resource;
import javax.inject.Inject;
import javax.inject.Named;
import org.jclouds.compute.domain.Architecture;
import org.jclouds.compute.domain.Image;
import org.jclouds.compute.domain.OperatingSystem;
import org.jclouds.compute.domain.Size;
import org.jclouds.compute.domain.Template;
import org.jclouds.compute.domain.TemplateBuilder;
import org.jclouds.compute.domain.internal.TemplateImpl;
import org.jclouds.compute.reference.ComputeServiceConstants;
import org.jclouds.domain.ResourceLocation;
import org.jclouds.logging.Logger;
import com.google.common.base.Predicate;
import com.google.common.base.Predicates;
import com.google.common.collect.ComparisonChain;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterables;
import com.google.common.collect.Ordering;
import com.google.common.primitives.Ints;
/**
*
* @author Adrian Cole
*/
@SuppressWarnings("unchecked")
public class TemplateBuilderImpl implements TemplateBuilder {
@Resource
@Named(ComputeServiceConstants.COMPUTE_LOGGER)
protected Logger logger = Logger.NULL;
private final Set<? extends Image> images;
private final Set<? extends Size> sizes;
private String location;
private OperatingSystem os;
private Architecture arch;
private String imageId;
private String sizeId;
private String osVersion;
private String imageVersion;
private String imageDescription;
private int minCores;
private int minRam;
private boolean biggest;
private boolean fastest;
@Inject
public TemplateBuilderImpl(@ResourceLocation String location, Set<? extends Image> images,
Set<? extends Size> sizes) {
this.location = location;
this.images = images;
this.sizes = sizes;
}
private final Predicate<Image> imageIdPredicate = new Predicate<Image>() {
@Override
public boolean apply(Image input) {
boolean returnVal = true;
if (imageId != null) {
returnVal = imageId.equals(input.getId());
// match our input params so that the later predicates pass.
if (returnVal) {
fromImage(input);
}
}
return returnVal;
}
};
private final Predicate<Image> locationPredicate = new Predicate<Image>() {
@Override
public boolean apply(Image input) {
boolean returnVal = true;
if (location != null)
returnVal = location.equals(input.getLocation());
return returnVal;
}
};
private final Predicate<Image> osPredicate = new Predicate<Image>() {
@Override
public boolean apply(Image input) {
boolean returnVal = true;
if (os != null)
returnVal = os.equals(input.getOperatingSystem());
return returnVal;
}
};
private final Predicate<Image> imageArchPredicate = new Predicate<Image>() {
@Override
public boolean apply(Image input) {
boolean returnVal = true;
if (arch != null)
returnVal = arch.equals(input.getArchitecture());
return returnVal;
}
};
private final Predicate<Image> osVersionPredicate = new Predicate<Image>() {
@Override
public boolean apply(Image input) {
boolean returnVal = true;
if (osVersion != null) {
if (input.getOperatingSystemVersion() == null)
returnVal = false;
else
returnVal = input.getOperatingSystemVersion().matches(osVersion);
}
return returnVal;
}
};
private final Predicate<Image> imageVersionPredicate = new Predicate<Image>() {
@Override
public boolean apply(Image input) {
boolean returnVal = true;
if (imageVersion != null) {
if (input.getVersion() == null)
returnVal = false;
else
returnVal = input.getVersion().matches(imageVersion);
}
return returnVal;
}
};
private final Predicate<Image> imageDescriptionPredicate = new Predicate<Image>() {
@Override
public boolean apply(Image input) {
boolean returnVal = true;
if (imageDescription != null) {
if (input.getDescription() == null)
returnVal = false;
else
returnVal = input.getDescription().matches(imageDescription);
}
return returnVal;
}
};
private final Predicate<Size> sizeIdPredicate = new Predicate<Size>() {
@Override
public boolean apply(Size input) {
boolean returnVal = true;
if (sizeId != null) {
returnVal = sizeId.equals(input.getId());
// match our input params so that the later predicates pass.
if (returnVal) {
fromSize(input);
}
}
return returnVal;
}
};
private final Predicate<Image> imagePredicate = Predicates.and(imageIdPredicate,
locationPredicate, osPredicate, imageArchPredicate, osVersionPredicate,
imageVersionPredicate, imageDescriptionPredicate);
private final Predicate<Size> sizeArchPredicate = new Predicate<Size>() {
@Override
public boolean apply(Size input) {
boolean returnVal = false;
if (arch != null)
returnVal = input.supportsArchitecture(arch);
return returnVal;
}
};
private final Predicate<Size> sizeCoresPredicate = new Predicate<Size>() {
@Override
public boolean apply(Size input) {
return input.getCores() >= TemplateBuilderImpl.this.minCores;
}
};
private final Predicate<Size> sizeRamPredicate = new Predicate<Size>() {
@Override
public boolean apply(Size input) {
return input.getRam() >= TemplateBuilderImpl.this.minRam;
}
};
private final Predicate<Size> sizePredicate = Predicates.and(sizeIdPredicate, sizeArchPredicate,
sizeCoresPredicate, sizeRamPredicate);
static final Ordering<Size> DEFAULT_SIZE_ORDERING = new Ordering<Size>() {
public int compare(Size left, Size right) {
return ComparisonChain.start().compare(left.getCores(), right.getCores()).compare(
left.getRam(), right.getRam()).compare(left.getDisk(), right.getDisk()).result();
}
};
static final Ordering<Size> BY_CORES_ORDERING = new Ordering<Size>() {
public int compare(Size left, Size right) {
return Ints.compare(left.getCores(), right.getCores());
}
};
static final Ordering<Image> DEFAULT_IMAGE_ORDERING = new Ordering<Image>() {
public int compare(Image left, Image right) {
return ComparisonChain.start().compare(left.getOperatingSystemVersion(),
right.getOperatingSystemVersion()).compare(left.getVersion(), right.getVersion())
.result();
}
};
/**
* {@inheritDoc}
*/
@Override
public TemplateBuilder fromTemplate(Template template) {
fromSize(template.getSize());
fromImage(template.getImage());
return this;
}
/**
* {@inheritDoc}
*/
@Override
public TemplateBuilder fromSize(Size size) {
this.minCores = size.getCores();
this.minRam = size.getRam();
return this;
}
/**
* {@inheritDoc}
*/
@Override
public TemplateBuilder fromImage(Image image) {
if (image.getLocation() != null)
this.location = image.getLocation();
if (image.getOperatingSystem() != null)
this.os = image.getOperatingSystem();
if (image.getOperatingSystemVersion() != null)
this.osVersion = image.getOperatingSystemVersion();
if (image.getVersion() != null)
this.imageVersion = image.getVersion();
if (image.getArchitecture() != null)
this.arch = image.getArchitecture();
return this;
}
/**
* {@inheritDoc}
*/
@Override
public TemplateBuilder smallest() {
this.biggest = false;
return this;
}
/**
* {@inheritDoc}
*/
@Override
public TemplateBuilder biggest() {
this.biggest = true;
return this;
}
/**
* {@inheritDoc}
*/
@Override
public TemplateBuilder fastest() {
this.fastest = true;
return this;
}
/**
* {@inheritDoc}
*/
@Override
public TemplateBuilder location(String location) {
this.location = location;
return this;
}
/**
* {@inheritDoc}
*/
@Override
public TemplateBuilder os(OperatingSystem os) {
this.os = os;
return this;
}
/**
* {@inheritDoc}
*/
@Override
public TemplateBuilder architecture(Architecture architecture) {
this.arch = architecture;
return this;
}
/**
* {@inheritDoc}
*/
@Override
public Template build() {
logger.debug(">> searching params(%s)", this);
Image image;
try {
image = DEFAULT_IMAGE_ORDERING.max(Iterables.filter(images, imagePredicate));
} catch (NoSuchElementException exception) {
throw new NoSuchElementException("image didn't match: " + toString() + "\n" + images);
}
logger.debug("<< matched image(%s)", image);
// ensure we have an architecture matching
this.arch = image.getArchitecture();
Ordering<Size> sizeOrdering = DEFAULT_SIZE_ORDERING;
if (!biggest)
sizeOrdering = sizeOrdering.reverse();
if (fastest)
sizeOrdering = Ordering.compound(ImmutableList.of(BY_CORES_ORDERING, sizeOrdering));
Size size;
try {
size = sizeOrdering.max(Iterables.filter(sizes, sizePredicate));
} catch (NoSuchElementException exception) {
throw new NoSuchElementException("size didn't match: " + toString() + "\n" + sizes);
}
logger.debug("<< matched size(%s)", size);
return new TemplateImpl(image, size) {
};
}
/**
* {@inheritDoc}
*/
@Override
public TemplateBuilder imageId(String imageId) {
this.imageId = imageId;
return this;
}
/**
* {@inheritDoc}
*/
@Override
public TemplateBuilder imageDescriptionMatches(String descriptionRegex) {
this.imageDescription = descriptionRegex;
return this;
}
/**
* {@inheritDoc}
*/
@Override
public TemplateBuilder imageVersionMatches(String imageVersionRegex) {
this.imageVersion = imageVersionRegex;
return this;
}
/**
* {@inheritDoc}
*/
@Override
public TemplateBuilder minCores(int minCores) {
this.minCores = minCores;
return this;
}
/**
* {@inheritDoc}
*/
@Override
public TemplateBuilder minRam(int megabytes) {
this.minRam = megabytes;
return this;
}
/**
* {@inheritDoc}
*/
@Override
public TemplateBuilder osVersionMatches(String osVersionRegex) {
this.osVersion = osVersionRegex;
return this;
}
/**
* {@inheritDoc}
*/
@Override
public TemplateBuilder sizeId(String sizeId) {
this.sizeId = sizeId;
return this;
}
@Override
public String toString() {
return "[arch=" + arch + ", biggest=" + biggest + ", fastest=" + fastest
+ ", imageDescription=" + imageDescription + ", imageId=" + imageId
+ ", imageVersion=" + imageVersion + ", location=" + location + ", minCores="
+ minCores + ", minRam=" + minRam + ", os=" + os + ", osVersion=" + osVersion
+ ", sizeId=" + sizeId + "]";
}
}

View File

@ -23,4 +23,6 @@ terremark.propertiesbuilder=org.jclouds.vcloud.terremark.TerremarkVCloudProperti
hostingdotcom.contextbuilder=org.jclouds.vcloud.hostingdotcom.compute.HostingDotComVCloudComputeServiceContextBuilder
hostingdotcom.propertiesbuilder=org.jclouds.vcloud.hostingdotcom.HostingDotComVCloudPropertiesBuilder
ec2.contextbuilder=org.jclouds.aws.ec2.compute.EC2ComputeServiceContextBuilder
ec2.propertiesbuilder=org.jclouds.aws.ec2.EC2PropertiesBuilder
ec2.propertiesbuilder=org.jclouds.aws.ec2.EC2PropertiesBuilder
# example of where to change your endpoint
# ec2.endpoint=https://ec2.us-west-1.amazonaws.com

View File

@ -32,11 +32,13 @@ import java.util.concurrent.TimeoutException;
import org.jclouds.compute.domain.ComputeMetadata;
import org.jclouds.compute.domain.ComputeType;
import org.jclouds.compute.domain.CreateNodeResponse;
import org.jclouds.compute.domain.Image;
import org.jclouds.compute.domain.LoginType;
import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.domain.OperatingSystem;
import org.jclouds.compute.domain.Size;
import org.jclouds.compute.domain.Template;
import org.jclouds.compute.domain.TemplateBuilder;
import org.jclouds.compute.options.RunNodeOptions;
import org.jclouds.http.HttpResponseException;
import org.jclouds.logging.log4j.config.Log4JLoggingModule;
@ -70,7 +72,6 @@ public abstract class BaseComputeServiceLiveTest {
abstract public void setServiceDefaults();
protected String service;
protected OperatingSystem testOS;
protected SshClient.Factory sshFactory;
protected RunNodeOptions options = RunNodeOptions.Builder.openPorts(22);
private String nodeName;
@ -81,23 +82,12 @@ public abstract class BaseComputeServiceLiveTest {
protected ComputeService client;
protected String user;
protected String password;
private Template template;
@BeforeGroups(groups = { "live" })
public void setupClient() throws InterruptedException, ExecutionException, TimeoutException,
IOException {
checkNotNull(testOS, "testOS");
nodeName = checkNotNull(service, "service");
if (canRunScript())
options.runScript(new ScriptBuilder()
// update add dns and install jdk
.addStatement(
Statements.exec("echo nameserver 208.67.222.222 >> /etc/resolv.conf"))
.addStatement(Statements.exec("apt-get update"))//
.addStatement(Statements.exec("apt-get upgrade -y"))//
.addStatement(Statements.exec("apt-get install -y openjdk-6-jdk"))//
.addStatement(Statements.exec("wget -qO/usr/bin/runurl run.alestic.com/runurl"))//
.addStatement(Statements.exec("chmod 755 /usr/bin/runurl"))//
.build(OsFamily.UNIX).getBytes());
user = checkNotNull(System.getProperty("jclouds.test.user"), "jclouds.test.user");
password = checkNotNull(System.getProperty("jclouds.test.key"), "jclouds.test.key");
context = new ComputeServiceContextFactory().createContext(service, user, password,
@ -110,12 +100,14 @@ public abstract class BaseComputeServiceLiveTest {
client = context.getComputeService();
}
private boolean canRunScript() {
return testOS == OperatingSystem.UBUNTU || testOS == OperatingSystem.JEOS;
private boolean canRunScript(Template template) {
return template.getImage().getOperatingSystem() == OperatingSystem.UBUNTU
|| template.getImage().getOperatingSystem() == OperatingSystem.JEOS;
}
abstract protected Module getSshModule();
@Test(enabled = false)
public void testCreate() throws Exception {
try {
client.destroyNode(Iterables.find(client.listNodes(), new Predicate<ComputeMetadata>() {
@ -129,7 +121,19 @@ public abstract class BaseComputeServiceLiveTest {
} catch (NoSuchElementException e) {
}
Template template = client.createTemplateInLocation("default").os(testOS).smallest();
template = buildTemplate(client.templateBuilder());
if (canRunScript(template))
options.runScript(new ScriptBuilder()
// update add dns and install jdk
.addStatement(
Statements.exec("echo nameserver 208.67.222.222 >> /etc/resolv.conf"))
.addStatement(Statements.exec("apt-get update"))//
.addStatement(Statements.exec("apt-get upgrade -y"))//
.addStatement(Statements.exec("apt-get install -y openjdk-6-jdk"))//
.addStatement(Statements.exec("wget -qO/usr/bin/runurl run.alestic.com/runurl"))//
.addStatement(Statements.exec("chmod 755 /usr/bin/runurl"))//
.build(OsFamily.UNIX).getBytes());
node = client.runNode(nodeName, template, options);
assertNotNull(node.getId());
assertEquals(node.getLoginPort(), 22);
@ -142,7 +146,9 @@ public abstract class BaseComputeServiceLiveTest {
sshPing();
}
@Test(dependsOnMethods = "testCreate")
protected abstract Template buildTemplate(TemplateBuilder templateBuilder);
@Test(enabled = false, dependsOnMethods = "testCreate")
public void testGet() throws Exception {
NodeMetadata metadata = client.getNodeMetadata(node);
assertEquals(metadata.getId(), node.getId());
@ -153,7 +159,7 @@ public abstract class BaseComputeServiceLiveTest {
assertEquals(metadata.getPublicAddresses(), node.getPublicAddresses());
}
public void testList() throws Exception {
public void testListNodes() throws Exception {
for (ComputeMetadata node : client.listNodes()) {
assert node.getId() != null;
assert node.getLocation() != null;
@ -161,9 +167,10 @@ public abstract class BaseComputeServiceLiveTest {
}
}
public void testListTemplates() throws Exception {
for (Template template : client.listTemplates()) {
assert template.getImage() != null;
public void testListImages() throws Exception {
for (Image image : client.listImages()) {
assert image.getId() != null : image;
assert image.getLocation() != null : image;
}
}
@ -197,7 +204,7 @@ public abstract class BaseComputeServiceLiveTest {
ssh.connect();
ExecResponse hello = ssh.exec("echo hello");
assertEquals(hello.getOutput().trim(), "hello");
if (canRunScript())
if (canRunScript(template))
System.out.println(ssh.exec("java -version"));
} finally {
if (ssh != null)

View File

@ -18,15 +18,22 @@
*/
package org.jclouds.concurrent;
import java.util.Set;
import java.util.concurrent.CancellationException;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.concurrent.atomic.AtomicBoolean;
import javax.inject.Singleton;
import org.jclouds.logging.Logger;
import com.google.common.base.Throwables;
import com.google.common.collect.Sets;
import com.google.common.util.concurrent.ExecutionList;
import com.google.common.util.concurrent.ForwardingFuture;
import com.google.common.util.concurrent.ListenableFuture;
@ -38,6 +45,37 @@ import com.google.common.util.concurrent.ListenableFuture;
*/
@Singleton
public class ConcurrentUtils {
public static void pollResponsesAndLogWhenComplete(int total, String description, Logger logger,
Set<Future<Void>> responses) throws InterruptedException, TimeoutException,
ExecutionException {
int complete = 0;
long start = System.currentTimeMillis();
long timeOut = 180 * 1000;
do {
Set<Future<Void>> retries = Sets.newHashSet();
for (Future<Void> future : responses) {
try {
future.get(100, TimeUnit.MILLISECONDS);
complete++;
} catch (ExecutionException e) {
Throwables.propagate(e);
} catch (TimeoutException e) {
retries.add(future);
}
}
responses = Sets.newHashSet(retries);
} while (responses.size() > 0 && System.currentTimeMillis() < start + timeOut);
long duration = System.currentTimeMillis() - start;
if (duration > timeOut)
throw new TimeoutException(String.format("TIMEOUT: %s(%d/%d) rate: %f %s/second",
description, complete, total, ((double) complete) / (duration / 1000.0),
description));
for (Future<Void> future : responses)
future.get(30, TimeUnit.SECONDS);
logger.debug("<< %s(%d)", description, total);
}
/**
* Converts an exception into an object, which is useful for transforming to null or false.
*/

View File

@ -0,0 +1,21 @@
package org.jclouds.domain;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import javax.inject.Qualifier;
/**
* Related to the location of a resource
*
* @author Adrian Cole
*
*/
@Retention(value = RetentionPolicy.RUNTIME)
@Target(value = { ElementType.FIELD, ElementType.PARAMETER, ElementType.METHOD })
@Qualifier
public @interface ResourceLocation {
}

View File

@ -36,12 +36,14 @@ import org.jclouds.compute.ComputeService;
import org.jclouds.compute.domain.ComputeMetadata;
import org.jclouds.compute.domain.ComputeType;
import org.jclouds.compute.domain.CreateNodeResponse;
import org.jclouds.compute.domain.Image;
import org.jclouds.compute.domain.LoginType;
import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.domain.NodeState;
import org.jclouds.compute.domain.OperatingSystem;
import org.jclouds.compute.domain.Size;
import org.jclouds.compute.domain.Template;
import org.jclouds.compute.domain.TemplateBuilder;
import org.jclouds.compute.domain.internal.ComputeMetadataImpl;
import org.jclouds.compute.domain.internal.CreateNodeResponseImpl;
import org.jclouds.compute.options.RunNodeOptions;
@ -145,18 +147,18 @@ public class RimuHostingComputeService implements ComputeService {
rhClient.destroyServer(new Long(node.getId()));
}
@Override
public Template createTemplateInLocation(String location) {
return null;
}
@Override
public SortedSet<? extends Size> listSizes() {
return null;
}
@Override
public Set<? extends Template> listTemplates() {
public Set<? extends Image> listImages() {
return null;
}
@Override
public TemplateBuilder templateBuilder() {
return null;
}
}

View File

@ -18,9 +18,11 @@
*/
package org.jclouds.rimuhosting.miro.compute;
import static org.jclouds.compute.domain.OperatingSystem.UBUNTU;
import static org.jclouds.compute.domain.OperatingSystem.JEOS;
import org.jclouds.compute.BaseComputeServiceLiveTest;
import org.jclouds.compute.domain.Template;
import org.jclouds.compute.domain.TemplateBuilder;
import org.jclouds.ssh.jsch.config.JschSshClientModule;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
@ -34,7 +36,10 @@ public class RimuHostingComputeServiceLiveTest extends BaseComputeServiceLiveTes
@Override
public void setServiceDefaults() {
service = "rimuhosting";
testOS = UBUNTU;
}
protected Template buildTemplate(TemplateBuilder templateBuilder) {
return templateBuilder.os(JEOS).osVersionMatches(".*9.04.*").smallest().build();
}
@Override

View File

@ -92,7 +92,7 @@
</compute>
</target>
<property name="location" value="default" />
<property name="location" value="" />
<target name="create" description="create the node ${nodename}">
<property name="os" value="UBUNTU" />

View File

@ -37,6 +37,7 @@ import org.jclouds.compute.ComputeServiceContext;
import org.jclouds.compute.ComputeServiceContextFactory;
import org.jclouds.compute.domain.OperatingSystem;
import org.jclouds.compute.domain.Template;
import org.jclouds.compute.domain.TemplateBuilder;
import org.jclouds.compute.options.RunNodeOptions;
import org.jclouds.compute.reference.ComputeServiceConstants;
import org.jclouds.ssh.jsch.config.JschSshClientModule;
@ -75,11 +76,11 @@ public class ComputeTaskUtils {
try {
Properties props = new Properties();
props.putAll(projectProvider.get().getProperties());
return new ComputeServiceContextFactory().createContext(from, ImmutableSet.of(
(Module) new AntLoggingModule(projectProvider.get(),
return new ComputeServiceContextFactory().createContext(from,
ImmutableSet
.of((Module) new AntLoggingModule(projectProvider.get(),
ComputeServiceConstants.COMPUTE_LOGGER),
new JschSshClientModule()),
props);
new JschSshClientModule()), props);
} catch (IOException e) {
throw new RuntimeException(e);
}
@ -90,13 +91,15 @@ public class ComputeTaskUtils {
}
static Template createTemplateFromElement(NodeElement nodeElement, ComputeService computeService) {
Template template = computeService.createTemplateInLocation(nodeElement.getLocation());
template.os(OperatingSystem.valueOf(nodeElement.getOs()));
addSizeFromElementToTemplate(nodeElement, template);
return template;
TemplateBuilder templateBuilder = computeService.templateBuilder();
if (nodeElement.getLocation() != null && !"".equals(nodeElement.getLocation()))
templateBuilder.location(nodeElement.getLocation());
templateBuilder.os(OperatingSystem.valueOf(nodeElement.getOs()));
addSizeFromElementToTemplate(nodeElement, templateBuilder);
return templateBuilder.build();
}
static void addSizeFromElementToTemplate(NodeElement nodeElement, Template template) {
static void addSizeFromElementToTemplate(NodeElement nodeElement, TemplateBuilder template) {
if (nodeElement.getSize().equalsIgnoreCase("smallest")) {
template.smallest();
} else if (nodeElement.getSize().equalsIgnoreCase("fastest")) {

View File

@ -34,7 +34,7 @@ public class NodeElement {
private String hostproperty;
private String idproperty;
private String usernameproperty;
private String location = "default";
private String location;
private File runscript;
public String getLocation() {

View File

@ -28,7 +28,6 @@ import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.util.Map;
import java.util.Set;
import java.util.SortedSet;
import javax.annotation.Resource;
import javax.inject.Named;
@ -45,6 +44,7 @@ import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.domain.NodeState;
import org.jclouds.compute.domain.Size;
import org.jclouds.compute.domain.Template;
import org.jclouds.compute.domain.TemplateBuilder;
import org.jclouds.compute.domain.internal.CreateNodeResponseImpl;
import org.jclouds.compute.domain.internal.NodeMetadataImpl;
import org.jclouds.compute.options.RunNodeOptions;
@ -76,9 +76,9 @@ public class VCloudComputeService implements ComputeService, VCloudComputeClient
protected Logger logger = Logger.NULL;
private final VCloudClient client;
protected final Provider<Set<? extends Image>> images;
protected final Provider<SortedSet<? extends Size>> sizes;
private final Provider<Set<? extends VCloudTemplate>> templates;
protected final Provider<Set<? extends Size>> sizes;
protected final Provider<TemplateBuilder> templateBuilderProvider;
private final Predicate<String> taskTester;
@Inject(optional = true)
private SshClient.Factory sshFactory;
private Predicate<InetSocketAddress> socketTester;
@ -90,15 +90,15 @@ public class VCloudComputeService implements ComputeService, VCloudComputeClient
NodeState.PENDING).build();
@Inject
public VCloudComputeService(VCloudClient client, Provider<Set<? extends Image>> images,
Provider<SortedSet<? extends Size>> sizes,
Provider<Set<? extends VCloudTemplate>> templates, Predicate<String> successTester,
Predicate<InetSocketAddress> socketTester) {
public VCloudComputeService(VCloudClient client,
Provider<TemplateBuilder> templateBuilderProvider,
Provider<Set<? extends Image>> images, Provider<Set<? extends Size>> sizes,
Predicate<String> successTester, Predicate<InetSocketAddress> socketTester) {
this.taskTester = successTester;
this.client = client;
this.images = images;
this.sizes = sizes;
this.templates = templates;
this.templateBuilderProvider = templateBuilderProvider;
this.socketTester = socketTester;
}
@ -204,22 +204,20 @@ public class VCloudComputeService implements ComputeService, VCloudComputeClient
}
@Override
public Template createTemplateInLocation(String location) {
return new VCloudTemplate(client, images.get(), sizes.get(), location);
public TemplateBuilder templateBuilder() {
return templateBuilderProvider.get();
}
@Override
public SortedSet<? extends Size> listSizes() {
public Set<? extends Size> listSizes() {
return sizes.get();
}
@Override
public Set<? extends Template> listTemplates() {
return templates.get();
public Set<? extends Image> listImages() {
return images.get();
}
private final Predicate<String> taskTester;
public Map<String, String> start(String vDCId, String name, String templateId, int minCores,
int minMegs, Long diskSize, Map<String, String> properties, int... portsToOpen) {
logger

View File

@ -1,180 +0,0 @@
package org.jclouds.vcloud.compute;
import java.util.Set;
import javax.annotation.Nullable;
import org.jclouds.compute.domain.Image;
import org.jclouds.compute.domain.OperatingSystem;
import org.jclouds.compute.domain.Size;
import org.jclouds.compute.domain.Template;
import org.jclouds.vcloud.VCloudClient;
import com.google.common.collect.Iterables;
/**
*
* @author Adrian Cole
*/
public class VCloudTemplate implements Template {
private final VCloudClient client;
private final Set<? extends Image> images;
private final Set<? extends Size> sizes;
private Size size;
private String vDC;
private OperatingSystem operatingSystem;
private transient Image image;
public VCloudTemplate(VCloudClient client,
Set<? extends Image> images, Set<? extends Size> sizes, String location,
@Nullable Size size, OperatingSystem operatingSystem, @Nullable Image image) {
this.client = client;
this.images = images;
this.sizes = sizes;
this.vDC = location;
this.image = image != null ? image : resolveTemplate(images, operatingSystem);
this.size = size != null ? size : Iterables.get(sizes, 0);
this.operatingSystem = operatingSystem;
}
private Image resolveTemplate(Set<? extends Image> images, OperatingSystem operatingSystem) {
for (Image image : images) {
if (image.getOperatingSystem() == operatingSystem)
return image;
}
throw new RuntimeException("no configured image matches os: " + operatingSystem);
}
VCloudTemplate(VCloudClient client, Set<? extends Image> images,
Set<? extends Size> sizes, String location) {
this(client, images, sizes, location, null, OperatingSystem.CENTOS, null);// note the default
// os
}
/**
* {@inheritDoc}
*/
@Override
public Size getSize() {
return size;
}
/**
* {@inheritDoc}
*/
@Override
public Image getImage() {
return image;
}
/**
* {@inheritDoc}
*/
@Override
public Template smallest() {
this.size = Iterables.get(sizes, 0);
return this;
}
/**
* {@inheritDoc}
*/
@Override
public Template biggest() {
this.size = Iterables.getLast(sizes);
return this;
}
/**
* {@inheritDoc}
*/
@Override
public Template fastest() {
this.size = Iterables.getLast(sizes);
return this;
}
/**
* {@inheritDoc}
*/
@Override
public Template inLocation(String location) {
if (location.equalsIgnoreCase("default"))
location = client.getDefaultVDC().getId();
this.vDC = location;// TODO match vdc on template as well arch
return this;
}
/**
* {@inheritDoc}
*/
@Override
public Template os(OperatingSystem os) {
this.operatingSystem = os;
this.image = resolveTemplate(images, operatingSystem);
return this;
}
/**
* {@inheritDoc}
*/
@Override
protected Object clone() throws CloneNotSupportedException {
return new VCloudTemplate(client, images, sizes, vDC, size, operatingSystem,
image);
}
public String getvDC() {
return vDC;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((image == null) ? 0 : image.hashCode());
result = prime * result + ((operatingSystem == null) ? 0 : operatingSystem.hashCode());
result = prime * result + ((size == null) ? 0 : size.hashCode());
result = prime * result + ((vDC == null) ? 0 : vDC.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;
VCloudTemplate other = (VCloudTemplate) obj;
if (image == null) {
if (other.image != null)
return false;
} else if (!image.equals(other.image))
return false;
if (operatingSystem == null) {
if (other.operatingSystem != null)
return false;
} else if (!operatingSystem.equals(other.operatingSystem))
return false;
if (size == null) {
if (other.size != null)
return false;
} else if (!size.equals(other.size))
return false;
if (vDC == null) {
if (other.vDC != null)
return false;
} else if (!vDC.equals(other.vDC))
return false;
return true;
}
@Override
public String toString() {
return "VCloudTemplate [image=" + image + ", operatingSystem=" + operatingSystem
+ ", size=" + size + ", vDC=" + vDC + "]";
}
}

View File

@ -19,12 +19,10 @@
package org.jclouds.vcloud.compute.config;
import java.util.Set;
import java.util.SortedSet;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import javax.annotation.Resource;
@ -41,6 +39,8 @@ import org.jclouds.compute.domain.internal.ImageImpl;
import org.jclouds.compute.domain.internal.SizeImpl;
import org.jclouds.compute.internal.ComputeServiceContextImpl;
import org.jclouds.compute.reference.ComputeServiceConstants;
import org.jclouds.concurrent.ConcurrentUtils;
import org.jclouds.domain.ResourceLocation;
import org.jclouds.logging.Logger;
import org.jclouds.rest.RestContext;
import org.jclouds.vcloud.VCloudAsyncClient;
@ -48,16 +48,13 @@ import org.jclouds.vcloud.VCloudClient;
import org.jclouds.vcloud.VCloudMediaType;
import org.jclouds.vcloud.compute.VCloudComputeClient;
import org.jclouds.vcloud.compute.VCloudComputeService;
import org.jclouds.vcloud.compute.VCloudTemplate;
import org.jclouds.vcloud.config.VCloudContextModule;
import org.jclouds.vcloud.domain.Catalog;
import org.jclouds.vcloud.domain.CatalogItem;
import org.jclouds.vcloud.domain.NamedResource;
import org.jclouds.vcloud.domain.VAppTemplate;
import com.google.common.base.Throwables;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.ImmutableSortedSet;
import com.google.common.collect.Sets;
import com.google.inject.Injector;
import com.google.inject.Provides;
@ -93,6 +90,13 @@ public class VCloudComputeServiceContextModule extends VCloudContextModule {
return new ComputeServiceContextImpl<VCloudAsyncClient, VCloudClient>(computeService, context);
}
@Provides
@Singleton
@ResourceLocation
String getVDC(VCloudClient client) {
return client.getDefaultVDC().getId();
}
protected static class LogHolder {
@Resource
@Named(ComputeServiceConstants.COMPUTE_LOGGER)
@ -101,13 +105,12 @@ public class VCloudComputeServiceContextModule extends VCloudContextModule {
@Provides
@Singleton
protected Set<? extends Image> provideImages(final VCloudClient client, LogHolder holder,
ExecutorService executor) throws InterruptedException, ExecutionException,
TimeoutException {
protected Set<? extends Image> provideImages(final VCloudClient client,
final @ResourceLocation String vDC, LogHolder holder, ExecutorService executor)
throws InterruptedException, ExecutionException, TimeoutException {
final Set<Image> images = Sets.newHashSet();
holder.logger.debug(">> providing images");
Catalog response = client.getDefaultCatalog();
final String vDC = client.getDefaultVDC().getId();
Set<Future<Void>> responses = Sets.newHashSet();
for (final NamedResource resource : response.values()) {
@ -117,9 +120,9 @@ public class VCloudComputeServiceContextModule extends VCloudContextModule {
responses.add(executor.submit(new Callable<Void>() {
@Override
public Void call() throws Exception {
OperatingSystem myOs = OperatingSystem.UNKNOWN;
OperatingSystem myOs = null;
for (OperatingSystem os : OperatingSystem.values()) {
if (resource.getName().toUpperCase().replaceAll("\\s", "").indexOf(
if (resource.getName().toLowerCase().replaceAll("\\s", "").indexOf(
os.toString()) != -1) {
myOs = os;
}
@ -127,73 +130,31 @@ public class VCloudComputeServiceContextModule extends VCloudContextModule {
Architecture arch = resource.getName().matches("64[- ]bit") ? Architecture.X86_32
: Architecture.X86_64;
VAppTemplate template = client.getVAppTemplate(item.getEntity().getId());
images.add(new ImageImpl(resource.getId(), template.getDescription(), myOs,
null, vDC, arch));
images.add(new ImageImpl(resource.getId(), template.getName(), "", myOs,
template.getName(), vDC, arch));
return null;
}
}));
}
}
}
pollResponsesAndLogWhenComplete(images.size(), "images", holder, responses);
ConcurrentUtils.pollResponsesAndLogWhenComplete(images.size(), "images", holder.logger,
responses);
return images;
}
protected void pollResponsesAndLogWhenComplete(int total, String description, LogHolder holder,
Set<Future<Void>> responses) throws InterruptedException, TimeoutException,
ExecutionException {
int complete = 0;
long start = System.currentTimeMillis();
long timeOut = 60 * 1000;
do {
Set<Future<Void>> retries = Sets.newHashSet();
for (Future<Void> future : responses) {
try {
future.get(100, TimeUnit.MILLISECONDS);
complete++;
} catch (ExecutionException e) {
Throwables.propagate(e);
} catch (TimeoutException e) {
retries.add(future);
}
}
responses = Sets.newHashSet(retries);
} while (responses.size() > 0 && System.currentTimeMillis() < start + timeOut);
long duration = System.currentTimeMillis() - start;
if (duration > timeOut)
throw new TimeoutException(String.format("TIMEOUT: %s(%d/%d) rate: %f %s/second%n",
description, complete, total, ((double) complete) / (duration / 1000.0),
description));
for (Future<Void> future : responses)
future.get(30, TimeUnit.SECONDS);
holder.logger.debug("<< %s(%d) rate: %f %s/second%n", description, total, ((double) complete)
/ (duration / 1000.0), description);
}
@Provides
@Singleton
protected SortedSet<? extends Size> provideSizes(VCloudClient client,
Set<? extends Image> images, LogHolder holder, ExecutorService executor)
throws InterruptedException, TimeoutException, ExecutionException {
return ImmutableSortedSet.of(new SizeImpl(1, 512, 10, ImmutableSet.<Architecture> of(
Architecture.X86_32, Architecture.X86_64)));
}
@Provides
@Singleton
protected Set<? extends VCloudTemplate> provideTemplates(VCloudClient client,
Set<? extends Image> images, SortedSet<? extends Size> sizes, LogHolder holder) {
Set<VCloudTemplate> templates = Sets.newHashSet();
holder.logger.debug(">> generating templates");
String vDC = client.getDefaultVDC().getId();
for (Size size : sizes) {
for (Image image : images) {
templates.add(new VCloudTemplate(client, images, sizes, vDC, size, image
.getOperatingSystem(), image));
}
}
holder.logger.debug("<< templates(%d)", templates.size());
return templates;
protected Set<? extends Size> provideSizes(VCloudClient client, Set<? extends Image> images,
LogHolder holder, ExecutorService executor) throws InterruptedException,
TimeoutException, ExecutionException {
Set<Size> sizes = Sets.newHashSet();
for (int cpus : new int[] { 1, 2, 4 })
for (int ram : new int[] { 512, 1024, 2048, 4096, 8192, 16384 })
sizes.add(new SizeImpl(String.format("cpu=%d,ram=%s,disk=%d", cpus, ram, 10), cpus,
ram, 10, ImmutableSet.<Architecture> of(Architecture.X86_32,
Architecture.X86_64)));
return sizes;
}
}

View File

@ -5,7 +5,6 @@ import static com.google.common.base.Preconditions.checkState;
import java.net.InetSocketAddress;
import java.util.Map;
import java.util.Set;
import java.util.SortedSet;
import javax.inject.Inject;
import javax.inject.Provider;
@ -13,9 +12,9 @@ import javax.inject.Singleton;
import org.jclouds.compute.domain.Image;
import org.jclouds.compute.domain.Size;
import org.jclouds.compute.domain.TemplateBuilder;
import org.jclouds.vcloud.VCloudClient;
import org.jclouds.vcloud.compute.VCloudComputeService;
import org.jclouds.vcloud.compute.VCloudTemplate;
import org.jclouds.vcloud.domain.VApp;
import org.jclouds.vcloud.hostingdotcom.domain.HostingDotComVApp;
@ -29,11 +28,11 @@ import com.google.common.collect.ImmutableMap;
public class HostingDotComVCloudComputeService extends VCloudComputeService {
@Inject
public HostingDotComVCloudComputeService(VCloudClient client,
Provider<Set<? extends Image>> images, Provider<SortedSet<? extends Size>> sizes,
Provider<Set<? extends VCloudTemplate>> templates, Predicate<String> successTester,
Predicate<InetSocketAddress> socketTester) {
super(client, images, sizes, templates, successTester, socketTester);
HostingDotComVCloudComputeService(VCloudClient client,
Provider<TemplateBuilder> templateBuilderProvider,
Provider<Set<? extends Image>> images, Provider<Set<? extends Size>> sizes,
Predicate<String> successTester, Predicate<InetSocketAddress> socketTester) {
super(client, templateBuilderProvider, images, sizes, successTester, socketTester);
}
@Override

View File

@ -22,6 +22,8 @@ package org.jclouds.vcloud.hostingdotcom.compute;
import static org.jclouds.compute.domain.OperatingSystem.CENTOS;
import org.jclouds.compute.BaseComputeServiceLiveTest;
import org.jclouds.compute.domain.Template;
import org.jclouds.compute.domain.TemplateBuilder;
import org.jclouds.ssh.jsch.config.JschSshClientModule;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
@ -37,7 +39,10 @@ public class HostingDotComVCloudComputeServiceLiveTest extends BaseComputeServic
@Override
public void setServiceDefaults() {
service = "hostingdotcom";
testOS = CENTOS;
}
protected Template buildTemplate(TemplateBuilder templateBuilder) {
return templateBuilder.os(CENTOS).smallest().build();
}
@Override

View File

@ -34,10 +34,10 @@ import javax.inject.Singleton;
import org.jclouds.compute.domain.Image;
import org.jclouds.compute.domain.Size;
import org.jclouds.compute.domain.TemplateBuilder;
import org.jclouds.compute.reference.ComputeServiceConstants;
import org.jclouds.logging.Logger;
import org.jclouds.vcloud.compute.VCloudComputeService;
import org.jclouds.vcloud.compute.VCloudTemplate;
import org.jclouds.vcloud.domain.VApp;
import org.jclouds.vcloud.terremark.TerremarkVCloudClient;
import org.jclouds.vcloud.terremark.domain.InternetService;
@ -62,10 +62,10 @@ public class TerremarkVCloudComputeService extends VCloudComputeService {
@Inject
public TerremarkVCloudComputeService(TerremarkVCloudClient client,
Provider<Set<? extends Image>> images, Provider<SortedSet<? extends Size>> sizes,
Provider<Set<? extends VCloudTemplate>> templates, Predicate<String> successTester,
Predicate<InetSocketAddress> socketTester) {
super(client, images, sizes, templates, successTester, socketTester);
Provider<TemplateBuilder> templateBuilderProvider,
Provider<Set<? extends Image>> images, Provider<Set<? extends Size>> sizes,
Predicate<String> successTester, Predicate<InetSocketAddress> socketTester) {
super(client, templateBuilderProvider, images, sizes, successTester, socketTester);
this.client = client;
}

View File

@ -62,8 +62,8 @@ public class TerremarkVCloudComputeServiceContextModule extends VCloudComputeSer
private static class ComputeOptionsToSize implements Function<ComputeOptions, Size> {
@Override
public Size apply(ComputeOptions from) {
return new SizeImpl(from.getProcessorCount(), from.getMemory(), 10, ImmutableSet
.<Architecture> of(Architecture.X86_32, Architecture.X86_64));
return new SizeImpl(from.toString(), from.getProcessorCount(), from.getMemory(), 10,
ImmutableSet.<Architecture> of(Architecture.X86_32, Architecture.X86_64));
}
}

View File

@ -23,6 +23,8 @@ import static org.jclouds.compute.domain.OperatingSystem.JEOS;
import org.jclouds.compute.BaseComputeServiceLiveTest;
import org.jclouds.compute.ComputeServiceContextFactory;
import org.jclouds.compute.domain.Template;
import org.jclouds.compute.domain.TemplateBuilder;
import org.jclouds.rest.RestContext;
import org.jclouds.ssh.jsch.config.JschSshClientModule;
import org.jclouds.vcloud.compute.VCloudComputeClient;
@ -39,11 +41,15 @@ import org.testng.annotations.Test;
*/
@Test(groups = "live", enabled = true, sequential = true, testName = "terremark.TerremarkVCloudComputeServiceLiveTest")
public class TerremarkVCloudComputeServiceLiveTest extends BaseComputeServiceLiveTest {
@BeforeClass
@Override
public void setServiceDefaults() {
service = "terremark";
testOS = JEOS;
}
protected Template buildTemplate(TemplateBuilder templateBuilder) {
return templateBuilder.os(JEOS).osVersionMatches(".*9.04.*").smallest().build();
}
@Override
@ -55,10 +61,10 @@ public class TerremarkVCloudComputeServiceLiveTest extends BaseComputeServiceLiv
@SuppressWarnings("unused")
RestContext<TerremarkVCloudAsyncClient, TerremarkVCloudClient> tmContext = new ComputeServiceContextFactory()
.createContext(service, user, password).getProviderSpecificContext();
TerremarkVCloudComputeService computeService = TerremarkVCloudComputeService.class
.cast(client);
@SuppressWarnings("unused")
VCloudComputeClient computeClient = VCloudComputeClient.class.cast(computeService);
}