mirror of https://github.com/apache/jclouds.git
fixed locking transient bug
This commit is contained in:
parent
28bd62edfc
commit
1f31e96a9f
|
@ -158,7 +158,7 @@ public class VirtualBoxComputeServiceContextModule extends
|
||||||
bind(new TypeLiteral<Function<IMachine, SshClient>>() {
|
bind(new TypeLiteral<Function<IMachine, SshClient>>() {
|
||||||
}).to(IMachineToSshClient.class);
|
}).to(IMachineToSshClient.class);
|
||||||
|
|
||||||
bind(ExecutionType.class).toInstance(ExecutionType.GUI);
|
bind(ExecutionType.class).toInstance(ExecutionType.HEADLESS);
|
||||||
bind(LockType.class).toInstance(LockType.Write);
|
bind(LockType.class).toInstance(LockType.Write);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -147,7 +147,7 @@ public class CreateAndInstallVm implements Function<MasterSpec, IMachine> {
|
||||||
.split(installationKeySequence), new StringToKeyCode());
|
.split(installationKeySequence), new StringToKeyCode());
|
||||||
|
|
||||||
for (List<Integer> scancodes : scancodelist) {
|
for (List<Integer> scancodes : scancodelist) {
|
||||||
machineUtils.readLockMachineAndApplyToSession(vmName,new SendScancodes(scancodes));
|
machineUtils.sharedLockMachineAndApplyToSession(vmName,new SendScancodes(scancodes));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -46,6 +46,7 @@ import org.jclouds.virtualbox.domain.NodeSpec;
|
||||||
import org.jclouds.virtualbox.domain.VmSpec;
|
import org.jclouds.virtualbox.domain.VmSpec;
|
||||||
import org.jclouds.virtualbox.statements.DeleteGShadowLock;
|
import org.jclouds.virtualbox.statements.DeleteGShadowLock;
|
||||||
import org.jclouds.virtualbox.statements.SetIpAddress;
|
import org.jclouds.virtualbox.statements.SetIpAddress;
|
||||||
|
import org.jclouds.virtualbox.util.MachineController;
|
||||||
import org.jclouds.virtualbox.util.MachineUtils;
|
import org.jclouds.virtualbox.util.MachineUtils;
|
||||||
import org.virtualbox_4_1.CleanupMode;
|
import org.virtualbox_4_1.CleanupMode;
|
||||||
import org.virtualbox_4_1.IMachine;
|
import org.virtualbox_4_1.IMachine;
|
||||||
|
@ -83,23 +84,22 @@ public class NodeCreator implements Function<NodeSpec, NodeAndInitialCredentials
|
||||||
// TODO parameterize
|
// TODO parameterize
|
||||||
public static final boolean USE_LINKED = true;
|
public static final boolean USE_LINKED = true;
|
||||||
|
|
||||||
// TODO parameterize
|
|
||||||
public static final ExecutionType EXECUTION_TYPE = ExecutionType.HEADLESS;
|
|
||||||
|
|
||||||
private final Supplier<VirtualBoxManager> manager;
|
private final Supplier<VirtualBoxManager> manager;
|
||||||
private final Function<CloneSpec, IMachine> cloner;
|
private final Function<CloneSpec, IMachine> cloner;
|
||||||
private final AtomicInteger nodePorts;
|
private final AtomicInteger nodePorts;
|
||||||
private final AtomicInteger nodeIps;
|
private final AtomicInteger nodeIps;
|
||||||
private MachineUtils machineUtils;
|
private final MachineUtils machineUtils;
|
||||||
|
private final MachineController machineController;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public NodeCreator(Supplier<VirtualBoxManager> manager, Function<CloneSpec, IMachine> cloner,
|
public NodeCreator(Supplier<VirtualBoxManager> manager, Function<CloneSpec, IMachine> cloner,
|
||||||
MachineUtils machineUtils, RunScriptOnNode.Factory scriptRunnerFactory) {
|
MachineUtils machineUtils, RunScriptOnNode.Factory scriptRunnerFactory, MachineController machineController) {
|
||||||
this.manager = manager;
|
this.manager = manager;
|
||||||
this.cloner = cloner;
|
this.cloner = cloner;
|
||||||
this.nodePorts = new AtomicInteger(NODE_PORT_INIT);
|
this.nodePorts = new AtomicInteger(NODE_PORT_INIT);
|
||||||
this.nodeIps = new AtomicInteger(2);
|
this.nodeIps = new AtomicInteger(2);
|
||||||
this.machineUtils = machineUtils;
|
this.machineUtils = machineUtils;
|
||||||
|
this.machineController = machineController;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -147,7 +147,7 @@ public class NodeCreator implements Function<NodeSpec, NodeAndInitialCredentials
|
||||||
|
|
||||||
IMachine cloned = cloner.apply(cloneSpec);
|
IMachine cloned = cloner.apply(cloneSpec);
|
||||||
|
|
||||||
new LaunchMachineIfNotAlreadyRunning(manager.get(), EXECUTION_TYPE, "").apply(cloned);
|
machineController.ensureMachineIsLaunched(cloneVmSpec.getVmName());
|
||||||
|
|
||||||
// IMachineToNodeMetadata produces the final ip's but these need to be set before so we build a
|
// IMachineToNodeMetadata produces the final ip's but these need to be set before so we build a
|
||||||
// NodeMetadata just for the sake of running the gshadow and setip scripts
|
// NodeMetadata just for the sake of running the gshadow and setip scripts
|
||||||
|
|
|
@ -67,7 +67,7 @@ public class MachineController {
|
||||||
public void ensureMachineHasPowerDown(String vmName) {
|
public void ensureMachineHasPowerDown(String vmName) {
|
||||||
while (!manager.get().getVBox().findMachine(vmName).getState().equals(MachineState.POWERED_OFF)) {
|
while (!manager.get().getVBox().findMachine(vmName).getState().equals(MachineState.POWERED_OFF)) {
|
||||||
try {
|
try {
|
||||||
machineUtils.writeLockMachineAndApplyToSession(vmName, new Function<ISession, Void>() {
|
machineUtils.sharedLockMachineAndApplyToSession(vmName, new Function<ISession, Void>() {
|
||||||
@Override
|
@Override
|
||||||
public Void apply(ISession session) {
|
public Void apply(ISession session) {
|
||||||
IProgress powerDownProgress = session.getConsole().powerDown();
|
IProgress powerDownProgress = session.getConsole().powerDown();
|
||||||
|
|
|
@ -57,15 +57,12 @@ public class MachineUtils {
|
||||||
|
|
||||||
private final Supplier<VirtualBoxManager> manager;
|
private final Supplier<VirtualBoxManager> manager;
|
||||||
private final Factory scriptRunner;
|
private final Factory scriptRunner;
|
||||||
private final Supplier<NodeMetadata> host;
|
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public MachineUtils(Supplier<VirtualBoxManager> manager, RunScriptOnNode.Factory scriptRunner,
|
public MachineUtils(Supplier<VirtualBoxManager> manager, RunScriptOnNode.Factory scriptRunner) {
|
||||||
Supplier<NodeMetadata> host) {
|
|
||||||
super();
|
super();
|
||||||
this.manager = manager;
|
this.manager = manager;
|
||||||
this.scriptRunner = scriptRunner;
|
this.scriptRunner = scriptRunner;
|
||||||
this.host = host;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public ListenableFuture<ExecResponse> runScriptOnNode(NodeMetadata metadata, Statement statement,
|
public ListenableFuture<ExecResponse> runScriptOnNode(NodeMetadata metadata, Statement statement,
|
||||||
|
@ -100,10 +97,11 @@ public class MachineUtils {
|
||||||
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Locks the machine and executes the given function using the machine matching the given id.
|
* Locks the machine and executes the given function using the machine matching the given id. The
|
||||||
* The machine is write locked and modifications to the session that reflect on the machine can be done safely.
|
* machine is write locked and modifications to the session that reflect on the machine can be
|
||||||
|
* done safely.
|
||||||
* <p/>
|
* <p/>
|
||||||
* Unlocks the machine before returning.
|
* Unlocks the machine before returning.
|
||||||
*
|
*
|
||||||
|
@ -116,10 +114,11 @@ public class MachineUtils {
|
||||||
public <T> T writeLockMachineAndApplyToSession(final String machineId, final Function<ISession, T> function) {
|
public <T> T writeLockMachineAndApplyToSession(final String machineId, final Function<ISession, T> function) {
|
||||||
return lockSessionOnMachineAndApply(machineId, LockType.Write, function);
|
return lockSessionOnMachineAndApply(machineId, LockType.Write, function);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Locks the machine and executes the given function using the machine matching the given id.
|
* Locks the machine and executes the given function using the machine matching the given id. The
|
||||||
* The machine is read locked, which means that settings can be read safely (but not changed) by function.
|
* machine is read locked, which means that settings can be read safely (but not changed) by
|
||||||
|
* function.
|
||||||
* <p/>
|
* <p/>
|
||||||
* Unlocks the machine before returning.
|
* Unlocks the machine before returning.
|
||||||
*
|
*
|
||||||
|
@ -129,7 +128,7 @@ public class MachineUtils {
|
||||||
* the function to execute
|
* the function to execute
|
||||||
* @return the result from applying the function to the machine.
|
* @return the result from applying the function to the machine.
|
||||||
*/
|
*/
|
||||||
public <T> T readLockMachineAndApply(final String machineId, final Function<IMachine, T> function) {
|
public <T> T sharedLockMachineAndApply(final String machineId, final Function<IMachine, T> function) {
|
||||||
return lockSessionOnMachineAndApply(machineId, LockType.Shared, new Function<ISession, T>() {
|
return lockSessionOnMachineAndApply(machineId, LockType.Shared, new Function<ISession, T>() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -144,10 +143,11 @@ public class MachineUtils {
|
||||||
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Locks the machine and executes the given function to the session using the machine matching the given id.
|
* Locks the machine and executes the given function to the session using the machine matching
|
||||||
* The machine is read locked, which means that settings can be read safely (but not changed) by function.
|
* the given id. The machine is read locked, which means that settings can be read safely (but
|
||||||
|
* not changed) by function.
|
||||||
* <p/>
|
* <p/>
|
||||||
* Unlocks the machine before returning.
|
* Unlocks the machine before returning.
|
||||||
*
|
*
|
||||||
|
@ -157,10 +157,9 @@ public class MachineUtils {
|
||||||
* the function to execute
|
* the function to execute
|
||||||
* @return the result from applying the function to the machine.
|
* @return the result from applying the function to the machine.
|
||||||
*/
|
*/
|
||||||
public <T> T readLockMachineAndApplyToSession(final String machineId, final Function<ISession, T> function) {
|
public <T> T sharedLockMachineAndApplyToSession(final String machineId, final Function<ISession, T> function) {
|
||||||
return lockSessionOnMachineAndApply(machineId, LockType.Shared, function);
|
return lockSessionOnMachineAndApply(machineId, LockType.Shared, function);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Locks the machine and executes the given function using the current session. Since the machine
|
* Locks the machine and executes the given function using the current session. Since the machine
|
||||||
|
@ -183,11 +182,14 @@ public class MachineUtils {
|
||||||
int retries = 5;
|
int retries = 5;
|
||||||
int count = 0;
|
int count = 0;
|
||||||
ISession session;
|
ISession session;
|
||||||
|
long time = System.currentTimeMillis();
|
||||||
while (true) {
|
while (true) {
|
||||||
try {
|
try {
|
||||||
session = manager.get().getSessionObject();
|
|
||||||
IMachine immutableMachine = manager.get().getVBox().findMachine(machineId);
|
IMachine immutableMachine = manager.get().getVBox().findMachine(machineId);
|
||||||
|
session = manager.get().getSessionObject();
|
||||||
immutableMachine.lockMachine(session, type);
|
immutableMachine.lockMachine(session, type);
|
||||||
|
System.err.println("ACQUIRED LOCK ["+time+"]");
|
||||||
|
print();
|
||||||
break;
|
break;
|
||||||
} catch (VBoxException e) {
|
} catch (VBoxException e) {
|
||||||
VBoxException vbex = Throwables2.getFirstThrowableOfType(e, VBoxException.class);
|
VBoxException vbex = Throwables2.getFirstThrowableOfType(e, VBoxException.class);
|
||||||
|
@ -195,7 +197,7 @@ public class MachineUtils {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
count++;
|
count++;
|
||||||
logger.warn("Could not lock machine (try %i of %i). Error: %s", retries, count, e.getMessage());
|
logger.warn(e, "Could not lock machine (try %d of %d). Error: %s", count, retries, e.getMessage());
|
||||||
if (count == retries) {
|
if (count == retries) {
|
||||||
throw new RuntimeException(String.format("error locking %s with %s lock: %s", machineId, type,
|
throw new RuntimeException(String.format("error locking %s with %s lock: %s", machineId, type,
|
||||||
e.getMessage()), e);
|
e.getMessage()), e);
|
||||||
|
@ -213,6 +215,14 @@ public class MachineUtils {
|
||||||
type, e.getMessage()), e);
|
type, e.getMessage()), e);
|
||||||
} finally {
|
} finally {
|
||||||
session.unlockMachine();
|
session.unlockMachine();
|
||||||
|
System.err.println("RELEASED LOCK ["+time+"]");
|
||||||
|
print();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void print() {
|
||||||
|
for (StackTraceElement element : Thread.currentThread().getStackTrace()){
|
||||||
|
System.err.println(element.toString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -142,7 +142,7 @@ public class CreateAndInstallVmLiveTest extends BaseVirtualBoxClientLiveTest {
|
||||||
|
|
||||||
String vboxVersion = Iterables.get(
|
String vboxVersion = Iterables.get(
|
||||||
Splitter.on('r').split(context.getProviderSpecificContext().getBuildVersion()), 0);
|
Splitter.on('r').split(context.getProviderSpecificContext().getBuildVersion()), 0);
|
||||||
assertEquals(vboxVersion, machineUtils.readLockMachineAndApplyToSession(machine.getName(),
|
assertEquals(vboxVersion, machineUtils.sharedLockMachineAndApplyToSession(machine.getName(),
|
||||||
new Function<ISession, String>() {
|
new Function<ISession, String>() {
|
||||||
@Override
|
@Override
|
||||||
public String apply(ISession session) {
|
public String apply(ISession session) {
|
||||||
|
|
|
@ -110,7 +110,7 @@ public class GuestAdditionsInstallerLiveTest extends
|
||||||
machineUtils.applyForMachine(machine.getName(),
|
machineUtils.applyForMachine(machine.getName(),
|
||||||
new LaunchMachineIfNotAlreadyRunning(manager.get(),
|
new LaunchMachineIfNotAlreadyRunning(manager.get(),
|
||||||
ExecutionType.GUI, ""));
|
ExecutionType.GUI, ""));
|
||||||
assertTrue(machineUtils.readLockMachineAndApplyToSession(
|
assertTrue(machineUtils.sharedLockMachineAndApplyToSession(
|
||||||
machine.getName(),
|
machine.getName(),
|
||||||
new Function<ISession, Boolean>() {
|
new Function<ISession, Boolean>() {
|
||||||
@Override
|
@Override
|
||||||
|
|
Loading…
Reference in New Issue