From 31cf2319653f88158d686ef5ef3e17820ab1bf8e Mon Sep 17 00:00:00 2001 From: Andrea Turli Date: Mon, 9 Jan 2012 17:17:05 +0000 Subject: [PATCH 1/2] issue 384: create Mutatemachine --- .../virtualbox/functions/MutateMachine.java | 143 ++++++++++++++++++ 1 file changed, 143 insertions(+) create mode 100644 sandbox-apis/virtualbox/src/main/java/org/jclouds/virtualbox/functions/MutateMachine.java diff --git a/sandbox-apis/virtualbox/src/main/java/org/jclouds/virtualbox/functions/MutateMachine.java b/sandbox-apis/virtualbox/src/main/java/org/jclouds/virtualbox/functions/MutateMachine.java new file mode 100644 index 0000000000..a62c6a8a36 --- /dev/null +++ b/sandbox-apis/virtualbox/src/main/java/org/jclouds/virtualbox/functions/MutateMachine.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.functions; + +import static com.google.common.base.Preconditions.checkState; +import static org.jclouds.compute.options.RunScriptOptions.Builder.runAsRoot; +import static org.jclouds.virtualbox.config.VirtualBoxConstants.VIRTUALBOX_INSTALLATION_KEY_SEQUENCE; +import static org.jclouds.virtualbox.util.MachineUtils.applyForMachine; +import static org.jclouds.virtualbox.util.MachineUtils.lockSessionOnMachineAndApply; +import static org.virtualbox_4_1.LockType.Shared; + +import java.net.URI; + +import javax.annotation.Resource; +import javax.inject.Named; +import javax.inject.Singleton; + +import org.jclouds.compute.callables.RunScriptOnNode; +import org.jclouds.compute.callables.RunScriptOnNode.Factory; +import org.jclouds.compute.domain.NodeMetadata; +import org.jclouds.compute.reference.ComputeServiceConstants; +import org.jclouds.config.ValueOfConfigurationKeyOrNull; +import org.jclouds.logging.Logger; +import org.jclouds.scriptbuilder.domain.Statements; +import org.jclouds.ssh.SshClient; +import org.jclouds.util.Throwables2; +import org.jclouds.virtualbox.Preconfiguration; +import org.jclouds.virtualbox.domain.ExecutionType; +import org.jclouds.virtualbox.domain.VmSpec; +import org.jclouds.virtualbox.settings.KeyboardScancodes; +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.VBoxException; +import org.virtualbox_4_1.VirtualBoxManager; + +import com.google.common.base.Function; +import com.google.common.base.Functions; +import com.google.common.base.Predicate; +import com.google.common.base.Supplier; +import com.google.inject.Inject; + +@Singleton +public class MutateMachine implements Function { + + @Resource + @Named(ComputeServiceConstants.COMPUTE_LOGGER) + protected Logger logger = Logger.NULL; + + private final Supplier manager; + private final CreateAndRegisterMachineFromIsoIfNotAlreadyExists createAndRegisterMachineFromIsoIfNotAlreadyExists; + private final ValueOfConfigurationKeyOrNull valueOfConfigurationKeyOrNull; + + private final Supplier preconfiguration; + private final Predicate sshResponds; + private final ExecutionType executionType; + + private final Factory scriptRunner; + private final Supplier host; + + private final Function sshClientForIMachine; + + @Inject + public MutateMachine(Supplier manager, + CreateAndRegisterMachineFromIsoIfNotAlreadyExists CreateAndRegisterMachineFromIsoIfNotAlreadyExists, + ValueOfConfigurationKeyOrNull valueOfConfigurationKeyOrNull, Predicate sshResponds, + Function sshClientForIMachine, Supplier host, + RunScriptOnNode.Factory scriptRunner, @Preconfiguration Supplier preconfiguration, + ExecutionType executionType) { + this.manager = manager; + this.createAndRegisterMachineFromIsoIfNotAlreadyExists = CreateAndRegisterMachineFromIsoIfNotAlreadyExists; + this.valueOfConfigurationKeyOrNull = valueOfConfigurationKeyOrNull; + this.sshResponds = sshResponds; + this.sshClientForIMachine = sshClientForIMachine; + this.scriptRunner = scriptRunner; + this.host = host; + this.preconfiguration = preconfiguration; + this.executionType = executionType; + } + + @Override + public IMachine apply(String machineId) { + return lockMachineAndApply(manager.get(), LockType.Write, machineId); + } + + /** + * Locks the machine and executes the given function using the machine matching the given id. + * Since the machine is locked it is possible to perform some modifications to the IMachine. + *

+ * Unlocks the machine before returning. + * + * @param manager the VirtualBoxManager + * @param type the kind of lock to use when initially locking the machine. + * @param machineId the id of the machine + * @return the locked machine. + */ + public static IMachine lockMachineAndApply(VirtualBoxManager manager, final LockType type, final String machineId) { + return lockSessionOnMachineAndReturn(manager, type, machineId); + } + + /** + * Locks the machine and executes the given function using the current session. + * Since the machine is locked it is possible to perform some modifications to the IMachine. + *

+ * Unlocks the machine before returning. + * + * @param manager the VirtualBoxManager + * @param type the kind of lock to use when initially locking the machine. + * @param machineId the id of the machine + * @return the result from applying the function to the session. + */ + public static IMachine lockSessionOnMachineAndReturn(VirtualBoxManager manager, LockType type, String machineId) { + try { + ISession session = manager.getSessionObject(); + IMachine immutableMachine = manager.getVBox().findMachine(machineId); + immutableMachine.lockMachine(session, type); + return immutableMachine; + } catch (VBoxException e) { + throw new RuntimeException(String.format("error locking %s with %s lock: %s", machineId, + type, e.getMessage()), e); + } + } + + +} From b82d68d9fd82b671654847335acf0117fdb5ced8 Mon Sep 17 00:00:00 2001 From: andreaturli Date: Wed, 11 Jan 2012 00:19:29 +0000 Subject: [PATCH 2/2] issue 384: change MachineUtils to use MutableMachine function --- .../VirtualBoxPropertiesBuilder.java | 2 +- ...VirtualBoxComputeServiceContextModule.java | 5 +- .../functions/CreateAndInstallVm.java | 78 ++++-- .../virtualbox/functions/MutableMachine.java | 85 +++++++ .../virtualbox/functions/MutateMachine.java | 143 ----------- .../jclouds/virtualbox/util/MachineUtils.java | 230 ++++++++++++------ .../BaseVirtualBoxClientLiveTest.java | 8 +- 7 files changed, 308 insertions(+), 243 deletions(-) create mode 100644 sandbox-apis/virtualbox/src/main/java/org/jclouds/virtualbox/functions/MutableMachine.java delete mode 100644 sandbox-apis/virtualbox/src/main/java/org/jclouds/virtualbox/functions/MutateMachine.java diff --git a/sandbox-apis/virtualbox/src/main/java/org/jclouds/virtualbox/VirtualBoxPropertiesBuilder.java b/sandbox-apis/virtualbox/src/main/java/org/jclouds/virtualbox/VirtualBoxPropertiesBuilder.java index 32478e6de1..7b2014b818 100644 --- a/sandbox-apis/virtualbox/src/main/java/org/jclouds/virtualbox/VirtualBoxPropertiesBuilder.java +++ b/sandbox-apis/virtualbox/src/main/java/org/jclouds/virtualbox/VirtualBoxPropertiesBuilder.java @@ -57,7 +57,7 @@ public class VirtualBoxPropertiesBuilder extends PropertiesBuilder { properties.put(PROPERTY_IDENTITY, "administrator"); properties.put(PROPERTY_CREDENTIAL, "12345"); - properties.put(PROPERTY_IMAGE_ID, "ubuntu-10.04.3-server-i386"); + properties.put(PROPERTY_IMAGE_ID, "ubuntu-11.04-server-i386"); properties.put(PROPERTY_IMAGE_LOGIN_USER, "toor:password"); properties.put(PROPERTY_IMAGE_AUTHENTICATE_SUDO, "true"); diff --git a/sandbox-apis/virtualbox/src/main/java/org/jclouds/virtualbox/config/VirtualBoxComputeServiceContextModule.java b/sandbox-apis/virtualbox/src/main/java/org/jclouds/virtualbox/config/VirtualBoxComputeServiceContextModule.java index 5be0bb62ca..27fbc46fd3 100644 --- a/sandbox-apis/virtualbox/src/main/java/org/jclouds/virtualbox/config/VirtualBoxComputeServiceContextModule.java +++ b/sandbox-apis/virtualbox/src/main/java/org/jclouds/virtualbox/config/VirtualBoxComputeServiceContextModule.java @@ -54,6 +54,7 @@ import org.jclouds.virtualbox.functions.admin.StartJettyIfNotAlreadyRunning; import org.jclouds.virtualbox.functions.admin.StartVBoxIfNotAlreadyRunning; import org.jclouds.virtualbox.predicates.SshResponds; import org.virtualbox_4_1.IMachine; +import org.virtualbox_4_1.LockType; import org.virtualbox_4_1.MachineState; import org.virtualbox_4_1.VirtualBoxManager; @@ -106,7 +107,9 @@ public class VirtualBoxComputeServiceContextModule extends bind(new TypeLiteral>() { }).to(IMachineToSshClient.class); - bind(ExecutionType.class).toInstance(ExecutionType.HEADLESS); + bind(ExecutionType.class).toInstance(ExecutionType.GUI); + bind(LockType.class).toInstance(LockType.Write); + } @Provides diff --git a/sandbox-apis/virtualbox/src/main/java/org/jclouds/virtualbox/functions/CreateAndInstallVm.java b/sandbox-apis/virtualbox/src/main/java/org/jclouds/virtualbox/functions/CreateAndInstallVm.java index e5c08a3e10..1687d984a5 100644 --- a/sandbox-apis/virtualbox/src/main/java/org/jclouds/virtualbox/functions/CreateAndInstallVm.java +++ b/sandbox-apis/virtualbox/src/main/java/org/jclouds/virtualbox/functions/CreateAndInstallVm.java @@ -27,6 +27,7 @@ import static org.jclouds.virtualbox.util.MachineUtils.lockSessionOnMachineAndAp import static org.virtualbox_4_1.LockType.Shared; import java.net.URI; +import java.util.List; import javax.annotation.Resource; import javax.inject.Named; @@ -51,7 +52,10 @@ import org.virtualbox_4_1.VirtualBoxManager; import com.google.common.base.Function; import com.google.common.base.Predicate; +import com.google.common.base.Splitter; import com.google.common.base.Supplier; +import com.google.common.collect.Iterables; +import com.google.common.collect.Lists; import com.google.inject.Inject; @Singleton @@ -75,12 +79,15 @@ public class CreateAndInstallVm implements Function { private final Function sshClientForIMachine; @Inject - public CreateAndInstallVm(Supplier manager, - CreateAndRegisterMachineFromIsoIfNotAlreadyExists CreateAndRegisterMachineFromIsoIfNotAlreadyExists, - ValueOfConfigurationKeyOrNull valueOfConfigurationKeyOrNull, Predicate sshResponds, - Function sshClientForIMachine, Supplier host, - RunScriptOnNode.Factory scriptRunner, @Preconfiguration Supplier preconfiguration, - ExecutionType executionType) { + public CreateAndInstallVm( + Supplier manager, + CreateAndRegisterMachineFromIsoIfNotAlreadyExists CreateAndRegisterMachineFromIsoIfNotAlreadyExists, + ValueOfConfigurationKeyOrNull valueOfConfigurationKeyOrNull, + Predicate sshResponds, + Function sshClientForIMachine, + Supplier host, RunScriptOnNode.Factory scriptRunner, + @Preconfiguration Supplier preconfiguration, + ExecutionType executionType) { this.manager = manager; this.createAndRegisterMachineFromIsoIfNotAlreadyExists = CreateAndRegisterMachineFromIsoIfNotAlreadyExists; this.valueOfConfigurationKeyOrNull = valueOfConfigurationKeyOrNull; @@ -98,10 +105,14 @@ public class CreateAndInstallVm implements Function { // note this may not be reachable, as this likely uses the 10.2.2 address URI preconfigurationUri = preconfiguration.get(); - String keySequence = valueOfConfigurationKeyOrNull.apply(VIRTUALBOX_INSTALLATION_KEY_SEQUENCE).replace( - "PRECONFIGURATION_URL", preconfigurationUri.toASCIIString()).replace("HOSTNAME", vmName); + String keySequence = valueOfConfigurationKeyOrNull + .apply(VIRTUALBOX_INSTALLATION_KEY_SEQUENCE) + .replace("PRECONFIGURATION_URL", + preconfigurationUri.toASCIIString()) + .replace("HOSTNAME", vmName); - final IMachine vm = createAndRegisterMachineFromIsoIfNotAlreadyExists.apply(vmSpec); + final IMachine vm = createAndRegisterMachineFromIsoIfNotAlreadyExists + .apply(vmSpec); // Launch machine and wait for it to come online ensureMachineIsLaunched(vmName); @@ -111,24 +122,30 @@ public class CreateAndInstallVm implements Function { SshClient client = sshClientForIMachine.apply(vm); 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); + checkState(sshResponds.apply(client), + "timed out waiting for guest %s to be accessible via ssh", vmName); - logger.debug("<< installation of image complete. Powering down node(%s)", vmName); - lockSessionOnMachineAndApply(manager.get(), Shared, vmName, new Function() { + logger.debug("<< installation of image complete. Powering down node(%s)", + vmName); + lockSessionOnMachineAndApply(manager.get(), Shared, vmName, + new Function() { - @Override - public Void apply(ISession session) { - IProgress powerDownProgress = session.getConsole().powerDown(); - powerDownProgress.waitForCompletion(-1); - return null; - } + @Override + public Void apply(ISession session) { + IProgress powerDownProgress = session.getConsole() + .powerDown(); + powerDownProgress.waitForCompletion(-1); + return null; + } - }); + }); return vm; } - private void ensureMachineIsLaunched(String vmName) { - applyForMachine(manager.get(), vmName, new LaunchMachineIfNotAlreadyRunning(manager.get(), executionType, "")); + private void ensureMachineIsLaunched(String vmName) { + applyForMachine(manager.get(), vmName, + new LaunchMachineIfNotAlreadyRunning(manager.get(), executionType, + "")); } private void sendKeyboardSequence(String keyboardSequence, String vmName) { @@ -137,16 +154,20 @@ public class CreateAndInstallVm implements Function { for (String line : splitSequence) { String converted = stringToKeycode(line); for (String word : converted.split(" ")) { - sb.append("vboxmanage controlvm ").append(vmName).append(" keyboardputscancode ").append(word).append("; "); + sb.append("vboxmanage controlvm ").append(vmName) + .append(" keyboardputscancode ").append(word).append("; "); runScriptIfWordEndsWith(sb, word, ""); runScriptIfWordEndsWith(sb, word, ""); } } } - private void runScriptIfWordEndsWith(StringBuilder sb, String word, String key) { + private void runScriptIfWordEndsWith(StringBuilder sb, String word, + String key) { if (word.endsWith(KeyboardScancodes.SPECIAL_KEYBOARD_BUTTON_MAP.get(key))) { - scriptRunner.create(host.get(), Statements.exec(sb.toString()), runAsRoot(false).wrapInInitScript(false)).init().call(); + scriptRunner + .create(host.get(), Statements.exec(sb.toString()), + runAsRoot(false).wrapInInitScript(false)).init().call(); sb.delete(0, sb.length() - 1); } } @@ -156,7 +177,9 @@ public class CreateAndInstallVm implements Function { if (s.startsWith("<")) { String[] specials = s.split("<"); for (int i = 1; i < specials.length; i++) { - keycodes.append(KeyboardScancodes.SPECIAL_KEYBOARD_BUTTON_MAP.get("<" + specials[i])).append(" "); + keycodes.append( + KeyboardScancodes.SPECIAL_KEYBOARD_BUTTON_MAP.get("<" + + specials[i])).append(" "); } return keycodes.toString(); } @@ -170,8 +193,11 @@ public class CreateAndInstallVm implements Function { keycodes.append(" "); i++; } - keycodes.append(KeyboardScancodes.SPECIAL_KEYBOARD_BUTTON_MAP.get("")).append(" "); + keycodes.append( + KeyboardScancodes.SPECIAL_KEYBOARD_BUTTON_MAP.get("")) + .append(" "); return keycodes.toString(); } + } diff --git a/sandbox-apis/virtualbox/src/main/java/org/jclouds/virtualbox/functions/MutableMachine.java b/sandbox-apis/virtualbox/src/main/java/org/jclouds/virtualbox/functions/MutableMachine.java new file mode 100644 index 0000000000..409bdebb53 --- /dev/null +++ b/sandbox-apis/virtualbox/src/main/java/org/jclouds/virtualbox/functions/MutableMachine.java @@ -0,0 +1,85 @@ +/* + * 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.functions; + +import javax.annotation.Resource; +import javax.inject.Named; +import javax.inject.Singleton; + +import org.jclouds.compute.reference.ComputeServiceConstants; +import org.jclouds.logging.Logger; +import org.virtualbox_4_1.IMachine; +import org.virtualbox_4_1.ISession; +import org.virtualbox_4_1.LockType; +import org.virtualbox_4_1.VBoxException; +import org.virtualbox_4_1.VirtualBoxManager; + +import com.google.common.base.Function; +import com.google.common.base.Supplier; +import com.google.inject.Inject; + +@Singleton +public class MutableMachine implements Function { + + @Resource + @Named(ComputeServiceConstants.COMPUTE_LOGGER) + protected Logger logger = Logger.NULL; + + private final Supplier manager; + private final LockType lockType; + + + @Inject + public MutableMachine(Supplier manager, + LockType lockType) { + this.manager = manager; + this.lockType = lockType; + } + + @Override + public IMachine apply(String machineId) { + return lockSessionOnMachineAndReturn(manager.get(), lockType, machineId); + } + + /** + * Locks the machine and executes the given function using the current session. + * Since the machine is locked it is possible to perform some modifications to the IMachine. + *

+ * Unlocks the machine before returning. + * + * @param manager the VirtualBoxManager + * @param type the kind of lock to use when initially locking the machine. + * @param machineId the id of the machine + * @return the result from applying the function to the session. + */ + public static IMachine lockSessionOnMachineAndReturn(VirtualBoxManager manager, LockType type, String machineId) { + try { + ISession session = manager.getSessionObject(); + IMachine immutableMachine = manager.getVBox().findMachine(machineId); + immutableMachine.lockMachine(session, type); + return immutableMachine; + } catch (VBoxException e) { + throw new RuntimeException(String.format("error locking %s with %s lock: %s", machineId, + type, e.getMessage()), e); + } + } + + +} diff --git a/sandbox-apis/virtualbox/src/main/java/org/jclouds/virtualbox/functions/MutateMachine.java b/sandbox-apis/virtualbox/src/main/java/org/jclouds/virtualbox/functions/MutateMachine.java deleted file mode 100644 index a62c6a8a36..0000000000 --- a/sandbox-apis/virtualbox/src/main/java/org/jclouds/virtualbox/functions/MutateMachine.java +++ /dev/null @@ -1,143 +0,0 @@ -/* - * 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.functions; - -import static com.google.common.base.Preconditions.checkState; -import static org.jclouds.compute.options.RunScriptOptions.Builder.runAsRoot; -import static org.jclouds.virtualbox.config.VirtualBoxConstants.VIRTUALBOX_INSTALLATION_KEY_SEQUENCE; -import static org.jclouds.virtualbox.util.MachineUtils.applyForMachine; -import static org.jclouds.virtualbox.util.MachineUtils.lockSessionOnMachineAndApply; -import static org.virtualbox_4_1.LockType.Shared; - -import java.net.URI; - -import javax.annotation.Resource; -import javax.inject.Named; -import javax.inject.Singleton; - -import org.jclouds.compute.callables.RunScriptOnNode; -import org.jclouds.compute.callables.RunScriptOnNode.Factory; -import org.jclouds.compute.domain.NodeMetadata; -import org.jclouds.compute.reference.ComputeServiceConstants; -import org.jclouds.config.ValueOfConfigurationKeyOrNull; -import org.jclouds.logging.Logger; -import org.jclouds.scriptbuilder.domain.Statements; -import org.jclouds.ssh.SshClient; -import org.jclouds.util.Throwables2; -import org.jclouds.virtualbox.Preconfiguration; -import org.jclouds.virtualbox.domain.ExecutionType; -import org.jclouds.virtualbox.domain.VmSpec; -import org.jclouds.virtualbox.settings.KeyboardScancodes; -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.VBoxException; -import org.virtualbox_4_1.VirtualBoxManager; - -import com.google.common.base.Function; -import com.google.common.base.Functions; -import com.google.common.base.Predicate; -import com.google.common.base.Supplier; -import com.google.inject.Inject; - -@Singleton -public class MutateMachine implements Function { - - @Resource - @Named(ComputeServiceConstants.COMPUTE_LOGGER) - protected Logger logger = Logger.NULL; - - private final Supplier manager; - private final CreateAndRegisterMachineFromIsoIfNotAlreadyExists createAndRegisterMachineFromIsoIfNotAlreadyExists; - private final ValueOfConfigurationKeyOrNull valueOfConfigurationKeyOrNull; - - private final Supplier preconfiguration; - private final Predicate sshResponds; - private final ExecutionType executionType; - - private final Factory scriptRunner; - private final Supplier host; - - private final Function sshClientForIMachine; - - @Inject - public MutateMachine(Supplier manager, - CreateAndRegisterMachineFromIsoIfNotAlreadyExists CreateAndRegisterMachineFromIsoIfNotAlreadyExists, - ValueOfConfigurationKeyOrNull valueOfConfigurationKeyOrNull, Predicate sshResponds, - Function sshClientForIMachine, Supplier host, - RunScriptOnNode.Factory scriptRunner, @Preconfiguration Supplier preconfiguration, - ExecutionType executionType) { - this.manager = manager; - this.createAndRegisterMachineFromIsoIfNotAlreadyExists = CreateAndRegisterMachineFromIsoIfNotAlreadyExists; - this.valueOfConfigurationKeyOrNull = valueOfConfigurationKeyOrNull; - this.sshResponds = sshResponds; - this.sshClientForIMachine = sshClientForIMachine; - this.scriptRunner = scriptRunner; - this.host = host; - this.preconfiguration = preconfiguration; - this.executionType = executionType; - } - - @Override - public IMachine apply(String machineId) { - return lockMachineAndApply(manager.get(), LockType.Write, machineId); - } - - /** - * Locks the machine and executes the given function using the machine matching the given id. - * Since the machine is locked it is possible to perform some modifications to the IMachine. - *

- * Unlocks the machine before returning. - * - * @param manager the VirtualBoxManager - * @param type the kind of lock to use when initially locking the machine. - * @param machineId the id of the machine - * @return the locked machine. - */ - public static IMachine lockMachineAndApply(VirtualBoxManager manager, final LockType type, final String machineId) { - return lockSessionOnMachineAndReturn(manager, type, machineId); - } - - /** - * Locks the machine and executes the given function using the current session. - * Since the machine is locked it is possible to perform some modifications to the IMachine. - *

- * Unlocks the machine before returning. - * - * @param manager the VirtualBoxManager - * @param type the kind of lock to use when initially locking the machine. - * @param machineId the id of the machine - * @return the result from applying the function to the session. - */ - public static IMachine lockSessionOnMachineAndReturn(VirtualBoxManager manager, LockType type, String machineId) { - try { - ISession session = manager.getSessionObject(); - IMachine immutableMachine = manager.getVBox().findMachine(machineId); - immutableMachine.lockMachine(session, type); - return immutableMachine; - } catch (VBoxException e) { - throw new RuntimeException(String.format("error locking %s with %s lock: %s", machineId, - type, e.getMessage()), e); - } - } - - -} diff --git a/sandbox-apis/virtualbox/src/main/java/org/jclouds/virtualbox/util/MachineUtils.java b/sandbox-apis/virtualbox/src/main/java/org/jclouds/virtualbox/util/MachineUtils.java index 46f51196c3..7417a9b8a4 100644 --- a/sandbox-apis/virtualbox/src/main/java/org/jclouds/virtualbox/util/MachineUtils.java +++ b/sandbox-apis/virtualbox/src/main/java/org/jclouds/virtualbox/util/MachineUtils.java @@ -23,9 +23,22 @@ import static org.jclouds.scriptbuilder.domain.Statements.call; import static org.jclouds.scriptbuilder.domain.Statements.findPid; import static org.jclouds.scriptbuilder.domain.Statements.kill; import static org.jclouds.scriptbuilder.domain.Statements.newStatementList; +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.callables.RunScriptOnNode; +import org.jclouds.compute.callables.RunScriptOnNode.Factory; +import org.jclouds.compute.domain.NodeMetadata; +import org.jclouds.compute.reference.ComputeServiceConstants; +import org.jclouds.logging.Logger; +import org.jclouds.scriptbuilder.domain.OsFamily; import org.jclouds.scriptbuilder.domain.Statement; +import org.jclouds.scriptbuilder.domain.Statements; import org.jclouds.util.Throwables2; +import org.jclouds.virtualbox.functions.MutableMachine; import org.virtualbox_4_1.IMachine; import org.virtualbox_4_1.ISession; import org.virtualbox_4_1.LockType; @@ -34,16 +47,61 @@ import org.virtualbox_4_1.VBoxException; import org.virtualbox_4_1.VirtualBoxManager; import com.google.common.base.Function; +import com.google.common.base.Functions; +import com.google.common.base.Supplier; +import com.google.inject.Inject; /** * Utilities for executing functions on a VirtualBox machine. - * - * @author Adrian Cole, Mattias Holmqvist + * + * @author Adrian Cole, Mattias Holmqvist, Andrea Turli */ + +@Singleton public class MachineUtils { - public static T applyForMachine(VirtualBoxManager manager, final String machineId, final Function function) { - final IMachine immutableMachine = manager.getVBox().findMachine(machineId); + @Resource + @Named(ComputeServiceConstants.COMPUTE_LOGGER) + protected Logger logger = Logger.NULL; + + private final Supplier manager; + private final LockType lockType; + private final Factory scriptRunner; + private final Supplier host; + + @Inject + public MachineUtils(Supplier manager, LockType lockType, RunScriptOnNode.Factory scriptRunner, Supplier host) { + super(); + this.manager = manager; + this.lockType = lockType; + this.scriptRunner = scriptRunner; + this.host = host; + } + + public Function mutateMachine(String machineId, + Function function) { + try { + return Functions.compose(function, new MutableMachine(manager, lockType)); + } finally { + unlockMachine(machineId); + } + } + + protected void unlockMachine(final String machineId) { + IMachine immutableMachine = manager.get().getVBox().findMachine(machineId); + if (immutableMachine.getSessionState().equals(SessionState.Locked)) { + Statement kill = newStatementList(call("default"), + findPid(immutableMachine.getSessionPid().toString()), kill()); + scriptRunner + .create(host.get(), kill, + runAsRoot(false).wrapInInitScript(false)).init().call(); + } + } + + public static T applyForMachine(VirtualBoxManager manager, + final String machineId, final Function function) { + final IMachine immutableMachine = manager.getVBox() + .findMachine(machineId); return new Function() { @Override public T apply(IMachine machine) { @@ -58,48 +116,60 @@ public class MachineUtils { } /** - * Locks the machine and executes the given function using the machine matching the given id. - * Since the machine is locked it is possible to perform some modifications to the IMachine. + * Locks the machine and executes the given function using the machine + * matching the given id. Since the machine is locked it is possible to + * perform some modifications to the IMachine. *

* Unlocks the machine before returning. - * - * @param manager the VirtualBoxManager - * @param type the kind of lock to use when initially locking the machine. - * @param machineId the id of the machine - * @param function the function to execute + * + * @param manager + * the VirtualBoxManager + * @param type + * the kind of lock to use when initially locking the machine. + * @param machineId + * the id of the machine + * @param function + * the function to execute * @return the result from applying the function to the machine. */ - public static T lockMachineAndApply(VirtualBoxManager manager, final LockType type, final String machineId, - final Function function) { - return lockSessionOnMachineAndApply(manager, type, machineId, new Function() { + public static T lockMachineAndApply(VirtualBoxManager manager, + final LockType type, final String machineId, + final Function function) { + return lockSessionOnMachineAndApply(manager, type, machineId, + new Function() { - @Override - public T apply(ISession session) { - return function.apply(session.getMachine()); - } + @Override + public T apply(ISession session) { + return function.apply(session.getMachine()); + } - @Override - public String toString() { - return function.toString(); - } + @Override + public String toString() { + return function.toString(); + } - }); + }); } - + /** - * Locks the machine and executes the given function using the current session. - * Since the machine is locked it is possible to perform some modifications to the IMachine. + * Locks the machine and executes the given function using the current + * session. Since the machine is locked it is possible to perform some + * modifications to the IMachine. *

* Unlocks the machine before returning. - * - * @param manager the VirtualBoxManager - * @param type the kind of lock to use when initially locking the machine. - * @param machineId the id of the machine - * @param function the function to execute + * + * @param manager + * the VirtualBoxManager + * @param type + * the kind of lock to use when initially locking the machine. + * @param machineId + * the id of the machine + * @param function + * the function to execute * @return the result from applying the function to the session. */ - public static T lockSessionOnMachineAndApply(VirtualBoxManager manager, LockType type, String machineId, - Function function) { + public static T lockSessionOnMachineAndApply(VirtualBoxManager manager, + LockType type, String machineId, Function function) { try { ISession session = manager.getSessionObject(); IMachine immutableMachine = manager.getVBox().findMachine(machineId); @@ -110,42 +180,52 @@ public class MachineUtils { session.unlockMachine(); } } catch (VBoxException e) { - throw new RuntimeException(String.format("error applying %s to %s with %s lock: %s", function, machineId, - type, e.getMessage()), e); + throw new RuntimeException(String.format( + "error applying %s to %s with %s lock: %s", function, machineId, + type, e.getMessage()), e); } } - + /** - * Locks the machine and executes the given function using the current session, if the machine is registered. - * Since the machine is locked it is possible to perform some modifications to the IMachine. + * Locks the machine and executes the given function using the current + * session, if the machine is registered. Since the machine is locked it is + * possible to perform some modifications to the IMachine. *

* Unlocks the machine before returning. - * - * @param manager the VirtualBoxManager - * @param type the kind of lock to use when initially locking the machine. - * @param machineId the id of the machine - * @param function the function to execute + * + * @param manager + * the VirtualBoxManager + * @param type + * the kind of lock to use when initially locking the machine. + * @param machineId + * the id of the machine + * @param function + * the function to execute * @return the result from applying the function to the session. */ - public static T lockMachineAndApplyOrReturnNullIfNotRegistered(VirtualBoxManager manager, LockType type, String machineId, - Function function) { + public static T lockMachineAndApplyOrReturnNullIfNotRegistered( + VirtualBoxManager manager, LockType type, String machineId, + Function function) { try { return lockMachineAndApply(manager, type, machineId, function); } catch (RuntimeException e) { - VBoxException vbex = Throwables2.getFirstThrowableOfType(e, VBoxException.class); - if (vbex != null && vbex.getMessage().indexOf("not find a registered") == -1) + VBoxException vbex = Throwables2.getFirstThrowableOfType(e, + VBoxException.class); + if (vbex != null + && vbex.getMessage().indexOf("not find a registered") == -1) throw e; return null; } } /** - * Unlocks the machine and executes the given function using the machine matching the given id. - * Since the machine is unlocked it is possible to delete the IMachine. + * Unlocks the machine and executes the given function using the machine + * matching the given id. Since the machine is unlocked it is possible to + * delete the IMachine. *

* - *

Note!

Currently, this can only unlock the machine, if the lock was created in the - * current session. + *

Note!

Currently, this can only unlock the machine, if the lock + * was created in the current session. * * @param manager * the VirtualBoxManager @@ -155,42 +235,54 @@ public class MachineUtils { * the function to execute * @return the result from applying the function to the machine. */ - public static T unlockMachineAndApply(VirtualBoxManager manager, final String machineId, - final Function function) { + public static T unlockMachineAndApply(VirtualBoxManager manager, + final String machineId, final Function function) { + ISession session = manager.getSessionObject(); + try { - ISession session = manager.getSessionObject(); IMachine immutableMachine = manager.getVBox().findMachine(machineId); SessionState state = immutableMachine.getSessionState(); + Statement kill = newStatementList(call("default"), + findPid(immutableMachine.getSessionPid().toString()), kill()); if (state.equals(SessionState.Locked)) - session.unlockMachine(); - //TODO: wire this in - Statement kill = newStatementList(call("default"), findPid(machineId), kill()); + // session.unlockMachine(); + kill.render(OsFamily.UNIX); + // TODO: wire this in return function.apply(immutableMachine); } catch (VBoxException e) { - throw new RuntimeException(String.format("error applying %s to %s: %s", function, machineId, e.getMessage()), - e); + session.unlockMachine(); + throw new RuntimeException(String.format( + "error applying %s to %s: %s", function, machineId, + e.getMessage()), e); } } /** - * Unlocks the machine and executes the given function, if the machine is registered. - * Since the machine is unlocked it is possible to delete the machine. + * Unlocks the machine and executes the given function, if the machine is + * registered. Since the machine is unlocked it is possible to delete the + * machine. *

- * - * @param manager the VirtualBoxManager - * @param machineId the id of the machine - * @param function the function to execute + * + * @param manager + * the VirtualBoxManager + * @param machineId + * the id of the machine + * @param function + * the function to execute * @return the result from applying the function to the session. */ - public static T unlockMachineAndApplyOrReturnNullIfNotRegistered(VirtualBoxManager manager, String machineId, - Function function) { + public static T unlockMachineAndApplyOrReturnNullIfNotRegistered( + VirtualBoxManager manager, String machineId, + Function function) { try { return unlockMachineAndApply(manager, machineId, function); } catch (RuntimeException e) { - VBoxException vbex = Throwables2.getFirstThrowableOfType(e, VBoxException.class); - if (vbex != null && vbex.getMessage().indexOf("not find a registered") == -1) + VBoxException vbex = Throwables2.getFirstThrowableOfType(e, + VBoxException.class); + if (vbex != null + && vbex.getMessage().indexOf("not find a registered") == -1) throw e; return null; } diff --git a/sandbox-apis/virtualbox/src/test/java/org/jclouds/virtualbox/BaseVirtualBoxClientLiveTest.java b/sandbox-apis/virtualbox/src/test/java/org/jclouds/virtualbox/BaseVirtualBoxClientLiveTest.java index e9294dd50b..99f83074f1 100644 --- a/sandbox-apis/virtualbox/src/test/java/org/jclouds/virtualbox/BaseVirtualBoxClientLiveTest.java +++ b/sandbox-apis/virtualbox/src/test/java/org/jclouds/virtualbox/BaseVirtualBoxClientLiveTest.java @@ -38,7 +38,10 @@ import org.jclouds.logging.slf4j.config.SLF4JLoggingModule; import org.jclouds.sshj.config.SshjSshClientModule; import org.jclouds.virtualbox.config.VirtualBoxConstants; import org.jclouds.virtualbox.domain.VmSpec; +import org.jclouds.virtualbox.functions.CreateAndInstallVm; +import org.jclouds.virtualbox.functions.CreateAndRegisterMachineFromIsoIfNotAlreadyExists; import org.jclouds.virtualbox.functions.admin.UnregisterMachineIfExistsAndDeleteItsMedia; +import org.jclouds.virtualbox.util.MachineUtils; import org.testng.annotations.AfterClass; import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; @@ -124,12 +127,11 @@ public class BaseVirtualBoxClientLiveTest extends BaseVersionedServiceLiveTest { adminDisk = workingDir + "/testadmin.vdi"; operatingSystemIso = String.format("%s/%s.iso", workingDir, imageId); guestAdditionsIso = String.format("%s/VBoxGuestAdditions_%s.iso", workingDir, hostVersion); - } protected void undoVm(VmSpec vmSpecification) { - unlockMachineAndApplyOrReturnNullIfNotRegistered(manager.get(), vmSpecification.getVmName(), - new UnregisterMachineIfExistsAndDeleteItsMedia(vmSpecification)); + MachineUtils machineUtils = context.utils().injector().getInstance(MachineUtils.class); + machineUtils.mutateMachine(vmSpecification.getVmId(), new UnregisterMachineIfExistsAndDeleteItsMedia(vmSpecification)); } @AfterClass(groups = "live")