From 623f3c6daa33842acfc72d1df839eaa6ea8792db Mon Sep 17 00:00:00 2001 From: andreaturli Date: Sun, 5 Feb 2012 23:05:15 +0000 Subject: [PATCH 1/4] issue 384: GuestAdditionsInstaller --- .../config/VirtualBoxConstants.java | 2 +- .../functions/CreateAndInstallVm.java | 1 - .../functions/IMachineToNodeMetadata.java | 7 +- .../statements/InstallGuestAdditions.java | 19 +++-- .../functions/installGuestAdditions.sh | 8 +- .../statements/GuestAdditionsInstaller.java | 83 +++++++++++++++++++ .../statements/InstallGuestAdditionsTest.java | 55 ++++++++++++ .../GuestAdditionsInstallation.java | 74 +++++++++++++++++ 8 files changed, 229 insertions(+), 20 deletions(-) create mode 100644 labs/virtualbox/src/test/java/org/jclouds/virtualbox/statements/GuestAdditionsInstaller.java create mode 100644 labs/virtualbox/src/test/java/org/jclouds/virtualbox/statements/InstallGuestAdditionsTest.java create mode 100644 sandbox-apis/virtualbox/src/main/java/org/jclouds/virtualbox/statements/GuestAdditionsInstallation.java diff --git a/labs/virtualbox/src/main/java/org/jclouds/virtualbox/config/VirtualBoxConstants.java b/labs/virtualbox/src/main/java/org/jclouds/virtualbox/config/VirtualBoxConstants.java index 5f949eca14..ae836e0fc4 100644 --- a/labs/virtualbox/src/main/java/org/jclouds/virtualbox/config/VirtualBoxConstants.java +++ b/labs/virtualbox/src/main/java/org/jclouds/virtualbox/config/VirtualBoxConstants.java @@ -27,7 +27,7 @@ package org.jclouds.virtualbox.config; */ public interface VirtualBoxConstants { - public static final String VIRTUALBOX_IMAGE_PREFIX = "jclouds#image#"; + public static final String VIRTUALBOX_IMAGE_PREFIX = "jclouds-image-"; public static final String VIRTUALBOX_PRECONFIGURATION_URL = "jclouds.virtualbox.preconfigurationurl"; diff --git a/labs/virtualbox/src/main/java/org/jclouds/virtualbox/functions/CreateAndInstallVm.java b/labs/virtualbox/src/main/java/org/jclouds/virtualbox/functions/CreateAndInstallVm.java index fe36700e8c..e35dafb531 100644 --- a/labs/virtualbox/src/main/java/org/jclouds/virtualbox/functions/CreateAndInstallVm.java +++ b/labs/virtualbox/src/main/java/org/jclouds/virtualbox/functions/CreateAndInstallVm.java @@ -75,7 +75,6 @@ public class CreateAndInstallVm implements Function { this.executionType = executionType; this.machineUtils = machineUtils; this.preConfiguration = preConfiguration; - } @Override diff --git a/labs/virtualbox/src/main/java/org/jclouds/virtualbox/functions/IMachineToNodeMetadata.java b/labs/virtualbox/src/main/java/org/jclouds/virtualbox/functions/IMachineToNodeMetadata.java index 1976e64e00..16fa75c6a4 100644 --- a/labs/virtualbox/src/main/java/org/jclouds/virtualbox/functions/IMachineToNodeMetadata.java +++ b/labs/virtualbox/src/main/java/org/jclouds/virtualbox/functions/IMachineToNodeMetadata.java @@ -35,6 +35,7 @@ import org.jclouds.compute.domain.Processor; import org.jclouds.compute.reference.ComputeServiceConstants; import org.jclouds.domain.LocationBuilder; import org.jclouds.domain.LocationScope; +import org.jclouds.domain.LoginCredentials; import org.jclouds.javax.annotation.Nullable; import org.jclouds.logging.Logger; import org.virtualbox_4_1.IMachine; @@ -104,9 +105,9 @@ public class IMachineToNodeMetadata implements Function } } - // nodeMetadataBuilder.imageId(""); - // nodeMetadataBuilder.group(""); - + LoginCredentials loginCredentials = new LoginCredentials("toor", "password", null, true); + nodeMetadataBuilder.credentials(loginCredentials); + return nodeMetadataBuilder.build(); } diff --git a/labs/virtualbox/src/main/java/org/jclouds/virtualbox/statements/InstallGuestAdditions.java b/labs/virtualbox/src/main/java/org/jclouds/virtualbox/statements/InstallGuestAdditions.java index 0a4e8f5023..cfcf5f7c5b 100644 --- a/labs/virtualbox/src/main/java/org/jclouds/virtualbox/statements/InstallGuestAdditions.java +++ b/labs/virtualbox/src/main/java/org/jclouds/virtualbox/statements/InstallGuestAdditions.java @@ -34,13 +34,13 @@ import org.jclouds.scriptbuilder.domain.Statement; import com.google.common.collect.ImmutableMultimap; public class InstallGuestAdditions implements Statement { - + private final String vboxVersion; private final String mountPoint; - + public InstallGuestAdditions(String vboxVersion) { this(vboxVersion, "/mnt"); - } + } public InstallGuestAdditions(String vboxVersion, String mountPoint) { this.vboxVersion = checkNotNull(vboxVersion, "vboxVersion"); @@ -57,17 +57,18 @@ public class InstallGuestAdditions implements Statement { checkNotNull(family, "family"); if (family == OsFamily.WINDOWS) throw new UnsupportedOperationException("windows not yet implemented"); - + String vboxGuestAdditionsIso = "VBoxGuestAdditions_" + vboxVersion + ".iso"; ScriptBuilder scriptBuilder = new ScriptBuilder() .addStatement( - new SaveHttpResponseTo("{tmp}", vboxGuestAdditionsIso, "GET", URI + new SaveHttpResponseTo("{tmp}{fs}", vboxGuestAdditionsIso, "GET", URI .create("http://download.virtualbox.org/virtualbox/" + vboxVersion + "/" + vboxGuestAdditionsIso), ImmutableMultimap. of())) - .addStatement(exec(String.format("mount -o loop {tmp}{fs}%s %s", vboxGuestAdditionsIso, mountPoint))) - .addStatement(call("installGuestAdditions")) - .addStatement(exec(String.format("sh %s%s", mountPoint, "/VBoxLinuxAdditions.run"))) - .addStatement(exec(String.format("umount %s", mountPoint))); + .addStatement(exec(String.format("mount -o loop {tmp}{fs}%s %s", vboxGuestAdditionsIso, mountPoint))) + .addStatement(call("installGuestAdditions")) + .addStatement(exec(String.format("sh %s%s", mountPoint, "/VBoxLinuxAdditions.run"))) + .addStatement(exec(String.format("umount %s", mountPoint))); + return scriptBuilder.render(family); } diff --git a/labs/virtualbox/src/main/resources/functions/installGuestAdditions.sh b/labs/virtualbox/src/main/resources/functions/installGuestAdditions.sh index e1bd00e9a4..205aa45d92 100644 --- a/labs/virtualbox/src/main/resources/functions/installGuestAdditions.sh +++ b/labs/virtualbox/src/main/resources/functions/installGuestAdditions.sh @@ -1,14 +1,10 @@ function installGuestAdditions { unset OSNAME; - [ $# -eq 1 ] || { - abort "installGuestAdditions requires virtual machine name parameter" - return 1 - } local OSNAME=`lsb_release -d -s | cut -d ' ' -f 1`; shift if [ $OSNAME = 'Ubuntu' ] then - echo "OS Name is Ubuntu" - `apt-get install build-essential module-assistant && m-a prepare -i` + echo "OS is Ubuntu" + apt-get -f -y -qq --force-yes install build-essential module-assistant && m-a prepare -i fi return 0 } \ No newline at end of file diff --git a/labs/virtualbox/src/test/java/org/jclouds/virtualbox/statements/GuestAdditionsInstaller.java b/labs/virtualbox/src/test/java/org/jclouds/virtualbox/statements/GuestAdditionsInstaller.java new file mode 100644 index 0000000000..62ba744ea3 --- /dev/null +++ b/labs/virtualbox/src/test/java/org/jclouds/virtualbox/statements/GuestAdditionsInstaller.java @@ -0,0 +1,83 @@ +package org.jclouds.virtualbox.statements; + +import static com.google.common.base.Preconditions.checkNotNull; +import static org.jclouds.compute.options.RunScriptOptions.Builder.runAsRoot; + +import javax.annotation.Resource; +import javax.inject.Named; +import javax.inject.Singleton; + +import org.jclouds.compute.ComputeServiceContext; +import org.jclouds.compute.RunScriptData; +import org.jclouds.compute.callables.RunScriptOnNode.Factory; +import org.jclouds.compute.domain.ExecResponse; +import org.jclouds.compute.domain.NodeMetadata; +import org.jclouds.compute.reference.ComputeServiceConstants; +import org.jclouds.logging.Logger; +import org.jclouds.scriptbuilder.domain.StatementList; +import org.jclouds.scriptbuilder.domain.Statements; +import org.jclouds.ssh.SshClient; +import org.jclouds.virtualbox.domain.ExecutionType; +import org.jclouds.virtualbox.functions.CreateAndRegisterMachineFromIsoIfNotAlreadyExists; +import org.jclouds.virtualbox.functions.IMachineToNodeMetadata; +import org.jclouds.virtualbox.functions.LaunchMachineIfNotAlreadyRunning; +import org.jclouds.virtualbox.util.MachineUtils; +import org.virtualbox_4_1.IMachine; +import org.virtualbox_4_1.VirtualBoxManager; + +import com.google.common.base.Function; +import com.google.common.base.Predicate; +import com.google.common.base.Supplier; +import com.google.common.util.concurrent.ListenableFuture; +import com.google.inject.Inject; + +@Singleton +public class GuestAdditionsInstaller implements Function { + + @Resource + @Named(ComputeServiceConstants.COMPUTE_LOGGER) + protected Logger logger = Logger.NULL; + + private final ComputeServiceContext context; + + private final Supplier manager; + private final ExecutionType executionType; + private final MachineUtils machineUtils; + // TODO remove this hardcoded value + private String vboxVersion = "4.1.6"; + + + @Inject + public GuestAdditionsInstaller(ComputeServiceContext context, Supplier manager, + CreateAndRegisterMachineFromIsoIfNotAlreadyExists createAndRegisterMachineFromIsoIfNotAlreadyExists, + Predicate installGuestAdditionsViaSshResponds, Function sshClientForIMachine, + ExecutionType executionType, MachineUtils machineUtils, Factory runScriptOnNodeFactory, + Supplier guest) { + this.context = context; + this.manager = manager; + this.executionType = executionType; + this.machineUtils = machineUtils; + } + + @Override + public IMachine apply(String vmName) { + IMachine vm = manager.get().getVBox().findMachine(vmName); + ensureMachineIsLaunched(vmName); + + InstallGuestAdditions installGuestAdditions = new InstallGuestAdditions(vboxVersion); + StatementList statementList = new StatementList(Statements.exec(RunScriptData.aptInstallLazyUpgrade("curl")), + installGuestAdditions); + + NodeMetadata vmMetadata = new IMachineToNodeMetadata().apply(vm); + + context.getComputeService().submitScriptOnNode(vmMetadata.getId(), statementList, + runAsRoot(true).wrapInInitScript(false)); + + return vm; + } + + private void ensureMachineIsLaunched(String vmName) { + machineUtils.applyForMachine(vmName, new LaunchMachineIfNotAlreadyRunning(manager.get(), executionType, "")); + } + +} diff --git a/labs/virtualbox/src/test/java/org/jclouds/virtualbox/statements/InstallGuestAdditionsTest.java b/labs/virtualbox/src/test/java/org/jclouds/virtualbox/statements/InstallGuestAdditionsTest.java new file mode 100644 index 0000000000..1fb1bd419f --- /dev/null +++ b/labs/virtualbox/src/test/java/org/jclouds/virtualbox/statements/InstallGuestAdditionsTest.java @@ -0,0 +1,55 @@ +/** + * 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.statements; + +import static org.jclouds.virtualbox.config.VirtualBoxConstants.VIRTUALBOX_IMAGE_PREFIX; + +import org.jclouds.virtualbox.BaseVirtualBoxClientLiveTest; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.Test; + +import com.google.common.base.CaseFormat; +import com.google.inject.Injector; + +/** + * @author Andrea Turli + */ +@Test(groups = "live", singleThreaded = true, testName = "InstallGuestAdditionsTest") +public class InstallGuestAdditionsTest extends BaseVirtualBoxClientLiveTest { + + private String vmName; + + @Override + @BeforeClass(groups = "live") + public void setupClient() { + super.setupClient(); + vmName = VIRTUALBOX_IMAGE_PREFIX + + CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_HYPHEN, getClass() + .getSimpleName()); + + vmName = "jclouds-image-create-and-install-vm-live-test"; + } + + public void testInstallGuestAdditionsOnTheMachine() throws Exception { + Injector injector = context.utils().injector(); + injector.getInstance(GuestAdditionsInstaller.class).apply(vmName); + } + +} \ No newline at end of file diff --git a/sandbox-apis/virtualbox/src/main/java/org/jclouds/virtualbox/statements/GuestAdditionsInstallation.java b/sandbox-apis/virtualbox/src/main/java/org/jclouds/virtualbox/statements/GuestAdditionsInstallation.java new file mode 100644 index 0000000000..28af1a9f23 --- /dev/null +++ b/sandbox-apis/virtualbox/src/main/java/org/jclouds/virtualbox/statements/GuestAdditionsInstallation.java @@ -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.virtualbox.statements; + +import static com.google.common.base.Preconditions.checkNotNull; +import static org.jclouds.scriptbuilder.domain.Statements.call; +import static org.jclouds.scriptbuilder.domain.Statements.exec; + +import java.net.URI; +import java.util.Collections; + +import org.jclouds.scriptbuilder.ScriptBuilder; +import org.jclouds.scriptbuilder.domain.OsFamily; +import org.jclouds.scriptbuilder.domain.SaveHttpResponseTo; +import org.jclouds.scriptbuilder.domain.Statement; + +import com.google.common.collect.ImmutableMultimap; + +public class GuestAdditionsInstallation implements Statement { + + private final String vboxVersion; + private final String mountPoint; + + public GuestAdditionsInstallation(String vboxVersion) { + this(vboxVersion, "/mnt"); + } + + public GuestAdditionsInstallation(String vboxVersion, String mountPoint) { + this.vboxVersion = checkNotNull(vboxVersion, "vboxVersion"); + this.mountPoint = checkNotNull(mountPoint, "mountPoint"); + } + + @Override + public Iterable functionDependencies(OsFamily family) { + return Collections.emptyList(); + } + + @Override + public String render(OsFamily family) { + checkNotNull(family, "family"); + if (family == OsFamily.WINDOWS) + throw new UnsupportedOperationException("windows not yet implemented"); + + String vboxGuestAdditionsIso = "VBoxGuestAdditions_" + vboxVersion + ".iso"; + ScriptBuilder scriptBuilder = new ScriptBuilder() + .addStatement( + new SaveHttpResponseTo("{tmp}", vboxGuestAdditionsIso, "GET", URI + .create("http://download.virtualbox.org/virtualbox/" + vboxVersion + "/" + + vboxGuestAdditionsIso), ImmutableMultimap. of())) + .addStatement(exec(String.format("mount -o loop {tmp}{fs}%s %s", vboxGuestAdditionsIso, mountPoint))) + .addStatement(call("installGuestAdditions")) + .addStatement(exec(String.format("sh %s%s", mountPoint, "/VBoxLinuxAdditions.run"))) + .addStatement(exec(String.format("umount %s", mountPoint))); + return scriptBuilder.render(family); + } + +} From af553b6294f485736c686ba9cd9f9ed32df10a86 Mon Sep 17 00:00:00 2001 From: andreaturli Date: Mon, 6 Feb 2012 22:53:09 +0000 Subject: [PATCH 2/4] issue 384: GuestAdditionsInstaller - fix future --- .../statements/InstallGuestAdditions.java | 4 +-- ...s.sh => installModuleAssistantIfNeeded.sh} | 2 +- ...va => GuestAdditionsInstallationTest.java} | 4 +-- .../statements/GuestAdditionsInstaller.java | 16 +++++++--- .../test_guest_additions_installer.sh | 26 ++++++++++++++++ .../resources/test_install_guest_additions.sh | 30 ------------------- 6 files changed, 43 insertions(+), 39 deletions(-) rename labs/virtualbox/src/main/resources/functions/{installGuestAdditions.sh => installModuleAssistantIfNeeded.sh} (85%) rename labs/virtualbox/src/test/java/org/jclouds/virtualbox/domain/{InstallGuestAdditionsTest.java => GuestAdditionsInstallationTest.java} (90%) create mode 100644 labs/virtualbox/src/test/resources/test_guest_additions_installer.sh delete mode 100644 labs/virtualbox/src/test/resources/test_install_guest_additions.sh diff --git a/labs/virtualbox/src/main/java/org/jclouds/virtualbox/statements/InstallGuestAdditions.java b/labs/virtualbox/src/main/java/org/jclouds/virtualbox/statements/InstallGuestAdditions.java index cfcf5f7c5b..8ba07609ea 100644 --- a/labs/virtualbox/src/main/java/org/jclouds/virtualbox/statements/InstallGuestAdditions.java +++ b/labs/virtualbox/src/main/java/org/jclouds/virtualbox/statements/InstallGuestAdditions.java @@ -65,8 +65,8 @@ public class InstallGuestAdditions implements Statement { .create("http://download.virtualbox.org/virtualbox/" + vboxVersion + "/" + vboxGuestAdditionsIso), ImmutableMultimap. of())) .addStatement(exec(String.format("mount -o loop {tmp}{fs}%s %s", vboxGuestAdditionsIso, mountPoint))) - .addStatement(call("installGuestAdditions")) - .addStatement(exec(String.format("sh %s%s", mountPoint, "/VBoxLinuxAdditions.run"))) + .addStatement(call("installModuleAssistantIfNeeded")) + .addStatement(exec(String.format("%s%s", mountPoint, "/VBoxLinuxAdditions.run"))) .addStatement(exec(String.format("umount %s", mountPoint))); return scriptBuilder.render(family); diff --git a/labs/virtualbox/src/main/resources/functions/installGuestAdditions.sh b/labs/virtualbox/src/main/resources/functions/installModuleAssistantIfNeeded.sh similarity index 85% rename from labs/virtualbox/src/main/resources/functions/installGuestAdditions.sh rename to labs/virtualbox/src/main/resources/functions/installModuleAssistantIfNeeded.sh index 205aa45d92..93e741f357 100644 --- a/labs/virtualbox/src/main/resources/functions/installGuestAdditions.sh +++ b/labs/virtualbox/src/main/resources/functions/installModuleAssistantIfNeeded.sh @@ -1,4 +1,4 @@ -function installGuestAdditions { +function installModuleAssistantIfNeeded { unset OSNAME; local OSNAME=`lsb_release -d -s | cut -d ' ' -f 1`; shift if [ $OSNAME = 'Ubuntu' ] diff --git a/labs/virtualbox/src/test/java/org/jclouds/virtualbox/domain/InstallGuestAdditionsTest.java b/labs/virtualbox/src/test/java/org/jclouds/virtualbox/domain/GuestAdditionsInstallationTest.java similarity index 90% rename from labs/virtualbox/src/test/java/org/jclouds/virtualbox/domain/InstallGuestAdditionsTest.java rename to labs/virtualbox/src/test/java/org/jclouds/virtualbox/domain/GuestAdditionsInstallationTest.java index 8aace24860..3f854e50b2 100644 --- a/labs/virtualbox/src/test/java/org/jclouds/virtualbox/domain/InstallGuestAdditionsTest.java +++ b/labs/virtualbox/src/test/java/org/jclouds/virtualbox/domain/GuestAdditionsInstallationTest.java @@ -32,11 +32,11 @@ import com.google.common.io.CharStreams; import com.google.common.io.Resources; @Test(groups = "unit") -public class InstallGuestAdditionsTest { +public class GuestAdditionsInstallationTest { @Test public void testUnix() throws IOException { InstallGuestAdditions statement = new InstallGuestAdditions("4.1.6"); assertEquals(statement.render(OsFamily.UNIX), CharStreams.toString(Resources.newReaderSupplier(Resources - .getResource("test_install_guest_additions." + ShellToken.SH.to(OsFamily.UNIX)), Charsets.UTF_8))); + .getResource("test_guest_additions_installer." + ShellToken.SH.to(OsFamily.UNIX)), Charsets.UTF_8))); } } \ No newline at end of file diff --git a/labs/virtualbox/src/test/java/org/jclouds/virtualbox/statements/GuestAdditionsInstaller.java b/labs/virtualbox/src/test/java/org/jclouds/virtualbox/statements/GuestAdditionsInstaller.java index 62ba744ea3..36fbba812a 100644 --- a/labs/virtualbox/src/test/java/org/jclouds/virtualbox/statements/GuestAdditionsInstaller.java +++ b/labs/virtualbox/src/test/java/org/jclouds/virtualbox/statements/GuestAdditionsInstaller.java @@ -3,6 +3,8 @@ package org.jclouds.virtualbox.statements; import static com.google.common.base.Preconditions.checkNotNull; import static org.jclouds.compute.options.RunScriptOptions.Builder.runAsRoot; +import java.util.concurrent.ExecutionException; + import javax.annotation.Resource; import javax.inject.Named; import javax.inject.Singleton; @@ -70,14 +72,20 @@ public class GuestAdditionsInstaller implements Function { NodeMetadata vmMetadata = new IMachineToNodeMetadata().apply(vm); - context.getComputeService().submitScriptOnNode(vmMetadata.getId(), statementList, + ListenableFuture execFuture = context.getComputeService().submitScriptOnNode(vmMetadata.getId(), statementList, runAsRoot(true).wrapInInitScript(false)); - + try { + execFuture.get(); + } catch (InterruptedException e) { + e.printStackTrace(); + } catch (ExecutionException e) { + e.printStackTrace(); + } return vm; } private void ensureMachineIsLaunched(String vmName) { machineUtils.applyForMachine(vmName, new LaunchMachineIfNotAlreadyRunning(manager.get(), executionType, "")); } - -} + +} \ No newline at end of file diff --git a/labs/virtualbox/src/test/resources/test_guest_additions_installer.sh b/labs/virtualbox/src/test/resources/test_guest_additions_installer.sh new file mode 100644 index 0000000000..8af63cbff9 --- /dev/null +++ b/labs/virtualbox/src/test/resources/test_guest_additions_installer.sh @@ -0,0 +1,26 @@ +#!/bin/bash +set +u +shopt -s xpg_echo +shopt -s expand_aliases +unset PATH JAVA_HOME LD_LIBRARY_PATH +function abort { + echo "aborting: $@" 1>&2 + exit 1 +} +function installModuleAssistantIfNeeded { + unset OSNAME; + local OSNAME=`lsb_release -d -s | cut -d ' ' -f 1`; shift + if [ $OSNAME = 'Ubuntu' ] + then + echo "OS is Ubuntu" + apt-get -f -y -qq --force-yes install build-essential module-assistant && m-a prepare -i + fi + return 0 +} +export PATH=/usr/ucb/bin:/bin:/sbin:/usr/bin:/usr/sbin +(mkdir -p /tmp/ && cd /tmp/ && [ ! -f VBoxGuestAdditions_4.1.6.iso ] && curl -q -s -S -L --connect-timeout 10 --max-time 600 --retry 20 -C - -X GET http://download.virtualbox.org/virtualbox/4.1.6/VBoxGuestAdditions_4.1.6.iso >VBoxGuestAdditions_4.1.6.iso) +mount -o loop /tmp/VBoxGuestAdditions_4.1.6.iso /mnt +installModuleAssistantIfNeeded || exit 1 +/mnt/VBoxLinuxAdditions.run +umount /mnt +exit 0 diff --git a/labs/virtualbox/src/test/resources/test_install_guest_additions.sh b/labs/virtualbox/src/test/resources/test_install_guest_additions.sh deleted file mode 100644 index fe2736bff5..0000000000 --- a/labs/virtualbox/src/test/resources/test_install_guest_additions.sh +++ /dev/null @@ -1,30 +0,0 @@ -#!/bin/bash -set +u -shopt -s xpg_echo -shopt -s expand_aliases -unset PATH JAVA_HOME LD_LIBRARY_PATH -function abort { - echo "aborting: $@" 1>&2 - exit 1 -} -function installGuestAdditions { - unset OSNAME; - [ $# -eq 1 ] || { - abort "installGuestAdditions requires virtual machine name parameter" - return 1 - } - local OSNAME=`lsb_release -d -s | cut -d ' ' -f 1`; shift - if [ $OSNAME = 'Ubuntu' ] - then - echo "OS Name is Ubuntu" - `apt-get install build-essential module-assistant && m-a prepare -i` - fi - return 0 -} -export PATH=/usr/ucb/bin:/bin:/sbin:/usr/bin:/usr/sbin -(mkdir -p /tmp && cd /tmp && [ ! -f VBoxGuestAdditions_4.1.6.iso ] && curl -q -s -S -L --connect-timeout 10 --max-time 600 --retry 20 -C - -X GET http://download.virtualbox.org/virtualbox/4.1.6/VBoxGuestAdditions_4.1.6.iso >VBoxGuestAdditions_4.1.6.iso) -mount -o loop /tmp/VBoxGuestAdditions_4.1.6.iso /mnt -installGuestAdditions || exit 1 -sh /mnt/VBoxLinuxAdditions.run -umount /mnt -exit 0 From 20ec953fb6b065594b95afd843387dbebd98691f Mon Sep 17 00:00:00 2001 From: andreaturli Date: Sun, 12 Feb 2012 00:55:12 +0000 Subject: [PATCH 3/4] issue 384: GuestAdditionsInstaller - fix scripts --- .../functions/CreateAndInstallVm.java | 12 +- .../predicates/GuestAdditionsInstaller.java | 67 ++++++++ .../functions/installGuestAdditions.sh | 10 ++ .../installModuleAssistantIfNeeded.sh | 4 +- ...st.java => InstallGuestAdditionsTest.java} | 2 +- ...hineFromIsoIfNotAlreadyExistsLiveTest.java | 12 +- .../functions/CreateAndInstallVmLiveTest.java | 2 +- .../GuestAdditionsInstallerLiveTest.java | 143 ++++++++++++++++++ 8 files changed, 243 insertions(+), 9 deletions(-) create mode 100644 labs/virtualbox/src/main/java/org/jclouds/virtualbox/predicates/GuestAdditionsInstaller.java create mode 100644 labs/virtualbox/src/main/resources/functions/installGuestAdditions.sh rename labs/virtualbox/src/test/java/org/jclouds/virtualbox/domain/{GuestAdditionsInstallationTest.java => InstallGuestAdditionsTest.java} (97%) create mode 100644 labs/virtualbox/src/test/java/org/jclouds/virtualbox/predicates/GuestAdditionsInstallerLiveTest.java diff --git a/labs/virtualbox/src/main/java/org/jclouds/virtualbox/functions/CreateAndInstallVm.java b/labs/virtualbox/src/main/java/org/jclouds/virtualbox/functions/CreateAndInstallVm.java index e35dafb531..e93ff50539 100644 --- a/labs/virtualbox/src/main/java/org/jclouds/virtualbox/functions/CreateAndInstallVm.java +++ b/labs/virtualbox/src/main/java/org/jclouds/virtualbox/functions/CreateAndInstallVm.java @@ -24,6 +24,8 @@ import com.google.common.base.Splitter; import com.google.common.base.Supplier; import com.google.common.cache.LoadingCache; import com.google.inject.Inject; + +import org.jclouds.compute.ComputeServiceContext; import org.jclouds.compute.reference.ComputeServiceConstants; import org.jclouds.logging.Logger; import org.jclouds.ssh.SshClient; @@ -32,6 +34,7 @@ import org.jclouds.virtualbox.domain.ExecutionType; import org.jclouds.virtualbox.domain.IsoSpec; import org.jclouds.virtualbox.domain.MasterSpec; import org.jclouds.virtualbox.domain.VmSpec; +import org.jclouds.virtualbox.predicates.GuestAdditionsInstaller; import org.jclouds.virtualbox.util.MachineUtils; import org.virtualbox_4_1.*; @@ -50,7 +53,8 @@ public class CreateAndInstallVm implements Function { @Resource @Named(ComputeServiceConstants.COMPUTE_LOGGER) protected Logger logger = Logger.NULL; - + + private final ComputeServiceContext context; private final Supplier manager; private final CreateAndRegisterMachineFromIsoIfNotAlreadyExists createAndRegisterMachineFromIsoIfNotAlreadyExists; @@ -64,10 +68,11 @@ public class CreateAndInstallVm implements Function { private final MachineUtils machineUtils; @Inject - public CreateAndInstallVm(Supplier manager, + public CreateAndInstallVm(ComputeServiceContext context, Supplier manager, CreateAndRegisterMachineFromIsoIfNotAlreadyExists CreateAndRegisterMachineFromIsoIfNotAlreadyExists, Predicate sshResponds, Function sshClientForIMachine, ExecutionType executionType, MachineUtils machineUtils, @Preconfiguration LoadingCache preConfiguration) { + this.context = context; this.manager = manager; this.createAndRegisterMachineFromIsoIfNotAlreadyExists = CreateAndRegisterMachineFromIsoIfNotAlreadyExists; this.sshResponds = sshResponds; @@ -98,6 +103,9 @@ public class CreateAndInstallVm implements Function { 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); + checkState(new GuestAdditionsInstaller(context).apply(vmName)); logger.debug("<< installation of image complete. Powering down node(%s)", vmName); ensureMachineHasPowerDown(vmName); diff --git a/labs/virtualbox/src/main/java/org/jclouds/virtualbox/predicates/GuestAdditionsInstaller.java b/labs/virtualbox/src/main/java/org/jclouds/virtualbox/predicates/GuestAdditionsInstaller.java new file mode 100644 index 0000000000..05afd85a3a --- /dev/null +++ b/labs/virtualbox/src/main/java/org/jclouds/virtualbox/predicates/GuestAdditionsInstaller.java @@ -0,0 +1,67 @@ +package org.jclouds.virtualbox.predicates; + +import static org.jclouds.compute.options.RunScriptOptions.Builder.runAsRoot; + +import java.util.concurrent.ExecutionException; + +import javax.annotation.Resource; +import javax.inject.Named; +import javax.inject.Singleton; + +import org.jclouds.compute.ComputeServiceContext; +import org.jclouds.compute.RunScriptData; +import org.jclouds.compute.domain.ExecResponse; +import org.jclouds.compute.reference.ComputeServiceConstants; +import org.jclouds.logging.Logger; +import org.jclouds.scriptbuilder.domain.StatementList; +import org.jclouds.scriptbuilder.domain.Statements; +import org.jclouds.virtualbox.statements.InstallGuestAdditions; + +import com.google.common.base.Predicate; +import com.google.common.base.Splitter; +import com.google.common.base.Throwables; +import com.google.common.collect.Iterables; +import com.google.common.util.concurrent.ListenableFuture; +import com.google.inject.Inject; + +@Singleton +public class GuestAdditionsInstaller implements Predicate { + + @Resource + @Named(ComputeServiceConstants.COMPUTE_LOGGER) + protected Logger logger = Logger.NULL; + + private final ComputeServiceContext context; + private String vboxVersion; + + @Inject + public GuestAdditionsInstaller(ComputeServiceContext context) { + this.context = context; + } + + @Override + public boolean apply(String vmName) { + StatementList statementList = prepareStatementList(); + + ListenableFuture execFuture = context.getComputeService().submitScriptOnNode(vmName, statementList, + runAsRoot(true).wrapInInitScript(false)); + ExecResponse execResponse = null; + try { + execResponse = execFuture.get(); + } catch (InterruptedException e) { + Throwables.propagate(e); + } catch (ExecutionException e) { + Throwables.propagate(e); + } + return execResponse == null ? false : execResponse.getExitCode() == 0; + } + + private StatementList prepareStatementList() { + vboxVersion = Iterables.get(Splitter.on('r').split(context.getProviderSpecificContext().getBuildVersion()), 0); + InstallGuestAdditions installGuestAdditions = new InstallGuestAdditions(vboxVersion); + StatementList statementList = new StatementList(Statements.exec(RunScriptData.aptInstallLazyUpgrade("curl")), + installGuestAdditions); + return statementList; + } + +} \ No newline at end of file diff --git a/labs/virtualbox/src/main/resources/functions/installGuestAdditions.sh b/labs/virtualbox/src/main/resources/functions/installGuestAdditions.sh new file mode 100644 index 0000000000..205aa45d92 --- /dev/null +++ b/labs/virtualbox/src/main/resources/functions/installGuestAdditions.sh @@ -0,0 +1,10 @@ +function installGuestAdditions { + unset OSNAME; + local OSNAME=`lsb_release -d -s | cut -d ' ' -f 1`; shift + if [ $OSNAME = 'Ubuntu' ] + then + echo "OS is Ubuntu" + apt-get -f -y -qq --force-yes install build-essential module-assistant && m-a prepare -i + fi + return 0 +} \ No newline at end of file diff --git a/labs/virtualbox/src/main/resources/functions/installModuleAssistantIfNeeded.sh b/labs/virtualbox/src/main/resources/functions/installModuleAssistantIfNeeded.sh index 93e741f357..4852add51e 100644 --- a/labs/virtualbox/src/main/resources/functions/installModuleAssistantIfNeeded.sh +++ b/labs/virtualbox/src/main/resources/functions/installModuleAssistantIfNeeded.sh @@ -4,7 +4,7 @@ function installModuleAssistantIfNeeded { if [ $OSNAME = 'Ubuntu' ] then echo "OS is Ubuntu" - apt-get -f -y -qq --force-yes install build-essential module-assistant && m-a prepare -i + apt-get -f -y -qq --force-yes install build-essential module-assistant; + m-a prepare -i fi - return 0 } \ No newline at end of file diff --git a/labs/virtualbox/src/test/java/org/jclouds/virtualbox/domain/GuestAdditionsInstallationTest.java b/labs/virtualbox/src/test/java/org/jclouds/virtualbox/domain/InstallGuestAdditionsTest.java similarity index 97% rename from labs/virtualbox/src/test/java/org/jclouds/virtualbox/domain/GuestAdditionsInstallationTest.java rename to labs/virtualbox/src/test/java/org/jclouds/virtualbox/domain/InstallGuestAdditionsTest.java index 3f854e50b2..68df010720 100644 --- a/labs/virtualbox/src/test/java/org/jclouds/virtualbox/domain/GuestAdditionsInstallationTest.java +++ b/labs/virtualbox/src/test/java/org/jclouds/virtualbox/domain/InstallGuestAdditionsTest.java @@ -32,7 +32,7 @@ import com.google.common.io.CharStreams; import com.google.common.io.Resources; @Test(groups = "unit") -public class GuestAdditionsInstallationTest { +public class InstallGuestAdditionsTest { @Test public void testUnix() throws IOException { InstallGuestAdditions statement = new InstallGuestAdditions("4.1.6"); diff --git a/labs/virtualbox/src/test/java/org/jclouds/virtualbox/functions/CloneAndRegisterMachineFromIsoIfNotAlreadyExistsLiveTest.java b/labs/virtualbox/src/test/java/org/jclouds/virtualbox/functions/CloneAndRegisterMachineFromIsoIfNotAlreadyExistsLiveTest.java index 92f533a498..c67956d000 100644 --- a/labs/virtualbox/src/test/java/org/jclouds/virtualbox/functions/CloneAndRegisterMachineFromIsoIfNotAlreadyExistsLiveTest.java +++ b/labs/virtualbox/src/test/java/org/jclouds/virtualbox/functions/CloneAndRegisterMachineFromIsoIfNotAlreadyExistsLiveTest.java @@ -23,11 +23,16 @@ import static org.jclouds.virtualbox.config.VirtualBoxConstants.VIRTUALBOX_IMAGE import static org.jclouds.virtualbox.config.VirtualBoxConstants.VIRTUALBOX_INSTALLATION_KEY_SEQUENCE; import static org.testng.Assert.assertEquals; -import com.google.inject.Injector; - import org.jclouds.config.ValueOfConfigurationKeyOrNull; import org.jclouds.virtualbox.BaseVirtualBoxClientLiveTest; -import org.jclouds.virtualbox.domain.*; +import org.jclouds.virtualbox.domain.HardDisk; +import org.jclouds.virtualbox.domain.IsoSpec; +import org.jclouds.virtualbox.domain.MasterSpec; +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.CreateAndRegisterMachineFromIsoIfNotAlreadyExists; import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; import org.virtualbox_4_1.CleanupMode; @@ -38,6 +43,7 @@ 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; /** * @author Andrea Turli diff --git a/labs/virtualbox/src/test/java/org/jclouds/virtualbox/functions/CreateAndInstallVmLiveTest.java b/labs/virtualbox/src/test/java/org/jclouds/virtualbox/functions/CreateAndInstallVmLiveTest.java index 9e2b36d763..362868c1a9 100644 --- a/labs/virtualbox/src/test/java/org/jclouds/virtualbox/functions/CreateAndInstallVmLiveTest.java +++ b/labs/virtualbox/src/test/java/org/jclouds/virtualbox/functions/CreateAndInstallVmLiveTest.java @@ -76,7 +76,7 @@ public class CreateAndInstallVmLiveTest extends BaseVirtualBoxClientLiveTest { .attachISO(0, 0, operatingSystemIso) .attachHardDisk(hardDisk) .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("jclouds-image-create-and-install-vm-test").name(vmName).memoryMB(512).osTypeId("") .controller(ideController) .forceOverwrite(true) .cleanUpMode(CleanupMode.Full).build(); diff --git a/labs/virtualbox/src/test/java/org/jclouds/virtualbox/predicates/GuestAdditionsInstallerLiveTest.java b/labs/virtualbox/src/test/java/org/jclouds/virtualbox/predicates/GuestAdditionsInstallerLiveTest.java new file mode 100644 index 0000000000..4abc0fea20 --- /dev/null +++ b/labs/virtualbox/src/test/java/org/jclouds/virtualbox/predicates/GuestAdditionsInstallerLiveTest.java @@ -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.predicates; + +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 org.jclouds.config.ValueOfConfigurationKeyOrNull; +import org.jclouds.virtualbox.BaseVirtualBoxClientLiveTest; +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.functions.CreateAndInstallVm; +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.IProgress; +import org.virtualbox_4_1.ISession; +import org.virtualbox_4_1.LockType; +import org.virtualbox_4_1.StorageBus; + +import com.google.common.base.CaseFormat; +import com.google.common.base.Function; +import com.google.common.base.Splitter; +import com.google.common.collect.ImmutableSet; +import com.google.inject.Injector; + +/** + * @author Andrea Turli + */ +@Test(groups = "live", singleThreaded = true, testName = "GuestAdditionsInstallerLiveTest") +public class GuestAdditionsInstallerLiveTest extends + BaseVirtualBoxClientLiveTest { + + private MasterSpec sourceMachineSpec; + + @Override + @BeforeClass(groups = "live") + public void setupClient() { + super.setupClient(); + String sourceName = 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).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(); + + Injector injector = context.utils().injector(); + Function configProperties = injector + .getInstance(ValueOfConfigurationKeyOrNull.class); + IsoSpec isoSpec = IsoSpec + .builder() + .sourcePath(operatingSystemIso) + .installationScript( + configProperties.apply(VIRTUALBOX_INSTALLATION_KEY_SEQUENCE) + .replace("HOSTNAME", sourceVmSpec.getVmName())).build(); + + NetworkSpec networkSpec = //NetworkSpec.builder().build(); + NetworkSpec.builder() + .natNetworkAdapter(0, NatAdapter.builder().tcpRedirectRule("127.0.0.1", 2222, "", 22).build()) + .build(); + sourceMachineSpec = MasterSpec.builder().iso(isoSpec).vm(sourceVmSpec).network(networkSpec).build(); + + } + + @Test + public void testGuestAdditionsAreInstalled() throws Exception { + try { + IMachine machine = getVmWithGuestAdditionsInstalled(); + assertTrue(machineUtils.lockSessionOnMachineAndApply(machine.getName(), LockType.Shared, new Function() { + @Override + public Boolean apply(ISession session) { + return session.getMachine().getGuestPropertyValue("/VirtualBox/GuestAdd/Version") != null; + } + })); + } finally { + for (VmSpec spec : ImmutableSet.of( + sourceMachineSpec.getVmSpec())) { + ensureMachineHasPowerDown(spec.getVmName()); + undoVm(spec); + } + } + + } + + 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 void ensureMachineHasPowerDown(String vmName) { + machineUtils.lockSessionOnMachineAndApply(vmName, LockType.Shared, new Function() { + @Override + public Void apply(ISession session) { + IProgress powerDownProgress = session.getConsole().powerDown(); + powerDownProgress.waitForCompletion(-1); + return null; + } + }); + } +} \ No newline at end of file From 40d19e0cf6b4023db53e1a3bf8e44328cc660087 Mon Sep 17 00:00:00 2001 From: andreaturli Date: Sun, 12 Feb 2012 19:20:41 +0000 Subject: [PATCH 4/4] issue 384: GuestAdditions installer - jclouds comments addressed --- .../virtualbox/statements/GuestAdditionsInstaller.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/labs/virtualbox/src/test/java/org/jclouds/virtualbox/statements/GuestAdditionsInstaller.java b/labs/virtualbox/src/test/java/org/jclouds/virtualbox/statements/GuestAdditionsInstaller.java index 36fbba812a..77e37c309c 100644 --- a/labs/virtualbox/src/test/java/org/jclouds/virtualbox/statements/GuestAdditionsInstaller.java +++ b/labs/virtualbox/src/test/java/org/jclouds/virtualbox/statements/GuestAdditionsInstaller.java @@ -30,6 +30,7 @@ import org.virtualbox_4_1.VirtualBoxManager; import com.google.common.base.Function; import com.google.common.base.Predicate; import com.google.common.base.Supplier; +import com.google.common.base.Throwables; import com.google.common.util.concurrent.ListenableFuture; import com.google.inject.Inject; @@ -77,9 +78,9 @@ public class GuestAdditionsInstaller implements Function { try { execFuture.get(); } catch (InterruptedException e) { - e.printStackTrace(); + Throwables.propagate(e); } catch (ExecutionException e) { - e.printStackTrace(); + Throwables.propagate(e); } return vm; }