Cleanup and improved readability for CloneAndRegisterMachineFromIMachineIfNotAlreadyExists.

This commit is contained in:
Mattias Holmqvist 2011-11-27 02:17:47 +01:00
parent 4effcc39ad
commit 65e0b937ae
2 changed files with 135 additions and 181 deletions

View File

@ -19,37 +19,24 @@
package org.jclouds.virtualbox.functions; package org.jclouds.virtualbox.functions;
import static com.google.common.base.Preconditions.checkNotNull; import com.google.common.base.Function;
import static org.jclouds.virtualbox.MachineUtils.lockMachineAndApply; import com.google.inject.Inject;
import static org.virtualbox_4_1.LockType.Write; import org.jclouds.compute.ComputeServiceContext;
import org.jclouds.compute.reference.ComputeServiceConstants;
import java.util.ArrayList; import org.jclouds.logging.Logger;
import java.util.List; import org.virtualbox_4_1.*;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import javax.annotation.Resource; import javax.annotation.Resource;
import javax.inject.Named; import javax.inject.Named;
import java.util.ArrayList;
import java.util.List;
import org.jclouds.compute.ComputeServiceContext; import static com.google.common.base.Preconditions.checkNotNull;
import org.jclouds.compute.domain.ExecResponse; import static org.jclouds.virtualbox.MachineUtils.lockMachineAndApply;
import org.jclouds.compute.options.RunScriptOptions; import static org.virtualbox_4_1.LockType.Write;
import org.jclouds.compute.reference.ComputeServiceConstants;
import org.jclouds.logging.Logger;
import org.virtualbox_4_1.CloneMode;
import org.virtualbox_4_1.CloneOptions;
import org.virtualbox_4_1.IMachine;
import org.virtualbox_4_1.IProgress;
import org.virtualbox_4_1.ISnapshot;
import org.virtualbox_4_1.IVirtualBox;
import org.virtualbox_4_1.VBoxException;
import org.virtualbox_4_1.VirtualBoxManager;
import com.google.common.base.Function;
import com.google.common.base.Throwables;
import com.google.inject.Inject;
/** /**
*
* CloneAndRegisterMachineFromIMachineIfNotAlreadyExists will take care of the * CloneAndRegisterMachineFromIMachineIfNotAlreadyExists will take care of the
* followings: - cloning the master - register the clone machine - * followings: - cloning the master - register the clone machine -
* ensureBridgedNetworkingIsAppliedToMachine(cloneName, macAddress, * ensureBridgedNetworkingIsAppliedToMachine(cloneName, macAddress,
@ -57,130 +44,99 @@ import com.google.inject.Inject;
* *
* @author Andrea Turli * @author Andrea Turli
*/ */
public class CloneAndRegisterMachineFromIMachineIfNotAlreadyExists implements public class CloneAndRegisterMachineFromIMachineIfNotAlreadyExists implements Function<IMachine, IMachine> {
Function<IMachine, IMachine> {
@Resource @Resource
@Named(ComputeServiceConstants.COMPUTE_LOGGER) @Named(ComputeServiceConstants.COMPUTE_LOGGER)
protected Logger logger = Logger.NULL; protected Logger logger = Logger.NULL;
private VirtualBoxManager manager; private VirtualBoxManager manager;
private ComputeServiceContext context; private ComputeServiceContext context;
private String settingsFile; private String settingsFile;
private String osTypeId; private String osTypeId;
private String vmId; private String vmId;
private boolean forceOverwrite; private boolean forceOverwrite;
private String cloneName; private String cloneName;
private String hostId; private String hostId;
private String snapshotName; private String snapshotName;
private String snapshotDesc; private String snapshotDesc;
private String controllerIDE; private String controllerIDE;
@Inject @Inject
public CloneAndRegisterMachineFromIMachineIfNotAlreadyExists( public CloneAndRegisterMachineFromIMachineIfNotAlreadyExists(
VirtualBoxManager manager, ComputeServiceContext context, VirtualBoxManager manager, ComputeServiceContext context,
String settingsFile, String osTypeId, String vmId, String settingsFile, String osTypeId, String vmId,
boolean forceOverwrite, String cloneName, String hostId, boolean forceOverwrite, String cloneName, String hostId,
String snashotName, String snapshotDesc, String controllerIDE) { String snashotName, String snapshotDesc, String controllerIDE) {
super(); this.manager = manager;
this.manager = manager; this.context = context;
this.context = context; this.settingsFile = settingsFile;
this.settingsFile = settingsFile; this.osTypeId = osTypeId;
this.osTypeId = osTypeId; this.vmId = vmId;
this.vmId = vmId; this.forceOverwrite = forceOverwrite;
this.forceOverwrite = forceOverwrite; this.cloneName = cloneName;
this.cloneName = cloneName; this.hostId = hostId;
this.hostId = hostId; this.snapshotName = snashotName;
this.snapshotName = snashotName; this.snapshotDesc = snapshotDesc;
this.snapshotDesc = snapshotDesc; this.controllerIDE = controllerIDE;
this.controllerIDE = controllerIDE; }
}
@Override @Override
public IMachine apply(@Nullable IMachine master) { public IMachine apply(@Nullable IMachine master) {
final IVirtualBox vBox = manager.getVBox();
try {
vBox.findMachine(cloneName);
throw new IllegalStateException("Machine " + cloneName + " is already registered.");
} catch (VBoxException e) {
if (machineNotFoundException(e))
return cloneMachine(cloneName, master);
else
throw e;
}
}
final IVirtualBox vBox = manager.getVBox(); private boolean machineNotFoundException(VBoxException e) {
try { return e.getMessage().contains("VirtualBox error: Could not find a registered machine named ");
vBox.findMachine(cloneName); }
throw new IllegalStateException("Machine " + cloneName
+ " is already registered.");
} catch (VBoxException e) {
if (machineNotFoundException(e))
return cloneMachine(vBox, cloneName, master);
else
throw e;
}
}
private boolean machineNotFoundException(VBoxException e) { private IMachine cloneMachine(String cloneName, IMachine master) {
return e.getMessage().indexOf( IMachine clonedMachine = manager.getVBox().createMachine(settingsFile, cloneName, osTypeId, vmId, forceOverwrite);
"VirtualBox error: Could not find a registered machine named ") != -1; List<CloneOptions> options = new ArrayList<CloneOptions>();
} options.add(CloneOptions.Link);
private IMachine cloneMachine(IVirtualBox vBox, String cloneName, // takeSnapshotIfNotAlreadyExists
IMachine master) { ISnapshot currentSnapshot = new TakeSnapshotIfNotAlreadyAttached(manager, snapshotName, snapshotDesc).apply(master);
IMachine clonedMachine = manager.getVBox().createMachine(settingsFile,
cloneName, osTypeId, vmId, forceOverwrite);
List<CloneOptions> options = new ArrayList<CloneOptions>();
options.add(CloneOptions.Link);
// takeSnapshotIfNotAlreadyExists // clone
ISnapshot currentSnapshot = new TakeSnapshotIfNotAlreadyAttached(manager, IProgress progress = currentSnapshot.getMachine().cloneTo(clonedMachine, CloneMode.MachineState, options);
snapshotName, snapshotDesc).apply(master);
// clone if (progress.getCompleted())
IProgress progress = currentSnapshot.getMachine().cloneTo(clonedMachine, logger.debug("clone done");
CloneMode.MachineState, options);
if (progress.getCompleted()) // registering
logger.debug("clone done"); manager.getVBox().registerMachine(clonedMachine);
// registering // Bridged Network
manager.getVBox().registerMachine(clonedMachine); List<String> activeBridgedInterfaces = new RetrieveActiveBridgedInterfaces(context).apply(hostId);
checkNotNull(activeBridgedInterfaces);
String macAddress = manager.getVBox().getHost().generateMACAddress();
// Bridged Network // TODO this behavior can be improved
List<String> activeBridgedInterfaces = new RetrieveActiveBridgedInterfaces( String bridgedInterface = activeBridgedInterfaces.get(0);
context).apply(hostId); ensureBridgedNetworkingIsAppliedToMachine(cloneName, macAddress, bridgedInterface);
checkNotNull(activeBridgedInterfaces);
String macAddress = manager.getVBox().getHost().generateMACAddress();
// TODO this behavior can be improved // detach iso
String bridgedInterface = activeBridgedInterfaces.get(0); ensureMachineHasDistroMediumDetached(cloneName, controllerIDE);
ensureBridgedNetworkingIsAppliedToMachine(cloneName, macAddress,
bridgedInterface);
// detach iso return clonedMachine;
ensureMachineHasDistroMediumDetached(cloneName, controllerIDE); }
return clonedMachine; private void ensureBridgedNetworkingIsAppliedToMachine(String vmName, String macAddress, String hostInterface) {
} lockMachineAndApply(manager, Write, vmName, new AttachBridgedAdapterToMachine(0l, macAddress, hostInterface));
}
private void ensureBridgedNetworkingIsAppliedToMachine(String vmName, private void ensureMachineHasDistroMediumDetached(String vmName, String controllerIDE) {
String macAddress, String hostInterface) { lockMachineAndApply(manager, Write, vmName, new DetachDistroMediumToMachine(checkNotNull(controllerIDE, "controllerIDE")));
lockMachineAndApply(manager, Write, vmName, }
new AttachBridgedAdapterToMachine(0l, macAddress, hostInterface));
}
private void ensureMachineHasDistroMediumDetached(String vmName,
String controllerIDE) {
lockMachineAndApply(
manager,
Write,
vmName,
new DetachDistroMediumToMachine(checkNotNull(controllerIDE,
"controllerIDE")));
}
protected ExecResponse runScriptOnNode(String nodeId, String command,
RunScriptOptions options) {
return context.getComputeService().runScriptOnNode(nodeId, command,
options);
}
protected <T> T propagate(Exception e) {
Throwables.propagate(e);
assert false;
return null;
}
} }

View File

@ -42,57 +42,55 @@ import com.google.common.base.Predicate;
* @author Andrea Turli * @author Andrea Turli
*/ */
@Test(groups = "live", singleThreaded = true, testName = "CloneAndRegisterMachineFromIsoIfNotAlreadyExistsLiveTest") @Test(groups = "live", singleThreaded = true, testName = "CloneAndRegisterMachineFromIsoIfNotAlreadyExistsLiveTest")
public class CloneAndRegisterMachineFromIsoIfNotAlreadyExistsLiveTest extends public class CloneAndRegisterMachineFromIsoIfNotAlreadyExistsLiveTest extends BaseVirtualBoxClientLiveTest {
BaseVirtualBoxClientLiveTest {
private String settingsFile = null; private String settingsFile = null;
private boolean forceOverwrite = true; private boolean forceOverwrite = true;
private String vmId = "jclouds-image-iso-1"; private String vmId = "jclouds-image-iso-1";
private String osTypeId = ""; private String osTypeId = "";
private String controllerIDE = "IDE Controller"; private String controllerIDE = "IDE Controller";
private String diskFormat = ""; private String diskFormat = "";
private String adminDisk = "testadmin.vdi"; private String adminDisk = "testadmin.vdi";
private String guestId = "guest"; private String guestId = "guest";
private String hostId = "host"; private String hostId = "host";
private String snapshotName = "snap"; private String snapshotName = "snap";
private String snapshotDesc = "snapDesc"; private String snapshotDesc = "snapDesc";
private String vmName = "jclouds-image-virtualbox-iso-to-machine-test"; private String vmName = "jclouds-image-virtualbox-iso-to-machine-test";
private String cloneName = vmName + "_clone"; private String cloneName = vmName + "_clone";
private String isoName = "ubuntu-11.04-server-i386.iso"; private String isoName = "ubuntu-11.04-server-i386.iso";
@Test @Test
public void testCloneMachineFromAnotherMachine() throws Exception { public void testCloneMachineFromAnotherMachine() throws Exception {
VirtualBoxManager manager = (VirtualBoxManager) context VirtualBoxManager manager = (VirtualBoxManager) context.getProviderSpecificContext().getApi();
.getProviderSpecificContext().getApi(); ComputeServiceContext localHostContext =
ComputeServiceContext localHostContext = computeServiceForLocalhostAndGuest( computeServiceForLocalhostAndGuest(hostId, "localhost", guestId, "localhost", new Credentials("toor", "password"));
hostId, "localhost", guestId, "localhost", new Credentials("toor",
"password"));
IMachine master = null; IMachine master = getMasterNode(manager, localHostContext);
try {
Predicate<IPSocket> socketTester = new RetryablePredicate<IPSocket>(
new InetSocketAddressConnect(), 10, 1, TimeUnit.SECONDS);
master = new IsoToIMachine(manager, adminDisk, diskFormat,
settingsFile, vmName, osTypeId, vmId, forceOverwrite,
controllerIDE, localHostContext, hostId, guestId, socketTester,
"127.0.0.1", 8080).apply(isoName);
} catch (IllegalStateException e) {
// already created
master = manager.getVBox().findMachine(vmName);
}
if (master.getCurrentSnapshot() != null) { if (master.getCurrentSnapshot() != null) {
ISession session = manager.openMachineSession(master); ISession session = manager.openMachineSession(master);
session.getConsole().deleteSnapshot( session.getConsole().deleteSnapshot(master.getCurrentSnapshot().getId());
master.getCurrentSnapshot().getId()); session.unlockMachine();
session.unlockMachine(); }
}
IMachine clone = new CloneAndRegisterMachineFromIMachineIfNotAlreadyExists( IMachine clone = new CloneAndRegisterMachineFromIMachineIfNotAlreadyExists(
manager, localHostContext, settingsFile, osTypeId, vmId, manager, localHostContext, settingsFile, osTypeId, vmId,
forceOverwrite, cloneName, hostId, snapshotName, snapshotDesc, forceOverwrite, cloneName, hostId, snapshotName, snapshotDesc,
controllerIDE).apply(master); controllerIDE).apply(master);
assertEquals(clone.getNetworkAdapter(0L).getAttachmentType(), Bridged); assertEquals(clone.getNetworkAdapter(0L).getAttachmentType(), Bridged);
} }
private IMachine getMasterNode(VirtualBoxManager manager, ComputeServiceContext localHostContext) {
try {
Predicate<IPSocket> socketTester = new RetryablePredicate<IPSocket>(new InetSocketAddressConnect(), 10, 1, TimeUnit.SECONDS);
return new IsoToIMachine(manager, adminDisk, diskFormat,
settingsFile, vmName, osTypeId, vmId, forceOverwrite,
controllerIDE, localHostContext, hostId, guestId, socketTester,
"127.0.0.1", 8080).apply(isoName);
} catch (IllegalStateException e) {
// already created
return manager.getVBox().findMachine(vmName);
}
}
} }