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;
|
||||
|
||||
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_AWS_EXPIREINTERVAL;
|
||||
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 java.net.URI;
|
||||
|
@ -40,6 +41,7 @@ public class EC2PropertiesBuilder extends PropertiesBuilder {
|
|||
Properties properties = super.defaultProperties();
|
||||
properties.setProperty(PROPERTY_EC2_ENDPOINT, "https://ec2.us-east-1.amazonaws.com");
|
||||
properties.setProperty(PROPERTY_AWS_EXPIREINTERVAL, "60");
|
||||
properties.setProperty(PROPERTY_EC2_AMI_OWNERS, "063491364108");
|
||||
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.checkNotNull;
|
||||
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.NoSuchElementException;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.inject.Inject;
|
||||
|
@ -33,39 +34,46 @@ import javax.inject.Named;
|
|||
import javax.inject.Provider;
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import org.jclouds.aws.AWSResponseException;
|
||||
import org.jclouds.Constants;
|
||||
import org.jclouds.aws.domain.Region;
|
||||
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.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.IpProtocol;
|
||||
import org.jclouds.aws.ec2.domain.KeyPair;
|
||||
import org.jclouds.aws.ec2.domain.Reservation;
|
||||
import org.jclouds.aws.ec2.domain.RunningInstance;
|
||||
import org.jclouds.aws.ec2.options.RunInstancesOptions;
|
||||
import org.jclouds.compute.ComputeService;
|
||||
import org.jclouds.compute.domain.ComputeMetadata;
|
||||
import org.jclouds.compute.domain.ComputeType;
|
||||
import org.jclouds.compute.domain.CreateNodeResponse;
|
||||
import org.jclouds.compute.domain.Image;
|
||||
import org.jclouds.compute.domain.NodeMetadata;
|
||||
import org.jclouds.compute.domain.NodeSet;
|
||||
import org.jclouds.compute.domain.NodeState;
|
||||
import org.jclouds.compute.domain.Size;
|
||||
import org.jclouds.compute.domain.Template;
|
||||
import org.jclouds.compute.domain.TemplateBuilder;
|
||||
import org.jclouds.compute.domain.internal.ComputeMetadataImpl;
|
||||
import org.jclouds.compute.domain.internal.CreateNodeResponseImpl;
|
||||
import org.jclouds.compute.domain.internal.NodeMetadataImpl;
|
||||
import org.jclouds.compute.options.RunNodeOptions;
|
||||
import org.jclouds.compute.domain.internal.NodeSetImpl;
|
||||
import org.jclouds.compute.options.TemplateOptions;
|
||||
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 com.google.common.base.Function;
|
||||
import com.google.common.base.Joiner;
|
||||
import com.google.common.base.Predicate;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.Iterables;
|
||||
import com.google.common.collect.Maps;
|
||||
import com.google.common.collect.Sets;
|
||||
import com.google.common.util.concurrent.ListenableFuture;
|
||||
import com.google.inject.internal.ImmutableSet;
|
||||
|
||||
/**
|
||||
|
@ -73,128 +81,129 @@ import com.google.inject.internal.ImmutableSet;
|
|||
*/
|
||||
@Singleton
|
||||
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
|
||||
@Named(ComputeServiceConstants.COMPUTE_LOGGER)
|
||||
protected Logger logger = Logger.NULL;
|
||||
private final EC2Client ec2Client;
|
||||
protected final Provider<Set<? extends Image>> images;
|
||||
protected final Provider<Set<? extends Size>> sizes;
|
||||
protected final EC2Client ec2Client;
|
||||
protected final Map<RegionTag, KeyPairCredentials> credentialsMap;
|
||||
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;
|
||||
private final Predicate<RunningInstance> instanceStateRunning;
|
||||
private final Predicate<RunningInstance> instanceStateTerminated;
|
||||
private final RunningInstanceToNodeMetadata runningInstanceToNodeMetadata;
|
||||
protected final Predicate<RunningInstance> instanceStateRunning;
|
||||
protected final Predicate<RunningInstance> instanceStateTerminated;
|
||||
protected final RunningInstanceToNodeMetadata runningInstanceToNodeMetadata;
|
||||
protected final ExecutorService executor;
|
||||
|
||||
@Inject
|
||||
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("TERMINATED") Predicate<RunningInstance> instanceStateTerminated,
|
||||
RunningInstanceToNodeMetadata runningInstanceToNodeMetadata) {
|
||||
RunningInstanceToNodeMetadata runningInstanceToNodeMetadata,
|
||||
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService executor) {
|
||||
this.templateBuilderProvider = templateBuilderProvider;
|
||||
this.ec2Client = client;
|
||||
this.images = images;
|
||||
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.instanceStateTerminated = instanceStateTerminated;
|
||||
this.runningInstanceToNodeMetadata = runningInstanceToNodeMetadata;
|
||||
}
|
||||
|
||||
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);
|
||||
this.executor = executor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CreateNodeResponse runNode(String name, Template template, RunNodeOptions options) {
|
||||
checkArgument(template.getImage() instanceof EC2Image,
|
||||
"unexpected image type. should be EC2Image, was: " + template.getImage().getClass());
|
||||
public NodeSet runNodes(String tag, int count, Template template) {
|
||||
checkArgument(tag.indexOf('-') == -1, "tag cannot contain hyphens");
|
||||
checkArgument(template.getSize() instanceof EC2Size,
|
||||
"unexpected image type. should be EC2Size, was: " + template.getSize().getClass());
|
||||
EC2Image ec2Image = EC2Image.class.cast(template.getImage());
|
||||
EC2Size ec2Size = EC2Size.class.cast(template.getSize());
|
||||
|
||||
Region region = ec2Image.getImage().getRegion();
|
||||
KeyPair keyPair = createKeyPairInRegion(region, name);
|
||||
String securityGroupName = name;
|
||||
createSecurityGroupInRegion(region, securityGroupName, options.getOpenPorts());
|
||||
// parse the availability zone of the request
|
||||
AvailabilityZone zone = template.getLocation().getScope() == LocationScope.ZONE ? AvailabilityZone
|
||||
.fromValue(template.getLocation().getId())
|
||||
: null;
|
||||
|
||||
logger.debug(">> running instance region(%s) ami(%s) type(%s) keyPair(%s) securityGroup(%s)",
|
||||
region, ec2Image.getId(), ec2Size.getInstanceType(), keyPair.getKeyName(),
|
||||
securityGroupName);
|
||||
RunInstancesOptions instanceOptions = withKeyName(keyPair.getKeyName())// key
|
||||
// if the location has a parent, it must be an availability zone.
|
||||
Region region = zone == null ? Region.fromValue(template.getLocation().getId()) : Region
|
||||
.fromValue(template.getLocation().getParent());
|
||||
|
||||
// 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
|
||||
.withSecurityGroup(securityGroupName)// group I created above
|
||||
.withAdditionalInfo(name);
|
||||
.withSecurityGroup(tag)// group I created above
|
||||
.withAdditionalInfo(tag);
|
||||
|
||||
if (options.getRunScript() != null)
|
||||
instanceOptions.withUserData(options.getRunScript());
|
||||
|
||||
RunningInstance runningInstance = Iterables.getOnlyElement(ec2Client.getInstanceServices()
|
||||
.runInstancesInRegion(region, null, ec2Image.getId(), 1, 1, instanceOptions));
|
||||
logger.debug("<< started instance(%s)", runningInstance.getId());
|
||||
instanceStateRunning.apply(runningInstance);
|
||||
logger.debug("<< running instance(%s)", runningInstance.getId());
|
||||
Reservation reservation = ec2Client.getInstanceServices().runInstancesInRegion(region, zone,
|
||||
template.getImage().getId(), 1, count, instanceOptions);
|
||||
Iterable<String> ids = Iterables.transform(reservation, instanceToId);
|
||||
|
||||
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
|
||||
runningInstance = getOnlyRunningInstanceInRegion(region, runningInstance.getId());
|
||||
|
||||
Set<InetAddress> publicAddresses = runningInstance.getIpAddress() == null ? ImmutableSet
|
||||
.<InetAddress> of() : ImmutableSet.<InetAddress> of(runningInstance.getIpAddress());
|
||||
Set<InetAddress> privateAddresses = runningInstance.getPrivateIpAddress() == null ? ImmutableSet
|
||||
.<InetAddress> of()
|
||||
: ImmutableSet.<InetAddress> of(runningInstance.getPrivateIpAddress());
|
||||
return new CreateNodeResponseImpl(runningInstance.getId(), name, runningInstance.getRegion()
|
||||
.toString(), null, ImmutableMap.<String, String> of(), instanceToNodeState
|
||||
.get(runningInstance.getInstanceState()), publicAddresses, privateAddresses,
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
return new NodeSetImpl(Iterables.transform(Iterables.concat(ec2Client.getInstanceServices()
|
||||
.describeInstancesInRegion(region, Iterables.toArray(ids, String.class))),
|
||||
runningInstanceToNodeMetadata));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -208,114 +217,132 @@ public class EC2ComputeService implements ComputeService {
|
|||
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) {
|
||||
return Iterables
|
||||
.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
|
||||
public Set<ComputeMetadata> listNodes() {
|
||||
public Map<String, NodeMetadata> getNodes() {
|
||||
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)) {
|
||||
Iterables.addAll(servers, Iterables.transform(Iterables.concat(ec2Client
|
||||
Iterables.addAll(nodes, Iterables.transform(Iterables.concat(ec2Client
|
||||
.getInstanceServices().describeInstancesInRegion(region)),
|
||||
new Function<RunningInstance, ComputeMetadata>() {
|
||||
@Override
|
||||
public ComputeMetadata apply(RunningInstance from) {
|
||||
return new ComputeMetadataImpl(ComputeType.NODE, from.getId(), from
|
||||
.getKeyName(), from.getRegion().toString(), null, ImmutableMap
|
||||
.<String, String> of());
|
||||
runningInstanceToNodeMetadata));
|
||||
}
|
||||
}));
|
||||
}
|
||||
logger.debug("<< list(%d)", servers.size());
|
||||
return servers;
|
||||
return Maps.uniqueIndex(nodes, METADATA_TO_ID);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void destroyNode(ComputeMetadata node) {
|
||||
checkArgument(node.getType() == ComputeType.NODE, "this is only valid for nodes, not "
|
||||
+ node.getType());
|
||||
checkNotNull(node.getId(), "node.id");
|
||||
public void destroyNode(ComputeMetadata metadata) {
|
||||
checkArgument(metadata.getType() == ComputeType.NODE, "this is only valid for nodes, not "
|
||||
+ metadata.getType());
|
||||
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);
|
||||
for (RunningInstance runningInstance : getAllRunningInstancesInRegion(region, node.getId())) {
|
||||
// grab the old keyname
|
||||
String name = runningInstance.getKeyName();
|
||||
|
||||
RunningInstance instance = getInstance(node, region);
|
||||
if (instance.getInstanceState() != InstanceState.TERMINATED) {
|
||||
logger.debug(">> terminating instance(%s)", node.getId());
|
||||
boolean success = false;
|
||||
while (!success) {
|
||||
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(">> deleting keyPair(%s)", name);
|
||||
ec2Client.getKeyPairServices().deleteKeyPairInRegion(region, name);
|
||||
logger.debug("<< deleted keyPair(%s)", name);
|
||||
logger.debug(">> deleting securityGroup(%s)", name);
|
||||
ec2Client.getSecurityGroupServices().deleteSecurityGroupInRegion(region, name);
|
||||
logger.debug("<< deleted securityGroup(%s)", name);
|
||||
}
|
||||
if (Iterables.all(doGetNodes(tag), new Predicate<NodeMetadata>() {
|
||||
@Override
|
||||
public boolean apply(NodeMetadata input) {
|
||||
return input.getState() == NodeState.TERMINATED;
|
||||
}
|
||||
})) {
|
||||
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) {
|
||||
Region region = node.getLocation() != null ? Region.fromValue(node.getLocation())
|
||||
: Region.DEFAULT;
|
||||
Location location = getLocations().get(node.getLocationId());
|
||||
Region region = location.getScope() == LocationScope.REGION ? Region.fromValue(location
|
||||
.getId()) : Region.fromValue(location.getParent());
|
||||
return region;
|
||||
}
|
||||
|
||||
@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();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<? extends Image> listImages() {
|
||||
public Map<String, ? extends Image> getImages() {
|
||||
return images.get();
|
||||
}
|
||||
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
package org.jclouds.aws.ec2.compute.config;
|
||||
|
||||
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.util.Map;
|
||||
|
@ -37,21 +38,36 @@ import org.jclouds.aws.ec2.EC2;
|
|||
import org.jclouds.aws.ec2.EC2AsyncClient;
|
||||
import org.jclouds.aws.ec2.EC2Client;
|
||||
import org.jclouds.aws.ec2.compute.EC2ComputeService;
|
||||
import org.jclouds.aws.ec2.compute.domain.EC2Image;
|
||||
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.domain.AvailabilityZone;
|
||||
import org.jclouds.compute.ComputeService;
|
||||
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.OsFamily;
|
||||
import org.jclouds.compute.domain.Size;
|
||||
import org.jclouds.compute.domain.internal.ImageImpl;
|
||||
import org.jclouds.compute.internal.ComputeServiceContextImpl;
|
||||
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.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.Iterables;
|
||||
import com.google.common.collect.Maps;
|
||||
import com.google.common.collect.Sets;
|
||||
import com.google.inject.Provides;
|
||||
|
||||
|
@ -68,6 +84,22 @@ public class EC2ComputeServiceContextModule extends EC2ContextModule {
|
|||
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
|
||||
@Singleton
|
||||
ComputeServiceContext provideContext(ComputeService computeService,
|
||||
|
@ -77,16 +109,47 @@ public class EC2ComputeServiceContextModule extends EC2ContextModule {
|
|||
|
||||
@Provides
|
||||
@Singleton
|
||||
Set<? extends Size> provideSizes() {
|
||||
return ImmutableSet.of(EC2Size.C1_MEDIUM, EC2Size.C1_XLARGE, EC2Size.M1_LARGE,
|
||||
EC2Size.M1_SMALL, EC2Size.M1_XLARGE, EC2Size.M2_2XLARGE, EC2Size.M2_4XLARGE);
|
||||
Function<ComputeMetadata, String> indexer() {
|
||||
return new Function<ComputeMetadata, String>() {
|
||||
@Override
|
||||
public String apply(ComputeMetadata from) {
|
||||
return from.getId();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
@ResourceLocation
|
||||
String getRegion(@EC2 Region region) {
|
||||
return region.value();
|
||||
Map<String, ? extends Size> provideSizes(Function<ComputeMetadata, String> indexer) {
|
||||
return Maps.uniqueIndex(ImmutableSet.of(EC2Size.C1_MEDIUM, EC2Size.C1_XLARGE,
|
||||
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 {
|
||||
|
@ -101,13 +164,24 @@ public class EC2ComputeServiceContextModule extends EC2ContextModule {
|
|||
|
||||
@Provides
|
||||
@Singleton
|
||||
protected Set<? extends Image> provideImages(final EC2Client sync, Map<Region, URI> regionMap,
|
||||
LogHolder holder) throws InterruptedException, ExecutionException, TimeoutException {
|
||||
@Named(PROPERTY_EC2_AMI_OWNERS)
|
||||
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();
|
||||
holder.logger.debug(">> providing images");
|
||||
|
||||
for (final Region region : regionMap.keySet()) {
|
||||
for (final org.jclouds.aws.ec2.domain.Image from : sync.getAMIServices()
|
||||
.describeImagesInRegion(region, ownedBy("063491364108"))) {
|
||||
.describeImagesInRegion(region, ownedBy(amiOwners))) {
|
||||
OsFamily os = null;
|
||||
String osDescription = from.getImageLocation();
|
||||
String version = "";
|
||||
|
@ -122,10 +196,22 @@ public class EC2ComputeServiceContextModule extends EC2ContextModule {
|
|||
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());
|
||||
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.internal.SizeImpl;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
|
||||
/**
|
||||
|
@ -34,11 +35,14 @@ import com.google.common.collect.ImmutableSet;
|
|||
* @author Adrian Cole
|
||||
*/
|
||||
public class EC2Size extends SizeImpl {
|
||||
/** The serialVersionUID */
|
||||
private static final long serialVersionUID = 8605688733788974797L;
|
||||
private final InstanceType instanceType;
|
||||
|
||||
EC2Size(InstanceType instanceType, Integer cores, Integer ram, Integer disk,
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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.RunningInstance;
|
||||
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.services.AMIAsyncClient;
|
||||
import org.jclouds.aws.ec2.services.AMIClient;
|
||||
|
@ -91,7 +92,8 @@ public class EC2RestClientModule extends AbstractModule {
|
|||
@Provides
|
||||
@Singleton
|
||||
@Named("TERMINATED")
|
||||
protected Predicate<RunningInstance> instanceStateTerminated(InstanceStateRunning stateTerminated) {
|
||||
protected Predicate<RunningInstance> instanceStateTerminated(
|
||||
InstanceStateTerminated stateTerminated) {
|
||||
return new RetryablePredicate<RunningInstance>(stateTerminated, 600, 50,
|
||||
TimeUnit.MILLISECONDS);
|
||||
}
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
package org.jclouds.aws.ec2.reference;
|
||||
|
||||
import org.jclouds.aws.reference.AWSConstants;
|
||||
import org.jclouds.compute.ComputeService;
|
||||
|
||||
/**
|
||||
* Configuration properties and constants used in EC2 connections.
|
||||
|
@ -27,5 +28,10 @@ import org.jclouds.aws.reference.AWSConstants;
|
|||
*/
|
||||
public interface EC2Constants extends AWSConstants {
|
||||
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,
|
||||
@FormParam("KeyName") String keyName);
|
||||
|
||||
// map resourcenotfoundexception to empty set
|
||||
/**
|
||||
* @see KeyPairClient#describeKeyPairsInRegion
|
||||
*/
|
||||
|
|
|
@ -34,6 +34,7 @@ import org.jclouds.http.HttpResponse;
|
|||
import org.jclouds.http.HttpResponseException;
|
||||
import org.jclouds.logging.Logger;
|
||||
import org.jclouds.rest.AuthorizationException;
|
||||
import org.jclouds.rest.ResourceNotFoundException;
|
||||
import org.jclouds.util.Utils;
|
||||
|
||||
import com.google.common.io.Closeables;
|
||||
|
@ -78,6 +79,8 @@ public class ParseAWSErrorFromXmlContent implements HttpErrorHandler {
|
|||
if (content.indexOf('<') >= 0) {
|
||||
AWSError error = utils.parseAWSErrorFromContent(command, response, content);
|
||||
exception = new AWSResponseException(command, response, error);
|
||||
if (error.getCode().indexOf("NotFound") >= 0)
|
||||
exception = new ResourceNotFoundException(exception);
|
||||
} else {
|
||||
exception = new HttpResponseException(command, response, content);
|
||||
}
|
||||
|
|
|
@ -113,11 +113,9 @@ public interface BlobStore {
|
|||
* fully qualified name relative to the container.
|
||||
* @param 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
|
||||
* if the container doesn't exist
|
||||
* @throws KeyNotFoundException
|
||||
* if the container doesn't exist
|
||||
*/
|
||||
Blob getBlob(String container, String name);
|
||||
|
||||
|
|
|
@ -66,7 +66,7 @@ public interface StorageMetadata extends ResourceMetadata<StorageType> {
|
|||
*
|
||||
*/
|
||||
@Override
|
||||
String getLocation();
|
||||
String getLocationId();
|
||||
|
||||
/**
|
||||
* URI used to access this resource
|
||||
|
|
|
@ -41,9 +41,9 @@ public class BlobMetadataImpl extends StorageMetadataImpl implements Serializabl
|
|||
private final String contentType;
|
||||
private final byte[] contentMD5;
|
||||
|
||||
public BlobMetadataImpl(String id, String name, @Nullable String location, URI uri, String eTag,
|
||||
Long size, Date lastModified, Map<String, String> userMetadata, String contentType,
|
||||
byte[] contentMD5) {
|
||||
public BlobMetadataImpl(String id, String name, @Nullable String location, URI uri,
|
||||
String eTag, Long size, Date lastModified, Map<String, String> userMetadata,
|
||||
String contentType, byte[] contentMD5) {
|
||||
super(StorageType.BLOB, id, name, location, uri, eTag, size, lastModified, userMetadata);
|
||||
this.contentType = contentType;
|
||||
this.contentMD5 = contentMD5;
|
||||
|
|
|
@ -38,7 +38,7 @@ public class ResourceMetadataToRelativePathResourceMetadata implements
|
|||
name = name.substring(0, name.length() - suffix.length());
|
||||
}
|
||||
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());
|
||||
}
|
||||
|
||||
|
|
|
@ -65,7 +65,7 @@ public class BlobStoreUtils {
|
|||
blob.getMetadata().setETag(blobMeta.getETag());
|
||||
blob.getMetadata().setId(blobMeta.getId());
|
||||
blob.getMetadata().setLastModified(blobMeta.getLastModified());
|
||||
blob.getMetadata().setLocation(blobMeta.getLocation());
|
||||
blob.getMetadata().setLocationId(blobMeta.getLocationId());
|
||||
blob.getMetadata().setUri(blobMeta.getUri());
|
||||
blob.getMetadata().setUserMetadata(blobMeta.getUserMetadata());
|
||||
return blob;
|
||||
|
|
|
@ -18,16 +18,16 @@
|
|||
*/
|
||||
package org.jclouds.compute;
|
||||
|
||||
import java.util.Set;
|
||||
import java.util.Map;
|
||||
|
||||
import org.jclouds.compute.domain.ComputeMetadata;
|
||||
import org.jclouds.compute.domain.CreateNodeResponse;
|
||||
import org.jclouds.compute.domain.Image;
|
||||
import org.jclouds.compute.domain.NodeMetadata;
|
||||
import org.jclouds.compute.domain.NodeSet;
|
||||
import org.jclouds.compute.domain.Size;
|
||||
import org.jclouds.compute.domain.Template;
|
||||
import org.jclouds.compute.domain.TemplateBuilder;
|
||||
import org.jclouds.compute.options.RunNodeOptions;
|
||||
import org.jclouds.domain.Location;
|
||||
|
||||
/**
|
||||
* Provides portable access to launching compute instances.
|
||||
|
@ -42,36 +42,62 @@ public interface ComputeService {
|
|||
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);
|
||||
|
||||
CreateNodeResponse runNode(String name, Template template, RunNodeOptions options);
|
||||
NodeSet runNodes(String tag, int maxNodes, Template template);
|
||||
|
||||
/**
|
||||
* 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);
|
||||
|
||||
/**
|
||||
* destroy the nodes identified by this tag.
|
||||
*/
|
||||
void destroyNodes(String tag);
|
||||
|
||||
/**
|
||||
* Find a node by its id
|
||||
*/
|
||||
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
|
||||
public String getName();
|
||||
|
||||
/**
|
||||
* location where the node exists..
|
||||
*
|
||||
*/
|
||||
@Override
|
||||
public String getLocation();
|
||||
|
||||
}
|
||||
|
|
|
@ -23,23 +23,22 @@
|
|||
*/
|
||||
package org.jclouds.compute.domain;
|
||||
|
||||
import org.jclouds.compute.domain.internal.ImageImpl;
|
||||
|
||||
import com.google.inject.ImplementedBy;
|
||||
|
||||
/**
|
||||
* Running Operating system
|
||||
*
|
||||
* @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();
|
||||
|
||||
/**
|
||||
* Description of the image
|
||||
*/
|
||||
String getDescription();
|
||||
String getVersion();
|
||||
|
||||
/**
|
||||
* Operating System
|
||||
|
@ -51,16 +50,6 @@ public interface Image {
|
|||
*/
|
||||
String getOsDescription();
|
||||
|
||||
/**
|
||||
* Version of the image
|
||||
*/
|
||||
String getVersion();
|
||||
|
||||
/**
|
||||
* Geographic location of the image.
|
||||
*/
|
||||
String getLocation();
|
||||
|
||||
/**
|
||||
* Operating System
|
||||
*/
|
||||
|
|
|
@ -20,18 +20,43 @@ package org.jclouds.compute.domain;
|
|||
|
||||
import java.net.InetAddress;
|
||||
import java.util.Map;
|
||||
import java.util.SortedSet;
|
||||
import java.util.Set;
|
||||
|
||||
import org.jclouds.domain.Credentials;
|
||||
|
||||
/**
|
||||
* @author Adrian Cole
|
||||
* @author Ivan Meredith
|
||||
*/
|
||||
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();
|
||||
|
||||
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
|
||||
|
|
|
@ -18,14 +18,11 @@
|
|||
*/
|
||||
package org.jclouds.compute.domain;
|
||||
|
||||
import org.jclouds.domain.Credentials;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* @author Adrian Cole
|
||||
* @author Ivan Meredith
|
||||
*/
|
||||
public interface CreateNodeResponse extends NodeMetadata {
|
||||
|
||||
Credentials getCredentials();
|
||||
public interface NodeSet extends Set<NodeMetadata> {
|
||||
|
||||
}
|
|
@ -23,6 +23,8 @@
|
|||
*/
|
||||
package org.jclouds.compute.domain;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
import org.jclouds.compute.domain.internal.SizeImpl;
|
||||
|
||||
import com.google.inject.ImplementedBy;
|
||||
|
@ -33,12 +35,7 @@ import com.google.inject.ImplementedBy;
|
|||
* @author Adrian Cole
|
||||
*/
|
||||
@ImplementedBy(SizeImpl.class)
|
||||
public interface Size extends Comparable<Size> {
|
||||
|
||||
/**
|
||||
* unique identifier of this configuration.
|
||||
*/
|
||||
String getId();
|
||||
public interface Size extends ComputeMetadata {
|
||||
|
||||
/**
|
||||
* Amount of virtual or physical cores provided
|
||||
|
@ -58,5 +55,5 @@ public interface Size extends Comparable<Size> {
|
|||
/**
|
||||
* Determines platforms this can support
|
||||
*/
|
||||
boolean supportsArchitecture(Architecture architecture);
|
||||
Set<Architecture> getSupportedArchitectures();
|
||||
}
|
|
@ -18,6 +18,9 @@
|
|||
*/
|
||||
package org.jclouds.compute.domain;
|
||||
|
||||
import org.jclouds.compute.options.TemplateOptions;
|
||||
import org.jclouds.domain.Location;
|
||||
|
||||
/**
|
||||
* Configured operating system used to start nodes.
|
||||
*
|
||||
|
@ -35,4 +38,13 @@ public interface Template extends Cloneable {
|
|||
*/
|
||||
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;
|
||||
|
||||
import org.jclouds.compute.internal.TemplateBuilderImpl;
|
||||
import org.jclouds.compute.options.TemplateOptions;
|
||||
|
||||
import com.google.inject.ImplementedBy;
|
||||
|
||||
|
@ -72,7 +73,7 @@ public interface TemplateBuilder {
|
|||
/**
|
||||
* 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
|
||||
|
@ -121,4 +122,9 @@ public interface TemplateBuilder {
|
|||
* Generate an immutable template from the current builder.
|
||||
*/
|
||||
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 */
|
||||
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) {
|
||||
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;
|
||||
|
||||
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.ComputeType;
|
||||
import org.jclouds.compute.domain.Image;
|
||||
import org.jclouds.compute.domain.OsFamily;
|
||||
|
||||
/**
|
||||
* @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 OsFamily operatingSystem;
|
||||
private final String operatingSystemDescription;
|
||||
private final String location;
|
||||
private final OsFamily osFamily;
|
||||
private final String osDescription;
|
||||
private final Architecture architecture;
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public int hashCode() {
|
||||
final int prime = 31;
|
||||
int result = 1;
|
||||
result = prime * result + ((architecture == null) ? 0 : architecture.hashCode());
|
||||
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;
|
||||
public ImageImpl(String id, String name, String locationId, URI uri,
|
||||
Map<String, String> userMetadata, String description, String version,
|
||||
@Nullable OsFamily osFamily, String osDescription, Architecture architecture) {
|
||||
super(ComputeType.IMAGE, id, name, locationId, uri, userMetadata);
|
||||
this.version = checkNotNull(version, "version");
|
||||
this.osFamily = osFamily;
|
||||
this.osDescription = checkNotNull(osDescription, "osDescription");
|
||||
this.architecture = checkNotNull(architecture, "architecture");
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -156,8 +70,16 @@ public class ImageImpl implements Image {
|
|||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public String getLocation() {
|
||||
return location;
|
||||
public OsFamily getOsFamily() {
|
||||
return osFamily;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public String getOsDescription() {
|
||||
return osDescription;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -168,12 +90,4 @@ public class ImageImpl implements Image {
|
|||
return architecture;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public String getOsDescription() {
|
||||
return operatingSystemDescription;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -18,15 +18,19 @@
|
|||
*/
|
||||
package org.jclouds.compute.domain.internal;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
import java.net.InetAddress;
|
||||
import java.net.URI;
|
||||
import java.util.Comparator;
|
||||
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.NodeMetadata;
|
||||
import org.jclouds.compute.domain.NodeState;
|
||||
import org.jclouds.domain.Credentials;
|
||||
|
||||
import com.google.common.collect.Iterables;
|
||||
import com.google.common.collect.Maps;
|
||||
|
@ -40,47 +44,62 @@ public class NodeMetadataImpl extends ComputeMetadataImpl implements NodeMetadat
|
|||
/** The serialVersionUID */
|
||||
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 SortedSet<InetAddress> publicAddresses = Sets.newTreeSet(ADDRESS_COMPARATOR);
|
||||
private final SortedSet<InetAddress> privateAddresses = Sets.newTreeSet(ADDRESS_COMPARATOR);
|
||||
private final Set<InetAddress> publicAddresses = Sets.newLinkedHashSet();
|
||||
private final Set<InetAddress> privateAddresses = Sets.newLinkedHashSet();
|
||||
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,
|
||||
Map<String, String> userMetadata, NodeState state,
|
||||
public NodeMetadataImpl(String id, String name, String locationId, URI uri,
|
||||
Map<String, String> userMetadata, String tag, NodeState state,
|
||||
Iterable<InetAddress> publicAddresses, Iterable<InetAddress> privateAddresses,
|
||||
Map<String, String> extra) {
|
||||
super(ComputeType.NODE, id, name, location, uri, userMetadata);
|
||||
this.state = state;
|
||||
Iterables.addAll(this.publicAddresses, publicAddresses);
|
||||
Iterables.addAll(this.privateAddresses, privateAddresses);
|
||||
this.extra.putAll(extra);
|
||||
Map<String, String> extra, @Nullable Credentials credentials) {
|
||||
super(ComputeType.NODE, id, name, locationId, uri, userMetadata);
|
||||
this.tag = checkNotNull(tag, "tag");
|
||||
this.state = checkNotNull(state, "state");
|
||||
Iterables.addAll(this.publicAddresses, checkNotNull(publicAddresses, "publicAddresses"));
|
||||
Iterables.addAll(this.privateAddresses, checkNotNull(privateAddresses, "privateAddresses"));
|
||||
this.extra.putAll(checkNotNull(extra, "extra"));
|
||||
this.credentials = credentials;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@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;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public SortedSet<InetAddress> getPrivateAddresses() {
|
||||
@Override
|
||||
public Set<InetAddress> getPrivateAddresses() {
|
||||
return privateAddresses;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public NodeState getState() {
|
||||
return state;
|
||||
}
|
||||
|
@ -95,20 +114,22 @@ public class NodeMetadataImpl extends ComputeMetadataImpl implements NodeMetadat
|
|||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "[id=" + getId() + ", name=" + getName() + ", location=" + getLocation() + ", uri="
|
||||
+ getUri() + ", userMetadata=" + getUserMetadata() + ", state=" + getState()
|
||||
+ ", privateAddresses=" + privateAddresses + ", publicAddresses=" + publicAddresses
|
||||
+ "]";
|
||||
return "[id=" + getId() + ", tag=" + getTag() + ", name=" + getName() + ", location="
|
||||
+ getLocationId() + ", uri=" + getUri() + ", userMetadata=" + getUserMetadata()
|
||||
+ ", state=" + getState() + ", privateAddresses=" + privateAddresses
|
||||
+ ", publicAddresses=" + publicAddresses + "]";
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
final int prime = 31;
|
||||
int result = super.hashCode();
|
||||
result = prime * result + ((credentials == null) ? 0 : credentials.hashCode());
|
||||
result = prime * result + ((extra == null) ? 0 : extra.hashCode());
|
||||
result = prime * result + ((privateAddresses == null) ? 0 : privateAddresses.hashCode());
|
||||
result = prime * result + ((publicAddresses == null) ? 0 : publicAddresses.hashCode());
|
||||
result = prime * result + ((state == null) ? 0 : state.hashCode());
|
||||
result = prime * result + ((tag == null) ? 0 : tag.hashCode());
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -121,6 +142,11 @@ public class NodeMetadataImpl extends ComputeMetadataImpl implements NodeMetadat
|
|||
if (getClass() != obj.getClass())
|
||||
return false;
|
||||
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 (other.extra != null)
|
||||
return false;
|
||||
|
@ -141,6 +167,11 @@ public class NodeMetadataImpl extends ComputeMetadataImpl implements NodeMetadat
|
|||
return false;
|
||||
} else if (!state.equals(other.state))
|
||||
return false;
|
||||
if (tag == null) {
|
||||
if (other.tag != null)
|
||||
return false;
|
||||
} else if (!tag.equals(other.tag))
|
||||
return false;
|
||||
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;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
import java.net.URI;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import org.jclouds.compute.domain.Architecture;
|
||||
import org.jclouds.compute.domain.ComputeType;
|
||||
import org.jclouds.compute.domain.Size;
|
||||
import org.jclouds.domain.ResourceMetadata;
|
||||
|
||||
import com.google.common.collect.ComparisonChain;
|
||||
import com.google.common.collect.Iterables;
|
||||
|
@ -30,20 +38,24 @@ import com.google.common.collect.Sets;
|
|||
/**
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
public class SizeImpl implements Size {
|
||||
private String id;
|
||||
public class SizeImpl extends ComputeMetadataImpl implements Size {
|
||||
/** The serialVersionUID */
|
||||
private static final long serialVersionUID = 8994255275911717567L;
|
||||
private final int cores;
|
||||
private final int ram;
|
||||
private final int disk;
|
||||
|
||||
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) {
|
||||
this.id = id;
|
||||
super(ComputeType.SIZE, id, name, location, uri, userMetadata);
|
||||
this.cores = cores;
|
||||
this.ram = ram;
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public int hashCode() {
|
||||
final int prime = 31;
|
||||
int result = 1;
|
||||
result = prime * result + cores;
|
||||
result = prime * result + disk;
|
||||
result = prime * result + ((id == null) ? 0 : id.hashCode());
|
||||
result = prime * result + ram;
|
||||
result = prime * result
|
||||
+ ((supportedArchitectures == null) ? 0 : supportedArchitectures.hashCode());
|
||||
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();
|
||||
public int compareTo(ResourceMetadata<ComputeType> that) {
|
||||
if (that instanceof Size) {
|
||||
Size thatSize = Size.class.cast(that);
|
||||
return ComparisonChain.start().compare(this.getCores(), thatSize.getCores()).compare(
|
||||
this.getRam(), thatSize.getRam()).compare(this.getDisk(), thatSize.getDisk())
|
||||
.result();
|
||||
} else {
|
||||
return super.compareTo(that);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
return "[id=" + id + ", cores=" + cores + ", ram=" + ram + ", disk=" + disk
|
||||
return "[id=" + getId() + ", cores=" + cores + ", ram=" + ram + ", disk=" + disk
|
||||
+ ", supportedArchitectures=" + supportedArchitectures + "]";
|
||||
}
|
||||
|
||||
|
@ -126,15 +110,7 @@ public class SizeImpl implements Size {
|
|||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public boolean supportsArchitecture(Architecture architecture) {
|
||||
return supportedArchitectures.contains(architecture);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public String getId() {
|
||||
return id;
|
||||
public Set<Architecture> getSupportedArchitectures() {
|
||||
return supportedArchitectures;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,9 +23,13 @@
|
|||
*/
|
||||
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.Size;
|
||||
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 Size size;
|
||||
private final Location location;
|
||||
private final TemplateOptions options;
|
||||
|
||||
protected TemplateImpl(Image image, Size size) {
|
||||
this.image = image;
|
||||
this.size = size;
|
||||
public TemplateImpl(Image image, Size size, Location location, TemplateOptions options) {
|
||||
this.image = checkNotNull(image, "image");
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public Location getLocation() {
|
||||
return location;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public TemplateOptions getOptions() {
|
||||
return options;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
final int prime = 31;
|
||||
int result = 1;
|
||||
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());
|
||||
return result;
|
||||
}
|
||||
|
@ -80,6 +106,16 @@ public class TemplateImpl implements Template {
|
|||
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 (options == null) {
|
||||
if (other.options != null)
|
||||
return false;
|
||||
} else if (!options.equals(other.options))
|
||||
return false;
|
||||
if (size == null) {
|
||||
if (other.size != null)
|
||||
return false;
|
||||
|
@ -98,6 +134,7 @@ public class TemplateImpl implements Template {
|
|||
*/
|
||||
@Override
|
||||
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,
|
||||
RestContext<X, Y> providerSpecificContext) {
|
||||
this.computeService = checkNotNull(computeService, "computeService");
|
||||
this.providerSpecificContext = providerSpecificContext;
|
||||
this.providerSpecificContext = checkNotNull(providerSpecificContext, "providerSpecificContext");;
|
||||
}
|
||||
|
||||
public ComputeService getComputeService() {
|
||||
|
|
|
@ -1,21 +1,26 @@
|
|||
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.Set;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Named;
|
||||
|
||||
import org.jclouds.compute.domain.Architecture;
|
||||
import org.jclouds.compute.domain.ComputeMetadata;
|
||||
import org.jclouds.compute.domain.Image;
|
||||
import org.jclouds.compute.domain.OsFamily;
|
||||
import org.jclouds.compute.domain.Size;
|
||||
import org.jclouds.compute.domain.Template;
|
||||
import org.jclouds.compute.domain.TemplateBuilder;
|
||||
import org.jclouds.compute.domain.internal.TemplateImpl;
|
||||
import org.jclouds.compute.options.TemplateOptions;
|
||||
import org.jclouds.compute.reference.ComputeServiceConstants;
|
||||
import org.jclouds.domain.ResourceLocation;
|
||||
import org.jclouds.domain.Location;
|
||||
import org.jclouds.logging.Logger;
|
||||
|
||||
import com.google.common.base.Predicate;
|
||||
|
@ -37,17 +42,17 @@ public class TemplateBuilderImpl implements TemplateBuilder {
|
|||
@Named(ComputeServiceConstants.COMPUTE_LOGGER)
|
||||
protected Logger logger = Logger.NULL;
|
||||
|
||||
private final Set<? extends Image> images;
|
||||
private final Set<? extends Size> sizes;
|
||||
private String location;
|
||||
private final Map<String, ? extends Image> images;
|
||||
private final Map<String, ? extends Size> sizes;
|
||||
private final Map<String, ? extends Location> locations;
|
||||
private OsFamily os;
|
||||
private Architecture arch;
|
||||
private String locationId;
|
||||
private String imageId;
|
||||
private String sizeId;
|
||||
|
||||
private String osDescription;
|
||||
private String imageVersion;
|
||||
private String imageDescription;
|
||||
private String imageName;
|
||||
|
||||
private int minCores;
|
||||
private int minRam;
|
||||
|
@ -55,15 +60,29 @@ public class TemplateBuilderImpl implements TemplateBuilder {
|
|||
private boolean biggest;
|
||||
private boolean fastest;
|
||||
|
||||
private TemplateOptions options = TemplateOptions.NONE;
|
||||
|
||||
@Inject
|
||||
public TemplateBuilderImpl(@ResourceLocation String location, Set<? extends Image> images,
|
||||
Set<? extends Size> sizes) {
|
||||
this.location = location;
|
||||
public TemplateBuilderImpl(Map<String, ? extends Location> locations,
|
||||
Map<String, ? extends Image> images, Map<String, ? extends Size> sizes,
|
||||
Location defaultLocation) {
|
||||
this.locations = locations;
|
||||
this.images = images;
|
||||
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
|
||||
public boolean apply(Image input) {
|
||||
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>() {
|
||||
|
||||
@Override
|
||||
|
@ -136,15 +145,15 @@ public class TemplateBuilderImpl implements TemplateBuilder {
|
|||
return returnVal;
|
||||
}
|
||||
};
|
||||
private final Predicate<Image> imageDescriptionPredicate = new Predicate<Image>() {
|
||||
private final Predicate<Image> imageNamePredicate = new Predicate<Image>() {
|
||||
@Override
|
||||
public boolean apply(Image input) {
|
||||
boolean returnVal = true;
|
||||
if (imageDescription != null) {
|
||||
if (input.getDescription() == null)
|
||||
if (imageName != null) {
|
||||
if (input.getName() == null)
|
||||
returnVal = false;
|
||||
else
|
||||
returnVal = input.getDescription().matches(imageDescription);
|
||||
returnVal = input.getName().matches(imageName);
|
||||
}
|
||||
return returnVal;
|
||||
}
|
||||
|
@ -165,16 +174,16 @@ public class TemplateBuilderImpl implements TemplateBuilder {
|
|||
}
|
||||
};
|
||||
|
||||
private final Predicate<Image> imagePredicate = Predicates.and(imageIdPredicate,
|
||||
locationPredicate, osPredicate, imageArchPredicate, osDescriptionPredicate,
|
||||
imageVersionPredicate, imageDescriptionPredicate);
|
||||
private final Predicate<Image> imagePredicate = Predicates.and(idPredicate, locationPredicate,
|
||||
osPredicate, imageArchPredicate, osDescriptionPredicate, imageVersionPredicate,
|
||||
imageNamePredicate);
|
||||
|
||||
private final Predicate<Size> sizeArchPredicate = new Predicate<Size>() {
|
||||
@Override
|
||||
public boolean apply(Size input) {
|
||||
boolean returnVal = false;
|
||||
if (arch != null)
|
||||
returnVal = input.supportsArchitecture(arch);
|
||||
returnVal = input.getSupportedArchitectures().contains(arch);
|
||||
return returnVal;
|
||||
}
|
||||
};
|
||||
|
@ -192,8 +201,8 @@ public class TemplateBuilderImpl implements TemplateBuilder {
|
|||
return input.getRam() >= TemplateBuilderImpl.this.minRam;
|
||||
}
|
||||
};
|
||||
private final Predicate<Size> sizePredicate = Predicates.and(sizeIdPredicate, sizeArchPredicate,
|
||||
sizeCoresPredicate, sizeRamPredicate);
|
||||
private final Predicate<Size> sizePredicate = Predicates.and(sizeIdPredicate, locationPredicate,
|
||||
sizeArchPredicate, sizeCoresPredicate, sizeRamPredicate);
|
||||
|
||||
static final Ordering<Size> DEFAULT_SIZE_ORDERING = new Ordering<Size>() {
|
||||
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>() {
|
||||
public int compare(Image left, Image right) {
|
||||
return ComparisonChain.start().compare(left.getOsDescription(),
|
||||
right.getOsDescription()).compare(left.getVersion(), right.getVersion())
|
||||
.result();
|
||||
return ComparisonChain.start().compare(left.getOsDescription(), right.getOsDescription())
|
||||
.compare(left.getVersion(), right.getVersion()).result();
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -229,6 +237,8 @@ public class TemplateBuilderImpl implements TemplateBuilder {
|
|||
*/
|
||||
@Override
|
||||
public TemplateBuilder fromSize(Size size) {
|
||||
if (size.getLocationId() != null)
|
||||
this.locationId = size.getLocationId();
|
||||
this.minCores = size.getCores();
|
||||
this.minRam = size.getRam();
|
||||
return this;
|
||||
|
@ -239,8 +249,8 @@ public class TemplateBuilderImpl implements TemplateBuilder {
|
|||
*/
|
||||
@Override
|
||||
public TemplateBuilder fromImage(Image image) {
|
||||
if (image.getLocation() != null)
|
||||
this.location = image.getLocation();
|
||||
if (image.getLocationId() != null)
|
||||
this.locationId = image.getLocationId();
|
||||
if (image.getOsFamily() != null)
|
||||
this.os = image.getOsFamily();
|
||||
if (image.getOsDescription() != null)
|
||||
|
@ -283,8 +293,10 @@ public class TemplateBuilderImpl implements TemplateBuilder {
|
|||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public TemplateBuilder location(String location) {
|
||||
this.location = location;
|
||||
public TemplateBuilder locationId(final String locationId) {
|
||||
checkArgument(locations.get(checkNotNull(locationId, "locationId")) != null, "locationId "
|
||||
+ locationId + " not configured in: " + locations.keySet());
|
||||
this.locationId = locationId;
|
||||
return this;
|
||||
}
|
||||
|
||||
|
@ -314,7 +326,7 @@ public class TemplateBuilderImpl implements TemplateBuilder {
|
|||
logger.debug(">> searching params(%s)", this);
|
||||
Image image;
|
||||
try {
|
||||
image = DEFAULT_IMAGE_ORDERING.max(Iterables.filter(images, imagePredicate));
|
||||
image = DEFAULT_IMAGE_ORDERING.max(Iterables.filter(images.values(), imagePredicate));
|
||||
} catch (NoSuchElementException exception) {
|
||||
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));
|
||||
Size size;
|
||||
try {
|
||||
size = sizeOrdering.max(Iterables.filter(sizes, sizePredicate));
|
||||
size = sizeOrdering.max(Iterables.filter(sizes.values(), sizePredicate));
|
||||
} catch (NoSuchElementException exception) {
|
||||
throw new NoSuchElementException("size didn't match: " + toString() + "\n" + sizes);
|
||||
}
|
||||
logger.debug("<< matched size(%s)", size);
|
||||
return new TemplateImpl(image, size) {
|
||||
};
|
||||
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
|
||||
public TemplateBuilder imageDescriptionMatches(String descriptionRegex) {
|
||||
this.imageDescription = descriptionRegex;
|
||||
this.imageName = descriptionRegex;
|
||||
return this;
|
||||
}
|
||||
|
||||
|
@ -401,13 +414,22 @@ public class TemplateBuilderImpl implements TemplateBuilder {
|
|||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public TemplateBuilder options(TemplateOptions options) {
|
||||
this.options = checkNotNull(options, "options");
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "[arch=" + arch + ", biggest=" + biggest + ", fastest=" + fastest
|
||||
+ ", imageDescription=" + imageDescription + ", imageId=" + imageId
|
||||
+ ", imageVersion=" + imageVersion + ", location=" + location + ", minCores="
|
||||
+ minCores + ", minRam=" + minRam + ", os=" + os + ", osDescription=" + osDescription
|
||||
+ ", sizeId=" + sizeId + "]";
|
||||
+ ", imageDescription=" + imageName + ", imageId=" + imageId + ", imageVersion="
|
||||
+ imageVersion + ", location=" + locationId + ", minCores=" + minCores + ", minRam="
|
||||
+ minRam + ", os=" + os + ", osDescription=" + osDescription + ", 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.net.ConnectException;
|
||||
import java.net.InetAddress;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.util.Comparator;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.inject.Named;
|
||||
|
||||
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.logging.Logger;
|
||||
import org.jclouds.ssh.SshClient;
|
||||
|
||||
import com.google.common.base.Function;
|
||||
import com.google.common.base.Predicate;
|
||||
import com.google.common.base.Throwables;
|
||||
import com.google.common.collect.Iterables;
|
||||
|
@ -50,6 +53,13 @@ public class ComputeUtils {
|
|||
private SshClient.Factory sshFactory;
|
||||
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
|
||||
public ComputeUtils(Predicate<InetSocketAddress> 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");
|
||||
|
||||
InetSocketAddress socket = new InetSocketAddress(node.getPublicAddresses().last(), 22);
|
||||
InetSocketAddress socket = new InetSocketAddress(Iterables.get(node.getPublicAddresses(), 0),
|
||||
22);
|
||||
socketTester.apply(socket);
|
||||
SshClient ssh = isKeyAuth(node) ? sshFactory.create(socket, node.getCredentials().account,
|
||||
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";
|
||||
ssh.put(scriptName, new ByteArrayInputStream(script));
|
||||
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
|
||||
&& createdNode.getCredentials().key.startsWith("-----BEGIN RSA PRIVATE KEY-----");
|
||||
}
|
||||
|
|
|
@ -25,20 +25,23 @@ import static org.testng.Assert.assertNotNull;
|
|||
import java.io.IOException;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.util.NoSuchElementException;
|
||||
import java.util.SortedSet;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
|
||||
import org.jclouds.compute.domain.ComputeMetadata;
|
||||
import org.jclouds.compute.domain.ComputeType;
|
||||
import org.jclouds.compute.domain.CreateNodeResponse;
|
||||
import org.jclouds.compute.domain.Image;
|
||||
import org.jclouds.compute.domain.NodeMetadata;
|
||||
import org.jclouds.compute.domain.NodeSet;
|
||||
import org.jclouds.compute.domain.NodeState;
|
||||
import org.jclouds.compute.domain.OsFamily;
|
||||
import org.jclouds.compute.domain.Size;
|
||||
import org.jclouds.compute.domain.Template;
|
||||
import org.jclouds.compute.domain.TemplateBuilder;
|
||||
import org.jclouds.compute.options.RunNodeOptions;
|
||||
import org.jclouds.domain.Location;
|
||||
import org.jclouds.http.HttpResponseException;
|
||||
import org.jclouds.logging.log4j.config.Log4JLoggingModule;
|
||||
import org.jclouds.predicates.RetryablePredicate;
|
||||
|
@ -56,6 +59,7 @@ import org.testng.annotations.Test;
|
|||
import com.google.common.base.Predicate;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.collect.Iterables;
|
||||
import com.google.common.collect.Sets;
|
||||
import com.google.inject.Guice;
|
||||
import com.google.inject.Injector;
|
||||
import com.google.inject.Module;
|
||||
|
@ -71,11 +75,10 @@ public abstract class BaseComputeServiceLiveTest {
|
|||
|
||||
protected String service;
|
||||
protected SshClient.Factory sshFactory;
|
||||
protected RunNodeOptions options = RunNodeOptions.Builder.openPorts(22);
|
||||
protected String nodeName;
|
||||
protected String tag;
|
||||
|
||||
private RetryablePredicate<InetSocketAddress> socketTester;
|
||||
private CreateNodeResponse node;
|
||||
private SortedSet<NodeMetadata> nodes;
|
||||
protected ComputeServiceContext context;
|
||||
protected ComputeService client;
|
||||
protected String user;
|
||||
|
@ -85,7 +88,8 @@ public abstract class BaseComputeServiceLiveTest {
|
|||
@BeforeGroups(groups = { "live" })
|
||||
public void setupClient() throws InterruptedException, ExecutionException, TimeoutException,
|
||||
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");
|
||||
password = checkNotNull(System.getProperty("jclouds.test.key"), "jclouds.test.key");
|
||||
context = new ComputeServiceContextFactory().createContext(service, user, password,
|
||||
|
@ -108,12 +112,7 @@ public abstract class BaseComputeServiceLiveTest {
|
|||
@Test(enabled = true)
|
||||
public void testCreate() throws Exception {
|
||||
try {
|
||||
client.destroyNode(Iterables.find(client.listNodes(), new Predicate<ComputeMetadata>() {
|
||||
@Override
|
||||
public boolean apply(ComputeMetadata input) {
|
||||
return input.getName().equals(nodeName);
|
||||
}
|
||||
}));
|
||||
client.destroyNodes(tag);
|
||||
} catch (HttpResponseException e) {
|
||||
// TODO hosting.com throws 400 when we try to delete a vApp
|
||||
} catch (NoSuchElementException e) {
|
||||
|
@ -122,75 +121,133 @@ public abstract class BaseComputeServiceLiveTest {
|
|||
template = buildTemplate(client.templateBuilder());
|
||||
|
||||
if (canRunScript(template))
|
||||
options.runScript(new ScriptBuilder()
|
||||
template
|
||||
.getOptions()
|
||||
.runScript(
|
||||
new ScriptBuilder()
|
||||
// update add dns and install jdk
|
||||
.addStatement(
|
||||
Statements.exec("echo nameserver 208.67.222.222 >> /etc/resolv.conf"))
|
||||
.addStatement(Statements.exec("apt-get update"))//
|
||||
.addStatement(Statements.exec("apt-get upgrade -y"))//
|
||||
.addStatement(Statements.exec("apt-get install -y openjdk-6-jdk"))//
|
||||
.addStatement(Statements.exec("wget -qO/usr/bin/runurl run.alestic.com/runurl"))//
|
||||
.addStatement(Statements.exec("chmod 755 /usr/bin/runurl"))//
|
||||
.build(org.jclouds.scriptbuilder.domain.OsFamily.UNIX).getBytes());
|
||||
node = client.runNode(nodeName, template, options);
|
||||
Statements
|
||||
.exec("echo nameserver 208.67.222.222 >> /etc/resolv.conf"))
|
||||
.addStatement(Statements.exec("apt-get update"))
|
||||
//
|
||||
.addStatement(Statements.exec("apt-get upgrade -y"))
|
||||
//
|
||||
.addStatement(
|
||||
Statements.exec("apt-get install -y openjdk-6-jdk"))
|
||||
//
|
||||
.addStatement(
|
||||
Statements
|
||||
.exec("wget -qO/usr/bin/runurl run.alestic.com/runurl"))
|
||||
//
|
||||
.addStatement(Statements.exec("chmod 755 /usr/bin/runurl"))
|
||||
//
|
||||
.build(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.getName());
|
||||
assert node.getPublicAddresses().size() >= 1: "no public ips in" + node;
|
||||
assertNotNull(node.getTag());
|
||||
assertEquals(node.getTag(), tag);
|
||||
assert node.getPublicAddresses().size() >= 1 || node.getPrivateAddresses().size() >= 1 : "no ips in"
|
||||
+ node;
|
||||
assertNotNull(node.getCredentials());
|
||||
if (node.getCredentials().account != null) {
|
||||
assertNotNull(node.getCredentials().account);
|
||||
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);
|
||||
|
||||
@Test(enabled = true, dependsOnMethods = "testCreate")
|
||||
public void testGet() throws Exception {
|
||||
NodeSet metadataSet = client.getNodes(tag);
|
||||
for (NodeMetadata node : nodes) {
|
||||
metadataSet.remove(node);
|
||||
NodeMetadata metadata = client.getNodeMetadata(node);
|
||||
assertEquals(metadata.getId(), node.getId());
|
||||
assertEquals(metadata.getName(), node.getName());
|
||||
assertEquals(metadata.getPrivateAddresses(), node.getPrivateAddresses());
|
||||
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 {
|
||||
for (ComputeMetadata node : client.listNodes()) {
|
||||
assert node.getId() != null;
|
||||
assert node.getLocation() != null;
|
||||
assertEquals(node.getType(), ComputeType.NODE);
|
||||
for (Entry<String, ? extends ComputeMetadata> node : client.getNodes().entrySet()) {
|
||||
assertEquals(node.getKey(), node.getValue().getId());
|
||||
assert node.getValue().getId() != null;
|
||||
assert node.getValue().getLocationId() != null;
|
||||
assertEquals(node.getValue().getType(), ComputeType.NODE);
|
||||
}
|
||||
}
|
||||
|
||||
public void testListImages() throws Exception {
|
||||
for (Image image : client.listImages()) {
|
||||
assert image.getId() != null : image;
|
||||
assert image.getLocation() != null : image;
|
||||
for (Entry<String, ? extends Image> image : client.getImages().entrySet()) {
|
||||
assertEquals(image.getKey(), image.getValue().getId());
|
||||
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 {
|
||||
for (Size size : client.listSizes()) {
|
||||
assert size.getCores() > 0 : size;
|
||||
for (Entry<String, ? extends Size> size : client.getSizes().entrySet()) {
|
||||
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 {
|
||||
doCheckKey();
|
||||
} catch (SshException e) {// try twice in case there is a network timeout
|
||||
doCheckKey(node);
|
||||
return;
|
||||
} catch (SshException e) {
|
||||
try {
|
||||
Thread.sleep(10 * 1000);
|
||||
} catch (InterruptedException e1) {
|
||||
}
|
||||
doCheckKey();
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void doCheckKey() throws IOException {
|
||||
InetSocketAddress socket = new InetSocketAddress(node.getPublicAddresses().last(), 22);
|
||||
socketTester.apply(socket);
|
||||
private void doCheckKey(NodeMetadata node) throws IOException {
|
||||
InetSocketAddress socket = new InetSocketAddress(Iterables.get(node.getPublicAddresses(), 0),
|
||||
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
|
||||
.create(socket, node.getCredentials().account, node.getCredentials().key.getBytes())
|
||||
: sshFactory
|
||||
|
@ -209,8 +266,12 @@ public abstract class BaseComputeServiceLiveTest {
|
|||
|
||||
@AfterTest
|
||||
protected void cleanup() throws InterruptedException, ExecutionException, TimeoutException {
|
||||
if (node != null)
|
||||
client.destroyNode(node);
|
||||
if (nodes != null) {
|
||||
client.destroyNodes(tag);
|
||||
for (NodeMetadata node : client.getNodes(tag)) {
|
||||
assert node.getState() == NodeState.TERMINATED : node;
|
||||
}
|
||||
}
|
||||
context.close();
|
||||
}
|
||||
|
||||
|
|
|
@ -101,9 +101,9 @@ public class ConcurrentUtils {
|
|||
}
|
||||
|
||||
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,
|
||||
complete, size, errors, ((double) complete)
|
||||
/ ((System.currentTimeMillis() - start) / 1000.0));
|
||||
return String
|
||||
.format("%s, completed: %d/%d, errors: %d, rate: %fms/op%n", prefix, complete,
|
||||
size, errors, ((System.currentTimeMillis() - start) / ((double) size)));
|
||||
}
|
||||
|
||||
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
|
||||
*/
|
||||
void setLocation(String location);
|
||||
void setLocationId(String location);
|
||||
|
||||
/**
|
||||
* @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();
|
||||
|
||||
/**
|
||||
* Physical location of the resource.
|
||||
* Physical location of the resource, or null if n/a
|
||||
*
|
||||
* ex. us-west-1
|
||||
*
|
||||
*/
|
||||
String getLocation();
|
||||
String getLocationId();
|
||||
|
||||
/**
|
||||
* URI used to access this resource
|
||||
|
@ -69,4 +69,5 @@ public interface ResourceMetadata<T extends Enum<T>> extends Comparable<Resource
|
|||
*/
|
||||
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.id = from.getId();
|
||||
this.name = from.getName();
|
||||
this.location = from.getLocation();
|
||||
this.location = from.getLocationId();
|
||||
this.uri = from.getUri();
|
||||
this.userMetadata = from.getUserMetadata();
|
||||
}
|
||||
|
@ -156,7 +156,7 @@ public class MutableResourceMetadataImpl<T extends Enum<T>> implements MutableRe
|
|||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public void setLocation(String location) {
|
||||
public void setLocationId(String location) {
|
||||
this.location = location;
|
||||
}
|
||||
|
||||
|
@ -164,7 +164,7 @@ public class MutableResourceMetadataImpl<T extends Enum<T>> implements MutableRe
|
|||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public String getLocation() {
|
||||
public String getLocationId() {
|
||||
return location;
|
||||
}
|
||||
|
||||
|
|
|
@ -45,17 +45,17 @@ public class ResourceMetadataImpl<T extends Enum<T>> implements ResourceMetadata
|
|||
@Nullable
|
||||
private final String name;
|
||||
@Nullable
|
||||
private final String location;
|
||||
private final String locationId;
|
||||
@Nullable
|
||||
private final URI uri;
|
||||
private final Map<String, String> userMetadata = Maps.newLinkedHashMap();
|
||||
|
||||
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.id = id;
|
||||
this.name = name;
|
||||
this.location = location;
|
||||
this.locationId = locationId;
|
||||
this.uri = uri;
|
||||
this.userMetadata.putAll(checkNotNull(userMetadata, "userMetadata"));
|
||||
}
|
||||
|
@ -98,8 +98,8 @@ public class ResourceMetadataImpl<T extends Enum<T>> implements ResourceMetadata
|
|||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public String getLocation() {
|
||||
return location;
|
||||
public String getLocationId() {
|
||||
return locationId;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -123,7 +123,7 @@ public class ResourceMetadataImpl<T extends Enum<T>> implements ResourceMetadata
|
|||
final int prime = 31;
|
||||
int result = 1;
|
||||
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 + ((type == null) ? 0 : type.hashCode());
|
||||
result = prime * result + ((uri == null) ? 0 : uri.hashCode());
|
||||
|
@ -145,10 +145,10 @@ public class ResourceMetadataImpl<T extends Enum<T>> implements ResourceMetadata
|
|||
return false;
|
||||
} else if (!id.equals(other.id))
|
||||
return false;
|
||||
if (location == null) {
|
||||
if (other.location != null)
|
||||
if (locationId == null) {
|
||||
if (other.locationId != null)
|
||||
return false;
|
||||
} else if (!location.equals(other.location))
|
||||
} else if (!locationId.equals(other.locationId))
|
||||
return false;
|
||||
if (name == null) {
|
||||
if (other.name != null)
|
||||
|
@ -175,7 +175,7 @@ public class ResourceMetadataImpl<T extends Enum<T>> implements ResourceMetadata
|
|||
|
||||
@Override
|
||||
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 + "]";
|
||||
}
|
||||
|
||||
|
|
|
@ -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.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.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.inject.Inject;
|
||||
|
@ -30,71 +37,96 @@ import javax.inject.Named;
|
|||
import javax.inject.Provider;
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import org.jclouds.Constants;
|
||||
import org.jclouds.compute.ComputeService;
|
||||
import org.jclouds.compute.domain.ComputeMetadata;
|
||||
import org.jclouds.compute.domain.ComputeType;
|
||||
import org.jclouds.compute.domain.CreateNodeResponse;
|
||||
import org.jclouds.compute.domain.Image;
|
||||
import org.jclouds.compute.domain.NodeMetadata;
|
||||
import org.jclouds.compute.domain.NodeSet;
|
||||
import org.jclouds.compute.domain.NodeState;
|
||||
import org.jclouds.compute.domain.Size;
|
||||
import org.jclouds.compute.domain.Template;
|
||||
import org.jclouds.compute.domain.TemplateBuilder;
|
||||
import org.jclouds.compute.domain.internal.CreateNodeResponseImpl;
|
||||
import org.jclouds.compute.domain.internal.NodeMetadataImpl;
|
||||
import org.jclouds.compute.options.RunNodeOptions;
|
||||
import org.jclouds.compute.domain.internal.NodeSetImpl;
|
||||
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.ResourceLocation;
|
||||
import org.jclouds.domain.Location;
|
||||
import org.jclouds.logging.Logger;
|
||||
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.ServerStatus;
|
||||
import org.jclouds.rackspace.cloudservers.options.ListOptions;
|
||||
import org.jclouds.rackspace.reference.RackspaceConstants;
|
||||
|
||||
import com.google.common.base.Function;
|
||||
import com.google.common.base.Predicate;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.Iterables;
|
||||
import com.google.common.collect.Maps;
|
||||
import com.google.common.collect.Sets;
|
||||
import com.google.common.util.concurrent.ListenableFuture;
|
||||
|
||||
/**
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
@Singleton
|
||||
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
|
||||
@Named(ComputeServiceConstants.COMPUTE_LOGGER)
|
||||
protected Logger logger = Logger.NULL;
|
||||
private final org.jclouds.rackspace.cloudservers.CloudServersClient client;
|
||||
protected final Provider<Set<? extends Image>> images;
|
||||
protected final Provider<Set<? extends Size>> sizes;
|
||||
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 String location;
|
||||
private final ComputeUtils utils;
|
||||
private final Predicate<Server> serverActive;
|
||||
private final ServerToNodeMetadata serverToNodeMetadata;
|
||||
private final Predicate<Server> serverDeleted;
|
||||
protected final ExecutorService executor;
|
||||
private final String account;
|
||||
|
||||
@Inject
|
||||
public CloudServersComputeService(CloudServersClient client,
|
||||
Provider<TemplateBuilder> templateBuilderProvider, @ResourceLocation String location,
|
||||
Provider<Set<? extends Image>> images, Provider<Set<? extends Size>> sizes,
|
||||
ComputeUtils utils, @Named("ACTIVE") Predicate<Server> serverActive,
|
||||
Provider<TemplateBuilder> templateBuilderProvider,
|
||||
Provider<Map<String, ? extends Image>> images,
|
||||
Provider<Map<String, ? extends Size>> sizes,
|
||||
Provider<Map<String, ? extends Location>> locations, ComputeUtils utils,
|
||||
@Named("ACTIVE") Predicate<Server> serverActive,
|
||||
@Named("DELETED") Predicate<Server> serverDeleted,
|
||||
ServerToNodeMetadata serverToNodeMetadata) {
|
||||
this.location = location;
|
||||
@Named(RackspaceConstants.PROPERTY_RACKSPACE_USER) String account,
|
||||
ServerToNodeMetadata serverToNodeMetadata,
|
||||
@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.serverActive = serverActive;
|
||||
this.serverDeleted = serverDeleted;
|
||||
this.account = account;
|
||||
this.serverToNodeMetadata = serverToNodeMetadata;
|
||||
this.executor = executor;
|
||||
}
|
||||
|
||||
private static Map<ServerStatus, NodeState> serverToNodeState = ImmutableMap
|
||||
|
@ -123,38 +155,40 @@ public class CloudServersComputeService implements ComputeService {
|
|||
.put(ServerStatus.UNKNOWN, NodeState.UNKNOWN).build();
|
||||
|
||||
@Override
|
||||
public CreateNodeResponse runNode(String name, Template template) {
|
||||
return this.runNode(name, template, RunNodeOptions.NONE);
|
||||
}
|
||||
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-%s-%d", account, tag, i + 1);
|
||||
responses.add(ConcurrentUtils.makeListenable(executor.submit(new Callable<Void>() {
|
||||
@Override
|
||||
public CreateNodeResponse runNode(String name, Template template, RunNodeOptions options) {
|
||||
checkArgument(template.getImage() instanceof CloudServersImage,
|
||||
"unexpected image type. should be CloudServersImage, was: "
|
||||
+ 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());
|
||||
public Void call() throws Exception {
|
||||
Server server = client.createServer(name, Integer.parseInt(template.getImage()
|
||||
.getId()), Integer.parseInt(template.getSize().getId()));
|
||||
|
||||
logger.debug(">> running server location(%s) image(%s) flavor(%s)", location,
|
||||
cloudServersImage.getId(), template.getSize().getId());
|
||||
|
||||
Server server = client.createServer(name, cloudServersImage.getImage().getId(),
|
||||
cloudServersSize.getFlavor().getId());
|
||||
|
||||
CreateNodeResponse node = new CreateNodeResponseImpl(server.getId() + "", name, location,
|
||||
null, server.getMetadata(), NodeState.RUNNING, server.getAddresses()
|
||||
.getPublicAddresses(), server.getAddresses().getPrivateAddresses(),
|
||||
new Credentials("root", server.getAdminPass()), ImmutableMap.<String, String> of());
|
||||
NodeMetadata node = new NodeMetadataImpl(server.getId() + "", name, null, null,
|
||||
server.getMetadata(), tag, NodeState.RUNNING, server.getAddresses()
|
||||
.getPublicAddresses(),
|
||||
server.getAddresses().getPrivateAddresses(), ImmutableMap
|
||||
.<String, String> of(), new Credentials("root", server
|
||||
.getAdminPass()));
|
||||
nodes.add(node);
|
||||
logger.debug("<< started server(%s)", server.getId());
|
||||
serverActive.apply(server);
|
||||
logger.debug("<< running server(%s)", server.getId());
|
||||
if (options.getRunScript() != null) {
|
||||
utils.runScriptOnNode(node, options.getRunScript());
|
||||
if (template.getOptions().getRunScript() != null) {
|
||||
utils.runScriptOnNode(node, template.getOptions().getRunScript());
|
||||
}
|
||||
return node;
|
||||
return null;
|
||||
}
|
||||
}), executor));
|
||||
}
|
||||
ConcurrentUtils.awaitCompletion(responses, executor, null, logger, "nodes");
|
||||
return new NodeSetImpl(nodes);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -165,33 +199,42 @@ public class CloudServersComputeService implements ComputeService {
|
|||
return serverToNodeMetadata.apply(client.getServer(Integer.parseInt(node.getId())));
|
||||
}
|
||||
|
||||
public static final Pattern TAG_PATTERN = Pattern.compile("[^-]+-([^-]+)-[0-9]+");
|
||||
|
||||
@Singleton
|
||||
private static class ServerToNodeMetadata implements Function<Server, NodeMetadata> {
|
||||
private final String location;
|
||||
private final Location location;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@Inject
|
||||
ServerToNodeMetadata(@ResourceLocation String location) {
|
||||
ServerToNodeMetadata(Location location) {
|
||||
this.location = location;
|
||||
}
|
||||
|
||||
@Override
|
||||
public NodeMetadata apply(Server from) {
|
||||
return new NodeMetadataImpl(from.getId() + "", from.getName(), location, null, from
|
||||
.getMetadata(), serverToNodeState.get(from.getStatus()), from.getAddresses()
|
||||
.getPublicAddresses(), from.getAddresses().getPrivateAddresses(), ImmutableMap
|
||||
.<String, String> of());
|
||||
Matcher matcher = TAG_PATTERN.matcher(from.getName());
|
||||
final String tag = matcher.find() ? matcher.group(1) : null;
|
||||
return new NodeMetadataImpl(from.getId() + "", from.getName(), location.getId(), null,
|
||||
from.getMetadata(), tag, serverToNodeState.get(from.getStatus()), from
|
||||
.getAddresses().getPublicAddresses(), from.getAddresses()
|
||||
.getPrivateAddresses(), ImmutableMap.<String, String> of(), null);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<ComputeMetadata> listNodes() {
|
||||
public Map<String, ? extends ComputeMetadata> getNodes() {
|
||||
logger.debug(">> listing servers");
|
||||
Set<ComputeMetadata> servers = Sets.newHashSet();
|
||||
Iterables.addAll(servers, Iterables.transform(client.listServers(ListOptions.Builder
|
||||
.withDetails()), serverToNodeMetadata));
|
||||
logger.debug("<< list(%d)", servers.size());
|
||||
return 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
|
||||
.listServers(ListOptions.Builder.withDetails()), serverToNodeMetadata),
|
||||
METADATA_TO_ID);
|
||||
return map;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -208,12 +251,62 @@ public class CloudServersComputeService implements ComputeService {
|
|||
}
|
||||
|
||||
@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();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<? extends Image> listImages() {
|
||||
public Map<String, ? extends Image> getImages() {
|
||||
return images.get();
|
||||
}
|
||||
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
*/
|
||||
package org.jclouds.rackspace.cloudservers.compute.config;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
|
@ -33,24 +34,30 @@ import org.jclouds.Constants;
|
|||
import org.jclouds.compute.ComputeService;
|
||||
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.OsFamily;
|
||||
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.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.rackspace.cloudservers.CloudServersAsyncClient;
|
||||
import org.jclouds.rackspace.cloudservers.CloudServersClient;
|
||||
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.domain.Flavor;
|
||||
import org.jclouds.rackspace.cloudservers.options.ListOptions;
|
||||
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.Maps;
|
||||
import com.google.common.collect.Sets;
|
||||
import com.google.inject.Provides;
|
||||
|
||||
|
@ -78,25 +85,44 @@ public class CloudServersComputeServiceContextModule extends CloudServersContext
|
|||
|
||||
@Provides
|
||||
@Singleton
|
||||
@ResourceLocation
|
||||
String getRegion() {
|
||||
return "default";
|
||||
Location getRegion() {
|
||||
return new LocationImpl(LocationScope.ZONE, "DALLAS", "Dallas, TX", null, true);
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
protected Set<? extends Size> provideSizes(CloudServersClient sync, Set<? extends Image> images,
|
||||
LogHolder holder, @Named(Constants.PROPERTY_USER_THREADS) ExecutorService executor)
|
||||
throws InterruptedException, TimeoutException, ExecutionException {
|
||||
Map<String, ? extends Location> provideLocations(Location location) {
|
||||
return ImmutableMap.of(location.getId(), location);
|
||||
}
|
||||
|
||||
@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();
|
||||
holder.logger.debug(">> providing sizes");
|
||||
for (final Flavor from : sync.listFlavors(ListOptions.Builder.withDetails())) {
|
||||
sizes.add(new CloudServersSize(from, from.getId() + "", from.getDisk() / 10,
|
||||
from.getRam(), from.getDisk(), ImmutableSet.<Architecture> of(
|
||||
Architecture.X86_32, Architecture.X86_64)));
|
||||
sizes.add(new SizeImpl(from.getId() + "", from.getName(), location.getId(), null,
|
||||
ImmutableMap.<String, String> of(), from.getDisk() / 10, from.getRam(), from
|
||||
.getDisk(), ImmutableSet.<Architecture> of(Architecture.X86_32,
|
||||
Architecture.X86_64)));
|
||||
}
|
||||
holder.logger.debug("<< sizes(%d)", sizes.size());
|
||||
return sizes;
|
||||
return Maps.uniqueIndex(sizes, indexer);
|
||||
}
|
||||
|
||||
private static class LogHolder {
|
||||
|
@ -109,9 +135,9 @@ public class CloudServersComputeServiceContextModule extends CloudServersContext
|
|||
|
||||
@Provides
|
||||
@Singleton
|
||||
protected Set<? extends Image> provideImages(final CloudServersClient sync,
|
||||
@ResourceLocation String location, LogHolder holder) throws InterruptedException,
|
||||
ExecutionException, TimeoutException {
|
||||
protected Map<String, ? extends Image> provideImages(final CloudServersClient sync,
|
||||
Location location, LogHolder holder, Function<ComputeMetadata, String> indexer)
|
||||
throws InterruptedException, ExecutionException, TimeoutException {
|
||||
final Set<Image> images = Sets.newHashSet();
|
||||
holder.logger.debug(">> providing images");
|
||||
for (final org.jclouds.rackspace.cloudservers.domain.Image from : sync
|
||||
|
@ -120,7 +146,6 @@ public class CloudServersComputeServiceContextModule extends CloudServersContext
|
|||
Architecture arch = Architecture.X86_64;
|
||||
String osDescription = "";
|
||||
String version = "";
|
||||
|
||||
Matcher matcher = RACKSPACE_PATTERN.matcher(from.getName());
|
||||
osDescription = from.getName();
|
||||
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));
|
||||
}
|
||||
}
|
||||
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());
|
||||
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.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.UnknownHostException;
|
||||
import java.util.Map;
|
||||
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.inject.Inject;
|
||||
|
@ -31,22 +38,24 @@ import javax.inject.Named;
|
|||
import javax.inject.Provider;
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import org.jclouds.Constants;
|
||||
import org.jclouds.compute.ComputeService;
|
||||
import org.jclouds.compute.domain.ComputeMetadata;
|
||||
import org.jclouds.compute.domain.ComputeType;
|
||||
import org.jclouds.compute.domain.CreateNodeResponse;
|
||||
import org.jclouds.compute.domain.Image;
|
||||
import org.jclouds.compute.domain.NodeMetadata;
|
||||
import org.jclouds.compute.domain.NodeSet;
|
||||
import org.jclouds.compute.domain.NodeState;
|
||||
import org.jclouds.compute.domain.Size;
|
||||
import org.jclouds.compute.domain.Template;
|
||||
import org.jclouds.compute.domain.TemplateBuilder;
|
||||
import org.jclouds.compute.domain.internal.CreateNodeResponseImpl;
|
||||
import org.jclouds.compute.domain.internal.NodeMetadataImpl;
|
||||
import org.jclouds.compute.options.RunNodeOptions;
|
||||
import org.jclouds.compute.domain.internal.NodeSetImpl;
|
||||
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.ResourceLocation;
|
||||
import org.jclouds.domain.Location;
|
||||
import org.jclouds.logging.Logger;
|
||||
import org.jclouds.rimuhosting.miro.RimuHostingClient;
|
||||
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.base.Function;
|
||||
import com.google.common.base.Predicate;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.Iterables;
|
||||
import com.google.common.collect.Maps;
|
||||
import com.google.common.collect.Sets;
|
||||
import com.google.common.util.concurrent.ListenableFuture;
|
||||
|
||||
/**
|
||||
* @author Ivan Meredith
|
||||
*/
|
||||
@Singleton
|
||||
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
|
||||
static Iterable<InetAddress> getPublicAddresses(Server server) {
|
||||
|
@ -122,20 +95,91 @@ public class RimuHostingComputeService implements ComputeService {
|
|||
});
|
||||
}
|
||||
|
||||
public Set<ComputeMetadata> listNodes() {
|
||||
Set<ComputeMetadata> serverSet = Sets.newLinkedHashSet();
|
||||
Set<Server> servers = client.getServerList();
|
||||
for (Server server : servers) {
|
||||
serverSet.add(toNode(server));
|
||||
}
|
||||
return serverSet;
|
||||
private static class NodeMatchesTag implements Predicate<NodeMetadata> {
|
||||
private final String tag;
|
||||
|
||||
@Override
|
||||
public boolean apply(NodeMetadata from) {
|
||||
return from.getTag().equals(tag);
|
||||
}
|
||||
|
||||
private NodeMetadataImpl toNode(Server server) {
|
||||
return new NodeMetadataImpl(server.getId() + "", server.getName(), location, null,
|
||||
ImmutableMap.<String, String> of(), NodeState.UNKNOWN, getPublicAddresses(server),
|
||||
ImmutableList.<InetAddress> of(), ImmutableMap.<String, String> of("state", server
|
||||
.getState()));
|
||||
public NodeMatchesTag(String tag) {
|
||||
super();
|
||||
this.tag = tag;
|
||||
}
|
||||
};
|
||||
|
||||
@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
|
||||
|
@ -143,7 +187,7 @@ public class RimuHostingComputeService implements ComputeService {
|
|||
checkArgument(node.getType() == ComputeType.NODE, "this is only valid for nodes, not "
|
||||
+ node.getType());
|
||||
checkNotNull(node.getId(), "node.id");
|
||||
return toNode(client.getServer(Long.parseLong(node.getId())));
|
||||
return serverToNodeMetadata.apply(client.getServer(Long.parseLong(node.getId())));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -151,21 +195,110 @@ public class RimuHostingComputeService implements ComputeService {
|
|||
checkArgument(node.getType() == ComputeType.NODE, "this is only valid for nodes, not "
|
||||
+ node.getType());
|
||||
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()));
|
||||
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
|
||||
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();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<? extends Image> listImages() {
|
||||
public Map<String, ? extends Image> getImages() {
|
||||
return images.get();
|
||||
}
|
||||
|
||||
@Override
|
||||
public TemplateBuilder templateBuilder() {
|
||||
return this.templateBuilderProvider.get();
|
||||
return templateBuilderProvider.get();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
*/
|
||||
package org.jclouds.rimuhosting.miro.compute.config;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
|
@ -33,6 +34,7 @@ import org.jclouds.Constants;
|
|||
import org.jclouds.compute.ComputeService;
|
||||
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.OsFamily;
|
||||
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.internal.ComputeServiceContextImpl;
|
||||
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.rest.RestContext;
|
||||
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.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.Maps;
|
||||
import com.google.common.collect.Sets;
|
||||
import com.google.inject.Provides;
|
||||
|
||||
|
@ -77,25 +84,66 @@ public class RimuHostingComputeServiceContextModule extends RimuHostingContextMo
|
|||
|
||||
@Provides
|
||||
@Singleton
|
||||
@ResourceLocation
|
||||
String getRegion() {
|
||||
return "default";
|
||||
Location getDefaultLocation(Map<String, ? extends Location> locations) {
|
||||
return locations.get("DCDALLAS");
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
protected Set<? extends Size> provideSizes(RimuHostingClient sync, Set<? extends Image> images,
|
||||
LogHolder holder, @Named(Constants.PROPERTY_USER_THREADS) ExecutorService userExecutor) throws InterruptedException,
|
||||
Map<String, ? extends Location> getDefaultLocations(RimuHostingClient sync, LogHolder holder,
|
||||
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 {
|
||||
final Set<Size> sizes = Sets.newHashSet();
|
||||
holder.logger.debug(">> providing sizes");
|
||||
for (final PricingPlan from : sync.getPricingPlanList()) {
|
||||
sizes.add(new SizeImpl(from.getId(), from.getDiskSize(), from.getRam(),
|
||||
from.getDiskSize(), ImmutableSet.<Architecture> of(Architecture.X86_32,
|
||||
try {
|
||||
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)));
|
||||
} catch (NullPointerException e) {
|
||||
holder.logger.warn("datacenter not present in " + from.getId());
|
||||
}
|
||||
}
|
||||
holder.logger.debug("<< sizes(%d)", sizes.size());
|
||||
return sizes;
|
||||
return Maps.uniqueIndex(sizes, indexer);
|
||||
}
|
||||
|
||||
private static class LogHolder {
|
||||
|
@ -108,9 +156,9 @@ public class RimuHostingComputeServiceContextModule extends RimuHostingContextMo
|
|||
|
||||
@Provides
|
||||
@Singleton
|
||||
protected Set<? extends Image> provideImages(final RimuHostingClient sync,
|
||||
@ResourceLocation String location, LogHolder holder) throws InterruptedException,
|
||||
ExecutionException, TimeoutException {
|
||||
protected Map<String, ? extends Image> provideImages(final RimuHostingClient sync,
|
||||
LogHolder holder, Function<ComputeMetadata, String> indexer)
|
||||
throws InterruptedException, ExecutionException, TimeoutException {
|
||||
final Set<Image> images = Sets.newHashSet();
|
||||
holder.logger.debug(">> providing images");
|
||||
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));
|
||||
}
|
||||
}
|
||||
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());
|
||||
return images;
|
||||
return Maps.uniqueIndex(images, indexer);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,10 +18,13 @@
|
|||
*/
|
||||
package org.jclouds.rimuhosting.miro.config;
|
||||
|
||||
import com.google.common.base.Predicate;
|
||||
import com.google.inject.AbstractModule;
|
||||
import com.google.inject.Provides;
|
||||
import org.jclouds.concurrent.internal.SyncProxy;
|
||||
import org.jclouds.http.RequiresHttp;
|
||||
import org.jclouds.predicates.RetryablePredicate;
|
||||
import org.jclouds.predicates.SocketOpen;
|
||||
import org.jclouds.rest.ConfiguresRestClient;
|
||||
import org.jclouds.rest.RestClientFactory;
|
||||
import org.jclouds.rimuhosting.miro.RimuHosting;
|
||||
|
@ -33,7 +36,9 @@ import org.jclouds.rimuhosting.miro.reference.RimuHostingConstants;
|
|||
import javax.inject.Named;
|
||||
import javax.inject.Singleton;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.URI;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* Configures the RimuHosting connection.
|
||||
|
@ -44,6 +49,12 @@ import java.net.URI;
|
|||
@ConfiguresRestClient
|
||||
public class RimuHostingRestClientModule extends AbstractModule {
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
protected Predicate<InetSocketAddress> socketTester(SocketOpen open) {
|
||||
return new RetryablePredicate<InetSocketAddress>(open, 130, 1, TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void configure() {
|
||||
bindErrorHandlers();
|
||||
|
@ -66,15 +77,16 @@ public class RimuHostingRestClientModule extends AbstractModule {
|
|||
|
||||
@Provides
|
||||
@Singleton
|
||||
public RimuHostingClient provideClient(RimuHostingAsyncClient client) throws IllegalArgumentException,
|
||||
SecurityException, NoSuchMethodException {
|
||||
public RimuHostingClient provideClient(RimuHostingAsyncClient client)
|
||||
throws IllegalArgumentException, SecurityException, NoSuchMethodException {
|
||||
return SyncProxy.create(RimuHostingClient.class, client);
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
@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);
|
||||
}
|
||||
|
||||
|
|
|
@ -36,7 +36,7 @@ public class RimuHostingComputeServiceLiveTest extends BaseComputeServiceLiveTes
|
|||
@Override
|
||||
public void setServiceDefaults() {
|
||||
service = "rimuhosting";
|
||||
nodeName = "rimuhosting.jclouds";
|
||||
tag = "rimuhosting.jclouds";
|
||||
}
|
||||
|
||||
protected Template buildTemplate(TemplateBuilder templateBuilder) {
|
||||
|
|
|
@ -2,28 +2,27 @@
|
|||
<!--
|
||||
|
||||
|
||||
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");
|
||||
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.
|
||||
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.
|
||||
====================================================================
|
||||
|
||||
-->
|
||||
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
|
||||
|
||||
<!--
|
||||
For more configuration infromation and examples see the Apache Log4j
|
||||
website: http://logging.apache.org/log4j/
|
||||
For more configuration infromation and examples see the Apache
|
||||
Log4j website: http://logging.apache.org/log4j/
|
||||
-->
|
||||
<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/"
|
||||
debug="false">
|
||||
|
@ -39,13 +38,17 @@
|
|||
<param name="Threshold" value="TRACE" />
|
||||
|
||||
<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" />
|
||||
|
||||
<!--
|
||||
The full pattern: Date MS Priority [Category] (Thread:NDC) Message${symbol_escape}n
|
||||
<param name="ConversionPattern" value="%d %-5r %-5p [%c] (%t:%x)
|
||||
%m%n"/>
|
||||
The full pattern: Date MS Priority [Category]
|
||||
(Thread:NDC) Message${symbol_escape}n <param
|
||||
name="ConversionPattern" value="%d %-5r %-5p [%c]
|
||||
(%t:%x) %m%n"/>
|
||||
-->
|
||||
</layout>
|
||||
</appender>
|
||||
|
@ -61,17 +64,45 @@
|
|||
<param name="Threshold" value="TRACE" />
|
||||
|
||||
<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" />
|
||||
|
||||
<!--
|
||||
The full pattern: Date MS Priority [Category] (Thread:NDC) Message${symbol_escape}n
|
||||
<param name="ConversionPattern" value="%d %-5r %-5p [%c] (%t:%x)
|
||||
%m%n"/>
|
||||
The full pattern: Date MS Priority [Category]
|
||||
(Thread:NDC) Message${symbol_escape}n <param
|
||||
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>
|
||||
</appender>
|
||||
|
||||
<appender name="ASYNCCOMPUTE" class="org.apache.log4j.AsyncAppender">
|
||||
<appender-ref ref="COMPUTEFILE" />
|
||||
</appender>
|
||||
<appender name="ASYNC" class="org.apache.log4j.AsyncAppender">
|
||||
<appender-ref ref="FILE" />
|
||||
</appender>
|
||||
|
@ -99,6 +130,11 @@
|
|||
<appender-ref ref="ASYNCWIRE" />
|
||||
</category>
|
||||
|
||||
<category name="jclouds.compute">
|
||||
<priority value="TRACE" />
|
||||
<appender-ref ref="ASYNCCOMPUTE" />
|
||||
</category>
|
||||
|
||||
<!-- ======================= -->
|
||||
<!-- Setup the Root category -->
|
||||
<!-- ======================= -->
|
||||
|
|
|
@ -2,4 +2,4 @@ service=ec2
|
|||
driver=aws
|
||||
account=accesskeyid
|
||||
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
|
||||
account=user@youregistered.com
|
||||
key=password
|
||||
nodename=name_of_your_vapp
|
||||
nodetag=name_of_your_vapp
|
||||
|
|
|
@ -2,4 +2,4 @@ service=cloudservers
|
|||
driver=rackspace
|
||||
account=user
|
||||
key=your_key
|
||||
nodename=name_of_your_server
|
||||
nodetag=name_of_your_server
|
||||
|
|
|
@ -2,4 +2,4 @@ service=rimuhosting
|
|||
driver=rimuhosting
|
||||
account=apikey
|
||||
key=apikey
|
||||
nodename=name_of_your_server
|
||||
nodetag=name_of_your_server
|
||||
|
|
|
@ -2,4 +2,4 @@ service=terremark
|
|||
driver=terremark
|
||||
account=user@youregistered.com
|
||||
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
|
||||
account=user@youregistered.com
|
||||
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 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}"/>
|
||||
|
||||
<target name="destroy" description="destroy the node ${nodename}">
|
||||
<compute action="destroy" provider="${url}">
|
||||
<node name="${nodename}" />
|
||||
<target name="destroy" description="destroy the nodes ${nodetag}">
|
||||
<compute actions="destroy" provider="${url}">
|
||||
<nodes tag="${nodetag}" />
|
||||
</compute>
|
||||
<sleep seconds="5" />
|
||||
</target>
|
||||
|
||||
<target name="create" description="create the node ${nodename}" depends="destroy" >
|
||||
<compute action="create" provider="${url}">
|
||||
<node name="${nodename}" os="UBUNTU" size="SMALLEST"
|
||||
<target name="create" description="create the nodes ${nodetag}" >
|
||||
<compute actions="destroy,create" provider="${url}">
|
||||
<nodes tag="${nodetag}" os="UBUNTU" size="SMALLEST"
|
||||
runscript="runscript.sh" openports="22,${listenport}"
|
||||
hostproperty="host" usernameproperty="username" passwordproperty="password" />
|
||||
</compute>
|
||||
</target>
|
||||
|
||||
<target name="cargooverssh" depends="create" description="run cargo on remote node" >
|
||||
<echo message="deploying tomcat and blaze to: ${nodename}" />
|
||||
<target name="cargooverssh" depends="create" description="run cargo on remote nodes" >
|
||||
<echo message="deploying tomcat and blaze to: ${nodetag}" />
|
||||
<cargo containerId="tomcat6x" output="build/output.log" log="build/cargo.log" action="start" timeout="600000">
|
||||
<zipurlinstaller installurl="${container.zip}" />
|
||||
<configuration home="build/cargo" type="standalone">
|
||||
|
|
|
@ -2,4 +2,4 @@ service=ec2
|
|||
driver=aws
|
||||
account=accesskeyid
|
||||
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
|
||||
account=user@youregistered.com
|
||||
key=password
|
||||
nodename=name_of_your_vapp
|
||||
nodetag=name_of_your_vapp
|
||||
|
|
|
@ -2,4 +2,4 @@ service=cloudservers
|
|||
driver=rackspace
|
||||
account=user
|
||||
key=your_key
|
||||
nodename=name_of_your_server
|
||||
nodetag=name_of_your_server
|
||||
|
|
|
@ -2,4 +2,4 @@ service=rimuhosting
|
|||
driver=rimuhosting
|
||||
account=apikey
|
||||
key=apikey
|
||||
nodename=name_of_your_server
|
||||
nodetag=name_of_your_server
|
||||
|
|
|
@ -2,4 +2,4 @@ service=terremark
|
|||
driver=terremark
|
||||
account=user@youregistered.com
|
||||
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
|
||||
account=user@youregistered.com
|
||||
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}" />
|
||||
|
||||
<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 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 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 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 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
|
||||
message="Which node do you wish to destroy"
|
||||
addproperty="nodename"
|
||||
addproperty="nodetag"
|
||||
/>
|
||||
|
||||
<compute action="destroy" provider="${jclouds.compute.url}">
|
||||
<node name="${nodename}" />
|
||||
<compute actions="destroy" provider="${jclouds.compute.url}">
|
||||
<node tag="${nodetag}" />
|
||||
</compute>
|
||||
</target>
|
||||
|
||||
<target name="get" description="get the node ${nodename}">
|
||||
<target name="get" description="get the node ${nodetag}">
|
||||
|
||||
<input
|
||||
message="Which node do you wish to describe?"
|
||||
addproperty="nodename"
|
||||
addproperty="nodetag"
|
||||
/>
|
||||
|
||||
<compute action="get" provider="${jclouds.compute.url}">
|
||||
<node name="${nodename}" />
|
||||
<compute actions="get" provider="${jclouds.compute.url}">
|
||||
<node tag="${nodetag}" />
|
||||
</compute>
|
||||
</target>
|
||||
|
||||
<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" />
|
||||
|
||||
<input
|
||||
message="What do you want to name your node?"
|
||||
addproperty="nodename"
|
||||
addproperty="nodetag"
|
||||
/>
|
||||
|
||||
<compute action="create" provider="${jclouds.compute.url}">
|
||||
<node name="${nodename}" location="${location}" os="${os}" size="SMALLEST" hostproperty="host" usernameproperty="username" passwordproperty="password" />
|
||||
<compute actions="create" provider="${jclouds.compute.url}">
|
||||
<node tag="${nodetag}" location="${location}" os="${os}" size="SMALLEST" hostproperty="host" usernameproperty="username" passwordproperty="password" />
|
||||
</compute>
|
||||
</target>
|
||||
|
||||
|
|
|
@ -18,11 +18,9 @@
|
|||
*/
|
||||
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.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.getNodeOptionsFromElement;
|
||||
import static org.jclouds.tools.ant.taskdefs.compute.ComputeTaskUtils.ipOrEmptyString;
|
||||
|
||||
import java.io.File;
|
||||
|
@ -39,15 +37,16 @@ import org.apache.tools.ant.Task;
|
|||
import org.jclouds.compute.ComputeService;
|
||||
import org.jclouds.compute.ComputeServiceContext;
|
||||
import org.jclouds.compute.domain.ComputeMetadata;
|
||||
import org.jclouds.compute.domain.CreateNodeResponse;
|
||||
import org.jclouds.compute.domain.Image;
|
||||
import org.jclouds.compute.domain.NodeMetadata;
|
||||
import org.jclouds.compute.domain.Size;
|
||||
import org.jclouds.compute.domain.Template;
|
||||
import org.jclouds.compute.options.RunNodeOptions;
|
||||
import org.jclouds.domain.Location;
|
||||
import org.jclouds.http.HttpUtils;
|
||||
|
||||
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.inject.Provider;
|
||||
|
||||
|
@ -59,7 +58,7 @@ public class ComputeTask extends Task {
|
|||
|
||||
private final Map<URI, ComputeServiceContext> computeMap;
|
||||
private String provider;
|
||||
private String action;
|
||||
private String actions;
|
||||
private NodeElement nodeElement;
|
||||
|
||||
/**
|
||||
|
@ -82,7 +81,7 @@ public class ComputeTask extends Task {
|
|||
}
|
||||
|
||||
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 {
|
||||
ComputeServiceContext context = computeMap.get(HttpUtils.createUri(provider));
|
||||
Action action = Action.valueOf(CaseFormat.LOWER_HYPHEN.to(CaseFormat.UPPER_UNDERSCORE,
|
||||
this.action));
|
||||
|
||||
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 {
|
||||
context.close();
|
||||
}
|
||||
|
@ -132,6 +134,9 @@ public class ComputeTask extends Task {
|
|||
case LIST_SIZES:
|
||||
listSizes(computeService);
|
||||
break;
|
||||
case LIST_LOCATIONS:
|
||||
listLocations(computeService);
|
||||
break;
|
||||
default:
|
||||
this.log("bad action: " + action, Project.MSG_ERR);
|
||||
}
|
||||
|
@ -139,7 +144,7 @@ public class ComputeTask extends Task {
|
|||
|
||||
private void listDetails(ComputeService computeService) {
|
||||
log("list details");
|
||||
for (ComputeMetadata node : computeService.listNodes()) {// TODO
|
||||
for (ComputeMetadata node : computeService.getNodes().values()) {// TODO
|
||||
// parallel
|
||||
logDetails(computeService, node);
|
||||
}
|
||||
|
@ -147,58 +152,67 @@ public class ComputeTask extends Task {
|
|||
|
||||
private void listImages(ComputeService computeService) {
|
||||
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",
|
||||
image.getLocation(), image.getId(), image.getVersion(), image.getArchitecture(),
|
||||
image.getOsFamily(), image.getOsDescription()));
|
||||
image.getLocationId(), image.getId(), image.getVersion(),
|
||||
image.getArchitecture(), image.getOsFamily(), image.getOsDescription()));
|
||||
}
|
||||
}
|
||||
|
||||
private void listSizes(ComputeService computeService) {
|
||||
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
|
||||
.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) {
|
||||
log("list");
|
||||
for (ComputeMetadata node : computeService.listNodes()) {
|
||||
log(String.format(" location=%s, id=%s, name=%s", node.getLocation(), node.getId(), node
|
||||
.getName()));
|
||||
for (ComputeMetadata node : computeService.getNodes().values()) {
|
||||
log(String.format(" location=%s, id=%s, tag=%s", node.getLocationId(), node.getId(),
|
||||
node.getName()));
|
||||
}
|
||||
}
|
||||
|
||||
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(),
|
||||
nodeElement.getOs()));
|
||||
log(String.format("create tag: %s, count: %d, size: %s, os: %s", tag, nodeElement.getCount(),
|
||||
nodeElement.getSize(), nodeElement.getOs()));
|
||||
|
||||
Template template = createTemplateFromElement(nodeElement, computeService);
|
||||
|
||||
RunNodeOptions options = getNodeOptionsFromElement(nodeElement);
|
||||
|
||||
CreateNodeResponse createdNode = computeService.runNode(name, template, options);
|
||||
NodeMetadata createdNode = Iterables.getOnlyElement(computeService.runNodes(tag, nodeElement
|
||||
.getCount(), template));
|
||||
|
||||
logNodeDetails(createdNode);
|
||||
|
||||
addNodeDetailsAsProjectProperties(createdNode);
|
||||
}
|
||||
|
||||
private void logNodeDetails(CreateNodeResponse createdNode) {
|
||||
log(String.format(" id=%s, name=%s, connection=%s:%s@%s", createdNode.getId(), createdNode
|
||||
.getName(), createdNode.getCredentials().account, createdNode.getCredentials().key,
|
||||
createdNode.getPublicAddresses().first().getHostAddress()));
|
||||
private void logNodeDetails(NodeMetadata createdNode) {
|
||||
log(String.format(" id=%s, tag=%s, location=%s, tag=%s, connection=%s:%s@%s", createdNode
|
||||
.getId(), createdNode.getTag(), createdNode.getLocationId(), createdNode.getName(),
|
||||
createdNode.getCredentials().account, createdNode.getCredentials().key,
|
||||
ipOrEmptyString(createdNode.getPublicAddresses())));
|
||||
}
|
||||
|
||||
private void addNodeDetailsAsProjectProperties(CreateNodeResponse createdNode) {
|
||||
private void addNodeDetailsAsProjectProperties(NodeMetadata createdNode) {
|
||||
if (nodeElement.getIdproperty() != null)
|
||||
getProject().setProperty(nodeElement.getIdproperty(), createdNode.getId());
|
||||
if (nodeElement.getHostproperty() != null)
|
||||
getProject().setProperty(nodeElement.getHostproperty(),
|
||||
createdNode.getPublicAddresses().first().getHostAddress());
|
||||
ipOrEmptyString(createdNode.getPublicAddresses()));
|
||||
if (nodeElement.getKeyfile() != null && isKeyAuth(createdNode))
|
||||
try {
|
||||
Files.write(createdNode.getCredentials().key, new File(nodeElement.getKeyfile()),
|
||||
|
@ -215,54 +229,49 @@ public class ComputeTask extends Task {
|
|||
}
|
||||
|
||||
private void destroy(ComputeService computeService) {
|
||||
log(String.format("destroy name: %s", nodeElement.getName()));
|
||||
Iterable<? extends ComputeMetadata> nodesThatMatch = filterByName(computeService.listNodes(),
|
||||
nodeElement.getName());
|
||||
for (ComputeMetadata node : nodesThatMatch) {
|
||||
log(String.format(" destroying id=%s, name=%s", node.getId(), node.getName()));
|
||||
computeService.destroyNode(node);
|
||||
}
|
||||
log(String.format("destroy tag: %s", nodeElement.getTag()));
|
||||
computeService.destroyNodes(nodeElement.getTag());
|
||||
}
|
||||
|
||||
private void get(ComputeService computeService) {
|
||||
log(String.format("get name: %s", nodeElement.getName()));
|
||||
Iterable<? extends ComputeMetadata> nodesThatMatch = filterByName(computeService.listNodes(),
|
||||
nodeElement.getName());
|
||||
for (ComputeMetadata node : nodesThatMatch) {
|
||||
log(String.format("get tag: %s", nodeElement.getTag()));
|
||||
for (ComputeMetadata node : computeService.getNodes(nodeElement.getTag())) {
|
||||
logDetails(computeService, 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
|
||||
.format(
|
||||
" node id=%s, name=%s, location=%s, state=%s, publicIp=%s, privateIp=%s, extra=%s",
|
||||
metadata.getId(), node.getName(), node.getLocation(), metadata.getState(),
|
||||
ipOrEmptyString(metadata.getPublicAddresses()), ipOrEmptyString(metadata
|
||||
.getPrivateAddresses()), metadata.getExtra()));
|
||||
" node id=%s, name=%s, tag=%s, location=%s, state=%s, publicIp=%s, privateIp=%s, extra=%s",
|
||||
metadata.getId(), metadata.getName(), metadata.getTag(), metadata
|
||||
.getLocationId(), metadata.getState(), ComputeTaskUtils
|
||||
.ipOrEmptyString(metadata.getPublicAddresses()),
|
||||
ipOrEmptyString(metadata.getPrivateAddresses()), metadata.getExtra()));
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the configured {@link NodeElement} element
|
||||
*/
|
||||
public final NodeElement createNode() {
|
||||
if (getNode() == null) {
|
||||
public final NodeElement createNodes() {
|
||||
if (getNodes() == null) {
|
||||
this.nodeElement = new NodeElement();
|
||||
}
|
||||
return this.nodeElement;
|
||||
}
|
||||
|
||||
public NodeElement getNode() {
|
||||
public NodeElement getNodes() {
|
||||
return this.nodeElement;
|
||||
}
|
||||
|
||||
public String getAction() {
|
||||
return action;
|
||||
public String getActions() {
|
||||
return actions;
|
||||
}
|
||||
|
||||
public void setAction(String action) {
|
||||
this.action = action;
|
||||
public void setActions(String actions) {
|
||||
this.actions = actions;
|
||||
}
|
||||
|
||||
public NodeElement getNodeElement() {
|
||||
|
|
|
@ -31,24 +31,22 @@ import java.net.URI;
|
|||
import java.util.Map;
|
||||
import java.util.NoSuchElementException;
|
||||
import java.util.Properties;
|
||||
import java.util.SortedSet;
|
||||
import java.util.Set;
|
||||
|
||||
import org.apache.tools.ant.BuildException;
|
||||
import org.apache.tools.ant.Project;
|
||||
import org.jclouds.compute.ComputeService;
|
||||
import org.jclouds.compute.ComputeServiceContext;
|
||||
import org.jclouds.compute.ComputeServiceContextFactory;
|
||||
import org.jclouds.compute.domain.Image;
|
||||
import org.jclouds.compute.domain.OsFamily;
|
||||
import org.jclouds.compute.domain.Template;
|
||||
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.ssh.jsch.config.JschSshClientModule;
|
||||
import org.jclouds.tools.ant.logging.config.AntLoggingModule;
|
||||
|
||||
import com.google.common.base.Function;
|
||||
import com.google.common.base.Predicate;
|
||||
import com.google.common.base.Splitter;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.collect.Iterables;
|
||||
|
@ -99,20 +97,11 @@ public class ComputeTaskUtils {
|
|||
static Template createTemplateFromElement(NodeElement nodeElement, ComputeService computeService) {
|
||||
TemplateBuilder templateBuilder = computeService.templateBuilder();
|
||||
if (nodeElement.getLocation() != null && !"".equals(nodeElement.getLocation()))
|
||||
templateBuilder.location(nodeElement.getLocation());
|
||||
templateBuilder.locationId(nodeElement.getLocation());
|
||||
if (nodeElement.getImage() != null && !"".equals(nodeElement.getImage())) {
|
||||
final String imageId = nodeElement.getImage();
|
||||
try {
|
||||
Image image = Iterables.getOnlyElement(Iterables.filter(computeService.listImages(),
|
||||
new Predicate<Image>() {
|
||||
|
||||
@Override
|
||||
public boolean apply(Image input) {
|
||||
return input.getId().equals(imageId);
|
||||
}
|
||||
|
||||
}));
|
||||
templateBuilder.fromImage(image);
|
||||
templateBuilder.imageId(imageId);
|
||||
} catch (NoSuchElementException e) {
|
||||
throw new BuildException("image not found " + nodeElement.getImage());
|
||||
}
|
||||
|
@ -120,6 +109,8 @@ public class ComputeTaskUtils {
|
|||
templateBuilder.osFamily(OsFamily.valueOf(nodeElement.getOs()));
|
||||
}
|
||||
addSizeFromElementToTemplate(nodeElement, templateBuilder);
|
||||
templateBuilder.options(getNodeOptionsFromElement(nodeElement));
|
||||
|
||||
return templateBuilder.build();
|
||||
}
|
||||
|
||||
|
@ -136,15 +127,15 @@ public class ComputeTaskUtils {
|
|||
}
|
||||
}
|
||||
|
||||
static RunNodeOptions getNodeOptionsFromElement(NodeElement nodeElement) {
|
||||
RunNodeOptions options = new RunNodeOptions()
|
||||
.openPorts(getPortsToOpenFromElement(nodeElement));
|
||||
static TemplateOptions getNodeOptionsFromElement(NodeElement nodeElement) {
|
||||
TemplateOptions options = new TemplateOptions()
|
||||
.inboundPorts(getPortsToOpenFromElement(nodeElement));
|
||||
addRunScriptToOptionsIfPresentInNodeElement(nodeElement, options);
|
||||
return options;
|
||||
}
|
||||
|
||||
static void addRunScriptToOptionsIfPresentInNodeElement(NodeElement nodeElement,
|
||||
RunNodeOptions options) {
|
||||
TemplateOptions options) {
|
||||
if (nodeElement.getRunscript() != null)
|
||||
try {
|
||||
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) {
|
||||
return set.last().getHostAddress();
|
||||
return Iterables.get(set, 0).getHostAddress();
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
|
|
|
@ -25,10 +25,11 @@ import java.io.File;
|
|||
* @author Ivan Meredith
|
||||
*/
|
||||
public class NodeElement {
|
||||
private String name;
|
||||
private String tag;
|
||||
private String size;
|
||||
private String os;
|
||||
private String image;
|
||||
private int count = 1;
|
||||
private String openports = "22";
|
||||
private String passwordproperty;
|
||||
private String keyfile;
|
||||
|
@ -46,14 +47,6 @@ public class NodeElement {
|
|||
this.location = location;
|
||||
}
|
||||
|
||||
String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
String getUsernameproperty() {
|
||||
return usernameproperty;
|
||||
}
|
||||
|
@ -153,4 +146,20 @@ public class NodeElement {
|
|||
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.checkNotNull;
|
||||
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 java.net.InetAddress;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.inject.Named;
|
||||
import javax.inject.Provider;
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import org.jclouds.Constants;
|
||||
import org.jclouds.compute.ComputeService;
|
||||
import org.jclouds.compute.domain.ComputeMetadata;
|
||||
import org.jclouds.compute.domain.ComputeType;
|
||||
import org.jclouds.compute.domain.CreateNodeResponse;
|
||||
import org.jclouds.compute.domain.Image;
|
||||
import org.jclouds.compute.domain.NodeMetadata;
|
||||
import org.jclouds.compute.domain.NodeSet;
|
||||
import org.jclouds.compute.domain.NodeState;
|
||||
import org.jclouds.compute.domain.Size;
|
||||
import org.jclouds.compute.domain.Template;
|
||||
import org.jclouds.compute.domain.TemplateBuilder;
|
||||
import org.jclouds.compute.domain.internal.CreateNodeResponseImpl;
|
||||
import org.jclouds.compute.domain.internal.NodeMetadataImpl;
|
||||
import org.jclouds.compute.options.RunNodeOptions;
|
||||
import org.jclouds.compute.domain.internal.NodeSetImpl;
|
||||
import org.jclouds.compute.reference.ComputeServiceConstants;
|
||||
import org.jclouds.compute.util.ComputeUtils;
|
||||
import org.jclouds.domain.Credentials;
|
||||
import org.jclouds.domain.Location;
|
||||
import org.jclouds.logging.Logger;
|
||||
import org.jclouds.vcloud.VCloudClient;
|
||||
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.options.InstantiateVAppTemplateOptions;
|
||||
|
||||
import com.google.common.base.Function;
|
||||
import com.google.common.base.Predicate;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.collect.Iterables;
|
||||
import com.google.common.collect.Maps;
|
||||
import com.google.common.collect.Sets;
|
||||
import com.google.common.util.concurrent.ListenableFuture;
|
||||
import com.google.inject.Inject;
|
||||
|
||||
/**
|
||||
|
@ -69,16 +78,33 @@ import com.google.inject.Inject;
|
|||
*/
|
||||
@Singleton
|
||||
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
|
||||
@Named(ComputeServiceConstants.COMPUTE_LOGGER)
|
||||
protected Logger logger = Logger.NULL;
|
||||
private final VCloudClient client;
|
||||
protected final Provider<Set<? extends Image>> images;
|
||||
protected final Provider<Set<? extends Size>> sizes;
|
||||
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;
|
||||
protected final ComputeUtils utils;
|
||||
protected final Predicate<String> taskTester;
|
||||
protected final Predicate<VApp> notFoundTester;
|
||||
protected final ExecutorService executor;
|
||||
|
||||
protected static final Map<VAppStatus, NodeState> vAppStatusToNodeState = ImmutableMap
|
||||
.<VAppStatus, NodeState> builder().put(VAppStatus.OFF, NodeState.TERMINATED).put(
|
||||
|
@ -89,65 +115,92 @@ public class VCloudComputeService implements ComputeService, VCloudComputeClient
|
|||
@Inject
|
||||
public VCloudComputeService(VCloudClient client,
|
||||
Provider<TemplateBuilder> templateBuilderProvider,
|
||||
Provider<Set<? extends Image>> images, Provider<Set<? extends Size>> sizes,
|
||||
ComputeUtils utils, Predicate<String> successTester,
|
||||
@Named("NOT_FOUND") Predicate<VApp> notFoundTester) {
|
||||
Provider<Map<String, ? extends Image>> images,
|
||||
Provider<Map<String, ? extends Size>> sizes,
|
||||
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.client = client;
|
||||
this.images = images;
|
||||
this.sizes = sizes;
|
||||
this.locations = locations;
|
||||
this.templateBuilderProvider = templateBuilderProvider;
|
||||
this.utils = utils;
|
||||
this.notFoundTester = notFoundTester;
|
||||
this.executor = executor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CreateNodeResponse runNode(String name, Template template) {
|
||||
return this.runNode(name, template, RunNodeOptions.NONE);
|
||||
public NodeSet runNodes(final String tag, int max, final Template template) {
|
||||
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
|
||||
public CreateNodeResponse runNode(String name, Template template, RunNodeOptions options) {
|
||||
checkNotNull(template.getImage().getLocation(), "location");
|
||||
Map<String, String> metaMap = start(template.getImage().getLocation(), name, template
|
||||
.getImage().getId(), template.getSize().getCores(), template.getSize().getRam(),
|
||||
template.getSize().getDisk() * 1024 * 1024l, ImmutableMap.<String, String> of(),
|
||||
options.getOpenPorts());
|
||||
private void runVAppAndAddToSet(String name, String tag, Template template,
|
||||
Set<NodeMetadata> nodes) {
|
||||
Map<String, String> metaMap = start(template.getLocation().getId(), name, template.getImage()
|
||||
.getId(), template.getSize().getCores(), template.getSize().getRam(), template
|
||||
.getSize().getDisk() * 1024 * 1024l, ImmutableMap.<String, String> of(), template
|
||||
.getOptions().getInboundPorts());
|
||||
VApp vApp = client.getVApp(metaMap.get("id"));
|
||||
CreateNodeResponse node = newCreateNodeResponse(template, metaMap, vApp);
|
||||
if (options.getRunScript() != null) {
|
||||
utils.runScriptOnNode(node, options.getRunScript());
|
||||
NodeMetadata node = newCreateNodeResponse(tag, template, metaMap, vApp);
|
||||
nodes.add(node);
|
||||
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) {
|
||||
return new CreateNodeResponseImpl(vApp.getId(), vApp.getName(), template.getImage()
|
||||
.getLocation(), vApp.getLocation(), ImmutableMap.<String, String> of(),
|
||||
vAppStatusToNodeState.get(vApp.getStatus()), getPublicAddresses(vApp.getId()),
|
||||
getPrivateAddresses(vApp.getId()), new Credentials(metaMap.get("username"), metaMap
|
||||
.get("password")), ImmutableMap.<String, String> of());
|
||||
return new NodeMetadataImpl(vApp.getId(), vApp.getName(), template.getLocation().getId(),
|
||||
vApp.getLocation(), ImmutableMap.<String, String> of(), tag, vAppStatusToNodeState
|
||||
.get(vApp.getStatus()), getPublicAddresses(vApp.getId()),
|
||||
getPrivateAddresses(vApp.getId()), ImmutableMap.<String, String> of(),
|
||||
new Credentials(metaMap.get("username"), metaMap.get("password")));
|
||||
}
|
||||
|
||||
@Override
|
||||
public NodeMetadata getNodeMetadata(ComputeMetadata node) {
|
||||
checkArgument(node.getType() == ComputeType.NODE, "this is only valid for nodes, not "
|
||||
+ node.getType());
|
||||
return getNodeMetadataByIdInVDC(checkNotNull(node.getLocation(), "location"), checkNotNull(
|
||||
return getNodeMetadataByIdInVDC(checkNotNull(node.getLocationId(), "location"), checkNotNull(
|
||||
node.getId(), "node.id"));
|
||||
}
|
||||
|
||||
protected NodeMetadata getNodeMetadataByIdInVDC(String vDCId, String id) {
|
||||
VApp vApp = client.getVApp(id);
|
||||
String tag = vApp.getName().replaceAll("-[0-9]+", "");
|
||||
return new NodeMetadataImpl(vApp.getId(), vApp.getName(), vDCId, vApp.getLocation(),
|
||||
ImmutableMap.<String, String> of(), vAppStatusToNodeState.get(vApp.getStatus()),
|
||||
vApp.getNetworkToAddresses().values(), ImmutableSet.<InetAddress> of(), ImmutableMap
|
||||
.<String, String> of());
|
||||
ImmutableMap.<String, String> of(), tag,
|
||||
vAppStatusToNodeState.get(vApp.getStatus()), vApp.getNetworkToAddresses().values(),
|
||||
ImmutableSet.<InetAddress> of(), ImmutableMap.<String, String> of(), null);
|
||||
}
|
||||
|
||||
@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();
|
||||
for (NamedResource vdc : client.getDefaultOrganization().getVDCs().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
|
||||
|
@ -172,12 +225,12 @@ public class VCloudComputeService implements ComputeService, VCloudComputeClient
|
|||
}
|
||||
|
||||
@Override
|
||||
public Set<? extends Size> listSizes() {
|
||||
public Map<String, ? extends Size> getSizes() {
|
||||
return sizes.get();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<? extends Image> listImages() {
|
||||
public Map<String, ? extends Image> getImages() {
|
||||
return images.get();
|
||||
}
|
||||
|
||||
|
@ -300,4 +353,53 @@ public class VCloudComputeService implements ComputeService, VCloudComputeClient
|
|||
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;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
|
@ -32,6 +33,7 @@ import org.jclouds.Constants;
|
|||
import org.jclouds.compute.ComputeService;
|
||||
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.OsFamily;
|
||||
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.reference.ComputeServiceConstants;
|
||||
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.rest.RestContext;
|
||||
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.NamedResource;
|
||||
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.Iterables;
|
||||
import com.google.common.collect.Maps;
|
||||
import com.google.common.collect.Sets;
|
||||
import com.google.common.util.concurrent.ListenableFuture;
|
||||
import com.google.inject.Injector;
|
||||
|
@ -91,13 +100,6 @@ public class VCloudComputeServiceContextModule extends VCloudContextModule {
|
|||
return new ComputeServiceContextImpl<VCloudAsyncClient, VCloudClient>(computeService, context);
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
@ResourceLocation
|
||||
String getVDC(VCloudClient client) {
|
||||
return client.getDefaultVDC().getId();
|
||||
}
|
||||
|
||||
protected static class LogHolder {
|
||||
@Resource
|
||||
@Named(ComputeServiceConstants.COMPUTE_LOGGER)
|
||||
|
@ -106,10 +108,12 @@ public class VCloudComputeServiceContextModule extends VCloudContextModule {
|
|||
|
||||
@Provides
|
||||
@Singleton
|
||||
protected Set<? extends Image> provideImages(final VCloudClient client,
|
||||
final @ResourceLocation String vDC, LogHolder holder,
|
||||
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService executor)
|
||||
throws InterruptedException, ExecutionException, TimeoutException {
|
||||
protected Map<String, ? extends Image> provideImages(final VCloudClient client,
|
||||
final Location vDC, LogHolder holder,
|
||||
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService executor,
|
||||
Function<ComputeMetadata, String> indexer) throws InterruptedException,
|
||||
ExecutionException, TimeoutException {
|
||||
// TODO multi-VDC
|
||||
final Set<Image> images = Sets.newHashSet();
|
||||
holder.logger.debug(">> providing images");
|
||||
Catalog response = client.getDefaultCatalog();
|
||||
|
@ -132,8 +136,9 @@ public class VCloudComputeServiceContextModule extends VCloudContextModule {
|
|||
Architecture arch = resource.getName().indexOf("64") == -1 ? Architecture.X86_32
|
||||
: Architecture.X86_64;
|
||||
VAppTemplate template = client.getVAppTemplate(item.getEntity().getId());
|
||||
images.add(new ImageImpl(resource.getId(), template.getName(), "", myOs,
|
||||
template.getName(), vDC, arch));
|
||||
images.add(new ImageImpl(resource.getId(), template.getName(), vDC.getId(),
|
||||
template.getLocation(), ImmutableMap.<String, String> of(), template
|
||||
.getDescription(), "", myOs, template.getName(), arch));
|
||||
return null;
|
||||
}
|
||||
}), executor));
|
||||
|
@ -142,21 +147,60 @@ public class VCloudComputeServiceContextModule extends VCloudContextModule {
|
|||
}
|
||||
|
||||
ConcurrentUtils.awaitCompletion(responses, executor, null, holder.logger, "images");
|
||||
return images;
|
||||
return Maps.uniqueIndex(images, indexer);
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
protected Set<? extends Size> provideSizes(VCloudClient client, Set<? extends Image> images,
|
||||
LogHolder holder, @Named(Constants.PROPERTY_USER_THREADS) ExecutorService executor)
|
||||
protected Function<ComputeMetadata, String> indexer() {
|
||||
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 {
|
||||
Set<Size> sizes = Sets.newHashSet();
|
||||
for (int cpus : new int[] { 1, 2, 4 })
|
||||
for (int ram : new int[] { 512, 1024, 2048, 4096, 8192, 16384 })
|
||||
sizes.add(new SizeImpl(String.format("cpu=%d,ram=%s,disk=%d", cpus, ram, 10), cpus,
|
||||
ram, 10, ImmutableSet.<Architecture> of(Architecture.X86_32,
|
||||
Architecture.X86_64)));
|
||||
return sizes;
|
||||
sizes.add(new SizeImpl(String.format("cpu=%d,ram=%s,disk=%d", cpus, ram, 10), null,
|
||||
null, null, ImmutableMap.<String, String> of(), cpus, ram, 10, ImmutableSet
|
||||
.<Architecture> of(Architecture.X86_32, Architecture.X86_64)));
|
||||
return Maps.uniqueIndex(sizes, indexer);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -29,12 +29,12 @@ import static org.testng.Assert.assertNotNull;
|
|||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.URI;
|
||||
import java.util.List;
|
||||
import java.util.Properties;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import javax.inject.Named;
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import org.jclouds.PropertiesBuilder;
|
||||
import org.jclouds.concurrent.config.ExecutorServiceModule;
|
||||
import org.jclouds.encryption.EncryptionService;
|
||||
import org.jclouds.http.RequiresHttp;
|
||||
|
@ -139,7 +139,18 @@ public class VCloudLoginLiveTest {
|
|||
context = new RestContextBuilder<VCloudLoginAsyncClient, 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) {
|
||||
|
||||
|
|
|
@ -3,17 +3,19 @@ package org.jclouds.vcloud.hostingdotcom.compute;
|
|||
import static com.google.common.base.Preconditions.checkState;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Named;
|
||||
import javax.inject.Provider;
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import org.jclouds.Constants;
|
||||
import org.jclouds.compute.domain.Image;
|
||||
import org.jclouds.compute.domain.Size;
|
||||
import org.jclouds.compute.domain.TemplateBuilder;
|
||||
import org.jclouds.compute.util.ComputeUtils;
|
||||
import org.jclouds.domain.Location;
|
||||
import org.jclouds.vcloud.VCloudClient;
|
||||
import org.jclouds.vcloud.compute.VCloudComputeService;
|
||||
import org.jclouds.vcloud.domain.VApp;
|
||||
|
@ -29,12 +31,15 @@ import com.google.common.collect.ImmutableMap;
|
|||
public class HostingDotComVCloudComputeService extends VCloudComputeService {
|
||||
|
||||
@Inject
|
||||
HostingDotComVCloudComputeService(VCloudClient client,
|
||||
public HostingDotComVCloudComputeService(VCloudClient client,
|
||||
Provider<TemplateBuilder> templateBuilderProvider,
|
||||
Provider<Set<? extends Image>> images, Provider<Set<? extends Size>> sizes,
|
||||
Predicate<String> successTester, ComputeUtils utils,
|
||||
@Named("NOT_FOUND") Predicate<VApp> notFoundTester) {
|
||||
super(client, templateBuilderProvider, images, sizes, utils, successTester, notFoundTester);
|
||||
Provider<Map<String, ? extends Image>> images,
|
||||
Provider<Map<String, ? extends Size>> sizes,
|
||||
Provider<Map<String, ? extends Location>> locations, ComputeUtils utils,
|
||||
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
|
||||
|
|
|
@ -24,6 +24,7 @@ import java.net.InetAddress;
|
|||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.SortedSet;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.inject.Inject;
|
||||
|
@ -31,6 +32,7 @@ import javax.inject.Named;
|
|||
import javax.inject.Provider;
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import org.jclouds.Constants;
|
||||
import org.jclouds.compute.domain.Image;
|
||||
import org.jclouds.compute.domain.NodeMetadata;
|
||||
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.reference.ComputeServiceConstants;
|
||||
import org.jclouds.compute.util.ComputeUtils;
|
||||
import org.jclouds.domain.Location;
|
||||
import org.jclouds.logging.Logger;
|
||||
import org.jclouds.vcloud.compute.VCloudComputeService;
|
||||
import org.jclouds.vcloud.domain.VApp;
|
||||
|
@ -65,10 +68,13 @@ public class TerremarkVCloudComputeService extends VCloudComputeService {
|
|||
@Inject
|
||||
public TerremarkVCloudComputeService(TerremarkVCloudClient client,
|
||||
Provider<TemplateBuilder> templateBuilderProvider,
|
||||
Provider<Set<? extends Image>> images, Provider<Set<? extends Size>> sizes,
|
||||
ComputeUtils utils, Predicate<String> successTester,
|
||||
@Named("NOT_FOUND") Predicate<VApp> notFoundTester) {
|
||||
super(client, templateBuilderProvider, images, sizes, utils, successTester, notFoundTester);
|
||||
Provider<Map<String, ? extends Image>> images,
|
||||
Provider<Map<String, ? extends Size>> sizes,
|
||||
Provider<Map<String, ? extends Location>> locations, ComputeUtils utils,
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -91,10 +97,11 @@ public class TerremarkVCloudComputeService extends VCloudComputeService {
|
|||
@Override
|
||||
protected NodeMetadata getNodeMetadataByIdInVDC(String vDCId, String id) {
|
||||
VApp vApp = client.getVApp(id);
|
||||
String tag = vApp.getName().replaceAll("-[0-9]+", "");
|
||||
return new NodeMetadataImpl(vApp.getId(), vApp.getName(), vDCId, vApp.getLocation(),
|
||||
ImmutableMap.<String, String> of(), vAppStatusToNodeState.get(vApp.getStatus()),
|
||||
getPublicAddresses(id), vApp.getNetworkToAddresses().values(), ImmutableMap
|
||||
.<String, String> of());
|
||||
ImmutableMap.<String, String> of(), tag,
|
||||
vAppStatusToNodeState.get(vApp.getStatus()), getPublicAddresses(id), vApp
|
||||
.getNetworkToAddresses().values(), ImmutableMap.<String, String> of(), null);
|
||||
}
|
||||
|
||||
public InetAddress createPublicAddressMappedToPorts(String vAppId, int... ports) {
|
||||
|
|
|
@ -18,15 +18,18 @@
|
|||
*/
|
||||
package org.jclouds.vcloud.terremark.compute.config;
|
||||
|
||||
import java.util.Set;
|
||||
import java.util.Map;
|
||||
import java.util.SortedSet;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
|
||||
import javax.inject.Named;
|
||||
|
||||
import org.jclouds.Constants;
|
||||
import org.jclouds.compute.ComputeService;
|
||||
import org.jclouds.compute.domain.Architecture;
|
||||
import org.jclouds.compute.domain.ComputeMetadata;
|
||||
import org.jclouds.compute.domain.Image;
|
||||
import org.jclouds.compute.domain.Size;
|
||||
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 com.google.common.base.Function;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.collect.Iterables;
|
||||
import com.google.common.collect.Maps;
|
||||
import com.google.common.collect.Sets;
|
||||
import com.google.inject.Injector;
|
||||
|
||||
|
@ -65,21 +70,23 @@ public class TerremarkVCloudComputeServiceContextModule extends VCloudComputeSer
|
|||
private static class ComputeOptionsToSize implements Function<ComputeOptions, Size> {
|
||||
@Override
|
||||
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));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected SortedSet<? extends Size> provideSizes(VCloudClient client,
|
||||
Set<? extends Image> images, LogHolder holder,
|
||||
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService executor) {
|
||||
Image anyImage = Iterables.get(images, 0);
|
||||
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 {
|
||||
Image anyImage = Iterables.get(images.values(), 0);
|
||||
holder.logger.debug(">> providing sizes");
|
||||
SortedSet<Size> sizes = Sets.newTreeSet(Iterables.transform(TerremarkVCloudClient.class.cast(
|
||||
client).getComputeOptionsOfCatalogItem(anyImage.getId()), sizeConverter));
|
||||
holder.logger.debug("<< sizes(%d)", sizes.size());
|
||||
return sizes;
|
||||
return Maps.uniqueIndex(sizes, indexer);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue