diff --git a/compute/src/main/java/org/jclouds/compute/ComputeService.java b/compute/src/main/java/org/jclouds/compute/ComputeService.java index bd71904f20..ea59f97095 100755 --- a/compute/src/main/java/org/jclouds/compute/ComputeService.java +++ b/compute/src/main/java/org/jclouds/compute/ComputeService.java @@ -18,6 +18,7 @@ */ package org.jclouds.compute; +import java.util.List; import java.util.Map; import java.util.Set; @@ -142,6 +143,8 @@ public interface ComputeService { * nodes which are tagged 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); @@ -172,6 +175,7 @@ public interface ComputeService { * Runs the script without any additional options * * @see #runScriptOnNodesMatching(Predicate, byte[], org.jclouds.compute.options.RunScriptOptions) + * @see org.jclouds.compute.predicates.NodePredicates#activeWithTag(String) */ Map runScriptOnNodesMatching(Predicate filter, byte[] runScript) throws RunScriptOnNodesException; @@ -189,6 +193,8 @@ public interface ComputeService { * 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) */ 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 be7e02cfeb..0228b189a3 100755 --- a/compute/src/main/java/org/jclouds/compute/internal/BaseComputeService.java +++ b/compute/src/main/java/org/jclouds/compute/internal/BaseComputeService.java @@ -28,6 +28,7 @@ import static com.google.common.base.Preconditions.checkNotNull; 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; @@ -40,6 +41,8 @@ import javax.inject.Named; import javax.inject.Provider; import javax.inject.Singleton; +import com.google.common.base.Predicates; +import com.google.common.collect.Lists; import org.jclouds.Constants; import org.jclouds.compute.ComputeService; import org.jclouds.compute.ComputeServiceContext; @@ -55,6 +58,7 @@ 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; import org.jclouds.compute.strategy.DestroyNodeStrategy; import org.jclouds.compute.strategy.GetNodeMetadataStrategy; @@ -74,6 +78,7 @@ import com.google.common.collect.Iterables; import com.google.common.collect.Maps; import com.google.common.collect.Sets; import com.google.common.util.concurrent.ListenableFuture; +import static org.jclouds.compute.predicates.NodePredicates.withTag; /** * @@ -100,20 +105,6 @@ public class BaseComputeService implements ComputeService { protected final ExecutorService executor; protected final ComputeMetadataToNodeMetadata computeMetadataToNodeMetadata; - private static class NodeMatchesTag implements Predicate { - private final String tag; - - public NodeMatchesTag(String tag) { - this.tag = tag; - } - - @Override - public boolean apply(NodeMetadata from) { - return from.getTag().equals(tag); - } - - }; - @Inject protected BaseComputeService(ComputeServiceContext context, Provider> images, Provider> sizes, @@ -180,19 +171,15 @@ public class BaseComputeService implements ComputeService { public void destroyNodesWithTag(String tag) { // TODO parallel logger.debug(">> destroying nodes by tag(%s)", tag); Iterable nodesToDestroy = Iterables.filter(doListNodesWithTag(tag), - new Predicate() { - @Override - public boolean apply(NodeMetadata input) { - return input.getState() != NodeState.TERMINATED; - - } - }); + Predicates.not(NodePredicates.TERMINATED)); Map> responses = Maps.newHashMap(); + final List destroyedNodes = Lists.newArrayList(); for (final NodeMetadata node : nodesToDestroy) { responses.put(node, makeListenable(executor.submit(new Callable() { @Override public Void call() throws Exception { destroyNode(node); + destroyedNodes.add(node); return null; } }), executor)); @@ -224,7 +211,7 @@ public class BaseComputeService implements ComputeService { */ protected Set doListNodesWithTag(final String tag) { return Sets.newHashSet(Iterables.filter(Iterables.transform(listNodesStrategy - .execute(GetNodesOptions.NONE), computeMetadataToNodeMetadata), new NodeMatchesTag(tag))); + .execute(GetNodesOptions.NONE), computeMetadataToNodeMetadata), withTag(tag))); } class ComputeMetadataToNodeMetadata @@ -287,13 +274,7 @@ public class BaseComputeService implements ComputeService { public void rebootNodesWithTag(String tag) { // TODO parallel logger.debug(">> rebooting nodes by tag(%s)", tag); Iterable nodesToReboot = Iterables.filter(doListNodesWithTag(tag), - new Predicate() { - @Override - public boolean apply(NodeMetadata input) { - return input.getState() != NodeState.TERMINATED; - - } - }); + Predicates.not(NodePredicates.TERMINATED)); Map> responses = Maps.newHashMap(); for (final NodeMetadata node : nodesToReboot) { responses.put(node, makeListenable(executor.submit(new Callable() { @@ -311,6 +292,7 @@ public class BaseComputeService implements ComputeService { /** * @throws RunScriptOnNodesException * @see #runScriptOnNodesMatching(Predicate, byte[], org.jclouds.compute.options.RunScriptOptions) + * @see org.jclouds.compute.predicates.NodePredicates#activeWithTag(String) */ public Map runScriptOnNodesMatching(Predicate filter, byte[] runScript) throws RunScriptOnNodesException { @@ -330,6 +312,8 @@ public class BaseComputeService implements ComputeService { * 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) */ public Map runScriptOnNodesMatching(Predicate filter, final byte[] runScript, @Nullable final RunScriptOptions options) diff --git a/compute/src/main/java/org/jclouds/compute/predicates/NodePredicates.java b/compute/src/main/java/org/jclouds/compute/predicates/NodePredicates.java new file mode 100644 index 0000000000..36b6f85587 --- /dev/null +++ b/compute/src/main/java/org/jclouds/compute/predicates/NodePredicates.java @@ -0,0 +1,90 @@ +/** + * + * Copyright (C) 2010 Cloud Conscious, LLC. + * + * ==================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ==================================================================== + */ +package org.jclouds.compute.predicates; + +import com.google.common.base.Predicate; +import org.jclouds.compute.domain.NodeMetadata; +import org.jclouds.compute.domain.NodeState; + +import javax.annotation.Nullable; +import static org.jclouds.util.Utils.checkNotEmpty; + +/** + * Container for node filters (predicates). + * + * This class has static methods that create customized predicates to use with + * {@link org.jclouds.compute.ComputeService}. + * + * @author Oleksiy Yarmula + */ +public class NodePredicates { + + /** + * Return nodes with specified tag. + * Note: returns all nodes, regardless of the state. + * + * @param tag tag to match the items + * @return predicate + */ + public static Predicate withTag(final String tag) { + checkNotEmpty(tag, "Tag must be defined"); + return new Predicate() { + @Override + public boolean apply(@Nullable NodeMetadata nodeMetadata) { + return tag.equals(nodeMetadata.getTag()); + } + }; + } + + /** + * Return nodes with specified tag that are in the RUNNING state. + * @param tag tag to match the items + * @return predicate + */ + public static Predicate activeWithTag(final String tag) { + checkNotEmpty(tag, "Tag must be defined"); + return new Predicate() { + @Override + public boolean apply(@Nullable NodeMetadata nodeMetadata) { + return tag.equals(nodeMetadata.getTag()) && nodeMetadata.getState() == NodeState.RUNNING; + } + }; + } + + /** + * Match nodes with State == RUNNING + */ + public static final Predicate ACTIVE = new Predicate() { + @Override + public boolean apply(@Nullable NodeMetadata nodeMetadata) { + return nodeMetadata.getState() == NodeState.RUNNING; + } + }; + + /** + * Match nodes with State == TERMINATED + */ + public static final Predicate TERMINATED = new Predicate() { + @Override + public boolean apply(@Nullable NodeMetadata nodeMetadata) { + return nodeMetadata.getState() == NodeState.TERMINATED; + } + }; + +} diff --git a/compute/src/test/java/org/jclouds/compute/BaseComputeServiceLiveTest.java b/compute/src/test/java/org/jclouds/compute/BaseComputeServiceLiveTest.java index c244f166e3..19d8b00d6f 100755 --- a/compute/src/test/java/org/jclouds/compute/BaseComputeServiceLiveTest.java +++ b/compute/src/test/java/org/jclouds/compute/BaseComputeServiceLiveTest.java @@ -47,6 +47,7 @@ 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; import org.jclouds.domain.Credentials; import org.jclouds.domain.Location; import org.jclouds.domain.LocationScope; @@ -249,15 +250,9 @@ public abstract class BaseComputeServiceLiveTest { private Map runScriptWithCreds(String tag, OsFamily osFamily, Credentials creds) throws RunScriptOnNodesException { - Predicate filter = new Predicate() { - @Override - public boolean apply(@Nullable NodeMetadata nodeMetadata) { - return true; /*accept all*/ - } - }; - try { - return client.runScriptOnNodesMatching(filter, buildScript(osFamily).getBytes(), + return client.runScriptOnNodesMatching(Predicates.alwaysTrue(), + buildScript(osFamily).getBytes(), RunScriptOptions.Builder.overrideCredentialsWith(creds)); } catch (SshException e) { if (Throwables.getRootCause(e).getMessage().contains("Auth fail")) { @@ -323,12 +318,7 @@ 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(new Predicate() { - @Override - public boolean apply(NodeMetadata input) { - return input.getState() == NodeState.TERMINATED; - } - }))); + .listNodesWithTag(tag), Predicates.not(NodePredicates.TERMINATED))); for (NodeMetadata node : nodes) { metadataSet.remove(node); NodeMetadata metadata = client.getNodeMetadata(node);