mirror of https://github.com/apache/jclouds.git
issue 384: preparing 1.5.0-beta - guestAdditions installations fixed
This commit is contained in:
parent
7e6b419068
commit
a2922006c9
|
@ -158,7 +158,7 @@ public class VirtualBoxComputeServiceContextModule extends
|
|||
bind(new TypeLiteral<Function<IMachine, SshClient>>() {
|
||||
}).to(IMachineToSshClient.class);
|
||||
|
||||
bind(ExecutionType.class).toInstance(ExecutionType.HEADLESS);
|
||||
bind(ExecutionType.class).toInstance(ExecutionType.GUI);
|
||||
bind(LockType.class).toInstance(LockType.Write);
|
||||
}
|
||||
|
||||
|
|
|
@ -57,83 +57,73 @@ import com.google.inject.Inject;
|
|||
@Singleton
|
||||
public class CreateAndInstallVm implements Function<MasterSpec, IMachine> {
|
||||
|
||||
@Resource
|
||||
@Named(ComputeServiceConstants.COMPUTE_LOGGER)
|
||||
protected Logger logger = Logger.NULL;
|
||||
@Resource
|
||||
@Named(ComputeServiceConstants.COMPUTE_LOGGER)
|
||||
protected Logger logger = Logger.NULL;
|
||||
|
||||
private final CreateAndRegisterMachineFromIsoIfNotAlreadyExists createAndRegisterMachineFromIsoIfNotAlreadyExists;
|
||||
private final Predicate<SshClient> sshResponds;
|
||||
private LoadingCache<IsoSpec, URI> preConfiguration;
|
||||
private final Function<IMachine, SshClient> sshClientForIMachine;
|
||||
private final MachineUtils machineUtils;
|
||||
private final IMachineToNodeMetadata imachineToNodeMetadata;
|
||||
private final MachineController machineController;
|
||||
private final String version;
|
||||
|
||||
private final CreateAndRegisterMachineFromIsoIfNotAlreadyExists createAndRegisterMachineFromIsoIfNotAlreadyExists;
|
||||
private final Predicate<SshClient> sshResponds;
|
||||
private LoadingCache<IsoSpec, URI> preConfiguration;
|
||||
private final Function<IMachine, SshClient> sshClientForIMachine;
|
||||
private final MachineUtils machineUtils;
|
||||
private final IMachineToNodeMetadata imachineToNodeMetadata;
|
||||
private final MachineController machineController;
|
||||
private final String version;
|
||||
|
||||
@Inject
|
||||
public CreateAndInstallVm(
|
||||
CreateAndRegisterMachineFromIsoIfNotAlreadyExists CreateAndRegisterMachineFromIsoIfNotAlreadyExists,
|
||||
IMachineToNodeMetadata imachineToNodeMetadata,
|
||||
Predicate<SshClient> sshResponds,
|
||||
Function<IMachine, SshClient> sshClientForIMachine,
|
||||
MachineUtils machineUtils,
|
||||
@Preconfiguration LoadingCache<IsoSpec, URI> preConfiguration,
|
||||
MachineController machineController, @Named(Constants.PROPERTY_BUILD_VERSION) String version) {
|
||||
this.createAndRegisterMachineFromIsoIfNotAlreadyExists = CreateAndRegisterMachineFromIsoIfNotAlreadyExists;
|
||||
this.sshResponds = sshResponds;
|
||||
this.sshClientForIMachine = sshClientForIMachine;
|
||||
this.machineUtils = machineUtils;
|
||||
this.preConfiguration = preConfiguration;
|
||||
this.imachineToNodeMetadata = imachineToNodeMetadata;
|
||||
this.machineController = machineController;
|
||||
this.version = Iterables.get(Splitter.on('r').split(version), 0);
|
||||
}
|
||||
@Inject
|
||||
public CreateAndInstallVm(
|
||||
CreateAndRegisterMachineFromIsoIfNotAlreadyExists CreateAndRegisterMachineFromIsoIfNotAlreadyExists,
|
||||
IMachineToNodeMetadata imachineToNodeMetadata, Predicate<SshClient> sshResponds,
|
||||
Function<IMachine, SshClient> sshClientForIMachine, MachineUtils machineUtils,
|
||||
@Preconfiguration LoadingCache<IsoSpec, URI> preConfiguration, MachineController machineController,
|
||||
@Named(Constants.PROPERTY_BUILD_VERSION) String version) {
|
||||
this.createAndRegisterMachineFromIsoIfNotAlreadyExists = CreateAndRegisterMachineFromIsoIfNotAlreadyExists;
|
||||
this.sshResponds = sshResponds;
|
||||
this.sshClientForIMachine = sshClientForIMachine;
|
||||
this.machineUtils = machineUtils;
|
||||
this.preConfiguration = preConfiguration;
|
||||
this.imachineToNodeMetadata = imachineToNodeMetadata;
|
||||
this.machineController = machineController;
|
||||
this.version = Iterables.get(Splitter.on('r').split(version), 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public IMachine apply(MasterSpec masterSpec) {
|
||||
@Override
|
||||
public IMachine apply(MasterSpec masterSpec) {
|
||||
|
||||
VmSpec vmSpec = masterSpec.getVmSpec();
|
||||
IsoSpec isoSpec = masterSpec.getIsoSpec();
|
||||
String vmName = vmSpec.getVmName();
|
||||
VmSpec vmSpec = masterSpec.getVmSpec();
|
||||
IsoSpec isoSpec = masterSpec.getIsoSpec();
|
||||
String vmName = vmSpec.getVmName();
|
||||
|
||||
IMachine vm = createAndRegisterMachineFromIsoIfNotAlreadyExists
|
||||
.apply(masterSpec);
|
||||
IMachine vm = createAndRegisterMachineFromIsoIfNotAlreadyExists.apply(masterSpec);
|
||||
|
||||
// Launch machine and wait for it to come online
|
||||
machineController.ensureMachineIsLaunched(vmName);
|
||||
// Launch machine and wait for it to come online
|
||||
machineController.ensureMachineIsLaunched(vmName);
|
||||
|
||||
URI uri = preConfiguration.getUnchecked(isoSpec);
|
||||
String installationKeySequence = isoSpec.getInstallationKeySequence()
|
||||
.replace("PRECONFIGURATION_URL", uri.toASCIIString());
|
||||
URI uri = preConfiguration.getUnchecked(isoSpec);
|
||||
String installationKeySequence = isoSpec.getInstallationKeySequence().replace("PRECONFIGURATION_URL",
|
||||
uri.toASCIIString());
|
||||
|
||||
configureOsInstallationWithKeyboardSequence(vmName,
|
||||
installationKeySequence);
|
||||
|
||||
SshClient client = sshClientForIMachine.apply(vm);
|
||||
configureOsInstallationWithKeyboardSequence(vmName, installationKeySequence);
|
||||
|
||||
logger.debug(">> awaiting installation to finish node(%s)", vmName);
|
||||
SshClient client = sshClientForIMachine.apply(vm);
|
||||
|
||||
checkState(sshResponds.apply(client),
|
||||
"timed out waiting for guest %s to be accessible via ssh",
|
||||
vmName);
|
||||
logger.debug(">> awaiting installation to finish node(%s)", vmName);
|
||||
|
||||
checkState(sshResponds.apply(client), "timed out waiting for guest %s to be accessible via ssh", vmName);
|
||||
|
||||
logger.debug(">> awaiting installation of guest additions on vm: %s", vmName);
|
||||
|
||||
ListenableFuture<ExecResponse> execFuture = machineUtils.runScriptOnNode(imachineToNodeMetadata.apply(vm),
|
||||
NodeMetadata nodeMetadata = imachineToNodeMetadata.apply(vm);
|
||||
ListenableFuture<ExecResponse> execInstallGA = machineUtils.runScriptOnNode(nodeMetadata,
|
||||
new InstallGuestAdditions(vmSpec, version), RunScriptOptions.NONE);
|
||||
ExecResponse execResponse = Futures.getUnchecked(execFuture);
|
||||
|
||||
checkState(execResponse.getExitStatus() == 0);
|
||||
ExecResponse gaInstallationResponse = Futures.getUnchecked(execInstallGA);
|
||||
checkState(gaInstallationResponse.getExitStatus() == 0);
|
||||
|
||||
logger.debug(">> awaiting post-installation actions on vm: %s", vmName);
|
||||
|
||||
NodeMetadata vmMetadata = imachineToNodeMetadata.apply(vm);
|
||||
|
||||
execFuture = machineUtils.runScriptOnNode(vmMetadata, call("cleanupUdevIfNeeded"), RunScriptOptions.NONE);
|
||||
|
||||
execResponse = Futures.getUnchecked(execFuture);
|
||||
checkState(execResponse.getExitStatus() == 0);
|
||||
ListenableFuture<ExecResponse> execCleanup = machineUtils.runScriptOnNode(nodeMetadata,
|
||||
call("cleanupUdevIfNeeded"), RunScriptOptions.NONE);
|
||||
ExecResponse cleanupResponse = Futures.getUnchecked(execCleanup);
|
||||
checkState(cleanupResponse.getExitStatus() == 0);
|
||||
|
||||
logger.debug("<< installation of image complete. Powering down node(%s)", vmName);
|
||||
|
||||
|
@ -141,14 +131,13 @@ public class CreateAndInstallVm implements Function<MasterSpec, IMachine> {
|
|||
return vm;
|
||||
}
|
||||
|
||||
private void configureOsInstallationWithKeyboardSequence(String vmName,
|
||||
String installationKeySequence) {
|
||||
Iterable<List<Integer>> scancodelist = transform(Splitter.on(" ")
|
||||
.split(installationKeySequence), new StringToKeyCode());
|
||||
private void configureOsInstallationWithKeyboardSequence(String vmName, String installationKeySequence) {
|
||||
Iterable<List<Integer>> scancodelist = transform(Splitter.on(" ").split(installationKeySequence),
|
||||
new StringToKeyCode());
|
||||
|
||||
for (List<Integer> scancodes : scancodelist) {
|
||||
machineUtils.sharedLockMachineAndApplyToSession(vmName,new SendScancodes(scancodes));
|
||||
}
|
||||
}
|
||||
for (List<Integer> scancodes : scancodelist) {
|
||||
machineUtils.sharedLockMachineAndApplyToSession(vmName, new SendScancodes(scancodes));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -79,13 +79,15 @@ public class IMachineToVmSpec implements Function<IMachine, VmSpec> {
|
|||
for (IMediumAttachment iMediumAttachment : machine.getMediumAttachmentsOfController(iStorageController
|
||||
.getName())) {
|
||||
IMedium iMedium = iMediumAttachment.getMedium();
|
||||
if (iMedium.getDeviceType().equals(DeviceType.HardDisk)) {
|
||||
storageControlleBuiler.attachHardDisk(HardDisk.builder().diskpath(iMedium.getLocation())
|
||||
.autoDelete(true).controllerPort(iMediumAttachment.getPort())
|
||||
.deviceSlot(iMediumAttachment.getDevice().intValue()).build());
|
||||
} else if (iMedium.getDeviceType().equals(DeviceType.DVD)) {
|
||||
storageControlleBuiler.attachISO(iMediumAttachment.getPort(), iMediumAttachment.getDevice().intValue(),
|
||||
iMedium.getLocation());
|
||||
if(iMedium != null) {
|
||||
if (iMedium.getDeviceType().equals(DeviceType.HardDisk)) {
|
||||
storageControlleBuiler.attachHardDisk(HardDisk.builder().diskpath(iMedium.getLocation())
|
||||
.autoDelete(true).controllerPort(iMediumAttachment.getPort())
|
||||
.deviceSlot(iMediumAttachment.getDevice().intValue()).build());
|
||||
} else if (iMedium.getDeviceType().equals(DeviceType.DVD)) {
|
||||
storageControlleBuiler.attachISO(iMediumAttachment.getPort(), iMediumAttachment.getDevice().intValue(),
|
||||
iMedium.getLocation());
|
||||
}
|
||||
}
|
||||
}
|
||||
controllers.add(storageControlleBuiler.name(iStorageController.getName()).bus(iStorageController.getBus())
|
||||
|
|
|
@ -30,6 +30,7 @@ import org.jclouds.virtualbox.domain.ErrorCode;
|
|||
import org.jclouds.virtualbox.domain.ExecutionType;
|
||||
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.VBoxException;
|
||||
import org.virtualbox_4_1.VirtualBoxManager;
|
||||
|
@ -52,7 +53,7 @@ import com.google.common.base.Function;
|
|||
* @author Mattias Holmqvist
|
||||
* @see ErrorCode
|
||||
*/
|
||||
public class LaunchMachineIfNotAlreadyRunning implements Function<IMachine, Void> {
|
||||
public class LaunchMachineIfNotAlreadyRunning implements Function<IMachine, ISession> {
|
||||
|
||||
@Resource
|
||||
@Named(ComputeServiceConstants.COMPUTE_LOGGER)
|
||||
|
@ -69,14 +70,12 @@ public class LaunchMachineIfNotAlreadyRunning implements Function<IMachine, Void
|
|||
}
|
||||
|
||||
@Override
|
||||
public Void apply(@Nullable IMachine machine) {
|
||||
public ISession apply(@Nullable IMachine machine) {
|
||||
ISession session = manager.getSessionObject();
|
||||
try {
|
||||
final IProgress progress = machine
|
||||
.launchVMProcess(manager.getSessionObject(), type.stringValue(), environment);
|
||||
.launchVMProcess(session, type.stringValue(), environment);
|
||||
progress.waitForCompletion(-1);
|
||||
Thread.sleep(5000);
|
||||
} catch (InterruptedException e) {
|
||||
propagate(e);
|
||||
} catch (VBoxException e) {
|
||||
ErrorCode errorCode = ErrorCode.valueOf(e);
|
||||
switch (errorCode) {
|
||||
|
@ -88,11 +87,12 @@ public class LaunchMachineIfNotAlreadyRunning implements Function<IMachine, Void
|
|||
propagate(e);
|
||||
}
|
||||
} finally {
|
||||
if (manager.getSessionObject().getState() == SessionState.Locked) {
|
||||
if (session.getState() == SessionState.Locked) {
|
||||
// Remove session lock taken by launchVmProcess()
|
||||
manager.getSessionObject().unlockMachine();
|
||||
session.unlockMachine();
|
||||
// TODO this unlock is not IMMEDIATELY visible outside (vbox doc)
|
||||
}
|
||||
}
|
||||
return null;
|
||||
return session;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -88,6 +88,8 @@ public class InstallGuestAdditions implements Statement {
|
|||
statements.add(exec(String.format("mount -o loop {tmp}{fs}%s %s", vboxGuestAdditionsIso, mountPoint)));
|
||||
}
|
||||
statements.add(exec(String.format("%s%s", mountPoint, "/VBoxLinuxAdditions.run"))); //
|
||||
statements.add(exec(String.format("echo VBoxService > /etc/rc.local"))); //
|
||||
statements.add(exec(String.format("echo exit 0 >> /etc/rc.local"))); //
|
||||
statements.add(exec(String.format("umount %s", mountPoint)));
|
||||
return statements;
|
||||
}
|
||||
|
|
|
@ -18,6 +18,10 @@
|
|||
*/
|
||||
package org.jclouds.virtualbox.util;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
import java.awt.print.Printable;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.inject.Named;
|
||||
import javax.inject.Singleton;
|
||||
|
@ -28,8 +32,9 @@ import org.jclouds.virtualbox.domain.ExecutionType;
|
|||
import org.jclouds.virtualbox.functions.LaunchMachineIfNotAlreadyRunning;
|
||||
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.VirtualBoxManager;
|
||||
import org.virtualbox_4_1.jaxws.MachineState;
|
||||
|
||||
import com.google.common.base.Function;
|
||||
import com.google.common.base.Supplier;
|
||||
|
@ -52,7 +57,6 @@ public class MachineController {
|
|||
private final MachineUtils machineUtils;
|
||||
private final ExecutionType executionType;
|
||||
|
||||
|
||||
@Inject
|
||||
public MachineController(Supplier<VirtualBoxManager> manager, MachineUtils machineUtils, ExecutionType executionType) {
|
||||
this.manager = manager;
|
||||
|
@ -60,32 +64,100 @@ public class MachineController {
|
|||
this.executionType = executionType;
|
||||
}
|
||||
|
||||
public void ensureMachineIsLaunched(String vmName) {
|
||||
machineUtils.applyForMachine(vmName, new LaunchMachineIfNotAlreadyRunning(manager.get(), executionType, ""));
|
||||
}
|
||||
|
||||
public void ensureMachineHasPowerDown(String vmName) {
|
||||
while (!manager.get().getVBox().findMachine(vmName).getState().equals(MachineState.POWERED_OFF)) {
|
||||
try {
|
||||
machineUtils.sharedLockMachineAndApplyToSession(vmName, new Function<ISession, Void>() {
|
||||
@Override
|
||||
public Void apply(ISession session) {
|
||||
IProgress powerDownProgress = session.getConsole().powerDown();
|
||||
powerDownProgress.waitForCompletion(-1);
|
||||
return null;
|
||||
}
|
||||
});
|
||||
} catch (RuntimeException e) {
|
||||
// sometimes the machine might be powered of between the while test and the call to
|
||||
// lockSessionOnMachineAndApply
|
||||
if (e.getMessage().contains("Invalid machine state: PoweredOff")) {
|
||||
return;
|
||||
} else if (e.getMessage().contains("VirtualBox error: The object is not ready")) {
|
||||
continue;
|
||||
} else {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
public ISession ensureMachineIsLaunched(String vmName) {
|
||||
ISession session = null;
|
||||
while (!manager.get().getVBox().findMachine(vmName).getState().equals(MachineState.Running)) {
|
||||
try {
|
||||
session = machineUtils.applyForMachine(vmName, new LaunchMachineIfNotAlreadyRunning(manager.get(), executionType, ""));
|
||||
} catch (RuntimeException e) {
|
||||
if (e.getMessage().contains("org.virtualbox_4_1.VBoxException: VirtualBox error: The given session is busy (0x80BB0007)")) {
|
||||
throw e;
|
||||
} else if (e.getMessage().contains("VirtualBox error: The object is not ready")) {
|
||||
continue;
|
||||
} else {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
}
|
||||
return checkNotNull(session, "session");
|
||||
}
|
||||
|
||||
public ISession ensureMachineHasPowerDown(String vmName) {
|
||||
ISession session = manager.get().getSessionObject();
|
||||
while (!manager.get().getVBox().findMachine(vmName).getState().equals(MachineState.PoweredOff)) {
|
||||
try {
|
||||
session = machineUtils.lockSessionOnMachineAndApply(vmName, LockType.Shared, new Function<ISession, ISession>() {
|
||||
@Override
|
||||
public ISession apply(ISession session) {
|
||||
IProgress powerDownProgress = session.getConsole().powerDown();
|
||||
powerDownProgress.waitForCompletion(-1);
|
||||
return session;
|
||||
}
|
||||
});
|
||||
} catch (RuntimeException e) {
|
||||
// sometimes the machine might be powered of between the while
|
||||
// test and the call to
|
||||
// lockSessionOnMachineAndApply
|
||||
if (e.getMessage().contains("Invalid machine state: PoweredOff")) {
|
||||
throw e;
|
||||
} else if (e.getMessage().contains("VirtualBox error: The object is not ready")) {
|
||||
continue;
|
||||
} else {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
}
|
||||
return checkNotNull(session, "session");
|
||||
}
|
||||
|
||||
public void ensureMachineIsPaused(String vmName) {
|
||||
while (!manager.get().getVBox().findMachine(vmName).getState().equals(MachineState.Paused)) {
|
||||
try {
|
||||
machineUtils.lockSessionOnMachineAndApply(vmName, LockType.Shared, new Function<ISession, Void>() {
|
||||
@Override
|
||||
public Void apply(ISession session) {
|
||||
session.getConsole().pause();
|
||||
return null;
|
||||
}
|
||||
});
|
||||
} catch (RuntimeException e) {
|
||||
// sometimes the machine might be powered of between the while
|
||||
// test and the call to
|
||||
// lockSessionOnMachineAndApply
|
||||
if (e.getMessage().contains("Invalid machine state: Paused")) {
|
||||
return;
|
||||
} else if (e.getMessage().contains("VirtualBox error: The object is not ready")) {
|
||||
continue;
|
||||
} else {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void ensureMachineIsResumed(String vmName) {
|
||||
while (!manager.get().getVBox().findMachine(vmName).getState().equals(MachineState.Running)) {
|
||||
try {
|
||||
machineUtils.lockSessionOnMachineAndApply(vmName, LockType.Shared, new Function<ISession, Void>() {
|
||||
@Override
|
||||
public Void apply(ISession session) {
|
||||
session.getConsole().resume();
|
||||
return null;
|
||||
}
|
||||
});
|
||||
} catch (RuntimeException e) {
|
||||
// sometimes the machine might be powered of between the while
|
||||
// test and the call to
|
||||
// lockSessionOnMachineAndApply
|
||||
if (e.getMessage().contains("Invalid machine state: Resumed")) {
|
||||
return;
|
||||
} else if (e.getMessage().contains("VirtualBox error: The object is not ready")) {
|
||||
continue;
|
||||
} else {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -18,6 +18,9 @@
|
|||
*/
|
||||
package org.jclouds.virtualbox.util;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkState;
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.inject.Named;
|
||||
import javax.inject.Singleton;
|
||||
|
@ -34,6 +37,7 @@ import org.jclouds.util.Throwables2;
|
|||
import org.virtualbox_4_1.IMachine;
|
||||
import org.virtualbox_4_1.ISession;
|
||||
import org.virtualbox_4_1.LockType;
|
||||
import org.virtualbox_4_1.SessionState;
|
||||
import org.virtualbox_4_1.VBoxException;
|
||||
import org.virtualbox_4_1.VirtualBoxManager;
|
||||
|
||||
|
@ -50,7 +54,11 @@ import com.google.inject.Inject;
|
|||
|
||||
@Singleton
|
||||
public class MachineUtils {
|
||||
|
||||
|
||||
public final String IP_V4_ADDRESS_PATTERN = "^([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\."
|
||||
+ "([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\." + "([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\."
|
||||
+ "([01]?\\d\\d?|2[0-4]\\d|25[0-5])$";
|
||||
|
||||
@Resource
|
||||
@Named(ComputeServiceConstants.COMPUTE_LOGGER)
|
||||
protected Logger logger = Logger.NULL;
|
||||
|
@ -178,14 +186,30 @@ public class MachineUtils {
|
|||
* the function to execute
|
||||
* @return the result from applying the function to the session.
|
||||
*/
|
||||
private <T> T lockSessionOnMachineAndApply(String machineId, LockType type, Function<ISession, T> function) {
|
||||
protected <T> T lockSessionOnMachineAndApply(String machineId, LockType type, Function<ISession, T> function) {
|
||||
int retries = 5;
|
||||
ISession session = lockSession(machineId, type, retries);
|
||||
try {
|
||||
return function.apply(session);
|
||||
} catch (VBoxException e) {
|
||||
throw new RuntimeException(String.format("error applying %s to %s with %s lock: %s", function, machineId,
|
||||
type, e.getMessage()), e);
|
||||
} finally {
|
||||
if (session != null && session.getState().equals(SessionState.Locked))
|
||||
session.unlockMachine();
|
||||
}
|
||||
}
|
||||
|
||||
private ISession lockSession(String machineId, LockType type, int retries) {
|
||||
int count = 0;
|
||||
ISession session;
|
||||
long time = System.currentTimeMillis();
|
||||
while (true) {
|
||||
try {
|
||||
IMachine immutableMachine = manager.get().getVBox().findMachine(machineId);
|
||||
try {
|
||||
Thread.sleep(300L);
|
||||
} catch (InterruptedException e1) {
|
||||
}
|
||||
session = manager.get().getSessionObject();
|
||||
immutableMachine.lockMachine(session, type);
|
||||
break;
|
||||
|
@ -206,14 +230,8 @@ public class MachineUtils {
|
|||
}
|
||||
}
|
||||
}
|
||||
try {
|
||||
return function.apply(session);
|
||||
} catch (VBoxException e) {
|
||||
throw new RuntimeException(String.format("error applying %s to %s with %s lock: %s", function, machineId,
|
||||
type, e.getMessage()), e);
|
||||
} finally {
|
||||
session.unlockMachine();
|
||||
}
|
||||
checkState(session.getState().equals(SessionState.Locked));
|
||||
return checkNotNull(session, "session");
|
||||
}
|
||||
|
||||
void print() {
|
||||
|
|
|
@ -1,8 +1,5 @@
|
|||
function cleanupUdevIfNeeded {
|
||||
# unset OSNAME;
|
||||
# local OSNAME=`lsb_release -d -s | cut -d ' ' -f 1`; shift
|
||||
# if [ $OSNAME = 'Ubuntu' ]
|
||||
if [ -f '/etc/udev/rules.d/70-persistent-net.rules']
|
||||
if [ -f '/etc/udev/rules.d/70-persistent-net.rules' ]
|
||||
then
|
||||
rm /etc/udev/rules.d/70-persistent-net.rules;
|
||||
mkdir /etc/udev/rules.d/70-persistent-net.rules;
|
||||
|
|
|
@ -4,11 +4,8 @@ function installModuleAssistantIfNeeded {
|
|||
if [ $OSNAME = 'Ubuntu' ]
|
||||
then
|
||||
echo "OS is Ubuntu"
|
||||
apt-get -f -y -qq --force-yes install build-essential module-assistant;
|
||||
apt-get -f -y -qq --force-yes install dkms build-essential linux-headers-`uname -r` module-assistant;
|
||||
m-a prepare -i
|
||||
rm /etc/udev/rules.d/70-persistent-net.rules;
|
||||
mkdir /etc/udev/rules.d/70-persistent-net.rules;
|
||||
rm -rf /dev/.udev/;
|
||||
rm /lib/udev/rules.d/75-persistent-net-generator.rules
|
||||
return 0
|
||||
fi
|
||||
}
|
|
@ -20,6 +20,7 @@
|
|||
package org.jclouds.virtualbox;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
import static org.jclouds.virtualbox.config.VirtualBoxConstants.VIRTUALBOX_INSTALLATION_KEY_SEQUENCE;
|
||||
|
||||
import java.io.File;
|
||||
import java.net.URI;
|
||||
|
@ -38,25 +39,41 @@ import org.jclouds.compute.domain.Template;
|
|||
import org.jclouds.compute.strategy.PrioritizeCredentialsFromTemplate;
|
||||
import org.jclouds.concurrent.MoreExecutors;
|
||||
import org.jclouds.concurrent.config.ExecutorServiceModule;
|
||||
import org.jclouds.config.ValueOfConfigurationKeyOrNull;
|
||||
import org.jclouds.logging.slf4j.config.SLF4JLoggingModule;
|
||||
import org.jclouds.sshj.config.SshjSshClientModule;
|
||||
import org.jclouds.virtualbox.config.VirtualBoxConstants;
|
||||
import org.jclouds.virtualbox.domain.HardDisk;
|
||||
import org.jclouds.virtualbox.domain.IsoSpec;
|
||||
import org.jclouds.virtualbox.domain.Master;
|
||||
import org.jclouds.virtualbox.domain.MasterSpec;
|
||||
import org.jclouds.virtualbox.domain.NetworkAdapter;
|
||||
import org.jclouds.virtualbox.domain.NetworkInterfaceCard;
|
||||
import org.jclouds.virtualbox.domain.NetworkSpec;
|
||||
import org.jclouds.virtualbox.domain.StorageController;
|
||||
import org.jclouds.virtualbox.domain.VmSpec;
|
||||
import org.jclouds.virtualbox.functions.IMachineToVmSpec;
|
||||
import org.jclouds.virtualbox.functions.admin.UnregisterMachineIfExistsAndDeleteItsMedia;
|
||||
import org.jclouds.virtualbox.util.MachineController;
|
||||
import org.jclouds.virtualbox.util.MachineUtils;
|
||||
import org.testng.annotations.AfterClass;
|
||||
import org.testng.annotations.BeforeClass;
|
||||
import org.testng.annotations.Test;
|
||||
import org.virtualbox_4_1.CleanupMode;
|
||||
import org.virtualbox_4_1.IMachine;
|
||||
import org.virtualbox_4_1.NetworkAttachmentType;
|
||||
import org.virtualbox_4_1.SessionState;
|
||||
import org.virtualbox_4_1.StorageBus;
|
||||
import org.virtualbox_4_1.VBoxException;
|
||||
import org.virtualbox_4_1.VirtualBoxManager;
|
||||
|
||||
import com.google.common.base.Function;
|
||||
import com.google.common.base.Splitter;
|
||||
import com.google.common.base.Supplier;
|
||||
import com.google.common.cache.LoadingCache;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.collect.Iterables;
|
||||
import com.google.inject.Injector;
|
||||
import com.google.inject.Module;
|
||||
|
||||
/**
|
||||
|
@ -152,12 +169,74 @@ public class BaseVirtualBoxClientLiveTest extends BaseVersionedServiceLiveTest {
|
|||
vmSpecification));
|
||||
}
|
||||
|
||||
protected void undoVm(String vmNameOrId) {
|
||||
IMachine vm = null;
|
||||
try {
|
||||
System.out.println("1: " + manager.get().getSessionObject().getState());
|
||||
|
||||
vm = manager.get().getVBox().findMachine(vmNameOrId);
|
||||
VmSpec vmSpec = new IMachineToVmSpec().apply(vm);
|
||||
System.out.println("2: " + vm.getSessionState());
|
||||
int attempts = 0;
|
||||
while (attempts < 10 && !vm.getSessionState().equals(SessionState.Unlocked)) {
|
||||
// TODO understand why this behavior and see if IEvent can help
|
||||
System.out.println("Unlocking ...");
|
||||
attempts++;
|
||||
try {
|
||||
Thread.sleep(200l);
|
||||
} catch (InterruptedException e) {
|
||||
}
|
||||
}
|
||||
machineUtils.applyForMachine(vmNameOrId, new UnregisterMachineIfExistsAndDeleteItsMedia(vmSpec));
|
||||
|
||||
} catch (VBoxException e) {
|
||||
if (e.getMessage().contains("Could not find a registered machine named"))
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
public String adminDisk(String vmName) {
|
||||
return workingDir + File.separator + vmName + ".vdi";
|
||||
}
|
||||
|
||||
public MasterSpec getMasterSpecForTest() {
|
||||
String masterName = "jclouds-image-0x0-default-ubuntu-11.04-i386";
|
||||
StorageController ideController = StorageController
|
||||
.builder()
|
||||
.name("IDE Controller")
|
||||
.bus(StorageBus.IDE)
|
||||
.attachISO(0, 0, operatingSystemIso)
|
||||
.attachHardDisk(
|
||||
HardDisk.builder().diskpath(adminDisk(masterName)).controllerPort(0).deviceSlot(1)
|
||||
.autoDelete(true).build()).attachISO(1, 0, guestAdditionsIso).build();
|
||||
|
||||
VmSpec sourceVmSpec = VmSpec.builder().id(masterName).name(masterName)
|
||||
.osTypeId("").memoryMB(512).cleanUpMode(CleanupMode.Full)
|
||||
.controller(ideController).forceOverwrite(true).build();
|
||||
|
||||
Injector injector = context.utils().injector();
|
||||
Function<String, String> configProperties = injector
|
||||
.getInstance(ValueOfConfigurationKeyOrNull.class);
|
||||
IsoSpec isoSpec = IsoSpec
|
||||
.builder()
|
||||
.sourcePath(operatingSystemIso)
|
||||
.installationScript(
|
||||
configProperties.apply(
|
||||
VIRTUALBOX_INSTALLATION_KEY_SEQUENCE).replace(
|
||||
"HOSTNAME", sourceVmSpec.getVmName())).build();
|
||||
|
||||
NetworkAdapter networkAdapter = NetworkAdapter.builder()
|
||||
.networkAttachmentType(NetworkAttachmentType.NAT)
|
||||
.tcpRedirectRule("127.0.0.1", 2222, "", 22).build();
|
||||
NetworkInterfaceCard networkInterfaceCard = NetworkInterfaceCard
|
||||
.builder().addNetworkAdapter(networkAdapter).build();
|
||||
|
||||
NetworkSpec networkSpec = NetworkSpec.builder()
|
||||
.addNIC(networkInterfaceCard).build();
|
||||
return MasterSpec.builder().iso(isoSpec).vm(sourceVmSpec)
|
||||
.network(networkSpec).build();
|
||||
}
|
||||
|
||||
@AfterClass(groups = "live")
|
||||
protected void tearDown() throws Exception {
|
||||
if (context != null)
|
||||
|
|
|
@ -19,12 +19,20 @@
|
|||
|
||||
package org.jclouds.virtualbox.predicates;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkState;
|
||||
import static org.jclouds.virtualbox.config.VirtualBoxConstants.VIRTUALBOX_IMAGE_PREFIX;
|
||||
import static org.jclouds.virtualbox.config.VirtualBoxConstants.VIRTUALBOX_INSTALLATION_KEY_SEQUENCE;
|
||||
import static org.testng.Assert.assertTrue;
|
||||
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.jclouds.compute.domain.ExecResponse;
|
||||
import org.jclouds.compute.domain.NodeMetadata;
|
||||
import org.jclouds.compute.options.RunScriptOptions;
|
||||
import org.jclouds.config.ValueOfConfigurationKeyOrNull;
|
||||
import org.jclouds.virtualbox.BaseVirtualBoxClientLiveTest;
|
||||
import org.jclouds.virtualbox.domain.CloneSpec;
|
||||
import org.jclouds.virtualbox.domain.ExecutionType;
|
||||
import org.jclouds.virtualbox.domain.HardDisk;
|
||||
import org.jclouds.virtualbox.domain.IsoSpec;
|
||||
|
@ -34,8 +42,10 @@ import org.jclouds.virtualbox.domain.NetworkInterfaceCard;
|
|||
import org.jclouds.virtualbox.domain.NetworkSpec;
|
||||
import org.jclouds.virtualbox.domain.StorageController;
|
||||
import org.jclouds.virtualbox.domain.VmSpec;
|
||||
import org.jclouds.virtualbox.functions.CloneAndRegisterMachineFromIMachineIfNotAlreadyExists;
|
||||
import org.jclouds.virtualbox.functions.CreateAndInstallVm;
|
||||
import org.jclouds.virtualbox.functions.LaunchMachineIfNotAlreadyRunning;
|
||||
import org.jclouds.virtualbox.statements.InstallGuestAdditions;
|
||||
import org.testng.annotations.BeforeClass;
|
||||
import org.testng.annotations.Test;
|
||||
import org.virtualbox_4_1.CleanupMode;
|
||||
|
@ -47,6 +57,8 @@ import org.virtualbox_4_1.StorageBus;
|
|||
import com.google.common.base.CaseFormat;
|
||||
import com.google.common.base.Function;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.util.concurrent.Futures;
|
||||
import com.google.common.util.concurrent.ListenableFuture;
|
||||
import com.google.inject.Injector;
|
||||
|
||||
/**
|
||||
|
@ -56,88 +68,108 @@ import com.google.inject.Injector;
|
|||
public class GuestAdditionsInstallerLiveTest extends
|
||||
BaseVirtualBoxClientLiveTest {
|
||||
|
||||
private MasterSpec sourceMachineSpec;
|
||||
private MasterSpec machineSpec;
|
||||
|
||||
@Override
|
||||
@BeforeClass(groups = "live")
|
||||
public void setupClient() {
|
||||
super.setupClient();
|
||||
String sourceName = VIRTUALBOX_IMAGE_PREFIX
|
||||
+ CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_HYPHEN, getClass()
|
||||
.getSimpleName());
|
||||
String instanceName = VIRTUALBOX_IMAGE_PREFIX
|
||||
+ CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_HYPHEN, getClass()
|
||||
.getSimpleName());
|
||||
|
||||
StorageController ideController = StorageController
|
||||
.builder()
|
||||
.name("IDE Controller")
|
||||
.bus(StorageBus.IDE)
|
||||
.attachISO(0, 0, operatingSystemIso)
|
||||
.attachHardDisk(
|
||||
HardDisk.builder().diskpath(adminDisk(sourceName)).controllerPort(0).deviceSlot(1)
|
||||
.autoDelete(true).build()).attachISO(1, 0, guestAdditionsIso).build();
|
||||
StorageController ideController = StorageController
|
||||
.builder()
|
||||
.name("IDE Controller")
|
||||
.bus(StorageBus.IDE)
|
||||
.attachISO(0, 0, operatingSystemIso)
|
||||
.attachHardDisk(
|
||||
HardDisk.builder().diskpath(adminDisk(instanceName))
|
||||
.controllerPort(0).deviceSlot(1)
|
||||
.autoDelete(true).build())
|
||||
.attachISO(1, 1, guestAdditionsIso).build();
|
||||
|
||||
VmSpec sourceVmSpec = VmSpec.builder().id(sourceName).name(sourceName)
|
||||
.osTypeId("").memoryMB(512).cleanUpMode(CleanupMode.Full)
|
||||
.controller(ideController).forceOverwrite(true).build();
|
||||
VmSpec instanceVmSpec = VmSpec.builder().id(instanceName)
|
||||
.name(instanceName).osTypeId("").memoryMB(512)
|
||||
.cleanUpMode(CleanupMode.Full).controller(ideController)
|
||||
.forceOverwrite(true).build();
|
||||
|
||||
Injector injector = context.utils().injector();
|
||||
Function<String, String> configProperties = injector
|
||||
.getInstance(ValueOfConfigurationKeyOrNull.class);
|
||||
IsoSpec isoSpec = IsoSpec
|
||||
.builder()
|
||||
.sourcePath(operatingSystemIso)
|
||||
.installationScript(
|
||||
configProperties.apply(
|
||||
VIRTUALBOX_INSTALLATION_KEY_SEQUENCE).replace(
|
||||
"HOSTNAME", sourceVmSpec.getVmName())).build();
|
||||
|
||||
NetworkAdapter networkAdapter = NetworkAdapter.builder()
|
||||
.networkAttachmentType(NetworkAttachmentType.NAT)
|
||||
.tcpRedirectRule("127.0.0.1", 2222, "", 22).build();
|
||||
NetworkInterfaceCard networkInterfaceCard = NetworkInterfaceCard
|
||||
.builder().addNetworkAdapter(networkAdapter).build();
|
||||
Injector injector = context.utils().injector();
|
||||
Function<String, String> configProperties = injector
|
||||
.getInstance(ValueOfConfigurationKeyOrNull.class);
|
||||
IsoSpec isoSpec = IsoSpec
|
||||
.builder()
|
||||
.sourcePath(operatingSystemIso)
|
||||
.installationScript(
|
||||
configProperties.apply(
|
||||
VIRTUALBOX_INSTALLATION_KEY_SEQUENCE).replace(
|
||||
"HOSTNAME", instanceVmSpec.getVmName()))
|
||||
.build();
|
||||
|
||||
NetworkSpec networkSpec = NetworkSpec.builder()
|
||||
.addNIC(networkInterfaceCard).build();
|
||||
sourceMachineSpec = MasterSpec.builder().iso(isoSpec).vm(sourceVmSpec)
|
||||
.network(networkSpec).build();
|
||||
NetworkAdapter networkAdapter = NetworkAdapter.builder()
|
||||
.networkAttachmentType(NetworkAttachmentType.NAT)
|
||||
.tcpRedirectRule("127.0.0.1", 2222, "", 22).build();
|
||||
NetworkInterfaceCard networkInterfaceCard = NetworkInterfaceCard
|
||||
.builder().addNetworkAdapter(networkAdapter).build();
|
||||
|
||||
NetworkSpec networkSpec = NetworkSpec.builder()
|
||||
.addNIC(networkInterfaceCard).build();
|
||||
machineSpec = MasterSpec.builder().iso(isoSpec)
|
||||
.vm(instanceVmSpec).network(networkSpec).build();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGuestAdditionsAreInstalled() throws Exception {
|
||||
IMachine machine = null;
|
||||
try {
|
||||
IMachine machine = getVmWithGuestAdditionsInstalled();
|
||||
machine = cloneFromMaster();
|
||||
machineUtils.applyForMachine(machine.getName(),
|
||||
new LaunchMachineIfNotAlreadyRunning(manager.get(),
|
||||
ExecutionType.GUI, ""));
|
||||
ExecutionType.GUI, ""));
|
||||
assertTrue(machineUtils.sharedLockMachineAndApplyToSession(
|
||||
machine.getName(),
|
||||
new Function<ISession, Boolean>() {
|
||||
@Override
|
||||
public Boolean apply(ISession session) {
|
||||
return session.getMachine().getGuestPropertyValue(
|
||||
"/VirtualBox/GuestAdd/Version") != null;
|
||||
}
|
||||
}));
|
||||
new Function<ISession, Boolean>() {
|
||||
@Override
|
||||
public Boolean apply(ISession session) {
|
||||
String s = session
|
||||
.getMachine()
|
||||
.getGuestPropertyValue(
|
||||
"/VirtualBox/GuestInfo/Net/0/V4/IP");
|
||||
return isIpv4(s);
|
||||
}
|
||||
|
||||
private boolean isIpv4(String s) {
|
||||
Pattern pattern = Pattern
|
||||
.compile(machineUtils.IP_V4_ADDRESS_PATTERN);
|
||||
Matcher matcher = pattern.matcher(s);
|
||||
return matcher.matches();
|
||||
}
|
||||
}));
|
||||
} finally {
|
||||
for (VmSpec spec : ImmutableSet.of(sourceMachineSpec.getVmSpec())) {
|
||||
machineController.ensureMachineHasPowerDown(spec.getVmName());
|
||||
undoVm(spec);
|
||||
for (String vmNameOrId : ImmutableSet.of(machine.getName())) {
|
||||
machineController.ensureMachineHasPowerDown(vmNameOrId);
|
||||
undoVm(vmNameOrId);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private IMachine cloneFromMaster() {
|
||||
IMachine source = getVmWithGuestAdditionsInstalled();
|
||||
CloneSpec cloneSpec = CloneSpec.builder().vm(machineSpec.getVmSpec())
|
||||
.network(machineSpec.getNetworkSpec()).master(source).linked(true).build();
|
||||
return new CloneAndRegisterMachineFromIMachineIfNotAlreadyExists(manager, workingDir, machineUtils)
|
||||
.apply(cloneSpec);
|
||||
}
|
||||
|
||||
private IMachine getVmWithGuestAdditionsInstalled() {
|
||||
try {
|
||||
Injector injector = context.utils().injector();
|
||||
return injector.getInstance(CreateAndInstallVm.class).apply(
|
||||
sourceMachineSpec);
|
||||
} catch (IllegalStateException e) {
|
||||
// already created
|
||||
return manager.get().getVBox()
|
||||
.findMachine(sourceMachineSpec.getVmSpec().getVmId());
|
||||
}
|
||||
}
|
||||
private IMachine getVmWithGuestAdditionsInstalled() {
|
||||
MasterSpec masterSpecForTest = super.getMasterSpecForTest();
|
||||
try {
|
||||
Injector injector = context.utils().injector();
|
||||
return injector.getInstance(CreateAndInstallVm.class).apply(masterSpecForTest);
|
||||
} catch (IllegalStateException e) {
|
||||
// already created
|
||||
return manager.get().getVBox().findMachine(masterSpecForTest.getVmSpec().getVmId());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,143 @@
|
|||
/**
|
||||
* 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.util;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkState;
|
||||
import static org.jclouds.virtualbox.config.VirtualBoxConstants.VIRTUALBOX_IMAGE_PREFIX;
|
||||
import static org.jclouds.virtualbox.config.VirtualBoxConstants.VIRTUALBOX_INSTALLATION_KEY_SEQUENCE;
|
||||
import static org.testng.AssertJUnit.assertTrue;
|
||||
|
||||
import org.jclouds.config.ValueOfConfigurationKeyOrNull;
|
||||
import org.jclouds.virtualbox.BaseVirtualBoxClientLiveTest;
|
||||
import org.jclouds.virtualbox.domain.CloneSpec;
|
||||
import org.jclouds.virtualbox.domain.HardDisk;
|
||||
import org.jclouds.virtualbox.domain.IsoSpec;
|
||||
import org.jclouds.virtualbox.domain.MasterSpec;
|
||||
import org.jclouds.virtualbox.domain.NetworkAdapter;
|
||||
import org.jclouds.virtualbox.domain.NetworkInterfaceCard;
|
||||
import org.jclouds.virtualbox.domain.NetworkSpec;
|
||||
import org.jclouds.virtualbox.domain.StorageController;
|
||||
import org.jclouds.virtualbox.domain.VmSpec;
|
||||
import org.jclouds.virtualbox.functions.CloneAndRegisterMachineFromIMachineIfNotAlreadyExists;
|
||||
import org.jclouds.virtualbox.functions.CreateAndInstallVm;
|
||||
import org.testng.annotations.AfterClass;
|
||||
import org.testng.annotations.BeforeClass;
|
||||
import org.testng.annotations.Test;
|
||||
import org.virtualbox_4_1.CleanupMode;
|
||||
import org.virtualbox_4_1.IMachine;
|
||||
import org.virtualbox_4_1.ISession;
|
||||
import org.virtualbox_4_1.NetworkAttachmentType;
|
||||
import org.virtualbox_4_1.SessionState;
|
||||
import org.virtualbox_4_1.StorageBus;
|
||||
|
||||
import com.google.common.base.CaseFormat;
|
||||
import com.google.common.base.Function;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.inject.Injector;
|
||||
|
||||
@Test(groups = "live", testName = "MachineControllerLiveTest")
|
||||
public class MachineControllerLiveTest extends BaseVirtualBoxClientLiveTest {
|
||||
|
||||
private MasterSpec machineSpec;
|
||||
private String instanceName;
|
||||
|
||||
@Override
|
||||
@BeforeClass(groups = "live")
|
||||
public void setupClient() {
|
||||
super.setupClient();
|
||||
instanceName = VIRTUALBOX_IMAGE_PREFIX
|
||||
+ CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_HYPHEN, getClass().getSimpleName());
|
||||
|
||||
StorageController ideController = StorageController
|
||||
.builder()
|
||||
.name("IDE Controller")
|
||||
.bus(StorageBus.IDE)
|
||||
.attachISO(0, 0, operatingSystemIso)
|
||||
.attachHardDisk(
|
||||
HardDisk.builder().diskpath(adminDisk(instanceName)).controllerPort(0).deviceSlot(1)
|
||||
.autoDelete(true).build()).attachISO(1, 1, guestAdditionsIso).build();
|
||||
|
||||
VmSpec instanceVmSpec = VmSpec.builder().id(instanceName).name(instanceName).osTypeId("").memoryMB(512)
|
||||
.cleanUpMode(CleanupMode.Full).controller(ideController).forceOverwrite(true).build();
|
||||
|
||||
Injector injector = context.utils().injector();
|
||||
Function<String, String> configProperties = injector.getInstance(ValueOfConfigurationKeyOrNull.class);
|
||||
IsoSpec isoSpec = IsoSpec
|
||||
.builder()
|
||||
.sourcePath(operatingSystemIso)
|
||||
.installationScript(
|
||||
configProperties.apply(VIRTUALBOX_INSTALLATION_KEY_SEQUENCE).replace("HOSTNAME",
|
||||
instanceVmSpec.getVmName())).build();
|
||||
|
||||
NetworkAdapter networkAdapter = NetworkAdapter.builder().networkAttachmentType(NetworkAttachmentType.NAT)
|
||||
.tcpRedirectRule("127.0.0.1", 2222, "", 22).build();
|
||||
NetworkInterfaceCard networkInterfaceCard = NetworkInterfaceCard.builder().addNetworkAdapter(networkAdapter)
|
||||
.build();
|
||||
|
||||
NetworkSpec networkSpec = NetworkSpec.builder().addNIC(networkInterfaceCard).build();
|
||||
machineSpec = MasterSpec.builder().iso(isoSpec).vm(instanceVmSpec).network(networkSpec).build();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEnsureMachineisLaunchedAndSessionIsUnlocked() {
|
||||
IMachine vm = cloneFromMaster();
|
||||
ISession cloneMachineSession = machineController.ensureMachineIsLaunched(instanceName);
|
||||
System.out.println("lock - cloneMachineSession " + cloneMachineSession.toString());
|
||||
assertTrue(cloneMachineSession.getState() == SessionState.Unlocked);
|
||||
cloneMachineSession = machineController.ensureMachineHasPowerDown(instanceName);
|
||||
System.out.println("unlock - cloneMachineSession " + cloneMachineSession.toString());
|
||||
assertTrue(cloneMachineSession.getState() == SessionState.Unlocked);
|
||||
}
|
||||
|
||||
@Test(dependsOnMethods="testEnsureMachineisLaunchedAndSessionIsUnlocked")
|
||||
public void testEnsureMachineCanBePoweredOffMoreThanOneTimeAndSessionIsUnlocked() {
|
||||
ISession cloneMachineSession = machineController.ensureMachineHasPowerDown(instanceName);
|
||||
cloneMachineSession = machineController.ensureMachineHasPowerDown(instanceName);
|
||||
assertTrue(cloneMachineSession.getState() == SessionState.Unlocked);
|
||||
}
|
||||
|
||||
private IMachine cloneFromMaster() {
|
||||
IMachine source = getVmWithGuestAdditionsInstalled();
|
||||
CloneSpec cloneSpec = CloneSpec.builder().vm(machineSpec.getVmSpec()).network(machineSpec.getNetworkSpec())
|
||||
.master(source).linked(true).build();
|
||||
return new CloneAndRegisterMachineFromIMachineIfNotAlreadyExists(manager, workingDir, machineUtils)
|
||||
.apply(cloneSpec);
|
||||
}
|
||||
|
||||
private IMachine getVmWithGuestAdditionsInstalled() {
|
||||
MasterSpec masterSpecForTest = super.getMasterSpecForTest();
|
||||
try {
|
||||
Injector injector = context.utils().injector();
|
||||
return injector.getInstance(CreateAndInstallVm.class).apply(masterSpecForTest);
|
||||
} catch (IllegalStateException e) {
|
||||
// already created
|
||||
return manager.get().getVBox().findMachine(masterSpecForTest.getVmSpec().getVmId());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@AfterClass(groups = "live")
|
||||
protected void tearDown() throws Exception {
|
||||
for (String vmName : ImmutableSet.of(instanceName)) {
|
||||
undoVm(vmName);
|
||||
}
|
||||
super.tearDown();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,144 @@
|
|||
/**
|
||||
* 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.util;
|
||||
import static com.google.common.base.Preconditions.checkState;
|
||||
import static org.jclouds.virtualbox.config.VirtualBoxConstants.VIRTUALBOX_IMAGE_PREFIX;
|
||||
import static org.jclouds.virtualbox.config.VirtualBoxConstants.VIRTUALBOX_INSTALLATION_KEY_SEQUENCE;
|
||||
|
||||
import org.jclouds.config.ValueOfConfigurationKeyOrNull;
|
||||
import org.jclouds.virtualbox.BaseVirtualBoxClientLiveTest;
|
||||
import org.jclouds.virtualbox.domain.CloneSpec;
|
||||
import org.jclouds.virtualbox.domain.ExecutionType;
|
||||
import org.jclouds.virtualbox.domain.HardDisk;
|
||||
import org.jclouds.virtualbox.domain.IsoSpec;
|
||||
import org.jclouds.virtualbox.domain.MasterSpec;
|
||||
import org.jclouds.virtualbox.domain.NetworkAdapter;
|
||||
import org.jclouds.virtualbox.domain.NetworkInterfaceCard;
|
||||
import org.jclouds.virtualbox.domain.NetworkSpec;
|
||||
import org.jclouds.virtualbox.domain.StorageController;
|
||||
import org.jclouds.virtualbox.domain.VmSpec;
|
||||
import org.jclouds.virtualbox.functions.CloneAndRegisterMachineFromIMachineIfNotAlreadyExists;
|
||||
import org.jclouds.virtualbox.functions.CreateAndInstallVm;
|
||||
import org.jclouds.virtualbox.functions.LaunchMachineIfNotAlreadyRunning;
|
||||
import org.testng.annotations.AfterClass;
|
||||
import org.testng.annotations.BeforeClass;
|
||||
import org.testng.annotations.Test;
|
||||
import org.virtualbox_4_1.CleanupMode;
|
||||
import org.virtualbox_4_1.IMachine;
|
||||
import org.virtualbox_4_1.ISession;
|
||||
import org.virtualbox_4_1.LockType;
|
||||
import org.virtualbox_4_1.NetworkAttachmentType;
|
||||
import org.virtualbox_4_1.SessionState;
|
||||
import org.virtualbox_4_1.StorageBus;
|
||||
|
||||
import com.google.common.base.CaseFormat;
|
||||
import com.google.common.base.Function;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.inject.Injector;
|
||||
|
||||
@Test(groups = "live", testName = "MachineControllerLiveTest")
|
||||
public class MachineUtilsLiveTest extends BaseVirtualBoxClientLiveTest {
|
||||
|
||||
private MasterSpec machineSpec;
|
||||
private String instanceName;
|
||||
|
||||
@Override
|
||||
@BeforeClass(groups = "live")
|
||||
public void setupClient() {
|
||||
super.setupClient();
|
||||
instanceName = VIRTUALBOX_IMAGE_PREFIX
|
||||
+ CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_HYPHEN, getClass().getSimpleName());
|
||||
|
||||
StorageController ideController = StorageController
|
||||
.builder()
|
||||
.name("IDE Controller")
|
||||
.bus(StorageBus.IDE)
|
||||
.attachISO(0, 0, operatingSystemIso)
|
||||
.attachHardDisk(
|
||||
HardDisk.builder().diskpath(adminDisk(instanceName)).controllerPort(0).deviceSlot(1)
|
||||
.autoDelete(true).build()).attachISO(1, 1, guestAdditionsIso).build();
|
||||
|
||||
VmSpec instanceVmSpec = VmSpec.builder().id(instanceName).name(instanceName).osTypeId("").memoryMB(512)
|
||||
.cleanUpMode(CleanupMode.Full).controller(ideController).forceOverwrite(true).build();
|
||||
|
||||
Injector injector = context.utils().injector();
|
||||
Function<String, String> configProperties = injector.getInstance(ValueOfConfigurationKeyOrNull.class);
|
||||
IsoSpec isoSpec = IsoSpec
|
||||
.builder()
|
||||
.sourcePath(operatingSystemIso)
|
||||
.installationScript(
|
||||
configProperties.apply(VIRTUALBOX_INSTALLATION_KEY_SEQUENCE).replace("HOSTNAME",
|
||||
instanceVmSpec.getVmName())).build();
|
||||
|
||||
NetworkAdapter networkAdapter = NetworkAdapter.builder().networkAttachmentType(NetworkAttachmentType.NAT)
|
||||
.tcpRedirectRule("127.0.0.1", 2222, "", 22).build();
|
||||
NetworkInterfaceCard networkInterfaceCard = NetworkInterfaceCard.builder().addNetworkAdapter(networkAdapter)
|
||||
.build();
|
||||
|
||||
NetworkSpec networkSpec = NetworkSpec.builder().addNIC(networkInterfaceCard).build();
|
||||
machineSpec = MasterSpec.builder().iso(isoSpec).vm(instanceVmSpec).network(networkSpec).build();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void lockSessionOnMachine() {
|
||||
IMachine machine = cloneFromMaster();
|
||||
ISession session = machineUtils.lockSessionOnMachineAndApply(instanceName, LockType.Shared,
|
||||
new Function<ISession, ISession>() {
|
||||
|
||||
@Override
|
||||
public ISession apply(ISession session) {
|
||||
return session;
|
||||
}
|
||||
});
|
||||
checkState(session.getState().equals(SessionState.Unlocked));
|
||||
machine = manager.get().getVBox().findMachine(instanceName);
|
||||
undoVm(instanceName);
|
||||
|
||||
}
|
||||
|
||||
|
||||
private IMachine cloneFromMaster() {
|
||||
IMachine source = getVmWithGuestAdditionsInstalled();
|
||||
CloneSpec cloneSpec = CloneSpec.builder().vm(machineSpec.getVmSpec()).network(machineSpec.getNetworkSpec())
|
||||
.master(source).linked(true).build();
|
||||
return new CloneAndRegisterMachineFromIMachineIfNotAlreadyExists(manager, workingDir, machineUtils)
|
||||
.apply(cloneSpec);
|
||||
}
|
||||
|
||||
private IMachine getVmWithGuestAdditionsInstalled() {
|
||||
MasterSpec masterSpecForTest = super.getMasterSpecForTest();
|
||||
try {
|
||||
Injector injector = context.utils().injector();
|
||||
return injector.getInstance(CreateAndInstallVm.class).apply(masterSpecForTest);
|
||||
} catch (IllegalStateException e) {
|
||||
// already created
|
||||
return manager.get().getVBox().findMachine(masterSpecForTest.getVmSpec().getVmId());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@AfterClass(groups = "live")
|
||||
protected void tearDown() throws Exception {
|
||||
for (String vmName : ImmutableSet.of(instanceName)) {
|
||||
undoVm(vmName);
|
||||
}
|
||||
super.tearDown();
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue