Merge branch 'master' of git://github.com/jclouds/jclouds

This commit is contained in:
Adam Lowe 2011-09-30 11:34:01 +01:00
commit 9afa28bab1
59 changed files with 2050 additions and 374 deletions

View File

@ -16,7 +16,7 @@ check out our examples site! https://github.com/jclouds/jclouds-examples
our compute api supports: aws-ec2, gogrid, cloudservers-us, stub (in-memory), deltacloud,
cloudservers-uk, vcloud (generic), ec2 (generic), byon, nova,
trmk-ecloud, trmk-vcloudexpress, eucalyptus (generic),
cloudsigma-zrh, elasticstack(generic),
cloudsigma-zrh, elasticstack(generic), go2cloud-jhb1,
bluelock-vcloud-zone01, stratogen-vcloud-mycloud, rimuhosting,
slicehost, eucalyptus-partnercloud-ec2, elastichosts-lon-p (Peer 1),
elastichosts-sat-p (Peer 1), elastichosts-lon-b (BlueSquare),

View File

@ -165,5 +165,10 @@
<artifactId>cloudsigma-zrh</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.jclouds.provider</groupId>
<artifactId>go2cloud-jhb1</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>
</project>

View File

@ -23,23 +23,27 @@ import static com.google.common.base.Preconditions.checkNotNull;
import java.util.Map;
import java.util.Map.Entry;
import javax.annotation.Resource;
import javax.inject.Inject;
import javax.inject.Singleton;
import org.jclouds.elasticstack.domain.Device;
import org.jclouds.elasticstack.domain.NIC;
import org.jclouds.elasticstack.domain.Server;
import org.jclouds.logging.Logger;
import org.jclouds.rest.annotations.ApiVersion;
import com.google.common.base.Function;
import com.google.common.base.Joiner;
import com.google.common.collect.ImmutableMap;
import org.jclouds.rest.annotations.ApiVersion;
/**
* @author Adrian Cole
*/
@Singleton
public class ServerToMap implements Function<Server, Map<String, String>> {
@Resource
protected Logger logger = Logger.NULL;
@ApiVersion
private final String apiVersion;
@ -75,7 +79,7 @@ public class ServerToMap implements Function<Server, Map<String, String>> {
if (nic.getVlan() != null)
builder.put("nic:" + nicId + ":vlan", nic.getVlan());
if (nic.getMac() != null)
builder.put("nic:" + nicId + ":mac", nic.getMac());
logger.trace("setting mac on network interfaces not supported: %s", nic);
nicId++;
}

View File

@ -63,6 +63,30 @@ public class ServerToMapTest {
"vnc:password", "XXXXXXXX")).build());
}
public void testWeDontSetMac() {
assertEquals(
SERVER_TO_MAP.apply(new Server.Builder()
.name("TestServer")
.cpu(2000)
.mem(1024)
.devices(
ImmutableMap.of("ide:0:0",
new IDEDevice.Builder(0, 0).uuid("08c92dd5-70a0-4f51-83d2-835919d254df").build()))
.bootDeviceIds(ImmutableSet.of("ide:0:0"))
.nics(ImmutableSet.of(new NIC.Builder().mac("foo").model(Model.E1000).
build())).vnc(new VNC(null, "XXXXXXXX", false)).build()),
ImmutableMap
.builder()
.putAll(ImmutableMap.of("name", "TestServer", "cpu", "2000", "smp", "auto", "mem", "1024"))
.putAll(
ImmutableMap.of("persistent", "false", "boot", "ide:0:0", "ide:0:0",
"08c92dd5-70a0-4f51-83d2-835919d254df"))
.putAll(
ImmutableMap.of("ide:0:0:media", "disk", "nic:0:model", "e1000", "vnc:ip", "auto",
"vnc:password", "XXXXXXXX")).build());
}
public void testBasicsV2() {
assertEquals(
SERVER_TO_MAP_V2.apply(new Server.Builder()

View File

@ -26,7 +26,7 @@ import org.testng.annotations.Test;
*
* @author Adrian Cole
*/
@Test(groups = "live", sequential = true, testName = "EucalyptusComputeServiceLiveTest")
@Test(groups = "live", singleThreaded = true, testName = "EucalyptusComputeServiceLiveTest")
public class EucalyptusComputeServiceLiveTest extends EC2ComputeServiceLiveTest {
public EucalyptusComputeServiceLiveTest() {
@ -45,7 +45,13 @@ public class EucalyptusComputeServiceLiveTest extends EC2ComputeServiceLiveTest
// ebs backed not yet available
}
}
@Override
@Test(enabled = true)
public void testMapEBS() throws Exception {
// ebs backed not yet available
}
@Override
@Test(enabled = true, dependsOnMethods = "testSuspendResume")
public void testListNodes() throws Exception {

View File

@ -109,7 +109,7 @@
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>10.0-rc3</version>
<version>10.0</version>
</dependency>
</dependencies>

View File

@ -52,7 +52,12 @@ import com.google.inject.Provides;
/**
* Configures {@link ExecutorService}.
*
* Note that this uses threads
* Note that this uses threads.
*
* <p>
* This extends the underlying Future to expose a description (the task's toString) and the submission context (stack trace).
* The submission stack trace is appended to relevant stack traces on exceptions that are returned,
* so the user can see the logical chain of execution (in the executor, and where it was passed to the executor).
*
* @author Adrian Cole
*/
@ -92,7 +97,7 @@ public class ExecutorServiceModule extends AbstractModule {
static ExecutorService addToStringOnSubmit(ExecutorService executor) {
if (executor != null) {
return new AddToStringOnSubmitExecutorService(executor);
return new DescribingExecutorService(executor);
}
return executor;
}
@ -117,11 +122,11 @@ public class ExecutorServiceModule extends AbstractModule {
protected void configure() {
}
static class AddToStringOnSubmitExecutorService implements ExecutorService {
static class DescribingExecutorService implements ExecutorService {
private final ExecutorService delegate;
public AddToStringOnSubmitExecutorService(ExecutorService delegate) {
public DescribingExecutorService(ExecutorService delegate) {
this.delegate = checkNotNull(delegate, "delegate");
}
@ -174,18 +179,18 @@ public class ExecutorServiceModule extends AbstractModule {
@Override
public <T> Future<T> submit(Callable<T> task) {
return new AddToStringFuture<T>(delegate.submit(task), task.toString());
return new DescribedFuture<T>(delegate.submit(task), task.toString(), getStackTraceHere());
}
@SuppressWarnings({ "unchecked", "rawtypes" })
@Override
public Future<?> submit(Runnable task) {
return new AddToStringFuture(delegate.submit(task), task.toString());
return new DescribedFuture(delegate.submit(task), task.toString(), getStackTraceHere());
}
@Override
public <T> Future<T> submit(Runnable task, T result) {
return new AddToStringFuture<T>(delegate.submit(task, result), task.toString());
return new DescribedFuture<T>(delegate.submit(task, result), task.toString(), getStackTraceHere());
}
@Override
@ -210,13 +215,15 @@ public class ExecutorServiceModule extends AbstractModule {
}
static class AddToStringFuture<T> implements Future<T> {
static class DescribedFuture<T> implements Future<T> {
private final Future<T> delegate;
private final String toString;
private final String description;
private StackTraceElement[] submissionTrace;
public AddToStringFuture(Future<T> delegate, String toString) {
public DescribedFuture(Future<T> delegate, String description, StackTraceElement[] submissionTrace) {
this.delegate = delegate;
this.toString = toString;
this.description = description;
this.submissionTrace = submissionTrace;
}
@Override
@ -226,12 +233,65 @@ public class ExecutorServiceModule extends AbstractModule {
@Override
public T get() throws InterruptedException, ExecutionException {
return delegate.get();
try {
return delegate.get();
} catch (ExecutionException e) {
throw ensureCauseHasSubmissionTrace(e);
} catch (InterruptedException e) {
throw ensureCauseHasSubmissionTrace(e);
}
}
@Override
public T get(long arg0, TimeUnit arg1) throws InterruptedException, ExecutionException, TimeoutException {
return delegate.get(arg0, arg1);
try {
return delegate.get(arg0, arg1);
} catch (ExecutionException e) {
throw ensureCauseHasSubmissionTrace(e);
} catch (InterruptedException e) {
throw ensureCauseHasSubmissionTrace(e);
} catch (TimeoutException e) {
throw ensureCauseHasSubmissionTrace(e);
}
}
/** This method does the work to ensure _if_ a submission stack trace was provided,
* it is included in the exception. most errors are thrown from the frame of the
* Future.get call, with a cause that took place in the executor's thread.
* We extend the stack trace of that cause with the submission stack trace.
* (An alternative would be to put the stack trace as a root cause,
* at the bottom of the stack, or appended to all traces, or inserted
* after the second cause, etc ... but since we can't change the "Caused by:"
* method in Throwable the compromise made here seems best.)
*/
private <ET extends Exception> ET ensureCauseHasSubmissionTrace(ET e) {
if (submissionTrace==null) return e;
if (e.getCause()==null) {
ExecutionException ee = new ExecutionException("task submitted from the following trace", null);
e.initCause(ee);
return e;
}
Throwable cause = e.getCause();
StackTraceElement[] causeTrace = cause.getStackTrace();
boolean causeIncludesSubmissionTrace = submissionTrace.length >= causeTrace.length;
for (int i=0; causeIncludesSubmissionTrace && i<submissionTrace.length; i++) {
if (!causeTrace[causeTrace.length-1-i].equals(submissionTrace[submissionTrace.length-1-i])) {
causeIncludesSubmissionTrace = false;
}
}
if (!causeIncludesSubmissionTrace) {
cause.setStackTrace(merge(causeTrace, submissionTrace));
}
return e;
}
private StackTraceElement[] merge(StackTraceElement[] t1, StackTraceElement[] t2) {
StackTraceElement[] t12 = new StackTraceElement[t1.length + t2.length];
System.arraycopy(t1, 0, t12, 0, t1.length);
System.arraycopy(t2, 0, t12, t1.length, t2.length);
return t12;
}
@Override
@ -256,7 +316,7 @@ public class ExecutorServiceModule extends AbstractModule {
@Override
public String toString() {
return toString;
return description;
}
}
@ -302,4 +362,14 @@ public class ExecutorServiceModule extends AbstractModule {
.setThreadFactory(Executors.defaultThreadFactory()).build());
}
/** returns the stack trace at the caller */
static StackTraceElement[] getStackTraceHere() {
// remove the first two items in the stack trace (because the first one refers to the call to
// Thread.getStackTrace, and the second one is us)
StackTraceElement[] fullSubmissionTrace = Thread.currentThread().getStackTrace();
StackTraceElement[] cleanedSubmissionTrace = new StackTraceElement[fullSubmissionTrace.length-2];
System.arraycopy(fullSubmissionTrace, 2, cleanedSubmissionTrace, 0, cleanedSubmissionTrace.length);
return cleanedSubmissionTrace;
}
}

View File

@ -25,12 +25,16 @@ import static org.easymock.classextension.EasyMock.verify;
import static org.testng.Assert.assertEquals;
import java.io.IOException;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;
import org.jclouds.Constants;
import org.jclouds.lifecycle.Closer;
import org.testng.annotations.Test;
import com.google.common.base.Throwables;
import com.google.common.collect.ImmutableList;
import com.google.inject.Guice;
import com.google.inject.Injector;
@ -64,15 +68,14 @@ public class ExecutorServiceModuleTest {
public void testShutdownOnCloseThroughModule() throws IOException {
ExecutorServiceModule module = new ExecutorServiceModule() {
@Override
protected void configure() {
bindConstant().annotatedWith(Names.named(Constants.PROPERTY_IO_WORKER_THREADS)).to(1);
bindConstant().annotatedWith(Names.named(Constants.PROPERTY_USER_THREADS)).to(1);
super.configure();
}
};
Injector i = Guice.createInjector(module);
assertEquals(module.userExecutorFromConstructor, null);
assertEquals(module.ioExecutorFromConstructor, null);
@ -93,4 +96,163 @@ public class ExecutorServiceModuleTest {
assert io.isShutdown();
}
@Test
public void testDescribedFutureToString() throws Exception {
ExecutorServiceModule module = new ExecutorServiceModule() {
@Override
protected void configure() {
bindConstant().annotatedWith(Names.named(Constants.PROPERTY_IO_WORKER_THREADS)).to(1);
bindConstant().annotatedWith(Names.named(Constants.PROPERTY_USER_THREADS)).to(1);
super.configure();
}
};
Injector i = Guice.createInjector(module);
Closer closer = i.getInstance(Closer.class);
ExecutorService user = i
.getInstance(Key.get(ExecutorService.class, Names.named(Constants.PROPERTY_USER_THREADS)));
ExecutorService io = i.getInstance(Key.get(ExecutorService.class, Names
.named(Constants.PROPERTY_IO_WORKER_THREADS)));
ConfigurableRunner t1 = new ConfigurableRunner();
t1.result = "okay";
Future<Object> euc = performSubmissionInSeparateMethod1(user, t1);
assert euc.toString().indexOf("ConfigurableRunner") >= 0;
assert euc.get().equals("okay");
Future<Object> eic = performSubmissionInSeparateMethod1(io, t1);
assert eic.toString().indexOf("ConfigurableRunner") >= 0;
assert eic.get().equals("okay");
closer.close();
}
/*
* The decoration makes sure that the stack trace looks like the following.
* Note the last three included trace elements: this details where the task was submitted _from_
* (technically it is a different stack frame, since it is across threads; but logically it is the same)
*
java.util.concurrent.ExecutionException: java.lang.IllegalStateException: foo
at java.util.concurrent.FutureTask$Sync.innerGet(FutureTask.java:222)
at java.util.concurrent.FutureTask.get(FutureTask.java:83)
at org.jclouds.concurrent.config.ExecutorServiceModule$DescribedFuture.get(ExecutorServiceModule.java:232)
at org.jclouds.concurrent.config.ExecutorServiceModuleTest.checkFutureGetFailsWith(ExecutorServiceModuleTest.java:186)
at org.jclouds.concurrent.config.ExecutorServiceModuleTest.testDescribedFutureExceptionIncludesSubmissionTrace(ExecutorServiceModuleTest.java:171)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.testng.internal.MethodInvocationHelper.invokeMethod(MethodInvocationHelper.java:80)
at org.testng.internal.Invoker.invokeMethod(Invoker.java:691)
at org.testng.internal.Invoker.invokeTestMethod(Invoker.java:883)
at org.testng.internal.Invoker.invokeTestMethods(Invoker.java:1208)
at org.testng.internal.TestMethodWorker.invokeTestMethods(TestMethodWorker.java:127)
at org.testng.internal.TestMethodWorker.run(TestMethodWorker.java:111)
at org.testng.TestRunner.privateRun(TestRunner.java:753)
at org.testng.TestRunner.run(TestRunner.java:613)
at org.testng.SuiteRunner.runTest(SuiteRunner.java:335)
at org.testng.SuiteRunner.runSequentially(SuiteRunner.java:330)
at org.testng.SuiteRunner.privateRun(SuiteRunner.java:292)
at org.testng.SuiteRunner.run(SuiteRunner.java:241)
at org.testng.SuiteRunnerWorker.runSuite(SuiteRunnerWorker.java:52)
at org.testng.SuiteRunnerWorker.run(SuiteRunnerWorker.java:86)
at org.testng.TestNG.runSuitesSequentially(TestNG.java:1169)
at org.testng.TestNG.runSuitesLocally(TestNG.java:1094)
at org.testng.TestNG.run(TestNG.java:1006)
at org.testng.remote.RemoteTestNG.run(RemoteTestNG.java:107)
at org.testng.remote.RemoteTestNG.initAndRun(RemoteTestNG.java:199)
at org.testng.remote.RemoteTestNG.main(RemoteTestNG.java:170)
Caused by: java.lang.IllegalStateException: foo
at org.jclouds.concurrent.config.ExecutorServiceModuleTest$ConfigurableRunner.call(ExecutorServiceModuleTest.java:206)
at org.jclouds.concurrent.config.ExecutorServiceModuleTest$ConfigurableRunner.run(ExecutorServiceModuleTest.java:203)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:441)
at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:303)
at java.util.concurrent.FutureTask.run(FutureTask.java:138)
at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
at java.lang.Thread.run(Thread.java:637)
at org.jclouds.concurrent.config.ExecutorServiceModule$DescribingExecutorService.submit(ExecutorServiceModule.java:188)
at org.jclouds.concurrent.config.ExecutorServiceModuleTest.performSubmissionInSeparateMethod2(ExecutorServiceModuleTest.java:181)
at org.jclouds.concurrent.config.ExecutorServiceModuleTest.testDescribedFutureExceptionIncludesSubmissionTrace(ExecutorServiceModuleTest.java:170)
... 24 more
*
*/
@Test
public void testDescribedFutureExceptionIncludesSubmissionTrace() throws Exception {
ExecutorServiceModule module = new ExecutorServiceModule() {
@Override
protected void configure() {
bindConstant().annotatedWith(Names.named(Constants.PROPERTY_IO_WORKER_THREADS)).to(1);
bindConstant().annotatedWith(Names.named(Constants.PROPERTY_USER_THREADS)).to(1);
super.configure();
}
};
Injector i = Guice.createInjector(module);
Closer closer = i.getInstance(Closer.class);
ExecutorService user = i
.getInstance(Key.get(ExecutorService.class, Names.named(Constants.PROPERTY_USER_THREADS)));
ExecutorService io = i.getInstance(Key.get(ExecutorService.class, Names
.named(Constants.PROPERTY_IO_WORKER_THREADS)));
ConfigurableRunner t1 = new ConfigurableRunner();
t1.failMessage = "foo";
t1.result = "shouldn't happen";
Future<Object> euc = performSubmissionInSeparateMethod1(user, t1);
checkFutureGetFailsWith(euc, "foo", "testDescribedFutureExceptionIncludesSubmissionTrace", "performSubmissionInSeparateMethod1");
Future<Object> eur = performSubmissionInSeparateMethod2(user, t1);
checkFutureGetFailsWith(eur, "foo", "testDescribedFutureExceptionIncludesSubmissionTrace", "performSubmissionInSeparateMethod2");
Future<Object> eic = performSubmissionInSeparateMethod1(io, t1);
checkFutureGetFailsWith(eic, "foo", "testDescribedFutureExceptionIncludesSubmissionTrace", "performSubmissionInSeparateMethod1");
Future<Object> eir = performSubmissionInSeparateMethod2(io, t1);
checkFutureGetFailsWith(eir, "foo", "testDescribedFutureExceptionIncludesSubmissionTrace", "performSubmissionInSeparateMethod2");
closer.close();
}
static Future<Object> performSubmissionInSeparateMethod1(ExecutorService user, ConfigurableRunner t1) {
return user.submit((Callable<Object>)t1);
}
static Future<Object> performSubmissionInSeparateMethod2(ExecutorService io, ConfigurableRunner t1) {
return io.submit((Runnable)t1, (Object)"shouldn't happen");
}
static void checkFutureGetFailsWith(Future<Object> task, String ...requiredPhrases) throws Exception {
try {
task.get();
assert false : "task should have failed";
} catch (ExecutionException e) {
String trace = Throwables.getStackTraceAsString(e);
for (String requiredPhrase : requiredPhrases) {
assert trace.indexOf(requiredPhrase) >= 0 : "stack trace should have contained '"+requiredPhrase+"'";
}
}
}
private static class ConfigurableRunner implements Runnable, Callable<Object> {
private Object result;
private String failMessage;
@Override
public void run() {
call();
}
public Object call() {
if (failMessage!=null) throw new IllegalStateException(failMessage);
return result;
}
}
}

View File

@ -18,7 +18,7 @@
*/
package org.jclouds.go2cloud.config;
import static org.jclouds.compute.domain.OsFamily.DEBIAN;
import static org.jclouds.compute.domain.OsFamily.UBUNTU;
import org.jclouds.compute.domain.TemplateBuilder;
import org.jclouds.elasticstack.compute.config.ElasticStackComputeServiceContextModule;
@ -33,6 +33,6 @@ public class Go2CloudJohannesburg1ComputeServiceContextModule extends ElasticSta
@Override
protected TemplateBuilder provideTemplate(Injector injector, TemplateBuilder template) {
return template.osFamily(DEBIAN).osVersionMatches("6.0").os64Bit(true);
return template.osFamily(UBUNTU).osVersionMatches("10.10").os64Bit(true);
}
}

View File

@ -0,0 +1,30 @@
[
{
"uuid": "14c88d27-1f5e-4ad5-9f3a-28e5d2282f61",
"description": "Ubuntu 10.10",
"osFamily": "UBUNTU",
"osVersion": "10.10",
"size": "1"
},
{
"uuid": "cc54132d-4912-4106-a91a-7a27e6866c8b",
"description": "Debian 6.0.2.1",
"osFamily": "DEBIAN",
"osVersion": "6.0",
"size": "1"
},
{
"uuid": "77ad0ffe-9537-4c64-a8e3-10db185261c0",
"description": "Windows 2008 R2 (x64) with SP1",
"osFamily": "WINDOWS",
"osVersion": "2008 R2",
"size": "13"
},
{
"uuid": "d971ddfb-7a69-48f7-8d14-a76ef61b01d8",
"description": "Windows 8 Developer Preview (x64)",
"osFamily": "WINDOWS",
"osVersion": "8",
"size": "13"
}
]

View File

@ -25,10 +25,10 @@ import org.testng.annotations.Test;
*
* @author Adrian Cole
*/
@Test(groups = "live", sequential = true)
@Test(groups = "live", singleThreaded = true)
public class Go2CloudJohannesburg1ClientLiveTest extends ElasticStackClientLiveTest {
public Go2CloudJohannesburg1ClientLiveTest() {
provider = "go2cloud-jhb1";
bootDrive = "5192adbd-046f-4a48-90f9-3db390b1efab";
bootDrive = "14c88d27-1f5e-4ad5-9f3a-28e5d2282f61";
}
}

View File

@ -52,6 +52,8 @@ public class Go2CloudJohannesburg1TemplateBuilderLiveTest extends BaseTemplateBu
@Override
public boolean apply(OsFamilyVersion64Bit input) {
switch (input.family) {
case UBUNTU:
return (input.version.equals("") || input.version.equals("10.10")) && input.is64Bit;
case DEBIAN:
return (input.version.equals("") || input.version.equals("6.0")) && input.is64Bit;
case WINDOWS:
@ -68,8 +70,8 @@ public class Go2CloudJohannesburg1TemplateBuilderLiveTest extends BaseTemplateBu
public void testDefaultTemplateBuilder() throws IOException {
Template defaultTemplate = this.context.getComputeService().templateBuilder().build();
assertEquals(defaultTemplate.getImage().getOperatingSystem().is64Bit(), true);
assertEquals(defaultTemplate.getImage().getOperatingSystem().getVersion(), "6.0");
assertEquals(defaultTemplate.getImage().getOperatingSystem().getFamily(), OsFamily.DEBIAN);
assertEquals(defaultTemplate.getImage().getOperatingSystem().getVersion(), "10.10");
assertEquals(defaultTemplate.getImage().getOperatingSystem().getFamily(), OsFamily.UBUNTU);
assertEquals(defaultTemplate.getLocation().getId(), "go2cloud-jhb1");
assertEquals(getCores(defaultTemplate.getHardware()), 1.0d);
}

View File

@ -35,7 +35,7 @@
<properties>
<test.openhosting-east1.endpoint>https://api.east1.openhosting.com</test.openhosting-east1.endpoint>
<test.openhosting-east1.apiversion>1.0</test.openhosting-east1.apiversion>
<test.openhosting-east1.apiversion>2.0</test.openhosting-east1.apiversion>
<test.openhosting-east1.identity>FIXME_IDENTITY</test.openhosting-east1.identity>
<test.openhosting-east1.credential>FIXME_CREDENTIAL</test.openhosting-east1.credential>
</properties>

View File

@ -35,9 +35,9 @@ public class OpenHostingEast1PropertiesBuilder extends ElasticStackPropertiesBui
@Override
protected Properties defaultProperties() {
Properties properties = super.defaultProperties();
properties.setProperty(PROPERTY_ISO3166_CODES, "US-VA");
properties.setProperty(PROPERTY_ISO3166_CODES, "US-FL");
properties.setProperty(PROPERTY_ENDPOINT, "https://api.east1.openhosting.com");
properties.setProperty(PROPERTY_API_VERSION, "1.0");
properties.setProperty(PROPERTY_API_VERSION, "2.0");
return properties;
}

View File

@ -102,7 +102,7 @@ public class OpenHostingEast1ProviderMetadata extends BaseProviderMetadata {
*/
@Override
public Set<String> getIso3166Codes() {
return ImmutableSet.of("US-VA");
return ImmutableSet.of("US-FL");
}
}

View File

@ -78,6 +78,6 @@ public class OpenHostingEast1TemplateBuilderLiveTest extends BaseTemplateBuilder
@Override
protected Set<String> getIso3166Codes() {
return ImmutableSet.<String> of("US-VA");
return ImmutableSet.<String> of("US-FL");
}
}

View File

@ -62,5 +62,6 @@
<module>savvis-symphonyvpdc</module>
<module>greenhousedata-element-vcloud</module>
<module>aws-cloudwatch</module>
<module>go2cloud-jhb1</module>
</modules>
</project>

View File

@ -69,6 +69,7 @@ public class VirtualBoxPropertiesBuilder extends PropertiesBuilder {
"jclouds-virtualbox-test"));
// TODO: Add more properties and use the wired properties from test code.
properties.put(VirtualBoxConstants.VIRTUALBOX_DISTRO_ISO_NAME, "ubuntu-11.04-server-i386.iso");
return properties;
}
}

View File

@ -21,19 +21,27 @@
package org.jclouds.virtualbox.compute;
import com.google.common.base.Throwables;
import com.google.inject.Singleton;
import org.jclouds.compute.ComputeServiceAdapter;
import org.jclouds.compute.domain.Template;
import org.jclouds.domain.Credentials;
import org.jclouds.virtualbox.domain.Host;
import org.virtualbox_4_1.*;
import static com.google.common.base.Preconditions.checkNotNull;
import javax.inject.Inject;
import java.util.Collections;
import java.util.Map;
import static com.google.common.base.Preconditions.checkNotNull;
import javax.inject.Inject;
import org.jclouds.compute.ComputeServiceAdapter;
import org.jclouds.compute.domain.Template;
import org.jclouds.domain.Credentials;
import org.jclouds.domain.Location;
import org.jclouds.location.suppliers.JustProvider;
import org.virtualbox_4_1.CleanupMode;
import org.virtualbox_4_1.IMachine;
import org.virtualbox_4_1.IProgress;
import org.virtualbox_4_1.ISession;
import org.virtualbox_4_1.SessionState;
import org.virtualbox_4_1.VirtualBoxManager;
import com.google.common.base.Throwables;
import com.google.inject.Singleton;
/**
* Defines the connection between the {@link org.virtualbox_4_1.VirtualBoxManager} implementation and the jclouds
@ -42,13 +50,15 @@ import static com.google.common.base.Preconditions.checkNotNull;
* @author Mattias Holmqvist, Andrea Turli
*/
@Singleton
public class VirtualBoxComputeServiceAdapter implements ComputeServiceAdapter<IMachine, IMachine, IMachine, Host> {
public class VirtualBoxComputeServiceAdapter implements ComputeServiceAdapter<IMachine, IMachine, IMachine, Location> {
private final VirtualBoxManager manager;
private final JustProvider justProvider;
@Inject
public VirtualBoxComputeServiceAdapter(VirtualBoxManager manager) {
public VirtualBoxComputeServiceAdapter(VirtualBoxManager manager, JustProvider justProvider) {
this.manager = checkNotNull(manager, "manager");
this.justProvider = checkNotNull(justProvider, "justProvider");
}
@Override
@ -63,17 +73,18 @@ public class VirtualBoxComputeServiceAdapter implements ComputeServiceAdapter<IM
@Override
public Iterable<IMachine> listHardwareProfiles() {
return Collections.emptyList();
return manager.getVBox().getMachines();
}
@Override
public Iterable<IMachine> listImages() {
return Collections.emptyList();
return manager.getVBox().getMachines();
}
@Override
public Iterable<Host> listLocations() {
return Collections.emptyList();
@SuppressWarnings("unchecked")
@Override
public Iterable<Location> listLocations() {
return (Iterable<Location>) justProvider.get();
}
@Override

View File

@ -21,23 +21,26 @@
package org.jclouds.virtualbox.config;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Function;
import com.google.common.base.Supplier;
import com.google.common.collect.ImmutableMap;
import com.google.inject.Injector;
import com.google.inject.Provides;
import com.google.inject.TypeLiteral;
import java.net.URI;
import java.util.Map;
import javax.inject.Named;
import javax.inject.Singleton;
import org.jclouds.Constants;
import org.jclouds.compute.ComputeServiceAdapter;
import org.jclouds.compute.config.ComputeServiceAdapterContextModule;
import org.jclouds.compute.domain.*;
import org.jclouds.compute.domain.Hardware;
import org.jclouds.compute.domain.Image;
import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.domain.NodeState;
import org.jclouds.compute.domain.OsFamily;
import org.jclouds.compute.domain.TemplateBuilder;
import org.jclouds.domain.Location;
import org.jclouds.functions.IdentityFunction;
import org.jclouds.location.Provider;
import org.jclouds.location.suppliers.OnlyLocationOrFirstZone;
import org.jclouds.virtualbox.compute.VirtualBoxComputeServiceAdapter;
import org.jclouds.virtualbox.domain.Host;
import org.jclouds.virtualbox.functions.HostToLocation;
import org.jclouds.virtualbox.functions.IMachineToHardware;
import org.jclouds.virtualbox.functions.IMachineToImage;
import org.jclouds.virtualbox.functions.IMachineToNodeMetadata;
@ -45,15 +48,18 @@ import org.virtualbox_4_1.IMachine;
import org.virtualbox_4_1.MachineState;
import org.virtualbox_4_1.VirtualBoxManager;
import javax.inject.Named;
import javax.inject.Singleton;
import java.net.URI;
import java.util.Map;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Function;
import com.google.common.base.Supplier;
import com.google.common.collect.ImmutableMap;
import com.google.inject.Injector;
import com.google.inject.Provides;
import com.google.inject.TypeLiteral;
/**
* @author Mattias Holmqvist, Andrea Turli
*/
public class VirtualBoxComputeServiceContextModule extends ComputeServiceAdapterContextModule<VirtualBoxManager, VirtualBoxManager, IMachine, IMachine, IMachine, Host> {
public class VirtualBoxComputeServiceContextModule extends ComputeServiceAdapterContextModule<VirtualBoxManager, VirtualBoxManager, IMachine, IMachine, IMachine, Location> {
public VirtualBoxComputeServiceContextModule() {
super(VirtualBoxManager.class, VirtualBoxManager.class);
@ -68,15 +74,16 @@ public class VirtualBoxComputeServiceContextModule extends ComputeServiceAdapter
return manager;
}
@SuppressWarnings({ "unchecked", "rawtypes" })
@Override
protected void configure() {
super.configure();
bind(new TypeLiteral<ComputeServiceAdapter<IMachine, IMachine, IMachine, Host>>() {
bind(new TypeLiteral<ComputeServiceAdapter<IMachine, IMachine, IMachine, Location>>() {
}).to(VirtualBoxComputeServiceAdapter.class);
bind(new TypeLiteral<Function<IMachine, NodeMetadata>>() {
}).to(IMachineToNodeMetadata.class);
bind(new TypeLiteral<Function<Host, Location>>() {
}).to(HostToLocation.class);
bind(new TypeLiteral<Function<Location, Location>>() {
}).to((Class) IdentityFunction.class);
bind(new TypeLiteral<Function<IMachine, Hardware>>() {
}).to(IMachineToHardware.class);
bind(new TypeLiteral<Function<IMachine, Image>>() {

View File

@ -50,4 +50,6 @@ public interface VirtualBoxConstants {
public static final String VIRTUALBOX_MACHINE_LOCATION = "jclouds.virtualbox.location";
public static final String VIRTUALBOX_HOST_ID = "jclouds.virtualbox.hostid";
public static final String VIRTUALBOX_DISTRO_ISO_NAME = "jclouds.virtualbox.distroIsoName";
}

View File

@ -1,25 +0,0 @@
/*
* *
* * Licensed to jclouds, Inc. (jclouds) under one or more
* * contributor license agreements. See the NOTICE file
* * distributed with this work for additional information
* * regarding copyright ownership. jclouds licenses this file
* * to you under the Apache License, Version 2.0 (the
* * "License"); you may not use this file except in compliance
* * with the License. You may obtain a copy of the License at
* *
* * http://www.apache.org/licenses/LICENSE-2.0
* *
* * Unless required by applicable law or agreed to in writing,
* * software distributed under the License is distributed on an
* * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* * KIND, either express or implied. See the License for the
* * specific language governing permissions and limitations
* * under the License.
*
*/
package org.jclouds.virtualbox.domain;
public class Host {
}

View File

@ -1,36 +0,0 @@
/*
* *
* * Licensed to jclouds, Inc. (jclouds) under one or more
* * contributor license agreements. See the NOTICE file
* * distributed with this work for additional information
* * regarding copyright ownership. jclouds licenses this file
* * to you under the Apache License, Version 2.0 (the
* * "License"); you may not use this file except in compliance
* * with the License. You may obtain a copy of the License at
* *
* * http://www.apache.org/licenses/LICENSE-2.0
* *
* * Unless required by applicable law or agreed to in writing,
* * software distributed under the License is distributed on an
* * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* * KIND, either express or implied. See the License for the
* * specific language governing permissions and limitations
* * under the License.
*
*/
package org.jclouds.virtualbox.functions;
import com.google.common.base.Function;
import org.jclouds.domain.Location;
import org.jclouds.domain.LocationBuilder;
import org.jclouds.javax.annotation.Nullable;
import org.jclouds.virtualbox.domain.Host;
public class HostToLocation implements Function<Host, Location> {
@Override
public Location apply(@Nullable Host input) {
LocationBuilder locationBuilder = new LocationBuilder();
return locationBuilder.build();
}
}

View File

@ -21,36 +21,39 @@
package org.jclouds.virtualbox.functions;
import com.google.common.base.Function;
import javax.inject.Inject;
import org.jclouds.compute.domain.Hardware;
import org.jclouds.compute.domain.HardwareBuilder;
import org.jclouds.compute.predicates.ImagePredicates;
import org.jclouds.javax.annotation.Nullable;
import org.jclouds.virtualbox.VirtualBox;
import org.virtualbox_4_1.IGuestOSType;
import org.virtualbox_4_1.IMachine;
import org.virtualbox_4_1.VirtualBoxManager;
import javax.inject.Inject;
import com.google.common.base.Function;
public class IMachineToHardware implements Function<IMachine, Hardware> {
private VirtualBox vbox;
private VirtualBoxManager virtualBoxManager;
@Inject
public IMachineToHardware(VirtualBox vbox) {
this.vbox = vbox;
public IMachineToHardware(VirtualBoxManager virtualBoxManager) {
this.virtualBoxManager = virtualBoxManager;
}
@Override
public Hardware apply(@Nullable IMachine vm) {
String osTypeId = vm.getOSTypeId();
IGuestOSType guestOSType = vbox.manager().getVBox().getGuestOSType(osTypeId);
IGuestOSType guestOSType = virtualBoxManager.getVBox().getGuestOSType(osTypeId);
Boolean is64Bit = guestOSType.getIs64Bit();
HardwareBuilder hardwareBuilder = new HardwareBuilder();
hardwareBuilder.ids(vm.getId());
vm.getSessionPid();
hardwareBuilder.supportsImage(ImagePredicates.idEquals(vm.getId()));
hardwareBuilder.is64Bit(is64Bit);
hardwareBuilder.supportsImage(ImagePredicates.idEquals(vm.getId()));
return hardwareBuilder.build();
}
}

View File

@ -21,89 +21,86 @@
package org.jclouds.virtualbox.functions;
import java.util.NoSuchElementException;
import javax.inject.Inject;
import com.google.common.base.Function;
import org.jclouds.compute.domain.Image;
import org.jclouds.compute.domain.ImageBuilder;
import org.jclouds.compute.domain.OperatingSystem;
import org.jclouds.compute.domain.OsFamily;
import org.jclouds.javax.annotation.Nullable;
import org.jclouds.virtualbox.VirtualBox;
import org.virtualbox_4_1.IGuestOSType;
import org.virtualbox_4_1.IMachine;
import org.virtualbox_4_1.VirtualBoxManager;
import com.google.common.base.Function;
import javax.inject.Inject;
public class IMachineToImage implements Function<IMachine, Image> {
private static final String UBUNTU = "Ubuntu Linux";
private static final String UBUNTU = "Ubuntu";
private VirtualBoxManager virtualboxManager;
private VirtualBoxManager virtualboxManager;
@Inject
public IMachineToImage(VirtualBoxManager virtualboxManager) {
this.virtualboxManager = virtualboxManager;
}
@Inject
public IMachineToImage(VirtualBoxManager virtualboxManager) {
this.virtualboxManager = virtualboxManager;
}
@Override
public Image apply(@Nullable IMachine from) {
@Override
public Image apply(@Nullable IMachine from) {
Boolean is64Bit = virtualboxManager.getVBox().getGuestOSType(from.getOSTypeId()).getIs64Bit();
IGuestOSType guestOSType = virtualboxManager.getVBox().getGuestOSType(from.getOSTypeId());
//Somehow this method gets called with the correct product item.
OsFamily family = osFamily().apply(from);
OperatingSystem os = OperatingSystem.builder()
.description(from.getDescription())
.family(family)
.version(osVersion().apply(from))
.is64Bit(is64Bit)
.build();
OsFamily family = osFamily().apply(guestOSType.getDescription());
OperatingSystem os = OperatingSystem.builder()
.description(guestOSType.getDescription())
.family(family)
.version(osVersion().apply(guestOSType.getDescription()))
.is64Bit(guestOSType.getIs64Bit())
.build();
return new ImageBuilder()
.id("" + from.getId())
.description(from.getDescription())
.operatingSystem(os)
.build();
}
return new ImageBuilder()
.id("" + from.getId())
.description(from.getDescription())
.operatingSystem(os)
.build();
}
/**
* Parses the item description to determine the OSFamily
* @return the @see OsFamily or OsFamily.UNRECOGNIZED
*/
public static Function<IMachine, OsFamily> osFamily() {
return new Function<IMachine,OsFamily>() {
@Override
public OsFamily apply(IMachine iMachine) {
final String description = iMachine.getDescription();
if ( description.startsWith(UBUNTU) ) return OsFamily.UBUNTU;
return OsFamily.UNRECOGNIZED;
}
};
}
/**
* Parses the item description to determine the OSFamily
*
* @return the @see OsFamily or OsFamily.UNRECOGNIZED
*/
public static Function<String, OsFamily> osFamily() {
/**
* Parses the item description to determine the os version
* @return the version
* @throws java.util.NoSuchElementException if the version cannot be determined
*/
public static Function<IMachine, String> osVersion() {
return new Function<IMachine, String>() {
@Override
public String apply(IMachine iMachine) {
final String description = iMachine.getDescription();
OsFamily family = osFamily().apply(iMachine);
if(family.equals(OsFamily.UBUNTU)) return parseVersion(description, UBUNTU);
else throw new NoSuchElementException("No os parseVersion for item:" + iMachine);
}
};
}
private static String parseVersion(String description, String os) {
String noOsName = description.replaceFirst(os,"").trim();
return noOsName.split(" ")[0];
}
return new Function<String, OsFamily>() {
@Override
public OsFamily apply(String osDescription) {
if (osDescription.startsWith(UBUNTU)) return OsFamily.UBUNTU;
return OsFamily.UNRECOGNIZED;
}
};
}
/**
* Parses the item description to determine the os version
*
* @return the version, empty if not found
*/
public static Function<String, String> osVersion() {
return new Function<String, String>() {
@Override
public String apply(String osDescription) {
OsFamily family = osFamily().apply(osDescription);
if (family.equals(OsFamily.UBUNTU))
return parseVersion(osDescription, UBUNTU);
else
return "";
}
};
}
private static String parseVersion(String description, String os) {
String noOsName = description.replaceFirst(os, "").trim();
return noOsName.split(" ")[0];
}
}

View File

@ -34,6 +34,11 @@ import javax.annotation.Nullable;
import static org.jclouds.compute.options.RunScriptOptions.Builder.runAsRoot;
/**
* Get an IP address from an IMachine using arp of the host machine.
*
* @author Mattias Holmqvist, Andrea Turli
*/
public class IMachineToIpAddress implements Function<IMachine, String> {
private VirtualBoxManager manager;
@ -67,13 +72,13 @@ public class IMachineToIpAddress implements Function<IMachine, String> {
simplifiedMacAddressOfClonedVM = new StringBuffer(simplifiedMacAddressOfClonedVM).delete(simplifiedMacAddressOfClonedVM.indexOf("0"), simplifiedMacAddressOfClonedVM.indexOf("0") + 1).toString();
}
// TODO: This is both shell-dependent and hard-coded. Needs to be fixed.
ExecResponse execResponse = runScriptOnNode(hostId, "for i in {1..254} ; do ping -c 1 -t 1 192.168.2.$i & done", runAsRoot(false).wrapInInitScript(false));
System.out.println(execResponse);
String arpLine = runScriptOnNode(hostId, "arp -an | grep " + simplifiedMacAddressOfClonedVM, runAsRoot(false).wrapInInitScript(false)).getOutput();
String ipAddress = arpLine.substring(arpLine.indexOf("(") + 1, arpLine.indexOf(")"));
System.out.println("IP address " + ipAddress);
return ipAddress;
}
@ -84,8 +89,7 @@ public class IMachineToIpAddress implements Function<IMachine, String> {
protected boolean isOSX(IMachine machine) {
String osTypeId = machine.getOSTypeId();
IGuestOSType guestOSType = manager.getVBox().getGuestOSType(osTypeId);
String familyDescription = guestOSType.getFamilyDescription();
return true;
return guestOSType.getFamilyDescription().equals("Other");
}
}

View File

@ -0,0 +1,229 @@
/*
* *
* * Licensed to jclouds, Inc. (jclouds) under one or more
* * contributor license agreements. See the NOTICE file
* * distributed with this work for additional information
* * regarding copyright ownership. jclouds licenses this file
* * to you under the Apache License, Version 2.0 (the
* * "License"); you may not use this file except in compliance
* * with the License. You may obtain a copy of the License at
* *
* * http://www.apache.org/licenses/LICENSE-2.0
* *
* * Unless required by applicable law or agreed to in writing,
* * software distributed under the License is distributed on an
* * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* * KIND, either express or implied. See the License for the
* * specific language governing permissions and limitations
* * under the License.
*
*/
package org.jclouds.virtualbox.functions;
import static com.google.common.base.Throwables.propagate;
import static org.jclouds.compute.options.RunScriptOptions.Builder.runAsRoot;
import static org.jclouds.compute.options.RunScriptOptions.Builder.wrapInInitScript;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNotNull;
import java.io.File;
import org.jclouds.compute.ComputeServiceContext;
import org.jclouds.compute.domain.ExecResponse;
import org.jclouds.compute.options.RunScriptOptions;
import org.jclouds.javax.annotation.Nullable;
import org.jclouds.virtualbox.config.VirtualBoxConstants;
import org.jclouds.virtualbox.experiment.settings.KeyboardScancodes;
import org.virtualbox_4_1.AccessMode;
import org.virtualbox_4_1.DeviceType;
import org.virtualbox_4_1.IMachine;
import org.virtualbox_4_1.IMedium;
import org.virtualbox_4_1.IProgress;
import org.virtualbox_4_1.ISession;
import org.virtualbox_4_1.LockType;
import org.virtualbox_4_1.MachineState;
import org.virtualbox_4_1.NATProtocol;
import org.virtualbox_4_1.NetworkAttachmentType;
import org.virtualbox_4_1.StorageBus;
import org.virtualbox_4_1.VirtualBoxManager;
import org.virtualbox_4_1.jaxws.MediumVariant;
import com.google.common.base.Function;
import com.google.inject.Inject;
public class IsoToIMachine implements Function<String, IMachine> {
private VirtualBoxManager manager;
private String adminDisk;
private String diskFormat;
private String settingsFile;
private String vmName;
private String osTypeId;
private String vmId;
private String controllerIDE;
private boolean forceOverwrite;
private ComputeServiceContext context;
private String hostId;
private String guestId;
@Inject
public IsoToIMachine(VirtualBoxManager manager, String adminDisk,
String diskFormat, String settingsFile, String vmName,
String osTypeId, String vmId, boolean forceOverwrite,
String controllerIDE, ComputeServiceContext context, String hostId,
String guestId) {
super();
this.manager = manager;
this.adminDisk = adminDisk;
this.diskFormat = diskFormat;
this.settingsFile = settingsFile;
this.vmName = vmName;
this.osTypeId = osTypeId;
this.vmId = vmId;
this.controllerIDE = controllerIDE;
this.forceOverwrite = forceOverwrite;
this.context = context;
this.hostId = hostId;
this.guestId = guestId;
}
@Override
public IMachine apply(@Nullable String isoName) {
IMachine vm = manager.getVBox().createMachine(settingsFile, vmName,
osTypeId, vmId, forceOverwrite);
assertNotNull(vm.getName());
IMedium distroMedium = manager.getVBox().openMedium(
VirtualBoxConstants.VIRTUALBOX_WORKINGDIR + "/" + isoName,
DeviceType.DVD, AccessMode.ReadOnly, forceOverwrite);
ISession session = manager.getSessionObject();
IMachine machine = manager.getVBox().findMachine(vmName);
machine.lockMachine(session, LockType.Write);
IMachine mutable = session.getMachine();
mutable.addStorageController(controllerIDE, StorageBus.IDE);
// assertEquals(manager.getVBox().findMachine(vmName).getStorageControllers().size(),
// 1);
mutable.saveSettings();
// CONTROLLER
mutable.attachDevice(controllerIDE, 0, 0, DeviceType.DVD, distroMedium);
mutable.saveSettings();
// DISK
IMedium hd = null;
if (new File(adminDisk).exists()) {
new File(adminDisk).delete();
}
hd = manager.getVBox().createHardDisk(diskFormat, adminDisk);
long size = 4L * 1024L * 1024L * 1024L - 4L;
hd.createBaseStorage(new Long(size),
new Long(MediumVariant.STANDARD.ordinal()));
mutable.attachDevice(controllerIDE, 0, 1, DeviceType.HardDisk, hd);
mutable.saveSettings();
assertEquals(hd.getId().equals(""), false);
// NIC
mutable.getNetworkAdapter(new Long(0)).setAttachmentType(
NetworkAttachmentType.NAT);
machine.getNetworkAdapter(new Long(0))
.getNatDriver()
.addRedirect("guestssh", NATProtocol.TCP, "127.0.0.1", 2222,
"", 22);
mutable.getNetworkAdapter(new Long(0)).setEnabled(true);
mutable.saveSettings();
launchVMProcess(machine, session);
assertEquals(machine.getState(), MachineState.Running);
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
propagate(e);
}
try {
sendKeyboardSequence(VirtualBoxConstants.VIRTUALBOX_INSTALLATION_KEY_SEQUENCE);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
session.unlockMachine();
return vm;
}
private void launchVMProcess(IMachine machine, ISession session) {
IProgress prog = machine.launchVMProcess(session, "gui", "");
prog.waitForCompletion(-1);
session.unlockMachine();
}
private void sendKeyboardSequence(String keyboardSequence)
throws InterruptedException {
String[] sequenceSplited = keyboardSequence.split(" ");
StringBuilder sb = new StringBuilder();
for (String line : sequenceSplited) {
String converted = stringToKeycode(line);
for (String word : converted.split(" ")) {
sb.append("vboxmanage controlvm " + vmName
+ " keyboardputscancode " + word + "; ");
if (word.endsWith(KeyboardScancodes.SPECIAL_KEYBOARD_BUTTON_MAP
.get("<Enter>"))) {
runScriptOnNode(hostId, sb.toString(), runAsRoot(false)
.wrapInInitScript(false));
sb.delete(0, sb.length() - 1);
}
if (word.endsWith(KeyboardScancodes.SPECIAL_KEYBOARD_BUTTON_MAP
.get("<Return>"))) {
runScriptOnNode(hostId, sb.toString(), runAsRoot(false)
.wrapInInitScript(false));
sb.delete(0, sb.length() - 1);
}
}
}
}
private String stringToKeycode(String s) {
StringBuilder keycodes = new StringBuilder();
if (s.startsWith("<")) {
String[] specials = s.split("<");
for (int i = 1; i < specials.length; i++) {
keycodes.append(KeyboardScancodes.SPECIAL_KEYBOARD_BUTTON_MAP
.get("<" + specials[i]) + " ");
}
return keycodes.toString();
}
int i = 0;
while (i < s.length()) {
String digit = s.substring(i, i + 1);
String hex = KeyboardScancodes.NORMAL_KEYBOARD_BUTTON_MAP
.get(digit);
keycodes.append(hex + " ");
if (i != 0 && i % 14 == 0)
keycodes.append(" ");
i++;
}
keycodes.append(KeyboardScancodes.SPECIAL_KEYBOARD_BUTTON_MAP
.get("<Spacebar>") + " ");
return keycodes.toString();
}
protected ExecResponse runScriptOnNode(String nodeId, String command,
RunScriptOptions options) {
ExecResponse toReturn = context.getComputeService().runScriptOnNode(
nodeId, command, options);
assert toReturn.getExitCode() == 0 : toReturn;
return toReturn;
}
protected ExecResponse runScriptOnNode(String nodeId, String command) {
return runScriptOnNode(nodeId, command, wrapInInitScript(false));
}
}

View File

@ -0,0 +1,77 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.virtualbox;
import static com.google.common.base.Preconditions.checkNotNull;
import java.util.Properties;
import org.jclouds.compute.ComputeServiceContext;
import org.jclouds.compute.ComputeServiceContextFactory;
import org.jclouds.logging.log4j.config.Log4JLoggingModule;
import org.jclouds.sshj.config.SshjSshClientModule;
import org.testng.annotations.AfterGroups;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.BeforeGroups;
import org.testng.annotations.Test;
import com.google.common.collect.ImmutableSet;
import com.google.inject.Module;
/**
* Tests behavior of {@code VirtualBoxClient}
*
* @author Adrian Cole
*/
@Test(groups = "live")
public class BaseVirtualBoxClientLiveTest {
protected String provider = "virtualbox";
protected String identity;
protected String credential;
protected String endpoint;
protected String apiversion;
@BeforeClass
protected void setupCredentials() {
identity = checkNotNull(System.getProperty("test." + provider + ".identity"), "test." + provider + ".identity");
credential = System.getProperty("test." + provider + ".credential");
endpoint = System.getProperty("test." + provider + ".endpoint", "http://localhost:18083/");
apiversion = System.getProperty("test." + provider + ".apiversion", "4.1.2r73507");
}
protected ComputeServiceContext context;
@BeforeGroups(groups = { "live" })
public void setupClient() {
Properties properties = new Properties();
properties.setProperty(provider + ".endpoint", endpoint);
properties.setProperty(provider + ".apiversion", apiversion);
context = new ComputeServiceContextFactory().createContext(provider, identity, credential,
ImmutableSet.<Module> of(new Log4JLoggingModule(), new SshjSshClientModule()));
}
@AfterGroups(groups = "live")
protected void tearDown() {
if (context != null)
context.close();
}
}

View File

@ -0,0 +1,127 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.virtualbox.compute;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertFalse;
import java.net.URI;
import java.util.Map;
import org.jclouds.compute.domain.ExecResponse;
import org.jclouds.compute.domain.Image;
import org.jclouds.compute.domain.Template;
import org.jclouds.domain.Credentials;
import org.jclouds.location.suppliers.JustProvider;
import org.jclouds.net.IPSocket;
import org.jclouds.ssh.SshClient;
import org.jclouds.virtualbox.BaseVirtualBoxClientLiveTest;
import org.jclouds.virtualbox.functions.IMachineToImage;
import org.testng.annotations.AfterGroups;
import org.testng.annotations.BeforeGroups;
import org.testng.annotations.Test;
import org.virtualbox_4_1.IMachine;
import org.virtualbox_4_1.VirtualBoxManager;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import com.google.common.collect.Maps;
@Test(groups = "live", singleThreaded = true, testName = "VirtualBoxComputeServiceAdapterLiveTest")
public class VirtualBoxComputeServiceAdapterLiveTest extends BaseVirtualBoxClientLiveTest {
private VirtualBoxComputeServiceAdapter adapter;
private IMachine machine;
@BeforeGroups(groups = { "live" })
public void setupClient() {
super.setupClient();
adapter = new VirtualBoxComputeServiceAdapter(getManager(),
new JustProvider(ImmutableSet.<String> of(), provider, URI.create(endpoint)));
}
protected VirtualBoxManager getManager() {
return (VirtualBoxManager) context.getProviderSpecificContext().getApi();
}
@Test
public void testListLocations() {
assertFalse(Iterables.isEmpty(adapter.listLocations()));
}
@Test
public void testCreateNodeWithGroupEncodedIntoNameThenStoreCredentials() {
String group = "foo";
String name = "foo-ef4";
Template template = context.getComputeService().templateBuilder().build();
Map<String, Credentials> credentialStore = Maps.newLinkedHashMap();
machine = adapter.createNodeWithGroupEncodedIntoNameThenStoreCredentials(group, name, template, credentialStore);
assertEquals(machine.getName(), name);
// is there a place for group?
// check other things, like cpu correct, mem correct, image/os is correct
// (as possible)
assert credentialStore.containsKey("node#" + machine.getId()) : "credentials to log into machine not found "
+ machine;
// TODO: what's the IP address?
// assert InetAddresses.isInetAddress(machine.getPrimaryBackendIpAddress()) : machine;
doConnectViaSsh(machine, credentialStore.get("node#" + machine.getId()));
}
protected void doConnectViaSsh(IMachine machine, Credentials creds) {
SshClient ssh = context.utils().sshFactory()
.create(new IPSocket("//TODO", 22), creds);
try {
ssh.connect();
ExecResponse hello = ssh.exec("echo hello");
assertEquals(hello.getOutput().trim(), "hello");
System.err.println(ssh.exec("df -k").getOutput());
System.err.println(ssh.exec("mount").getOutput());
System.err.println(ssh.exec("uname -a").getOutput());
} finally {
if (ssh != null)
ssh.disconnect();
}
}
@Test
public void testListHardwareProfiles() {
Iterable<IMachine> profiles = adapter.listHardwareProfiles();
assertFalse(Iterables.isEmpty(profiles));
// check state;
}
@Test
public void testListImages() {
IMachineToImage iMachineToImage = new IMachineToImage(getManager());
Iterable<IMachine> iMachineIterable = adapter.listImages();
for (IMachine iMachine : iMachineIterable) {
Image image = iMachineToImage.apply(iMachine);
System.out.println(image);
}
// check state;
}
@AfterGroups(groups = "live")
protected void tearDown() {
if (machine != null)
adapter.destroyNode(machine.getId() + "");
super.tearDown();
}
}

View File

@ -1,88 +0,0 @@
/*
* *
* * Licensed to jclouds, Inc. (jclouds) under one or more
* * contributor license agreements. See the NOTICE file
* * distributed with this work for additional information
* * regarding copyright ownership. jclouds licenses this file
* * to you under the Apache License, Version 2.0 (the
* * "License"); you may not use this file except in compliance
* * with the License. You may obtain a copy of the License at
* *
* * http://www.apache.org/licenses/LICENSE-2.0
* *
* * Unless required by applicable law or agreed to in writing,
* * software distributed under the License is distributed on an
* * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* * KIND, either express or implied. See the License for the
* * specific language governing permissions and limitations
* * under the License.
*
*/
package org.jclouds.virtualbox.compute;
import com.google.common.collect.ImmutableSet;
import com.google.inject.Module;
import org.jclouds.compute.BaseComputeServiceLiveTest;
import org.jclouds.compute.ComputeServiceContext;
import org.jclouds.compute.ComputeServiceContextFactory;
import org.jclouds.compute.StandaloneComputeServiceContextSpec;
import org.jclouds.sshj.config.SshjSshClientModule;
import org.jclouds.virtualbox.VirtualBox;
import org.jclouds.virtualbox.VirtualBoxContextBuilder;
import org.jclouds.virtualbox.domain.Host;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
import org.virtualbox_4_1.IMachine;
import org.virtualbox_4_1.VirtualBoxManager;
import java.util.Properties;
import static com.google.common.base.Preconditions.checkNotNull;
@Test(groups = "live")
public class VirtualBoxComputeServiceLiveTest extends BaseComputeServiceLiveTest {
public VirtualBoxComputeServiceLiveTest() {
provider = "virtualbox";
}
@Override
protected Module getSshModule() {
return new SshjSshClientModule();
}
@Override
protected Properties setupRestProperties() {
Properties restProperties = new Properties();
restProperties.setProperty("virtualbox.contextbuilder", VirtualBoxContextBuilder.class.getName());
restProperties.setProperty("virtualbox.endpoint", "http://localhost:18083/");
restProperties.setProperty("virtualbox.apiversion", "4.1.2r73507");
return restProperties;
}
@BeforeClass
protected void setupCredentials() {
identity = checkNotNull(System.getProperty("test." + provider + ".identity"), "test." + provider + ".identity");
credential = System.getProperty("test." + provider + ".credential");
endpoint = System.getProperty("test." + provider + ".endpoint");
apiversion = System.getProperty("test." + provider + ".apiversion");
}
@Test
public void testAndExperiment() {
ComputeServiceContext context = null;
try {
context = new ComputeServiceContextFactory()
.createContext(new StandaloneComputeServiceContextSpec<VirtualBoxManager, IMachine, IMachine, IMachine, Host>(
"virtualbox", endpoint, apiversion, "", identity, credential, VirtualBoxManager.class,
VirtualBoxContextBuilder.class, ImmutableSet.<Module>of()));
context.getComputeService().listNodes();
} finally {
if (context != null)
context.close();
}
}
}

View File

@ -0,0 +1,37 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.virtualbox.compute;
import org.jclouds.virtualbox.BaseVirtualBoxClientLiveTest;
import org.testng.annotations.Test;
/**
*
* @author Adrian Cole
*/
@Test(groups = "live", testName = "VirtualBoxExperimentLiveTest")
public class VirtualBoxExperimentLiveTest extends BaseVirtualBoxClientLiveTest{
@Test
public void testAndExperiment() {
context.getComputeService().listNodes();
}
}

View File

@ -174,7 +174,7 @@ public class KickstartTest2 {
}
private void runAll() throws Exception {
context = TestUtils.computeServiceForLocalhost();
context = TestUtils.computeServiceForLocalhostAndGuest();
socketTester = new RetryablePredicate<IPSocket>(
new InetSocketAddressConnect(), 130, 10, TimeUnit.SECONDS);

View File

@ -0,0 +1,72 @@
/*
* *
* * Licensed to jclouds, Inc. (jclouds) under one or more
* * contributor license agreements. See the NOTICE file
* * distributed with this work for additional information
* * regarding copyright ownership. jclouds licenses this file
* * to you under the Apache License, Version 2.0 (the
* * "License"); you may not use this file except in compliance
* * with the License. You may obtain a copy of the License at
* *
* * http://www.apache.org/licenses/LICENSE-2.0
* *
* * Unless required by applicable law or agreed to in writing,
* * software distributed under the License is distributed on an
* * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* * KIND, either express or implied. See the License for the
* * specific language governing permissions and limitations
* * under the License.
*
*/
package org.jclouds.virtualbox.functions;
import static org.easymock.EasyMock.eq;
import static org.easymock.EasyMock.expect;
import static org.easymock.classextension.EasyMock.createNiceMock;
import static org.easymock.classextension.EasyMock.replay;
import static org.testng.Assert.assertEquals;
import org.jclouds.compute.domain.Hardware;
import org.jclouds.compute.predicates.ImagePredicates;
import org.testng.annotations.Test;
import org.virtualbox_4_1.IGuestOSType;
import org.virtualbox_4_1.IMachine;
import org.virtualbox_4_1.IVirtualBox;
import org.virtualbox_4_1.VirtualBoxManager;
@Test(groups = "unit")
public class IMachineToHardwareTest {
@Test
public void testConvert() throws Exception {
VirtualBoxManager vbm = createNiceMock(VirtualBoxManager.class);
IVirtualBox vBox = createNiceMock(IVirtualBox.class);
IMachine vm = createNiceMock(IMachine.class);
IGuestOSType guestOsType = createNiceMock(IGuestOSType.class);
String linuxDescription = "Ubuntu Linux 10.04";
String machineId = "hw-machineId";
expect(vm.getOSTypeId()).andReturn("os-type").anyTimes();
expect(vm.getId()).andReturn(machineId).anyTimes();
expect(vm.getDescription()).andReturn(linuxDescription).anyTimes();
expect(vBox.getGuestOSType(eq("os-type"))).andReturn(guestOsType);
expect(vbm.getVBox()).andReturn(vBox);
expect(guestOsType.getIs64Bit()).andReturn(true);
replay(vbm, vBox, vm, guestOsType);
Hardware hardware = new IMachineToHardware(vbm).apply(vm);
assertEquals(hardware.getId(), machineId);
assertEquals(hardware.getProviderId(), machineId);
// for starters assume 1-to-1 relationship hardware to image (which
// correlate to a single source IMachine)
assertEquals(hardware.supportsImage().toString(), ImagePredicates.idEquals(machineId).toString());
}
}

View File

@ -0,0 +1,111 @@
/*
* *
* * Licensed to jclouds, Inc. (jclouds) under one or more
* * contributor license agreements. See the NOTICE file
* * distributed with this work for additional information
* * regarding copyright ownership. jclouds licenses this file
* * to you under the Apache License, Version 2.0 (the
* * "License"); you may not use this file except in compliance
* * with the License. You may obtain a copy of the License at
* *
* * http://www.apache.org/licenses/LICENSE-2.0
* *
* * Unless required by applicable law or agreed to in writing,
* * software distributed under the License is distributed on an
* * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* * KIND, either express or implied. See the License for the
* * specific language governing permissions and limitations
* * under the License.
*
*/
package org.jclouds.virtualbox.functions;
import com.google.common.base.Function;
import org.jclouds.compute.domain.Image;
import org.jclouds.compute.domain.OsFamily;
import org.testng.annotations.Test;
import org.virtualbox_4_1.IGuestOSType;
import org.virtualbox_4_1.IMachine;
import org.virtualbox_4_1.IVirtualBox;
import org.virtualbox_4_1.VirtualBoxManager;
import static org.easymock.EasyMock.eq;
import static org.easymock.EasyMock.expect;
import static org.easymock.classextension.EasyMock.createNiceMock;
import static org.easymock.classextension.EasyMock.replay;
import static org.testng.Assert.assertEquals;
import static org.testng.AssertJUnit.assertTrue;
@Test(groups = "unit")
public class IMachineToImageTest {
@Test
public void testConvert() throws Exception {
VirtualBoxManager vbm = createNiceMock(VirtualBoxManager.class);
IVirtualBox vBox= createNiceMock(IVirtualBox.class);
IMachine vm = createNiceMock(IMachine.class);
IGuestOSType guestOsType = createNiceMock(IGuestOSType.class);
String linuxDescription = "Ubuntu 10.04";
expect(vbm.getVBox()).andReturn(vBox).anyTimes();
expect(vm.getOSTypeId()).andReturn("os-type").anyTimes();
expect(vBox.getGuestOSType(eq("os-type"))).andReturn(guestOsType);
expect(vm.getDescription()).andReturn("my-ubuntu-machine").anyTimes();
expect(guestOsType.getDescription()).andReturn(linuxDescription).anyTimes();
expect(guestOsType.getIs64Bit()).andReturn(true);
replay(vbm, vBox, vm, guestOsType);
IMachineToImage fn = new IMachineToImage(vbm);
Image image = fn.apply(vm);
assertEquals(image.getDescription(), "my-ubuntu-machine");
assertEquals(image.getOperatingSystem().getDescription(), linuxDescription);
assertTrue(image.getOperatingSystem().is64Bit());
assertEquals(image.getOperatingSystem().getFamily(), OsFamily.UBUNTU);
assertEquals(image.getOperatingSystem().getVersion(), "10.04");
}
@Test
public void testOsVersion() throws Exception {
String osDescription = "Ubuntu 10.04";
Function<String, String> iMachineStringFunction = IMachineToImage.osVersion();
assertEquals("10.04", iMachineStringFunction.apply(osDescription));
}
@Test
public void testUnparseableOsString() throws Exception {
VirtualBoxManager vbm = createNiceMock(VirtualBoxManager.class);
IVirtualBox vBox= createNiceMock(IVirtualBox.class);
IMachine vm = createNiceMock(IMachine.class);
IGuestOSType guestOsType = createNiceMock(IGuestOSType.class);
expect(vbm.getVBox()).andReturn(vBox).anyTimes();
String unknownOsDescription = "SomeOtherOs 2.04";
expect(vm.getOSTypeId()).andReturn("os-type").anyTimes();
expect(vm.getDescription()).andReturn("my-unknown-machine").anyTimes();
expect(guestOsType.getDescription()).andReturn(unknownOsDescription).anyTimes();
expect(guestOsType.getIs64Bit()).andReturn(true);
expect(vBox.getGuestOSType(eq("os-type"))).andReturn(guestOsType);
replay(vbm, vBox, vm, guestOsType);
Image image = new IMachineToImage(vbm).apply(vm);
assertEquals(image.getOperatingSystem().getDescription(), "SomeOtherOs 2.04");
assertEquals(image.getOperatingSystem().getVersion(), "");
}
}

View File

@ -47,7 +47,7 @@ public class IMachineToNodeMetadataTest {
VirtualBox virtualBox = new VirtualBox();
IMachineToNodeMetadata parser = new IMachineToNodeMetadata();
IMachineToHardware hwParser = new IMachineToHardware(virtualBox);
IMachineToHardware hwParser = new IMachineToHardware(manager);
// hwParser.apply()

View File

@ -0,0 +1,85 @@
/*
* *
* * Licensed to jclouds, Inc. (jclouds) under one or more
* * contributor license agreements. See the NOTICE file
* * distributed with this work for additional information
* * regarding copyright ownership. jclouds licenses this file
* * to you under the Apache License, Version 2.0 (the
* * "License"); you may not use this file except in compliance
* * with the License. You may obtain a copy of the License at
* *
* * http://www.apache.org/licenses/LICENSE-2.0
* *
* * Unless required by applicable law or agreed to in writing,
* * software distributed under the License is distributed on an
* * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* * KIND, either express or implied. See the License for the
* * specific language governing permissions and limitations
* * under the License.
*
*/
package org.jclouds.virtualbox.functions;
/**
* @author Andrea Turli
*/
import static org.easymock.EasyMock.expect;
import static org.easymock.classextension.EasyMock.createNiceMock;
import static org.easymock.classextension.EasyMock.replay;
import static org.testng.Assert.assertEquals;
import org.jclouds.compute.ComputeServiceContext;
import org.jclouds.virtualbox.config.VirtualBoxConstants;
import org.jclouds.virtualbox.experiment.TestUtils;
import org.testng.annotations.Test;
import org.virtualbox_4_1.IMachine;
import org.virtualbox_4_1.ISession;
import org.virtualbox_4_1.IVirtualBox;
import org.virtualbox_4_1.VirtualBoxManager;
//TODO should it be a live test?
@Test(groups = "unit")
public class IsoToIMachineTest {
private String settingsFile = "";
private boolean forceOverwrite = true;
private String vmId = null;
private String osTypeId = null;
private String controllerIDE = "test-IDE";
private String diskFormat = "";
private String adminDisk = "testAdmin.vdi";
private String guestId = "guestId";
private String hostId = "hostId";
@Test
public void testConvert() throws Exception {
String vmName = "virtualbox-iso-to-machine-test";
VirtualBoxManager vbm = createNiceMock(VirtualBoxManager.class);
IVirtualBox vBox = createNiceMock(IVirtualBox.class);
IMachine vm = createNiceMock(IMachine.class);
ISession session = createNiceMock(ISession.class);
expect(vbm.getVBox()).andReturn(vBox).anyTimes();
expect(vbm.getSessionObject()).andReturn(session).anyTimes();
expect(vBox.findMachine(vmName)).andReturn(vm).anyTimes();
expect(
vBox.createMachine(settingsFile, vmName, osTypeId, vmId,
forceOverwrite)).andReturn(vm).anyTimes();
expect(vm.getName()).andReturn(vmName).anyTimes();
// expect(vm.lockMachine(session, LockType.Write)).and
expect(session.getMachine()).andReturn(vm).anyTimes();
replay(vbm, vBox, vm, session);
ComputeServiceContext context = TestUtils
.computeServiceForLocalhostAndGuest();
IMachine iMachine = new IsoToIMachine(vbm, adminDisk, diskFormat,
settingsFile, vmName, osTypeId, vmId, forceOverwrite,
controllerIDE, context, hostId, guestId)
.apply(VirtualBoxConstants.VIRTUALBOX_DISTRO_ISO_NAME);
assertEquals(iMachine.getName(), vmName);
}
}

View File

@ -1,16 +0,0 @@
[
{
"uuid": "cc54132d-4912-4106-a91a-7a27e6866c8b",
"description": "Debian 6.0.2.1",
"osFamily": "DEBIAN",
"osVersion": "6.0",
"size": "1"
},
{
"uuid": "46e305b6-6a49-409c-bd12-eb966cdb3664",
"description": "Windows 2008 R2 with SP1 (x64)",
"osFamily": "WINDOWS",
"osVersion": "2008 R2",
"size": "13"
}
]

View File

@ -54,7 +54,7 @@ public class SoftLayerProviderMetadata extends BaseProviderMetadata {
*/
@Override
public String getName() {
return "//TODO SoftLayer";
return "SoftLayer";
}
/**
@ -62,7 +62,7 @@ public class SoftLayerProviderMetadata extends BaseProviderMetadata {
*/
@Override
public String getIdentityName() {
return "//TODO";
return "API Username";
}
/**
@ -70,7 +70,7 @@ public class SoftLayerProviderMetadata extends BaseProviderMetadata {
*/
@Override
public String getCredentialName() {
return "//TODO";
return "API Key";
}
/**
@ -78,7 +78,7 @@ public class SoftLayerProviderMetadata extends BaseProviderMetadata {
*/
@Override
public URI getHomepage() {
return URI.create("//TODO");
return URI.create("http://www.softlayer.com");
}
/**
@ -86,7 +86,7 @@ public class SoftLayerProviderMetadata extends BaseProviderMetadata {
*/
@Override
public URI getConsole() {
return URI.create("//TODO");
return URI.create("https://manage.softlayer.com");
}
/**
* {@inheritDoc}

View File

@ -18,15 +18,14 @@
*/
package org.jclouds.softlayer.compute.config;
import com.google.common.base.Function;
import com.google.common.base.Supplier;
import com.google.inject.Injector;
import com.google.inject.TypeLiteral;
import java.util.Set;
import org.jclouds.compute.ComputeServiceAdapter;
import org.jclouds.compute.config.ComputeServiceAdapterContextModule;
import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.domain.OsFamily;
import org.jclouds.compute.domain.TemplateBuilder;
import org.jclouds.compute.options.TemplateOptions;
import org.jclouds.domain.Location;
import org.jclouds.location.suppliers.OnlyLocationOrFirstZone;
import org.jclouds.softlayer.SoftLayerAsyncClient;
@ -35,12 +34,16 @@ import org.jclouds.softlayer.compute.functions.DatacenterToLocation;
import org.jclouds.softlayer.compute.functions.ProductItemToImage;
import org.jclouds.softlayer.compute.functions.ProductItemsToHardware;
import org.jclouds.softlayer.compute.functions.VirtualGuestToNodeMetadata;
import org.jclouds.softlayer.compute.options.SoftLayerTemplateOptions;
import org.jclouds.softlayer.compute.strategy.SoftLayerComputeServiceAdapter;
import org.jclouds.softlayer.domain.Datacenter;
import org.jclouds.softlayer.domain.ProductItem;
import org.jclouds.softlayer.domain.VirtualGuest;
import java.util.Set;
import com.google.common.base.Function;
import com.google.common.base.Supplier;
import com.google.inject.Injector;
import com.google.inject.TypeLiteral;
/**
*
@ -68,6 +71,7 @@ public class SoftLayerComputeServiceContextModule extends
.to(DatacenterToLocation.class);
bind(new TypeLiteral<Supplier<Location>>() {})
.to(OnlyLocationOrFirstZone.class);
bind(TemplateOptions.class).to(SoftLayerTemplateOptions.class);
}
protected TemplateBuilder provideTemplate(Injector injector, TemplateBuilder template) {

View File

@ -0,0 +1,231 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.softlayer.compute.options;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import org.jclouds.compute.ComputeService;
import org.jclouds.compute.options.TemplateOptions;
import org.jclouds.io.Payload;
import org.jclouds.softlayer.features.VirtualGuestClient;
import com.google.common.net.InternetDomainName;
/**
* Contains options supported by the
* {@link ComputeService#createNodesInGroup(String, int, TemplateOptions)} and
* {@link ComputeService#runNodesWithTag(String, int, TemplateOptions)} operations on the
* <em>gogrid</em> provider.
*
* <h2>Usage</h2> The recommended way to instantiate a {@link SoftLayerTemplateOptions} object is to
* statically import {@code SoftLayerTemplateOptions.*} and invoke a static creation method followed
* by an instance mutator (if needed):
* <p>
*
* <pre>
* import static org.jclouds.compute.options.SoftLayerTemplateOptions.Builder.*;
* ComputeService client = // get connection
* templateBuilder.options(inboundPorts(22, 80, 8080, 443));
* Set&lt;? extends NodeMetadata&gt; set = client.runNodesWithTag(tag, 2, templateBuilder.build());
* </pre>
*
* @author Adrian Cole
*/
public class SoftLayerTemplateOptions extends TemplateOptions implements Cloneable {
protected String domainName = "jclouds.org";
@Override
public SoftLayerTemplateOptions clone() {
SoftLayerTemplateOptions options = new SoftLayerTemplateOptions();
copyTo(options);
return options;
}
@Override
public void copyTo(TemplateOptions to) {
super.copyTo(to);
if (to instanceof SoftLayerTemplateOptions) {
SoftLayerTemplateOptions eTo = SoftLayerTemplateOptions.class.cast(to);
eTo.domainName(domainName);
}
}
/**
* will replace the default domain used when ordering virtual guests. Note this needs to contain
* a public suffix!
*
* @see VirtualGuestClient#orderVirtualGuest
* @see InternetDomainName#hasPublicSuffix
*/
public TemplateOptions domainName(String domainName) {
checkNotNull(domainName, "domainName was null");
checkArgument(InternetDomainName.from(domainName).hasPublicSuffix(), "domainName %s has no public suffix",
domainName);
this.domainName = domainName;
return this;
}
public String getDomainName() {
return domainName;
}
public static final SoftLayerTemplateOptions NONE = new SoftLayerTemplateOptions();
public static class Builder {
/**
* @see #domainName
*/
public static SoftLayerTemplateOptions domainName(String domainName) {
SoftLayerTemplateOptions options = new SoftLayerTemplateOptions();
return SoftLayerTemplateOptions.class.cast(options.domainName(domainName));
}
// methods that only facilitate returning the correct object type
/**
* @see TemplateOptions#inboundPorts(int...)
*/
public static SoftLayerTemplateOptions inboundPorts(int... ports) {
SoftLayerTemplateOptions options = new SoftLayerTemplateOptions();
return SoftLayerTemplateOptions.class.cast(options.inboundPorts(ports));
}
/**
* @see TemplateOptions#blockOnPort(int, int)
*/
public static SoftLayerTemplateOptions blockOnPort(int port, int seconds) {
SoftLayerTemplateOptions options = new SoftLayerTemplateOptions();
return SoftLayerTemplateOptions.class.cast(options.blockOnPort(port, seconds));
}
/**
* @see TemplateOptions#runScript(Payload)
*/
public static SoftLayerTemplateOptions runScript(Payload script) {
SoftLayerTemplateOptions options = new SoftLayerTemplateOptions();
return SoftLayerTemplateOptions.class.cast(options.runScript(script));
}
/**
* @see TemplateOptions#installPrivateKey(Payload)
*/
@Deprecated
public static SoftLayerTemplateOptions installPrivateKey(Payload rsaKey) {
SoftLayerTemplateOptions options = new SoftLayerTemplateOptions();
return SoftLayerTemplateOptions.class.cast(options.installPrivateKey(rsaKey));
}
/**
* @see TemplateOptions#authorizePublicKey(Payload)
*/
@Deprecated
public static SoftLayerTemplateOptions authorizePublicKey(Payload rsaKey) {
SoftLayerTemplateOptions options = new SoftLayerTemplateOptions();
return SoftLayerTemplateOptions.class.cast(options.authorizePublicKey(rsaKey));
}
/**
* @see TemplateOptions#withMetadata()
*/
public static SoftLayerTemplateOptions withMetadata() {
SoftLayerTemplateOptions options = new SoftLayerTemplateOptions();
return SoftLayerTemplateOptions.class.cast(options.withMetadata());
}
}
// methods that only facilitate returning the correct object type
/**
* @see TemplateOptions#blockOnPort(int, int)
*/
@Override
public SoftLayerTemplateOptions blockOnPort(int port, int seconds) {
return SoftLayerTemplateOptions.class.cast(super.blockOnPort(port, seconds));
}
/**
* @see TemplateOptions#inboundPorts(int...)
*/
@Override
public SoftLayerTemplateOptions inboundPorts(int... ports) {
return SoftLayerTemplateOptions.class.cast(super.inboundPorts(ports));
}
/**
* @see TemplateOptions#authorizePublicKey(String)
*/
@Override
public SoftLayerTemplateOptions authorizePublicKey(String publicKey) {
return SoftLayerTemplateOptions.class.cast(super.authorizePublicKey(publicKey));
}
/**
* @see TemplateOptions#authorizePublicKey(Payload)
*/
@Override
@Deprecated
public SoftLayerTemplateOptions authorizePublicKey(Payload publicKey) {
return SoftLayerTemplateOptions.class.cast(super.authorizePublicKey(publicKey));
}
/**
* @see TemplateOptions#installPrivateKey(String)
*/
@Override
public SoftLayerTemplateOptions installPrivateKey(String privateKey) {
return SoftLayerTemplateOptions.class.cast(super.installPrivateKey(privateKey));
}
/**
* @see TemplateOptions#installPrivateKey(Payload)
*/
@Override
@Deprecated
public SoftLayerTemplateOptions installPrivateKey(Payload privateKey) {
return SoftLayerTemplateOptions.class.cast(super.installPrivateKey(privateKey));
}
/**
* @see TemplateOptions#runScript(Payload)
*/
@Override
public SoftLayerTemplateOptions runScript(Payload script) {
return SoftLayerTemplateOptions.class.cast(super.runScript(script));
}
/**
* @see TemplateOptions#runScript(byte[])
*/
@Override
@Deprecated
public SoftLayerTemplateOptions runScript(byte[] script) {
return SoftLayerTemplateOptions.class.cast(super.runScript(script));
}
/**
* @see TemplateOptions#withMetadata()
*/
@Override
public SoftLayerTemplateOptions withMetadata() {
return SoftLayerTemplateOptions.class.cast(super.withMetadata());
}
}

View File

@ -18,31 +18,46 @@
*/
package org.jclouds.softlayer.compute.strategy;
import com.google.common.base.Predicates;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import static org.jclouds.softlayer.predicates.ProductItemPredicates.categoryCode;
import static org.jclouds.softlayer.predicates.ProductItemPredicates.matches;
import static org.jclouds.softlayer.predicates.ProductItemPredicates.units;
import static org.jclouds.softlayer.predicates.ProductPackagePredicates.named;
import java.util.Map;
import java.util.Set;
import javax.inject.Inject;
import javax.inject.Named;
import javax.inject.Singleton;
import org.jclouds.compute.ComputeService;
import org.jclouds.compute.ComputeServiceAdapter;
import org.jclouds.compute.domain.Template;
import org.jclouds.domain.Credentials;
import org.jclouds.softlayer.SoftLayerClient;
import org.jclouds.softlayer.compute.functions.ProductItems;
import org.jclouds.softlayer.domain.*;
import org.jclouds.softlayer.compute.options.SoftLayerTemplateOptions;
import org.jclouds.softlayer.domain.BillingItemVirtualGuest;
import org.jclouds.softlayer.domain.Datacenter;
import org.jclouds.softlayer.domain.OperatingSystem;
import org.jclouds.softlayer.domain.Password;
import org.jclouds.softlayer.domain.ProductItem;
import org.jclouds.softlayer.domain.ProductItemPrice;
import org.jclouds.softlayer.domain.ProductOrder;
import org.jclouds.softlayer.domain.ProductPackage;
import org.jclouds.softlayer.domain.VirtualGuest;
import org.jclouds.softlayer.features.AccountClient;
import org.jclouds.softlayer.features.ProductPackageClient;
import org.jclouds.softlayer.reference.SoftLayerConstants;
import javax.inject.Inject;
import javax.inject.Named;
import javax.inject.Singleton;
import java.util.Map;
import java.util.Set;
import static com.google.common.base.Preconditions.checkNotNull;
import static org.jclouds.softlayer.predicates.ProductItemPredicates.*;
import static org.jclouds.softlayer.predicates.ProductPackagePredicates.named;
import com.google.common.base.Predicates;
import com.google.common.base.Splitter;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
/**
* defines the connection between the {@link SoftLayerClient} implementation and the jclouds
@ -54,7 +69,6 @@ public class SoftLayerComputeServiceAdapter implements
ComputeServiceAdapter<VirtualGuest, Set<ProductItem>, ProductItem, Datacenter> {
public static final String SAN_DESCRIPTION_REGEX=".*GB \\(SAN\\).*";
//TODO: Better to pass this in as a property like virtualGuestPackageName?
private static final Float BOOT_VOLUME_CAPACITY = 100F;
private final SoftLayerClient client;
@ -68,20 +82,87 @@ public class SoftLayerComputeServiceAdapter implements
}
@Override
public VirtualGuest createNodeWithGroupEncodedIntoNameThenStoreCredentials(String tag, String name,
public VirtualGuest createNodeWithGroupEncodedIntoNameThenStoreCredentials(String group, String name,
Template template, Map<String, Credentials> credentialStore) {
VirtualGuest from = null; // TODO create the backend object using parameters from the
// template. ex.
// VirtualGuest from =
// client.getVirtualGuestClient().createServerInDC(template.getLocation().getId(), name,
// Long.parseLong(template.getImage().getProviderId()),
// Long.parseLong(template.getHardware().getProviderId()));
// store the credentials so that later functions can use them
// credentialStore.put("node#"+ from.getId() + "", new Credentials(from.loginUser,
// from.password));
return from;
checkNotNull(template, "template was null");
checkNotNull(template.getOptions(), "template options was null");
checkArgument(template.getOptions().getClass().isAssignableFrom(SoftLayerTemplateOptions.class),
"options class %s should have been assignable from SoftLayerTemplateOptions", template.getOptions()
.getClass());
Iterable<VirtualGuest> existing = findVirtualGuests(name,group);
if(!Iterables.isEmpty(existing)) {
throw new IllegalStateException(
"VirtualGuest(s) already exist with hostname:"+name+", group:"+group+". Existing:"+existing);
}
VirtualGuest newGuest = VirtualGuest.builder()
.domain(template.getOptions().as(SoftLayerTemplateOptions.class).getDomainName())
.hostname(name)
.build();
ProductOrder order = ProductOrder.builder()
.packageId(getProductPackage().getId())
.location(template.getLocation().getId())
.quantity(1)
.useHourlyPricing(true)
.prices(getPrices(template))
.virtualGuest(newGuest)
.build();
client.getVirtualGuestClient().orderVirtualGuest(order);
VirtualGuest result = Iterables.getOnlyElement(findVirtualGuests(name, group));
Credentials credentials = new Credentials(null,null);
// This information is not always available.
OperatingSystem os = result.getOperatingSystem();
if(os!=null) {
Set<Password> passwords = os.getPasswords();
if(passwords.size()>0) {
Password pw = Iterables.get(passwords,0);
credentials = new Credentials(pw.getUsername(),pw.getPassword());
}
}
credentialStore.put("node#"+result.getId(),credentials);
return result;
}
private Iterable<VirtualGuest> findVirtualGuests(String hostname,String domain) {
checkNotNull(hostname,"hostname");
checkNotNull(domain,"domain");
Set<VirtualGuest> result = Sets.newLinkedHashSet();
for( VirtualGuest guest : client.getVirtualGuestClient().listVirtualGuests()) {
if ( guest.getHostname().equals(hostname) && guest.getDomain().equals(domain)) {
result.add(guest);
}
}
return result;
}
private Iterable<ProductItemPrice> getPrices(Template template) {
Set<ProductItemPrice> result = Sets.newLinkedHashSet();
int imageId = Integer.parseInt(template.getImage().getId());
result.add(ProductItemPrice.builder().id(imageId).build());
Iterable<String> hardwareIds = Splitter.on(",").split(template.getHardware().getId());
for(String hardwareId: hardwareIds) {
int id = Integer.parseInt(hardwareId);
result.add(ProductItemPrice.builder().id(id).build());
}
result.addAll(SoftLayerConstants.DEFAULT_VIRTUAL_GUEST_PRICES);
return result;
}
@Override
public Iterable<Set<ProductItem>> listHardwareProfiles() {
ProductPackage productPackage = getProductPackage();

View File

@ -0,0 +1,137 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.softlayer.domain;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Sets;
import java.util.Set;
import static com.google.common.base.Preconditions.checkNotNull;
/**
* Extends the SoftLayer_Software_Component data type to include operating system specific properties.
*
* @author Jason King
* @see <a href=
* "http://sldn.softlayer.com/reference/datatypes/SoftLayer_Software_Component_OperatingSystem"
* />
*/
public class OperatingSystem implements Comparable<OperatingSystem> {
// There are other properties
public static Builder builder() {
return new Builder();
}
public static class Builder {
private int id = -1;
private Set<Password> passwords = Sets.newLinkedHashSet();
public Builder id(int id) {
this.id = id;
return this;
}
public Builder password(Password password) {
this.passwords.add(checkNotNull(password, "password"));
return this;
}
public Builder passwords(Iterable<Password> passwords) {
this.passwords = ImmutableSet.<Password> copyOf(checkNotNull(passwords, "passwords"));
return this;
}
public OperatingSystem build() {
return new OperatingSystem(id, passwords);
}
public static Builder fromOperatingSystem(OperatingSystem in) {
return OperatingSystem.builder()
.id(in.getId())
.passwords(in.getPasswords());
}
}
private int id = -1;
private Set<Password> passwords = Sets.newLinkedHashSet();
// for deserializer
OperatingSystem() {
}
public OperatingSystem(int id,Iterable<Password> passwords) {
this.id = id;
this.passwords = ImmutableSet.<Password> copyOf(checkNotNull(passwords, "passwords"));
}
@Override
public int compareTo(OperatingSystem arg0) {
return new Integer(id).compareTo(arg0.getId());
}
/**
* @return An ID number identifying this Software Component (Software Installation)
*/
public int getId() {
return id;
}
/**
*
* @return Username/Password pairs used for access to this Software Installation.
*/
public Set<Password> getPasswords() {
return passwords;
}
public Builder toBuilder() {
return Builder.fromOperatingSystem(this);
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + (id ^ (id >>> 32));
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
OperatingSystem other = (OperatingSystem) obj;
if (id != other.id)
return false;
return true;
}
@Override
public String toString() {
return "OperatingSystem [id=" + id + ", passwords=" + passwords + "]";
}
}

View File

@ -0,0 +1,141 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.softlayer.domain;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Strings.emptyToNull;
/**
*
* Contains a password for a specific software component instance
*
* @author Jason King
* @see <a href= "http://sldn.softlayer.com/reference/datatypes/SoftLayer_Software_Component_Password"
* />
*/
public class Password implements Comparable<Password> {
public static Builder builder() {
return new Builder();
}
public static class Builder {
private int id = -1;
private String username;
private String password;
public Builder id(int id) {
this.id = id;
return this;
}
public Builder username(String username) {
this.username = username;
return this;
}
public Builder password(String password) {
this.password = password;
return this;
}
public Password build() {
return new Password(id, username, password);
}
public static Builder fromPassword(Password in) {
return Password.builder().id(in.getId())
.username(in.getUsername())
.password(in.getPassword());
}
}
private int id = -1;
private String username;
private String password;
// for deserializer
Password() {
}
public Password(int id, String username, String password) {
this.id = id;
this.username = checkNotNull(emptyToNull(username),"username cannot be null or empty:"+username);
this.password = password;
}
@Override
public int compareTo(Password arg0) {
return new Integer(id).compareTo(arg0.getId());
}
/**
* @return An id number for this specific username/password pair.
*/
public int getId() {
return id;
}
/**
* @return The username part of the username/password pair.
*/
public String getUsername() {
return username;
}
/**
* @return The password part of the username/password pair.
*/
public String getPassword() {
return password;
}
public Builder toBuilder() {
return Builder.fromPassword(this);
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + (id ^ (id >>> 32));
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Password other = (Password) obj;
if (id != other.id)
return false;
return true;
}
@Override
public String toString() {
return "Password [id=" + id + ", username=" + username + ", password=**********]";
}
}

View File

@ -31,6 +31,17 @@ import com.google.gson.annotations.SerializedName;
* interaction. <br/>
* A guest, also known as a virtual server or CloudLayer Computing Instance, represents an
* allocation of resources on a virtual host.
*
* The hostname and domain must be alphanumeric strings that may be separated by periods '.'.
* The only other allowable special character is the dash '-'.
* However the special characters '.' and '-' may not be consecutive.
* Each alphanumeric string separated by a period is considered a label.
* Labels must begin and end with an alphanumeric character.
* Each label cannot be soley comprised of digits and must be between 1-63 characters in length.
* The last label, the TLD (top level domain) must be between 2-6 alphabetic characters.
* The domain portion must consist of least one label followed by a period '.' then ending with the TLD label.
* Combining the hostname, followed by a period '.', followed by the domain gives the FQDN (fully qualified domain name),
* which may not exceed 253 characters in total length.
*
* @author Adrian Cole
* @see <a href=
@ -64,6 +75,7 @@ public class VirtualGuest implements Comparable<VirtualGuest> {
private String primaryBackendIpAddress;
private String primaryIpAddress;
private BillingItemVirtualGuest billingItem;
private OperatingSystem operatingSystem;
public Builder id(int id) {
this.id = id;
@ -170,12 +182,17 @@ public class VirtualGuest implements Comparable<VirtualGuest> {
return this;
}
public Builder operatingSystem(OperatingSystem operatingSystem) {
this.operatingSystem = operatingSystem;
return this;
}
public VirtualGuest build() {
return new VirtualGuest(accountId, createDate, dedicatedAccountHostOnly, domain,
fullyQualifiedDomainName, hostname, id, lastVerifiedDate, maxCpu,
maxCpuUnits, maxMemory, metricPollDate, modifyDate, notes,
privateNetworkOnly, startCpus, statusId, uuid, primaryBackendIpAddress,
primaryIpAddress,billingItem);
primaryIpAddress,billingItem,operatingSystem);
}
public static Builder fromVirtualGuest(VirtualGuest in) {
@ -200,7 +217,9 @@ public class VirtualGuest implements Comparable<VirtualGuest> {
.uuid(in.getUuid())
.primaryBackendIpAddress(in.getPrimaryBackendIpAddress())
.primaryIpAddress(in.getPrimaryIpAddress())
.billingItem(in.getBillingItem());
.billingItem(in.getBillingItem())
.operatingSystem(in.getOperatingSystem());
}
}
@ -252,6 +271,7 @@ public class VirtualGuest implements Comparable<VirtualGuest> {
private String primaryIpAddress;
private BillingItemVirtualGuest billingItem;
private OperatingSystem operatingSystem;
// for deserializer
VirtualGuest() {
@ -262,7 +282,7 @@ public class VirtualGuest implements Comparable<VirtualGuest> {
String fullyQualifiedDomainName, String hostname, int id, Date lastVerifiedDate, int maxCpu,
String maxCpuUnits, int maxMemory, Date metricPollDate, Date modifyDate, String notes,
boolean privateNetworkOnly, int startCpus, int statusId, String uuid, String primaryBackendIpAddress,
String primaryIpAddress,BillingItemVirtualGuest billingItem) {
String primaryIpAddress,BillingItemVirtualGuest billingItem, OperatingSystem operatingSystem) {
this.accountId = accountId;
this.createDate = createDate;
this.dedicatedAccountHostOnly = dedicatedAccountHostOnly;
@ -284,6 +304,7 @@ public class VirtualGuest implements Comparable<VirtualGuest> {
this.primaryBackendIpAddress = primaryBackendIpAddress;
this.primaryIpAddress = primaryIpAddress;
this.billingItem = billingItem;
this.operatingSystem = operatingSystem;
}
@Override
@ -441,6 +462,13 @@ public class VirtualGuest implements Comparable<VirtualGuest> {
return billingItem;
}
/**
* @return A guest's operating system.
*/
public OperatingSystem getOperatingSystem() {
return operatingSystem;
}
@Override
public int hashCode() {
final int prime = 31;
@ -466,6 +494,7 @@ public class VirtualGuest implements Comparable<VirtualGuest> {
result = prime * result + statusId;
result = prime * result + ((uuid == null) ? 0 : uuid.hashCode());
result = prime * result + ((billingItem == null) ? 0 : billingItem.hashCode());
result = prime * result + ((operatingSystem == null) ? 0 : operatingSystem.hashCode());
return result;
}
@ -559,6 +588,11 @@ public class VirtualGuest implements Comparable<VirtualGuest> {
return false;
} else if (!billingItem.equals(other.billingItem))
return false;
if (operatingSystem == null) {
if (other.operatingSystem != null)
return false;
} else if (!operatingSystem.equals(other.operatingSystem))
return false;
return true;
}
@ -571,7 +605,7 @@ public class VirtualGuest implements Comparable<VirtualGuest> {
+ ", metricPollDate=" + metricPollDate + ", modifyDate=" + modifyDate + ", notes=" + notes
+ ", primaryBackendIpAddress=" + primaryBackendIpAddress + ", primaryIpAddress=" + primaryIpAddress
+ ", privateNetworkOnly=" + privateNetworkOnly + ", startCpus=" + startCpus + ", statusId=" + statusId
+ ", uuid=" + uuid + ", billingItem="+billingItem+"]";
+ ", uuid=" + uuid + ", billingItem="+billingItem+", operatingSystem="+operatingSystem+"]";
}
}

View File

@ -47,6 +47,7 @@ import java.util.Set;
@RequestFilters(BasicAuthentication.class)
@Path("/v{jclouds.api-version}")
public interface VirtualGuestAsyncClient {
public static String LIST_GUEST_MASK = "virtualGuests.powerState;virtualGuests.networkVlans;virtualGuests.operatingSystem.passwords;virtualGuests.datacenter;virtualGuests.billingItem";
public static String GUEST_MASK = "powerState;networkVlans;operatingSystem.passwords;datacenter;virtualGuests.billingItem";
/**
@ -54,7 +55,7 @@ public interface VirtualGuestAsyncClient {
*/
@GET
@Path("/SoftLayer_Account/VirtualGuests.json")
@QueryParams(keys = "objectMask", values = GUEST_MASK)
@QueryParams(keys = "objectMask", values = LIST_GUEST_MASK)
@Consumes(MediaType.APPLICATION_JSON)
@ExceptionParser(ReturnEmptySetOnNotFoundOr404.class)
ListenableFuture<Set<VirtualGuest>> listVirtualGuests();

View File

@ -20,30 +20,42 @@ package org.jclouds.softlayer.compute;
import static org.jclouds.softlayer.predicates.ProductItemPredicates.categoryCode;
import static org.jclouds.softlayer.predicates.ProductItemPredicates.units;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertFalse;
import static org.testng.AssertJUnit.assertEquals;
import java.util.Map;
import java.util.Set;
import org.jclouds.compute.domain.ExecResponse;
import org.jclouds.compute.domain.Template;
import org.jclouds.domain.Credentials;
import org.jclouds.net.IPSocket;
import org.jclouds.softlayer.compute.options.SoftLayerTemplateOptions;
import org.jclouds.softlayer.compute.strategy.SoftLayerComputeServiceAdapter;
import org.jclouds.softlayer.domain.ProductItem;
import org.jclouds.softlayer.domain.VirtualGuest;
import org.jclouds.softlayer.features.BaseSoftLayerClientLiveTest;
import org.jclouds.softlayer.features.ProductPackageClientLiveTest;
import org.testng.Assert;
import org.jclouds.ssh.SshClient;
import org.testng.annotations.AfterGroups;
import org.testng.annotations.BeforeGroups;
import org.testng.annotations.Test;
import com.google.common.collect.Iterables;
import com.google.common.collect.Maps;
import com.google.common.net.InetAddresses;
@Test(groups = "live", testName = "SoftLayerComputeServiceAdapterLiveTest")
@Test(groups = "live", singleThreaded = true, testName = "SoftLayerComputeServiceAdapterLiveTest")
public class SoftLayerComputeServiceAdapterLiveTest extends BaseSoftLayerClientLiveTest {
private SoftLayerComputeServiceAdapter adapter;
private VirtualGuest guest;
@BeforeGroups(groups = { "live" })
public void setupClient() {
super.setupClient();
adapter = new SoftLayerComputeServiceAdapter(context.getApi(), ProductPackageClientLiveTest.CLOUD_SERVER_PACKAGE_NAME);
adapter = new SoftLayerComputeServiceAdapter(context.getApi(),
ProductPackageClientLiveTest.CLOUD_SERVER_PACKAGE_NAME);
}
@Test
@ -51,18 +63,62 @@ public class SoftLayerComputeServiceAdapterLiveTest extends BaseSoftLayerClientL
assertFalse(Iterables.isEmpty(adapter.listLocations()));
}
@Test
public void testCreateNodeWithGroupEncodedIntoNameThenStoreCredentials() {
String group = "foo";
String name = "foo-ef4";
Template template = computeContext.getComputeService().templateBuilder()
.locationId("3") // the default (singapore) doesn't work.
.build();
// test passing custom options
template.getOptions().as(SoftLayerTemplateOptions.class).domainName("me.org");
Map<String, Credentials> credentialStore = Maps.newLinkedHashMap();
guest = adapter.createNodeWithGroupEncodedIntoNameThenStoreCredentials(group, name, template, credentialStore);
assertEquals(guest.getHostname(), name);
assertEquals(guest.getDomain(), template.getOptions().as(SoftLayerTemplateOptions.class).getDomainName());
// check other things, like cpu correct, mem correct, image/os is correct
// (as possible)
assert credentialStore.containsKey("node#" + guest.getId()) : "credentials to log into guest not found " + guest;
assert InetAddresses.isInetAddress(guest.getPrimaryBackendIpAddress()) : guest;
doConnectViaSsh(guest, credentialStore.get("node#" + guest.getId()));
}
protected void doConnectViaSsh(VirtualGuest guest, Credentials creds) {
SshClient ssh = computeContext.utils().sshFactory()
.create(new IPSocket(guest.getPrimaryBackendIpAddress(), 22), creds);
try {
ssh.connect();
ExecResponse hello = ssh.exec("echo hello");
assertEquals(hello.getOutput().trim(), "hello");
System.err.println(ssh.exec("df -k").getOutput());
System.err.println(ssh.exec("mount").getOutput());
System.err.println(ssh.exec("uname -a").getOutput());
} finally {
if (ssh != null)
ssh.disconnect();
}
}
@Test
public void testListHardwareProfiles() {
Iterable<Set<ProductItem>> profiles = adapter.listHardwareProfiles();
assertFalse(Iterables.isEmpty(profiles));
for( Set<ProductItem> profile: profiles) {
for (Set<ProductItem> profile : profiles) {
// CPU, RAM and Volume
assertEquals(profile.size(), 3);
ProductItem cpuItem = Iterables.getOnlyElement(Iterables.filter(profile, units("PRIVATE_CORE")));
ProductItem ramItem = Iterables.getOnlyElement(Iterables.filter(profile,categoryCode("ram")));
Assert.assertEquals(cpuItem.getCapacity(),ramItem.getCapacity());
ProductItem ramItem = Iterables.getOnlyElement(Iterables.filter(profile, categoryCode("ram")));
assertEquals(cpuItem.getCapacity(), ramItem.getCapacity());
}
}
@AfterGroups(groups = "live")
protected void tearDown() {
if (guest != null)
adapter.destroyNode(guest.getId() + "");
super.tearDown();
}
}

View File

@ -18,20 +18,22 @@
*/
package org.jclouds.softlayer.compute;
import com.google.common.base.Predicate;
import com.google.common.base.Predicates;
import com.google.common.collect.ImmutableSet;
import org.jclouds.compute.BaseTemplateBuilderLiveTest;
import org.jclouds.compute.domain.OsFamily;
import org.jclouds.compute.domain.OsFamilyVersion64Bit;
import org.jclouds.compute.domain.Template;
import org.testng.annotations.Test;
import static org.jclouds.compute.util.ComputeServiceUtils.getCores;
import static org.testng.Assert.assertEquals;
import java.io.IOException;
import java.util.Set;
import static org.jclouds.compute.util.ComputeServiceUtils.getCores;
import static org.testng.Assert.assertEquals;
import org.jclouds.compute.BaseTemplateBuilderLiveTest;
import org.jclouds.compute.domain.OsFamily;
import org.jclouds.compute.domain.OsFamilyVersion64Bit;
import org.jclouds.compute.domain.Template;
import org.jclouds.softlayer.compute.options.SoftLayerTemplateOptions;
import org.testng.annotations.Test;
import com.google.common.base.Predicate;
import com.google.common.base.Predicates;
import com.google.common.collect.ImmutableSet;
/**
*
@ -80,6 +82,8 @@ public class SoftLayerTemplateBuilderLiveTest extends BaseTemplateBuilderLiveTes
assertEquals(defaultTemplate.getImage().getOperatingSystem().is64Bit(), true);
assertEquals(defaultTemplate.getImage().getOperatingSystem().getFamily(), OsFamily.UBUNTU);
assertEquals(getCores(defaultTemplate.getHardware()), 2.0d);
// test that we bound the correct templateoptions in guice
assertEquals(defaultTemplate.getOptions().getClass(), SoftLayerTemplateOptions.class);
}
@Override

View File

@ -0,0 +1,74 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.softlayer.compute.options;
import static org.jclouds.softlayer.compute.options.SoftLayerTemplateOptions.Builder.domainName;
import static org.testng.Assert.assertEquals;
import org.jclouds.compute.options.TemplateOptions;
import org.testng.annotations.Test;
/**
* Tests possible uses of {@code SoftLayerTemplateOptions} and {@code
* SoftLayerTemplateOptions.Builder.*}.
*
* @author Adrian Cole
*/
// NOTE:without testName, this will not call @Before* and fail w/NPE during surefire
@Test(groups = "unit", testName = "SoftLayerTemplateOptionsTest")
public class SoftLayerTemplateOptionsTest {
@Test
public void testAs() {
TemplateOptions options = new SoftLayerTemplateOptions();
assertEquals(options.as(SoftLayerTemplateOptions.class), options);
}
@Test
public void testDefaultDomainName() {
TemplateOptions options = new SoftLayerTemplateOptions();
assertEquals(options.as(SoftLayerTemplateOptions.class).getDomainName(), "jclouds.org");
}
@Test
public void testDomainName() {
TemplateOptions options = new SoftLayerTemplateOptions().domainName("me.com");
assertEquals(options.as(SoftLayerTemplateOptions.class).getDomainName(), "me.com");
}
@Test
public void testDomainNameStatic() {
TemplateOptions options = domainName("me.com");
assertEquals(options.as(SoftLayerTemplateOptions.class).getDomainName(), "me.com");
}
@Test
public void testDomainNameNullHasDecentMessage() {
try {
new SoftLayerTemplateOptions().domainName(null);
assert false : "should NPE";
} catch (NullPointerException e) {
assertEquals(e.getMessage(), "domainName was null");
}
}
@Test(expectedExceptions = IllegalArgumentException.class)
public void testDomainNameIsInvalidThrowsIllegalArgument() {
new SoftLayerTemplateOptions().domainName("foo");
}
}

View File

@ -20,11 +20,13 @@ package org.jclouds.softlayer.features;
import static com.google.common.base.Preconditions.checkNotNull;
import org.jclouds.compute.ComputeServiceContext;
import org.jclouds.compute.ComputeServiceContextFactory;
import org.jclouds.logging.log4j.config.Log4JLoggingModule;
import org.jclouds.rest.RestContext;
import org.jclouds.softlayer.SoftLayerAsyncClient;
import org.jclouds.softlayer.SoftLayerClient;
import org.jclouds.sshj.config.SshjSshClientModule;
import org.testng.annotations.AfterGroups;
import org.testng.annotations.BeforeGroups;
import org.testng.annotations.Test;
@ -41,15 +43,16 @@ import com.google.inject.Module;
public class BaseSoftLayerClientLiveTest {
protected RestContext<SoftLayerClient, SoftLayerAsyncClient> context;
protected ComputeServiceContext computeContext;
@BeforeGroups(groups = { "live" })
public void setupClient() {
String identity = checkNotNull(System.getProperty("test.softlayer.identity"), "test.softlayer.identity");
String credential = checkNotNull(System.getProperty("test.softlayer.credential"), "test.softlayer.credential");
context = new ComputeServiceContextFactory().createContext("softlayer", identity, credential,
ImmutableSet.<Module> of(new Log4JLoggingModule())).getProviderSpecificContext();
computeContext = new ComputeServiceContextFactory().createContext("softlayer", identity, credential,
ImmutableSet.<Module> of(new Log4JLoggingModule(), new SshjSshClientModule()));
context = computeContext.getProviderSpecificContext();
}

View File

@ -47,7 +47,7 @@ public class VirtualGuestAsyncClientTest extends BaseSoftLayerAsyncClientTest<Vi
assertRequestLineEquals(
httpRequest,
"GET https://api.softlayer.com/rest/v3/SoftLayer_Account/VirtualGuests.json?objectMask=powerState%3BnetworkVlans%3BoperatingSystem.passwords%3Bdatacenter%3BvirtualGuests.billingItem HTTP/1.1");
"GET https://api.softlayer.com/rest/v3/SoftLayer_Account/VirtualGuests.json?objectMask=virtualGuests.powerState%3BvirtualGuests.networkVlans%3BvirtualGuests.operatingSystem.passwords%3BvirtualGuests.datacenter%3BvirtualGuests.billingItem HTTP/1.1");
assertNonPayloadHeadersEqual(httpRequest, "Accept: application/json\n");
assertPayloadEquals(httpRequest, null, null, false);
@ -57,7 +57,7 @@ public class VirtualGuestAsyncClientTest extends BaseSoftLayerAsyncClientTest<Vi
assertRequestLineEquals(
httpRequest,
"GET https://api.softlayer.com/rest/v3/SoftLayer_Account/VirtualGuests.json?objectMask=powerState%3BnetworkVlans%3BoperatingSystem.passwords%3Bdatacenter%3BvirtualGuests.billingItem HTTP/1.1");
"GET https://api.softlayer.com/rest/v3/SoftLayer_Account/VirtualGuests.json?objectMask=virtualGuests.powerState%3BvirtualGuests.networkVlans%3BvirtualGuests.operatingSystem.passwords%3BvirtualGuests.datacenter%3BvirtualGuests.billingItem HTTP/1.1");
// for example, using basic authentication, we should get "only one"
// header
assertNonPayloadHeadersEqual(httpRequest,

View File

@ -62,7 +62,9 @@ public class Utils {
}
}
private static final Pattern pattern = Pattern.compile("\\{(.+?)\\}");
/** matches any expression inside curly braces (where the expression does not including an open curly brace) */
private static final Pattern pattern = Pattern.compile("\\{([^\\{]+?)\\}");
/**
* replaces tokens that are expressed as <code>{token}</code>

View File

@ -23,6 +23,7 @@ import static org.testng.Assert.assertEquals;
import java.io.UnsupportedEncodingException;
import org.jclouds.scriptbuilder.domain.OsFamily;
import org.jclouds.scriptbuilder.domain.ShellToken;
import org.testng.annotations.Test;
import com.google.common.collect.ImmutableList;
@ -80,4 +81,9 @@ public class UtilsTest {
"set HOST=\r\nset PORT=\r\n");
}
public void testSingleCurlyBraceDoesntBreakLfTokenReplacement() {
assertEquals(Utils.replaceTokens("{{lf}", ShellToken.tokenValueMap(OsFamily.UNIX)),
"{\n");
}
}