Merge pull request #1502 from abayer/listnodesdetails-work

Adding listNodesByIds across the board.
This commit is contained in:
Adrian Cole 2013-04-08 20:00:18 -07:00
commit 33745cdeb1
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>>>>() {
@Override
public ListenableFuture<? extends Set<? extends Reservation<? extends RunningInstance>>> apply(String from) {
return client.getInstanceServices().describeInstancesInRegion(from);
}
}, userExecutor, maxTime, logger, "reservations");
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 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);
}
};
}
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
@ -78,6 +82,17 @@ public class ServerManagerComputeServiceAdapter implements ComputeServiceAdapter
public Iterable<Server> listNodes() {
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() {