blob: 1524eeb4cf3b47f9343736db160032e096a5faca [file] [log] [blame]
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.vcloud.compute.strategy;
import static com.google.common.base.Preconditions.checkNotNull;
import java.net.URI;
import java.util.Map;
import java.util.Set;
import javax.annotation.Resource;
import javax.inject.Inject;
import javax.inject.Named;
import javax.inject.Singleton;
import org.jclouds.compute.ComputeService;
import org.jclouds.compute.ComputeServiceAdapter;
import org.jclouds.compute.domain.Template;
import org.jclouds.compute.reference.ComputeServiceConstants;
import org.jclouds.domain.Location;
import org.jclouds.logging.Logger;
import org.jclouds.vcloud.VCloudClient;
import org.jclouds.vcloud.VCloudMediaType;
import org.jclouds.vcloud.compute.suppliers.OrgAndVDCToLocationSupplier;
import org.jclouds.vcloud.domain.Org;
import org.jclouds.vcloud.domain.ReferenceType;
import org.jclouds.vcloud.domain.Status;
import org.jclouds.vcloud.domain.Task;
import org.jclouds.vcloud.domain.VApp;
import org.jclouds.vcloud.domain.VAppTemplate;
import org.jclouds.vcloud.suppliers.VAppTemplatesSupplier;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Predicate;
import com.google.common.base.Supplier;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.ImmutableSet.Builder;
/**
* defines the connection between the {@link VCloudClient} implementation and the jclouds
* {@link ComputeService}
*
*/
@Singleton
public class VCloudComputeServiceAdapter implements ComputeServiceAdapter<VApp, VAppTemplate, VAppTemplate, Location> {
@Resource
@Named(ComputeServiceConstants.COMPUTE_LOGGER)
protected Logger logger = Logger.NULL;
protected final VCloudClient client;
protected final Predicate<URI> successTester;
protected final InstantiateVAppTemplateWithGroupEncodedIntoNameThenCustomizeDeployAndPowerOn booter;
protected final Supplier<Map<String, Org>> nameToOrg;
protected final Supplier<Set<VAppTemplate>> templates;
protected final Supplier<Set<? extends Location>> locations;
@Inject
protected VCloudComputeServiceAdapter(VCloudClient client, Predicate<URI> successTester,
InstantiateVAppTemplateWithGroupEncodedIntoNameThenCustomizeDeployAndPowerOn booter,
Supplier<Map<String, Org>> nameToOrg, VAppTemplatesSupplier templates,
OrgAndVDCToLocationSupplier locations) {
this.client = checkNotNull(client, "client");
this.successTester = checkNotNull(successTester, "successTester");
this.booter = checkNotNull(booter, "booter");
this.nameToOrg = checkNotNull(nameToOrg, "nameToOrg");
this.templates = checkNotNull(templates, "templates");
this.locations = checkNotNull(locations, "locations");
}
@Override
public NodeAndInitialCredentials<VApp> createNodeWithGroupEncodedIntoName(String group, String name,
Template template) {
return booter.createNodeWithGroupEncodedIntoName(group, name, template);
}
@Override
public Iterable<VAppTemplate> listHardwareProfiles() {
return templates.get();
}
@Override
public Iterable<VAppTemplate> listImages() {
return templates.get();
}
@Override
public Iterable<VApp> listNodes() {
// TODO: parallel or cache
Builder<VApp> nodes = ImmutableSet.<VApp> builder();
for (Org org : nameToOrg.get().values()) {
for (ReferenceType vdc : org.getVDCs().values()) {
for (ReferenceType resource : client.getVDCClient().getVDC(vdc.getHref()).getResourceEntities().values()) {
if (resource.getType().equals(VCloudMediaType.VAPP_XML)) {
addVAppToSetRetryingIfNotYetPresent(nodes, vdc, resource);
}
}
}
}
return nodes.build();
}
@VisibleForTesting
void addVAppToSetRetryingIfNotYetPresent(Builder<VApp> nodes, ReferenceType vdc, ReferenceType resource) {
VApp node = null;
int i = 0;
while (node == null && i++ < 3) {
try {
node = client.getVAppClient().getVApp(resource.getHref());
nodes.add(node);
} catch (NullPointerException e) {
logger.warn("vApp %s not yet present in vdc %s", resource.getName(), vdc.getName());
}
}
}
@SuppressWarnings("unchecked")
@Override
public Iterable<Location> listLocations() {
return (Iterable<Location>) locations.get();
}
@Override
public VApp getNode(String in) {
URI id = URI.create(in);
return client.getVAppClient().getVApp(id);
}
@Override
public void destroyNode(String id) {
URI vappId = URI.create(checkNotNull(id, "node.id"));
VApp vApp = client.getVAppClient().getVApp(vappId);
waitForPendingTasksToComplete(vApp);
vApp = undeployVAppIfDeployed(vApp);
deleteVApp(vApp);
}
void waitForPendingTasksToComplete(VApp vApp) {
for (Task task : vApp.getTasks())
waitForTask(task, vApp);
}
public void waitForTask(Task task, VApp vAppResponse) {
if (!successTester.apply(task.getHref())) {
throw new RuntimeException(String.format("failed to %s %s: %s", task.getName(), vAppResponse.getName(), task));
}
}
void deleteVApp(VApp vApp) {
logger.debug(">> deleting vApp(%s)", vApp.getHref());
waitForTask(client.getVAppClient().deleteVApp(vApp.getHref()), vApp);
logger.debug("<< deleted vApp(%s)", vApp.getHref());
}
VApp undeployVAppIfDeployed(VApp vApp) {
if (vApp.getStatus() != Status.OFF) {
logger.debug(">> undeploying vApp(%s), current status: %s", vApp.getName(), vApp.getStatus());
try {
waitForTask(client.getVAppClient().undeployVApp(vApp.getHref()), vApp);
vApp = client.getVAppClient().getVApp(vApp.getHref());
logger.debug("<< %s vApp(%s)", vApp.getStatus(), vApp.getName());
} catch (IllegalStateException e) {
logger.warn(e, "<< %s vApp(%s)", vApp.getStatus(), vApp.getName());
}
}
return vApp;
}
@Override
public void rebootNode(String in) {
URI id = URI.create(checkNotNull(in, "node.id"));
Task task = client.getVAppClient().resetVApp(id);
successTester.apply(task.getHref());
}
@Override
public void resumeNode(String in) {
URI id = URI.create(checkNotNull(in, "node.id"));
Task task = client.getVAppClient().powerOnVApp(id);
successTester.apply(task.getHref());
}
@Override
public void suspendNode(String in) {
URI id = URI.create(checkNotNull(in, "node.id"));
Task task = client.getVAppClient().powerOffVApp(id);
successTester.apply(task.getHref());
}
}