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, our compute api supports: aws-ec2, gogrid, cloudservers-us, stub (in-memory), deltacloud,
cloudservers-uk, vcloud (generic), ec2 (generic), byon, nova, cloudservers-uk, vcloud (generic), ec2 (generic), byon, nova,
trmk-ecloud, trmk-vcloudexpress, eucalyptus (generic), trmk-ecloud, trmk-vcloudexpress, eucalyptus (generic),
cloudsigma-zrh, elasticstack(generic), cloudsigma-zrh, elasticstack(generic), go2cloud-jhb1,
bluelock-vcloud-zone01, stratogen-vcloud-mycloud, rimuhosting, bluelock-vcloud-zone01, stratogen-vcloud-mycloud, rimuhosting,
slicehost, eucalyptus-partnercloud-ec2, elastichosts-lon-p (Peer 1), slicehost, eucalyptus-partnercloud-ec2, elastichosts-lon-p (Peer 1),
elastichosts-sat-p (Peer 1), elastichosts-lon-b (BlueSquare), elastichosts-sat-p (Peer 1), elastichosts-lon-b (BlueSquare),

View File

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

View File

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

View File

@ -63,6 +63,30 @@ public class ServerToMapTest {
"vnc:password", "XXXXXXXX")).build()); "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() { public void testBasicsV2() {
assertEquals( assertEquals(
SERVER_TO_MAP_V2.apply(new Server.Builder() SERVER_TO_MAP_V2.apply(new Server.Builder()

View File

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

View File

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

View File

@ -52,7 +52,12 @@ import com.google.inject.Provides;
/** /**
* Configures {@link ExecutorService}. * 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 * @author Adrian Cole
*/ */
@ -92,7 +97,7 @@ public class ExecutorServiceModule extends AbstractModule {
static ExecutorService addToStringOnSubmit(ExecutorService executor) { static ExecutorService addToStringOnSubmit(ExecutorService executor) {
if (executor != null) { if (executor != null) {
return new AddToStringOnSubmitExecutorService(executor); return new DescribingExecutorService(executor);
} }
return executor; return executor;
} }
@ -117,11 +122,11 @@ public class ExecutorServiceModule extends AbstractModule {
protected void configure() { protected void configure() {
} }
static class AddToStringOnSubmitExecutorService implements ExecutorService { static class DescribingExecutorService implements ExecutorService {
private final ExecutorService delegate; private final ExecutorService delegate;
public AddToStringOnSubmitExecutorService(ExecutorService delegate) { public DescribingExecutorService(ExecutorService delegate) {
this.delegate = checkNotNull(delegate, "delegate"); this.delegate = checkNotNull(delegate, "delegate");
} }
@ -174,18 +179,18 @@ public class ExecutorServiceModule extends AbstractModule {
@Override @Override
public <T> Future<T> submit(Callable<T> task) { 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" }) @SuppressWarnings({ "unchecked", "rawtypes" })
@Override @Override
public Future<?> submit(Runnable task) { public Future<?> submit(Runnable task) {
return new AddToStringFuture(delegate.submit(task), task.toString()); return new DescribedFuture(delegate.submit(task), task.toString(), getStackTraceHere());
} }
@Override @Override
public <T> Future<T> submit(Runnable task, T result) { 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 @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 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.delegate = delegate;
this.toString = toString; this.description = description;
this.submissionTrace = submissionTrace;
} }
@Override @Override
@ -226,12 +233,65 @@ public class ExecutorServiceModule extends AbstractModule {
@Override @Override
public T get() throws InterruptedException, ExecutionException { 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 @Override
public T get(long arg0, TimeUnit arg1) throws InterruptedException, ExecutionException, TimeoutException { 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 @Override
@ -256,7 +316,7 @@ public class ExecutorServiceModule extends AbstractModule {
@Override @Override
public String toString() { public String toString() {
return toString; return description;
} }
} }
@ -302,4 +362,14 @@ public class ExecutorServiceModule extends AbstractModule {
.setThreadFactory(Executors.defaultThreadFactory()).build()); .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 static org.testng.Assert.assertEquals;
import java.io.IOException; import java.io.IOException;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService; import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;
import org.jclouds.Constants; import org.jclouds.Constants;
import org.jclouds.lifecycle.Closer; import org.jclouds.lifecycle.Closer;
import org.testng.annotations.Test; import org.testng.annotations.Test;
import com.google.common.base.Throwables;
import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableList;
import com.google.inject.Guice; import com.google.inject.Guice;
import com.google.inject.Injector; import com.google.inject.Injector;
@ -64,15 +68,14 @@ public class ExecutorServiceModuleTest {
public void testShutdownOnCloseThroughModule() throws IOException { public void testShutdownOnCloseThroughModule() throws IOException {
ExecutorServiceModule module = new ExecutorServiceModule() { ExecutorServiceModule module = new ExecutorServiceModule() {
@Override @Override
protected void configure() { protected void configure() {
bindConstant().annotatedWith(Names.named(Constants.PROPERTY_IO_WORKER_THREADS)).to(1); bindConstant().annotatedWith(Names.named(Constants.PROPERTY_IO_WORKER_THREADS)).to(1);
bindConstant().annotatedWith(Names.named(Constants.PROPERTY_USER_THREADS)).to(1); bindConstant().annotatedWith(Names.named(Constants.PROPERTY_USER_THREADS)).to(1);
super.configure(); super.configure();
} }
}; };
Injector i = Guice.createInjector(module); Injector i = Guice.createInjector(module);
assertEquals(module.userExecutorFromConstructor, null); assertEquals(module.userExecutorFromConstructor, null);
assertEquals(module.ioExecutorFromConstructor, null); assertEquals(module.ioExecutorFromConstructor, null);
@ -93,4 +96,163 @@ public class ExecutorServiceModuleTest {
assert io.isShutdown(); 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; 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.compute.domain.TemplateBuilder;
import org.jclouds.elasticstack.compute.config.ElasticStackComputeServiceContextModule; import org.jclouds.elasticstack.compute.config.ElasticStackComputeServiceContextModule;
@ -33,6 +33,6 @@ public class Go2CloudJohannesburg1ComputeServiceContextModule extends ElasticSta
@Override @Override
protected TemplateBuilder provideTemplate(Injector injector, TemplateBuilder template) { 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 * @author Adrian Cole
*/ */
@Test(groups = "live", sequential = true) @Test(groups = "live", singleThreaded = true)
public class Go2CloudJohannesburg1ClientLiveTest extends ElasticStackClientLiveTest { public class Go2CloudJohannesburg1ClientLiveTest extends ElasticStackClientLiveTest {
public Go2CloudJohannesburg1ClientLiveTest() { public Go2CloudJohannesburg1ClientLiveTest() {
provider = "go2cloud-jhb1"; 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 @Override
public boolean apply(OsFamilyVersion64Bit input) { public boolean apply(OsFamilyVersion64Bit input) {
switch (input.family) { switch (input.family) {
case UBUNTU:
return (input.version.equals("") || input.version.equals("10.10")) && input.is64Bit;
case DEBIAN: case DEBIAN:
return (input.version.equals("") || input.version.equals("6.0")) && input.is64Bit; return (input.version.equals("") || input.version.equals("6.0")) && input.is64Bit;
case WINDOWS: case WINDOWS:
@ -68,8 +70,8 @@ public class Go2CloudJohannesburg1TemplateBuilderLiveTest extends BaseTemplateBu
public void testDefaultTemplateBuilder() throws IOException { public void testDefaultTemplateBuilder() throws IOException {
Template defaultTemplate = this.context.getComputeService().templateBuilder().build(); Template defaultTemplate = this.context.getComputeService().templateBuilder().build();
assertEquals(defaultTemplate.getImage().getOperatingSystem().is64Bit(), true); assertEquals(defaultTemplate.getImage().getOperatingSystem().is64Bit(), true);
assertEquals(defaultTemplate.getImage().getOperatingSystem().getVersion(), "6.0"); assertEquals(defaultTemplate.getImage().getOperatingSystem().getVersion(), "10.10");
assertEquals(defaultTemplate.getImage().getOperatingSystem().getFamily(), OsFamily.DEBIAN); assertEquals(defaultTemplate.getImage().getOperatingSystem().getFamily(), OsFamily.UBUNTU);
assertEquals(defaultTemplate.getLocation().getId(), "go2cloud-jhb1"); assertEquals(defaultTemplate.getLocation().getId(), "go2cloud-jhb1");
assertEquals(getCores(defaultTemplate.getHardware()), 1.0d); assertEquals(getCores(defaultTemplate.getHardware()), 1.0d);
} }

View File

@ -35,7 +35,7 @@
<properties> <properties>
<test.openhosting-east1.endpoint>https://api.east1.openhosting.com</test.openhosting-east1.endpoint> <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.identity>FIXME_IDENTITY</test.openhosting-east1.identity>
<test.openhosting-east1.credential>FIXME_CREDENTIAL</test.openhosting-east1.credential> <test.openhosting-east1.credential>FIXME_CREDENTIAL</test.openhosting-east1.credential>
</properties> </properties>

View File

@ -35,9 +35,9 @@ public class OpenHostingEast1PropertiesBuilder extends ElasticStackPropertiesBui
@Override @Override
protected Properties defaultProperties() { protected Properties defaultProperties() {
Properties properties = super.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_ENDPOINT, "https://api.east1.openhosting.com");
properties.setProperty(PROPERTY_API_VERSION, "1.0"); properties.setProperty(PROPERTY_API_VERSION, "2.0");
return properties; return properties;
} }

View File

@ -102,7 +102,7 @@ public class OpenHostingEast1ProviderMetadata extends BaseProviderMetadata {
*/ */
@Override @Override
public Set<String> getIso3166Codes() { 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 @Override
protected Set<String> getIso3166Codes() { 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>savvis-symphonyvpdc</module>
<module>greenhousedata-element-vcloud</module> <module>greenhousedata-element-vcloud</module>
<module>aws-cloudwatch</module> <module>aws-cloudwatch</module>
<module>go2cloud-jhb1</module>
</modules> </modules>
</project> </project>

View File

@ -69,6 +69,7 @@ public class VirtualBoxPropertiesBuilder extends PropertiesBuilder {
"jclouds-virtualbox-test")); "jclouds-virtualbox-test"));
// TODO: Add more properties and use the wired properties from test code. // 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; return properties;
} }
} }

View File

@ -21,19 +21,27 @@
package org.jclouds.virtualbox.compute; package org.jclouds.virtualbox.compute;
import com.google.common.base.Throwables; import static com.google.common.base.Preconditions.checkNotNull;
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 javax.inject.Inject;
import java.util.Collections; import java.util.Collections;
import java.util.Map; 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 * 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 * @author Mattias Holmqvist, Andrea Turli
*/ */
@Singleton @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 VirtualBoxManager manager;
private final JustProvider justProvider;
@Inject @Inject
public VirtualBoxComputeServiceAdapter(VirtualBoxManager manager) { public VirtualBoxComputeServiceAdapter(VirtualBoxManager manager, JustProvider justProvider) {
this.manager = checkNotNull(manager, "manager"); this.manager = checkNotNull(manager, "manager");
this.justProvider = checkNotNull(justProvider, "justProvider");
} }
@Override @Override
@ -63,17 +73,18 @@ public class VirtualBoxComputeServiceAdapter implements ComputeServiceAdapter<IM
@Override @Override
public Iterable<IMachine> listHardwareProfiles() { public Iterable<IMachine> listHardwareProfiles() {
return Collections.emptyList(); return manager.getVBox().getMachines();
} }
@Override @Override
public Iterable<IMachine> listImages() { public Iterable<IMachine> listImages() {
return Collections.emptyList(); return manager.getVBox().getMachines();
} }
@Override @SuppressWarnings("unchecked")
public Iterable<Host> listLocations() { @Override
return Collections.emptyList(); public Iterable<Location> listLocations() {
return (Iterable<Location>) justProvider.get();
} }
@Override @Override

View File

@ -21,23 +21,26 @@
package org.jclouds.virtualbox.config; package org.jclouds.virtualbox.config;
import com.google.common.annotations.VisibleForTesting; import java.net.URI;
import com.google.common.base.Function; import java.util.Map;
import com.google.common.base.Supplier;
import com.google.common.collect.ImmutableMap; import javax.inject.Named;
import com.google.inject.Injector; import javax.inject.Singleton;
import com.google.inject.Provides;
import com.google.inject.TypeLiteral;
import org.jclouds.Constants; import org.jclouds.Constants;
import org.jclouds.compute.ComputeServiceAdapter; import org.jclouds.compute.ComputeServiceAdapter;
import org.jclouds.compute.config.ComputeServiceAdapterContextModule; 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.domain.Location;
import org.jclouds.functions.IdentityFunction;
import org.jclouds.location.Provider; import org.jclouds.location.Provider;
import org.jclouds.location.suppliers.OnlyLocationOrFirstZone; import org.jclouds.location.suppliers.OnlyLocationOrFirstZone;
import org.jclouds.virtualbox.compute.VirtualBoxComputeServiceAdapter; 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.IMachineToHardware;
import org.jclouds.virtualbox.functions.IMachineToImage; import org.jclouds.virtualbox.functions.IMachineToImage;
import org.jclouds.virtualbox.functions.IMachineToNodeMetadata; 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.MachineState;
import org.virtualbox_4_1.VirtualBoxManager; import org.virtualbox_4_1.VirtualBoxManager;
import javax.inject.Named; import com.google.common.annotations.VisibleForTesting;
import javax.inject.Singleton; import com.google.common.base.Function;
import java.net.URI; import com.google.common.base.Supplier;
import java.util.Map; 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 * @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() { public VirtualBoxComputeServiceContextModule() {
super(VirtualBoxManager.class, VirtualBoxManager.class); super(VirtualBoxManager.class, VirtualBoxManager.class);
@ -68,15 +74,16 @@ public class VirtualBoxComputeServiceContextModule extends ComputeServiceAdapter
return manager; return manager;
} }
@SuppressWarnings({ "unchecked", "rawtypes" })
@Override @Override
protected void configure() { protected void configure() {
super.configure(); super.configure();
bind(new TypeLiteral<ComputeServiceAdapter<IMachine, IMachine, IMachine, Host>>() { bind(new TypeLiteral<ComputeServiceAdapter<IMachine, IMachine, IMachine, Location>>() {
}).to(VirtualBoxComputeServiceAdapter.class); }).to(VirtualBoxComputeServiceAdapter.class);
bind(new TypeLiteral<Function<IMachine, NodeMetadata>>() { bind(new TypeLiteral<Function<IMachine, NodeMetadata>>() {
}).to(IMachineToNodeMetadata.class); }).to(IMachineToNodeMetadata.class);
bind(new TypeLiteral<Function<Host, Location>>() { bind(new TypeLiteral<Function<Location, Location>>() {
}).to(HostToLocation.class); }).to((Class) IdentityFunction.class);
bind(new TypeLiteral<Function<IMachine, Hardware>>() { bind(new TypeLiteral<Function<IMachine, Hardware>>() {
}).to(IMachineToHardware.class); }).to(IMachineToHardware.class);
bind(new TypeLiteral<Function<IMachine, Image>>() { 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_MACHINE_LOCATION = "jclouds.virtualbox.location";
public static final String VIRTUALBOX_HOST_ID = "jclouds.virtualbox.hostid"; 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; 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.Hardware;
import org.jclouds.compute.domain.HardwareBuilder; import org.jclouds.compute.domain.HardwareBuilder;
import org.jclouds.compute.predicates.ImagePredicates;
import org.jclouds.javax.annotation.Nullable; import org.jclouds.javax.annotation.Nullable;
import org.jclouds.virtualbox.VirtualBox;
import org.virtualbox_4_1.IGuestOSType; import org.virtualbox_4_1.IGuestOSType;
import org.virtualbox_4_1.IMachine; import org.virtualbox_4_1.IMachine;
import org.virtualbox_4_1.VirtualBoxManager; import org.virtualbox_4_1.VirtualBoxManager;
import javax.inject.Inject; import com.google.common.base.Function;
public class IMachineToHardware implements Function<IMachine, Hardware> { public class IMachineToHardware implements Function<IMachine, Hardware> {
private VirtualBox vbox; private VirtualBoxManager virtualBoxManager;
@Inject @Inject
public IMachineToHardware(VirtualBox vbox) { public IMachineToHardware(VirtualBoxManager virtualBoxManager) {
this.vbox = vbox; this.virtualBoxManager = virtualBoxManager;
} }
@Override @Override
public Hardware apply(@Nullable IMachine vm) { public Hardware apply(@Nullable IMachine vm) {
String osTypeId = vm.getOSTypeId(); String osTypeId = vm.getOSTypeId();
IGuestOSType guestOSType = vbox.manager().getVBox().getGuestOSType(osTypeId);
IGuestOSType guestOSType = virtualBoxManager.getVBox().getGuestOSType(osTypeId);
Boolean is64Bit = guestOSType.getIs64Bit(); Boolean is64Bit = guestOSType.getIs64Bit();
HardwareBuilder hardwareBuilder = new HardwareBuilder(); HardwareBuilder hardwareBuilder = new HardwareBuilder();
hardwareBuilder.ids(vm.getId()); hardwareBuilder.ids(vm.getId());
vm.getSessionPid(); hardwareBuilder.supportsImage(ImagePredicates.idEquals(vm.getId()));
hardwareBuilder.is64Bit(is64Bit); hardwareBuilder.is64Bit(is64Bit);
hardwareBuilder.supportsImage(ImagePredicates.idEquals(vm.getId()));
return hardwareBuilder.build(); return hardwareBuilder.build();
} }
} }

View File

@ -21,89 +21,86 @@
package org.jclouds.virtualbox.functions; package org.jclouds.virtualbox.functions;
import java.util.NoSuchElementException; import com.google.common.base.Function;
import javax.inject.Inject;
import org.jclouds.compute.domain.Image; import org.jclouds.compute.domain.Image;
import org.jclouds.compute.domain.ImageBuilder; import org.jclouds.compute.domain.ImageBuilder;
import org.jclouds.compute.domain.OperatingSystem; import org.jclouds.compute.domain.OperatingSystem;
import org.jclouds.compute.domain.OsFamily; import org.jclouds.compute.domain.OsFamily;
import org.jclouds.javax.annotation.Nullable; import org.jclouds.javax.annotation.Nullable;
import org.jclouds.virtualbox.VirtualBox;
import org.virtualbox_4_1.IGuestOSType; import org.virtualbox_4_1.IGuestOSType;
import org.virtualbox_4_1.IMachine; import org.virtualbox_4_1.IMachine;
import org.virtualbox_4_1.VirtualBoxManager; import org.virtualbox_4_1.VirtualBoxManager;
import com.google.common.base.Function; import javax.inject.Inject;
public class IMachineToImage implements Function<IMachine, Image> { 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 @Inject
public IMachineToImage(VirtualBoxManager virtualboxManager) { public IMachineToImage(VirtualBoxManager virtualboxManager) {
this.virtualboxManager = virtualboxManager; this.virtualboxManager = virtualboxManager;
} }
@Override @Override
public Image apply(@Nullable IMachine from) { 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(guestOSType.getDescription());
OsFamily family = osFamily().apply(from); OperatingSystem os = OperatingSystem.builder()
OperatingSystem os = OperatingSystem.builder() .description(guestOSType.getDescription())
.description(from.getDescription()) .family(family)
.family(family) .version(osVersion().apply(guestOSType.getDescription()))
.version(osVersion().apply(from)) .is64Bit(guestOSType.getIs64Bit())
.is64Bit(is64Bit) .build();
.build();
return new ImageBuilder() return new ImageBuilder()
.id("" + from.getId()) .id("" + from.getId())
.description(from.getDescription()) .description(from.getDescription())
.operatingSystem(os) .operatingSystem(os)
.build(); .build();
} }
/** /**
* Parses the item description to determine the OSFamily * Parses the item description to determine the OSFamily
* @return the @see OsFamily or OsFamily.UNRECOGNIZED *
*/ * @return the @see OsFamily or OsFamily.UNRECOGNIZED
public static Function<IMachine, OsFamily> osFamily() { */
return new Function<IMachine,OsFamily>() { public static Function<String, OsFamily> osFamily() {
@Override
public OsFamily apply(IMachine iMachine) {
final String description = iMachine.getDescription();
if ( description.startsWith(UBUNTU) ) return OsFamily.UBUNTU;
return OsFamily.UNRECOGNIZED;
}
};
}
/** return new Function<String, OsFamily>() {
* Parses the item description to determine the os version @Override
* @return the version public OsFamily apply(String osDescription) {
* @throws java.util.NoSuchElementException if the version cannot be determined if (osDescription.startsWith(UBUNTU)) return OsFamily.UBUNTU;
*/ return OsFamily.UNRECOGNIZED;
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); * Parses the item description to determine the os version
if(family.equals(OsFamily.UBUNTU)) return parseVersion(description, UBUNTU); *
else throw new NoSuchElementException("No os parseVersion for item:" + iMachine); * @return the version, empty if not found
} */
}; public static Function<String, String> osVersion() {
} return new Function<String, String>() {
@Override
private static String parseVersion(String description, String os) { public String apply(String osDescription) {
String noOsName = description.replaceFirst(os,"").trim(); OsFamily family = osFamily().apply(osDescription);
return noOsName.split(" ")[0]; 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; 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> { public class IMachineToIpAddress implements Function<IMachine, String> {
private VirtualBoxManager manager; 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(); 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)); 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); System.out.println(execResponse);
String arpLine = runScriptOnNode(hostId, "arp -an | grep " + simplifiedMacAddressOfClonedVM, runAsRoot(false).wrapInInitScript(false)).getOutput(); String arpLine = runScriptOnNode(hostId, "arp -an | grep " + simplifiedMacAddressOfClonedVM, runAsRoot(false).wrapInInitScript(false)).getOutput();
String ipAddress = arpLine.substring(arpLine.indexOf("(") + 1, arpLine.indexOf(")")); String ipAddress = arpLine.substring(arpLine.indexOf("(") + 1, arpLine.indexOf(")"));
System.out.println("IP address " + ipAddress); System.out.println("IP address " + ipAddress);
return ipAddress; return ipAddress;
} }
@ -84,8 +89,7 @@ public class IMachineToIpAddress implements Function<IMachine, String> {
protected boolean isOSX(IMachine machine) { protected boolean isOSX(IMachine machine) {
String osTypeId = machine.getOSTypeId(); String osTypeId = machine.getOSTypeId();
IGuestOSType guestOSType = manager.getVBox().getGuestOSType(osTypeId); IGuestOSType guestOSType = manager.getVBox().getGuestOSType(osTypeId);
String familyDescription = guestOSType.getFamilyDescription(); return guestOSType.getFamilyDescription().equals("Other");
return true;
} }
} }

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 { private void runAll() throws Exception {
context = TestUtils.computeServiceForLocalhost(); context = TestUtils.computeServiceForLocalhostAndGuest();
socketTester = new RetryablePredicate<IPSocket>( socketTester = new RetryablePredicate<IPSocket>(
new InetSocketAddressConnect(), 130, 10, TimeUnit.SECONDS); 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(); VirtualBox virtualBox = new VirtualBox();
IMachineToNodeMetadata parser = new IMachineToNodeMetadata(); IMachineToNodeMetadata parser = new IMachineToNodeMetadata();
IMachineToHardware hwParser = new IMachineToHardware(virtualBox); IMachineToHardware hwParser = new IMachineToHardware(manager);
// hwParser.apply() // 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 @Override
public String getName() { public String getName() {
return "//TODO SoftLayer"; return "SoftLayer";
} }
/** /**
@ -62,7 +62,7 @@ public class SoftLayerProviderMetadata extends BaseProviderMetadata {
*/ */
@Override @Override
public String getIdentityName() { public String getIdentityName() {
return "//TODO"; return "API Username";
} }
/** /**
@ -70,7 +70,7 @@ public class SoftLayerProviderMetadata extends BaseProviderMetadata {
*/ */
@Override @Override
public String getCredentialName() { public String getCredentialName() {
return "//TODO"; return "API Key";
} }
/** /**
@ -78,7 +78,7 @@ public class SoftLayerProviderMetadata extends BaseProviderMetadata {
*/ */
@Override @Override
public URI getHomepage() { public URI getHomepage() {
return URI.create("//TODO"); return URI.create("http://www.softlayer.com");
} }
/** /**
@ -86,7 +86,7 @@ public class SoftLayerProviderMetadata extends BaseProviderMetadata {
*/ */
@Override @Override
public URI getConsole() { public URI getConsole() {
return URI.create("//TODO"); return URI.create("https://manage.softlayer.com");
} }
/** /**
* {@inheritDoc} * {@inheritDoc}

View File

@ -18,15 +18,14 @@
*/ */
package org.jclouds.softlayer.compute.config; package org.jclouds.softlayer.compute.config;
import com.google.common.base.Function; import java.util.Set;
import com.google.common.base.Supplier;
import com.google.inject.Injector;
import com.google.inject.TypeLiteral;
import org.jclouds.compute.ComputeServiceAdapter; import org.jclouds.compute.ComputeServiceAdapter;
import org.jclouds.compute.config.ComputeServiceAdapterContextModule; import org.jclouds.compute.config.ComputeServiceAdapterContextModule;
import org.jclouds.compute.domain.NodeMetadata; import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.domain.OsFamily; import org.jclouds.compute.domain.OsFamily;
import org.jclouds.compute.domain.TemplateBuilder; import org.jclouds.compute.domain.TemplateBuilder;
import org.jclouds.compute.options.TemplateOptions;
import org.jclouds.domain.Location; import org.jclouds.domain.Location;
import org.jclouds.location.suppliers.OnlyLocationOrFirstZone; import org.jclouds.location.suppliers.OnlyLocationOrFirstZone;
import org.jclouds.softlayer.SoftLayerAsyncClient; 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.ProductItemToImage;
import org.jclouds.softlayer.compute.functions.ProductItemsToHardware; import org.jclouds.softlayer.compute.functions.ProductItemsToHardware;
import org.jclouds.softlayer.compute.functions.VirtualGuestToNodeMetadata; 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.compute.strategy.SoftLayerComputeServiceAdapter;
import org.jclouds.softlayer.domain.Datacenter; import org.jclouds.softlayer.domain.Datacenter;
import org.jclouds.softlayer.domain.ProductItem; import org.jclouds.softlayer.domain.ProductItem;
import org.jclouds.softlayer.domain.VirtualGuest; 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); .to(DatacenterToLocation.class);
bind(new TypeLiteral<Supplier<Location>>() {}) bind(new TypeLiteral<Supplier<Location>>() {})
.to(OnlyLocationOrFirstZone.class); .to(OnlyLocationOrFirstZone.class);
bind(TemplateOptions.class).to(SoftLayerTemplateOptions.class);
} }
protected TemplateBuilder provideTemplate(Injector injector, TemplateBuilder template) { 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; package org.jclouds.softlayer.compute.strategy;
import com.google.common.base.Predicates; import static com.google.common.base.Preconditions.checkArgument;
import com.google.common.collect.ImmutableSet; import static com.google.common.base.Preconditions.checkNotNull;
import com.google.common.collect.Iterables; import static org.jclouds.softlayer.predicates.ProductItemPredicates.categoryCode;
import com.google.common.collect.Maps; import static org.jclouds.softlayer.predicates.ProductItemPredicates.matches;
import com.google.common.collect.Sets; 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.ComputeService;
import org.jclouds.compute.ComputeServiceAdapter; import org.jclouds.compute.ComputeServiceAdapter;
import org.jclouds.compute.domain.Template; import org.jclouds.compute.domain.Template;
import org.jclouds.domain.Credentials; import org.jclouds.domain.Credentials;
import org.jclouds.softlayer.SoftLayerClient; import org.jclouds.softlayer.SoftLayerClient;
import org.jclouds.softlayer.compute.functions.ProductItems; 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.AccountClient;
import org.jclouds.softlayer.features.ProductPackageClient; import org.jclouds.softlayer.features.ProductPackageClient;
import org.jclouds.softlayer.reference.SoftLayerConstants; import org.jclouds.softlayer.reference.SoftLayerConstants;
import javax.inject.Inject; import com.google.common.base.Predicates;
import javax.inject.Named; import com.google.common.base.Splitter;
import javax.inject.Singleton; import com.google.common.collect.ImmutableSet;
import java.util.Map; import com.google.common.collect.Iterables;
import java.util.Set; import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import static com.google.common.base.Preconditions.checkNotNull;
import static org.jclouds.softlayer.predicates.ProductItemPredicates.*;
import static org.jclouds.softlayer.predicates.ProductPackagePredicates.named;
/** /**
* defines the connection between the {@link SoftLayerClient} implementation and the jclouds * 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> { ComputeServiceAdapter<VirtualGuest, Set<ProductItem>, ProductItem, Datacenter> {
public static final String SAN_DESCRIPTION_REGEX=".*GB \\(SAN\\).*"; 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 static final Float BOOT_VOLUME_CAPACITY = 100F;
private final SoftLayerClient client; private final SoftLayerClient client;
@ -68,20 +82,87 @@ public class SoftLayerComputeServiceAdapter implements
} }
@Override @Override
public VirtualGuest createNodeWithGroupEncodedIntoNameThenStoreCredentials(String tag, String name, public VirtualGuest createNodeWithGroupEncodedIntoNameThenStoreCredentials(String group, String name,
Template template, Map<String, Credentials> credentialStore) { Template template, Map<String, Credentials> credentialStore) {
VirtualGuest from = null; // TODO create the backend object using parameters from the checkNotNull(template, "template was null");
// template. ex. checkNotNull(template.getOptions(), "template options was null");
// VirtualGuest from = checkArgument(template.getOptions().getClass().isAssignableFrom(SoftLayerTemplateOptions.class),
// client.getVirtualGuestClient().createServerInDC(template.getLocation().getId(), name, "options class %s should have been assignable from SoftLayerTemplateOptions", template.getOptions()
// Long.parseLong(template.getImage().getProviderId()), .getClass());
// Long.parseLong(template.getHardware().getProviderId()));
// store the credentials so that later functions can use them Iterable<VirtualGuest> existing = findVirtualGuests(name,group);
// credentialStore.put("node#"+ from.getId() + "", new Credentials(from.loginUser, if(!Iterables.isEmpty(existing)) {
// from.password)); throw new IllegalStateException(
return from; "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 @Override
public Iterable<Set<ProductItem>> listHardwareProfiles() { public Iterable<Set<ProductItem>> listHardwareProfiles() {
ProductPackage productPackage = getProductPackage(); 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/> * interaction. <br/>
* A guest, also known as a virtual server or CloudLayer Computing Instance, represents an * A guest, also known as a virtual server or CloudLayer Computing Instance, represents an
* allocation of resources on a virtual host. * 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 * @author Adrian Cole
* @see <a href= * @see <a href=
@ -64,6 +75,7 @@ public class VirtualGuest implements Comparable<VirtualGuest> {
private String primaryBackendIpAddress; private String primaryBackendIpAddress;
private String primaryIpAddress; private String primaryIpAddress;
private BillingItemVirtualGuest billingItem; private BillingItemVirtualGuest billingItem;
private OperatingSystem operatingSystem;
public Builder id(int id) { public Builder id(int id) {
this.id = id; this.id = id;
@ -170,12 +182,17 @@ public class VirtualGuest implements Comparable<VirtualGuest> {
return this; return this;
} }
public Builder operatingSystem(OperatingSystem operatingSystem) {
this.operatingSystem = operatingSystem;
return this;
}
public VirtualGuest build() { public VirtualGuest build() {
return new VirtualGuest(accountId, createDate, dedicatedAccountHostOnly, domain, return new VirtualGuest(accountId, createDate, dedicatedAccountHostOnly, domain,
fullyQualifiedDomainName, hostname, id, lastVerifiedDate, maxCpu, fullyQualifiedDomainName, hostname, id, lastVerifiedDate, maxCpu,
maxCpuUnits, maxMemory, metricPollDate, modifyDate, notes, maxCpuUnits, maxMemory, metricPollDate, modifyDate, notes,
privateNetworkOnly, startCpus, statusId, uuid, primaryBackendIpAddress, privateNetworkOnly, startCpus, statusId, uuid, primaryBackendIpAddress,
primaryIpAddress,billingItem); primaryIpAddress,billingItem,operatingSystem);
} }
public static Builder fromVirtualGuest(VirtualGuest in) { public static Builder fromVirtualGuest(VirtualGuest in) {
@ -200,7 +217,9 @@ public class VirtualGuest implements Comparable<VirtualGuest> {
.uuid(in.getUuid()) .uuid(in.getUuid())
.primaryBackendIpAddress(in.getPrimaryBackendIpAddress()) .primaryBackendIpAddress(in.getPrimaryBackendIpAddress())
.primaryIpAddress(in.getPrimaryIpAddress()) .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 String primaryIpAddress;
private BillingItemVirtualGuest billingItem; private BillingItemVirtualGuest billingItem;
private OperatingSystem operatingSystem;
// for deserializer // for deserializer
VirtualGuest() { VirtualGuest() {
@ -262,7 +282,7 @@ public class VirtualGuest implements Comparable<VirtualGuest> {
String fullyQualifiedDomainName, String hostname, int id, Date lastVerifiedDate, int maxCpu, String fullyQualifiedDomainName, String hostname, int id, Date lastVerifiedDate, int maxCpu,
String maxCpuUnits, int maxMemory, Date metricPollDate, Date modifyDate, String notes, String maxCpuUnits, int maxMemory, Date metricPollDate, Date modifyDate, String notes,
boolean privateNetworkOnly, int startCpus, int statusId, String uuid, String primaryBackendIpAddress, boolean privateNetworkOnly, int startCpus, int statusId, String uuid, String primaryBackendIpAddress,
String primaryIpAddress,BillingItemVirtualGuest billingItem) { String primaryIpAddress,BillingItemVirtualGuest billingItem, OperatingSystem operatingSystem) {
this.accountId = accountId; this.accountId = accountId;
this.createDate = createDate; this.createDate = createDate;
this.dedicatedAccountHostOnly = dedicatedAccountHostOnly; this.dedicatedAccountHostOnly = dedicatedAccountHostOnly;
@ -284,6 +304,7 @@ public class VirtualGuest implements Comparable<VirtualGuest> {
this.primaryBackendIpAddress = primaryBackendIpAddress; this.primaryBackendIpAddress = primaryBackendIpAddress;
this.primaryIpAddress = primaryIpAddress; this.primaryIpAddress = primaryIpAddress;
this.billingItem = billingItem; this.billingItem = billingItem;
this.operatingSystem = operatingSystem;
} }
@Override @Override
@ -441,6 +462,13 @@ public class VirtualGuest implements Comparable<VirtualGuest> {
return billingItem; return billingItem;
} }
/**
* @return A guest's operating system.
*/
public OperatingSystem getOperatingSystem() {
return operatingSystem;
}
@Override @Override
public int hashCode() { public int hashCode() {
final int prime = 31; final int prime = 31;
@ -466,6 +494,7 @@ public class VirtualGuest implements Comparable<VirtualGuest> {
result = prime * result + statusId; result = prime * result + statusId;
result = prime * result + ((uuid == null) ? 0 : uuid.hashCode()); result = prime * result + ((uuid == null) ? 0 : uuid.hashCode());
result = prime * result + ((billingItem == null) ? 0 : billingItem.hashCode()); result = prime * result + ((billingItem == null) ? 0 : billingItem.hashCode());
result = prime * result + ((operatingSystem == null) ? 0 : operatingSystem.hashCode());
return result; return result;
} }
@ -559,6 +588,11 @@ public class VirtualGuest implements Comparable<VirtualGuest> {
return false; return false;
} else if (!billingItem.equals(other.billingItem)) } else if (!billingItem.equals(other.billingItem))
return false; return false;
if (operatingSystem == null) {
if (other.operatingSystem != null)
return false;
} else if (!operatingSystem.equals(other.operatingSystem))
return false;
return true; return true;
} }
@ -571,7 +605,7 @@ public class VirtualGuest implements Comparable<VirtualGuest> {
+ ", metricPollDate=" + metricPollDate + ", modifyDate=" + modifyDate + ", notes=" + notes + ", metricPollDate=" + metricPollDate + ", modifyDate=" + modifyDate + ", notes=" + notes
+ ", primaryBackendIpAddress=" + primaryBackendIpAddress + ", primaryIpAddress=" + primaryIpAddress + ", primaryBackendIpAddress=" + primaryBackendIpAddress + ", primaryIpAddress=" + primaryIpAddress
+ ", privateNetworkOnly=" + privateNetworkOnly + ", startCpus=" + startCpus + ", statusId=" + statusId + ", 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) @RequestFilters(BasicAuthentication.class)
@Path("/v{jclouds.api-version}") @Path("/v{jclouds.api-version}")
public interface VirtualGuestAsyncClient { 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"; public static String GUEST_MASK = "powerState;networkVlans;operatingSystem.passwords;datacenter;virtualGuests.billingItem";
/** /**
@ -54,7 +55,7 @@ public interface VirtualGuestAsyncClient {
*/ */
@GET @GET
@Path("/SoftLayer_Account/VirtualGuests.json") @Path("/SoftLayer_Account/VirtualGuests.json")
@QueryParams(keys = "objectMask", values = GUEST_MASK) @QueryParams(keys = "objectMask", values = LIST_GUEST_MASK)
@Consumes(MediaType.APPLICATION_JSON) @Consumes(MediaType.APPLICATION_JSON)
@ExceptionParser(ReturnEmptySetOnNotFoundOr404.class) @ExceptionParser(ReturnEmptySetOnNotFoundOr404.class)
ListenableFuture<Set<VirtualGuest>> listVirtualGuests(); 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.categoryCode;
import static org.jclouds.softlayer.predicates.ProductItemPredicates.units; import static org.jclouds.softlayer.predicates.ProductItemPredicates.units;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertFalse; import static org.testng.Assert.assertFalse;
import static org.testng.AssertJUnit.assertEquals;
import java.util.Map;
import java.util.Set; 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.compute.strategy.SoftLayerComputeServiceAdapter;
import org.jclouds.softlayer.domain.ProductItem; import org.jclouds.softlayer.domain.ProductItem;
import org.jclouds.softlayer.domain.VirtualGuest;
import org.jclouds.softlayer.features.BaseSoftLayerClientLiveTest; import org.jclouds.softlayer.features.BaseSoftLayerClientLiveTest;
import org.jclouds.softlayer.features.ProductPackageClientLiveTest; 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.BeforeGroups;
import org.testng.annotations.Test; import org.testng.annotations.Test;
import com.google.common.collect.Iterables; 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 { public class SoftLayerComputeServiceAdapterLiveTest extends BaseSoftLayerClientLiveTest {
private SoftLayerComputeServiceAdapter adapter; private SoftLayerComputeServiceAdapter adapter;
private VirtualGuest guest;
@BeforeGroups(groups = { "live" }) @BeforeGroups(groups = { "live" })
public void setupClient() { public void setupClient() {
super.setupClient(); super.setupClient();
adapter = new SoftLayerComputeServiceAdapter(context.getApi(), ProductPackageClientLiveTest.CLOUD_SERVER_PACKAGE_NAME); adapter = new SoftLayerComputeServiceAdapter(context.getApi(),
ProductPackageClientLiveTest.CLOUD_SERVER_PACKAGE_NAME);
} }
@Test @Test
@ -51,18 +63,62 @@ public class SoftLayerComputeServiceAdapterLiveTest extends BaseSoftLayerClientL
assertFalse(Iterables.isEmpty(adapter.listLocations())); 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 @Test
public void testListHardwareProfiles() { public void testListHardwareProfiles() {
Iterable<Set<ProductItem>> profiles = adapter.listHardwareProfiles(); Iterable<Set<ProductItem>> profiles = adapter.listHardwareProfiles();
assertFalse(Iterables.isEmpty(profiles)); assertFalse(Iterables.isEmpty(profiles));
for( Set<ProductItem> profile: profiles) { for (Set<ProductItem> profile : profiles) {
// CPU, RAM and Volume // CPU, RAM and Volume
assertEquals(profile.size(), 3); assertEquals(profile.size(), 3);
ProductItem cpuItem = Iterables.getOnlyElement(Iterables.filter(profile, units("PRIVATE_CORE"))); ProductItem cpuItem = Iterables.getOnlyElement(Iterables.filter(profile, units("PRIVATE_CORE")));
ProductItem ramItem = Iterables.getOnlyElement(Iterables.filter(profile,categoryCode("ram"))); ProductItem ramItem = Iterables.getOnlyElement(Iterables.filter(profile, categoryCode("ram")));
Assert.assertEquals(cpuItem.getCapacity(),ramItem.getCapacity()); 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; package org.jclouds.softlayer.compute;
import com.google.common.base.Predicate; import static org.jclouds.compute.util.ComputeServiceUtils.getCores;
import com.google.common.base.Predicates; import static org.testng.Assert.assertEquals;
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 java.io.IOException; import java.io.IOException;
import java.util.Set; import java.util.Set;
import static org.jclouds.compute.util.ComputeServiceUtils.getCores; import org.jclouds.compute.BaseTemplateBuilderLiveTest;
import static org.testng.Assert.assertEquals; 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().is64Bit(), true);
assertEquals(defaultTemplate.getImage().getOperatingSystem().getFamily(), OsFamily.UBUNTU); assertEquals(defaultTemplate.getImage().getOperatingSystem().getFamily(), OsFamily.UBUNTU);
assertEquals(getCores(defaultTemplate.getHardware()), 2.0d); assertEquals(getCores(defaultTemplate.getHardware()), 2.0d);
// test that we bound the correct templateoptions in guice
assertEquals(defaultTemplate.getOptions().getClass(), SoftLayerTemplateOptions.class);
} }
@Override @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 static com.google.common.base.Preconditions.checkNotNull;
import org.jclouds.compute.ComputeServiceContext;
import org.jclouds.compute.ComputeServiceContextFactory; import org.jclouds.compute.ComputeServiceContextFactory;
import org.jclouds.logging.log4j.config.Log4JLoggingModule; import org.jclouds.logging.log4j.config.Log4JLoggingModule;
import org.jclouds.rest.RestContext; import org.jclouds.rest.RestContext;
import org.jclouds.softlayer.SoftLayerAsyncClient; import org.jclouds.softlayer.SoftLayerAsyncClient;
import org.jclouds.softlayer.SoftLayerClient; import org.jclouds.softlayer.SoftLayerClient;
import org.jclouds.sshj.config.SshjSshClientModule;
import org.testng.annotations.AfterGroups; import org.testng.annotations.AfterGroups;
import org.testng.annotations.BeforeGroups; import org.testng.annotations.BeforeGroups;
import org.testng.annotations.Test; import org.testng.annotations.Test;
@ -41,15 +43,16 @@ import com.google.inject.Module;
public class BaseSoftLayerClientLiveTest { public class BaseSoftLayerClientLiveTest {
protected RestContext<SoftLayerClient, SoftLayerAsyncClient> context; protected RestContext<SoftLayerClient, SoftLayerAsyncClient> context;
protected ComputeServiceContext computeContext;
@BeforeGroups(groups = { "live" }) @BeforeGroups(groups = { "live" })
public void setupClient() { public void setupClient() {
String identity = checkNotNull(System.getProperty("test.softlayer.identity"), "test.softlayer.identity"); String identity = checkNotNull(System.getProperty("test.softlayer.identity"), "test.softlayer.identity");
String credential = checkNotNull(System.getProperty("test.softlayer.credential"), "test.softlayer.credential"); String credential = checkNotNull(System.getProperty("test.softlayer.credential"), "test.softlayer.credential");
computeContext = new ComputeServiceContextFactory().createContext("softlayer", identity, credential,
context = new ComputeServiceContextFactory().createContext("softlayer", identity, credential, ImmutableSet.<Module> of(new Log4JLoggingModule(), new SshjSshClientModule()));
ImmutableSet.<Module> of(new Log4JLoggingModule())).getProviderSpecificContext(); context = computeContext.getProviderSpecificContext();
} }

View File

@ -47,7 +47,7 @@ public class VirtualGuestAsyncClientTest extends BaseSoftLayerAsyncClientTest<Vi
assertRequestLineEquals( assertRequestLineEquals(
httpRequest, 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"); assertNonPayloadHeadersEqual(httpRequest, "Accept: application/json\n");
assertPayloadEquals(httpRequest, null, null, false); assertPayloadEquals(httpRequest, null, null, false);
@ -57,7 +57,7 @@ public class VirtualGuestAsyncClientTest extends BaseSoftLayerAsyncClientTest<Vi
assertRequestLineEquals( assertRequestLineEquals(
httpRequest, 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" // for example, using basic authentication, we should get "only one"
// header // header
assertNonPayloadHeadersEqual(httpRequest, 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> * 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 java.io.UnsupportedEncodingException;
import org.jclouds.scriptbuilder.domain.OsFamily; import org.jclouds.scriptbuilder.domain.OsFamily;
import org.jclouds.scriptbuilder.domain.ShellToken;
import org.testng.annotations.Test; import org.testng.annotations.Test;
import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableList;
@ -80,4 +81,9 @@ public class UtilsTest {
"set HOST=\r\nset PORT=\r\n"); "set HOST=\r\nset PORT=\r\n");
} }
public void testSingleCurlyBraceDoesntBreakLfTokenReplacement() {
assertEquals(Utils.replaceTokens("{{lf}", ShellToken.tokenValueMap(OsFamily.UNIX)),
"{\n");
}
} }