mirror of https://github.com/apache/jclouds.git
Issue 130: added location and made compute service set-based
git-svn-id: http://jclouds.googlecode.com/svn/trunk@2730 3d8758e0-26b5-11de-8745-db77d3ebf521
This commit is contained in:
parent
70aa7e4ef3
commit
3521c47029
|
@ -19,9 +19,10 @@
|
||||||
package org.jclouds.aws.ec2;
|
package org.jclouds.aws.ec2;
|
||||||
|
|
||||||
import static com.google.common.base.Preconditions.checkNotNull;
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
|
import static org.jclouds.aws.ec2.reference.EC2Constants.PROPERTY_EC2_AMI_OWNERS;
|
||||||
import static org.jclouds.aws.ec2.reference.EC2Constants.PROPERTY_EC2_ENDPOINT;
|
import static org.jclouds.aws.ec2.reference.EC2Constants.PROPERTY_EC2_ENDPOINT;
|
||||||
import static org.jclouds.aws.ec2.reference.EC2Constants.PROPERTY_AWS_EXPIREINTERVAL;
|
|
||||||
import static org.jclouds.aws.reference.AWSConstants.PROPERTY_AWS_ACCESSKEYID;
|
import static org.jclouds.aws.reference.AWSConstants.PROPERTY_AWS_ACCESSKEYID;
|
||||||
|
import static org.jclouds.aws.reference.AWSConstants.PROPERTY_AWS_EXPIREINTERVAL;
|
||||||
import static org.jclouds.aws.reference.AWSConstants.PROPERTY_AWS_SECRETACCESSKEY;
|
import static org.jclouds.aws.reference.AWSConstants.PROPERTY_AWS_SECRETACCESSKEY;
|
||||||
|
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
|
@ -40,6 +41,7 @@ public class EC2PropertiesBuilder extends PropertiesBuilder {
|
||||||
Properties properties = super.defaultProperties();
|
Properties properties = super.defaultProperties();
|
||||||
properties.setProperty(PROPERTY_EC2_ENDPOINT, "https://ec2.us-east-1.amazonaws.com");
|
properties.setProperty(PROPERTY_EC2_ENDPOINT, "https://ec2.us-east-1.amazonaws.com");
|
||||||
properties.setProperty(PROPERTY_AWS_EXPIREINTERVAL, "60");
|
properties.setProperty(PROPERTY_AWS_EXPIREINTERVAL, "60");
|
||||||
|
properties.setProperty(PROPERTY_EC2_AMI_OWNERS, "063491364108");
|
||||||
return properties;
|
return properties;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -21,11 +21,12 @@ package org.jclouds.aws.ec2.compute;
|
||||||
import static com.google.common.base.Preconditions.checkArgument;
|
import static com.google.common.base.Preconditions.checkArgument;
|
||||||
import static com.google.common.base.Preconditions.checkNotNull;
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
import static org.jclouds.aws.ec2.options.RunInstancesOptions.Builder.withKeyName;
|
import static org.jclouds.aws.ec2.options.RunInstancesOptions.Builder.withKeyName;
|
||||||
|
import static org.jclouds.compute.util.ComputeUtils.METADATA_TO_ID;
|
||||||
|
|
||||||
import java.net.InetAddress;
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.NoSuchElementException;
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import java.util.concurrent.Callable;
|
||||||
|
import java.util.concurrent.ExecutorService;
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
@ -33,39 +34,46 @@ import javax.inject.Named;
|
||||||
import javax.inject.Provider;
|
import javax.inject.Provider;
|
||||||
import javax.inject.Singleton;
|
import javax.inject.Singleton;
|
||||||
|
|
||||||
import org.jclouds.aws.AWSResponseException;
|
import org.jclouds.Constants;
|
||||||
import org.jclouds.aws.domain.Region;
|
import org.jclouds.aws.domain.Region;
|
||||||
import org.jclouds.aws.ec2.EC2Client;
|
import org.jclouds.aws.ec2.EC2Client;
|
||||||
import org.jclouds.aws.ec2.compute.domain.EC2Image;
|
|
||||||
import org.jclouds.aws.ec2.compute.domain.EC2Size;
|
import org.jclouds.aws.ec2.compute.domain.EC2Size;
|
||||||
|
import org.jclouds.aws.ec2.compute.domain.KeyPairCredentials;
|
||||||
|
import org.jclouds.aws.ec2.compute.domain.PortsRegionTag;
|
||||||
|
import org.jclouds.aws.ec2.compute.domain.RegionTag;
|
||||||
|
import org.jclouds.aws.ec2.compute.functions.CreateKeyPairIfNeeded;
|
||||||
|
import org.jclouds.aws.ec2.compute.functions.CreateSecurityGroupIfNeeded;
|
||||||
|
import org.jclouds.aws.ec2.compute.functions.RunningInstanceToNodeMetadata;
|
||||||
|
import org.jclouds.aws.ec2.domain.AvailabilityZone;
|
||||||
import org.jclouds.aws.ec2.domain.InstanceState;
|
import org.jclouds.aws.ec2.domain.InstanceState;
|
||||||
import org.jclouds.aws.ec2.domain.IpProtocol;
|
import org.jclouds.aws.ec2.domain.Reservation;
|
||||||
import org.jclouds.aws.ec2.domain.KeyPair;
|
|
||||||
import org.jclouds.aws.ec2.domain.RunningInstance;
|
import org.jclouds.aws.ec2.domain.RunningInstance;
|
||||||
import org.jclouds.aws.ec2.options.RunInstancesOptions;
|
import org.jclouds.aws.ec2.options.RunInstancesOptions;
|
||||||
import org.jclouds.compute.ComputeService;
|
import org.jclouds.compute.ComputeService;
|
||||||
import org.jclouds.compute.domain.ComputeMetadata;
|
import org.jclouds.compute.domain.ComputeMetadata;
|
||||||
import org.jclouds.compute.domain.ComputeType;
|
import org.jclouds.compute.domain.ComputeType;
|
||||||
import org.jclouds.compute.domain.CreateNodeResponse;
|
|
||||||
import org.jclouds.compute.domain.Image;
|
import org.jclouds.compute.domain.Image;
|
||||||
import org.jclouds.compute.domain.NodeMetadata;
|
import org.jclouds.compute.domain.NodeMetadata;
|
||||||
|
import org.jclouds.compute.domain.NodeSet;
|
||||||
import org.jclouds.compute.domain.NodeState;
|
import org.jclouds.compute.domain.NodeState;
|
||||||
import org.jclouds.compute.domain.Size;
|
import org.jclouds.compute.domain.Size;
|
||||||
import org.jclouds.compute.domain.Template;
|
import org.jclouds.compute.domain.Template;
|
||||||
import org.jclouds.compute.domain.TemplateBuilder;
|
import org.jclouds.compute.domain.TemplateBuilder;
|
||||||
import org.jclouds.compute.domain.internal.ComputeMetadataImpl;
|
import org.jclouds.compute.domain.internal.NodeSetImpl;
|
||||||
import org.jclouds.compute.domain.internal.CreateNodeResponseImpl;
|
import org.jclouds.compute.options.TemplateOptions;
|
||||||
import org.jclouds.compute.domain.internal.NodeMetadataImpl;
|
|
||||||
import org.jclouds.compute.options.RunNodeOptions;
|
|
||||||
import org.jclouds.compute.reference.ComputeServiceConstants;
|
import org.jclouds.compute.reference.ComputeServiceConstants;
|
||||||
import org.jclouds.domain.Credentials;
|
import org.jclouds.concurrent.ConcurrentUtils;
|
||||||
|
import org.jclouds.domain.Location;
|
||||||
|
import org.jclouds.domain.LocationScope;
|
||||||
import org.jclouds.logging.Logger;
|
import org.jclouds.logging.Logger;
|
||||||
|
|
||||||
import com.google.common.base.Function;
|
import com.google.common.base.Function;
|
||||||
|
import com.google.common.base.Joiner;
|
||||||
import com.google.common.base.Predicate;
|
import com.google.common.base.Predicate;
|
||||||
import com.google.common.collect.ImmutableMap;
|
|
||||||
import com.google.common.collect.Iterables;
|
import com.google.common.collect.Iterables;
|
||||||
|
import com.google.common.collect.Maps;
|
||||||
import com.google.common.collect.Sets;
|
import com.google.common.collect.Sets;
|
||||||
|
import com.google.common.util.concurrent.ListenableFuture;
|
||||||
import com.google.inject.internal.ImmutableSet;
|
import com.google.inject.internal.ImmutableSet;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -73,128 +81,129 @@ import com.google.inject.internal.ImmutableSet;
|
||||||
*/
|
*/
|
||||||
@Singleton
|
@Singleton
|
||||||
public class EC2ComputeService implements ComputeService {
|
public class EC2ComputeService implements ComputeService {
|
||||||
|
|
||||||
|
private static Function<RunningInstance, String> instanceToId = new Function<RunningInstance, String>() {
|
||||||
|
@Override
|
||||||
|
public String apply(RunningInstance from) {
|
||||||
|
return from.getId();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
private static class NodeMatchesTag implements Predicate<NodeMetadata> {
|
||||||
|
private final String tag;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean apply(NodeMetadata from) {
|
||||||
|
return from.getTag().equals(tag);
|
||||||
|
}
|
||||||
|
|
||||||
|
public NodeMatchesTag(String tag) {
|
||||||
|
super();
|
||||||
|
this.tag = tag;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
@Named(ComputeServiceConstants.COMPUTE_LOGGER)
|
@Named(ComputeServiceConstants.COMPUTE_LOGGER)
|
||||||
protected Logger logger = Logger.NULL;
|
protected Logger logger = Logger.NULL;
|
||||||
private final EC2Client ec2Client;
|
protected final EC2Client ec2Client;
|
||||||
protected final Provider<Set<? extends Image>> images;
|
protected final Map<RegionTag, KeyPairCredentials> credentialsMap;
|
||||||
protected final Provider<Set<? extends Size>> sizes;
|
protected final Map<PortsRegionTag, String> securityGroupMap;
|
||||||
|
protected final Provider<Map<String, ? extends Image>> images;
|
||||||
|
protected final Provider<Map<String, ? extends Size>> sizes;
|
||||||
|
protected final Provider<Map<String, ? extends Location>> locations;
|
||||||
|
protected final CreateKeyPairIfNeeded createKeyPairIfNeeded;
|
||||||
|
protected final CreateSecurityGroupIfNeeded createSecurityGroupIfNeeded;
|
||||||
protected final Provider<TemplateBuilder> templateBuilderProvider;
|
protected final Provider<TemplateBuilder> templateBuilderProvider;
|
||||||
private final Predicate<RunningInstance> instanceStateRunning;
|
protected final Predicate<RunningInstance> instanceStateRunning;
|
||||||
private final Predicate<RunningInstance> instanceStateTerminated;
|
protected final Predicate<RunningInstance> instanceStateTerminated;
|
||||||
private final RunningInstanceToNodeMetadata runningInstanceToNodeMetadata;
|
protected final RunningInstanceToNodeMetadata runningInstanceToNodeMetadata;
|
||||||
|
protected final ExecutorService executor;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public EC2ComputeService(EC2Client client, Provider<TemplateBuilder> templateBuilderProvider,
|
public EC2ComputeService(EC2Client client, Provider<TemplateBuilder> templateBuilderProvider,
|
||||||
Provider<Set<? extends Image>> images, Provider<Set<? extends Size>> sizes,
|
Provider<Map<String, ? extends Image>> images,
|
||||||
|
Provider<Map<String, ? extends Size>> sizes,
|
||||||
|
Provider<Map<String, ? extends Location>> locations,
|
||||||
|
Map<RegionTag, KeyPairCredentials> credentialsMap,
|
||||||
|
Map<PortsRegionTag, String> securityGroupMap,
|
||||||
|
CreateKeyPairIfNeeded createKeyPairIfNeeded,
|
||||||
|
CreateSecurityGroupIfNeeded createSecurityGroupIfNeeded,
|
||||||
@Named("RUNNING") Predicate<RunningInstance> instanceStateRunning,
|
@Named("RUNNING") Predicate<RunningInstance> instanceStateRunning,
|
||||||
@Named("TERMINATED") Predicate<RunningInstance> instanceStateTerminated,
|
@Named("TERMINATED") Predicate<RunningInstance> instanceStateTerminated,
|
||||||
RunningInstanceToNodeMetadata runningInstanceToNodeMetadata) {
|
RunningInstanceToNodeMetadata runningInstanceToNodeMetadata,
|
||||||
|
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService executor) {
|
||||||
|
this.templateBuilderProvider = templateBuilderProvider;
|
||||||
this.ec2Client = client;
|
this.ec2Client = client;
|
||||||
this.images = images;
|
this.images = images;
|
||||||
this.sizes = sizes;
|
this.sizes = sizes;
|
||||||
this.templateBuilderProvider = templateBuilderProvider;
|
this.locations = locations;
|
||||||
|
this.credentialsMap = credentialsMap;
|
||||||
|
this.createKeyPairIfNeeded = createKeyPairIfNeeded;
|
||||||
|
this.createSecurityGroupIfNeeded = createSecurityGroupIfNeeded;
|
||||||
|
this.securityGroupMap = securityGroupMap;
|
||||||
this.instanceStateRunning = instanceStateRunning;
|
this.instanceStateRunning = instanceStateRunning;
|
||||||
this.instanceStateTerminated = instanceStateTerminated;
|
this.instanceStateTerminated = instanceStateTerminated;
|
||||||
this.runningInstanceToNodeMetadata = runningInstanceToNodeMetadata;
|
this.runningInstanceToNodeMetadata = runningInstanceToNodeMetadata;
|
||||||
}
|
this.executor = executor;
|
||||||
|
|
||||||
private static Map<InstanceState, NodeState> instanceToNodeState = ImmutableMap
|
|
||||||
.<InstanceState, NodeState> builder().put(InstanceState.PENDING, NodeState.PENDING)
|
|
||||||
.put(InstanceState.RUNNING, NodeState.RUNNING).put(InstanceState.SHUTTING_DOWN,
|
|
||||||
NodeState.PENDING).put(InstanceState.TERMINATED, NodeState.TERMINATED).build();
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public CreateNodeResponse runNode(String name, Template template) {
|
|
||||||
return this.runNode(name, template, RunNodeOptions.NONE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CreateNodeResponse runNode(String name, Template template, RunNodeOptions options) {
|
public NodeSet runNodes(String tag, int count, Template template) {
|
||||||
checkArgument(template.getImage() instanceof EC2Image,
|
checkArgument(tag.indexOf('-') == -1, "tag cannot contain hyphens");
|
||||||
"unexpected image type. should be EC2Image, was: " + template.getImage().getClass());
|
|
||||||
checkArgument(template.getSize() instanceof EC2Size,
|
checkArgument(template.getSize() instanceof EC2Size,
|
||||||
"unexpected image type. should be EC2Size, was: " + template.getSize().getClass());
|
"unexpected image type. should be EC2Size, was: " + template.getSize().getClass());
|
||||||
EC2Image ec2Image = EC2Image.class.cast(template.getImage());
|
|
||||||
EC2Size ec2Size = EC2Size.class.cast(template.getSize());
|
EC2Size ec2Size = EC2Size.class.cast(template.getSize());
|
||||||
|
|
||||||
Region region = ec2Image.getImage().getRegion();
|
// parse the availability zone of the request
|
||||||
KeyPair keyPair = createKeyPairInRegion(region, name);
|
AvailabilityZone zone = template.getLocation().getScope() == LocationScope.ZONE ? AvailabilityZone
|
||||||
String securityGroupName = name;
|
.fromValue(template.getLocation().getId())
|
||||||
createSecurityGroupInRegion(region, securityGroupName, options.getOpenPorts());
|
: null;
|
||||||
|
|
||||||
logger.debug(">> running instance region(%s) ami(%s) type(%s) keyPair(%s) securityGroup(%s)",
|
// if the location has a parent, it must be an availability zone.
|
||||||
region, ec2Image.getId(), ec2Size.getInstanceType(), keyPair.getKeyName(),
|
Region region = zone == null ? Region.fromValue(template.getLocation().getId()) : Region
|
||||||
securityGroupName);
|
.fromValue(template.getLocation().getParent());
|
||||||
RunInstancesOptions instanceOptions = withKeyName(keyPair.getKeyName())// key
|
|
||||||
|
// get or create incidental resources
|
||||||
|
// TODO race condition. we were using MapMaker, but it doesn't seem to refresh properly when
|
||||||
|
// another thread
|
||||||
|
// deletes a key
|
||||||
|
RegionTag regionTag = new RegionTag(region, tag);
|
||||||
|
if (!credentialsMap.containsKey(regionTag)) {
|
||||||
|
credentialsMap.put(regionTag, createKeyPairIfNeeded.apply(regionTag));
|
||||||
|
}
|
||||||
|
TemplateOptions options = template.getOptions();
|
||||||
|
PortsRegionTag portsRegionTag = new PortsRegionTag(region, tag, options.getInboundPorts());
|
||||||
|
if (!securityGroupMap.containsKey(portsRegionTag)) {
|
||||||
|
securityGroupMap.put(portsRegionTag, createSecurityGroupIfNeeded.apply(portsRegionTag));
|
||||||
|
}
|
||||||
|
|
||||||
|
logger
|
||||||
|
.debug(
|
||||||
|
">> running %d instance region(%s) zone(%s) ami(%s) type(%s) keyPair(%s) securityGroup(%s)",
|
||||||
|
count, region, zone, template.getImage().getId(),
|
||||||
|
ec2Size.getInstanceType(), tag, tag);
|
||||||
|
RunInstancesOptions instanceOptions = withKeyName(tag)// key
|
||||||
.asType(ec2Size.getInstanceType())// instance size
|
.asType(ec2Size.getInstanceType())// instance size
|
||||||
.withSecurityGroup(securityGroupName)// group I created above
|
.withSecurityGroup(tag)// group I created above
|
||||||
.withAdditionalInfo(name);
|
.withAdditionalInfo(tag);
|
||||||
|
|
||||||
if (options.getRunScript() != null)
|
if (options.getRunScript() != null)
|
||||||
instanceOptions.withUserData(options.getRunScript());
|
instanceOptions.withUserData(options.getRunScript());
|
||||||
|
|
||||||
RunningInstance runningInstance = Iterables.getOnlyElement(ec2Client.getInstanceServices()
|
Reservation reservation = ec2Client.getInstanceServices().runInstancesInRegion(region, zone,
|
||||||
.runInstancesInRegion(region, null, ec2Image.getId(), 1, 1, instanceOptions));
|
template.getImage().getId(), 1, count, instanceOptions);
|
||||||
logger.debug("<< started instance(%s)", runningInstance.getId());
|
Iterable<String> ids = Iterables.transform(reservation, instanceToId);
|
||||||
instanceStateRunning.apply(runningInstance);
|
|
||||||
logger.debug("<< running instance(%s)", runningInstance.getId());
|
String idsString = Joiner.on(',').join(ids);
|
||||||
|
logger.debug("<< started instances(%s)", idsString);
|
||||||
|
Iterables.all(reservation, instanceStateRunning);
|
||||||
|
logger.debug("<< running instances(%s)", idsString);
|
||||||
|
|
||||||
// refresh to get IP address
|
// refresh to get IP address
|
||||||
runningInstance = getOnlyRunningInstanceInRegion(region, runningInstance.getId());
|
return new NodeSetImpl(Iterables.transform(Iterables.concat(ec2Client.getInstanceServices()
|
||||||
|
.describeInstancesInRegion(region, Iterables.toArray(ids, String.class))),
|
||||||
Set<InetAddress> publicAddresses = runningInstance.getIpAddress() == null ? ImmutableSet
|
runningInstanceToNodeMetadata));
|
||||||
.<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,
|
|
||||||
new Credentials("root", keyPair.getKeyMaterial()), ImmutableMap
|
|
||||||
.<String, String> of());
|
|
||||||
}
|
|
||||||
|
|
||||||
private KeyPair createKeyPairInRegion(Region region, String name) {
|
|
||||||
logger.debug(">> creating keyPair region(%s) name(%s)", region, name);
|
|
||||||
KeyPair keyPair;
|
|
||||||
try {
|
|
||||||
keyPair = ec2Client.getKeyPairServices().createKeyPairInRegion(region, name);
|
|
||||||
logger.debug("<< created keyPair(%s)", keyPair.getKeyName());
|
|
||||||
|
|
||||||
} catch (AWSResponseException e) {
|
|
||||||
if (e.getError().getCode().equals("InvalidKeyPair.Duplicate")) {
|
|
||||||
keyPair = Iterables.getLast(ec2Client.getKeyPairServices().describeKeyPairsInRegion(
|
|
||||||
region, name));
|
|
||||||
logger.debug("<< reused keyPair(%s)", keyPair.getKeyName());
|
|
||||||
|
|
||||||
} else {
|
|
||||||
throw e;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return keyPair;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void createSecurityGroupInRegion(Region region, String name, int... ports) {
|
|
||||||
logger.debug(">> creating securityGroup region(%s) name(%s)", region, name);
|
|
||||||
try {
|
|
||||||
ec2Client.getSecurityGroupServices().createSecurityGroupInRegion(region, name, name);
|
|
||||||
logger.debug("<< created securityGroup(%s)", name);
|
|
||||||
for (int port : ports) {
|
|
||||||
logger.debug(">> authorizing securityGroup region(%s) name(%s) port(%s)", region, name,
|
|
||||||
port);
|
|
||||||
ec2Client.getSecurityGroupServices().authorizeSecurityGroupIngressInRegion(region,
|
|
||||||
name, IpProtocol.TCP, port, port, "0.0.0.0/0");
|
|
||||||
logger.debug("<< authorized securityGroup(%s)", name);
|
|
||||||
}
|
|
||||||
} catch (AWSResponseException e) {
|
|
||||||
if (e.getError().getCode().equals("InvalidGroup.Duplicate")) {
|
|
||||||
logger.debug("<< reused securityGroup(%s)", name);
|
|
||||||
} else {
|
|
||||||
throw e;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -208,114 +217,132 @@ public class EC2ComputeService implements ComputeService {
|
||||||
return runningInstanceToNodeMetadata.apply(runningInstance);
|
return runningInstanceToNodeMetadata.apply(runningInstance);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Singleton
|
|
||||||
private static class RunningInstanceToNodeMetadata implements
|
|
||||||
Function<RunningInstance, NodeMetadata> {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public NodeMetadata apply(RunningInstance from) {
|
|
||||||
return new NodeMetadataImpl(from.getId(), from.getKeyName(), from.getRegion().toString(),
|
|
||||||
null, ImmutableMap.<String, String> of(), instanceToNodeState.get(from
|
|
||||||
.getInstanceState()), nullSafeSet(from.getIpAddress()), nullSafeSet(from
|
|
||||||
.getPrivateIpAddress()), ImmutableMap.<String, String> of(
|
|
||||||
"availabilityZone", from.getAvailabilityZone().toString()));
|
|
||||||
}
|
|
||||||
|
|
||||||
Set<InetAddress> nullSafeSet(InetAddress in) {
|
|
||||||
if (in == null) {
|
|
||||||
return ImmutableSet.<InetAddress> of();
|
|
||||||
}
|
|
||||||
return ImmutableSet.<InetAddress> of(in);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private RunningInstance getOnlyRunningInstanceInRegion(Region region, String id) {
|
|
||||||
Iterable<RunningInstance> instances = Iterables.filter(getAllRunningInstancesInRegion(region,
|
|
||||||
id), new Predicate<RunningInstance>() {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean apply(RunningInstance instance) {
|
|
||||||
return instance.getInstanceState() == InstanceState.PENDING
|
|
||||||
|| instance.getInstanceState() == InstanceState.RUNNING;
|
|
||||||
}
|
|
||||||
|
|
||||||
});
|
|
||||||
int size = Iterables.size(instances);
|
|
||||||
if (size == 0)
|
|
||||||
throw new NoSuchElementException(String.format(
|
|
||||||
"%d instances in region %s have an instance with id %s running.", size, region,
|
|
||||||
id));
|
|
||||||
if (size > 1)
|
|
||||||
throw new IllegalStateException(String.format(
|
|
||||||
"%d instances in region %s have an instance with id %s running. Expected 1",
|
|
||||||
size, region, id));
|
|
||||||
return Iterables.getOnlyElement(instances);
|
|
||||||
}
|
|
||||||
|
|
||||||
private Iterable<RunningInstance> getAllRunningInstancesInRegion(Region region, String id) {
|
private Iterable<RunningInstance> getAllRunningInstancesInRegion(Region region, String id) {
|
||||||
return Iterables
|
return Iterables
|
||||||
.concat(ec2Client.getInstanceServices().describeInstancesInRegion(region, id));
|
.concat(ec2Client.getInstanceServices().describeInstancesInRegion(region, id));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* hack alert. can't find a good place to store the original servername, so we are reusing the
|
|
||||||
* keyname. This will break.
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public Set<ComputeMetadata> listNodes() {
|
public Map<String, NodeMetadata> getNodes() {
|
||||||
logger.debug(">> listing servers");
|
logger.debug(">> listing servers");
|
||||||
Set<ComputeMetadata> servers = Sets.newHashSet();
|
Map<String, NodeMetadata> nodes = doGetNodes();
|
||||||
|
logger.debug("<< list(%d)", nodes.size());
|
||||||
|
return nodes;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Map<String, NodeMetadata> doGetNodes() {
|
||||||
|
Set<NodeMetadata> nodes = Sets.newHashSet();
|
||||||
for (Region region : ImmutableSet.of(Region.US_EAST_1, Region.US_WEST_1, Region.EU_WEST_1)) {
|
for (Region region : ImmutableSet.of(Region.US_EAST_1, Region.US_WEST_1, Region.EU_WEST_1)) {
|
||||||
Iterables.addAll(servers, Iterables.transform(Iterables.concat(ec2Client
|
Iterables.addAll(nodes, Iterables.transform(Iterables.concat(ec2Client
|
||||||
.getInstanceServices().describeInstancesInRegion(region)),
|
.getInstanceServices().describeInstancesInRegion(region)),
|
||||||
new Function<RunningInstance, ComputeMetadata>() {
|
runningInstanceToNodeMetadata));
|
||||||
@Override
|
|
||||||
public ComputeMetadata apply(RunningInstance from) {
|
|
||||||
return new ComputeMetadataImpl(ComputeType.NODE, from.getId(), from
|
|
||||||
.getKeyName(), from.getRegion().toString(), null, ImmutableMap
|
|
||||||
.<String, String> of());
|
|
||||||
}
|
}
|
||||||
}));
|
return Maps.uniqueIndex(nodes, METADATA_TO_ID);
|
||||||
}
|
|
||||||
logger.debug("<< list(%d)", servers.size());
|
|
||||||
return servers;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void destroyNode(ComputeMetadata node) {
|
public void destroyNode(ComputeMetadata metadata) {
|
||||||
checkArgument(node.getType() == ComputeType.NODE, "this is only valid for nodes, not "
|
checkArgument(metadata.getType() == ComputeType.NODE, "this is only valid for nodes, not "
|
||||||
+ node.getType());
|
+ metadata.getType());
|
||||||
checkNotNull(node.getId(), "node.id");
|
checkNotNull(metadata.getId(), "node.id");
|
||||||
|
NodeMetadata node = metadata instanceof NodeMetadata ? NodeMetadata.class.cast(metadata)
|
||||||
|
: getNodeMetadata(metadata);
|
||||||
|
String tag = checkNotNull(node.getTag(), "node.tag");
|
||||||
|
|
||||||
Region region = getRegionFromNodeOrDefault(node);
|
Region region = getRegionFromNodeOrDefault(node);
|
||||||
for (RunningInstance runningInstance : getAllRunningInstancesInRegion(region, node.getId())) {
|
|
||||||
// grab the old keyname
|
RunningInstance instance = getInstance(node, region);
|
||||||
String name = runningInstance.getKeyName();
|
if (instance.getInstanceState() != InstanceState.TERMINATED) {
|
||||||
logger.debug(">> terminating instance(%s)", node.getId());
|
logger.debug(">> terminating instance(%s)", node.getId());
|
||||||
|
boolean success = false;
|
||||||
|
while (!success) {
|
||||||
ec2Client.getInstanceServices().terminateInstancesInRegion(region, node.getId());
|
ec2Client.getInstanceServices().terminateInstancesInRegion(region, node.getId());
|
||||||
boolean success = instanceStateTerminated.apply(runningInstance);
|
success = instanceStateTerminated.apply(getInstance(node, region));
|
||||||
|
}
|
||||||
logger.debug("<< terminated instance(%s) success(%s)", node.getId(), success);
|
logger.debug("<< terminated instance(%s) success(%s)", node.getId(), success);
|
||||||
logger.debug(">> deleting keyPair(%s)", name);
|
}
|
||||||
ec2Client.getKeyPairServices().deleteKeyPairInRegion(region, name);
|
if (Iterables.all(doGetNodes(tag), new Predicate<NodeMetadata>() {
|
||||||
logger.debug("<< deleted keyPair(%s)", name);
|
@Override
|
||||||
logger.debug(">> deleting securityGroup(%s)", name);
|
public boolean apply(NodeMetadata input) {
|
||||||
ec2Client.getSecurityGroupServices().deleteSecurityGroupInRegion(region, name);
|
return input.getState() == NodeState.TERMINATED;
|
||||||
logger.debug("<< deleted securityGroup(%s)", name);
|
}
|
||||||
|
})) {
|
||||||
|
deleteKeyPair(region, tag);
|
||||||
|
deleteSecurityGroup(region, tag);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private RunningInstance getInstance(NodeMetadata node, Region region) {
|
||||||
|
return Iterables.getOnlyElement(getAllRunningInstancesInRegion(region, node.getId()));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void deleteSecurityGroup(Region region, String tag) {
|
||||||
|
if (ec2Client.getSecurityGroupServices().describeSecurityGroupsInRegion(region, tag).size() > 0) {
|
||||||
|
logger.debug(">> deleting securityGroup(%s)", tag);
|
||||||
|
ec2Client.getSecurityGroupServices().deleteSecurityGroupInRegion(region, tag);
|
||||||
|
securityGroupMap.remove(new PortsRegionTag(region, tag, null)); // TODO: test this clear
|
||||||
|
// happens
|
||||||
|
logger.debug("<< deleted securityGroup(%s)", tag);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void deleteKeyPair(Region region, String tag) {
|
||||||
|
if (ec2Client.getKeyPairServices().describeKeyPairsInRegion(region, tag).size() > 0) {
|
||||||
|
logger.debug(">> deleting keyPair(%s)", tag);
|
||||||
|
ec2Client.getKeyPairServices().deleteKeyPairInRegion(region, tag);
|
||||||
|
credentialsMap.remove(new RegionTag(region, tag)); // TODO: test this clear happens
|
||||||
|
logger.debug("<< deleted keyPair(%s)", tag);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private Region getRegionFromNodeOrDefault(ComputeMetadata node) {
|
private Region getRegionFromNodeOrDefault(ComputeMetadata node) {
|
||||||
Region region = node.getLocation() != null ? Region.fromValue(node.getLocation())
|
Location location = getLocations().get(node.getLocationId());
|
||||||
: Region.DEFAULT;
|
Region region = location.getScope() == LocationScope.REGION ? Region.fromValue(location
|
||||||
|
.getId()) : Region.fromValue(location.getParent());
|
||||||
return region;
|
return region;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Set<? extends Size> listSizes() {
|
public void destroyNodes(String tag) { // TODO parallel
|
||||||
|
logger.debug(">> terminating servers by tag(%s)", tag);
|
||||||
|
Set<ListenableFuture<Void>> responses = Sets.newHashSet();
|
||||||
|
for (final NodeMetadata node : doGetNodes(tag)) {
|
||||||
|
responses.add(ConcurrentUtils.makeListenable(executor.submit(new Callable<Void>() {
|
||||||
|
@Override
|
||||||
|
public Void call() throws Exception {
|
||||||
|
destroyNode(node);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}), executor));
|
||||||
|
}
|
||||||
|
ConcurrentUtils.awaitCompletion(responses, executor, null, logger, "nodes");
|
||||||
|
logger.debug("<< destroyed");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Map<String, ? extends Location> getLocations() {
|
||||||
|
return locations.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public NodeSet getNodes(String tag) {
|
||||||
|
logger.debug(">> listing servers by tag(%s)", tag);
|
||||||
|
NodeSet nodes = doGetNodes(tag);
|
||||||
|
logger.debug("<< list(%d)", nodes.size());
|
||||||
|
return nodes;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected NodeSet doGetNodes(String tag) {
|
||||||
|
return new NodeSetImpl(Iterables.filter(doGetNodes().values(), new NodeMatchesTag(tag)));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Map<String, ? extends Size> getSizes() {
|
||||||
return sizes.get();
|
return sizes.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Set<? extends Image> listImages() {
|
public Map<String, ? extends Image> getImages() {
|
||||||
return images.get();
|
return images.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
package org.jclouds.aws.ec2.compute.config;
|
package org.jclouds.aws.ec2.compute.config;
|
||||||
|
|
||||||
import static org.jclouds.aws.ec2.options.DescribeImagesOptions.Builder.ownedBy;
|
import static org.jclouds.aws.ec2.options.DescribeImagesOptions.Builder.ownedBy;
|
||||||
|
import static org.jclouds.aws.ec2.reference.EC2Constants.PROPERTY_EC2_AMI_OWNERS;
|
||||||
|
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
@ -37,21 +38,36 @@ import org.jclouds.aws.ec2.EC2;
|
||||||
import org.jclouds.aws.ec2.EC2AsyncClient;
|
import org.jclouds.aws.ec2.EC2AsyncClient;
|
||||||
import org.jclouds.aws.ec2.EC2Client;
|
import org.jclouds.aws.ec2.EC2Client;
|
||||||
import org.jclouds.aws.ec2.compute.EC2ComputeService;
|
import org.jclouds.aws.ec2.compute.EC2ComputeService;
|
||||||
import org.jclouds.aws.ec2.compute.domain.EC2Image;
|
|
||||||
import org.jclouds.aws.ec2.compute.domain.EC2Size;
|
import org.jclouds.aws.ec2.compute.domain.EC2Size;
|
||||||
|
import org.jclouds.aws.ec2.compute.domain.KeyPairCredentials;
|
||||||
|
import org.jclouds.aws.ec2.compute.domain.PortsRegionTag;
|
||||||
|
import org.jclouds.aws.ec2.compute.domain.RegionTag;
|
||||||
|
import org.jclouds.aws.ec2.compute.functions.CreateKeyPairIfNeeded;
|
||||||
|
import org.jclouds.aws.ec2.compute.functions.CreateSecurityGroupIfNeeded;
|
||||||
import org.jclouds.aws.ec2.config.EC2ContextModule;
|
import org.jclouds.aws.ec2.config.EC2ContextModule;
|
||||||
|
import org.jclouds.aws.ec2.domain.AvailabilityZone;
|
||||||
import org.jclouds.compute.ComputeService;
|
import org.jclouds.compute.ComputeService;
|
||||||
import org.jclouds.compute.ComputeServiceContext;
|
import org.jclouds.compute.ComputeServiceContext;
|
||||||
|
import org.jclouds.compute.domain.Architecture;
|
||||||
|
import org.jclouds.compute.domain.ComputeMetadata;
|
||||||
import org.jclouds.compute.domain.Image;
|
import org.jclouds.compute.domain.Image;
|
||||||
import org.jclouds.compute.domain.OsFamily;
|
import org.jclouds.compute.domain.OsFamily;
|
||||||
import org.jclouds.compute.domain.Size;
|
import org.jclouds.compute.domain.Size;
|
||||||
|
import org.jclouds.compute.domain.internal.ImageImpl;
|
||||||
import org.jclouds.compute.internal.ComputeServiceContextImpl;
|
import org.jclouds.compute.internal.ComputeServiceContextImpl;
|
||||||
import org.jclouds.compute.reference.ComputeServiceConstants;
|
import org.jclouds.compute.reference.ComputeServiceConstants;
|
||||||
import org.jclouds.domain.ResourceLocation;
|
import org.jclouds.domain.Location;
|
||||||
|
import org.jclouds.domain.LocationScope;
|
||||||
|
import org.jclouds.domain.internal.LocationImpl;
|
||||||
import org.jclouds.logging.Logger;
|
import org.jclouds.logging.Logger;
|
||||||
import org.jclouds.rest.RestContext;
|
import org.jclouds.rest.RestContext;
|
||||||
|
|
||||||
|
import com.google.common.base.Function;
|
||||||
|
import com.google.common.base.Splitter;
|
||||||
|
import com.google.common.collect.ImmutableMap;
|
||||||
import com.google.common.collect.ImmutableSet;
|
import com.google.common.collect.ImmutableSet;
|
||||||
|
import com.google.common.collect.Iterables;
|
||||||
|
import com.google.common.collect.Maps;
|
||||||
import com.google.common.collect.Sets;
|
import com.google.common.collect.Sets;
|
||||||
import com.google.inject.Provides;
|
import com.google.inject.Provides;
|
||||||
|
|
||||||
|
@ -68,6 +84,22 @@ public class EC2ComputeServiceContextModule extends EC2ContextModule {
|
||||||
bind(ComputeService.class).to(EC2ComputeService.class).asEagerSingleton();
|
bind(ComputeService.class).to(EC2ComputeService.class).asEagerSingleton();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Provides
|
||||||
|
@Singleton
|
||||||
|
protected final Map<RegionTag, KeyPairCredentials> credentialsMap(CreateKeyPairIfNeeded in) {
|
||||||
|
// doesn't seem to clear when someone issues remove(key)
|
||||||
|
// return new MapMaker().makeComputingMap(in);
|
||||||
|
return Maps.newLinkedHashMap();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Provides
|
||||||
|
@Singleton
|
||||||
|
protected final Map<PortsRegionTag, String> securityGroupMap(CreateSecurityGroupIfNeeded in) {
|
||||||
|
// doesn't seem to clear when someone issues remove(key)
|
||||||
|
// return new MapMaker().makeComputingMap(in);
|
||||||
|
return Maps.newLinkedHashMap();
|
||||||
|
}
|
||||||
|
|
||||||
@Provides
|
@Provides
|
||||||
@Singleton
|
@Singleton
|
||||||
ComputeServiceContext provideContext(ComputeService computeService,
|
ComputeServiceContext provideContext(ComputeService computeService,
|
||||||
|
@ -77,16 +109,47 @@ public class EC2ComputeServiceContextModule extends EC2ContextModule {
|
||||||
|
|
||||||
@Provides
|
@Provides
|
||||||
@Singleton
|
@Singleton
|
||||||
Set<? extends Size> provideSizes() {
|
Function<ComputeMetadata, String> indexer() {
|
||||||
return ImmutableSet.of(EC2Size.C1_MEDIUM, EC2Size.C1_XLARGE, EC2Size.M1_LARGE,
|
return new Function<ComputeMetadata, String>() {
|
||||||
EC2Size.M1_SMALL, EC2Size.M1_XLARGE, EC2Size.M2_2XLARGE, EC2Size.M2_4XLARGE);
|
@Override
|
||||||
|
public String apply(ComputeMetadata from) {
|
||||||
|
return from.getId();
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@Provides
|
@Provides
|
||||||
@Singleton
|
@Singleton
|
||||||
@ResourceLocation
|
Map<String, ? extends Size> provideSizes(Function<ComputeMetadata, String> indexer) {
|
||||||
String getRegion(@EC2 Region region) {
|
return Maps.uniqueIndex(ImmutableSet.of(EC2Size.C1_MEDIUM, EC2Size.C1_XLARGE,
|
||||||
return region.value();
|
EC2Size.M1_LARGE, EC2Size.M1_SMALL, EC2Size.M1_XLARGE, EC2Size.M2_2XLARGE,
|
||||||
|
EC2Size.M2_4XLARGE), indexer);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Provides
|
||||||
|
@Singleton
|
||||||
|
Map<String, ? extends Location> provideLocations(Map<AvailabilityZone, Region> map) {
|
||||||
|
Set<Location> locations = Sets.newHashSet();
|
||||||
|
for (AvailabilityZone zone : map.keySet()) {
|
||||||
|
locations.add(new LocationImpl(LocationScope.ZONE, zone.toString(), zone.toString(), map
|
||||||
|
.get(zone).toString(), true));
|
||||||
|
}
|
||||||
|
for (Region region : map.values()) {
|
||||||
|
locations.add(new LocationImpl(LocationScope.REGION, region.toString(), region.toString(),
|
||||||
|
null, true));
|
||||||
|
}
|
||||||
|
return Maps.uniqueIndex(locations, new Function<Location, String>() {
|
||||||
|
@Override
|
||||||
|
public String apply(Location from) {
|
||||||
|
return from.getId();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Provides
|
||||||
|
@Singleton
|
||||||
|
Location getDefaultLocation(@EC2 Region region, Map<String, ? extends Location> map) {
|
||||||
|
return map.get(region.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class LogHolder {
|
private static class LogHolder {
|
||||||
|
@ -101,13 +164,24 @@ public class EC2ComputeServiceContextModule extends EC2ContextModule {
|
||||||
|
|
||||||
@Provides
|
@Provides
|
||||||
@Singleton
|
@Singleton
|
||||||
protected Set<? extends Image> provideImages(final EC2Client sync, Map<Region, URI> regionMap,
|
@Named(PROPERTY_EC2_AMI_OWNERS)
|
||||||
LogHolder holder) throws InterruptedException, ExecutionException, TimeoutException {
|
String[] amiOwners(@Named(PROPERTY_EC2_AMI_OWNERS) String amiOwners) {
|
||||||
|
return Iterables.toArray(Splitter.on('.').split(amiOwners), String.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Provides
|
||||||
|
@Singleton
|
||||||
|
protected Map<String, ? extends Image> provideImages(final EC2Client sync,
|
||||||
|
Map<Region, URI> regionMap, LogHolder holder,
|
||||||
|
Function<ComputeMetadata, String> indexer,
|
||||||
|
@Named(PROPERTY_EC2_AMI_OWNERS) String[] amiOwners) throws InterruptedException,
|
||||||
|
ExecutionException, TimeoutException {
|
||||||
final Set<Image> images = Sets.newHashSet();
|
final Set<Image> images = Sets.newHashSet();
|
||||||
holder.logger.debug(">> providing images");
|
holder.logger.debug(">> providing images");
|
||||||
|
|
||||||
for (final Region region : regionMap.keySet()) {
|
for (final Region region : regionMap.keySet()) {
|
||||||
for (final org.jclouds.aws.ec2.domain.Image from : sync.getAMIServices()
|
for (final org.jclouds.aws.ec2.domain.Image from : sync.getAMIServices()
|
||||||
.describeImagesInRegion(region, ownedBy("063491364108"))) {
|
.describeImagesInRegion(region, ownedBy(amiOwners))) {
|
||||||
OsFamily os = null;
|
OsFamily os = null;
|
||||||
String osDescription = from.getImageLocation();
|
String osDescription = from.getImageLocation();
|
||||||
String version = "";
|
String version = "";
|
||||||
|
@ -116,16 +190,28 @@ public class EC2ComputeServiceContextModule extends EC2ContextModule {
|
||||||
if (matcher.find()) {
|
if (matcher.find()) {
|
||||||
try {
|
try {
|
||||||
os = OsFamily.fromValue(matcher.group(1));
|
os = OsFamily.fromValue(matcher.group(1));
|
||||||
matcher.group(2);//TODO no field for os version
|
matcher.group(2);// TODO no field for os version
|
||||||
version = matcher.group(3);
|
version = matcher.group(3);
|
||||||
} catch (IllegalArgumentException e) {
|
} catch (IllegalArgumentException e) {
|
||||||
holder.logger.debug("<< didn't match os(%s)", matcher.group(1));
|
holder.logger.debug("<< didn't match os(%s)", matcher.group(1));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
images.add(new EC2Image(from, os, osDescription, version));
|
images
|
||||||
|
.add(new ImageImpl(
|
||||||
|
from.getId(),
|
||||||
|
from.getName(),
|
||||||
|
region.toString(),
|
||||||
|
null,
|
||||||
|
ImmutableMap.<String, String> of(),
|
||||||
|
from.getDescription(),
|
||||||
|
version,
|
||||||
|
os,
|
||||||
|
osDescription,
|
||||||
|
from.getArchitecture() == org.jclouds.aws.ec2.domain.Image.Architecture.I386 ? Architecture.X86_32
|
||||||
|
: Architecture.X86_64));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
holder.logger.debug("<< images(%d)", images.size());
|
holder.logger.debug("<< images(%d)", images.size());
|
||||||
return images;
|
return Maps.uniqueIndex(images, indexer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,139 +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.domain;
|
|
||||||
|
|
||||||
import org.jclouds.compute.domain.Architecture;
|
|
||||||
import org.jclouds.compute.domain.Image;
|
|
||||||
import org.jclouds.compute.domain.OsFamily;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @author Adrian Cole
|
|
||||||
*/
|
|
||||||
public class EC2Image implements Image {
|
|
||||||
private final org.jclouds.aws.ec2.domain.Image image;
|
|
||||||
private final OsFamily os;
|
|
||||||
private final String osDescription;
|
|
||||||
private final String version;
|
|
||||||
|
|
||||||
public EC2Image(org.jclouds.aws.ec2.domain.Image image, OsFamily os, String osDescription,
|
|
||||||
String version) {
|
|
||||||
this.image = image;
|
|
||||||
this.os = os;
|
|
||||||
this.osDescription = osDescription;
|
|
||||||
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 OsFamily getOsFamily() {
|
|
||||||
return os;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getOsDescription() {
|
|
||||||
return osDescription;
|
|
||||||
}
|
|
||||||
|
|
||||||
@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 + ((osDescription == null) ? 0 : osDescription.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 (osDescription == null) {
|
|
||||||
if (other.osDescription != null)
|
|
||||||
return false;
|
|
||||||
} else if (!osDescription.equals(other.osDescription))
|
|
||||||
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="
|
|
||||||
+ getOsFamily() + ", operatingSystemVersion=" + getOsDescription()
|
|
||||||
+ ", description=" + getDescription() + "]";
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -27,6 +27,7 @@ import org.jclouds.aws.ec2.domain.InstanceType;
|
||||||
import org.jclouds.compute.domain.Architecture;
|
import org.jclouds.compute.domain.Architecture;
|
||||||
import org.jclouds.compute.domain.internal.SizeImpl;
|
import org.jclouds.compute.domain.internal.SizeImpl;
|
||||||
|
|
||||||
|
import com.google.common.collect.ImmutableMap;
|
||||||
import com.google.common.collect.ImmutableSet;
|
import com.google.common.collect.ImmutableSet;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -34,11 +35,14 @@ import com.google.common.collect.ImmutableSet;
|
||||||
* @author Adrian Cole
|
* @author Adrian Cole
|
||||||
*/
|
*/
|
||||||
public class EC2Size extends SizeImpl {
|
public class EC2Size extends SizeImpl {
|
||||||
|
/** The serialVersionUID */
|
||||||
|
private static final long serialVersionUID = 8605688733788974797L;
|
||||||
private final InstanceType instanceType;
|
private final InstanceType instanceType;
|
||||||
|
|
||||||
EC2Size(InstanceType instanceType, Integer cores, Integer ram, Integer disk,
|
EC2Size(InstanceType instanceType, Integer cores, Integer ram, Integer disk,
|
||||||
Iterable<Architecture> supportedArchitectures) {
|
Iterable<Architecture> supportedArchitectures) {
|
||||||
super(instanceType.toString(), cores, ram, disk, supportedArchitectures);
|
super(instanceType.toString(), instanceType.toString(), null, null, ImmutableMap
|
||||||
|
.<String, String> of(),cores, ram, disk, supportedArchitectures);
|
||||||
this.instanceType = instanceType;
|
this.instanceType = instanceType;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,39 @@
|
||||||
|
package org.jclouds.aws.ec2.compute.domain;
|
||||||
|
|
||||||
|
import org.jclouds.aws.ec2.domain.KeyPair;
|
||||||
|
import org.jclouds.domain.Credentials;
|
||||||
|
|
||||||
|
public class KeyPairCredentials extends Credentials {
|
||||||
|
private final KeyPair keyPair;
|
||||||
|
|
||||||
|
public KeyPairCredentials(String account, KeyPair keyPair) {
|
||||||
|
super(account, keyPair.getKeyMaterial());
|
||||||
|
this.keyPair = keyPair;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
final int prime = 31;
|
||||||
|
int result = super.hashCode();
|
||||||
|
result = prime * result + ((keyPair == null) ? 0 : keyPair.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;
|
||||||
|
KeyPairCredentials other = (KeyPairCredentials) obj;
|
||||||
|
if (keyPair == null) {
|
||||||
|
if (other.keyPair != null)
|
||||||
|
return false;
|
||||||
|
} else if (!keyPair.equals(other.keyPair))
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,20 @@
|
||||||
|
package org.jclouds.aws.ec2.compute.domain;
|
||||||
|
|
||||||
|
import org.jclouds.aws.domain.Region;
|
||||||
|
|
||||||
|
public class PortsRegionTag extends RegionTag {
|
||||||
|
private final int[] ports;
|
||||||
|
|
||||||
|
public PortsRegionTag(Region region, String tag, int[] ports) {
|
||||||
|
super(region, tag);
|
||||||
|
this.ports = ports;
|
||||||
|
}
|
||||||
|
|
||||||
|
// intentionally not overriding equals or hash-code so that we can search only by region/tag in a
|
||||||
|
// map
|
||||||
|
|
||||||
|
public int[] getPorts() {
|
||||||
|
return ports;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,54 @@
|
||||||
|
package org.jclouds.aws.ec2.compute.domain;
|
||||||
|
|
||||||
|
import org.jclouds.aws.domain.Region;
|
||||||
|
|
||||||
|
|
||||||
|
public class RegionTag {
|
||||||
|
protected final Region region;
|
||||||
|
protected final String tag;
|
||||||
|
|
||||||
|
public RegionTag(Region region, String tag) {
|
||||||
|
this.region = region;
|
||||||
|
this.tag = tag;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
final int prime = 31;
|
||||||
|
int result = 1;
|
||||||
|
result = prime * result + ((region == null) ? 0 : region.hashCode());
|
||||||
|
result = prime * result + ((tag == null) ? 0 : tag.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;
|
||||||
|
RegionTag other = (RegionTag) obj;
|
||||||
|
if (region == null) {
|
||||||
|
if (other.region != null)
|
||||||
|
return false;
|
||||||
|
} else if (!region.equals(other.region))
|
||||||
|
return false;
|
||||||
|
if (tag == null) {
|
||||||
|
if (other.tag != null)
|
||||||
|
return false;
|
||||||
|
} else if (!tag.equals(other.tag))
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Region getRegion() {
|
||||||
|
return region;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getTag() {
|
||||||
|
return tag;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,54 @@
|
||||||
|
package org.jclouds.aws.ec2.compute.functions;
|
||||||
|
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
import javax.inject.Inject;
|
||||||
|
import javax.inject.Named;
|
||||||
|
import javax.inject.Singleton;
|
||||||
|
|
||||||
|
import org.jclouds.aws.AWSResponseException;
|
||||||
|
import org.jclouds.aws.domain.Region;
|
||||||
|
import org.jclouds.aws.ec2.EC2Client;
|
||||||
|
import org.jclouds.aws.ec2.compute.domain.KeyPairCredentials;
|
||||||
|
import org.jclouds.aws.ec2.compute.domain.RegionTag;
|
||||||
|
import org.jclouds.aws.ec2.domain.KeyPair;
|
||||||
|
import org.jclouds.compute.reference.ComputeServiceConstants;
|
||||||
|
import org.jclouds.logging.Logger;
|
||||||
|
|
||||||
|
import com.google.common.base.Function;
|
||||||
|
import com.google.common.collect.Iterables;
|
||||||
|
|
||||||
|
@Singleton
|
||||||
|
public class CreateKeyPairIfNeeded implements Function<RegionTag, KeyPairCredentials> {
|
||||||
|
@Resource
|
||||||
|
@Named(ComputeServiceConstants.COMPUTE_LOGGER)
|
||||||
|
protected Logger logger = Logger.NULL;
|
||||||
|
protected final EC2Client ec2Client;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
public CreateKeyPairIfNeeded(EC2Client ec2Client) {
|
||||||
|
this.ec2Client = ec2Client;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public KeyPairCredentials apply(RegionTag from) {
|
||||||
|
return new KeyPairCredentials("root", createKeyPairInRegion(from.getRegion(), from.getTag()));
|
||||||
|
}
|
||||||
|
|
||||||
|
private KeyPair createKeyPairInRegion(Region region, String name) {
|
||||||
|
logger.debug(">> creating keyPair region(%s) name(%s)", region, name);
|
||||||
|
KeyPair keyPair;
|
||||||
|
try {
|
||||||
|
keyPair = ec2Client.getKeyPairServices().createKeyPairInRegion(region, name);
|
||||||
|
logger.debug("<< created keyPair(%s)", keyPair.getKeyName());
|
||||||
|
} catch (AWSResponseException e) {
|
||||||
|
if (e.getError().getCode().equals("InvalidKeyPair.Duplicate")) {
|
||||||
|
keyPair = Iterables.getLast(ec2Client.getKeyPairServices().describeKeyPairsInRegion(
|
||||||
|
region, name));
|
||||||
|
logger.debug("<< reused keyPair(%s)", keyPair.getKeyName());
|
||||||
|
} else {
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return keyPair;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,57 @@
|
||||||
|
package org.jclouds.aws.ec2.compute.functions;
|
||||||
|
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
import javax.inject.Inject;
|
||||||
|
import javax.inject.Named;
|
||||||
|
import javax.inject.Singleton;
|
||||||
|
|
||||||
|
import org.jclouds.aws.AWSResponseException;
|
||||||
|
import org.jclouds.aws.domain.Region;
|
||||||
|
import org.jclouds.aws.ec2.EC2Client;
|
||||||
|
import org.jclouds.aws.ec2.compute.domain.PortsRegionTag;
|
||||||
|
import org.jclouds.aws.ec2.domain.IpProtocol;
|
||||||
|
import org.jclouds.compute.reference.ComputeServiceConstants;
|
||||||
|
import org.jclouds.logging.Logger;
|
||||||
|
|
||||||
|
import com.google.common.base.Function;
|
||||||
|
|
||||||
|
@Singleton
|
||||||
|
public class CreateSecurityGroupIfNeeded implements Function<PortsRegionTag, String> {
|
||||||
|
@Resource
|
||||||
|
@Named(ComputeServiceConstants.COMPUTE_LOGGER)
|
||||||
|
protected Logger logger = Logger.NULL;
|
||||||
|
protected final EC2Client ec2Client;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
public CreateSecurityGroupIfNeeded(EC2Client ec2Client) {
|
||||||
|
this.ec2Client = ec2Client;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String apply(PortsRegionTag from) {
|
||||||
|
createSecurityGroupInRegion(from.getRegion(), from.getTag(), from.getPorts());
|
||||||
|
return from.getTag();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void createSecurityGroupInRegion(Region region, String name, int... ports) {
|
||||||
|
logger.debug(">> creating securityGroup region(%s) name(%s)", region, name);
|
||||||
|
try {
|
||||||
|
ec2Client.getSecurityGroupServices().createSecurityGroupInRegion(region, name, name);
|
||||||
|
logger.debug("<< created securityGroup(%s)", name);
|
||||||
|
for (int port : ports) {
|
||||||
|
logger.debug(">> authorizing securityGroup region(%s) name(%s) port(%s)", region, name,
|
||||||
|
port);
|
||||||
|
ec2Client.getSecurityGroupServices().authorizeSecurityGroupIngressInRegion(region,
|
||||||
|
name, IpProtocol.TCP, port, port, "0.0.0.0/0");
|
||||||
|
logger.debug("<< authorized securityGroup(%s)", name);
|
||||||
|
}
|
||||||
|
} catch (AWSResponseException e) {
|
||||||
|
if (e.getError().getCode().equals("InvalidGroup.Duplicate")) {
|
||||||
|
logger.debug("<< reused securityGroup(%s)", name);
|
||||||
|
} else {
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,63 @@
|
||||||
|
package org.jclouds.aws.ec2.compute.functions;
|
||||||
|
|
||||||
|
import java.net.InetAddress;
|
||||||
|
import java.net.URI;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import javax.inject.Inject;
|
||||||
|
import javax.inject.Singleton;
|
||||||
|
|
||||||
|
import org.jclouds.aws.ec2.compute.domain.KeyPairCredentials;
|
||||||
|
import org.jclouds.aws.ec2.compute.domain.RegionTag;
|
||||||
|
import org.jclouds.aws.ec2.domain.InstanceState;
|
||||||
|
import org.jclouds.aws.ec2.domain.RunningInstance;
|
||||||
|
import org.jclouds.compute.domain.NodeMetadata;
|
||||||
|
import org.jclouds.compute.domain.NodeState;
|
||||||
|
import org.jclouds.compute.domain.internal.NodeMetadataImpl;
|
||||||
|
import org.jclouds.domain.Credentials;
|
||||||
|
|
||||||
|
import com.google.common.base.Function;
|
||||||
|
import com.google.common.collect.ImmutableMap;
|
||||||
|
import com.google.common.collect.ImmutableSet;
|
||||||
|
|
||||||
|
@Singleton
|
||||||
|
public class RunningInstanceToNodeMetadata implements Function<RunningInstance, NodeMetadata> {
|
||||||
|
private static final Map<InstanceState, NodeState> instanceToNodeState = ImmutableMap
|
||||||
|
.<InstanceState, NodeState> builder().put(InstanceState.PENDING, NodeState.PENDING)
|
||||||
|
.put(InstanceState.RUNNING, NodeState.RUNNING).put(InstanceState.SHUTTING_DOWN,
|
||||||
|
NodeState.PENDING).put(InstanceState.TERMINATED, NodeState.TERMINATED).build();
|
||||||
|
private final Map<RegionTag, KeyPairCredentials> credentialsMap;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
public RunningInstanceToNodeMetadata(Map<RegionTag, KeyPairCredentials> credentialsMap) {
|
||||||
|
this.credentialsMap = credentialsMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public NodeMetadata apply(RunningInstance from) {
|
||||||
|
String id = from.getId();
|
||||||
|
String name = null; // user doesn't determine a node name;
|
||||||
|
URI uri = null; // no uri to get rest access to host info
|
||||||
|
Map<String, String> userMetadata = ImmutableMap.<String, String> of();
|
||||||
|
String tag = from.getKeyName();
|
||||||
|
NodeState state = instanceToNodeState.get(from.getInstanceState());
|
||||||
|
Set<InetAddress> publicAddresses = nullSafeSet(from.getIpAddress());
|
||||||
|
Set<InetAddress> privateAddresses = nullSafeSet(from.getPrivateIpAddress());
|
||||||
|
Credentials credentials = credentialsMap.containsKey(new RegionTag(from.getRegion(), tag)) ? credentialsMap
|
||||||
|
.get(new RegionTag(from.getRegion(), tag))
|
||||||
|
: null;
|
||||||
|
String locationId = from.getAvailabilityZone().toString();
|
||||||
|
Map<String, String> extra = ImmutableMap.<String, String> of();
|
||||||
|
return new NodeMetadataImpl(id, name, locationId, uri, userMetadata, tag, state,
|
||||||
|
publicAddresses, privateAddresses, extra, credentials);
|
||||||
|
}
|
||||||
|
|
||||||
|
Set<InetAddress> nullSafeSet(InetAddress in) {
|
||||||
|
if (in == null) {
|
||||||
|
return ImmutableSet.<InetAddress> of();
|
||||||
|
}
|
||||||
|
return ImmutableSet.<InetAddress> of(in);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -32,6 +32,7 @@ import org.jclouds.aws.ec2.domain.AvailabilityZone;
|
||||||
import org.jclouds.aws.ec2.domain.AvailabilityZoneInfo;
|
import org.jclouds.aws.ec2.domain.AvailabilityZoneInfo;
|
||||||
import org.jclouds.aws.ec2.domain.RunningInstance;
|
import org.jclouds.aws.ec2.domain.RunningInstance;
|
||||||
import org.jclouds.aws.ec2.predicates.InstanceStateRunning;
|
import org.jclouds.aws.ec2.predicates.InstanceStateRunning;
|
||||||
|
import org.jclouds.aws.ec2.predicates.InstanceStateTerminated;
|
||||||
import org.jclouds.aws.ec2.reference.EC2Constants;
|
import org.jclouds.aws.ec2.reference.EC2Constants;
|
||||||
import org.jclouds.aws.ec2.services.AMIAsyncClient;
|
import org.jclouds.aws.ec2.services.AMIAsyncClient;
|
||||||
import org.jclouds.aws.ec2.services.AMIClient;
|
import org.jclouds.aws.ec2.services.AMIClient;
|
||||||
|
@ -91,7 +92,8 @@ public class EC2RestClientModule extends AbstractModule {
|
||||||
@Provides
|
@Provides
|
||||||
@Singleton
|
@Singleton
|
||||||
@Named("TERMINATED")
|
@Named("TERMINATED")
|
||||||
protected Predicate<RunningInstance> instanceStateTerminated(InstanceStateRunning stateTerminated) {
|
protected Predicate<RunningInstance> instanceStateTerminated(
|
||||||
|
InstanceStateTerminated stateTerminated) {
|
||||||
return new RetryablePredicate<RunningInstance>(stateTerminated, 600, 50,
|
return new RetryablePredicate<RunningInstance>(stateTerminated, 600, 50,
|
||||||
TimeUnit.MILLISECONDS);
|
TimeUnit.MILLISECONDS);
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
package org.jclouds.aws.ec2.reference;
|
package org.jclouds.aws.ec2.reference;
|
||||||
|
|
||||||
import org.jclouds.aws.reference.AWSConstants;
|
import org.jclouds.aws.reference.AWSConstants;
|
||||||
|
import org.jclouds.compute.ComputeService;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Configuration properties and constants used in EC2 connections.
|
* Configuration properties and constants used in EC2 connections.
|
||||||
|
@ -27,5 +28,10 @@ import org.jclouds.aws.reference.AWSConstants;
|
||||||
*/
|
*/
|
||||||
public interface EC2Constants extends AWSConstants {
|
public interface EC2Constants extends AWSConstants {
|
||||||
public static final String PROPERTY_EC2_ENDPOINT = "jclouds.ec2.endpoint";
|
public static final String PROPERTY_EC2_ENDPOINT = "jclouds.ec2.endpoint";
|
||||||
|
/**
|
||||||
|
* Listing the universe of amis is extremely expensive. set this to a comma separated value of
|
||||||
|
* the ami owners you wish to use in {@link ComputeService}
|
||||||
|
*/
|
||||||
|
public static final String PROPERTY_EC2_AMI_OWNERS = "jclouds.ec2.ami-owners";
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -65,6 +65,7 @@ public interface KeyPairAsyncClient {
|
||||||
@EndpointParam(parser = RegionToEndpoint.class) Region region,
|
@EndpointParam(parser = RegionToEndpoint.class) Region region,
|
||||||
@FormParam("KeyName") String keyName);
|
@FormParam("KeyName") String keyName);
|
||||||
|
|
||||||
|
// map resourcenotfoundexception to empty set
|
||||||
/**
|
/**
|
||||||
* @see KeyPairClient#describeKeyPairsInRegion
|
* @see KeyPairClient#describeKeyPairsInRegion
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -34,6 +34,7 @@ import org.jclouds.http.HttpResponse;
|
||||||
import org.jclouds.http.HttpResponseException;
|
import org.jclouds.http.HttpResponseException;
|
||||||
import org.jclouds.logging.Logger;
|
import org.jclouds.logging.Logger;
|
||||||
import org.jclouds.rest.AuthorizationException;
|
import org.jclouds.rest.AuthorizationException;
|
||||||
|
import org.jclouds.rest.ResourceNotFoundException;
|
||||||
import org.jclouds.util.Utils;
|
import org.jclouds.util.Utils;
|
||||||
|
|
||||||
import com.google.common.io.Closeables;
|
import com.google.common.io.Closeables;
|
||||||
|
@ -78,6 +79,8 @@ public class ParseAWSErrorFromXmlContent implements HttpErrorHandler {
|
||||||
if (content.indexOf('<') >= 0) {
|
if (content.indexOf('<') >= 0) {
|
||||||
AWSError error = utils.parseAWSErrorFromContent(command, response, content);
|
AWSError error = utils.parseAWSErrorFromContent(command, response, content);
|
||||||
exception = new AWSResponseException(command, response, error);
|
exception = new AWSResponseException(command, response, error);
|
||||||
|
if (error.getCode().indexOf("NotFound") >= 0)
|
||||||
|
exception = new ResourceNotFoundException(exception);
|
||||||
} else {
|
} else {
|
||||||
exception = new HttpResponseException(command, response, content);
|
exception = new HttpResponseException(command, response, content);
|
||||||
}
|
}
|
||||||
|
|
|
@ -113,11 +113,9 @@ public interface BlobStore {
|
||||||
* fully qualified name relative to the container.
|
* fully qualified name relative to the container.
|
||||||
* @param options
|
* @param options
|
||||||
* byte range or condition options
|
* byte range or condition options
|
||||||
* @return the blob you intended to receive.
|
* @return the blob you intended to receive or null, if it doesn't exist.
|
||||||
* @throws ContainerNotFoundException
|
* @throws ContainerNotFoundException
|
||||||
* if the container doesn't exist
|
* if the container doesn't exist
|
||||||
* @throws KeyNotFoundException
|
|
||||||
* if the container doesn't exist
|
|
||||||
*/
|
*/
|
||||||
Blob getBlob(String container, String name);
|
Blob getBlob(String container, String name);
|
||||||
|
|
||||||
|
|
|
@ -66,7 +66,7 @@ public interface StorageMetadata extends ResourceMetadata<StorageType> {
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
String getLocation();
|
String getLocationId();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* URI used to access this resource
|
* URI used to access this resource
|
||||||
|
|
|
@ -41,9 +41,9 @@ public class BlobMetadataImpl extends StorageMetadataImpl implements Serializabl
|
||||||
private final String contentType;
|
private final String contentType;
|
||||||
private final byte[] contentMD5;
|
private final byte[] contentMD5;
|
||||||
|
|
||||||
public BlobMetadataImpl(String id, String name, @Nullable String location, URI uri, String eTag,
|
public BlobMetadataImpl(String id, String name, @Nullable String location, URI uri,
|
||||||
Long size, Date lastModified, Map<String, String> userMetadata, String contentType,
|
String eTag, Long size, Date lastModified, Map<String, String> userMetadata,
|
||||||
byte[] contentMD5) {
|
String contentType, byte[] contentMD5) {
|
||||||
super(StorageType.BLOB, id, name, location, uri, eTag, size, lastModified, userMetadata);
|
super(StorageType.BLOB, id, name, location, uri, eTag, size, lastModified, userMetadata);
|
||||||
this.contentType = contentType;
|
this.contentType = contentType;
|
||||||
this.contentMD5 = contentMD5;
|
this.contentMD5 = contentMD5;
|
||||||
|
|
|
@ -38,7 +38,7 @@ public class ResourceMetadataToRelativePathResourceMetadata implements
|
||||||
name = name.substring(0, name.length() - suffix.length());
|
name = name.substring(0, name.length() - suffix.length());
|
||||||
}
|
}
|
||||||
return new StorageMetadataImpl(StorageType.RELATIVE_PATH, md.getId(), name, md
|
return new StorageMetadataImpl(StorageType.RELATIVE_PATH, md.getId(), name, md
|
||||||
.getLocation(), md.getUri(), md.getETag(), md.getSize(), md.getLastModified(), md
|
.getLocationId(), md.getUri(), md.getETag(), md.getSize(), md.getLastModified(), md
|
||||||
.getUserMetadata());
|
.getUserMetadata());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -65,7 +65,7 @@ public class BlobStoreUtils {
|
||||||
blob.getMetadata().setETag(blobMeta.getETag());
|
blob.getMetadata().setETag(blobMeta.getETag());
|
||||||
blob.getMetadata().setId(blobMeta.getId());
|
blob.getMetadata().setId(blobMeta.getId());
|
||||||
blob.getMetadata().setLastModified(blobMeta.getLastModified());
|
blob.getMetadata().setLastModified(blobMeta.getLastModified());
|
||||||
blob.getMetadata().setLocation(blobMeta.getLocation());
|
blob.getMetadata().setLocationId(blobMeta.getLocationId());
|
||||||
blob.getMetadata().setUri(blobMeta.getUri());
|
blob.getMetadata().setUri(blobMeta.getUri());
|
||||||
blob.getMetadata().setUserMetadata(blobMeta.getUserMetadata());
|
blob.getMetadata().setUserMetadata(blobMeta.getUserMetadata());
|
||||||
return blob;
|
return blob;
|
||||||
|
|
|
@ -18,16 +18,16 @@
|
||||||
*/
|
*/
|
||||||
package org.jclouds.compute;
|
package org.jclouds.compute;
|
||||||
|
|
||||||
import java.util.Set;
|
import java.util.Map;
|
||||||
|
|
||||||
import org.jclouds.compute.domain.ComputeMetadata;
|
import org.jclouds.compute.domain.ComputeMetadata;
|
||||||
import org.jclouds.compute.domain.CreateNodeResponse;
|
|
||||||
import org.jclouds.compute.domain.Image;
|
import org.jclouds.compute.domain.Image;
|
||||||
import org.jclouds.compute.domain.NodeMetadata;
|
import org.jclouds.compute.domain.NodeMetadata;
|
||||||
|
import org.jclouds.compute.domain.NodeSet;
|
||||||
import org.jclouds.compute.domain.Size;
|
import org.jclouds.compute.domain.Size;
|
||||||
import org.jclouds.compute.domain.Template;
|
import org.jclouds.compute.domain.Template;
|
||||||
import org.jclouds.compute.domain.TemplateBuilder;
|
import org.jclouds.compute.domain.TemplateBuilder;
|
||||||
import org.jclouds.compute.options.RunNodeOptions;
|
import org.jclouds.domain.Location;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Provides portable access to launching compute instances.
|
* Provides portable access to launching compute instances.
|
||||||
|
@ -42,36 +42,62 @@ public interface ComputeService {
|
||||||
TemplateBuilder templateBuilder();
|
TemplateBuilder templateBuilder();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* List all sizes available to the current user
|
* all sizes available to the current user by id
|
||||||
*/
|
*/
|
||||||
Set<? extends Size> listSizes();
|
Map<String, ? extends Size> getSizes();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* List all images available to the current user
|
* all images available to the current user by id
|
||||||
*/
|
*/
|
||||||
Set<? extends Image> listImages();
|
Map<String, ? extends Image> getImages();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* List all nodes available to the current user
|
* all nodes available to the current user by id. If possible, the returned set will include
|
||||||
|
* {@link NodeMetadata} objects.
|
||||||
*/
|
*/
|
||||||
Set<? extends ComputeMetadata> listNodes();
|
Map<String, ? extends ComputeMetadata> getNodes();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new node given the name, and template
|
* all nodes available to the current user by id
|
||||||
|
*/
|
||||||
|
Map<String, ? extends Location> getLocations();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* create and run nodes in the specified tagset. If resources needed are currently available for
|
||||||
|
* this tag, they will be reused. Otherwise, they will be created. Inbound port 22 will always be
|
||||||
|
* opened up.
|
||||||
|
*
|
||||||
|
* @param tag
|
||||||
|
* - common identifier to group nodes by, cannot contain hyphens
|
||||||
|
* @param maxNodes
|
||||||
|
* - how many to fire up.
|
||||||
|
* @param template
|
||||||
|
* - how to configure the nodes
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
CreateNodeResponse runNode(String name, Template template);
|
NodeSet runNodes(String tag, int maxNodes, Template template);
|
||||||
|
|
||||||
CreateNodeResponse runNode(String name, Template template, RunNodeOptions options);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* destroy the node.
|
* destroy the node. If it is the only node in a tag set, the dependent resources will also be
|
||||||
|
* destroyed.
|
||||||
*/
|
*/
|
||||||
void destroyNode(ComputeMetadata node);
|
void destroyNode(ComputeMetadata node);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* destroy the nodes identified by this tag.
|
||||||
|
*/
|
||||||
|
void destroyNodes(String tag);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Find a node by its id
|
* Find a node by its id
|
||||||
*/
|
*/
|
||||||
NodeMetadata getNodeMetadata(ComputeMetadata node);
|
NodeMetadata getNodeMetadata(ComputeMetadata node);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* get all nodes matching the tag.
|
||||||
|
*
|
||||||
|
* @param tag
|
||||||
|
*/
|
||||||
|
NodeSet getNodes(String tag);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -50,11 +50,4 @@ public interface ComputeMetadata extends ResourceMetadata<ComputeType> {
|
||||||
@Override
|
@Override
|
||||||
public String getName();
|
public String getName();
|
||||||
|
|
||||||
/**
|
|
||||||
* location where the node exists..
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public String getLocation();
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,23 +23,22 @@
|
||||||
*/
|
*/
|
||||||
package org.jclouds.compute.domain;
|
package org.jclouds.compute.domain;
|
||||||
|
|
||||||
|
import org.jclouds.compute.domain.internal.ImageImpl;
|
||||||
|
|
||||||
|
import com.google.inject.ImplementedBy;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Running Operating system
|
* Running Operating system
|
||||||
*
|
*
|
||||||
* @author Adrian Cole
|
* @author Adrian Cole
|
||||||
*/
|
*/
|
||||||
public interface Image {
|
@ImplementedBy(ImageImpl.class)
|
||||||
|
public interface Image extends ComputeMetadata {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Unique ID provided by the provider (ami-abcd1234, etc)
|
* Version of the image
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
String getId();
|
String getVersion();
|
||||||
|
|
||||||
/**
|
|
||||||
* Description of the image
|
|
||||||
*/
|
|
||||||
String getDescription();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Operating System
|
* Operating System
|
||||||
|
@ -51,16 +50,6 @@ public interface Image {
|
||||||
*/
|
*/
|
||||||
String getOsDescription();
|
String getOsDescription();
|
||||||
|
|
||||||
/**
|
|
||||||
* Version of the image
|
|
||||||
*/
|
|
||||||
String getVersion();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Geographic location of the image.
|
|
||||||
*/
|
|
||||||
String getLocation();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Operating System
|
* Operating System
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -20,18 +20,43 @@ package org.jclouds.compute.domain;
|
||||||
|
|
||||||
import java.net.InetAddress;
|
import java.net.InetAddress;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.SortedSet;
|
import java.util.Set;
|
||||||
|
|
||||||
|
import org.jclouds.domain.Credentials;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Adrian Cole
|
* @author Adrian Cole
|
||||||
* @author Ivan Meredith
|
* @author Ivan Meredith
|
||||||
*/
|
*/
|
||||||
public interface NodeMetadata extends ComputeMetadata {
|
public interface NodeMetadata extends ComputeMetadata {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tag used for all resources that belong to the same logical group. run, destroy commands are
|
||||||
|
* scoped to tag.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
String getTag();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Current State of the node
|
||||||
|
*/
|
||||||
NodeState getState();
|
NodeState getState();
|
||||||
|
|
||||||
SortedSet<InetAddress> getPublicAddresses();
|
/**
|
||||||
|
* All public IP addresses, potentially including shared ips.
|
||||||
|
*/
|
||||||
|
Set<InetAddress> getPublicAddresses();
|
||||||
|
|
||||||
SortedSet<InetAddress> getPrivateAddresses();
|
/**
|
||||||
|
* All private IP addresses.
|
||||||
|
*/
|
||||||
|
Set<InetAddress> getPrivateAddresses();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If possible, these are returned upon all detail requests. However, it is often the case that
|
||||||
|
* credentials are only available at "run" time.
|
||||||
|
*/
|
||||||
|
Credentials getCredentials();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Other variables present that the provider supports
|
* Other variables present that the provider supports
|
||||||
|
|
|
@ -18,14 +18,11 @@
|
||||||
*/
|
*/
|
||||||
package org.jclouds.compute.domain;
|
package org.jclouds.compute.domain;
|
||||||
|
|
||||||
import org.jclouds.domain.Credentials;
|
import java.util.Set;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Adrian Cole
|
* @author Adrian Cole
|
||||||
* @author Ivan Meredith
|
|
||||||
*/
|
*/
|
||||||
public interface CreateNodeResponse extends NodeMetadata {
|
public interface NodeSet extends Set<NodeMetadata> {
|
||||||
|
|
||||||
Credentials getCredentials();
|
|
||||||
|
|
||||||
}
|
}
|
|
@ -23,6 +23,8 @@
|
||||||
*/
|
*/
|
||||||
package org.jclouds.compute.domain;
|
package org.jclouds.compute.domain;
|
||||||
|
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
import org.jclouds.compute.domain.internal.SizeImpl;
|
import org.jclouds.compute.domain.internal.SizeImpl;
|
||||||
|
|
||||||
import com.google.inject.ImplementedBy;
|
import com.google.inject.ImplementedBy;
|
||||||
|
@ -33,12 +35,7 @@ import com.google.inject.ImplementedBy;
|
||||||
* @author Adrian Cole
|
* @author Adrian Cole
|
||||||
*/
|
*/
|
||||||
@ImplementedBy(SizeImpl.class)
|
@ImplementedBy(SizeImpl.class)
|
||||||
public interface Size extends Comparable<Size> {
|
public interface Size extends ComputeMetadata {
|
||||||
|
|
||||||
/**
|
|
||||||
* unique identifier of this configuration.
|
|
||||||
*/
|
|
||||||
String getId();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Amount of virtual or physical cores provided
|
* Amount of virtual or physical cores provided
|
||||||
|
@ -58,5 +55,5 @@ public interface Size extends Comparable<Size> {
|
||||||
/**
|
/**
|
||||||
* Determines platforms this can support
|
* Determines platforms this can support
|
||||||
*/
|
*/
|
||||||
boolean supportsArchitecture(Architecture architecture);
|
Set<Architecture> getSupportedArchitectures();
|
||||||
}
|
}
|
|
@ -18,6 +18,9 @@
|
||||||
*/
|
*/
|
||||||
package org.jclouds.compute.domain;
|
package org.jclouds.compute.domain;
|
||||||
|
|
||||||
|
import org.jclouds.compute.options.TemplateOptions;
|
||||||
|
import org.jclouds.domain.Location;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Configured operating system used to start nodes.
|
* Configured operating system used to start nodes.
|
||||||
*
|
*
|
||||||
|
@ -35,4 +38,13 @@ public interface Template extends Cloneable {
|
||||||
*/
|
*/
|
||||||
Size getSize();
|
Size getSize();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Location of the nodes.
|
||||||
|
*/
|
||||||
|
Location getLocation();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* options for launching this template, like run scripts or inbound ports
|
||||||
|
*/
|
||||||
|
TemplateOptions getOptions();
|
||||||
}
|
}
|
|
@ -24,6 +24,7 @@
|
||||||
package org.jclouds.compute.domain;
|
package org.jclouds.compute.domain;
|
||||||
|
|
||||||
import org.jclouds.compute.internal.TemplateBuilderImpl;
|
import org.jclouds.compute.internal.TemplateBuilderImpl;
|
||||||
|
import org.jclouds.compute.options.TemplateOptions;
|
||||||
|
|
||||||
import com.google.inject.ImplementedBy;
|
import com.google.inject.ImplementedBy;
|
||||||
|
|
||||||
|
@ -72,7 +73,7 @@ public interface TemplateBuilder {
|
||||||
/**
|
/**
|
||||||
* Configure this template to start in a specific location
|
* Configure this template to start in a specific location
|
||||||
*/
|
*/
|
||||||
TemplateBuilder location(String location);
|
TemplateBuilder locationId(String locationId);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Configure this template to require a specific architecture
|
* Configure this template to require a specific architecture
|
||||||
|
@ -121,4 +122,9 @@ public interface TemplateBuilder {
|
||||||
* Generate an immutable template from the current builder.
|
* Generate an immutable template from the current builder.
|
||||||
*/
|
*/
|
||||||
Template build();
|
Template build();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* options such as inbound ports and run scripts.
|
||||||
|
*/
|
||||||
|
TemplateBuilder options(TemplateOptions options);
|
||||||
}
|
}
|
|
@ -35,9 +35,9 @@ public class ComputeMetadataImpl extends ResourceMetadataImpl<ComputeType> imple
|
||||||
/** The serialVersionUID */
|
/** The serialVersionUID */
|
||||||
private static final long serialVersionUID = 7374704415964898694L;
|
private static final long serialVersionUID = 7374704415964898694L;
|
||||||
|
|
||||||
public ComputeMetadataImpl(ComputeType type, String id, String name, String location, URI uri,
|
public ComputeMetadataImpl(ComputeType type, String id, String name, String locationId, URI uri,
|
||||||
Map<String, String> userMetadata) {
|
Map<String, String> userMetadata) {
|
||||||
super(type, id, name, location, uri, userMetadata);
|
super(type, id, name, locationId, uri, userMetadata);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,77 +0,0 @@
|
||||||
/**
|
|
||||||
*
|
|
||||||
* 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.compute.domain.internal;
|
|
||||||
|
|
||||||
import java.net.InetAddress;
|
|
||||||
import java.net.URI;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
import org.jclouds.compute.domain.CreateNodeResponse;
|
|
||||||
import org.jclouds.compute.domain.NodeState;
|
|
||||||
import org.jclouds.domain.Credentials;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Adrian Cole
|
|
||||||
* @author Ivan Meredith
|
|
||||||
*/
|
|
||||||
public class CreateNodeResponseImpl extends NodeMetadataImpl implements CreateNodeResponse {
|
|
||||||
|
|
||||||
/** The serialVersionUID */
|
|
||||||
private static final long serialVersionUID = 3414239861247046054L;
|
|
||||||
|
|
||||||
private final Credentials credentials;
|
|
||||||
|
|
||||||
public CreateNodeResponseImpl(String id, String name, String location, URI uri,
|
|
||||||
Map<String, String> userMetadata, NodeState state,
|
|
||||||
Iterable<InetAddress> publicAddresses, Iterable<InetAddress> privateAddresses,
|
|
||||||
Credentials credentials, Map<String, String> extra) {
|
|
||||||
super(id, name, location, uri, userMetadata, state, publicAddresses, privateAddresses, extra);
|
|
||||||
this.credentials = credentials;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Credentials getCredentials() {
|
|
||||||
return credentials;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int hashCode() {
|
|
||||||
final int prime = 31;
|
|
||||||
int result = super.hashCode();
|
|
||||||
result = prime * result + ((credentials == null) ? 0 : credentials.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;
|
|
||||||
CreateNodeResponseImpl other = (CreateNodeResponseImpl) obj;
|
|
||||||
if (credentials == null) {
|
|
||||||
if (other.credentials != null)
|
|
||||||
return false;
|
|
||||||
} else if (!credentials.equals(other.credentials))
|
|
||||||
return false;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -23,125 +23,39 @@
|
||||||
*/
|
*/
|
||||||
package org.jclouds.compute.domain.internal;
|
package org.jclouds.compute.domain.internal;
|
||||||
|
|
||||||
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
|
|
||||||
|
import java.net.URI;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
import org.jclouds.compute.domain.Architecture;
|
import org.jclouds.compute.domain.Architecture;
|
||||||
|
import org.jclouds.compute.domain.ComputeType;
|
||||||
import org.jclouds.compute.domain.Image;
|
import org.jclouds.compute.domain.Image;
|
||||||
import org.jclouds.compute.domain.OsFamily;
|
import org.jclouds.compute.domain.OsFamily;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Adrian Cole
|
* @author Adrian Cole
|
||||||
*/
|
*/
|
||||||
public class ImageImpl implements Image {
|
public class ImageImpl extends ComputeMetadataImpl implements Image {
|
||||||
|
|
||||||
|
/** The serialVersionUID */
|
||||||
|
private static final long serialVersionUID = 7856744554191025307L;
|
||||||
|
|
||||||
private final String id;
|
|
||||||
private final String description;
|
|
||||||
private final String version;
|
private final String version;
|
||||||
private final OsFamily operatingSystem;
|
private final OsFamily osFamily;
|
||||||
private final String operatingSystemDescription;
|
private final String osDescription;
|
||||||
private final String location;
|
|
||||||
private final Architecture architecture;
|
private final Architecture architecture;
|
||||||
|
|
||||||
/**
|
public ImageImpl(String id, String name, String locationId, URI uri,
|
||||||
* {@inheritDoc}
|
Map<String, String> userMetadata, String description, String version,
|
||||||
*/
|
@Nullable OsFamily osFamily, String osDescription, Architecture architecture) {
|
||||||
@Override
|
super(ComputeType.IMAGE, id, name, locationId, uri, userMetadata);
|
||||||
public int hashCode() {
|
this.version = checkNotNull(version, "version");
|
||||||
final int prime = 31;
|
this.osFamily = osFamily;
|
||||||
int result = 1;
|
this.osDescription = checkNotNull(osDescription, "osDescription");
|
||||||
result = prime * result + ((architecture == null) ? 0 : architecture.hashCode());
|
this.architecture = checkNotNull(architecture, "architecture");
|
||||||
result = prime * result + ((description == null) ? 0 : description.hashCode());
|
|
||||||
result = prime * result + ((id == null) ? 0 : id.hashCode());
|
|
||||||
result = prime * result + ((location == null) ? 0 : location.hashCode());
|
|
||||||
result = prime * result + ((operatingSystem == null) ? 0 : operatingSystem.hashCode());
|
|
||||||
result = prime * result + ((version == null) ? 0 : version.hashCode());
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ImageImpl(String id, String description, String version, OsFamily operatingSystem,
|
|
||||||
String operatingSystemDescription, String location, Architecture architecture) {
|
|
||||||
this.id = id;
|
|
||||||
this.description = description;
|
|
||||||
this.version = version;
|
|
||||||
this.operatingSystem = operatingSystem;
|
|
||||||
this.operatingSystemDescription = operatingSystemDescription;
|
|
||||||
this.location = location;
|
|
||||||
this.architecture = architecture;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public boolean equals(Object obj) {
|
|
||||||
if (this == obj)
|
|
||||||
return true;
|
|
||||||
if (obj == null)
|
|
||||||
return false;
|
|
||||||
if (getClass() != obj.getClass())
|
|
||||||
return false;
|
|
||||||
ImageImpl other = (ImageImpl) obj;
|
|
||||||
if (architecture == null) {
|
|
||||||
if (other.architecture != null)
|
|
||||||
return false;
|
|
||||||
} else if (!architecture.equals(other.architecture))
|
|
||||||
return false;
|
|
||||||
if (description == null) {
|
|
||||||
if (other.description != null)
|
|
||||||
return false;
|
|
||||||
} else if (!description.equals(other.description))
|
|
||||||
return false;
|
|
||||||
if (id == null) {
|
|
||||||
if (other.id != null)
|
|
||||||
return false;
|
|
||||||
} else if (!id.equals(other.id))
|
|
||||||
return false;
|
|
||||||
if (location == null) {
|
|
||||||
if (other.location != null)
|
|
||||||
return false;
|
|
||||||
} else if (!location.equals(other.location))
|
|
||||||
return false;
|
|
||||||
if (operatingSystem == null) {
|
|
||||||
if (other.operatingSystem != null)
|
|
||||||
return false;
|
|
||||||
} else if (!operatingSystem.equals(other.operatingSystem))
|
|
||||||
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=" + id + ", version=" + version + ", location=" + location + ", architecture="
|
|
||||||
+ architecture + ", operatingSystem=" + operatingSystem
|
|
||||||
+ ", operatingSystemVersion=" + operatingSystemDescription + ", description="
|
|
||||||
+ description + "]";
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public String getId() {
|
|
||||||
return id;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public String getDescription() {
|
|
||||||
return description;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public OsFamily getOsFamily() {
|
|
||||||
return operatingSystem;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -156,8 +70,16 @@ public class ImageImpl implements Image {
|
||||||
* {@inheritDoc}
|
* {@inheritDoc}
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public String getLocation() {
|
public OsFamily getOsFamily() {
|
||||||
return location;
|
return osFamily;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public String getOsDescription() {
|
||||||
|
return osDescription;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -168,12 +90,4 @@ public class ImageImpl implements Image {
|
||||||
return architecture;
|
return architecture;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public String getOsDescription() {
|
|
||||||
return operatingSystemDescription;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,15 +18,19 @@
|
||||||
*/
|
*/
|
||||||
package org.jclouds.compute.domain.internal;
|
package org.jclouds.compute.domain.internal;
|
||||||
|
|
||||||
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
|
|
||||||
import java.net.InetAddress;
|
import java.net.InetAddress;
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
import java.util.Comparator;
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.SortedSet;
|
import java.util.Set;
|
||||||
|
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
import org.jclouds.compute.domain.ComputeType;
|
import org.jclouds.compute.domain.ComputeType;
|
||||||
import org.jclouds.compute.domain.NodeMetadata;
|
import org.jclouds.compute.domain.NodeMetadata;
|
||||||
import org.jclouds.compute.domain.NodeState;
|
import org.jclouds.compute.domain.NodeState;
|
||||||
|
import org.jclouds.domain.Credentials;
|
||||||
|
|
||||||
import com.google.common.collect.Iterables;
|
import com.google.common.collect.Iterables;
|
||||||
import com.google.common.collect.Maps;
|
import com.google.common.collect.Maps;
|
||||||
|
@ -40,47 +44,62 @@ public class NodeMetadataImpl extends ComputeMetadataImpl implements NodeMetadat
|
||||||
/** The serialVersionUID */
|
/** The serialVersionUID */
|
||||||
private static final long serialVersionUID = 7924307572338157887L;
|
private static final long serialVersionUID = 7924307572338157887L;
|
||||||
|
|
||||||
public static final Comparator<InetAddress> ADDRESS_COMPARATOR = new Comparator<InetAddress>() {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int compare(InetAddress o1, InetAddress o2) {
|
|
||||||
return (o1 == o2) ? 0 : o1.getHostAddress().compareTo(o2.getHostAddress());
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
||||||
private final NodeState state;
|
private final NodeState state;
|
||||||
private final SortedSet<InetAddress> publicAddresses = Sets.newTreeSet(ADDRESS_COMPARATOR);
|
private final Set<InetAddress> publicAddresses = Sets.newLinkedHashSet();
|
||||||
private final SortedSet<InetAddress> privateAddresses = Sets.newTreeSet(ADDRESS_COMPARATOR);
|
private final Set<InetAddress> privateAddresses = Sets.newLinkedHashSet();
|
||||||
private final Map<String, String> extra = Maps.newLinkedHashMap();
|
private final Map<String, String> extra = Maps.newLinkedHashMap();
|
||||||
|
private final Credentials credentials;
|
||||||
|
private final String tag;
|
||||||
|
|
||||||
public NodeMetadataImpl(String id, String name, String location, URI uri,
|
public NodeMetadataImpl(String id, String name, String locationId, URI uri,
|
||||||
Map<String, String> userMetadata, NodeState state,
|
Map<String, String> userMetadata, String tag, NodeState state,
|
||||||
Iterable<InetAddress> publicAddresses, Iterable<InetAddress> privateAddresses,
|
Iterable<InetAddress> publicAddresses, Iterable<InetAddress> privateAddresses,
|
||||||
Map<String, String> extra) {
|
Map<String, String> extra, @Nullable Credentials credentials) {
|
||||||
super(ComputeType.NODE, id, name, location, uri, userMetadata);
|
super(ComputeType.NODE, id, name, locationId, uri, userMetadata);
|
||||||
this.state = state;
|
this.tag = checkNotNull(tag, "tag");
|
||||||
Iterables.addAll(this.publicAddresses, publicAddresses);
|
this.state = checkNotNull(state, "state");
|
||||||
Iterables.addAll(this.privateAddresses, privateAddresses);
|
Iterables.addAll(this.publicAddresses, checkNotNull(publicAddresses, "publicAddresses"));
|
||||||
this.extra.putAll(extra);
|
Iterables.addAll(this.privateAddresses, checkNotNull(privateAddresses, "privateAddresses"));
|
||||||
|
this.extra.putAll(checkNotNull(extra, "extra"));
|
||||||
|
this.credentials = credentials;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@inheritDoc}
|
* {@inheritDoc}
|
||||||
*/
|
*/
|
||||||
public SortedSet<InetAddress> getPublicAddresses() {
|
@Override
|
||||||
|
public String getTag() {
|
||||||
|
return tag;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public Credentials getCredentials() {
|
||||||
|
return credentials;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public Set<InetAddress> getPublicAddresses() {
|
||||||
return publicAddresses;
|
return publicAddresses;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@inheritDoc}
|
* {@inheritDoc}
|
||||||
*/
|
*/
|
||||||
public SortedSet<InetAddress> getPrivateAddresses() {
|
@Override
|
||||||
|
public Set<InetAddress> getPrivateAddresses() {
|
||||||
return privateAddresses;
|
return privateAddresses;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@inheritDoc}
|
* {@inheritDoc}
|
||||||
*/
|
*/
|
||||||
|
@Override
|
||||||
public NodeState getState() {
|
public NodeState getState() {
|
||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
|
@ -95,20 +114,22 @@ public class NodeMetadataImpl extends ComputeMetadataImpl implements NodeMetadat
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "[id=" + getId() + ", name=" + getName() + ", location=" + getLocation() + ", uri="
|
return "[id=" + getId() + ", tag=" + getTag() + ", name=" + getName() + ", location="
|
||||||
+ getUri() + ", userMetadata=" + getUserMetadata() + ", state=" + getState()
|
+ getLocationId() + ", uri=" + getUri() + ", userMetadata=" + getUserMetadata()
|
||||||
+ ", privateAddresses=" + privateAddresses + ", publicAddresses=" + publicAddresses
|
+ ", state=" + getState() + ", privateAddresses=" + privateAddresses
|
||||||
+ "]";
|
+ ", publicAddresses=" + publicAddresses + "]";
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
final int prime = 31;
|
final int prime = 31;
|
||||||
int result = super.hashCode();
|
int result = super.hashCode();
|
||||||
|
result = prime * result + ((credentials == null) ? 0 : credentials.hashCode());
|
||||||
result = prime * result + ((extra == null) ? 0 : extra.hashCode());
|
result = prime * result + ((extra == null) ? 0 : extra.hashCode());
|
||||||
result = prime * result + ((privateAddresses == null) ? 0 : privateAddresses.hashCode());
|
result = prime * result + ((privateAddresses == null) ? 0 : privateAddresses.hashCode());
|
||||||
result = prime * result + ((publicAddresses == null) ? 0 : publicAddresses.hashCode());
|
result = prime * result + ((publicAddresses == null) ? 0 : publicAddresses.hashCode());
|
||||||
result = prime * result + ((state == null) ? 0 : state.hashCode());
|
result = prime * result + ((state == null) ? 0 : state.hashCode());
|
||||||
|
result = prime * result + ((tag == null) ? 0 : tag.hashCode());
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -121,6 +142,11 @@ public class NodeMetadataImpl extends ComputeMetadataImpl implements NodeMetadat
|
||||||
if (getClass() != obj.getClass())
|
if (getClass() != obj.getClass())
|
||||||
return false;
|
return false;
|
||||||
NodeMetadataImpl other = (NodeMetadataImpl) obj;
|
NodeMetadataImpl other = (NodeMetadataImpl) obj;
|
||||||
|
if (credentials == null) {
|
||||||
|
if (other.credentials != null)
|
||||||
|
return false;
|
||||||
|
} else if (!credentials.equals(other.credentials))
|
||||||
|
return false;
|
||||||
if (extra == null) {
|
if (extra == null) {
|
||||||
if (other.extra != null)
|
if (other.extra != null)
|
||||||
return false;
|
return false;
|
||||||
|
@ -141,6 +167,11 @@ public class NodeMetadataImpl extends ComputeMetadataImpl implements NodeMetadat
|
||||||
return false;
|
return false;
|
||||||
} else if (!state.equals(other.state))
|
} else if (!state.equals(other.state))
|
||||||
return false;
|
return false;
|
||||||
|
if (tag == null) {
|
||||||
|
if (other.tag != null)
|
||||||
|
return false;
|
||||||
|
} else if (!tag.equals(other.tag))
|
||||||
|
return false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,40 @@
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* 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.compute.domain.internal;
|
||||||
|
|
||||||
|
import java.util.HashSet;
|
||||||
|
|
||||||
|
import org.jclouds.compute.domain.NodeMetadata;
|
||||||
|
import org.jclouds.compute.domain.NodeSet;
|
||||||
|
|
||||||
|
import com.google.common.collect.Iterables;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Adrian Cole
|
||||||
|
*/
|
||||||
|
public class NodeSetImpl extends HashSet<NodeMetadata> implements NodeSet {
|
||||||
|
|
||||||
|
/** The serialVersionUID */
|
||||||
|
private static final long serialVersionUID = 3414239861247046054L;
|
||||||
|
|
||||||
|
public NodeSetImpl(Iterable<NodeMetadata> nodes) {
|
||||||
|
Iterables.addAll(this, nodes);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -18,10 +18,18 @@
|
||||||
*/
|
*/
|
||||||
package org.jclouds.compute.domain.internal;
|
package org.jclouds.compute.domain.internal;
|
||||||
|
|
||||||
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
|
|
||||||
|
import java.net.URI;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
import org.jclouds.compute.domain.Architecture;
|
import org.jclouds.compute.domain.Architecture;
|
||||||
|
import org.jclouds.compute.domain.ComputeType;
|
||||||
import org.jclouds.compute.domain.Size;
|
import org.jclouds.compute.domain.Size;
|
||||||
|
import org.jclouds.domain.ResourceMetadata;
|
||||||
|
|
||||||
import com.google.common.collect.ComparisonChain;
|
import com.google.common.collect.ComparisonChain;
|
||||||
import com.google.common.collect.Iterables;
|
import com.google.common.collect.Iterables;
|
||||||
|
@ -30,20 +38,24 @@ import com.google.common.collect.Sets;
|
||||||
/**
|
/**
|
||||||
* @author Adrian Cole
|
* @author Adrian Cole
|
||||||
*/
|
*/
|
||||||
public class SizeImpl implements Size {
|
public class SizeImpl extends ComputeMetadataImpl implements Size {
|
||||||
private String id;
|
/** The serialVersionUID */
|
||||||
|
private static final long serialVersionUID = 8994255275911717567L;
|
||||||
private final int cores;
|
private final int cores;
|
||||||
private final int ram;
|
private final int ram;
|
||||||
private final int disk;
|
private final int disk;
|
||||||
|
|
||||||
private final Set<Architecture> supportedArchitectures = Sets.newHashSet();
|
private final Set<Architecture> supportedArchitectures = Sets.newHashSet();
|
||||||
|
|
||||||
public SizeImpl(String id, int cores, int ram, int disk,
|
public SizeImpl(String id, String name, @Nullable String location, URI uri,
|
||||||
|
Map<String, String> userMetadata, int cores, int ram, int disk,
|
||||||
Iterable<Architecture> supportedArchitectures) {
|
Iterable<Architecture> supportedArchitectures) {
|
||||||
this.id = id;
|
super(ComputeType.SIZE, id, name, location, uri, userMetadata);
|
||||||
this.cores = cores;
|
this.cores = cores;
|
||||||
this.ram = ram;
|
this.ram = ram;
|
||||||
this.disk = disk;
|
this.disk = disk;
|
||||||
Iterables.addAll(this.supportedArchitectures, supportedArchitectures);
|
Iterables.addAll(this.supportedArchitectures, checkNotNull(supportedArchitectures,
|
||||||
|
"supportedArchitectures"));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -70,55 +82,27 @@ public class SizeImpl implements Size {
|
||||||
return disk;
|
return disk;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
public int compareTo(ResourceMetadata<ComputeType> that) {
|
||||||
final int prime = 31;
|
if (that instanceof Size) {
|
||||||
int result = 1;
|
Size thatSize = Size.class.cast(that);
|
||||||
result = prime * result + cores;
|
return ComparisonChain.start().compare(this.getCores(), thatSize.getCores()).compare(
|
||||||
result = prime * result + disk;
|
this.getRam(), thatSize.getRam()).compare(this.getDisk(), thatSize.getDisk())
|
||||||
result = prime * result + ((id == null) ? 0 : id.hashCode());
|
.result();
|
||||||
result = prime * result + ram;
|
} else {
|
||||||
result = prime * result
|
return super.compareTo(that);
|
||||||
+ ((supportedArchitectures == null) ? 0 : supportedArchitectures.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;
|
|
||||||
SizeImpl other = (SizeImpl) obj;
|
|
||||||
if (cores != other.cores)
|
|
||||||
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) {
|
|
||||||
if (other.supportedArchitectures != null)
|
|
||||||
return false;
|
|
||||||
} else if (!supportedArchitectures.equals(other.supportedArchitectures))
|
|
||||||
return false;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int compareTo(Size that) {
|
|
||||||
return ComparisonChain.start().compare(this.getCores(), that.getCores()).compare(
|
|
||||||
this.getRam(), that.getRam()).compare(this.getDisk(), that.getDisk()).result();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "[id=" + id + ", cores=" + cores + ", ram=" + ram + ", disk=" + disk
|
return "[id=" + getId() + ", cores=" + cores + ", ram=" + ram + ", disk=" + disk
|
||||||
+ ", supportedArchitectures=" + supportedArchitectures + "]";
|
+ ", supportedArchitectures=" + supportedArchitectures + "]";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -126,15 +110,7 @@ public class SizeImpl implements Size {
|
||||||
* {@inheritDoc}
|
* {@inheritDoc}
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public boolean supportsArchitecture(Architecture architecture) {
|
public Set<Architecture> getSupportedArchitectures() {
|
||||||
return supportedArchitectures.contains(architecture);
|
return supportedArchitectures;
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public String getId() {
|
|
||||||
return id;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,9 +23,13 @@
|
||||||
*/
|
*/
|
||||||
package org.jclouds.compute.domain.internal;
|
package org.jclouds.compute.domain.internal;
|
||||||
|
|
||||||
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
|
|
||||||
import org.jclouds.compute.domain.Image;
|
import org.jclouds.compute.domain.Image;
|
||||||
import org.jclouds.compute.domain.Size;
|
import org.jclouds.compute.domain.Size;
|
||||||
import org.jclouds.compute.domain.Template;
|
import org.jclouds.compute.domain.Template;
|
||||||
|
import org.jclouds.compute.options.TemplateOptions;
|
||||||
|
import org.jclouds.domain.Location;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
|
@ -35,10 +39,14 @@ public class TemplateImpl implements Template {
|
||||||
|
|
||||||
private final Image image;
|
private final Image image;
|
||||||
private final Size size;
|
private final Size size;
|
||||||
|
private final Location location;
|
||||||
|
private final TemplateOptions options;
|
||||||
|
|
||||||
protected TemplateImpl(Image image, Size size) {
|
public TemplateImpl(Image image, Size size, Location location, TemplateOptions options) {
|
||||||
this.image = image;
|
this.image = checkNotNull(image, "image");
|
||||||
this.size = size;
|
this.size = checkNotNull(size, "size");
|
||||||
|
this.location = checkNotNull(location, "location");
|
||||||
|
this.options = checkNotNull(options, "options");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -57,11 +65,29 @@ public class TemplateImpl implements Template {
|
||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public Location getLocation() {
|
||||||
|
return location;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public TemplateOptions getOptions() {
|
||||||
|
return options;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
final int prime = 31;
|
final int prime = 31;
|
||||||
int result = 1;
|
int result = 1;
|
||||||
result = prime * result + ((image == null) ? 0 : image.hashCode());
|
result = prime * result + ((image == null) ? 0 : image.hashCode());
|
||||||
|
result = prime * result + ((location == null) ? 0 : location.hashCode());
|
||||||
|
result = prime * result + ((options == null) ? 0 : options.hashCode());
|
||||||
result = prime * result + ((size == null) ? 0 : size.hashCode());
|
result = prime * result + ((size == null) ? 0 : size.hashCode());
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -80,6 +106,16 @@ public class TemplateImpl implements Template {
|
||||||
return false;
|
return false;
|
||||||
} else if (!image.equals(other.image))
|
} else if (!image.equals(other.image))
|
||||||
return false;
|
return false;
|
||||||
|
if (location == null) {
|
||||||
|
if (other.location != null)
|
||||||
|
return false;
|
||||||
|
} else if (!location.equals(other.location))
|
||||||
|
return false;
|
||||||
|
if (options == null) {
|
||||||
|
if (other.options != null)
|
||||||
|
return false;
|
||||||
|
} else if (!options.equals(other.options))
|
||||||
|
return false;
|
||||||
if (size == null) {
|
if (size == null) {
|
||||||
if (other.size != null)
|
if (other.size != null)
|
||||||
return false;
|
return false;
|
||||||
|
@ -98,6 +134,7 @@ public class TemplateImpl implements Template {
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
protected Object clone() throws CloneNotSupportedException {
|
protected Object clone() throws CloneNotSupportedException {
|
||||||
return new TemplateImpl(image, size);
|
return new TemplateImpl(image, size, location, options);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,7 +38,7 @@ public class ComputeServiceContextImpl<X, Y> implements ComputeServiceContext {
|
||||||
public ComputeServiceContextImpl(ComputeService computeService,
|
public ComputeServiceContextImpl(ComputeService computeService,
|
||||||
RestContext<X, Y> providerSpecificContext) {
|
RestContext<X, Y> providerSpecificContext) {
|
||||||
this.computeService = checkNotNull(computeService, "computeService");
|
this.computeService = checkNotNull(computeService, "computeService");
|
||||||
this.providerSpecificContext = providerSpecificContext;
|
this.providerSpecificContext = checkNotNull(providerSpecificContext, "providerSpecificContext");;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ComputeService getComputeService() {
|
public ComputeService getComputeService() {
|
||||||
|
|
|
@ -1,21 +1,26 @@
|
||||||
package org.jclouds.compute.internal;
|
package org.jclouds.compute.internal;
|
||||||
|
|
||||||
|
import static com.google.common.base.Preconditions.checkArgument;
|
||||||
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
import java.util.NoSuchElementException;
|
import java.util.NoSuchElementException;
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
import javax.inject.Named;
|
import javax.inject.Named;
|
||||||
|
|
||||||
import org.jclouds.compute.domain.Architecture;
|
import org.jclouds.compute.domain.Architecture;
|
||||||
|
import org.jclouds.compute.domain.ComputeMetadata;
|
||||||
import org.jclouds.compute.domain.Image;
|
import org.jclouds.compute.domain.Image;
|
||||||
import org.jclouds.compute.domain.OsFamily;
|
import org.jclouds.compute.domain.OsFamily;
|
||||||
import org.jclouds.compute.domain.Size;
|
import org.jclouds.compute.domain.Size;
|
||||||
import org.jclouds.compute.domain.Template;
|
import org.jclouds.compute.domain.Template;
|
||||||
import org.jclouds.compute.domain.TemplateBuilder;
|
import org.jclouds.compute.domain.TemplateBuilder;
|
||||||
import org.jclouds.compute.domain.internal.TemplateImpl;
|
import org.jclouds.compute.domain.internal.TemplateImpl;
|
||||||
|
import org.jclouds.compute.options.TemplateOptions;
|
||||||
import org.jclouds.compute.reference.ComputeServiceConstants;
|
import org.jclouds.compute.reference.ComputeServiceConstants;
|
||||||
import org.jclouds.domain.ResourceLocation;
|
import org.jclouds.domain.Location;
|
||||||
import org.jclouds.logging.Logger;
|
import org.jclouds.logging.Logger;
|
||||||
|
|
||||||
import com.google.common.base.Predicate;
|
import com.google.common.base.Predicate;
|
||||||
|
@ -37,17 +42,17 @@ public class TemplateBuilderImpl implements TemplateBuilder {
|
||||||
@Named(ComputeServiceConstants.COMPUTE_LOGGER)
|
@Named(ComputeServiceConstants.COMPUTE_LOGGER)
|
||||||
protected Logger logger = Logger.NULL;
|
protected Logger logger = Logger.NULL;
|
||||||
|
|
||||||
private final Set<? extends Image> images;
|
private final Map<String, ? extends Image> images;
|
||||||
private final Set<? extends Size> sizes;
|
private final Map<String, ? extends Size> sizes;
|
||||||
private String location;
|
private final Map<String, ? extends Location> locations;
|
||||||
private OsFamily os;
|
private OsFamily os;
|
||||||
private Architecture arch;
|
private Architecture arch;
|
||||||
|
private String locationId;
|
||||||
private String imageId;
|
private String imageId;
|
||||||
private String sizeId;
|
private String sizeId;
|
||||||
|
|
||||||
private String osDescription;
|
private String osDescription;
|
||||||
private String imageVersion;
|
private String imageVersion;
|
||||||
private String imageDescription;
|
private String imageName;
|
||||||
|
|
||||||
private int minCores;
|
private int minCores;
|
||||||
private int minRam;
|
private int minRam;
|
||||||
|
@ -55,15 +60,29 @@ public class TemplateBuilderImpl implements TemplateBuilder {
|
||||||
private boolean biggest;
|
private boolean biggest;
|
||||||
private boolean fastest;
|
private boolean fastest;
|
||||||
|
|
||||||
|
private TemplateOptions options = TemplateOptions.NONE;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public TemplateBuilderImpl(@ResourceLocation String location, Set<? extends Image> images,
|
public TemplateBuilderImpl(Map<String, ? extends Location> locations,
|
||||||
Set<? extends Size> sizes) {
|
Map<String, ? extends Image> images, Map<String, ? extends Size> sizes,
|
||||||
this.location = location;
|
Location defaultLocation) {
|
||||||
|
this.locations = locations;
|
||||||
this.images = images;
|
this.images = images;
|
||||||
this.sizes = sizes;
|
this.sizes = sizes;
|
||||||
|
this.locationId = defaultLocation.getId();
|
||||||
}
|
}
|
||||||
|
|
||||||
private final Predicate<Image> imageIdPredicate = new Predicate<Image>() {
|
private final Predicate<ComputeMetadata> locationPredicate = new Predicate<ComputeMetadata>() {
|
||||||
|
@Override
|
||||||
|
public boolean apply(ComputeMetadata input) {
|
||||||
|
boolean returnVal = true;
|
||||||
|
if (locationId != null && input.getLocationId() != null)
|
||||||
|
returnVal = locationId.equals(input.getLocationId());
|
||||||
|
return returnVal;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
private final Predicate<Image> idPredicate = new Predicate<Image>() {
|
||||||
@Override
|
@Override
|
||||||
public boolean apply(Image input) {
|
public boolean apply(Image input) {
|
||||||
boolean returnVal = true;
|
boolean returnVal = true;
|
||||||
|
@ -78,16 +97,6 @@ public class TemplateBuilderImpl implements TemplateBuilder {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
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>() {
|
private final Predicate<Image> osPredicate = new Predicate<Image>() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -136,15 +145,15 @@ public class TemplateBuilderImpl implements TemplateBuilder {
|
||||||
return returnVal;
|
return returnVal;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
private final Predicate<Image> imageDescriptionPredicate = new Predicate<Image>() {
|
private final Predicate<Image> imageNamePredicate = new Predicate<Image>() {
|
||||||
@Override
|
@Override
|
||||||
public boolean apply(Image input) {
|
public boolean apply(Image input) {
|
||||||
boolean returnVal = true;
|
boolean returnVal = true;
|
||||||
if (imageDescription != null) {
|
if (imageName != null) {
|
||||||
if (input.getDescription() == null)
|
if (input.getName() == null)
|
||||||
returnVal = false;
|
returnVal = false;
|
||||||
else
|
else
|
||||||
returnVal = input.getDescription().matches(imageDescription);
|
returnVal = input.getName().matches(imageName);
|
||||||
}
|
}
|
||||||
return returnVal;
|
return returnVal;
|
||||||
}
|
}
|
||||||
|
@ -165,16 +174,16 @@ public class TemplateBuilderImpl implements TemplateBuilder {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
private final Predicate<Image> imagePredicate = Predicates.and(imageIdPredicate,
|
private final Predicate<Image> imagePredicate = Predicates.and(idPredicate, locationPredicate,
|
||||||
locationPredicate, osPredicate, imageArchPredicate, osDescriptionPredicate,
|
osPredicate, imageArchPredicate, osDescriptionPredicate, imageVersionPredicate,
|
||||||
imageVersionPredicate, imageDescriptionPredicate);
|
imageNamePredicate);
|
||||||
|
|
||||||
private final Predicate<Size> sizeArchPredicate = new Predicate<Size>() {
|
private final Predicate<Size> sizeArchPredicate = new Predicate<Size>() {
|
||||||
@Override
|
@Override
|
||||||
public boolean apply(Size input) {
|
public boolean apply(Size input) {
|
||||||
boolean returnVal = false;
|
boolean returnVal = false;
|
||||||
if (arch != null)
|
if (arch != null)
|
||||||
returnVal = input.supportsArchitecture(arch);
|
returnVal = input.getSupportedArchitectures().contains(arch);
|
||||||
return returnVal;
|
return returnVal;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -192,8 +201,8 @@ public class TemplateBuilderImpl implements TemplateBuilder {
|
||||||
return input.getRam() >= TemplateBuilderImpl.this.minRam;
|
return input.getRam() >= TemplateBuilderImpl.this.minRam;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
private final Predicate<Size> sizePredicate = Predicates.and(sizeIdPredicate, sizeArchPredicate,
|
private final Predicate<Size> sizePredicate = Predicates.and(sizeIdPredicate, locationPredicate,
|
||||||
sizeCoresPredicate, sizeRamPredicate);
|
sizeArchPredicate, sizeCoresPredicate, sizeRamPredicate);
|
||||||
|
|
||||||
static final Ordering<Size> DEFAULT_SIZE_ORDERING = new Ordering<Size>() {
|
static final Ordering<Size> DEFAULT_SIZE_ORDERING = new Ordering<Size>() {
|
||||||
public int compare(Size left, Size right) {
|
public int compare(Size left, Size right) {
|
||||||
|
@ -208,9 +217,8 @@ public class TemplateBuilderImpl implements TemplateBuilder {
|
||||||
};
|
};
|
||||||
static final Ordering<Image> DEFAULT_IMAGE_ORDERING = new Ordering<Image>() {
|
static final Ordering<Image> DEFAULT_IMAGE_ORDERING = new Ordering<Image>() {
|
||||||
public int compare(Image left, Image right) {
|
public int compare(Image left, Image right) {
|
||||||
return ComparisonChain.start().compare(left.getOsDescription(),
|
return ComparisonChain.start().compare(left.getOsDescription(), right.getOsDescription())
|
||||||
right.getOsDescription()).compare(left.getVersion(), right.getVersion())
|
.compare(left.getVersion(), right.getVersion()).result();
|
||||||
.result();
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -229,6 +237,8 @@ public class TemplateBuilderImpl implements TemplateBuilder {
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public TemplateBuilder fromSize(Size size) {
|
public TemplateBuilder fromSize(Size size) {
|
||||||
|
if (size.getLocationId() != null)
|
||||||
|
this.locationId = size.getLocationId();
|
||||||
this.minCores = size.getCores();
|
this.minCores = size.getCores();
|
||||||
this.minRam = size.getRam();
|
this.minRam = size.getRam();
|
||||||
return this;
|
return this;
|
||||||
|
@ -239,8 +249,8 @@ public class TemplateBuilderImpl implements TemplateBuilder {
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public TemplateBuilder fromImage(Image image) {
|
public TemplateBuilder fromImage(Image image) {
|
||||||
if (image.getLocation() != null)
|
if (image.getLocationId() != null)
|
||||||
this.location = image.getLocation();
|
this.locationId = image.getLocationId();
|
||||||
if (image.getOsFamily() != null)
|
if (image.getOsFamily() != null)
|
||||||
this.os = image.getOsFamily();
|
this.os = image.getOsFamily();
|
||||||
if (image.getOsDescription() != null)
|
if (image.getOsDescription() != null)
|
||||||
|
@ -283,8 +293,10 @@ public class TemplateBuilderImpl implements TemplateBuilder {
|
||||||
* {@inheritDoc}
|
* {@inheritDoc}
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public TemplateBuilder location(String location) {
|
public TemplateBuilder locationId(final String locationId) {
|
||||||
this.location = location;
|
checkArgument(locations.get(checkNotNull(locationId, "locationId")) != null, "locationId "
|
||||||
|
+ locationId + " not configured in: " + locations.keySet());
|
||||||
|
this.locationId = locationId;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -314,7 +326,7 @@ public class TemplateBuilderImpl implements TemplateBuilder {
|
||||||
logger.debug(">> searching params(%s)", this);
|
logger.debug(">> searching params(%s)", this);
|
||||||
Image image;
|
Image image;
|
||||||
try {
|
try {
|
||||||
image = DEFAULT_IMAGE_ORDERING.max(Iterables.filter(images, imagePredicate));
|
image = DEFAULT_IMAGE_ORDERING.max(Iterables.filter(images.values(), imagePredicate));
|
||||||
} catch (NoSuchElementException exception) {
|
} catch (NoSuchElementException exception) {
|
||||||
throw new NoSuchElementException("image didn't match: " + toString() + "\n" + images);
|
throw new NoSuchElementException("image didn't match: " + toString() + "\n" + images);
|
||||||
}
|
}
|
||||||
|
@ -329,13 +341,14 @@ public class TemplateBuilderImpl implements TemplateBuilder {
|
||||||
sizeOrdering = Ordering.compound(ImmutableList.of(BY_CORES_ORDERING, sizeOrdering));
|
sizeOrdering = Ordering.compound(ImmutableList.of(BY_CORES_ORDERING, sizeOrdering));
|
||||||
Size size;
|
Size size;
|
||||||
try {
|
try {
|
||||||
size = sizeOrdering.max(Iterables.filter(sizes, sizePredicate));
|
size = sizeOrdering.max(Iterables.filter(sizes.values(), sizePredicate));
|
||||||
} catch (NoSuchElementException exception) {
|
} catch (NoSuchElementException exception) {
|
||||||
throw new NoSuchElementException("size didn't match: " + toString() + "\n" + sizes);
|
throw new NoSuchElementException("size didn't match: " + toString() + "\n" + sizes);
|
||||||
}
|
}
|
||||||
logger.debug("<< matched size(%s)", size);
|
logger.debug("<< matched size(%s)", size);
|
||||||
return new TemplateImpl(image, size) {
|
Location location = locations.get(locationId);
|
||||||
};
|
logger.debug("<< matched location(%s)", location);
|
||||||
|
return new TemplateImpl(image, size, location, options);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -352,7 +365,7 @@ public class TemplateBuilderImpl implements TemplateBuilder {
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public TemplateBuilder imageDescriptionMatches(String descriptionRegex) {
|
public TemplateBuilder imageDescriptionMatches(String descriptionRegex) {
|
||||||
this.imageDescription = descriptionRegex;
|
this.imageName = descriptionRegex;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -401,13 +414,22 @@ public class TemplateBuilderImpl implements TemplateBuilder {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public TemplateBuilder options(TemplateOptions options) {
|
||||||
|
this.options = checkNotNull(options, "options");
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "[arch=" + arch + ", biggest=" + biggest + ", fastest=" + fastest
|
return "[arch=" + arch + ", biggest=" + biggest + ", fastest=" + fastest
|
||||||
+ ", imageDescription=" + imageDescription + ", imageId=" + imageId
|
+ ", imageDescription=" + imageName + ", imageId=" + imageId + ", imageVersion="
|
||||||
+ ", imageVersion=" + imageVersion + ", location=" + location + ", minCores="
|
+ imageVersion + ", location=" + locationId + ", minCores=" + minCores + ", minRam="
|
||||||
+ minCores + ", minRam=" + minRam + ", os=" + os + ", osDescription=" + osDescription
|
+ minRam + ", os=" + os + ", osDescription=" + osDescription + ", sizeId=" + sizeId
|
||||||
+ ", sizeId=" + sizeId + "]";
|
+ "]";
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,74 +0,0 @@
|
||||||
package org.jclouds.compute.options;
|
|
||||||
|
|
||||||
import static com.google.common.base.Preconditions.checkArgument;
|
|
||||||
import static com.google.common.base.Preconditions.checkNotNull;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Contains options supported in the {@code ComputeService#runNode} operation. <h2>
|
|
||||||
* Usage</h2> The recommended way to instantiate a RunOptions object is to statically import
|
|
||||||
* RunOptions.* and invoke a static creation method followed by an instance mutator (if needed):
|
|
||||||
* <p/>
|
|
||||||
* <code>
|
|
||||||
* import static org.jclouds.compute.options.RunOptions.Builder.*
|
|
||||||
* <p/>
|
|
||||||
* ComputeService client = // get connection
|
|
||||||
* CreateNodeResponse client.runNode(name, template, openPorts(22, 80, 8080, 443));
|
|
||||||
* <code>
|
|
||||||
*
|
|
||||||
* @author Adrian Cole
|
|
||||||
*/
|
|
||||||
public class RunNodeOptions {
|
|
||||||
|
|
||||||
public static final RunNodeOptions NONE = new RunNodeOptions();
|
|
||||||
|
|
||||||
private int[] openPorts = new int[0];
|
|
||||||
|
|
||||||
private byte[] script;
|
|
||||||
|
|
||||||
public int[] getOpenPorts() {
|
|
||||||
return openPorts;
|
|
||||||
}
|
|
||||||
|
|
||||||
public byte[] getRunScript() {
|
|
||||||
return script;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This script will be executed as the root user upon system startup.
|
|
||||||
*/
|
|
||||||
public RunNodeOptions runScript(byte[] script) {
|
|
||||||
checkArgument(checkNotNull(script, "script").length <= 16 * 1024,
|
|
||||||
"script cannot be larger than 16kb");
|
|
||||||
this.script = script;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Opens the set of ports to public access.
|
|
||||||
*/
|
|
||||||
public RunNodeOptions openPorts(int... ports) {
|
|
||||||
this.openPorts = ports;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class Builder {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @see RunNodeOptions#openPorts
|
|
||||||
*/
|
|
||||||
public static RunNodeOptions openPorts(int... ports) {
|
|
||||||
RunNodeOptions options = new RunNodeOptions();
|
|
||||||
return options.openPorts(ports);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @see RunNodeOptions#runScript
|
|
||||||
*/
|
|
||||||
public static RunNodeOptions runScript(byte[] script) {
|
|
||||||
RunNodeOptions options = new RunNodeOptions();
|
|
||||||
return options.runScript(script);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,73 @@
|
||||||
|
package org.jclouds.compute.options;
|
||||||
|
|
||||||
|
import static com.google.common.base.Preconditions.checkArgument;
|
||||||
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Contains options supported in the {@code ComputeService#runNode} operation. <h2>
|
||||||
|
* Usage</h2> The recommended way to instantiate a TemplateOptions object is to statically import
|
||||||
|
* TemplateOptions.* and invoke a static creation method followed by an instance mutator (if needed):
|
||||||
|
* <p/>
|
||||||
|
* <code>
|
||||||
|
* import static org.jclouds.compute.options.TemplateOptions.Builder.*;
|
||||||
|
* <p/>
|
||||||
|
* ComputeService client = // get connection
|
||||||
|
* NodeSet set = client.runNode(name, template.options(inboundPorts(22, 80, 8080, 443)));
|
||||||
|
* <code>
|
||||||
|
*
|
||||||
|
* @author Adrian Cole
|
||||||
|
*/
|
||||||
|
public class TemplateOptions {
|
||||||
|
|
||||||
|
public static final TemplateOptions NONE = new TemplateOptions();
|
||||||
|
|
||||||
|
private int[] inboundPorts = new int[] { 22 };
|
||||||
|
|
||||||
|
private byte[] script;
|
||||||
|
|
||||||
|
public int[] getInboundPorts() {
|
||||||
|
return inboundPorts;
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte[] getRunScript() {
|
||||||
|
return script;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This script will be executed as the root user upon system startup.
|
||||||
|
*/
|
||||||
|
public TemplateOptions runScript(byte[] script) {
|
||||||
|
checkArgument(checkNotNull(script, "script").length <= 16 * 1024,
|
||||||
|
"script cannot be larger than 16kb");
|
||||||
|
this.script = script;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Opens the set of ports to public access.
|
||||||
|
*/
|
||||||
|
public TemplateOptions inboundPorts(int... ports) {
|
||||||
|
this.inboundPorts = ports;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Builder {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see TemplateOptions#inboundPorts
|
||||||
|
*/
|
||||||
|
public static TemplateOptions inboundPorts(int... ports) {
|
||||||
|
TemplateOptions options = new TemplateOptions();
|
||||||
|
return options.inboundPorts(ports);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see TemplateOptions#runScript
|
||||||
|
*/
|
||||||
|
public static TemplateOptions runScript(byte[] script) {
|
||||||
|
TemplateOptions options = new TemplateOptions();
|
||||||
|
return options.runScript(script);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -22,17 +22,20 @@ import static com.google.common.base.Preconditions.checkState;
|
||||||
|
|
||||||
import java.io.ByteArrayInputStream;
|
import java.io.ByteArrayInputStream;
|
||||||
import java.net.ConnectException;
|
import java.net.ConnectException;
|
||||||
|
import java.net.InetAddress;
|
||||||
import java.net.InetSocketAddress;
|
import java.net.InetSocketAddress;
|
||||||
|
import java.util.Comparator;
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
import javax.inject.Named;
|
import javax.inject.Named;
|
||||||
|
|
||||||
import org.jclouds.compute.domain.ComputeMetadata;
|
import org.jclouds.compute.domain.ComputeMetadata;
|
||||||
import org.jclouds.compute.domain.CreateNodeResponse;
|
import org.jclouds.compute.domain.NodeMetadata;
|
||||||
import org.jclouds.compute.reference.ComputeServiceConstants;
|
import org.jclouds.compute.reference.ComputeServiceConstants;
|
||||||
import org.jclouds.logging.Logger;
|
import org.jclouds.logging.Logger;
|
||||||
import org.jclouds.ssh.SshClient;
|
import org.jclouds.ssh.SshClient;
|
||||||
|
|
||||||
|
import com.google.common.base.Function;
|
||||||
import com.google.common.base.Predicate;
|
import com.google.common.base.Predicate;
|
||||||
import com.google.common.base.Throwables;
|
import com.google.common.base.Throwables;
|
||||||
import com.google.common.collect.Iterables;
|
import com.google.common.collect.Iterables;
|
||||||
|
@ -50,6 +53,13 @@ public class ComputeUtils {
|
||||||
private SshClient.Factory sshFactory;
|
private SshClient.Factory sshFactory;
|
||||||
private final Predicate<InetSocketAddress> socketTester;
|
private final Predicate<InetSocketAddress> socketTester;
|
||||||
|
|
||||||
|
public static Function<ComputeMetadata, String> METADATA_TO_ID = new Function<ComputeMetadata, String>() {
|
||||||
|
@Override
|
||||||
|
public String apply(ComputeMetadata from) {
|
||||||
|
return from.getId();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public ComputeUtils(Predicate<InetSocketAddress> socketTester) {
|
public ComputeUtils(Predicate<InetSocketAddress> socketTester) {
|
||||||
this.socketTester = socketTester;
|
this.socketTester = socketTester;
|
||||||
|
@ -65,10 +75,20 @@ public class ComputeUtils {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public void runScriptOnNode(CreateNodeResponse node, byte[] script) {
|
public static final Comparator<InetAddress> ADDRESS_COMPARATOR = new Comparator<InetAddress>() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int compare(InetAddress o1, InetAddress o2) {
|
||||||
|
return (o1 == o2) ? 0 : o1.getHostAddress().compareTo(o2.getHostAddress());
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
public void runScriptOnNode(NodeMetadata node, byte[] script) {
|
||||||
checkState(this.sshFactory != null, "runScript requested, but no SshModule configured");
|
checkState(this.sshFactory != null, "runScript requested, but no SshModule configured");
|
||||||
|
|
||||||
InetSocketAddress socket = new InetSocketAddress(node.getPublicAddresses().last(), 22);
|
InetSocketAddress socket = new InetSocketAddress(Iterables.get(node.getPublicAddresses(), 0),
|
||||||
|
22);
|
||||||
socketTester.apply(socket);
|
socketTester.apply(socket);
|
||||||
SshClient ssh = isKeyAuth(node) ? sshFactory.create(socket, node.getCredentials().account,
|
SshClient ssh = isKeyAuth(node) ? sshFactory.create(socket, node.getCredentials().account,
|
||||||
node.getCredentials().key.getBytes()) : sshFactory.create(socket, node
|
node.getCredentials().key.getBytes()) : sshFactory.create(socket, node
|
||||||
|
@ -96,7 +116,7 @@ public class ComputeUtils {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void runScriptOnNodeWithClient(SshClient ssh, CreateNodeResponse node, byte[] script) {
|
private void runScriptOnNodeWithClient(SshClient ssh, NodeMetadata node, byte[] script) {
|
||||||
String scriptName = node.getId() + ".sh";
|
String scriptName = node.getId() + ".sh";
|
||||||
ssh.put(scriptName, new ByteArrayInputStream(script));
|
ssh.put(scriptName, new ByteArrayInputStream(script));
|
||||||
ssh.exec("chmod 755 " + scriptName);
|
ssh.exec("chmod 755 " + scriptName);
|
||||||
|
@ -114,7 +134,7 @@ public class ComputeUtils {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean isKeyAuth(CreateNodeResponse createdNode) {
|
public static boolean isKeyAuth(NodeMetadata createdNode) {
|
||||||
return createdNode.getCredentials().key != null
|
return createdNode.getCredentials().key != null
|
||||||
&& createdNode.getCredentials().key.startsWith("-----BEGIN RSA PRIVATE KEY-----");
|
&& createdNode.getCredentials().key.startsWith("-----BEGIN RSA PRIVATE KEY-----");
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,20 +25,23 @@ import static org.testng.Assert.assertNotNull;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.net.InetSocketAddress;
|
import java.net.InetSocketAddress;
|
||||||
import java.util.NoSuchElementException;
|
import java.util.NoSuchElementException;
|
||||||
|
import java.util.SortedSet;
|
||||||
|
import java.util.Map.Entry;
|
||||||
import java.util.concurrent.ExecutionException;
|
import java.util.concurrent.ExecutionException;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
import java.util.concurrent.TimeoutException;
|
import java.util.concurrent.TimeoutException;
|
||||||
|
|
||||||
import org.jclouds.compute.domain.ComputeMetadata;
|
import org.jclouds.compute.domain.ComputeMetadata;
|
||||||
import org.jclouds.compute.domain.ComputeType;
|
import org.jclouds.compute.domain.ComputeType;
|
||||||
import org.jclouds.compute.domain.CreateNodeResponse;
|
|
||||||
import org.jclouds.compute.domain.Image;
|
import org.jclouds.compute.domain.Image;
|
||||||
import org.jclouds.compute.domain.NodeMetadata;
|
import org.jclouds.compute.domain.NodeMetadata;
|
||||||
|
import org.jclouds.compute.domain.NodeSet;
|
||||||
|
import org.jclouds.compute.domain.NodeState;
|
||||||
import org.jclouds.compute.domain.OsFamily;
|
import org.jclouds.compute.domain.OsFamily;
|
||||||
import org.jclouds.compute.domain.Size;
|
import org.jclouds.compute.domain.Size;
|
||||||
import org.jclouds.compute.domain.Template;
|
import org.jclouds.compute.domain.Template;
|
||||||
import org.jclouds.compute.domain.TemplateBuilder;
|
import org.jclouds.compute.domain.TemplateBuilder;
|
||||||
import org.jclouds.compute.options.RunNodeOptions;
|
import org.jclouds.domain.Location;
|
||||||
import org.jclouds.http.HttpResponseException;
|
import org.jclouds.http.HttpResponseException;
|
||||||
import org.jclouds.logging.log4j.config.Log4JLoggingModule;
|
import org.jclouds.logging.log4j.config.Log4JLoggingModule;
|
||||||
import org.jclouds.predicates.RetryablePredicate;
|
import org.jclouds.predicates.RetryablePredicate;
|
||||||
|
@ -56,6 +59,7 @@ import org.testng.annotations.Test;
|
||||||
import com.google.common.base.Predicate;
|
import com.google.common.base.Predicate;
|
||||||
import com.google.common.collect.ImmutableSet;
|
import com.google.common.collect.ImmutableSet;
|
||||||
import com.google.common.collect.Iterables;
|
import com.google.common.collect.Iterables;
|
||||||
|
import com.google.common.collect.Sets;
|
||||||
import com.google.inject.Guice;
|
import com.google.inject.Guice;
|
||||||
import com.google.inject.Injector;
|
import com.google.inject.Injector;
|
||||||
import com.google.inject.Module;
|
import com.google.inject.Module;
|
||||||
|
@ -71,11 +75,10 @@ public abstract class BaseComputeServiceLiveTest {
|
||||||
|
|
||||||
protected String service;
|
protected String service;
|
||||||
protected SshClient.Factory sshFactory;
|
protected SshClient.Factory sshFactory;
|
||||||
protected RunNodeOptions options = RunNodeOptions.Builder.openPorts(22);
|
protected String tag;
|
||||||
protected String nodeName;
|
|
||||||
|
|
||||||
private RetryablePredicate<InetSocketAddress> socketTester;
|
private RetryablePredicate<InetSocketAddress> socketTester;
|
||||||
private CreateNodeResponse node;
|
private SortedSet<NodeMetadata> nodes;
|
||||||
protected ComputeServiceContext context;
|
protected ComputeServiceContext context;
|
||||||
protected ComputeService client;
|
protected ComputeService client;
|
||||||
protected String user;
|
protected String user;
|
||||||
|
@ -85,7 +88,8 @@ public abstract class BaseComputeServiceLiveTest {
|
||||||
@BeforeGroups(groups = { "live" })
|
@BeforeGroups(groups = { "live" })
|
||||||
public void setupClient() throws InterruptedException, ExecutionException, TimeoutException,
|
public void setupClient() throws InterruptedException, ExecutionException, TimeoutException,
|
||||||
IOException {
|
IOException {
|
||||||
if (nodeName == null) nodeName = checkNotNull(service, "service");
|
if (tag == null)
|
||||||
|
tag = checkNotNull(service, "service");
|
||||||
user = checkNotNull(System.getProperty("jclouds.test.user"), "jclouds.test.user");
|
user = checkNotNull(System.getProperty("jclouds.test.user"), "jclouds.test.user");
|
||||||
password = checkNotNull(System.getProperty("jclouds.test.key"), "jclouds.test.key");
|
password = checkNotNull(System.getProperty("jclouds.test.key"), "jclouds.test.key");
|
||||||
context = new ComputeServiceContextFactory().createContext(service, user, password,
|
context = new ComputeServiceContextFactory().createContext(service, user, password,
|
||||||
|
@ -108,12 +112,7 @@ public abstract class BaseComputeServiceLiveTest {
|
||||||
@Test(enabled = true)
|
@Test(enabled = true)
|
||||||
public void testCreate() throws Exception {
|
public void testCreate() throws Exception {
|
||||||
try {
|
try {
|
||||||
client.destroyNode(Iterables.find(client.listNodes(), new Predicate<ComputeMetadata>() {
|
client.destroyNodes(tag);
|
||||||
@Override
|
|
||||||
public boolean apply(ComputeMetadata input) {
|
|
||||||
return input.getName().equals(nodeName);
|
|
||||||
}
|
|
||||||
}));
|
|
||||||
} catch (HttpResponseException e) {
|
} catch (HttpResponseException e) {
|
||||||
// TODO hosting.com throws 400 when we try to delete a vApp
|
// TODO hosting.com throws 400 when we try to delete a vApp
|
||||||
} catch (NoSuchElementException e) {
|
} catch (NoSuchElementException e) {
|
||||||
|
@ -122,75 +121,133 @@ public abstract class BaseComputeServiceLiveTest {
|
||||||
template = buildTemplate(client.templateBuilder());
|
template = buildTemplate(client.templateBuilder());
|
||||||
|
|
||||||
if (canRunScript(template))
|
if (canRunScript(template))
|
||||||
options.runScript(new ScriptBuilder()
|
template
|
||||||
|
.getOptions()
|
||||||
|
.runScript(
|
||||||
|
new ScriptBuilder()
|
||||||
// update add dns and install jdk
|
// update add dns and install jdk
|
||||||
.addStatement(
|
.addStatement(
|
||||||
Statements.exec("echo nameserver 208.67.222.222 >> /etc/resolv.conf"))
|
Statements
|
||||||
.addStatement(Statements.exec("apt-get update"))//
|
.exec("echo nameserver 208.67.222.222 >> /etc/resolv.conf"))
|
||||||
.addStatement(Statements.exec("apt-get upgrade -y"))//
|
.addStatement(Statements.exec("apt-get update"))
|
||||||
.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("apt-get upgrade -y"))
|
||||||
.addStatement(Statements.exec("chmod 755 /usr/bin/runurl"))//
|
//
|
||||||
.build(org.jclouds.scriptbuilder.domain.OsFamily.UNIX).getBytes());
|
.addStatement(
|
||||||
node = client.runNode(nodeName, template, options);
|
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(org.jclouds.scriptbuilder.domain.OsFamily.UNIX)
|
||||||
|
.getBytes());
|
||||||
|
nodes = Sets.newTreeSet(client.runNodes(tag, 2, template));
|
||||||
|
assertEquals(nodes.size(), 2);
|
||||||
|
for (NodeMetadata node : nodes) {
|
||||||
assertNotNull(node.getId());
|
assertNotNull(node.getId());
|
||||||
assertNotNull(node.getName());
|
assertNotNull(node.getTag());
|
||||||
assert node.getPublicAddresses().size() >= 1: "no public ips in" + node;
|
assertEquals(node.getTag(), tag);
|
||||||
|
assert node.getPublicAddresses().size() >= 1 || node.getPrivateAddresses().size() >= 1 : "no ips in"
|
||||||
|
+ node;
|
||||||
assertNotNull(node.getCredentials());
|
assertNotNull(node.getCredentials());
|
||||||
if (node.getCredentials().account != null) {
|
if (node.getCredentials().account != null) {
|
||||||
assertNotNull(node.getCredentials().account);
|
assertNotNull(node.getCredentials().account);
|
||||||
assertNotNull(node.getCredentials().key);
|
assertNotNull(node.getCredentials().key);
|
||||||
sshPing();
|
sshPing(node);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NodeMetadata node1 = nodes.first();
|
||||||
|
NodeMetadata node2 = nodes.last();
|
||||||
|
// credentials aren't always the same
|
||||||
|
// assertEquals(node1.getCredentials(), node2.getCredentials());
|
||||||
|
assert !node1.getId().equals(node2.getId());
|
||||||
|
}
|
||||||
|
|
||||||
protected abstract Template buildTemplate(TemplateBuilder templateBuilder);
|
protected abstract Template buildTemplate(TemplateBuilder templateBuilder);
|
||||||
|
|
||||||
@Test(enabled = true, dependsOnMethods = "testCreate")
|
@Test(enabled = true, dependsOnMethods = "testCreate")
|
||||||
public void testGet() throws Exception {
|
public void testGet() throws Exception {
|
||||||
|
NodeSet metadataSet = client.getNodes(tag);
|
||||||
|
for (NodeMetadata node : nodes) {
|
||||||
|
metadataSet.remove(node);
|
||||||
NodeMetadata metadata = client.getNodeMetadata(node);
|
NodeMetadata metadata = client.getNodeMetadata(node);
|
||||||
assertEquals(metadata.getId(), node.getId());
|
assertEquals(metadata.getId(), node.getId());
|
||||||
assertEquals(metadata.getName(), node.getName());
|
assertEquals(metadata.getName(), node.getName());
|
||||||
assertEquals(metadata.getPrivateAddresses(), node.getPrivateAddresses());
|
assertEquals(metadata.getPrivateAddresses(), node.getPrivateAddresses());
|
||||||
assertEquals(metadata.getPublicAddresses(), node.getPublicAddresses());
|
assertEquals(metadata.getPublicAddresses(), node.getPublicAddresses());
|
||||||
}
|
}
|
||||||
|
assert Iterables.all(metadataSet, new Predicate<NodeMetadata>() {
|
||||||
|
@Override
|
||||||
|
public boolean apply(NodeMetadata input) {
|
||||||
|
return input.getState() == NodeState.TERMINATED;
|
||||||
|
}
|
||||||
|
}) : metadataSet;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
public void testListNodes() throws Exception {
|
public void testListNodes() throws Exception {
|
||||||
for (ComputeMetadata node : client.listNodes()) {
|
for (Entry<String, ? extends ComputeMetadata> node : client.getNodes().entrySet()) {
|
||||||
assert node.getId() != null;
|
assertEquals(node.getKey(), node.getValue().getId());
|
||||||
assert node.getLocation() != null;
|
assert node.getValue().getId() != null;
|
||||||
assertEquals(node.getType(), ComputeType.NODE);
|
assert node.getValue().getLocationId() != null;
|
||||||
|
assertEquals(node.getValue().getType(), ComputeType.NODE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testListImages() throws Exception {
|
public void testListImages() throws Exception {
|
||||||
for (Image image : client.listImages()) {
|
for (Entry<String, ? extends Image> image : client.getImages().entrySet()) {
|
||||||
assert image.getId() != null : image;
|
assertEquals(image.getKey(), image.getValue().getId());
|
||||||
assert image.getLocation() != null : image;
|
assert image.getValue().getId() != null : image;
|
||||||
|
assert image.getValue().getLocationId() != null : image;
|
||||||
|
assertEquals(image.getValue().getType(), ComputeType.IMAGE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testListLocations() throws Exception {
|
||||||
|
for (Entry<String, ? extends Location> image : client.getLocations().entrySet()) {
|
||||||
|
assertEquals(image.getKey(), image.getValue().getId());
|
||||||
|
assert image.getValue().getId() != null : image;
|
||||||
|
assert image.getValue().getId() != image.getValue().getParent() : image;
|
||||||
|
assert image.getValue().getScope() != null : image;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testListSizes() throws Exception {
|
public void testListSizes() throws Exception {
|
||||||
for (Size size : client.listSizes()) {
|
for (Entry<String, ? extends Size> size : client.getSizes().entrySet()) {
|
||||||
assert size.getCores() > 0 : size;
|
assertEquals(size.getKey(), size.getValue().getId());
|
||||||
|
assert size.getValue().getId() != null;
|
||||||
|
assert size.getValue().getCores() > 0;
|
||||||
|
assert size.getValue().getDisk() > 0;
|
||||||
|
assert size.getValue().getRam() > 0;
|
||||||
|
assert size.getValue().getSupportedArchitectures() != null;
|
||||||
|
assertEquals(size.getValue().getType(), ComputeType.SIZE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void sshPing() throws IOException {
|
private void sshPing(NodeMetadata node) throws IOException {
|
||||||
|
for (int i = 0; i < 5; i++) {// retry loop TODO replace with predicate.
|
||||||
try {
|
try {
|
||||||
doCheckKey();
|
doCheckKey(node);
|
||||||
} catch (SshException e) {// try twice in case there is a network timeout
|
return;
|
||||||
|
} catch (SshException e) {
|
||||||
try {
|
try {
|
||||||
Thread.sleep(10 * 1000);
|
Thread.sleep(10 * 1000);
|
||||||
} catch (InterruptedException e1) {
|
} catch (InterruptedException e1) {
|
||||||
}
|
}
|
||||||
doCheckKey();
|
continue;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void doCheckKey() throws IOException {
|
private void doCheckKey(NodeMetadata node) throws IOException {
|
||||||
InetSocketAddress socket = new InetSocketAddress(node.getPublicAddresses().last(), 22);
|
InetSocketAddress socket = new InetSocketAddress(Iterables.get(node.getPublicAddresses(), 0),
|
||||||
socketTester.apply(socket);
|
22);
|
||||||
|
socketTester.apply(socket); // TODO add transitionTo option that accepts a socket conection
|
||||||
|
// state.
|
||||||
SshClient ssh = node.getCredentials().key.startsWith("-----BEGIN RSA PRIVATE KEY-----") ? sshFactory
|
SshClient ssh = node.getCredentials().key.startsWith("-----BEGIN RSA PRIVATE KEY-----") ? sshFactory
|
||||||
.create(socket, node.getCredentials().account, node.getCredentials().key.getBytes())
|
.create(socket, node.getCredentials().account, node.getCredentials().key.getBytes())
|
||||||
: sshFactory
|
: sshFactory
|
||||||
|
@ -209,8 +266,12 @@ public abstract class BaseComputeServiceLiveTest {
|
||||||
|
|
||||||
@AfterTest
|
@AfterTest
|
||||||
protected void cleanup() throws InterruptedException, ExecutionException, TimeoutException {
|
protected void cleanup() throws InterruptedException, ExecutionException, TimeoutException {
|
||||||
if (node != null)
|
if (nodes != null) {
|
||||||
client.destroyNode(node);
|
client.destroyNodes(tag);
|
||||||
|
for (NodeMetadata node : client.getNodes(tag)) {
|
||||||
|
assert node.getState() == NodeState.TERMINATED : node;
|
||||||
|
}
|
||||||
|
}
|
||||||
context.close();
|
context.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -101,9 +101,9 @@ public class ConcurrentUtils {
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String message(String prefix, int size, int complete, int errors, long start) {
|
private static String message(String prefix, int size, int complete, int errors, long start) {
|
||||||
return String.format("%s, completed: %d/%d, errors: %d, rate: %f ops/sec%n", prefix,
|
return String
|
||||||
complete, size, errors, ((double) complete)
|
.format("%s, completed: %d/%d, errors: %d, rate: %fms/op%n", prefix, complete,
|
||||||
/ ((System.currentTimeMillis() - start) / 1000.0));
|
size, errors, ((System.currentTimeMillis() - start) / ((double) size)));
|
||||||
}
|
}
|
||||||
|
|
||||||
protected static boolean timeOut(long start, Long maxTime) {
|
protected static boolean timeOut(long start, Long maxTime) {
|
||||||
|
|
|
@ -0,0 +1,62 @@
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* 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.domain;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Running Operating system
|
||||||
|
*
|
||||||
|
* @author Adrian Cole
|
||||||
|
*/
|
||||||
|
public interface Location {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Scope of the location, ex. region, datacenter
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
LocationScope getScope();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unique ID provided by the provider (us-standard, miami, etc)
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
String getId();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Description of the location
|
||||||
|
*/
|
||||||
|
String getDescription();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Id of the parent, or null, if top-level
|
||||||
|
*/
|
||||||
|
String getParent();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether nodes can be assigned to this location. It is possible that a location is a container
|
||||||
|
* type that cannot be assigned to, or that a location is full.
|
||||||
|
*/
|
||||||
|
boolean isAssignable();
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,30 @@
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* 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.domain;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The scope of the location
|
||||||
|
*
|
||||||
|
* @author Adrian Cole
|
||||||
|
*/
|
||||||
|
public enum LocationScope {
|
||||||
|
|
||||||
|
REGION, ZONE, RACK, HOST;
|
||||||
|
|
||||||
|
}
|
|
@ -51,7 +51,7 @@ public interface MutableResourceMetadata<T extends Enum<T>> extends ResourceMeta
|
||||||
/**
|
/**
|
||||||
* @see #getLocation
|
* @see #getLocation
|
||||||
*/
|
*/
|
||||||
void setLocation(String location);
|
void setLocationId(String location);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see #getUri
|
* @see #getUri
|
||||||
|
|
|
@ -1,21 +0,0 @@
|
||||||
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 {
|
|
||||||
|
|
||||||
}
|
|
|
@ -52,12 +52,12 @@ public interface ResourceMetadata<T extends Enum<T>> extends Comparable<Resource
|
||||||
String getName();
|
String getName();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Physical location of the resource.
|
* Physical location of the resource, or null if n/a
|
||||||
*
|
*
|
||||||
* ex. us-west-1
|
* ex. us-west-1
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
String getLocation();
|
String getLocationId();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* URI used to access this resource
|
* URI used to access this resource
|
||||||
|
@ -69,4 +69,5 @@ public interface ResourceMetadata<T extends Enum<T>> extends Comparable<Resource
|
||||||
*/
|
*/
|
||||||
Map<String, String> getUserMetadata();
|
Map<String, String> getUserMetadata();
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
|
@ -0,0 +1,127 @@
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* 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.domain.internal;
|
||||||
|
|
||||||
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
|
import org.jclouds.domain.Location;
|
||||||
|
import org.jclouds.domain.LocationScope;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Idpayload of the object
|
||||||
|
*
|
||||||
|
* @author Adrian Cole
|
||||||
|
*/
|
||||||
|
public class LocationImpl implements Location, Serializable {
|
||||||
|
|
||||||
|
/** The serialVersionUID */
|
||||||
|
private static final long serialVersionUID = -280558162576368264L;
|
||||||
|
|
||||||
|
private final LocationScope scope;
|
||||||
|
private final String id;
|
||||||
|
private final String description;
|
||||||
|
private final String parent;
|
||||||
|
private final boolean assignable;
|
||||||
|
|
||||||
|
public LocationImpl(LocationScope scope, String id, String description, @Nullable String parent,
|
||||||
|
boolean assignable) {
|
||||||
|
this.scope = checkNotNull(scope, "scope");
|
||||||
|
this.id = checkNotNull(id, "id");
|
||||||
|
this.description = checkNotNull(description, "description");
|
||||||
|
this.parent = parent;
|
||||||
|
this.assignable = checkNotNull(assignable, "assignable");
|
||||||
|
}
|
||||||
|
|
||||||
|
public LocationScope getScope() {
|
||||||
|
return scope;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDescription() {
|
||||||
|
return description;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getParent() {
|
||||||
|
return parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isAssignable() {
|
||||||
|
return assignable;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
final int prime = 31;
|
||||||
|
int result = 1;
|
||||||
|
result = prime * result + (assignable ? 1231 : 1237);
|
||||||
|
result = prime * result + ((description == null) ? 0 : description.hashCode());
|
||||||
|
result = prime * result + ((id == null) ? 0 : id.hashCode());
|
||||||
|
result = prime * result + ((parent == null) ? 0 : parent.hashCode());
|
||||||
|
result = prime * result + ((scope == null) ? 0 : scope.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;
|
||||||
|
LocationImpl other = (LocationImpl) obj;
|
||||||
|
if (assignable != other.assignable)
|
||||||
|
return false;
|
||||||
|
if (description == null) {
|
||||||
|
if (other.description != null)
|
||||||
|
return false;
|
||||||
|
} else if (!description.equals(other.description))
|
||||||
|
return false;
|
||||||
|
if (id == null) {
|
||||||
|
if (other.id != null)
|
||||||
|
return false;
|
||||||
|
} else if (!id.equals(other.id))
|
||||||
|
return false;
|
||||||
|
if (parent == null) {
|
||||||
|
if (other.parent != null)
|
||||||
|
return false;
|
||||||
|
} else if (!parent.equals(other.parent))
|
||||||
|
return false;
|
||||||
|
if (scope == null) {
|
||||||
|
if (other.scope != null)
|
||||||
|
return false;
|
||||||
|
} else if (!scope.equals(other.scope))
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "[id=" + id + ", scope=" + scope + ", description=" + description + ", parent="
|
||||||
|
+ parent + ", assignable=" + assignable + "]";
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -57,7 +57,7 @@ public class MutableResourceMetadataImpl<T extends Enum<T>> implements MutableRe
|
||||||
this.type = from.getType();
|
this.type = from.getType();
|
||||||
this.id = from.getId();
|
this.id = from.getId();
|
||||||
this.name = from.getName();
|
this.name = from.getName();
|
||||||
this.location = from.getLocation();
|
this.location = from.getLocationId();
|
||||||
this.uri = from.getUri();
|
this.uri = from.getUri();
|
||||||
this.userMetadata = from.getUserMetadata();
|
this.userMetadata = from.getUserMetadata();
|
||||||
}
|
}
|
||||||
|
@ -156,7 +156,7 @@ public class MutableResourceMetadataImpl<T extends Enum<T>> implements MutableRe
|
||||||
* {@inheritDoc}
|
* {@inheritDoc}
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void setLocation(String location) {
|
public void setLocationId(String location) {
|
||||||
this.location = location;
|
this.location = location;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -164,7 +164,7 @@ public class MutableResourceMetadataImpl<T extends Enum<T>> implements MutableRe
|
||||||
* {@inheritDoc}
|
* {@inheritDoc}
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public String getLocation() {
|
public String getLocationId() {
|
||||||
return location;
|
return location;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -45,17 +45,17 @@ public class ResourceMetadataImpl<T extends Enum<T>> implements ResourceMetadata
|
||||||
@Nullable
|
@Nullable
|
||||||
private final String name;
|
private final String name;
|
||||||
@Nullable
|
@Nullable
|
||||||
private final String location;
|
private final String locationId;
|
||||||
@Nullable
|
@Nullable
|
||||||
private final URI uri;
|
private final URI uri;
|
||||||
private final Map<String, String> userMetadata = Maps.newLinkedHashMap();
|
private final Map<String, String> userMetadata = Maps.newLinkedHashMap();
|
||||||
|
|
||||||
public ResourceMetadataImpl(T type, @Nullable String id, @Nullable String name,
|
public ResourceMetadataImpl(T type, @Nullable String id, @Nullable String name,
|
||||||
@Nullable String location, @Nullable URI uri, Map<String, String> userMetadata) {
|
@Nullable String locationId, @Nullable URI uri, Map<String, String> userMetadata) {
|
||||||
this.type = checkNotNull(type, "type");
|
this.type = checkNotNull(type, "type");
|
||||||
this.id = id;
|
this.id = id;
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.location = location;
|
this.locationId = locationId;
|
||||||
this.uri = uri;
|
this.uri = uri;
|
||||||
this.userMetadata.putAll(checkNotNull(userMetadata, "userMetadata"));
|
this.userMetadata.putAll(checkNotNull(userMetadata, "userMetadata"));
|
||||||
}
|
}
|
||||||
|
@ -98,8 +98,8 @@ public class ResourceMetadataImpl<T extends Enum<T>> implements ResourceMetadata
|
||||||
* {@inheritDoc}
|
* {@inheritDoc}
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public String getLocation() {
|
public String getLocationId() {
|
||||||
return location;
|
return locationId;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -123,7 +123,7 @@ public class ResourceMetadataImpl<T extends Enum<T>> implements ResourceMetadata
|
||||||
final int prime = 31;
|
final int prime = 31;
|
||||||
int result = 1;
|
int result = 1;
|
||||||
result = prime * result + ((id == null) ? 0 : id.hashCode());
|
result = prime * result + ((id == null) ? 0 : id.hashCode());
|
||||||
result = prime * result + ((location == null) ? 0 : location.hashCode());
|
result = prime * result + ((locationId == null) ? 0 : locationId.hashCode());
|
||||||
result = prime * result + ((name == null) ? 0 : name.hashCode());
|
result = prime * result + ((name == null) ? 0 : name.hashCode());
|
||||||
result = prime * result + ((type == null) ? 0 : type.hashCode());
|
result = prime * result + ((type == null) ? 0 : type.hashCode());
|
||||||
result = prime * result + ((uri == null) ? 0 : uri.hashCode());
|
result = prime * result + ((uri == null) ? 0 : uri.hashCode());
|
||||||
|
@ -145,10 +145,10 @@ public class ResourceMetadataImpl<T extends Enum<T>> implements ResourceMetadata
|
||||||
return false;
|
return false;
|
||||||
} else if (!id.equals(other.id))
|
} else if (!id.equals(other.id))
|
||||||
return false;
|
return false;
|
||||||
if (location == null) {
|
if (locationId == null) {
|
||||||
if (other.location != null)
|
if (other.locationId != null)
|
||||||
return false;
|
return false;
|
||||||
} else if (!location.equals(other.location))
|
} else if (!locationId.equals(other.locationId))
|
||||||
return false;
|
return false;
|
||||||
if (name == null) {
|
if (name == null) {
|
||||||
if (other.name != null)
|
if (other.name != null)
|
||||||
|
@ -175,7 +175,7 @@ public class ResourceMetadataImpl<T extends Enum<T>> implements ResourceMetadata
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "[type=" + type + ", id=" + id + ", name=" + name + ", location=" + location
|
return "[type=" + type + ", id=" + id + ", name=" + name + ", locationId=" + locationId
|
||||||
+ ", uri=" + uri + ", userMetadata=" + userMetadata + "]";
|
+ ", uri=" + uri + ", userMetadata=" + userMetadata + "]";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -20,9 +20,16 @@ package org.jclouds.rackspace.cloudservers.compute;
|
||||||
|
|
||||||
import static com.google.common.base.Preconditions.checkArgument;
|
import static com.google.common.base.Preconditions.checkArgument;
|
||||||
import static com.google.common.base.Preconditions.checkNotNull;
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
|
import static org.jclouds.compute.util.ComputeUtils.METADATA_TO_ID;
|
||||||
|
import static org.jclouds.concurrent.ConcurrentUtils.awaitCompletion;
|
||||||
|
import static org.jclouds.concurrent.ConcurrentUtils.makeListenable;
|
||||||
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import java.util.concurrent.Callable;
|
||||||
|
import java.util.concurrent.ExecutorService;
|
||||||
|
import java.util.regex.Matcher;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
@ -30,71 +37,96 @@ import javax.inject.Named;
|
||||||
import javax.inject.Provider;
|
import javax.inject.Provider;
|
||||||
import javax.inject.Singleton;
|
import javax.inject.Singleton;
|
||||||
|
|
||||||
|
import org.jclouds.Constants;
|
||||||
import org.jclouds.compute.ComputeService;
|
import org.jclouds.compute.ComputeService;
|
||||||
import org.jclouds.compute.domain.ComputeMetadata;
|
import org.jclouds.compute.domain.ComputeMetadata;
|
||||||
import org.jclouds.compute.domain.ComputeType;
|
import org.jclouds.compute.domain.ComputeType;
|
||||||
import org.jclouds.compute.domain.CreateNodeResponse;
|
|
||||||
import org.jclouds.compute.domain.Image;
|
import org.jclouds.compute.domain.Image;
|
||||||
import org.jclouds.compute.domain.NodeMetadata;
|
import org.jclouds.compute.domain.NodeMetadata;
|
||||||
|
import org.jclouds.compute.domain.NodeSet;
|
||||||
import org.jclouds.compute.domain.NodeState;
|
import org.jclouds.compute.domain.NodeState;
|
||||||
import org.jclouds.compute.domain.Size;
|
import org.jclouds.compute.domain.Size;
|
||||||
import org.jclouds.compute.domain.Template;
|
import org.jclouds.compute.domain.Template;
|
||||||
import org.jclouds.compute.domain.TemplateBuilder;
|
import org.jclouds.compute.domain.TemplateBuilder;
|
||||||
import org.jclouds.compute.domain.internal.CreateNodeResponseImpl;
|
|
||||||
import org.jclouds.compute.domain.internal.NodeMetadataImpl;
|
import org.jclouds.compute.domain.internal.NodeMetadataImpl;
|
||||||
import org.jclouds.compute.options.RunNodeOptions;
|
import org.jclouds.compute.domain.internal.NodeSetImpl;
|
||||||
import org.jclouds.compute.reference.ComputeServiceConstants;
|
import org.jclouds.compute.reference.ComputeServiceConstants;
|
||||||
import org.jclouds.compute.util.ComputeUtils;
|
import org.jclouds.compute.util.ComputeUtils;
|
||||||
|
import org.jclouds.concurrent.ConcurrentUtils;
|
||||||
import org.jclouds.domain.Credentials;
|
import org.jclouds.domain.Credentials;
|
||||||
import org.jclouds.domain.ResourceLocation;
|
import org.jclouds.domain.Location;
|
||||||
import org.jclouds.logging.Logger;
|
import org.jclouds.logging.Logger;
|
||||||
import org.jclouds.rackspace.cloudservers.CloudServersClient;
|
import org.jclouds.rackspace.cloudservers.CloudServersClient;
|
||||||
import org.jclouds.rackspace.cloudservers.compute.domain.CloudServersImage;
|
|
||||||
import org.jclouds.rackspace.cloudservers.compute.domain.CloudServersSize;
|
|
||||||
import org.jclouds.rackspace.cloudservers.domain.Server;
|
import org.jclouds.rackspace.cloudservers.domain.Server;
|
||||||
import org.jclouds.rackspace.cloudservers.domain.ServerStatus;
|
import org.jclouds.rackspace.cloudservers.domain.ServerStatus;
|
||||||
import org.jclouds.rackspace.cloudservers.options.ListOptions;
|
import org.jclouds.rackspace.cloudservers.options.ListOptions;
|
||||||
|
import org.jclouds.rackspace.reference.RackspaceConstants;
|
||||||
|
|
||||||
import com.google.common.base.Function;
|
import com.google.common.base.Function;
|
||||||
import com.google.common.base.Predicate;
|
import com.google.common.base.Predicate;
|
||||||
import com.google.common.collect.ImmutableMap;
|
import com.google.common.collect.ImmutableMap;
|
||||||
import com.google.common.collect.Iterables;
|
import com.google.common.collect.Iterables;
|
||||||
|
import com.google.common.collect.Maps;
|
||||||
import com.google.common.collect.Sets;
|
import com.google.common.collect.Sets;
|
||||||
|
import com.google.common.util.concurrent.ListenableFuture;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Adrian Cole
|
* @author Adrian Cole
|
||||||
*/
|
*/
|
||||||
@Singleton
|
@Singleton
|
||||||
public class CloudServersComputeService implements ComputeService {
|
public class CloudServersComputeService implements ComputeService {
|
||||||
|
|
||||||
|
private static class NodeMatchesTag implements Predicate<NodeMetadata> {
|
||||||
|
private final String tag;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean apply(NodeMetadata from) {
|
||||||
|
return from.getTag().equals(tag);
|
||||||
|
}
|
||||||
|
|
||||||
|
public NodeMatchesTag(String tag) {
|
||||||
|
super();
|
||||||
|
this.tag = tag;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
@Named(ComputeServiceConstants.COMPUTE_LOGGER)
|
@Named(ComputeServiceConstants.COMPUTE_LOGGER)
|
||||||
protected Logger logger = Logger.NULL;
|
protected Logger logger = Logger.NULL;
|
||||||
private final org.jclouds.rackspace.cloudservers.CloudServersClient client;
|
private final org.jclouds.rackspace.cloudservers.CloudServersClient client;
|
||||||
protected final Provider<Set<? extends Image>> images;
|
protected final Provider<Map<String, ? extends Image>> images;
|
||||||
protected final Provider<Set<? extends Size>> sizes;
|
protected final Provider<Map<String, ? extends Size>> sizes;
|
||||||
|
protected final Provider<Map<String, ? extends Location>> locations;
|
||||||
protected final Provider<TemplateBuilder> templateBuilderProvider;
|
protected final Provider<TemplateBuilder> templateBuilderProvider;
|
||||||
private final String location;
|
|
||||||
private final ComputeUtils utils;
|
private final ComputeUtils utils;
|
||||||
private final Predicate<Server> serverActive;
|
private final Predicate<Server> serverActive;
|
||||||
private final ServerToNodeMetadata serverToNodeMetadata;
|
private final ServerToNodeMetadata serverToNodeMetadata;
|
||||||
private final Predicate<Server> serverDeleted;
|
private final Predicate<Server> serverDeleted;
|
||||||
|
protected final ExecutorService executor;
|
||||||
|
private final String account;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public CloudServersComputeService(CloudServersClient client,
|
public CloudServersComputeService(CloudServersClient client,
|
||||||
Provider<TemplateBuilder> templateBuilderProvider, @ResourceLocation String location,
|
Provider<TemplateBuilder> templateBuilderProvider,
|
||||||
Provider<Set<? extends Image>> images, Provider<Set<? extends Size>> sizes,
|
Provider<Map<String, ? extends Image>> images,
|
||||||
ComputeUtils utils, @Named("ACTIVE") Predicate<Server> serverActive,
|
Provider<Map<String, ? extends Size>> sizes,
|
||||||
|
Provider<Map<String, ? extends Location>> locations, ComputeUtils utils,
|
||||||
|
@Named("ACTIVE") Predicate<Server> serverActive,
|
||||||
@Named("DELETED") Predicate<Server> serverDeleted,
|
@Named("DELETED") Predicate<Server> serverDeleted,
|
||||||
ServerToNodeMetadata serverToNodeMetadata) {
|
@Named(RackspaceConstants.PROPERTY_RACKSPACE_USER) String account,
|
||||||
this.location = location;
|
ServerToNodeMetadata serverToNodeMetadata,
|
||||||
|
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService executor) {
|
||||||
this.client = client;
|
this.client = client;
|
||||||
this.images = images;
|
this.images = images;
|
||||||
this.sizes = sizes;
|
this.sizes = sizes;
|
||||||
|
this.locations = locations;
|
||||||
this.utils = utils;
|
this.utils = utils;
|
||||||
this.templateBuilderProvider = templateBuilderProvider;
|
this.templateBuilderProvider = templateBuilderProvider;
|
||||||
this.serverActive = serverActive;
|
this.serverActive = serverActive;
|
||||||
this.serverDeleted = serverDeleted;
|
this.serverDeleted = serverDeleted;
|
||||||
|
this.account = account;
|
||||||
this.serverToNodeMetadata = serverToNodeMetadata;
|
this.serverToNodeMetadata = serverToNodeMetadata;
|
||||||
|
this.executor = executor;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Map<ServerStatus, NodeState> serverToNodeState = ImmutableMap
|
private static Map<ServerStatus, NodeState> serverToNodeState = ImmutableMap
|
||||||
|
@ -123,38 +155,40 @@ public class CloudServersComputeService implements ComputeService {
|
||||||
.put(ServerStatus.UNKNOWN, NodeState.UNKNOWN).build();
|
.put(ServerStatus.UNKNOWN, NodeState.UNKNOWN).build();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CreateNodeResponse runNode(String name, Template template) {
|
public NodeSet runNodes(final String tag, int max, final Template template) {
|
||||||
return this.runNode(name, template, RunNodeOptions.NONE);
|
checkArgument(tag.indexOf('-') == -1, "tag cannot contain hyphens");
|
||||||
}
|
logger.debug(">> running server image(%s) flavor(%s)", template.getImage().getId(), template
|
||||||
|
.getSize().getId());
|
||||||
|
|
||||||
|
final Set<NodeMetadata> nodes = Sets.newHashSet();
|
||||||
|
Set<ListenableFuture<Void>> responses = Sets.newHashSet();
|
||||||
|
for (int i = 0; i < max; i++) {
|
||||||
|
final String name = String.format("%s-%s-%d", account, tag, i + 1);
|
||||||
|
responses.add(ConcurrentUtils.makeListenable(executor.submit(new Callable<Void>() {
|
||||||
@Override
|
@Override
|
||||||
public CreateNodeResponse runNode(String name, Template template, RunNodeOptions options) {
|
public Void call() throws Exception {
|
||||||
checkArgument(template.getImage() instanceof CloudServersImage,
|
Server server = client.createServer(name, Integer.parseInt(template.getImage()
|
||||||
"unexpected image type. should be CloudServersImage, was: "
|
.getId()), Integer.parseInt(template.getSize().getId()));
|
||||||
+ template.getImage().getClass());
|
|
||||||
CloudServersImage cloudServersImage = CloudServersImage.class.cast(template.getImage());
|
|
||||||
checkArgument(template.getSize() instanceof CloudServersSize,
|
|
||||||
"unexpected size type. should be CloudServersSize, was: "
|
|
||||||
+ template.getSize().getClass());
|
|
||||||
CloudServersSize cloudServersSize = CloudServersSize.class.cast(template.getSize());
|
|
||||||
|
|
||||||
logger.debug(">> running server location(%s) image(%s) flavor(%s)", location,
|
NodeMetadata node = new NodeMetadataImpl(server.getId() + "", name, null, null,
|
||||||
cloudServersImage.getId(), template.getSize().getId());
|
server.getMetadata(), tag, NodeState.RUNNING, server.getAddresses()
|
||||||
|
.getPublicAddresses(),
|
||||||
Server server = client.createServer(name, cloudServersImage.getImage().getId(),
|
server.getAddresses().getPrivateAddresses(), ImmutableMap
|
||||||
cloudServersSize.getFlavor().getId());
|
.<String, String> of(), new Credentials("root", server
|
||||||
|
.getAdminPass()));
|
||||||
CreateNodeResponse node = new CreateNodeResponseImpl(server.getId() + "", name, location,
|
nodes.add(node);
|
||||||
null, server.getMetadata(), NodeState.RUNNING, server.getAddresses()
|
|
||||||
.getPublicAddresses(), server.getAddresses().getPrivateAddresses(),
|
|
||||||
new Credentials("root", server.getAdminPass()), ImmutableMap.<String, String> of());
|
|
||||||
logger.debug("<< started server(%s)", server.getId());
|
logger.debug("<< started server(%s)", server.getId());
|
||||||
serverActive.apply(server);
|
serverActive.apply(server);
|
||||||
logger.debug("<< running server(%s)", server.getId());
|
logger.debug("<< running server(%s)", server.getId());
|
||||||
if (options.getRunScript() != null) {
|
if (template.getOptions().getRunScript() != null) {
|
||||||
utils.runScriptOnNode(node, options.getRunScript());
|
utils.runScriptOnNode(node, template.getOptions().getRunScript());
|
||||||
}
|
}
|
||||||
return node;
|
return null;
|
||||||
|
}
|
||||||
|
}), executor));
|
||||||
|
}
|
||||||
|
ConcurrentUtils.awaitCompletion(responses, executor, null, logger, "nodes");
|
||||||
|
return new NodeSetImpl(nodes);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -165,33 +199,42 @@ public class CloudServersComputeService implements ComputeService {
|
||||||
return serverToNodeMetadata.apply(client.getServer(Integer.parseInt(node.getId())));
|
return serverToNodeMetadata.apply(client.getServer(Integer.parseInt(node.getId())));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static final Pattern TAG_PATTERN = Pattern.compile("[^-]+-([^-]+)-[0-9]+");
|
||||||
|
|
||||||
@Singleton
|
@Singleton
|
||||||
private static class ServerToNodeMetadata implements Function<Server, NodeMetadata> {
|
private static class ServerToNodeMetadata implements Function<Server, NodeMetadata> {
|
||||||
private final String location;
|
private final Location location;
|
||||||
|
|
||||||
@SuppressWarnings("unused")
|
@SuppressWarnings("unused")
|
||||||
@Inject
|
@Inject
|
||||||
ServerToNodeMetadata(@ResourceLocation String location) {
|
ServerToNodeMetadata(Location location) {
|
||||||
this.location = location;
|
this.location = location;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public NodeMetadata apply(Server from) {
|
public NodeMetadata apply(Server from) {
|
||||||
return new NodeMetadataImpl(from.getId() + "", from.getName(), location, null, from
|
Matcher matcher = TAG_PATTERN.matcher(from.getName());
|
||||||
.getMetadata(), serverToNodeState.get(from.getStatus()), from.getAddresses()
|
final String tag = matcher.find() ? matcher.group(1) : null;
|
||||||
.getPublicAddresses(), from.getAddresses().getPrivateAddresses(), ImmutableMap
|
return new NodeMetadataImpl(from.getId() + "", from.getName(), location.getId(), null,
|
||||||
.<String, String> of());
|
from.getMetadata(), tag, serverToNodeState.get(from.getStatus()), from
|
||||||
|
.getAddresses().getPublicAddresses(), from.getAddresses()
|
||||||
|
.getPrivateAddresses(), ImmutableMap.<String, String> of(), null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Set<ComputeMetadata> listNodes() {
|
public Map<String, ? extends ComputeMetadata> getNodes() {
|
||||||
logger.debug(">> listing servers");
|
logger.debug(">> listing servers");
|
||||||
Set<ComputeMetadata> servers = Sets.newHashSet();
|
ImmutableMap<String, NodeMetadata> map = doGetNodes();
|
||||||
Iterables.addAll(servers, Iterables.transform(client.listServers(ListOptions.Builder
|
logger.debug("<< list(%d)", map.size());
|
||||||
.withDetails()), serverToNodeMetadata));
|
return map;
|
||||||
logger.debug("<< list(%d)", servers.size());
|
}
|
||||||
return servers;
|
|
||||||
|
private ImmutableMap<String, NodeMetadata> doGetNodes() {
|
||||||
|
ImmutableMap<String, NodeMetadata> map = Maps.uniqueIndex(Iterables.transform(client
|
||||||
|
.listServers(ListOptions.Builder.withDetails()), serverToNodeMetadata),
|
||||||
|
METADATA_TO_ID);
|
||||||
|
return map;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -208,12 +251,62 @@ public class CloudServersComputeService implements ComputeService {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Set<? extends Size> listSizes() {
|
public void destroyNodes(String tag) { // TODO parallel
|
||||||
|
logger.debug(">> terminating servers by tag(%s)", tag);
|
||||||
|
Set<ListenableFuture<Void>> responses = Sets.newHashSet();
|
||||||
|
for (final NodeMetadata node : doGetNodes(tag)) {
|
||||||
|
responses.add(makeListenable(executor.submit(new Callable<Void>() {
|
||||||
|
@Override
|
||||||
|
public Void call() throws Exception {
|
||||||
|
destroyNode(node);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}), executor));
|
||||||
|
}
|
||||||
|
awaitCompletion(responses, executor, null, logger, "nodes");
|
||||||
|
logger.debug("<< destroyed");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Map<String, ? extends Location> getLocations() {
|
||||||
|
return locations.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public NodeSet getNodes(String tag) {
|
||||||
|
logger.debug(">> listing servers by tag(%s)", tag);
|
||||||
|
NodeSet nodes = doGetNodes(tag);
|
||||||
|
logger.debug("<< list(%d)", nodes.size());
|
||||||
|
return nodes;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected NodeSet doGetNodes(final String tag) {
|
||||||
|
Iterable<NodeMetadata> nodes = Iterables.filter(Iterables.transform(doGetNodes().values(),
|
||||||
|
new Function<ComputeMetadata, NodeMetadata>() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public NodeMetadata apply(ComputeMetadata from) {
|
||||||
|
return getNodeMetadata(from);
|
||||||
|
}
|
||||||
|
|
||||||
|
}), new Predicate<NodeMetadata>() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean apply(NodeMetadata input) {
|
||||||
|
return tag.equals(input.getTag());
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
return new NodeSetImpl(Iterables.filter(nodes, new NodeMatchesTag(tag)));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Map<String, ? extends Size> getSizes() {
|
||||||
return sizes.get();
|
return sizes.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Set<? extends Image> listImages() {
|
public Map<String, ? extends Image> getImages() {
|
||||||
return images.get();
|
return images.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
*/
|
*/
|
||||||
package org.jclouds.rackspace.cloudservers.compute.config;
|
package org.jclouds.rackspace.cloudservers.compute.config;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.concurrent.ExecutionException;
|
import java.util.concurrent.ExecutionException;
|
||||||
import java.util.concurrent.ExecutorService;
|
import java.util.concurrent.ExecutorService;
|
||||||
|
@ -33,24 +34,30 @@ import org.jclouds.Constants;
|
||||||
import org.jclouds.compute.ComputeService;
|
import org.jclouds.compute.ComputeService;
|
||||||
import org.jclouds.compute.ComputeServiceContext;
|
import org.jclouds.compute.ComputeServiceContext;
|
||||||
import org.jclouds.compute.domain.Architecture;
|
import org.jclouds.compute.domain.Architecture;
|
||||||
|
import org.jclouds.compute.domain.ComputeMetadata;
|
||||||
import org.jclouds.compute.domain.Image;
|
import org.jclouds.compute.domain.Image;
|
||||||
import org.jclouds.compute.domain.OsFamily;
|
import org.jclouds.compute.domain.OsFamily;
|
||||||
import org.jclouds.compute.domain.Size;
|
import org.jclouds.compute.domain.Size;
|
||||||
|
import org.jclouds.compute.domain.internal.ImageImpl;
|
||||||
|
import org.jclouds.compute.domain.internal.SizeImpl;
|
||||||
import org.jclouds.compute.internal.ComputeServiceContextImpl;
|
import org.jclouds.compute.internal.ComputeServiceContextImpl;
|
||||||
import org.jclouds.compute.reference.ComputeServiceConstants;
|
import org.jclouds.compute.reference.ComputeServiceConstants;
|
||||||
import org.jclouds.domain.ResourceLocation;
|
import org.jclouds.domain.Location;
|
||||||
|
import org.jclouds.domain.LocationScope;
|
||||||
|
import org.jclouds.domain.internal.LocationImpl;
|
||||||
import org.jclouds.logging.Logger;
|
import org.jclouds.logging.Logger;
|
||||||
import org.jclouds.rackspace.cloudservers.CloudServersAsyncClient;
|
import org.jclouds.rackspace.cloudservers.CloudServersAsyncClient;
|
||||||
import org.jclouds.rackspace.cloudservers.CloudServersClient;
|
import org.jclouds.rackspace.cloudservers.CloudServersClient;
|
||||||
import org.jclouds.rackspace.cloudservers.compute.CloudServersComputeService;
|
import org.jclouds.rackspace.cloudservers.compute.CloudServersComputeService;
|
||||||
import org.jclouds.rackspace.cloudservers.compute.domain.CloudServersImage;
|
|
||||||
import org.jclouds.rackspace.cloudservers.compute.domain.CloudServersSize;
|
|
||||||
import org.jclouds.rackspace.cloudservers.config.CloudServersContextModule;
|
import org.jclouds.rackspace.cloudservers.config.CloudServersContextModule;
|
||||||
import org.jclouds.rackspace.cloudservers.domain.Flavor;
|
import org.jclouds.rackspace.cloudservers.domain.Flavor;
|
||||||
import org.jclouds.rackspace.cloudservers.options.ListOptions;
|
import org.jclouds.rackspace.cloudservers.options.ListOptions;
|
||||||
import org.jclouds.rest.RestContext;
|
import org.jclouds.rest.RestContext;
|
||||||
|
|
||||||
|
import com.google.common.base.Function;
|
||||||
|
import com.google.common.collect.ImmutableMap;
|
||||||
import com.google.common.collect.ImmutableSet;
|
import com.google.common.collect.ImmutableSet;
|
||||||
|
import com.google.common.collect.Maps;
|
||||||
import com.google.common.collect.Sets;
|
import com.google.common.collect.Sets;
|
||||||
import com.google.inject.Provides;
|
import com.google.inject.Provides;
|
||||||
|
|
||||||
|
@ -78,25 +85,44 @@ public class CloudServersComputeServiceContextModule extends CloudServersContext
|
||||||
|
|
||||||
@Provides
|
@Provides
|
||||||
@Singleton
|
@Singleton
|
||||||
@ResourceLocation
|
Location getRegion() {
|
||||||
String getRegion() {
|
return new LocationImpl(LocationScope.ZONE, "DALLAS", "Dallas, TX", null, true);
|
||||||
return "default";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Provides
|
@Provides
|
||||||
@Singleton
|
@Singleton
|
||||||
protected Set<? extends Size> provideSizes(CloudServersClient sync, Set<? extends Image> images,
|
Map<String, ? extends Location> provideLocations(Location location) {
|
||||||
LogHolder holder, @Named(Constants.PROPERTY_USER_THREADS) ExecutorService executor)
|
return ImmutableMap.of(location.getId(), location);
|
||||||
throws InterruptedException, TimeoutException, ExecutionException {
|
}
|
||||||
|
|
||||||
|
@Provides
|
||||||
|
@Singleton
|
||||||
|
protected Function<ComputeMetadata, String> indexer() {
|
||||||
|
return new Function<ComputeMetadata, String>() {
|
||||||
|
@Override
|
||||||
|
public String apply(ComputeMetadata from) {
|
||||||
|
return from.getId();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
@Provides
|
||||||
|
@Singleton
|
||||||
|
protected Map<String, ? extends Size> provideSizes(CloudServersClient sync,
|
||||||
|
Map<String, ? extends Image> images, Location location, LogHolder holder,
|
||||||
|
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService executor,
|
||||||
|
Function<ComputeMetadata, String> indexer) throws InterruptedException,
|
||||||
|
TimeoutException, ExecutionException {
|
||||||
final Set<Size> sizes = Sets.newHashSet();
|
final Set<Size> sizes = Sets.newHashSet();
|
||||||
holder.logger.debug(">> providing sizes");
|
holder.logger.debug(">> providing sizes");
|
||||||
for (final Flavor from : sync.listFlavors(ListOptions.Builder.withDetails())) {
|
for (final Flavor from : sync.listFlavors(ListOptions.Builder.withDetails())) {
|
||||||
sizes.add(new CloudServersSize(from, from.getId() + "", from.getDisk() / 10,
|
sizes.add(new SizeImpl(from.getId() + "", from.getName(), location.getId(), null,
|
||||||
from.getRam(), from.getDisk(), ImmutableSet.<Architecture> of(
|
ImmutableMap.<String, String> of(), from.getDisk() / 10, from.getRam(), from
|
||||||
Architecture.X86_32, Architecture.X86_64)));
|
.getDisk(), ImmutableSet.<Architecture> of(Architecture.X86_32,
|
||||||
|
Architecture.X86_64)));
|
||||||
}
|
}
|
||||||
holder.logger.debug("<< sizes(%d)", sizes.size());
|
holder.logger.debug("<< sizes(%d)", sizes.size());
|
||||||
return sizes;
|
return Maps.uniqueIndex(sizes, indexer);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class LogHolder {
|
private static class LogHolder {
|
||||||
|
@ -109,9 +135,9 @@ public class CloudServersComputeServiceContextModule extends CloudServersContext
|
||||||
|
|
||||||
@Provides
|
@Provides
|
||||||
@Singleton
|
@Singleton
|
||||||
protected Set<? extends Image> provideImages(final CloudServersClient sync,
|
protected Map<String, ? extends Image> provideImages(final CloudServersClient sync,
|
||||||
@ResourceLocation String location, LogHolder holder) throws InterruptedException,
|
Location location, LogHolder holder, Function<ComputeMetadata, String> indexer)
|
||||||
ExecutionException, TimeoutException {
|
throws InterruptedException, ExecutionException, TimeoutException {
|
||||||
final Set<Image> images = Sets.newHashSet();
|
final Set<Image> images = Sets.newHashSet();
|
||||||
holder.logger.debug(">> providing images");
|
holder.logger.debug(">> providing images");
|
||||||
for (final org.jclouds.rackspace.cloudservers.domain.Image from : sync
|
for (final org.jclouds.rackspace.cloudservers.domain.Image from : sync
|
||||||
|
@ -120,7 +146,6 @@ public class CloudServersComputeServiceContextModule extends CloudServersContext
|
||||||
Architecture arch = Architecture.X86_64;
|
Architecture arch = Architecture.X86_64;
|
||||||
String osDescription = "";
|
String osDescription = "";
|
||||||
String version = "";
|
String version = "";
|
||||||
|
|
||||||
Matcher matcher = RACKSPACE_PATTERN.matcher(from.getName());
|
Matcher matcher = RACKSPACE_PATTERN.matcher(from.getName());
|
||||||
osDescription = from.getName();
|
osDescription = from.getName();
|
||||||
if (from.getName().indexOf("Red Hat EL") != -1) {
|
if (from.getName().indexOf("Red Hat EL") != -1) {
|
||||||
|
@ -132,9 +157,11 @@ public class CloudServersComputeServiceContextModule extends CloudServersContext
|
||||||
holder.logger.debug("<< didn't match os(%s)", matcher.group(2));
|
holder.logger.debug("<< didn't match os(%s)", matcher.group(2));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
images.add(new CloudServersImage(from, location, arch, os, osDescription, version));
|
images.add(new ImageImpl(from.getId() + "", from.getName(), location.getId(), null,
|
||||||
|
ImmutableMap.<String, String> of(), from.getName(), version, os, osDescription,
|
||||||
|
arch));
|
||||||
}
|
}
|
||||||
holder.logger.debug("<< images(%d)", images.size());
|
holder.logger.debug("<< images(%d)", images.size());
|
||||||
return images;
|
return Maps.uniqueIndex(images, indexer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,154 +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.rackspace.cloudservers.compute.domain;
|
|
||||||
|
|
||||||
import org.jclouds.compute.domain.Architecture;
|
|
||||||
import org.jclouds.compute.domain.Image;
|
|
||||||
import org.jclouds.compute.domain.OsFamily;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @author Adrian Cole
|
|
||||||
*/
|
|
||||||
public class CloudServersImage implements Image {
|
|
||||||
private final org.jclouds.rackspace.cloudservers.domain.Image image;
|
|
||||||
private final String location;
|
|
||||||
private final Architecture architecture;
|
|
||||||
private final OsFamily os;
|
|
||||||
private final String osDescription;
|
|
||||||
private final String version;
|
|
||||||
|
|
||||||
public CloudServersImage(org.jclouds.rackspace.cloudservers.domain.Image image, String location,
|
|
||||||
Architecture architecture, OsFamily os, String osDescription, String version) {
|
|
||||||
this.location = location;
|
|
||||||
this.architecture = architecture;
|
|
||||||
this.image = image;
|
|
||||||
this.os = os;
|
|
||||||
this.osDescription = osDescription;
|
|
||||||
this.version = version;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Architecture getArchitecture() {
|
|
||||||
return architecture;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getDescription() {
|
|
||||||
return getImage().getName();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getId() {
|
|
||||||
return getImage().getId()+"";
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getLocation() {
|
|
||||||
return location;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public OsFamily getOsFamily() {
|
|
||||||
return os;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getOsDescription() {
|
|
||||||
return osDescription;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getVersion() {
|
|
||||||
return version;
|
|
||||||
}
|
|
||||||
|
|
||||||
public org.jclouds.rackspace.cloudservers.domain.Image getImage() {
|
|
||||||
return image;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int hashCode() {
|
|
||||||
final int prime = 31;
|
|
||||||
int result = 1;
|
|
||||||
result = prime * result + ((architecture == null) ? 0 : architecture.hashCode());
|
|
||||||
result = prime * result + ((image == null) ? 0 : image.hashCode());
|
|
||||||
result = prime * result + ((location == null) ? 0 : location.hashCode());
|
|
||||||
result = prime * result + ((os == null) ? 0 : os.hashCode());
|
|
||||||
result = prime * result + ((osDescription == null) ? 0 : osDescription.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;
|
|
||||||
CloudServersImage other = (CloudServersImage) obj;
|
|
||||||
if (architecture == null) {
|
|
||||||
if (other.architecture != null)
|
|
||||||
return false;
|
|
||||||
} else if (!architecture.equals(other.architecture))
|
|
||||||
return false;
|
|
||||||
if (image == null) {
|
|
||||||
if (other.image != null)
|
|
||||||
return false;
|
|
||||||
} else if (!image.equals(other.image))
|
|
||||||
return false;
|
|
||||||
if (location == null) {
|
|
||||||
if (other.location != null)
|
|
||||||
return false;
|
|
||||||
} else if (!location.equals(other.location))
|
|
||||||
return false;
|
|
||||||
if (os == null) {
|
|
||||||
if (other.os != null)
|
|
||||||
return false;
|
|
||||||
} else if (!os.equals(other.os))
|
|
||||||
return false;
|
|
||||||
if (osDescription == null) {
|
|
||||||
if (other.osDescription != null)
|
|
||||||
return false;
|
|
||||||
} else if (!osDescription.equals(other.osDescription))
|
|
||||||
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="
|
|
||||||
+ getOsFamily() + ", operatingSystemVersion=" + getOsDescription()
|
|
||||||
+ ", description=" + getDescription() + "]";
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,72 +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.rackspace.cloudservers.compute.domain;
|
|
||||||
|
|
||||||
import org.jclouds.compute.domain.Architecture;
|
|
||||||
import org.jclouds.compute.domain.internal.SizeImpl;
|
|
||||||
import org.jclouds.rackspace.cloudservers.domain.Flavor;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @author Adrian Cole
|
|
||||||
*/
|
|
||||||
public class CloudServersSize extends SizeImpl {
|
|
||||||
private final Flavor flavor;
|
|
||||||
|
|
||||||
public CloudServersSize(Flavor flavor, String id, int cores, int ram, int disk,
|
|
||||||
Iterable<Architecture> supportedArchitectures) {
|
|
||||||
super(id, cores, ram, disk, supportedArchitectures);
|
|
||||||
this.flavor = flavor;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int hashCode() {
|
|
||||||
final int prime = 31;
|
|
||||||
int result = super.hashCode();
|
|
||||||
result = prime * result + ((flavor == null) ? 0 : flavor.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;
|
|
||||||
CloudServersSize other = (CloudServersSize) obj;
|
|
||||||
if (flavor == null) {
|
|
||||||
if (other.flavor != null)
|
|
||||||
return false;
|
|
||||||
} else if (!flavor.equals(other.flavor))
|
|
||||||
return false;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Flavor getFlavor() {
|
|
||||||
return flavor;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -20,10 +20,17 @@ package org.jclouds.rimuhosting.miro.compute;
|
||||||
|
|
||||||
import static com.google.common.base.Preconditions.checkArgument;
|
import static com.google.common.base.Preconditions.checkArgument;
|
||||||
import static com.google.common.base.Preconditions.checkNotNull;
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
|
import static org.jclouds.compute.util.ComputeUtils.METADATA_TO_ID;
|
||||||
|
import static org.jclouds.concurrent.ConcurrentUtils.awaitCompletion;
|
||||||
|
import static org.jclouds.concurrent.ConcurrentUtils.makeListenable;
|
||||||
|
|
||||||
import java.net.InetAddress;
|
import java.net.InetAddress;
|
||||||
import java.net.UnknownHostException;
|
import java.net.UnknownHostException;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import java.util.concurrent.Callable;
|
||||||
|
import java.util.concurrent.ExecutorService;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
@ -31,22 +38,24 @@ import javax.inject.Named;
|
||||||
import javax.inject.Provider;
|
import javax.inject.Provider;
|
||||||
import javax.inject.Singleton;
|
import javax.inject.Singleton;
|
||||||
|
|
||||||
|
import org.jclouds.Constants;
|
||||||
import org.jclouds.compute.ComputeService;
|
import org.jclouds.compute.ComputeService;
|
||||||
import org.jclouds.compute.domain.ComputeMetadata;
|
import org.jclouds.compute.domain.ComputeMetadata;
|
||||||
import org.jclouds.compute.domain.ComputeType;
|
import org.jclouds.compute.domain.ComputeType;
|
||||||
import org.jclouds.compute.domain.CreateNodeResponse;
|
|
||||||
import org.jclouds.compute.domain.Image;
|
import org.jclouds.compute.domain.Image;
|
||||||
import org.jclouds.compute.domain.NodeMetadata;
|
import org.jclouds.compute.domain.NodeMetadata;
|
||||||
|
import org.jclouds.compute.domain.NodeSet;
|
||||||
import org.jclouds.compute.domain.NodeState;
|
import org.jclouds.compute.domain.NodeState;
|
||||||
import org.jclouds.compute.domain.Size;
|
import org.jclouds.compute.domain.Size;
|
||||||
import org.jclouds.compute.domain.Template;
|
import org.jclouds.compute.domain.Template;
|
||||||
import org.jclouds.compute.domain.TemplateBuilder;
|
import org.jclouds.compute.domain.TemplateBuilder;
|
||||||
import org.jclouds.compute.domain.internal.CreateNodeResponseImpl;
|
|
||||||
import org.jclouds.compute.domain.internal.NodeMetadataImpl;
|
import org.jclouds.compute.domain.internal.NodeMetadataImpl;
|
||||||
import org.jclouds.compute.options.RunNodeOptions;
|
import org.jclouds.compute.domain.internal.NodeSetImpl;
|
||||||
import org.jclouds.compute.reference.ComputeServiceConstants;
|
import org.jclouds.compute.reference.ComputeServiceConstants;
|
||||||
|
import org.jclouds.compute.util.ComputeUtils;
|
||||||
|
import org.jclouds.concurrent.ConcurrentUtils;
|
||||||
import org.jclouds.domain.Credentials;
|
import org.jclouds.domain.Credentials;
|
||||||
import org.jclouds.domain.ResourceLocation;
|
import org.jclouds.domain.Location;
|
||||||
import org.jclouds.logging.Logger;
|
import org.jclouds.logging.Logger;
|
||||||
import org.jclouds.rimuhosting.miro.RimuHostingClient;
|
import org.jclouds.rimuhosting.miro.RimuHostingClient;
|
||||||
import org.jclouds.rimuhosting.miro.domain.NewServerResponse;
|
import org.jclouds.rimuhosting.miro.domain.NewServerResponse;
|
||||||
|
@ -54,55 +63,19 @@ import org.jclouds.rimuhosting.miro.domain.Server;
|
||||||
|
|
||||||
import com.google.common.annotations.VisibleForTesting;
|
import com.google.common.annotations.VisibleForTesting;
|
||||||
import com.google.common.base.Function;
|
import com.google.common.base.Function;
|
||||||
|
import com.google.common.base.Predicate;
|
||||||
import com.google.common.collect.ImmutableList;
|
import com.google.common.collect.ImmutableList;
|
||||||
import com.google.common.collect.ImmutableMap;
|
import com.google.common.collect.ImmutableMap;
|
||||||
import com.google.common.collect.Iterables;
|
import com.google.common.collect.Iterables;
|
||||||
|
import com.google.common.collect.Maps;
|
||||||
import com.google.common.collect.Sets;
|
import com.google.common.collect.Sets;
|
||||||
|
import com.google.common.util.concurrent.ListenableFuture;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Ivan Meredith
|
* @author Ivan Meredith
|
||||||
*/
|
*/
|
||||||
@Singleton
|
@Singleton
|
||||||
public class RimuHostingComputeService implements ComputeService {
|
public class RimuHostingComputeService implements ComputeService {
|
||||||
@Resource
|
|
||||||
@Named(ComputeServiceConstants.COMPUTE_LOGGER)
|
|
||||||
protected Logger logger = Logger.NULL;
|
|
||||||
protected final RimuHostingClient client;
|
|
||||||
protected final Provider<Set<? extends Image>> images;
|
|
||||||
protected final Provider<Set<? extends Size>> sizes;
|
|
||||||
protected final Provider<TemplateBuilder> templateBuilderProvider;
|
|
||||||
private final String location;
|
|
||||||
|
|
||||||
@Inject
|
|
||||||
public RimuHostingComputeService(RimuHostingClient client,
|
|
||||||
Provider<TemplateBuilder> templateBuilderProvider, @ResourceLocation String location,
|
|
||||||
Provider<Set<? extends Image>> images, Provider<Set<? extends Size>> sizes) {
|
|
||||||
this.client = client;
|
|
||||||
this.location = location;
|
|
||||||
this.images = images;
|
|
||||||
this.sizes = sizes;
|
|
||||||
this.templateBuilderProvider = templateBuilderProvider;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public CreateNodeResponse runNode(String name, Template template) {
|
|
||||||
return this.runNode(name, template, RunNodeOptions.NONE);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public CreateNodeResponse runNode(String name, Template template, RunNodeOptions options) {
|
|
||||||
NewServerResponse serverResponse = client.createServer(name, checkNotNull(template.getImage()
|
|
||||||
.getId(), "imageId"), checkNotNull(template.getSize().getId(), "sizeId"));
|
|
||||||
return new CreateNodeResponseImpl(serverResponse.getServer().getId().toString(),
|
|
||||||
name, location, null, ImmutableMap.<String, String> of(), NodeState.UNKNOWN,// TODO
|
|
||||||
// need a
|
|
||||||
// real
|
|
||||||
// state!
|
|
||||||
getPublicAddresses(serverResponse.getServer()),// no real useful data here..
|
|
||||||
ImmutableList.<InetAddress> of(), new Credentials("root", serverResponse
|
|
||||||
.getNewInstanceRequest().getCreateOptions().getPassword()), ImmutableMap
|
|
||||||
.<String, String> of());
|
|
||||||
}
|
|
||||||
|
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
static Iterable<InetAddress> getPublicAddresses(Server server) {
|
static Iterable<InetAddress> getPublicAddresses(Server server) {
|
||||||
|
@ -122,20 +95,91 @@ public class RimuHostingComputeService implements ComputeService {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public Set<ComputeMetadata> listNodes() {
|
private static class NodeMatchesTag implements Predicate<NodeMetadata> {
|
||||||
Set<ComputeMetadata> serverSet = Sets.newLinkedHashSet();
|
private final String tag;
|
||||||
Set<Server> servers = client.getServerList();
|
|
||||||
for (Server server : servers) {
|
@Override
|
||||||
serverSet.add(toNode(server));
|
public boolean apply(NodeMetadata from) {
|
||||||
}
|
return from.getTag().equals(tag);
|
||||||
return serverSet;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private NodeMetadataImpl toNode(Server server) {
|
public NodeMatchesTag(String tag) {
|
||||||
return new NodeMetadataImpl(server.getId() + "", server.getName(), location, null,
|
super();
|
||||||
ImmutableMap.<String, String> of(), NodeState.UNKNOWN, getPublicAddresses(server),
|
this.tag = tag;
|
||||||
ImmutableList.<InetAddress> of(), ImmutableMap.<String, String> of("state", server
|
}
|
||||||
.getState()));
|
};
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
@Named(ComputeServiceConstants.COMPUTE_LOGGER)
|
||||||
|
protected Logger logger = Logger.NULL;
|
||||||
|
private final RimuHostingClient client;
|
||||||
|
protected final Provider<Map<String, ? extends Image>> images;
|
||||||
|
protected final Provider<Map<String, ? extends Size>> sizes;
|
||||||
|
protected final Provider<Map<String, ? extends Location>> locations;
|
||||||
|
protected final Provider<TemplateBuilder> templateBuilderProvider;
|
||||||
|
private final ComputeUtils utils;
|
||||||
|
private final ServerToNodeMetadata serverToNodeMetadata;
|
||||||
|
protected final ExecutorService executor;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
public RimuHostingComputeService(RimuHostingClient client,
|
||||||
|
Provider<TemplateBuilder> templateBuilderProvider,
|
||||||
|
Provider<Map<String, ? extends Image>> images,
|
||||||
|
Provider<Map<String, ? extends Size>> sizes, ServerToNodeMetadata serverToNodeMetadata,
|
||||||
|
Provider<Map<String, ? extends Location>> locations, ComputeUtils utils,
|
||||||
|
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService executor) {
|
||||||
|
this.client = client;
|
||||||
|
this.images = images;
|
||||||
|
this.sizes = sizes;
|
||||||
|
this.locations = locations;
|
||||||
|
this.utils = utils;
|
||||||
|
this.templateBuilderProvider = templateBuilderProvider;
|
||||||
|
this.serverToNodeMetadata = serverToNodeMetadata;
|
||||||
|
this.executor = executor;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public NodeSet runNodes(final String tag, int max, final Template template) {
|
||||||
|
checkArgument(tag.indexOf('-') == -1, "tag cannot contain hyphens");
|
||||||
|
logger.debug(">> running server image(%s) flavor(%s)", template.getImage().getId(), template
|
||||||
|
.getSize().getId());
|
||||||
|
|
||||||
|
final Set<NodeMetadata> nodes = Sets.newHashSet();
|
||||||
|
Set<ListenableFuture<Void>> responses = Sets.newHashSet();
|
||||||
|
for (int i = 0; i < max; i++) {
|
||||||
|
final String name = String.format("%s-%d", tag, i + 1);
|
||||||
|
responses.add(ConcurrentUtils.makeListenable(executor.submit(new Callable<Void>() {
|
||||||
|
@Override
|
||||||
|
public Void call() throws Exception {
|
||||||
|
NewServerResponse serverResponse = client.createServer(name, checkNotNull(template
|
||||||
|
.getImage().getId(), "imageId"), checkNotNull(template.getSize().getId(),
|
||||||
|
"sizeId"));
|
||||||
|
NodeMetadata node = new NodeMetadataImpl(serverResponse.getServer().getId()
|
||||||
|
.toString(), name, template.getLocation().getId(),
|
||||||
|
null,
|
||||||
|
ImmutableMap.<String, String> of(),
|
||||||
|
tag,
|
||||||
|
NodeState.UNKNOWN,// TODO
|
||||||
|
// need a
|
||||||
|
// real
|
||||||
|
// state!
|
||||||
|
getPublicAddresses(serverResponse.getServer()),// no real useful data here..
|
||||||
|
ImmutableList.<InetAddress> of(), ImmutableMap.<String, String> of(),
|
||||||
|
new Credentials("root", serverResponse.getNewInstanceRequest()
|
||||||
|
.getCreateOptions().getPassword()));
|
||||||
|
nodes.add(node);
|
||||||
|
logger.debug("<< started server(%s)", node.getId());
|
||||||
|
// TODO! serverActive.apply(server);
|
||||||
|
logger.debug("<< running server(%s)", node.getId());
|
||||||
|
if (template.getOptions().getRunScript() != null) {
|
||||||
|
utils.runScriptOnNode(node, template.getOptions().getRunScript());
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}), executor));
|
||||||
|
}
|
||||||
|
ConcurrentUtils.awaitCompletion(responses, executor, null, logger, "nodes");
|
||||||
|
return new NodeSetImpl(nodes);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -143,7 +187,7 @@ public class RimuHostingComputeService implements ComputeService {
|
||||||
checkArgument(node.getType() == ComputeType.NODE, "this is only valid for nodes, not "
|
checkArgument(node.getType() == ComputeType.NODE, "this is only valid for nodes, not "
|
||||||
+ node.getType());
|
+ node.getType());
|
||||||
checkNotNull(node.getId(), "node.id");
|
checkNotNull(node.getId(), "node.id");
|
||||||
return toNode(client.getServer(Long.parseLong(node.getId())));
|
return serverToNodeMetadata.apply(client.getServer(Long.parseLong(node.getId())));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -151,21 +195,110 @@ public class RimuHostingComputeService implements ComputeService {
|
||||||
checkArgument(node.getType() == ComputeType.NODE, "this is only valid for nodes, not "
|
checkArgument(node.getType() == ComputeType.NODE, "this is only valid for nodes, not "
|
||||||
+ node.getType());
|
+ node.getType());
|
||||||
checkNotNull(node.getId(), "node.id");
|
checkNotNull(node.getId(), "node.id");
|
||||||
|
|
||||||
|
checkArgument(node.getType() == ComputeType.NODE, "this is only valid for nodes, not "
|
||||||
|
+ node.getType());
|
||||||
|
checkNotNull(node.getId(), "node.id");
|
||||||
|
|
||||||
|
logger.debug(">> deleting server(%s)", node.getId());
|
||||||
client.destroyServer(new Long(node.getId()));
|
client.destroyServer(new Long(node.getId()));
|
||||||
|
logger.debug("<< deleted server(%s)", node.getId());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final Pattern TAG_PATTERN = Pattern.compile("[^-]+-([^-]+)-[0-9]+");
|
||||||
|
|
||||||
|
@Singleton
|
||||||
|
private static class ServerToNodeMetadata implements Function<Server, NodeMetadata> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public NodeMetadata apply(Server from) {
|
||||||
|
String locationId = "//TODO";
|
||||||
|
String tag = from.getName().replaceAll("-[0-9]+", "");
|
||||||
|
Credentials creds = null;
|
||||||
|
NodeState state = NodeState.UNKNOWN;
|
||||||
|
return new NodeMetadataImpl(from.getId() + "", from.getName(), locationId, null,
|
||||||
|
ImmutableMap.<String, String> of(), tag, state, getPublicAddresses(from),
|
||||||
|
ImmutableList.<InetAddress> of(), ImmutableMap.<String, String> of("state", from
|
||||||
|
.getState()), creds);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Set<? extends Size> listSizes() {
|
public Map<String, ? extends ComputeMetadata> getNodes() {
|
||||||
|
logger.debug(">> listing servers");
|
||||||
|
ImmutableMap<String, NodeMetadata> map = doGetNodes();
|
||||||
|
logger.debug("<< list(%d)", map.size());
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
|
||||||
|
private ImmutableMap<String, NodeMetadata> doGetNodes() {
|
||||||
|
ImmutableMap<String, NodeMetadata> map = Maps.uniqueIndex(Iterables.transform(client
|
||||||
|
.getServerList(), serverToNodeMetadata), METADATA_TO_ID);
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void destroyNodes(String tag) { // TODO parallel
|
||||||
|
logger.debug(">> terminating servers by tag(%s)", tag);
|
||||||
|
Set<ListenableFuture<Void>> responses = Sets.newHashSet();
|
||||||
|
for (final NodeMetadata node : doGetNodes(tag)) {
|
||||||
|
responses.add(makeListenable(executor.submit(new Callable<Void>() {
|
||||||
|
@Override
|
||||||
|
public Void call() throws Exception {
|
||||||
|
destroyNode(node);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}), executor));
|
||||||
|
}
|
||||||
|
awaitCompletion(responses, executor, null, logger, "nodes");
|
||||||
|
logger.debug("<< destroyed");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Map<String, ? extends Location> getLocations() {
|
||||||
|
return locations.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public NodeSet getNodes(String tag) {
|
||||||
|
logger.debug(">> listing servers by tag(%s)", tag);
|
||||||
|
NodeSet nodes = doGetNodes(tag);
|
||||||
|
logger.debug("<< list(%d)", nodes.size());
|
||||||
|
return nodes;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected NodeSet doGetNodes(final String tag) {
|
||||||
|
Iterable<NodeMetadata> nodes = Iterables.filter(Iterables.transform(doGetNodes().values(),
|
||||||
|
new Function<ComputeMetadata, NodeMetadata>() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public NodeMetadata apply(ComputeMetadata from) {
|
||||||
|
return getNodeMetadata(from);
|
||||||
|
}
|
||||||
|
|
||||||
|
}), new Predicate<NodeMetadata>() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean apply(NodeMetadata input) {
|
||||||
|
return tag.equals(input.getTag());
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
return new NodeSetImpl(Iterables.filter(nodes, new NodeMatchesTag(tag)));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Map<String, ? extends Size> getSizes() {
|
||||||
return sizes.get();
|
return sizes.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Set<? extends Image> listImages() {
|
public Map<String, ? extends Image> getImages() {
|
||||||
return images.get();
|
return images.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public TemplateBuilder templateBuilder() {
|
public TemplateBuilder templateBuilder() {
|
||||||
return this.templateBuilderProvider.get();
|
return templateBuilderProvider.get();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
*/
|
*/
|
||||||
package org.jclouds.rimuhosting.miro.compute.config;
|
package org.jclouds.rimuhosting.miro.compute.config;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.concurrent.ExecutionException;
|
import java.util.concurrent.ExecutionException;
|
||||||
import java.util.concurrent.ExecutorService;
|
import java.util.concurrent.ExecutorService;
|
||||||
|
@ -33,6 +34,7 @@ import org.jclouds.Constants;
|
||||||
import org.jclouds.compute.ComputeService;
|
import org.jclouds.compute.ComputeService;
|
||||||
import org.jclouds.compute.ComputeServiceContext;
|
import org.jclouds.compute.ComputeServiceContext;
|
||||||
import org.jclouds.compute.domain.Architecture;
|
import org.jclouds.compute.domain.Architecture;
|
||||||
|
import org.jclouds.compute.domain.ComputeMetadata;
|
||||||
import org.jclouds.compute.domain.Image;
|
import org.jclouds.compute.domain.Image;
|
||||||
import org.jclouds.compute.domain.OsFamily;
|
import org.jclouds.compute.domain.OsFamily;
|
||||||
import org.jclouds.compute.domain.Size;
|
import org.jclouds.compute.domain.Size;
|
||||||
|
@ -40,7 +42,9 @@ import org.jclouds.compute.domain.internal.ImageImpl;
|
||||||
import org.jclouds.compute.domain.internal.SizeImpl;
|
import org.jclouds.compute.domain.internal.SizeImpl;
|
||||||
import org.jclouds.compute.internal.ComputeServiceContextImpl;
|
import org.jclouds.compute.internal.ComputeServiceContextImpl;
|
||||||
import org.jclouds.compute.reference.ComputeServiceConstants;
|
import org.jclouds.compute.reference.ComputeServiceConstants;
|
||||||
import org.jclouds.domain.ResourceLocation;
|
import org.jclouds.domain.Location;
|
||||||
|
import org.jclouds.domain.LocationScope;
|
||||||
|
import org.jclouds.domain.internal.LocationImpl;
|
||||||
import org.jclouds.logging.Logger;
|
import org.jclouds.logging.Logger;
|
||||||
import org.jclouds.rest.RestContext;
|
import org.jclouds.rest.RestContext;
|
||||||
import org.jclouds.rimuhosting.miro.RimuHostingAsyncClient;
|
import org.jclouds.rimuhosting.miro.RimuHostingAsyncClient;
|
||||||
|
@ -49,7 +53,10 @@ import org.jclouds.rimuhosting.miro.compute.RimuHostingComputeService;
|
||||||
import org.jclouds.rimuhosting.miro.config.RimuHostingContextModule;
|
import org.jclouds.rimuhosting.miro.config.RimuHostingContextModule;
|
||||||
import org.jclouds.rimuhosting.miro.domain.PricingPlan;
|
import org.jclouds.rimuhosting.miro.domain.PricingPlan;
|
||||||
|
|
||||||
|
import com.google.common.base.Function;
|
||||||
|
import com.google.common.collect.ImmutableMap;
|
||||||
import com.google.common.collect.ImmutableSet;
|
import com.google.common.collect.ImmutableSet;
|
||||||
|
import com.google.common.collect.Maps;
|
||||||
import com.google.common.collect.Sets;
|
import com.google.common.collect.Sets;
|
||||||
import com.google.inject.Provides;
|
import com.google.inject.Provides;
|
||||||
|
|
||||||
|
@ -77,25 +84,66 @@ public class RimuHostingComputeServiceContextModule extends RimuHostingContextMo
|
||||||
|
|
||||||
@Provides
|
@Provides
|
||||||
@Singleton
|
@Singleton
|
||||||
@ResourceLocation
|
Location getDefaultLocation(Map<String, ? extends Location> locations) {
|
||||||
String getRegion() {
|
return locations.get("DCDALLAS");
|
||||||
return "default";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Provides
|
@Provides
|
||||||
@Singleton
|
@Singleton
|
||||||
protected Set<? extends Size> provideSizes(RimuHostingClient sync, Set<? extends Image> images,
|
Map<String, ? extends Location> getDefaultLocations(RimuHostingClient sync, LogHolder holder,
|
||||||
LogHolder holder, @Named(Constants.PROPERTY_USER_THREADS) ExecutorService userExecutor) throws InterruptedException,
|
Function<ComputeMetadata, String> indexer) {
|
||||||
|
final Set<Location> locations = Sets.newHashSet();
|
||||||
|
holder.logger.debug(">> providing locations");
|
||||||
|
for (final PricingPlan from : sync.getPricingPlanList()) {
|
||||||
|
try {
|
||||||
|
locations.add(new LocationImpl(LocationScope.ZONE, from.getDataCenter().getId(), from
|
||||||
|
.getDataCenter().getName(), null, true));
|
||||||
|
} catch (NullPointerException e) {
|
||||||
|
holder.logger.warn("datacenter not present in " + from.getId());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
holder.logger.debug("<< locations(%d)", locations.size());
|
||||||
|
return Maps.uniqueIndex(locations, new Function<Location, String>() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String apply(Location from) {
|
||||||
|
return from.getId();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Provides
|
||||||
|
@Singleton
|
||||||
|
protected Function<ComputeMetadata, String> indexer() {
|
||||||
|
return new Function<ComputeMetadata, String>() {
|
||||||
|
@Override
|
||||||
|
public String apply(ComputeMetadata from) {
|
||||||
|
return from.getId();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
@Provides
|
||||||
|
@Singleton
|
||||||
|
protected Map<String, ? extends Size> provideSizes(RimuHostingClient sync,
|
||||||
|
Map<String, ? extends Image> images, LogHolder holder,
|
||||||
|
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService userExecutor,
|
||||||
|
Function<ComputeMetadata, String> indexer) throws InterruptedException,
|
||||||
TimeoutException, ExecutionException {
|
TimeoutException, ExecutionException {
|
||||||
final Set<Size> sizes = Sets.newHashSet();
|
final Set<Size> sizes = Sets.newHashSet();
|
||||||
holder.logger.debug(">> providing sizes");
|
holder.logger.debug(">> providing sizes");
|
||||||
for (final PricingPlan from : sync.getPricingPlanList()) {
|
for (final PricingPlan from : sync.getPricingPlanList()) {
|
||||||
sizes.add(new SizeImpl(from.getId(), from.getDiskSize(), from.getRam(),
|
try {
|
||||||
from.getDiskSize(), ImmutableSet.<Architecture> of(Architecture.X86_32,
|
sizes.add(new SizeImpl(from.getId(), from.getId(), from.getDataCenter().getId(), null,
|
||||||
|
ImmutableMap.<String, String> of(), from.getDiskSize(), from.getRam(), from
|
||||||
|
.getDiskSize(), ImmutableSet.<Architecture> of(Architecture.X86_32,
|
||||||
Architecture.X86_64)));
|
Architecture.X86_64)));
|
||||||
|
} catch (NullPointerException e) {
|
||||||
|
holder.logger.warn("datacenter not present in " + from.getId());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
holder.logger.debug("<< sizes(%d)", sizes.size());
|
holder.logger.debug("<< sizes(%d)", sizes.size());
|
||||||
return sizes;
|
return Maps.uniqueIndex(sizes, indexer);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class LogHolder {
|
private static class LogHolder {
|
||||||
|
@ -108,9 +156,9 @@ public class RimuHostingComputeServiceContextModule extends RimuHostingContextMo
|
||||||
|
|
||||||
@Provides
|
@Provides
|
||||||
@Singleton
|
@Singleton
|
||||||
protected Set<? extends Image> provideImages(final RimuHostingClient sync,
|
protected Map<String, ? extends Image> provideImages(final RimuHostingClient sync,
|
||||||
@ResourceLocation String location, LogHolder holder) throws InterruptedException,
|
LogHolder holder, Function<ComputeMetadata, String> indexer)
|
||||||
ExecutionException, TimeoutException {
|
throws InterruptedException, ExecutionException, TimeoutException {
|
||||||
final Set<Image> images = Sets.newHashSet();
|
final Set<Image> images = Sets.newHashSet();
|
||||||
holder.logger.debug(">> providing images");
|
holder.logger.debug(">> providing images");
|
||||||
for (final org.jclouds.rimuhosting.miro.domain.Image from : sync.getImageList()) {
|
for (final org.jclouds.rimuhosting.miro.domain.Image from : sync.getImageList()) {
|
||||||
|
@ -130,10 +178,11 @@ public class RimuHostingComputeServiceContextModule extends RimuHostingContextMo
|
||||||
holder.logger.debug("<< didn't match os(%s)", matcher.group(2));
|
holder.logger.debug("<< didn't match os(%s)", matcher.group(2));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
images.add(new ImageImpl(from.getId(), from.getDescription(), version, os, osDescription,
|
|
||||||
location, arch));
|
images.add(new ImageImpl(from.getId(), from.getDescription(), null, null, ImmutableMap
|
||||||
|
.<String, String> of(), from.getDescription(), version, os, osDescription, arch));
|
||||||
}
|
}
|
||||||
holder.logger.debug("<< images(%d)", images.size());
|
holder.logger.debug("<< images(%d)", images.size());
|
||||||
return images;
|
return Maps.uniqueIndex(images, indexer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,10 +18,13 @@
|
||||||
*/
|
*/
|
||||||
package org.jclouds.rimuhosting.miro.config;
|
package org.jclouds.rimuhosting.miro.config;
|
||||||
|
|
||||||
|
import com.google.common.base.Predicate;
|
||||||
import com.google.inject.AbstractModule;
|
import com.google.inject.AbstractModule;
|
||||||
import com.google.inject.Provides;
|
import com.google.inject.Provides;
|
||||||
import org.jclouds.concurrent.internal.SyncProxy;
|
import org.jclouds.concurrent.internal.SyncProxy;
|
||||||
import org.jclouds.http.RequiresHttp;
|
import org.jclouds.http.RequiresHttp;
|
||||||
|
import org.jclouds.predicates.RetryablePredicate;
|
||||||
|
import org.jclouds.predicates.SocketOpen;
|
||||||
import org.jclouds.rest.ConfiguresRestClient;
|
import org.jclouds.rest.ConfiguresRestClient;
|
||||||
import org.jclouds.rest.RestClientFactory;
|
import org.jclouds.rest.RestClientFactory;
|
||||||
import org.jclouds.rimuhosting.miro.RimuHosting;
|
import org.jclouds.rimuhosting.miro.RimuHosting;
|
||||||
|
@ -33,7 +36,9 @@ import org.jclouds.rimuhosting.miro.reference.RimuHostingConstants;
|
||||||
import javax.inject.Named;
|
import javax.inject.Named;
|
||||||
import javax.inject.Singleton;
|
import javax.inject.Singleton;
|
||||||
import java.io.UnsupportedEncodingException;
|
import java.io.UnsupportedEncodingException;
|
||||||
|
import java.net.InetSocketAddress;
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Configures the RimuHosting connection.
|
* Configures the RimuHosting connection.
|
||||||
|
@ -44,6 +49,12 @@ import java.net.URI;
|
||||||
@ConfiguresRestClient
|
@ConfiguresRestClient
|
||||||
public class RimuHostingRestClientModule extends AbstractModule {
|
public class RimuHostingRestClientModule extends AbstractModule {
|
||||||
|
|
||||||
|
@Provides
|
||||||
|
@Singleton
|
||||||
|
protected Predicate<InetSocketAddress> socketTester(SocketOpen open) {
|
||||||
|
return new RetryablePredicate<InetSocketAddress>(open, 130, 1, TimeUnit.SECONDS);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void configure() {
|
protected void configure() {
|
||||||
bindErrorHandlers();
|
bindErrorHandlers();
|
||||||
|
@ -66,15 +77,16 @@ public class RimuHostingRestClientModule extends AbstractModule {
|
||||||
|
|
||||||
@Provides
|
@Provides
|
||||||
@Singleton
|
@Singleton
|
||||||
public RimuHostingClient provideClient(RimuHostingAsyncClient client) throws IllegalArgumentException,
|
public RimuHostingClient provideClient(RimuHostingAsyncClient client)
|
||||||
SecurityException, NoSuchMethodException {
|
throws IllegalArgumentException, SecurityException, NoSuchMethodException {
|
||||||
return SyncProxy.create(RimuHostingClient.class, client);
|
return SyncProxy.create(RimuHostingClient.class, client);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Provides
|
@Provides
|
||||||
@Singleton
|
@Singleton
|
||||||
@RimuHosting
|
@RimuHosting
|
||||||
protected URI provideURI(@Named(RimuHostingConstants.PROPERTY_RIMUHOSTING_ENDPOINT) String endpoint) {
|
protected URI provideURI(
|
||||||
|
@Named(RimuHostingConstants.PROPERTY_RIMUHOSTING_ENDPOINT) String endpoint) {
|
||||||
return URI.create(endpoint);
|
return URI.create(endpoint);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -36,7 +36,7 @@ public class RimuHostingComputeServiceLiveTest extends BaseComputeServiceLiveTes
|
||||||
@Override
|
@Override
|
||||||
public void setServiceDefaults() {
|
public void setServiceDefaults() {
|
||||||
service = "rimuhosting";
|
service = "rimuhosting";
|
||||||
nodeName = "rimuhosting.jclouds";
|
tag = "rimuhosting.jclouds";
|
||||||
}
|
}
|
||||||
|
|
||||||
protected Template buildTemplate(TemplateBuilder templateBuilder) {
|
protected Template buildTemplate(TemplateBuilder templateBuilder) {
|
||||||
|
|
|
@ -1,29 +1,28 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<!--
|
<!--
|
||||||
|
|
||||||
|
|
||||||
Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
|
Copyright (C) 2009 Cloud Conscious, LLC.
|
||||||
|
<info@cloudconscious.com>
|
||||||
|
|
||||||
====================================================================
|
====================================================================
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
You may obtain a copy of the License at
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
http://www.apache.org/licenses/LICENSE-2.0
|
http://www.apache.org/licenses/LICENSE-2.0 Unless required by
|
||||||
|
applicable law or agreed to in writing, software distributed
|
||||||
Unless required by applicable law or agreed to in writing, software
|
under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
distributed under the License is distributed on an "AS IS" BASIS,
|
WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
See the License for the specific language governing permissions
|
||||||
See the License for the specific language governing permissions and
|
and limitations under the License.
|
||||||
limitations under the License.
|
|
||||||
====================================================================
|
====================================================================
|
||||||
|
-->
|
||||||
-->
|
|
||||||
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
|
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
|
||||||
|
|
||||||
<!--
|
<!--
|
||||||
For more configuration infromation and examples see the Apache Log4j
|
For more configuration infromation and examples see the Apache
|
||||||
website: http://logging.apache.org/log4j/
|
Log4j website: http://logging.apache.org/log4j/
|
||||||
-->
|
-->
|
||||||
<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/"
|
<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/"
|
||||||
debug="false">
|
debug="false">
|
||||||
|
@ -39,13 +38,17 @@
|
||||||
<param name="Threshold" value="TRACE" />
|
<param name="Threshold" value="TRACE" />
|
||||||
|
|
||||||
<layout class="org.apache.log4j.PatternLayout">
|
<layout class="org.apache.log4j.PatternLayout">
|
||||||
<!-- The default pattern: Date Priority [Category] Message${symbol_escape}n -->
|
<!--
|
||||||
|
The default pattern: Date Priority [Category]
|
||||||
|
Message${symbol_escape}n
|
||||||
|
-->
|
||||||
<param name="ConversionPattern" value="%d %-5p [%c] (%t) %m%n" />
|
<param name="ConversionPattern" value="%d %-5p [%c] (%t) %m%n" />
|
||||||
|
|
||||||
<!--
|
<!--
|
||||||
The full pattern: Date MS Priority [Category] (Thread:NDC) Message${symbol_escape}n
|
The full pattern: Date MS Priority [Category]
|
||||||
<param name="ConversionPattern" value="%d %-5r %-5p [%c] (%t:%x)
|
(Thread:NDC) Message${symbol_escape}n <param
|
||||||
%m%n"/>
|
name="ConversionPattern" value="%d %-5r %-5p [%c]
|
||||||
|
(%t:%x) %m%n"/>
|
||||||
-->
|
-->
|
||||||
</layout>
|
</layout>
|
||||||
</appender>
|
</appender>
|
||||||
|
@ -61,17 +64,45 @@
|
||||||
<param name="Threshold" value="TRACE" />
|
<param name="Threshold" value="TRACE" />
|
||||||
|
|
||||||
<layout class="org.apache.log4j.PatternLayout">
|
<layout class="org.apache.log4j.PatternLayout">
|
||||||
<!-- The default pattern: Date Priority [Category] Message${symbol_escape}n -->
|
<!--
|
||||||
|
The default pattern: Date Priority [Category]
|
||||||
|
Message${symbol_escape}n
|
||||||
|
-->
|
||||||
<param name="ConversionPattern" value="%d %-5p [%c] (%t) %m%n" />
|
<param name="ConversionPattern" value="%d %-5p [%c] (%t) %m%n" />
|
||||||
|
|
||||||
<!--
|
<!--
|
||||||
The full pattern: Date MS Priority [Category] (Thread:NDC) Message${symbol_escape}n
|
The full pattern: Date MS Priority [Category]
|
||||||
<param name="ConversionPattern" value="%d %-5r %-5p [%c] (%t:%x)
|
(Thread:NDC) Message${symbol_escape}n <param
|
||||||
%m%n"/>
|
name="ConversionPattern" value="%d %-5r %-5p [%c]
|
||||||
|
(%t:%x) %m%n"/>
|
||||||
|
-->
|
||||||
|
</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" />
|
||||||
|
<param name="Append" value="true" />
|
||||||
|
|
||||||
|
<!-- Rollover at midnight each day -->
|
||||||
|
<param name="DatePattern" value="'.'yyyy-MM-dd" />
|
||||||
|
|
||||||
|
<param name="Threshold" value="TRACE" />
|
||||||
|
|
||||||
|
<layout class="org.apache.log4j.PatternLayout">
|
||||||
|
<!-- The default pattern: Date Priority [Category] Message\n -->
|
||||||
|
<param name="ConversionPattern" value="%d %-5p [%c] (%t) %m%n" />
|
||||||
|
|
||||||
|
<!--
|
||||||
|
The full pattern: Date MS Priority [Category]
|
||||||
|
(Thread:NDC) Message\n <param name="ConversionPattern"
|
||||||
|
value="%d %-5r %-5p [%c] (%t:%x) %m%n"/>
|
||||||
-->
|
-->
|
||||||
</layout>
|
</layout>
|
||||||
</appender>
|
</appender>
|
||||||
|
|
||||||
|
<appender name="ASYNCCOMPUTE" class="org.apache.log4j.AsyncAppender">
|
||||||
|
<appender-ref ref="COMPUTEFILE" />
|
||||||
|
</appender>
|
||||||
<appender name="ASYNC" class="org.apache.log4j.AsyncAppender">
|
<appender name="ASYNC" class="org.apache.log4j.AsyncAppender">
|
||||||
<appender-ref ref="FILE" />
|
<appender-ref ref="FILE" />
|
||||||
</appender>
|
</appender>
|
||||||
|
@ -99,6 +130,11 @@
|
||||||
<appender-ref ref="ASYNCWIRE" />
|
<appender-ref ref="ASYNCWIRE" />
|
||||||
</category>
|
</category>
|
||||||
|
|
||||||
|
<category name="jclouds.compute">
|
||||||
|
<priority value="TRACE" />
|
||||||
|
<appender-ref ref="ASYNCCOMPUTE" />
|
||||||
|
</category>
|
||||||
|
|
||||||
<!-- ======================= -->
|
<!-- ======================= -->
|
||||||
<!-- Setup the Root category -->
|
<!-- Setup the Root category -->
|
||||||
<!-- ======================= -->
|
<!-- ======================= -->
|
||||||
|
|
|
@ -2,4 +2,4 @@ service=ec2
|
||||||
driver=aws
|
driver=aws
|
||||||
account=accesskeyid
|
account=accesskeyid
|
||||||
key=secretaccesskey
|
key=secretaccesskey
|
||||||
nodename=we_create_and_delete_based_on_key_and_security_group_name_not_instance_id
|
nodetag=we_create_and_delete_based_on_key_and_security_group_name_not_instance_id
|
||||||
|
|
|
@ -2,4 +2,4 @@ service=hostingdotcom
|
||||||
driver=hostingdotcom
|
driver=hostingdotcom
|
||||||
account=user@youregistered.com
|
account=user@youregistered.com
|
||||||
key=password
|
key=password
|
||||||
nodename=name_of_your_vapp
|
nodetag=name_of_your_vapp
|
||||||
|
|
|
@ -2,4 +2,4 @@ service=cloudservers
|
||||||
driver=rackspace
|
driver=rackspace
|
||||||
account=user
|
account=user
|
||||||
key=your_key
|
key=your_key
|
||||||
nodename=name_of_your_server
|
nodetag=name_of_your_server
|
||||||
|
|
|
@ -2,4 +2,4 @@ service=rimuhosting
|
||||||
driver=rimuhosting
|
driver=rimuhosting
|
||||||
account=apikey
|
account=apikey
|
||||||
key=apikey
|
key=apikey
|
||||||
nodename=name_of_your_server
|
nodetag=name_of_your_server
|
||||||
|
|
|
@ -2,4 +2,4 @@ service=terremark
|
||||||
driver=terremark
|
driver=terremark
|
||||||
account=user@youregistered.com
|
account=user@youregistered.com
|
||||||
key=password
|
key=password
|
||||||
nodename=name_of_your_vapp
|
nodetag=name_of_your_vapp
|
||||||
|
|
|
@ -4,4 +4,4 @@ driver=vcloud
|
||||||
vcloud.endpoint=https://vcloud_host_you_want/api
|
vcloud.endpoint=https://vcloud_host_you_want/api
|
||||||
account=user@youregistered.com
|
account=user@youregistered.com
|
||||||
key=password
|
key=password
|
||||||
nodename=name_of_your_vapp
|
nodetag=name_of_your_vapp
|
||||||
|
|
|
@ -71,26 +71,26 @@
|
||||||
|
|
||||||
<input message="What is your account on ${service}?" addproperty="account"/>
|
<input message="What is your account on ${service}?" addproperty="account"/>
|
||||||
<input message="What is the key for ${account}?" addproperty="key"/>
|
<input message="What is the key for ${account}?" addproperty="key"/>
|
||||||
<input message="What is the nodename for the deployment?" addproperty="nodename"/>
|
<input message="What is the nodetag for the deployment?" addproperty="nodetag"/>
|
||||||
<property name="url" value="compute://${account}:${key}@${service}"/>
|
<property name="url" value="compute://${account}:${key}@${service}"/>
|
||||||
|
|
||||||
<target name="destroy" description="destroy the node ${nodename}">
|
<target name="destroy" description="destroy the nodes ${nodetag}">
|
||||||
<compute action="destroy" provider="${url}">
|
<compute actions="destroy" provider="${url}">
|
||||||
<node name="${nodename}" />
|
<nodes tag="${nodetag}" />
|
||||||
</compute>
|
</compute>
|
||||||
<sleep seconds="5" />
|
<sleep seconds="5" />
|
||||||
</target>
|
</target>
|
||||||
|
|
||||||
<target name="create" description="create the node ${nodename}" depends="destroy" >
|
<target name="create" description="create the nodes ${nodetag}" >
|
||||||
<compute action="create" provider="${url}">
|
<compute actions="destroy,create" provider="${url}">
|
||||||
<node name="${nodename}" os="UBUNTU" size="SMALLEST"
|
<nodes tag="${nodetag}" os="UBUNTU" size="SMALLEST"
|
||||||
runscript="runscript.sh" openports="22,${listenport}"
|
runscript="runscript.sh" openports="22,${listenport}"
|
||||||
hostproperty="host" usernameproperty="username" passwordproperty="password" />
|
hostproperty="host" usernameproperty="username" passwordproperty="password" />
|
||||||
</compute>
|
</compute>
|
||||||
</target>
|
</target>
|
||||||
|
|
||||||
<target name="cargooverssh" depends="create" description="run cargo on remote node" >
|
<target name="cargooverssh" depends="create" description="run cargo on remote nodes" >
|
||||||
<echo message="deploying tomcat and blaze to: ${nodename}" />
|
<echo message="deploying tomcat and blaze to: ${nodetag}" />
|
||||||
<cargo containerId="tomcat6x" output="build/output.log" log="build/cargo.log" action="start" timeout="600000">
|
<cargo containerId="tomcat6x" output="build/output.log" log="build/cargo.log" action="start" timeout="600000">
|
||||||
<zipurlinstaller installurl="${container.zip}" />
|
<zipurlinstaller installurl="${container.zip}" />
|
||||||
<configuration home="build/cargo" type="standalone">
|
<configuration home="build/cargo" type="standalone">
|
||||||
|
|
|
@ -2,4 +2,4 @@ service=ec2
|
||||||
driver=aws
|
driver=aws
|
||||||
account=accesskeyid
|
account=accesskeyid
|
||||||
key=secretaccesskey
|
key=secretaccesskey
|
||||||
nodename=we_create_and_delete_based_on_key_and_security_group_name_not_instance_id
|
nodetag=we_create_and_delete_based_on_key_and_security_group_name_not_instance_id
|
||||||
|
|
|
@ -2,4 +2,4 @@ service=hostingdotcom
|
||||||
driver=hostingdotcom
|
driver=hostingdotcom
|
||||||
account=user@youregistered.com
|
account=user@youregistered.com
|
||||||
key=password
|
key=password
|
||||||
nodename=name_of_your_vapp
|
nodetag=name_of_your_vapp
|
||||||
|
|
|
@ -2,4 +2,4 @@ service=cloudservers
|
||||||
driver=rackspace
|
driver=rackspace
|
||||||
account=user
|
account=user
|
||||||
key=your_key
|
key=your_key
|
||||||
nodename=name_of_your_server
|
nodetag=name_of_your_server
|
||||||
|
|
|
@ -2,4 +2,4 @@ service=rimuhosting
|
||||||
driver=rimuhosting
|
driver=rimuhosting
|
||||||
account=apikey
|
account=apikey
|
||||||
key=apikey
|
key=apikey
|
||||||
nodename=name_of_your_server
|
nodetag=name_of_your_server
|
||||||
|
|
|
@ -2,4 +2,4 @@ service=terremark
|
||||||
driver=terremark
|
driver=terremark
|
||||||
account=user@youregistered.com
|
account=user@youregistered.com
|
||||||
key=password
|
key=password
|
||||||
nodename=name_of_your_vapp
|
nodetag=name_of_your_vapp
|
||||||
|
|
|
@ -4,4 +4,4 @@ driver=vcloud
|
||||||
vcloud.endpoint=https://vcloud_host_you_want/api
|
vcloud.endpoint=https://vcloud_host_you_want/api
|
||||||
account=user@youregistered.com
|
account=user@youregistered.com
|
||||||
key=password
|
key=password
|
||||||
nodename=name_of_your_vapp
|
nodetag=name_of_your_vapp
|
||||||
|
|
|
@ -65,56 +65,64 @@
|
||||||
<property name="jclouds.compute.url" value="compute://${account}:${key}@${service}" />
|
<property name="jclouds.compute.url" value="compute://${account}:${key}@${service}" />
|
||||||
|
|
||||||
<target name="list" description="list the identity of all nodes">
|
<target name="list" description="list the identity of all nodes">
|
||||||
<compute action="list" provider="${jclouds.compute.url}" />
|
<compute actions="list" provider="${jclouds.compute.url}" />
|
||||||
</target>
|
</target>
|
||||||
|
|
||||||
<target name="list-details" description="list the details of all nodes">
|
<target name="list-details" description="list the details of all nodes">
|
||||||
<compute action="list-details" provider="${jclouds.compute.url}" />
|
<compute actions="list-details" provider="${jclouds.compute.url}" />
|
||||||
</target>
|
</target>
|
||||||
|
|
||||||
<target name="list-images" description="list the images supported">
|
<target name="list-images" description="list the images supported">
|
||||||
<compute action="list-images" provider="${jclouds.compute.url}" />
|
<compute actions="list-images" provider="${jclouds.compute.url}" />
|
||||||
</target>
|
</target>
|
||||||
|
|
||||||
<target name="list-sizes" description="list the sizes supported">
|
<target name="list-sizes" description="list the sizes supported">
|
||||||
<compute action="list-sizes" provider="${jclouds.compute.url}" />
|
<compute actions="list-sizes" provider="${jclouds.compute.url}" />
|
||||||
</target>
|
</target>
|
||||||
|
|
||||||
<target name="destroy" description="destroy the node ${nodename}">
|
<target name="list-locations" description="list the locations supported">
|
||||||
|
<compute actions="list-locations" provider="${jclouds.compute.url}" />
|
||||||
|
</target>
|
||||||
|
|
||||||
|
<target name="dump" description="list all information we can obtain about the cloud">
|
||||||
|
<compute actions="list-locations,list-sizes,list-images,list-details" provider="${jclouds.compute.url}" />
|
||||||
|
</target>
|
||||||
|
|
||||||
|
<target name="destroy" description="destroy the node ${nodetag}">
|
||||||
|
|
||||||
<input
|
<input
|
||||||
message="Which node do you wish to destroy"
|
message="Which node do you wish to destroy"
|
||||||
addproperty="nodename"
|
addproperty="nodetag"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<compute action="destroy" provider="${jclouds.compute.url}">
|
<compute actions="destroy" provider="${jclouds.compute.url}">
|
||||||
<node name="${nodename}" />
|
<node tag="${nodetag}" />
|
||||||
</compute>
|
</compute>
|
||||||
</target>
|
</target>
|
||||||
|
|
||||||
<target name="get" description="get the node ${nodename}">
|
<target name="get" description="get the node ${nodetag}">
|
||||||
|
|
||||||
<input
|
<input
|
||||||
message="Which node do you wish to describe?"
|
message="Which node do you wish to describe?"
|
||||||
addproperty="nodename"
|
addproperty="nodetag"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<compute action="get" provider="${jclouds.compute.url}">
|
<compute actions="get" provider="${jclouds.compute.url}">
|
||||||
<node name="${nodename}" />
|
<node tag="${nodetag}" />
|
||||||
</compute>
|
</compute>
|
||||||
</target>
|
</target>
|
||||||
|
|
||||||
<property name="location" value="" />
|
<property name="location" value="" />
|
||||||
<target name="create" description="create the node ${nodename}">
|
<target name="create" description="create the node ${nodetag}">
|
||||||
<property name="os" value="UBUNTU" />
|
<property name="os" value="UBUNTU" />
|
||||||
|
|
||||||
<input
|
<input
|
||||||
message="What do you want to name your node?"
|
message="What do you want to name your node?"
|
||||||
addproperty="nodename"
|
addproperty="nodetag"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<compute action="create" provider="${jclouds.compute.url}">
|
<compute actions="create" provider="${jclouds.compute.url}">
|
||||||
<node name="${nodename}" location="${location}" os="${os}" size="SMALLEST" hostproperty="host" usernameproperty="username" passwordproperty="password" />
|
<node tag="${nodetag}" location="${location}" os="${os}" size="SMALLEST" hostproperty="host" usernameproperty="username" passwordproperty="password" />
|
||||||
</compute>
|
</compute>
|
||||||
</target>
|
</target>
|
||||||
|
|
||||||
|
|
|
@ -18,11 +18,9 @@
|
||||||
*/
|
*/
|
||||||
package org.jclouds.tools.ant.taskdefs.compute;
|
package org.jclouds.tools.ant.taskdefs.compute;
|
||||||
|
|
||||||
import static org.jclouds.compute.util.ComputeUtils.filterByName;
|
|
||||||
import static org.jclouds.compute.util.ComputeUtils.isKeyAuth;
|
import static org.jclouds.compute.util.ComputeUtils.isKeyAuth;
|
||||||
import static org.jclouds.tools.ant.taskdefs.compute.ComputeTaskUtils.buildComputeMap;
|
import static org.jclouds.tools.ant.taskdefs.compute.ComputeTaskUtils.buildComputeMap;
|
||||||
import static org.jclouds.tools.ant.taskdefs.compute.ComputeTaskUtils.createTemplateFromElement;
|
import static org.jclouds.tools.ant.taskdefs.compute.ComputeTaskUtils.createTemplateFromElement;
|
||||||
import static org.jclouds.tools.ant.taskdefs.compute.ComputeTaskUtils.getNodeOptionsFromElement;
|
|
||||||
import static org.jclouds.tools.ant.taskdefs.compute.ComputeTaskUtils.ipOrEmptyString;
|
import static org.jclouds.tools.ant.taskdefs.compute.ComputeTaskUtils.ipOrEmptyString;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
@ -39,15 +37,16 @@ import org.apache.tools.ant.Task;
|
||||||
import org.jclouds.compute.ComputeService;
|
import org.jclouds.compute.ComputeService;
|
||||||
import org.jclouds.compute.ComputeServiceContext;
|
import org.jclouds.compute.ComputeServiceContext;
|
||||||
import org.jclouds.compute.domain.ComputeMetadata;
|
import org.jclouds.compute.domain.ComputeMetadata;
|
||||||
import org.jclouds.compute.domain.CreateNodeResponse;
|
|
||||||
import org.jclouds.compute.domain.Image;
|
import org.jclouds.compute.domain.Image;
|
||||||
import org.jclouds.compute.domain.NodeMetadata;
|
import org.jclouds.compute.domain.NodeMetadata;
|
||||||
import org.jclouds.compute.domain.Size;
|
import org.jclouds.compute.domain.Size;
|
||||||
import org.jclouds.compute.domain.Template;
|
import org.jclouds.compute.domain.Template;
|
||||||
import org.jclouds.compute.options.RunNodeOptions;
|
import org.jclouds.domain.Location;
|
||||||
import org.jclouds.http.HttpUtils;
|
import org.jclouds.http.HttpUtils;
|
||||||
|
|
||||||
import com.google.common.base.CaseFormat;
|
import com.google.common.base.CaseFormat;
|
||||||
|
import com.google.common.base.Splitter;
|
||||||
|
import com.google.common.collect.Iterables;
|
||||||
import com.google.common.io.Files;
|
import com.google.common.io.Files;
|
||||||
import com.google.inject.Provider;
|
import com.google.inject.Provider;
|
||||||
|
|
||||||
|
@ -59,7 +58,7 @@ public class ComputeTask extends Task {
|
||||||
|
|
||||||
private final Map<URI, ComputeServiceContext> computeMap;
|
private final Map<URI, ComputeServiceContext> computeMap;
|
||||||
private String provider;
|
private String provider;
|
||||||
private String action;
|
private String actions;
|
||||||
private NodeElement nodeElement;
|
private NodeElement nodeElement;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -82,7 +81,7 @@ public class ComputeTask extends Task {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static enum Action {
|
public static enum Action {
|
||||||
CREATE, GET, LIST, LIST_DETAILS, DESTROY, LIST_IMAGES, LIST_SIZES
|
CREATE, GET, LIST, LIST_DETAILS, DESTROY, LIST_IMAGES, LIST_SIZES, LIST_LOCATIONS
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -90,10 +89,13 @@ public class ComputeTask extends Task {
|
||||||
*/
|
*/
|
||||||
public void execute() throws BuildException {
|
public void execute() throws BuildException {
|
||||||
ComputeServiceContext context = computeMap.get(HttpUtils.createUri(provider));
|
ComputeServiceContext context = computeMap.get(HttpUtils.createUri(provider));
|
||||||
Action action = Action.valueOf(CaseFormat.LOWER_HYPHEN.to(CaseFormat.UPPER_UNDERSCORE,
|
|
||||||
this.action));
|
|
||||||
try {
|
try {
|
||||||
invokeActionOnService(action, context.getComputeService());
|
for (String action : Splitter.on(',').split(actions)) {
|
||||||
|
Action act = Action.valueOf(CaseFormat.LOWER_HYPHEN.to(CaseFormat.UPPER_UNDERSCORE,
|
||||||
|
action));
|
||||||
|
invokeActionOnService(act, context.getComputeService());
|
||||||
|
}
|
||||||
} finally {
|
} finally {
|
||||||
context.close();
|
context.close();
|
||||||
}
|
}
|
||||||
|
@ -132,6 +134,9 @@ public class ComputeTask extends Task {
|
||||||
case LIST_SIZES:
|
case LIST_SIZES:
|
||||||
listSizes(computeService);
|
listSizes(computeService);
|
||||||
break;
|
break;
|
||||||
|
case LIST_LOCATIONS:
|
||||||
|
listLocations(computeService);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
this.log("bad action: " + action, Project.MSG_ERR);
|
this.log("bad action: " + action, Project.MSG_ERR);
|
||||||
}
|
}
|
||||||
|
@ -139,7 +144,7 @@ public class ComputeTask extends Task {
|
||||||
|
|
||||||
private void listDetails(ComputeService computeService) {
|
private void listDetails(ComputeService computeService) {
|
||||||
log("list details");
|
log("list details");
|
||||||
for (ComputeMetadata node : computeService.listNodes()) {// TODO
|
for (ComputeMetadata node : computeService.getNodes().values()) {// TODO
|
||||||
// parallel
|
// parallel
|
||||||
logDetails(computeService, node);
|
logDetails(computeService, node);
|
||||||
}
|
}
|
||||||
|
@ -147,58 +152,67 @@ public class ComputeTask extends Task {
|
||||||
|
|
||||||
private void listImages(ComputeService computeService) {
|
private void listImages(ComputeService computeService) {
|
||||||
log("list images");
|
log("list images");
|
||||||
for (Image image : computeService.listImages()) {// TODO
|
for (Image image : computeService.getImages().values()) {// TODO
|
||||||
log(String.format(" image location=%s, id=%s, version=%s, arch=%s, osfam=%s, desc=%s",
|
log(String.format(" image location=%s, id=%s, version=%s, arch=%s, osfam=%s, desc=%s",
|
||||||
image.getLocation(), image.getId(), image.getVersion(), image.getArchitecture(),
|
image.getLocationId(), image.getId(), image.getVersion(),
|
||||||
image.getOsFamily(), image.getOsDescription()));
|
image.getArchitecture(), image.getOsFamily(), image.getOsDescription()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void listSizes(ComputeService computeService) {
|
private void listSizes(ComputeService computeService) {
|
||||||
log("list sizes");
|
log("list sizes");
|
||||||
for (Size size : computeService.listSizes()) {// TODO
|
for (Size size : computeService.getSizes().values()) {// TODO
|
||||||
log(String.format(" size id=%s, cores=%s, ram=%s, disk=%s", size.getId(), size
|
log(String.format(" size id=%s, cores=%s, ram=%s, disk=%s", size.getId(), size
|
||||||
.getCores(), size.getRam(), size.getDisk()));
|
.getCores(), size.getRam(), size.getDisk()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void listLocations(ComputeService computeService) {
|
||||||
|
log("list locations");
|
||||||
|
for (Location location : computeService.getLocations().values()) {// TODO
|
||||||
|
log(String.format(" location id=%s, scope=%s, description=%s, parent=%s, assignable=%s",
|
||||||
|
location.getId(), location.getScope(), location.getDescription(), location
|
||||||
|
.getParent(), location.isAssignable()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void list(ComputeService computeService) {
|
private void list(ComputeService computeService) {
|
||||||
log("list");
|
log("list");
|
||||||
for (ComputeMetadata node : computeService.listNodes()) {
|
for (ComputeMetadata node : computeService.getNodes().values()) {
|
||||||
log(String.format(" location=%s, id=%s, name=%s", node.getLocation(), node.getId(), node
|
log(String.format(" location=%s, id=%s, tag=%s", node.getLocationId(), node.getId(),
|
||||||
.getName()));
|
node.getName()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void create(ComputeService computeService) {
|
private void create(ComputeService computeService) {
|
||||||
String name = nodeElement.getName();
|
String tag = nodeElement.getTag();
|
||||||
|
|
||||||
log(String.format("create name: %s, size: %s, os: %s", name, nodeElement.getSize(),
|
log(String.format("create tag: %s, count: %d, size: %s, os: %s", tag, nodeElement.getCount(),
|
||||||
nodeElement.getOs()));
|
nodeElement.getSize(), nodeElement.getOs()));
|
||||||
|
|
||||||
Template template = createTemplateFromElement(nodeElement, computeService);
|
Template template = createTemplateFromElement(nodeElement, computeService);
|
||||||
|
|
||||||
RunNodeOptions options = getNodeOptionsFromElement(nodeElement);
|
NodeMetadata createdNode = Iterables.getOnlyElement(computeService.runNodes(tag, nodeElement
|
||||||
|
.getCount(), template));
|
||||||
CreateNodeResponse createdNode = computeService.runNode(name, template, options);
|
|
||||||
|
|
||||||
logNodeDetails(createdNode);
|
logNodeDetails(createdNode);
|
||||||
|
|
||||||
addNodeDetailsAsProjectProperties(createdNode);
|
addNodeDetailsAsProjectProperties(createdNode);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void logNodeDetails(CreateNodeResponse createdNode) {
|
private void logNodeDetails(NodeMetadata createdNode) {
|
||||||
log(String.format(" id=%s, name=%s, connection=%s:%s@%s", createdNode.getId(), createdNode
|
log(String.format(" id=%s, tag=%s, location=%s, tag=%s, connection=%s:%s@%s", createdNode
|
||||||
.getName(), createdNode.getCredentials().account, createdNode.getCredentials().key,
|
.getId(), createdNode.getTag(), createdNode.getLocationId(), createdNode.getName(),
|
||||||
createdNode.getPublicAddresses().first().getHostAddress()));
|
createdNode.getCredentials().account, createdNode.getCredentials().key,
|
||||||
|
ipOrEmptyString(createdNode.getPublicAddresses())));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addNodeDetailsAsProjectProperties(CreateNodeResponse createdNode) {
|
private void addNodeDetailsAsProjectProperties(NodeMetadata createdNode) {
|
||||||
if (nodeElement.getIdproperty() != null)
|
if (nodeElement.getIdproperty() != null)
|
||||||
getProject().setProperty(nodeElement.getIdproperty(), createdNode.getId());
|
getProject().setProperty(nodeElement.getIdproperty(), createdNode.getId());
|
||||||
if (nodeElement.getHostproperty() != null)
|
if (nodeElement.getHostproperty() != null)
|
||||||
getProject().setProperty(nodeElement.getHostproperty(),
|
getProject().setProperty(nodeElement.getHostproperty(),
|
||||||
createdNode.getPublicAddresses().first().getHostAddress());
|
ipOrEmptyString(createdNode.getPublicAddresses()));
|
||||||
if (nodeElement.getKeyfile() != null && isKeyAuth(createdNode))
|
if (nodeElement.getKeyfile() != null && isKeyAuth(createdNode))
|
||||||
try {
|
try {
|
||||||
Files.write(createdNode.getCredentials().key, new File(nodeElement.getKeyfile()),
|
Files.write(createdNode.getCredentials().key, new File(nodeElement.getKeyfile()),
|
||||||
|
@ -215,54 +229,49 @@ public class ComputeTask extends Task {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void destroy(ComputeService computeService) {
|
private void destroy(ComputeService computeService) {
|
||||||
log(String.format("destroy name: %s", nodeElement.getName()));
|
log(String.format("destroy tag: %s", nodeElement.getTag()));
|
||||||
Iterable<? extends ComputeMetadata> nodesThatMatch = filterByName(computeService.listNodes(),
|
computeService.destroyNodes(nodeElement.getTag());
|
||||||
nodeElement.getName());
|
|
||||||
for (ComputeMetadata node : nodesThatMatch) {
|
|
||||||
log(String.format(" destroying id=%s, name=%s", node.getId(), node.getName()));
|
|
||||||
computeService.destroyNode(node);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void get(ComputeService computeService) {
|
private void get(ComputeService computeService) {
|
||||||
log(String.format("get name: %s", nodeElement.getName()));
|
log(String.format("get tag: %s", nodeElement.getTag()));
|
||||||
Iterable<? extends ComputeMetadata> nodesThatMatch = filterByName(computeService.listNodes(),
|
for (ComputeMetadata node : computeService.getNodes(nodeElement.getTag())) {
|
||||||
nodeElement.getName());
|
|
||||||
for (ComputeMetadata node : nodesThatMatch) {
|
|
||||||
logDetails(computeService, node);
|
logDetails(computeService, node);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void logDetails(ComputeService computeService, ComputeMetadata node) {
|
private void logDetails(ComputeService computeService, ComputeMetadata node) {
|
||||||
NodeMetadata metadata = computeService.getNodeMetadata(node);
|
NodeMetadata metadata = node instanceof NodeMetadata ? NodeMetadata.class.cast(node)
|
||||||
|
: computeService.getNodeMetadata(node);
|
||||||
log(String
|
log(String
|
||||||
.format(
|
.format(
|
||||||
" node id=%s, name=%s, location=%s, state=%s, publicIp=%s, privateIp=%s, extra=%s",
|
" node id=%s, name=%s, tag=%s, location=%s, state=%s, publicIp=%s, privateIp=%s, extra=%s",
|
||||||
metadata.getId(), node.getName(), node.getLocation(), metadata.getState(),
|
metadata.getId(), metadata.getName(), metadata.getTag(), metadata
|
||||||
ipOrEmptyString(metadata.getPublicAddresses()), ipOrEmptyString(metadata
|
.getLocationId(), metadata.getState(), ComputeTaskUtils
|
||||||
.getPrivateAddresses()), metadata.getExtra()));
|
.ipOrEmptyString(metadata.getPublicAddresses()),
|
||||||
|
ipOrEmptyString(metadata.getPrivateAddresses()), metadata.getExtra()));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return the configured {@link NodeElement} element
|
* @return the configured {@link NodeElement} element
|
||||||
*/
|
*/
|
||||||
public final NodeElement createNode() {
|
public final NodeElement createNodes() {
|
||||||
if (getNode() == null) {
|
if (getNodes() == null) {
|
||||||
this.nodeElement = new NodeElement();
|
this.nodeElement = new NodeElement();
|
||||||
}
|
}
|
||||||
return this.nodeElement;
|
return this.nodeElement;
|
||||||
}
|
}
|
||||||
|
|
||||||
public NodeElement getNode() {
|
public NodeElement getNodes() {
|
||||||
return this.nodeElement;
|
return this.nodeElement;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getAction() {
|
public String getActions() {
|
||||||
return action;
|
return actions;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setAction(String action) {
|
public void setActions(String actions) {
|
||||||
this.action = action;
|
this.actions = actions;
|
||||||
}
|
}
|
||||||
|
|
||||||
public NodeElement getNodeElement() {
|
public NodeElement getNodeElement() {
|
||||||
|
|
|
@ -31,24 +31,22 @@ import java.net.URI;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.NoSuchElementException;
|
import java.util.NoSuchElementException;
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
import java.util.SortedSet;
|
import java.util.Set;
|
||||||
|
|
||||||
import org.apache.tools.ant.BuildException;
|
import org.apache.tools.ant.BuildException;
|
||||||
import org.apache.tools.ant.Project;
|
import org.apache.tools.ant.Project;
|
||||||
import org.jclouds.compute.ComputeService;
|
import org.jclouds.compute.ComputeService;
|
||||||
import org.jclouds.compute.ComputeServiceContext;
|
import org.jclouds.compute.ComputeServiceContext;
|
||||||
import org.jclouds.compute.ComputeServiceContextFactory;
|
import org.jclouds.compute.ComputeServiceContextFactory;
|
||||||
import org.jclouds.compute.domain.Image;
|
|
||||||
import org.jclouds.compute.domain.OsFamily;
|
import org.jclouds.compute.domain.OsFamily;
|
||||||
import org.jclouds.compute.domain.Template;
|
import org.jclouds.compute.domain.Template;
|
||||||
import org.jclouds.compute.domain.TemplateBuilder;
|
import org.jclouds.compute.domain.TemplateBuilder;
|
||||||
import org.jclouds.compute.options.RunNodeOptions;
|
import org.jclouds.compute.options.TemplateOptions;
|
||||||
import org.jclouds.compute.reference.ComputeServiceConstants;
|
import org.jclouds.compute.reference.ComputeServiceConstants;
|
||||||
import org.jclouds.ssh.jsch.config.JschSshClientModule;
|
import org.jclouds.ssh.jsch.config.JschSshClientModule;
|
||||||
import org.jclouds.tools.ant.logging.config.AntLoggingModule;
|
import org.jclouds.tools.ant.logging.config.AntLoggingModule;
|
||||||
|
|
||||||
import com.google.common.base.Function;
|
import com.google.common.base.Function;
|
||||||
import com.google.common.base.Predicate;
|
|
||||||
import com.google.common.base.Splitter;
|
import com.google.common.base.Splitter;
|
||||||
import com.google.common.collect.ImmutableSet;
|
import com.google.common.collect.ImmutableSet;
|
||||||
import com.google.common.collect.Iterables;
|
import com.google.common.collect.Iterables;
|
||||||
|
@ -99,20 +97,11 @@ public class ComputeTaskUtils {
|
||||||
static Template createTemplateFromElement(NodeElement nodeElement, ComputeService computeService) {
|
static Template createTemplateFromElement(NodeElement nodeElement, ComputeService computeService) {
|
||||||
TemplateBuilder templateBuilder = computeService.templateBuilder();
|
TemplateBuilder templateBuilder = computeService.templateBuilder();
|
||||||
if (nodeElement.getLocation() != null && !"".equals(nodeElement.getLocation()))
|
if (nodeElement.getLocation() != null && !"".equals(nodeElement.getLocation()))
|
||||||
templateBuilder.location(nodeElement.getLocation());
|
templateBuilder.locationId(nodeElement.getLocation());
|
||||||
if (nodeElement.getImage() != null && !"".equals(nodeElement.getImage())) {
|
if (nodeElement.getImage() != null && !"".equals(nodeElement.getImage())) {
|
||||||
final String imageId = nodeElement.getImage();
|
final String imageId = nodeElement.getImage();
|
||||||
try {
|
try {
|
||||||
Image image = Iterables.getOnlyElement(Iterables.filter(computeService.listImages(),
|
templateBuilder.imageId(imageId);
|
||||||
new Predicate<Image>() {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean apply(Image input) {
|
|
||||||
return input.getId().equals(imageId);
|
|
||||||
}
|
|
||||||
|
|
||||||
}));
|
|
||||||
templateBuilder.fromImage(image);
|
|
||||||
} catch (NoSuchElementException e) {
|
} catch (NoSuchElementException e) {
|
||||||
throw new BuildException("image not found " + nodeElement.getImage());
|
throw new BuildException("image not found " + nodeElement.getImage());
|
||||||
}
|
}
|
||||||
|
@ -120,6 +109,8 @@ public class ComputeTaskUtils {
|
||||||
templateBuilder.osFamily(OsFamily.valueOf(nodeElement.getOs()));
|
templateBuilder.osFamily(OsFamily.valueOf(nodeElement.getOs()));
|
||||||
}
|
}
|
||||||
addSizeFromElementToTemplate(nodeElement, templateBuilder);
|
addSizeFromElementToTemplate(nodeElement, templateBuilder);
|
||||||
|
templateBuilder.options(getNodeOptionsFromElement(nodeElement));
|
||||||
|
|
||||||
return templateBuilder.build();
|
return templateBuilder.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -136,15 +127,15 @@ public class ComputeTaskUtils {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static RunNodeOptions getNodeOptionsFromElement(NodeElement nodeElement) {
|
static TemplateOptions getNodeOptionsFromElement(NodeElement nodeElement) {
|
||||||
RunNodeOptions options = new RunNodeOptions()
|
TemplateOptions options = new TemplateOptions()
|
||||||
.openPorts(getPortsToOpenFromElement(nodeElement));
|
.inboundPorts(getPortsToOpenFromElement(nodeElement));
|
||||||
addRunScriptToOptionsIfPresentInNodeElement(nodeElement, options);
|
addRunScriptToOptionsIfPresentInNodeElement(nodeElement, options);
|
||||||
return options;
|
return options;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void addRunScriptToOptionsIfPresentInNodeElement(NodeElement nodeElement,
|
static void addRunScriptToOptionsIfPresentInNodeElement(NodeElement nodeElement,
|
||||||
RunNodeOptions options) {
|
TemplateOptions options) {
|
||||||
if (nodeElement.getRunscript() != null)
|
if (nodeElement.getRunscript() != null)
|
||||||
try {
|
try {
|
||||||
options.runScript(Files.toByteArray(nodeElement.getRunscript()));
|
options.runScript(Files.toByteArray(nodeElement.getRunscript()));
|
||||||
|
@ -153,9 +144,9 @@ public class ComputeTaskUtils {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static String ipOrEmptyString(SortedSet<InetAddress> set) {
|
static String ipOrEmptyString(Set<InetAddress> set) {
|
||||||
if (set.size() > 0) {
|
if (set.size() > 0) {
|
||||||
return set.last().getHostAddress();
|
return Iterables.get(set, 0).getHostAddress();
|
||||||
} else {
|
} else {
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,10 +25,11 @@ import java.io.File;
|
||||||
* @author Ivan Meredith
|
* @author Ivan Meredith
|
||||||
*/
|
*/
|
||||||
public class NodeElement {
|
public class NodeElement {
|
||||||
private String name;
|
private String tag;
|
||||||
private String size;
|
private String size;
|
||||||
private String os;
|
private String os;
|
||||||
private String image;
|
private String image;
|
||||||
|
private int count = 1;
|
||||||
private String openports = "22";
|
private String openports = "22";
|
||||||
private String passwordproperty;
|
private String passwordproperty;
|
||||||
private String keyfile;
|
private String keyfile;
|
||||||
|
@ -46,14 +47,6 @@ public class NodeElement {
|
||||||
this.location = location;
|
this.location = location;
|
||||||
}
|
}
|
||||||
|
|
||||||
String getName() {
|
|
||||||
return name;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setName(String name) {
|
|
||||||
this.name = name;
|
|
||||||
}
|
|
||||||
|
|
||||||
String getUsernameproperty() {
|
String getUsernameproperty() {
|
||||||
return usernameproperty;
|
return usernameproperty;
|
||||||
}
|
}
|
||||||
|
@ -153,4 +146,20 @@ public class NodeElement {
|
||||||
return image;
|
return image;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setCount(int count) {
|
||||||
|
this.count = count;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getCount() {
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTag(String tag) {
|
||||||
|
this.tag = tag;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getTag() {
|
||||||
|
return tag;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,33 +21,39 @@ package org.jclouds.vcloud.compute;
|
||||||
import static com.google.common.base.Preconditions.checkArgument;
|
import static com.google.common.base.Preconditions.checkArgument;
|
||||||
import static com.google.common.base.Preconditions.checkNotNull;
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
import static com.google.common.base.Preconditions.checkState;
|
import static com.google.common.base.Preconditions.checkState;
|
||||||
|
import static org.jclouds.compute.util.ComputeUtils.METADATA_TO_ID;
|
||||||
|
import static org.jclouds.concurrent.ConcurrentUtils.awaitCompletion;
|
||||||
|
import static org.jclouds.concurrent.ConcurrentUtils.makeListenable;
|
||||||
import static org.jclouds.vcloud.options.InstantiateVAppTemplateOptions.Builder.processorCount;
|
import static org.jclouds.vcloud.options.InstantiateVAppTemplateOptions.Builder.processorCount;
|
||||||
|
|
||||||
import java.net.InetAddress;
|
import java.net.InetAddress;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import java.util.concurrent.Callable;
|
||||||
|
import java.util.concurrent.ExecutorService;
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
import javax.inject.Named;
|
import javax.inject.Named;
|
||||||
import javax.inject.Provider;
|
import javax.inject.Provider;
|
||||||
import javax.inject.Singleton;
|
import javax.inject.Singleton;
|
||||||
|
|
||||||
|
import org.jclouds.Constants;
|
||||||
import org.jclouds.compute.ComputeService;
|
import org.jclouds.compute.ComputeService;
|
||||||
import org.jclouds.compute.domain.ComputeMetadata;
|
import org.jclouds.compute.domain.ComputeMetadata;
|
||||||
import org.jclouds.compute.domain.ComputeType;
|
import org.jclouds.compute.domain.ComputeType;
|
||||||
import org.jclouds.compute.domain.CreateNodeResponse;
|
|
||||||
import org.jclouds.compute.domain.Image;
|
import org.jclouds.compute.domain.Image;
|
||||||
import org.jclouds.compute.domain.NodeMetadata;
|
import org.jclouds.compute.domain.NodeMetadata;
|
||||||
|
import org.jclouds.compute.domain.NodeSet;
|
||||||
import org.jclouds.compute.domain.NodeState;
|
import org.jclouds.compute.domain.NodeState;
|
||||||
import org.jclouds.compute.domain.Size;
|
import org.jclouds.compute.domain.Size;
|
||||||
import org.jclouds.compute.domain.Template;
|
import org.jclouds.compute.domain.Template;
|
||||||
import org.jclouds.compute.domain.TemplateBuilder;
|
import org.jclouds.compute.domain.TemplateBuilder;
|
||||||
import org.jclouds.compute.domain.internal.CreateNodeResponseImpl;
|
|
||||||
import org.jclouds.compute.domain.internal.NodeMetadataImpl;
|
import org.jclouds.compute.domain.internal.NodeMetadataImpl;
|
||||||
import org.jclouds.compute.options.RunNodeOptions;
|
import org.jclouds.compute.domain.internal.NodeSetImpl;
|
||||||
import org.jclouds.compute.reference.ComputeServiceConstants;
|
import org.jclouds.compute.reference.ComputeServiceConstants;
|
||||||
import org.jclouds.compute.util.ComputeUtils;
|
import org.jclouds.compute.util.ComputeUtils;
|
||||||
import org.jclouds.domain.Credentials;
|
import org.jclouds.domain.Credentials;
|
||||||
|
import org.jclouds.domain.Location;
|
||||||
import org.jclouds.logging.Logger;
|
import org.jclouds.logging.Logger;
|
||||||
import org.jclouds.vcloud.VCloudClient;
|
import org.jclouds.vcloud.VCloudClient;
|
||||||
import org.jclouds.vcloud.VCloudMediaType;
|
import org.jclouds.vcloud.VCloudMediaType;
|
||||||
|
@ -57,11 +63,14 @@ import org.jclouds.vcloud.domain.VApp;
|
||||||
import org.jclouds.vcloud.domain.VAppStatus;
|
import org.jclouds.vcloud.domain.VAppStatus;
|
||||||
import org.jclouds.vcloud.options.InstantiateVAppTemplateOptions;
|
import org.jclouds.vcloud.options.InstantiateVAppTemplateOptions;
|
||||||
|
|
||||||
|
import com.google.common.base.Function;
|
||||||
import com.google.common.base.Predicate;
|
import com.google.common.base.Predicate;
|
||||||
import com.google.common.collect.ImmutableMap;
|
import com.google.common.collect.ImmutableMap;
|
||||||
import com.google.common.collect.ImmutableSet;
|
import com.google.common.collect.ImmutableSet;
|
||||||
|
import com.google.common.collect.Iterables;
|
||||||
import com.google.common.collect.Maps;
|
import com.google.common.collect.Maps;
|
||||||
import com.google.common.collect.Sets;
|
import com.google.common.collect.Sets;
|
||||||
|
import com.google.common.util.concurrent.ListenableFuture;
|
||||||
import com.google.inject.Inject;
|
import com.google.inject.Inject;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -69,16 +78,33 @@ import com.google.inject.Inject;
|
||||||
*/
|
*/
|
||||||
@Singleton
|
@Singleton
|
||||||
public class VCloudComputeService implements ComputeService, VCloudComputeClient {
|
public class VCloudComputeService implements ComputeService, VCloudComputeClient {
|
||||||
|
|
||||||
|
private static class NodeMatchesTag implements Predicate<NodeMetadata> {
|
||||||
|
private final String tag;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean apply(NodeMetadata from) {
|
||||||
|
return from.getTag().equals(tag);
|
||||||
|
}
|
||||||
|
|
||||||
|
public NodeMatchesTag(String tag) {
|
||||||
|
super();
|
||||||
|
this.tag = tag;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
@Named(ComputeServiceConstants.COMPUTE_LOGGER)
|
@Named(ComputeServiceConstants.COMPUTE_LOGGER)
|
||||||
protected Logger logger = Logger.NULL;
|
protected Logger logger = Logger.NULL;
|
||||||
private final VCloudClient client;
|
private final VCloudClient client;
|
||||||
protected final Provider<Set<? extends Image>> images;
|
protected final Provider<Map<String, ? extends Image>> images;
|
||||||
protected final Provider<Set<? extends Size>> sizes;
|
protected final Provider<Map<String, ? extends Size>> sizes;
|
||||||
|
protected final Provider<Map<String, ? extends Location>> locations;
|
||||||
protected final Provider<TemplateBuilder> templateBuilderProvider;
|
protected final Provider<TemplateBuilder> templateBuilderProvider;
|
||||||
protected final ComputeUtils utils;
|
protected final ComputeUtils utils;
|
||||||
protected final Predicate<String> taskTester;
|
protected final Predicate<String> taskTester;
|
||||||
protected final Predicate<VApp> notFoundTester;
|
protected final Predicate<VApp> notFoundTester;
|
||||||
|
protected final ExecutorService executor;
|
||||||
|
|
||||||
protected static final Map<VAppStatus, NodeState> vAppStatusToNodeState = ImmutableMap
|
protected static final Map<VAppStatus, NodeState> vAppStatusToNodeState = ImmutableMap
|
||||||
.<VAppStatus, NodeState> builder().put(VAppStatus.OFF, NodeState.TERMINATED).put(
|
.<VAppStatus, NodeState> builder().put(VAppStatus.OFF, NodeState.TERMINATED).put(
|
||||||
|
@ -89,65 +115,92 @@ public class VCloudComputeService implements ComputeService, VCloudComputeClient
|
||||||
@Inject
|
@Inject
|
||||||
public VCloudComputeService(VCloudClient client,
|
public VCloudComputeService(VCloudClient client,
|
||||||
Provider<TemplateBuilder> templateBuilderProvider,
|
Provider<TemplateBuilder> templateBuilderProvider,
|
||||||
Provider<Set<? extends Image>> images, Provider<Set<? extends Size>> sizes,
|
Provider<Map<String, ? extends Image>> images,
|
||||||
ComputeUtils utils, Predicate<String> successTester,
|
Provider<Map<String, ? extends Size>> sizes,
|
||||||
@Named("NOT_FOUND") Predicate<VApp> notFoundTester) {
|
Provider<Map<String, ? extends Location>> locations, ComputeUtils utils,
|
||||||
|
Predicate<String> successTester, @Named("NOT_FOUND") Predicate<VApp> notFoundTester,
|
||||||
|
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService executor) {
|
||||||
this.taskTester = successTester;
|
this.taskTester = successTester;
|
||||||
this.client = client;
|
this.client = client;
|
||||||
this.images = images;
|
this.images = images;
|
||||||
this.sizes = sizes;
|
this.sizes = sizes;
|
||||||
|
this.locations = locations;
|
||||||
this.templateBuilderProvider = templateBuilderProvider;
|
this.templateBuilderProvider = templateBuilderProvider;
|
||||||
this.utils = utils;
|
this.utils = utils;
|
||||||
this.notFoundTester = notFoundTester;
|
this.notFoundTester = notFoundTester;
|
||||||
|
this.executor = executor;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CreateNodeResponse runNode(String name, Template template) {
|
public NodeSet runNodes(final String tag, int max, final Template template) {
|
||||||
return this.runNode(name, template, RunNodeOptions.NONE);
|
checkArgument(tag.indexOf('-') == -1, "tag cannot contain hyphens");
|
||||||
|
checkNotNull(template.getLocation(), "location");
|
||||||
|
// TODO: find next id
|
||||||
|
final Set<NodeMetadata> nodes = Sets.newHashSet();
|
||||||
|
Set<ListenableFuture<Void>> responses = Sets.newHashSet();
|
||||||
|
for (int i = 0; i < max; i++) {
|
||||||
|
final String name = String.format("%s-%d", tag, i + 1);
|
||||||
|
responses.add(makeListenable(executor.submit(new Callable<Void>() {
|
||||||
|
@Override
|
||||||
|
public Void call() throws Exception {
|
||||||
|
runVAppAndAddToSet(name, tag, template, nodes);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}), executor));
|
||||||
|
}
|
||||||
|
awaitCompletion(responses, executor, null, logger, "nodes");
|
||||||
|
return new NodeSetImpl(nodes);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
private void runVAppAndAddToSet(String name, String tag, Template template,
|
||||||
public CreateNodeResponse runNode(String name, Template template, RunNodeOptions options) {
|
Set<NodeMetadata> nodes) {
|
||||||
checkNotNull(template.getImage().getLocation(), "location");
|
Map<String, String> metaMap = start(template.getLocation().getId(), name, template.getImage()
|
||||||
Map<String, String> metaMap = start(template.getImage().getLocation(), name, template
|
.getId(), template.getSize().getCores(), template.getSize().getRam(), template
|
||||||
.getImage().getId(), template.getSize().getCores(), template.getSize().getRam(),
|
.getSize().getDisk() * 1024 * 1024l, ImmutableMap.<String, String> of(), template
|
||||||
template.getSize().getDisk() * 1024 * 1024l, ImmutableMap.<String, String> of(),
|
.getOptions().getInboundPorts());
|
||||||
options.getOpenPorts());
|
|
||||||
VApp vApp = client.getVApp(metaMap.get("id"));
|
VApp vApp = client.getVApp(metaMap.get("id"));
|
||||||
CreateNodeResponse node = newCreateNodeResponse(template, metaMap, vApp);
|
NodeMetadata node = newCreateNodeResponse(tag, template, metaMap, vApp);
|
||||||
if (options.getRunScript() != null) {
|
nodes.add(node);
|
||||||
utils.runScriptOnNode(node, options.getRunScript());
|
if (template.getOptions().getRunScript() != null) {
|
||||||
|
utils.runScriptOnNode(node, template.getOptions().getRunScript());
|
||||||
}
|
}
|
||||||
return node;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected CreateNodeResponse newCreateNodeResponse(Template template,
|
protected NodeMetadata newCreateNodeResponse(String tag, Template template,
|
||||||
Map<String, String> metaMap, VApp vApp) {
|
Map<String, String> metaMap, VApp vApp) {
|
||||||
return new CreateNodeResponseImpl(vApp.getId(), vApp.getName(), template.getImage()
|
return new NodeMetadataImpl(vApp.getId(), vApp.getName(), template.getLocation().getId(),
|
||||||
.getLocation(), vApp.getLocation(), ImmutableMap.<String, String> of(),
|
vApp.getLocation(), ImmutableMap.<String, String> of(), tag, vAppStatusToNodeState
|
||||||
vAppStatusToNodeState.get(vApp.getStatus()), getPublicAddresses(vApp.getId()),
|
.get(vApp.getStatus()), getPublicAddresses(vApp.getId()),
|
||||||
getPrivateAddresses(vApp.getId()), new Credentials(metaMap.get("username"), metaMap
|
getPrivateAddresses(vApp.getId()), ImmutableMap.<String, String> of(),
|
||||||
.get("password")), ImmutableMap.<String, String> of());
|
new Credentials(metaMap.get("username"), metaMap.get("password")));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public NodeMetadata getNodeMetadata(ComputeMetadata node) {
|
public NodeMetadata getNodeMetadata(ComputeMetadata node) {
|
||||||
checkArgument(node.getType() == ComputeType.NODE, "this is only valid for nodes, not "
|
checkArgument(node.getType() == ComputeType.NODE, "this is only valid for nodes, not "
|
||||||
+ node.getType());
|
+ node.getType());
|
||||||
return getNodeMetadataByIdInVDC(checkNotNull(node.getLocation(), "location"), checkNotNull(
|
return getNodeMetadataByIdInVDC(checkNotNull(node.getLocationId(), "location"), checkNotNull(
|
||||||
node.getId(), "node.id"));
|
node.getId(), "node.id"));
|
||||||
}
|
}
|
||||||
|
|
||||||
protected NodeMetadata getNodeMetadataByIdInVDC(String vDCId, String id) {
|
protected NodeMetadata getNodeMetadataByIdInVDC(String vDCId, String id) {
|
||||||
VApp vApp = client.getVApp(id);
|
VApp vApp = client.getVApp(id);
|
||||||
|
String tag = vApp.getName().replaceAll("-[0-9]+", "");
|
||||||
return new NodeMetadataImpl(vApp.getId(), vApp.getName(), vDCId, vApp.getLocation(),
|
return new NodeMetadataImpl(vApp.getId(), vApp.getName(), vDCId, vApp.getLocation(),
|
||||||
ImmutableMap.<String, String> of(), vAppStatusToNodeState.get(vApp.getStatus()),
|
ImmutableMap.<String, String> of(), tag,
|
||||||
vApp.getNetworkToAddresses().values(), ImmutableSet.<InetAddress> of(), ImmutableMap
|
vAppStatusToNodeState.get(vApp.getStatus()), vApp.getNetworkToAddresses().values(),
|
||||||
.<String, String> of());
|
ImmutableSet.<InetAddress> of(), ImmutableMap.<String, String> of(), null);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Set<ComputeMetadata> listNodes() {
|
public Map<String, ? extends ComputeMetadata> getNodes() {
|
||||||
|
logger.debug(">> listing vApps");
|
||||||
|
Map<String, ? extends ComputeMetadata> nodes = doGetNodes();
|
||||||
|
logger.debug("<< list(%d)", nodes.size());
|
||||||
|
return nodes;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Map<String, ? extends ComputeMetadata> doGetNodes() {
|
||||||
Set<ComputeMetadata> nodes = Sets.newHashSet();
|
Set<ComputeMetadata> nodes = Sets.newHashSet();
|
||||||
for (NamedResource vdc : client.getDefaultOrganization().getVDCs().values()) {
|
for (NamedResource vdc : client.getDefaultOrganization().getVDCs().values()) {
|
||||||
for (NamedResource resource : client.getVDC(vdc.getId()).getResourceEntities().values()) {
|
for (NamedResource resource : client.getVDC(vdc.getId()).getResourceEntities().values()) {
|
||||||
|
@ -156,7 +209,7 @@ public class VCloudComputeService implements ComputeService, VCloudComputeClient
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nodes;
|
return Maps.uniqueIndex(nodes, METADATA_TO_ID);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -172,12 +225,12 @@ public class VCloudComputeService implements ComputeService, VCloudComputeClient
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Set<? extends Size> listSizes() {
|
public Map<String, ? extends Size> getSizes() {
|
||||||
return sizes.get();
|
return sizes.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Set<? extends Image> listImages() {
|
public Map<String, ? extends Image> getImages() {
|
||||||
return images.get();
|
return images.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -300,4 +353,53 @@ public class VCloudComputeService implements ComputeService, VCloudComputeClient
|
||||||
return Sets.newHashSet(vApp.getNetworkToAddresses().values());
|
return Sets.newHashSet(vApp.getNetworkToAddresses().values());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void destroyNodes(String tag) { // TODO parallel
|
||||||
|
logger.debug(">> terminating servers by tag(%s)", tag);
|
||||||
|
Set<ListenableFuture<Void>> responses = Sets.newHashSet();
|
||||||
|
for (final NodeMetadata node : doGetNodes(tag)) {
|
||||||
|
responses.add(makeListenable(executor.submit(new Callable<Void>() {
|
||||||
|
@Override
|
||||||
|
public Void call() throws Exception {
|
||||||
|
destroyNode(node);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}), executor));
|
||||||
|
}
|
||||||
|
awaitCompletion(responses, executor, null, logger, "nodes");
|
||||||
|
logger.debug("<< destroyed");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Map<String, ? extends Location> getLocations() {
|
||||||
|
return locations.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public NodeSet getNodes(String tag) {
|
||||||
|
logger.debug(">> listing servers by tag(%s)", tag);
|
||||||
|
NodeSet nodes = doGetNodes(tag);
|
||||||
|
logger.debug("<< list(%d)", nodes.size());
|
||||||
|
return nodes;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected NodeSet doGetNodes(final String tag) {
|
||||||
|
Iterable<NodeMetadata> nodes = Iterables.filter(Iterables.transform(doGetNodes().values(),
|
||||||
|
new Function<ComputeMetadata, NodeMetadata>() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public NodeMetadata apply(ComputeMetadata from) {
|
||||||
|
return getNodeMetadata(from);
|
||||||
|
}
|
||||||
|
|
||||||
|
}), new Predicate<NodeMetadata>() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean apply(NodeMetadata input) {
|
||||||
|
return tag.equals(input.getTag());
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
return new NodeSetImpl(Iterables.filter(nodes, new NodeMatchesTag(tag)));
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -18,6 +18,7 @@
|
||||||
*/
|
*/
|
||||||
package org.jclouds.vcloud.compute.config;
|
package org.jclouds.vcloud.compute.config;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.concurrent.Callable;
|
import java.util.concurrent.Callable;
|
||||||
import java.util.concurrent.ExecutionException;
|
import java.util.concurrent.ExecutionException;
|
||||||
|
@ -32,6 +33,7 @@ import org.jclouds.Constants;
|
||||||
import org.jclouds.compute.ComputeService;
|
import org.jclouds.compute.ComputeService;
|
||||||
import org.jclouds.compute.ComputeServiceContext;
|
import org.jclouds.compute.ComputeServiceContext;
|
||||||
import org.jclouds.compute.domain.Architecture;
|
import org.jclouds.compute.domain.Architecture;
|
||||||
|
import org.jclouds.compute.domain.ComputeMetadata;
|
||||||
import org.jclouds.compute.domain.Image;
|
import org.jclouds.compute.domain.Image;
|
||||||
import org.jclouds.compute.domain.OsFamily;
|
import org.jclouds.compute.domain.OsFamily;
|
||||||
import org.jclouds.compute.domain.Size;
|
import org.jclouds.compute.domain.Size;
|
||||||
|
@ -40,7 +42,9 @@ import org.jclouds.compute.domain.internal.SizeImpl;
|
||||||
import org.jclouds.compute.internal.ComputeServiceContextImpl;
|
import org.jclouds.compute.internal.ComputeServiceContextImpl;
|
||||||
import org.jclouds.compute.reference.ComputeServiceConstants;
|
import org.jclouds.compute.reference.ComputeServiceConstants;
|
||||||
import org.jclouds.concurrent.ConcurrentUtils;
|
import org.jclouds.concurrent.ConcurrentUtils;
|
||||||
import org.jclouds.domain.ResourceLocation;
|
import org.jclouds.domain.Location;
|
||||||
|
import org.jclouds.domain.LocationScope;
|
||||||
|
import org.jclouds.domain.internal.LocationImpl;
|
||||||
import org.jclouds.logging.Logger;
|
import org.jclouds.logging.Logger;
|
||||||
import org.jclouds.rest.RestContext;
|
import org.jclouds.rest.RestContext;
|
||||||
import org.jclouds.vcloud.VCloudAsyncClient;
|
import org.jclouds.vcloud.VCloudAsyncClient;
|
||||||
|
@ -53,8 +57,13 @@ import org.jclouds.vcloud.domain.Catalog;
|
||||||
import org.jclouds.vcloud.domain.CatalogItem;
|
import org.jclouds.vcloud.domain.CatalogItem;
|
||||||
import org.jclouds.vcloud.domain.NamedResource;
|
import org.jclouds.vcloud.domain.NamedResource;
|
||||||
import org.jclouds.vcloud.domain.VAppTemplate;
|
import org.jclouds.vcloud.domain.VAppTemplate;
|
||||||
|
import org.jclouds.vcloud.domain.VDC;
|
||||||
|
|
||||||
|
import com.google.common.base.Function;
|
||||||
|
import com.google.common.collect.ImmutableMap;
|
||||||
import com.google.common.collect.ImmutableSet;
|
import com.google.common.collect.ImmutableSet;
|
||||||
|
import com.google.common.collect.Iterables;
|
||||||
|
import com.google.common.collect.Maps;
|
||||||
import com.google.common.collect.Sets;
|
import com.google.common.collect.Sets;
|
||||||
import com.google.common.util.concurrent.ListenableFuture;
|
import com.google.common.util.concurrent.ListenableFuture;
|
||||||
import com.google.inject.Injector;
|
import com.google.inject.Injector;
|
||||||
|
@ -91,13 +100,6 @@ public class VCloudComputeServiceContextModule extends VCloudContextModule {
|
||||||
return new ComputeServiceContextImpl<VCloudAsyncClient, VCloudClient>(computeService, context);
|
return new ComputeServiceContextImpl<VCloudAsyncClient, VCloudClient>(computeService, context);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Provides
|
|
||||||
@Singleton
|
|
||||||
@ResourceLocation
|
|
||||||
String getVDC(VCloudClient client) {
|
|
||||||
return client.getDefaultVDC().getId();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected static class LogHolder {
|
protected static class LogHolder {
|
||||||
@Resource
|
@Resource
|
||||||
@Named(ComputeServiceConstants.COMPUTE_LOGGER)
|
@Named(ComputeServiceConstants.COMPUTE_LOGGER)
|
||||||
|
@ -106,10 +108,12 @@ public class VCloudComputeServiceContextModule extends VCloudContextModule {
|
||||||
|
|
||||||
@Provides
|
@Provides
|
||||||
@Singleton
|
@Singleton
|
||||||
protected Set<? extends Image> provideImages(final VCloudClient client,
|
protected Map<String, ? extends Image> provideImages(final VCloudClient client,
|
||||||
final @ResourceLocation String vDC, LogHolder holder,
|
final Location vDC, LogHolder holder,
|
||||||
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService executor)
|
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService executor,
|
||||||
throws InterruptedException, ExecutionException, TimeoutException {
|
Function<ComputeMetadata, String> indexer) throws InterruptedException,
|
||||||
|
ExecutionException, TimeoutException {
|
||||||
|
// TODO multi-VDC
|
||||||
final Set<Image> images = Sets.newHashSet();
|
final Set<Image> images = Sets.newHashSet();
|
||||||
holder.logger.debug(">> providing images");
|
holder.logger.debug(">> providing images");
|
||||||
Catalog response = client.getDefaultCatalog();
|
Catalog response = client.getDefaultCatalog();
|
||||||
|
@ -132,8 +136,9 @@ public class VCloudComputeServiceContextModule extends VCloudContextModule {
|
||||||
Architecture arch = resource.getName().indexOf("64") == -1 ? Architecture.X86_32
|
Architecture arch = resource.getName().indexOf("64") == -1 ? Architecture.X86_32
|
||||||
: Architecture.X86_64;
|
: Architecture.X86_64;
|
||||||
VAppTemplate template = client.getVAppTemplate(item.getEntity().getId());
|
VAppTemplate template = client.getVAppTemplate(item.getEntity().getId());
|
||||||
images.add(new ImageImpl(resource.getId(), template.getName(), "", myOs,
|
images.add(new ImageImpl(resource.getId(), template.getName(), vDC.getId(),
|
||||||
template.getName(), vDC, arch));
|
template.getLocation(), ImmutableMap.<String, String> of(), template
|
||||||
|
.getDescription(), "", myOs, template.getName(), arch));
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}), executor));
|
}), executor));
|
||||||
|
@ -142,21 +147,60 @@ public class VCloudComputeServiceContextModule extends VCloudContextModule {
|
||||||
}
|
}
|
||||||
|
|
||||||
ConcurrentUtils.awaitCompletion(responses, executor, null, holder.logger, "images");
|
ConcurrentUtils.awaitCompletion(responses, executor, null, holder.logger, "images");
|
||||||
return images;
|
return Maps.uniqueIndex(images, indexer);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Provides
|
@Provides
|
||||||
@Singleton
|
@Singleton
|
||||||
protected Set<? extends Size> provideSizes(VCloudClient client, Set<? extends Image> images,
|
protected Function<ComputeMetadata, String> indexer() {
|
||||||
LogHolder holder, @Named(Constants.PROPERTY_USER_THREADS) ExecutorService executor)
|
return new Function<ComputeMetadata, String>() {
|
||||||
|
@Override
|
||||||
|
public String apply(ComputeMetadata from) {
|
||||||
|
return from.getId();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
@Provides
|
||||||
|
@Singleton
|
||||||
|
Map<String, ? extends Location> provideLocations(final VCloudClient client) {
|
||||||
|
return Maps.uniqueIndex(Iterables.transform(client.getDefaultOrganization().getVDCs()
|
||||||
|
.values(), new Function<NamedResource, Location>() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Location apply(NamedResource from) {
|
||||||
|
VDC vdc = client.getVDC(from.getId());
|
||||||
|
return new LocationImpl(LocationScope.ZONE, vdc.getId(), vdc.getName(), null, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
}), new Function<Location, String>() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String apply(Location from) {
|
||||||
|
return from.getId();
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Provides
|
||||||
|
@Singleton
|
||||||
|
Location getVDC(VCloudClient client, Map<String, ? extends Location> locations) {
|
||||||
|
return locations.get(client.getDefaultVDC().getId());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Provides
|
||||||
|
@Singleton
|
||||||
|
protected Map<String, ? extends Size> provideSizes(Function<ComputeMetadata, String> indexer,
|
||||||
|
VCloudClient client, Map<String, ? extends Image> images, LogHolder holder,
|
||||||
|
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService executor)
|
||||||
throws InterruptedException, TimeoutException, ExecutionException {
|
throws InterruptedException, TimeoutException, ExecutionException {
|
||||||
Set<Size> sizes = Sets.newHashSet();
|
Set<Size> sizes = Sets.newHashSet();
|
||||||
for (int cpus : new int[] { 1, 2, 4 })
|
for (int cpus : new int[] { 1, 2, 4 })
|
||||||
for (int ram : new int[] { 512, 1024, 2048, 4096, 8192, 16384 })
|
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,
|
sizes.add(new SizeImpl(String.format("cpu=%d,ram=%s,disk=%d", cpus, ram, 10), null,
|
||||||
ram, 10, ImmutableSet.<Architecture> of(Architecture.X86_32,
|
null, null, ImmutableMap.<String, String> of(), cpus, ram, 10, ImmutableSet
|
||||||
Architecture.X86_64)));
|
.<Architecture> of(Architecture.X86_32, Architecture.X86_64)));
|
||||||
return sizes;
|
return Maps.uniqueIndex(sizes, indexer);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,12 +29,12 @@ import static org.testng.Assert.assertNotNull;
|
||||||
import java.io.UnsupportedEncodingException;
|
import java.io.UnsupportedEncodingException;
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Properties;
|
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
import javax.inject.Named;
|
import javax.inject.Named;
|
||||||
import javax.inject.Singleton;
|
import javax.inject.Singleton;
|
||||||
|
|
||||||
|
import org.jclouds.PropertiesBuilder;
|
||||||
import org.jclouds.concurrent.config.ExecutorServiceModule;
|
import org.jclouds.concurrent.config.ExecutorServiceModule;
|
||||||
import org.jclouds.encryption.EncryptionService;
|
import org.jclouds.encryption.EncryptionService;
|
||||||
import org.jclouds.http.RequiresHttp;
|
import org.jclouds.http.RequiresHttp;
|
||||||
|
@ -139,7 +139,18 @@ public class VCloudLoginLiveTest {
|
||||||
context = new RestContextBuilder<VCloudLoginAsyncClient, VCloudLoginAsyncClient>(
|
context = new RestContextBuilder<VCloudLoginAsyncClient, VCloudLoginAsyncClient>(
|
||||||
new TypeLiteral<VCloudLoginAsyncClient>() {
|
new TypeLiteral<VCloudLoginAsyncClient>() {
|
||||||
}, new TypeLiteral<VCloudLoginAsyncClient>() {
|
}, new TypeLiteral<VCloudLoginAsyncClient>() {
|
||||||
}, new Properties()) {
|
}, new PropertiesBuilder() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PropertiesBuilder withCredentials(String account, String key) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PropertiesBuilder withEndpoint(URI endpoint) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}.build()) {
|
||||||
|
|
||||||
public void addContextModule(List<Module> modules) {
|
public void addContextModule(List<Module> modules) {
|
||||||
|
|
||||||
|
|
|
@ -3,17 +3,19 @@ package org.jclouds.vcloud.hostingdotcom.compute;
|
||||||
import static com.google.common.base.Preconditions.checkState;
|
import static com.google.common.base.Preconditions.checkState;
|
||||||
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.concurrent.ExecutorService;
|
||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
import javax.inject.Named;
|
import javax.inject.Named;
|
||||||
import javax.inject.Provider;
|
import javax.inject.Provider;
|
||||||
import javax.inject.Singleton;
|
import javax.inject.Singleton;
|
||||||
|
|
||||||
|
import org.jclouds.Constants;
|
||||||
import org.jclouds.compute.domain.Image;
|
import org.jclouds.compute.domain.Image;
|
||||||
import org.jclouds.compute.domain.Size;
|
import org.jclouds.compute.domain.Size;
|
||||||
import org.jclouds.compute.domain.TemplateBuilder;
|
import org.jclouds.compute.domain.TemplateBuilder;
|
||||||
import org.jclouds.compute.util.ComputeUtils;
|
import org.jclouds.compute.util.ComputeUtils;
|
||||||
|
import org.jclouds.domain.Location;
|
||||||
import org.jclouds.vcloud.VCloudClient;
|
import org.jclouds.vcloud.VCloudClient;
|
||||||
import org.jclouds.vcloud.compute.VCloudComputeService;
|
import org.jclouds.vcloud.compute.VCloudComputeService;
|
||||||
import org.jclouds.vcloud.domain.VApp;
|
import org.jclouds.vcloud.domain.VApp;
|
||||||
|
@ -29,12 +31,15 @@ import com.google.common.collect.ImmutableMap;
|
||||||
public class HostingDotComVCloudComputeService extends VCloudComputeService {
|
public class HostingDotComVCloudComputeService extends VCloudComputeService {
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
HostingDotComVCloudComputeService(VCloudClient client,
|
public HostingDotComVCloudComputeService(VCloudClient client,
|
||||||
Provider<TemplateBuilder> templateBuilderProvider,
|
Provider<TemplateBuilder> templateBuilderProvider,
|
||||||
Provider<Set<? extends Image>> images, Provider<Set<? extends Size>> sizes,
|
Provider<Map<String, ? extends Image>> images,
|
||||||
Predicate<String> successTester, ComputeUtils utils,
|
Provider<Map<String, ? extends Size>> sizes,
|
||||||
@Named("NOT_FOUND") Predicate<VApp> notFoundTester) {
|
Provider<Map<String, ? extends Location>> locations, ComputeUtils utils,
|
||||||
super(client, templateBuilderProvider, images, sizes, utils, successTester, notFoundTester);
|
Predicate<String> successTester, @Named("NOT_FOUND") Predicate<VApp> notFoundTester,
|
||||||
|
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService executor) {
|
||||||
|
super(client, templateBuilderProvider, images, sizes, locations, utils, successTester,
|
||||||
|
notFoundTester, executor);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -24,6 +24,7 @@ import java.net.InetAddress;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.SortedSet;
|
import java.util.SortedSet;
|
||||||
|
import java.util.concurrent.ExecutorService;
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
@ -31,6 +32,7 @@ import javax.inject.Named;
|
||||||
import javax.inject.Provider;
|
import javax.inject.Provider;
|
||||||
import javax.inject.Singleton;
|
import javax.inject.Singleton;
|
||||||
|
|
||||||
|
import org.jclouds.Constants;
|
||||||
import org.jclouds.compute.domain.Image;
|
import org.jclouds.compute.domain.Image;
|
||||||
import org.jclouds.compute.domain.NodeMetadata;
|
import org.jclouds.compute.domain.NodeMetadata;
|
||||||
import org.jclouds.compute.domain.Size;
|
import org.jclouds.compute.domain.Size;
|
||||||
|
@ -38,6 +40,7 @@ import org.jclouds.compute.domain.TemplateBuilder;
|
||||||
import org.jclouds.compute.domain.internal.NodeMetadataImpl;
|
import org.jclouds.compute.domain.internal.NodeMetadataImpl;
|
||||||
import org.jclouds.compute.reference.ComputeServiceConstants;
|
import org.jclouds.compute.reference.ComputeServiceConstants;
|
||||||
import org.jclouds.compute.util.ComputeUtils;
|
import org.jclouds.compute.util.ComputeUtils;
|
||||||
|
import org.jclouds.domain.Location;
|
||||||
import org.jclouds.logging.Logger;
|
import org.jclouds.logging.Logger;
|
||||||
import org.jclouds.vcloud.compute.VCloudComputeService;
|
import org.jclouds.vcloud.compute.VCloudComputeService;
|
||||||
import org.jclouds.vcloud.domain.VApp;
|
import org.jclouds.vcloud.domain.VApp;
|
||||||
|
@ -65,10 +68,13 @@ public class TerremarkVCloudComputeService extends VCloudComputeService {
|
||||||
@Inject
|
@Inject
|
||||||
public TerremarkVCloudComputeService(TerremarkVCloudClient client,
|
public TerremarkVCloudComputeService(TerremarkVCloudClient client,
|
||||||
Provider<TemplateBuilder> templateBuilderProvider,
|
Provider<TemplateBuilder> templateBuilderProvider,
|
||||||
Provider<Set<? extends Image>> images, Provider<Set<? extends Size>> sizes,
|
Provider<Map<String, ? extends Image>> images,
|
||||||
ComputeUtils utils, Predicate<String> successTester,
|
Provider<Map<String, ? extends Size>> sizes,
|
||||||
@Named("NOT_FOUND") Predicate<VApp> notFoundTester) {
|
Provider<Map<String, ? extends Location>> locations, ComputeUtils utils,
|
||||||
super(client, templateBuilderProvider, images, sizes, utils, successTester, notFoundTester);
|
Predicate<String> successTester, @Named("NOT_FOUND") Predicate<VApp> notFoundTester,
|
||||||
|
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService executor) {
|
||||||
|
super(client, templateBuilderProvider, images, sizes, locations, utils, successTester,
|
||||||
|
notFoundTester, executor);
|
||||||
this.client = client;
|
this.client = client;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -91,10 +97,11 @@ public class TerremarkVCloudComputeService extends VCloudComputeService {
|
||||||
@Override
|
@Override
|
||||||
protected NodeMetadata getNodeMetadataByIdInVDC(String vDCId, String id) {
|
protected NodeMetadata getNodeMetadataByIdInVDC(String vDCId, String id) {
|
||||||
VApp vApp = client.getVApp(id);
|
VApp vApp = client.getVApp(id);
|
||||||
|
String tag = vApp.getName().replaceAll("-[0-9]+", "");
|
||||||
return new NodeMetadataImpl(vApp.getId(), vApp.getName(), vDCId, vApp.getLocation(),
|
return new NodeMetadataImpl(vApp.getId(), vApp.getName(), vDCId, vApp.getLocation(),
|
||||||
ImmutableMap.<String, String> of(), vAppStatusToNodeState.get(vApp.getStatus()),
|
ImmutableMap.<String, String> of(), tag,
|
||||||
getPublicAddresses(id), vApp.getNetworkToAddresses().values(), ImmutableMap
|
vAppStatusToNodeState.get(vApp.getStatus()), getPublicAddresses(id), vApp
|
||||||
.<String, String> of());
|
.getNetworkToAddresses().values(), ImmutableMap.<String, String> of(), null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public InetAddress createPublicAddressMappedToPorts(String vAppId, int... ports) {
|
public InetAddress createPublicAddressMappedToPorts(String vAppId, int... ports) {
|
||||||
|
|
|
@ -18,15 +18,18 @@
|
||||||
*/
|
*/
|
||||||
package org.jclouds.vcloud.terremark.compute.config;
|
package org.jclouds.vcloud.terremark.compute.config;
|
||||||
|
|
||||||
import java.util.Set;
|
import java.util.Map;
|
||||||
import java.util.SortedSet;
|
import java.util.SortedSet;
|
||||||
|
import java.util.concurrent.ExecutionException;
|
||||||
import java.util.concurrent.ExecutorService;
|
import java.util.concurrent.ExecutorService;
|
||||||
|
import java.util.concurrent.TimeoutException;
|
||||||
|
|
||||||
import javax.inject.Named;
|
import javax.inject.Named;
|
||||||
|
|
||||||
import org.jclouds.Constants;
|
import org.jclouds.Constants;
|
||||||
import org.jclouds.compute.ComputeService;
|
import org.jclouds.compute.ComputeService;
|
||||||
import org.jclouds.compute.domain.Architecture;
|
import org.jclouds.compute.domain.Architecture;
|
||||||
|
import org.jclouds.compute.domain.ComputeMetadata;
|
||||||
import org.jclouds.compute.domain.Image;
|
import org.jclouds.compute.domain.Image;
|
||||||
import org.jclouds.compute.domain.Size;
|
import org.jclouds.compute.domain.Size;
|
||||||
import org.jclouds.compute.domain.internal.SizeImpl;
|
import org.jclouds.compute.domain.internal.SizeImpl;
|
||||||
|
@ -37,8 +40,10 @@ import org.jclouds.vcloud.terremark.compute.TerremarkVCloudComputeService;
|
||||||
import org.jclouds.vcloud.terremark.domain.ComputeOptions;
|
import org.jclouds.vcloud.terremark.domain.ComputeOptions;
|
||||||
|
|
||||||
import com.google.common.base.Function;
|
import com.google.common.base.Function;
|
||||||
|
import com.google.common.collect.ImmutableMap;
|
||||||
import com.google.common.collect.ImmutableSet;
|
import com.google.common.collect.ImmutableSet;
|
||||||
import com.google.common.collect.Iterables;
|
import com.google.common.collect.Iterables;
|
||||||
|
import com.google.common.collect.Maps;
|
||||||
import com.google.common.collect.Sets;
|
import com.google.common.collect.Sets;
|
||||||
import com.google.inject.Injector;
|
import com.google.inject.Injector;
|
||||||
|
|
||||||
|
@ -65,21 +70,23 @@ public class TerremarkVCloudComputeServiceContextModule extends VCloudComputeSer
|
||||||
private static class ComputeOptionsToSize implements Function<ComputeOptions, Size> {
|
private static class ComputeOptionsToSize implements Function<ComputeOptions, Size> {
|
||||||
@Override
|
@Override
|
||||||
public Size apply(ComputeOptions from) {
|
public Size apply(ComputeOptions from) {
|
||||||
return new SizeImpl(from.toString(), from.getProcessorCount(), from.getMemory(), 10,
|
return new SizeImpl(from.toString(), from.toString(), null, null, ImmutableMap
|
||||||
|
.<String, String> of(), from.getProcessorCount(), from.getMemory(), 10,
|
||||||
ImmutableSet.<Architecture> of(Architecture.X86_32, Architecture.X86_64));
|
ImmutableSet.<Architecture> of(Architecture.X86_32, Architecture.X86_64));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected SortedSet<? extends Size> provideSizes(VCloudClient client,
|
protected Map<String, ? extends Size> provideSizes(Function<ComputeMetadata, String> indexer,
|
||||||
Set<? extends Image> images, LogHolder holder,
|
VCloudClient client, Map<String, ? extends Image> images, LogHolder holder,
|
||||||
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService executor) {
|
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService executor)
|
||||||
Image anyImage = Iterables.get(images, 0);
|
throws InterruptedException, TimeoutException, ExecutionException {
|
||||||
|
Image anyImage = Iterables.get(images.values(), 0);
|
||||||
holder.logger.debug(">> providing sizes");
|
holder.logger.debug(">> providing sizes");
|
||||||
SortedSet<Size> sizes = Sets.newTreeSet(Iterables.transform(TerremarkVCloudClient.class.cast(
|
SortedSet<Size> sizes = Sets.newTreeSet(Iterables.transform(TerremarkVCloudClient.class.cast(
|
||||||
client).getComputeOptionsOfCatalogItem(anyImage.getId()), sizeConverter));
|
client).getComputeOptionsOfCatalogItem(anyImage.getId()), sizeConverter));
|
||||||
holder.logger.debug("<< sizes(%d)", sizes.size());
|
holder.logger.debug("<< sizes(%d)", sizes.size());
|
||||||
return sizes;
|
return Maps.uniqueIndex(sizes, indexer);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue