Added LaunchMachineIfNotAlreadyRunning to IsoToIMachine.

This commit is contained in:
Mattias Holmqvist 2011-10-28 07:43:34 +02:00
parent c3eb23399b
commit f4a53fa0da
4 changed files with 219 additions and 49 deletions

View File

@ -46,27 +46,27 @@ import java.util.Map;
*/
public enum ErrorCode {
E_OBJECT_NOT_FOUND(2159738881L),
E_INVALID_VM_STATE(2159738882L),
E_VM_ERROR(2159738883L),
E_FILE_ERROR(2159738884L),
E_IPRT_ERROR(2159738885L),
E_PDM_ERROR(2159738886L),
E_INVALID_OBJECT_STATE(2159738887L),
E_HOST_ERROR(2159738888L),
E_NOT_SUPPORTED(2159738889L),
E_XML_ERROR(2159738890L),
E_INVALID_SESSION_STATE(2159738891L),
E_OBJECT_IN_USE(2159738892L),
E_ACCESSDENIED(2147942405L),
E_POINTER(2147500035L),
E_FAIL(2147500037L),
E_NOTIMPL(2147500033L),
E_OUTOFMEMORY(2147942414L),
E_INVALIDARG(2147942487L),
E_UNEXPECTED(2147549183L),
E_UNKNOWN_ERROR_CODE(-1L),
E_ERROR_CODE_UNAVAILABLE(-2L);
VBOX_E_OBJECT_NOT_FOUND(2159738881L),
VBOX_E_INVALID_VM_STATE(2159738882L),
VBOX_E_VM_ERROR(2159738883L),
VBOX_E_FILE_ERROR(2159738884L),
VBOX_E_IPRT_ERROR(2159738885L),
VBOX_E_PDM_ERROR(2159738886L),
VBOX_E_INVALID_OBJECT_STATE(2159738887L),
VBOX_E_HOST_ERROR(2159738888L),
VBOX_E_NOT_SUPPORTED(2159738889L),
VBOX_E_XML_ERROR(2159738890L),
VBOX_E_INVALID_SESSION_STATE(2159738891L),
VBOX_E_OBJECT_IN_USE(2159738892L),
VBOX_E_ACCESSDENIED(2147942405L),
VBOX_E_POINTER(2147500035L),
VBOX_E_FAIL(2147500037L),
VBOX_E_NOTIMPL(2147500033L),
VBOX_E_OUTOFMEMORY(2147942414L),
VBOX_E_INVALIDARG(2147942487L),
VBOX_E_UNEXPECTED(2147549183L),
VBOX_E_UNKNOWN_ERROR_CODE(-1L),
VBOX_E_ERROR_CODE_UNAVAILABLE(-2L);
private long code;
@ -97,9 +97,9 @@ public enum ErrorCode {
if (errorCode != null) {
return errorCode;
}
return E_UNKNOWN_ERROR_CODE;
return VBOX_E_UNKNOWN_ERROR_CODE;
}
return E_ERROR_CODE_UNAVAILABLE;
return VBOX_E_ERROR_CODE_UNAVAILABLE;
}
private static long unsignedIntToLong(int faultCode) {

View File

@ -19,23 +19,8 @@
package org.jclouds.virtualbox.functions;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Throwables.propagate;
import static org.jclouds.compute.options.RunScriptOptions.Builder.runAsRoot;
import static org.jclouds.compute.options.RunScriptOptions.Builder.wrapInInitScript;
import static org.jclouds.virtualbox.config.VirtualBoxConstants.VIRTUALBOX_INSTALLATION_KEY_SEQUENCE;
import static org.jclouds.virtualbox.config.VirtualBoxConstants.VIRTUALBOX_WORKINGDIR;
import static org.virtualbox_4_1.AccessMode.ReadOnly;
import static org.virtualbox_4_1.DeviceType.DVD;
import static org.virtualbox_4_1.DeviceType.HardDisk;
import static org.virtualbox_4_1.LockType.Shared;
import static org.virtualbox_4_1.LockType.Write;
import java.io.File;
import javax.annotation.Resource;
import javax.inject.Named;
import com.google.common.base.Function;
import com.google.inject.Inject;
import org.eclipse.jetty.server.Server;
import org.jclouds.compute.ComputeServiceContext;
import org.jclouds.compute.domain.ExecResponse;
@ -46,12 +31,25 @@ import org.jclouds.javax.annotation.Nullable;
import org.jclouds.logging.Logger;
import org.jclouds.ssh.SshException;
import org.jclouds.virtualbox.config.VirtualBoxConstants;
import org.jclouds.virtualbox.domain.ExecutionType;
import org.jclouds.virtualbox.functions.admin.StartJettyIfNotAlreadyRunning;
import org.jclouds.virtualbox.settings.KeyboardScancodes;
import org.virtualbox_4_1.*;
import com.google.common.base.Function;
import com.google.inject.Inject;
import javax.annotation.Resource;
import javax.inject.Named;
import java.io.File;
import static com.google.common.base.Preconditions.checkNotNull;
import static org.jclouds.compute.options.RunScriptOptions.Builder.runAsRoot;
import static org.jclouds.compute.options.RunScriptOptions.Builder.wrapInInitScript;
import static org.jclouds.virtualbox.config.VirtualBoxConstants.VIRTUALBOX_INSTALLATION_KEY_SEQUENCE;
import static org.jclouds.virtualbox.config.VirtualBoxConstants.VIRTUALBOX_WORKINGDIR;
import static org.virtualbox_4_1.AccessMode.ReadOnly;
import static org.virtualbox_4_1.DeviceType.DVD;
import static org.virtualbox_4_1.DeviceType.HardDisk;
import static org.virtualbox_4_1.LockType.Shared;
import static org.virtualbox_4_1.LockType.Write;
public class IsoToIMachine implements Function<String, IMachine> {
@ -136,13 +134,8 @@ public class IsoToIMachine implements Function<String, IMachine> {
// Guest additions
ensureGuestAdditionsMediumIsAttached(vmName, guestAdditionsDvdMedium);
IProgress prog = vm.launchVMProcess(manager.getSessionObject(), "gui", "");
prog.waitForCompletion(-1);
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
propagate(e);
}
// Launch machine and wait for it to come online
ensureMachineIsLaunched(vmName);
String installKeySequence = System.getProperty(VIRTUALBOX_INSTALLATION_KEY_SEQUENCE, defaultInstallSequence());
sendKeyboardSequence(installKeySequence);
@ -180,6 +173,10 @@ public class IsoToIMachine implements Function<String, IMachine> {
return vm;
}
private void ensureMachineIsLaunched(String vmName) {
applyForMachine(manager, vmName, new LaunchMachineIfNotAlreadyRunning(manager, ExecutionType.GUI, ""));
}
private void ensureGuestAdditionsMediumIsAttached(String vmName, final IMedium guestAdditionsDvdMedium) {
lockMachineAndApply(manager, Write, vmName,
new AttachMediumToMachineIfNotAlreadyAttached(controllerIDE, guestAdditionsDvdMedium, 1, 1, DeviceType.DVD));
@ -219,6 +216,21 @@ public class IsoToIMachine implements Function<String, IMachine> {
new AddIDEControllerIfNotExists(checkNotNull(controllerIDE, "controllerIDE")));
}
private <T> T applyForMachine(VirtualBoxManager manager, final String machineId, final Function<IMachine, T> function) {
final IMachine immutableMachine = manager.getVBox().findMachine(machineId);
return new Function<IMachine, T>() {
@Override
public T apply(IMachine machine) {
return function.apply(machine);
}
@Override
public String toString() {
return function.toString();
}
}.apply(immutableMachine);
}
public static <T> T lockMachineAndApply(VirtualBoxManager manager, final LockType type, final String machineId,
final Function<IMachine, T> function) {
return lockSessionOnMachineAndApply(manager, type, machineId, new Function<ISession, T>() {

View File

@ -0,0 +1,91 @@
/*
* 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 com.google.common.base.Function;
import org.jclouds.compute.reference.ComputeServiceConstants;
import org.jclouds.logging.Logger;
import org.jclouds.virtualbox.domain.ErrorCode;
import org.jclouds.virtualbox.domain.ExecutionType;
import org.virtualbox_4_1.*;
import org.virtualbox_4_1.jaxws.RuntimeFaultMsg;
import javax.annotation.Nullable;
import javax.annotation.Resource;
import javax.inject.Named;
import javax.lang.model.type.ExecutableType;
import static com.google.common.base.Throwables.propagate;
import static javax.xml.bind.DatatypeConverter.parseUnsignedInt;
/**
* Starts a machine using launchMachine() with the provided type and environment.
* <p/>
* Note that launchMachine() may throw VBoxException with the following error codes:
* <p/>
* VBOX_E_UNEXPECTED: Virtual machine not registered.
* VBOX_E_INVALIDARG: Invalid session type type.
* VBOX_E_OBJECT_NOT_FOUND: No machine matching machineId found.
* VBOX_E_INVALID_OBJECT_STATE: Session already open or being opened.
* VBOX_E_IPRT_ERROR: Launching process for machine failed.
* VBOX_E_VM_ERROR: Failed to assign machine to session.
*
* @author Mattias Holmqvist
*
* @see ErrorCode
*/
public class LaunchMachineIfNotAlreadyRunning implements Function<IMachine, Void> {
@Resource
@Named(ComputeServiceConstants.COMPUTE_LOGGER)
protected Logger logger = Logger.NULL;
private final VirtualBoxManager manager;
private final ExecutionType type;
private final String environment;
public LaunchMachineIfNotAlreadyRunning(VirtualBoxManager manager, ExecutionType type, String environment) {
this.manager = manager;
this.type = type;
this.environment = environment;
}
@Override
public Void apply(@Nullable IMachine machine) {
try {
final IProgress progress = machine.launchVMProcess(manager.getSessionObject(), type.stringValue(), environment);
progress.waitForCompletion(-1);
Thread.sleep(5000);
} catch (InterruptedException e) {
propagate(e);
} catch (VBoxException e) {
ErrorCode errorCode = ErrorCode.valueOf(e);
switch (errorCode) {
case VBOX_E_INVALID_OBJECT_STATE:
logger.warn(e, "Could not start machine. Got error code %s from launchMachine(). " +
"The machine might already be running.", errorCode);
break;
default:
propagate(e);
}
}
return null;
}
}

View File

@ -0,0 +1,67 @@
/*
* 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 org.jclouds.virtualbox.domain.ExecutionType;
import org.testng.annotations.Test;
import org.virtualbox_4_1.IMachine;
import org.virtualbox_4_1.IProgress;
import org.virtualbox_4_1.ISession;
import org.virtualbox_4_1.VirtualBoxManager;
import static org.easymock.classextension.EasyMock.verify;
import static org.easymock.classextension.EasyMock.replay;
import static org.easymock.classextension.EasyMock.createMock;
import static org.easymock.classextension.EasyMock.expect;
@Test(groups = "unit", testName = "LaunchMachineIfNotAlreadyRunningTest")
public class LaunchMachineIfNotAlreadyRunningTest {
@Test
public void testDoNotLaunchIfAlreadyRunning() throws Exception {
}
// VirtualBox error: The given session is busy (0x80BB0007)
// VirtualBox error: The machine 'jclouds-image-virtualbox-iso-to-machine-test' is not registered (0x8000FFFF)
@Test
public void testLaunchIfNotStarted() throws Exception {
final String type = "gui";
final String environment = "";
ISession session = createMock(ISession.class);
VirtualBoxManager manager = createMock(VirtualBoxManager.class);
IMachine machine = createMock(IMachine.class);
IProgress progress = createMock(IProgress.class);
expect(manager.getSessionObject()).andReturn(session);
expect(machine.launchVMProcess(session, type, environment)).andReturn(progress);
progress.waitForCompletion(-1);
replay(manager, machine, session, progress);
new LaunchMachineIfNotAlreadyRunning(manager, ExecutionType.GUI, "").apply(machine);
verify(manager, machine, session, progress);
}
}