1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.jclouds.compute.strategy.impl;
20
21 import static com.google.common.base.Objects.toStringHelper;
22 import static com.google.common.base.Preconditions.checkNotNull;
23 import static com.google.common.collect.Iterables.any;
24 import static com.google.common.collect.Maps.newLinkedHashMap;
25 import static com.google.common.collect.Sets.newLinkedHashSet;
26 import static org.jclouds.concurrent.Futures.compose;
27
28 import java.security.SecureRandom;
29 import java.util.Map;
30 import java.util.Set;
31 import java.util.concurrent.Callable;
32 import java.util.concurrent.ExecutorService;
33 import java.util.concurrent.Future;
34
35 import javax.annotation.Resource;
36 import javax.inject.Inject;
37 import javax.inject.Named;
38 import javax.inject.Singleton;
39
40 import org.jclouds.Constants;
41 import org.jclouds.compute.config.CustomizationResponse;
42 import org.jclouds.compute.domain.ComputeMetadata;
43 import org.jclouds.compute.domain.NodeMetadata;
44 import org.jclouds.compute.domain.Template;
45 import org.jclouds.compute.reference.ComputeServiceConstants;
46 import org.jclouds.compute.strategy.CreateNodeWithGroupEncodedIntoName;
47 import org.jclouds.compute.strategy.CustomizeNodeAndAddToGoodMapOrPutExceptionIntoBadMap;
48 import org.jclouds.compute.strategy.ListNodesStrategy;
49 import org.jclouds.compute.strategy.CreateNodesInGroupThenAddToSet;
50 import org.jclouds.logging.Logger;
51
52 import com.google.common.base.Predicate;
53 import com.google.common.collect.Multimap;
54
55
56
57
58
59
60 @Singleton
61 public class CreateNodesWithGroupEncodedIntoNameThenAddToSet implements CreateNodesInGroupThenAddToSet {
62
63 private class AddNode implements Callable<NodeMetadata> {
64 private final String name;
65 private final String tag;
66 private final Template template;
67
68 private AddNode(String name, String tag, Template template) {
69 this.name = checkNotNull(name, "name");
70 this.tag = checkNotNull(tag, "tag");
71 this.template = checkNotNull(template, "template");
72 }
73
74 @Override
75 public NodeMetadata call() throws Exception {
76 NodeMetadata node = null;
77 logger.debug(">> adding node location(%s) name(%s) image(%s) hardware(%s)",
78 template.getLocation().getId(), name, template.getImage().getProviderId(), template.getHardware()
79 .getProviderId());
80 node = addNodeWithTagStrategy.createNodeWithGroupEncodedIntoName(tag, name, template);
81 logger.debug("<< %s node(%s)", node.getState(), node.getId());
82 return node;
83 }
84
85 public String toString() {
86 return toStringHelper(this).add("name", name).add("tag", tag).add("template", template).toString();
87 }
88
89 }
90
91 @Resource
92 @Named(ComputeServiceConstants.COMPUTE_LOGGER)
93 protected Logger logger = Logger.NULL;
94 protected final CreateNodeWithGroupEncodedIntoName addNodeWithTagStrategy;
95 protected final ListNodesStrategy listNodesStrategy;
96 protected final String nodeNamingConvention;
97 protected final ExecutorService executor;
98 protected final CustomizeNodeAndAddToGoodMapOrPutExceptionIntoBadMap.Factory customizeNodeAndAddToGoodMapOrPutExceptionIntoBadMapFactory;
99
100 @Inject
101 protected CreateNodesWithGroupEncodedIntoNameThenAddToSet(
102 CreateNodeWithGroupEncodedIntoName addNodeWithTagStrategy,
103 ListNodesStrategy listNodesStrategy,
104 @Named("NAMING_CONVENTION") String nodeNamingConvention,
105 @Named(Constants.PROPERTY_USER_THREADS) ExecutorService executor,
106 CustomizeNodeAndAddToGoodMapOrPutExceptionIntoBadMap.Factory customizeNodeAndAddToGoodMapOrPutExceptionIntoBadMapFactory) {
107 this.addNodeWithTagStrategy = addNodeWithTagStrategy;
108 this.listNodesStrategy = listNodesStrategy;
109 this.nodeNamingConvention = nodeNamingConvention;
110 this.executor = executor;
111 this.customizeNodeAndAddToGoodMapOrPutExceptionIntoBadMapFactory = customizeNodeAndAddToGoodMapOrPutExceptionIntoBadMapFactory;
112 }
113
114
115
116
117
118 @Override
119 public Map<?, Future<Void>> execute(String tag, int count, Template template, Set<NodeMetadata> goodNodes,
120 Map<NodeMetadata, Exception> badNodes, Multimap<NodeMetadata, CustomizationResponse> customizationResponses) {
121 Map<String, Future<Void>> responses = newLinkedHashMap();
122 for (String name : getNextNames(tag, template, count)) {
123 responses.put(name, compose(executor.submit(new AddNode(name, tag, template)),
124 customizeNodeAndAddToGoodMapOrPutExceptionIntoBadMapFactory.create(template.getOptions(),
125 goodNodes, badNodes, customizationResponses), executor));
126 }
127 return responses;
128 }
129
130
131
132
133
134
135
136
137
138
139
140 protected Set<String> getNextNames(final String tag, final Template template, int count) {
141 Set<String> names = newLinkedHashSet();
142 Iterable<? extends ComputeMetadata> currentNodes = listNodesStrategy.listNodes();
143 int maxTries = 100;
144 int currentTries = 0;
145 while (names.size() < count && currentTries++ < maxTries) {
146 final String name = getNextName(tag, template);
147 if (!any(currentNodes, new Predicate<ComputeMetadata>() {
148
149 @Override
150 public boolean apply(ComputeMetadata input) {
151 return name.equals(input.getName());
152 }
153
154 })) {
155 names.add(name);
156 }
157 }
158 return names;
159 }
160
161
162
163
164
165
166
167
168 protected String getNextName(final String tag, final Template template) {
169 return String.format(nodeNamingConvention, tag, Integer.toHexString(new SecureRandom().nextInt(4095)));
170 }
171
172 }