normalized usage of null across compute apis, removed loop of recreating nodes, extracted BaseComputeService class

This commit is contained in:
Adrian Cole 2010-02-08 01:32:53 -08:00
parent 1a5016a4f8
commit 52e40c4651
48 changed files with 996 additions and 1121 deletions

View File

@ -45,7 +45,6 @@ import org.jclouds.atmosonline.saas.functions.ReturnEndpointIfAlreadyExists;
import org.jclouds.atmosonline.saas.options.ListOptions; import org.jclouds.atmosonline.saas.options.ListOptions;
import org.jclouds.blobstore.attr.ConsistencyModel; import org.jclouds.blobstore.attr.ConsistencyModel;
import org.jclouds.blobstore.attr.ConsistencyModels; import org.jclouds.blobstore.attr.ConsistencyModels;
import org.jclouds.blobstore.functions.ReturnVoidOnNotFoundOr404;
import org.jclouds.blobstore.functions.ThrowContainerNotFoundOn404; import org.jclouds.blobstore.functions.ThrowContainerNotFoundOn404;
import org.jclouds.blobstore.functions.ThrowKeyNotFoundOn404; import org.jclouds.blobstore.functions.ThrowKeyNotFoundOn404;
import org.jclouds.http.options.GetOptions; import org.jclouds.http.options.GetOptions;
@ -57,8 +56,9 @@ import org.jclouds.rest.annotations.QueryParams;
import org.jclouds.rest.annotations.RequestFilters; import org.jclouds.rest.annotations.RequestFilters;
import org.jclouds.rest.annotations.ResponseParser; import org.jclouds.rest.annotations.ResponseParser;
import org.jclouds.rest.annotations.SkipEncoding; import org.jclouds.rest.annotations.SkipEncoding;
import org.jclouds.rest.functions.ReturnFalseOnResourceNotFound; import org.jclouds.rest.functions.ReturnFalseOnNotFoundOr404;
import org.jclouds.rest.functions.ReturnNullOnResourceNotFound; import org.jclouds.rest.functions.ReturnNullOnNotFoundOr404;
import org.jclouds.rest.functions.ReturnVoidOnNotFoundOr404;
import com.google.common.util.concurrent.ListenableFuture; import com.google.common.util.concurrent.ListenableFuture;
@ -136,7 +136,7 @@ public interface AtmosStorageAsyncClient {
*/ */
@GET @GET
@ResponseParser(ParseObjectFromHeadersAndHttpContent.class) @ResponseParser(ParseObjectFromHeadersAndHttpContent.class)
@ExceptionParser(ReturnNullOnResourceNotFound.class) @ExceptionParser(ReturnNullOnNotFoundOr404.class)
@Path("/rest/namespace/{path}") @Path("/rest/namespace/{path}")
@Consumes(MediaType.WILDCARD) @Consumes(MediaType.WILDCARD)
ListenableFuture<AtmosObject> readFile(@PathParam("path") String path, GetOptions... options); ListenableFuture<AtmosObject> readFile(@PathParam("path") String path, GetOptions... options);
@ -146,7 +146,7 @@ public interface AtmosStorageAsyncClient {
*/ */
@HEAD @HEAD
@ResponseParser(ParseObjectFromHeadersAndHttpContent.class) @ResponseParser(ParseObjectFromHeadersAndHttpContent.class)
@ExceptionParser(ReturnNullOnResourceNotFound.class) @ExceptionParser(ReturnNullOnNotFoundOr404.class)
@Path("/rest/namespace/{path}") @Path("/rest/namespace/{path}")
@Consumes(MediaType.WILDCARD) @Consumes(MediaType.WILDCARD)
ListenableFuture<AtmosObject> headFile(@PathParam("path") String path); ListenableFuture<AtmosObject> headFile(@PathParam("path") String path);
@ -156,7 +156,7 @@ public interface AtmosStorageAsyncClient {
*/ */
@HEAD @HEAD
@ResponseParser(ParseSystemMetadataFromHeaders.class) @ResponseParser(ParseSystemMetadataFromHeaders.class)
@ExceptionParser(ReturnNullOnResourceNotFound.class) @ExceptionParser(ReturnNullOnNotFoundOr404.class)
// currently throws 403 errors @QueryParams(keys = "metadata/system") // currently throws 403 errors @QueryParams(keys = "metadata/system")
@Path("/rest/namespace/{path}") @Path("/rest/namespace/{path}")
@Consumes(MediaType.WILDCARD) @Consumes(MediaType.WILDCARD)
@ -167,7 +167,7 @@ public interface AtmosStorageAsyncClient {
*/ */
@HEAD @HEAD
@ResponseParser(ParseSystemMetadataFromHeaders.class) @ResponseParser(ParseSystemMetadataFromHeaders.class)
@ExceptionParser(ReturnNullOnResourceNotFound.class) @ExceptionParser(ReturnNullOnNotFoundOr404.class)
@Path("/rest/namespace/{path}") @Path("/rest/namespace/{path}")
@QueryParams(keys = "metadata/user") @QueryParams(keys = "metadata/user")
@Consumes(MediaType.WILDCARD) @Consumes(MediaType.WILDCARD)
@ -186,7 +186,7 @@ public interface AtmosStorageAsyncClient {
* @see AtmosStorageClient#pathExists * @see AtmosStorageClient#pathExists
*/ */
@HEAD @HEAD
@ExceptionParser(ReturnFalseOnResourceNotFound.class) @ExceptionParser(ReturnFalseOnNotFoundOr404.class)
@Path("/rest/namespace/{path}") @Path("/rest/namespace/{path}")
@Consumes(MediaType.WILDCARD) @Consumes(MediaType.WILDCARD)
ListenableFuture<Boolean> pathExists(@PathParam("path") String path); ListenableFuture<Boolean> pathExists(@PathParam("path") String path);

View File

@ -39,7 +39,6 @@ import org.jclouds.atmosonline.saas.options.ListOptions;
import org.jclouds.atmosonline.saas.reference.AtmosStorageConstants; import org.jclouds.atmosonline.saas.reference.AtmosStorageConstants;
import org.jclouds.blobstore.binders.BindBlobToMultipartFormTest; import org.jclouds.blobstore.binders.BindBlobToMultipartFormTest;
import org.jclouds.blobstore.config.BlobStoreObjectModule; import org.jclouds.blobstore.config.BlobStoreObjectModule;
import org.jclouds.blobstore.functions.ReturnVoidOnNotFoundOr404;
import org.jclouds.blobstore.functions.ThrowContainerNotFoundOn404; import org.jclouds.blobstore.functions.ThrowContainerNotFoundOn404;
import org.jclouds.blobstore.functions.ThrowKeyNotFoundOn404; import org.jclouds.blobstore.functions.ThrowKeyNotFoundOn404;
import org.jclouds.date.TimeStamp; import org.jclouds.date.TimeStamp;
@ -50,7 +49,8 @@ import org.jclouds.http.options.GetOptions;
import org.jclouds.logging.Logger; import org.jclouds.logging.Logger;
import org.jclouds.logging.Logger.LoggerFactory; import org.jclouds.logging.Logger.LoggerFactory;
import org.jclouds.rest.RestClientTest; import org.jclouds.rest.RestClientTest;
import org.jclouds.rest.functions.ReturnNullOnResourceNotFound; import org.jclouds.rest.functions.ReturnNullOnNotFoundOr404;
import org.jclouds.rest.functions.ReturnVoidOnNotFoundOr404;
import org.jclouds.rest.internal.GeneratedHttpRequest; import org.jclouds.rest.internal.GeneratedHttpRequest;
import org.jclouds.rest.internal.RestAnnotationProcessor; import org.jclouds.rest.internal.RestAnnotationProcessor;
import org.jclouds.util.Jsr330; import org.jclouds.util.Jsr330;
@ -221,7 +221,7 @@ public class AtmosStorageClientTest extends RestClientTest<AtmosStorageAsyncClie
assertResponseParserClassEquals(method, httpMethod, assertResponseParserClassEquals(method, httpMethod,
ParseObjectFromHeadersAndHttpContent.class); ParseObjectFromHeadersAndHttpContent.class);
assertSaxResponseParserClassEquals(method, null); assertSaxResponseParserClassEquals(method, null);
assertExceptionParserClassEquals(method, ReturnNullOnResourceNotFound.class); assertExceptionParserClassEquals(method, ReturnNullOnNotFoundOr404.class);
checkFilters(httpMethod); checkFilters(httpMethod);
} }
@ -238,7 +238,7 @@ public class AtmosStorageClientTest extends RestClientTest<AtmosStorageAsyncClie
assertResponseParserClassEquals(method, httpMethod, ParseSystemMetadataFromHeaders.class); assertResponseParserClassEquals(method, httpMethod, ParseSystemMetadataFromHeaders.class);
assertSaxResponseParserClassEquals(method, null); assertSaxResponseParserClassEquals(method, null);
assertExceptionParserClassEquals(method, ReturnNullOnResourceNotFound.class); assertExceptionParserClassEquals(method, ReturnNullOnNotFoundOr404.class);
checkFilters(httpMethod); checkFilters(httpMethod);
} }

View File

@ -21,14 +21,14 @@ package org.jclouds.aws.ec2.compute;
import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkNotNull;
import static org.jclouds.aws.ec2.options.RunInstancesOptions.Builder.withKeyName; import static org.jclouds.aws.ec2.options.RunInstancesOptions.Builder.withKeyName;
import static org.jclouds.compute.util.ComputeUtils.METADATA_TO_ID; import static org.jclouds.concurrent.ConcurrentUtils.awaitCompletion;
import static org.jclouds.concurrent.ConcurrentUtils.makeListenable;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.concurrent.Callable; import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService; import java.util.concurrent.ExecutorService;
import javax.annotation.Resource;
import javax.inject.Inject; import javax.inject.Inject;
import javax.inject.Named; import javax.inject.Named;
import javax.inject.Provider; import javax.inject.Provider;
@ -49,24 +49,19 @@ import org.jclouds.aws.ec2.domain.InstanceState;
import org.jclouds.aws.ec2.domain.Reservation; import org.jclouds.aws.ec2.domain.Reservation;
import org.jclouds.aws.ec2.domain.RunningInstance; import org.jclouds.aws.ec2.domain.RunningInstance;
import org.jclouds.aws.ec2.options.RunInstancesOptions; import org.jclouds.aws.ec2.options.RunInstancesOptions;
import org.jclouds.compute.ComputeService;
import org.jclouds.compute.domain.ComputeMetadata; import org.jclouds.compute.domain.ComputeMetadata;
import org.jclouds.compute.domain.ComputeType; import org.jclouds.compute.domain.ComputeType;
import org.jclouds.compute.domain.Image; import org.jclouds.compute.domain.Image;
import org.jclouds.compute.domain.NodeMetadata; import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.domain.NodeSet;
import org.jclouds.compute.domain.NodeState; import org.jclouds.compute.domain.NodeState;
import org.jclouds.compute.domain.Size; import org.jclouds.compute.domain.Size;
import org.jclouds.compute.domain.Template; import org.jclouds.compute.domain.Template;
import org.jclouds.compute.domain.TemplateBuilder; import org.jclouds.compute.domain.TemplateBuilder;
import org.jclouds.compute.domain.internal.NodeSetImpl; import org.jclouds.compute.internal.BaseComputeService;
import org.jclouds.compute.options.TemplateOptions; import org.jclouds.compute.options.TemplateOptions;
import org.jclouds.compute.reference.ComputeServiceConstants;
import org.jclouds.compute.util.ComputeUtils; import org.jclouds.compute.util.ComputeUtils;
import static org.jclouds.concurrent.ConcurrentUtils.*;
import org.jclouds.domain.Location; import org.jclouds.domain.Location;
import org.jclouds.domain.LocationScope; import org.jclouds.domain.LocationScope;
import org.jclouds.logging.Logger;
import com.google.common.base.Function; import com.google.common.base.Function;
import com.google.common.base.Joiner; import com.google.common.base.Joiner;
@ -81,7 +76,7 @@ import com.google.inject.internal.ImmutableSet;
* @author Adrian Cole * @author Adrian Cole
*/ */
@Singleton @Singleton
public class EC2ComputeService implements ComputeService { public class EC2ComputeService extends BaseComputeService {
private static Function<RunningInstance, String> instanceToId = new Function<RunningInstance, String>() { private static Function<RunningInstance, String> instanceToId = new Function<RunningInstance, String>() {
@Override @Override
@ -89,70 +84,42 @@ public class EC2ComputeService implements ComputeService {
return from.getId(); 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) && from.getState() != NodeState.TERMINATED;
}
public NodeMatchesTag(String tag) {
super();
this.tag = tag;
}
};
@Resource
@Named(ComputeServiceConstants.COMPUTE_LOGGER)
protected Logger logger = Logger.NULL;
protected final EC2Client ec2Client; protected final EC2Client ec2Client;
protected final Map<RegionTag, KeyPairCredentials> credentialsMap; protected final Map<RegionTag, KeyPairCredentials> credentialsMap;
protected final Map<PortsRegionTag, String> securityGroupMap; 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 CreateKeyPairIfNeeded createKeyPairIfNeeded;
protected final CreateSecurityGroupIfNeeded createSecurityGroupIfNeeded; protected final CreateSecurityGroupIfNeeded createSecurityGroupIfNeeded;
protected final Provider<TemplateBuilder> templateBuilderProvider;
protected final Predicate<RunningInstance> instanceStateRunning; protected final Predicate<RunningInstance> instanceStateRunning;
protected final Predicate<RunningInstance> instanceStateTerminated; protected final Predicate<RunningInstance> instanceStateTerminated;
protected final RunningInstanceToNodeMetadata runningInstanceToNodeMetadata; protected final RunningInstanceToNodeMetadata runningInstanceToNodeMetadata;
protected final ExecutorService executor;
protected final ComputeUtils utils;
@Inject @Inject
public EC2ComputeService(EC2Client client, Provider<TemplateBuilder> templateBuilderProvider, EC2ComputeService(Provider<Map<String, ? extends Image>> images,
Provider<Map<String, ? extends Image>> images,
Provider<Map<String, ? extends Size>> sizes, Provider<Map<String, ? extends Size>> sizes,
Provider<Map<String, ? extends Location>> locations, Provider<Map<String, ? extends Location>> locations,
Map<RegionTag, KeyPairCredentials> credentialsMap, Provider<TemplateBuilder> templateBuilderProvider, String nodeNamingConvention,
ComputeUtils utils, @Named(Constants.PROPERTY_USER_THREADS) ExecutorService executor,
EC2Client ec2Client, Map<RegionTag, KeyPairCredentials> credentialsMap,
Map<PortsRegionTag, String> securityGroupMap, Map<PortsRegionTag, String> securityGroupMap,
CreateKeyPairIfNeeded createKeyPairIfNeeded, CreateKeyPairIfNeeded createKeyPairIfNeeded,
CreateSecurityGroupIfNeeded createSecurityGroupIfNeeded, ComputeUtils utils, CreateSecurityGroupIfNeeded createSecurityGroupIfNeeded,
@Named("RUNNING") Predicate<RunningInstance> instanceStateRunning, @Named("RUNNING") Predicate<RunningInstance> instanceStateRunning,
@Named("TERMINATED") Predicate<RunningInstance> instanceStateTerminated, @Named("TERMINATED") Predicate<RunningInstance> instanceStateTerminated,
RunningInstanceToNodeMetadata runningInstanceToNodeMetadata, RunningInstanceToNodeMetadata runningInstanceToNodeMetadata) {
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService executor) { super(images, sizes, locations, templateBuilderProvider, nodeNamingConvention, utils,
this.templateBuilderProvider = templateBuilderProvider; executor);
this.ec2Client = client; this.ec2Client = ec2Client;
this.images = images;
this.utils = utils;
this.sizes = sizes;
this.locations = locations;
this.credentialsMap = credentialsMap; this.credentialsMap = credentialsMap;
this.securityGroupMap = securityGroupMap;
this.createKeyPairIfNeeded = createKeyPairIfNeeded; this.createKeyPairIfNeeded = createKeyPairIfNeeded;
this.createSecurityGroupIfNeeded = createSecurityGroupIfNeeded; this.createSecurityGroupIfNeeded = createSecurityGroupIfNeeded;
this.securityGroupMap = securityGroupMap;
this.instanceStateRunning = instanceStateRunning; this.instanceStateRunning = instanceStateRunning;
this.instanceStateTerminated = instanceStateTerminated; this.instanceStateTerminated = instanceStateTerminated;
this.runningInstanceToNodeMetadata = runningInstanceToNodeMetadata; this.runningInstanceToNodeMetadata = runningInstanceToNodeMetadata;
this.executor = executor;
} }
@Override @Override
public NodeSet runNodesWithTag(String tag, int count, final Template template) { public Map<String, NodeMetadata> runNodesWithTag(String tag, int count, final Template template) {
checkArgument(tag.indexOf('-') == -1, "tag cannot contain hyphens"); checkArgument(tag.indexOf('-') == -1, "tag cannot contain hyphens");
checkArgument(template.getSize() instanceof EC2Size, checkArgument(template.getSize() instanceof EC2Size,
"unexpected image type. should be EC2Size, was: " + template.getSize().getClass()); "unexpected image type. should be EC2Size, was: " + template.getSize().getClass());
@ -224,7 +191,7 @@ public class EC2ComputeService implements ComputeService {
} }
nodesToStart = awaitCompletion(responses, executor, null, logger, "nodes").size(); nodesToStart = awaitCompletion(responses, executor, null, logger, "nodes").size();
} }
return new NodeSetImpl(nodes); return Maps.uniqueIndex(nodes, METADATA_TO_ID);
} }
@Override @Override
@ -243,29 +210,18 @@ public class EC2ComputeService implements ComputeService {
.concat(ec2Client.getInstanceServices().describeInstancesInRegion(region, id)); .concat(ec2Client.getInstanceServices().describeInstancesInRegion(region, id));
} }
@Override protected Iterable<NodeMetadata> doGetNodes() {
public Map<String, NodeMetadata> getNodes() {
logger.debug(">> listing servers");
Map<String, NodeMetadata> nodes = doGetNodes();
logger.debug("<< list(%d)", nodes.size());
return nodes;
}
protected Map<String, NodeMetadata> doGetNodes() {
Set<NodeMetadata> nodes = Sets.newHashSet(); Set<NodeMetadata> nodes = Sets.newHashSet();
for (Region region : ImmutableSet.of(Region.US_EAST_1, Region.US_WEST_1, Region.EU_WEST_1)) { for (Region region : ImmutableSet.of(Region.US_EAST_1, Region.US_WEST_1, Region.EU_WEST_1)) {
Iterables.addAll(nodes, Iterables.transform(Iterables.concat(ec2Client Iterables.addAll(nodes, Iterables.transform(Iterables.concat(ec2Client
.getInstanceServices().describeInstancesInRegion(region)), .getInstanceServices().describeInstancesInRegion(region)),
runningInstanceToNodeMetadata)); runningInstanceToNodeMetadata));
} }
return Maps.uniqueIndex(nodes, METADATA_TO_ID); return nodes;
} }
@Override @Override
public void destroyNode(ComputeMetadata metadata) { protected boolean doDestroyNode(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) NodeMetadata node = metadata instanceof NodeMetadata ? NodeMetadata.class.cast(metadata)
: getNodeMetadata(metadata); : getNodeMetadata(metadata);
String tag = checkNotNull(node.getTag(), "node.tag"); String tag = checkNotNull(node.getTag(), "node.tag");
@ -282,7 +238,7 @@ public class EC2ComputeService implements ComputeService {
} }
logger.debug("<< terminated instance(%s) success(%s)", node.getId(), success); logger.debug("<< terminated instance(%s) success(%s)", node.getId(), success);
} }
if (Iterables.all(doGetNodes(tag), new Predicate<NodeMetadata>() { if (Iterables.all(doGetNodes(tag).values(), new Predicate<NodeMetadata>() {
@Override @Override
public boolean apply(NodeMetadata input) { public boolean apply(NodeMetadata input) {
return input.getState() == NodeState.TERMINATED; return input.getState() == NodeState.TERMINATED;
@ -291,6 +247,7 @@ public class EC2ComputeService implements ComputeService {
deleteKeyPair(region, tag); deleteKeyPair(region, tag);
deleteSecurityGroup(region, tag); deleteSecurityGroup(region, tag);
} }
return true;
} }
private RunningInstance getInstance(NodeMetadata node, Region region) { private RunningInstance getInstance(NodeMetadata node, Region region) {
@ -324,60 +281,8 @@ public class EC2ComputeService implements ComputeService {
} }
@Override @Override
public void destroyNodesWithTag(String tag) { // TODO parallel protected NodeMetadata startNode(String tag, String name, Template template) {
logger.debug(">> terminating servers by tag(%s)", tag); throw new UnsupportedOperationException();
Iterable<NodeMetadata> nodesToDestroy = Iterables.filter(doGetNodes(tag),
new Predicate<NodeMetadata>() {
@Override
public boolean apply(NodeMetadata input) {
return input.getState() != NodeState.TERMINATED;
}
});
Map<NodeMetadata, ListenableFuture<Void>> responses = Maps.newHashMap();
for (final NodeMetadata node : nodesToDestroy) {
responses.put(node, 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 getNodesWithTag(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 Map<String, ? extends Image> getImages() {
return images.get();
}
@Override
public TemplateBuilder templateBuilder() {
return templateBuilderProvider.get();
} }
} }

View File

@ -67,7 +67,6 @@ import org.jclouds.blobstore.attr.ConsistencyModels;
import org.jclouds.blobstore.functions.ReturnFalseOnContainerNotFound; import org.jclouds.blobstore.functions.ReturnFalseOnContainerNotFound;
import org.jclouds.blobstore.functions.ReturnFalseOnKeyNotFound; import org.jclouds.blobstore.functions.ReturnFalseOnKeyNotFound;
import org.jclouds.blobstore.functions.ReturnNullOnKeyNotFound; import org.jclouds.blobstore.functions.ReturnNullOnKeyNotFound;
import org.jclouds.blobstore.functions.ReturnVoidOnNotFoundOr404;
import org.jclouds.blobstore.functions.ThrowContainerNotFoundOn404; import org.jclouds.blobstore.functions.ThrowContainerNotFoundOn404;
import org.jclouds.blobstore.functions.ThrowKeyNotFoundOn404; import org.jclouds.blobstore.functions.ThrowKeyNotFoundOn404;
import org.jclouds.http.functions.ParseETagHeader; import org.jclouds.http.functions.ParseETagHeader;
@ -84,6 +83,7 @@ import org.jclouds.rest.annotations.ResponseParser;
import org.jclouds.rest.annotations.SkipEncoding; import org.jclouds.rest.annotations.SkipEncoding;
import org.jclouds.rest.annotations.VirtualHost; import org.jclouds.rest.annotations.VirtualHost;
import org.jclouds.rest.annotations.XMLResponseParser; import org.jclouds.rest.annotations.XMLResponseParser;
import org.jclouds.rest.functions.ReturnVoidOnNotFoundOr404;
import com.google.common.util.concurrent.ListenableFuture; import com.google.common.util.concurrent.ListenableFuture;

View File

@ -58,7 +58,6 @@ import org.jclouds.blobstore.config.BlobStoreObjectModule;
import org.jclouds.blobstore.functions.ReturnFalseOnContainerNotFound; import org.jclouds.blobstore.functions.ReturnFalseOnContainerNotFound;
import org.jclouds.blobstore.functions.ReturnFalseOnKeyNotFound; import org.jclouds.blobstore.functions.ReturnFalseOnKeyNotFound;
import org.jclouds.blobstore.functions.ReturnNullOnKeyNotFound; import org.jclouds.blobstore.functions.ReturnNullOnKeyNotFound;
import org.jclouds.blobstore.functions.ReturnVoidOnNotFoundOr404;
import org.jclouds.blobstore.functions.ThrowContainerNotFoundOn404; import org.jclouds.blobstore.functions.ThrowContainerNotFoundOn404;
import org.jclouds.blobstore.functions.ThrowKeyNotFoundOn404; import org.jclouds.blobstore.functions.ThrowKeyNotFoundOn404;
import org.jclouds.blobstore.reference.BlobStoreConstants; import org.jclouds.blobstore.reference.BlobStoreConstants;
@ -71,6 +70,7 @@ import org.jclouds.http.options.GetOptions;
import org.jclouds.logging.Logger; import org.jclouds.logging.Logger;
import org.jclouds.logging.Logger.LoggerFactory; import org.jclouds.logging.Logger.LoggerFactory;
import org.jclouds.rest.RestClientTest; import org.jclouds.rest.RestClientTest;
import org.jclouds.rest.functions.ReturnVoidOnNotFoundOr404;
import org.jclouds.rest.internal.GeneratedHttpRequest; import org.jclouds.rest.internal.GeneratedHttpRequest;
import org.jclouds.rest.internal.RestAnnotationProcessor; import org.jclouds.rest.internal.RestAnnotationProcessor;
import org.jclouds.util.Jsr330; import org.jclouds.util.Jsr330;

View File

@ -53,7 +53,6 @@ import org.jclouds.blobstore.functions.ReturnFalseOnContainerNotFound;
import org.jclouds.blobstore.functions.ReturnFalseOnKeyNotFound; import org.jclouds.blobstore.functions.ReturnFalseOnKeyNotFound;
import org.jclouds.blobstore.functions.ReturnNullOnContainerNotFound; import org.jclouds.blobstore.functions.ReturnNullOnContainerNotFound;
import org.jclouds.blobstore.functions.ReturnNullOnKeyNotFound; import org.jclouds.blobstore.functions.ReturnNullOnKeyNotFound;
import org.jclouds.blobstore.functions.ReturnVoidOnNotFoundOr404;
import org.jclouds.http.functions.ParseETagHeader; import org.jclouds.http.functions.ParseETagHeader;
import org.jclouds.http.functions.ReturnTrueOn404; import org.jclouds.http.functions.ReturnTrueOn404;
import org.jclouds.http.options.GetOptions; import org.jclouds.http.options.GetOptions;
@ -67,6 +66,7 @@ import org.jclouds.rest.annotations.RequestFilters;
import org.jclouds.rest.annotations.ResponseParser; import org.jclouds.rest.annotations.ResponseParser;
import org.jclouds.rest.annotations.SkipEncoding; import org.jclouds.rest.annotations.SkipEncoding;
import org.jclouds.rest.annotations.XMLResponseParser; import org.jclouds.rest.annotations.XMLResponseParser;
import org.jclouds.rest.functions.ReturnVoidOnNotFoundOr404;
import com.google.common.util.concurrent.ListenableFuture; import com.google.common.util.concurrent.ListenableFuture;

View File

@ -41,7 +41,6 @@ import org.jclouds.azure.storage.config.AzureStorageRestClientModule;
import org.jclouds.azure.storage.options.ListOptions; import org.jclouds.azure.storage.options.ListOptions;
import org.jclouds.azure.storage.reference.AzureStorageConstants; import org.jclouds.azure.storage.reference.AzureStorageConstants;
import org.jclouds.blobstore.functions.ReturnNullOnContainerNotFound; import org.jclouds.blobstore.functions.ReturnNullOnContainerNotFound;
import org.jclouds.blobstore.functions.ReturnVoidOnNotFoundOr404;
import org.jclouds.concurrent.config.ExecutorServiceModule; import org.jclouds.concurrent.config.ExecutorServiceModule;
import org.jclouds.http.config.JavaUrlHttpCommandExecutorServiceModule; import org.jclouds.http.config.JavaUrlHttpCommandExecutorServiceModule;
import org.jclouds.http.functions.CloseContentAndReturn; import org.jclouds.http.functions.CloseContentAndReturn;
@ -52,6 +51,7 @@ import org.jclouds.logging.Logger;
import org.jclouds.logging.Logger.LoggerFactory; import org.jclouds.logging.Logger.LoggerFactory;
import org.jclouds.rest.config.RestModule; import org.jclouds.rest.config.RestModule;
import org.jclouds.rest.functions.MapHttp4xxCodesToExceptions; import org.jclouds.rest.functions.MapHttp4xxCodesToExceptions;
import org.jclouds.rest.functions.ReturnVoidOnNotFoundOr404;
import org.jclouds.rest.internal.GeneratedHttpRequest; import org.jclouds.rest.internal.GeneratedHttpRequest;
import org.jclouds.rest.internal.RestAnnotationProcessor; import org.jclouds.rest.internal.RestAnnotationProcessor;
import org.jclouds.util.Jsr330; import org.jclouds.util.Jsr330;

View File

@ -23,7 +23,6 @@ import java.util.Map;
import org.jclouds.compute.domain.ComputeMetadata; import org.jclouds.compute.domain.ComputeMetadata;
import org.jclouds.compute.domain.Image; import org.jclouds.compute.domain.Image;
import org.jclouds.compute.domain.NodeMetadata; import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.domain.NodeSet;
import org.jclouds.compute.domain.Size; import org.jclouds.compute.domain.Size;
import org.jclouds.compute.domain.Template; import org.jclouds.compute.domain.Template;
import org.jclouds.compute.domain.TemplateBuilder; import org.jclouds.compute.domain.TemplateBuilder;
@ -105,7 +104,7 @@ public interface ComputeService {
* - how to configure the nodes * - how to configure the nodes
* @return all of the nodes the api was able to launch in a running state. * @return all of the nodes the api was able to launch in a running state.
*/ */
NodeSet runNodesWithTag(String tag, int count, Template template); Map<String, ? extends NodeMetadata> runNodesWithTag(String tag, int count, Template template);
/** /**
* destroy the node. If it is the only node in a tag set, the dependent resources will also be * destroy the node. If it is the only node in a tag set, the dependent resources will also be
@ -130,6 +129,6 @@ public interface ComputeService {
* *
* @param tag * @param tag
*/ */
NodeSet getNodesWithTag(String tag); Map<String, ? extends NodeMetadata> getNodesWithTag(String tag);
} }

View File

@ -1,28 +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;
import java.util.Set;
/**
* @author Adrian Cole
*/
public interface NodeSet extends Set<NodeMetadata> {
}

View File

@ -124,11 +124,8 @@ public class NodeMetadataImpl extends ComputeMetadataImpl implements NodeMetadat
public int hashCode() { public int hashCode() {
final int prime = 31; final int prime = 31;
int result = super.hashCode(); int result = super.hashCode();
result = prime * result + ((credentials == null) ? 0 : credentials.hashCode());
result = prime * result + ((extra == null) ? 0 : extra.hashCode());
result = prime * result + ((privateAddresses == null) ? 0 : privateAddresses.hashCode()); result = prime * result + ((privateAddresses == null) ? 0 : privateAddresses.hashCode());
result = prime * result + ((publicAddresses == null) ? 0 : publicAddresses.hashCode()); result = prime * result + ((publicAddresses == null) ? 0 : publicAddresses.hashCode());
result = prime * result + ((state == null) ? 0 : state.hashCode());
result = prime * result + ((tag == null) ? 0 : tag.hashCode()); result = prime * result + ((tag == null) ? 0 : tag.hashCode());
return result; return result;
} }
@ -142,16 +139,6 @@ public class NodeMetadataImpl extends ComputeMetadataImpl implements NodeMetadat
if (getClass() != obj.getClass()) if (getClass() != obj.getClass())
return false; return false;
NodeMetadataImpl other = (NodeMetadataImpl) obj; NodeMetadataImpl other = (NodeMetadataImpl) obj;
if (credentials == null) {
if (other.credentials != null)
return false;
} else if (!credentials.equals(other.credentials))
return false;
if (extra == null) {
if (other.extra != null)
return false;
} else if (!extra.equals(other.extra))
return false;
if (privateAddresses == null) { if (privateAddresses == null) {
if (other.privateAddresses != null) if (other.privateAddresses != null)
return false; return false;
@ -162,11 +149,6 @@ public class NodeMetadataImpl extends ComputeMetadataImpl implements NodeMetadat
return false; return false;
} else if (!publicAddresses.equals(other.publicAddresses)) } else if (!publicAddresses.equals(other.publicAddresses))
return false; return false;
if (state == null) {
if (other.state != null)
return false;
} else if (!state.equals(other.state))
return false;
if (tag == null) { if (tag == null) {
if (other.tag != null) if (other.tag != null)
return false; return false;

View File

@ -1,40 +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.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);
}
}

View File

@ -126,7 +126,8 @@ public class TemplateImpl implements Template {
@Override @Override
public String toString() { public String toString() {
return "TemplateImpl [image=" + image + ", size=" + size + "]"; return "[location=" + location + ", image=" + image + ", size=" + size + ", options="
+ options + "]";
} }
/** /**

View File

@ -0,0 +1,280 @@
/**
*
* Copyright (C) 2009 Global Cloud Specialists, Inc. <info@globalcloudspecialists.com>
*
* ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
* ====================================================================
*/
package org.jclouds.compute.internal;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import static org.jclouds.concurrent.ConcurrentUtils.awaitCompletion;
import static org.jclouds.concurrent.ConcurrentUtils.makeListenable;
import java.security.SecureRandom;
import java.util.Map;
import java.util.Set;
import java.util.Map.Entry;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import javax.annotation.Resource;
import javax.inject.Named;
import javax.inject.Provider;
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.Image;
import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.domain.NodeState;
import org.jclouds.compute.domain.Size;
import org.jclouds.compute.domain.Template;
import org.jclouds.compute.domain.TemplateBuilder;
import org.jclouds.compute.reference.ComputeServiceConstants;
import org.jclouds.compute.util.ComputeUtils;
import org.jclouds.domain.Location;
import org.jclouds.logging.Logger;
import com.google.common.base.Function;
import com.google.common.base.Predicate;
import com.google.common.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
*/
public abstract class BaseComputeService implements ComputeService {
@Resource
@Named(ComputeServiceConstants.COMPUTE_LOGGER)
protected Logger logger = Logger.NULL;
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 String nodeNamingConvention;
protected final ComputeUtils utils;
protected final ExecutorService executor;
private static class NodeMatchesTag implements Predicate<NodeMetadata> {
private final String tag;
public NodeMatchesTag(String tag) {
this.tag = tag;
}
@Override
public boolean apply(NodeMetadata from) {
return from.getTag().equals(tag);
}
};
public static Function<ComputeMetadata, String> METADATA_TO_ID = new Function<ComputeMetadata, String>() {
@Override
public String apply(ComputeMetadata from) {
return from.getId();
}
};
public static Function<ComputeMetadata, String> METADATA_TO_NAME = new Function<ComputeMetadata, String>() {
@Override
public String apply(ComputeMetadata from) {
return from.getName();
}
};
protected BaseComputeService(Provider<Map<String, ? extends Image>> images,
Provider<Map<String, ? extends Size>> sizes,
Provider<Map<String, ? extends Location>> locations,
Provider<TemplateBuilder> templateBuilderProvider, String nodeNamingConvention,
ComputeUtils utils, @Named(Constants.PROPERTY_USER_THREADS) ExecutorService executor) {
this.images = images;
this.sizes = sizes;
this.locations = locations;
this.templateBuilderProvider = templateBuilderProvider;
this.nodeNamingConvention = nodeNamingConvention;
this.utils = utils;
this.executor = executor;
}
@Override
public Map<String, ? extends NodeMetadata> runNodesWithTag(final String tag, int count,
final Template template) {
checkArgument(tag.indexOf('-') == -1, "tag cannot contain hyphens");
checkNotNull(template.getLocation(), "location");
final Set<NodeMetadata> nodes = Sets.newHashSet();
logger.debug(">> running %d node%s tag(%s) location(%s) image(%s) size(%s) options(%s)",
count, count > 1 ? "s" : "", tag, template.getLocation().getId(), template
.getImage().getId(), template.getSize().getId(), template.getOptions());
Map<String, ListenableFuture<Void>> responses = Maps.newHashMap();
for (final String name : getNextNames(tag, count)) {
responses.put(name, makeListenable(executor.submit(new Callable<Void>() {
@Override
public Void call() throws Exception {
NodeMetadata node = null;
logger.debug(">> starting node(%s) tag(%s)", name, tag);
node = startNode(tag, name, template);
logger.debug("<< running node(%s)", node.getId());
try {
utils.runOptionsOnNode(node, template.getOptions());
logger.debug("<< options applied node(%s)", node.getId());
nodes.add(node);
} catch (Exception e) {
if (!template.getOptions().shouldDestroyOnError())
nodes.add(node);
}
return null;
}
}), executor));
}
Map<String, Exception> exceptions = awaitCompletion(responses, executor, null, logger,
"starting nodes");
if (exceptions.size() > 0 && template.getOptions().shouldDestroyOnError()) {
ImmutableMap<String, ? extends ComputeMetadata> currentNodes = Maps.uniqueIndex(doGetNodes(),
METADATA_TO_ID);
for (Entry<String, Exception> entry : exceptions.entrySet()) {
logger.error(entry.getValue(), "<< error applying nodes(%s) [%s] destroying ", entry
.getKey(), entry.getValue().getMessage());
destroyNode(currentNodes.get(entry.getKey()));
}
}
return Maps.uniqueIndex(nodes, METADATA_TO_ID);
}
protected Set<String> getNextNames(final String tag, int count) {
Set<String> names = Sets.newHashSet();
int nodeIndex = new SecureRandom().nextInt(8096);
Iterable<? extends ComputeMetadata> allNodes = doGetNodes();
Map<String, ? extends ComputeMetadata> currentNodes = Maps.uniqueIndex(allNodes, METADATA_TO_NAME);
while (names.size() < count) {
String name = String.format(nodeNamingConvention, tag, nodeIndex++);
if (!currentNodes.containsKey(name)) {
names.add(name);
}
}
return names;
}
protected abstract NodeMetadata startNode(String tag, String name, Template template);
protected abstract boolean doDestroyNode(ComputeMetadata node);
protected abstract Iterable<? extends ComputeMetadata> doGetNodes();
@Override
public void destroyNodesWithTag(String tag) { // TODO parallel
logger.debug(">> terminating nodes by tag(%s)", tag);
Iterable<? extends NodeMetadata> nodesToDestroy = Iterables.filter(doGetNodes(tag).values(),
new Predicate<NodeMetadata>() {
@Override
public boolean apply(NodeMetadata input) {
return input.getState() != NodeState.TERMINATED;
}
});
Map<NodeMetadata, ListenableFuture<Void>> responses = Maps.newHashMap();
for (final NodeMetadata node : nodesToDestroy) {
responses.put(node, makeListenable(executor.submit(new Callable<Void>() {
@Override
public Void call() throws Exception {
destroyNode(node);
return null;
}
}), executor));
}
awaitCompletion(responses, executor, null, logger, "destroying nodes");
logger.debug("<< destroyed");
}
@Override
public Map<String, ? extends Location> getLocations() {
return locations.get();
}
@Override
public Map<String, ? extends ComputeMetadata> getNodes() {
logger.debug(">> listing servers");
ImmutableMap<String, ? extends ComputeMetadata> map = Maps.uniqueIndex(doGetNodes(), METADATA_TO_ID);
logger.debug("<< list(%d)", map.size());
return map;
}
@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");
logger.debug(">> deleting node(%s)", node.getId());
boolean successful = doDestroyNode(node);
logger.debug("<< deleted node(%s) success(%s)", node.getId(), successful);
}
protected Map<String, ? extends NodeMetadata> doGetNodes(final String tag) {
Iterable<? extends NodeMetadata> nodes = Iterables.filter(Iterables.transform(doGetNodes(),
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 Maps.uniqueIndex(Iterables.filter(nodes, new NodeMatchesTag(tag)), METADATA_TO_ID);
}
@Override
public Map<String, ? extends NodeMetadata> getNodesWithTag(String tag) {
logger.debug(">> listing nodes by tag(%s)", tag);
Map<String, ? extends NodeMetadata> nodes = doGetNodes(tag);
logger.debug("<< list(%d)", nodes.size());
return nodes;
}
@Override
public Map<String, ? extends Size> getSizes() {
return sizes.get();
}
@Override
public Map<String, ? extends Image> getImages() {
return images.get();
}
@Override
public TemplateBuilder templateBuilder() {
return templateBuilderProvider.get();
}
}

View File

@ -3,6 +3,8 @@ package org.jclouds.compute.options;
import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkNotNull;
import java.util.Arrays;
/** /**
* Contains options supported in the {@code ComputeService#runNode} operation. <h2> * Contains options supported in the {@code ComputeService#runNode} operation. <h2>
* Usage</h2> The recommended way to instantiate a TemplateOptions object is to statically import * Usage</h2> The recommended way to instantiate a TemplateOptions object is to statically import
@ -30,6 +32,8 @@ public class TemplateOptions {
private String publicKey; private String publicKey;
private boolean destroyOnError;
public int[] getInboundPorts() { public int[] getInboundPorts() {
return inboundPorts; return inboundPorts;
} }
@ -46,6 +50,18 @@ public class TemplateOptions {
return publicKey; return publicKey;
} }
public boolean shouldDestroyOnError() {
return destroyOnError;
}
/**
* If there is an error applying options after creating the node, destroy it.
*/
public TemplateOptions destroyOnError() {
this.destroyOnError = true;
return this;
}
/** /**
* This script will be executed as the root user upon system startup. * This script will be executed as the root user upon system startup.
*/ */
@ -86,6 +102,13 @@ public class TemplateOptions {
} }
public static class Builder { public static class Builder {
/**
* @see TemplateOptions#destroyOnError
*/
public static TemplateOptions destroyOnError() {
TemplateOptions options = new TemplateOptions();
return options.destroyOnError();
}
/** /**
* @see TemplateOptions#inboundPorts * @see TemplateOptions#inboundPorts
@ -120,4 +143,11 @@ public class TemplateOptions {
} }
} }
@Override
public String toString() {
return "TemplateOptions [inboundPorts=" + Arrays.toString(inboundPorts) + ", privateKey="
+ (privateKey != null) + ", publicKey=" + (publicKey != null) + ", runScript="
+ (script != null) + ", destroyOnError=" + destroyOnError + "]";
}
} }

View File

@ -48,7 +48,6 @@ import org.jclouds.scriptbuilder.domain.OsFamily;
import org.jclouds.ssh.ExecResponse; import org.jclouds.ssh.ExecResponse;
import org.jclouds.ssh.SshClient; import org.jclouds.ssh.SshClient;
import com.google.common.base.Function;
import com.google.common.base.Predicate; import com.google.common.base.Predicate;
import com.google.common.base.Splitter; import com.google.common.base.Splitter;
import com.google.common.base.Throwables; import com.google.common.base.Throwables;
@ -73,13 +72,6 @@ public class ComputeUtils {
private final Predicate<InetSocketAddress> socketTester; private final Predicate<InetSocketAddress> socketTester;
private final ExecutorService executor; private final ExecutorService executor;
public static Function<ComputeMetadata, String> METADATA_TO_ID = new Function<ComputeMetadata, String>() {
@Override
public String apply(ComputeMetadata from) {
return from.getId();
}
};
@Inject @Inject
public ComputeUtils(Predicate<InetSocketAddress> socketTester, public ComputeUtils(Predicate<InetSocketAddress> socketTester,
@Named("NOT_RUNNING") Predicate<SshClient> runScriptNotRunning, @Named("NOT_RUNNING") Predicate<SshClient> runScriptNotRunning,
@ -113,7 +105,6 @@ public class ComputeUtils {
if (options.getRunScript() != null) { if (options.getRunScript() != null) {
callables.add(runScriptOnNode(node, "runscript.sh", options.getRunScript())); callables.add(runScriptOnNode(node, "runscript.sh", options.getRunScript()));
} }
if (options.getPublicKey() != null) { if (options.getPublicKey() != null) {
callables.add(authorizeKeyOnNode(node, options.getPublicKey())); callables.add(authorizeKeyOnNode(node, options.getPublicKey()));
} }

View File

@ -27,6 +27,7 @@ import java.io.IOException;
import java.net.InetSocketAddress; import java.net.InetSocketAddress;
import java.util.Map; import java.util.Map;
import java.util.NoSuchElementException; import java.util.NoSuchElementException;
import java.util.Set;
import java.util.SortedSet; import java.util.SortedSet;
import java.util.Map.Entry; import java.util.Map.Entry;
import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutionException;
@ -37,7 +38,6 @@ import org.jclouds.compute.domain.ComputeMetadata;
import org.jclouds.compute.domain.ComputeType; import org.jclouds.compute.domain.ComputeType;
import org.jclouds.compute.domain.Image; import org.jclouds.compute.domain.Image;
import org.jclouds.compute.domain.NodeMetadata; import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.domain.NodeSet;
import org.jclouds.compute.domain.NodeState; import org.jclouds.compute.domain.NodeState;
import org.jclouds.compute.domain.Size; import org.jclouds.compute.domain.Size;
import org.jclouds.compute.domain.Template; import org.jclouds.compute.domain.Template;
@ -79,8 +79,8 @@ public abstract class BaseComputeServiceLiveTest {
protected SshClient.Factory sshFactory; protected SshClient.Factory sshFactory;
protected String tag; protected String tag;
private RetryablePredicate<InetSocketAddress> socketTester; protected RetryablePredicate<InetSocketAddress> socketTester;
private SortedSet<NodeMetadata> nodes; protected SortedSet<NodeMetadata> nodes;
protected ComputeServiceContext context; protected ComputeServiceContext context;
protected ComputeService client; protected ComputeService client;
protected String user; protected String user;
@ -145,8 +145,22 @@ public abstract class BaseComputeServiceLiveTest {
.append("wget -qO/usr/bin/runurl run.alestic.com/runurl\n")// .append("wget -qO/usr/bin/runurl run.alestic.com/runurl\n")//
.append("chmod 755 /usr/bin/runurl\n")// .append("chmod 755 /usr/bin/runurl\n")//
.toString().getBytes()); .toString().getBytes());
nodes = Sets.newTreeSet(client.runNodesWithTag(tag, 2, template)); nodes = Sets.newTreeSet(client.runNodesWithTag(tag, 2, template).values());
assertEquals(nodes.size(), 2); assertEquals(nodes.size(), 2);
checkNodes();
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());
// run one more
nodes.addAll(client.runNodesWithTag(tag, 1, template).values());
assertEquals(nodes.size(), 3);
checkNodes();
}
private void checkNodes() throws IOException {
for (NodeMetadata node : nodes) { for (NodeMetadata node : nodes) {
assertNotNull(node.getId()); assertNotNull(node.getId());
assertNotNull(node.getTag()); assertNotNull(node.getTag());
@ -160,19 +174,14 @@ public abstract class BaseComputeServiceLiveTest {
sshPing(node); sshPing(node);
} }
} }
NodeMetadata node1 = nodes.first();
NodeMetadata node2 = nodes.last();
// credentials aren't always the same
// assertEquals(node1.getCredentials(), node2.getCredentials());
assert !node1.getId().equals(node2.getId());
} }
protected abstract Template buildTemplate(TemplateBuilder templateBuilder); protected abstract Template buildTemplate(TemplateBuilder templateBuilder);
@Test(enabled = true, dependsOnMethods = "testCreate") @Test(enabled = true, dependsOnMethods = "testCreate")
public void testGet() throws Exception { public void testGet() throws Exception {
NodeSet metadataSet = client.getNodesWithTag(tag); Set<? extends NodeMetadata> metadataSet = Sets.newHashSet(client.getNodesWithTag(tag)
.values());
for (NodeMetadata node : nodes) { for (NodeMetadata node : nodes) {
metadataSet.remove(node); metadataSet.remove(node);
NodeMetadata metadata = client.getNodeMetadata(node); NodeMetadata metadata = client.getNodeMetadata(node);
@ -267,7 +276,7 @@ public abstract class BaseComputeServiceLiveTest {
protected void cleanup() throws InterruptedException, ExecutionException, TimeoutException { protected void cleanup() throws InterruptedException, ExecutionException, TimeoutException {
if (nodes != null) { if (nodes != null) {
client.destroyNodesWithTag(tag); client.destroyNodesWithTag(tag);
for (NodeMetadata node : client.getNodesWithTag(tag)) { for (NodeMetadata node : client.getNodesWithTag(tag).values()) {
assert node.getState() == NodeState.TERMINATED : node; assert node.getState() == NodeState.TERMINATED : node;
} }
} }

View File

@ -25,17 +25,19 @@ import javax.inject.Singleton;
import org.jclouds.http.HttpResponseException; import org.jclouds.http.HttpResponseException;
import com.google.common.base.Function; import com.google.common.base.Function;
import com.google.common.base.Throwables;
import com.google.common.collect.Iterables;
@Singleton @Singleton
public class ReturnTrueOn404 implements Function<Exception, Boolean> { public class ReturnTrueOn404 implements Function<Exception, Boolean> {
public Boolean apply(Exception from) { public Boolean apply(Exception from) {
if (from instanceof HttpResponseException) { Iterable<HttpResponseException> throwables = Iterables.filter(
HttpResponseException responseException = (HttpResponseException) from; Throwables.getCausalChain(from), HttpResponseException.class);
if (responseException.getResponse().getStatusCode() == 404) { if (Iterables.size(throwables) >= 1
&& Iterables.get(throwables, 0).getResponse().getStatusCode() == 404) {
return true; return true;
} }
}
return Boolean.class.cast(propagateOrNull(from)); return Boolean.class.cast(propagateOrNull(from));
} }

View File

@ -18,12 +18,13 @@
*/ */
package org.jclouds.rest.functions; package org.jclouds.rest.functions;
import static org.jclouds.util.Utils.propagateOrNull; import static com.google.common.base.Preconditions.checkNotNull;
import java.util.List;
import javax.inject.Inject;
import javax.inject.Singleton; import javax.inject.Singleton;
import org.jclouds.http.HttpResponseException;
import org.jclouds.http.functions.ReturnTrueOn404;
import org.jclouds.rest.ResourceNotFoundException; import org.jclouds.rest.ResourceNotFoundException;
import com.google.common.base.Function; import com.google.common.base.Function;
@ -35,13 +36,23 @@ import com.google.common.collect.Iterables;
* @author Adrian Cole * @author Adrian Cole
*/ */
@Singleton @Singleton
public class ReturnFalseOnResourceNotFound implements Function<Exception, Boolean> { public class ReturnFalseOnNotFoundOr404 implements Function<Exception, Boolean> {
private final ReturnTrueOn404 rto404;
@Inject
private ReturnFalseOnNotFoundOr404(ReturnTrueOn404 rto404) {
this.rto404 = checkNotNull(rto404, "rto404");
}
public Boolean apply(Exception from) { public Boolean apply(Exception from) {
List<Throwable> throwables = Throwables.getCausalChain(from); Iterable<HttpResponseException> throwables = Iterables.filter(
Throwables.getCausalChain(from), HttpResponseException.class);
if (Iterables.size(Iterables.filter(throwables, ResourceNotFoundException.class)) >= 1) { if (Iterables.size(Iterables.filter(throwables, ResourceNotFoundException.class)) >= 1) {
return false; return false;
} else {
return !rto404.apply(from);
} }
return Boolean.class.cast(propagateOrNull(from));
} }
} }

View File

@ -18,25 +18,42 @@
*/ */
package org.jclouds.rest.functions; package org.jclouds.rest.functions;
import static com.google.common.base.Preconditions.checkNotNull;
import static org.jclouds.util.Utils.propagateOrNull; import static org.jclouds.util.Utils.propagateOrNull;
import javax.inject.Inject;
import javax.inject.Singleton; import javax.inject.Singleton;
import org.jclouds.http.HttpResponseException;
import org.jclouds.http.functions.ReturnTrueOn404;
import org.jclouds.rest.ResourceNotFoundException; import org.jclouds.rest.ResourceNotFoundException;
import com.google.common.base.Function; import com.google.common.base.Function;
import com.google.common.base.Throwables;
import com.google.common.collect.Iterables;
/** /**
* *
* @author Adrian Cole * @author Adrian Cole
*/ */
@Singleton @Singleton
public class ReturnNullOnResourceNotFound implements Function<Exception, Object> { public class ReturnNullOnNotFoundOr404 implements Function<Exception, Object> {
private final ReturnTrueOn404 rto404;
@Inject
private ReturnNullOnNotFoundOr404(ReturnTrueOn404 rto404) {
this.rto404 = checkNotNull(rto404, "rto404");
}
public Object apply(Exception from) { public Object apply(Exception from) {
if (from instanceof ResourceNotFoundException) { Iterable<HttpResponseException> throwables = Iterables.filter(
Throwables.getCausalChain(from), HttpResponseException.class);
if (Iterables.size(Iterables.filter(throwables, ResourceNotFoundException.class)) >= 1) {
return null;
} else if (rto404.apply(from)) {
return null; return null;
} }
return propagateOrNull(from); return Object.class.cast(propagateOrNull(from));
} }
} }

View File

@ -16,7 +16,7 @@
* limitations under the License. * limitations under the License.
* ==================================================================== * ====================================================================
*/ */
package org.jclouds.blobstore.functions; package org.jclouds.rest.functions;
import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkNotNull;
import static org.jclouds.util.Utils.propagateOrNull; import static org.jclouds.util.Utils.propagateOrNull;
@ -24,11 +24,18 @@ import static org.jclouds.util.Utils.propagateOrNull;
import javax.inject.Inject; import javax.inject.Inject;
import javax.inject.Singleton; import javax.inject.Singleton;
import org.jclouds.http.HttpResponseException;
import org.jclouds.http.functions.ReturnTrueOn404; import org.jclouds.http.functions.ReturnTrueOn404;
import org.jclouds.rest.ResourceNotFoundException; import org.jclouds.rest.ResourceNotFoundException;
import com.google.common.base.Function; import com.google.common.base.Function;
import com.google.common.base.Throwables;
import com.google.common.collect.Iterables;
/**
*
* @author Adrian Cole
*/
@Singleton @Singleton
public class ReturnVoidOnNotFoundOr404 implements Function<Exception, Void> { public class ReturnVoidOnNotFoundOr404 implements Function<Exception, Void> {
@ -40,7 +47,9 @@ public class ReturnVoidOnNotFoundOr404 implements Function<Exception, Void> {
} }
public Void apply(Exception from) { public Void apply(Exception from) {
if (from instanceof ResourceNotFoundException) { Iterable<HttpResponseException> throwables = Iterables.filter(
Throwables.getCausalChain(from), HttpResponseException.class);
if (Iterables.size(Iterables.filter(throwables, ResourceNotFoundException.class)) >= 1) {
return null; return null;
} else { } else {
Boolean value = rto404.apply(from); Boolean value = rto404.apply(from);

View File

@ -30,7 +30,6 @@ import javax.ws.rs.Path;
import javax.ws.rs.PathParam; import javax.ws.rs.PathParam;
import org.jclouds.blobstore.functions.ReturnNullOnKeyNotFound; import org.jclouds.blobstore.functions.ReturnNullOnKeyNotFound;
import org.jclouds.blobstore.functions.ReturnVoidOnNotFoundOr404;
import org.jclouds.http.filters.BasicAuthentication; import org.jclouds.http.filters.BasicAuthentication;
import org.jclouds.mezeo.pcs2.binders.BindContainerNameToXmlPayload; import org.jclouds.mezeo.pcs2.binders.BindContainerNameToXmlPayload;
import org.jclouds.mezeo.pcs2.binders.BindDataToPayload; import org.jclouds.mezeo.pcs2.binders.BindDataToPayload;
@ -54,6 +53,7 @@ import org.jclouds.rest.annotations.ResponseParser;
import org.jclouds.rest.annotations.SkipEncoding; import org.jclouds.rest.annotations.SkipEncoding;
import org.jclouds.rest.annotations.XMLResponseParser; import org.jclouds.rest.annotations.XMLResponseParser;
import org.jclouds.rest.binders.BindToStringPayload; import org.jclouds.rest.binders.BindToStringPayload;
import org.jclouds.rest.functions.ReturnVoidOnNotFoundOr404;
import com.google.common.util.concurrent.ListenableFuture; import com.google.common.util.concurrent.ListenableFuture;

View File

@ -35,7 +35,6 @@ import javax.ws.rs.core.HttpHeaders;
import org.jclouds.blobstore.binders.BindBlobToMultipartFormTest; import org.jclouds.blobstore.binders.BindBlobToMultipartFormTest;
import org.jclouds.blobstore.config.BlobStoreObjectModule; import org.jclouds.blobstore.config.BlobStoreObjectModule;
import org.jclouds.blobstore.functions.ReturnNullOnKeyNotFound; import org.jclouds.blobstore.functions.ReturnNullOnKeyNotFound;
import org.jclouds.blobstore.functions.ReturnVoidOnNotFoundOr404;
import org.jclouds.encryption.EncryptionService; import org.jclouds.encryption.EncryptionService;
import org.jclouds.http.filters.BasicAuthentication; import org.jclouds.http.filters.BasicAuthentication;
import org.jclouds.http.functions.CloseContentAndReturn; import org.jclouds.http.functions.CloseContentAndReturn;
@ -54,6 +53,7 @@ import org.jclouds.mezeo.pcs2.xml.ContainerHandler;
import org.jclouds.mezeo.pcs2.xml.FileHandler; import org.jclouds.mezeo.pcs2.xml.FileHandler;
import org.jclouds.rest.RestClientTest; import org.jclouds.rest.RestClientTest;
import org.jclouds.rest.functions.MapHttp4xxCodesToExceptions; import org.jclouds.rest.functions.MapHttp4xxCodesToExceptions;
import org.jclouds.rest.functions.ReturnVoidOnNotFoundOr404;
import org.jclouds.rest.internal.GeneratedHttpRequest; import org.jclouds.rest.internal.GeneratedHttpRequest;
import org.jclouds.rest.internal.RestAnnotationProcessor; import org.jclouds.rest.internal.RestAnnotationProcessor;
import org.testng.annotations.BeforeClass; import org.testng.annotations.BeforeClass;

View File

@ -39,7 +39,6 @@ import org.jclouds.blobstore.domain.PageSet;
import org.jclouds.blobstore.functions.ReturnFalseOnContainerNotFound; import org.jclouds.blobstore.functions.ReturnFalseOnContainerNotFound;
import org.jclouds.blobstore.functions.ReturnFalseOnKeyNotFound; import org.jclouds.blobstore.functions.ReturnFalseOnKeyNotFound;
import org.jclouds.blobstore.functions.ReturnNullOnKeyNotFound; import org.jclouds.blobstore.functions.ReturnNullOnKeyNotFound;
import org.jclouds.blobstore.functions.ReturnVoidOnNotFoundOr404;
import org.jclouds.blobstore.functions.ThrowContainerNotFoundOn404; import org.jclouds.blobstore.functions.ThrowContainerNotFoundOn404;
import org.jclouds.http.functions.ParseETagHeader; import org.jclouds.http.functions.ParseETagHeader;
import org.jclouds.http.options.GetOptions; import org.jclouds.http.options.GetOptions;
@ -75,6 +74,7 @@ import org.jclouds.rest.annotations.QueryParams;
import org.jclouds.rest.annotations.RequestFilters; import org.jclouds.rest.annotations.RequestFilters;
import org.jclouds.rest.annotations.ResponseParser; import org.jclouds.rest.annotations.ResponseParser;
import org.jclouds.rest.annotations.SkipEncoding; import org.jclouds.rest.annotations.SkipEncoding;
import org.jclouds.rest.functions.ReturnVoidOnNotFoundOr404;
import com.google.common.util.concurrent.ListenableFuture; import com.google.common.util.concurrent.ListenableFuture;

View File

@ -75,6 +75,9 @@ import org.jclouds.rest.annotations.QueryParams;
import org.jclouds.rest.annotations.RequestFilters; import org.jclouds.rest.annotations.RequestFilters;
import org.jclouds.rest.annotations.ResponseParser; import org.jclouds.rest.annotations.ResponseParser;
import org.jclouds.rest.annotations.SkipEncoding; import org.jclouds.rest.annotations.SkipEncoding;
import org.jclouds.rest.functions.ReturnFalseOnNotFoundOr404;
import org.jclouds.rest.functions.ReturnNullOnNotFoundOr404;
import org.jclouds.rest.functions.ReturnVoidOnNotFoundOr404;
import com.google.common.util.concurrent.ListenableFuture; import com.google.common.util.concurrent.ListenableFuture;
@ -109,6 +112,7 @@ public interface CloudServersAsyncClient {
@GET @GET
@ResponseParser(ParseServerFromJsonResponse.class) @ResponseParser(ParseServerFromJsonResponse.class)
@QueryParams(keys = "format", values = "json") @QueryParams(keys = "format", values = "json")
@ExceptionParser(ReturnNullOnNotFoundOr404.class)
@Path("/servers/{id}") @Path("/servers/{id}")
ListenableFuture<Server> getServer(@PathParam("id") int id); ListenableFuture<Server> getServer(@PathParam("id") int id);
@ -116,7 +120,7 @@ public interface CloudServersAsyncClient {
* @see CloudServersClient#deleteServer * @see CloudServersClient#deleteServer
*/ */
@DELETE @DELETE
@ExceptionParser(ReturnFalseOn404.class) @ExceptionParser(ReturnFalseOnNotFoundOr404.class)
@Path("/servers/{id}") @Path("/servers/{id}")
ListenableFuture<Boolean> deleteServer(@PathParam("id") int id); ListenableFuture<Boolean> deleteServer(@PathParam("id") int id);
@ -126,8 +130,7 @@ public interface CloudServersAsyncClient {
@POST @POST
@QueryParams(keys = "format", values = "json") @QueryParams(keys = "format", values = "json")
@Path("/servers/{id}/action") @Path("/servers/{id}/action")
@ExceptionParser(ReturnFalseOn404.class) ListenableFuture<Void> rebootServer(@PathParam("id") int id,
ListenableFuture<Boolean> rebootServer(@PathParam("id") int id,
@BinderParam(BindRebootTypeToJsonPayload.class) RebootType rebootType); @BinderParam(BindRebootTypeToJsonPayload.class) RebootType rebootType);
/** /**
@ -136,8 +139,7 @@ public interface CloudServersAsyncClient {
@POST @POST
@QueryParams(keys = "format", values = "json") @QueryParams(keys = "format", values = "json")
@Path("/servers/{id}/action") @Path("/servers/{id}/action")
@ExceptionParser(ReturnFalseOn404.class) ListenableFuture<Void> resizeServer(@PathParam("id") int id,
ListenableFuture<Boolean> resizeServer(@PathParam("id") int id,
@BinderParam(BindResizeFlavorToJsonPayload.class) int flavorId); @BinderParam(BindResizeFlavorToJsonPayload.class) int flavorId);
/** /**
@ -146,8 +148,7 @@ public interface CloudServersAsyncClient {
@POST @POST
@QueryParams(keys = "format", values = "json") @QueryParams(keys = "format", values = "json")
@Path("/servers/{id}/action") @Path("/servers/{id}/action")
@ExceptionParser(ReturnFalseOn404.class) ListenableFuture<Void> confirmResizeServer(
ListenableFuture<Boolean> confirmResizeServer(
@PathParam("id") @BinderParam(BindConfirmResizeToJsonPayload.class) int id); @PathParam("id") @BinderParam(BindConfirmResizeToJsonPayload.class) int id);
/** /**
@ -156,8 +157,7 @@ public interface CloudServersAsyncClient {
@POST @POST
@QueryParams(keys = "format", values = "json") @QueryParams(keys = "format", values = "json")
@Path("/servers/{id}/action") @Path("/servers/{id}/action")
@ExceptionParser(ReturnFalseOn404.class) ListenableFuture<Void> revertResizeServer(
ListenableFuture<Boolean> revertResizeServer(
@PathParam("id") @BinderParam(BindRevertResizeToJsonPayload.class) int id); @PathParam("id") @BinderParam(BindRevertResizeToJsonPayload.class) int id);
/** /**
@ -178,18 +178,16 @@ public interface CloudServersAsyncClient {
@POST @POST
@QueryParams(keys = "format", values = "json") @QueryParams(keys = "format", values = "json")
@Path("/servers/{id}/action") @Path("/servers/{id}/action")
@ExceptionParser(ReturnFalseOn404.class)
@MapBinder(RebuildServerOptions.class) @MapBinder(RebuildServerOptions.class)
ListenableFuture<Boolean> rebuildServer(@PathParam("id") int id, RebuildServerOptions... options); ListenableFuture<Void> rebuildServer(@PathParam("id") int id, RebuildServerOptions... options);
/** /**
* @see CloudServersClient#shareIp * @see CloudServersClient#shareIp
*/ */
@PUT @PUT
@ExceptionParser(ReturnFalseOn404.class)
@Path("/servers/{id}/ips/public/{address}") @Path("/servers/{id}/ips/public/{address}")
@MapBinder(BindSharedIpGroupToJsonPayload.class) @MapBinder(BindSharedIpGroupToJsonPayload.class)
ListenableFuture<Boolean> shareIp( ListenableFuture<Void> shareIp(
@PathParam("address") @ParamParser(IpAddress.class) InetAddress addressToShare, @PathParam("address") @ParamParser(IpAddress.class) InetAddress addressToShare,
@PathParam("id") int serverToTosignBindressTo, @PathParam("id") int serverToTosignBindressTo,
@MapPayloadParam("sharedIpGroupId") int sharedIpGroup, @MapPayloadParam("sharedIpGroupId") int sharedIpGroup,
@ -199,9 +197,9 @@ public interface CloudServersAsyncClient {
* @see CloudServersClient#unshareIp * @see CloudServersClient#unshareIp
*/ */
@DELETE @DELETE
@ExceptionParser(ReturnFalseOn404.class)
@Path("/servers/{id}/ips/public/{address}") @Path("/servers/{id}/ips/public/{address}")
ListenableFuture<Boolean> unshareIp( @ExceptionParser(ReturnVoidOnNotFoundOr404.class)
ListenableFuture<Void> unshareIp(
@PathParam("address") @ParamParser(IpAddress.class) InetAddress addressToShare, @PathParam("address") @ParamParser(IpAddress.class) InetAddress addressToShare,
@PathParam("id") int serverToTosignBindressTo); @PathParam("id") int serverToTosignBindressTo);
@ -209,18 +207,16 @@ public interface CloudServersAsyncClient {
* @see CloudServersClient#changeAdminPass * @see CloudServersClient#changeAdminPass
*/ */
@PUT @PUT
@ExceptionParser(ReturnFalseOn404.class)
@Path("/servers/{id}") @Path("/servers/{id}")
ListenableFuture<Boolean> changeAdminPass(@PathParam("id") int id, ListenableFuture<Void> changeAdminPass(@PathParam("id") int id,
@BinderParam(BindAdminPassToJsonPayload.class) String adminPass); @BinderParam(BindAdminPassToJsonPayload.class) String adminPass);
/** /**
* @see CloudServersClient#renameServer * @see CloudServersClient#renameServer
*/ */
@PUT @PUT
@ExceptionParser(ReturnFalseOn404.class)
@Path("/servers/{id}") @Path("/servers/{id}")
ListenableFuture<Boolean> renameServer(@PathParam("id") int id, ListenableFuture<Void> renameServer(@PathParam("id") int id,
@BinderParam(BindServerNameToJsonPayload.class) String newName); @BinderParam(BindServerNameToJsonPayload.class) String newName);
/** /**
@ -239,6 +235,7 @@ public interface CloudServersAsyncClient {
@ResponseParser(ParseFlavorFromJsonResponse.class) @ResponseParser(ParseFlavorFromJsonResponse.class)
@QueryParams(keys = "format", values = "json") @QueryParams(keys = "format", values = "json")
@Path("/flavors/{id}") @Path("/flavors/{id}")
@ExceptionParser(ReturnNullOnNotFoundOr404.class)
ListenableFuture<Flavor> getFlavor(@PathParam("id") int id); ListenableFuture<Flavor> getFlavor(@PathParam("id") int id);
/** /**
@ -255,6 +252,7 @@ public interface CloudServersAsyncClient {
*/ */
@GET @GET
@ResponseParser(ParseImageFromJsonResponse.class) @ResponseParser(ParseImageFromJsonResponse.class)
@ExceptionParser(ReturnNullOnNotFoundOr404.class)
@QueryParams(keys = "format", values = "json") @QueryParams(keys = "format", values = "json")
@Path("/images/{id}") @Path("/images/{id}")
ListenableFuture<Image> getImage(@PathParam("id") int id); ListenableFuture<Image> getImage(@PathParam("id") int id);
@ -263,7 +261,7 @@ public interface CloudServersAsyncClient {
* @see CloudServersClient#deleteImage * @see CloudServersClient#deleteImage
*/ */
@DELETE @DELETE
@ExceptionParser(ReturnFalseOn404.class) @ExceptionParser(ReturnFalseOnNotFoundOr404.class)
@Path("/images/{id}") @Path("/images/{id}")
ListenableFuture<Boolean> deleteImage(@PathParam("id") int id); ListenableFuture<Boolean> deleteImage(@PathParam("id") int id);
@ -294,6 +292,7 @@ public interface CloudServersAsyncClient {
@ResponseParser(ParseSharedIpGroupFromJsonResponse.class) @ResponseParser(ParseSharedIpGroupFromJsonResponse.class)
@QueryParams(keys = "format", values = "json") @QueryParams(keys = "format", values = "json")
@Path("/shared_ip_groups/{id}") @Path("/shared_ip_groups/{id}")
@ExceptionParser(ReturnNullOnNotFoundOr404.class)
ListenableFuture<SharedIpGroup> getSharedIpGroup(@PathParam("id") int id); ListenableFuture<SharedIpGroup> getSharedIpGroup(@PathParam("id") int id);
/** /**
@ -311,7 +310,7 @@ public interface CloudServersAsyncClient {
* @see CloudServersClient#deleteSharedIpGroup * @see CloudServersClient#deleteSharedIpGroup
*/ */
@DELETE @DELETE
@ExceptionParser(ReturnFalseOn404.class) @ExceptionParser(ReturnFalseOnNotFoundOr404.class)
@Path("/shared_ip_groups/{id}") @Path("/shared_ip_groups/{id}")
ListenableFuture<Boolean> deleteSharedIpGroup(@PathParam("id") int id); ListenableFuture<Boolean> deleteSharedIpGroup(@PathParam("id") int id);
@ -322,13 +321,13 @@ public interface CloudServersAsyncClient {
@ResponseParser(ParseBackupScheduleFromJsonResponse.class) @ResponseParser(ParseBackupScheduleFromJsonResponse.class)
@QueryParams(keys = "format", values = "json") @QueryParams(keys = "format", values = "json")
@Path("/servers/{id}/backup_schedule") @Path("/servers/{id}/backup_schedule")
ListenableFuture<BackupSchedule> listBackupSchedule(@PathParam("id") int serverId); ListenableFuture<BackupSchedule> getBackupSchedule(@PathParam("id") int serverId);
/** /**
* @see CloudServersClient#deleteBackupSchedule * @see CloudServersClient#deleteBackupSchedule
*/ */
@DELETE @DELETE
@ExceptionParser(ReturnFalseOn404.class) @ExceptionParser(ReturnFalseOnNotFoundOr404.class)
@Path("/servers/{id}/backup_schedule") @Path("/servers/{id}/backup_schedule")
ListenableFuture<Boolean> deleteBackupSchedule(@PathParam("id") int serverId); ListenableFuture<Boolean> deleteBackupSchedule(@PathParam("id") int serverId);
@ -338,7 +337,7 @@ public interface CloudServersAsyncClient {
@POST @POST
@ExceptionParser(ReturnFalseOn404.class) @ExceptionParser(ReturnFalseOn404.class)
@Path("/servers/{id}/backup_schedule") @Path("/servers/{id}/backup_schedule")
ListenableFuture<Boolean> replaceBackupSchedule(@PathParam("id") int id, ListenableFuture<Void> replaceBackupSchedule(@PathParam("id") int id,
@BinderParam(BindBackupScheduleToJsonPayload.class) BackupSchedule backupSchedule); @BinderParam(BindBackupScheduleToJsonPayload.class) BackupSchedule backupSchedule);
/** /**
@ -348,7 +347,7 @@ public interface CloudServersAsyncClient {
@ResponseParser(ParseAddressesFromJsonResponse.class) @ResponseParser(ParseAddressesFromJsonResponse.class)
@QueryParams(keys = "format", values = "json") @QueryParams(keys = "format", values = "json")
@Path("/servers/{id}/ips") @Path("/servers/{id}/ips")
ListenableFuture<Addresses> listAddresses(@PathParam("id") int serverId); ListenableFuture<Addresses> getAddresses(@PathParam("id") int serverId);
/** /**
* @see CloudServersClient#listPublicAddresses * @see CloudServersClient#listPublicAddresses

View File

@ -71,8 +71,7 @@ public interface CloudServersClient {
* *
* This operation returns details of the specified server. * This operation returns details of the specified server.
* *
* @throws ResourceNotFoundException * @return null, if the server is not found
* if the server is not found
* @see Server * @see Server
*/ */
Server getServer(@PathParam("id") int id); Server getServer(@PathParam("id") int id);
@ -102,7 +101,7 @@ public interface CloudServersClient {
* graceful shutdown of all processes. A hard reboot is the equivalent of power cycling * graceful shutdown of all processes. A hard reboot is the equivalent of power cycling
* the server. * the server.
*/ */
boolean rebootServer(int id, RebootType rebootType); void rebootServer(int id, RebootType rebootType);
/** /**
* The resize function converts an existing server to a different flavor, in essence, scaling the * The resize function converts an existing server to a different flavor, in essence, scaling the
@ -117,7 +116,7 @@ public interface CloudServersClient {
* <p/> * <p/>
* ACTIVE - QUEUE_RESIZE - ACTIVE (on error) * ACTIVE - QUEUE_RESIZE - ACTIVE (on error)
*/ */
boolean resizeServer(int id, int flavorId); void resizeServer(int id, int flavorId);
/** /**
* The resize function converts an existing server to a different flavor, in essence, scaling the * The resize function converts an existing server to a different flavor, in essence, scaling the
@ -130,7 +129,7 @@ public interface CloudServersClient {
* <p/> * <p/>
* VERIFY_RESIZE - ACTIVE * VERIFY_RESIZE - ACTIVE
*/ */
boolean confirmResizeServer(int id); void confirmResizeServer(int id);
/** /**
* The resize function converts an existing server to a different flavor, in essence, scaling the * The resize function converts an existing server to a different flavor, in essence, scaling the
@ -143,7 +142,7 @@ public interface CloudServersClient {
* <p/> * <p/>
* VERIFY_RESIZE - ACTIVE * VERIFY_RESIZE - ACTIVE
*/ */
boolean revertResizeServer(int id); void revertResizeServer(int id);
/** /**
* This operation asynchronously provisions a new server. The progress of this operation depends * This operation asynchronously provisions a new server. The progress of this operation depends
@ -173,7 +172,7 @@ public interface CloudServersClient {
* - imageId is an optional argument. If it is not specified, the server is rebuilt * - imageId is an optional argument. If it is not specified, the server is rebuilt
* with the original imageId. * with the original imageId.
*/ */
boolean rebuildServer(int id, RebuildServerOptions... options); void rebuildServer(int id, RebuildServerOptions... options);
/** /**
* /** This operation allows you share an IP address to the specified server * /** This operation allows you share an IP address to the specified server
@ -194,9 +193,8 @@ public interface CloudServersClient {
* If set to false, does not bind the IP to the server itself. A heartbeat facility * If set to false, does not bind the IP to the server itself. A heartbeat facility
* (e.g. keepalived) can then be used within the servers to perform health checks and * (e.g. keepalived) can then be used within the servers to perform health checks and
* manage IP failover. * manage IP failover.
* @return false if the server is not found
*/ */
boolean shareIp(InetAddress addressToShare, int serverToTosignBindressTo, int sharedIpGroup, void shareIp(InetAddress addressToShare, int serverToTosignBindressTo, int sharedIpGroup,
boolean configureServer); boolean configureServer);
/** /**
@ -208,16 +206,15 @@ public interface CloudServersClient {
* @param serverToTosignBindressTo * @param serverToTosignBindressTo
* @return * @return
*/ */
boolean unshareIp(InetAddress addressToShare, int serverToTosignBindressTo); void unshareIp(InetAddress addressToShare, int serverToTosignBindressTo);
/** /**
* This operation allows you to change the administrative password. * This operation allows you to change the administrative password.
* <p/> * <p/>
* Status Transition: ACTIVE - PASSWORD - ACTIVE * Status Transition: ACTIVE - PASSWORD - ACTIVE
* *
* @return false if the server is not found
*/ */
boolean changeAdminPass(int id, String adminPass); void changeAdminPass(int id, String adminPass);
/** /**
* This operation allows you to update the name of the server. This operation changes the name of * This operation allows you to update the name of the server. This operation changes the name of
@ -225,9 +222,8 @@ public interface CloudServersClient {
* <p/> * <p/>
* Status Transition: ACTIVE - PASSWORD - ACTIVE * Status Transition: ACTIVE - PASSWORD - ACTIVE
* *
* @return false if the server is not found
*/ */
boolean renameServer(int id, String newName); void renameServer(int id, String newName);
/** /**
* *
@ -242,8 +238,7 @@ public interface CloudServersClient {
* *
* This operation returns details of the specified flavor. * This operation returns details of the specified flavor.
* *
* @throws ResourceNotFoundException * @return null, if the flavor is not found
* if the flavor is not found
* @see Flavor * @see Flavor
*/ */
Flavor getFlavor(int id); Flavor getFlavor(int id);
@ -261,8 +256,8 @@ public interface CloudServersClient {
* *
* This operation returns details of the specified image. * This operation returns details of the specified image.
* *
* @throws ResourceNotFoundException * @return null, if the image is not found
* if the image is not found *
* @see Image * @see Image
*/ */
Image getImage(int id); Image getImage(int id);
@ -314,8 +309,8 @@ public interface CloudServersClient {
* *
* This operation returns details of the specified shared IP group. * This operation returns details of the specified shared IP group.
* *
* @throws ResourceNotFoundException * @return null, if the shared ip group is not found
* if the shared IP group is not found *
* @see SharedIpGroup * @see SharedIpGroup
*/ */
SharedIpGroup getSharedIpGroup(int id); SharedIpGroup getSharedIpGroup(int id);
@ -340,37 +335,48 @@ public interface CloudServersClient {
/** /**
* List the backup schedule for the specified server * List the backup schedule for the specified server
*
* @throws ResourceNotFoundException
* , if the server doesn't exist
*/ */
BackupSchedule listBackupSchedule(int serverId); BackupSchedule getBackupSchedule(int serverId);
/** /**
* Delete backup schedule for the specified server. * Delete backup schedule for the specified server.
* <p/> * <p/>
* Web Hosting #119571 currently disables the schedule, not deletes it. * Web Hosting #119571 currently disables the schedule, not deletes it.
* *
* @return false if the server is not found * @return false if the schedule is not found
*/ */
boolean deleteBackupSchedule(int serverId); boolean deleteBackupSchedule(int serverId);
/** /**
* Enable/update the backup schedule for the specified server * Enable/update the backup schedule for the specified server
* *
* @return false if the server is not found
*/ */
boolean replaceBackupSchedule(int id, BackupSchedule backupSchedule); void replaceBackupSchedule(int id, BackupSchedule backupSchedule);
/** /**
* List all server addresses * List all server addresses
*
* @throws ResourceNotFoundException
* , if the server doesn't exist
*/ */
Addresses listAddresses(int serverId); Addresses getAddresses(int serverId);
/** /**
* List all public server addresses * List all public server addresses
*
* @throws ResourceNotFoundException
* , if the server doesn't exist
*/ */
List<InetAddress> listPublicAddresses(int serverId); List<InetAddress> listPublicAddresses(int serverId);
/** /**
* List all private server addresses * List all private server addresses
*
* @throws ResourceNotFoundException
* , if the server doesn't exist
*/ */
List<InetAddress> listPrivateAddresses(int serverId); List<InetAddress> listPrivateAddresses(int serverId);

View File

@ -20,44 +20,31 @@ package org.jclouds.rackspace.cloudservers.compute;
import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkNotNull;
import static org.jclouds.compute.util.ComputeUtils.METADATA_TO_ID;
import static org.jclouds.concurrent.ConcurrentUtils.awaitCompletion;
import static org.jclouds.concurrent.ConcurrentUtils.makeListenable;
import java.util.Map; import java.util.Map;
import java.util.Set;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService; import java.util.concurrent.ExecutorService;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.annotation.Resource;
import javax.inject.Inject; import javax.inject.Inject;
import javax.inject.Named; import javax.inject.Named;
import javax.inject.Provider; import javax.inject.Provider;
import javax.inject.Singleton; import javax.inject.Singleton;
import org.jclouds.Constants; import org.jclouds.Constants;
import org.jclouds.compute.ComputeService;
import org.jclouds.compute.domain.ComputeMetadata; import org.jclouds.compute.domain.ComputeMetadata;
import org.jclouds.compute.domain.ComputeType; import org.jclouds.compute.domain.ComputeType;
import org.jclouds.compute.domain.Image; import org.jclouds.compute.domain.Image;
import org.jclouds.compute.domain.NodeMetadata; import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.domain.NodeSet;
import org.jclouds.compute.domain.NodeState; import org.jclouds.compute.domain.NodeState;
import org.jclouds.compute.domain.Size; import org.jclouds.compute.domain.Size;
import org.jclouds.compute.domain.Template; import org.jclouds.compute.domain.Template;
import org.jclouds.compute.domain.TemplateBuilder; import org.jclouds.compute.domain.TemplateBuilder;
import org.jclouds.compute.domain.internal.NodeMetadataImpl; import org.jclouds.compute.domain.internal.NodeMetadataImpl;
import org.jclouds.compute.domain.internal.NodeSetImpl; import org.jclouds.compute.internal.BaseComputeService;
import org.jclouds.compute.reference.ComputeServiceConstants;
import org.jclouds.compute.util.ComputeUtils; import org.jclouds.compute.util.ComputeUtils;
import org.jclouds.domain.Credentials; import org.jclouds.domain.Credentials;
import org.jclouds.domain.Location; import org.jclouds.domain.Location;
import org.jclouds.logging.Logger;
import org.jclouds.rackspace.cloudservers.CloudServersClient; import org.jclouds.rackspace.cloudservers.CloudServersClient;
import org.jclouds.rackspace.cloudservers.domain.Server; import org.jclouds.rackspace.cloudservers.domain.Server;
import org.jclouds.rackspace.cloudservers.domain.ServerStatus;
import org.jclouds.rackspace.cloudservers.options.ListOptions; import org.jclouds.rackspace.cloudservers.options.ListOptions;
import org.jclouds.rackspace.reference.RackspaceConstants; import org.jclouds.rackspace.reference.RackspaceConstants;
@ -65,144 +52,44 @@ import com.google.common.base.Function;
import com.google.common.base.Predicate; import com.google.common.base.Predicate;
import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Iterables; import com.google.common.collect.Iterables;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import com.google.common.util.concurrent.ListenableFuture;
/** /**
* @author Adrian Cole * @author Adrian Cole
*/ */
@Singleton @Singleton
public class CloudServersComputeService implements ComputeService { public class CloudServersComputeService extends BaseComputeService {
private static class NodeMatchesTag implements Predicate<NodeMetadata> { private final CloudServersClient client;
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<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 String nodeNamingConvention;
private final ComputeUtils utils;
private final Predicate<Server> serverActive; private final Predicate<Server> serverActive;
private final ServerToNodeMetadata serverToNodeMetadata;
private final Predicate<Server> serverDeleted; private final Predicate<Server> serverDeleted;
protected final ExecutorService executor; private final Function<Server, NodeMetadata> serverToNodeMetadata;
@Inject @Inject
public CloudServersComputeService(CloudServersClient client, public CloudServersComputeService(Provider<TemplateBuilder> templateBuilderProvider,
Provider<TemplateBuilder> templateBuilderProvider,
Provider<Map<String, ? extends Image>> images, Provider<Map<String, ? extends Image>> images,
Provider<Map<String, ? extends Size>> sizes, Provider<Map<String, ? extends Size>> sizes,
Provider<Map<String, ? extends Location>> locations, ComputeUtils utils, Provider<Map<String, ? extends Location>> locations, ComputeUtils utils,
CloudServersClient client, Function<Server, NodeMetadata> serverToNodeMetadata,
@Named("ACTIVE") Predicate<Server> serverActive, @Named("ACTIVE") Predicate<Server> serverActive,
@Named("DELETED") Predicate<Server> serverDeleted, @Named("DELETED") Predicate<Server> serverDeleted,
@Named(RackspaceConstants.PROPERTY_RACKSPACE_USER) String account, @Named(RackspaceConstants.PROPERTY_RACKSPACE_USER) String account,
ServerToNodeMetadata serverToNodeMetadata,
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService executor) { @Named(Constants.PROPERTY_USER_THREADS) ExecutorService executor) {
super(images, sizes, locations, templateBuilderProvider, account + "-%s-%d", utils, executor);
this.client = client; this.client = client;
this.images = images;
this.sizes = sizes;
this.locations = locations;
this.utils = utils;
this.templateBuilderProvider = templateBuilderProvider;
this.serverActive = serverActive; this.serverActive = serverActive;
this.serverDeleted = serverDeleted; this.serverDeleted = serverDeleted;
this.serverToNodeMetadata = serverToNodeMetadata; this.serverToNodeMetadata = serverToNodeMetadata;
this.executor = executor;
this.nodeNamingConvention = account + "-%s-%d";
} }
private static Map<ServerStatus, NodeState> serverToNodeState = ImmutableMap
.<ServerStatus, NodeState> builder().put(ServerStatus.ACTIVE, NodeState.RUNNING)//
.put(ServerStatus.SUSPENDED, NodeState.SUSPENDED)//
.put(ServerStatus.DELETED, NodeState.TERMINATED)//
.put(ServerStatus.QUEUE_RESIZE, NodeState.PENDING)//
.put(ServerStatus.PREP_RESIZE, NodeState.PENDING)//
.put(ServerStatus.RESIZE, NodeState.PENDING)//
.put(ServerStatus.VERIFY_RESIZE, NodeState.PENDING)//
.put(ServerStatus.QUEUE_MOVE, NodeState.PENDING)//
.put(ServerStatus.PREP_MOVE, NodeState.PENDING)//
.put(ServerStatus.MOVE, NodeState.PENDING)//
.put(ServerStatus.VERIFY_MOVE, NodeState.PENDING)//
.put(ServerStatus.RESCUE, NodeState.PENDING)//
.put(ServerStatus.ERROR, NodeState.ERROR)//
.put(ServerStatus.BUILD, NodeState.PENDING)//
.put(ServerStatus.RESTORING, NodeState.PENDING)//
.put(ServerStatus.PASSWORD, NodeState.PENDING)//
.put(ServerStatus.REBUILD, NodeState.PENDING)//
.put(ServerStatus.DELETE_IP, NodeState.PENDING)//
.put(ServerStatus.SHARE_IP_NO_CONFIG, NodeState.PENDING)//
.put(ServerStatus.SHARE_IP, NodeState.PENDING)//
.put(ServerStatus.REBOOT, NodeState.PENDING)//
.put(ServerStatus.HARD_REBOOT, NodeState.PENDING)//
.put(ServerStatus.UNKNOWN, NodeState.UNKNOWN).build();
@Override @Override
public NodeSet runNodesWithTag(final String tag, int count, final Template template) { protected NodeMetadata startNode(final String tag, final String name, final Template template) {
checkArgument(tag.indexOf('-') == -1, "tag cannot contain hyphens");
checkNotNull(template.getLocation(), "location");
final Set<NodeMetadata> nodes = Sets.newHashSet();
int nodesToStart = count;
int i = 0;
while (nodesToStart > 0) {
int currentCount = i;
Map<String, ListenableFuture<Void>> responses = Maps.newHashMap();
for (; i < currentCount + nodesToStart; i++) {
final String name = String.format(nodeNamingConvention, tag, i + 1);
responses.put(name, makeListenable(executor.submit(new Callable<Void>() {
@Override
public Void call() throws Exception {
NodeMetadata node = null;
try {
node = startServerAndConvertToNode(tag, name, template);
logger.debug("<< running server(%s)", node.getId());
utils.runOptionsOnNode(node, template.getOptions());
logger.debug("<< options applied server(%s)", node.getId());
nodes.add(node);
} catch (Exception e) {
if (node != null) {
destroyNode(node);
logger.error(e, "<< error applying server(%s) [%s] destroying ", name, e
.getMessage());
}
}
return null;
}
}), executor));
}
nodesToStart = awaitCompletion(responses, executor, null, logger, "nodes").size();
}
return new NodeSetImpl(nodes);
}
private NodeMetadata startServerAndConvertToNode(final String tag, final String name,
final Template template) {
Server server = client.createServer(name, Integer.parseInt(template.getImage().getId()), Server server = client.createServer(name, Integer.parseInt(template.getImage().getId()),
Integer.parseInt(template.getSize().getId())); Integer.parseInt(template.getSize().getId()));
logger.debug("<< started server(%s)", server.getId());
serverActive.apply(server); serverActive.apply(server);
return new NodeMetadataImpl(server.getId() + "", name, null, null, server.getMetadata(), tag, return new NodeMetadataImpl(server.getId() + "", name, template.getLocation().getId(), null, server.getMetadata(), tag,
NodeState.RUNNING, server.getAddresses().getPublicAddresses(), server.getAddresses() NodeState.RUNNING, server.getAddresses().getPublicAddresses(), server.getAddresses()
.getPrivateAddresses(), ImmutableMap.<String, String> of(), .getPrivateAddresses(), ImmutableMap.<String, String> of(),
new Credentials("root", server.getAdminPass())); new Credentials("root", server.getAdminPass()));
} }
@Override @Override
@ -210,131 +97,25 @@ public class CloudServersComputeService implements ComputeService {
checkArgument(node.getType() == ComputeType.NODE, "this is only valid for nodes, not " checkArgument(node.getType() == ComputeType.NODE, "this is only valid for nodes, not "
+ node.getType()); + node.getType());
checkNotNull(node.getId(), "node.id"); checkNotNull(node.getId(), "node.id");
return 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 Location location;
@SuppressWarnings("unused")
@Inject
ServerToNodeMetadata(Location location) {
this.location = location;
}
@Override
public NodeMetadata apply(Server from) {
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 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
.listServers(ListOptions.Builder.withDetails()), serverToNodeMetadata),
METADATA_TO_ID);
return map;
}
@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");
logger.debug(">> deleting server(%s)", node.getId());
int serverId = Integer.parseInt(node.getId()); int serverId = Integer.parseInt(node.getId());
client.deleteServer(serverId); Server server = client.getServer(serverId);
boolean successful = serverDeleted.apply(client.getServer(serverId)); return server == null ? null : serverToNodeMetadata.apply(server);
logger.debug("<< deleted server(%s) success(%s)", node.getId(), successful);
} }
@Override @Override
public void destroyNodesWithTag(String tag) { // TODO parallel protected Iterable<NodeMetadata> doGetNodes() {
logger.debug(">> terminating servers by tag(%s)", tag); return Iterables.transform(client.listServers(ListOptions.Builder.withDetails()),
Iterable<NodeMetadata> nodesToDestroy = Iterables.filter(doGetNodes(tag), serverToNodeMetadata);
new Predicate<NodeMetadata>() {
@Override
public boolean apply(NodeMetadata input) {
return input.getState() != NodeState.TERMINATED;
}
});
Map<NodeMetadata, ListenableFuture<Void>> responses = Maps.newHashMap();
for (final NodeMetadata node : nodesToDestroy) {
responses.put(node, 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 @Override
public Map<String, ? extends Location> getLocations() { protected boolean doDestroyNode(ComputeMetadata node) {
return locations.get(); int serverId = Integer.parseInt(node.getId());
} // if false server wasn't around in the first place
if (!client.deleteServer(serverId))
@Override return false;
public NodeSet getNodesWithTag(String tag) { Server server = client.getServer(serverId);
logger.debug(">> listing servers by tag(%s)", tag); return server == null ? false : serverDeleted.apply(server);
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 Map<String, ? extends Image> getImages() {
return images.get();
}
@Override
public TemplateBuilder templateBuilder() {
return templateBuilderProvider.get();
} }
} }

View File

@ -28,6 +28,7 @@ import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import javax.annotation.Resource; import javax.annotation.Resource;
import javax.inject.Inject;
import javax.inject.Named; import javax.inject.Named;
import javax.inject.Singleton; import javax.inject.Singleton;
@ -37,9 +38,12 @@ import org.jclouds.compute.ComputeServiceContext;
import org.jclouds.compute.domain.Architecture; import org.jclouds.compute.domain.Architecture;
import org.jclouds.compute.domain.ComputeMetadata; import org.jclouds.compute.domain.ComputeMetadata;
import org.jclouds.compute.domain.Image; import org.jclouds.compute.domain.Image;
import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.domain.NodeState;
import org.jclouds.compute.domain.OsFamily; import org.jclouds.compute.domain.OsFamily;
import org.jclouds.compute.domain.Size; import org.jclouds.compute.domain.Size;
import org.jclouds.compute.domain.internal.ImageImpl; import org.jclouds.compute.domain.internal.ImageImpl;
import org.jclouds.compute.domain.internal.NodeMetadataImpl;
import org.jclouds.compute.domain.internal.SizeImpl; import org.jclouds.compute.domain.internal.SizeImpl;
import org.jclouds.compute.internal.ComputeServiceContextImpl; import org.jclouds.compute.internal.ComputeServiceContextImpl;
import org.jclouds.compute.predicates.RunScriptRunning; import org.jclouds.compute.predicates.RunScriptRunning;
@ -54,6 +58,8 @@ import org.jclouds.rackspace.cloudservers.CloudServersClient;
import org.jclouds.rackspace.cloudservers.compute.CloudServersComputeService; import org.jclouds.rackspace.cloudservers.compute.CloudServersComputeService;
import org.jclouds.rackspace.cloudservers.config.CloudServersContextModule; import org.jclouds.rackspace.cloudservers.config.CloudServersContextModule;
import org.jclouds.rackspace.cloudservers.domain.Flavor; import org.jclouds.rackspace.cloudservers.domain.Flavor;
import org.jclouds.rackspace.cloudservers.domain.Server;
import org.jclouds.rackspace.cloudservers.domain.ServerStatus;
import org.jclouds.rackspace.cloudservers.options.ListOptions; import org.jclouds.rackspace.cloudservers.options.ListOptions;
import org.jclouds.rest.RestContext; import org.jclouds.rest.RestContext;
import org.jclouds.ssh.SshClient; import org.jclouds.ssh.SshClient;
@ -66,6 +72,7 @@ import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Maps; import com.google.common.collect.Maps;
import com.google.common.collect.Sets; import com.google.common.collect.Sets;
import com.google.inject.Provides; import com.google.inject.Provides;
import com.google.inject.TypeLiteral;
/** /**
* Configures the {@link CloudServersComputeServiceContext}; requires * Configures the {@link CloudServersComputeServiceContext}; requires
@ -79,6 +86,59 @@ public class CloudServersComputeServiceContextModule extends CloudServersContext
protected void configure() { protected void configure() {
super.configure(); super.configure();
bind(ComputeService.class).to(CloudServersComputeService.class).asEagerSingleton(); bind(ComputeService.class).to(CloudServersComputeService.class).asEagerSingleton();
bind(new TypeLiteral<Function<Server, NodeMetadata>>() {
}).to(ServerToNodeMetadata.class);
}
@Singleton
@Provides
Map<ServerStatus, NodeState> provideServerToNodeState() {
return ImmutableMap.<ServerStatus, NodeState> builder().put(ServerStatus.ACTIVE,
NodeState.RUNNING)//
.put(ServerStatus.SUSPENDED, NodeState.SUSPENDED)//
.put(ServerStatus.DELETED, NodeState.TERMINATED)//
.put(ServerStatus.QUEUE_RESIZE, NodeState.PENDING)//
.put(ServerStatus.PREP_RESIZE, NodeState.PENDING)//
.put(ServerStatus.RESIZE, NodeState.PENDING)//
.put(ServerStatus.VERIFY_RESIZE, NodeState.PENDING)//
.put(ServerStatus.QUEUE_MOVE, NodeState.PENDING)//
.put(ServerStatus.PREP_MOVE, NodeState.PENDING)//
.put(ServerStatus.MOVE, NodeState.PENDING)//
.put(ServerStatus.VERIFY_MOVE, NodeState.PENDING)//
.put(ServerStatus.RESCUE, NodeState.PENDING)//
.put(ServerStatus.ERROR, NodeState.ERROR)//
.put(ServerStatus.BUILD, NodeState.PENDING)//
.put(ServerStatus.RESTORING, NodeState.PENDING)//
.put(ServerStatus.PASSWORD, NodeState.PENDING)//
.put(ServerStatus.REBUILD, NodeState.PENDING)//
.put(ServerStatus.DELETE_IP, NodeState.PENDING)//
.put(ServerStatus.SHARE_IP_NO_CONFIG, NodeState.PENDING)//
.put(ServerStatus.SHARE_IP, NodeState.PENDING)//
.put(ServerStatus.REBOOT, NodeState.PENDING)//
.put(ServerStatus.HARD_REBOOT, NodeState.PENDING)//
.put(ServerStatus.UNKNOWN, NodeState.UNKNOWN).build();
}
protected static class ServerToNodeMetadata implements Function<Server, NodeMetadata> {
public static final Pattern TAG_PATTERN = Pattern.compile("[^-]+-([^-]+)-[0-9]+");
private final Location location;
private final Map<ServerStatus, NodeState> serverToNodeState;
@Inject
ServerToNodeMetadata(Location location, Map<ServerStatus, NodeState> serverToNodeState) {
this.location = location;
this.serverToNodeState = serverToNodeState;
}
@Override
public NodeMetadata apply(Server from) {
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);
}
} }
@Provides @Provides

View File

@ -1,5 +1,7 @@
package org.jclouds.rackspace.cloudservers.predicates; package org.jclouds.rackspace.cloudservers.predicates;
import static com.google.common.base.Preconditions.checkNotNull;
import javax.annotation.Resource; import javax.annotation.Resource;
import javax.inject.Singleton; import javax.inject.Singleton;
@ -7,7 +9,6 @@ import org.jclouds.logging.Logger;
import org.jclouds.rackspace.cloudservers.CloudServersClient; import org.jclouds.rackspace.cloudservers.CloudServersClient;
import org.jclouds.rackspace.cloudservers.domain.Server; import org.jclouds.rackspace.cloudservers.domain.Server;
import org.jclouds.rackspace.cloudservers.domain.ServerStatus; import org.jclouds.rackspace.cloudservers.domain.ServerStatus;
import org.jclouds.rest.ResourceNotFoundException;
import com.google.common.base.Predicate; import com.google.common.base.Predicate;
import com.google.inject.Inject; import com.google.inject.Inject;
@ -32,15 +33,13 @@ public class ServerActive implements Predicate<Server> {
} }
public boolean apply(Server server) { public boolean apply(Server server) {
logger.trace("looking for state on server %s", server); logger.trace("looking for state on server %s", checkNotNull(server, "server"));
try {
server = refresh(server); server = refresh(server);
if (server == null)
return false;
logger.trace("%s: looking for server state %s: currently: %s", server.getId(), logger.trace("%s: looking for server state %s: currently: %s", server.getId(),
ServerStatus.ACTIVE, server.getStatus()); ServerStatus.ACTIVE, server.getStatus());
return server.getStatus() == ServerStatus.ACTIVE; return server.getStatus() == ServerStatus.ACTIVE;
} catch (ResourceNotFoundException e) {
return false;
}
} }
private Server refresh(Server server) { private Server refresh(Server server) {

View File

@ -1,5 +1,7 @@
package org.jclouds.rackspace.cloudservers.predicates; package org.jclouds.rackspace.cloudservers.predicates;
import static com.google.common.base.Preconditions.checkNotNull;
import javax.annotation.Resource; import javax.annotation.Resource;
import javax.inject.Singleton; import javax.inject.Singleton;
@ -7,7 +9,6 @@ import org.jclouds.logging.Logger;
import org.jclouds.rackspace.cloudservers.CloudServersClient; import org.jclouds.rackspace.cloudservers.CloudServersClient;
import org.jclouds.rackspace.cloudservers.domain.Server; import org.jclouds.rackspace.cloudservers.domain.Server;
import org.jclouds.rackspace.cloudservers.domain.ServerStatus; import org.jclouds.rackspace.cloudservers.domain.ServerStatus;
import org.jclouds.rest.ResourceNotFoundException;
import com.google.common.base.Predicate; import com.google.common.base.Predicate;
import com.google.inject.Inject; import com.google.inject.Inject;
@ -32,15 +33,13 @@ public class ServerDeleted implements Predicate<Server> {
} }
public boolean apply(Server server) { public boolean apply(Server server) {
logger.trace("looking for state on server %s", server); logger.trace("looking for state on server %s", checkNotNull(server, "server"));
try {
server = refresh(server); server = refresh(server);
if (server == null)
return true;
logger.trace("%s: looking for server state %s: currently: %s", server.getId(), logger.trace("%s: looking for server state %s: currently: %s", server.getId(),
ServerStatus.DELETED, server.getStatus()); ServerStatus.DELETED, server.getStatus());
return server.getStatus() == ServerStatus.DELETED; return server.getStatus() == ServerStatus.DELETED;
} catch (ResourceNotFoundException e) {
return true;
}
} }
private Server refresh(Server server) { private Server refresh(Server server) {

View File

@ -52,7 +52,6 @@ import org.jclouds.rackspace.cloudservers.domain.ServerStatus;
import org.jclouds.rackspace.cloudservers.domain.SharedIpGroup; import org.jclouds.rackspace.cloudservers.domain.SharedIpGroup;
import org.jclouds.rackspace.cloudservers.domain.WeeklyBackup; import org.jclouds.rackspace.cloudservers.domain.WeeklyBackup;
import org.jclouds.rackspace.cloudservers.options.RebuildServerOptions; import org.jclouds.rackspace.cloudservers.options.RebuildServerOptions;
import org.jclouds.rest.ResourceNotFoundException;
import org.jclouds.ssh.ExecResponse; import org.jclouds.ssh.ExecResponse;
import org.jclouds.ssh.SshClient; import org.jclouds.ssh.SshClient;
import org.jclouds.ssh.SshException; import org.jclouds.ssh.SshException;
@ -148,19 +147,14 @@ public class CloudServersClientLiveTest {
} }
} }
@Test(expectedExceptions = ResourceNotFoundException.class) @Test
public void testGetImageDetailsNotFound() throws Exception { public void testGetImageDetailsNotFound() throws Exception {
try { assert client.getImage(12312987) == null;
client.getImage(12312987);
} catch (HttpResponseException e) {// Ticket #9867
if (e.getResponse().getStatusCode() != 400)
throw e;
}
} }
@Test(expectedExceptions = ResourceNotFoundException.class) @Test
public void testGetServerDetailsNotFound() throws Exception { public void testGetServerDetailsNotFound() throws Exception {
client.getServer(12312987); assert client.getServer(12312987) == null;
} }
public void testGetServersDetail() throws Exception { public void testGetServersDetail() throws Exception {
@ -210,9 +204,9 @@ public class CloudServersClientLiveTest {
} }
} }
@Test(expectedExceptions = ResourceNotFoundException.class) @Test
public void testGetFlavorDetailsNotFound() throws Exception { public void testGetFlavorDetailsNotFound() throws Exception {
client.getFlavor(12312987); assert client.getFlavor(12312987) == null;
} }
public void testListSharedIpGroups() throws Exception { public void testListSharedIpGroups() throws Exception {
@ -250,9 +244,9 @@ public class CloudServersClientLiveTest {
} }
} }
@Test(expectedExceptions = ResourceNotFoundException.class) @Test
public void testGetSharedIpGroupDetailsNotFound() throws Exception { public void testGetSharedIpGroupDetailsNotFound() throws Exception {
client.getSharedIpGroup(12312987); assert client.getSharedIpGroup(12312987) == null;
} }
@Test(timeOut = 5 * 60 * 1000, dependsOnMethods = "testCreateServer") @Test(timeOut = 5 * 60 * 1000, dependsOnMethods = "testCreateServer")
@ -349,7 +343,7 @@ public class CloudServersClientLiveTest {
assertEquals(new Integer(1), server.getFlavorId()); assertEquals(new Integer(1), server.getFlavorId());
assertNotNull(server.getAddresses()); assertNotNull(server.getAddresses());
// listAddresses tests.. // listAddresses tests..
assertEquals(client.listAddresses(serverId), server.getAddresses()); assertEquals(client.getAddresses(serverId), server.getAddresses());
assertEquals(server.getAddresses().getPublicAddresses().size(), 1); assertEquals(server.getAddresses().getPublicAddresses().size(), 1);
assertEquals(client.listPublicAddresses(serverId), server.getAddresses().getPublicAddresses()); assertEquals(client.listPublicAddresses(serverId), server.getAddresses().getPublicAddresses());
assertEquals(server.getAddresses().getPrivateAddresses().size(), 1); assertEquals(server.getAddresses().getPrivateAddresses().size(), 1);
@ -412,14 +406,14 @@ public class CloudServersClientLiveTest {
public void testRenameServer() throws Exception { public void testRenameServer() throws Exception {
Server server = client.getServer(serverId); Server server = client.getServer(serverId);
String oldName = server.getName(); String oldName = server.getName();
assertTrue(client.renameServer(serverId, oldName + "new")); client.renameServer(serverId, oldName + "new");
blockUntilServerActive(serverId); blockUntilServerActive(serverId);
assertEquals(oldName + "new", client.getServer(serverId).getName()); assertEquals(oldName + "new", client.getServer(serverId).getName());
} }
@Test(timeOut = 5 * 60 * 1000, dependsOnMethods = "testCreateServer") @Test(timeOut = 5 * 60 * 1000, dependsOnMethods = "testCreateServer")
public void testChangePassword() throws Exception { public void testChangePassword() throws Exception {
assertTrue(client.changeAdminPass(serverId, "elmo")); client.changeAdminPass(serverId, "elmo");
blockUntilServerActive(serverId); blockUntilServerActive(serverId);
checkPassOk(client.getServer(serverId), "elmo"); checkPassOk(client.getServer(serverId), "elmo");
this.adminPass = "elmo"; this.adminPass = "elmo";
@ -508,15 +502,15 @@ public class CloudServersClientLiveTest {
@Test(timeOut = 10 * 60 * 1000, dependsOnMethods = "testShareNoConfig") @Test(timeOut = 10 * 60 * 1000, dependsOnMethods = "testShareNoConfig")
public void testBackup() throws Exception { public void testBackup() throws Exception {
assertEquals(new BackupSchedule(), client.listBackupSchedule(serverId)); assertEquals(new BackupSchedule(), client.getBackupSchedule(serverId));
BackupSchedule dailyWeekly = new BackupSchedule(); BackupSchedule dailyWeekly = new BackupSchedule();
dailyWeekly.setEnabled(true); dailyWeekly.setEnabled(true);
dailyWeekly.setWeekly(WeeklyBackup.FRIDAY); dailyWeekly.setWeekly(WeeklyBackup.FRIDAY);
dailyWeekly.setDaily(DailyBackup.H_0400_0600); dailyWeekly.setDaily(DailyBackup.H_0400_0600);
assertEquals(true, client.replaceBackupSchedule(serverId, dailyWeekly)); client.replaceBackupSchedule(serverId, dailyWeekly);
client.deleteBackupSchedule(serverId); client.deleteBackupSchedule(serverId);
// disables, doesn't delete: Web Hosting #119571 // disables, doesn't delete: Web Hosting #119571
assertEquals(client.listBackupSchedule(serverId).isEnabled(), false); assertEquals(client.getBackupSchedule(serverId).isEnabled(), false);
} }
@Test(timeOut = 10 * 60 * 1000, dependsOnMethods = "testBackup") @Test(timeOut = 10 * 60 * 1000, dependsOnMethods = "testBackup")
@ -530,7 +524,7 @@ public class CloudServersClientLiveTest {
@Test(timeOut = 10 * 60 * 1000, dependsOnMethods = "testCreateImage") @Test(timeOut = 10 * 60 * 1000, dependsOnMethods = "testCreateImage")
public void testRebuildServer() throws Exception { public void testRebuildServer() throws Exception {
assertTrue(client.rebuildServer(serverId, new RebuildServerOptions().withImage(imageId))); client.rebuildServer(serverId, new RebuildServerOptions().withImage(imageId));
blockUntilServerActive(serverId); blockUntilServerActive(serverId);
// issue Web Hosting #119580 imageId comes back incorrect after rebuild // issue Web Hosting #119580 imageId comes back incorrect after rebuild
// assertEquals(new Integer(imageId), client.getServer(serverId).getImageId()); // assertEquals(new Integer(imageId), client.getServer(serverId).getImageId());
@ -538,64 +532,64 @@ public class CloudServersClientLiveTest {
@Test(timeOut = 10 * 60 * 1000, dependsOnMethods = "testRebuildServer") @Test(timeOut = 10 * 60 * 1000, dependsOnMethods = "testRebuildServer")
public void testRebootHard() throws Exception { public void testRebootHard() throws Exception {
assertTrue(client.rebootServer(serverId, RebootType.HARD)); client.rebootServer(serverId, RebootType.HARD);
blockUntilServerActive(serverId); blockUntilServerActive(serverId);
} }
@Test(timeOut = 10 * 60 * 1000, dependsOnMethods = "testRebootHard") @Test(timeOut = 10 * 60 * 1000, dependsOnMethods = "testRebootHard")
public void testRebootSoft() throws Exception { public void testRebootSoft() throws Exception {
assertTrue(client.rebootServer(serverId, RebootType.SOFT)); client.rebootServer(serverId, RebootType.SOFT);
blockUntilServerActive(serverId); blockUntilServerActive(serverId);
} }
@Test(timeOut = 10 * 60 * 1000, dependsOnMethods = "testRebootSoft") @Test(timeOut = 10 * 60 * 1000, dependsOnMethods = "testRebootSoft")
public void testRevertResize() throws Exception { public void testRevertResize() throws Exception {
assertTrue(client.resizeServer(serverId, 2)); client.resizeServer(serverId, 2);
blockUntilServerVerifyResize(serverId); blockUntilServerVerifyResize(serverId);
assertTrue(client.revertResizeServer(serverId)); client.revertResizeServer(serverId);
blockUntilServerActive(serverId); blockUntilServerActive(serverId);
assertEquals(new Integer(1), client.getServer(serverId).getFlavorId()); assertEquals(new Integer(1), client.getServer(serverId).getFlavorId());
} }
@Test(timeOut = 10 * 60 * 1000, dependsOnMethods = "testRebootSoft") @Test(timeOut = 10 * 60 * 1000, dependsOnMethods = "testRebootSoft")
public void testConfirmResize() throws Exception { public void testConfirmResize() throws Exception {
assertTrue(client.resizeServer(serverId2, 2)); client.resizeServer(serverId2, 2);
blockUntilServerVerifyResize(serverId2); blockUntilServerVerifyResize(serverId2);
assertTrue(client.confirmResizeServer(serverId2)); client.confirmResizeServer(serverId2);
blockUntilServerActive(serverId2); blockUntilServerActive(serverId2);
assertEquals(new Integer(2), client.getServer(serverId2).getFlavorId()); assertEquals(new Integer(2), client.getServer(serverId2).getFlavorId());
} }
@Test(timeOut = 10 * 60 * 1000, dependsOnMethods = { "testRebootSoft", "testRevertResize", @Test(timeOut = 10 * 60 * 1000, dependsOnMethods = { "testRebootSoft", "testRevertResize",
"testConfirmResize" }, expectedExceptions = ResourceNotFoundException.class) "testConfirmResize" })
void deleteServer2() { void deleteServer2() {
if (serverId2 > 0) { if (serverId2 > 0) {
client.deleteServer(serverId2); client.deleteServer(serverId2);
client.getServer(serverId2); assert client.getServer(serverId2) == null;
} }
} }
@Test(timeOut = 10 * 60 * 1000, dependsOnMethods = "deleteServer2", expectedExceptions = ResourceNotFoundException.class) @Test(timeOut = 10 * 60 * 1000, dependsOnMethods = "deleteServer2")
void testDeleteImage() { void testDeleteImage() {
if (imageId > 0) { if (imageId > 0) {
client.deleteImage(imageId); client.deleteImage(imageId);
client.getImage(imageId); assert client.getImage(imageId) == null;
} }
} }
@Test(timeOut = 10 * 60 * 1000, dependsOnMethods = "testDeleteImage", expectedExceptions = ResourceNotFoundException.class) @Test(timeOut = 10 * 60 * 1000, dependsOnMethods = "testDeleteImage")
void deleteServer1() { void deleteServer1() {
if (serverId > 0) { if (serverId > 0) {
client.deleteServer(serverId); client.deleteServer(serverId);
client.getServer(serverId); assert client.getServer(serverId) == null;
} }
} }
@Test(timeOut = 10 * 60 * 1000, dependsOnMethods = { "deleteServer1" }, expectedExceptions = ResourceNotFoundException.class) @Test(timeOut = 10 * 60 * 1000, dependsOnMethods = { "deleteServer1" })
void testDeleteSharedIpGroup() { void testDeleteSharedIpGroup() {
if (sharedIpGroupId > 0) { if (sharedIpGroupId > 0) {
client.deleteSharedIpGroup(sharedIpGroupId); client.deleteSharedIpGroup(sharedIpGroupId);
client.getSharedIpGroup(sharedIpGroupId); assert client.getSharedIpGroup(sharedIpGroupId) == null;
} }
} }

View File

@ -42,6 +42,7 @@ import javax.ws.rs.core.MediaType;
import org.jclouds.concurrent.config.ExecutorServiceModule; import org.jclouds.concurrent.config.ExecutorServiceModule;
import org.jclouds.date.TimeStamp; import org.jclouds.date.TimeStamp;
import org.jclouds.http.config.JavaUrlHttpCommandExecutorServiceModule; import org.jclouds.http.config.JavaUrlHttpCommandExecutorServiceModule;
import org.jclouds.http.functions.CloseContentAndReturn;
import org.jclouds.http.functions.ReturnFalseOn404; import org.jclouds.http.functions.ReturnFalseOn404;
import org.jclouds.http.functions.ReturnTrueIf2xx; import org.jclouds.http.functions.ReturnTrueIf2xx;
import org.jclouds.logging.Logger; import org.jclouds.logging.Logger;
@ -70,6 +71,9 @@ import org.jclouds.rackspace.cloudservers.options.ListOptions;
import org.jclouds.rackspace.cloudservers.options.RebuildServerOptions; import org.jclouds.rackspace.cloudservers.options.RebuildServerOptions;
import org.jclouds.rest.config.RestModule; import org.jclouds.rest.config.RestModule;
import org.jclouds.rest.functions.MapHttp4xxCodesToExceptions; import org.jclouds.rest.functions.MapHttp4xxCodesToExceptions;
import org.jclouds.rest.functions.ReturnFalseOnNotFoundOr404;
import org.jclouds.rest.functions.ReturnNullOnNotFoundOr404;
import org.jclouds.rest.functions.ReturnVoidOnNotFoundOr404;
import org.jclouds.rest.internal.GeneratedHttpRequest; import org.jclouds.rest.internal.GeneratedHttpRequest;
import org.jclouds.rest.internal.RestAnnotationProcessor; import org.jclouds.rest.internal.RestAnnotationProcessor;
import org.jclouds.util.Jsr330; import org.jclouds.util.Jsr330;
@ -196,7 +200,7 @@ public class CloudServersClientTest {
assertEquals(httpMethod.getHeaders().size(), 0); assertEquals(httpMethod.getHeaders().size(), 0);
assertEquals(processor assertEquals(processor
.createExceptionParserOrThrowResourceNotFoundOn404IfNoAnnotation(method).getClass(), .createExceptionParserOrThrowResourceNotFoundOn404IfNoAnnotation(method).getClass(),
ReturnFalseOn404.class); ReturnFalseOnNotFoundOr404.class);
assertEquals(processor.createResponseParser(method, httpMethod).getClass(), assertEquals(processor.createResponseParser(method, httpMethod).getClass(),
ReturnTrueIf2xx.class); ReturnTrueIf2xx.class);
} }
@ -272,7 +276,7 @@ public class CloudServersClientTest {
ParseServerFromJsonResponse.class); ParseServerFromJsonResponse.class);
assertEquals(processor assertEquals(processor
.createExceptionParserOrThrowResourceNotFoundOn404IfNoAnnotation(method).getClass(), .createExceptionParserOrThrowResourceNotFoundOn404IfNoAnnotation(method).getClass(),
MapHttp4xxCodesToExceptions.class); ReturnNullOnNotFoundOr404.class);
} }
public void testListFlavors() throws SecurityException, NoSuchMethodException { public void testListFlavors() throws SecurityException, NoSuchMethodException {
@ -363,7 +367,7 @@ public class CloudServersClientTest {
ParseFlavorFromJsonResponse.class); ParseFlavorFromJsonResponse.class);
assertEquals(processor assertEquals(processor
.createExceptionParserOrThrowResourceNotFoundOn404IfNoAnnotation(method).getClass(), .createExceptionParserOrThrowResourceNotFoundOn404IfNoAnnotation(method).getClass(),
MapHttp4xxCodesToExceptions.class); ReturnNullOnNotFoundOr404.class);
} }
public void testListImages() throws SecurityException, NoSuchMethodException { public void testListImages() throws SecurityException, NoSuchMethodException {
@ -454,7 +458,7 @@ public class CloudServersClientTest {
ParseImageFromJsonResponse.class); ParseImageFromJsonResponse.class);
assertEquals(processor assertEquals(processor
.createExceptionParserOrThrowResourceNotFoundOn404IfNoAnnotation(method).getClass(), .createExceptionParserOrThrowResourceNotFoundOn404IfNoAnnotation(method).getClass(),
MapHttp4xxCodesToExceptions.class); ReturnNullOnNotFoundOr404.class);
} }
public void testDeleteServer() throws SecurityException, NoSuchMethodException { public void testDeleteServer() throws SecurityException, NoSuchMethodException {
@ -468,7 +472,7 @@ public class CloudServersClientTest {
assertEquals(httpMethod.getHeaders().size(), 0); assertEquals(httpMethod.getHeaders().size(), 0);
assertEquals(processor assertEquals(processor
.createExceptionParserOrThrowResourceNotFoundOn404IfNoAnnotation(method).getClass(), .createExceptionParserOrThrowResourceNotFoundOn404IfNoAnnotation(method).getClass(),
ReturnFalseOn404.class); ReturnFalseOnNotFoundOr404.class);
assertEquals(processor.createResponseParser(method, httpMethod).getClass(), assertEquals(processor.createResponseParser(method, httpMethod).getClass(),
ReturnTrueIf2xx.class); ReturnTrueIf2xx.class);
} }
@ -492,9 +496,9 @@ public class CloudServersClientTest {
assertEquals("{\"shareIp\":{\"sharedIpGroupId\":3}}", httpMethod.getPayload().getRawContent()); assertEquals("{\"shareIp\":{\"sharedIpGroupId\":3}}", httpMethod.getPayload().getRawContent());
assertEquals(processor assertEquals(processor
.createExceptionParserOrThrowResourceNotFoundOn404IfNoAnnotation(method).getClass(), .createExceptionParserOrThrowResourceNotFoundOn404IfNoAnnotation(method).getClass(),
ReturnFalseOn404.class); MapHttp4xxCodesToExceptions.class);
assertEquals(processor.createResponseParser(method, httpMethod).getClass(), assertEquals(processor.createResponseParser(method, httpMethod).getClass(),
ReturnTrueIf2xx.class); CloseContentAndReturn.class);
} }
public void testShareIpConfig() throws SecurityException, NoSuchMethodException, public void testShareIpConfig() throws SecurityException, NoSuchMethodException,
@ -517,9 +521,9 @@ public class CloudServersClientTest {
.getPayload().getRawContent()); .getPayload().getRawContent());
assertEquals(processor assertEquals(processor
.createExceptionParserOrThrowResourceNotFoundOn404IfNoAnnotation(method).getClass(), .createExceptionParserOrThrowResourceNotFoundOn404IfNoAnnotation(method).getClass(),
ReturnFalseOn404.class); MapHttp4xxCodesToExceptions.class);
assertEquals(processor.createResponseParser(method, httpMethod).getClass(), assertEquals(processor.createResponseParser(method, httpMethod).getClass(),
ReturnTrueIf2xx.class); CloseContentAndReturn.class);
} }
public void testUnshareIpNoConfig() throws SecurityException, NoSuchMethodException, public void testUnshareIpNoConfig() throws SecurityException, NoSuchMethodException,
@ -535,9 +539,9 @@ public class CloudServersClientTest {
assertEquals(httpMethod.getHeaders().size(), 0); assertEquals(httpMethod.getHeaders().size(), 0);
assertEquals(processor assertEquals(processor
.createExceptionParserOrThrowResourceNotFoundOn404IfNoAnnotation(method).getClass(), .createExceptionParserOrThrowResourceNotFoundOn404IfNoAnnotation(method).getClass(),
ReturnFalseOn404.class); ReturnVoidOnNotFoundOr404.class);
assertEquals(processor.createResponseParser(method, httpMethod).getClass(), assertEquals(processor.createResponseParser(method, httpMethod).getClass(),
ReturnTrueIf2xx.class); CloseContentAndReturn.class);
} }
public void testReplaceBackupSchedule() throws SecurityException, NoSuchMethodException { public void testReplaceBackupSchedule() throws SecurityException, NoSuchMethodException {
@ -562,7 +566,7 @@ public class CloudServersClientTest {
.createExceptionParserOrThrowResourceNotFoundOn404IfNoAnnotation(method).getClass(), .createExceptionParserOrThrowResourceNotFoundOn404IfNoAnnotation(method).getClass(),
ReturnFalseOn404.class); ReturnFalseOn404.class);
assertEquals(processor.createResponseParser(method, httpMethod).getClass(), assertEquals(processor.createResponseParser(method, httpMethod).getClass(),
ReturnTrueIf2xx.class); CloseContentAndReturn.class);
} }
public void testDeleteBackupSchedule() throws SecurityException, NoSuchMethodException { public void testDeleteBackupSchedule() throws SecurityException, NoSuchMethodException {
@ -576,7 +580,7 @@ public class CloudServersClientTest {
assertEquals(httpMethod.getHeaders().size(), 0); assertEquals(httpMethod.getHeaders().size(), 0);
assertEquals(processor assertEquals(processor
.createExceptionParserOrThrowResourceNotFoundOn404IfNoAnnotation(method).getClass(), .createExceptionParserOrThrowResourceNotFoundOn404IfNoAnnotation(method).getClass(),
ReturnFalseOn404.class); ReturnFalseOnNotFoundOr404.class);
assertEquals(processor.createResponseParser(method, httpMethod).getClass(), assertEquals(processor.createResponseParser(method, httpMethod).getClass(),
ReturnTrueIf2xx.class); ReturnTrueIf2xx.class);
} }
@ -599,9 +603,9 @@ public class CloudServersClientTest {
assertEquals("{\"server\":{\"adminPass\":\"foo\"}}", httpMethod.getPayload().getRawContent()); assertEquals("{\"server\":{\"adminPass\":\"foo\"}}", httpMethod.getPayload().getRawContent());
assertEquals(processor assertEquals(processor
.createExceptionParserOrThrowResourceNotFoundOn404IfNoAnnotation(method).getClass(), .createExceptionParserOrThrowResourceNotFoundOn404IfNoAnnotation(method).getClass(),
ReturnFalseOn404.class); MapHttp4xxCodesToExceptions.class);
assertEquals(processor.createResponseParser(method, httpMethod).getClass(), assertEquals(processor.createResponseParser(method, httpMethod).getClass(),
ReturnTrueIf2xx.class); CloseContentAndReturn.class);
} }
public void testChangeServerName() throws SecurityException, NoSuchMethodException { public void testChangeServerName() throws SecurityException, NoSuchMethodException {
@ -622,9 +626,9 @@ public class CloudServersClientTest {
assertEquals("{\"server\":{\"name\":\"foo\"}}", httpMethod.getPayload().getRawContent()); assertEquals("{\"server\":{\"name\":\"foo\"}}", httpMethod.getPayload().getRawContent());
assertEquals(processor assertEquals(processor
.createExceptionParserOrThrowResourceNotFoundOn404IfNoAnnotation(method).getClass(), .createExceptionParserOrThrowResourceNotFoundOn404IfNoAnnotation(method).getClass(),
ReturnFalseOn404.class); MapHttp4xxCodesToExceptions.class);
assertEquals(processor.createResponseParser(method, httpMethod).getClass(), assertEquals(processor.createResponseParser(method, httpMethod).getClass(),
ReturnTrueIf2xx.class); CloseContentAndReturn.class);
} }
public void testListSharedIpGroups() throws SecurityException, NoSuchMethodException { public void testListSharedIpGroups() throws SecurityException, NoSuchMethodException {
@ -716,7 +720,7 @@ public class CloudServersClientTest {
ParseSharedIpGroupFromJsonResponse.class); ParseSharedIpGroupFromJsonResponse.class);
assertEquals(processor assertEquals(processor
.createExceptionParserOrThrowResourceNotFoundOn404IfNoAnnotation(method).getClass(), .createExceptionParserOrThrowResourceNotFoundOn404IfNoAnnotation(method).getClass(),
MapHttp4xxCodesToExceptions.class); ReturnNullOnNotFoundOr404.class);
} }
private static final Class<? extends CreateSharedIpGroupOptions[]> createSharedIpGroupOptionsVarargsClass = new CreateSharedIpGroupOptions[] {} private static final Class<? extends CreateSharedIpGroupOptions[]> createSharedIpGroupOptionsVarargsClass = new CreateSharedIpGroupOptions[] {}
@ -776,13 +780,13 @@ public class CloudServersClientTest {
assertEquals(httpMethod.getHeaders().size(), 0); assertEquals(httpMethod.getHeaders().size(), 0);
assertEquals(processor assertEquals(processor
.createExceptionParserOrThrowResourceNotFoundOn404IfNoAnnotation(method).getClass(), .createExceptionParserOrThrowResourceNotFoundOn404IfNoAnnotation(method).getClass(),
ReturnFalseOn404.class); ReturnFalseOnNotFoundOr404.class);
assertEquals(processor.createResponseParser(method, httpMethod).getClass(), assertEquals(processor.createResponseParser(method, httpMethod).getClass(),
ReturnTrueIf2xx.class); ReturnTrueIf2xx.class);
} }
public void testListAddresses() throws SecurityException, NoSuchMethodException { public void testListAddresses() throws SecurityException, NoSuchMethodException {
Method method = CloudServersAsyncClient.class.getMethod("listAddresses", int.class); Method method = CloudServersAsyncClient.class.getMethod("getAddresses", int.class);
GeneratedHttpRequest<CloudServersAsyncClient> httpMethod = processor.createRequest(method, GeneratedHttpRequest<CloudServersAsyncClient> httpMethod = processor.createRequest(method,
new Object[] { 2 }); new Object[] { 2 });
@ -824,7 +828,7 @@ public class CloudServersClientTest {
} }
public void testListBackupSchedule() throws SecurityException, NoSuchMethodException { public void testListBackupSchedule() throws SecurityException, NoSuchMethodException {
Method method = CloudServersAsyncClient.class.getMethod("listBackupSchedule", int.class); Method method = CloudServersAsyncClient.class.getMethod("getBackupSchedule", int.class);
GeneratedHttpRequest<CloudServersAsyncClient> httpMethod = processor.createRequest(method, GeneratedHttpRequest<CloudServersAsyncClient> httpMethod = processor.createRequest(method,
new Object[] { 2 }); new Object[] { 2 });
@ -899,9 +903,9 @@ public class CloudServersClientTest {
.singletonList(MediaType.APPLICATION_JSON)); .singletonList(MediaType.APPLICATION_JSON));
assertEquals(processor assertEquals(processor
.createExceptionParserOrThrowResourceNotFoundOn404IfNoAnnotation(method).getClass(), .createExceptionParserOrThrowResourceNotFoundOn404IfNoAnnotation(method).getClass(),
ReturnFalseOn404.class); MapHttp4xxCodesToExceptions.class);
assertEquals(processor.createResponseParser(method, httpMethod).getClass(), assertEquals(processor.createResponseParser(method, httpMethod).getClass(),
ReturnTrueIf2xx.class); CloseContentAndReturn.class);
assertNotNull(processor.getMapPayloadBinderOrNull(method, new Object[] { "", assertNotNull(processor.getMapPayloadBinderOrNull(method, new Object[] { "",
new RebuildServerOptions[] { withImage(2) } })); new RebuildServerOptions[] { withImage(2) } }));
} }
@ -924,9 +928,9 @@ public class CloudServersClientTest {
assertEquals("{\"reboot\":{\"type\":\"HARD\"}}", httpMethod.getPayload().getRawContent()); assertEquals("{\"reboot\":{\"type\":\"HARD\"}}", httpMethod.getPayload().getRawContent());
assertEquals(processor assertEquals(processor
.createExceptionParserOrThrowResourceNotFoundOn404IfNoAnnotation(method).getClass(), .createExceptionParserOrThrowResourceNotFoundOn404IfNoAnnotation(method).getClass(),
ReturnFalseOn404.class); MapHttp4xxCodesToExceptions.class);
assertEquals(processor.createResponseParser(method, httpMethod).getClass(), assertEquals(processor.createResponseParser(method, httpMethod).getClass(),
ReturnTrueIf2xx.class); CloseContentAndReturn.class);
} }
public void testResize() throws SecurityException, NoSuchMethodException { public void testResize() throws SecurityException, NoSuchMethodException {
@ -946,9 +950,9 @@ public class CloudServersClientTest {
assertEquals("{\"resize\":{\"flavorId\":3}}", httpMethod.getPayload().getRawContent()); assertEquals("{\"resize\":{\"flavorId\":3}}", httpMethod.getPayload().getRawContent());
assertEquals(processor assertEquals(processor
.createExceptionParserOrThrowResourceNotFoundOn404IfNoAnnotation(method).getClass(), .createExceptionParserOrThrowResourceNotFoundOn404IfNoAnnotation(method).getClass(),
ReturnFalseOn404.class); MapHttp4xxCodesToExceptions.class);
assertEquals(processor.createResponseParser(method, httpMethod).getClass(), assertEquals(processor.createResponseParser(method, httpMethod).getClass(),
ReturnTrueIf2xx.class); CloseContentAndReturn.class);
} }
public void testConfirmResize() throws SecurityException, NoSuchMethodException { public void testConfirmResize() throws SecurityException, NoSuchMethodException {
@ -968,9 +972,9 @@ public class CloudServersClientTest {
assertEquals("{\"confirmResize\":null}", httpMethod.getPayload().getRawContent()); assertEquals("{\"confirmResize\":null}", httpMethod.getPayload().getRawContent());
assertEquals(processor assertEquals(processor
.createExceptionParserOrThrowResourceNotFoundOn404IfNoAnnotation(method).getClass(), .createExceptionParserOrThrowResourceNotFoundOn404IfNoAnnotation(method).getClass(),
ReturnFalseOn404.class); MapHttp4xxCodesToExceptions.class);
assertEquals(processor.createResponseParser(method, httpMethod).getClass(), assertEquals(processor.createResponseParser(method, httpMethod).getClass(),
ReturnTrueIf2xx.class); CloseContentAndReturn.class);
} }
public void testRevertResize() throws SecurityException, NoSuchMethodException { public void testRevertResize() throws SecurityException, NoSuchMethodException {
@ -989,9 +993,9 @@ public class CloudServersClientTest {
assertEquals("{\"revertResize\":null}", httpMethod.getPayload().getRawContent()); assertEquals("{\"revertResize\":null}", httpMethod.getPayload().getRawContent());
assertEquals(processor assertEquals(processor
.createExceptionParserOrThrowResourceNotFoundOn404IfNoAnnotation(method).getClass(), .createExceptionParserOrThrowResourceNotFoundOn404IfNoAnnotation(method).getClass(),
ReturnFalseOn404.class); MapHttp4xxCodesToExceptions.class);
assertEquals(processor.createResponseParser(method, httpMethod).getClass(), assertEquals(processor.createResponseParser(method, httpMethod).getClass(),
ReturnTrueIf2xx.class); CloseContentAndReturn.class);
} }
@BeforeClass @BeforeClass

View File

@ -60,7 +60,6 @@ public class CloudServersComputeServiceLiveTest extends BaseComputeServiceLiveTe
@SuppressWarnings("unused") @SuppressWarnings("unused")
RestContext<CloudServersAsyncClient, CloudServersClient> tmContext = new ComputeServiceContextFactory() RestContext<CloudServersAsyncClient, CloudServersClient> tmContext = new ComputeServiceContextFactory()
.createContext(service, user, password).getProviderSpecificContext(); .createContext(service, user, password).getProviderSpecificContext();
CloudServersComputeService.class.cast(client); CloudServersComputeService.class.cast(client);
} }
} }

View File

@ -20,179 +20,84 @@ package org.jclouds.rimuhosting.miro.compute;
import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkNotNull;
import static org.jclouds.compute.util.ComputeUtils.METADATA_TO_ID;
import static org.jclouds.concurrent.ConcurrentUtils.awaitCompletion;
import static org.jclouds.concurrent.ConcurrentUtils.makeListenable;
import java.net.InetAddress; import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.Map; import java.util.Map;
import java.util.Set;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService; import java.util.concurrent.ExecutorService;
import java.util.regex.Pattern;
import javax.annotation.Resource;
import javax.inject.Inject; import javax.inject.Inject;
import javax.inject.Named; import javax.inject.Named;
import javax.inject.Provider; import javax.inject.Provider;
import javax.inject.Singleton; import javax.inject.Singleton;
import org.jclouds.Constants; import org.jclouds.Constants;
import org.jclouds.compute.ComputeService;
import org.jclouds.compute.domain.ComputeMetadata; import org.jclouds.compute.domain.ComputeMetadata;
import org.jclouds.compute.domain.ComputeType; import org.jclouds.compute.domain.ComputeType;
import org.jclouds.compute.domain.Image; import org.jclouds.compute.domain.Image;
import org.jclouds.compute.domain.NodeMetadata; import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.domain.NodeSet;
import org.jclouds.compute.domain.NodeState; import org.jclouds.compute.domain.NodeState;
import org.jclouds.compute.domain.Size; import org.jclouds.compute.domain.Size;
import org.jclouds.compute.domain.Template; import org.jclouds.compute.domain.Template;
import org.jclouds.compute.domain.TemplateBuilder; import org.jclouds.compute.domain.TemplateBuilder;
import org.jclouds.compute.domain.internal.NodeMetadataImpl; import org.jclouds.compute.domain.internal.NodeMetadataImpl;
import org.jclouds.compute.domain.internal.NodeSetImpl; import org.jclouds.compute.internal.BaseComputeService;
import org.jclouds.compute.reference.ComputeServiceConstants;
import org.jclouds.compute.util.ComputeUtils; import org.jclouds.compute.util.ComputeUtils;
import org.jclouds.domain.Credentials; import org.jclouds.domain.Credentials;
import org.jclouds.domain.Location; import org.jclouds.domain.Location;
import org.jclouds.logging.Logger;
import org.jclouds.rimuhosting.miro.RimuHostingClient; import org.jclouds.rimuhosting.miro.RimuHostingClient;
import org.jclouds.rimuhosting.miro.domain.NewServerResponse; import org.jclouds.rimuhosting.miro.domain.NewServerResponse;
import org.jclouds.rimuhosting.miro.domain.Server; import org.jclouds.rimuhosting.miro.domain.Server;
import org.jclouds.rimuhosting.miro.domain.internal.RunningState;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Function; import com.google.common.base.Function;
import com.google.common.base.Predicate; import com.google.common.base.Predicate;
import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Iterables; import com.google.common.collect.Iterables;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import com.google.common.util.concurrent.ListenableFuture;
/** /**
* @author Ivan Meredith * @author Ivan Meredith
*/ */
@Singleton @Singleton
public class RimuHostingComputeService implements ComputeService { public class RimuHostingComputeService extends BaseComputeService {
@VisibleForTesting
static Iterable<InetAddress> getPublicAddresses(Server server) {
Iterable<String> addresses = Iterables.concat(ImmutableList.of(server.getIpAddresses()
.getPrimaryIp()), server.getIpAddresses().getSecondaryIps());
return Iterables.transform(addresses, new Function<String, InetAddress>() {
@Override
public InetAddress apply(String from) {
try {
return InetAddress.getByName(from);
} catch (UnknownHostException e) {
// TODO: log the failure.
return null;
}
}
});
}
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 RimuHostingClient client; private final RimuHostingClient client;
protected final Provider<Map<String, ? extends Image>> images; private final Function<Server, NodeMetadata> serverToNodeMetadata;
protected final Provider<Map<String, ? extends Size>> sizes; private final Map<RunningState, NodeState> runningStateToNodeState;
protected final Provider<Map<String, ? extends Location>> locations; private final Predicate<Server> serverRunning;
protected final Provider<TemplateBuilder> templateBuilderProvider; private final Predicate<Server> serverDestroyed;
protected final String nodeNamingConvention; private final Function<Server, Iterable<InetAddress>> getPublicAddresses;
private final ComputeUtils utils;
private final ServerToNodeMetadata serverToNodeMetadata;
protected final ExecutorService executor;
@Inject @Inject
public RimuHostingComputeService(RimuHostingClient client, public RimuHostingComputeService(Provider<TemplateBuilder> templateBuilderProvider,
Provider<TemplateBuilder> templateBuilderProvider,
Provider<Map<String, ? extends Image>> images, Provider<Map<String, ? extends Image>> images,
Provider<Map<String, ? extends Size>> sizes, ServerToNodeMetadata serverToNodeMetadata, Provider<Map<String, ? extends Size>> sizes,
Provider<Map<String, ? extends Location>> locations, ComputeUtils utils, Provider<Map<String, ? extends Location>> locations, ComputeUtils utils,
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService executor) { RimuHostingClient client, Map<RunningState, NodeState> runningStateToNodeState,
@Named("RUNNING") Predicate<Server> serverRunning,
@Named("DESTROYED") Predicate<Server> serverDestroyed,
Function<Server, NodeMetadata> serverToNodeMetadata,
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService executor,
Function<Server, Iterable<InetAddress>> getPublicAddresses) {
super(images, sizes, locations, templateBuilderProvider, "%s-%d", utils, executor);
this.client = client; this.client = client;
this.images = images; this.runningStateToNodeState = runningStateToNodeState;
this.sizes = sizes; this.serverRunning = serverRunning;
this.locations = locations; this.serverDestroyed = serverDestroyed;
this.utils = utils;
this.templateBuilderProvider = templateBuilderProvider;
this.serverToNodeMetadata = serverToNodeMetadata; this.serverToNodeMetadata = serverToNodeMetadata;
this.executor = executor; this.getPublicAddresses = getPublicAddresses;
this.nodeNamingConvention = "%s-%d";
} }
@Override @Override
public NodeSet runNodesWithTag(final String tag, int count, final Template template) { protected NodeMetadata startNode(final String tag, final String name, final Template template) {
checkArgument(tag.indexOf('-') == -1, "tag cannot contain hyphens");
checkNotNull(template.getLocation(), "location");
final Set<NodeMetadata> nodes = Sets.newHashSet();
int nodesToStart = count;
int i = 0;
while (nodesToStart > 0) {
int currentCount = i;
Map<String, ListenableFuture<Void>> responses = Maps.newHashMap();
for (; i < currentCount + nodesToStart; i++) {
final String name = String.format(nodeNamingConvention, tag, i + 1);
responses.put(name, makeListenable(executor.submit(new Callable<Void>() {
@Override
public Void call() throws Exception {
NodeMetadata node = null;
try {
node = startServerAndConvertToNode(tag, name, template);
logger.debug("<< running server(%s)", node.getId());
utils.runOptionsOnNode(node, template.getOptions());
logger.debug("<< options applied server(%s)", node.getId());
nodes.add(node);
} catch (Exception e) {
if (node != null) {
destroyNode(node);
logger.error(e, "<< error applying server(%s) [%s] destroying ", name, e
.getMessage());
}
}
return null;
}
}), executor));
}
nodesToStart = awaitCompletion(responses, executor, null, logger, "nodes").size();
}
return new NodeSetImpl(nodes);
}
private NodeMetadata startServerAndConvertToNode(final String tag, final String name,
final Template template) {
NewServerResponse serverResponse = client.createServer(name, checkNotNull(template.getImage() NewServerResponse serverResponse = client.createServer(name, checkNotNull(template.getImage()
.getId(), "imageId"), checkNotNull(template.getSize().getId(), "sizeId")); .getId(), "imageId"), checkNotNull(template.getSize().getId(), "sizeId"));
NodeMetadata node = new NodeMetadataImpl(serverResponse.getServer().getId().toString(), serverRunning.apply(serverResponse.getServer());
name, Server server = client.getServer(serverResponse.getServer().getId());
template.getLocation().getId(), // we have to lookup the new details in order to retrieve the currently assigned ip address.
null, NodeMetadata node = new NodeMetadataImpl(server.getId().toString(), name, template
ImmutableMap.<String, String> of(), .getLocation().getId(), null, ImmutableMap.<String, String> of(), tag,
tag, runningStateToNodeState.get(server.getState()), getPublicAddresses.apply(server),
NodeState.UNKNOWN,// TODO
// need a
// real
// state!
getPublicAddresses(serverResponse.getServer()),// no real useful data here..
ImmutableList.<InetAddress> of(), ImmutableMap.<String, String> of(), ImmutableList.<InetAddress> of(), ImmutableMap.<String, String> of(),
new Credentials("root", serverResponse.getNewInstanceRequest().getCreateOptions() new Credentials("root", serverResponse.getNewInstanceRequest().getCreateOptions()
.getPassword())); .getPassword()));
@ -204,126 +109,21 @@ public class RimuHostingComputeService implements ComputeService {
checkArgument(node.getType() == ComputeType.NODE, "this is only valid for nodes, not " checkArgument(node.getType() == ComputeType.NODE, "this is only valid for nodes, not "
+ node.getType()); + node.getType());
checkNotNull(node.getId(), "node.id"); checkNotNull(node.getId(), "node.id");
return serverToNodeMetadata.apply(client.getServer(Long.parseLong(node.getId()))); long serverId = Long.parseLong(node.getId());
Server server = client.getServer(serverId);
return server == null ? null : serverToNodeMetadata.apply(server);
} }
@Override @Override
public void destroyNode(ComputeMetadata node) { protected Iterable<NodeMetadata> doGetNodes() {
checkArgument(node.getType() == ComputeType.NODE, "this is only valid for nodes, not " return Iterables.transform(client.getServerList(), serverToNodeMetadata);
+ 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 @Override
public Map<String, ? extends ComputeMetadata> getNodes() { protected boolean doDestroyNode(ComputeMetadata node) {
logger.debug(">> listing servers"); long serverId = Long.parseLong(node.getId());
ImmutableMap<String, NodeMetadata> map = doGetNodes(); client.destroyServer(serverId);
logger.debug("<< list(%d)", map.size()); return serverDestroyed.apply(client.getServer(serverId));
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 destroyNodesWithTag(String tag) { // TODO parallel
logger.debug(">> terminating servers by tag(%s)", tag);
Iterable<NodeMetadata> nodesToDestroy = Iterables.filter(doGetNodes(tag),
new Predicate<NodeMetadata>() {
@Override
public boolean apply(NodeMetadata input) {
return input.getState() != NodeState.TERMINATED;
}
});
Map<NodeMetadata, ListenableFuture<Void>> responses = Maps.newHashMap();
for (final NodeMetadata node : nodesToDestroy) {
responses.put(node, 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 getNodesWithTag(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 Map<String, ? extends Image> getImages() {
return images.get();
}
@Override
public TemplateBuilder templateBuilder() {
return templateBuilderProvider.get();
}
} }

View File

@ -18,6 +18,8 @@
*/ */
package org.jclouds.rimuhosting.miro.compute.config; package org.jclouds.rimuhosting.miro.compute.config;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutionException;
@ -28,6 +30,7 @@ import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import javax.annotation.Resource; import javax.annotation.Resource;
import javax.inject.Inject;
import javax.inject.Named; import javax.inject.Named;
import javax.inject.Singleton; import javax.inject.Singleton;
@ -37,13 +40,17 @@ import org.jclouds.compute.ComputeServiceContext;
import org.jclouds.compute.domain.Architecture; import org.jclouds.compute.domain.Architecture;
import org.jclouds.compute.domain.ComputeMetadata; import org.jclouds.compute.domain.ComputeMetadata;
import org.jclouds.compute.domain.Image; import org.jclouds.compute.domain.Image;
import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.domain.NodeState;
import org.jclouds.compute.domain.OsFamily; import org.jclouds.compute.domain.OsFamily;
import org.jclouds.compute.domain.Size; import org.jclouds.compute.domain.Size;
import org.jclouds.compute.domain.internal.ImageImpl; import org.jclouds.compute.domain.internal.ImageImpl;
import org.jclouds.compute.domain.internal.NodeMetadataImpl;
import org.jclouds.compute.domain.internal.SizeImpl; import org.jclouds.compute.domain.internal.SizeImpl;
import org.jclouds.compute.internal.ComputeServiceContextImpl; import org.jclouds.compute.internal.ComputeServiceContextImpl;
import org.jclouds.compute.predicates.RunScriptRunning; import org.jclouds.compute.predicates.RunScriptRunning;
import org.jclouds.compute.reference.ComputeServiceConstants; import org.jclouds.compute.reference.ComputeServiceConstants;
import org.jclouds.domain.Credentials;
import org.jclouds.domain.Location; import org.jclouds.domain.Location;
import org.jclouds.domain.LocationScope; import org.jclouds.domain.LocationScope;
import org.jclouds.domain.internal.LocationImpl; import org.jclouds.domain.internal.LocationImpl;
@ -55,16 +62,21 @@ import org.jclouds.rimuhosting.miro.RimuHostingClient;
import org.jclouds.rimuhosting.miro.compute.RimuHostingComputeService; import org.jclouds.rimuhosting.miro.compute.RimuHostingComputeService;
import org.jclouds.rimuhosting.miro.config.RimuHostingContextModule; import org.jclouds.rimuhosting.miro.config.RimuHostingContextModule;
import org.jclouds.rimuhosting.miro.domain.PricingPlan; import org.jclouds.rimuhosting.miro.domain.PricingPlan;
import org.jclouds.rimuhosting.miro.domain.Server;
import org.jclouds.rimuhosting.miro.domain.internal.RunningState;
import org.jclouds.ssh.SshClient; import org.jclouds.ssh.SshClient;
import com.google.common.base.Function; import com.google.common.base.Function;
import com.google.common.base.Predicate; import com.google.common.base.Predicate;
import com.google.common.base.Predicates; import com.google.common.base.Predicates;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet; import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import com.google.common.collect.Maps; import com.google.common.collect.Maps;
import com.google.common.collect.Sets; import com.google.common.collect.Sets;
import com.google.inject.Provides; import com.google.inject.Provides;
import com.google.inject.TypeLiteral;
/** /**
* Configures the {@link RimuHostingComputeServiceContext}; requires * Configures the {@link RimuHostingComputeServiceContext}; requires
@ -78,6 +90,69 @@ public class RimuHostingComputeServiceContextModule extends RimuHostingContextMo
protected void configure() { protected void configure() {
super.configure(); super.configure();
bind(ComputeService.class).to(RimuHostingComputeService.class).asEagerSingleton(); bind(ComputeService.class).to(RimuHostingComputeService.class).asEagerSingleton();
bind(new TypeLiteral<Function<Server, NodeMetadata>>() {
}).to(ServerToNodeMetadata.class);
bind(new TypeLiteral<Function<Server, Iterable<InetAddress>>>() {
}).to(ServerToPublicAddresses.class);
}
@Singleton
@Provides
Map<RunningState, NodeState> provideServerToNodeState() {
return ImmutableMap.<RunningState, NodeState> builder().put(RunningState.RUNNING,
NodeState.RUNNING)//
.put(RunningState.NOTRUNNING, NodeState.SUSPENDED)//
.put(RunningState.POWERCYCLING, NodeState.PENDING)//
.put(RunningState.RESTARTING, NodeState.PENDING)//
.build();
}
@Singleton
private static class ServerToNodeMetadata implements Function<Server, NodeMetadata> {
private final Function<Server, Iterable<InetAddress>> getPublicAddresses;
private final Map<RunningState, NodeState> runningStateToNodeState;
@SuppressWarnings("unused")
@Inject
ServerToNodeMetadata(Function<Server, Iterable<InetAddress>> getPublicAddresses,
Map<RunningState, NodeState> runningStateToNodeState) {
this.getPublicAddresses = getPublicAddresses;
this.runningStateToNodeState = runningStateToNodeState;
}
@Override
public NodeMetadata apply(Server from) {
String locationId = "//TODO";
String tag = from.getName().replaceAll("-[0-9]+", "");
Credentials creds = null;
NodeState state = runningStateToNodeState.get(from.getState());
return new NodeMetadataImpl(from.getId() + "", from.getName(), locationId, null,
ImmutableMap.<String, String> of(), tag, state, getPublicAddresses.apply(from),
ImmutableList.<InetAddress> of(), ImmutableMap.<String, String> of(), creds);
}
}
@Singleton
private static class ServerToPublicAddresses implements Function<Server, Iterable<InetAddress>> {
@Override
public Iterable<InetAddress> apply(Server server) {
Iterable<String> addresses = server.getIpAddresses() == null ? ImmutableSet.<String> of()
: Iterables.concat(ImmutableList.of(server.getIpAddresses().getPrimaryIp()),
server.getIpAddresses().getSecondaryIps());
return Iterables.transform(addresses, new Function<String, InetAddress>() {
@Override
public InetAddress apply(String from) {
try {
return InetAddress.getByName(from);
} catch (UnknownHostException e) {
// TODO: log the failure.
return null;
}
}
});
}
} }
@Provides @Provides
@ -199,4 +274,5 @@ public class RimuHostingComputeServiceContextModule extends RimuHostingContextMo
holder.logger.debug("<< images(%d)", images.size()); holder.logger.debug("<< images(%d)", images.size());
return Maps.uniqueIndex(images, indexer); return Maps.uniqueIndex(images, indexer);
} }
} }

View File

@ -18,9 +18,14 @@
*/ */
package org.jclouds.rimuhosting.miro.config; package org.jclouds.rimuhosting.miro.config;
import com.google.common.base.Predicate; import java.io.UnsupportedEncodingException;
import com.google.inject.AbstractModule; import java.net.InetSocketAddress;
import com.google.inject.Provides; import java.net.URI;
import java.util.concurrent.TimeUnit;
import javax.inject.Named;
import javax.inject.Singleton;
import org.jclouds.concurrent.internal.SyncProxy; import org.jclouds.concurrent.internal.SyncProxy;
import org.jclouds.http.RequiresHttp; import org.jclouds.http.RequiresHttp;
import org.jclouds.predicates.RetryablePredicate; import org.jclouds.predicates.RetryablePredicate;
@ -30,15 +35,15 @@ import org.jclouds.rest.RestClientFactory;
import org.jclouds.rimuhosting.miro.RimuHosting; import org.jclouds.rimuhosting.miro.RimuHosting;
import org.jclouds.rimuhosting.miro.RimuHostingAsyncClient; import org.jclouds.rimuhosting.miro.RimuHostingAsyncClient;
import org.jclouds.rimuhosting.miro.RimuHostingClient; import org.jclouds.rimuhosting.miro.RimuHostingClient;
import org.jclouds.rimuhosting.miro.domain.Server;
import org.jclouds.rimuhosting.miro.filters.RimuHostingAuthentication; import org.jclouds.rimuhosting.miro.filters.RimuHostingAuthentication;
import org.jclouds.rimuhosting.miro.predicates.ServerDestroyed;
import org.jclouds.rimuhosting.miro.predicates.ServerRunning;
import org.jclouds.rimuhosting.miro.reference.RimuHostingConstants; import org.jclouds.rimuhosting.miro.reference.RimuHostingConstants;
import javax.inject.Named; import com.google.common.base.Predicate;
import javax.inject.Singleton; import com.google.inject.AbstractModule;
import java.io.UnsupportedEncodingException; import com.google.inject.Provides;
import java.net.InetSocketAddress;
import java.net.URI;
import java.util.concurrent.TimeUnit;
/** /**
* Configures the RimuHosting connection. * Configures the RimuHosting connection.
@ -49,6 +54,20 @@ import java.util.concurrent.TimeUnit;
@ConfiguresRestClient @ConfiguresRestClient
public class RimuHostingRestClientModule extends AbstractModule { public class RimuHostingRestClientModule extends AbstractModule {
@Provides
@Singleton
@Named("RUNNING")
protected Predicate<Server> serverRunning(ServerRunning stateRunning) {
return new RetryablePredicate<Server>(stateRunning, 600, 1, TimeUnit.SECONDS);
}
@Provides
@Singleton
@Named("DESTROYED")
protected Predicate<Server> serverDeleted(ServerDestroyed stateDeleted) {
return new RetryablePredicate<Server>(stateDeleted, 600, 50, TimeUnit.MILLISECONDS);
}
@Provides @Provides
@Singleton @Singleton
protected Predicate<InetSocketAddress> socketTester(SocketOpen open) { protected Predicate<InetSocketAddress> socketTester(SocketOpen open) {

View File

@ -20,6 +20,7 @@ package org.jclouds.rimuhosting.miro.domain;
import com.google.gson.annotations.SerializedName; import com.google.gson.annotations.SerializedName;
import org.jclouds.rimuhosting.miro.data.NewServerData; import org.jclouds.rimuhosting.miro.data.NewServerData;
import org.jclouds.rimuhosting.miro.domain.internal.RunningState;
/** /**
* Instance Object. * Instance Object.
@ -50,7 +51,7 @@ public class Server implements Comparable<Server> {
@SerializedName("order_oid") @SerializedName("order_oid")
private Long id; private Long id;
@SerializedName("running_state") @SerializedName("running_state")
private String state; private RunningState state;
@SerializedName("server_type") @SerializedName("server_type")
private String type; private String type;
private String slug; private String slug;
@ -133,11 +134,11 @@ public class Server implements Comparable<Server> {
this.id = id; this.id = id;
} }
public String getState() { public RunningState getState() {
return state; return state;
} }
public void setState(String state) { public void setState(RunningState state) {
this.state = state; this.state = state;
} }

View File

@ -0,0 +1,42 @@
package org.jclouds.rimuhosting.miro.predicates;
import javax.annotation.Resource;
import javax.inject.Singleton;
import org.jclouds.logging.Logger;
import org.jclouds.rimuhosting.miro.RimuHostingClient;
import org.jclouds.rimuhosting.miro.domain.Server;
import com.google.common.base.Predicate;
import com.google.inject.Inject;
/**
*
* Tests to see if a task succeeds.
*
* @author Adrian Cole
*/
@Singleton
public class ServerDestroyed implements Predicate<Server> {
private final RimuHostingClient client;
@Resource
protected Logger logger = Logger.NULL;
@Inject
public ServerDestroyed(RimuHostingClient client) {
this.client = client;
}
public boolean apply(Server server) {
server = refresh(server);
if (server == null)
return true;
return false;
}
private Server refresh(Server server) {
return client.getServer(server.getId());
}
}

View File

@ -0,0 +1,48 @@
package org.jclouds.rimuhosting.miro.predicates;
import static com.google.common.base.Preconditions.checkNotNull;
import javax.annotation.Resource;
import javax.inject.Singleton;
import org.jclouds.logging.Logger;
import org.jclouds.rimuhosting.miro.RimuHostingClient;
import org.jclouds.rimuhosting.miro.domain.Server;
import org.jclouds.rimuhosting.miro.domain.internal.RunningState;
import com.google.common.base.Predicate;
import com.google.inject.Inject;
/**
*
* Tests to see if a task succeeds.
*
* @author Adrian Cole
*/
@Singleton
public class ServerRunning implements Predicate<Server> {
private final RimuHostingClient client;
@Resource
protected Logger logger = Logger.NULL;
@Inject
public ServerRunning(RimuHostingClient client) {
this.client = client;
}
public boolean apply(Server server) {
logger.trace("looking for state on server %s", checkNotNull(server, "server"));
server = refresh(server);
if (server == null)
return false;
logger.trace("%s: looking for server state %s: currently: %s", server.getId(),
RunningState.RUNNING, server.getState());
return server.getState() == RunningState.RUNNING;
}
private Server refresh(Server server) {
return client.getServer(server.getId());
}
}

View File

@ -189,7 +189,7 @@ public class ComputeTask extends Task {
Template template = createTemplateFromElement(nodeElement, computeService); Template template = createTemplateFromElement(nodeElement, computeService);
for (NodeMetadata createdNode : computeService.runNodesWithTag(tag, nodeElement.getCount(), for (NodeMetadata createdNode : computeService.runNodesWithTag(tag, nodeElement.getCount(),
template)) { template).values()) {
logDetails(computeService, createdNode); logDetails(computeService, createdNode);
addNodeDetailsAsProjectProperties(createdNode); addNodeDetailsAsProjectProperties(createdNode);
} }
@ -216,7 +216,7 @@ public class ComputeTask extends Task {
private void get(ComputeService computeService) { private void get(ComputeService computeService) {
log(String.format("get tag: %s", nodeElement.getTag())); log(String.format("get tag: %s", nodeElement.getTag()));
for (ComputeMetadata node : computeService.getNodesWithTag(nodeElement.getTag())) { for (ComputeMetadata node : computeService.getNodesWithTag(nodeElement.getTag()).values()) {
logDetails(computeService, node); logDetails(computeService, node);
} }
} }

View File

@ -37,11 +37,14 @@ import javax.ws.rs.PathParam;
import javax.ws.rs.Produces; import javax.ws.rs.Produces;
import org.jclouds.rest.annotations.Endpoint; import org.jclouds.rest.annotations.Endpoint;
import org.jclouds.rest.annotations.ExceptionParser;
import org.jclouds.rest.annotations.MapBinder; import org.jclouds.rest.annotations.MapBinder;
import org.jclouds.rest.annotations.MapPayloadParam; import org.jclouds.rest.annotations.MapPayloadParam;
import org.jclouds.rest.annotations.ParamParser; import org.jclouds.rest.annotations.ParamParser;
import org.jclouds.rest.annotations.RequestFilters; import org.jclouds.rest.annotations.RequestFilters;
import org.jclouds.rest.annotations.XMLResponseParser; import org.jclouds.rest.annotations.XMLResponseParser;
import org.jclouds.rest.functions.ReturnNullOnNotFoundOr404;
import org.jclouds.rest.functions.ReturnVoidOnNotFoundOr404;
import org.jclouds.vcloud.binders.BindCloneVAppParamsToXmlPayload; import org.jclouds.vcloud.binders.BindCloneVAppParamsToXmlPayload;
import org.jclouds.vcloud.binders.BindInstantiateVAppTemplateParamsToXmlPayload; import org.jclouds.vcloud.binders.BindInstantiateVAppTemplateParamsToXmlPayload;
import org.jclouds.vcloud.domain.Catalog; import org.jclouds.vcloud.domain.Catalog;
@ -91,6 +94,7 @@ public interface VCloudAsyncClient {
@Endpoint(org.jclouds.vcloud.endpoints.VCloudApi.class) @Endpoint(org.jclouds.vcloud.endpoints.VCloudApi.class)
@Path("/org/{orgId}") @Path("/org/{orgId}")
@XMLResponseParser(OrgHandler.class) @XMLResponseParser(OrgHandler.class)
@ExceptionParser(ReturnNullOnNotFoundOr404.class)
@Consumes(ORG_XML) @Consumes(ORG_XML)
ListenableFuture<? extends Organization> getOrganization(@PathParam("orgId") String orgId); ListenableFuture<? extends Organization> getOrganization(@PathParam("orgId") String orgId);
@ -104,6 +108,7 @@ public interface VCloudAsyncClient {
@Endpoint(org.jclouds.vcloud.endpoints.VCloudApi.class) @Endpoint(org.jclouds.vcloud.endpoints.VCloudApi.class)
@Path("/catalog/{catalogId}") @Path("/catalog/{catalogId}")
@XMLResponseParser(CatalogHandler.class) @XMLResponseParser(CatalogHandler.class)
@ExceptionParser(ReturnNullOnNotFoundOr404.class)
@Consumes(CATALOG_XML) @Consumes(CATALOG_XML)
ListenableFuture<? extends Catalog> getCatalog(@PathParam("catalogId") String catalogId); ListenableFuture<? extends Catalog> getCatalog(@PathParam("catalogId") String catalogId);
@ -112,20 +117,25 @@ public interface VCloudAsyncClient {
@Path("/vAppTemplate/{vAppTemplateId}") @Path("/vAppTemplate/{vAppTemplateId}")
@Consumes(VAPPTEMPLATE_XML) @Consumes(VAPPTEMPLATE_XML)
@XMLResponseParser(VAppTemplateHandler.class) @XMLResponseParser(VAppTemplateHandler.class)
ListenableFuture<? extends VAppTemplate> getVAppTemplate(@PathParam("vAppTemplateId") String vAppTemplateId); @ExceptionParser(ReturnNullOnNotFoundOr404.class)
ListenableFuture<? extends VAppTemplate> getVAppTemplate(
@PathParam("vAppTemplateId") String vAppTemplateId);
@GET @GET
@Endpoint(org.jclouds.vcloud.endpoints.VCloudApi.class) @Endpoint(org.jclouds.vcloud.endpoints.VCloudApi.class)
@Path("/catalogItem/{catalogItemId}") @Path("/catalogItem/{catalogItemId}")
@Consumes(CATALOGITEM_XML) @Consumes(CATALOGITEM_XML)
@XMLResponseParser(CatalogItemHandler.class) @XMLResponseParser(CatalogItemHandler.class)
ListenableFuture<? extends CatalogItem> getCatalogItem(@PathParam("catalogItemId") String catalogItemId); @ExceptionParser(ReturnNullOnNotFoundOr404.class)
ListenableFuture<? extends CatalogItem> getCatalogItem(
@PathParam("catalogItemId") String catalogItemId);
@GET @GET
@Endpoint(org.jclouds.vcloud.endpoints.VCloudApi.class) @Endpoint(org.jclouds.vcloud.endpoints.VCloudApi.class)
@Path("/network/{networkId}") @Path("/network/{networkId}")
@Consumes(NETWORK_XML) @Consumes(NETWORK_XML)
@XMLResponseParser(NetworkHandler.class) @XMLResponseParser(NetworkHandler.class)
@ExceptionParser(ReturnNullOnNotFoundOr404.class)
ListenableFuture<? extends Network> getNetwork(@PathParam("networkId") String networkId); ListenableFuture<? extends Network> getNetwork(@PathParam("networkId") String networkId);
@GET @GET
@ -139,6 +149,7 @@ public interface VCloudAsyncClient {
@Path("/vdc/{vDCId}") @Path("/vdc/{vDCId}")
@XMLResponseParser(VDCHandler.class) @XMLResponseParser(VDCHandler.class)
@Consumes(VDC_XML) @Consumes(VDC_XML)
@ExceptionParser(ReturnNullOnNotFoundOr404.class)
ListenableFuture<? extends VDC> getVDC(@PathParam("vDCId") String vDCId); ListenableFuture<? extends VDC> getVDC(@PathParam("vDCId") String vDCId);
@GET @GET
@ -146,6 +157,7 @@ public interface VCloudAsyncClient {
@Path("/tasksList/{tasksListId}") @Path("/tasksList/{tasksListId}")
@Consumes(TASKSLIST_XML) @Consumes(TASKSLIST_XML)
@XMLResponseParser(TasksListHandler.class) @XMLResponseParser(TasksListHandler.class)
@ExceptionParser(ReturnNullOnNotFoundOr404.class)
ListenableFuture<? extends TasksList> getTasksList(@PathParam("tasksListId") String tasksListId); ListenableFuture<? extends TasksList> getTasksList(@PathParam("tasksListId") String tasksListId);
@GET @GET
@ -163,6 +175,7 @@ public interface VCloudAsyncClient {
@DELETE @DELETE
@Endpoint(org.jclouds.vcloud.endpoints.VCloudApi.class) @Endpoint(org.jclouds.vcloud.endpoints.VCloudApi.class)
@ExceptionParser(ReturnVoidOnNotFoundOr404.class)
@Path("/vApp/{vAppId}") @Path("/vApp/{vAppId}")
ListenableFuture<Void> deleteVApp(@PathParam("vAppId") String vAppId); ListenableFuture<Void> deleteVApp(@PathParam("vAppId") String vAppId);
@ -226,6 +239,7 @@ public interface VCloudAsyncClient {
@Endpoint(org.jclouds.vcloud.endpoints.VCloudApi.class) @Endpoint(org.jclouds.vcloud.endpoints.VCloudApi.class)
@Path("/task/{taskId}") @Path("/task/{taskId}")
@XMLResponseParser(TaskHandler.class) @XMLResponseParser(TaskHandler.class)
@ExceptionParser(ReturnNullOnNotFoundOr404.class)
ListenableFuture<? extends Task> getTask(@PathParam("taskId") String taskId); ListenableFuture<? extends Task> getTask(@PathParam("taskId") String taskId);
@POST @POST
@ -238,6 +252,7 @@ public interface VCloudAsyncClient {
@Endpoint(org.jclouds.vcloud.endpoints.VCloudApi.class) @Endpoint(org.jclouds.vcloud.endpoints.VCloudApi.class)
@Path("/vApp/{vAppId}") @Path("/vApp/{vAppId}")
@XMLResponseParser(VAppHandler.class) @XMLResponseParser(VAppHandler.class)
@ExceptionParser(ReturnNullOnNotFoundOr404.class)
ListenableFuture<? extends VApp> getVApp(@PathParam("vAppId") String appId); ListenableFuture<? extends VApp> getVApp(@PathParam("vAppId") String appId);
@POST @POST

View File

@ -21,18 +21,13 @@ package org.jclouds.vcloud.compute;
import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState; import static com.google.common.base.Preconditions.checkState;
import static org.jclouds.compute.util.ComputeUtils.METADATA_TO_ID;
import static org.jclouds.concurrent.ConcurrentUtils.awaitCompletion;
import static org.jclouds.concurrent.ConcurrentUtils.makeListenable;
import static org.jclouds.vcloud.options.InstantiateVAppTemplateOptions.Builder.processorCount; import static org.jclouds.vcloud.options.InstantiateVAppTemplateOptions.Builder.processorCount;
import java.net.InetAddress; import java.net.InetAddress;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService; import java.util.concurrent.ExecutorService;
import javax.annotation.Resource;
import javax.inject.Named; import javax.inject.Named;
import javax.inject.Provider; import javax.inject.Provider;
import javax.inject.Singleton; import javax.inject.Singleton;
@ -43,18 +38,15 @@ import org.jclouds.compute.domain.ComputeMetadata;
import org.jclouds.compute.domain.ComputeType; import org.jclouds.compute.domain.ComputeType;
import org.jclouds.compute.domain.Image; import org.jclouds.compute.domain.Image;
import org.jclouds.compute.domain.NodeMetadata; import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.domain.NodeSet;
import org.jclouds.compute.domain.NodeState; import org.jclouds.compute.domain.NodeState;
import org.jclouds.compute.domain.Size; import org.jclouds.compute.domain.Size;
import org.jclouds.compute.domain.Template; import org.jclouds.compute.domain.Template;
import org.jclouds.compute.domain.TemplateBuilder; import org.jclouds.compute.domain.TemplateBuilder;
import org.jclouds.compute.domain.internal.NodeMetadataImpl; import org.jclouds.compute.domain.internal.NodeMetadataImpl;
import org.jclouds.compute.domain.internal.NodeSetImpl; import org.jclouds.compute.internal.BaseComputeService;
import org.jclouds.compute.reference.ComputeServiceConstants;
import org.jclouds.compute.util.ComputeUtils; import org.jclouds.compute.util.ComputeUtils;
import org.jclouds.domain.Credentials; import org.jclouds.domain.Credentials;
import org.jclouds.domain.Location; import org.jclouds.domain.Location;
import org.jclouds.logging.Logger;
import org.jclouds.vcloud.VCloudClient; import org.jclouds.vcloud.VCloudClient;
import org.jclouds.vcloud.VCloudMediaType; import org.jclouds.vcloud.VCloudMediaType;
import org.jclouds.vcloud.domain.NamedResource; import org.jclouds.vcloud.domain.NamedResource;
@ -63,117 +55,43 @@ import org.jclouds.vcloud.domain.VApp;
import org.jclouds.vcloud.domain.VAppStatus; import org.jclouds.vcloud.domain.VAppStatus;
import org.jclouds.vcloud.options.InstantiateVAppTemplateOptions; import org.jclouds.vcloud.options.InstantiateVAppTemplateOptions;
import com.google.common.base.Function;
import com.google.common.base.Predicate; import com.google.common.base.Predicate;
import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet; import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import com.google.common.collect.Maps; import com.google.common.collect.Maps;
import com.google.common.collect.Sets; import com.google.common.collect.Sets;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.inject.Inject; import com.google.inject.Inject;
/** /**
* @author Adrian Cole * @author Adrian Cole
*/ */
@Singleton @Singleton
public class VCloudComputeService implements ComputeService, VCloudComputeClient { public class VCloudComputeService extends BaseComputeService implements ComputeService,
VCloudComputeClient {
private static class NodeMatchesTag implements Predicate<NodeMetadata> { protected final VCloudClient client;
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<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 String nodeNamingConvention;
protected final ComputeUtils utils;
protected final Predicate<String> taskTester; protected final Predicate<String> taskTester;
protected final Predicate<VApp> notFoundTester; protected final Predicate<VApp> notFoundTester;
protected final ExecutorService executor; protected final Map<VAppStatus, NodeState> vAppStatusToNodeState;
protected static final Map<VAppStatus, NodeState> vAppStatusToNodeState = ImmutableMap
.<VAppStatus, NodeState> builder().put(VAppStatus.OFF, NodeState.TERMINATED).put(
VAppStatus.ON, NodeState.RUNNING).put(VAppStatus.RESOLVED, NodeState.PENDING)
.put(VAppStatus.SUSPENDED, NodeState.SUSPENDED).put(VAppStatus.UNRESOLVED,
NodeState.PENDING).build();
@Inject @Inject
public VCloudComputeService(VCloudClient client, public VCloudComputeService(Provider<TemplateBuilder> templateBuilderProvider,
Provider<TemplateBuilder> templateBuilderProvider,
Provider<Map<String, ? extends Image>> images, Provider<Map<String, ? extends Image>> images,
Provider<Map<String, ? extends Size>> sizes, Provider<Map<String, ? extends Size>> sizes,
Provider<Map<String, ? extends Location>> locations, ComputeUtils utils, Provider<Map<String, ? extends Location>> locations, ComputeUtils utils,
Predicate<String> successTester, @Named("NOT_FOUND") Predicate<VApp> notFoundTester, VCloudClient client, Predicate<String> successTester,
@Named("NOT_FOUND") Predicate<VApp> notFoundTester,
Map<VAppStatus, NodeState> vAppStatusToNodeState,
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService executor) { @Named(Constants.PROPERTY_USER_THREADS) ExecutorService executor) {
this.taskTester = successTester; super(images, sizes, locations, templateBuilderProvider, "%s-%d", utils, executor);
this.client = client; this.client = client;
this.images = images; this.taskTester = successTester;
this.sizes = sizes;
this.locations = locations;
this.templateBuilderProvider = templateBuilderProvider;
this.utils = utils;
this.notFoundTester = notFoundTester; this.notFoundTester = notFoundTester;
this.executor = executor; this.vAppStatusToNodeState = vAppStatusToNodeState;
this.nodeNamingConvention = "%s-%d";
} }
@Override @Override
public NodeSet runNodesWithTag(final String tag, int count, final Template template) { protected NodeMetadata startNode(final String tag, final String name, final Template template) {
checkArgument(tag.indexOf('-') == -1, "tag cannot contain hyphens");
checkNotNull(template.getLocation(), "location");
final Set<NodeMetadata> nodes = Sets.newHashSet();
int nodesToStart = count;
int i = 0;
while (nodesToStart > 0) {
int currentCount = i;
Map<String, ListenableFuture<Void>> responses = Maps.newHashMap();
for (; i < currentCount + nodesToStart; i++) {
final String name = String.format(nodeNamingConvention, tag, i + 1);
responses.put(name, makeListenable(executor.submit(new Callable<Void>() {
@Override
public Void call() throws Exception {
NodeMetadata node = null;
try {
node = startServerAndConvertToNode(tag, name, template);
logger.debug("<< running server(%s)", node.getId());
utils.runOptionsOnNode(node, template.getOptions());
logger.debug("<< options applied server(%s)", node.getId());
nodes.add(node);
} catch (Exception e) {
if (node != null) {
destroyNode(node);
logger.error(e, "<< error applying server(%s) [%s] destroying ", name, e
.getMessage());
}
}
return null;
}
}), executor));
}
nodesToStart = awaitCompletion(responses, executor, null, logger, "nodes").size();
}
return new NodeSetImpl(nodes);
}
private NodeMetadata startServerAndConvertToNode(final String tag, final String name,
final Template template) {
Map<String, String> metaMap = start(template.getLocation().getId(), name, template.getImage() Map<String, String> metaMap = start(template.getLocation().getId(), name, template.getImage()
.getId(), template.getSize().getCores(), template.getSize().getRam(), template .getId(), template.getSize().getCores(), template.getSize().getRam(), template
.getSize().getDisk() * 1024 * 1024l, ImmutableMap.<String, String> of(), template .getSize().getDisk() * 1024 * 1024l, ImmutableMap.<String, String> of(), template
@ -186,8 +104,8 @@ public class VCloudComputeService implements ComputeService, VCloudComputeClient
Map<String, String> metaMap, VApp vApp) { Map<String, String> metaMap, VApp vApp) {
return new NodeMetadataImpl(vApp.getId(), vApp.getName(), template.getLocation().getId(), return new NodeMetadataImpl(vApp.getId(), vApp.getName(), template.getLocation().getId(),
vApp.getLocation(), ImmutableMap.<String, String> of(), tag, vAppStatusToNodeState vApp.getLocation(), ImmutableMap.<String, String> of(), tag, vAppStatusToNodeState
.get(vApp.getStatus()), getPublicAddresses(vApp.getId()), .get(vApp.getStatus()), getPublicAddresses(vApp.getId()), vApp
getPrivateAddresses(vApp.getId()), ImmutableMap.<String, String> of(), .getNetworkToAddresses().values(), ImmutableMap.<String, String> of(),
new Credentials(metaMap.get("username"), metaMap.get("password"))); new Credentials(metaMap.get("username"), metaMap.get("password")));
} }
@ -209,14 +127,7 @@ public class VCloudComputeService implements ComputeService, VCloudComputeClient
} }
@Override @Override
public Map<String, ? extends ComputeMetadata> getNodes() { protected Iterable<? extends ComputeMetadata> doGetNodes() {
logger.debug(">> listing vApps");
Map<String, ? extends ComputeMetadata> nodes = doGetNodes();
logger.debug("<< list(%d)", nodes.size());
return nodes;
}
private Map<String, ? extends ComputeMetadata> doGetNodes() {
Set<ComputeMetadata> nodes = Sets.newHashSet(); Set<ComputeMetadata> nodes = Sets.newHashSet();
for (NamedResource vdc : client.getDefaultOrganization().getVDCs().values()) { for (NamedResource vdc : client.getDefaultOrganization().getVDCs().values()) {
for (NamedResource resource : client.getVDC(vdc.getId()).getResourceEntities().values()) { for (NamedResource resource : client.getVDC(vdc.getId()).getResourceEntities().values()) {
@ -225,29 +136,13 @@ public class VCloudComputeService implements ComputeService, VCloudComputeClient
} }
} }
} }
return Maps.uniqueIndex(nodes, METADATA_TO_ID); return nodes;
} }
@Override @Override
public void destroyNode(ComputeMetadata node) { protected boolean doDestroyNode(ComputeMetadata node) {
checkArgument(node.getType() == ComputeType.NODE, "this is only valid for nodes, not "
+ node.getType());
stop(checkNotNull(node.getId(), "node.id")); stop(checkNotNull(node.getId(), "node.id"));
} return true;
@Override
public TemplateBuilder templateBuilder() {
return templateBuilderProvider.get();
}
@Override
public Map<String, ? extends Size> getSizes() {
return sizes.get();
}
@Override
public Map<String, ? extends Image> getImages() {
return images.get();
} }
public Map<String, String> start(String vDCId, String name, String templateId, int minCores, public Map<String, String> start(String vDCId, String name, String templateId, int minCores,
@ -369,61 +264,4 @@ public class VCloudComputeService implements ComputeService, VCloudComputeClient
return Sets.newHashSet(vApp.getNetworkToAddresses().values()); return Sets.newHashSet(vApp.getNetworkToAddresses().values());
} }
@Override
public void destroyNodesWithTag(String tag) { // TODO parallel
logger.debug(">> terminating servers by tag(%s)", tag);
Iterable<NodeMetadata> nodesToDestroy = Iterables.filter(doGetNodes(tag),
new Predicate<NodeMetadata>() {
@Override
public boolean apply(NodeMetadata input) {
return input.getState() != NodeState.TERMINATED;
}
});
Map<NodeMetadata, ListenableFuture<Void>> responses = Maps.newHashMap();
for (final NodeMetadata node : nodesToDestroy) {
responses.put(node, 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 getNodesWithTag(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)));
}
} }

View File

@ -36,6 +36,7 @@ import org.jclouds.compute.ComputeServiceContext;
import org.jclouds.compute.domain.Architecture; import org.jclouds.compute.domain.Architecture;
import org.jclouds.compute.domain.ComputeMetadata; import org.jclouds.compute.domain.ComputeMetadata;
import org.jclouds.compute.domain.Image; import org.jclouds.compute.domain.Image;
import org.jclouds.compute.domain.NodeState;
import org.jclouds.compute.domain.OsFamily; import org.jclouds.compute.domain.OsFamily;
import org.jclouds.compute.domain.Size; import org.jclouds.compute.domain.Size;
import org.jclouds.compute.domain.internal.ImageImpl; import org.jclouds.compute.domain.internal.ImageImpl;
@ -60,6 +61,7 @@ import org.jclouds.vcloud.config.VCloudContextModule;
import org.jclouds.vcloud.domain.Catalog; import org.jclouds.vcloud.domain.Catalog;
import org.jclouds.vcloud.domain.CatalogItem; import org.jclouds.vcloud.domain.CatalogItem;
import org.jclouds.vcloud.domain.NamedResource; import org.jclouds.vcloud.domain.NamedResource;
import org.jclouds.vcloud.domain.VAppStatus;
import org.jclouds.vcloud.domain.VAppTemplate; import org.jclouds.vcloud.domain.VAppTemplate;
import org.jclouds.vcloud.domain.VDC; import org.jclouds.vcloud.domain.VDC;
@ -82,6 +84,16 @@ import com.google.inject.Provides;
*/ */
public class VCloudComputeServiceContextModule extends VCloudContextModule { public class VCloudComputeServiceContextModule extends VCloudContextModule {
@Singleton
@Provides
Map<VAppStatus, NodeState> provideVAppStatusToNodeState() {
return ImmutableMap
.<VAppStatus, NodeState> builder().put(VAppStatus.OFF, NodeState.TERMINATED).put(
VAppStatus.ON, NodeState.RUNNING).put(VAppStatus.RESOLVED, NodeState.PENDING).put(
VAppStatus.SUSPENDED, NodeState.SUSPENDED).put(VAppStatus.UNRESOLVED,
NodeState.PENDING).build();
}
@Override @Override
protected void configure() { protected void configure() {
super.configure(); super.configure();

View File

@ -37,6 +37,8 @@ import org.jclouds.http.functions.ParseSax;
import org.jclouds.logging.Logger; import org.jclouds.logging.Logger;
import org.jclouds.logging.Logger.LoggerFactory; import org.jclouds.logging.Logger.LoggerFactory;
import org.jclouds.rest.RestClientTest; import org.jclouds.rest.RestClientTest;
import org.jclouds.rest.functions.ReturnNullOnNotFoundOr404;
import org.jclouds.rest.functions.ReturnVoidOnNotFoundOr404;
import org.jclouds.rest.internal.GeneratedHttpRequest; import org.jclouds.rest.internal.GeneratedHttpRequest;
import org.jclouds.rest.internal.RestAnnotationProcessor; import org.jclouds.rest.internal.RestAnnotationProcessor;
import org.jclouds.util.Jsr330; import org.jclouds.util.Jsr330;
@ -189,7 +191,7 @@ public class VCloudAsyncClientTest extends RestClientTest<VCloudAsyncClient> {
assertResponseParserClassEquals(method, httpMethod, ParseSax.class); assertResponseParserClassEquals(method, httpMethod, ParseSax.class);
assertSaxResponseParserClassEquals(method, OrgHandler.class); assertSaxResponseParserClassEquals(method, OrgHandler.class);
assertExceptionParserClassEquals(method, null); assertExceptionParserClassEquals(method, ReturnNullOnNotFoundOr404.class);
checkFilters(httpMethod); checkFilters(httpMethod);
} }
@ -219,7 +221,7 @@ public class VCloudAsyncClientTest extends RestClientTest<VCloudAsyncClient> {
assertResponseParserClassEquals(method, httpMethod, ParseSax.class); assertResponseParserClassEquals(method, httpMethod, ParseSax.class);
assertSaxResponseParserClassEquals(method, CatalogHandler.class); assertSaxResponseParserClassEquals(method, CatalogHandler.class);
assertExceptionParserClassEquals(method, null); assertExceptionParserClassEquals(method, ReturnNullOnNotFoundOr404.class);
checkFilters(httpMethod); checkFilters(httpMethod);
} }
@ -234,7 +236,7 @@ public class VCloudAsyncClientTest extends RestClientTest<VCloudAsyncClient> {
assertResponseParserClassEquals(method, httpMethod, ParseSax.class); assertResponseParserClassEquals(method, httpMethod, ParseSax.class);
assertSaxResponseParserClassEquals(method, NetworkHandler.class); assertSaxResponseParserClassEquals(method, NetworkHandler.class);
assertExceptionParserClassEquals(method, null); assertExceptionParserClassEquals(method, ReturnNullOnNotFoundOr404.class);
checkFilters(httpMethod); checkFilters(httpMethod);
} }
@ -249,7 +251,7 @@ public class VCloudAsyncClientTest extends RestClientTest<VCloudAsyncClient> {
assertResponseParserClassEquals(method, httpMethod, ParseSax.class); assertResponseParserClassEquals(method, httpMethod, ParseSax.class);
assertSaxResponseParserClassEquals(method, CatalogItemHandler.class); assertSaxResponseParserClassEquals(method, CatalogItemHandler.class);
assertExceptionParserClassEquals(method, null); assertExceptionParserClassEquals(method, ReturnNullOnNotFoundOr404.class);
checkFilters(httpMethod); checkFilters(httpMethod);
} }
@ -264,7 +266,7 @@ public class VCloudAsyncClientTest extends RestClientTest<VCloudAsyncClient> {
assertResponseParserClassEquals(method, httpMethod, ParseSax.class); assertResponseParserClassEquals(method, httpMethod, ParseSax.class);
assertSaxResponseParserClassEquals(method, VAppTemplateHandler.class); assertSaxResponseParserClassEquals(method, VAppTemplateHandler.class);
assertExceptionParserClassEquals(method, null); assertExceptionParserClassEquals(method, ReturnNullOnNotFoundOr404.class);
checkFilters(httpMethod); checkFilters(httpMethod);
} }
@ -294,7 +296,7 @@ public class VCloudAsyncClientTest extends RestClientTest<VCloudAsyncClient> {
assertResponseParserClassEquals(method, httpMethod, ParseSax.class); assertResponseParserClassEquals(method, httpMethod, ParseSax.class);
assertSaxResponseParserClassEquals(method, VDCHandler.class); assertSaxResponseParserClassEquals(method, VDCHandler.class);
assertExceptionParserClassEquals(method, null); assertExceptionParserClassEquals(method, ReturnNullOnNotFoundOr404.class);
checkFilters(httpMethod); checkFilters(httpMethod);
} }
@ -325,7 +327,7 @@ public class VCloudAsyncClientTest extends RestClientTest<VCloudAsyncClient> {
assertResponseParserClassEquals(method, httpMethod, ParseSax.class); assertResponseParserClassEquals(method, httpMethod, ParseSax.class);
assertSaxResponseParserClassEquals(method, TasksListHandler.class); assertSaxResponseParserClassEquals(method, TasksListHandler.class);
assertExceptionParserClassEquals(method, null); assertExceptionParserClassEquals(method, ReturnNullOnNotFoundOr404.class);
checkFilters(httpMethod); checkFilters(httpMethod);
} }
@ -355,7 +357,7 @@ public class VCloudAsyncClientTest extends RestClientTest<VCloudAsyncClient> {
assertResponseParserClassEquals(method, httpMethod, ParseSax.class); assertResponseParserClassEquals(method, httpMethod, ParseSax.class);
assertSaxResponseParserClassEquals(method, VAppHandler.class); assertSaxResponseParserClassEquals(method, VAppHandler.class);
assertExceptionParserClassEquals(method, null); assertExceptionParserClassEquals(method, ReturnNullOnNotFoundOr404.class);
checkFilters(httpMethod); checkFilters(httpMethod);
} }
@ -385,7 +387,7 @@ public class VCloudAsyncClientTest extends RestClientTest<VCloudAsyncClient> {
assertResponseParserClassEquals(method, httpMethod, CloseContentAndReturn.class); assertResponseParserClassEquals(method, httpMethod, CloseContentAndReturn.class);
assertSaxResponseParserClassEquals(method, null); assertSaxResponseParserClassEquals(method, null);
assertExceptionParserClassEquals(method, null); assertExceptionParserClassEquals(method, ReturnVoidOnNotFoundOr404.class);
checkFilters(httpMethod); checkFilters(httpMethod);
} }
@ -477,7 +479,7 @@ public class VCloudAsyncClientTest extends RestClientTest<VCloudAsyncClient> {
assertResponseParserClassEquals(method, httpMethod, ParseSax.class); assertResponseParserClassEquals(method, httpMethod, ParseSax.class);
assertSaxResponseParserClassEquals(method, TaskHandler.class); assertSaxResponseParserClassEquals(method, TaskHandler.class);
assertExceptionParserClassEquals(method, null); assertExceptionParserClassEquals(method, ReturnNullOnNotFoundOr404.class);
checkFilters(httpMethod); checkFilters(httpMethod);
} }

View File

@ -29,11 +29,13 @@ import javax.ws.rs.PathParam;
import javax.ws.rs.Produces; import javax.ws.rs.Produces;
import org.jclouds.rest.annotations.Endpoint; import org.jclouds.rest.annotations.Endpoint;
import org.jclouds.rest.annotations.ExceptionParser;
import org.jclouds.rest.annotations.MapBinder; import org.jclouds.rest.annotations.MapBinder;
import org.jclouds.rest.annotations.MapPayloadParam; import org.jclouds.rest.annotations.MapPayloadParam;
import org.jclouds.rest.annotations.ParamParser; import org.jclouds.rest.annotations.ParamParser;
import org.jclouds.rest.annotations.RequestFilters; import org.jclouds.rest.annotations.RequestFilters;
import org.jclouds.rest.annotations.XMLResponseParser; import org.jclouds.rest.annotations.XMLResponseParser;
import org.jclouds.rest.functions.ReturnNullOnNotFoundOr404;
import org.jclouds.vcloud.VCloudAsyncClient; import org.jclouds.vcloud.VCloudAsyncClient;
import org.jclouds.vcloud.binders.BindInstantiateVAppTemplateParamsToXmlPayload; import org.jclouds.vcloud.binders.BindInstantiateVAppTemplateParamsToXmlPayload;
import org.jclouds.vcloud.domain.Catalog; import org.jclouds.vcloud.domain.Catalog;
@ -70,6 +72,7 @@ public interface HostingDotComVCloudAsyncClient extends VCloudAsyncClient {
@Endpoint(org.jclouds.vcloud.endpoints.VCloudApi.class) @Endpoint(org.jclouds.vcloud.endpoints.VCloudApi.class)
@Path("/vapp/{vAppId}") @Path("/vapp/{vAppId}")
@XMLResponseParser(HostingDotComVAppHandler.class) @XMLResponseParser(HostingDotComVAppHandler.class)
@ExceptionParser(ReturnNullOnNotFoundOr404.class)
@Override @Override
ListenableFuture<? extends HostingDotComVApp> getVApp(@PathParam("vAppId") String appId); ListenableFuture<? extends HostingDotComVApp> getVApp(@PathParam("vAppId") String appId);

View File

@ -12,6 +12,7 @@ import javax.inject.Singleton;
import org.jclouds.Constants; import org.jclouds.Constants;
import org.jclouds.compute.domain.Image; import org.jclouds.compute.domain.Image;
import org.jclouds.compute.domain.NodeState;
import org.jclouds.compute.domain.Size; import org.jclouds.compute.domain.Size;
import org.jclouds.compute.domain.TemplateBuilder; import org.jclouds.compute.domain.TemplateBuilder;
import org.jclouds.compute.util.ComputeUtils; import org.jclouds.compute.util.ComputeUtils;
@ -19,6 +20,7 @@ import org.jclouds.domain.Location;
import org.jclouds.vcloud.VCloudClient; import org.jclouds.vcloud.VCloudClient;
import org.jclouds.vcloud.compute.VCloudComputeService; import org.jclouds.vcloud.compute.VCloudComputeService;
import org.jclouds.vcloud.domain.VApp; import org.jclouds.vcloud.domain.VApp;
import org.jclouds.vcloud.domain.VAppStatus;
import org.jclouds.vcloud.hostingdotcom.domain.HostingDotComVApp; import org.jclouds.vcloud.hostingdotcom.domain.HostingDotComVApp;
import com.google.common.base.Predicate; import com.google.common.base.Predicate;
@ -29,17 +31,17 @@ import com.google.common.collect.ImmutableMap;
*/ */
@Singleton @Singleton
public class HostingDotComVCloudComputeService extends VCloudComputeService { public class HostingDotComVCloudComputeService extends VCloudComputeService {
@Inject @Inject
public HostingDotComVCloudComputeService(VCloudClient client, HostingDotComVCloudComputeService(Provider<TemplateBuilder> templateBuilderProvider,
Provider<TemplateBuilder> templateBuilderProvider,
Provider<Map<String, ? extends Image>> images, Provider<Map<String, ? extends Image>> images,
Provider<Map<String, ? extends Size>> sizes, Provider<Map<String, ? extends Size>> sizes,
Provider<Map<String, ? extends Location>> locations, ComputeUtils utils, Provider<Map<String, ? extends Location>> locations, ComputeUtils utils,
Predicate<String> successTester, @Named("NOT_FOUND") Predicate<VApp> notFoundTester, VCloudClient client, Predicate<String> successTester,
@Named("NOT_FOUND") Predicate<VApp> notFoundTester,
Map<VAppStatus, NodeState> vAppStatusToNodeState,
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService executor) { @Named(Constants.PROPERTY_USER_THREADS) ExecutorService executor) {
super(client, templateBuilderProvider, images, sizes, locations, utils, successTester, super(templateBuilderProvider, images, sizes, locations, utils, client, successTester,
notFoundTester, executor); notFoundTester, vAppStatusToNodeState, executor);
} }
@Override @Override
@ -51,4 +53,5 @@ public class HostingDotComVCloudComputeService extends VCloudComputeService {
return ImmutableMap.<String, String> of("id", vAppResponse.getId(), "username", hVApp return ImmutableMap.<String, String> of("id", vAppResponse.getId(), "username", hVApp
.getUsername(), "password", hVApp.getPassword()); .getUsername(), "password", hVApp.getPassword());
} }
} }

View File

@ -45,6 +45,8 @@ import org.jclouds.rest.annotations.RequestFilters;
import org.jclouds.rest.annotations.ResponseParser; import org.jclouds.rest.annotations.ResponseParser;
import org.jclouds.rest.annotations.XMLResponseParser; import org.jclouds.rest.annotations.XMLResponseParser;
import org.jclouds.rest.functions.InetAddressToHostAddress; import org.jclouds.rest.functions.InetAddressToHostAddress;
import org.jclouds.rest.functions.ReturnNullOnNotFoundOr404;
import org.jclouds.rest.functions.ReturnVoidOnNotFoundOr404;
import org.jclouds.vcloud.VCloudAsyncClient; import org.jclouds.vcloud.VCloudAsyncClient;
import org.jclouds.vcloud.domain.Catalog; import org.jclouds.vcloud.domain.Catalog;
import org.jclouds.vcloud.domain.Task; import org.jclouds.vcloud.domain.Task;
@ -113,6 +115,8 @@ public interface TerremarkVCloudAsyncClient extends VCloudAsyncClient {
@Endpoint(org.jclouds.vcloud.endpoints.Catalog.class) @Endpoint(org.jclouds.vcloud.endpoints.Catalog.class)
@XMLResponseParser(CatalogHandler.class) @XMLResponseParser(CatalogHandler.class)
@Consumes(CATALOG_XML) @Consumes(CATALOG_XML)
@ExceptionParser(ReturnNullOnNotFoundOr404.class)
@Override
ListenableFuture<? extends Catalog> getCatalog(String catalogId); ListenableFuture<? extends Catalog> getCatalog(String catalogId);
/** /**
@ -123,6 +127,7 @@ public interface TerremarkVCloudAsyncClient extends VCloudAsyncClient {
@Path("/vdc/{vDCId}") @Path("/vdc/{vDCId}")
@XMLResponseParser(TerremarkVDCHandler.class) @XMLResponseParser(TerremarkVDCHandler.class)
@Consumes(VDC_XML) @Consumes(VDC_XML)
@ExceptionParser(ReturnNullOnNotFoundOr404.class)
@Override @Override
ListenableFuture<? extends VDC> getVDC(@PathParam("vDCId") String vDCId); ListenableFuture<? extends VDC> getVDC(@PathParam("vDCId") String vDCId);
@ -137,8 +142,8 @@ public interface TerremarkVCloudAsyncClient extends VCloudAsyncClient {
@XMLResponseParser(VAppHandler.class) @XMLResponseParser(VAppHandler.class)
@MapBinder(TerremarkBindInstantiateVAppTemplateParamsToXmlPayload.class) @MapBinder(TerremarkBindInstantiateVAppTemplateParamsToXmlPayload.class)
@Override @Override
ListenableFuture<? extends VApp> instantiateVAppTemplateInVDC( ListenableFuture<? extends VApp> instantiateVAppTemplateInVDC(@PathParam("vDCId") String vDCId,
@PathParam("vDCId") String vDCId, @MapPayloadParam("name") String appName, @MapPayloadParam("name") String appName,
@MapPayloadParam("template") @ParamParser(CatalogIdToUri.class) String templateId, @MapPayloadParam("template") @ParamParser(CatalogIdToUri.class) String templateId,
InstantiateVAppTemplateOptions... options); InstantiateVAppTemplateOptions... options);
@ -211,6 +216,7 @@ public interface TerremarkVCloudAsyncClient extends VCloudAsyncClient {
@Path("/publicIps/{ipId}") @Path("/publicIps/{ipId}")
@Consumes(APPLICATION_XML) @Consumes(APPLICATION_XML)
@XMLResponseParser(InternetServicesHandler.class) @XMLResponseParser(InternetServicesHandler.class)
@ExceptionParser(ReturnNullOnNotFoundOr404.class)
ListenableFuture<? extends SortedSet<InternetService>> getPublicIp(@PathParam("ipId") int ipId); ListenableFuture<? extends SortedSet<InternetService>> getPublicIp(@PathParam("ipId") int ipId);
/** /**
@ -230,6 +236,7 @@ public interface TerremarkVCloudAsyncClient extends VCloudAsyncClient {
@DELETE @DELETE
@Endpoint(org.jclouds.vcloud.endpoints.VCloudApi.class) @Endpoint(org.jclouds.vcloud.endpoints.VCloudApi.class)
@Path("/internetServices/{internetServiceId}") @Path("/internetServices/{internetServiceId}")
@ExceptionParser(ReturnVoidOnNotFoundOr404.class)
ListenableFuture<Void> deleteInternetService( ListenableFuture<Void> deleteInternetService(
@PathParam("internetServiceId") int internetServiceId); @PathParam("internetServiceId") int internetServiceId);
@ -254,6 +261,7 @@ public interface TerremarkVCloudAsyncClient extends VCloudAsyncClient {
@Path("/internetServices/{internetServiceId}") @Path("/internetServices/{internetServiceId}")
@Consumes(APPLICATION_XML) @Consumes(APPLICATION_XML)
@XMLResponseParser(InternetServiceHandler.class) @XMLResponseParser(InternetServiceHandler.class)
@ExceptionParser(ReturnNullOnNotFoundOr404.class)
ListenableFuture<? extends InternetService> getInternetService( ListenableFuture<? extends InternetService> getInternetService(
@PathParam("internetServiceId") int internetServiceId); @PathParam("internetServiceId") int internetServiceId);
@ -292,6 +300,7 @@ public interface TerremarkVCloudAsyncClient extends VCloudAsyncClient {
@Path("/nodeServices/{nodeId}") @Path("/nodeServices/{nodeId}")
@XMLResponseParser(NodeHandler.class) @XMLResponseParser(NodeHandler.class)
@Consumes(APPLICATION_XML) @Consumes(APPLICATION_XML)
@ExceptionParser(ReturnNullOnNotFoundOr404.class)
ListenableFuture<? extends Node> getNode(@PathParam("nodeId") int nodeId); ListenableFuture<? extends Node> getNode(@PathParam("nodeId") int nodeId);
/** /**
@ -313,6 +322,7 @@ public interface TerremarkVCloudAsyncClient extends VCloudAsyncClient {
@DELETE @DELETE
@Endpoint(org.jclouds.vcloud.endpoints.VCloudApi.class) @Endpoint(org.jclouds.vcloud.endpoints.VCloudApi.class)
@Path("/nodeServices/{nodeId}") @Path("/nodeServices/{nodeId}")
@ExceptionParser(ReturnVoidOnNotFoundOr404.class)
ListenableFuture<Void> deleteNode(@PathParam("nodeId") int nodeId); ListenableFuture<Void> deleteNode(@PathParam("nodeId") int nodeId);
/** /**

View File

@ -26,7 +26,6 @@ import java.util.Set;
import java.util.SortedSet; import java.util.SortedSet;
import java.util.concurrent.ExecutorService; import java.util.concurrent.ExecutorService;
import javax.annotation.Resource;
import javax.inject.Inject; import javax.inject.Inject;
import javax.inject.Named; import javax.inject.Named;
import javax.inject.Provider; import javax.inject.Provider;
@ -35,15 +34,15 @@ import javax.inject.Singleton;
import org.jclouds.Constants; import org.jclouds.Constants;
import org.jclouds.compute.domain.Image; import org.jclouds.compute.domain.Image;
import org.jclouds.compute.domain.NodeMetadata; import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.domain.NodeState;
import org.jclouds.compute.domain.Size; import org.jclouds.compute.domain.Size;
import org.jclouds.compute.domain.TemplateBuilder; import org.jclouds.compute.domain.TemplateBuilder;
import org.jclouds.compute.domain.internal.NodeMetadataImpl; import org.jclouds.compute.domain.internal.NodeMetadataImpl;
import org.jclouds.compute.reference.ComputeServiceConstants;
import org.jclouds.compute.util.ComputeUtils; import org.jclouds.compute.util.ComputeUtils;
import org.jclouds.domain.Location; import org.jclouds.domain.Location;
import org.jclouds.logging.Logger;
import org.jclouds.vcloud.compute.VCloudComputeService; import org.jclouds.vcloud.compute.VCloudComputeService;
import org.jclouds.vcloud.domain.VApp; import org.jclouds.vcloud.domain.VApp;
import org.jclouds.vcloud.domain.VAppStatus;
import org.jclouds.vcloud.terremark.TerremarkVCloudClient; import org.jclouds.vcloud.terremark.TerremarkVCloudClient;
import org.jclouds.vcloud.terremark.domain.InternetService; import org.jclouds.vcloud.terremark.domain.InternetService;
import org.jclouds.vcloud.terremark.domain.Node; import org.jclouds.vcloud.terremark.domain.Node;
@ -60,21 +59,20 @@ import com.google.common.collect.Sets;
*/ */
@Singleton @Singleton
public class TerremarkVCloudComputeService extends VCloudComputeService { public class TerremarkVCloudComputeService extends VCloudComputeService {
@Resource
@Named(ComputeServiceConstants.COMPUTE_LOGGER)
protected Logger logger = Logger.NULL;
private final TerremarkVCloudClient client; private final TerremarkVCloudClient client;
@Inject @Inject
public TerremarkVCloudComputeService(TerremarkVCloudClient client, TerremarkVCloudComputeService(Provider<TemplateBuilder> templateBuilderProvider,
Provider<TemplateBuilder> templateBuilderProvider,
Provider<Map<String, ? extends Image>> images, Provider<Map<String, ? extends Image>> images,
Provider<Map<String, ? extends Size>> sizes, Provider<Map<String, ? extends Size>> sizes,
Provider<Map<String, ? extends Location>> locations, ComputeUtils utils, Provider<Map<String, ? extends Location>> locations, ComputeUtils utils,
Predicate<String> successTester, @Named("NOT_FOUND") Predicate<VApp> notFoundTester, TerremarkVCloudClient client, Predicate<String> successTester,
@Named("NOT_FOUND") Predicate<VApp> notFoundTester,
Map<VAppStatus, NodeState> vAppStatusToNodeState,
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService executor) { @Named(Constants.PROPERTY_USER_THREADS) ExecutorService executor) {
super(client, templateBuilderProvider, images, sizes, locations, utils, successTester, super(templateBuilderProvider, images, sizes, locations, utils, client, successTester,
notFoundTester, executor); notFoundTester, vAppStatusToNodeState, executor);
this.client = client; this.client = client;
} }
@ -201,16 +199,13 @@ public class TerremarkVCloudComputeService extends VCloudComputeService {
} }
} }
/** @Override
* public Set<InetAddress> getPrivateAddresses(String id) {
* @throws ElementNotFoundException
* if no address is configured
*/
public InetAddress getAnyPrivateAddress(String id) {
VApp vApp = client.getVApp(id); VApp vApp = client.getVApp(id);
return Iterables.getLast(vApp.getNetworkToAddresses().values()); return Sets.newHashSet(vApp.getNetworkToAddresses().values());
} }
@Override
public Set<InetAddress> getPublicAddresses(String id) { public Set<InetAddress> getPublicAddresses(String id) {
VApp vApp = client.getVApp(id); VApp vApp = client.getVApp(id);
Set<InetAddress> ipAddresses = Sets.newHashSet(); Set<InetAddress> ipAddresses = Sets.newHashSet();

View File

@ -42,6 +42,8 @@ import org.jclouds.http.functions.ParseSax;
import org.jclouds.logging.Logger; import org.jclouds.logging.Logger;
import org.jclouds.logging.Logger.LoggerFactory; import org.jclouds.logging.Logger.LoggerFactory;
import org.jclouds.rest.RestClientTest; import org.jclouds.rest.RestClientTest;
import org.jclouds.rest.functions.ReturnNullOnNotFoundOr404;
import org.jclouds.rest.functions.ReturnVoidOnNotFoundOr404;
import org.jclouds.rest.internal.GeneratedHttpRequest; import org.jclouds.rest.internal.GeneratedHttpRequest;
import org.jclouds.rest.internal.RestAnnotationProcessor; import org.jclouds.rest.internal.RestAnnotationProcessor;
import org.jclouds.util.Jsr330; import org.jclouds.util.Jsr330;
@ -98,7 +100,7 @@ public class TerremarkVCloudAsyncClientTest extends RestClientTest<TerremarkVClo
assertResponseParserClassEquals(method, httpMethod, ParseSax.class); assertResponseParserClassEquals(method, httpMethod, ParseSax.class);
assertSaxResponseParserClassEquals(method, CatalogHandler.class); assertSaxResponseParserClassEquals(method, CatalogHandler.class);
assertExceptionParserClassEquals(method, null); assertExceptionParserClassEquals(method, ReturnNullOnNotFoundOr404.class);
checkFilters(httpMethod); checkFilters(httpMethod);
} }
@ -147,7 +149,7 @@ public class TerremarkVCloudAsyncClientTest extends RestClientTest<TerremarkVClo
assertResponseParserClassEquals(method, httpMethod, ParseSax.class); assertResponseParserClassEquals(method, httpMethod, ParseSax.class);
assertSaxResponseParserClassEquals(method, TerremarkVDCHandler.class); assertSaxResponseParserClassEquals(method, TerremarkVDCHandler.class);
assertExceptionParserClassEquals(method, null); assertExceptionParserClassEquals(method, ReturnNullOnNotFoundOr404.class);
checkFilters(httpMethod); checkFilters(httpMethod);
} }
@ -271,7 +273,7 @@ public class TerremarkVCloudAsyncClientTest extends RestClientTest<TerremarkVClo
assertResponseParserClassEquals(method, httpMethod, ParseSax.class); assertResponseParserClassEquals(method, httpMethod, ParseSax.class);
assertSaxResponseParserClassEquals(method, InternetServiceHandler.class); assertSaxResponseParserClassEquals(method, InternetServiceHandler.class);
assertExceptionParserClassEquals(method, null); assertExceptionParserClassEquals(method, ReturnNullOnNotFoundOr404.class);
checkFilters(httpMethod); checkFilters(httpMethod);
} }
@ -289,7 +291,7 @@ public class TerremarkVCloudAsyncClientTest extends RestClientTest<TerremarkVClo
assertResponseParserClassEquals(method, httpMethod, CloseContentAndReturn.class); assertResponseParserClassEquals(method, httpMethod, CloseContentAndReturn.class);
assertSaxResponseParserClassEquals(method, null); assertSaxResponseParserClassEquals(method, null);
assertExceptionParserClassEquals(method, null); assertExceptionParserClassEquals(method, ReturnVoidOnNotFoundOr404.class);
checkFilters(httpMethod); checkFilters(httpMethod);
} }
@ -388,7 +390,7 @@ public class TerremarkVCloudAsyncClientTest extends RestClientTest<TerremarkVClo
assertResponseParserClassEquals(method, httpMethod, ParseSax.class); assertResponseParserClassEquals(method, httpMethod, ParseSax.class);
assertSaxResponseParserClassEquals(method, NodeHandler.class); assertSaxResponseParserClassEquals(method, NodeHandler.class);
assertExceptionParserClassEquals(method, null); assertExceptionParserClassEquals(method, ReturnNullOnNotFoundOr404.class);
checkFilters(httpMethod); checkFilters(httpMethod);
} }
@ -461,7 +463,7 @@ public class TerremarkVCloudAsyncClientTest extends RestClientTest<TerremarkVClo
assertResponseParserClassEquals(method, httpMethod, CloseContentAndReturn.class); assertResponseParserClassEquals(method, httpMethod, CloseContentAndReturn.class);
assertSaxResponseParserClassEquals(method, null); assertSaxResponseParserClassEquals(method, null);
assertExceptionParserClassEquals(method, null); assertExceptionParserClassEquals(method, ReturnVoidOnNotFoundOr404.class);
checkFilters(httpMethod); checkFilters(httpMethod);
} }