From 623f3c6daa33842acfc72d1df839eaa6ea8792db Mon Sep 17 00:00:00 2001 From: andreaturli Date: Sun, 5 Feb 2012 23:05:15 +0000 Subject: [PATCH] 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); + } + +}