diff --git a/aws/core/src/main/java/org/jclouds/aws/ec2/compute/EC2ComputeService.java b/aws/core/src/main/java/org/jclouds/aws/ec2/compute/EC2ComputeService.java index 0c95920c62..4375c03038 100644 --- a/aws/core/src/main/java/org/jclouds/aws/ec2/compute/EC2ComputeService.java +++ b/aws/core/src/main/java/org/jclouds/aws/ec2/compute/EC2ComputeService.java @@ -22,9 +22,9 @@ import static org.jclouds.util.Utils.checkNotEmpty; import java.util.Map; import java.util.Set; +import java.util.Map.Entry; import java.util.concurrent.ExecutorService; -import javax.annotation.Nullable; import javax.inject.Inject; import javax.inject.Named; import javax.inject.Provider; @@ -32,7 +32,7 @@ import javax.inject.Singleton; import org.jclouds.Constants; import org.jclouds.aws.ec2.EC2Client; -import org.jclouds.aws.ec2.compute.config.EC2ComputeServiceContextModule.GetRegionFromNodeOrDefault; +import org.jclouds.aws.ec2.compute.config.EC2ComputeServiceContextModule.GetRegionFromLocation; import org.jclouds.aws.ec2.compute.domain.RegionAndName; import org.jclouds.aws.ec2.compute.domain.RegionNameAndIngressRules; import org.jclouds.aws.ec2.domain.KeyPair; @@ -50,9 +50,8 @@ import org.jclouds.compute.strategy.RunNodesAndAddToSetStrategy; import org.jclouds.compute.util.ComputeUtils; import org.jclouds.domain.Location; -import com.google.common.base.Function; -import com.google.common.collect.Iterables; -import com.google.common.collect.Sets; +import com.google.common.base.Predicate; +import com.google.common.collect.Maps; /** * @author Adrian Cole @@ -60,7 +59,7 @@ import com.google.common.collect.Sets; @Singleton public class EC2ComputeService extends BaseComputeService { private final EC2Client ec2Client; - private final GetRegionFromNodeOrDefault getRegionFromNodeOrDefault; + private final GetRegionFromLocation getRegionFromLocation; private final Map credentialsMap; private final Map securityGroupMap; @@ -73,14 +72,13 @@ public class EC2ComputeService extends BaseComputeService { RebootNodeStrategy rebootNodeStrategy, DestroyNodeStrategy destroyNodeStrategy, Provider templateBuilderProvider, ComputeUtils utils, @Named(Constants.PROPERTY_USER_THREADS) ExecutorService executor, EC2Client ec2Client, - GetRegionFromNodeOrDefault getRegionFromNodeOrDefault, - Map credentialsMap, - Map securityGroupMap) { + GetRegionFromLocation getRegionFromLocation, + Map credentialsMap, Map securityGroupMap) { super(context, images, sizes, locations, listNodesStrategy, getNodeMetadataStrategy, runNodesAndAddToSetStrategy, rebootNodeStrategy, destroyNodeStrategy, templateBuilderProvider, utils, executor); this.ec2Client = ec2Client; - this.getRegionFromNodeOrDefault = getRegionFromNodeOrDefault; + this.getRegionFromLocation = getRegionFromLocation; this.credentialsMap = credentialsMap; this.securityGroupMap = securityGroupMap; } @@ -110,18 +108,18 @@ public class EC2ComputeService extends BaseComputeService { } @Override - public void destroyNodesWithTag(String tag) { - super.destroyNodesWithTag(tag); - Set regions = Sets.newHashSet(Iterables.transform(listNodesWithTag(tag), - new Function() { - @Override - public String apply(@Nullable NodeMetadata nodeMetadata) { - return getRegionFromNodeOrDefault.apply(nodeMetadata); - } - })); - for (String region : regions) { - deleteKeyPair(region, tag); - deleteSecurityGroup(region, tag); + public Set destroyNodesMatching(Predicate filter) { + Set deadOnes = super.destroyNodesMatching(filter); + Map regionTags = Maps.newHashMap(); + for (NodeMetadata nodeMetadata : deadOnes) { + if (nodeMetadata.getTag() != null) + regionTags.put(getRegionFromLocation.apply(nodeMetadata.getLocation()), nodeMetadata + .getTag()); } + for (Entry regionTag : regionTags.entrySet()) { + deleteKeyPair(regionTag.getKey(), regionTag.getValue()); + deleteSecurityGroup(regionTag.getKey(), regionTag.getValue()); + } + return deadOnes; } } \ No newline at end of file diff --git a/aws/core/src/main/java/org/jclouds/aws/ec2/compute/config/EC2ComputeServiceContextModule.java b/aws/core/src/main/java/org/jclouds/aws/ec2/compute/config/EC2ComputeServiceContextModule.java index 25622ae20e..0147f5a2ff 100755 --- a/aws/core/src/main/java/org/jclouds/aws/ec2/compute/config/EC2ComputeServiceContextModule.java +++ b/aws/core/src/main/java/org/jclouds/aws/ec2/compute/config/EC2ComputeServiceContextModule.java @@ -18,6 +18,7 @@ */ package org.jclouds.aws.ec2.compute.config; +import static com.google.common.base.Preconditions.checkNotNull; import static org.jclouds.aws.ec2.options.DescribeImagesOptions.Builder.ownedBy; import static org.jclouds.aws.ec2.reference.EC2Constants.PROPERTY_EC2_AMI_OWNERS; import static org.jclouds.compute.domain.OsFamily.UBUNTU; @@ -64,8 +65,8 @@ import org.jclouds.compute.domain.Size; import org.jclouds.compute.domain.TemplateBuilder; import org.jclouds.compute.internal.ComputeServiceContextImpl; import org.jclouds.compute.internal.TemplateBuilderImpl; -import org.jclouds.compute.options.GetNodesOptions; import org.jclouds.compute.options.TemplateOptions; +import org.jclouds.compute.predicates.NodePredicates; import org.jclouds.compute.predicates.ScriptStatusReturnsZero; import org.jclouds.compute.predicates.ScriptStatusReturnsZero.CommandUsingClient; import org.jclouds.compute.reference.ComputeServiceConstants; @@ -142,6 +143,8 @@ public class EC2ComputeServiceContextModule extends EC2ContextModule { return template.architecture(Architecture.X86_32).osFamily(UBUNTU); } + // TODO make this more efficient for listNodes(); currently RunningInstanceToNodeMetadata is slow + // due to image parsing; consider using MapMaker. computing map @Singleton public static class EC2ListNodesStrategy implements ListNodesStrategy { private final InstanceClient client; @@ -155,21 +158,25 @@ public class EC2ComputeServiceContextModule extends EC2ContextModule { } @Override - public Iterable execute(GetNodesOptions options) { + public Iterable list() { + return listDetailsOnNodesMatching(NodePredicates.all()); + } + + @Override + public Iterable listDetailsOnNodesMatching( + Predicate filter) { Set nodes = Sets.newHashSet(); for (String region : ImmutableSet.of(Region.US_EAST_1, Region.US_WEST_1, Region.EU_WEST_1)) { Iterables.addAll(nodes, Iterables.transform(Iterables.concat(client .describeInstancesInRegion(region)), runningInstanceToNodeMetadata)); } - return nodes; + return Iterables.filter(nodes, filter); } - } @Singleton - public static class GetRegionFromNodeOrDefault implements Function { - public String apply(ComputeMetadata node) { - Location location = node.getLocation(); + public static class GetRegionFromLocation implements Function { + public String apply(Location location) { String region = location.getScope() == LocationScope.REGION ? location.getId() : location .getParent().getId(); return region; @@ -181,22 +188,22 @@ public class EC2ComputeServiceContextModule extends EC2ContextModule { private final InstanceClient client; private final RunningInstanceToNodeMetadata runningInstanceToNodeMetadata; - private final GetRegionFromNodeOrDefault getRegionFromNodeOrDefault; + private final GetRegionFromLocation getRegionFromLocation; @Inject protected EC2GetNodeMetadataStrategy(InstanceClient client, - GetRegionFromNodeOrDefault getRegionFromNodeOrDefault, + GetRegionFromLocation getRegionFromLocation, RunningInstanceToNodeMetadata runningInstanceToNodeMetadata) { this.client = client; - this.getRegionFromNodeOrDefault = getRegionFromNodeOrDefault; + this.getRegionFromLocation = getRegionFromLocation; this.runningInstanceToNodeMetadata = runningInstanceToNodeMetadata; } @Override - public NodeMetadata execute(ComputeMetadata node) { - String region = getRegionFromNodeOrDefault.apply(node); + public NodeMetadata execute(Location location, String id) { + String region = getRegionFromLocation.apply(checkNotNull(location, "location")); RunningInstance runningInstance = Iterables.getOnlyElement(getAllRunningInstancesInRegion( - client, region, node.getId())); + client, region, checkNotNull(id, "id"))); return runningInstanceToNodeMetadata.apply(runningInstance); } @@ -210,19 +217,19 @@ public class EC2ComputeServiceContextModule extends EC2ContextModule { @Singleton public static class EC2RebootNodeStrategy implements RebootNodeStrategy { private final InstanceClient client; - private final GetRegionFromNodeOrDefault getRegionFromNodeOrDefault; + private final GetRegionFromLocation getRegionFromLocation; @Inject protected EC2RebootNodeStrategy(InstanceClient client, - GetRegionFromNodeOrDefault getRegionFromNodeOrDefault) { + GetRegionFromLocation getRegionFromLocation) { this.client = client; - this.getRegionFromNodeOrDefault = getRegionFromNodeOrDefault; + this.getRegionFromLocation = getRegionFromLocation; } @Override - public boolean execute(ComputeMetadata node) { - String region = getRegionFromNodeOrDefault.apply(node); - client.rebootInstancesInRegion(region, node.getId()); + public boolean execute(Location location, String id) { + String region = getRegionFromLocation.apply(location); + client.rebootInstancesInRegion(region, id); return true; } diff --git a/aws/core/src/main/java/org/jclouds/aws/ec2/compute/strategy/EC2DestroyNodeStrategy.java b/aws/core/src/main/java/org/jclouds/aws/ec2/compute/strategy/EC2DestroyNodeStrategy.java index a11d7f16fc..edab707165 100644 --- a/aws/core/src/main/java/org/jclouds/aws/ec2/compute/strategy/EC2DestroyNodeStrategy.java +++ b/aws/core/src/main/java/org/jclouds/aws/ec2/compute/strategy/EC2DestroyNodeStrategy.java @@ -25,13 +25,12 @@ import javax.inject.Named; import javax.inject.Singleton; import org.jclouds.aws.ec2.EC2Client; -import org.jclouds.aws.ec2.compute.config.EC2ComputeServiceContextModule.GetRegionFromNodeOrDefault; +import org.jclouds.aws.ec2.compute.config.EC2ComputeServiceContextModule.GetRegionFromLocation; import org.jclouds.aws.ec2.domain.RunningInstance; -import org.jclouds.compute.domain.ComputeMetadata; -import org.jclouds.compute.domain.NodeMetadata; import org.jclouds.compute.reference.ComputeServiceConstants; import org.jclouds.compute.strategy.DestroyNodeStrategy; import org.jclouds.compute.strategy.GetNodeMetadataStrategy; +import org.jclouds.domain.Location; import org.jclouds.logging.Logger; import com.google.common.base.Predicate; @@ -48,29 +47,25 @@ public class EC2DestroyNodeStrategy implements DestroyNodeStrategy { protected Logger logger = Logger.NULL; protected final EC2Client ec2Client; protected final Predicate instanceStateTerminated; - protected final GetRegionFromNodeOrDefault getRegionFromNodeOrDefault; + protected final GetRegionFromLocation getRegionFromLocation; protected final GetNodeMetadataStrategy getNodeMetadataStrategy; @Inject protected EC2DestroyNodeStrategy(EC2Client ec2Client, @Named("TERMINATED") Predicate instanceStateTerminated, - GetRegionFromNodeOrDefault getRegionFromNodeOrDefault, + GetRegionFromLocation getRegionFromLocation, GetNodeMetadataStrategy getNodeMetadataStrategy) { this.ec2Client = ec2Client; this.instanceStateTerminated = instanceStateTerminated; - this.getRegionFromNodeOrDefault = getRegionFromNodeOrDefault; + this.getRegionFromLocation = getRegionFromLocation; this.getNodeMetadataStrategy = getNodeMetadataStrategy; } @Override - public boolean execute(ComputeMetadata metadata) { - NodeMetadata node = metadata instanceof NodeMetadata ? NodeMetadata.class.cast(metadata) - : getNodeMetadataStrategy.execute(metadata); - String region = getRegionFromNodeOrDefault.apply(node); - - ec2Client.getInstanceServices().terminateInstancesInRegion(region, node.getId()); + public boolean execute(Location location, String id) { + String region = getRegionFromLocation.apply(location); + ec2Client.getInstanceServices().terminateInstancesInRegion(region, id); return instanceStateTerminated.apply(Iterables.getOnlyElement(Iterables.concat(ec2Client - .getInstanceServices().describeInstancesInRegion(region, node.getId())))); + .getInstanceServices().describeInstancesInRegion(region, id)))); } - } \ No newline at end of file diff --git a/aws/core/src/test/java/org/jclouds/aws/ec2/compute/EC2ComputeServiceLiveTest.java b/aws/core/src/test/java/org/jclouds/aws/ec2/compute/EC2ComputeServiceLiveTest.java index b0998a6e1a..5fd4a86cfe 100644 --- a/aws/core/src/test/java/org/jclouds/aws/ec2/compute/EC2ComputeServiceLiveTest.java +++ b/aws/core/src/test/java/org/jclouds/aws/ec2/compute/EC2ComputeServiceLiveTest.java @@ -37,6 +37,7 @@ import org.jclouds.compute.domain.NodeMetadata; import org.jclouds.compute.domain.OsFamily; import org.jclouds.compute.domain.Template; import org.jclouds.compute.domain.TemplateBuilder; +import org.jclouds.compute.predicates.NodePredicates; import org.jclouds.domain.Credentials; import org.jclouds.ssh.jsch.config.JschSshClientModule; import org.testng.annotations.BeforeClass; @@ -138,7 +139,7 @@ public class EC2ComputeServiceLiveTest extends BaseComputeServiceLiveTest { result.getKeyMaterial())); } finally { - client.destroyNodesWithTag(tag); + client.destroyNodesMatching(NodePredicates.withTag(tag)); if (startedId != null) { // ensure we didn't delete these resources! assertEquals(keyPairClient.describeKeyPairsInRegion(null, tag).size(), 1); @@ -190,7 +191,7 @@ public class EC2ComputeServiceLiveTest extends BaseComputeServiceLiveTest { assert group.getIpPermissions().size() == 0 : group; } finally { - client.destroyNodesWithTag(tag); + client.destroyNodesMatching(NodePredicates.withTag(tag)); if (startedId != null) { // ensure we didn't delete these resources! assertEquals(securityGroupClient.describeSecurityGroupsInRegion(null, tag).size(), 1); diff --git a/compute/src/main/clojure/org/jclouds/compute.clj b/compute/src/main/clojure/org/jclouds/compute.clj index 21bb18ed26..8bcc5fbf6f 100644 --- a/compute/src/main/clojure/org/jclouds/compute.clj +++ b/compute/src/main/clojure/org/jclouds/compute.clj @@ -60,7 +60,9 @@ See http://code.google.com/p/jclouds for details." [org.jclouds.compute.domain Template TemplateBuilder ComputeMetadata NodeMetadata Size OsFamily Image Architecture] - [org.jclouds.compute.options TemplateOptions GetNodesOptions] + [org.jclouds.compute.options TemplateOptions] + [org.jclouds.compute.predicates + NodePredicates] [com.google.common.collect ImmutableSet])) (try @@ -121,26 +123,12 @@ See http://code.google.com/p/jclouds for details." (defn nodes-with-tag [#^String tag #^ComputeService compute] - (seq (.listNodesWithTag compute tag))) - -(def #^{:private true} list-nodes-map - { :with-details #(when %2 (.withDetails %1)) }) + (seq (.listNodesMatching(compute (NodePredicates/withTag tag))))) (defn nodes - "Retrieve the existing nodes for the compute context. - Options are: - :with-details true" - ([] (nodes *compute*)) - ([compute-or-tag & options] - (if (compute-service? compute-or-tag) - (let [options (apply hash-map options) - list-nodes-options (reduce - (fn [lno [k v]] - ((list-nodes-map k) lno v) - lno) - (GetNodesOptions.) options)] - (seq (.listNodes compute-or-tag list-nodes-options))) - (nodes-with-tag compute-or-tag *compute*)))) + "Retrieve the existing nodes for the compute context." + [#^ComputeService compute] + (seq (.listNodes compute))) (defn images "Retrieve the available images for the compute context." @@ -219,33 +207,33 @@ See http://code.google.com/p/jclouds for details." (defn #^NodeMetadata node-details "Retrieve the node metadata." - ([node] (node-details node *compute*)) - ([node #^ComputeService compute] - (.getNodeMetadata compute node ))) + ([location id] (node-details location id *compute*)) + ([#^Location location id #^ComputeService compute] + (.getNodeMetadata compute location id))) -(defn reboot-nodes +(defn reboot-nodes-with-tag "Reboot all the nodes with the given tag." - ([tag] (reboot-nodes tag *compute*)) + ([tag] (reboot-nodes-with-tag tag *compute*)) ([#^String tag #^ComputeService compute] - (.rebootNodesWithTag compute tag ))) - + (.rebootNodesMatching(compute (NodePredicates/withTag tag))))) + (defn reboot-node "Reboot a given node." - ([node] (reboot-node node *compute*)) - ([#^ComputeMetadata node #^ComputeService compute] - (.rebootNode compute node ))) + ([location id] (reboot-node location id *compute*)) + ([#^Location location id #^ComputeService compute] + (.rebootNode compute location id))) -(defn destroy-nodes +(defn destroy-nodes-with-tag "Destroy all the nodes with the given tag." - ([tag] (destroy-nodes tag *compute*)) + ([tag] (destroy-nodes-with-tag tag *compute*)) ([#^String tag #^ComputeService compute] - (.destroyNodesWithTag compute tag ))) - + (seq (.destroyNodesMatching(compute (NodePredicates/withTag tag)))))) + (defn destroy-node "Destroy a given node." - ([node] (destroy-node node *compute*)) - ([#^ComputeMetadata node #^ComputeServiceContext compute] - (.destroyNode compute node))) + ([location id] (destroy-node location id *compute*)) + ([#^Location location id #^ComputeService compute] + (.destroyNode compute location id))) (defmacro state-predicate [node state] `(= (.getState ~node) @@ -406,5 +394,4 @@ There are many options to use for the default template (add-keyword-option builder option)) (if next (recur next remaining))))) - (.build builder))) - + (.build builder))) \ No newline at end of file diff --git a/compute/src/main/java/org/jclouds/compute/ComputeService.java b/compute/src/main/java/org/jclouds/compute/ComputeService.java index 0c9f2a5ffe..038ee250c6 100755 --- a/compute/src/main/java/org/jclouds/compute/ComputeService.java +++ b/compute/src/main/java/org/jclouds/compute/ComputeService.java @@ -28,7 +28,6 @@ import org.jclouds.compute.domain.Size; import org.jclouds.compute.domain.Template; import org.jclouds.compute.domain.TemplateBuilder; import org.jclouds.compute.internal.BaseComputeService; -import org.jclouds.compute.options.GetNodesOptions; import org.jclouds.compute.options.RunScriptOptions; import org.jclouds.domain.Location; import org.jclouds.ssh.ExecResponse; @@ -80,12 +79,6 @@ public interface ComputeService { */ Set listNodes(); - /** - * all nodes available to the current user by id. If possible, the returned set will include - * {@link NodeMetadata} objects. - */ - Set listNodes(GetNodesOptions options); - /** * 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 @@ -136,66 +129,70 @@ public interface ComputeService { * destroy the node. If it is the only node in a tag set, the dependent resources will also be * destroyed. */ - void destroyNode(ComputeMetadata node); + void destroyNode(Location location, String id); /** - * nodes which are tagged are treated as a logical set. Using the delete command, you can save + * nodes matching the filter are treated as a logical set. Using the delete command, you can save * time by removing the nodes in parallel. When the last node in a set is destroyed, any indirect * resources it uses, such as keypairs, are also destroyed. - * + * * @return list of nodes destroyed */ - void destroyNodesWithTag(String tag); + Set destroyNodesMatching(Predicate filter); /** * reboot the node. */ - void rebootNode(ComputeMetadata node); + void rebootNode(Location location, String id); /** - * nodes which are tagged are treated as a logical set. Using this command, you can save time by - * rebooting the nodes in parallel. + * nodes matching the filter are treated as a logical set. Using this command, you can save time + * by rebooting the nodes in parallel. */ - void rebootNodesWithTag(String tag); + void rebootNodesMatching(Predicate filter); - /** + /** * Find a node by its id */ - NodeMetadata getNodeMetadata(ComputeMetadata node); + NodeMetadata getNodeMetadata(Location location, String id); /** - * get all nodes matching the tag. + * get all nodes including details such as image and ip addresses even if it incurs extra + * requests to the service. * - * @param tag + * @param filter + * how to select the nodes you are interested in details on. */ - Set listNodesWithTag(String tag); + Set listNodesDetailsMatching(Predicate filter); /** * Runs the script without any additional options * - * @see #runScriptOnNodesMatching(Predicate, byte[], org.jclouds.compute.options.RunScriptOptions) - * @see org.jclouds.compute.predicates.NodePredicates#activeWithTag(String) + * @see #runScriptOnNodesMatching(Predicate, byte[], + * org.jclouds.compute.options.RunScriptOptions) + * @see org.jclouds.compute.predicates.NodePredicates#runningWithTag(String) */ - Map runScriptOnNodesMatching(Predicate filter, byte[] runScript) - throws RunScriptOnNodesException; + Map runScriptOnNodesMatching( + Predicate filter, byte[] runScript) throws RunScriptOnNodesException; /** * Run the script on all nodes with the specific tag. - * + * * @param filter - * Predicate-based filter to define on which nodes the script is to be - * executed + * Predicate-based filter to define on which nodes the script is to be executed * @param runScript * script to run in byte format. If the script is a string, use * {@link String#getBytes()} to retrieve the bytes * @param options * nullable options to how to run the script, whether to override credentials * @return map with node identifiers and corresponding responses - * @throws RunScriptOnNodesException if anything goes wrong during script execution - * - * @see org.jclouds.compute.predicates.NodePredicates#activeWithTag(String) + * @throws RunScriptOnNodesException + * if anything goes wrong during script execution + * + * @see org.jclouds.compute.predicates.NodePredicates#runningWithTag(String) */ - Map runScriptOnNodesMatching(Predicate filter, byte[] runScript, - RunScriptOptions options) throws RunScriptOnNodesException; + Map runScriptOnNodesMatching( + Predicate filter, byte[] runScript, RunScriptOptions options) + throws RunScriptOnNodesException; } diff --git a/compute/src/main/java/org/jclouds/compute/internal/BaseComputeService.java b/compute/src/main/java/org/jclouds/compute/internal/BaseComputeService.java index 2ec565baad..2e36de874f 100755 --- a/compute/src/main/java/org/jclouds/compute/internal/BaseComputeService.java +++ b/compute/src/main/java/org/jclouds/compute/internal/BaseComputeService.java @@ -25,11 +25,9 @@ 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.compute.predicates.NodePredicates.withTag; import static org.jclouds.concurrent.ConcurrentUtils.awaitCompletion; import static org.jclouds.concurrent.ConcurrentUtils.makeListenable; -import java.util.List; import java.util.Map; import java.util.Set; import java.util.concurrent.Callable; @@ -48,13 +46,11 @@ import org.jclouds.compute.ComputeServiceContext; import org.jclouds.compute.RunNodesException; import org.jclouds.compute.RunScriptOnNodesException; 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.Size; import org.jclouds.compute.domain.Template; import org.jclouds.compute.domain.TemplateBuilder; -import org.jclouds.compute.options.GetNodesOptions; import org.jclouds.compute.options.RunScriptOptions; import org.jclouds.compute.predicates.NodePredicates; import org.jclouds.compute.reference.ComputeServiceConstants; @@ -74,7 +70,6 @@ import com.google.common.base.Function; import com.google.common.base.Predicate; import com.google.common.base.Predicates; import com.google.common.collect.Iterables; -import com.google.common.collect.Lists; import com.google.common.collect.Maps; import com.google.common.collect.Sets; import com.google.common.util.concurrent.ListenableFuture; @@ -102,7 +97,6 @@ public class BaseComputeService implements ComputeService { protected final Provider templateBuilderProvider; protected final ComputeUtils utils; protected final ExecutorService executor; - protected final ComputeMetadataToNodeMetadata computeMetadataToNodeMetadata; @Inject protected BaseComputeService(ComputeServiceContext context, @@ -128,7 +122,6 @@ public class BaseComputeService implements ComputeService { "templateBuilderProvider"); this.utils = checkNotNull(utils, "utils"); this.executor = checkNotNull(executor, "executor"); - this.computeMetadataToNodeMetadata = new ComputeMetadataToNodeMetadata(); } @Override @@ -157,27 +150,24 @@ public class BaseComputeService implements ComputeService { } @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(">> destroying node(%s)", node.getId()); - boolean successful = destroyNodeStrategy.execute(node); - logger.debug("<< destroyed node(%s) success(%s)", node.getId(), successful); + public void destroyNode(Location location, String id) { + checkNotNull(location, "location"); + checkNotNull(id, "id"); + logger.debug(">> destroying node(%s/%s)", location.getId(), id); + boolean successful = destroyNodeStrategy.execute(location, id); + logger.debug("<< destroyed node(%s/%s) success(%s)", location.getId(), id, successful); } @Override - public void destroyNodesWithTag(String tag) { // TODO parallel - logger.debug(">> destroying nodes by tag(%s)", tag); - Iterable nodesToDestroy = Iterables.filter(doListNodesWithTag(tag), - Predicates.not(NodePredicates.TERMINATED)); + public Set destroyNodesMatching(Predicate filter) { + logger.debug(">> destroying nodes matching(%s)", filter); Map> responses = Maps.newHashMap(); - final List destroyedNodes = Lists.newArrayList(); - for (final NodeMetadata node : nodesToDestroy) { + final Set destroyedNodes = Sets.newLinkedHashSet(); + for (final NodeMetadata node : nodesMatchingFilterAndNotTerminated(filter)) { responses.put(node, makeListenable(executor.submit(new Callable() { @Override public Void call() throws Exception { - destroyNode(node); + destroyNode(node.getLocation(), node.getId()); destroyedNodes.add(node); return null; } @@ -185,49 +175,31 @@ public class BaseComputeService implements ComputeService { } awaitCompletion(responses, executor, null, logger, "destroying nodes"); logger.debug("<< destroyed"); + return destroyedNodes; + } + + private Iterable nodesMatchingFilterAndNotTerminated( + Predicate filter) { + return Iterables.filter(detailsOnAllNodes(), Predicates.and(filter, Predicates + .not(NodePredicates.TERMINATED))); } @Override public Set listNodes() { - return listNodes(null); - } - - @Override - public Set listNodes(GetNodesOptions options) { - logger.debug(">> listing servers"); - if (options == null) { - options = GetNodesOptions.NONE; - } - Set set = Sets - .newLinkedHashSet(listNodesStrategy.execute(options)); + logger.debug(">> listing nodes"); + Set set = Sets.newLinkedHashSet(listNodesStrategy.list()); logger.debug("<< list(%d)", set.size()); return set; } - /** - * If the result of {@link ListNodesStrategy#execute} is a set of nodes, then return them. - * Otherwise iteratively call {@link #getNodeMetadata} - */ - protected Set doListNodesWithTag(final String tag) { - return Sets.newHashSet(Iterables.filter(Iterables.transform(listNodesStrategy - .execute(GetNodesOptions.NONE), computeMetadataToNodeMetadata), withTag(tag))); - } - - class ComputeMetadataToNodeMetadata implements Function { - - @Override - public NodeMetadata apply(ComputeMetadata from) { - return from instanceof NodeMetadata ? NodeMetadata.class.cast(from) - : getNodeMetadata(from); - } - } - @Override - public Set listNodesWithTag(String tag) { - logger.debug(">> listing nodes by tag(%s)", tag); - Set nodes = doListNodesWithTag(tag); - logger.debug("<< list(%d)", nodes.size()); - return nodes; + public Set listNodesDetailsMatching(Predicate filter) { + checkNotNull(filter, "filter"); + logger.debug(">> listing node details matching(%s)", filter); + Set set = Sets.newLinkedHashSet(listNodesStrategy + .listDetailsOnNodesMatching(filter)); + logger.debug("<< list(%d)", set.size()); + return set; } @Override @@ -251,33 +223,31 @@ public class BaseComputeService implements ComputeService { } @Override - public NodeMetadata getNodeMetadata(ComputeMetadata node) { - checkArgument(node.getType() == ComputeType.NODE, "this is only valid for nodes, not " - + node.getType()); - return getNodeMetadataStrategy.execute(node); + public NodeMetadata getNodeMetadata(Location location, String id) { + checkNotNull(location, "location"); + checkNotNull(id, "id"); + return getNodeMetadataStrategy.execute(location, id); } @Override - public void rebootNode(ComputeMetadata node) { - checkArgument(node.getType() == ComputeType.NODE, "this is only valid for nodes, not " - + node.getType()); - checkNotNull(node.getId(), "node.id"); - logger.debug(">> rebooting node(%s)", node.getId()); - boolean successful = rebootNodeStrategy.execute(node); - logger.debug("<< rebooted node(%s) success(%s)", node.getId(), successful); + public void rebootNode(Location location, String id) { + checkNotNull(location, "location"); + checkNotNull(id, "id"); + logger.debug(">> rebooting node(%s/%s)", location.getId(), id); + boolean successful = rebootNodeStrategy.execute(location, id); + logger.debug("<< rebooted node(%s/%s) success(%s)", location.getId(), id, successful); } @Override - public void rebootNodesWithTag(String tag) { // TODO parallel - logger.debug(">> rebooting nodes by tag(%s)", tag); - Iterable nodesToReboot = Iterables.filter(doListNodesWithTag(tag), - Predicates.not(NodePredicates.TERMINATED)); + public void rebootNodesMatching(Predicate filter) { + logger.debug(">> rebooting nodes matching(%s)", filter); + Map> responses = Maps.newHashMap(); - for (final NodeMetadata node : nodesToReboot) { + for (final NodeMetadata node : nodesMatchingFilterAndNotTerminated(filter)) { responses.put(node, makeListenable(executor.submit(new Callable() { @Override public Void call() throws Exception { - rebootNode(node); + rebootNode(node.getLocation(), node.getId()); return null; } }), executor)); @@ -290,10 +260,11 @@ public class BaseComputeService implements ComputeService { * @throws RunScriptOnNodesException * @see #runScriptOnNodesMatching(Predicate, byte[], * org.jclouds.compute.options.RunScriptOptions) - * @see org.jclouds.compute.predicates.NodePredicates#activeWithTag(String) + * @see org.jclouds.compute.predicates.NodePredicates#runningWithTag(String) */ - public Map runScriptOnNodesMatching(Predicate filter, - byte[] runScript) throws RunScriptOnNodesException { + @Override + public Map runScriptOnNodesMatching( + Predicate filter, byte[] runScript) throws RunScriptOnNodesException { return runScriptOnNodesMatching(filter, runScript, RunScriptOptions.NONE); } @@ -311,12 +282,13 @@ public class BaseComputeService implements ComputeService { * @throws RunScriptOnNodesException * if anything goes wrong during script execution * - * @see org.jclouds.compute.predicates.NodePredicates#activeWithTag(String) + * @see org.jclouds.compute.predicates.NodePredicates#runningWithTag(String) */ + @Override public Map runScriptOnNodesMatching(Predicate filter, final byte[] runScript, @Nullable final RunScriptOptions options) throws RunScriptOnNodesException { - Iterable nodes = verifyParametersAndGetNodes(filter, runScript, + Iterable nodes = verifyParametersAndListNodes(filter, runScript, (options != null) ? options : RunScriptOptions.NONE); final Map execs = Maps.newHashMap(); @@ -363,14 +335,14 @@ public class BaseComputeService implements ComputeService { } - private Iterable verifyParametersAndGetNodes( + private Iterable verifyParametersAndListNodes( Predicate filter, byte[] runScript, final RunScriptOptions options) { checkNotNull(filter, "Filter must be provided"); checkNotNull(runScript, "The script (represented by bytes array - use \"script\".getBytes() must be provided"); checkNotNull(options, "options"); - Iterable nodes = Iterables.filter(Iterables.transform(listNodes(), - computeMetadataToNodeMetadata), filter); + + Iterable nodes = Iterables.filter(detailsOnAllNodes(), filter); return Iterables.transform(nodes, new Function() { @@ -397,4 +369,8 @@ public class BaseComputeService implements ComputeService { } }); } + + private Iterable detailsOnAllNodes() { + return listNodesStrategy.listDetailsOnNodesMatching(NodePredicates.all()); + } } \ No newline at end of file diff --git a/compute/src/main/java/org/jclouds/compute/options/GetNodesOptions.java b/compute/src/main/java/org/jclouds/compute/options/GetNodesOptions.java deleted file mode 100755 index 2a3a3ea125..0000000000 --- a/compute/src/main/java/org/jclouds/compute/options/GetNodesOptions.java +++ /dev/null @@ -1,80 +0,0 @@ -package org.jclouds.compute.options; - - -/** - * @author Ivan Meredith - */ -public class GetNodesOptions implements Cloneable { - public static final ImmutableGetNodesOptions NONE = new ImmutableGetNodesOptions( - new GetNodesOptions()); - - private boolean detailed; - - public GetNodesOptions() { - } - - GetNodesOptions(boolean detailed) { - this.detailed = detailed; - } - - public static class ImmutableGetNodesOptions extends GetNodesOptions { - private final GetNodesOptions delegate; - - - - public ImmutableGetNodesOptions(GetNodesOptions delegate) { - this.delegate = delegate; - } - - @Override - public boolean isDetailed() { - return delegate.isDetailed(); - } - - - @Override - public GetNodesOptions clone() { - return delegate.clone(); - } - - @Override - public String toString() { - return delegate.toString(); - } - - } - - public boolean isDetailed() { - return detailed; - } - /** - * populate each result with detailed such as metadata even if it incurs extra requests to the - * service. - */ - public GetNodesOptions withDetails() { - this.detailed = true; - return this; - } - - public static class Builder { - - - /** - * @see GetNodesOptions#withDetails() - */ - public static GetNodesOptions withDetails() { - GetNodesOptions options = new GetNodesOptions(); - return options.withDetails(); - } - } - - @Override - public GetNodesOptions clone() { - return new GetNodesOptions(detailed); - } - - @Override - public String toString() { - return "[detailed=" + detailed + "]"; - } -} diff --git a/compute/src/main/java/org/jclouds/compute/options/RunScriptOptions.java b/compute/src/main/java/org/jclouds/compute/options/RunScriptOptions.java index f8172eb351..f442abf8aa 100644 --- a/compute/src/main/java/org/jclouds/compute/options/RunScriptOptions.java +++ b/compute/src/main/java/org/jclouds/compute/options/RunScriptOptions.java @@ -35,7 +35,43 @@ public class RunScriptOptions { *
  • run the script as root (versus running with current privileges)
  • * */ - public static final RunScriptOptions NONE = new RunScriptOptions(); + public static final RunScriptOptions NONE = new ImmutableRunScriptOptions(new RunScriptOptions()); + + public static class ImmutableRunScriptOptions extends RunScriptOptions { + private final RunScriptOptions delegate; + + public ImmutableRunScriptOptions(RunScriptOptions delegate) { + this.delegate = delegate; + } + + @Override + public String toString() { + return delegate.toString(); + } + + @Override + public Credentials getOverrideCredentials() { + return delegate.getOverrideCredentials(); + + } + + @Override + public boolean isRunAsRoot() { + return delegate.isRunAsRoot(); + + } + + @Override + public RunScriptOptions runAsRoot(boolean runAsRoot) { + throw new IllegalArgumentException("runAsRoot is immutable"); + } + + @Override + public RunScriptOptions withOverridingCredentials(Credentials overridingCredentials) { + throw new IllegalArgumentException("overridingCredentials is immutable"); + } + + } private Credentials overridingCredentials; private boolean runAsRoot = true; diff --git a/compute/src/main/java/org/jclouds/compute/options/TemplateOptions.java b/compute/src/main/java/org/jclouds/compute/options/TemplateOptions.java index 29bfc91f91..71b37cdb3c 100644 --- a/compute/src/main/java/org/jclouds/compute/options/TemplateOptions.java +++ b/compute/src/main/java/org/jclouds/compute/options/TemplateOptions.java @@ -43,6 +43,90 @@ public class TemplateOptions { public static final TemplateOptions NONE = new TemplateOptions(); + public static class ImmutableTemplateOptions extends TemplateOptions { + private final TemplateOptions delegate; + + public ImmutableTemplateOptions(TemplateOptions delegate) { + this.delegate = delegate; + } + + @Override + public String toString() { + return delegate.toString(); + } + + @Override + public T as(Class clazz) { + return delegate.as(clazz); + } + + @Override + public TemplateOptions authorizePublicKey(String publicKey) { + return delegate.authorizePublicKey(publicKey); + } + + @Override + public TemplateOptions blockOnPort(int port, int seconds) { + throw new IllegalArgumentException("port, seconds are immutable"); + } + + @Override + public int[] getInboundPorts() { + return delegate.getInboundPorts(); + } + + @Override + public int getPort() { + return delegate.getPort(); + } + + @Override + public String getPrivateKey() { + return delegate.getPrivateKey(); + } + + @Override + public String getPublicKey() { + return delegate.getPublicKey(); + } + + @Override + public byte[] getRunScript() { + return delegate.getRunScript(); + } + + @Override + public int getSeconds() { + return delegate.getSeconds(); + } + + @Override + public TemplateOptions inboundPorts(int... ports) { + throw new IllegalArgumentException("ports is immutable"); + } + + @Override + public TemplateOptions installPrivateKey(String privateKey) { + throw new IllegalArgumentException("privateKey is immutable"); + } + + @Override + public boolean isIncludeMetadata() { + return delegate.isIncludeMetadata(); + } + + @Override + public TemplateOptions runScript(byte[] script) { + throw new IllegalArgumentException("withMetadata is immutable"); + } + + @Override + public TemplateOptions withMetadata() { + throw new IllegalArgumentException("withMetadata is immutable"); + } + + } + protected int[] inboundPorts = new int[] { 22 }; protected byte[] script; diff --git a/compute/src/main/java/org/jclouds/compute/predicates/NodePredicates.java b/compute/src/main/java/org/jclouds/compute/predicates/NodePredicates.java index 295ce3aa9d..0fb5820999 100644 --- a/compute/src/main/java/org/jclouds/compute/predicates/NodePredicates.java +++ b/compute/src/main/java/org/jclouds/compute/predicates/NodePredicates.java @@ -30,6 +30,7 @@ import org.jclouds.compute.domain.NodeMetadata; import org.jclouds.compute.domain.NodeState; import com.google.common.base.Predicate; +import com.google.common.base.Predicates; import com.google.common.collect.Sets; /** @@ -65,6 +66,13 @@ public class NodePredicates { }; } + /** + * return everything. + */ + public static Predicate all() { + return Predicates. alwaysTrue(); + } + /** * Return nodes with specified tag. Note: returns all nodes, regardless of the state. * @@ -94,7 +102,7 @@ public class NodePredicates { * tag to match the items * @return predicate */ - public static Predicate activeWithTag(final String tag) { + public static Predicate runningWithTag(final String tag) { checkNotEmpty(tag, "Tag must be defined"); return new Predicate() { @Override @@ -105,7 +113,7 @@ public class NodePredicates { @Override public String toString() { - return "activeWithTag(" + tag + ")"; + return "runningWithTag(" + tag + ")"; } }; } diff --git a/compute/src/main/java/org/jclouds/compute/strategy/DestroyNodeStrategy.java b/compute/src/main/java/org/jclouds/compute/strategy/DestroyNodeStrategy.java index 616fa3bda5..7534dd71a0 100644 --- a/compute/src/main/java/org/jclouds/compute/strategy/DestroyNodeStrategy.java +++ b/compute/src/main/java/org/jclouds/compute/strategy/DestroyNodeStrategy.java @@ -19,7 +19,7 @@ package org.jclouds.compute.strategy; -import org.jclouds.compute.domain.ComputeMetadata; +import org.jclouds.domain.Location; /** * terminates the node and blocks until it is no longer visible or in the state TERMINATED. If this @@ -29,6 +29,6 @@ import org.jclouds.compute.domain.ComputeMetadata; */ public interface DestroyNodeStrategy { - boolean execute(ComputeMetadata node); + boolean execute(Location location, String id); } \ No newline at end of file diff --git a/compute/src/main/java/org/jclouds/compute/strategy/GetNodeMetadataStrategy.java b/compute/src/main/java/org/jclouds/compute/strategy/GetNodeMetadataStrategy.java index 9cc0512a0c..c65b8a5461 100644 --- a/compute/src/main/java/org/jclouds/compute/strategy/GetNodeMetadataStrategy.java +++ b/compute/src/main/java/org/jclouds/compute/strategy/GetNodeMetadataStrategy.java @@ -19,8 +19,8 @@ package org.jclouds.compute.strategy; -import org.jclouds.compute.domain.ComputeMetadata; import org.jclouds.compute.domain.NodeMetadata; +import org.jclouds.domain.Location; /** * returns all details associated to the node below. @@ -29,6 +29,6 @@ import org.jclouds.compute.domain.NodeMetadata; */ public interface GetNodeMetadataStrategy { - NodeMetadata execute(ComputeMetadata node); + NodeMetadata execute(Location location, String id); } \ No newline at end of file diff --git a/compute/src/main/java/org/jclouds/compute/strategy/ListNodesStrategy.java b/compute/src/main/java/org/jclouds/compute/strategy/ListNodesStrategy.java index d2f05abc55..db1257eb81 100755 --- a/compute/src/main/java/org/jclouds/compute/strategy/ListNodesStrategy.java +++ b/compute/src/main/java/org/jclouds/compute/strategy/ListNodesStrategy.java @@ -20,7 +20,9 @@ package org.jclouds.compute.strategy; import org.jclouds.compute.domain.ComputeMetadata; -import org.jclouds.compute.options.GetNodesOptions; +import org.jclouds.compute.domain.NodeMetadata; + +import com.google.common.base.Predicate; /** * @@ -28,5 +30,8 @@ import org.jclouds.compute.options.GetNodesOptions; */ public interface ListNodesStrategy { - Iterable execute(GetNodesOptions options); + Iterable list(); + + Iterable listDetailsOnNodesMatching(Predicate filter); + } \ No newline at end of file diff --git a/compute/src/main/java/org/jclouds/compute/strategy/RebootNodeStrategy.java b/compute/src/main/java/org/jclouds/compute/strategy/RebootNodeStrategy.java index f8dcc4a3c9..ce554caf97 100644 --- a/compute/src/main/java/org/jclouds/compute/strategy/RebootNodeStrategy.java +++ b/compute/src/main/java/org/jclouds/compute/strategy/RebootNodeStrategy.java @@ -19,7 +19,7 @@ package org.jclouds.compute.strategy; -import org.jclouds.compute.domain.ComputeMetadata; +import org.jclouds.domain.Location; /** * Reboots a node unless it is in the state TERMINATED. @@ -28,6 +28,6 @@ import org.jclouds.compute.domain.ComputeMetadata; */ public interface RebootNodeStrategy { - boolean execute(ComputeMetadata node); + boolean execute(Location location, String id); } \ No newline at end of file diff --git a/compute/src/main/java/org/jclouds/compute/strategy/impl/EncodeTagIntoNameRunNodesAndAddToSetStrategy.java b/compute/src/main/java/org/jclouds/compute/strategy/impl/EncodeTagIntoNameRunNodesAndAddToSetStrategy.java index 494aa4b470..bb71f24a77 100755 --- a/compute/src/main/java/org/jclouds/compute/strategy/impl/EncodeTagIntoNameRunNodesAndAddToSetStrategy.java +++ b/compute/src/main/java/org/jclouds/compute/strategy/impl/EncodeTagIntoNameRunNodesAndAddToSetStrategy.java @@ -36,7 +36,6 @@ import org.jclouds.Constants; import org.jclouds.compute.domain.ComputeMetadata; import org.jclouds.compute.domain.NodeMetadata; import org.jclouds.compute.domain.Template; -import org.jclouds.compute.options.GetNodesOptions; import org.jclouds.compute.reference.ComputeServiceConstants; import org.jclouds.compute.strategy.AddNodeWithTagStrategy; import org.jclouds.compute.strategy.ListNodesStrategy; @@ -123,8 +122,7 @@ public class EncodeTagIntoNameRunNodesAndAddToSetStrategy implements RunNodesAnd */ protected Set getNextNames(final String tag, final Template template, int count) { Set names = Sets.newHashSet(); - Iterable currentNodes = listNodesStrategy - .execute(GetNodesOptions.NONE); + Iterable currentNodes = listNodesStrategy.list(); int maxTries = 100; int currentTries = 0; while (names.size() < count && currentTries++ < maxTries) { diff --git a/compute/src/test/java/org/jclouds/compute/BaseComputeServiceLiveTest.java b/compute/src/test/java/org/jclouds/compute/BaseComputeServiceLiveTest.java index 614ba77ea6..dca25cb618 100755 --- a/compute/src/test/java/org/jclouds/compute/BaseComputeServiceLiveTest.java +++ b/compute/src/test/java/org/jclouds/compute/BaseComputeServiceLiveTest.java @@ -44,7 +44,6 @@ import org.jclouds.compute.domain.OsFamily; import org.jclouds.compute.domain.Size; import org.jclouds.compute.domain.Template; import org.jclouds.compute.domain.TemplateBuilder; -import org.jclouds.compute.options.GetNodesOptions; import org.jclouds.compute.options.RunScriptOptions; import org.jclouds.compute.options.TemplateOptions; import org.jclouds.compute.predicates.NodePredicates; @@ -66,7 +65,6 @@ import org.testng.annotations.BeforeGroups; import org.testng.annotations.Test; import com.google.common.base.Charsets; -import com.google.common.base.Predicate; import com.google.common.base.Predicates; import com.google.common.base.Throwables; import com.google.common.collect.ImmutableMap; @@ -172,7 +170,7 @@ public abstract class BaseComputeServiceLiveTest { @Test(enabled = true, dependsOnMethods = "testTemplateMatch") public void testCreateTwoNodesWithRunScript() throws Exception { try { - client.destroyNodesWithTag(tag); + client.destroyNodesMatching(NodePredicates.withTag(tag)); } catch (HttpResponseException e) { // TODO hosting.com throws 400 when we try to delete a vApp } catch (NoSuchElementException e) { @@ -236,8 +234,9 @@ public abstract class BaseComputeServiceLiveTest { assert good.account != null; try { - Map responses = runScriptWithCreds(tag, simpleTemplate - .getImage().getOsFamily(), new Credentials(good.account, "romeo")); + Map responses = runScriptWithCreds(tag, + simpleTemplate.getImage().getOsFamily(), + new Credentials(good.account, "romeo")); assert false : "shouldn't pass with a bad password\n" + responses; } catch (RunScriptOnNodesException e) { assert Throwables.getRootCause(e).getMessage().contains("Auth fail") : e; @@ -248,25 +247,19 @@ public abstract class BaseComputeServiceLiveTest { checkNodes(nodes, tag); } finally { - client.destroyNodesWithTag(tag); + client.destroyNodesMatching(NodePredicates.withTag(tag)); } } - protected Map runScriptWithCreds(final String tag, OsFamily osFamily, - Credentials creds) throws RunScriptOnNodesException { + protected Map runScriptWithCreds(final String tag, + OsFamily osFamily, Credentials creds) throws RunScriptOnNodesException { try { - return client.runScriptOnNodesMatching(new Predicate() { - - @Override - public boolean apply(NodeMetadata arg0) { - return arg0.getState() == NodeState.RUNNING && tag.equals(arg0.getTag()); - } - }, buildScript(osFamily).getBytes(), RunScriptOptions.Builder - .overrideCredentialsWith(creds)); + return client.runScriptOnNodesMatching(NodePredicates.runningWithTag(tag), buildScript( + osFamily).getBytes(), RunScriptOptions.Builder.overrideCredentialsWith(creds)); } catch (SshException e) { if (Throwables.getRootCause(e).getMessage().contains("Auth fail")) { - System.err.printf("bad credentials: %s:%s for %s%n", creds.account, creds.key, client - .listNodesWithTag(tag)); + // System.err.printf("bad credentials: %s:%s for %s%n", creds.account, creds.key, client + // .listNodesDetailsMatching(tag)); } throw e; } @@ -326,11 +319,12 @@ public abstract class BaseComputeServiceLiveTest { @Test(enabled = true, dependsOnMethods = "testCreateAnotherNodeWithANewContextToEnsureSharedMemIsntRequired") public void testGet() throws Exception { - Set metadataSet = Sets.newHashSet(Iterables.filter(client - .listNodesWithTag(tag), Predicates.not(NodePredicates.TERMINATED))); + Set nodes = client.listNodesDetailsMatching(NodePredicates.all()); + Set metadataSet = Sets.newHashSet(Iterables.filter(nodes, Predicates + .and(NodePredicates.withTag(tag), Predicates.not(NodePredicates.TERMINATED)))); for (NodeMetadata node : nodes) { metadataSet.remove(node); - NodeMetadata metadata = client.getNodeMetadata(node); + NodeMetadata metadata = client.getNodeMetadata(node.getLocation(), node.getId()); assertEquals(metadata.getId(), node.getId()); assertEquals(metadata.getTag(), node.getTag()); assertLocationSameOrChild(metadata.getLocation(), template.getLocation()); @@ -345,7 +339,7 @@ public abstract class BaseComputeServiceLiveTest { @Test(enabled = true, dependsOnMethods = "testGet") public void testReboot() throws Exception { - client.rebootNodesWithTag(tag);// TODO test validation + client.rebootNodesMatching(NodePredicates.withTag(tag));// TODO test validation testGet(); } @@ -366,7 +360,7 @@ public abstract class BaseComputeServiceLiveTest { } public void testGetNodesWithDetails() throws Exception { - for (ComputeMetadata node : client.listNodes(new GetNodesOptions().withDetails())) { + for (NodeMetadata node : client.listNodesDetailsMatching(NodePredicates.all())) { assert node.getId() != null : node; assert node.getLocation() != null : node; assertEquals(node.getType(), ComputeType.NODE); @@ -479,8 +473,9 @@ public abstract class BaseComputeServiceLiveTest { @AfterTest protected void cleanup() throws InterruptedException, ExecutionException, TimeoutException { if (nodes != null) { - client.destroyNodesWithTag(tag); - for (NodeMetadata node : client.listNodesWithTag(tag)) { + client.destroyNodesMatching(NodePredicates.withTag(tag)); + for (NodeMetadata node : Iterables.filter(client.listNodesDetailsMatching(NodePredicates + .all()), NodePredicates.withTag(tag))) { assert node.getState() == NodeState.TERMINATED : node; } } diff --git a/gogrid/src/main/java/org/jclouds/gogrid/compute/config/GoGridComputeServiceContextModule.java b/gogrid/src/main/java/org/jclouds/gogrid/compute/config/GoGridComputeServiceContextModule.java index 4256c24104..5c0487c5d9 100755 --- a/gogrid/src/main/java/org/jclouds/gogrid/compute/config/GoGridComputeServiceContextModule.java +++ b/gogrid/src/main/java/org/jclouds/gogrid/compute/config/GoGridComputeServiceContextModule.java @@ -18,6 +18,7 @@ */ package org.jclouds.gogrid.compute.config; +import static com.google.common.base.Preconditions.checkNotNull; import static org.jclouds.compute.domain.OsFamily.CENTOS; import static org.jclouds.gogrid.reference.GoGridConstants.PROPERTY_GOGRID_DEFAULT_DC; @@ -49,7 +50,7 @@ import org.jclouds.compute.domain.internal.ImageImpl; import org.jclouds.compute.domain.internal.SizeImpl; import org.jclouds.compute.internal.ComputeServiceContextImpl; import org.jclouds.compute.internal.TemplateBuilderImpl; -import org.jclouds.compute.options.GetNodesOptions; +import org.jclouds.compute.predicates.NodePredicates; import org.jclouds.compute.predicates.ScriptStatusReturnsZero; import org.jclouds.compute.predicates.ScriptStatusReturnsZero.CommandUsingClient; import org.jclouds.compute.reference.ComputeServiceConstants; @@ -137,9 +138,9 @@ public class GoGridComputeServiceContextModule extends GoGridContextModule { } @Override - public boolean execute(ComputeMetadata node) { - Server server = Iterables.getOnlyElement(client.getServerServices().getServersByName( - node.getName())); + public boolean execute(Location location, String id) { + Server server = Iterables.getOnlyElement(client.getServerServices().getServersById( + new Long(id))); client.getServerServices().power(server.getName(), PowerCommand.RESTART); serverLatestJobCompleted.apply(server); client.getServerServices().power(server.getName(), PowerCommand.START); @@ -160,11 +161,16 @@ public class GoGridComputeServiceContextModule extends GoGridContextModule { } @Override - public Iterable execute(GetNodesOptions options) { - return Iterables.transform(client.getServerServices().getServerList(), - serverToNodeMetadata); + public Iterable list() { + return listDetailsOnNodesMatching(NodePredicates.all()); } + @Override + public Iterable listDetailsOnNodesMatching( + Predicate filter) { + return Iterables.filter(Iterables.transform(client.getServerServices().getServerList(), + serverToNodeMetadata), filter); + } } @Singleton @@ -180,9 +186,9 @@ public class GoGridComputeServiceContextModule extends GoGridContextModule { } @Override - public NodeMetadata execute(ComputeMetadata node) { - Server server = Iterables.getOnlyElement(client.getServerServices().getServersByName( - node.getName())); + public NodeMetadata execute(Location location, String id) { + Server server = Iterables.getOnlyElement(client.getServerServices().getServersById( + new Long(checkNotNull(id, "id")))); return server == null ? null : serverToNodeMetadata.apply(server); } } @@ -200,9 +206,9 @@ public class GoGridComputeServiceContextModule extends GoGridContextModule { } @Override - public boolean execute(ComputeMetadata node) { - Server server = Iterables.getOnlyElement(client.getServerServices().getServersByName( - node.getName())); + public boolean execute(Location location, String id) { + Server server = Iterables.getOnlyElement(client.getServerServices().getServersById( + new Long(id))); client.getServerServices().deleteByName(server.getName()); return serverLatestJobCompleted.apply(server); } diff --git a/rackspace/src/main/java/org/jclouds/rackspace/cloudservers/compute/config/CloudServersComputeServiceContextModule.java b/rackspace/src/main/java/org/jclouds/rackspace/cloudservers/compute/config/CloudServersComputeServiceContextModule.java index cbdc47b704..6bdeb1b8f2 100755 --- a/rackspace/src/main/java/org/jclouds/rackspace/cloudservers/compute/config/CloudServersComputeServiceContextModule.java +++ b/rackspace/src/main/java/org/jclouds/rackspace/cloudservers/compute/config/CloudServersComputeServiceContextModule.java @@ -53,7 +53,7 @@ import org.jclouds.compute.domain.internal.SizeImpl; import org.jclouds.compute.internal.BaseComputeService; import org.jclouds.compute.internal.ComputeServiceContextImpl; import org.jclouds.compute.internal.TemplateBuilderImpl; -import org.jclouds.compute.options.GetNodesOptions; +import org.jclouds.compute.predicates.NodePredicates; import org.jclouds.compute.predicates.ScriptStatusReturnsZero; import org.jclouds.compute.predicates.ScriptStatusReturnsZero.CommandUsingClient; import org.jclouds.compute.reference.ComputeServiceConstants; @@ -142,8 +142,8 @@ public class CloudServersComputeServiceContextModule extends CloudServersContext } @Override - public boolean execute(ComputeMetadata node) { - int serverId = Integer.parseInt(node.getId()); + public boolean execute(Location location, String id) { + int serverId = Integer.parseInt(id); // if false server wasn't around in the first place client.rebootServer(serverId, RebootType.HARD); Server server = client.getServer(serverId); @@ -165,8 +165,8 @@ public class CloudServersComputeServiceContextModule extends CloudServersContext } @Override - public boolean execute(ComputeMetadata node) { - int serverId = Integer.parseInt(node.getId()); + public boolean execute(Location location, String id) { + int serverId = Integer.parseInt(id); // if false server wasn't around in the first place if (!client.deleteServer(serverId)) return false; @@ -216,11 +216,16 @@ public class CloudServersComputeServiceContextModule extends CloudServersContext } @Override - public Iterable execute(GetNodesOptions options) { - return Iterables.transform(client.listServers(ListOptions.Builder.withDetails()), - serverToNodeMetadata); + public Iterable list() { + return listDetailsOnNodesMatching(NodePredicates.all()); } + @Override + public Iterable listDetailsOnNodesMatching( + Predicate filter) { + return Iterables.filter(Iterables.transform(client.listServers(ListOptions.Builder + .withDetails()), serverToNodeMetadata), filter); + } } @Singleton @@ -237,8 +242,8 @@ public class CloudServersComputeServiceContextModule extends CloudServersContext } @Override - public NodeMetadata execute(ComputeMetadata node) { - int serverId = Integer.parseInt(node.getId()); + public NodeMetadata execute(Location location, String id) { + int serverId = Integer.parseInt(id); Server server = client.getServer(serverId); return server == null ? null : serverToNodeMetadata.apply(server); } diff --git a/rimuhosting/src/main/java/org/jclouds/rimuhosting/miro/compute/config/RimuHostingComputeServiceContextModule.java b/rimuhosting/src/main/java/org/jclouds/rimuhosting/miro/compute/config/RimuHostingComputeServiceContextModule.java index 376a767313..18200261b5 100755 --- a/rimuhosting/src/main/java/org/jclouds/rimuhosting/miro/compute/config/RimuHostingComputeServiceContextModule.java +++ b/rimuhosting/src/main/java/org/jclouds/rimuhosting/miro/compute/config/RimuHostingComputeServiceContextModule.java @@ -56,7 +56,7 @@ import org.jclouds.compute.domain.internal.NodeMetadataImpl; import org.jclouds.compute.domain.internal.SizeImpl; import org.jclouds.compute.internal.ComputeServiceContextImpl; import org.jclouds.compute.internal.TemplateBuilderImpl; -import org.jclouds.compute.options.GetNodesOptions; +import org.jclouds.compute.predicates.NodePredicates; import org.jclouds.compute.predicates.ScriptStatusReturnsZero; import org.jclouds.compute.predicates.ScriptStatusReturnsZero.CommandUsingClient; import org.jclouds.compute.reference.ComputeServiceConstants; @@ -140,8 +140,8 @@ public class RimuHostingComputeServiceContextModule extends RimuHostingContextMo } @Override - public boolean execute(ComputeMetadata node) { - Long serverId = Long.parseLong(node.getId()); + public boolean execute(Location location, String id) { + Long serverId = Long.parseLong(id); // if false server wasn't around in the first place return client.restartServer(serverId).getState() == RunningState.RUNNING; } @@ -161,8 +161,8 @@ public class RimuHostingComputeServiceContextModule extends RimuHostingContextMo } @Override - public boolean execute(ComputeMetadata node) { - long serverId = Long.parseLong(node.getId()); + public boolean execute(Location location, String id) { + long serverId = Long.parseLong(id); client.destroyServer(serverId); return serverDestroyed.apply(client.getServer(serverId)); } @@ -220,8 +220,15 @@ public class RimuHostingComputeServiceContextModule extends RimuHostingContextMo } @Override - public Iterable execute(GetNodesOptions options) { - return Iterables.transform(client.getServerList(), serverToNodeMetadata); + public Iterable list() { + return listDetailsOnNodesMatching(NodePredicates.all()); + } + + @Override + public Iterable listDetailsOnNodesMatching( + Predicate filter) { + return Iterables.filter(Iterables.transform(client.getServerList(), serverToNodeMetadata), + filter); } } @@ -240,8 +247,9 @@ public class RimuHostingComputeServiceContextModule extends RimuHostingContextMo } @Override - public NodeMetadata execute(ComputeMetadata node) { - long serverId = Long.parseLong(node.getId()); + public NodeMetadata execute(Location location, String id) { + // TODO location + long serverId = Long.parseLong(id); Server server = client.getServer(serverId); return server == null ? null : serverToNodeMetadata.apply(server); } diff --git a/tools/antcontrib/src/main/java/org/jclouds/tools/ant/taskdefs/compute/ComputeTask.java b/tools/antcontrib/src/main/java/org/jclouds/tools/ant/taskdefs/compute/ComputeTask.java index 6a2c02a35e..eb7a2aaa61 100644 --- a/tools/antcontrib/src/main/java/org/jclouds/tools/ant/taskdefs/compute/ComputeTask.java +++ b/tools/antcontrib/src/main/java/org/jclouds/tools/ant/taskdefs/compute/ComputeTask.java @@ -40,11 +40,13 @@ import org.jclouds.compute.domain.Image; import org.jclouds.compute.domain.NodeMetadata; import org.jclouds.compute.domain.Size; import org.jclouds.compute.domain.Template; +import org.jclouds.compute.predicates.NodePredicates; import org.jclouds.domain.Location; import org.jclouds.http.HttpUtils; import com.google.common.base.CaseFormat; import com.google.common.base.Splitter; +import com.google.common.collect.Iterables; import com.google.inject.Provider; /** @@ -219,19 +221,21 @@ public class ComputeTask extends Task { private void destroy(ComputeService computeService) { log(String.format("destroy tag: %s", nodeElement.getTag())); - computeService.destroyNodesWithTag(nodeElement.getTag()); + computeService.destroyNodesMatching(NodePredicates.withTag(nodeElement.getTag())); } private void get(ComputeService computeService) { log(String.format("get tag: %s", nodeElement.getTag())); - for (ComputeMetadata node : computeService.listNodesWithTag(nodeElement.getTag())) { + for (ComputeMetadata node : Iterables.filter(computeService + .listNodesDetailsMatching(NodePredicates.all()), NodePredicates.withTag(nodeElement + .getTag()))) { logDetails(computeService, node); } } private void logDetails(ComputeService computeService, ComputeMetadata node) { NodeMetadata metadata = node instanceof NodeMetadata ? NodeMetadata.class.cast(node) - : computeService.getNodeMetadata(node); + : computeService.getNodeMetadata(node.getLocation(), node.getId()); log(String .format( " node id=%s, name=%s, tag=%s, location=%s, state=%s, publicIp=%s, privateIp=%s, extra=%s", diff --git a/vcloud/core/src/main/java/org/jclouds/vcloud/compute/config/VCloudComputeServiceContextModule.java b/vcloud/core/src/main/java/org/jclouds/vcloud/compute/config/VCloudComputeServiceContextModule.java index 539c7121c2..4b5204de3e 100755 --- a/vcloud/core/src/main/java/org/jclouds/vcloud/compute/config/VCloudComputeServiceContextModule.java +++ b/vcloud/core/src/main/java/org/jclouds/vcloud/compute/config/VCloudComputeServiceContextModule.java @@ -18,7 +18,6 @@ */ package org.jclouds.vcloud.compute.config; -import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkNotNull; import static org.jclouds.compute.domain.OsFamily.UBUNTU; import static org.jclouds.vcloud.options.InstantiateVAppTemplateOptions.Builder.processorCount; @@ -50,12 +49,12 @@ import org.jclouds.compute.domain.OsFamily; import org.jclouds.compute.domain.Size; import org.jclouds.compute.domain.Template; import org.jclouds.compute.domain.TemplateBuilder; +import org.jclouds.compute.domain.internal.ComputeMetadataImpl; 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.internal.ComputeServiceContextImpl; import org.jclouds.compute.internal.TemplateBuilderImpl; -import org.jclouds.compute.options.GetNodesOptions; import org.jclouds.compute.predicates.ScriptStatusReturnsZero; import org.jclouds.compute.predicates.ScriptStatusReturnsZero.CommandUsingClient; import org.jclouds.compute.reference.ComputeServiceConstants; @@ -163,8 +162,8 @@ public class VCloudComputeServiceContextModule extends VCloudContextModule { } @Override - public boolean execute(ComputeMetadata node) { - Task task = client.resetVApp(node.getId()); + public boolean execute(Location location, String id) { + Task task = client.resetVApp(id); return taskTester.apply(task.getId()); } @@ -180,8 +179,8 @@ public class VCloudComputeServiceContextModule extends VCloudContextModule { } @Override - public boolean execute(ComputeMetadata node) { - computeClient.stop(checkNotNull(node.getId(), "node.id")); + public boolean execute(Location location, String id) { + computeClient.stop(checkNotNull(id, "node.id")); return true; } @@ -241,11 +240,31 @@ public class VCloudComputeServiceContextModule extends VCloudContextModule { } @Override - public Iterable execute(GetNodesOptions options) { + public Iterable list() { Set nodes = Sets.newHashSet(); for (NamedResource vdc : client.getDefaultOrganization().getVDCs().values()) { for (NamedResource resource : client.getVDC(vdc.getId()).getResourceEntities().values()) { if (resource.getType().equals(VCloudMediaType.VAPP_XML)) { + nodes.add(convertVAppToComputeMetadata(vdc, resource)); + } + } + } + return nodes; + } + + private ComputeMetadata convertVAppToComputeMetadata(NamedResource vdc, NamedResource resource) { + Location location = findLocationForResourceInVDC.apply(resource, vdc.getId()); + return new ComputeMetadataImpl(ComputeType.NODE, resource.getId(), resource.getName(), + location, null, ImmutableMap. of()); + } + + @Override + public Iterable listDetailsOnNodesMatching(Predicate filter) { + Set nodes = Sets.newHashSet(); + for (NamedResource vdc : client.getDefaultOrganization().getVDCs().values()) { + for (NamedResource resource : client.getVDC(vdc.getId()).getResourceEntities().values()) { + if (resource.getType().equals(VCloudMediaType.VAPP_XML) + && filter.apply(convertVAppToComputeMetadata(vdc, resource))) { addVAppToSetRetryingIfNotYetPresent(nodes, vdc, resource); } } @@ -254,7 +273,7 @@ public class VCloudComputeServiceContextModule extends VCloudContextModule { } @VisibleForTesting - void addVAppToSetRetryingIfNotYetPresent(Set nodes, NamedResource vdc, + void addVAppToSetRetryingIfNotYetPresent(Set nodes, NamedResource vdc, NamedResource resource) { NodeMetadata node = null; int i = 0; @@ -284,11 +303,9 @@ public class VCloudComputeServiceContextModule extends VCloudContextModule { } @Override - public NodeMetadata execute(ComputeMetadata node) { - checkArgument(node.getType() == ComputeType.NODE, "this is only valid for nodes, not " - + node.getType()); - return getNodeMetadataByIdInVDC(checkNotNull(node.getLocation(), "location").getId(), - checkNotNull(node.getId(), "node.id")); + public NodeMetadata execute(Location location, String id) { + return getNodeMetadataByIdInVDC(checkNotNull(location, "location").getId(), checkNotNull( + id, "node.id")); } } diff --git a/vcloud/core/src/main/java/org/jclouds/vcloud/compute/functions/VCloudGetNodeMetadata.java b/vcloud/core/src/main/java/org/jclouds/vcloud/compute/functions/VCloudGetNodeMetadata.java index 0a1ca7630f..0a1f6db8db 100644 --- a/vcloud/core/src/main/java/org/jclouds/vcloud/compute/functions/VCloudGetNodeMetadata.java +++ b/vcloud/core/src/main/java/org/jclouds/vcloud/compute/functions/VCloudGetNodeMetadata.java @@ -57,6 +57,7 @@ import com.google.common.collect.Iterables; */ @Singleton public class VCloudGetNodeMetadata { + @Resource @Named(ComputeServiceConstants.COMPUTE_LOGGER) public Logger logger = Logger.NULL; @@ -85,7 +86,7 @@ public class VCloudGetNodeMetadata { this.computeClient = checkNotNull(computeClient, "computeClient"); this.vAppStatusToNodeState = checkNotNull(vAppStatusToNodeState, "vAppStatusToNodeState"); } - + protected NodeMetadata getNodeMetadataByIdInVDC(String vDCId, String id) { VApp vApp = client.getVApp(id); diff --git a/vcloud/core/src/test/java/org/jclouds/vcloud/compute/VCloudComputeServiceLiveTest.java b/vcloud/core/src/test/java/org/jclouds/vcloud/compute/VCloudComputeServiceLiveTest.java index c651f7689b..03887ea65d 100644 --- a/vcloud/core/src/test/java/org/jclouds/vcloud/compute/VCloudComputeServiceLiveTest.java +++ b/vcloud/core/src/test/java/org/jclouds/vcloud/compute/VCloudComputeServiceLiveTest.java @@ -48,7 +48,7 @@ public class VCloudComputeServiceLiveTest extends BaseComputeServiceLiveTest { assert node.getId() != null; assert node.getLocation() != null; assertEquals(node.getType(), ComputeType.NODE); - NodeMetadata allData = client.getNodeMetadata(node); + NodeMetadata allData = client.getNodeMetadata(node.getLocation(), node.getId()); assert allData.getExtra().get("processor/count") != null; assert allData.getExtra().get("disk_drive/1/kb") != null; assert allData.getExtra().get("memory/mb") != null; diff --git a/vcloud/core/src/test/java/org/jclouds/vcloud/compute/config/VCloudComputeServiceContextModuleTest.java b/vcloud/core/src/test/java/org/jclouds/vcloud/compute/config/VCloudComputeServiceContextModuleTest.java index 3ac00af9b2..550512f9e3 100644 --- a/vcloud/core/src/test/java/org/jclouds/vcloud/compute/config/VCloudComputeServiceContextModuleTest.java +++ b/vcloud/core/src/test/java/org/jclouds/vcloud/compute/config/VCloudComputeServiceContextModuleTest.java @@ -33,8 +33,8 @@ import java.util.SortedSet; import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeoutException; -import org.jclouds.compute.domain.ComputeMetadata; import org.jclouds.compute.domain.Image; +import org.jclouds.compute.domain.NodeMetadata; import org.jclouds.compute.domain.NodeState; import org.jclouds.domain.Location; import org.jclouds.domain.LocationScope; @@ -124,7 +124,7 @@ public class VCloudComputeServiceContextModuleTest { VCloudListNodesStrategy strategy = new VCloudListNodesStrategy(client, computeClient, vAppStatusToNodeState, getExtra, findLocationForResourceInVDC, images); - Set nodes = Sets.newHashSet(); + Set nodes = Sets.newHashSet(); NamedResource vdc = new NamedResourceImpl("1", null, null, null); NamedResource resource = new NamedResourceImpl("10", null, null, null);