Issue 130: added options to runNode like openPorts and runScript; added ability to specify alternate endpoint in *ContextBuilderFactory; updated ant tasks to use new node features; Issue 112: normalized vcloud clients

git-svn-id: http://jclouds.googlecode.com/svn/trunk@2712 3d8758e0-26b5-11de-8745-db77d3ebf521
This commit is contained in:
adrian.f.cole 2010-01-21 06:22:42 +00:00
parent 1d2b1495a2
commit cb906ded3c
45 changed files with 1018 additions and 2362 deletions

View File

@ -21,12 +21,12 @@ package org.jclouds.aws.ec2.compute;
import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkNotNull;
import static org.jclouds.aws.ec2.options.RunInstancesOptions.Builder.withKeyName; import static org.jclouds.aws.ec2.options.RunInstancesOptions.Builder.withKeyName;
import static org.jclouds.scriptbuilder.domain.Statements.exec;
import java.net.InetAddress; import java.net.InetAddress;
import java.util.Map; import java.util.Map;
import java.util.NoSuchElementException; import java.util.NoSuchElementException;
import java.util.Set; import java.util.Set;
import java.util.SortedSet;
import javax.annotation.Resource; import javax.annotation.Resource;
import javax.inject.Inject; import javax.inject.Inject;
@ -41,6 +41,7 @@ import org.jclouds.aws.ec2.domain.InstanceState;
import org.jclouds.aws.ec2.domain.IpProtocol; import org.jclouds.aws.ec2.domain.IpProtocol;
import org.jclouds.aws.ec2.domain.KeyPair; import org.jclouds.aws.ec2.domain.KeyPair;
import org.jclouds.aws.ec2.domain.RunningInstance; import org.jclouds.aws.ec2.domain.RunningInstance;
import org.jclouds.aws.ec2.options.RunInstancesOptions;
import org.jclouds.compute.ComputeService; import org.jclouds.compute.ComputeService;
import org.jclouds.compute.domain.Architecture; import org.jclouds.compute.domain.Architecture;
import org.jclouds.compute.domain.ComputeMetadata; import org.jclouds.compute.domain.ComputeMetadata;
@ -54,11 +55,10 @@ import org.jclouds.compute.domain.Template;
import org.jclouds.compute.domain.internal.ComputeMetadataImpl; import org.jclouds.compute.domain.internal.ComputeMetadataImpl;
import org.jclouds.compute.domain.internal.CreateNodeResponseImpl; import org.jclouds.compute.domain.internal.CreateNodeResponseImpl;
import org.jclouds.compute.domain.internal.NodeMetadataImpl; import org.jclouds.compute.domain.internal.NodeMetadataImpl;
import org.jclouds.compute.options.RunNodeOptions;
import org.jclouds.compute.reference.ComputeServiceConstants; import org.jclouds.compute.reference.ComputeServiceConstants;
import org.jclouds.domain.Credentials; import org.jclouds.domain.Credentials;
import org.jclouds.logging.Logger; import org.jclouds.logging.Logger;
import org.jclouds.scriptbuilder.ScriptBuilder;
import org.jclouds.scriptbuilder.domain.OsFamily;
import com.google.common.base.Function; import com.google.common.base.Function;
import com.google.common.base.Predicate; import com.google.common.base.Predicate;
@ -76,14 +76,14 @@ public class EC2ComputeService implements ComputeService {
@Named(ComputeServiceConstants.COMPUTE_LOGGER) @Named(ComputeServiceConstants.COMPUTE_LOGGER)
protected Logger logger = Logger.NULL; protected Logger logger = Logger.NULL;
private final EC2Client ec2Client; private final EC2Client ec2Client;
private final Set<EC2Size> sizes; private final SortedSet<EC2Size> sizes;
private final Provider<Set<EC2Template>> templates; private final Provider<Set<EC2Template>> templates;
private final Predicate<RunningInstance> instanceStateRunning; private final Predicate<RunningInstance> instanceStateRunning;
private final RunningInstanceToNodeMetadata runningInstanceToNodeMetadata; private final RunningInstanceToNodeMetadata runningInstanceToNodeMetadata;
private final Map<Architecture, Map<OperatingSystem, Map<Region, String>>> imageAmiIdMap; private final Map<Architecture, Map<OperatingSystem, Map<Region, String>>> imageAmiIdMap;
@Inject @Inject
public EC2ComputeService(EC2Client client, Set<EC2Size> sizes, public EC2ComputeService(EC2Client client, SortedSet<EC2Size> sizes,
Provider<Set<EC2Template>> templates, Provider<Set<EC2Template>> templates,
Map<Architecture, Map<OperatingSystem, Map<Region, String>>> imageAmiIdMap, Map<Architecture, Map<OperatingSystem, Map<Region, String>>> imageAmiIdMap,
Predicate<RunningInstance> instanceStateRunning, Predicate<RunningInstance> instanceStateRunning,
@ -103,34 +103,34 @@ public class EC2ComputeService implements ComputeService {
@Override @Override
public CreateNodeResponse runNode(String name, Template template) { public CreateNodeResponse runNode(String name, Template template) {
return this.runNode(name, template, RunNodeOptions.NONE);
}
@Override
public CreateNodeResponse runNode(String name, Template template, RunNodeOptions options) {
checkArgument(template instanceof EC2Template, checkArgument(template instanceof EC2Template,
"unexpected template type. should be EC2Template, was: " + template.getClass()); "unexpected template type. should be EC2Template, was: " + template.getClass());
EC2Template ec2Template = (EC2Template) template; EC2Template ec2Template = (EC2Template) template;
KeyPair keyPair = createKeyPairInRegion(ec2Template.getRegion(), name); KeyPair keyPair = createKeyPairInRegion(ec2Template.getRegion(), name);
String securityGroupName = name; String securityGroupName = name;
createSecurityGroupInRegion(ec2Template.getRegion(), securityGroupName, 22, 80, 8080, 443); createSecurityGroupInRegion(ec2Template.getRegion(), securityGroupName, options
.getOpenPorts());
String script = new ScriptBuilder() // update and install jdk
.addStatement(exec("apt-get update"))//
.addStatement(exec("apt-get upgrade -y"))//
.addStatement(exec("apt-get install -y openjdk-6-jdk"))//
.addStatement(exec("wget -qO/usr/bin/runurl run.alestic.com/runurl"))//
.addStatement(exec("chmod 755 /usr/bin/runurl"))//
.build(OsFamily.UNIX);
logger.debug(">> running instance region(%s) ami(%s) type(%s) keyPair(%s) securityGroup(%s)", logger.debug(">> running instance region(%s) ami(%s) type(%s) keyPair(%s) securityGroup(%s)",
ec2Template.getRegion(), ec2Template.getImage().getId(), ec2Template.getSize() ec2Template.getRegion(), ec2Template.getImage().getId(), ec2Template.getSize()
.getInstanceType(), keyPair.getKeyName(), securityGroupName); .getInstanceType(), keyPair.getKeyName(), securityGroupName);
RunInstancesOptions instanceOptions = withKeyName(keyPair.getKeyName())// key
.asType(ec2Template.getSize().getInstanceType())// instance size
.withSecurityGroup(securityGroupName)// group I created above
.withAdditionalInfo(name);
if (options.getRunScript() != null)
instanceOptions.withUserData(options.getRunScript());
RunningInstance runningInstance = Iterables.getOnlyElement(ec2Client.getInstanceServices() RunningInstance runningInstance = Iterables.getOnlyElement(ec2Client.getInstanceServices()
.runInstancesInRegion(ec2Template.getRegion(), null, ec2Template.getImage().getId(), .runInstancesInRegion(ec2Template.getRegion(), null, ec2Template.getImage().getId(),
1, 1, withKeyName(keyPair.getKeyName())// key 1, 1, instanceOptions));
.asType(ec2Template.getSize().getInstanceType())// instance size
.withSecurityGroup(securityGroupName)// group I created above
.withAdditionalInfo(name)// description
.withUserData(script.getBytes()) // script to run as root
));
logger.debug("<< started instance(%s)", runningInstance.getId()); logger.debug("<< started instance(%s)", runningInstance.getId());
instanceStateRunning.apply(runningInstance); instanceStateRunning.apply(runningInstance);
logger.debug("<< running instance(%s)", runningInstance.getId()); logger.debug("<< running instance(%s)", runningInstance.getId());
@ -316,7 +316,7 @@ public class EC2ComputeService implements ComputeService {
} }
@Override @Override
public Set<EC2Size> listSizes() { public SortedSet<EC2Size> listSizes() {
return sizes; return sizes;
} }

View File

@ -20,6 +20,7 @@ package org.jclouds.aws.ec2.compute.config;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.SortedSet;
import javax.annotation.Resource; import javax.annotation.Resource;
import javax.inject.Named; import javax.inject.Named;
@ -43,7 +44,7 @@ import org.jclouds.logging.Logger;
import org.jclouds.rest.RestContext; import org.jclouds.rest.RestContext;
import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet; import com.google.common.collect.ImmutableSortedSet;
import com.google.common.collect.Sets; import com.google.common.collect.Sets;
import com.google.inject.Provides; import com.google.inject.Provides;
@ -69,8 +70,8 @@ public class EC2ComputeServiceContextModule extends EC2ContextModule {
@Provides @Provides
@Singleton @Singleton
Set<EC2Size> provideSizes() { SortedSet<EC2Size> provideSizes() {
return ImmutableSet.<EC2Size> of(EC2Size.C1_MEDIUM, EC2Size.C1_XLARGE, EC2Size.M1_LARGE, return ImmutableSortedSet.of(EC2Size.C1_MEDIUM, EC2Size.C1_XLARGE, EC2Size.M1_LARGE,
EC2Size.M1_SMALL, EC2Size.M1_XLARGE, EC2Size.M2_2XLARGE, EC2Size.M2_4XLARGE); EC2Size.M1_SMALL, EC2Size.M1_XLARGE, EC2Size.M2_2XLARGE, EC2Size.M2_4XLARGE);
} }
@ -82,7 +83,7 @@ public class EC2ComputeServiceContextModule extends EC2ContextModule {
@Provides @Provides
@Singleton @Singleton
Set<EC2Template> provideTemplates(EC2Client client, Set<EC2Size> sizes, Set<EC2Template> provideTemplates(EC2Client client, SortedSet<EC2Size> sizes,
Map<Architecture, Map<OperatingSystem, Map<Region, String>>> imageAmiIdMap, Map<Architecture, Map<OperatingSystem, Map<Region, String>>> imageAmiIdMap,
LogHolder holder) { LogHolder holder) {
Set<EC2Template> templates = Sets.newHashSet(); Set<EC2Template> templates = Sets.newHashSet();

View File

@ -18,43 +18,13 @@
*/ */
package org.jclouds.aws.ec2.compute; package org.jclouds.aws.ec2.compute;
import static com.google.common.base.Preconditions.checkNotNull;
import static org.jclouds.compute.domain.OperatingSystem.UBUNTU; import static org.jclouds.compute.domain.OperatingSystem.UBUNTU;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNotNull;
import java.io.IOException; import org.jclouds.compute.BaseComputeServiceLiveTest;
import java.net.InetSocketAddress;
import java.util.Properties;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import org.jclouds.compute.ComputeService;
import org.jclouds.compute.ComputeServiceContext;
import org.jclouds.compute.ComputeServiceContextFactory;
import org.jclouds.compute.domain.ComputeMetadata;
import org.jclouds.compute.domain.ComputeType;
import org.jclouds.compute.domain.CreateNodeResponse;
import org.jclouds.compute.domain.LoginType;
import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.domain.Size;
import org.jclouds.compute.domain.Template;
import org.jclouds.logging.log4j.config.Log4JLoggingModule;
import org.jclouds.predicates.RetryablePredicate;
import org.jclouds.predicates.SocketOpen;
import org.jclouds.ssh.ExecResponse;
import org.jclouds.ssh.SshClient;
import org.jclouds.ssh.SshException;
import org.jclouds.ssh.jsch.config.JschSshClientModule; import org.jclouds.ssh.jsch.config.JschSshClientModule;
import org.testng.annotations.AfterTest; import org.testng.annotations.BeforeClass;
import org.testng.annotations.BeforeGroups;
import org.testng.annotations.Test; import org.testng.annotations.Test;
import com.google.common.collect.ImmutableSet;
import com.google.inject.Guice;
import com.google.inject.Injector;
/** /**
* *
* Generally disabled, as it incurs higher fees. * Generally disabled, as it incurs higher fees.
@ -62,115 +32,17 @@ import com.google.inject.Injector;
* @author Adrian Cole * @author Adrian Cole
*/ */
@Test(groups = "live", enabled = true, sequential = true, testName = "ec2.EC2ComputeServiceLiveTest") @Test(groups = "live", enabled = true, sequential = true, testName = "ec2.EC2ComputeServiceLiveTest")
public class EC2ComputeServiceLiveTest { public class EC2ComputeServiceLiveTest extends BaseComputeServiceLiveTest {
private static final String service = "ec2"; @BeforeClass
@Override
protected SshClient.Factory sshFactory; public void setServiceDefaults() {
private String nodeName = System.getProperty("user.name") + service; service = "ec2";
testOS = UBUNTU;
private RetryablePredicate<InetSocketAddress> socketTester;
private CreateNodeResponse node;
private ComputeServiceContext context;
private ComputeService client;
@BeforeGroups(groups = { "live" })
public void setupClient() throws InterruptedException, ExecutionException, TimeoutException,
IOException {
String user = checkNotNull(System.getProperty("jclouds.test.user"), "jclouds.test.user");
String password = checkNotNull(System.getProperty("jclouds.test.key"), "jclouds.test.key");
context = new ComputeServiceContextFactory().createContext(service, user, password,
ImmutableSet.of(new Log4JLoggingModule()), new Properties());
Injector injector = Guice.createInjector(new JschSshClientModule());
sshFactory = injector.getInstance(SshClient.Factory.class);
SocketOpen socketOpen = injector.getInstance(SocketOpen.class);
socketTester = new RetryablePredicate<InetSocketAddress>(socketOpen, 60, 1, TimeUnit.SECONDS);
injector.injectMembers(socketOpen); // add logger
client = context.getComputeService();
} }
public void testCreate() throws Exception { @Override
Template template = client.createTemplateInLocation("default").os(UBUNTU).smallest(); protected JschSshClientModule getSshModule() {
node = client.runNode(nodeName, template); return new JschSshClientModule();
assertNotNull(node.getId());
assertEquals(node.getLoginPort(), 22);
assertEquals(node.getLoginType(), LoginType.SSH);
assertNotNull(node.getName());
assertEquals(node.getPrivateAddresses().size(), 1);
assertEquals(node.getPublicAddresses().size(), 1);
assertNotNull(node.getCredentials());
assertNotNull(node.getCredentials().account);
assertNotNull(node.getCredentials().key);
sshPing();
}
@Test(dependsOnMethods = "testCreate")
public void testGet() throws Exception {
NodeMetadata metadata = client.getNodeMetadata(node);
assertEquals(metadata.getId(), node.getId());
assertEquals(metadata.getLoginPort(), node.getLoginPort());
assertEquals(metadata.getLoginType(), node.getLoginType());
assertEquals(metadata.getName(), node.getName());
assertEquals(metadata.getPrivateAddresses(), node.getPrivateAddresses());
assertEquals(metadata.getPublicAddresses(), node.getPublicAddresses());
}
public void testList() throws Exception {
for (ComputeMetadata node : client.listNodes()) {
assert node.getId() != null;
assert node.getLocation() != null;
assertEquals(node.getType(), ComputeType.NODE);
}
}
public void testListTemplates() throws Exception {
for (Template template : client.listTemplates()) {
assert template.getImage() != null;
System.out.println(template);
}
}
public void testListSizes() throws Exception {
for (Size size : client.listSizes()) {
assert size.getCores() != null;
System.out.println(size);
}
}
private void sshPing() throws IOException {
try {
doCheckKey();
} catch (SshException e) {// try twice in case there is a network timeout
try {
Thread.sleep(10 * 1000);
} catch (InterruptedException e1) {
}
doCheckKey();
}
}
private void doCheckKey() throws IOException {
InetSocketAddress socket = new InetSocketAddress(node.getPublicAddresses().last(), node
.getLoginPort());
socketTester.apply(socket);
SshClient ssh = node.getCredentials().key.startsWith("-----BEGIN RSA PRIVATE KEY-----") ? sshFactory
.create(socket, node.getCredentials().account, node.getCredentials().key.getBytes())
: sshFactory
.create(socket, node.getCredentials().account, node.getCredentials().key);
try {
ssh.connect();
ExecResponse hello = ssh.exec("echo hello");
assertEquals(hello.getOutput().trim(), "hello");
} finally {
if (ssh != null)
ssh.disconnect();
}
}
@AfterTest
void cleanup() throws InterruptedException, ExecutionException, TimeoutException {
if (node != null)
client.destroyNode(node);
context.close();
} }
} }

View File

@ -1,50 +0,0 @@
/**
*
* 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.blobstore;
import java.util.Properties;
import org.jclouds.blobstore.reference.BlobStoreConstants;
import org.jclouds.http.HttpPropertiesBuilder;
/**
* Builds properties used in Blob Stores
*
* @author Adrian Cole, Andrew Newdigate
*/
public class BlobStorePropertiesBuilder extends HttpPropertiesBuilder {
protected BlobStorePropertiesBuilder() {
super();
}
protected BlobStorePropertiesBuilder(Properties properties) {
super(properties);
}
/**
* longest time a single synchronous operation can take before throwing an exception.
*/
public BlobStorePropertiesBuilder withRequestTimeout(long milliseconds) {
properties.setProperty(BlobStoreConstants.PROPERTY_BLOBSTORE_TIMEOUT, Long
.toString(milliseconds));
return this;
}
}

View File

@ -18,6 +18,7 @@
*/ */
package org.jclouds.blobstore.integration; package org.jclouds.blobstore.integration;
import java.net.URI;
import java.util.Properties; import java.util.Properties;
import org.jclouds.http.HttpPropertiesBuilder; import org.jclouds.http.HttpPropertiesBuilder;
@ -37,4 +38,14 @@ public class StubPropertiesBuilder extends HttpPropertiesBuilder {
super(); super();
} }
@Override
public HttpPropertiesBuilder withCredentials(String account, String key) {
return this;
}
@Override
public HttpPropertiesBuilder withEndpoint(URI endpoint) {
return this;
}
} }

View File

@ -40,6 +40,11 @@
</scm> </scm>
<dependencies> <dependencies>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>jclouds-scriptbuilder</artifactId>
<version>${project.version}</version>
</dependency>
<dependency> <dependency>
<groupId>${project.groupId}</groupId> <groupId>${project.groupId}</groupId>
<artifactId>jclouds-core</artifactId> <artifactId>jclouds-core</artifactId>
@ -52,5 +57,17 @@
<type>test-jar</type> <type>test-jar</type>
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>jclouds-log4j</artifactId>
<version>${project.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.14</version>
<scope>test</scope>
</dependency>
</dependencies> </dependencies>
</project> </project>

View File

@ -19,12 +19,14 @@
package org.jclouds.compute; package org.jclouds.compute;
import java.util.Set; import java.util.Set;
import java.util.SortedSet;
import org.jclouds.compute.domain.ComputeMetadata; import org.jclouds.compute.domain.ComputeMetadata;
import org.jclouds.compute.domain.CreateNodeResponse; import org.jclouds.compute.domain.CreateNodeResponse;
import org.jclouds.compute.domain.NodeMetadata; import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.domain.Size; import org.jclouds.compute.domain.Size;
import org.jclouds.compute.domain.Template; import org.jclouds.compute.domain.Template;
import org.jclouds.compute.options.RunNodeOptions;
/** /**
* Provides portable access to launching compute instances. * Provides portable access to launching compute instances.
@ -44,7 +46,12 @@ public interface ComputeService {
/** /**
* List all sizes available to the current user * List all sizes available to the current user
*/ */
Set<? extends Size> listSizes(); SortedSet<? extends Size> listSizes();
/**
* List all images available to the current user
*/
// Set<? extends Image> listImages();
/** /**
* List all templates available to the current user * List all templates available to the current user
@ -61,6 +68,7 @@ public interface ComputeService {
* *
*/ */
CreateNodeResponse runNode(String name, Template template); CreateNodeResponse runNode(String name, Template template);
CreateNodeResponse runNode(String name, Template template, RunNodeOptions options);
/** /**
* destroy the node. * destroy the node.

View File

@ -29,6 +29,5 @@ package org.jclouds.compute.domain;
* @author Adrian Cole * @author Adrian Cole
*/ */
public enum OperatingSystem { public enum OperatingSystem {
CENTOS, RHEL, UBUNTU, JEOS, WINDOWS, UNKNOWN;
CENTOS, RHEL, UBUNTU, WINDOWS, UNKNOWN;
} }

View File

@ -33,17 +33,17 @@ public interface Size extends Comparable<Size> {
/** /**
* Amount of virtual or physical cores provided * Amount of virtual or physical cores provided
*/ */
Integer getCores(); int getCores();
/** /**
* Amount of RAM provided in MB (256M, 1740) * Amount of RAM provided in MB (256M, 1740)
*/ */
Integer getRam(); int getRam();
/** /**
* Amount of boot disk provided in GB (200) * Amount of boot disk provided in GB (200)
*/ */
Integer getDisk(); int getDisk();
/** /**
* Determines platforms this can support * Determines platforms this can support

View File

@ -23,6 +23,7 @@ import java.util.Set;
import org.jclouds.compute.domain.Architecture; import org.jclouds.compute.domain.Architecture;
import org.jclouds.compute.domain.Size; import org.jclouds.compute.domain.Size;
import com.google.common.collect.ComparisonChain;
import com.google.common.collect.Iterables; import com.google.common.collect.Iterables;
import com.google.common.collect.Sets; import com.google.common.collect.Sets;
@ -31,13 +32,12 @@ import com.google.common.collect.Sets;
*/ */
public class SizeImpl implements Size { public class SizeImpl implements Size {
private final Integer cores; private final int cores;
private final Integer ram; private final int ram;
private final Integer disk; private final int disk;
private final Set<Architecture> supportedArchitectures = Sets.newHashSet(); private final Set<Architecture> supportedArchitectures = Sets.newHashSet();
public SizeImpl(Integer cores, Integer ram, Integer disk, public SizeImpl(int cores, int ram, int disk, Iterable<Architecture> supportedArchitectures) {
Iterable<Architecture> supportedArchitectures) {
this.cores = cores; this.cores = cores;
this.ram = ram; this.ram = ram;
this.disk = disk; this.disk = disk;
@ -48,7 +48,7 @@ public class SizeImpl implements Size {
* {@inheritDoc} * {@inheritDoc}
*/ */
@Override @Override
public Integer getCores() { public int getCores() {
return cores; return cores;
} }
@ -56,7 +56,7 @@ public class SizeImpl implements Size {
* {@inheritDoc} * {@inheritDoc}
*/ */
@Override @Override
public Integer getRam() { public int getRam() {
return ram; return ram;
} }
@ -64,7 +64,7 @@ public class SizeImpl implements Size {
* {@inheritDoc} * {@inheritDoc}
*/ */
@Override @Override
public Integer getDisk() { public int getDisk() {
return disk; return disk;
} }
@ -72,9 +72,9 @@ public class SizeImpl implements Size {
public int hashCode() { public int hashCode() {
final int prime = 31; final int prime = 31;
int result = 1; int result = 1;
result = prime * result + ((cores == null) ? 0 : cores.hashCode()); result = prime * result + cores;
result = prime * result + ((disk == null) ? 0 : disk.hashCode()); result = prime * result + disk;
result = prime * result + ((ram == null) ? 0 : ram.hashCode()); result = prime * result + ram;
result = prime * result result = prime * result
+ ((supportedArchitectures == null) ? 0 : supportedArchitectures.hashCode()); + ((supportedArchitectures == null) ? 0 : supportedArchitectures.hashCode());
return result; return result;
@ -89,20 +89,11 @@ public class SizeImpl implements Size {
if (getClass() != obj.getClass()) if (getClass() != obj.getClass())
return false; return false;
SizeImpl other = (SizeImpl) obj; SizeImpl other = (SizeImpl) obj;
if (cores == null) { if (cores != other.cores)
if (other.cores != null)
return false;
} else if (!cores.equals(other.cores))
return false; return false;
if (disk == null) { if (disk != other.disk)
if (other.disk != null)
return false;
} else if (!disk.equals(other.disk))
return false; return false;
if (ram == null) { if (ram != other.ram)
if (other.ram != null)
return false;
} else if (!ram.equals(other.ram))
return false; return false;
if (supportedArchitectures == null) { if (supportedArchitectures == null) {
if (other.supportedArchitectures != null) if (other.supportedArchitectures != null)
@ -112,20 +103,17 @@ public class SizeImpl implements Size {
return true; return true;
} }
/** public int compareTo(Size that) {
* {@inheritDoc} return ComparisonChain.start().compare(this.getCores(), that.getCores()).compare(
*/ this.getRam(), that.getRam()).compare(this.getDisk(), that.getDisk()).result();
@Override
public String toString() {
return "SizeImpl [cores=" + cores + ", disk=" + disk + ", ram=" + ram + "]";
} }
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
@Override @Override
public int compareTo(Size o) { public String toString() {
return (this == o) ? 0 : getCores().compareTo(o.getCores()); return "Size [cores=" + cores + ", disk=" + disk + ", ram=" + ram + "]";
} }
/** /**

View File

@ -0,0 +1,74 @@
package org.jclouds.compute.options;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
/**
* Contains options supported in the {@code ComputeService#runNode} operation. <h2>
* Usage</h2> The recommended way to instantiate a RunOptions object is to statically import
* RunOptions.* and invoke a static creation method followed by an instance mutator (if needed):
* <p/>
* <code>
* import static org.jclouds.compute.options.RunOptions.Builder.*
* <p/>
* ComputeService client = // get connection
* CreateNodeResponse client.runNode(name, template, openPorts(22, 80, 8080, 443));
* <code>
*
* @author Adrian Cole
*/
public class RunNodeOptions {
public static final RunNodeOptions NONE = new RunNodeOptions();
private int[] openPorts = new int[0];
private byte[] script;
public int[] getOpenPorts() {
return openPorts;
}
public byte[] getRunScript() {
return script;
}
/**
* This script will be executed as the root user upon system startup.
*/
public RunNodeOptions runScript(byte[] script) {
checkArgument(checkNotNull(script, "script").length <= 16 * 1024,
"script cannot be larger than 16kb");
this.script = script;
return this;
}
/**
* Opens the set of ports to public access.
*/
public RunNodeOptions openPorts(int... ports) {
this.openPorts = ports;
return this;
}
public static class Builder {
/**
* @see RunNodeOptions#openPorts
*/
public static RunNodeOptions openPorts(int... ports) {
RunNodeOptions options = new RunNodeOptions();
return options.openPorts(ports);
}
/**
* @see RunNodeOptions#runScript
*/
public static RunNodeOptions runScript(byte[] script) {
RunNodeOptions options = new RunNodeOptions();
return options.runScript(script);
}
}
}

View File

@ -19,6 +19,7 @@
package org.jclouds.compute.util; package org.jclouds.compute.util;
import org.jclouds.compute.domain.ComputeMetadata; import org.jclouds.compute.domain.ComputeMetadata;
import org.jclouds.compute.domain.CreateNodeResponse;
import com.google.common.base.Predicate; import com.google.common.base.Predicate;
import com.google.common.collect.Iterables; import com.google.common.collect.Iterables;
@ -28,8 +29,8 @@ import com.google.common.collect.Iterables;
* @author Adrian Cole * @author Adrian Cole
*/ */
public class ComputeUtils { public class ComputeUtils {
public static Iterable<? extends ComputeMetadata> filterByName(Iterable<? extends ComputeMetadata> nodes, public static Iterable<? extends ComputeMetadata> filterByName(
final String name) { Iterable<? extends ComputeMetadata> nodes, final String name) {
return Iterables.filter(nodes, new Predicate<ComputeMetadata>() { return Iterables.filter(nodes, new Predicate<ComputeMetadata>() {
@Override @Override
public boolean apply(ComputeMetadata input) { public boolean apply(ComputeMetadata input) {
@ -38,4 +39,7 @@ public class ComputeUtils {
}); });
} }
public static boolean isKeyAuth(CreateNodeResponse createdNode) {
return createdNode.getCredentials().key.startsWith("-----BEGIN RSA PRIVATE KEY-----");
}
} }

View File

@ -0,0 +1,216 @@
/**
*
* 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.compute;
import static com.google.common.base.Preconditions.checkNotNull;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNotNull;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.util.NoSuchElementException;
import java.util.Properties;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import org.jclouds.compute.domain.ComputeMetadata;
import org.jclouds.compute.domain.ComputeType;
import org.jclouds.compute.domain.CreateNodeResponse;
import org.jclouds.compute.domain.LoginType;
import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.domain.OperatingSystem;
import org.jclouds.compute.domain.Size;
import org.jclouds.compute.domain.Template;
import org.jclouds.compute.options.RunNodeOptions;
import org.jclouds.http.HttpResponseException;
import org.jclouds.logging.log4j.config.Log4JLoggingModule;
import org.jclouds.predicates.RetryablePredicate;
import org.jclouds.predicates.SocketOpen;
import org.jclouds.scriptbuilder.ScriptBuilder;
import org.jclouds.scriptbuilder.domain.OsFamily;
import org.jclouds.scriptbuilder.domain.Statements;
import org.jclouds.ssh.ExecResponse;
import org.jclouds.ssh.SshClient;
import org.jclouds.ssh.SshException;
import org.testng.annotations.AfterTest;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.BeforeGroups;
import org.testng.annotations.Test;
import com.google.common.base.Predicate;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import com.google.inject.Guice;
import com.google.inject.Injector;
import com.google.inject.Module;
/**
*
* @author Adrian Cole
*/
@Test(groups = "live", enabled = true, sequential = true, testName = "compute.ComputeServiceLiveTest")
public abstract class BaseComputeServiceLiveTest {
@BeforeClass
abstract public void setServiceDefaults();
protected String service;
protected OperatingSystem testOS;
protected SshClient.Factory sshFactory;
protected RunNodeOptions options = RunNodeOptions.Builder.openPorts(22);
private String nodeName;
private RetryablePredicate<InetSocketAddress> socketTester;
private CreateNodeResponse node;
protected ComputeServiceContext context;
protected ComputeService client;
protected String user;
protected String password;
@BeforeGroups(groups = { "live" })
public void setupClient() throws InterruptedException, ExecutionException, TimeoutException,
IOException {
checkNotNull(testOS, "testOS");
nodeName = checkNotNull(service, "service");
if (canRunScript())
options.runScript(new ScriptBuilder()
// update add dns and install jdk
.addStatement(
Statements.exec("echo nameserver 208.67.222.222 >> /etc/resolv.conf"))
.addStatement(Statements.exec("apt-get update"))//
.addStatement(Statements.exec("apt-get upgrade -y"))//
.addStatement(Statements.exec("apt-get install -y openjdk-6-jdk"))//
.addStatement(Statements.exec("wget -qO/usr/bin/runurl run.alestic.com/runurl"))//
.addStatement(Statements.exec("chmod 755 /usr/bin/runurl"))//
.build(OsFamily.UNIX).getBytes());
user = checkNotNull(System.getProperty("jclouds.test.user"), "jclouds.test.user");
password = checkNotNull(System.getProperty("jclouds.test.key"), "jclouds.test.key");
context = new ComputeServiceContextFactory().createContext(service, user, password,
ImmutableSet.of(new Log4JLoggingModule(), getSshModule()), new Properties());
Injector injector = Guice.createInjector(getSshModule());
sshFactory = injector.getInstance(SshClient.Factory.class);
SocketOpen socketOpen = injector.getInstance(SocketOpen.class);
socketTester = new RetryablePredicate<InetSocketAddress>(socketOpen, 60, 1, TimeUnit.SECONDS);
injector.injectMembers(socketOpen); // add logger
client = context.getComputeService();
}
private boolean canRunScript() {
return testOS == OperatingSystem.UBUNTU || testOS == OperatingSystem.JEOS;
}
abstract protected Module getSshModule();
public void testCreate() throws Exception {
try {
client.destroyNode(Iterables.find(client.listNodes(), new Predicate<ComputeMetadata>() {
@Override
public boolean apply(ComputeMetadata input) {
return input.getName().equals(nodeName);
}
}));
} catch (HttpResponseException e) {
// TODO hosting.com throws 400 when we try to delete a vApp
} catch (NoSuchElementException e) {
}
Template template = client.createTemplateInLocation("default").os(testOS).smallest();
node = client.runNode(nodeName, template, options);
assertNotNull(node.getId());
assertEquals(node.getLoginPort(), 22);
assertEquals(node.getLoginType(), LoginType.SSH);
assertNotNull(node.getName());
assertEquals(node.getPublicAddresses().size(), 1);
assertNotNull(node.getCredentials());
assertNotNull(node.getCredentials().account);
assertNotNull(node.getCredentials().key);
sshPing();
}
@Test(dependsOnMethods = "testCreate")
public void testGet() throws Exception {
NodeMetadata metadata = client.getNodeMetadata(node);
assertEquals(metadata.getId(), node.getId());
assertEquals(metadata.getLoginPort(), node.getLoginPort());
assertEquals(metadata.getLoginType(), node.getLoginType());
assertEquals(metadata.getName(), node.getName());
assertEquals(metadata.getPrivateAddresses(), node.getPrivateAddresses());
assertEquals(metadata.getPublicAddresses(), node.getPublicAddresses());
}
public void testList() throws Exception {
for (ComputeMetadata node : client.listNodes()) {
assert node.getId() != null;
assert node.getLocation() != null;
assertEquals(node.getType(), ComputeType.NODE);
}
}
public void testListTemplates() throws Exception {
for (Template template : client.listTemplates()) {
assert template.getImage() != null;
}
}
public void testListSizes() throws Exception {
for (Size size : client.listSizes()) {
assert size.getCores() > 0;
}
}
private void sshPing() throws IOException {
try {
doCheckKey();
} catch (SshException e) {// try twice in case there is a network timeout
try {
Thread.sleep(10 * 1000);
} catch (InterruptedException e1) {
}
doCheckKey();
}
}
private void doCheckKey() throws IOException {
InetSocketAddress socket = new InetSocketAddress(node.getPublicAddresses().last(), node
.getLoginPort());
socketTester.apply(socket);
SshClient ssh = node.getCredentials().key.startsWith("-----BEGIN RSA PRIVATE KEY-----") ? sshFactory
.create(socket, node.getCredentials().account, node.getCredentials().key.getBytes())
: sshFactory
.create(socket, node.getCredentials().account, node.getCredentials().key);
try {
ssh.connect();
ExecResponse hello = ssh.exec("echo hello");
assertEquals(hello.getOutput().trim(), "hello");
if (canRunScript())
System.out.println(ssh.exec("java -version"));
} finally {
if (ssh != null)
ssh.disconnect();
}
}
@AfterTest
void cleanup() throws InterruptedException, ExecutionException, TimeoutException {
if (node != null)
client.destroyNode(node);
context.close();
}
}

View File

@ -27,6 +27,7 @@ import static org.jclouds.http.pool.PoolConstants.PROPERTY_POOL_MAX_CONNECTIONS;
import static org.jclouds.http.pool.PoolConstants.PROPERTY_POOL_MAX_CONNECTION_REUSE; import static org.jclouds.http.pool.PoolConstants.PROPERTY_POOL_MAX_CONNECTION_REUSE;
import static org.jclouds.http.pool.PoolConstants.PROPERTY_POOL_MAX_SESSION_FAILURES; import static org.jclouds.http.pool.PoolConstants.PROPERTY_POOL_MAX_SESSION_FAILURES;
import java.net.URI;
import java.util.Properties; import java.util.Properties;
import com.google.common.annotations.VisibleForTesting; import com.google.common.annotations.VisibleForTesting;
@ -36,7 +37,7 @@ import com.google.common.annotations.VisibleForTesting;
* *
* @author Adrian Cole, Andrew Newdigate * @author Adrian Cole, Andrew Newdigate
*/ */
public class HttpPropertiesBuilder { public abstract class HttpPropertiesBuilder {
/** /**
* @see org.jclouds.http.HttpConstants.PROPERTY_HTTP_RELAX_HOSTNAME * @see org.jclouds.http.HttpConstants.PROPERTY_HTTP_RELAX_HOSTNAME
@ -122,9 +123,8 @@ public class HttpPropertiesBuilder {
this.properties.putAll(properties); this.properties.putAll(properties);
} }
public HttpPropertiesBuilder withCredentials(String account, String key) { public abstract HttpPropertiesBuilder withEndpoint(URI endpoint);
return this; public abstract HttpPropertiesBuilder withCredentials(String account, String key);
}
@VisibleForTesting @VisibleForTesting
public Properties build() { public Properties build() {

View File

@ -110,30 +110,18 @@ public class HttpRequest extends HttpMessage {
setLength(); setLength();
} }
/**
* {@inheritDoc}
*/
public void setPayload(InputStream data) { public void setPayload(InputStream data) {
setPayload(Payloads.newPayload(checkNotNull(data, "data"))); setPayload(Payloads.newPayload(checkNotNull(data, "data")));
} }
/**
* {@inheritDoc}
*/
public void setPayload(byte[] data) { public void setPayload(byte[] data) {
setPayload(Payloads.newPayload(checkNotNull(data, "data"))); setPayload(Payloads.newPayload(checkNotNull(data, "data")));
} }
/**
* {@inheritDoc}
*/
public void setPayload(String data) { public void setPayload(String data) {
setPayload(Payloads.newPayload(checkNotNull(data, "data"))); setPayload(Payloads.newPayload(checkNotNull(data, "data")));
} }
/**
* {@inheritDoc}
*/
public void setPayload(File data) { public void setPayload(File data) {
setPayload(Payloads.newPayload(checkNotNull(data, "data"))); setPayload(Payloads.newPayload(checkNotNull(data, "data")));
} }

View File

@ -48,10 +48,10 @@ public abstract class RestContextFactory<T, B extends RestContextBuilder<?, ?>>
* Initializes with the default properties built-in to jclouds. This is typically stored in the * Initializes with the default properties built-in to jclouds. This is typically stored in the
* classpath resource {@code filename} * classpath resource {@code filename}
* *
* @parma filename name of the properties file to initialize from * @param filename name of the properties file to initialize from
* @throws IOException * @throws IOException
* if the default properties file cannot be loaded * if the default properties file cannot be loaded
* @see #init * @see #getPropertiesFromResource
*/ */
public RestContextFactory(String filename) throws IOException { public RestContextFactory(String filename) throws IOException {
this(getPropertiesFromResource(filename)); this(getPropertiesFromResource(filename));
@ -82,6 +82,7 @@ public abstract class RestContextFactory<T, B extends RestContextBuilder<?, ?>>
static Properties getPropertiesFromResource(String filename) throws IOException { static Properties getPropertiesFromResource(String filename) throws IOException {
Properties properties = new Properties(); Properties properties = new Properties();
properties.load(Resources.newInputStreamSupplier(Resources.getResource(filename)).getInput()); properties.load(Resources.newInputStreamSupplier(Resources.getResource(filename)).getInput());
properties.putAll(System.getProperties());
return properties; return properties;
} }
@ -125,8 +126,7 @@ public abstract class RestContextFactory<T, B extends RestContextBuilder<?, ?>>
} }
/** /**
* * Creates a new remote context.
* FIXME Comment this // ImmutableSet.<Module>of(new ExecutorServiceModule(myexecutor))
* *
* @param hint * @param hint
* @param account * @param account
@ -134,8 +134,11 @@ public abstract class RestContextFactory<T, B extends RestContextBuilder<?, ?>>
* @param key * @param key
* nullable, if credentials are present in the overrides * nullable, if credentials are present in the overrides
* @param modules * @param modules
* Configuration you'd like to pass to the context. Ex. ImmutableSet.<Module>of(new
* ExecutorServiceModule(myexecutor))
* @param overrides * @param overrides
* @return * properties to override defaults with.
* @return initialized context ready for use
*/ */
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public T createContext(String hint, @Nullable String account, @Nullable String key, public T createContext(String hint, @Nullable String account, @Nullable String key,
@ -151,6 +154,8 @@ public abstract class RestContextFactory<T, B extends RestContextBuilder<?, ?>>
String contextBuilderClassName = checkNotNull(properties.getProperty(contextBuilderKey), String contextBuilderClassName = checkNotNull(properties.getProperty(contextBuilderKey),
contextBuilderKey); contextBuilderKey);
String endpointKey = String.format("%s.endpoint", hint);
String endpoint = properties.getProperty(endpointKey);
try { try {
Class<HttpPropertiesBuilder> propertiesBuilderClass = (Class<HttpPropertiesBuilder>) Class Class<HttpPropertiesBuilder> propertiesBuilderClass = (Class<HttpPropertiesBuilder>) Class
.forName(propertiesBuilderClassName); .forName(propertiesBuilderClassName);
@ -159,7 +164,8 @@ public abstract class RestContextFactory<T, B extends RestContextBuilder<?, ?>>
.newInstance(overrides); .newInstance(overrides);
if (key != null) if (key != null)
builder.withCredentials(account, key); builder.withCredentials(account, key);
if (endpoint != null)
builder.withEndpoint(URI.create(endpoint));
B contextBuilder = (B) contextBuilderClass.getConstructor(Properties.class).newInstance( B contextBuilder = (B) contextBuilderClass.getConstructor(Properties.class).newInstance(
builder.build()).withModules(Iterables.toArray(modules, Module.class)); builder.build()).withModules(Iterables.toArray(modules, Module.class));
return build(contextBuilder); return build(contextBuilder);

View File

@ -41,12 +41,6 @@ public class InputStreamChain extends InputStream {
*/ */
private InputStream current; private InputStream current;
/**
* Constructor with an initial stream
*
* @param first
* Initial InputStream
*/
public InputStreamChain(InputStream... inputStreams) { public InputStreamChain(InputStream... inputStreams) {
for (InputStream stream : inputStreams) { for (InputStream stream : inputStreams) {
addInputStream(stream); addInputStream(stream);

View File

@ -32,6 +32,7 @@ import com.google.common.collect.MapMaker;
* @author Adrian Cole * @author Adrian Cole
*/ */
public class Patterns { public class Patterns {
public static final Pattern TOKEN_PATTERN = Pattern.compile("\\{(.+?)\\}");
public static final Pattern TWO_SPACE_PATTERN = Pattern.compile(" "); public static final Pattern TWO_SPACE_PATTERN = Pattern.compile(" ");
public static final Pattern URL_ENCODED_PATTERN = Pattern.compile(".*%[a-fA-F0-9][a-fA-F0-9].*"); public static final Pattern URL_ENCODED_PATTERN = Pattern.compile(".*%[a-fA-F0-9][a-fA-F0-9].*");
public static final Pattern URI_PATTERN = Pattern.compile("([a-z0-9]+)://([^:]*):(.*)@(.*)"); public static final Pattern URI_PATTERN = Pattern.compile("([a-z0-9]+)://([^:]*):(.*)@(.*)");

View File

@ -43,7 +43,7 @@ import com.google.common.io.Closeables;
import com.google.common.io.OutputSupplier; import com.google.common.io.OutputSupplier;
/** /**
* // TODO: Adrian: Document this! * General utilities used in jclouds code.
* *
* @author Adrian Cole * @author Adrian Cole
*/ */
@ -137,14 +137,16 @@ public class Utils {
* @see {@link String#getBytes()} - used as fall-back. * @see {@link String#getBytes()} - used as fall-back.
* *
* @param str * @param str
* @param encoding * what to encode
* @return * @param charsetName
* the name of a supported {@link java.nio.charset.Charset </code>charset<code>}
* @return properly encoded String.
*/ */
public static byte[] encodeString(String str, String encoding) { public static byte[] encodeString(String str, String charsetName) {
try { try {
return str.getBytes(encoding); return str.getBytes(charsetName);
} catch (UnsupportedEncodingException e) { } catch (UnsupportedEncodingException e) {
logger.warn(e, "Failed to encode string to bytes with encoding " + encoding logger.warn(e, "Failed to encode string to bytes with encoding " + charsetName
+ ". Falling back to system's default encoding"); + ". Falling back to system's default encoding");
return str.getBytes(); return str.getBytes();
} }
@ -156,45 +158,13 @@ public class Utils {
* the system's default encoding. * the system's default encoding.
* *
* @param str * @param str
* @return * what to encode
* @return properly encoded String.
*/ */
public static byte[] encodeString(String str) { public static byte[] encodeString(String str) {
return encodeString(str, UTF8_ENCODING); return encodeString(str, UTF8_ENCODING);
} }
/**
* Decode the given string with the given encoding, if possible. If the decoding fails with
* {@link UnsupportedEncodingException}, log a warning and fall back to the system's default
* encoding.
*
* @param bytes
* @param encoding
* @return
*/
public static String decodeString(byte[] bytes, String encoding) {
try {
return new String(bytes, encoding);
} catch (UnsupportedEncodingException e) {
logger.warn(e, "Failed to decode bytes to string with encoding " + encoding
+ ". Falling back to system's default encoding");
return new String(bytes);
}
}
/**
* Decode the given string with the UTF-8 encoding, the sane default. In the very unlikely event
* the encoding fails with {@link UnsupportedEncodingException}, log a warning and fall back to
* the system's default encoding.
*
* @param str
* @return
*/
public static String decodeString(byte[] bytes) {
return decodeString(bytes, UTF8_ENCODING);
}
public static final Pattern pattern = Pattern.compile("\\{(.+?)\\}");
/** /**
* replaces tokens that are expressed as <code>{token}</code> * replaces tokens that are expressed as <code>{token}</code>
* *
@ -209,7 +179,7 @@ public class Utils {
* token/value pairs * token/value pairs
*/ */
public static String replaceTokens(String input, Map<String, String> replacements) { public static String replaceTokens(String input, Map<String, String> replacements) {
Matcher matcher = pattern.matcher(input); Matcher matcher = Patterns.TOKEN_PATTERN.matcher(input);
StringBuilder builder = new StringBuilder(); StringBuilder builder = new StringBuilder();
int i = 0; int i = 0;
while (matcher.find()) { while (matcher.find()) {

View File

@ -18,6 +18,7 @@
*/ */
package org.jclouds.http; package org.jclouds.http;
import java.net.URI;
import java.util.Properties; import java.util.Properties;
import org.testng.annotations.Test; import org.testng.annotations.Test;
@ -37,7 +38,18 @@ public class HttpPropertiesBuilderTest {
int poolMaxClients = 3382; int poolMaxClients = 3382;
int poolMaxSessionFailures = 857; int poolMaxSessionFailures = 857;
HttpPropertiesBuilder builder = new HttpPropertiesBuilder(new Properties()); HttpPropertiesBuilder builder = new HttpPropertiesBuilder(new Properties()) {
@Override
public HttpPropertiesBuilder withCredentials(String account, String key) {
return this;
}
@Override
public HttpPropertiesBuilder withEndpoint(URI endpoint) {
return this;
}
};
builder.withHttpMaxRetries(httpMaxRetries); builder.withHttpMaxRetries(httpMaxRetries);
builder.withPoolIoWorkerThreads(poolIoWorkerThreads); builder.withPoolIoWorkerThreads(poolIoWorkerThreads);

View File

@ -21,11 +21,15 @@ package org.jclouds.nirvanix.sdn;
import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkNotNull;
import java.net.URI; import java.net.URI;
import java.util.List;
import java.util.Properties; import java.util.Properties;
import org.jclouds.http.HttpPropertiesBuilder; import org.jclouds.http.HttpPropertiesBuilder;
import org.jclouds.nirvanix.sdn.reference.SDNConstants; import org.jclouds.nirvanix.sdn.reference.SDNConstants;
import com.google.common.base.Splitter;
import com.google.common.collect.Lists;
/** /**
* Builds properties used in SDN Clients * Builds properties used in SDN Clients
* *
@ -65,4 +69,13 @@ public class SDNPropertiesBuilder extends HttpPropertiesBuilder {
.toString()); .toString());
return this; return this;
} }
@Override
public SDNPropertiesBuilder withCredentials(String account, String key) {
List<String> parts = Lists.newArrayList(Splitter.on('/').split(account));
if (parts.size() != 3) {
throw new IllegalArgumentException("account syntax is appkey/appname/username");
}
return withCredentials(parts.get(0), parts.get(1), parts.get(2), key);
}
} }

View File

@ -19,15 +19,17 @@
package org.jclouds.rimuhosting.miro; package org.jclouds.rimuhosting.miro;
import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkNotNull;
import org.jclouds.http.HttpPropertiesBuilder; import static org.jclouds.rimuhosting.miro.reference.RimuHostingConstants.PROPERTY_RIMUHOSTING_APIKEY;
import static org.jclouds.rimuhosting.miro.reference.RimuHostingConstants.*; import static org.jclouds.rimuhosting.miro.reference.RimuHostingConstants.PROPERTY_RIMUHOSTING_ENDPOINT;
import java.net.URI; import java.net.URI;
import java.util.Properties; import java.util.Properties;
import org.jclouds.http.HttpPropertiesBuilder;
/** /**
* Builds properties used in RimuHosting Clients * Builds properties used in RimuHosting Clients
* *
* @author Adrian Cole * @author Adrian Cole
*/ */
public class RimuHostingPropertiesBuilder extends HttpPropertiesBuilder { public class RimuHostingPropertiesBuilder extends HttpPropertiesBuilder {
@ -52,9 +54,15 @@ public class RimuHostingPropertiesBuilder extends HttpPropertiesBuilder {
return this; return this;
} }
@Override
public RimuHostingPropertiesBuilder withEndpoint(URI endpoint) { public RimuHostingPropertiesBuilder withEndpoint(URI endpoint) {
properties.setProperty(PROPERTY_RIMUHOSTING_ENDPOINT, checkNotNull(endpoint, "endpoint") properties.setProperty(PROPERTY_RIMUHOSTING_ENDPOINT, checkNotNull(endpoint, "endpoint")
.toString()); .toString());
return this; return this;
} }
@Override
public HttpPropertiesBuilder withCredentials(String account, String key) {
return withCredentials(account != null ? account : key);
}
} }

View File

@ -25,6 +25,7 @@ import java.net.InetAddress;
import java.net.UnknownHostException; import java.net.UnknownHostException;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.SortedSet;
import javax.annotation.Resource; import javax.annotation.Resource;
import javax.inject.Inject; import javax.inject.Inject;
@ -43,6 +44,7 @@ import org.jclouds.compute.domain.Size;
import org.jclouds.compute.domain.Template; import org.jclouds.compute.domain.Template;
import org.jclouds.compute.domain.internal.ComputeMetadataImpl; import org.jclouds.compute.domain.internal.ComputeMetadataImpl;
import org.jclouds.compute.domain.internal.CreateNodeResponseImpl; import org.jclouds.compute.domain.internal.CreateNodeResponseImpl;
import org.jclouds.compute.options.RunNodeOptions;
import org.jclouds.compute.reference.ComputeServiceConstants; import org.jclouds.compute.reference.ComputeServiceConstants;
import org.jclouds.domain.Credentials; import org.jclouds.domain.Credentials;
import org.jclouds.logging.Logger; import org.jclouds.logging.Logger;
@ -82,6 +84,11 @@ public class RimuHostingComputeService implements ComputeService {
@Override @Override
public CreateNodeResponse runNode(String name, Template template) { public CreateNodeResponse runNode(String name, Template template) {
return this.runNode(name, template, RunNodeOptions.NONE);
}
@Override
public CreateNodeResponse runNode(String name, Template template, RunNodeOptions options) {
NewServerResponse serverResponse = rhClient.createServer(name, checkNotNull(imageNameMap NewServerResponse serverResponse = rhClient.createServer(name, checkNotNull(imageNameMap
.get(template.getImage().getOperatingSystem()), "os not supported: " .get(template.getImage().getOperatingSystem()), "os not supported: "
+ template.getImage().getOperatingSystem()), "MIRO1B"); + template.getImage().getOperatingSystem()), "MIRO1B");
@ -144,7 +151,7 @@ public class RimuHostingComputeService implements ComputeService {
} }
@Override @Override
public Set<? extends Size> listSizes() { public SortedSet<? extends Size> listSizes() {
return null; return null;
} }

View File

@ -18,156 +18,28 @@
*/ */
package org.jclouds.rimuhosting.miro.compute; package org.jclouds.rimuhosting.miro.compute;
import static com.google.common.base.Preconditions.checkNotNull;
import static org.jclouds.compute.domain.OperatingSystem.UBUNTU; import static org.jclouds.compute.domain.OperatingSystem.UBUNTU;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNotNull;
import java.io.IOException; import org.jclouds.compute.BaseComputeServiceLiveTest;
import java.net.InetSocketAddress;
import java.util.Properties;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import org.jclouds.compute.ComputeService;
import org.jclouds.compute.ComputeServiceContext;
import org.jclouds.compute.ComputeServiceContextFactory;
import org.jclouds.compute.domain.ComputeMetadata;
import org.jclouds.compute.domain.ComputeType;
import org.jclouds.compute.domain.CreateNodeResponse;
import org.jclouds.compute.domain.LoginType;
import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.domain.Size;
import org.jclouds.compute.domain.Template;
import org.jclouds.logging.log4j.config.Log4JLoggingModule;
import org.jclouds.predicates.RetryablePredicate;
import org.jclouds.predicates.SocketOpen;
import org.jclouds.ssh.ExecResponse;
import org.jclouds.ssh.SshClient;
import org.jclouds.ssh.SshException;
import org.jclouds.ssh.jsch.config.JschSshClientModule; import org.jclouds.ssh.jsch.config.JschSshClientModule;
import org.testng.annotations.AfterTest; import org.testng.annotations.BeforeClass;
import org.testng.annotations.BeforeGroups;
import org.testng.annotations.Test; import org.testng.annotations.Test;
import com.google.common.collect.ImmutableSet;
import com.google.inject.Guice;
import com.google.inject.Injector;
/** /**
* @author Ivan Meredith * @author Ivan Meredith
*/ */
@Test(groups = "live", sequential = true, testName = "rimuhosting.RimuHostingNodeServiceLiveTest") @Test(groups = "live", sequential = true, testName = "rimuhosting.RimuHostingNodeServiceLiveTest")
public class RimuHostingComputeServiceLiveTest { public class RimuHostingComputeServiceLiveTest extends BaseComputeServiceLiveTest {
private static final String service = "rimuhosting"; @BeforeClass
@Override
protected SshClient.Factory sshFactory; public void setServiceDefaults() {
private String nodeName = System.getProperty("user.name") + service; service = "rimuhosting";
testOS = UBUNTU;
private RetryablePredicate<InetSocketAddress> socketTester;
private CreateNodeResponse node;
private ComputeServiceContext context;
private ComputeService client;
@BeforeGroups(groups = { "live" })
public void setupClient() throws InterruptedException, ExecutionException, TimeoutException,
IOException {
String user = checkNotNull(System.getProperty("jclouds.test.user"), "jclouds.test.user");
String password = checkNotNull(System.getProperty("jclouds.test.key"), "jclouds.test.key");
context = new ComputeServiceContextFactory().createContext(service, user, password,
ImmutableSet.of(new Log4JLoggingModule()), new Properties());
Injector injector = Guice.createInjector(new JschSshClientModule());
sshFactory = injector.getInstance(SshClient.Factory.class);
SocketOpen socketOpen = injector.getInstance(SocketOpen.class);
socketTester = new RetryablePredicate<InetSocketAddress>(socketOpen, 60, 1, TimeUnit.SECONDS);
injector.injectMembers(socketOpen); // add logger
client = context.getComputeService();
} }
public void testCreate() throws Exception { @Override
Template template = client.createTemplateInLocation("default").os(UBUNTU).smallest(); protected JschSshClientModule getSshModule() {
node = client.runNode(nodeName, template); return new JschSshClientModule();
assertNotNull(node.getId());
assertEquals(node.getLoginPort(), 22);
assertEquals(node.getLoginType(), LoginType.SSH);
assertNotNull(node.getName());
assertEquals(node.getPrivateAddresses().size(), 1);
assertEquals(node.getPublicAddresses().size(), 1);
assertNotNull(node.getCredentials());
assertNotNull(node.getCredentials().account);
assertNotNull(node.getCredentials().key);
sshPing();
} }
@Test(dependsOnMethods = "testCreate") }
public void testGet() throws Exception {
NodeMetadata metadata = client.getNodeMetadata(node);
assertEquals(metadata.getId(), node.getId());
assertEquals(metadata.getLoginPort(), node.getLoginPort());
assertEquals(metadata.getLoginType(), node.getLoginType());
assertEquals(metadata.getName(), node.getName());
assertEquals(metadata.getPrivateAddresses(), node.getPrivateAddresses());
assertEquals(metadata.getPublicAddresses(), node.getPublicAddresses());
}
public void testList() throws Exception {
for (ComputeMetadata node : client.listNodes()) {
assert node.getId() != null;
assert node.getLocation() != null;
assertEquals(node.getType(), ComputeType.NODE);
}
}
public void testListTemplates() throws Exception {
for (Template template : client.listTemplates()) {
assert template.getImage() != null;
System.out.println(template);
}
}
public void testListSizes() throws Exception {
for (Size size : client.listSizes()) {
assert size.getCores() != null;
System.out.println(size);
}
}
private void sshPing() throws IOException {
try {
doCheckKey();
} catch (SshException e) {// try twice in case there is a network timeout
try {
Thread.sleep(10 * 1000);
} catch (InterruptedException e1) {
}
doCheckKey();
}
}
private void doCheckKey() throws IOException {
InetSocketAddress socket = new InetSocketAddress(node.getPublicAddresses().last(), node
.getLoginPort());
socketTester.apply(socket);
SshClient ssh = node.getCredentials().key.startsWith("-----BEGIN RSA PRIVATE KEY-----") ? sshFactory
.create(socket, node.getCredentials().account, node.getCredentials().key.getBytes())
: sshFactory
.create(socket, node.getCredentials().account, node.getCredentials().key);
try {
ssh.connect();
ExecResponse hello = ssh.exec("echo hello");
assertEquals(hello.getOutput().trim(), "hello");
} finally {
if (ssh != null)
ssh.disconnect();
}
}
@AfterTest
void cleanup() throws InterruptedException, ExecutionException, TimeoutException {
if (node != null)
client.destroyNode(node);
context.close();
}
}

View File

@ -1,7 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<!-- <!--
Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com> Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
==================================================================== ====================================================================
@ -23,6 +22,7 @@
<property file="build.properties" /> <property file="build.properties" />
<property name="password" value="" /> <property name="password" value="" />
<property name="keyfile" value="" /> <property name="keyfile" value="" />
<property name="listenport" value="8080" />
<property name="container.zip" value="http://www.ibiblio.org/pub/mirrors/apache/tomcat/tomcat-6/v6.0.20/bin/apache-tomcat-6.0.20.zip" /> <property name="container.zip" value="http://www.ibiblio.org/pub/mirrors/apache/tomcat/tomcat-6/v6.0.20/bin/apache-tomcat-6.0.20.zip" />
<property name="warfile" value="build/samples-blazeds.war" /> <property name="warfile" value="build/samples-blazeds.war" />
@ -60,55 +60,32 @@
<property name="service" value="terremark"/> <property name="service" value="terremark"/>
<input message="What is your account on ${service}?" addproperty="account"/> <input message="What is your account on ${service}?" addproperty="account"/>
<input message="What is the key for ${account}?" addproperty="key"/> <input message="What is the key for ${account}?" addproperty="key"/>
<property name="jclouds.compute.nodename" value="terremark-blaze"/> <property name="nodename" value="terremark-blaze"/>
<property name="jclouds.compute.url" value="compute://${account}:${key}@${service}"/> <property name="url" value="compute://${account}:${key}@${service}"/>
<target name="destroy" description="destroy the node ${jclouds.compute.nodename}"> <target name="destroy" description="destroy the node ${nodename}">
<compute action="destroy" provider="${jclouds.compute.url}"> <compute action="destroy" provider="${url}">
<node name="${jclouds.compute.nodename}" /> <node name="${nodename}" />
</compute> </compute>
<sleep seconds="2" /> <sleep seconds="2" />
</target> </target>
<target name="create" description="create the node ${jclouds.compute.nodename}" depends="destroy" > <target name="create" description="create the node ${nodename}" depends="destroy" >
<compute action="create" provider="${jclouds.compute.url}"> <compute action="create" provider="${url}">
<node name="${jclouds.compute.nodename}" os="UBUNTU" size="SMALLEST" <node name="${nodename}" os="JEOS" size="SMALLEST"
hostproperty="host" usernameproperty="username" passwordproperty="password" /> runscript="runscript.sh" openports="22,${listenport}"
hostproperty="host" usernameproperty="username" passwordproperty="password" />
</compute> </compute>
<echo message="provisioning java on: ${jclouds.compute.nodename}" />
<property name="sudo" value="echo ${password}|sudo -S" />
<!-- funny game to get around sudo problems with >>. first sudo is only to prime the password -->
<sshexec host="${host}" username="${username}" password="${password}" trust="true"
command="${sudo} echo hello;echo nameserver 208.67.222.222 |sudo tee -a /etc/resolv.conf" />
<sshexec host="${host}" username="${username}" password="${password}" trust="true"
command="${sudo} apt-get update -qq" />
<sshexec host="${host}" username="${username}" password="${password}" trust="true"
command="${sudo} apt-get upgrade -y -qq" />
<sshexec host="${host}" username="${username}" password="${password}" trust="true"
command="${sudo} apt-get install -y -qq wget" />
<sshexec host="${host}" username="${username}" password="${password}" trust="true"
command="${sudo} apt-get install -y -qq openjdk-6-jdk" />
<sshexec host="${host}" username="${username}" password="${password}" trust="true"
command="wget -q http://www.alliedquotes.com/mirrors/apache/tomcat/tomcat-6/v6.0.20/bin/apache-tomcat-6.0.20.tar.gz" />
<sshexec host="${host}" username="${username}" password="${password}" trust="true"
command="tar xzf apache-tomcat-6.0.20.tar.gz" />
<sshexec host="${host}" username="${username}" password="${password}" trust="true"
command="${sudo} mkdir -p /tmp/cargo/containers/" />
<sshexec host="${host}" username="${username}" password="${password}" trust="true"
command="${sudo} chmod 1777 /tmp/cargo" />
<sshexec host="${host}" username="${username}" password="${password}" trust="true"
command="${sudo} mv apache-tomcat-6.0.20 /tmp/cargo/containers/tomcat6x" />
</target> </target>
<target name="cargooverssh" depends="create" description="run cargo on remote node" > <target name="cargooverssh" depends="create" description="run cargo on remote node" >
<echo message="deploying tomcat and blaze to: ${jclouds.compute.nodename}" /> <echo message="deploying tomcat and blaze to: ${nodename}" />
<cargo containerId="tomcat6x" output="build/output.log" log="build/cargo.log" action="start" timeout="600000"> <cargo containerId="tomcat6x" output="build/output.log" log="build/cargo.log" action="start" timeout="600000">
<zipurlinstaller installurl="${container.zip}" /> <zipurlinstaller installurl="${container.zip}" />
<configuration home="build/cargo" type="standalone"> <configuration home="build/cargo" type="standalone">
<property name="cargo.java.home" value="/usr/lib/jvm/java-6-openjdk"/> <property name="cargo.java.home" value="/usr/lib/jvm/java-6-openjdk"/>
<property name="cargo.hostname" value="${host}"/> <property name="cargo.hostname" value="${host}"/>
<property name="cargo.servlet.port" value="8080"/> <property name="cargo.servlet.port" value="${listenport}"/>
<property name="cargo.ssh.host" value="${host}"/> <property name="cargo.ssh.host" value="${host}"/>
<property name="cargo.ssh.username" value="${username}"/> <property name="cargo.ssh.username" value="${username}"/>
<property name="cargo.ssh.password" value="${password}"/> <property name="cargo.ssh.password" value="${password}"/>
@ -125,7 +102,7 @@
<cargo containerId="tomcat6x" output="build/output.log" log="build/cargo.log" action="start" timeout="600000"> <cargo containerId="tomcat6x" output="build/output.log" log="build/cargo.log" action="start" timeout="600000">
<zipurlinstaller installurl="${container.zip}" /> <zipurlinstaller installurl="${container.zip}" />
<configuration home="build/cargo" type="standalone"> <configuration home="build/cargo" type="standalone">
<property name="cargo.servlet.port" value="8080"/> <property name="cargo.servlet.port" value="${listenport}"/>
<property name="cargo.logging" value="high"/> <property name="cargo.logging" value="high"/>
<deployable type="war" file="${warfile}"/> <deployable type="war" file="${warfile}"/>
</configuration> </configuration>

View File

@ -0,0 +1,10 @@
echo nameserver 208.67.222.222 >> /etc/resolv.conf
apt-get update -qq
apt-get upgrade -y -qq
apt-get install -y -qq wget
apt-get install -y -qq openjdk-6-jdk
wget -q http://www.alliedquotes.com/mirrors/apache/tomcat/tomcat-6/v6.0.20/bin/apache-tomcat-6.0.20.tar.gz
tar xzf apache-tomcat-6.0.20.tar.gz
mkdir -p /tmp/cargo/containers
chmod 1777 /tmp/cargo
mv apache-tomcat-6.0.20 /tmp/cargo/containers/tomcat6x

View File

@ -18,37 +18,35 @@
*/ */
package org.jclouds.tools.ant.taskdefs.compute; package org.jclouds.tools.ant.taskdefs.compute;
import static org.jclouds.compute.util.ComputeUtils.filterByName;
import static org.jclouds.compute.util.ComputeUtils.isKeyAuth;
import static org.jclouds.tools.ant.taskdefs.compute.ComputeTaskUtils.buildComputeMap;
import static org.jclouds.tools.ant.taskdefs.compute.ComputeTaskUtils.createTemplateFromElement;
import static org.jclouds.tools.ant.taskdefs.compute.ComputeTaskUtils.getNodeOptionsFromElement;
import static org.jclouds.tools.ant.taskdefs.compute.ComputeTaskUtils.ipOrEmptyString;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.net.InetAddress;
import java.net.URI; import java.net.URI;
import java.nio.charset.Charset; import java.nio.charset.Charset;
import java.util.Map; import java.util.Map;
import java.util.Properties;
import java.util.SortedSet; import javax.annotation.Nullable;
import org.apache.tools.ant.BuildException; import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.Project; import org.apache.tools.ant.Project;
import org.apache.tools.ant.Task; import org.apache.tools.ant.Task;
import org.jclouds.compute.ComputeService; import org.jclouds.compute.ComputeService;
import org.jclouds.compute.ComputeServiceContext; import org.jclouds.compute.ComputeServiceContext;
import org.jclouds.compute.ComputeServiceContextFactory;
import org.jclouds.compute.domain.ComputeMetadata; import org.jclouds.compute.domain.ComputeMetadata;
import org.jclouds.compute.domain.CreateNodeResponse; import org.jclouds.compute.domain.CreateNodeResponse;
import org.jclouds.compute.domain.NodeMetadata; import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.domain.OperatingSystem;
import org.jclouds.compute.domain.Template; import org.jclouds.compute.domain.Template;
import org.jclouds.compute.reference.ComputeServiceConstants; import org.jclouds.compute.options.RunNodeOptions;
import org.jclouds.compute.util.ComputeUtils;
import org.jclouds.http.HttpUtils; import org.jclouds.http.HttpUtils;
import org.jclouds.tools.ant.logging.config.AntLoggingModule;
import com.google.common.base.CaseFormat; import com.google.common.base.CaseFormat;
import com.google.common.base.Function;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.MapMaker;
import com.google.common.io.Files; import com.google.common.io.Files;
import com.google.inject.Module;
import com.google.inject.Provider; import com.google.inject.Provider;
/** /**
@ -58,169 +56,133 @@ import com.google.inject.Provider;
public class ComputeTask extends Task { public class ComputeTask extends Task {
private final Map<URI, ComputeServiceContext> computeMap; private final Map<URI, ComputeServiceContext> computeMap;
private static Project project; private String provider;
/** private String action;
* we don't have a reference to the project during the constructor, so we need to defer expansion private NodeElement nodeElement;
* with a Provider.
*/
private static Provider<Iterable<? extends Module>> defaultModulesProvider = new Provider<Iterable<? extends Module>>() {
@Override
public Iterable<Module> get() {
return ImmutableSet.of((Module) new AntLoggingModule(project,
ComputeServiceConstants.COMPUTE_LOGGER));
}
};
/** /**
* we don't have a reference to the project during the constructor, so we need to defer expansion * we don't have a reference to the project during the constructor, so we need to defer expansion
* with a Provider. * with a Provider.
*/ */
private static Provider<Properties> defaultPropertiesProvider = new Provider<Properties>() { private final Provider<Project> projectProvider = new Provider<Project>() {
@SuppressWarnings("unchecked")
@Override @Override
public Properties get() { public Project get() {
Properties props = new Properties(); return getProject();
props.putAll(project.getProperties());
return props;
} }
}; };
public ComputeTask(Map<URI, ComputeServiceContext> computeMap) { public ComputeTask(@Nullable Map<URI, ComputeServiceContext> computeMap) {
this.computeMap = computeMap; this.computeMap = computeMap != null ? computeMap : buildComputeMap(projectProvider);
} }
public ComputeTask() throws IOException { public ComputeTask() throws IOException {
this(buildComputeMap()); this(null);
}
static Map<URI, ComputeServiceContext> buildComputeMap() {
return new MapMaker().makeComputingMap(new Function<URI, ComputeServiceContext>() {
@Override
public ComputeServiceContext apply(URI from) {
try {
return new ComputeServiceContextFactory().createContext(from, defaultModulesProvider
.get(), defaultPropertiesProvider.get());
} catch (IOException e) {
throw new RuntimeException(e);
}
}
});
} }
public static enum Action { public static enum Action {
CREATE, GET, LIST, LIST_DETAILS, DESTROY CREATE, GET, LIST, LIST_DETAILS, DESTROY
} }
private String provider;
private String action;
private NodeElement nodeElement;
/** /**
* @return the configured {@link NodeElement} element * makes a connection to the compute service and invokes
*/ */
public final NodeElement createNode() {
if (getNode() == null) {
this.nodeElement = new NodeElement();
}
return this.nodeElement;
}
public NodeElement getNode() {
return this.nodeElement;
}
public void execute() throws BuildException { public void execute() throws BuildException {
ComputeTask.project = getProject(); ComputeServiceContext context = computeMap.get(HttpUtils.createUri(provider));
Action action = Action.valueOf(CaseFormat.LOWER_HYPHEN.to(CaseFormat.UPPER_UNDERSCORE, Action action = Action.valueOf(CaseFormat.LOWER_HYPHEN.to(CaseFormat.UPPER_UNDERSCORE,
this.action)); this.action));
ComputeServiceContext context = computeMap.get(HttpUtils.createUri(provider));
try { try {
ComputeService computeService = context.getComputeService(); invokeActionOnService(action, context.getComputeService());
switch (action) {
case CREATE:
case GET:
case DESTROY:
if (nodeElement != null) {
switch (action) {
case CREATE:
create(computeService);
break;
case GET:
get(computeService);
break;
case DESTROY:
destroy(computeService);
break;
}
} else {
this.log("missing node element for action: " + action, Project.MSG_ERR);
}
break;
case LIST:
log("list");
for (ComputeMetadata node : computeService.listNodes()) {
log(String.format(" location=%s, id=%s, name=%s", node.getLocation(), node
.getId(), node.getName()));
}
break;
case LIST_DETAILS:
log("list details");
for (ComputeMetadata node : computeService.listNodes()) {// TODO
// parallel
logDetails(computeService, node);
}
break;
default:
this.log("bad action: " + action, Project.MSG_ERR);
}
} finally { } finally {
context.close(); context.close();
} }
} }
private void create(ComputeService computeService) { private void invokeActionOnService(Action action, ComputeService computeService) {
log(String.format("create name: %s, size: %s, os: %s", nodeElement.getName(), nodeElement switch (action) {
.getSize(), nodeElement.getOs())); case CREATE:
Template template = computeService.createTemplateInLocation(nodeElement.getLocation()); case GET:
template.os(OperatingSystem.valueOf(nodeElement.getOs())); case DESTROY:
if (nodeElement.getSize().equalsIgnoreCase("smallest")) { if (nodeElement != null) {
template.smallest(); switch (action) {
} else if (nodeElement.getSize().equalsIgnoreCase("fastest")) { case CREATE:
template.fastest(); create(computeService);
} else if (nodeElement.getSize().equalsIgnoreCase("biggest")) { break;
template.biggest(); case GET:
} else { get(computeService);
throw new BuildException("size: " + nodeElement.getSize() break;
+ " not supported. valid sizes are smallest, fastest, biggest"); case DESTROY:
destroy(computeService);
break;
}
} else {
this.log("missing node element for action: " + action, Project.MSG_ERR);
}
break;
case LIST:
list(computeService);
break;
case LIST_DETAILS:
listDetails(computeService);
break;
default:
this.log("bad action: " + action, Project.MSG_ERR);
} }
CreateNodeResponse createdNode = computeService.runNode(nodeElement.getName(), template); }
private void listDetails(ComputeService computeService) {
log("list details");
for (ComputeMetadata node : computeService.listNodes()) {// TODO
// parallel
logDetails(computeService, node);
}
}
private void list(ComputeService computeService) {
log("list");
for (ComputeMetadata node : computeService.listNodes()) {
log(String.format(" location=%s, id=%s, name=%s", node.getLocation(), node.getId(), node
.getName()));
}
}
private void create(ComputeService computeService) {
String name = nodeElement.getName();
log(String.format("create name: %s, size: %s, os: %s", name, nodeElement.getSize(),
nodeElement.getOs()));
Template template = createTemplateFromElement(nodeElement, computeService);
RunNodeOptions options = getNodeOptionsFromElement(nodeElement);
CreateNodeResponse createdNode = computeService.runNode(name, template, options);
logNodeDetails(createdNode);
addNodeDetailsAsProjectProperties(createdNode);
}
private void logNodeDetails(CreateNodeResponse createdNode) {
log(String.format(" id=%s, name=%s, connection=%s://%s:%s@%s:%d", createdNode.getId(), log(String.format(" id=%s, name=%s, connection=%s://%s:%s@%s:%d", createdNode.getId(),
createdNode.getName(), createdNode.getLoginType().toString().toLowerCase(), createdNode.getName(), createdNode.getLoginType().toString().toLowerCase(),
createdNode.getCredentials().account, createdNode.getCredentials().key, createdNode createdNode.getCredentials().account, createdNode.getCredentials().key, createdNode
.getPublicAddresses().first().getHostAddress(), createdNode.getLoginPort())); .getPublicAddresses().first().getHostAddress(), createdNode.getLoginPort()));
}
private void addNodeDetailsAsProjectProperties(CreateNodeResponse createdNode) {
if (nodeElement.getIdproperty() != null) if (nodeElement.getIdproperty() != null)
getProject().setProperty(nodeElement.getIdproperty(), createdNode.getId()); getProject().setProperty(nodeElement.getIdproperty(), createdNode.getId());
if (nodeElement.getHostproperty() != null) if (nodeElement.getHostproperty() != null)
getProject().setProperty(nodeElement.getHostproperty(), getProject().setProperty(nodeElement.getHostproperty(),
createdNode.getPublicAddresses().first().getHostAddress()); createdNode.getPublicAddresses().first().getHostAddress());
if (nodeElement.getKeyfile() != null if (nodeElement.getKeyfile() != null && isKeyAuth(createdNode))
&& createdNode.getCredentials().key.startsWith("-----BEGIN RSA PRIVATE KEY-----"))
try { try {
Files.write(createdNode.getCredentials().key, new File(nodeElement.getKeyfile()), Files.write(createdNode.getCredentials().key, new File(nodeElement.getKeyfile()),
Charset.defaultCharset()); Charset.defaultCharset());
} catch (IOException e) { } catch (IOException e) {
throw new BuildException(e); throw new BuildException(e);
} }
if (nodeElement.getPasswordproperty() != null if (nodeElement.getPasswordproperty() != null && !isKeyAuth(createdNode))
&& !createdNode.getCredentials().key.startsWith("-----BEGIN RSA PRIVATE KEY-----"))
getProject().setProperty(nodeElement.getPasswordproperty(), getProject().setProperty(nodeElement.getPasswordproperty(),
createdNode.getCredentials().key); createdNode.getCredentials().key);
if (nodeElement.getUsernameproperty() != null) if (nodeElement.getUsernameproperty() != null)
@ -230,8 +192,8 @@ public class ComputeTask extends Task {
private void destroy(ComputeService computeService) { private void destroy(ComputeService computeService) {
log(String.format("destroy name: %s", nodeElement.getName())); log(String.format("destroy name: %s", nodeElement.getName()));
Iterable<? extends ComputeMetadata> nodesThatMatch = ComputeUtils.filterByName(computeService Iterable<? extends ComputeMetadata> nodesThatMatch = filterByName(computeService.listNodes(),
.listNodes(), nodeElement.getName()); nodeElement.getName());
for (ComputeMetadata node : nodesThatMatch) { for (ComputeMetadata node : nodesThatMatch) {
log(String.format(" destroying id=%s, name=%s", node.getId(), node.getName())); log(String.format(" destroying id=%s, name=%s", node.getId(), node.getName()));
computeService.destroyNode(node); computeService.destroyNode(node);
@ -240,8 +202,8 @@ public class ComputeTask extends Task {
private void get(ComputeService computeService) { private void get(ComputeService computeService) {
log(String.format("get name: %s", nodeElement.getName())); log(String.format("get name: %s", nodeElement.getName()));
Iterable<? extends ComputeMetadata> nodesThatMatch = ComputeUtils.filterByName(computeService Iterable<? extends ComputeMetadata> nodesThatMatch = filterByName(computeService.listNodes(),
.listNodes(), nodeElement.getName()); nodeElement.getName());
for (ComputeMetadata node : nodesThatMatch) { for (ComputeMetadata node : nodesThatMatch) {
logDetails(computeService, node); logDetails(computeService, node);
} }
@ -257,12 +219,18 @@ public class ComputeTask extends Task {
.getPrivateAddresses()), metadata.getExtra())); .getPrivateAddresses()), metadata.getExtra()));
} }
public static String ipOrEmptyString(SortedSet<InetAddress> set) { /**
if (set.size() > 0) { * @return the configured {@link NodeElement} element
return set.last().getHostAddress(); */
} else { public final NodeElement createNode() {
return ""; if (getNode() == null) {
this.nodeElement = new NodeElement();
} }
return this.nodeElement;
}
public NodeElement getNode() {
return this.nodeElement;
} }
public String getAction() { public String getAction() {

View File

@ -0,0 +1,143 @@
/**
*
* Copyright (C) 2009 Global Cloud Specialists, Inc. <info@globalcloudspecialists.com>
*
* ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF 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.tools.ant.taskdefs.compute;
import java.io.IOException;
import java.net.InetAddress;
import java.net.URI;
import java.util.Map;
import java.util.Properties;
import java.util.SortedSet;
import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.Project;
import org.jclouds.compute.ComputeService;
import org.jclouds.compute.ComputeServiceContext;
import org.jclouds.compute.ComputeServiceContextFactory;
import org.jclouds.compute.domain.OperatingSystem;
import org.jclouds.compute.domain.Template;
import org.jclouds.compute.options.RunNodeOptions;
import org.jclouds.compute.reference.ComputeServiceConstants;
import org.jclouds.tools.ant.logging.config.AntLoggingModule;
import com.google.common.base.Function;
import com.google.common.base.Splitter;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import com.google.common.collect.MapMaker;
import com.google.common.io.Files;
import com.google.inject.Module;
import com.google.inject.Provider;
/**
*
* @author Adrian Cole
*/
public class ComputeTaskUtils {
/**
*
* Creates a Map that associates a uri with a live connection to the compute provider. This is
* done on-demand.
*
* @param projectProvider
* allows access to the ant project to retrieve default properties needed for compute
* providers.
*/
static Map<URI, ComputeServiceContext> buildComputeMap(final Provider<Project> projectProvider) {
return new MapMaker().makeComputingMap(new Function<URI, ComputeServiceContext>() {
@SuppressWarnings("unchecked")
@Override
public ComputeServiceContext apply(URI from) {
try {
Properties props = new Properties();
props.putAll(projectProvider.get().getProperties());
return new ComputeServiceContextFactory().createContext(from, ImmutableSet
.of((Module) new AntLoggingModule(projectProvider.get(),
ComputeServiceConstants.COMPUTE_LOGGER)), props);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
});
}
static Template createTemplateFromElement(NodeElement nodeElement, ComputeService computeService) {
Template template = computeService.createTemplateInLocation(nodeElement.getLocation());
template.os(OperatingSystem.valueOf(nodeElement.getOs()));
addSizeFromElementToTemplate(nodeElement, template);
return template;
}
static void addSizeFromElementToTemplate(NodeElement nodeElement, Template template) {
if (nodeElement.getSize().equalsIgnoreCase("smallest")) {
template.smallest();
} else if (nodeElement.getSize().equalsIgnoreCase("fastest")) {
template.fastest();
} else if (nodeElement.getSize().equalsIgnoreCase("biggest")) {
template.biggest();
} else {
throw new BuildException("size: " + nodeElement.getSize()
+ " not supported. valid sizes are smallest, fastest, biggest");
}
}
static RunNodeOptions getNodeOptionsFromElement(NodeElement nodeElement) {
RunNodeOptions options = new RunNodeOptions()
.openPorts(getPortsToOpenFromElement(nodeElement));
addRunScriptToOptionsIfPresentInNodeElement(nodeElement, options);
return options;
}
static void addRunScriptToOptionsIfPresentInNodeElement(NodeElement nodeElement,
RunNodeOptions options) {
if (nodeElement.getRunscript() != null)
try {
options.runScript(Files.toByteArray(nodeElement.getRunscript()));
} catch (IOException e) {
throw new BuildException(e);
}
}
static String ipOrEmptyString(SortedSet<InetAddress> set) {
if (set.size() > 0) {
return set.last().getHostAddress();
} else {
return "";
}
}
static int[] getPortsToOpenFromElement(NodeElement nodeElement) {
Iterable<String> portStrings = Splitter.on(',').split(nodeElement.getOpenports());
int[] ports = new int[Iterables.size(portStrings)];
int i = 0;
for (String port : portStrings) {
ports[i++] = Integer.parseInt(port);
}
return ports;
}
}

View File

@ -18,6 +18,8 @@
*/ */
package org.jclouds.tools.ant.taskdefs.compute; package org.jclouds.tools.ant.taskdefs.compute;
import java.io.File;
/** /**
* @author Adrian Cole * @author Adrian Cole
* @author Ivan Meredith * @author Ivan Meredith
@ -26,12 +28,14 @@ public class NodeElement {
private String name; private String name;
private String size; private String size;
private String os; private String os;
private String openports = "22";
private String passwordproperty; private String passwordproperty;
private String keyfi1le; private String keyfile;
private String hostproperty; private String hostproperty;
private String idproperty; private String idproperty;
private String usernameproperty; private String usernameproperty;
private String location = "default"; private String location = "default";
private File runscript;
public String getLocation() { public String getLocation() {
return location; return location;
@ -40,7 +44,7 @@ public class NodeElement {
public void setLocation(String location) { public void setLocation(String location) {
this.location = location; this.location = location;
} }
String getName() { String getName() {
return name; return name;
} }
@ -101,11 +105,11 @@ public class NodeElement {
* The name of a file under which to store the DSA key of the user (if supported) * The name of a file under which to store the DSA key of the user (if supported)
*/ */
public void setKeyfile(String keyfile) { public void setKeyfile(String keyfile) {
this.keyfi1le = keyfile; this.keyfile = keyfile;
} }
String getKeyfile() { String getKeyfile() {
return keyfi1le; return keyfile;
} }
public void setSize(String size) { public void setSize(String size) {
@ -124,4 +128,20 @@ public class NodeElement {
return os; return os;
} }
public void setRunscript(File runscript) {
this.runscript = runscript;
}
public File getRunscript() {
return runscript;
}
public void setOpenports(String openports) {
this.openports = openports;
}
public String getOpenports() {
return openports;
}
} }

View File

@ -1,171 +0,0 @@
/**
*
* 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;
import static com.google.common.base.Preconditions.checkArgument;
import java.net.InetAddress;
import java.util.Map;
import javax.annotation.Resource;
import javax.inject.Inject;
import org.jclouds.compute.domain.OperatingSystem;
import org.jclouds.logging.Logger;
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.Iterables;
/**
*
* @author Adrian Cole
*/
public class VCloudComputeClient {
@Resource
protected Logger logger = Logger.NULL;
private final Predicate<String> taskTester;
private final VCloudClient tmClient;
@Inject
public VCloudComputeClient(VCloudClient tmClient, Predicate<String> successTester) {
this.tmClient = tmClient;
this.taskTester = successTester;
}
private Map<OperatingSystem, String> imageCatalogIdMap = ImmutableMap
.<OperatingSystem, String> builder().put(OperatingSystem.CENTOS, "1").put(
OperatingSystem.RHEL, "8").put(OperatingSystem.UBUNTU, "11").build();
public Map<String, String> start(String name, OperatingSystem image, int minCores, int minMegs,
long diskSize, Map<String, String> properties) {
checkArgument(imageCatalogIdMap.containsKey(image), "image not configured: " + image);
String templateId = imageCatalogIdMap.get(image);
String vDCId = tmClient.getDefaultVDC().getId();
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);
VApp vAppResponse = tmClient.instantiateVAppTemplateInVDC(vDCId, name, templateId,
InstantiateVAppTemplateOptions.Builder.processorCount(minCores).memory(minMegs)
.disk(diskSize).productProperties(properties));
logger.debug("<< instantiated VApp(%s)", vAppResponse.getId());
logger.debug(">> deploying vApp(%s)", vAppResponse.getId());
VApp vApp = blockUntilVAppStatusOrThrowException(vAppResponse, tmClient
.deployVApp(vAppResponse.getId()), "deploy", VAppStatus.ON);// TODO, I'm not sure
// this should be on
// already
// logger.debug("<< deployed vApp(%s)", vApp.getId());
//
// logger.debug(">> powering vApp(%s)", vApp.getId());
// vApp = blockUntilVAppStatusOrThrowException(vApp, tmClient.powerOnVApp(vApp.getId()),
// "powerOn", VAppStatus.ON);
logger.debug("<< on vApp(%s)", vApp.getId());
return ImmutableMap.<String, String> of("id", vApp.getId(), "username", null, "password",
null);
}
/**
*
* @throws ElementNotFoundException
* if no address is configured
*/
public InetAddress getAnyPrivateAddress(String id) {
VApp vApp = tmClient.getVApp(id);
return Iterables.getLast(vApp.getNetworkToAddresses().values());
}
public void reboot(String id) {
VApp vApp = tmClient.getVApp(id);
logger.debug(">> rebooting vApp(%s)", vApp.getId());
blockUntilVAppStatusOrThrowException(vApp, tmClient.resetVApp(vApp.getId()), "reset",
VAppStatus.ON);
logger.debug("<< on vApp(%s)", vApp.getId());
}
public void stop(String id) {
VApp vApp = tmClient.getVApp(id);
if (vApp.getStatus() != VAppStatus.OFF) {
logger.debug(">> powering off vApp(%s), current status: %s", vApp.getId(), vApp
.getStatus());
blockUntilVAppStatusOrThrowException(vApp, tmClient.powerOffVApp(vApp.getId()),
"powerOff", VAppStatus.OFF);
logger.debug("<< off vApp(%s)", vApp.getId());
}
logger.debug(">> deleting vApp(%s)", vApp.getId());
tmClient.deleteVApp(id);
logger.debug("<< deleted vApp(%s)", vApp.getId());
}
private VApp blockUntilVAppStatusOrThrowException(VApp vApp, Task deployTask, String taskType,
VAppStatus expectedStatus) {
if (!taskTester.apply(deployTask.getId())) {
throw new TaskException(taskType, vApp, deployTask);
}
vApp = tmClient.getVApp(vApp.getId());
if (vApp.getStatus() != expectedStatus) {
throw new VAppException(String.format("vApp %s status %s should be %s after %s", vApp
.getId(), vApp.getStatus(), expectedStatus, 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;
}
}
}

View File

@ -1,158 +0,0 @@
/**
*
* 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;
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.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 VCloudComputeClientLiveTest}
*
* @author Adrian Cole
*/
@Test(groups = "live", sequential = true, testName = "vcloud.VCloudClientLiveTest")
public class VCloudComputeClientLiveTest {
VCloudComputeClient client;
VCloudClient tmClient;
private String id;
private InetAddress privateAddress;
public static final String PREFIX = (System.getProperty("user.name") + "-vcloud").replaceAll(
"\\.", "");
private static class Expectation {
final long hardDisk;
final String os;
public Expectation(long hardDisk, String os) {
this.hardDisk = hardDisk;
this.os = os;
}
}
private Map<OperatingSystem, Expectation> expectationMap = ImmutableMap
.<OperatingSystem, Expectation> builder().put(OperatingSystem.CENTOS,
new Expectation(4194304 / 2 * 10, "Red Hat Enterprise Linux 5 (64-bit)")).put(
OperatingSystem.RHEL,
new Expectation(4194304 / 2 * 10, "Red Hat Enterprise Linux 5 (64-bit)")).put(
OperatingSystem.UBUNTU, new Expectation(4194304, "Ubuntu Linux (32-bit)"))
.build();
private Predicate<InetAddress> addressTester;
@Test
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 = client.start(serverName, toTest, processorCount, memory, disk, properties).get("id");
Expectation expectation = expectationMap.get(toTest);
VApp vApp = tmClient.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_CAMEL, toTest.toString())
.substring(0,
toTest.toString().length() - 1 <= 15 ? toTest.toString().length() - 1 : 14);
return serverName;
}
@Test(dependsOnMethods = "testPowerOn")
public void testGetAnyPrivateAddress() {
privateAddress = client.getAnyPrivateAddress(id);
assert !addressTester.apply(privateAddress);
}
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)
client.stop(id);
}
@BeforeGroups(groups = { "live" })
public void setupClient() {
String endpoint = checkNotNull(System.getProperty("jclouds.test.endpoint"),
"jclouds.test.endpoint");
String account = checkNotNull(System.getProperty("jclouds.test.user"), "jclouds.test.user");
String key = checkNotNull(System.getProperty("jclouds.test.key"), "jclouds.test.key");
Injector injector = new VCloudContextBuilder(new VCloudPropertiesBuilder(
URI.create(endpoint), account, key).build()).withModules(new Log4JLoggingModule(),
new JschSshClientModule()).buildInjector();
client = injector.getInstance(VCloudComputeClient.class);
tmClient = injector.getInstance(VCloudClient.class);
addressTester = injector.getInstance(Key.get(new TypeLiteral<Predicate<InetAddress>>() {
}));
}
}

View File

@ -1,164 +0,0 @@
/**
*
* 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.hostingdotcom.compute;
import java.net.InetAddress;
import java.util.Map;
import javax.annotation.Resource;
import javax.inject.Inject;
import org.jclouds.logging.Logger;
import org.jclouds.vcloud.domain.Task;
import org.jclouds.vcloud.domain.VApp;
import org.jclouds.vcloud.domain.VAppStatus;
import org.jclouds.vcloud.hostingdotcom.HostingDotComVCloudClient;
import org.jclouds.vcloud.hostingdotcom.domain.HostingDotComVApp;
import org.jclouds.vcloud.options.InstantiateVAppTemplateOptions;
import com.google.common.base.Predicate;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Iterables;
/**
*
* @author Adrian Cole
*/
public class HostingDotComVCloudComputeClient {
@Resource
protected Logger logger = Logger.NULL;
private final Predicate<String> taskTester;
private final HostingDotComVCloudClient tmClient;
@Inject
public HostingDotComVCloudComputeClient(HostingDotComVCloudClient tmClient,
Predicate<String> successTester) {
this.tmClient = tmClient;
this.taskTester = successTester;
}
public Map<String, String> start(String vDCId, String name, String templateId, int minCores,
int minMegs, long diskSize, Map<String, String> properties) {
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);
HostingDotComVApp vAppResponse = tmClient.instantiateVAppTemplateInVDC(vDCId, name,
templateId, InstantiateVAppTemplateOptions.Builder.processorCount(minCores).memory(
minMegs).disk(diskSize).productProperties(properties));
logger.debug("<< instantiated VApp(%s)", vAppResponse.getId());
logger.debug(">> deploying vApp(%s)", vAppResponse.getId());
VApp vApp = blockUntilVAppStatusOrThrowException(vAppResponse, tmClient
.deployVApp(vAppResponse.getId()), "deploy", VAppStatus.ON);// TODO, I'm not sure
// this should be on
// already
// logger.debug("<< deployed vApp(%s)", vApp.getId());
//
// logger.debug(">> powering vApp(%s)", vApp.getId());
// vApp = blockUntilVAppStatusOrThrowException(vApp, tmClient.powerOnVApp(vApp.getId()),
// "powerOn", VAppStatus.ON);
logger.debug("<< on vApp(%s)", vApp.getId());
return ImmutableMap.<String, String> of("id", vApp.getId(), "username", vAppResponse
.getUsername(), "password", vAppResponse.getPassword());
}
/**
*
* @throws ElementNotFoundException
* if no address is configured
*/
public InetAddress getAnyPrivateAddress(String id) {
VApp vApp = tmClient.getVApp(id);
return Iterables.getLast(vApp.getNetworkToAddresses().values());
}
public void reboot(String id) {
VApp vApp = tmClient.getVApp(id);
logger.debug(">> rebooting vApp(%s)", vApp.getId());
blockUntilVAppStatusOrThrowException(vApp, tmClient.resetVApp(vApp.getId()), "reset",
VAppStatus.ON);
logger.debug("<< on vApp(%s)", vApp.getId());
}
public void stop(String id) {
VApp vApp = tmClient.getVApp(id);
if (vApp.getStatus() != VAppStatus.OFF) {
logger.debug(">> powering off vApp(%s), current status: %s", vApp.getId(), vApp
.getStatus());
blockUntilVAppStatusOrThrowException(vApp, tmClient.powerOffVApp(vApp.getId()),
"powerOff", VAppStatus.OFF);
logger.debug("<< off vApp(%s)", vApp.getId());
}
logger.debug(">> deleting vApp(%s)", vApp.getId());
tmClient.deleteVApp(id);
logger.debug("<< deleted vApp(%s)", vApp.getId());
}
private VApp blockUntilVAppStatusOrThrowException(VApp vApp, Task deployTask, String taskType,
VAppStatus expectedStatus) {
if (!taskTester.apply(deployTask.getId())) {
throw new TaskException(taskType, vApp, deployTask);
}
vApp = tmClient.getVApp(vApp.getId());
if (vApp.getStatus() != expectedStatus) {
throw new VAppException(String.format("vApp %s status %s should be %s after %s", vApp
.getId(), vApp.getStatus(), expectedStatus, 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;
}
}
}

View File

@ -1,155 +1,48 @@
/**
*
* 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.hostingdotcom.compute; package org.jclouds.vcloud.hostingdotcom.compute;
import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkState;
import static com.google.common.base.Preconditions.checkNotNull;
import java.net.InetAddress; import java.net.InetSocketAddress;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.SortedSet;
import javax.annotation.Resource;
import javax.inject.Inject; import javax.inject.Inject;
import javax.inject.Named;
import javax.inject.Provider; import javax.inject.Provider;
import javax.inject.Singleton; 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.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.Size;
import org.jclouds.compute.domain.Template; import org.jclouds.vcloud.VCloudClient;
import org.jclouds.compute.domain.internal.CreateNodeResponseImpl; import org.jclouds.vcloud.compute.VCloudComputeService;
import org.jclouds.compute.domain.internal.NodeMetadataImpl; import org.jclouds.vcloud.compute.VCloudTemplate;
import org.jclouds.compute.reference.ComputeServiceConstants;
import org.jclouds.domain.Credentials;
import org.jclouds.logging.Logger;
import org.jclouds.vcloud.VCloudMediaType;
import org.jclouds.vcloud.domain.NamedResource;
import org.jclouds.vcloud.domain.VApp; import org.jclouds.vcloud.domain.VApp;
import org.jclouds.vcloud.domain.VAppStatus; import org.jclouds.vcloud.hostingdotcom.domain.HostingDotComVApp;
import org.jclouds.vcloud.hostingdotcom.HostingDotComVCloudClient;
import com.google.common.base.Predicate;
import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Sets;
import com.google.inject.internal.ImmutableSet;
/** /**
* @author Adrian Cole * @author Adrian Cole
*/ */
@Singleton @Singleton
public class HostingDotComVCloudComputeService implements ComputeService { public class HostingDotComVCloudComputeService extends VCloudComputeService {
@Resource
@Named(ComputeServiceConstants.COMPUTE_LOGGER)
protected Logger logger = Logger.NULL;
private final HostingDotComVCloudComputeClient computeClient;
private final HostingDotComVCloudClient client;
private final Set<? extends Image> images;
private final Set<? extends Size> sizes;
private final Provider<Set<HostingDotComVCloudTemplate>> templates;
private 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 @Inject
public HostingDotComVCloudComputeService(HostingDotComVCloudClient client, public HostingDotComVCloudComputeService(VCloudClient client,
HostingDotComVCloudComputeClient computeClient, Set<? extends Image> images, Provider<Set<? extends Image>> images, Provider<SortedSet<? extends Size>> sizes,
Set<? extends Size> sizes, Provider<Set<HostingDotComVCloudTemplate>> templates) { Provider<Set<? extends VCloudTemplate>> templates, Predicate<String> successTester,
this.client = client; Predicate<InetSocketAddress> socketTester) {
this.computeClient = computeClient; super(client, images, sizes, templates, successTester, socketTester);
this.images = images;
this.sizes = sizes;
this.templates = templates;
} }
@Override @Override
public CreateNodeResponse runNode(String name, Template template) { protected Map<String, String> parseResponse(VApp vAppResponse) {
checkNotNull(template.getImage().getLocation(), "location"); checkState(vAppResponse instanceof HostingDotComVApp,
Map<String, String> metaMap = computeClient.start(template.getImage().getLocation(), name, "bad configuration, vApp should be an instance of "
template.getImage().getId(), template.getSize().getCores(), template.getSize() + HostingDotComVApp.class.getName());
.getRam(), template.getSize().getDisk(), ImmutableMap.<String, String> of()); HostingDotComVApp hVApp = HostingDotComVApp.class.cast(vAppResponse);
VApp vApp = client.getVApp(metaMap.get("id")); return ImmutableMap.<String, String> of("id", vAppResponse.getId(), "username", hVApp
return new CreateNodeResponseImpl(vApp.getId(), vApp.getName(), template.getImage() .getUsername(), "password", hVApp.getPassword());
.getLocation(), vApp.getLocation(), ImmutableMap.<String, String> of(),
vAppStatusToNodeState.get(vApp.getStatus()), vApp.getNetworkToAddresses().values(),
ImmutableSet.<InetAddress> of(), 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());
computeClient.stop(checkNotNull(node.getId(), "node.id"));
}
@Override
public Template createTemplateInLocation(String location) {
return new HostingDotComVCloudTemplate(client, images, sizes, location);
}
@Override
public Set<? extends Size> listSizes() {
return sizes;
}
@Override
public Set<? extends Template> listTemplates() {
return templates.get();
} }
} }

View File

@ -20,22 +20,15 @@ package org.jclouds.vcloud.hostingdotcom.compute;
import java.util.List; import java.util.List;
import java.util.Properties; 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.http.config.JavaUrlHttpCommandExecutorServiceModule;
import org.jclouds.logging.jdk.config.JDKLoggingModule; import org.jclouds.logging.jdk.config.JDKLoggingModule;
import org.jclouds.vcloud.hostingdotcom.HostingDotComVCloudAsyncClient; import org.jclouds.vcloud.compute.VCloudComputeServiceContextBuilder;
import org.jclouds.vcloud.hostingdotcom.HostingDotComVCloudClient;
import org.jclouds.vcloud.hostingdotcom.compute.config.HostingDotComVCloudComputeServiceContextModule; import org.jclouds.vcloud.hostingdotcom.compute.config.HostingDotComVCloudComputeServiceContextModule;
import org.jclouds.vcloud.hostingdotcom.config.HostingDotComVCloudRestClientModule; import org.jclouds.vcloud.hostingdotcom.config.HostingDotComVCloudRestClientModule;
import com.google.inject.Injector; import com.google.inject.Injector;
import com.google.inject.Key;
import com.google.inject.Module; import com.google.inject.Module;
import com.google.inject.TypeLiteral;
/** /**
* Creates {@link HostingDotComVCloudComputeServiceContext} or {@link Injector} instances based on * Creates {@link HostingDotComVCloudComputeServiceContext} or {@link Injector} instances based on
@ -51,23 +44,10 @@ import com.google.inject.TypeLiteral;
* @see HostingDotComVCloudComputeServiceContext * @see HostingDotComVCloudComputeServiceContext
*/ */
public class HostingDotComVCloudComputeServiceContextBuilder extends public class HostingDotComVCloudComputeServiceContextBuilder extends
ComputeServiceContextBuilder<HostingDotComVCloudAsyncClient, HostingDotComVCloudClient> { VCloudComputeServiceContextBuilder {
public HostingDotComVCloudComputeServiceContextBuilder(Properties props) { public HostingDotComVCloudComputeServiceContextBuilder(Properties props) {
super(new TypeLiteral<HostingDotComVCloudAsyncClient>() { super(props);
}, new TypeLiteral<HostingDotComVCloudClient>() {
}, props);
}
@Override
public HostingDotComVCloudComputeServiceContextBuilder withExecutorService(
ExecutorService service) {
return (HostingDotComVCloudComputeServiceContextBuilder) super.withExecutorService(service);
}
@Override
public HostingDotComVCloudComputeServiceContextBuilder withModules(Module... modules) {
return (HostingDotComVCloudComputeServiceContextBuilder) super.withModules(modules);
} }
@Override @Override
@ -80,14 +60,4 @@ public class HostingDotComVCloudComputeServiceContextBuilder extends
modules.add(new HostingDotComVCloudRestClientModule()); modules.add(new HostingDotComVCloudRestClientModule());
} }
@Override
public ComputeServiceContext buildComputeServiceContext() {
// need the generic type information
return (ComputeServiceContext) this
.buildInjector()
.getInstance(
Key
.get(new TypeLiteral<ComputeServiceContextImpl<HostingDotComVCloudAsyncClient, HostingDotComVCloudClient>>() {
}));
}
} }

View File

@ -1,180 +0,0 @@
package org.jclouds.vcloud.hostingdotcom.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.hostingdotcom.HostingDotComVCloudClient;
import com.google.common.collect.Iterables;
/**
*
* @author Adrian Cole
*/
public class HostingDotComVCloudTemplate implements Template {
private final HostingDotComVCloudClient 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 HostingDotComVCloudTemplate(HostingDotComVCloudClient 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);
}
HostingDotComVCloudTemplate(HostingDotComVCloudClient 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 HostingDotComVCloudTemplate(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;
HostingDotComVCloudTemplate other = (HostingDotComVCloudTemplate) 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 "HostingDotComVCloudTemplate [image=" + image + ", operatingSystem=" + operatingSystem
+ ", size=" + size + ", vDC=" + vDC + "]";
}
}

View File

@ -18,39 +18,11 @@
*/ */
package org.jclouds.vcloud.hostingdotcom.compute.config; package org.jclouds.vcloud.hostingdotcom.compute.config;
import java.util.Set;
import javax.annotation.Resource;
import javax.inject.Named;
import javax.inject.Singleton;
import org.jclouds.compute.ComputeService; import org.jclouds.compute.ComputeService;
import org.jclouds.compute.ComputeServiceContext; import org.jclouds.vcloud.compute.config.VCloudComputeServiceContextModule;
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.VCloudClient;
import org.jclouds.vcloud.VCloudMediaType;
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 org.jclouds.vcloud.hostingdotcom.HostingDotComVCloudAsyncClient;
import org.jclouds.vcloud.hostingdotcom.HostingDotComVCloudClient;
import org.jclouds.vcloud.hostingdotcom.compute.HostingDotComVCloudComputeService; import org.jclouds.vcloud.hostingdotcom.compute.HostingDotComVCloudComputeService;
import org.jclouds.vcloud.hostingdotcom.compute.HostingDotComVCloudTemplate;
import org.jclouds.vcloud.hostingdotcom.config.HostingDotComVCloudContextModule;
import com.google.common.collect.ImmutableSet; import com.google.inject.Injector;
import com.google.common.collect.Sets;
import com.google.inject.Provides;
/** /**
* Configures the {@link HostingDotComVCloudComputeServiceContext}; requires * Configures the {@link HostingDotComVCloudComputeServiceContext}; requires
@ -59,81 +31,16 @@ import com.google.inject.Provides;
* @author Adrian Cole * @author Adrian Cole
*/ */
public class HostingDotComVCloudComputeServiceContextModule extends public class HostingDotComVCloudComputeServiceContextModule extends
HostingDotComVCloudContextModule { VCloudComputeServiceContextModule {
@Override @Override
protected void configure() { protected void configure() {
super.configure(); super.configure();
bind(ComputeService.class).to(HostingDotComVCloudComputeService.class).asEagerSingleton();
} }
@Provides @Override
@Singleton protected ComputeService provideComputeService(Injector injector) {
ComputeServiceContext provideContext(ComputeService computeService, return injector.getInstance(HostingDotComVCloudComputeService.class);
RestContext<HostingDotComVCloudAsyncClient, HostingDotComVCloudClient> context) {
return new ComputeServiceContextImpl<HostingDotComVCloudAsyncClient, HostingDotComVCloudClient>(
computeService, context);
}
private static class LogHolder {
@Resource
@Named(ComputeServiceConstants.COMPUTE_LOGGER)
protected Logger logger = Logger.NULL;
}
@Provides
@Singleton
Set<? extends Image> provideImages(VCloudClient client, LogHolder holder) {
Set<Image> images = Sets.newLinkedHashSet();
holder.logger.debug(">> providing images");
Catalog response = client.getDefaultCatalog();
String vDC = client.getDefaultVDC().getId();
for (NamedResource resource : response.values()) {
if (resource.getType().equals(VCloudMediaType.CATALOGITEM_XML)) {
CatalogItem item = client.getCatalogItem(resource.getId());
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;
if (item.getEntity().getType().equals(VCloudMediaType.VAPPTEMPLATE_XML)) {
VAppTemplate template = client.getVAppTemplate(item.getEntity().getId());
images.add(new ImageImpl(resource.getId(), template.getDescription(), myOs, null,
vDC, arch));
}
}
}
holder.logger.debug("<< images(%d)", images.size());
return images;
}
@Provides
@Singleton
Set<? extends Size> provideSizes(HostingDotComVCloudClient client, Set<? extends Image> images,
LogHolder holder) {
return ImmutableSet.<Size> of(new SizeImpl(1, 512, (int) (10l * 1025 * 1024), ImmutableSet
.<Architecture> of(Architecture.X86_32, Architecture.X86_64)));
}
@Provides
@Singleton
Set<HostingDotComVCloudTemplate> provideTemplates(HostingDotComVCloudClient client,
Set<? extends Image> images, Set<? extends Size> sizes, LogHolder holder) {
Set<HostingDotComVCloudTemplate> templates = Sets.newHashSet();
holder.logger.debug(">> generating templates");
String vDC = client.getDefaultVDC().getId();
for (Size size : sizes) {
for (Image image : images) {
templates.add(new HostingDotComVCloudTemplate(client, images, sizes, vDC, size, image
.getOperatingSystem(), image));
}
}
holder.logger.debug("<< templates(%d)", templates.size());
return templates;
} }
} }

View File

@ -19,138 +19,49 @@
package org.jclouds.vcloud.hostingdotcom.compute; package org.jclouds.vcloud.hostingdotcom.compute;
import static com.google.common.base.Preconditions.checkNotNull; 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.InetAddress;
import java.util.Map;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeoutException;
import org.jclouds.compute.domain.OperatingSystem; import org.jclouds.compute.domain.OperatingSystem;
import org.jclouds.logging.log4j.config.Log4JLoggingModule; import org.jclouds.logging.log4j.config.Log4JLoggingModule;
import org.jclouds.ssh.jsch.config.JschSshClientModule; import org.jclouds.ssh.jsch.config.JschSshClientModule;
import org.jclouds.vcloud.domain.ResourceType; import org.jclouds.vcloud.compute.VCloudComputeClientLiveTest;
import org.jclouds.vcloud.domain.VApp;
import org.jclouds.vcloud.domain.VAppStatus;
import org.jclouds.vcloud.hostingdotcom.HostingDotComVCloudClient; import org.jclouds.vcloud.hostingdotcom.HostingDotComVCloudClient;
import org.jclouds.vcloud.hostingdotcom.HostingDotComVCloudContextBuilder;
import org.jclouds.vcloud.hostingdotcom.HostingDotComVCloudPropertiesBuilder; import org.jclouds.vcloud.hostingdotcom.HostingDotComVCloudPropertiesBuilder;
import org.testng.annotations.AfterTest;
import org.testng.annotations.BeforeGroups; import org.testng.annotations.BeforeGroups;
import org.testng.annotations.Test; import org.testng.annotations.Test;
import com.google.common.base.CaseFormat;
import com.google.common.base.Predicate; import com.google.common.base.Predicate;
import com.google.common.collect.Iterables;
import com.google.inject.Injector; import com.google.inject.Injector;
import com.google.inject.Key; import com.google.inject.Key;
import com.google.inject.TypeLiteral; import com.google.inject.TypeLiteral;
import com.google.inject.internal.ImmutableMap; import com.google.inject.internal.ImmutableMap;
/** /**
* Tests behavior of {@code HostingDotComVCloudClient} * Tests behavior of {@code HostingDotComVCloudComputeClient}
* *
* @author Adrian Cole * @author Adrian Cole
*/ */
@Test(groups = "live", enabled = true, sequential = true, testName = "vcloud.HostingDotComVCloudClientLiveTest") @Test(groups = "live", enabled = true, sequential = true, testName = "vcloud.HostingDotComVCloudComputeClientLiveTest")
public class HostingDotComVCloudComputeClientLiveTest { public class HostingDotComVCloudComputeClientLiveTest extends VCloudComputeClientLiveTest {
HostingDotComVCloudComputeClient client;
HostingDotComVCloudClient hostingClient;
private String id;
private InetAddress privateAddress;
public static final String PREFIX = System.getProperty("user.name") + "-terremark";
private static class Expectation {
final long hardDisk;
final String os;
public Expectation(long hardDisk, String os) {
this.hardDisk = hardDisk;
this.os = os;
}
}
private Map<OperatingSystem, Expectation> expectationMap = ImmutableMap
.<OperatingSystem, Expectation> builder().put(OperatingSystem.CENTOS,
new Expectation(4194304 / 2 * 10, "Red Hat Enterprise Linux 5 (64-bit)"))
.build();
private 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 = client.start(hostingClient.getDefaultVDC().getId(), serverName, "3", processorCount,
memory, disk, properties).get("id");
Expectation expectation = expectationMap.get(toTest);
VApp vApp = hostingClient.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 testGetAnyPrivateAddress() {
privateAddress = client.getAnyPrivateAddress(id);
assert !addressTester.apply(privateAddress);
}
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)
client.stop(id);
}
@BeforeGroups(groups = { "live" }) @BeforeGroups(groups = { "live" })
@Override
public void setupClient() { public void setupClient() {
String account = checkNotNull(System.getProperty("jclouds.test.user"), "jclouds.test.user"); String account = checkNotNull(System.getProperty("jclouds.test.user"), "jclouds.test.user");
String key = checkNotNull(System.getProperty("jclouds.test.key"), "jclouds.test.key"); String key = checkNotNull(System.getProperty("jclouds.test.key"), "jclouds.test.key");
Injector injector = new HostingDotComVCloudContextBuilder( Injector injector = new HostingDotComVCloudComputeServiceContextBuilder(
new HostingDotComVCloudPropertiesBuilder(account, key).build()).withModules( new HostingDotComVCloudPropertiesBuilder(account, key).build()).withModules(
new Log4JLoggingModule(), new JschSshClientModule()).buildInjector(); new Log4JLoggingModule(), new JschSshClientModule()).buildInjector();
client = injector.getInstance(HostingDotComVCloudComputeClient.class); computeClient = injector.getInstance(HostingDotComVCloudComputeService.class);
hostingClient = injector.getInstance(HostingDotComVCloudClient.class); client = injector.getInstance(HostingDotComVCloudClient.class);
addressTester = injector.getInstance(Key.get(new TypeLiteral<Predicate<InetAddress>>() { 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";
} }
} }

View File

@ -19,160 +19,30 @@
package org.jclouds.vcloud.hostingdotcom.compute; package org.jclouds.vcloud.hostingdotcom.compute;
import static com.google.common.base.Preconditions.checkNotNull;
import static org.jclouds.compute.domain.OperatingSystem.CENTOS; import static org.jclouds.compute.domain.OperatingSystem.CENTOS;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNotNull;
import java.io.IOException; import org.jclouds.compute.BaseComputeServiceLiveTest;
import java.net.InetSocketAddress;
import java.util.Properties;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import org.jclouds.compute.ComputeService;
import org.jclouds.compute.ComputeServiceContext;
import org.jclouds.compute.ComputeServiceContextFactory;
import org.jclouds.compute.domain.ComputeMetadata;
import org.jclouds.compute.domain.ComputeType;
import org.jclouds.compute.domain.CreateNodeResponse;
import org.jclouds.compute.domain.LoginType;
import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.domain.OperatingSystem;
import org.jclouds.compute.domain.Size;
import org.jclouds.compute.domain.Template;
import org.jclouds.logging.log4j.config.Log4JLoggingModule;
import org.jclouds.predicates.RetryablePredicate;
import org.jclouds.predicates.SocketOpen;
import org.jclouds.ssh.ExecResponse;
import org.jclouds.ssh.SshClient;
import org.jclouds.ssh.SshException;
import org.jclouds.ssh.jsch.config.JschSshClientModule; import org.jclouds.ssh.jsch.config.JschSshClientModule;
import org.testng.annotations.AfterTest; import org.testng.annotations.BeforeClass;
import org.testng.annotations.BeforeGroups;
import org.testng.annotations.Test; import org.testng.annotations.Test;
import com.google.common.collect.ImmutableSet;
import com.google.inject.Guice;
import com.google.inject.Injector;
/** /**
* *
* Generally disabled, as it incurs higher fees.
* *
* @author Adrian Cole * @author Adrian Cole
*/ */
@Test(groups = "live", enabled = true, sequential = true, testName = "compute.HostingDotComVCloudComputeServiceLiveTest") @Test(groups = "live", enabled = true, sequential = true, testName = "compute.HostingDotComVCloudComputeServiceLiveTest")
public class HostingDotComVCloudComputeServiceLiveTest { public class HostingDotComVCloudComputeServiceLiveTest extends BaseComputeServiceLiveTest {
private static final String service = "hostingdotcom"; @BeforeClass
private static final OperatingSystem testOS = CENTOS; @Override
public void setServiceDefaults() {
protected SshClient.Factory sshFactory; service = "hostingdotcom";
private String nodeName = service; testOS = CENTOS;
private RetryablePredicate<InetSocketAddress> socketTester;
private CreateNodeResponse node;
private ComputeServiceContext context;
private ComputeService client;
@BeforeGroups(groups = { "live" })
public void setupClient() throws InterruptedException, ExecutionException, TimeoutException,
IOException {
String user = checkNotNull(System.getProperty("jclouds.test.user"), "jclouds.test.user");
String password = checkNotNull(System.getProperty("jclouds.test.key"), "jclouds.test.key");
context = new ComputeServiceContextFactory().createContext(service, user, password,
ImmutableSet.of(new Log4JLoggingModule()), new Properties());
Injector injector = Guice.createInjector(new JschSshClientModule());
sshFactory = injector.getInstance(SshClient.Factory.class);
SocketOpen socketOpen = injector.getInstance(SocketOpen.class);
socketTester = new RetryablePredicate<InetSocketAddress>(socketOpen, 60, 1, TimeUnit.SECONDS);
injector.injectMembers(socketOpen); // add logger
client = context.getComputeService();
} }
public void testCreate() throws Exception { @Override
Template template = client.createTemplateInLocation("default").os(testOS).smallest(); protected JschSshClientModule getSshModule() {
node = client.runNode(nodeName, template); return new JschSshClientModule();
assertNotNull(node.getId());
assertEquals(node.getLoginPort(), 22);
assertEquals(node.getLoginType(), LoginType.SSH);
assertNotNull(node.getName());
assertEquals(node.getPrivateAddresses().size(), 1);
assertEquals(node.getPublicAddresses().size(), 1);
assertNotNull(node.getCredentials());
assertNotNull(node.getCredentials().account);
assertNotNull(node.getCredentials().key);
sshPing();
} }
@Test(dependsOnMethods = "testCreate") }
public void testGet() throws Exception {
NodeMetadata metadata = client.getNodeMetadata(node);
assertEquals(metadata.getId(), node.getId());
assertEquals(metadata.getLoginPort(), node.getLoginPort());
assertEquals(metadata.getLoginType(), node.getLoginType());
assertEquals(metadata.getName(), node.getName());
assertEquals(metadata.getPrivateAddresses(), node.getPrivateAddresses());
assertEquals(metadata.getPublicAddresses(), node.getPublicAddresses());
}
public void testList() throws Exception {
for (ComputeMetadata node : client.listNodes()) {
assert node.getId() != null;
assert node.getLocation() != null;
assertEquals(node.getType(), ComputeType.NODE);
}
}
public void testListTemplates() throws Exception {
for (Template template : client.listTemplates()) {
assert template.getImage() != null;
System.out.println(template);
}
}
public void testListSizes() throws Exception {
for (Size size : client.listSizes()) {
assert size.getCores() != null;
System.out.println(size);
}
}
private void sshPing() throws IOException {
try {
doCheckKey();
} catch (SshException e) {// try twice in case there is a network timeout
try {
Thread.sleep(10 * 1000);
} catch (InterruptedException e1) {
}
doCheckKey();
}
}
private void doCheckKey() throws IOException {
InetSocketAddress socket = new InetSocketAddress(node.getPublicAddresses().last(), node
.getLoginPort());
socketTester.apply(socket);
SshClient ssh = node.getCredentials().key.startsWith("-----BEGIN RSA PRIVATE KEY-----") ? sshFactory
.create(socket, node.getCredentials().account, node.getCredentials().key.getBytes())
: sshFactory
.create(socket, node.getCredentials().account, node.getCredentials().key);
try {
ssh.connect();
ExecResponse hello = ssh.exec("echo hello");
assertEquals(hello.getOutput().trim(), "hello");
} finally {
if (ssh != null)
ssh.disconnect();
}
}
@AfterTest
void cleanup() throws InterruptedException, ExecutionException, TimeoutException {
if (node != null)
client.destroyNode(node);
context.close();
}
}

View File

@ -86,9 +86,8 @@ public class TerremarkVCloudComputeClient {
properties); properties);
} }
public String start(String vdc, String name, String templateId, int minCores, int minMegs, public String start(String vDCId, String name, String templateId, int minCores, int minMegs,
Map<String, String> properties) { Map<String, String> properties) {
String vDCId = tmClient.getDefaultVDC().getId();
logger logger
.debug( .debug(
">> instantiating vApp vDC(%s) template(%s) name(%s) minCores(%d) minMegs(%d) properties(%s)", ">> instantiating vApp vDC(%s) template(%s) name(%s) minCores(%d) minMegs(%d) properties(%s)",

View File

@ -18,12 +18,13 @@
*/ */
package org.jclouds.vcloud.terremark.compute; package org.jclouds.vcloud.terremark.compute;
import static com.google.common.base.Preconditions.checkArgument; import static org.jclouds.vcloud.terremark.options.AddInternetServiceOptions.Builder.withDescription;
import static com.google.common.base.Preconditions.checkNotNull;
import java.net.InetAddress; import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.SortedSet;
import javax.annotation.Resource; import javax.annotation.Resource;
import javax.inject.Inject; import javax.inject.Inject;
@ -31,127 +32,176 @@ import javax.inject.Named;
import javax.inject.Provider; import javax.inject.Provider;
import javax.inject.Singleton; 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.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.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.reference.ComputeServiceConstants; import org.jclouds.compute.reference.ComputeServiceConstants;
import org.jclouds.domain.Credentials;
import org.jclouds.logging.Logger; import org.jclouds.logging.Logger;
import org.jclouds.vcloud.VCloudMediaType; import org.jclouds.vcloud.compute.VCloudComputeService;
import org.jclouds.vcloud.domain.NamedResource; import org.jclouds.vcloud.compute.VCloudTemplate;
import org.jclouds.vcloud.domain.VApp; import org.jclouds.vcloud.domain.VApp;
import org.jclouds.vcloud.domain.VAppStatus;
import org.jclouds.vcloud.terremark.TerremarkVCloudClient; import org.jclouds.vcloud.terremark.TerremarkVCloudClient;
import org.jclouds.vcloud.terremark.domain.InternetService;
import org.jclouds.vcloud.terremark.domain.Node;
import org.jclouds.vcloud.terremark.domain.Protocol;
import org.jclouds.vcloud.terremark.domain.PublicIpAddress;
import com.google.common.base.Predicate;
import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Iterables;
import com.google.common.collect.Sets; import com.google.common.collect.Sets;
import com.google.inject.internal.ImmutableSet;
/** /**
* @author Adrian Cole * @author Adrian Cole
*/ */
@Singleton @Singleton
public class TerremarkVCloudComputeService implements ComputeService { public class TerremarkVCloudComputeService extends VCloudComputeService {
@Resource @Resource
@Named(ComputeServiceConstants.COMPUTE_LOGGER) @Named(ComputeServiceConstants.COMPUTE_LOGGER)
protected Logger logger = Logger.NULL; protected Logger logger = Logger.NULL;
private final TerremarkVCloudComputeClient computeClient;
private final TerremarkVCloudClient client; private final TerremarkVCloudClient client;
private Set<? extends Image> images;
private Set<? extends Size> sizes;
private Provider<Set<TerremarkVCloudTemplate>> templates;
private 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 @Inject
public TerremarkVCloudComputeService(TerremarkVCloudClient tmClient, public TerremarkVCloudComputeService(TerremarkVCloudClient client,
TerremarkVCloudComputeClient computeClient, Set<? extends Image> images, Provider<Set<? extends Image>> images, Provider<SortedSet<? extends Size>> sizes,
Set<? extends Size> sizes, Provider<Set<TerremarkVCloudTemplate>> templates) { Provider<Set<? extends VCloudTemplate>> templates, Predicate<String> successTester,
this.client = tmClient; Predicate<InetSocketAddress> socketTester) {
this.computeClient = computeClient; super(client, images, sizes, templates, successTester, socketTester);
this.images = images; this.client = client;
this.sizes = sizes;
this.templates = templates;
} }
@Override @Override
public CreateNodeResponse runNode(String name, Template template) { protected Map<String, String> parseResponse(VApp vAppResponse) {
checkNotNull(template.getImage().getLocation(), "location"); return ImmutableMap.<String, String> of("id", vAppResponse.getId(), "username", "vcloud",
String id = computeClient.start(template.getImage().getLocation(), name, template.getImage() "password", "p4ssw0rd");
.getId(), (int) template.getSize().getCores(), (int) template.getSize().getRam(), }
ImmutableMap.<String, String> of());
@Override
public Map<String, String> start(String vDCId, String name, String templateId, int minCores,
int minMegs, Long diskSize, Map<String, String> properties, int... portsToOpen) {
Map<String, String> response = super.start(vDCId, name, templateId, minCores, minMegs, null,
properties, portsToOpen);// trmk does not support resizing the primary disk
if (portsToOpen.length > 0)
createPublicAddressMappedToPorts(response.get("id"), portsToOpen);
return response;
}
public InetAddress createPublicAddressMappedToPorts(String vAppId, int... ports) {
VApp vApp = client.getVApp(vAppId);
PublicIpAddress ip = null;
InetAddress privateAddress = Iterables.getLast(vApp.getNetworkToAddresses().values());
for (int port : ports) {
InternetService is = null;
Protocol protocol;
switch (port) {
case 22:
protocol = Protocol.TCP;
break;
case 80:
case 8080:
protocol = Protocol.HTTP;
break;
case 443:
protocol = Protocol.HTTPS;
break;
default:
protocol = Protocol.HTTP;
break;
}
if (ip == null) {
logger.debug(">> creating InternetService in vDC %s:%s:%d", vApp.getVDC().getId(),
protocol, port);
is = client.addInternetServiceToVDC(vApp.getVDC().getId(), vApp.getName() + "-" + port,
protocol, port, withDescription(String.format(
"port %d access to serverId: %s name: %s", port, vApp.getId(), vApp
.getName())));
ip = is.getPublicIpAddress();
} else {
logger.debug(">> adding InternetService %s:%s:%d", ip.getAddress().getHostAddress(),
protocol, port);
is = client.addInternetServiceToExistingIp(ip.getId(), vApp.getName() + "-" + port,
protocol, port, withDescription(String.format(
"port %d access to serverId: %s name: %s", port, vApp.getId(), vApp
.getName())));
}
logger.debug("<< created InternetService(%s) %s:%s:%d", is.getId(), is
.getPublicIpAddress().getAddress().getHostAddress(), is.getProtocol(), is
.getPort());
logger.debug(">> adding Node %s:%d -> %s:%d", is.getPublicIpAddress().getAddress()
.getHostAddress(), is.getPort(), privateAddress.getHostAddress(), port);
Node node = client.addNode(is.getId(), privateAddress, vApp.getName() + "-" + port, port);
logger.debug("<< added Node(%s)", node.getId());
}
return ip != null ? ip.getAddress() : null;
}
@Override
public void stop(String id) {
VApp vApp = client.getVApp(id); VApp vApp = client.getVApp(id);
InetAddress publicIp = computeClient Set<PublicIpAddress> ipAddresses = deleteInternetServicesAndNodesAssociatedWithVApp(vApp);
.createPublicAddressMappedToPorts(vApp, 22, 80, 8080, 443); deletePublicIpAddressesWithNoServicesAttached(ipAddresses);
return new CreateNodeResponseImpl(vApp.getId(), vApp.getName(), template.getImage().getLocation(), vApp.getLocation(), super.stop(id);
ImmutableMap.<String, String> of(), vAppStatusToNodeState.get(vApp.getStatus()),
ImmutableSet.<InetAddress> of(publicIp), vApp.getNetworkToAddresses().values(), 22,
LoginType.SSH, new Credentials("vcloud", "p4ssw0rd"), ImmutableMap
.<String, String> of());
} }
@Override private Set<PublicIpAddress> deleteInternetServicesAndNodesAssociatedWithVApp(VApp vApp) {
public NodeMetadata getNodeMetadata(ComputeMetadata node) { Set<PublicIpAddress> ipAddresses = Sets.newHashSet();
checkArgument(node.getType() == ComputeType.NODE, "this is only valid for nodes, not " SERVICE: for (InternetService service : client.getAllInternetServicesInVDC(vApp.getVDC()
+ node.getType()); .getId())) {
return getNodeMetadataByIdInVDC(checkNotNull(node.getLocation(), "location"), checkNotNull( for (Node node : client.getNodes(service.getId())) {
node.getId(), "node.id")); if (vApp.getNetworkToAddresses().containsValue(node.getIpAddress())) {
} ipAddresses.add(service.getPublicIpAddress());
logger.debug(">> deleting Node(%s) %s:%d -> %s:%d", node.getId(), service
private NodeMetadata getNodeMetadataByIdInVDC(String vDCId, String id) { .getPublicIpAddress().getAddress().getHostAddress(), service.getPort(),
VApp vApp = client.getVApp(id); node.getIpAddress().getHostAddress(), node.getPort());
Set<InetAddress> publicAddresses = computeClient.getPublicAddresses(vApp.getId()); client.deleteNode(node.getId());
return new NodeMetadataImpl(vApp.getId(), vApp.getName(), vDCId, vApp.getLocation(), logger.debug("<< deleted Node(%s)", node.getId());
ImmutableMap.<String, String> of(), vAppStatusToNodeState.get(vApp.getStatus()), SortedSet<Node> nodes = client.getNodes(service.getId());
publicAddresses, vApp.getNetworkToAddresses().values(), 22, LoginType.SSH, if (nodes.size() == 0) {
ImmutableMap.<String, String> of()); logger.debug(">> deleting InternetService(%s) %s:%d", service.getId(), service
} .getPublicIpAddress().getAddress().getHostAddress(), service.getPort());
client.deleteInternetService(service.getId());
@Override logger.debug("<< deleted InternetService(%s)", service.getId());
public Set<ComputeMetadata> listNodes() { continue SERVICE;
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; return ipAddresses;
} }
@Override private void deletePublicIpAddressesWithNoServicesAttached(Set<PublicIpAddress> ipAddresses) {
public void destroyNode(ComputeMetadata node) { IPADDRESS: for (PublicIpAddress address : ipAddresses) {
checkArgument(node.getType() == ComputeType.NODE, "this is only valid for nodes, not " SortedSet<InternetService> services = client
+ node.getType()); .getInternetServicesOnPublicIp(address.getId());
computeClient.stop(checkNotNull(node.getId(), "node.id")); if (services.size() == 0) {
logger.debug(">> deleting PublicIpAddress(%s) %s", address.getId(), address
.getAddress().getHostAddress());
client.deletePublicIp(address.getId());
logger.debug("<< deleted PublicIpAddress(%s)", address.getId());
continue IPADDRESS;
}
}
} }
@Override /**
public Template createTemplateInLocation(String location) { *
return new TerremarkVCloudTemplate(client, images, sizes, location); * @throws ElementNotFoundException
* if no address is configured
*/
public InetAddress getAnyPrivateAddress(String id) {
VApp vApp = client.getVApp(id);
return Iterables.getLast(vApp.getNetworkToAddresses().values());
} }
@Override public Set<InetAddress> getPublicAddresses(String id) {
public Set<? extends Size> listSizes() { VApp vApp = client.getVApp(id);
return sizes; Set<InetAddress> ipAddresses = Sets.newHashSet();
} for (InternetService service : client.getAllInternetServicesInVDC(vApp.getVDC().getId())) {
for (Node node : client.getNodes(service.getId())) {
@Override if (vApp.getNetworkToAddresses().containsValue(node.getIpAddress())) {
public Set<? extends Template> listTemplates() { ipAddresses.add(service.getPublicIpAddress().getAddress());
return templates.get(); }
}
}
return ipAddresses;
} }
} }

View File

@ -20,22 +20,15 @@ package org.jclouds.vcloud.terremark.compute;
import java.util.List; import java.util.List;
import java.util.Properties; 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.http.config.JavaUrlHttpCommandExecutorServiceModule;
import org.jclouds.logging.jdk.config.JDKLoggingModule; import org.jclouds.logging.jdk.config.JDKLoggingModule;
import org.jclouds.vcloud.terremark.TerremarkVCloudAsyncClient; import org.jclouds.vcloud.compute.VCloudComputeServiceContextBuilder;
import org.jclouds.vcloud.terremark.TerremarkVCloudClient;
import org.jclouds.vcloud.terremark.compute.config.TerremarkVCloudComputeServiceContextModule; import org.jclouds.vcloud.terremark.compute.config.TerremarkVCloudComputeServiceContextModule;
import org.jclouds.vcloud.terremark.config.TerremarkVCloudRestClientModule; import org.jclouds.vcloud.terremark.config.TerremarkVCloudRestClientModule;
import com.google.inject.Injector; import com.google.inject.Injector;
import com.google.inject.Key;
import com.google.inject.Module; import com.google.inject.Module;
import com.google.inject.TypeLiteral;
/** /**
* Creates {@link TerremarkVCloudComputeServiceContext} or {@link Injector} instances based on the * Creates {@link TerremarkVCloudComputeServiceContext} or {@link Injector} instances based on the
@ -50,23 +43,10 @@ import com.google.inject.TypeLiteral;
* @author Adrian Cole * @author Adrian Cole
* @see TerremarkVCloudComputeServiceContext * @see TerremarkVCloudComputeServiceContext
*/ */
public class TerremarkVCloudComputeServiceContextBuilder extends public class TerremarkVCloudComputeServiceContextBuilder extends VCloudComputeServiceContextBuilder {
ComputeServiceContextBuilder<TerremarkVCloudAsyncClient, TerremarkVCloudClient> {
public TerremarkVCloudComputeServiceContextBuilder(Properties props) { public TerremarkVCloudComputeServiceContextBuilder(Properties props) {
super(new TypeLiteral<TerremarkVCloudAsyncClient>() { super(props);
}, new TypeLiteral<TerremarkVCloudClient>() {
}, props);
}
@Override
public TerremarkVCloudComputeServiceContextBuilder withExecutorService(ExecutorService service) {
return (TerremarkVCloudComputeServiceContextBuilder) super.withExecutorService(service);
}
@Override
public TerremarkVCloudComputeServiceContextBuilder withModules(Module... modules) {
return (TerremarkVCloudComputeServiceContextBuilder) super.withModules(modules);
} }
@Override @Override
@ -79,14 +59,4 @@ public class TerremarkVCloudComputeServiceContextBuilder extends
modules.add(new TerremarkVCloudRestClientModule()); modules.add(new TerremarkVCloudRestClientModule());
} }
@Override
public ComputeServiceContext buildComputeServiceContext() {
// need the generic type information
return (ComputeServiceContext) this
.buildInjector()
.getInstance(
Key
.get(new TypeLiteral<ComputeServiceContextImpl<TerremarkVCloudAsyncClient, TerremarkVCloudClient>>() {
}));
}
} }

View File

@ -1,178 +0,0 @@
package org.jclouds.vcloud.terremark.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.terremark.TerremarkVCloudClient;
import com.google.common.collect.Iterables;
/**
*
* @author Adrian Cole
*/
public class TerremarkVCloudTemplate implements Template {
private final TerremarkVCloudClient 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 TerremarkVCloudTemplate(TerremarkVCloudClient 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);
}
TerremarkVCloudTemplate(TerremarkVCloudClient client, Set<? extends Image> images,
Set<? extends Size> sizes, String location) {
this(client, images, sizes, location, null, OperatingSystem.UBUNTU, null);
}
/**
* {@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 TerremarkVCloudTemplate(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;
TerremarkVCloudTemplate other = (TerremarkVCloudTemplate) 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 "TerremarkVCloudTemplate [image=" + image + ", operatingSystem=" + operatingSystem
+ ", size=" + size + ", vDC=" + vDC + "]";
}
}

View File

@ -18,43 +18,26 @@
*/ */
package org.jclouds.vcloud.terremark.compute.config; package org.jclouds.vcloud.terremark.compute.config;
import java.util.LinkedHashSet;
import java.util.Set; import java.util.Set;
import java.util.SortedSet;
import javax.annotation.Resource; import java.util.concurrent.ExecutorService;
import javax.inject.Named;
import javax.inject.Singleton;
import org.jclouds.compute.ComputeService; import org.jclouds.compute.ComputeService;
import org.jclouds.compute.ComputeServiceContext;
import org.jclouds.compute.domain.Architecture; import org.jclouds.compute.domain.Architecture;
import org.jclouds.compute.domain.Image; import org.jclouds.compute.domain.Image;
import org.jclouds.compute.domain.OperatingSystem;
import org.jclouds.compute.domain.Size; import org.jclouds.compute.domain.Size;
import org.jclouds.compute.domain.internal.ImageImpl;
import org.jclouds.compute.domain.internal.SizeImpl; 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.VCloudClient; import org.jclouds.vcloud.VCloudClient;
import org.jclouds.vcloud.VCloudMediaType; import org.jclouds.vcloud.compute.config.VCloudComputeServiceContextModule;
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 org.jclouds.vcloud.terremark.TerremarkVCloudAsyncClient;
import org.jclouds.vcloud.terremark.TerremarkVCloudClient; import org.jclouds.vcloud.terremark.TerremarkVCloudClient;
import org.jclouds.vcloud.terremark.compute.TerremarkVCloudComputeService; import org.jclouds.vcloud.terremark.compute.TerremarkVCloudComputeService;
import org.jclouds.vcloud.terremark.compute.TerremarkVCloudTemplate;
import org.jclouds.vcloud.terremark.config.TerremarkVCloudContextModule;
import org.jclouds.vcloud.terremark.domain.ComputeOptions; import org.jclouds.vcloud.terremark.domain.ComputeOptions;
import com.google.common.base.Function; import com.google.common.base.Function;
import com.google.common.collect.ImmutableSet; import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables; import com.google.common.collect.Iterables;
import com.google.common.collect.Sets; import com.google.common.collect.Sets;
import com.google.inject.Provides; import com.google.inject.Injector;
/** /**
* Configures the {@link TerremarkVCloudComputeServiceContext}; requires * Configures the {@link TerremarkVCloudComputeServiceContext}; requires
@ -62,98 +45,37 @@ import com.google.inject.Provides;
* *
* @author Adrian Cole * @author Adrian Cole
*/ */
public class TerremarkVCloudComputeServiceContextModule extends TerremarkVCloudContextModule { public class TerremarkVCloudComputeServiceContextModule extends VCloudComputeServiceContextModule {
@Override @Override
protected void configure() { protected void configure() {
super.configure(); super.configure();
bind(ComputeService.class).to(TerremarkVCloudComputeService.class).asEagerSingleton();
} }
@Provides @Override
@Singleton protected ComputeService provideComputeService(Injector injector) {
ComputeServiceContext provideContext(ComputeService computeService, return injector.getInstance(TerremarkVCloudComputeService.class);
RestContext<TerremarkVCloudAsyncClient, TerremarkVCloudClient> context) {
return new ComputeServiceContextImpl<TerremarkVCloudAsyncClient, TerremarkVCloudClient>(
computeService, context);
} }
private static final ComputeOptionsToSize sizeConverter = new ComputeOptionsToSize(); private static final ComputeOptionsToSize sizeConverter = new ComputeOptionsToSize();
private static class ComputeOptionsToSize implements Function<ComputeOptions, Size> { private static class ComputeOptionsToSize implements Function<ComputeOptions, Size> {
@Override @Override
public Size apply(ComputeOptions from) { public Size apply(ComputeOptions from) {
return new SizeImpl(from.getProcessorCount(), (int) from.getMemory(), null, ImmutableSet return new SizeImpl(from.getProcessorCount(), from.getMemory(), 10, ImmutableSet
.<Architecture> of(Architecture.X86_32, Architecture.X86_64)); .<Architecture> of(Architecture.X86_32, Architecture.X86_64));
} }
} }
private static class LogHolder { @Override
@Resource protected SortedSet<? extends Size> provideSizes(VCloudClient client,
@Named(ComputeServiceConstants.COMPUTE_LOGGER) Set<? extends Image> images, LogHolder holder, ExecutorService executor) {
protected Logger logger = Logger.NULL;
}
@Provides
@Singleton
Set<? extends Image> provideImages(VCloudClient client, LogHolder holder) {
Set<Image> images = Sets.newLinkedHashSet();
holder.logger.debug(">> providing images");
Catalog response = client.getDefaultCatalog();
String vDC = client.getDefaultVDC().getId();
for (NamedResource resource : response.values()) {
if (resource.getType().equals(VCloudMediaType.CATALOGITEM_XML)) {
CatalogItem item = client.getCatalogItem(resource.getId());
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;
if (item.getEntity().getType().equals(VCloudMediaType.VAPPTEMPLATE_XML)) {
VAppTemplate template = client.getVAppTemplate(item.getEntity().getId());
images.add(new ImageImpl(resource.getId(), template.getDescription(), myOs, null,
vDC, arch));
}
}
}
holder.logger.debug("<< images(%d)", images.size());
return images;
}
@Provides
@Singleton
Set<? extends Size> provideSizes(TerremarkVCloudClient client, Set<? extends Image> images,
LogHolder holder) {
Image anyImage = Iterables.get(images, 0); Image anyImage = Iterables.get(images, 0);
holder.logger.debug(">> providing sizes"); holder.logger.debug(">> providing sizes");
LinkedHashSet<Size> sizes = Sets.newLinkedHashSet(Iterables.transform(client SortedSet<Size> sizes = Sets.newTreeSet(Iterables.transform(TerremarkVCloudClient.class.cast(
.getComputeOptionsOfCatalogItem(anyImage.getId()), sizeConverter)); client).getComputeOptionsOfCatalogItem(anyImage.getId()), sizeConverter));
holder.logger.debug("<< sizes(%d)", sizes.size()); holder.logger.debug("<< sizes(%d)", sizes.size());
return sizes; return sizes;
} }
@Provides
@Singleton
Set<TerremarkVCloudTemplate> provideTemplates(TerremarkVCloudClient client,
Set<? extends Image> images, Set<? extends Size> sizes, LogHolder holder) {
Set<TerremarkVCloudTemplate> templates = Sets.newHashSet();
holder.logger.debug(">> generating templates");
String vDC = client.getDefaultVDC().getId();
for (Size size : sizes) {
for (Image image : images) {
templates.add(new TerremarkVCloudTemplate(client, images, sizes, vDC, size, image
.getOperatingSystem(), image));
}
}
holder.logger.debug("<< templates(%d)", templates.size());
return templates;
}
} }

View File

@ -29,10 +29,10 @@ package org.jclouds.vcloud.terremark.domain;
*/ */
public class ComputeOptions implements Comparable<ComputeOptions> { public class ComputeOptions implements Comparable<ComputeOptions> {
private final int processorCount; private final int processorCount;
private final long memory; private final int memory;
private final float costPerHour; private final float costPerHour;
public ComputeOptions(int processorCount, long memory, float costPerHour) { public ComputeOptions(int processorCount, int memory, float costPerHour) {
this.processorCount = processorCount; this.processorCount = processorCount;
this.memory = memory; this.memory = memory;
this.costPerHour = costPerHour; this.costPerHour = costPerHour;
@ -42,7 +42,7 @@ public class ComputeOptions implements Comparable<ComputeOptions> {
return processorCount; return processorCount;
} }
public long getMemory() { public int getMemory() {
return memory; return memory;
} }

View File

@ -19,45 +19,18 @@
package org.jclouds.vcloud.terremark.compute; package org.jclouds.vcloud.terremark.compute;
import static com.google.common.base.Preconditions.checkNotNull; import static org.jclouds.compute.domain.OperatingSystem.JEOS;
import static org.jclouds.compute.domain.OperatingSystem.CENTOS;
import static org.jclouds.compute.domain.OperatingSystem.UBUNTU;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNotNull;
import java.io.IOException; import org.jclouds.compute.BaseComputeServiceLiveTest;
import java.net.InetSocketAddress;
import java.util.Properties;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import org.jclouds.compute.ComputeService;
import org.jclouds.compute.ComputeServiceContext;
import org.jclouds.compute.ComputeServiceContextFactory; import org.jclouds.compute.ComputeServiceContextFactory;
import org.jclouds.compute.domain.ComputeMetadata; import org.jclouds.rest.RestContext;
import org.jclouds.compute.domain.ComputeType;
import org.jclouds.compute.domain.CreateNodeResponse;
import org.jclouds.compute.domain.LoginType;
import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.domain.OperatingSystem;
import org.jclouds.compute.domain.Size;
import org.jclouds.compute.domain.Template;
import org.jclouds.logging.log4j.config.Log4JLoggingModule;
import org.jclouds.predicates.RetryablePredicate;
import org.jclouds.predicates.SocketOpen;
import org.jclouds.ssh.ExecResponse;
import org.jclouds.ssh.SshClient;
import org.jclouds.ssh.SshException;
import org.jclouds.ssh.jsch.config.JschSshClientModule; import org.jclouds.ssh.jsch.config.JschSshClientModule;
import org.testng.annotations.AfterTest; import org.jclouds.vcloud.compute.VCloudComputeClient;
import org.testng.annotations.BeforeGroups; import org.jclouds.vcloud.terremark.TerremarkVCloudAsyncClient;
import org.jclouds.vcloud.terremark.TerremarkVCloudClient;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test; import org.testng.annotations.Test;
import com.google.common.collect.ImmutableSet;
import com.google.inject.Guice;
import com.google.inject.Injector;
/** /**
* *
* Generally disabled, as it incurs higher fees. * Generally disabled, as it incurs higher fees.
@ -65,115 +38,28 @@ import com.google.inject.Injector;
* @author Adrian Cole * @author Adrian Cole
*/ */
@Test(groups = "live", enabled = true, sequential = true, testName = "terremark.TerremarkVCloudComputeServiceLiveTest") @Test(groups = "live", enabled = true, sequential = true, testName = "terremark.TerremarkVCloudComputeServiceLiveTest")
public class TerremarkVCloudComputeServiceLiveTest { public class TerremarkVCloudComputeServiceLiveTest extends BaseComputeServiceLiveTest {
private static final String service = "terremark"; @BeforeClass
private static final OperatingSystem testOS = UBUNTU; @Override
public void setServiceDefaults() {
protected SshClient.Factory sshFactory; service = "terremark";
private String nodeName = service; testOS = JEOS;
private RetryablePredicate<InetSocketAddress> socketTester;
private CreateNodeResponse node;
private ComputeServiceContext context;
private ComputeService client;
@BeforeGroups(groups = { "live" })
public void setupClient() throws InterruptedException, ExecutionException, TimeoutException,
IOException {
String user = checkNotNull(System.getProperty("jclouds.test.user"), "jclouds.test.user");
String password = checkNotNull(System.getProperty("jclouds.test.key"), "jclouds.test.key");
context = new ComputeServiceContextFactory().createContext(service, user, password,
ImmutableSet.of(new Log4JLoggingModule()), new Properties());
Injector injector = Guice.createInjector(new JschSshClientModule());
sshFactory = injector.getInstance(SshClient.Factory.class);
SocketOpen socketOpen = injector.getInstance(SocketOpen.class);
socketTester = new RetryablePredicate<InetSocketAddress>(socketOpen, 60, 1, TimeUnit.SECONDS);
injector.injectMembers(socketOpen); // add logger
client = context.getComputeService();
} }
public void testCreate() throws Exception { @Override
Template template = client.createTemplateInLocation("default").os(testOS).smallest(); protected JschSshClientModule getSshModule() {
node = client.runNode(nodeName, template); return new JschSshClientModule();
assertNotNull(node.getId());
assertEquals(node.getLoginPort(), 22);
assertEquals(node.getLoginType(), LoginType.SSH);
assertNotNull(node.getName());
assertEquals(node.getPrivateAddresses().size(), 1);
assertEquals(node.getPublicAddresses().size(), 1);
assertNotNull(node.getCredentials());
assertNotNull(node.getCredentials().account);
assertNotNull(node.getCredentials().key);
sshPing();
} }
@Test(dependsOnMethods = "testCreate") public void testAssignability() throws Exception {
public void testGet() throws Exception { @SuppressWarnings("unused")
NodeMetadata metadata = client.getNodeMetadata(node); RestContext<TerremarkVCloudAsyncClient, TerremarkVCloudClient> tmContext = new ComputeServiceContextFactory()
assertEquals(metadata.getId(), node.getId()); .createContext(service, user, password).getProviderSpecificContext();
assertEquals(metadata.getLoginPort(), node.getLoginPort());
assertEquals(metadata.getLoginType(), node.getLoginType()); TerremarkVCloudComputeService computeService = TerremarkVCloudComputeService.class
assertEquals(metadata.getName(), node.getName()); .cast(client);
assertEquals(metadata.getPrivateAddresses(), node.getPrivateAddresses());
assertEquals(metadata.getPublicAddresses(), node.getPublicAddresses()); @SuppressWarnings("unused")
} VCloudComputeClient computeClient = VCloudComputeClient.class.cast(computeService);
public void testList() throws Exception {
for (ComputeMetadata node : client.listNodes()) {
assert node.getId() != null;
assert node.getLocation() != null;
assertEquals(node.getType(), ComputeType.NODE);
}
}
public void testListTemplates() throws Exception {
for (Template template : client.listTemplates()) {
assert template.getImage() != null;
System.out.println(template);
}
}
public void testListSizes() throws Exception {
for (Size size : client.listSizes()) {
assert size.getCores() != null;
System.out.println(size);
}
}
private void sshPing() throws IOException {
try {
doCheckKey();
} catch (SshException e) {// try twice in case there is a network timeout
try {
Thread.sleep(10 * 1000);
} catch (InterruptedException e1) {
}
doCheckKey();
}
}
private void doCheckKey() throws IOException {
InetSocketAddress socket = new InetSocketAddress(node.getPublicAddresses().last(), node
.getLoginPort());
socketTester.apply(socket);
SshClient ssh = node.getCredentials().key.startsWith("-----BEGIN RSA PRIVATE KEY-----") ? sshFactory
.create(socket, node.getCredentials().account, node.getCredentials().key.getBytes())
: sshFactory
.create(socket, node.getCredentials().account, node.getCredentials().key);
try {
ssh.connect();
ExecResponse hello = ssh.exec("echo hello");
assertEquals(hello.getOutput().trim(), "hello");
} finally {
if (ssh != null)
ssh.disconnect();
}
}
@AfterTest
void cleanup() throws InterruptedException, ExecutionException, TimeoutException {
if (node != null)
client.destroyNode(node);
context.close();
} }
} }