Issue 112: missed files from last commit

git-svn-id: http://jclouds.googlecode.com/svn/trunk@2713 3d8758e0-26b5-11de-8745-db77d3ebf521
This commit is contained in:
adrian.f.cole 2010-01-21 08:14:35 +00:00
parent cb906ded3c
commit bc1c1fd793
7 changed files with 1128 additions and 0 deletions

View File

@ -0,0 +1,96 @@
/**
*
* Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed 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;
import java.net.InetAddress;
import java.util.Map;
import java.util.Set;
import javax.annotation.Nullable;
/**
*
* @author Adrian Cole
*/
public interface VCloudComputeClient {
/**
* Runs through all commands necessary to startup a vApp, opening at least one ip address to the
* public network. These are the steps:
* <p/>
* instantiate -> deploy -> powerOn
* <p/>
* This command blocks until the vApp is in state {@code VAppStatus#ON}
*
* @param vDCId
* id of the virtual datacenter {@code VCloudClient#getDefaultVDC}
* @param name
* name of the vApp
* @param templateId
* id of the vAppTemplate you wish to instantiate
* @param cores
* amount of virtual cpu cores
* @param megs
* amount of ram in megabytes
* @param diskSizeKilobytes
* size of disk in kilobytes, null is ok
* @param properties
* sets product properties on the vApp
* @param portsToOpen
* opens the following ports on the public ip address
* @return map contains at least the following properties
* <ol>
* <li>id - vApp id</li> <li>username - console login user</li> <li>password - console
* login password</li>
* </ol>
*/
Map<String, String> start(String vDCId, String name, String templateId, int cores, int megs,
@Nullable Long diskSizeKilobytes, Map<String, String> properties, int... portsToOpen);
/**
* returns a set of addresses that are only visible to the private network.
*/
Set<InetAddress> getPrivateAddresses(String vAppId);
/**
* returns a set of addresses that are publically visible
*/
Set<InetAddress> getPublicAddresses(String vAppId);
/**
* reboots the vApp, blocking until the following state transition is complete:
* <p/>
* current -> {@code VAppStatus#OFF} -> {@code VAppStatus#ON}
*
* @param vAppId
* vApp to reboot
*/
void reboot(String vAppId);
/**
* Destroys dependent resources, powers off and deletes the vApp, blocking until the following
* state transition is complete:
* <p/>
* current -> {@code VAppStatus#OFF} -> deleted
*
* @param vAppId
* vApp to stop
*/
void stop(String vAppId);
}

View File

@ -0,0 +1,338 @@
/**
*
* Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed 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;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState;
import static org.jclouds.vcloud.options.InstantiateVAppTemplateOptions.Builder.processorCount;
import java.io.ByteArrayInputStream;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.util.Map;
import java.util.Set;
import java.util.SortedSet;
import javax.annotation.Resource;
import javax.inject.Named;
import javax.inject.Provider;
import javax.inject.Singleton;
import org.jclouds.compute.ComputeService;
import org.jclouds.compute.domain.ComputeMetadata;
import org.jclouds.compute.domain.ComputeType;
import org.jclouds.compute.domain.CreateNodeResponse;
import org.jclouds.compute.domain.Image;
import org.jclouds.compute.domain.LoginType;
import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.domain.NodeState;
import org.jclouds.compute.domain.Size;
import org.jclouds.compute.domain.Template;
import org.jclouds.compute.domain.internal.CreateNodeResponseImpl;
import org.jclouds.compute.domain.internal.NodeMetadataImpl;
import org.jclouds.compute.options.RunNodeOptions;
import org.jclouds.compute.reference.ComputeServiceConstants;
import org.jclouds.domain.Credentials;
import org.jclouds.logging.Logger;
import org.jclouds.ssh.SshClient;
import org.jclouds.vcloud.VCloudClient;
import org.jclouds.vcloud.VCloudMediaType;
import org.jclouds.vcloud.domain.NamedResource;
import org.jclouds.vcloud.domain.Task;
import org.jclouds.vcloud.domain.VApp;
import org.jclouds.vcloud.domain.VAppStatus;
import org.jclouds.vcloud.options.InstantiateVAppTemplateOptions;
import com.google.common.base.Predicate;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Sets;
import com.google.inject.Inject;
/**
* @author Adrian Cole
*/
@Singleton
public class VCloudComputeService implements ComputeService, VCloudComputeClient {
@Resource
@Named(ComputeServiceConstants.COMPUTE_LOGGER)
protected Logger logger = Logger.NULL;
private final VCloudClient client;
protected final Provider<Set<? extends Image>> images;
protected final Provider<SortedSet<? extends Size>> sizes;
private final Provider<Set<? extends VCloudTemplate>> templates;
@Inject(optional = true)
private SshClient.Factory sshFactory;
private Predicate<InetSocketAddress> socketTester;
protected static final Map<VAppStatus, NodeState> vAppStatusToNodeState = ImmutableMap
.<VAppStatus, NodeState> builder().put(VAppStatus.OFF, NodeState.TERMINATED).put(
VAppStatus.ON, NodeState.RUNNING).put(VAppStatus.RESOLVED, NodeState.PENDING)
.put(VAppStatus.SUSPENDED, NodeState.SUSPENDED).put(VAppStatus.UNRESOLVED,
NodeState.PENDING).build();
@Inject
public VCloudComputeService(VCloudClient client, Provider<Set<? extends Image>> images,
Provider<SortedSet<? extends Size>> sizes,
Provider<Set<? extends VCloudTemplate>> templates, Predicate<String> successTester,
Predicate<InetSocketAddress> socketTester) {
this.taskTester = successTester;
this.client = client;
this.images = images;
this.sizes = sizes;
this.templates = templates;
this.socketTester = socketTester;
}
@Override
public CreateNodeResponse runNode(String name, Template template) {
return this.runNode(name, template, RunNodeOptions.NONE);
}
@Override
public CreateNodeResponse runNode(String name, Template template, RunNodeOptions options) {
checkNotNull(template.getImage().getLocation(), "location");
Map<String, String> metaMap = start(template.getImage().getLocation(), name, template
.getImage().getId(), template.getSize().getCores(), template.getSize().getRam(),
template.getSize().getDisk() * 1024 * 1024l, ImmutableMap.<String, String> of(),
options.getOpenPorts());
VApp vApp = client.getVApp(metaMap.get("id"));
CreateNodeResponse node = newCreateNodeResponse(template, metaMap, vApp);
if (options.getRunScript() != null) {
checkState(this.sshFactory != null, "runScript requested, but no SshModule configured");
runScriptOnNode(node, options.getRunScript());
}
return node;
}
private void runScriptOnNode(CreateNodeResponse node, byte[] script) {
InetSocketAddress socket = new InetSocketAddress(node.getPublicAddresses().last(), node
.getLoginPort());
socketTester.apply(socket);
SshClient ssh = isKeyBasedAuth(node) ? sshFactory.create(socket,
node.getCredentials().account, node.getCredentials().key.getBytes()) : sshFactory
.create(socket, node.getCredentials().account, node.getCredentials().key);
try {
ssh.connect();
String scriptName = node.getId() + ".sh";
ssh.put(scriptName, new ByteArrayInputStream(script));
ssh.exec("chmod 755 " + scriptName);
if (node.getCredentials().account.equals("root")) {
logger.debug(ssh.exec("./" + scriptName).toString());
} else if (isKeyBasedAuth(node)) {
logger.debug(ssh.exec("sudo ./" + scriptName).toString());
} else {
logger.debug(ssh.exec(
String.format("echo %s|sudo -S ./%s", node.getCredentials().key, scriptName))
.toString());
}
} finally {
if (ssh != null)
ssh.disconnect();
}
}
private boolean isKeyBasedAuth(CreateNodeResponse node) {
return node.getCredentials().key.startsWith("-----BEGIN RSA PRIVATE KEY-----");
}
protected CreateNodeResponse newCreateNodeResponse(Template template,
Map<String, String> metaMap, VApp vApp) {
return new CreateNodeResponseImpl(vApp.getId(), vApp.getName(), template.getImage()
.getLocation(), vApp.getLocation(), ImmutableMap.<String, String> of(),
vAppStatusToNodeState.get(vApp.getStatus()), getPublicAddresses(vApp.getId()),
getPrivateAddresses(vApp.getId()), 22, LoginType.SSH, new Credentials(metaMap
.get("username"), metaMap.get("password")), ImmutableMap
.<String, String> of());
}
@Override
public NodeMetadata getNodeMetadata(ComputeMetadata node) {
checkArgument(node.getType() == ComputeType.NODE, "this is only valid for nodes, not "
+ node.getType());
return getNodeMetadataByIdInVDC(checkNotNull(node.getLocation(), "location"), checkNotNull(
node.getId(), "node.id"));
}
private NodeMetadata getNodeMetadataByIdInVDC(String vDCId, String id) {
VApp vApp = client.getVApp(id);
return new NodeMetadataImpl(vApp.getId(), vApp.getName(), vDCId, vApp.getLocation(),
ImmutableMap.<String, String> of(), vAppStatusToNodeState.get(vApp.getStatus()),
vApp.getNetworkToAddresses().values(), ImmutableSet.<InetAddress> of(), 22,
LoginType.SSH, ImmutableMap.<String, String> of());
}
@Override
public Set<ComputeMetadata> listNodes() {
Set<ComputeMetadata> nodes = Sets.newHashSet();
for (NamedResource vdc : client.getDefaultOrganization().getVDCs().values()) {
for (NamedResource resource : client.getVDC(vdc.getId()).getResourceEntities().values()) {
if (resource.getType().equals(VCloudMediaType.VAPP_XML)) {
nodes.add(getNodeMetadataByIdInVDC(vdc.getId(), resource.getId()));
}
}
}
return nodes;
}
@Override
public void destroyNode(ComputeMetadata node) {
checkArgument(node.getType() == ComputeType.NODE, "this is only valid for nodes, not "
+ node.getType());
stop(checkNotNull(node.getId(), "node.id"));
}
@Override
public Template createTemplateInLocation(String location) {
return new VCloudTemplate(client, images.get(), sizes.get(), location);
}
@Override
public SortedSet<? extends Size> listSizes() {
return sizes.get();
}
@Override
public Set<? extends Template> listTemplates() {
return templates.get();
}
private final Predicate<String> taskTester;
public Map<String, String> start(String vDCId, String name, String templateId, int minCores,
int minMegs, Long diskSize, Map<String, String> properties, int... portsToOpen) {
logger
.debug(
">> instantiating vApp vDC(%s) name(%s) template(%s) minCores(%d) minMegs(%d) diskSize(%d) properties(%s) ",
vDCId, name, templateId, minCores, minMegs, diskSize, properties);
InstantiateVAppTemplateOptions options = processorCount(minCores).memory(minMegs)
.productProperties(properties);
if (diskSize != null)
options.disk(diskSize);
VApp vAppResponse = client.instantiateVAppTemplateInVDC(vDCId, name, templateId, options);
logger.debug("<< instantiated VApp(%s)", vAppResponse.getId());
logger.debug(">> deploying vApp(%s)", vAppResponse.getId());
VApp vApp = blockUntilVAppStatusOrThrowException(vAppResponse, client.deployVApp(vAppResponse
.getId()), "deploy", ImmutableSet.of(VAppStatus.OFF, VAppStatus.ON));
logger.debug("<< deployed vApp(%s)", vApp.getId());
logger.debug(">> powering vApp(%s)", vApp.getId());
vApp = blockUntilVAppStatusOrThrowException(vApp, client.powerOnVApp(vApp.getId()),
"powerOn", ImmutableSet.of(VAppStatus.ON));
logger.debug("<< on vApp(%s)", vApp.getId());
Map<String, String> response = parseResponse(vAppResponse);
checkState(response.containsKey("id"), "bad configuration: [id] should be in response");
checkState(response.containsKey("username"),
"bad configuration: [username] should be in response");
checkState(response.containsKey("password"),
"bad configuration: [password] should be in response");
return response;
}
protected Map<String, String> parseResponse(VApp vAppResponse) {
return ImmutableMap.<String, String> of("id", vAppResponse.getId(), "username", "",
"password", "");
}
public void reboot(String id) {
VApp vApp = client.getVApp(id);
logger.debug(">> rebooting vApp(%s)", vApp.getId());
blockUntilVAppStatusOrThrowException(vApp, client.resetVApp(vApp.getId()), "reset",
ImmutableSet.of(VAppStatus.ON));
logger.debug("<< on vApp(%s)", vApp.getId());
}
public void stop(String id) {
VApp vApp = client.getVApp(id);
if (vApp.getStatus() != VAppStatus.OFF) {
logger.debug(">> powering off vApp(%s), current status: %s", vApp.getId(), vApp
.getStatus());
blockUntilVAppStatusOrThrowException(vApp, client.powerOffVApp(vApp.getId()), "powerOff",
ImmutableSet.of(VAppStatus.OFF));
logger.debug("<< off vApp(%s)", vApp.getId());
}
logger.debug(">> deleting vApp(%s)", vApp.getId());
client.deleteVApp(id);
logger.debug("<< deleted vApp(%s)", vApp.getId());
}
private VApp blockUntilVAppStatusOrThrowException(VApp vApp, Task deployTask, String taskType,
Set<VAppStatus> acceptableStatuses) {
if (!taskTester.apply(deployTask.getId())) {
throw new TaskException(taskType, vApp, deployTask);
}
vApp = client.getVApp(vApp.getId());
if (!acceptableStatuses.contains(vApp.getStatus())) {
throw new VAppException(String.format("vApp %s status %s should be %s after %s", vApp
.getId(), vApp.getStatus(), acceptableStatuses, taskType), vApp);
}
return vApp;
}
public static class TaskException extends VAppException {
private final Task task;
/** The serialVersionUID */
private static final long serialVersionUID = 251801929573211256L;
public TaskException(String type, VApp vApp, Task task) {
super(String.format("failed to %s vApp %s status %s;task %s status %s", type,
vApp.getId(), vApp.getStatus(), task.getLocation(), task.getStatus()), vApp);
this.task = task;
}
public Task getTask() {
return task;
}
}
public static class VAppException extends RuntimeException {
private final VApp vApp;
/** The serialVersionUID */
private static final long serialVersionUID = 251801929573211256L;
public VAppException(String message, VApp vApp) {
super(message);
this.vApp = vApp;
}
public VApp getvApp() {
return vApp;
}
}
@Override
public Set<InetAddress> getPrivateAddresses(String id) {
return ImmutableSet.of();
}
@Override
public Set<InetAddress> getPublicAddresses(String id) {
VApp vApp = client.getVApp(id);
return Sets.newHashSet(vApp.getNetworkToAddresses().values());
}
}

View File

@ -0,0 +1,92 @@
/**
*
* Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed 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;
import java.util.List;
import java.util.Properties;
import java.util.concurrent.ExecutorService;
import org.jclouds.compute.ComputeServiceContext;
import org.jclouds.compute.ComputeServiceContextBuilder;
import org.jclouds.compute.internal.ComputeServiceContextImpl;
import org.jclouds.http.config.JavaUrlHttpCommandExecutorServiceModule;
import org.jclouds.logging.jdk.config.JDKLoggingModule;
import org.jclouds.vcloud.VCloudAsyncClient;
import org.jclouds.vcloud.VCloudClient;
import org.jclouds.vcloud.compute.config.VCloudComputeServiceContextModule;
import org.jclouds.vcloud.config.VCloudRestClientModule;
import com.google.inject.Injector;
import com.google.inject.Key;
import com.google.inject.Module;
import com.google.inject.TypeLiteral;
/**
* Creates {@link VCloudComputeServiceContext} or {@link Injector} instances based on the most
* commonly requested arguments.
* <p/>
* Note that Threadsafe objects will be bound as singletons to the Injector or Context provided.
* <p/>
* <p/>
* If no <code>Module</code>s are specified, the default {@link JDKLoggingModule logging} and
* {@link JavaUrlHttpCommandExecutorServiceModule http transports} will be installed.
*
* @author Adrian Cole
* @see VCloudComputeServiceContext
*/
public class VCloudComputeServiceContextBuilder extends
ComputeServiceContextBuilder<VCloudAsyncClient, VCloudClient> {
public VCloudComputeServiceContextBuilder(Properties props) {
super(new TypeLiteral<VCloudAsyncClient>() {
}, new TypeLiteral<VCloudClient>() {
}, props);
}
@Override
public VCloudComputeServiceContextBuilder withExecutorService(ExecutorService service) {
return (VCloudComputeServiceContextBuilder) super.withExecutorService(service);
}
@Override
public VCloudComputeServiceContextBuilder withModules(Module... modules) {
return (VCloudComputeServiceContextBuilder) super.withModules(modules);
}
@Override
protected void addContextModule(List<Module> modules) {
modules.add(new VCloudComputeServiceContextModule());
}
@Override
protected void addClientModule(List<Module> modules) {
modules.add(new VCloudRestClientModule());
}
@Override
public ComputeServiceContext buildComputeServiceContext() {
// need the generic type information
return (ComputeServiceContext) this
.buildInjector()
.getInstance(
Key
.get(new TypeLiteral<ComputeServiceContextImpl<VCloudAsyncClient, VCloudClient>>() {
}));
}
}

View File

@ -0,0 +1,64 @@
/**
*
* Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed 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;
import java.net.URI;
import java.util.Properties;
import org.jclouds.compute.ComputeServiceContext;
import org.jclouds.http.config.JavaUrlHttpCommandExecutorServiceModule;
import org.jclouds.logging.jdk.config.JDKLoggingModule;
import org.jclouds.vcloud.VCloudPropertiesBuilder;
import com.google.inject.Module;
/**
* Creates {@link VCloudComputeServiceContext} instances based on the most commonly
* requested arguments.
* <p/>
* Note that Threadsafe objects will be bound as singletons to the Injector or Context provided.
* <p/>
* <p/>
* If no <code>Module</code>s are specified, the default {@link JDKLoggingModule logging} and
* {@link JavaUrlHttpCommandExecutorServiceModule http transports} will be installed.
*
* @author Adrian Cole
* @see VCloudComputeServiceContext
*/
public class VCloudComputeServiceContextFactory {
public static ComputeServiceContext createContext(Properties properties, Module... modules) {
return new VCloudComputeServiceContextBuilder(
new VCloudPropertiesBuilder(properties).build()).withModules(modules)
.buildComputeServiceContext();
}
public static ComputeServiceContext createContext(Properties properties, String user,
String key, Module... modules) {
return new VCloudComputeServiceContextBuilder(
new VCloudPropertiesBuilder(properties).withCredentials(user, key)
.build()).withModules(modules).buildComputeServiceContext();
}
public static ComputeServiceContext createContext(URI endpoint, String user, String key,
Module... modules) {
return new VCloudComputeServiceContextBuilder(
new VCloudPropertiesBuilder(endpoint, user, key).withEndpoint(endpoint).build())
.withModules(modules).buildComputeServiceContext();
}
}

View File

@ -0,0 +1,180 @@
package org.jclouds.vcloud.compute;
import java.util.Set;
import javax.annotation.Nullable;
import org.jclouds.compute.domain.Image;
import org.jclouds.compute.domain.OperatingSystem;
import org.jclouds.compute.domain.Size;
import org.jclouds.compute.domain.Template;
import org.jclouds.vcloud.VCloudClient;
import com.google.common.collect.Iterables;
/**
*
* @author Adrian Cole
*/
public class VCloudTemplate implements Template {
private final VCloudClient client;
private final Set<? extends Image> images;
private final Set<? extends Size> sizes;
private Size size;
private String vDC;
private OperatingSystem operatingSystem;
private transient Image image;
public VCloudTemplate(VCloudClient client,
Set<? extends Image> images, Set<? extends Size> sizes, String location,
@Nullable Size size, OperatingSystem operatingSystem, @Nullable Image image) {
this.client = client;
this.images = images;
this.sizes = sizes;
this.vDC = location;
this.image = image != null ? image : resolveTemplate(images, operatingSystem);
this.size = size != null ? size : Iterables.get(sizes, 0);
this.operatingSystem = operatingSystem;
}
private Image resolveTemplate(Set<? extends Image> images, OperatingSystem operatingSystem) {
for (Image image : images) {
if (image.getOperatingSystem() == operatingSystem)
return image;
}
throw new RuntimeException("no configured image matches os: " + operatingSystem);
}
VCloudTemplate(VCloudClient client, Set<? extends Image> images,
Set<? extends Size> sizes, String location) {
this(client, images, sizes, location, null, OperatingSystem.CENTOS, null);// note the default
// os
}
/**
* {@inheritDoc}
*/
@Override
public Size getSize() {
return size;
}
/**
* {@inheritDoc}
*/
@Override
public Image getImage() {
return image;
}
/**
* {@inheritDoc}
*/
@Override
public Template smallest() {
this.size = Iterables.get(sizes, 0);
return this;
}
/**
* {@inheritDoc}
*/
@Override
public Template biggest() {
this.size = Iterables.getLast(sizes);
return this;
}
/**
* {@inheritDoc}
*/
@Override
public Template fastest() {
this.size = Iterables.getLast(sizes);
return this;
}
/**
* {@inheritDoc}
*/
@Override
public Template inLocation(String location) {
if (location.equalsIgnoreCase("default"))
location = client.getDefaultVDC().getId();
this.vDC = location;// TODO match vdc on template as well arch
return this;
}
/**
* {@inheritDoc}
*/
@Override
public Template os(OperatingSystem os) {
this.operatingSystem = os;
this.image = resolveTemplate(images, operatingSystem);
return this;
}
/**
* {@inheritDoc}
*/
@Override
protected Object clone() throws CloneNotSupportedException {
return new VCloudTemplate(client, images, sizes, vDC, size, operatingSystem,
image);
}
public String getvDC() {
return vDC;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((image == null) ? 0 : image.hashCode());
result = prime * result + ((operatingSystem == null) ? 0 : operatingSystem.hashCode());
result = prime * result + ((size == null) ? 0 : size.hashCode());
result = prime * result + ((vDC == null) ? 0 : vDC.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
VCloudTemplate other = (VCloudTemplate) obj;
if (image == null) {
if (other.image != null)
return false;
} else if (!image.equals(other.image))
return false;
if (operatingSystem == null) {
if (other.operatingSystem != null)
return false;
} else if (!operatingSystem.equals(other.operatingSystem))
return false;
if (size == null) {
if (other.size != null)
return false;
} else if (!size.equals(other.size))
return false;
if (vDC == null) {
if (other.vDC != null)
return false;
} else if (!vDC.equals(other.vDC))
return false;
return true;
}
@Override
public String toString() {
return "VCloudTemplate [image=" + image + ", operatingSystem=" + operatingSystem
+ ", size=" + size + ", vDC=" + vDC + "]";
}
}

View File

@ -0,0 +1,199 @@
/**
*
* Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed 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.config;
import java.util.Set;
import java.util.SortedSet;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import javax.annotation.Resource;
import javax.inject.Named;
import javax.inject.Singleton;
import org.jclouds.compute.ComputeService;
import org.jclouds.compute.ComputeServiceContext;
import org.jclouds.compute.domain.Architecture;
import org.jclouds.compute.domain.Image;
import org.jclouds.compute.domain.OperatingSystem;
import org.jclouds.compute.domain.Size;
import org.jclouds.compute.domain.internal.ImageImpl;
import org.jclouds.compute.domain.internal.SizeImpl;
import org.jclouds.compute.internal.ComputeServiceContextImpl;
import org.jclouds.compute.reference.ComputeServiceConstants;
import org.jclouds.logging.Logger;
import org.jclouds.rest.RestContext;
import org.jclouds.vcloud.VCloudAsyncClient;
import org.jclouds.vcloud.VCloudClient;
import org.jclouds.vcloud.VCloudMediaType;
import org.jclouds.vcloud.compute.VCloudComputeClient;
import org.jclouds.vcloud.compute.VCloudComputeService;
import org.jclouds.vcloud.compute.VCloudTemplate;
import org.jclouds.vcloud.config.VCloudContextModule;
import org.jclouds.vcloud.domain.Catalog;
import org.jclouds.vcloud.domain.CatalogItem;
import org.jclouds.vcloud.domain.NamedResource;
import org.jclouds.vcloud.domain.VAppTemplate;
import com.google.common.base.Throwables;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.ImmutableSortedSet;
import com.google.common.collect.Sets;
import com.google.inject.Injector;
import com.google.inject.Provides;
/**
* Configures the {@link VCloudComputeServiceContext}; requires {@link VCloudComputeService} bound.
*
* @author Adrian Cole
*/
public class VCloudComputeServiceContextModule extends VCloudContextModule {
@Override
protected void configure() {
super.configure();
}
@Provides
@Singleton
protected ComputeService provideComputeService(Injector injector) {
return injector.getInstance(VCloudComputeService.class);
}
@Provides
@Singleton
protected VCloudComputeClient provideComputeClient(VCloudComputeService in) {
return in;
}
@Provides
@Singleton
protected ComputeServiceContext provideContext(ComputeService computeService,
RestContext<VCloudAsyncClient, VCloudClient> context) {
return new ComputeServiceContextImpl<VCloudAsyncClient, VCloudClient>(computeService, context);
}
protected static class LogHolder {
@Resource
@Named(ComputeServiceConstants.COMPUTE_LOGGER)
public Logger logger = Logger.NULL;
}
@Provides
@Singleton
protected Set<? extends Image> provideImages(final VCloudClient client, LogHolder holder,
ExecutorService executor) throws InterruptedException, ExecutionException,
TimeoutException {
final Set<Image> images = Sets.newHashSet();
holder.logger.debug(">> providing images");
Catalog response = client.getDefaultCatalog();
final String vDC = client.getDefaultVDC().getId();
Set<Future<Void>> responses = Sets.newHashSet();
for (final NamedResource resource : response.values()) {
if (resource.getType().equals(VCloudMediaType.CATALOGITEM_XML)) {
final CatalogItem item = client.getCatalogItem(resource.getId());
if (item.getEntity().getType().equals(VCloudMediaType.VAPPTEMPLATE_XML)) {
responses.add(executor.submit(new Callable<Void>() {
@Override
public Void call() throws Exception {
OperatingSystem myOs = OperatingSystem.UNKNOWN;
for (OperatingSystem os : OperatingSystem.values()) {
if (resource.getName().toUpperCase().replaceAll("\\s", "").indexOf(
os.toString()) != -1) {
myOs = os;
}
}
Architecture arch = resource.getName().matches("64[- ]bit") ? Architecture.X86_32
: Architecture.X86_64;
VAppTemplate template = client.getVAppTemplate(item.getEntity().getId());
images.add(new ImageImpl(resource.getId(), template.getDescription(), myOs,
null, vDC, arch));
return null;
}
}));
}
}
}
pollResponsesAndLogWhenComplete(images.size(), "images", holder, responses);
return images;
}
protected void pollResponsesAndLogWhenComplete(int total, String description, LogHolder holder,
Set<Future<Void>> responses) throws InterruptedException, TimeoutException,
ExecutionException {
int complete = 0;
long start = System.currentTimeMillis();
long timeOut = 60 * 1000;
do {
Set<Future<Void>> retries = Sets.newHashSet();
for (Future<Void> future : responses) {
try {
future.get(100, TimeUnit.MILLISECONDS);
complete++;
} catch (ExecutionException e) {
Throwables.propagate(e);
} catch (TimeoutException e) {
retries.add(future);
}
}
responses = Sets.newHashSet(retries);
} while (responses.size() > 0 && System.currentTimeMillis() < start + timeOut);
long duration = System.currentTimeMillis() - start;
if (duration > timeOut)
throw new TimeoutException(String.format("TIMEOUT: %s(%d/%d) rate: %f %s/second%n",
description, complete, total, ((double) complete) / (duration / 1000.0),
description));
for (Future<Void> future : responses)
future.get(30, TimeUnit.SECONDS);
holder.logger.debug("<< %s(%d) rate: %f %s/second%n", description, total, ((double) complete)
/ (duration / 1000.0), description);
}
@Provides
@Singleton
protected SortedSet<? extends Size> provideSizes(VCloudClient client,
Set<? extends Image> images, LogHolder holder, ExecutorService executor)
throws InterruptedException, TimeoutException, ExecutionException {
return ImmutableSortedSet.of(new SizeImpl(1, 512, 10, ImmutableSet.<Architecture> of(
Architecture.X86_32, Architecture.X86_64)));
}
@Provides
@Singleton
protected Set<? extends VCloudTemplate> provideTemplates(VCloudClient client,
Set<? extends Image> images, SortedSet<? extends Size> sizes, LogHolder holder) {
Set<VCloudTemplate> templates = Sets.newHashSet();
holder.logger.debug(">> generating templates");
String vDC = client.getDefaultVDC().getId();
for (Size size : sizes) {
for (Image image : images) {
templates.add(new VCloudTemplate(client, images, sizes, vDC, size, image
.getOperatingSystem(), image));
}
}
holder.logger.debug("<< templates(%d)", templates.size());
return templates;
}
}

View File

@ -0,0 +1,159 @@
/**
*
* Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed 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;
import static com.google.common.base.Preconditions.checkNotNull;
import static org.testng.Assert.assertEquals;
import java.io.IOException;
import java.net.InetAddress;
import java.net.URI;
import java.util.Map;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeoutException;
import org.jclouds.compute.domain.OperatingSystem;
import org.jclouds.logging.log4j.config.Log4JLoggingModule;
import org.jclouds.ssh.jsch.config.JschSshClientModule;
import org.jclouds.vcloud.VCloudClient;
import org.jclouds.vcloud.VCloudPropertiesBuilder;
import org.jclouds.vcloud.domain.ResourceType;
import org.jclouds.vcloud.domain.VApp;
import org.jclouds.vcloud.domain.VAppStatus;
import org.testng.annotations.AfterTest;
import org.testng.annotations.BeforeGroups;
import org.testng.annotations.Test;
import com.google.common.base.CaseFormat;
import com.google.common.base.Predicate;
import com.google.common.collect.Iterables;
import com.google.inject.Injector;
import com.google.inject.Key;
import com.google.inject.TypeLiteral;
import com.google.inject.internal.ImmutableMap;
/**
* Tests behavior of {@code VCloudClient}
*
* @author Adrian Cole
*/
@Test(groups = "live", enabled = true, sequential = true, testName = "vcloud.VCloudClientLiveTest")
public class VCloudComputeClientLiveTest {
protected String service;
protected VCloudComputeClient computeClient;
protected VCloudClient client;
protected String id;
protected InetAddress publicAddress;
protected String templateId;
public static class Expectation {
final long hardDisk;
final String os;
public Expectation(long hardDisk, String os) {
this.hardDisk = hardDisk;
this.os = os;
}
}
protected Map<OperatingSystem, Expectation> expectationMap;
protected Predicate<InetAddress> addressTester;
@Test(enabled = true)
public void testPowerOn() throws InterruptedException, ExecutionException, TimeoutException,
IOException {
OperatingSystem toTest = OperatingSystem.CENTOS;
String serverName = getCompatibleServerName(toTest);
int processorCount = 1;
int memory = 512;
long disk = 10 * 1025 * 1024;
Map<String, String> properties = ImmutableMap.of("foo", "bar");
id = computeClient.start(client.getDefaultVDC().getId(), serverName, templateId,
processorCount, memory, disk, properties).get("id");
Expectation expectation = expectationMap.get(toTest);
VApp vApp = client.getVApp(id);
verifyConfigurationOfVApp(vApp, serverName, expectation.os, processorCount, memory,
expectation.hardDisk);
assertEquals(vApp.getStatus(), VAppStatus.ON);
}
private String getCompatibleServerName(OperatingSystem toTest) {
String serverName = CaseFormat.UPPER_UNDERSCORE
.to(CaseFormat.LOWER_HYPHEN, toTest.toString()).substring(0,
toTest.toString().length() <= 15 ? toTest.toString().length() : 14);
return serverName;
}
@Test(dependsOnMethods = "testPowerOn", enabled = true)
public void testGetPublicAddresses() {
publicAddress = Iterables.getLast(computeClient.getPublicAddresses(id));
assert !addressTester.apply(publicAddress);
}
private void verifyConfigurationOfVApp(VApp vApp, String serverName, String expectedOs,
int processorCount, int memory, long hardDisk) {
// assertEquals(vApp.getName(), serverName);
// assertEquals(vApp.getOperatingSystemDescription(), expectedOs);
assertEquals(
Iterables.getOnlyElement(
vApp.getResourceAllocationByType().get(ResourceType.PROCESSOR))
.getVirtualQuantity(), processorCount);
assertEquals(Iterables.getOnlyElement(
vApp.getResourceAllocationByType().get(ResourceType.SCSI_CONTROLLER))
.getVirtualQuantity(), 1);
assertEquals(Iterables.getOnlyElement(
vApp.getResourceAllocationByType().get(ResourceType.MEMORY)).getVirtualQuantity(),
memory);
assertEquals(Iterables.getOnlyElement(
vApp.getResourceAllocationByType().get(ResourceType.DISK_DRIVE))
.getVirtualQuantity(), hardDisk);
}
@AfterTest
void cleanup() throws InterruptedException, ExecutionException, TimeoutException {
if (id != null)
computeClient.stop(id);
}
@BeforeGroups(groups = { "live" })
public void setupClient() {
String account = checkNotNull(System.getProperty("jclouds.test.user"), "jclouds.test.user");
String key = checkNotNull(System.getProperty("jclouds.test.key"), "jclouds.test.key");
String endpoint = checkNotNull(System.getProperty("jclouds.test.endpoint"),
"jclouds.test.endpoint");
Injector injector = new VCloudComputeServiceContextBuilder(new VCloudPropertiesBuilder(
URI.create(endpoint), account, key).build()).withModules(new Log4JLoggingModule(),
new JschSshClientModule()).buildInjector();
computeClient = injector.getInstance(VCloudComputeClient.class);
client = injector.getInstance(VCloudClient.class);
addressTester = injector.getInstance(Key.get(new TypeLiteral<Predicate<InetAddress>>() {
}));
expectationMap = ImmutableMap.<OperatingSystem, Expectation> builder().put(
OperatingSystem.CENTOS,
new Expectation(4194304 / 2 * 10, "Red Hat Enterprise Linux 5 (64-bit)")).build();
service = "vcloudtest";
templateId = "3";
}
}