issue 384: GuestAdditionsInstaller

This commit is contained in:
andreaturli 2012-02-05 23:05:15 +00:00
parent 64a1593c0c
commit 623f3c6daa
8 changed files with 229 additions and 20 deletions

View File

@ -27,7 +27,7 @@ package org.jclouds.virtualbox.config;
*/ */
public interface VirtualBoxConstants { 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"; public static final String VIRTUALBOX_PRECONFIGURATION_URL = "jclouds.virtualbox.preconfigurationurl";

View File

@ -75,7 +75,6 @@ public class CreateAndInstallVm implements Function<MasterSpec, IMachine> {
this.executionType = executionType; this.executionType = executionType;
this.machineUtils = machineUtils; this.machineUtils = machineUtils;
this.preConfiguration = preConfiguration; this.preConfiguration = preConfiguration;
} }
@Override @Override

View File

@ -35,6 +35,7 @@ import org.jclouds.compute.domain.Processor;
import org.jclouds.compute.reference.ComputeServiceConstants; import org.jclouds.compute.reference.ComputeServiceConstants;
import org.jclouds.domain.LocationBuilder; import org.jclouds.domain.LocationBuilder;
import org.jclouds.domain.LocationScope; import org.jclouds.domain.LocationScope;
import org.jclouds.domain.LoginCredentials;
import org.jclouds.javax.annotation.Nullable; import org.jclouds.javax.annotation.Nullable;
import org.jclouds.logging.Logger; import org.jclouds.logging.Logger;
import org.virtualbox_4_1.IMachine; import org.virtualbox_4_1.IMachine;
@ -104,8 +105,8 @@ public class IMachineToNodeMetadata implements Function<IMachine, NodeMetadata>
} }
} }
// nodeMetadataBuilder.imageId(""); LoginCredentials loginCredentials = new LoginCredentials("toor", "password", null, true);
// nodeMetadataBuilder.group(""); nodeMetadataBuilder.credentials(loginCredentials);
return nodeMetadataBuilder.build(); return nodeMetadataBuilder.build();
} }

View File

@ -61,13 +61,14 @@ public class InstallGuestAdditions implements Statement {
String vboxGuestAdditionsIso = "VBoxGuestAdditions_" + vboxVersion + ".iso"; String vboxGuestAdditionsIso = "VBoxGuestAdditions_" + vboxVersion + ".iso";
ScriptBuilder scriptBuilder = new ScriptBuilder() ScriptBuilder scriptBuilder = new ScriptBuilder()
.addStatement( .addStatement(
new SaveHttpResponseTo("{tmp}", vboxGuestAdditionsIso, "GET", URI new SaveHttpResponseTo("{tmp}{fs}", vboxGuestAdditionsIso, "GET", URI
.create("http://download.virtualbox.org/virtualbox/" + vboxVersion + "/" .create("http://download.virtualbox.org/virtualbox/" + vboxVersion + "/"
+ vboxGuestAdditionsIso), ImmutableMultimap.<String, String> of())) + vboxGuestAdditionsIso), ImmutableMultimap.<String, String> of()))
.addStatement(exec(String.format("mount -o loop {tmp}{fs}%s %s", vboxGuestAdditionsIso, mountPoint))) .addStatement(exec(String.format("mount -o loop {tmp}{fs}%s %s", vboxGuestAdditionsIso, mountPoint)))
.addStatement(call("installGuestAdditions")) .addStatement(call("installGuestAdditions"))
.addStatement(exec(String.format("sh %s%s", mountPoint, "/VBoxLinuxAdditions.run"))) .addStatement(exec(String.format("sh %s%s", mountPoint, "/VBoxLinuxAdditions.run")))
.addStatement(exec(String.format("umount %s", mountPoint))); .addStatement(exec(String.format("umount %s", mountPoint)));
return scriptBuilder.render(family); return scriptBuilder.render(family);
} }

View File

@ -1,14 +1,10 @@
function installGuestAdditions { function installGuestAdditions {
unset OSNAME; unset OSNAME;
[ $# -eq 1 ] || {
abort "installGuestAdditions requires virtual machine name parameter"
return 1
}
local OSNAME=`lsb_release -d -s | cut -d ' ' -f 1`; shift local OSNAME=`lsb_release -d -s | cut -d ' ' -f 1`; shift
if [ $OSNAME = 'Ubuntu' ] if [ $OSNAME = 'Ubuntu' ]
then then
echo "OS Name is Ubuntu" echo "OS is Ubuntu"
`apt-get 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 fi
return 0 return 0
} }

View File

@ -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<String, IMachine> {
@Resource
@Named(ComputeServiceConstants.COMPUTE_LOGGER)
protected Logger logger = Logger.NULL;
private final ComputeServiceContext context;
private final Supplier<VirtualBoxManager> 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<VirtualBoxManager> manager,
CreateAndRegisterMachineFromIsoIfNotAlreadyExists createAndRegisterMachineFromIsoIfNotAlreadyExists,
Predicate<SshClient> installGuestAdditionsViaSshResponds, Function<IMachine, SshClient> sshClientForIMachine,
ExecutionType executionType, MachineUtils machineUtils, Factory runScriptOnNodeFactory,
Supplier<NodeMetadata> 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, ""));
}
}

View File

@ -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);
}
}

View File

@ -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<String> 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.<String, String> 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);
}
}