diff --git a/compute/src/main/java/org/jclouds/compute/strategy/impl/CreateNodesWithGroupEncodedIntoNameThenAddToSet.java b/compute/src/main/java/org/jclouds/compute/strategy/impl/CreateNodesWithGroupEncodedIntoNameThenAddToSet.java index 22e1dca93a..b1c94e8791 100644 --- a/compute/src/main/java/org/jclouds/compute/strategy/impl/CreateNodesWithGroupEncodedIntoNameThenAddToSet.java +++ b/compute/src/main/java/org/jclouds/compute/strategy/impl/CreateNodesWithGroupEncodedIntoNameThenAddToSet.java @@ -42,12 +42,13 @@ import org.jclouds.Constants; import org.jclouds.compute.config.CustomizationResponse; import org.jclouds.compute.domain.ComputeMetadata; import org.jclouds.compute.domain.NodeMetadata; +import org.jclouds.compute.domain.NodeState; import org.jclouds.compute.domain.Template; import org.jclouds.compute.reference.ComputeServiceConstants; import org.jclouds.compute.strategy.CreateNodeWithGroupEncodedIntoName; +import org.jclouds.compute.strategy.CreateNodesInGroupThenAddToSet; import org.jclouds.compute.strategy.CustomizeNodeAndAddToGoodMapOrPutExceptionIntoBadMap; import org.jclouds.compute.strategy.ListNodesStrategy; -import org.jclouds.compute.strategy.CreateNodesInGroupThenAddToSet; import org.jclouds.logging.Logger; import com.google.common.base.Predicate; @@ -61,12 +62,12 @@ import com.google.common.collect.Multimap; @Singleton public class CreateNodesWithGroupEncodedIntoNameThenAddToSet implements CreateNodesInGroupThenAddToSet { - private class AddNode implements Callable> { + protected class AddNode implements Callable> { private final String name; private final String group; private final Template template; - private AddNode(String name, String group, Template template) { + public AddNode(String name, String group, Template template) { this.name = checkNotNull(name, "name"); this.group = checkNotNull(group, "group"); this.template = checkNotNull(template, "template"); @@ -75,9 +76,8 @@ public class CreateNodesWithGroupEncodedIntoNameThenAddToSet implements CreateNo @Override public AtomicReference call() throws Exception { NodeMetadata node = null; - logger.debug(">> adding node location(%s) name(%s) image(%s) hardware(%s)", - template.getLocation().getId(), name, template.getImage().getProviderId(), template.getHardware() - .getProviderId()); + logger.debug(">> adding node location(%s) name(%s) image(%s) hardware(%s)", template.getLocation().getId(), + name, template.getImage().getProviderId(), template.getHardware().getProviderId()); node = addNodeWithGroupStrategy.createNodeWithGroupEncodedIntoName(group, name, template); logger.debug("<< %s node(%s)", node.getState(), node.getId()); return new AtomicReference(node); @@ -121,13 +121,54 @@ public class CreateNodesWithGroupEncodedIntoNameThenAddToSet implements CreateNo Map badNodes, Multimap customizationResponses) { Map> responses = newLinkedHashMap(); for (String name : getNextNames(group, template, count)) { - responses.put(name, compose(executor.submit(new AddNode(name, group, template)), - customizeNodeAndAddToGoodMapOrPutExceptionIntoBadMapFactory.create(template.getOptions(), - goodNodes, badNodes, customizationResponses), executor)); + responses.put(name, compose(createNodeInGroupWithNameAndTemplate(group, name, template), + customizeNodeAndAddToGoodMapOrPutExceptionIntoBadMapFactory.create(template.getOptions(), goodNodes, + badNodes, customizationResponses), executor)); } return responses; } + /** + * This calls logic necessary to create a node and convert it from its provider-specific object + * to the jclouds {@link NodeMetadata} object. This call directly precedes customization, such as + * executing scripts. + * + *

The outcome of this operation does not imply the node is {@link NodeState#RUNNING + * running}. If you want to insert logic after the node is created, yet before an attempt to + * customize the node, then append your behaviour to this method. + * + * ex. to attach an ip address post-creation + * + *
+    * @Override
+    * protected Future<AtomicReference<NodeMetadata>> createNodeInGroupWithNameAndTemplate(String group, String name,
+    *          Template template) {
+    * 
+    *    Future<AtomicReference<NodeMetadata>> future = super.addNodeIntoGroupWithNameAndTemplate(group, name, template);
+    *    return Futures.compose(future, new Function<AtomicReference<NodeMetadata>, AtomicReference<NodeMetadata>>() {
+    * 
+    *       @Override
+    *       public AtomicReference<NodeMetadata> apply(AtomicReference<NodeMetadata> input) {
+    *          NodeMetadata node = input.get();
+    *          // allocate and attach an ip
+    *          input.set(NodeMetadataBuilder.fromNodeMetadata(node).publicAddresses(ImmutableSet.of(ip.getIp())).build());
+    *          return input;
+    *       }
+    * 
+    *    }, executor);
+    * }
+    * 
+ * + * @param group group the node belongs to + * @param name generated name of the node + * @param template user-specified template + * @return node that is created, yet not necessarily in {@link NodeState#RUNNING} + */ + protected Future> createNodeInGroupWithNameAndTemplate(String group, String name, + Template template) { + return executor.submit(new AddNode(name, group, template)); + } + /** * Find the next node names that can be used. These will be derived from the group and the * template. We will pre-allocate a specified quantity, and attempt to verify that there is no