EMMA Coverage Report (generated Fri Aug 26 14:14:05 EDT 2011)
[all classes][org.jclouds.ec2.compute]

COVERAGE SUMMARY FOR SOURCE FILE [EC2ComputeService.java]

nameclass, %method, %block, %line, %
EC2ComputeService.java0%   (0/4)0%   (0/13)0%   (0/390)0%   (0/45)

COVERAGE BREAKDOWN BY CLASS AND METHOD

nameclass, %method, %block, %line, %
     
class EC2ComputeService0%   (0/1)0%   (0/8)0%   (0/338)0%   (0/41)
EC2ComputeService (ComputeServiceContext, Map, Supplier, Supplier, Supplier, ... 0%   (0/1)0%   (0/35)0%   (0/5)
cleanUpIncidentalResources (Map$Entry): void 0%   (0/1)0%   (0/17)0%   (0/3)
deleteKeyPair (String, String): void 0%   (0/1)0%   (0/139)0%   (0/11)
deleteSecurityGroup (String, String): void 0%   (0/1)0%   (0/79)0%   (0/11)
destroyNodesMatching (Predicate): Set 0%   (0/1)0%   (0/48)0%   (0/8)
extractIdsFromInstances (Iterable): ImmutableSet 0%   (0/1)0%   (0/8)0%   (0/1)
templateOptions (): EC2TemplateOptions 0%   (0/1)0%   (0/6)0%   (0/1)
usingKeyPairAndNotDead (KeyPair): Predicate 0%   (0/1)0%   (0/6)0%   (0/1)
     
class EC2ComputeService$10%   (0/1)0%   (0/2)0%   (0/9)0%   (0/2)
EC2ComputeService$1 (EC2ComputeService): void 0%   (0/1)0%   (0/6)0%   (0/1)
apply (RunningInstance): String 0%   (0/1)0%   (0/3)0%   (0/1)
     
class EC2ComputeService$20%   (0/1)0%   (0/2)0%   (0/24)0%   (0/4)
EC2ComputeService$2 (EC2ComputeService, KeyPair): void 0%   (0/1)0%   (0/9)0%   (0/1)
apply (RunningInstance): boolean 0%   (0/1)0%   (0/15)0%   (0/3)
     
class EC2ComputeService$30%   (0/1)0%   (0/1)0%   (0/19)0%   (0/1)
<static initializer> 0%   (0/1)0%   (0/19)0%   (0/1)

1/**
2 *
3 * Copyright (C) 2011 Cloud Conscious, LLC. <info@cloudconscious.com>
4 *
5 * ====================================================================
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * 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, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 * ====================================================================
18 */
19package org.jclouds.ec2.compute;
20 
21import static com.google.common.collect.Iterables.concat;
22import static com.google.common.collect.Iterables.filter;
23import static com.google.common.collect.Iterables.transform;
24import static org.jclouds.util.Preconditions2.checkNotEmpty;
25 
26import java.util.Map;
27import java.util.Map.Entry;
28import java.util.Set;
29import java.util.concurrent.ExecutorService;
30 
31import javax.inject.Inject;
32import javax.inject.Named;
33import javax.inject.Provider;
34import javax.inject.Singleton;
35 
36import org.jclouds.Constants;
37import org.jclouds.aws.util.AWSUtils;
38import org.jclouds.collect.Memoized;
39import org.jclouds.compute.ComputeServiceContext;
40import org.jclouds.compute.callables.RunScriptOnNode;
41import org.jclouds.compute.domain.Hardware;
42import org.jclouds.compute.domain.Image;
43import org.jclouds.compute.domain.NodeMetadata;
44import org.jclouds.compute.domain.TemplateBuilder;
45import org.jclouds.compute.internal.BaseComputeService;
46import org.jclouds.compute.internal.PersistNodeCredentials;
47import org.jclouds.compute.options.TemplateOptions;
48import org.jclouds.compute.reference.ComputeServiceConstants.Timeouts;
49import org.jclouds.compute.strategy.CreateNodesInGroupThenAddToSet;
50import org.jclouds.compute.strategy.DestroyNodeStrategy;
51import org.jclouds.compute.strategy.GetNodeMetadataStrategy;
52import org.jclouds.compute.strategy.InitializeRunScriptOnNodeOrPlaceInBadMap;
53import org.jclouds.compute.strategy.ListNodesStrategy;
54import org.jclouds.compute.strategy.RebootNodeStrategy;
55import org.jclouds.compute.strategy.ResumeNodeStrategy;
56import org.jclouds.compute.strategy.SuspendNodeStrategy;
57import org.jclouds.domain.Credentials;
58import org.jclouds.domain.Location;
59import org.jclouds.ec2.EC2Client;
60import org.jclouds.ec2.compute.domain.RegionAndName;
61import org.jclouds.ec2.compute.domain.RegionNameAndIngressRules;
62import org.jclouds.ec2.compute.options.EC2TemplateOptions;
63import org.jclouds.ec2.domain.KeyPair;
64import org.jclouds.ec2.domain.RunningInstance;
65import org.jclouds.scriptbuilder.functions.InitAdminAccess;
66 
67import com.google.common.annotations.VisibleForTesting;
68import com.google.common.base.Function;
69import com.google.common.base.Predicate;
70import com.google.common.base.Supplier;
71import com.google.common.collect.ImmutableMultimap;
72import com.google.common.collect.ImmutableMultimap.Builder;
73import com.google.common.collect.ImmutableSet;
74 
75/**
76 * @author Adrian Cole
77 */
78@Singleton
79public class EC2ComputeService extends BaseComputeService {
80   private final EC2Client ec2Client;
81   private final Map<RegionAndName, KeyPair> credentialsMap;
82   private final Map<RegionAndName, String> securityGroupMap;
83 
84   @Inject
85   protected EC2ComputeService(ComputeServiceContext context, Map<String, Credentials> credentialStore,
86         @Memoized Supplier<Set<? extends Image>> images, @Memoized Supplier<Set<? extends Hardware>> sizes,
87         @Memoized Supplier<Set<? extends Location>> locations, ListNodesStrategy listNodesStrategy,
88         GetNodeMetadataStrategy getNodeMetadataStrategy, CreateNodesInGroupThenAddToSet runNodesAndAddToSetStrategy,
89         RebootNodeStrategy rebootNodeStrategy, DestroyNodeStrategy destroyNodeStrategy,
90         ResumeNodeStrategy startNodeStrategy, SuspendNodeStrategy stopNodeStrategy,
91         Provider<TemplateBuilder> templateBuilderProvider, Provider<TemplateOptions> templateOptionsProvider,
92         @Named("NODE_RUNNING") Predicate<NodeMetadata> nodeRunning,
93         @Named("NODE_TERMINATED") Predicate<NodeMetadata> nodeTerminated,
94         @Named("NODE_SUSPENDED") Predicate<NodeMetadata> nodeSuspended,
95         InitializeRunScriptOnNodeOrPlaceInBadMap.Factory initScriptRunnerFactory,
96         RunScriptOnNode.Factory runScriptOnNodeFactory, InitAdminAccess initAdminAccess,
97         PersistNodeCredentials persistNodeCredentials, Timeouts timeouts,
98         @Named(Constants.PROPERTY_USER_THREADS) ExecutorService executor, EC2Client ec2Client,
99         Map<RegionAndName, KeyPair> credentialsMap, @Named("SECURITY") Map<RegionAndName, String> securityGroupMap) {
100      super(context, credentialStore, images, sizes, locations, listNodesStrategy, getNodeMetadataStrategy,
101            runNodesAndAddToSetStrategy, rebootNodeStrategy, destroyNodeStrategy, startNodeStrategy, stopNodeStrategy,
102            templateBuilderProvider, templateOptionsProvider, nodeRunning, nodeTerminated, nodeSuspended,
103            initScriptRunnerFactory, initAdminAccess, runScriptOnNodeFactory, persistNodeCredentials, timeouts,
104            executor);
105      this.ec2Client = ec2Client;
106      this.credentialsMap = credentialsMap;
107      this.securityGroupMap = securityGroupMap;
108   }
109 
110   @VisibleForTesting
111   void deleteSecurityGroup(String region, String group) {
112      checkNotEmpty(group, "group");
113      String groupName = String.format("jclouds#%s#%s", group, region);
114      if (ec2Client.getSecurityGroupServices().describeSecurityGroupsInRegion(region, groupName).size() > 0) {
115         logger.debug(">> deleting securityGroup(%s)", groupName);
116         try {
117            ec2Client.getSecurityGroupServices().deleteSecurityGroupInRegion(region, groupName);
118            // TODO: test this clear happens
119            securityGroupMap.remove(new RegionNameAndIngressRules(region, groupName, null, false));
120            logger.debug("<< deleted securityGroup(%s)", groupName);
121         } catch (IllegalStateException e) {
122            logger.debug("<< inUse securityGroup(%s)", groupName);
123         }
124      }
125   }
126 
127   @VisibleForTesting
128   void deleteKeyPair(String region, String group) {
129      for (KeyPair keyPair : ec2Client.getKeyPairServices().describeKeyPairsInRegion(region)) {
130         if (
131         // when the keypair is unique per group
132         keyPair.getKeyName().equals("jclouds#" + group)
133               || keyPair.getKeyName().matches(String.format("jclouds#%s#%s", group, "[0-9a-f]+"))
134               // old keypair pattern too verbose as it has an unnecessary
135               // region qualifier
136               || keyPair.getKeyName().matches(String.format("jclouds#%s#%s#%s", group, region, "[0-9a-f]+"))) {
137            Set<String> instancesUsingKeyPair = extractIdsFromInstances(filter(concat(ec2Client.getInstanceServices()
138                  .describeInstancesInRegion(region)), usingKeyPairAndNotDead(keyPair)));
139            if (instancesUsingKeyPair.size() > 0) {
140               logger.debug("<< inUse keyPair(%s), by (%s)", keyPair.getKeyName(), instancesUsingKeyPair);
141            } else {
142               logger.debug(">> deleting keyPair(%s)", keyPair.getKeyName());
143               ec2Client.getKeyPairServices().deleteKeyPairInRegion(region, keyPair.getKeyName());
144               // TODO: test this clear happens
145               credentialsMap.remove(new RegionAndName(region, keyPair.getKeyName()));
146               logger.debug("<< deleted keyPair(%s)", keyPair.getKeyName());
147            }
148         }
149      }
150   }
151 
152   protected ImmutableSet<String> extractIdsFromInstances(Iterable<? extends RunningInstance> deadOnes) {
153      return ImmutableSet.copyOf(transform(deadOnes, new Function<RunningInstance, String>() {
154 
155         @Override
156         public String apply(RunningInstance input) {
157            return input.getId();
158         }
159 
160      }));
161   }
162 
163   protected Predicate<RunningInstance> usingKeyPairAndNotDead(final KeyPair keyPair) {
164      return new Predicate<RunningInstance>() {
165 
166         @Override
167         public boolean apply(RunningInstance input) {
168            switch (input.getInstanceState()) {
169            case TERMINATED:
170            case SHUTTING_DOWN:
171               return false;
172            }
173            return keyPair.getKeyName().equals(input.getKeyName());
174         }
175 
176      };
177   }
178 
179   /**
180    * like {@link BaseComputeService#destroyNodesMatching} except that this will
181    * clean implicit keypairs and security groups.
182    */
183   @Override
184   public Set<? extends NodeMetadata> destroyNodesMatching(Predicate<NodeMetadata> filter) {
185      Set<? extends NodeMetadata> deadOnes = super.destroyNodesMatching(filter);
186      Builder<String, String> regionGroups = ImmutableMultimap.<String, String> builder();
187      for (NodeMetadata nodeMetadata : deadOnes) {
188         if (nodeMetadata.getGroup() != null)
189            regionGroups.put(AWSUtils.parseHandle(nodeMetadata.getId())[0], nodeMetadata.getGroup());
190      }
191      for (Entry<String, String> regionGroup : regionGroups.build().entries()) {
192         cleanUpIncidentalResources(regionGroup);
193      }
194      return deadOnes;
195   }
196 
197   protected void cleanUpIncidentalResources(Entry<String, String> regionGroup) {
198      deleteKeyPair(regionGroup.getKey(), regionGroup.getValue());
199      deleteSecurityGroup(regionGroup.getKey(), regionGroup.getValue());
200   }
201 
202   /**
203    * returns template options, except of type {@link EC2TemplateOptions}.
204    */
205   @Override
206   public EC2TemplateOptions templateOptions() {
207      return EC2TemplateOptions.class.cast(super.templateOptions());
208   }
209 
210}

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