Adding listNodesByIds across the board.

Adding to both ListNodesStrategy and ComputeServiceAdapter. When
possible, does a query explicitly for the specified IDs. When not,
falls back on either listDetailsOnNodesMatching (for ListNodesStrategy
implementations and in BaseComputeService) or filters listNodes output
itself (in ComputeServiceAdapter).
This commit is contained in:
Andrew Bayer 2013-03-17 15:07:55 -04:00 committed by adriancole
parent 900f26d700
commit 15046719eb
27 changed files with 517 additions and 38 deletions

View File

@ -19,6 +19,11 @@
package org.jclouds.byon.internal;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Predicates.in;
import static com.google.common.collect.Iterables.filter;
import static com.google.common.collect.Iterables.getOnlyElement;
import static com.google.common.collect.Iterables.transform;
import static com.google.common.collect.Maps.filterKeys;
import java.util.Set;
@ -44,6 +49,7 @@ import com.google.common.cache.LoadingCache;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import com.google.common.collect.ImmutableSet.Builder;
import com.google.common.collect.Maps;
import com.google.common.util.concurrent.UncheckedExecutionException;
/**
*
@ -80,14 +86,19 @@ public class BYONComputeServiceAdapter implements JCloudsNativeComputeServiceAda
@Override
public Iterable<NodeMetadata> listNodes() {
return Iterables.transform(nodes.get().asMap().values(), converter);
return transform(nodes.get().asMap().values(), converter);
}
@Override
public Iterable<NodeMetadata> listNodesByIds(Iterable<String> ids) {
return transform(filterKeys(nodes.get().asMap(), in(ImmutableSet.copyOf(ids))).values(), converter);
}
@Override
public Iterable<Location> listLocations() {
Builder<Location> locations = ImmutableSet.builder();
Location provider = Iterables.getOnlyElement(locationSupplier.get());
Set<String> zones = ImmutableSet.copyOf(Iterables.filter(Iterables.transform(nodes.get().asMap().values(),
Location provider = getOnlyElement(locationSupplier.get());
Set<String> zones = ImmutableSet.copyOf(filter(transform(nodes.get().asMap().values(),
new Function<Node, String>() {
@Override

View File

@ -19,6 +19,8 @@
package org.jclouds.cloudservers.compute.strategy;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.collect.Iterables.contains;
import static com.google.common.collect.Iterables.filter;
import static org.jclouds.cloudservers.options.CreateServerOptions.Builder.withMetadata;
import static org.jclouds.cloudservers.options.ListOptions.Builder.withDetails;
import static org.jclouds.compute.util.ComputeServiceUtils.metadataAndTagsAsCommaDelimitedValue;
@ -37,7 +39,9 @@ import org.jclouds.compute.domain.Template;
import org.jclouds.domain.Location;
import org.jclouds.domain.LoginCredentials;
import com.google.common.base.Predicate;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
/**
* defines the connection between the {@link CloudServersClient} implementation and the jclouds
@ -83,6 +87,17 @@ public class CloudServersComputeServiceAdapter implements ComputeServiceAdapter<
return client.listServers(ListOptions.Builder.withDetails());
}
@Override
public Iterable<Server> listNodesByIds(final Iterable<String> ids) {
return filter(listNodes(), new Predicate<Server>() {
@Override
public boolean apply(Server server) {
return contains(ids, server.getId());
}
});
}
@Override
public Iterable<Location> listLocations() {
// Not using the adapter to determine locations

View File

@ -73,7 +73,13 @@ public class CloudServersComputeServiceLiveTest extends BaseComputeServiceLiveTe
super.testListNodes();
}
@Test(enabled = true, dependsOnMethods = { "testListNodes", "testGetNodesWithDetails" })
@Test(enabled = true, dependsOnMethods = "testSuspendResume")
@Override
public void testListNodesByIds() throws Exception {
super.testListNodesByIds();
}
@Test(enabled = true, dependsOnMethods = { "testListNodes", "testGetNodesWithDetails", "listNodesByIds" })
@Override
public void testDestroyNodes() {
super.testDestroyNodes();

View File

@ -20,6 +20,8 @@ package org.jclouds.cloudsigma.compute;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.collect.Iterables.contains;
import static com.google.common.collect.Iterables.filter;
import static org.jclouds.concurrent.FutureIterables.transformParallel;
import javax.annotation.Resource;
@ -62,6 +64,7 @@ import com.google.common.collect.FluentIterable;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.ImmutableSet.Builder;
import com.google.common.collect.Iterables;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.ListeningExecutorService;
@ -197,6 +200,17 @@ public class CloudSigmaComputeServiceAdapter implements
return (Iterable<ServerInfo>) client.listServerInfo();
}
@Override
public Iterable<ServerInfo> listNodesByIds(final Iterable<String> ids) {
return filter(listNodes(), new Predicate<ServerInfo>() {
@Override
public boolean apply(ServerInfo server) {
return contains(ids, server.getUuid());
}
});
}
@Override
public Iterable<Location> listLocations() {
// Not using the adapter to determine locations

View File

@ -21,6 +21,7 @@ package org.jclouds.cloudstack.compute.strategy;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState;
import static com.google.common.collect.Iterables.contains;
import static com.google.common.collect.Iterables.filter;
import static com.google.common.collect.Iterables.get;
import static org.jclouds.cloudstack.options.DeployVirtualMachineOptions.Builder.displayName;
@ -69,6 +70,7 @@ import com.google.common.base.Supplier;
import com.google.common.base.Throwables;
import com.google.common.cache.LoadingCache;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import com.google.common.collect.Sets;
import com.google.common.collect.ImmutableSet.Builder;
import com.google.common.primitives.Ints;
@ -234,6 +236,17 @@ public class CloudStackComputeServiceAdapter implements
return client.getVirtualMachineClient().listVirtualMachines();
}
@Override
public Iterable<VirtualMachine> listNodesByIds(final Iterable<String> ids) {
return filter(listNodes(), new Predicate<VirtualMachine>() {
@Override
public boolean apply(VirtualMachine vm) {
return contains(ids, vm.getId());
}
});
}
@Override
public Iterable<Zone> listLocations() {
// TODO: we may need to filter these

View File

@ -20,10 +20,15 @@ package org.jclouds.ec2.compute.strategy;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Predicates.and;
import static com.google.common.base.Predicates.in;
import static com.google.common.base.Predicates.notNull;
import static com.google.common.collect.Iterables.concat;
import static com.google.common.collect.Iterables.filter;
import static com.google.common.collect.Iterables.toArray;
import static com.google.common.collect.Iterables.transform;
import static com.google.common.collect.Multimaps.filterKeys;
import static com.google.common.collect.Multimaps.index;
import static com.google.common.collect.Multimaps.transformValues;
import static org.jclouds.concurrent.FutureIterables.transformParallel;
import java.util.Set;
@ -33,12 +38,13 @@ import javax.inject.Named;
import javax.inject.Singleton;
import org.jclouds.Constants;
import org.jclouds.aws.util.AWSUtils;
import org.jclouds.compute.domain.ComputeMetadata;
import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.predicates.NodePredicates;
import org.jclouds.compute.reference.ComputeServiceConstants;
import org.jclouds.compute.strategy.ListNodesStrategy;
import org.jclouds.ec2.EC2AsyncClient;
import org.jclouds.ec2.EC2Client;
import org.jclouds.ec2.domain.Reservation;
import org.jclouds.ec2.domain.RunningInstance;
import org.jclouds.location.Region;
@ -48,6 +54,8 @@ import com.google.common.base.Function;
import com.google.common.base.Predicate;
import com.google.common.base.Supplier;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import com.google.common.collect.Multimap;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.ListeningExecutorService;
import com.google.inject.Inject;
@ -67,13 +75,13 @@ public class EC2ListNodesStrategy implements ListNodesStrategy {
@Named(Constants.PROPERTY_REQUEST_TIMEOUT)
protected static Long maxTime;
protected final EC2AsyncClient client;
protected final EC2Client client;
protected final Supplier<Set<String>> regions;
protected final Function<RunningInstance, NodeMetadata> runningInstanceToNodeMetadata;
protected final ListeningExecutorService userExecutor;
@Inject
protected EC2ListNodesStrategy(EC2AsyncClient client, @Region Supplier<Set<String>> regions,
protected EC2ListNodesStrategy(EC2Client client, @Region Supplier<Set<String>> regions,
Function<RunningInstance, NodeMetadata> runningInstanceToNodeMetadata,
@Named(Constants.PROPERTY_USER_THREADS) ListeningExecutorService userExecutor) {
this.client = checkNotNull(client, "client");
@ -87,6 +95,22 @@ public class EC2ListNodesStrategy implements ListNodesStrategy {
return listDetailsOnNodesMatching(NodePredicates.all());
}
@Override
public Set<? extends NodeMetadata> listNodesByIds(Iterable<String> ids) {
Multimap<String, String> idsByHandles = index(ids, splitHandle(1));
Multimap<String, String> idsByRegions = transformValues(idsByHandles, splitHandle(0));
Multimap<String, String> idsByConfiguredRegions = filterKeys(idsByRegions, in(regions.get()));
if (idsByConfiguredRegions.isEmpty()) {
return ImmutableSet.of();
}
Iterable<? extends RunningInstance> instances = pollRunningInstancesByRegionsAndIds(idsByConfiguredRegions);
Iterable<? extends NodeMetadata> nodes = transform(filter(instances, notNull()),
runningInstanceToNodeMetadata);
return ImmutableSet.copyOf(nodes);
}
@Override
public Set<? extends NodeMetadata> listDetailsOnNodesMatching(Predicate<ComputeMetadata> filter) {
Iterable<? extends RunningInstance> instances = pollRunningInstances();
@ -96,15 +120,50 @@ public class EC2ListNodesStrategy implements ListNodesStrategy {
}
protected Iterable<? extends RunningInstance> pollRunningInstances() {
Iterable<? extends Set<? extends Reservation<? extends RunningInstance>>> reservations = transformParallel(
regions.get(), new Function<String, ListenableFuture<? extends Set<? extends Reservation<? extends RunningInstance>>>>() {
Iterable<? extends Set<? extends Reservation<? extends RunningInstance>>> reservations
= transform(regions.get(), allInstancesInRegion());
return concat(concat(reservations));
}
protected Iterable<? extends RunningInstance> pollRunningInstancesByRegionsAndIds(final Multimap<String,String> idsByRegions) {
Iterable<? extends Set<? extends Reservation<? extends RunningInstance>>> reservations
= transform(idsByRegions.keySet(), instancesByIdInRegion(idsByRegions));
return concat(concat(reservations));
}
protected Function<String, String> splitHandle(final int pos) {
return new Function<String, String>() {
@Override
public ListenableFuture<? extends Set<? extends Reservation<? extends RunningInstance>>> apply(String from) {
public String apply(String handle) {
return AWSUtils.parseHandle(handle)[pos];
}
};
}
protected Function<String, Set<? extends Reservation<? extends RunningInstance>>> allInstancesInRegion() {
return new Function<String, Set<? extends Reservation<? extends RunningInstance>>>() {
@Override
public Set<? extends Reservation<? extends RunningInstance>> apply(String from) {
return client.getInstanceServices().describeInstancesInRegion(from);
}
}, userExecutor, maxTime, logger, "reservations");
return concat(concat(reservations));
};
}
protected Function<String, Set<? extends Reservation<? extends RunningInstance>>>
instancesByIdInRegion(final Multimap<String,String> idsByRegions) {
return new Function<String, Set<? extends Reservation<? extends RunningInstance>>>() {
@Override
public Set<? extends Reservation<? extends RunningInstance>> apply(String from) {
return client.getInstanceServices()
.describeInstancesInRegion(from, toArray(idsByRegions.get(from), String.class));
}
};
}
}

View File

@ -52,6 +52,7 @@ public class EC2ComputeServiceExpectTest extends BaseEC2ComputeServiceExpectTest
requestResponseMap.put(authorizeSecurityGroupIngressRequestGroup, authorizeSecurityGroupIngressResponse);
requestResponseMap.put(runInstancesRequest, runInstancesResponse);
requestResponseMap.put(describeInstanceRequest, describeInstanceResponse);
requestResponseMap.put(describeInstanceMultiIdsRequest, describeInstanceMultiIdsResponse);
requestResponseMap.put(describeImageRequest, describeImagesResponse);
ComputeService apiThatCreatesNode = requestsSendResponses(requestResponseMap.build());
@ -77,6 +78,7 @@ public class EC2ComputeServiceExpectTest extends BaseEC2ComputeServiceExpectTest
requestResponseMap.put(authorizeSecurityGroupIngressRequestGroup, authorizeSecurityGroupIngressResponse);
requestResponseMap.put(runInstancesRequest, runInstancesResponse);
requestResponseMap.put(describeInstanceRequest, describeInstanceResponse);
requestResponseMap.put(describeInstanceMultiIdsRequest, describeInstanceMultiIdsResponse);
requestResponseMap.put(describeImageRequest, describeImagesResponse);
ComputeService apiThatCreatesNode = requestsSendResponses(requestResponseMap.build());

View File

@ -59,6 +59,8 @@ public abstract class BaseEC2ComputeServiceExpectTest extends BaseEC2ComputeServ
protected HttpResponse runInstancesResponse;
protected HttpRequest describeInstanceRequest;
protected HttpResponse describeInstanceResponse;
protected HttpRequest describeInstanceMultiIdsRequest;
protected HttpResponse describeInstanceMultiIdsResponse;
protected HttpRequest describeImageRequest;
public BaseEC2ComputeServiceExpectTest() {
@ -190,6 +192,20 @@ public abstract class BaseEC2ComputeServiceExpectTest extends BaseEC2ComputeServ
.payload(payloadFromResourceWithContentType(
"/describe_instances_running-1.xml", MediaType.APPLICATION_XML)).build();
describeInstanceMultiIdsRequest =
formSigner.filter(HttpRequest.builder()
.method("POST")
.endpoint("https://ec2." + region + ".amazonaws.com/")
.addHeader("Host", "ec2." + region + ".amazonaws.com")
.addFormParam("Action", "DescribeInstances")
.addFormParam("InstanceId.1", "i-2baa5550")
.addFormParam("InstanceId.2", "i-abcd1234").build());
describeInstanceMultiIdsResponse =
HttpResponse.builder().statusCode(200)
.payload(payloadFromResourceWithContentType(
"/describe_instances_multiple.xml", MediaType.APPLICATION_XML)).build();
//TODO: duplicate.. shouldn't need this
describeImageRequest =
formSigner.filter(HttpRequest.builder()

View File

@ -0,0 +1,130 @@
<?xml version="1.0" encoding="UTF-8"?>
<DescribeInstancesResponse xmlns="http://ec2.amazonaws.com/doc/2011-05-15/">
<requestId>f6d3252e-35e5-4ef5-b2c5-62da95dd829b</requestId>
<reservationSet>
<item>
<reservationId>r-205ad944</reservationId>
<ownerId>993194456877</ownerId>
<groupSet>
<item>
<groupId>sg-3c6ef654</groupId>
<groupName>jclouds#mygroup2</groupName>
</item>
</groupSet>
<instancesSet>
<item>
<instanceId>i-2baa5550</instanceId>
<imageId>ami-aecd60c7</imageId>
<instanceState>
<code>16</code>
<name>running</name>
</instanceState>
<privateDnsName>ip-10-28-89-195.ec2.internal</privateDnsName>
<dnsName>ec2-50-16-1-166.compute-1.amazonaws.com</dnsName>
<reason/>
<keyName>jclouds#mygroup2#81</keyName>
<amiLaunchIndex>0</amiLaunchIndex>
<productCodes/>
<instanceType>t1.micro</instanceType>
<launchTime>2012-08-02T04:28:30.000Z</launchTime>
<placement>
<availabilityZone>us-east-1e</availabilityZone>
<groupName/>
<tenancy>default</tenancy>
</placement>
<kernelId>aki-88aa75e1</kernelId>
<monitoring>
<state>disabled</state>
</monitoring>
<privateIpAddress>10.28.89.195</privateIpAddress>
<ipAddress>50.16.1.166</ipAddress>
<groupSet>
<item>
<groupId>sg-3c6ef654</groupId>
<groupName>jclouds#mygroup2</groupName>
</item>
</groupSet>
<architecture>x86_64</architecture>
<rootDeviceType>ebs</rootDeviceType>
<rootDeviceName>/dev/sda1</rootDeviceName>
<blockDeviceMapping>
<item>
<deviceName>/dev/sda1</deviceName>
<ebs>
<volumeId>vol-f2d7c993</volumeId>
<status>attached</status>
<attachTime>2012-08-02T04:28:56.000Z</attachTime>
<deleteOnTermination>true</deleteOnTermination>
</ebs>
</item>
</blockDeviceMapping>
<virtualizationType>paravirtual</virtualizationType>
<clientToken/>
<tagSet>
<item>
<key>Name</key>
<value>mygroup2-2baa5550</value>
</item>
</tagSet>
<hypervisor>xen</hypervisor>
</item>
<item>
<instanceId>i-abcd1234</instanceId>
<imageId>ami-aecd60c7</imageId>
<instanceState>
<code>16</code>
<name>running</name>
</instanceState>
<privateDnsName>ip-10-28-89-100.ec2.internal</privateDnsName>
<dnsName>ec2-50-16-1-100.compute-1.amazonaws.com</dnsName>
<reason/>
<keyName>jclouds#mygroup2#82</keyName>
<amiLaunchIndex>0</amiLaunchIndex>
<productCodes/>
<instanceType>t1.micro</instanceType>
<launchTime>2012-08-01T04:28:30.000Z</launchTime>
<placement>
<availabilityZone>us-east-1e</availabilityZone>
<groupName/>
<tenancy>default</tenancy>
</placement>
<kernelId>aki-88aa75e1</kernelId>
<monitoring>
<state>disabled</state>
</monitoring>
<privateIpAddress>10.28.89.100</privateIpAddress>
<ipAddress>50.16.1.100</ipAddress>
<groupSet>
<item>
<groupId>sg-3c6ef654</groupId>
<groupName>jclouds#mygroup2</groupName>
</item>
</groupSet>
<architecture>x86_64</architecture>
<rootDeviceType>ebs</rootDeviceType>
<rootDeviceName>/dev/sda1</rootDeviceName>
<blockDeviceMapping>
<item>
<deviceName>/dev/sda1</deviceName>
<ebs>
<volumeId>vol-f2d7c900</volumeId>
<status>attached</status>
<attachTime>2012-08-01T04:28:56.000Z</attachTime>
<deleteOnTermination>true</deleteOnTermination>
</ebs>
</item>
</blockDeviceMapping>
<virtualizationType>paravirtual</virtualizationType>
<clientToken/>
<tagSet>
<item>
<key>Name</key>
<value>mygroup2-abcd1234</value>
</item>
</tagSet>
<hypervisor>xen</hypervisor>
</item>
</instancesSet>
</item>
</reservationSet>
</DescribeInstancesResponse>

View File

@ -21,6 +21,8 @@ package org.jclouds.elasticstack.compute;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Predicates.notNull;
import static com.google.common.collect.Iterables.contains;
import static com.google.common.collect.Iterables.filter;
import static org.jclouds.concurrent.FutureIterables.transformParallel;
import static org.jclouds.elasticstack.util.Servers.small;
@ -64,6 +66,7 @@ import com.google.common.collect.FluentIterable;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.ImmutableSet.Builder;
import com.google.common.collect.Iterables;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.ListeningExecutorService;
@ -192,6 +195,17 @@ public class ElasticStackComputeServiceAdapter implements
return (Iterable<ServerInfo>) client.listServerInfo();
}
@Override
public Iterable<ServerInfo> listNodesByIds(final Iterable<String> ids) {
return filter(listNodes(), new Predicate<ServerInfo>() {
@Override
public boolean apply(ServerInfo server) {
return contains(ids, server.getUuid());
}
});
}
@Override
public Iterable<Location> listLocations() {
// Not using the adapter to determine locations

View File

@ -20,6 +20,7 @@ package org.jclouds.openstack.nova.v2_0.compute;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState;
import static com.google.common.collect.Iterables.contains;
import static com.google.common.collect.Iterables.filter;
import static com.google.common.collect.Iterables.transform;
import static org.jclouds.compute.util.ComputeServiceUtils.metadataAndTagsAsCommaDelimitedValue;
@ -57,10 +58,12 @@ import org.jclouds.openstack.nova.v2_0.predicates.ImagePredicates;
import com.google.common.base.Function;
import com.google.common.base.Objects;
import com.google.common.base.Optional;
import com.google.common.base.Predicate;
import com.google.common.base.Supplier;
import com.google.common.cache.LoadingCache;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.ImmutableSet.Builder;
import com.google.common.collect.Iterables;
/**
* The adapter used by the NovaComputeServiceContextModule to interface the nova-specific domain
@ -207,6 +210,17 @@ public class NovaComputeServiceAdapter implements
return builder.build();
}
@Override
public Iterable<ServerInZone> listNodesByIds(final Iterable<String> ids) {
return filter(listNodes(), new Predicate<ServerInZone>() {
@Override
public boolean apply(ServerInZone server) {
return contains(ids, server.slashEncode());
}
});
}
@Override
public Iterable<Location> listLocations() {
// locations provided by keystone

View File

@ -58,7 +58,13 @@ public class NovaComputeServiceLiveTest extends BaseComputeServiceLiveTest {
super.testListNodes();
}
@Test(enabled = true, dependsOnMethods = { "testListNodes", "testGetNodesWithDetails" })
@Test(enabled = true, dependsOnMethods = "testSuspendResume")
@Override
public void testListNodesByIds() throws Exception {
super.testListNodesByIds();
}
@Test(enabled = true, dependsOnMethods = { "testListNodes", "testGetNodesWithDetails", "testListNodesByIds" })
@Override
public void testDestroyNodes() {
super.testDestroyNodes();

View File

@ -19,6 +19,8 @@
package org.jclouds.vcloud.compute.strategy;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.collect.Iterables.contains;
import static com.google.common.collect.Iterables.filter;
import java.net.URI;
import java.util.Map;
@ -100,7 +102,7 @@ public class VCloudComputeServiceAdapter implements ComputeServiceAdapter<VApp,
}
private Iterable<VAppTemplate> supportedTemplates() {
return Iterables.filter(templates.get(), new Predicate<VAppTemplate>() {
return filter(templates.get(), new Predicate<VAppTemplate>() {
@Override
public boolean apply(VAppTemplate from) {
@ -145,6 +147,17 @@ public class VCloudComputeServiceAdapter implements ComputeServiceAdapter<VApp,
return nodes.build();
}
@Override
public Iterable<VApp> listNodesByIds(final Iterable<String> ids) {
return filter(listNodes(), new Predicate<VApp>() {
@Override
public boolean apply(VApp vm) {
return contains(ids, vm.getHref().toASCIIString());
}
});
}
@VisibleForTesting
void addVAppToSetRetryingIfNotYetPresent(Builder<VApp> nodes, ReferenceType vdc, ReferenceType resource) {
VApp node = null;

View File

@ -17,7 +17,10 @@
* under the License.
*/
package org.jclouds.trmk.vcloud_0_8.compute.strategy;
import static com.google.common.collect.Iterables.toArray;
import static org.jclouds.compute.config.ComputeServiceProperties.BLACKLIST_NODES;
import static org.jclouds.compute.predicates.NodePredicates.all;
import static org.jclouds.compute.predicates.NodePredicates.withIds;
import static org.jclouds.compute.reference.ComputeServiceConstants.COMPUTE_LOGGER;
import java.util.Map;
@ -43,7 +46,9 @@ import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Predicate;
import com.google.common.base.Splitter;
import com.google.common.base.Supplier;
import com.google.common.collect.FluentIterable;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import com.google.common.collect.Sets;
import com.google.inject.Inject;
@ -108,6 +113,11 @@ public class TerremarkVCloudListNodesStrategy implements ListNodesStrategy {
return builder.build();
}
@Override
public Iterable<? extends NodeMetadata> listNodesByIds(Iterable<String> ids) {
return FluentIterable.from(listDetailsOnNodesMatching(all())).filter(withIds(toArray(ids, String.class))).toSet();
}
@Override
public Iterable<NodeMetadata> listDetailsOnNodesMatching(Predicate<ComputeMetadata> filter) {
Set<NodeMetadata> nodes = Sets.newHashSet();

View File

@ -99,11 +99,16 @@ public interface ComputeService {
Image getImage(String id);
/**
* all nodes available to the current user by id. If possible, the returned set will include
* @return all nodes available to the current user. If possible, the returned set will include
* {@link NodeMetadata} objects.
*/
Set<? extends ComputeMetadata> listNodes();
/**
* @return all nodes with one of the provided ids available to the current user.
*/
Set<? extends NodeMetadata> listNodesByIds(Iterable<String> ids);
/**
* The list locations command returns all the valid locations for nodes. A location has a scope,
* which is typically region or zone. A region is a general area, like eu-west, where a zone is

View File

@ -146,4 +146,5 @@ public interface ComputeServiceAdapter<N, H, I, L> {
Iterable<N> listNodes();
Iterable<N> listNodesByIds(Iterable<String> ids);
}

View File

@ -341,6 +341,18 @@ public class BaseComputeService implements ComputeService {
return set;
}
/**
* {@inheritDoc}
*/
@Override
public Set<? extends NodeMetadata> listNodesByIds(Iterable<String> ids) {
checkNotNull(ids, "ids");
logger.trace(">> listing node with ids(%s)", ids);
Set<NodeMetadata> set = ImmutableSet.copyOf(listNodesStrategy.listNodesByIds(ids));
logger.trace("<< list(%d)", set.size());
return set;
}
/**
* {@inheritDoc}
*/

View File

@ -33,4 +33,5 @@ public interface ListNodesStrategy {
Iterable<? extends NodeMetadata> listDetailsOnNodesMatching(Predicate<ComputeMetadata> filter);
Iterable<? extends NodeMetadata> listNodesByIds(Iterable<String> ids);
}

View File

@ -20,6 +20,11 @@ package org.jclouds.compute.strategy.impl;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState;
import static com.google.common.collect.Iterables.filter;
import static com.google.common.collect.Iterables.toArray;
import static com.google.common.collect.Iterables.transform;
import static org.jclouds.compute.predicates.NodePredicates.all;
import static org.jclouds.compute.predicates.NodePredicates.withIds;
import static org.jclouds.compute.util.ComputeServiceUtils.formatStatus;
import java.util.Map;
@ -55,6 +60,7 @@ import org.jclouds.logging.Logger;
import com.google.common.base.Function;
import com.google.common.base.Functions;
import com.google.common.base.Predicate;
import com.google.common.collect.FluentIterable;
import com.google.common.collect.Iterables;
/**
@ -110,9 +116,14 @@ public class AdaptingComputeServiceStrategies<N, H, I, L> implements CreateNodeW
return listDetailsOnNodesMatching(NodePredicates.all());
}
@Override
public Iterable<? extends NodeMetadata> listNodesByIds(Iterable<String> ids) {
return FluentIterable.from(listDetailsOnNodesMatching(all())).filter(withIds(toArray(ids, String.class))).toSet();
}
@Override
public Iterable<? extends NodeMetadata> listDetailsOnNodesMatching(Predicate<ComputeMetadata> filter) {
return Iterables.filter(Iterables.transform(client.listNodes(), nodeMetadataAdapter), filter);
return filter(transform(client.listNodes(), nodeMetadataAdapter), filter);
}
@Override

View File

@ -18,6 +18,9 @@
*/
package org.jclouds.compute.stub.config;
import static com.google.common.base.Predicates.in;
import static com.google.common.collect.Iterables.find;
import static com.google.common.collect.Maps.filterKeys;
import static org.jclouds.compute.util.ComputeServiceUtils.formatStatus;
import java.util.Map;
@ -53,6 +56,8 @@ import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableList.Builder;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import com.google.common.util.concurrent.ListeningExecutorService;
/**
@ -161,7 +166,7 @@ public class StubComputeServiceAdapter implements JCloudsNativeComputeServiceAda
@Override
public Image getImage(String id) {
return Iterables.find(listImages(), ImagePredicates.idEquals(id), null);
return find(listImages(), ImagePredicates.idEquals(id), null);
}
@Override
@ -169,6 +174,11 @@ public class StubComputeServiceAdapter implements JCloudsNativeComputeServiceAda
return nodes.values();
}
@Override
public Iterable<NodeMetadata> listNodesByIds(Iterable<String> ids) {
return filterKeys(nodes, in(ImmutableSet.copyOf(ids))).values();
}
@SuppressWarnings("unchecked")
@Override
public Iterable<Location> listLocations() {

View File

@ -526,7 +526,12 @@ public class StubComputeServiceIntegrationTest extends BaseComputeServiceLiveTes
super.testListNodes();
}
@Test(enabled = true, dependsOnMethods = { "testListNodes", "testGetNodesWithDetails" })
@Test(enabled = true, dependsOnMethods = "testSuspendResume")
public void testListNodesByIds() throws Exception {
super.testListNodesByIds();
}
@Test(enabled = true, dependsOnMethods = { "testListNodes", "testGetNodesWithDetails", "testListNodesByIds" })
public void testDestroyNodes() {
super.testDestroyNodes();
}

View File

@ -20,9 +20,11 @@ package org.jclouds.compute.internal;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Predicates.and;
import static com.google.common.base.Predicates.not;
import static com.google.common.collect.ImmutableSet.copyOf;
import static com.google.common.collect.Iterables.concat;
import static com.google.common.collect.Iterables.get;
import static com.google.common.collect.Iterables.getOnlyElement;
import static com.google.common.collect.Iterables.transform;
import static com.google.common.collect.Maps.newLinkedHashMap;
import static com.google.common.collect.Maps.uniqueIndex;
import static com.google.common.collect.Sets.filter;
@ -560,6 +562,22 @@ public abstract class BaseComputeServiceLiveTest extends BaseComputeServiceConte
}
}
@Test(enabled = true, dependsOnMethods = "testSuspendResume")
public void testListNodesByIds() throws Exception {
Set<String> nodeIds = copyOf(transform(nodes,
new Function<NodeMetadata, String>() {
@Override
public String apply(NodeMetadata from) {
return from.getId();
}
}));
// newTreeSet is here because elementsEqual cares about ordering.
assert Iterables.elementsEqual(nodes, newTreeSet(client.listNodesByIds(nodeIds)));
}
@Test(enabled = true, dependsOnMethods = "testSuspendResume")
public void testGetNodesWithDetails() throws Exception {
for (NodeMetadata node : client.listNodesDetailsMatching(all())) {
@ -581,7 +599,7 @@ public abstract class BaseComputeServiceLiveTest extends BaseComputeServiceConte
}
}
@Test(enabled = true, dependsOnMethods = { "testListNodes", "testGetNodesWithDetails" })
@Test(enabled = true, dependsOnMethods = { "testListNodes", "testGetNodesWithDetails", "testListNodesByIds" })
public void testDestroyNodes() {
int toDestroy = refreshNodes().size();
Set<? extends NodeMetadata> destroyed = client.destroyNodesMatching(inGroup(group));

View File

@ -22,16 +22,18 @@ import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Predicates.notNull;
import static com.google.common.collect.Iterables.concat;
import static com.google.common.collect.Iterables.filter;
import static com.google.common.collect.Iterables.toArray;
import static com.google.common.collect.Iterables.transform;
import static org.jclouds.concurrent.FutureIterables.transformParallel;
import java.util.Map.Entry;
import java.util.Set;
import javax.inject.Named;
import javax.inject.Singleton;
import org.jclouds.Constants;
import org.jclouds.aws.ec2.AWSEC2AsyncClient;
import org.jclouds.aws.ec2.AWSEC2Client;
import org.jclouds.aws.ec2.domain.AWSRunningInstance;
import org.jclouds.aws.ec2.domain.SpotInstanceRequest;
import org.jclouds.aws.ec2.functions.SpotInstanceRequestToAWSRunningInstance;
@ -42,6 +44,8 @@ import org.jclouds.location.Region;
import com.google.common.base.Function;
import com.google.common.base.Supplier;
import com.google.common.collect.Iterables;
import com.google.common.collect.Multimap;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.ListeningExecutorService;
import com.google.inject.Inject;
@ -53,11 +57,11 @@ import com.google.inject.Inject;
@Singleton
public class AWSEC2ListNodesStrategy extends EC2ListNodesStrategy {
protected final AWSEC2AsyncClient client;
protected final AWSEC2Client client;
protected final SpotInstanceRequestToAWSRunningInstance spotConverter;
@Inject
protected AWSEC2ListNodesStrategy(AWSEC2AsyncClient client, @Region Supplier<Set<String>> regions,
protected AWSEC2ListNodesStrategy(AWSEC2Client client, @Region Supplier<Set<String>> regions,
Function<RunningInstance, NodeMetadata> runningInstanceToNodeMetadata,
@Named(Constants.PROPERTY_USER_THREADS) ListeningExecutorService userExecutor,
SpotInstanceRequestToAWSRunningInstance spotConverter) {
@ -68,15 +72,42 @@ public class AWSEC2ListNodesStrategy extends EC2ListNodesStrategy {
@Override
protected Iterable<? extends RunningInstance> pollRunningInstances() {
Iterable<? extends AWSRunningInstance> spots = filter(transform(concat(transformParallel(regions.get(),
new Function<String, ListenableFuture<? extends Set<SpotInstanceRequest>>>() {
@Override
public ListenableFuture<? extends Set<SpotInstanceRequest>> apply(String from) {
return client.getSpotInstanceServices().describeSpotInstanceRequestsInRegion(from);
}
}, userExecutor, maxTime, logger, "reservations")), spotConverter), notNull());
Iterable<? extends AWSRunningInstance> spots = filter(transform(concat(transform(regions.get(),
allSpotInstancesInRegion())),
spotConverter), notNull());
return concat(super.pollRunningInstances(), spots);
}
@Override
protected Iterable<? extends RunningInstance> pollRunningInstancesByRegionsAndIds(final Multimap<String,String> idsByRegions) {
Iterable<? extends AWSRunningInstance> spots = filter(transform(concat(transform(idsByRegions.keySet(),
spotInstancesByIdInRegion(idsByRegions))),
spotConverter), notNull());
return concat(super.pollRunningInstancesByRegionsAndIds(idsByRegions), spots);
}
protected Function<String, Set<SpotInstanceRequest>> allSpotInstancesInRegion() {
return new Function<String, Set<SpotInstanceRequest>>() {
@Override
public Set<SpotInstanceRequest> apply(String from) {
return client.getSpotInstanceServices().describeSpotInstanceRequestsInRegion(from);
}
};
}
protected Function<String, Set<SpotInstanceRequest>> spotInstancesByIdInRegion(final Multimap<String,String> idsByRegions) {
return new Function<String, Set<SpotInstanceRequest>>() {
@Override
public Set<SpotInstanceRequest> apply(String from) {
return client.getSpotInstanceServices()
.describeSpotInstanceRequestsInRegion(from, toArray(idsByRegions.get(from), String.class));
}
};
}
}

View File

@ -21,6 +21,9 @@ package org.jclouds.glesys.compute;
import static com.google.common.base.Charsets.UTF_8;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.collect.Iterables.contains;
import static com.google.common.collect.Iterables.filter;
import static com.google.common.collect.Iterables.find;
import static com.google.common.io.BaseEncoding.base16;
import static org.jclouds.compute.util.ComputeServiceUtils.metadataAndTagsAsCommaDelimitedValue;
import static org.jclouds.concurrent.FutureIterables.transformParallel;
@ -182,7 +185,7 @@ public class GleSYSComputeServiceAdapter implements ComputeServiceAdapter<Server
.processors(ImmutableList.of(new Processor(cpuCores, 1.0)))
.volumes(ImmutableList.<Volume> of(new VolumeImpl((float) diskSizeGB, true, true)))
.hypervisor(platformToArgs.getKey())
.location(Iterables.find(locationsSet, LocationPredicates.idEquals(datacenter)))
.location(find(locationsSet, LocationPredicates.idEquals(datacenter)))
.supportsImage(ImagePredicates.idIn(templatesSupported)).build());
}
@ -197,7 +200,7 @@ public class GleSYSComputeServiceAdapter implements ComputeServiceAdapter<Server
// cheat until we have a getTemplate command
@Override
public OSTemplate getImage(final String id) {
return Iterables.find(listImages(), new Predicate<OSTemplate>(){
return find(listImages(), new Predicate<OSTemplate>(){
@Override
public boolean apply(OSTemplate input) {
@ -216,6 +219,17 @@ public class GleSYSComputeServiceAdapter implements ComputeServiceAdapter<Server
}, userExecutor, null, logger, "server details");
}
@Override
public Iterable<ServerDetails> listNodesByIds(final Iterable<String> ids) {
return filter(listNodes(), new Predicate<ServerDetails>() {
@Override
public boolean apply(ServerDetails server) {
return contains(ids, server.getId());
}
});
}
@Override
public Set<String> listLocations() {
return FluentIterable.from(api.getServerApi().getAllowedArgumentsForCreateByPlatform().values())

View File

@ -49,7 +49,10 @@ import org.jclouds.logging.Logger;
import com.google.common.base.Function;
import com.google.common.base.Predicate;
import com.google.common.base.Throwables;
import com.google.common.collect.FluentIterable;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import com.google.common.primitives.Longs;
/**
* defines the connection between the {@link GoGridClient} implementation and the jclouds
@ -136,6 +139,15 @@ public class GoGridComputeServiceAdapter implements ComputeServiceAdapter<Server
return client.getServerServices().getServerList();
}
@Override
public Iterable<Server> listNodesByIds(final Iterable<String> ids) {
Set<Long> idsAsLongs = FluentIterable.from(ids)
.transform(toLong())
.toSet();
return client.getServerServices().getServersById(Longs.toArray(idsAsLongs));
}
@Override
public Iterable<Option> listLocations() {
return client.getServerServices().getDatacenters();
@ -182,4 +194,13 @@ public class GoGridComputeServiceAdapter implements ComputeServiceAdapter<Server
executeCommandOnServer(PowerCommand.STOP, id);
}
private Function<String, Long> toLong() {
return new Function<String, Long>() {
@Override
public Long apply(String id) {
return Long.valueOf(checkNotNull(id, "id"));
}
};
}
}

View File

@ -22,6 +22,7 @@ import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState;
import static com.google.common.base.Predicates.and;
import static com.google.common.collect.Iterables.contains;
import static com.google.common.collect.Iterables.filter;
import static com.google.common.collect.Iterables.find;
import static com.google.common.collect.Iterables.get;
@ -186,7 +187,7 @@ public class SoftLayerComputeServiceAdapter implements
// cheat until we have a getProductItem command
@Override
public ProductItem getImage(final String id) {
return Iterables.find(listImages(), new Predicate<ProductItem>(){
return find(listImages(), new Predicate<ProductItem>(){
@Override
public boolean apply(ProductItem input) {
@ -198,7 +199,7 @@ public class SoftLayerComputeServiceAdapter implements
@Override
public Iterable<VirtualGuest> listNodes() {
return Iterables.filter(client.getVirtualGuestClient().listVirtualGuests(), new Predicate<VirtualGuest>() {
return filter(client.getVirtualGuestClient().listVirtualGuests(), new Predicate<VirtualGuest>() {
@Override
public boolean apply(VirtualGuest arg0) {
@ -212,6 +213,17 @@ public class SoftLayerComputeServiceAdapter implements
});
}
@Override
public Iterable<VirtualGuest> listNodesByIds(final Iterable<String> ids) {
return filter(listNodes(), new Predicate<VirtualGuest>() {
@Override
public boolean apply(VirtualGuest server) {
return contains(ids, server.getId());
}
});
}
@Override
public Iterable<Datacenter> listLocations() {
return productPackageSupplier.get().getDatacenters();

View File

@ -19,6 +19,8 @@
package org.jclouds.servermanager.compute.strategy;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.collect.Iterables.contains;
import static com.google.common.collect.Iterables.filter;
import javax.inject.Inject;
import javax.inject.Singleton;
@ -32,7 +34,9 @@ import org.jclouds.servermanager.Image;
import org.jclouds.servermanager.Server;
import org.jclouds.servermanager.ServerManager;
import com.google.common.base.Predicate;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
/**
* defines the connection between the {@link ServerManager} implementation and the jclouds
@ -79,6 +83,17 @@ public class ServerManagerComputeServiceAdapter implements ComputeServiceAdapter
return client.listServers();
}
@Override
public Iterable<Server> listNodesByIds(final Iterable<String> ids) {
return filter(listNodes(), new Predicate<Server>() {
@Override
public boolean apply(Server server) {
return contains(ids, Integer.toString(server.id));
}
});
}
@Override
public Iterable<Datacenter> listLocations() {
return ImmutableSet.of(new Datacenter(1, "SFO"));