EMMA Coverage Report (generated Wed Jun 22 19:47:49 EDT 2011)
[all classes][org.jclouds.vcloud.terremark.compute]

COVERAGE SUMMARY FOR SOURCE FILE [TerremarkVCloudComputeClient.java]

nameclass, %method, %block, %line, %
TerremarkVCloudComputeClient.java50%  (1/2)17%  (2/12)12%  (97/836)16%  (19.5/119)

COVERAGE BREAKDOWN BY CLASS AND METHOD

nameclass, %method, %block, %line, %
     
class TerremarkVCloudComputeClient$10%   (0/1)0%   (0/2)0%   (0/18)0%   (0/2)
TerremarkVCloudComputeClient$1 (TerremarkVCloudComputeClient): void 0%   (0/1)0%   (0/6)0%   (0/1)
apply (Task): boolean 0%   (0/1)0%   (0/12)0%   (0/1)
     
class TerremarkVCloudComputeClient100% (1/1)20%  (2/10)12%  (97/818)17%  (19.5/118)
blockOnLastTask (VCloudExpressVApp): void 0%   (0/1)0%   (0/45)0%   (0/7)
createPublicAddressMappedToPorts (URI, int []): String 0%   (0/1)0%   (0/220)0%   (0/25)
deleteInternetServicesAndNodesAssociatedWithVApp (VCloudExpressVApp): Set 0%   (0/1)0%   (0/157)0%   (0/17)
deletePublicIpAddressesWithNoServicesAttached (Set): void 0%   (0/1)0%   (0/67)0%   (0/12)
getPrivateAddresses (URI): Set 0%   (0/1)0%   (0/14)0%   (0/4)
getPublicAddresses (URI): Set 0%   (0/1)0%   (0/56)0%   (0/9)
powerOffAndWait (VCloudExpressVApp): void 0%   (0/1)0%   (0/50)0%   (0/5)
stop (URI): void 0%   (0/1)0%   (0/92)0%   (0/16)
start (URI, URI, String, InstantiateVAppTemplateOptions, int []): VCloudExpre... 100% (1/1)79%  (76/96)78%  (12.5/16)
TerremarkVCloudComputeClient (TerremarkVCloudClient, PopulateDefaultLoginCred... 100% (1/1)100% (21/21)100% (7/7)

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.vcloud.terremark.compute;
20 
21import static com.google.common.base.Preconditions.checkNotNull;
22import static com.google.common.collect.Iterables.filter;
23import static com.google.common.collect.Iterables.getLast;
24import static org.jclouds.vcloud.terremark.options.AddInternetServiceOptions.Builder.withDescription;
25 
26import java.net.URI;
27import java.util.Map;
28import java.util.NoSuchElementException;
29import java.util.Set;
30import java.util.Map.Entry;
31 
32import javax.annotation.Nullable;
33import javax.inject.Inject;
34import javax.inject.Named;
35import javax.inject.Provider;
36import javax.inject.Singleton;
37 
38import org.jclouds.compute.domain.NodeState;
39import org.jclouds.compute.strategy.PopulateDefaultLoginCredentialsForImageStrategy;
40import org.jclouds.domain.Credentials;
41import org.jclouds.vcloud.compute.internal.VCloudExpressComputeClientImpl;
42import org.jclouds.vcloud.domain.Status;
43import org.jclouds.vcloud.domain.Task;
44import org.jclouds.vcloud.domain.TaskStatus;
45import org.jclouds.vcloud.domain.TasksList;
46import org.jclouds.vcloud.domain.VCloudExpressVApp;
47import org.jclouds.vcloud.domain.VCloudExpressVAppTemplate;
48import org.jclouds.vcloud.options.InstantiateVAppTemplateOptions;
49import org.jclouds.vcloud.terremark.TerremarkVCloudClient;
50import org.jclouds.vcloud.terremark.domain.InternetService;
51import org.jclouds.vcloud.terremark.domain.Node;
52import org.jclouds.vcloud.terremark.domain.Protocol;
53import org.jclouds.vcloud.terremark.domain.PublicIpAddress;
54import org.jclouds.vcloud.terremark.options.TerremarkInstantiateVAppTemplateOptions;
55import org.jclouds.vcloud.terremark.suppliers.InternetServiceAndPublicIpAddressSupplier;
56 
57import com.google.common.base.Predicate;
58import com.google.common.collect.ImmutableSet;
59import com.google.common.collect.Sets;
60 
61/**
62 * @author Adrian Cole
63 */
64@Singleton
65public class TerremarkVCloudComputeClient extends VCloudExpressComputeClientImpl {
66 
67   protected final TerremarkVCloudClient client;
68   protected final PopulateDefaultLoginCredentialsForImageStrategy credentialsProvider;
69   protected final Provider<String> passwordGenerator;
70   protected final Map<String, Credentials> credentialStore;
71   protected final InternetServiceAndPublicIpAddressSupplier internetServiceAndPublicIpAddressSupplier;
72 
73   @Inject
74   protected TerremarkVCloudComputeClient(TerremarkVCloudClient client,
75            PopulateDefaultLoginCredentialsForImageStrategy credentialsProvider,
76            @Named("PASSWORD") Provider<String> passwordGenerator, Predicate<URI> successTester,
77            Map<Status, NodeState> vAppStatusToNodeState, Map<String, Credentials> credentialStore,
78            InternetServiceAndPublicIpAddressSupplier internetServiceAndPublicIpAddressSupplier) {
79      super(client, successTester, vAppStatusToNodeState);
80      this.client = client;
81      this.credentialsProvider = credentialsProvider;
82      this.passwordGenerator = passwordGenerator;
83      this.credentialStore = credentialStore;
84      this.internetServiceAndPublicIpAddressSupplier = internetServiceAndPublicIpAddressSupplier;
85   }
86 
87   @Override
88   public VCloudExpressVApp start(@Nullable URI VDC, URI templateId, String name,
89            InstantiateVAppTemplateOptions options, int... portsToOpen) {
90      if (options.getDiskSizeKilobytes() != null) {
91         logger.warn("trmk does not support resizing the primary disk; unsetting disk size");
92      }
93      // we only get IP addresses after "deploy"
94      if (portsToOpen.length > 0 && !options.shouldBlock())
95         throw new IllegalArgumentException("We cannot open ports on terremark unless we can deploy the vapp");
96      String password = null;
97      VCloudExpressVAppTemplate template = client.getVAppTemplate(templateId);
98      if (template.getDescription().indexOf("Windows") != -1
99               && options instanceof TerremarkInstantiateVAppTemplateOptions) {
100         password = passwordGenerator.get();
101         TerremarkInstantiateVAppTemplateOptions.class.cast(options).getProperties().put("password", password);
102      }
103      Credentials defaultCredentials = credentialsProvider.execute(template);
104 
105      VCloudExpressVApp vAppResponse = super.start(VDC, templateId, name, options, portsToOpen);
106      if (password != null) {
107         credentialStore.put("node#" + vAppResponse.getHref().toASCIIString(), new Credentials(
108                  defaultCredentials.identity, password));
109      }
110      if (portsToOpen.length > 0)
111         createPublicAddressMappedToPorts(vAppResponse.getHref(), portsToOpen);
112      return vAppResponse;
113   }
114 
115   public String createPublicAddressMappedToPorts(URI vAppId, int... ports) {
116      VCloudExpressVApp vApp = client.getVApp(vAppId);
117      PublicIpAddress ip = null;
118      String privateAddress = getLast(vApp.getNetworkToAddresses().values());
119      for (int port : ports) {
120         InternetService is = null;
121         Protocol protocol;
122         switch (port) {
123            case 22:
124               protocol = Protocol.TCP;
125               break;
126            case 80:
127            case 8080:
128               protocol = Protocol.HTTP;
129               break;
130            case 443:
131               protocol = Protocol.HTTPS;
132               break;
133            default:
134               protocol = Protocol.HTTP;
135               break;
136         }
137         if (ip == null) {
138 
139            Entry<InternetService, PublicIpAddress> entry = internetServiceAndPublicIpAddressSupplier
140                     .getNewInternetServiceAndIp(vApp, port, protocol);
141            is = entry.getKey();
142            ip = entry.getValue();
143 
144         } else {
145            logger.debug(">> adding InternetService %s:%s:%d", ip.getAddress(), protocol, port);
146            is = client.addInternetServiceToExistingIp(ip.getId(), vApp.getName() + "-" + port, protocol, port,
147                     withDescription(String.format("port %d access to serverId: %s name: %s", port, vApp.getName(),
148                              vApp.getName())));
149         }
150         logger.debug("<< created InternetService(%s) %s:%s:%d", is.getName(), is.getPublicIpAddress().getAddress(), is
151                  .getProtocol(), is.getPort());
152         logger.debug(">> adding Node %s:%d -> %s:%d", is.getPublicIpAddress().getAddress(), is.getPort(),
153                  privateAddress, port);
154         Node node = client.addNode(is.getId(), privateAddress, vApp.getName() + "-" + port, port);
155         logger.debug("<< added Node(%s)", node.getName());
156      }
157      return ip != null ? ip.getAddress() : null;
158   }
159 
160   private Set<PublicIpAddress> deleteInternetServicesAndNodesAssociatedWithVApp(VCloudExpressVApp vApp) {
161      checkNotNull(vApp.getVDC(), "VDC reference missing for vApp(%s)", vApp.getName());
162      Set<PublicIpAddress> ipAddresses = Sets.newHashSet();
163      SERVICE: for (InternetService service : client.getAllInternetServicesInVDC(vApp.getVDC().getHref())) {
164         for (Node node : client.getNodes(service.getId())) {
165            if (vApp.getNetworkToAddresses().containsValue(node.getIpAddress())) {
166               ipAddresses.add(service.getPublicIpAddress());
167               logger.debug(">> deleting Node(%s) %s:%d -> %s:%d", node.getName(), service.getPublicIpAddress()
168                        .getAddress(), service.getPort(), node.getIpAddress(), node.getPort());
169               client.deleteNode(node.getId());
170               logger.debug("<< deleted Node(%s)", node.getName());
171               Set<Node> nodes = client.getNodes(service.getId());
172               if (nodes.size() == 0) {
173                  logger.debug(">> deleting InternetService(%s) %s:%d", service.getName(), service.getPublicIpAddress()
174                           .getAddress(), service.getPort());
175                  client.deleteInternetService(service.getId());
176                  logger.debug("<< deleted InternetService(%s)", service.getName());
177                  continue SERVICE;
178               }
179            }
180         }
181      }
182      return ipAddresses;
183   }
184 
185   private void deletePublicIpAddressesWithNoServicesAttached(Set<PublicIpAddress> ipAddresses) {
186      IPADDRESS: for (PublicIpAddress address : ipAddresses) {
187         Set<InternetService> services = client.getInternetServicesOnPublicIp(address.getId());
188         if (services.size() == 0) {
189            logger.debug(">> deleting PublicIpAddress(%s) %s", address.getId(), address.getAddress());
190            try {
191               client.deletePublicIp(address.getId());
192               logger.debug("<< deleted PublicIpAddress(%s)", address.getId());
193            } catch (Exception e) {
194               logger.trace("cannot delete PublicIpAddress(%s) as it is unsupported", address.getId());
195            }
196            continue IPADDRESS;
197         }
198      }
199   }
200 
201   /**
202    * deletes the internet service and nodes associated with the vapp. Deletes the IP address, if
203    * there are no others using it. Finally, it powers off and deletes the vapp. Note that we do not
204    * call undeploy, as terremark does not support the command.
205    */
206   @Override
207   public void stop(URI id) {
208      VCloudExpressVApp vApp = client.getVApp(id);
209      Set<PublicIpAddress> ipAddresses = deleteInternetServicesAndNodesAssociatedWithVApp(vApp);
210      deletePublicIpAddressesWithNoServicesAttached(ipAddresses);
211      if (vApp.getStatus() != Status.OFF) {
212         try {
213            powerOffAndWait(vApp);
214         } catch (IllegalStateException e) {
215            logger.warn("<< %s vApp(%s)", e.getMessage(), vApp.getName());
216            blockOnLastTask(vApp);
217            powerOffAndWait(vApp);
218         }
219         vApp = client.getVApp(id);
220         logger.debug("<< %s vApp(%s)", vApp.getStatus(), vApp.getName());
221      }
222      logger.debug(">> deleting vApp(%s)", vApp.getName());
223      client.deleteVApp(id);
224      logger.debug("<< deleted vApp(%s))", vApp.getName());
225   }
226 
227   private void powerOffAndWait(VCloudExpressVApp vApp) {
228      logger.debug(">> powering off vApp(%s), current status: %s", vApp.getName(), vApp.getStatus());
229      Task task = client.powerOffVApp(vApp.getHref());
230      if (!taskTester.apply(task.getHref()))
231         throw new RuntimeException(String.format("failed to %s %s: %s", "powerOff", vApp.getName(), task));
232   }
233 
234   void blockOnLastTask(VCloudExpressVApp vApp) {
235      TasksList list = client.findTasksListInOrgNamed(null);
236      try {
237         Task lastTask = getLast(filter(list.getTasks(), new Predicate<Task>() {
238 
239            @Override
240            public boolean apply(Task input) {
241               return input.getStatus() == TaskStatus.QUEUED || input.getStatus() == TaskStatus.RUNNING;
242            }
243 
244         }));
245         if (!taskTester.apply(lastTask.getHref()))
246            throw new RuntimeException(String.format("failed to %s %s: %s", "powerOff", vApp.getName(), lastTask));
247      } catch (NoSuchElementException ex) {
248 
249      }
250   }
251 
252   /**
253    * @returns empty set if the node is not found
254    */
255   @Override
256   public Set<String> getPrivateAddresses(URI id) {
257      VCloudExpressVApp vApp = client.getVApp(id);
258      if (vApp != null)
259         return Sets.newHashSet(vApp.getNetworkToAddresses().values());
260      else
261         return ImmutableSet.<String> of();
262   }
263 
264   /**
265    * @returns empty set if the node is not found
266    */
267   @Override
268   public Set<String> getPublicAddresses(URI id) {
269      VCloudExpressVApp vApp = client.getVApp(id);
270      if (vApp != null) {
271         Set<String> ipAddresses = Sets.newHashSet();
272         for (InternetService service : client.getAllInternetServicesInVDC(vApp.getVDC().getHref())) {
273            for (Node node : client.getNodes(service.getId())) {
274               if (vApp.getNetworkToAddresses().containsValue(node.getIpAddress())) {
275                  ipAddresses.add(service.getPublicIpAddress().getAddress());
276               }
277            }
278         }
279         return ipAddresses;
280      } else {
281         return ImmutableSet.<String> of();
282      }
283   }
284}

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