mirror of https://github.com/apache/jclouds.git
Merge branch 'master' of git://github.com/jclouds/jclouds
This commit is contained in:
commit
9afa28bab1
|
@ -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),
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -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++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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()
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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>
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -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"
|
||||||
|
}
|
||||||
|
]
|
|
@ -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";
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -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);
|
||||||
}
|
}
|
|
@ -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>
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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");
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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>>() {
|
||||||
|
|
|
@ -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";
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 {
|
|
||||||
}
|
|
|
@ -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();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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();
|
||||||
|
}
|
||||||
|
}
|
|
@ -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();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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(), "");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -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()
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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"
|
|
||||||
}
|
|
||||||
]
|
|
|
@ -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}
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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<? extends NodeMetadata> 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());
|
||||||
|
}
|
||||||
|
}
|
|
@ -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();
|
||||||
|
|
|
@ -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 + "]";
|
||||||
|
}
|
||||||
|
}
|
|
@ -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=**********]";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -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+"]";
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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");
|
||||||
|
}
|
||||||
|
}
|
|
@ -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();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -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");
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue