EMMA Coverage Report (generated Mon Oct 17 05:41:20 EDT 2011)
[all classes][org.jclouds.ec2.compute.strategy]

COVERAGE SUMMARY FOR SOURCE FILE [EC2CreateNodesInGroupThenAddToSet.java]

nameclass, %method, %block, %line, %
EC2CreateNodesInGroupThenAddToSet.java100% (2/2)100% (8/8)84%  (262/312)95%  (44.5/47)

COVERAGE BREAKDOWN BY CLASS AND METHOD

nameclass, %method, %block, %line, %
     
class EC2CreateNodesInGroupThenAddToSet100% (1/1)100% (6/6)83%  (251/301)95%  (43.5/46)
createNodesInRegionAndZone (String, String, String, int, Template, RunInstanc... 100% (1/1)49%  (47/96)82%  (9/11)
populateCredentials (Iterable): void 100% (1/1)98%  (54/55)94%  (8.5/9)
<static initializer> 100% (1/1)100% (5/5)100% (1/1)
EC2CreateNodesInGroupThenAddToSet (EC2Client, Provider, CreateKeyPairAndSecur... 100% (1/1)100% (54/54)100% (11/11)
createKeyPairAndSecurityGroupsAsNeededThenRunInstances (String, int, Template... 100% (1/1)100% (24/24)100% (4/4)
execute (String, int, Template, Set, Map, Multimap): Map 100% (1/1)100% (67/67)100% (10/10)
     
class EC2CreateNodesInGroupThenAddToSet$1100% (1/1)100% (2/2)100% (11/11)100% (2/2)
EC2CreateNodesInGroupThenAddToSet$1 (): void 100% (1/1)100% (3/3)100% (1/1)
apply (RunningInstance): RegionAndName 100% (1/1)100% (8/8)100% (1/1)

1/**
2 * Licensed to jclouds, Inc. (jclouds) under one or more
3 * contributor license agreements.  See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership.  jclouds licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance
8 * with the License.  You may obtain a copy of the License at
9 *
10 *   http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing,
13 * software distributed under the License is distributed on an
14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 * KIND, either express or implied.  See the License for the
16 * specific language governing permissions and limitations
17 * under the License.
18 */
19package org.jclouds.ec2.compute.strategy;
20 
21import static com.google.common.base.Preconditions.checkNotNull;
22import static com.google.common.collect.Iterables.all;
23import static com.google.common.collect.Iterables.transform;
24import static org.jclouds.ec2.compute.util.EC2ComputeUtils.getZoneFromLocationOrNull;
25 
26import java.util.Map;
27import java.util.Set;
28import java.util.concurrent.Future;
29 
30import javax.annotation.Resource;
31import javax.inject.Inject;
32import javax.inject.Named;
33import javax.inject.Provider;
34import javax.inject.Singleton;
35 
36import org.jclouds.aws.util.AWSUtils;
37import org.jclouds.compute.config.CustomizationResponse;
38import org.jclouds.compute.domain.NodeMetadata;
39import org.jclouds.compute.domain.Template;
40import org.jclouds.compute.domain.TemplateBuilder;
41import org.jclouds.compute.reference.ComputeServiceConstants;
42import org.jclouds.compute.strategy.CreateNodesInGroupThenAddToSet;
43import org.jclouds.compute.util.ComputeUtils;
44import org.jclouds.domain.Credentials;
45import org.jclouds.ec2.EC2Client;
46import org.jclouds.ec2.compute.domain.RegionAndName;
47import org.jclouds.ec2.compute.predicates.InstancePresent;
48import org.jclouds.ec2.domain.RunningInstance;
49import org.jclouds.ec2.options.RunInstancesOptions;
50import org.jclouds.logging.Logger;
51 
52import com.google.common.annotations.VisibleForTesting;
53import com.google.common.base.Function;
54import com.google.common.base.Joiner;
55import com.google.common.cache.Cache;
56import com.google.common.collect.ImmutableSet;
57import com.google.common.collect.Iterables;
58import com.google.common.collect.Multimap;
59 
60/**
61 * creates futures that correlate to
62 * 
63 * @author Adrian Cole
64 */
65@Singleton
66public class EC2CreateNodesInGroupThenAddToSet implements CreateNodesInGroupThenAddToSet {
67 
68   @Resource
69   @Named(ComputeServiceConstants.COMPUTE_LOGGER)
70   protected Logger logger = Logger.NULL;
71 
72   @VisibleForTesting
73   final EC2Client client;
74   @VisibleForTesting
75   final CreateKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions createKeyPairAndSecurityGroupsAsNeededAndReturncustomize;
76   @VisibleForTesting
77   final Function<RunningInstance, NodeMetadata> runningInstanceToNodeMetadata;
78   @VisibleForTesting
79   final ComputeUtils utils;
80   final InstancePresent instancePresent;
81   final Cache<RunningInstance, Credentials> instanceToCredentials;
82   final Map<String, Credentials> credentialStore;
83   final Provider<TemplateBuilder> templateBuilderProvider;
84 
85   @Inject
86   protected EC2CreateNodesInGroupThenAddToSet(
87            EC2Client client,
88            Provider<TemplateBuilder> templateBuilderProvider,
89            CreateKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions createKeyPairAndSecurityGroupsAsNeededAndReturncustomize,
90            InstancePresent instancePresent, Function<RunningInstance, NodeMetadata> runningInstanceToNodeMetadata,
91            Cache<RunningInstance, Credentials> instanceToCredentials, Map<String, Credentials> credentialStore,
92            ComputeUtils utils) {
93      this.client = checkNotNull(client, "client");
94      this.templateBuilderProvider = checkNotNull(templateBuilderProvider, "templateBuilderProvider");
95      this.instancePresent = checkNotNull(instancePresent, "instancePresent");
96      this.createKeyPairAndSecurityGroupsAsNeededAndReturncustomize = checkNotNull(
97               createKeyPairAndSecurityGroupsAsNeededAndReturncustomize,
98               "createKeyPairAndSecurityGroupsAsNeededAndReturncustomize");
99      this.runningInstanceToNodeMetadata = checkNotNull(runningInstanceToNodeMetadata, "runningInstanceToNodeMetadata");
100      this.instanceToCredentials = checkNotNull(instanceToCredentials, "instanceToCredentials");
101      this.credentialStore = checkNotNull(credentialStore, "credentialStore");
102      this.utils = checkNotNull(utils, "utils");
103   }
104 
105   public static Function<RunningInstance, RegionAndName> instanceToRegionAndName = new Function<RunningInstance, RegionAndName>() {
106      @Override
107      public RegionAndName apply(RunningInstance from) {
108         return new RegionAndName(from.getRegion(), from.getId());
109      }
110   };
111 
112   @Override
113   public Map<?, Future<Void>> execute(String group, int count, Template template, Set<NodeMetadata> goodNodes,
114            Map<NodeMetadata, Exception> badNodes, Multimap<NodeMetadata, CustomizationResponse> customizationResponses) {
115      // ensure we don't mutate the input template
116      template = templateBuilderProvider.get().fromTemplate(template).build();
117      Iterable<? extends RunningInstance> started = createKeyPairAndSecurityGroupsAsNeededThenRunInstances(group,
118               count, template);
119 
120      Iterable<RegionAndName> ids = transform(started, instanceToRegionAndName);
121 
122      String idsString = Joiner.on(',').join(ids);
123      if (Iterables.size(ids) > 0) {
124         logger.debug("<< started instances(%s)", idsString);
125         all(ids, instancePresent);
126         logger.debug("<< present instances(%s)", idsString);
127         populateCredentials(started);
128      }
129 
130      return utils.customizeNodesAndAddToGoodMapOrPutExceptionIntoBadMap(template.getOptions(), transform(started,
131               runningInstanceToNodeMetadata), goodNodes, badNodes, customizationResponses);
132   }
133 
134   protected void populateCredentials(Iterable<? extends RunningInstance> started) {
135      Credentials credentials = null;
136      for (RunningInstance instance : started) {
137         credentials = instanceToCredentials.apply(instance);
138         if (credentials != null)
139            break;
140      }
141      if (credentials != null)
142         for (RunningInstance instance : started)
143            credentialStore.put("node#" + instance.getRegion() + "/" + instance.getId(), credentials);
144   }
145 
146   // TODO write test for this
147   protected Iterable<? extends RunningInstance> createKeyPairAndSecurityGroupsAsNeededThenRunInstances(String group,
148            int count, Template template) {
149      String region = AWSUtils.getRegionFromLocationOrNull(template.getLocation());
150      String zone = getZoneFromLocationOrNull(template.getLocation());
151      RunInstancesOptions instanceOptions = createKeyPairAndSecurityGroupsAsNeededAndReturncustomize.execute(region,
152               group, template);
153      return createNodesInRegionAndZone(region, zone, group, count, template, instanceOptions);
154   }
155 
156   protected Iterable<? extends RunningInstance> createNodesInRegionAndZone(String region, String zone, String group,
157            int count, Template template, RunInstancesOptions instanceOptions) {
158      int countStarted = 0;
159      int tries = 0;
160      Iterable<? extends RunningInstance> started = ImmutableSet.<RunningInstance> of();
161 
162      while (countStarted < count && tries++ < count) {
163         if (logger.isDebugEnabled())
164            logger.debug(">> running %d instance region(%s) zone(%s) ami(%s) params(%s)", count - countStarted, region,
165                     zone, template.getImage().getProviderId(), instanceOptions.buildFormParameters());
166 
167         started = Iterables.concat(started, client.getInstanceServices().runInstancesInRegion(region, zone,
168                  template.getImage().getProviderId(), 1, count - countStarted, instanceOptions));
169 
170         countStarted = Iterables.size(started);
171         if (countStarted < count)
172            logger.debug(">> not enough instances (%d/%d) started, attempting again", countStarted, count);
173      }
174      return started;
175   }
176 
177}

[all classes][org.jclouds.ec2.compute.strategy]
EMMA 2.0.5312 (C) Vladimir Roubtsov