Merge pull request #378 from andreaturli/development

issue 384: fixed GuestAdditions LiveTest
This commit is contained in:
Adrian Cole 2012-02-19 06:48:55 -08:00
commit 6317c880ad
7 changed files with 164 additions and 76 deletions

View File

@ -139,7 +139,7 @@ public class VirtualBoxComputeServiceAdapter implements ComputeServiceAdapter<IM
machineSession.getConsole().resume(); machineSession.getConsole().resume();
machineSession.unlockMachine(); machineSession.unlockMachine();
} catch (Exception e) { } catch (Exception e) {
propogate(e); throw Throwables.propagate(e);
} }
} }
@ -152,16 +152,10 @@ public class VirtualBoxComputeServiceAdapter implements ComputeServiceAdapter<IM
machineSession.getConsole().pause(); machineSession.getConsole().pause();
machineSession.unlockMachine(); machineSession.unlockMachine();
} catch (Exception e) { } catch (Exception e) {
propogate(e); throw Throwables.propagate(e);
} }
} }
protected <T> T propogate(Exception e) {
Throwables.propagate(e);
assert false;
return null;
}
private void launchVMProcess(IMachine machine, ISession session) { private void launchVMProcess(IMachine machine, ISession session) {
IProgress prog = machine.launchVMProcess(session, "gui", ""); IProgress prog = machine.launchVMProcess(session, "gui", "");
prog.waitForCompletion(-1); prog.waitForCompletion(-1);
@ -184,8 +178,7 @@ public class VirtualBoxComputeServiceAdapter implements ComputeServiceAdapter<IM
} }
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); throw Throwables.propagate(e);
e.printStackTrace();
} }
} }
} }

View File

@ -18,14 +18,20 @@
*/ */
package org.jclouds.virtualbox.functions; package org.jclouds.virtualbox.functions;
import com.google.common.base.Function; import static com.google.common.base.Preconditions.checkState;
import com.google.common.base.Predicate; import static com.google.common.collect.Iterables.transform;
import com.google.common.base.Splitter; import static org.jclouds.scriptbuilder.domain.Statements.call;
import com.google.common.base.Supplier;
import com.google.common.cache.LoadingCache; import java.net.URI;
import com.google.inject.Inject; import java.util.List;
import javax.annotation.Resource;
import javax.inject.Named;
import javax.inject.Singleton;
import org.jclouds.compute.ComputeServiceContext; import org.jclouds.compute.ComputeServiceContext;
import org.jclouds.compute.domain.ExecResponse;
import org.jclouds.compute.options.RunScriptOptions;
import org.jclouds.compute.reference.ComputeServiceConstants; import org.jclouds.compute.reference.ComputeServiceConstants;
import org.jclouds.logging.Logger; import org.jclouds.logging.Logger;
import org.jclouds.ssh.SshClient; import org.jclouds.ssh.SshClient;
@ -36,16 +42,20 @@ import org.jclouds.virtualbox.domain.MasterSpec;
import org.jclouds.virtualbox.domain.VmSpec; import org.jclouds.virtualbox.domain.VmSpec;
import org.jclouds.virtualbox.predicates.GuestAdditionsInstaller; import org.jclouds.virtualbox.predicates.GuestAdditionsInstaller;
import org.jclouds.virtualbox.util.MachineUtils; import org.jclouds.virtualbox.util.MachineUtils;
import org.virtualbox_4_1.*; import org.virtualbox_4_1.IMachine;
import org.virtualbox_4_1.IProgress;
import org.virtualbox_4_1.ISession;
import org.virtualbox_4_1.LockType;
import org.virtualbox_4_1.VirtualBoxManager;
import javax.annotation.Resource; import com.google.common.base.Function;
import javax.inject.Named; import com.google.common.base.Predicate;
import javax.inject.Singleton; import com.google.common.base.Splitter;
import java.net.URI; import com.google.common.base.Supplier;
import java.util.List; import com.google.common.cache.LoadingCache;
import com.google.common.util.concurrent.Futures;
import static com.google.common.base.Preconditions.checkState; import com.google.common.util.concurrent.ListenableFuture;
import static com.google.common.collect.Iterables.transform; import com.google.inject.Inject;
@Singleton @Singleton
public class CreateAndInstallVm implements Function<MasterSpec, IMachine> { public class CreateAndInstallVm implements Function<MasterSpec, IMachine> {
@ -88,12 +98,12 @@ public class CreateAndInstallVm implements Function<MasterSpec, IMachine> {
VmSpec vmSpec = masterSpec.getVmSpec(); VmSpec vmSpec = masterSpec.getVmSpec();
IsoSpec isoSpec = masterSpec.getIsoSpec(); IsoSpec isoSpec = masterSpec.getIsoSpec();
String vmName = vmSpec.getVmName(); String vmName = vmSpec.getVmName();
final IMachine vm = createAndRegisterMachineFromIsoIfNotAlreadyExists.apply(masterSpec); final IMachine vm = createAndRegisterMachineFromIsoIfNotAlreadyExists.apply(masterSpec);
// Launch machine and wait for it to come online // Launch machine and wait for it to come online
ensureMachineIsLaunched(vmName); ensureMachineIsLaunched(vmName);
URI uri = preConfiguration.getUnchecked(isoSpec); URI uri = preConfiguration.getUnchecked(isoSpec);
String installationKeySequence = isoSpec.getInstallationKeySequence().replace("PRECONFIGURATION_URL", String installationKeySequence = isoSpec.getInstallationKeySequence().replace("PRECONFIGURATION_URL",
uri.toASCIIString()); uri.toASCIIString());
@ -106,7 +116,13 @@ public class CreateAndInstallVm implements Function<MasterSpec, IMachine> {
logger.debug(">> awaiting installation of guest additions on vm: %s", vmName); logger.debug(">> awaiting installation of guest additions on vm: %s", vmName);
checkState(new GuestAdditionsInstaller(context).apply(vmName)); checkState(new GuestAdditionsInstaller(context).apply(vmName));
logger.debug(">> awaiting post-installation actions on vm: %s", vmName);
ListenableFuture<ExecResponse> execFuture = context.getComputeService().submitScriptOnNode(vmName,
call("cleanupUdevIfNeeded"), RunScriptOptions.NONE);
ExecResponse execResponse = Futures.getUnchecked(execFuture);
checkState(execResponse.getExitCode() == 0);
logger.debug("<< installation of image complete. Powering down node(%s)", vmName); logger.debug("<< installation of image complete. Powering down node(%s)", vmName);
ensureMachineHasPowerDown(vmName); ensureMachineHasPowerDown(vmName);
return vm; return vm;

View File

@ -0,0 +1,12 @@
function cleanupUdevIfNeeded {
unset OSNAME;
local OSNAME=`lsb_release -d -s | cut -d ' ' -f 1`; shift
if [ $OSNAME = 'Ubuntu' ]
then
echo "OS is Ubuntu"
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
fi
}

View File

@ -50,11 +50,6 @@ public class VirtualBoxComputeServiceAdapterLiveTest extends BaseVirtualBoxClien
adapter = context.utils().injector().getInstance(VirtualBoxComputeServiceAdapter.class); adapter = context.utils().injector().getInstance(VirtualBoxComputeServiceAdapter.class);
} }
@Test
public void testListLocations() {
assertFalse(Iterables.isEmpty(adapter.listLocations()));
}
private static final PrioritizeCredentialsFromTemplate prioritizeCredentialsFromTemplate = new PrioritizeCredentialsFromTemplate( private static final PrioritizeCredentialsFromTemplate prioritizeCredentialsFromTemplate = new PrioritizeCredentialsFromTemplate(
new DefaultCredentialsFromImageOrOverridingCredentials()); new DefaultCredentialsFromImageOrOverridingCredentials());

View File

@ -33,6 +33,7 @@ import org.jclouds.virtualbox.domain.StorageController;
import org.jclouds.virtualbox.domain.VmSpec; import org.jclouds.virtualbox.domain.VmSpec;
import org.jclouds.virtualbox.functions.CloneAndRegisterMachineFromIMachineIfNotAlreadyExists; import org.jclouds.virtualbox.functions.CloneAndRegisterMachineFromIMachineIfNotAlreadyExists;
import org.jclouds.virtualbox.functions.CreateAndRegisterMachineFromIsoIfNotAlreadyExists; import org.jclouds.virtualbox.functions.CreateAndRegisterMachineFromIsoIfNotAlreadyExists;
import org.testng.annotations.AfterClass;
import org.testng.annotations.BeforeClass; import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test; import org.testng.annotations.Test;
import org.virtualbox_4_1.CleanupMode; import org.virtualbox_4_1.CleanupMode;
@ -138,4 +139,5 @@ public class CloneAndRegisterMachineFromIsoIfNotAlreadyExistsLiveTest extends
.findMachine(sourceMachineSpec.getVmSpec().getVmId()); .findMachine(sourceMachineSpec.getVmSpec().getVmId());
} }
} }
} }

View File

@ -19,10 +19,19 @@
package org.jclouds.virtualbox.functions; package org.jclouds.virtualbox.functions;
import com.google.common.base.CaseFormat; import static com.google.common.base.Preconditions.checkState;
import com.google.common.base.Function; import static com.google.common.base.Predicates.equalTo;
import com.google.inject.Guice; import static com.google.common.collect.Iterables.any;
import com.google.inject.Injector; import static com.google.common.collect.Iterables.transform;
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.Map;
import java.util.Set;
import javax.annotation.Nullable;
import org.jclouds.compute.config.BaseComputeServiceContextModule; import org.jclouds.compute.config.BaseComputeServiceContextModule;
import org.jclouds.compute.domain.Image; import org.jclouds.compute.domain.Image;
import org.jclouds.compute.domain.OsFamily; import org.jclouds.compute.domain.OsFamily;
@ -30,25 +39,35 @@ import org.jclouds.compute.reference.ComputeServiceConstants;
import org.jclouds.config.ValueOfConfigurationKeyOrNull; import org.jclouds.config.ValueOfConfigurationKeyOrNull;
import org.jclouds.json.Json; import org.jclouds.json.Json;
import org.jclouds.json.config.GsonModule; import org.jclouds.json.config.GsonModule;
import org.jclouds.ssh.SshClient;
import org.jclouds.virtualbox.BaseVirtualBoxClientLiveTest; import org.jclouds.virtualbox.BaseVirtualBoxClientLiveTest;
import org.jclouds.virtualbox.domain.*; 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.NatAdapter;
import org.jclouds.virtualbox.domain.NetworkSpec;
import org.jclouds.virtualbox.domain.StorageController;
import org.jclouds.virtualbox.domain.VmSpec;
import org.jclouds.virtualbox.predicates.SshResponds;
import org.testng.annotations.AfterClass; import org.testng.annotations.AfterClass;
import org.testng.annotations.BeforeClass; import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test; import org.testng.annotations.Test;
import org.virtualbox_4_1.CleanupMode; import org.virtualbox_4_1.CleanupMode;
import org.virtualbox_4_1.IMachine; import org.virtualbox_4_1.IMachine;
import org.virtualbox_4_1.IProgress;
import org.virtualbox_4_1.ISession;
import org.virtualbox_4_1.LockType;
import org.virtualbox_4_1.StorageBus; import org.virtualbox_4_1.StorageBus;
import javax.annotation.Nullable; import com.google.common.base.CaseFormat;
import java.util.Map; import com.google.common.base.Function;
import java.util.Set; import com.google.common.base.Predicate;
import com.google.common.base.Splitter;
import static com.google.common.base.Predicates.equalTo; import com.google.common.collect.ImmutableSet;
import static com.google.common.collect.Iterables.any; import com.google.common.collect.Iterables;
import static com.google.common.collect.Iterables.transform; import com.google.inject.Guice;
import static org.jclouds.virtualbox.config.VirtualBoxConstants.VIRTUALBOX_IMAGE_PREFIX; import com.google.inject.Injector;
import static org.jclouds.virtualbox.config.VirtualBoxConstants.VIRTUALBOX_INSTALLATION_KEY_SEQUENCE;
import static org.testng.Assert.assertTrue;
/** /**
* @author Andrea Turli, Mattias Holmqvist * @author Andrea Turli, Mattias Holmqvist
@ -61,7 +80,12 @@ public class CreateAndInstallVmLiveTest extends BaseVirtualBoxClientLiveTest {
.createInjector(new GsonModule()).getInstance(Json.class)); .createInjector(new GsonModule()).getInstance(Json.class));
private VmSpec vmSpecification; private VmSpec vmSpecification;
private MasterSpec masterSpec;
private Injector injector;
private Function<IMachine, SshClient> sshClientForIMachine;
private Predicate<SshClient> sshResponds;
@Override @Override
@BeforeClass(groups = "live") @BeforeClass(groups = "live")
public void setupClient() { public void setupClient() {
@ -76,28 +100,31 @@ public class CreateAndInstallVmLiveTest extends BaseVirtualBoxClientLiveTest {
.attachISO(0, 0, operatingSystemIso) .attachISO(0, 0, operatingSystemIso)
.attachHardDisk(hardDisk) .attachHardDisk(hardDisk)
.attachISO(1, 1, guestAdditionsIso).build(); .attachISO(1, 1, guestAdditionsIso).build();
vmSpecification = VmSpec.builder().id("jclouds-image-create-and-install-vm-test").name(vmName).memoryMB(512).osTypeId("") vmSpecification = VmSpec.builder().id(vmName).name(vmName).memoryMB(512).osTypeId("")
.controller(ideController) .controller(ideController)
.forceOverwrite(true) .forceOverwrite(true)
.cleanUpMode(CleanupMode.Full).build(); .cleanUpMode(CleanupMode.Full).build();
}
injector = context.utils().injector();
public void testCreateImageMachineFromIso() throws Exception {
Injector injector = context.utils().injector();
Function<String, String> configProperties = injector Function<String, String> configProperties = injector
.getInstance(ValueOfConfigurationKeyOrNull.class); .getInstance(ValueOfConfigurationKeyOrNull.class);
MasterSpec masterSpec = MasterSpec.builder().vm(vmSpecification) masterSpec = MasterSpec.builder().vm(vmSpecification)
.iso(IsoSpec.builder() .iso(IsoSpec.builder()
.sourcePath(operatingSystemIso) .sourcePath(operatingSystemIso)
.installationScript(configProperties .installationScript(configProperties
.apply(VIRTUALBOX_INSTALLATION_KEY_SEQUENCE) .apply(VIRTUALBOX_INSTALLATION_KEY_SEQUENCE)
.replace("HOSTNAME", vmSpecification.getVmName())) .replace("HOSTNAME", vmSpecification.getVmName()))
.build()) .build())
.network(NetworkSpec.builder() .network(NetworkSpec.builder()
.natNetworkAdapter(0, NatAdapter.builder().tcpRedirectRule("127.0.0.1", 2222, "", 22).build()) .natNetworkAdapter(0, NatAdapter.builder().tcpRedirectRule("127.0.0.1", 2222, "", 22).build())
.build()).build(); .build()).build();
IMachine imageMachine = injector.getInstance(CreateAndInstallVm.class).apply(masterSpec);
undoVm(vmSpecification);
}
public void testCreateImageMachineFromIso() throws Exception {
IMachine imageMachine = getVmWithGuestAdditionsInstalled();
IMachineToImage iMachineToImage = new IMachineToImage(manager, map); IMachineToImage iMachineToImage = new IMachineToImage(manager, map);
Image newImage = iMachineToImage.apply(imageMachine); Image newImage = iMachineToImage.apply(imageMachine);
@ -107,6 +134,33 @@ public class CreateAndInstallVmLiveTest extends BaseVirtualBoxClientLiveTest {
Iterable<String> imageIds = transform(images, extractId()); Iterable<String> imageIds = transform(images, extractId());
assertTrue(any(imageIds, equalTo(newImage.getId()))); assertTrue(any(imageIds, equalTo(newImage.getId())));
} }
@Test
public void testGuestAdditionsAreInstalled() throws Exception {
try {
IMachine machine = getVmWithGuestAdditionsInstalled();
machineUtils.applyForMachine(machine.getName(), new LaunchMachineIfNotAlreadyRunning(manager.get(), ExecutionType.GUI, ""));
sshClientForIMachine = injector.getInstance(IMachineToSshClient.class);
SshClient client = sshClientForIMachine.apply(machine);
sshResponds = injector.getInstance(SshResponds.class);
checkState(sshResponds.apply(client), "timed out waiting for guest %s to be accessible via ssh", machine.getName());
assertTrue(machineUtils.lockSessionOnMachineAndApply(machine.getName(), LockType.Shared, new Function<ISession, Boolean>() {
@Override
public Boolean apply(ISession session) {
String vboxVersion = Iterables.get(Splitter.on('r').split(context.getProviderSpecificContext().getBuildVersion()), 0);
return session.getMachine().getGuestPropertyValue("/VirtualBox/GuestAdd/Version").equals(vboxVersion);
}
}));
} finally {
for (VmSpec spec : ImmutableSet.of(
vmSpecification)) {
ensureMachineHasPowerDown(spec.getVmName());
}
}
}
private Function<Image, String> extractId() { private Function<Image, String> extractId() {
return new Function<Image, String>() { return new Function<Image, String>() {
@ -118,10 +172,37 @@ public class CreateAndInstallVmLiveTest extends BaseVirtualBoxClientLiveTest {
}; };
} }
private IMachine getVmWithGuestAdditionsInstalled() {
try {
Injector injector = context.utils().injector();
return injector.getInstance(
CreateAndInstallVm.class).apply(
masterSpec);
} catch (IllegalStateException e) {
// already created
return manager.get().getVBox()
.findMachine(masterSpec.getVmSpec().getVmId());
}
}
private void ensureMachineHasPowerDown(String vmName) {
machineUtils.lockSessionOnMachineAndApply(vmName, LockType.Shared, new Function<ISession, Void>() {
@Override
public Void apply(ISession session) {
IProgress powerDownProgress = session.getConsole().powerDown();
powerDownProgress.waitForCompletion(-1);
return null;
}
});
}
@Override @Override
@AfterClass(groups = "live") @AfterClass(groups = "live")
protected void tearDown() throws Exception { protected void tearDown() throws Exception {
undoVm(vmSpecification); for (VmSpec spec : ImmutableSet.of(
vmSpecification)) {
undoVm(spec);
}
super.tearDown(); super.tearDown();
} }
} }

View File

@ -96,17 +96,6 @@ public class IMachinePredicatesLiveTest extends BaseVirtualBoxClientLiveTest {
assertTrue(isLinkedClone().apply(clone)); assertTrue(isLinkedClone().apply(clone));
} }
/*
* public void testFullClone() { IMachine master =
* context.utils().injector().
* getInstance(CreateAndRegisterMachineFromIsoIfNotAlreadyExists.class)
* .apply(masterSpec); IMachine clone = new
* CloneAndRegisterMachineFromIMachineIfNotAlreadyExists(manager, workingDir,
* cloneSpec, !IS_LINKED_CLONE).apply(master);
*
* assertFalse(new IsLinkedClone(manager).apply(clone)); }
*/
@BeforeMethod @BeforeMethod
@AfterMethod @AfterMethod
void cleanUpVms() { void cleanUpVms() {