diff --git a/labs/virtualbox/src/main/java/org/jclouds/virtualbox/config/VirtualBoxComputeServiceContextModule.java b/labs/virtualbox/src/main/java/org/jclouds/virtualbox/config/VirtualBoxComputeServiceContextModule.java index fcaac83da1..b54e2031c8 100644 --- a/labs/virtualbox/src/main/java/org/jclouds/virtualbox/config/VirtualBoxComputeServiceContextModule.java +++ b/labs/virtualbox/src/main/java/org/jclouds/virtualbox/config/VirtualBoxComputeServiceContextModule.java @@ -27,6 +27,7 @@ import java.net.URI; import java.util.Map; import java.util.Set; import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeUnit; import javax.inject.Named; import javax.inject.Singleton; @@ -137,8 +138,7 @@ public class VirtualBoxComputeServiceContextModule extends bind(new TypeLiteral>>() { }).to((Class) ImagesToYamlImagesFromYamlDescriptor.class); // the yaml config provider - bind(new TypeLiteral>() { - }).to((Class) YamlImagesFromFileConfig.class); + bind(YamlImagesFromFileConfig.class); // the master machines cache bind(new TypeLiteral>() { }).to((Class) MastersLoadingCache.class); @@ -213,7 +213,7 @@ public class VirtualBoxComputeServiceContextModule extends @Provides @Singleton protected Predicate sshResponds(SshResponds sshResponds, Timeouts timeouts) { - return new RetryablePredicate(sshResponds, timeouts.nodeRunning); + return new RetryablePredicate(sshResponds, timeouts.nodeRunning, 500l, TimeUnit.MILLISECONDS); } @Override diff --git a/labs/virtualbox/src/main/java/org/jclouds/virtualbox/domain/BridgedIf.java b/labs/virtualbox/src/main/java/org/jclouds/virtualbox/domain/BridgedIf.java index 2584986fa3..a3b2d80b40 100644 --- a/labs/virtualbox/src/main/java/org/jclouds/virtualbox/domain/BridgedIf.java +++ b/labs/virtualbox/src/main/java/org/jclouds/virtualbox/domain/BridgedIf.java @@ -166,15 +166,12 @@ public class BridgedIf { public boolean equals(Object o) { if (this == o) return true; - if (o instanceof VmSpec) { + if (o instanceof BridgedIf) { BridgedIf other = (BridgedIf) o; return Objects.equal(name, other.name) - && Objects.equal(guid, other.guid) && Objects.equal(dhcp, other.dhcp) && Objects.equal(ipAddress, other.ipAddress) && Objects.equal(networkMask, other.networkMask) - && Objects.equal(ipv6Address, other.ipv6Address) - && Objects.equal(ipv6NetworkMask, other.ipv6NetworkMask) && Objects.equal(mediumType, other.mediumType) && Objects.equal(status, other.status); } diff --git a/labs/virtualbox/src/main/java/org/jclouds/virtualbox/domain/NetworkAdapter.java b/labs/virtualbox/src/main/java/org/jclouds/virtualbox/domain/NetworkAdapter.java index 54ccac7392..9b6c203a82 100644 --- a/labs/virtualbox/src/main/java/org/jclouds/virtualbox/domain/NetworkAdapter.java +++ b/labs/virtualbox/src/main/java/org/jclouds/virtualbox/domain/NetworkAdapter.java @@ -167,10 +167,10 @@ public class NetworkAdapter { @Override public String toString() { - return "NetworkAdapter{" + "networkAttachmentType= "+ + return "NetworkAdapter{networkAttachmentType="+ networkAttachmentType + - "macAddress= " + macAddress + - "redirectRules= " + redirectRules + + ", macAddress=" + macAddress + + ", redirectRules=" + redirectRules + '}'; } } diff --git a/labs/virtualbox/src/main/java/org/jclouds/virtualbox/domain/NetworkInterfaceCard.java b/labs/virtualbox/src/main/java/org/jclouds/virtualbox/domain/NetworkInterfaceCard.java index 8d338bd108..57f565e802 100644 --- a/labs/virtualbox/src/main/java/org/jclouds/virtualbox/domain/NetworkInterfaceCard.java +++ b/labs/virtualbox/src/main/java/org/jclouds/virtualbox/domain/NetworkInterfaceCard.java @@ -101,9 +101,9 @@ public class NetworkInterfaceCard { @Override public String toString() { - return "NetworkInterfaceCard{" + "slot= "+ + return "NetworkInterfaceCard{slot="+ slot + - "networkAdapter= " + networkAdapter + + ", networkAdapter=" + networkAdapter + '}'; } diff --git a/labs/virtualbox/src/main/java/org/jclouds/virtualbox/functions/AttachNicToMachine.java b/labs/virtualbox/src/main/java/org/jclouds/virtualbox/functions/AttachNicToMachine.java index daaa28c610..586bc41afd 100644 --- a/labs/virtualbox/src/main/java/org/jclouds/virtualbox/functions/AttachNicToMachine.java +++ b/labs/virtualbox/src/main/java/org/jclouds/virtualbox/functions/AttachNicToMachine.java @@ -33,38 +33,34 @@ import com.google.common.base.Function; */ public class AttachNicToMachine implements Function { - private final String vmName; - private final MachineUtils machineUtils; + private final String vmName; + private final MachineUtils machineUtils; + public AttachNicToMachine(String vmName, MachineUtils machineUtils) { + this.vmName = checkNotNull(vmName, "vmName"); + this.machineUtils = checkNotNull(machineUtils, "machineUtils"); + } - public AttachNicToMachine(String vmName, MachineUtils machineUtils) { - this.vmName = checkNotNull(vmName, "vmName"); - this.machineUtils = checkNotNull(machineUtils, "machineUtils"); - } - - @Override + @Override public Void apply(@Nullable NetworkInterfaceCard nic) { - if(hasNatAdapter(nic)) { - return machineUtils.writeLockMachineAndApply(vmName, new AttachNATAdapterToMachineIfNotAlreadyExists(nic)); - - } else if (hasBridgedAdapter(nic)) { - return machineUtils.writeLockMachineAndApply(vmName, new AttachBridgedAdapterToMachine(nic)); + if (hasNatAdapter(nic)) { + return machineUtils.writeLockMachineAndApply(vmName, new AttachNATAdapterToMachineIfNotAlreadyExists(nic)); + } else if (hasBridgedAdapter(nic)) { + return machineUtils.writeLockMachineAndApply(vmName, new AttachBridgedAdapterToMachine(nic)); } else if (hasHostOnlyAdapter(nic)) { return machineUtils.writeLockMachineAndApply(vmName, new AttachHostOnlyAdapter(nic)); - } else - return null; - } - - private boolean hasNatAdapter(NetworkInterfaceCard nic) { - return nic.getNetworkAdapter().getNetworkAttachmentType() - .equals(NetworkAttachmentType.NAT); - } - - private boolean hasBridgedAdapter(NetworkInterfaceCard nic) { - return nic.getNetworkAdapter().getNetworkAttachmentType() - .equals(NetworkAttachmentType.Bridged); + } else + return null; } - + + private boolean hasNatAdapter(NetworkInterfaceCard nic) { + return nic.getNetworkAdapter().getNetworkAttachmentType().equals(NetworkAttachmentType.NAT); + } + + private boolean hasBridgedAdapter(NetworkInterfaceCard nic) { + return nic.getNetworkAdapter().getNetworkAttachmentType().equals(NetworkAttachmentType.Bridged); + } + private boolean hasHostOnlyAdapter(NetworkInterfaceCard nic) { return nic.getNetworkAdapter().getNetworkAttachmentType().equals(NetworkAttachmentType.HostOnly); } diff --git a/labs/virtualbox/src/main/java/org/jclouds/virtualbox/functions/CloneAndRegisterMachineFromIMachineIfNotAlreadyExists.java b/labs/virtualbox/src/main/java/org/jclouds/virtualbox/functions/CloneAndRegisterMachineFromIMachineIfNotAlreadyExists.java index 4584b6221b..0fb2f36414 100644 --- a/labs/virtualbox/src/main/java/org/jclouds/virtualbox/functions/CloneAndRegisterMachineFromIMachineIfNotAlreadyExists.java +++ b/labs/virtualbox/src/main/java/org/jclouds/virtualbox/functions/CloneAndRegisterMachineFromIMachineIfNotAlreadyExists.java @@ -112,7 +112,7 @@ public class CloneAndRegisterMachineFromIMachineIfNotAlreadyExists implements Fu IProgress progress = currentSnapshot.getMachine().cloneTo(clonedMachine, CloneMode.MachineState, options); progress.waitForCompletion(-1); - logger.debug("clone done"); + logger.debug(String.format("Machine %s is cloned correctly", clonedMachine.getName())); // registering manager.get().getVBox().registerMachine(clonedMachine); diff --git a/labs/virtualbox/src/main/java/org/jclouds/virtualbox/functions/CreateAndInstallVm.java b/labs/virtualbox/src/main/java/org/jclouds/virtualbox/functions/CreateAndInstallVm.java index bf75aa686d..ad3bc8983f 100644 --- a/labs/virtualbox/src/main/java/org/jclouds/virtualbox/functions/CreateAndInstallVm.java +++ b/labs/virtualbox/src/main/java/org/jclouds/virtualbox/functions/CreateAndInstallVm.java @@ -48,6 +48,7 @@ import org.virtualbox_4_1.IMachine; import com.google.common.base.Function; import com.google.common.base.Predicate; import com.google.common.base.Splitter; +import com.google.common.base.Throwables; import com.google.common.cache.LoadingCache; import com.google.common.collect.Iterables; import com.google.common.util.concurrent.Futures; @@ -57,98 +58,94 @@ import com.google.inject.Inject; @Singleton public class CreateAndInstallVm implements Function { - @Resource - @Named(ComputeServiceConstants.COMPUTE_LOGGER) - protected Logger logger = Logger.NULL; + @Resource + @Named(ComputeServiceConstants.COMPUTE_LOGGER) + protected Logger logger = Logger.NULL; - private final CreateAndRegisterMachineFromIsoIfNotAlreadyExists createAndRegisterMachineFromIsoIfNotAlreadyExists; - private final Predicate sshResponds; - private LoadingCache preConfiguration; - private final Function sshClientForIMachine; - private final MachineUtils machineUtils; - private final IMachineToNodeMetadata imachineToNodeMetadata; - private final MachineController machineController; - private final String version; - + private final CreateAndRegisterMachineFromIsoIfNotAlreadyExists createAndRegisterMachineFromIsoIfNotAlreadyExists; + private final Predicate sshResponds; + private LoadingCache preConfiguration; + private final Function sshClientForIMachine; + private final MachineUtils machineUtils; + private final IMachineToNodeMetadata imachineToNodeMetadata; + private final MachineController machineController; + private final String version; - @Inject - public CreateAndInstallVm( - CreateAndRegisterMachineFromIsoIfNotAlreadyExists CreateAndRegisterMachineFromIsoIfNotAlreadyExists, - IMachineToNodeMetadata imachineToNodeMetadata, - Predicate sshResponds, - Function sshClientForIMachine, - MachineUtils machineUtils, - @Preconfiguration LoadingCache preConfiguration, - MachineController machineController, @Named(Constants.PROPERTY_BUILD_VERSION) String version) { - this.createAndRegisterMachineFromIsoIfNotAlreadyExists = CreateAndRegisterMachineFromIsoIfNotAlreadyExists; - this.sshResponds = sshResponds; - this.sshClientForIMachine = sshClientForIMachine; - this.machineUtils = machineUtils; - this.preConfiguration = preConfiguration; - this.imachineToNodeMetadata = imachineToNodeMetadata; - this.machineController = machineController; - this.version = Iterables.get(Splitter.on('r').split(version), 0); - } + @Inject + public CreateAndInstallVm( + CreateAndRegisterMachineFromIsoIfNotAlreadyExists CreateAndRegisterMachineFromIsoIfNotAlreadyExists, + IMachineToNodeMetadata imachineToNodeMetadata, Predicate sshResponds, + Function sshClientForIMachine, MachineUtils machineUtils, + @Preconfiguration LoadingCache preConfiguration, MachineController machineController, + @Named(Constants.PROPERTY_BUILD_VERSION) String version) { + this.createAndRegisterMachineFromIsoIfNotAlreadyExists = CreateAndRegisterMachineFromIsoIfNotAlreadyExists; + this.sshResponds = sshResponds; + this.sshClientForIMachine = sshClientForIMachine; + this.machineUtils = machineUtils; + this.preConfiguration = preConfiguration; + this.imachineToNodeMetadata = imachineToNodeMetadata; + this.machineController = machineController; + this.version = Iterables.get(Splitter.on('r').split(version), 0); + } - @Override - public IMachine apply(MasterSpec masterSpec) { + @Override + public IMachine apply(MasterSpec masterSpec) { - VmSpec vmSpec = masterSpec.getVmSpec(); - IsoSpec isoSpec = masterSpec.getIsoSpec(); - String vmName = vmSpec.getVmName(); + VmSpec vmSpec = masterSpec.getVmSpec(); + IsoSpec isoSpec = masterSpec.getIsoSpec(); + String vmName = vmSpec.getVmName(); - IMachine vm = createAndRegisterMachineFromIsoIfNotAlreadyExists - .apply(masterSpec); + IMachine vm = createAndRegisterMachineFromIsoIfNotAlreadyExists.apply(masterSpec); - // Launch machine and wait for it to come online - machineController.ensureMachineIsLaunched(vmName); + // Launch machine and wait for it to come online + machineController.ensureMachineIsLaunched(vmName); - URI uri = preConfiguration.getUnchecked(isoSpec); - String installationKeySequence = isoSpec.getInstallationKeySequence() - .replace("PRECONFIGURATION_URL", uri.toASCIIString()); + URI uri = preConfiguration.getUnchecked(isoSpec); + String installationKeySequence = isoSpec.getInstallationKeySequence().replace("PRECONFIGURATION_URL", + uri.toASCIIString()); - configureOsInstallationWithKeyboardSequence(vmName, - installationKeySequence); - - SshClient client = sshClientForIMachine.apply(vm); + configureOsInstallationWithKeyboardSequence(vmName, installationKeySequence); - logger.debug(">> awaiting installation to finish node(%s)", vmName); + // the OS installation is a long process: let's delay the check for ssh of 30 sec + try { + Thread.sleep(30000l); + } catch (InterruptedException e) { + Throwables.propagate(e); + } + + SshClient client = sshClientForIMachine.apply(vm); - checkState(sshResponds.apply(client), - "timed out waiting for guest %s to be accessible via ssh", - vmName); + logger.debug(">> awaiting installation to finish node(%s)", vmName); - logger.debug(">> awaiting installation of guest additions on vm: %s", vmName); + checkState(sshResponds.apply(client), "timed out waiting for guest %s to be accessible via ssh", vmName); - ListenableFuture execFuture = machineUtils.runScriptOnNode(imachineToNodeMetadata.apply(vm), - new InstallGuestAdditions(vmSpec, version), RunScriptOptions.NONE); - ExecResponse execResponse = Futures.getUnchecked(execFuture); - - checkState(execResponse.getExitStatus() == 0); + NodeMetadata nodeMetadata = imachineToNodeMetadata.apply(vm); logger.debug(">> awaiting post-installation actions on vm: %s", vmName); + ListenableFuture execCleanup = machineUtils.runScriptOnNode(nodeMetadata, + call("cleanupUdevIfNeeded"), RunScriptOptions.NONE); + ExecResponse cleanupResponse = Futures.getUnchecked(execCleanup); + checkState(cleanupResponse.getExitStatus() == 0); - NodeMetadata vmMetadata = imachineToNodeMetadata.apply(vm); + + logger.debug(">> awaiting installation of guest additions on vm: %s", vmName); + ListenableFuture execInstallGA = machineUtils.runScriptOnNode(nodeMetadata, + new InstallGuestAdditions(vmSpec, version), RunScriptOptions.NONE); + ExecResponse gaInstallationResponse = Futures.getUnchecked(execInstallGA); + checkState(gaInstallationResponse.getExitStatus() == 0); - execFuture = machineUtils.runScriptOnNode(vmMetadata, call("cleanupUdevIfNeeded"), RunScriptOptions.NONE); + machineController.ensureMachineIsShutdown(vmName); - execResponse = Futures.getUnchecked(execFuture); - checkState(execResponse.getExitStatus() == 0); - - logger.debug("<< installation of image complete. Powering down node(%s)", vmName); - - machineController.ensureMachineHasPowerDown(vmName); return vm; } - private void configureOsInstallationWithKeyboardSequence(String vmName, - String installationKeySequence) { - Iterable> scancodelist = transform(Splitter.on(" ") - .split(installationKeySequence), new StringToKeyCode()); + private void configureOsInstallationWithKeyboardSequence(String vmName, String installationKeySequence) { + Iterable> scancodelist = transform(Splitter.on(" ").split(installationKeySequence), + new StringToKeyCode()); - for (List scancodes : scancodelist) { - machineUtils.sharedLockMachineAndApplyToSession(vmName,new SendScancodes(scancodes)); - } - } + for (List scancodes : scancodelist) { + machineUtils.sharedLockMachineAndApplyToSession(vmName, new SendScancodes(scancodes)); + } + } } diff --git a/labs/virtualbox/src/main/java/org/jclouds/virtualbox/functions/IMachineToNodeMetadata.java b/labs/virtualbox/src/main/java/org/jclouds/virtualbox/functions/IMachineToNodeMetadata.java index 7096aa01c0..9e99d8c2c0 100644 --- a/labs/virtualbox/src/main/java/org/jclouds/virtualbox/functions/IMachineToNodeMetadata.java +++ b/labs/virtualbox/src/main/java/org/jclouds/virtualbox/functions/IMachineToNodeMetadata.java @@ -19,12 +19,12 @@ package org.jclouds.virtualbox.functions; -import static com.google.common.base.Preconditions.checkNotNull; -import static com.google.common.base.Preconditions.checkState; import static org.jclouds.virtualbox.config.VirtualBoxComputeServiceContextModule.machineToNodeState; import static org.jclouds.virtualbox.config.VirtualBoxConstants.VIRTUALBOX_NODE_NAME_SEPARATOR; import static org.jclouds.virtualbox.config.VirtualBoxConstants.VIRTUALBOX_NODE_PREFIX; +import java.util.List; + import javax.annotation.Resource; import javax.inject.Named; @@ -37,6 +37,8 @@ import org.jclouds.domain.LocationScope; import org.jclouds.domain.LoginCredentials; import org.jclouds.javax.annotation.Nullable; import org.jclouds.logging.Logger; +import org.jclouds.virtualbox.util.MachineUtils; +import org.testng.collections.Lists; import org.virtualbox_4_1.IMachine; import org.virtualbox_4_1.INetworkAdapter; import org.virtualbox_4_1.MachineState; @@ -46,13 +48,23 @@ import com.google.common.base.Function; import com.google.common.base.Splitter; import com.google.common.collect.ImmutableSet; import com.google.common.collect.Iterables; +import com.google.inject.Inject; +import com.google.inject.Singleton; +@Singleton public class IMachineToNodeMetadata implements Function { @Resource @Named(ComputeServiceConstants.COMPUTE_LOGGER) protected Logger logger = Logger.NULL; + + private final MachineUtils machineUtils; + @Inject + public IMachineToNodeMetadata(MachineUtils machineUtils) { + this.machineUtils = machineUtils; + } + @Override public NodeMetadata apply(@Nullable IMachine vm) { @@ -85,6 +97,7 @@ public class IMachineToNodeMetadata implements Function logger.debug("Setting virtualbox node to: " + nodeState + " from machine state: " + vmState); + /* // nat adapter INetworkAdapter natAdapter = vm.getNetworkAdapter(0l); checkNotNull(natAdapter, "slot 0 networkadapter"); @@ -115,11 +128,53 @@ public class IMachineToNodeMetadata implements Function nodeMetadataBuilder.privateAddresses(ImmutableSet.of((NodeCreator.VMS_NETWORK + ipTermination) + "")); nodeMetadataBuilder.publicAddresses(ImmutableSet.of((NodeCreator.VMS_NETWORK + ipTermination) + "")); } + */ + nodeMetadataBuilder = getIpAddresses(vm, nodeMetadataBuilder); LoginCredentials loginCredentials = new LoginCredentials("toor", "password", null, true); nodeMetadataBuilder.credentials(loginCredentials); return nodeMetadataBuilder.build(); } + + private NodeMetadataBuilder getIpAddresses(IMachine vm, NodeMetadataBuilder nodeMetadataBuilder) { + List publicIpAddresses = Lists.newArrayList(); + List privateIpAddresses = Lists.newArrayList(); + + for(long slot = 0; slot < 4; slot ++) { + INetworkAdapter adapter = vm.getNetworkAdapter(slot); + if(adapter != null) { + if (adapter.getAttachmentType() == NetworkAttachmentType.NAT) { + publicIpAddresses.add(adapter.getNatDriver().getHostIP()); + for (String nameProtocolnumberAddressInboudportGuestTargetport : adapter.getNatDriver().getRedirects()) { + Iterable stuff = Splitter.on(',').split(nameProtocolnumberAddressInboudportGuestTargetport); + String protocolNumber = Iterables.get(stuff, 1); + String hostAddress = Iterables.get(stuff, 2); + String inboundPort = Iterables.get(stuff, 3); + String targetPort = Iterables.get(stuff, 5); + if ("1".equals(protocolNumber) && "22".equals(targetPort)) { + int inPort = Integer.parseInt(inboundPort); + nodeMetadataBuilder.publicAddresses(ImmutableSet.of(hostAddress)).loginPort(inPort); + } + //privateIpAddresses.add((NodeCreator.VMS_NETWORK + ipTermination) + ""); + } + // TODO this could be a public and private address + } else if (adapter.getAttachmentType() == NetworkAttachmentType.Bridged) { + String clientIpAddress = machineUtils.getIpAddressFromBridgedNIC(vm.getName()); + //privateIpAddresses.add(clientIpAddress); + publicIpAddresses.add(clientIpAddress); + + } else if (adapter.getAttachmentType() == NetworkAttachmentType.HostOnly) { + String clientIpAddress = machineUtils.getIpAddressFromHostOnlyNIC(vm.getName()); + publicIpAddresses.add(clientIpAddress); + + } + } + } + nodeMetadataBuilder.publicAddresses(publicIpAddresses); + nodeMetadataBuilder.privateAddresses(publicIpAddresses); + + return nodeMetadataBuilder; + } } diff --git a/labs/virtualbox/src/main/java/org/jclouds/virtualbox/functions/IMachineToSshClient.java b/labs/virtualbox/src/main/java/org/jclouds/virtualbox/functions/IMachineToSshClient.java index 56e05d11f7..e4ffe87a42 100644 --- a/labs/virtualbox/src/main/java/org/jclouds/virtualbox/functions/IMachineToSshClient.java +++ b/labs/virtualbox/src/main/java/org/jclouds/virtualbox/functions/IMachineToSshClient.java @@ -39,6 +39,7 @@ import org.jclouds.ssh.SshClient; import org.jclouds.virtualbox.domain.BridgedIf; import org.jclouds.virtualbox.statements.GetIPAddressFromMAC; import org.jclouds.virtualbox.statements.ScanNetworkWithPing; +import org.jclouds.virtualbox.util.MachineUtils; import org.virtualbox_4_1.IMachine; import org.virtualbox_4_1.INetworkAdapter; import org.virtualbox_4_1.NetworkAttachmentType; @@ -59,14 +60,16 @@ public class IMachineToSshClient implements Function { private final SshClient.Factory sshClientFactory; private final RunScriptOnNode.Factory scriptRunnerFactory; private final Supplier hostSupplier; + private final MachineUtils machineUtils; @Inject public IMachineToSshClient(SshClient.Factory sshClientFactory, RunScriptOnNode.Factory scriptRunnerFactory, - Supplier hostSupplier) { + Supplier hostSupplier, MachineUtils machineUtils) { this.sshClientFactory = sshClientFactory; this.scriptRunnerFactory = scriptRunnerFactory; this.hostSupplier = hostSupplier; + this.machineUtils = machineUtils; } @Override @@ -104,6 +107,9 @@ public class IMachineToSshClient implements Function { NetworkAttachmentType.Bridged)) { String network = "1.1.1.1"; clientIpAddress = getIpAddressFromBridgedNIC(networkAdapter, network); + } else if (networkAdapter.getAttachmentType().equals( + NetworkAttachmentType.HostOnly)) { + clientIpAddress = machineUtils.getIpAddressFromHostOnlyNIC(vm.getName()); } checkNotNull(clientIpAddress, "clientIpAddress"); diff --git a/labs/virtualbox/src/main/java/org/jclouds/virtualbox/functions/IMachineToVmSpec.java b/labs/virtualbox/src/main/java/org/jclouds/virtualbox/functions/IMachineToVmSpec.java index 7a1ad0fb13..14410ba1d0 100644 --- a/labs/virtualbox/src/main/java/org/jclouds/virtualbox/functions/IMachineToVmSpec.java +++ b/labs/virtualbox/src/main/java/org/jclouds/virtualbox/functions/IMachineToVmSpec.java @@ -79,13 +79,15 @@ public class IMachineToVmSpec implements Function { for (IMediumAttachment iMediumAttachment : machine.getMediumAttachmentsOfController(iStorageController .getName())) { IMedium iMedium = iMediumAttachment.getMedium(); - if (iMedium.getDeviceType().equals(DeviceType.HardDisk)) { - storageControlleBuiler.attachHardDisk(HardDisk.builder().diskpath(iMedium.getLocation()) - .autoDelete(true).controllerPort(iMediumAttachment.getPort()) - .deviceSlot(iMediumAttachment.getDevice().intValue()).build()); - } else if (iMedium.getDeviceType().equals(DeviceType.DVD)) { - storageControlleBuiler.attachISO(iMediumAttachment.getPort(), iMediumAttachment.getDevice().intValue(), - iMedium.getLocation()); + if(iMedium != null) { + if (iMedium.getDeviceType().equals(DeviceType.HardDisk)) { + storageControlleBuiler.attachHardDisk(HardDisk.builder().diskpath(iMedium.getLocation()) + .autoDelete(true).controllerPort(iMediumAttachment.getPort()) + .deviceSlot(iMediumAttachment.getDevice().intValue()).build()); + } else if (iMedium.getDeviceType().equals(DeviceType.DVD)) { + storageControlleBuiler.attachISO(iMediumAttachment.getPort(), iMediumAttachment.getDevice().intValue(), + iMedium.getLocation()); + } } } controllers.add(storageControlleBuiler.name(iStorageController.getName()).bus(iStorageController.getBus()) diff --git a/labs/virtualbox/src/main/java/org/jclouds/virtualbox/functions/LaunchMachineIfNotAlreadyRunning.java b/labs/virtualbox/src/main/java/org/jclouds/virtualbox/functions/LaunchMachineIfNotAlreadyRunning.java index df6af1e5e8..9c9ee59aa7 100644 --- a/labs/virtualbox/src/main/java/org/jclouds/virtualbox/functions/LaunchMachineIfNotAlreadyRunning.java +++ b/labs/virtualbox/src/main/java/org/jclouds/virtualbox/functions/LaunchMachineIfNotAlreadyRunning.java @@ -30,6 +30,7 @@ import org.jclouds.virtualbox.domain.ErrorCode; import org.jclouds.virtualbox.domain.ExecutionType; import org.virtualbox_4_1.IMachine; import org.virtualbox_4_1.IProgress; +import org.virtualbox_4_1.ISession; import org.virtualbox_4_1.SessionState; import org.virtualbox_4_1.VBoxException; import org.virtualbox_4_1.VirtualBoxManager; @@ -52,7 +53,7 @@ import com.google.common.base.Function; * @author Mattias Holmqvist * @see ErrorCode */ -public class LaunchMachineIfNotAlreadyRunning implements Function { +public class LaunchMachineIfNotAlreadyRunning implements Function { @Resource @Named(ComputeServiceConstants.COMPUTE_LOGGER) @@ -69,14 +70,17 @@ public class LaunchMachineIfNotAlreadyRunning implements Function { // TODO parameterize public static final int MASTER_PORT = 2222; + public static final String HOST_ONLY_IFACE_NAME = "vboxnet0"; @Resource @Named(ComputeServiceConstants.COMPUTE_LOGGER) @@ -170,7 +171,7 @@ public class MastersLoadingCache extends AbstractLoadingCache { NetworkInterfaceCard networkInterfaceCard = NetworkInterfaceCard.builder().addNetworkAdapter(networkAdapter) .slot(0L).build(); - + NetworkSpec networkSpec = NetworkSpec.builder().addNIC(networkInterfaceCard).build(); MasterSpec masterSpec = MasterSpec diff --git a/labs/virtualbox/src/main/java/org/jclouds/virtualbox/functions/NodeCreator.java b/labs/virtualbox/src/main/java/org/jclouds/virtualbox/functions/NodeCreator.java index e94645327d..a7f2ff9ded 100644 --- a/labs/virtualbox/src/main/java/org/jclouds/virtualbox/functions/NodeCreator.java +++ b/labs/virtualbox/src/main/java/org/jclouds/virtualbox/functions/NodeCreator.java @@ -1,4 +1,4 @@ -/** + /** * Licensed to jclouds, Inc. (jclouds) under one or more * contributor license agreements. See the NOTICE file * distributed with this work for additional information @@ -20,21 +20,26 @@ package org.jclouds.virtualbox.functions; import static com.google.common.base.Preconditions.checkNotNull; +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_IMAGE_PREFIX; import static org.jclouds.virtualbox.config.VirtualBoxConstants.VIRTUALBOX_NODE_NAME_SEPARATOR; import static org.jclouds.virtualbox.config.VirtualBoxConstants.VIRTUALBOX_NODE_PREFIX; -import java.util.concurrent.atomic.AtomicInteger; +import java.util.List; import javax.inject.Inject; import javax.inject.Singleton; import org.jclouds.compute.ComputeServiceAdapter.NodeAndInitialCredentials; import org.jclouds.compute.callables.RunScriptOnNode; +import org.jclouds.compute.callables.RunScriptOnNode.Factory; +import org.jclouds.compute.domain.ExecResponse; import org.jclouds.compute.domain.NodeMetadata; import org.jclouds.compute.domain.NodeMetadataBuilder; import org.jclouds.compute.options.RunScriptOptions; import org.jclouds.domain.LoginCredentials; +import org.jclouds.scriptbuilder.domain.Statements; import org.jclouds.virtualbox.config.VirtualBoxComputeServiceContextModule; import org.jclouds.virtualbox.domain.CloneSpec; import org.jclouds.virtualbox.domain.Master; @@ -44,19 +49,21 @@ import org.jclouds.virtualbox.domain.NetworkSpec; import org.jclouds.virtualbox.domain.NodeSpec; import org.jclouds.virtualbox.domain.VmSpec; import org.jclouds.virtualbox.statements.DeleteGShadowLock; -import org.jclouds.virtualbox.statements.SetIpAddress; +import org.jclouds.virtualbox.statements.EnableNetworkInterface; import org.jclouds.virtualbox.util.MachineController; import org.jclouds.virtualbox.util.MachineUtils; import org.virtualbox_4_1.CleanupMode; +import org.virtualbox_4_1.HostNetworkInterfaceType; +import org.virtualbox_4_1.IDHCPServer; +import org.virtualbox_4_1.IHostNetworkInterface; import org.virtualbox_4_1.IMachine; -import org.virtualbox_4_1.INetworkAdapter; import org.virtualbox_4_1.IProgress; import org.virtualbox_4_1.ISession; import org.virtualbox_4_1.NetworkAttachmentType; import org.virtualbox_4_1.VirtualBoxManager; import com.google.common.base.Function; -import com.google.common.base.Splitter; +import com.google.common.base.Predicate; import com.google.common.base.Supplier; import com.google.common.collect.ImmutableSet; import com.google.common.collect.Iterables; @@ -65,38 +72,29 @@ import com.google.common.collect.Iterables; * Creates nodes, by cloning a master vm and based on the provided {@link NodeSpec}. Must be * synchronized mainly because of snapshot creation (must be synchronized on a per-master-basis). * - * @author David Alves + * @author David Alves, Andrea Turli * */ @Singleton public class NodeCreator implements Function> { - // TODO parameterize - public static final int NODE_PORT_INIT = 3000; - - // TODO parameterize - public static final String VMS_NETWORK = "192.168.86."; - - // TODO parameterize - public static final String HOST_ONLY_IFACE_NAME = "vboxnet0"; - - // TODO parameterize - public static final boolean USE_LINKED = true; - private final Supplier manager; private final Function cloner; - private final AtomicInteger nodePorts; - private final AtomicInteger nodeIps; private final MachineUtils machineUtils; private final MachineController machineController; + private final Factory runScriptOnNodeFactory; + private final Supplier host; + @Inject - public NodeCreator(Supplier manager, Function cloner, + public NodeCreator(Supplier manager, Function cloner, Factory runScriptOnNodeFactory, + Supplier host, MachineUtils machineUtils, RunScriptOnNode.Factory scriptRunnerFactory, MachineController machineController) { this.manager = manager; this.cloner = cloner; - this.nodePorts = new AtomicInteger(NODE_PORT_INIT); - this.nodeIps = new AtomicInteger(2); + this.runScriptOnNodeFactory = checkNotNull(runScriptOnNodeFactory, "runScriptOnNodeFactory"); + this.host = checkNotNull(host, "host"); + this.machineUtils = machineUtils; this.machineController = machineController; } @@ -130,18 +128,21 @@ public class NodeCreator implements Function stuff = Splitter.on(',').split(nameProtocolnumberAddressInboudportGuestTargetport); - String protocolNumber = Iterables.get(stuff, 1); - String inboundPort = Iterables.get(stuff, 3); - String targetPort = Iterables.get(stuff, 5); - if ("1".equals(protocolNumber) && "22".equals(targetPort)) { - int inPort = Integer.parseInt(inboundPort); - nodeMetadataBuilder.loginPort(inPort); - } - } + nodeMetadataBuilder.publicAddresses(ImmutableSet.of(machineUtils.getIpAddressFromHostOnlyNIC(clone.getName()))); LoginCredentials loginCredentials = new LoginCredentials("toor", "password", null, true); nodeMetadataBuilder.credentials(loginCredentials); @@ -194,5 +184,94 @@ public class NodeCreator implements Function availableNetworkInterfaces = manager.get().getVBox().getHost() + .getNetworkInterfaces(); + + IHostNetworkInterface iHostNetworkInterfaceWithHostOnlyIfName = Iterables.getOnlyElement(Iterables.filter(availableNetworkInterfaces, new Predicate() { + + @Override + public boolean apply(IHostNetworkInterface iHostNetworkInterface) { + return iHostNetworkInterface.getName().equals(hostOnlyIfName); + } + })); + + String hostOnlyIfIpAddress = iHostNetworkInterfaceWithHostOnlyIfName.getIPAddress(); + String dhcpIpAddress = hostOnlyIfIpAddress.substring(0, hostOnlyIfIpAddress.lastIndexOf(".")) + ".254"; + String dhcpNetmask = "255.255.255.0"; + String dhcpLowerIp = hostOnlyIfIpAddress.substring(0, hostOnlyIfIpAddress.lastIndexOf(".")) + ".2"; + String dhcpUpperIp = hostOnlyIfIpAddress.substring(0, hostOnlyIfIpAddress.lastIndexOf(".")) + ".253"; + + ExecResponse response = runScriptOnNodeFactory + .create(host.get(), + Statements.exec(String + .format("VBoxManage dhcpserver add --ifname %s --ip %s --netmask %s --lowerip %s --upperip %s --enable", + hostOnlyIfName, dhcpIpAddress, dhcpNetmask, dhcpLowerIp, dhcpUpperIp)), runAsRoot(false).wrapInInitScript(false)).init().call(); + checkState(response.getExitStatus()==0); + /* + runScriptOnNodeFactory + .create(host.get(), + Statements.exec(String.format("VBoxManage hostonlyif ipconfig %s --ip %s", + hostOnlyIfName, hostOnlyIfIpAddress)), runAsRoot(false).wrapInInitScript(false)).init().call(); + */ + } + + private String createHostOnlyIf() { + final String hostOnlyIfName; + ExecResponse createHostOnyResponse = runScriptOnNodeFactory + .create(host.get(), Statements.exec("VBoxManage hostonlyif create"), + runAsRoot(false).wrapInInitScript(false)).init().call(); + String output = createHostOnyResponse.getOutput(); + checkState(createHostOnyResponse.getExitStatus()==0); + checkState(output.contains("'"), "cannot create hostonlyif"); + hostOnlyIfName = output.substring(output.indexOf("'") + 1, output.lastIndexOf("'")); + return hostOnlyIfName; + } + + private IHostNetworkInterface returnExistingHostNetworkInterfaceWithDHCPenabledOrNull(Iterable availableNetworkInterfaces) { + checkNotNull(availableNetworkInterfaces); + return Iterables.getFirst(filterAvailableNetworkInterfaceByHostOnlyAndDHCPenabled(availableNetworkInterfaces), null); + } + + /** + * @param availableNetworkInterfaces + * @param hostOnlyIfIpAddress + * @return + */ + private Iterable filterAvailableNetworkInterfaceByHostOnlyAndDHCPenabled(Iterable availableNetworkInterfaces) { + Iterable filteredNetworkInterfaces = Iterables.filter(availableNetworkInterfaces, new Predicate() { + @Override + public boolean apply(IHostNetworkInterface iHostNetworkInterface) { + // this is an horrible workaround cause iHostNetworkInterface.getDhcpEnabled is working only for windows host + boolean match = false; + List availableDHCPservers = manager.get().getVBox().getDHCPServers(); + for (IDHCPServer idhcpServer : availableDHCPservers) { + if(idhcpServer.getEnabled() && idhcpServer.getNetworkName().equals(iHostNetworkInterface.getNetworkName())) + match = true; + } + return iHostNetworkInterface.getInterfaceType().equals(HostNetworkInterfaceType.HostOnly) && + match; + } + }); + return filteredNetworkInterfaces; + } } diff --git a/labs/virtualbox/src/main/java/org/jclouds/virtualbox/functions/admin/ImagesToYamlImagesFromYamlDescriptor.java b/labs/virtualbox/src/main/java/org/jclouds/virtualbox/functions/admin/ImagesToYamlImagesFromYamlDescriptor.java index 80c5195741..5d0b373c80 100644 --- a/labs/virtualbox/src/main/java/org/jclouds/virtualbox/functions/admin/ImagesToYamlImagesFromYamlDescriptor.java +++ b/labs/virtualbox/src/main/java/org/jclouds/virtualbox/functions/admin/ImagesToYamlImagesFromYamlDescriptor.java @@ -30,6 +30,7 @@ import javax.inject.Singleton; import org.jclouds.compute.domain.Image; import org.jclouds.virtualbox.domain.YamlImage; +import org.jclouds.virtualbox.functions.YamlImagesFromFileConfig; import org.yaml.snakeyaml.Loader; import org.yaml.snakeyaml.TypeDescription; import org.yaml.snakeyaml.Yaml; @@ -47,7 +48,7 @@ public class ImagesToYamlImagesFromYamlDescriptor implements Supplier yamlDescriptorSupplier) { + public ImagesToYamlImagesFromYamlDescriptor(/*Supplier yamlDescriptorSupplier*/YamlImagesFromFileConfig yamlDescriptorSupplier) { this.yamlDescriptor = yamlDescriptorSupplier.get(); checkNotNull(yamlDescriptor, "yaml descriptor"); checkState(!yamlDescriptor.equals(""), "yaml descriptor is empty"); diff --git a/labs/virtualbox/src/main/java/org/jclouds/virtualbox/statements/EnableNetworkInterface.java b/labs/virtualbox/src/main/java/org/jclouds/virtualbox/statements/EnableNetworkInterface.java new file mode 100644 index 0000000000..224fd2f7f8 --- /dev/null +++ b/labs/virtualbox/src/main/java/org/jclouds/virtualbox/statements/EnableNetworkInterface.java @@ -0,0 +1,88 @@ +/** + * 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.exec; + +import java.util.List; + +import org.jclouds.scriptbuilder.domain.OsFamily; +import org.jclouds.scriptbuilder.domain.Statement; +import org.jclouds.scriptbuilder.domain.StatementList; +import org.jclouds.virtualbox.domain.NetworkInterfaceCard; +import org.testng.collections.Lists; + +/** + * Up the network interface chosen + * + * @author Andrea Turli + * + */ +public class EnableNetworkInterface implements Statement { + + private final StatementList statements; + + public EnableNetworkInterface(NetworkInterfaceCard networkInterfaceCard) { + int slot = (int) networkInterfaceCard.getSlot(); + String iface = null; + switch (slot) { + case 0: + iface = "eth0"; + break; + case 1: + iface = "eth1"; + break; + case 2: + iface = "eth2"; + break; + case 3: + iface = "eth3"; + break; + default: + throw new IllegalArgumentException("slot must be 0,1,2,3 (was: " + slot + ")"); + } + this.statements = new StatementList(getStatements(iface)); + } + + private List getStatements(String iface) { + /* + * auto eth0 + */ + List statements = Lists.newArrayList(); + statements.add(exec(String.format("echo auto %s >> /etc/network/interfaces", iface))); // + statements.add(exec(String.format("echo iface %s inet dhcp >> /etc/network/interfaces", iface))); // + statements.add(exec("/etc/init.d/networking restart")); + return statements; + } + + @Override + public Iterable functionDependencies(OsFamily family) { + return statements.functionDependencies(family); + } + + @Override + public String render(OsFamily family) { + if (checkNotNull(family, "family") == OsFamily.WINDOWS) + throw new UnsupportedOperationException("windows not yet implemented"); + return statements.render(family); + } + +} diff --git a/labs/virtualbox/src/main/java/org/jclouds/virtualbox/statements/InstallGuestAdditions.java b/labs/virtualbox/src/main/java/org/jclouds/virtualbox/statements/InstallGuestAdditions.java index 2f85e40625..06d4ec128e 100644 --- a/labs/virtualbox/src/main/java/org/jclouds/virtualbox/statements/InstallGuestAdditions.java +++ b/labs/virtualbox/src/main/java/org/jclouds/virtualbox/statements/InstallGuestAdditions.java @@ -88,6 +88,10 @@ public class InstallGuestAdditions implements Statement { statements.add(exec(String.format("mount -o loop {tmp}{fs}%s %s", vboxGuestAdditionsIso, mountPoint))); } statements.add(exec(String.format("%s%s", mountPoint, "/VBoxLinuxAdditions.run"))); // + statements.add(exec("service vboxadd setup")); // + statements.add(exec("VBoxService")); // + statements.add(exec(String.format("echo VBoxService > /etc/rc.local"))); // + statements.add(exec(String.format("echo exit 0 >> /etc/rc.local"))); // statements.add(exec(String.format("umount %s", mountPoint))); return statements; } diff --git a/labs/virtualbox/src/main/java/org/jclouds/virtualbox/util/MachineController.java b/labs/virtualbox/src/main/java/org/jclouds/virtualbox/util/MachineController.java index 548534d7b0..3a59f68f18 100644 --- a/labs/virtualbox/src/main/java/org/jclouds/virtualbox/util/MachineController.java +++ b/labs/virtualbox/src/main/java/org/jclouds/virtualbox/util/MachineController.java @@ -18,6 +18,8 @@ */ package org.jclouds.virtualbox.util; +import static com.google.common.base.Preconditions.checkNotNull; + import javax.annotation.Resource; import javax.inject.Named; import javax.inject.Singleton; @@ -28,11 +30,13 @@ import org.jclouds.virtualbox.domain.ExecutionType; import org.jclouds.virtualbox.functions.LaunchMachineIfNotAlreadyRunning; import org.virtualbox_4_1.IProgress; import org.virtualbox_4_1.ISession; +import org.virtualbox_4_1.LockType; +import org.virtualbox_4_1.MachineState; import org.virtualbox_4_1.VirtualBoxManager; -import org.virtualbox_4_1.jaxws.MachineState; import com.google.common.base.Function; import com.google.common.base.Supplier; +import com.google.common.base.Throwables; import com.google.inject.Inject; /** @@ -52,7 +56,6 @@ public class MachineController { private final MachineUtils machineUtils; private final ExecutionType executionType; - @Inject public MachineController(Supplier manager, MachineUtils machineUtils, ExecutionType executionType) { this.manager = manager; @@ -60,32 +63,128 @@ public class MachineController { this.executionType = executionType; } - public void ensureMachineIsLaunched(String vmName) { - machineUtils.applyForMachine(vmName, new LaunchMachineIfNotAlreadyRunning(manager.get(), executionType, "")); - } + public ISession ensureMachineIsLaunched(String vmName) { + ISession session = null; + while (!manager.get().getVBox().findMachine(vmName).getState().equals(MachineState.Running)) { + try { + session = machineUtils.applyForMachine(vmName, new LaunchMachineIfNotAlreadyRunning(manager.get(), + executionType, "")); + } catch (RuntimeException e) { + if (e.getMessage().contains( + "org.virtualbox_4_1.VBoxException: VirtualBox error: The given session is busy (0x80BB0007)")) { + throw e; + } else if (e.getMessage().contains("VirtualBox error: The object is not ready")) { + continue; + } else { + throw e; + } + } + } + return checkNotNull(session, "session"); + } + + public ISession ensureMachineHasPowerDown(String vmName) { + ISession session = manager.get().getSessionObject(); + while (!manager.get().getVBox().findMachine(vmName).getState().equals(MachineState.PoweredOff)) { + try { + session = machineUtils.lockSessionOnMachineAndApply(vmName, LockType.Shared, + new Function() { + @Override + public ISession apply(ISession session) { + IProgress powerDownProgress = session.getConsole().powerDown(); + powerDownProgress.waitForCompletion(-1); + return session; + } + }); + } catch (RuntimeException e) { + // sometimes the machine might be powered of between the while + // test and the call to + // lockSessionOnMachineAndApply + if (e.getMessage().contains("Invalid machine state: PoweredOff")) { + throw e; + } else if (e.getMessage().contains("VirtualBox error: The object is not ready")) { + continue; + } else { + throw e; + } + } + } + return checkNotNull(session, "session"); + } - public void ensureMachineHasPowerDown(String vmName) { - while (!manager.get().getVBox().findMachine(vmName).getState().equals(MachineState.POWERED_OFF)) { - try { - machineUtils.sharedLockMachineAndApplyToSession(vmName, new Function() { - @Override - public Void apply(ISession session) { - IProgress powerDownProgress = session.getConsole().powerDown(); - powerDownProgress.waitForCompletion(-1); - return null; - } - }); - } catch (RuntimeException e) { - // sometimes the machine might be powered of between the while test and the call to - // lockSessionOnMachineAndApply - if (e.getMessage().contains("Invalid machine state: PoweredOff")) { - return; - } else if (e.getMessage().contains("VirtualBox error: The object is not ready")) { - continue; - } else { - throw e; - } - } - } - } + /** + * if machine supports ACPI it can be shutdown gently - not powerdown() + * http://askubuntu.com/questions/82015/shutting-down-ubuntu-server-running-in-headless-virtualbox + */ + public ISession ensureMachineIsShutdown(String vmName) { + ISession session = machineUtils.lockSessionOnMachineAndApply(vmName, LockType.Shared, + new Function() { + @Override + public ISession apply(ISession session) { + session.getConsole().powerButton(); + return session; + } + }); + int count = 0; + while (!manager.get().getVBox().findMachine(vmName).getState().equals(MachineState.PoweredOff) && count < 10) { + try { + Thread.sleep(500l * count); + } catch (InterruptedException e) { + Throwables.propagate(e); + } + count++; + } + return checkNotNull(session, "session"); + } + + public void ensureMachineIsPaused(String vmName) { + while (!manager.get().getVBox().findMachine(vmName).getState().equals(MachineState.Paused)) { + try { + machineUtils.lockSessionOnMachineAndApply(vmName, LockType.Shared, new Function() { + @Override + public Void apply(ISession session) { + session.getConsole().pause(); + return null; + } + }); + } catch (RuntimeException e) { + // sometimes the machine might be powered of between the while + // test and the call to + // lockSessionOnMachineAndApply + if (e.getMessage().contains("Invalid machine state: Paused")) { + return; + } else if (e.getMessage().contains("VirtualBox error: The object is not ready")) { + continue; + } else { + throw e; + } + } + } + } + + public void ensureMachineIsResumed(String vmName) { + while (!manager.get().getVBox().findMachine(vmName).getState().equals(MachineState.Running)) { + try { + machineUtils.lockSessionOnMachineAndApply(vmName, LockType.Shared, new Function() { + @Override + public Void apply(ISession session) { + session.getConsole().resume(); + return null; + } + }); + } catch (RuntimeException e) { + // sometimes the machine might be powered of between the while + // test and the call to + // lockSessionOnMachineAndApply + if (e.getMessage().contains("Invalid machine state: Resumed")) { + return; + } else if (e.getMessage().contains("VirtualBox error: The object is not ready")) { + continue; + } else { + throw e; + } + } + } + } + } diff --git a/labs/virtualbox/src/main/java/org/jclouds/virtualbox/util/MachineUtils.java b/labs/virtualbox/src/main/java/org/jclouds/virtualbox/util/MachineUtils.java index 296f175b71..26133e05ad 100644 --- a/labs/virtualbox/src/main/java/org/jclouds/virtualbox/util/MachineUtils.java +++ b/labs/virtualbox/src/main/java/org/jclouds/virtualbox/util/MachineUtils.java @@ -18,6 +18,12 @@ */ package org.jclouds.virtualbox.util; +import static com.google.common.base.Preconditions.checkNotNull; +import static com.google.common.base.Preconditions.checkState; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + import javax.annotation.Resource; import javax.inject.Named; import javax.inject.Singleton; @@ -34,11 +40,13 @@ import org.jclouds.util.Throwables2; import org.virtualbox_4_1.IMachine; import org.virtualbox_4_1.ISession; import org.virtualbox_4_1.LockType; +import org.virtualbox_4_1.SessionState; 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.common.base.Throwables; import com.google.common.util.concurrent.ListenableFuture; import com.google.inject.Inject; @@ -50,7 +58,11 @@ import com.google.inject.Inject; @Singleton public class MachineUtils { - + + public final String IP_V4_ADDRESS_PATTERN = "^([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\." + + "([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\." + "([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\." + + "([01]?\\d\\d?|2[0-4]\\d|25[0-5])$"; + @Resource @Named(ComputeServiceConstants.COMPUTE_LOGGER) protected Logger logger = Logger.NULL; @@ -178,11 +190,23 @@ public class MachineUtils { * the function to execute * @return the result from applying the function to the session. */ - private T lockSessionOnMachineAndApply(String machineId, LockType type, Function function) { - int retries = 5; + protected T lockSessionOnMachineAndApply(String machineId, LockType type, Function function) { + int retries = 15; + ISession session = lockSession(machineId, type, retries); + try { + return function.apply(session); + } catch (VBoxException e) { + throw new RuntimeException(String.format("error applying %s to %s with %s lock: %s", function, machineId, + type, e.getMessage()), e); + } finally { + if (session != null && session.getState().equals(SessionState.Locked)) + session.unlockMachine(); + } + } + + private ISession lockSession(String machineId, LockType type, int retries) { int count = 0; ISession session; - long time = System.currentTimeMillis(); while (true) { try { IMachine immutableMachine = manager.get().getVBox().findMachine(machineId); @@ -206,14 +230,8 @@ public class MachineUtils { } } } - try { - return function.apply(session); - } catch (VBoxException e) { - throw new RuntimeException(String.format("error applying %s to %s with %s lock: %s", function, machineId, - type, e.getMessage()), e); - } finally { - session.unlockMachine(); - } + checkState(session.getState().equals(SessionState.Locked)); + return checkNotNull(session, "session"); } void print() { @@ -246,4 +264,71 @@ public class MachineUtils { return e.getMessage().contains("VirtualBox error: Could not find a registered machine named ") || e.getMessage().contains("Could not find a registered machine with UUID {"); } + + public String getIpAddressFromBridgedNIC(String machineName) { + String ip = ""; + int attempt = 0; + while (!isIpv4(ip) && attempt < 10) { + ip = this.lockSessionOnMachineAndApply(machineName, LockType.Shared, new Function() { + @Override + public String apply(ISession session) { + String ip = session.getMachine().getGuestPropertyValue("/VirtualBox/GuestInfo/Net/0/V4/IP"); + return ip; + } + }); + attempt++; + long sleepTime = 1000 * attempt; + logger.debug("Instance %s is still not ready. Attempt n:%d. Sleeping for %d millisec", machineName, attempt, + sleepTime); + try { + Thread.sleep(sleepTime); + } catch (InterruptedException e) { + Throwables.propagate(e); + } + } + return ip; + } + + private boolean isIpv4(String s) { + Pattern pattern = Pattern.compile(this.IP_V4_ADDRESS_PATTERN); + Matcher matcher = pattern.matcher(s); + return matcher.matches(); + } + + public String getIpAddressFromHostOnlyNIC(String machineName) { + // TODO using a caching mechanism to avoid to call everytime this vboxmanage api call + String currentIp = "", previousIp = "1.1.1.1"; + int attempt = 0, count = 0; + while(count < 5) { + currentIp = ""; + attempt = 0; + while (!isIpv4(currentIp) && attempt < 5) { + currentIp = this.lockSessionOnMachineAndApply(machineName, LockType.Shared, new Function() { + @Override + public String apply(ISession session) { + return session.getMachine().getGuestPropertyValue("/VirtualBox/GuestInfo/Net/0/V4/IP"); + } + }); + attempt++; + } + if(previousIp.equals(currentIp)) { + count++; + delayer(500l * (count + 1)); + } else { + count = 0; + delayer(5000l); + } + previousIp = currentIp; + } + return currentIp; + } + + private void delayer(long millisec) { + try { + Thread.sleep(millisec); + } catch (InterruptedException e) { + Throwables.propagate(e); + } + } + } diff --git a/labs/virtualbox/src/main/resources/functions/cleanupUdevIfNeeded.sh b/labs/virtualbox/src/main/resources/functions/cleanupUdevIfNeeded.sh index 5c8d269744..fcc3618e80 100644 --- a/labs/virtualbox/src/main/resources/functions/cleanupUdevIfNeeded.sh +++ b/labs/virtualbox/src/main/resources/functions/cleanupUdevIfNeeded.sh @@ -1,12 +1,9 @@ function cleanupUdevIfNeeded { -# unset OSNAME; -# local OSNAME=`lsb_release -d -s | cut -d ' ' -f 1`; shift -# if [ $OSNAME = 'Ubuntu' ] - if [ -f '/etc/udev/rules.d/70-persistent-net.rules'] + if [ -f '/etc/udev/rules.d/70-persistent-net.rules' ] then - rm /etc/udev/rules.d/70-persistent-net.rules; - mkdir /etc/udev/rules.d/70-persistent-net.rules; - rm -rf /dev/.udev/; + rm /etc/udev/rules.d/70-persistent-net.rules + mkdir /etc/udev/rules.d/70-persistent-net.rules + rm -rf /dev/.udev/ rm /lib/udev/rules.d/75-persistent-net-generator.rules fi } \ No newline at end of file diff --git a/labs/virtualbox/src/main/resources/functions/installModuleAssistantIfNeeded.sh b/labs/virtualbox/src/main/resources/functions/installModuleAssistantIfNeeded.sh index a6b71f03ba..e3c73dca77 100644 --- a/labs/virtualbox/src/main/resources/functions/installModuleAssistantIfNeeded.sh +++ b/labs/virtualbox/src/main/resources/functions/installModuleAssistantIfNeeded.sh @@ -4,11 +4,8 @@ function installModuleAssistantIfNeeded { if [ $OSNAME = 'Ubuntu' ] then echo "OS is Ubuntu" - apt-get -f -y -qq --force-yes install build-essential module-assistant; + apt-get -f -y -qq --force-yes install dkms build-essential linux-headers-`uname -r` module-assistant acpid; m-a prepare -i - rm /etc/udev/rules.d/70-persistent-net.rules; - mkdir /etc/udev/rules.d/70-persistent-net.rules; - rm -rf /dev/.udev/; - rm /lib/udev/rules.d/75-persistent-net-generator.rules + return 0 fi } \ No newline at end of file diff --git a/labs/virtualbox/src/test/java/org/jclouds/virtualbox/BaseVirtualBoxClientLiveTest.java b/labs/virtualbox/src/test/java/org/jclouds/virtualbox/BaseVirtualBoxClientLiveTest.java index 4c082ffc24..75ab267429 100644 --- a/labs/virtualbox/src/test/java/org/jclouds/virtualbox/BaseVirtualBoxClientLiveTest.java +++ b/labs/virtualbox/src/test/java/org/jclouds/virtualbox/BaseVirtualBoxClientLiveTest.java @@ -20,6 +20,7 @@ package org.jclouds.virtualbox; import static com.google.common.base.Preconditions.checkNotNull; +import static org.jclouds.virtualbox.config.VirtualBoxConstants.VIRTUALBOX_INSTALLATION_KEY_SEQUENCE; import java.io.File; import java.net.URI; @@ -38,25 +39,41 @@ import org.jclouds.compute.domain.Template; import org.jclouds.compute.strategy.PrioritizeCredentialsFromTemplate; import org.jclouds.concurrent.MoreExecutors; import org.jclouds.concurrent.config.ExecutorServiceModule; +import org.jclouds.config.ValueOfConfigurationKeyOrNull; import org.jclouds.logging.slf4j.config.SLF4JLoggingModule; import org.jclouds.sshj.config.SshjSshClientModule; import org.jclouds.virtualbox.config.VirtualBoxConstants; +import org.jclouds.virtualbox.domain.HardDisk; import org.jclouds.virtualbox.domain.IsoSpec; import org.jclouds.virtualbox.domain.Master; +import org.jclouds.virtualbox.domain.MasterSpec; +import org.jclouds.virtualbox.domain.NetworkAdapter; +import org.jclouds.virtualbox.domain.NetworkInterfaceCard; +import org.jclouds.virtualbox.domain.NetworkSpec; +import org.jclouds.virtualbox.domain.StorageController; import org.jclouds.virtualbox.domain.VmSpec; +import org.jclouds.virtualbox.functions.IMachineToVmSpec; import org.jclouds.virtualbox.functions.admin.UnregisterMachineIfExistsAndDeleteItsMedia; import org.jclouds.virtualbox.util.MachineController; import org.jclouds.virtualbox.util.MachineUtils; import org.testng.annotations.AfterClass; import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; +import org.virtualbox_4_1.CleanupMode; +import org.virtualbox_4_1.IMachine; +import org.virtualbox_4_1.NetworkAttachmentType; +import org.virtualbox_4_1.SessionState; +import org.virtualbox_4_1.StorageBus; +import org.virtualbox_4_1.VBoxException; import org.virtualbox_4_1.VirtualBoxManager; +import com.google.common.base.Function; import com.google.common.base.Splitter; import com.google.common.base.Supplier; import com.google.common.cache.LoadingCache; import com.google.common.collect.ImmutableSet; import com.google.common.collect.Iterables; +import com.google.inject.Injector; import com.google.inject.Module; /** @@ -146,18 +163,69 @@ public class BaseVirtualBoxClientLiveTest extends BaseVersionedServiceLiveTest { checkNotNull(mastersCache.apply(template.getImage())); } + protected void undoVm(String vmNameOrId) { + IMachine vm = null; + try { + vm = manager.get().getVBox().findMachine(vmNameOrId); + VmSpec vmSpec = new IMachineToVmSpec().apply(vm); + int attempts = 0; + while (attempts < 10 && !vm.getSessionState().equals(SessionState.Unlocked)) { + attempts++; + try { + Thread.sleep(200l); + } catch (InterruptedException e) { + } + } + machineUtils.applyForMachine(vmNameOrId, new UnregisterMachineIfExistsAndDeleteItsMedia(vmSpec)); - protected void undoVm(VmSpec vmSpecification) { - machineUtils.writeLockMachineAndApply(vmSpecification.getVmId(), new UnregisterMachineIfExistsAndDeleteItsMedia( - vmSpecification)); + } catch (VBoxException e) { + if (e.getMessage().contains("Could not find a registered machine named")) + return; + } } - - public String adminDisk(String vmName) { return workingDir + File.separator + vmName + ".vdi"; } + public MasterSpec getMasterSpecForTest() { + String masterName = "jclouds-image-0x0-default-ubuntu-11.04-i386"; + StorageController ideController = StorageController + .builder() + .name("IDE Controller") + .bus(StorageBus.IDE) + .attachISO(0, 0, operatingSystemIso) + .attachHardDisk( + HardDisk.builder().diskpath(adminDisk(masterName)).controllerPort(0).deviceSlot(1) + .autoDelete(true).build()).attachISO(1, 0, guestAdditionsIso).build(); + + VmSpec sourceVmSpec = VmSpec.builder().id(masterName).name(masterName) + .osTypeId("").memoryMB(512).cleanUpMode(CleanupMode.Full) + .controller(ideController).forceOverwrite(true).build(); + + Injector injector = context.utils().injector(); + Function configProperties = injector + .getInstance(ValueOfConfigurationKeyOrNull.class); + IsoSpec isoSpec = IsoSpec + .builder() + .sourcePath(operatingSystemIso) + .installationScript( + configProperties.apply( + VIRTUALBOX_INSTALLATION_KEY_SEQUENCE).replace( + "HOSTNAME", sourceVmSpec.getVmName())).build(); + + NetworkAdapter networkAdapter = NetworkAdapter.builder() + .networkAttachmentType(NetworkAttachmentType.NAT) + .tcpRedirectRule("127.0.0.1", 2222, "", 22).build(); + NetworkInterfaceCard networkInterfaceCard = NetworkInterfaceCard + .builder().addNetworkAdapter(networkAdapter).build(); + + NetworkSpec networkSpec = NetworkSpec.builder() + .addNIC(networkInterfaceCard).build(); + return MasterSpec.builder().iso(isoSpec).vm(sourceVmSpec) + .network(networkSpec).build(); + } + @AfterClass(groups = "live") protected void tearDown() throws Exception { if (context != null) diff --git a/labs/virtualbox/src/test/java/org/jclouds/virtualbox/compute/VirtualBoxComputeServiceAdapterLiveTest.java b/labs/virtualbox/src/test/java/org/jclouds/virtualbox/compute/VirtualBoxComputeServiceAdapterLiveTest.java index a427a05b0a..a3d61ba27b 100644 --- a/labs/virtualbox/src/test/java/org/jclouds/virtualbox/compute/VirtualBoxComputeServiceAdapterLiveTest.java +++ b/labs/virtualbox/src/test/java/org/jclouds/virtualbox/compute/VirtualBoxComputeServiceAdapterLiveTest.java @@ -50,8 +50,7 @@ public class VirtualBoxComputeServiceAdapterLiveTest extends BaseVirtualBoxClien public void testCreatedNodeHasExpectedNameAndWeCanConnectViaSsh() { String group = "foo"; String name = "foo-ef4"; - String machineName = VIRTUALBOX_NODE_PREFIX + "default-ubuntu-11.04-i386-" + group + "-" + name; - + String machineName = VIRTUALBOX_NODE_PREFIX + "default-ubuntu-11.04-i386-" + "0x0-" + group + "-0x0-" + name; Template template = context.getComputeService().templateBuilder().build(); machine = adapter.createNodeWithGroupEncodedIntoName(group, name, template); diff --git a/labs/virtualbox/src/test/java/org/jclouds/virtualbox/compute/VirtualBoxExperimentLiveTest.java b/labs/virtualbox/src/test/java/org/jclouds/virtualbox/compute/VirtualBoxExperimentLiveTest.java index b4d86b48f4..6415236e77 100644 --- a/labs/virtualbox/src/test/java/org/jclouds/virtualbox/compute/VirtualBoxExperimentLiveTest.java +++ b/labs/virtualbox/src/test/java/org/jclouds/virtualbox/compute/VirtualBoxExperimentLiveTest.java @@ -67,10 +67,9 @@ public class VirtualBoxExperimentLiveTest { @Test public void testLaunchCluster() throws RunNodesException { - int numNodes = 4; + int numNodes = 2; final String clusterName = "test-launch-cluster"; - Set nodes = context.getComputeService().createNodesInGroup(clusterName, numNodes, - TemplateOptions.Builder.runScript(AdminAccess.standard())); + Set nodes = context.getComputeService().createNodesInGroup(clusterName, numNodes, TemplateOptions.Builder.runScript(AdminAccess.standard())); assertEquals(numNodes, nodes.size(), "wrong number of nodes"); for (NodeMetadata node : nodes) { assertTrue(node.getGroup().equals("test-launch-cluster")); diff --git a/labs/virtualbox/src/test/java/org/jclouds/virtualbox/functions/CloneAndRegisterMachineFromIMachineIfNotAlreadyExistsLiveTest.java b/labs/virtualbox/src/test/java/org/jclouds/virtualbox/functions/CloneAndRegisterMachineFromIMachineIfNotAlreadyExistsLiveTest.java index 8912476737..ed73ee4c54 100644 --- a/labs/virtualbox/src/test/java/org/jclouds/virtualbox/functions/CloneAndRegisterMachineFromIMachineIfNotAlreadyExistsLiveTest.java +++ b/labs/virtualbox/src/test/java/org/jclouds/virtualbox/functions/CloneAndRegisterMachineFromIMachineIfNotAlreadyExistsLiveTest.java @@ -23,12 +23,9 @@ import static org.jclouds.virtualbox.config.VirtualBoxConstants.VIRTUALBOX_IMAGE import static org.jclouds.virtualbox.config.VirtualBoxConstants.VIRTUALBOX_INSTALLATION_KEY_SEQUENCE; import static org.testng.Assert.assertEquals; -import java.util.Set; - import org.jclouds.config.ValueOfConfigurationKeyOrNull; import org.jclouds.virtualbox.BaseVirtualBoxClientLiveTest; import org.jclouds.virtualbox.domain.CloneSpec; -import org.jclouds.virtualbox.domain.ExecutionType; import org.jclouds.virtualbox.domain.HardDisk; import org.jclouds.virtualbox.domain.IsoSpec; import org.jclouds.virtualbox.domain.MasterSpec; @@ -37,11 +34,11 @@ import org.jclouds.virtualbox.domain.NetworkInterfaceCard; import org.jclouds.virtualbox.domain.NetworkSpec; import org.jclouds.virtualbox.domain.StorageController; import org.jclouds.virtualbox.domain.VmSpec; +import org.testng.annotations.AfterClass; import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; import org.virtualbox_4_1.CleanupMode; import org.virtualbox_4_1.IMachine; -import org.virtualbox_4_1.ISession; import org.virtualbox_4_1.NetworkAttachmentType; import org.virtualbox_4_1.StorageBus; @@ -56,20 +53,14 @@ import com.google.inject.Injector; @Test(groups = "live", singleThreaded = true, testName = "CloneAndRegisterMachineFromIMachineIfNotAlreadyExistsLiveTest") public class CloneAndRegisterMachineFromIMachineIfNotAlreadyExistsLiveTest extends BaseVirtualBoxClientLiveTest { - private static final boolean IS_LINKED_CLONE = true; - - private MasterSpec sourceMachineSpec; - private CleanupMode mode = CleanupMode.Full; - private VmSpec clonedVmSpec; - private NetworkSpec cloneNetworkSpec; + private MasterSpec machineSpec; + private String instanceName; @Override @BeforeClass(groups = "live") public void setupClient() { super.setupClient(); - String sourceName = VIRTUALBOX_IMAGE_PREFIX - + CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_HYPHEN, getClass().getSimpleName()); - String cloneName = VIRTUALBOX_IMAGE_PREFIX + "Clone#" + instanceName = VIRTUALBOX_IMAGE_PREFIX + CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_HYPHEN, getClass().getSimpleName()); StorageController ideController = StorageController @@ -78,10 +69,10 @@ public class CloneAndRegisterMachineFromIMachineIfNotAlreadyExistsLiveTest exten .bus(StorageBus.IDE) .attachISO(0, 0, operatingSystemIso) .attachHardDisk( - HardDisk.builder().diskpath(adminDisk(sourceName)).controllerPort(0).deviceSlot(1) + HardDisk.builder().diskpath(adminDisk(instanceName)).controllerPort(0).deviceSlot(1) .autoDelete(true).build()).attachISO(1, 1, guestAdditionsIso).build(); - VmSpec sourceVmSpec = VmSpec.builder().id(sourceName).name(sourceName).osTypeId("").memoryMB(512) + VmSpec instanceVmSpec = VmSpec.builder().id(instanceName).name(instanceName).osTypeId("").memoryMB(512) .cleanUpMode(CleanupMode.Full).controller(ideController).forceOverwrite(true).build(); Injector injector = context.utils().injector(); @@ -91,65 +82,47 @@ public class CloneAndRegisterMachineFromIMachineIfNotAlreadyExistsLiveTest exten .sourcePath(operatingSystemIso) .installationScript( configProperties.apply(VIRTUALBOX_INSTALLATION_KEY_SEQUENCE).replace("HOSTNAME", - sourceVmSpec.getVmName())).build(); - - NetworkAdapter networkAdapter = NetworkAdapter.builder().networkAttachmentType(NetworkAttachmentType.Bridged) - .build(); + instanceVmSpec.getVmName())).build(); + NetworkAdapter networkAdapter = NetworkAdapter.builder().networkAttachmentType(NetworkAttachmentType.NAT) + .tcpRedirectRule("127.0.0.1", 2222, "", 22).build(); NetworkInterfaceCard networkInterfaceCard = NetworkInterfaceCard.builder().addNetworkAdapter(networkAdapter) .build(); - this.cloneNetworkSpec = NetworkSpec.builder().addNIC(networkInterfaceCard).build(); - - sourceMachineSpec = MasterSpec.builder().iso(isoSpec).vm(sourceVmSpec).network(cloneNetworkSpec).build(); - - this.clonedVmSpec = VmSpec.builder().id(cloneName).name(cloneName).memoryMB(512).cleanUpMode(mode) - .forceOverwrite(true).build(); + NetworkSpec networkSpec = NetworkSpec.builder().addNIC(networkInterfaceCard).build(); + machineSpec = MasterSpec.builder().iso(isoSpec).vm(instanceVmSpec).network(networkSpec).build(); } - + @Test - public void testCloneMachineFromAnotherMachine() throws Exception { - CloneSpec cloneSpec = null; - try { + public void testCloneMachineFromAnotherMachine() { + IMachine source = getVmWithGuestAdditionsInstalled(); + CloneSpec cloneSpec = CloneSpec.builder().vm(machineSpec.getVmSpec()).network(machineSpec.getNetworkSpec()) + .master(source).linked(true).build(); + IMachine clone = new CloneAndRegisterMachineFromIMachineIfNotAlreadyExists(manager, workingDir, machineUtils) + .apply(cloneSpec); + assertEquals(clone.getName(), cloneSpec.getVmSpec().getVmName()); - IMachine source = getSourceNode(); - - cloneSpec = CloneSpec.builder().vm(clonedVmSpec).network(cloneNetworkSpec).master(source) - .linked(IS_LINKED_CLONE).build(); - - if (source.getCurrentSnapshot() != null) { - ISession session = manager.get().openMachineSession(source); - session.getConsole().deleteSnapshot(source.getCurrentSnapshot().getId()); - session.unlockMachine(); - } - - IMachine clone = new CloneAndRegisterMachineFromIMachineIfNotAlreadyExists(manager, workingDir, machineUtils) - .apply(cloneSpec); - assertEquals(clone.getName(), cloneSpec.getVmSpec().getVmName()); - - new LaunchMachineIfNotAlreadyRunning(manager.get(), ExecutionType.GUI, "").apply(clone); - - // TODO ssh into the node - - } finally { - Set specs = cloneSpec == null ? ImmutableSet.of(sourceMachineSpec.getVmSpec()) : ImmutableSet.of( - cloneSpec.getVmSpec(), sourceMachineSpec.getVmSpec()); - for (VmSpec spec : specs) { - undoVm(spec); - } - - } } - private IMachine getSourceNode() { + private IMachine getVmWithGuestAdditionsInstalled() { + MasterSpec masterSpecForTest = super.getMasterSpecForTest(); try { Injector injector = context.utils().injector(); - return injector.getInstance(CreateAndRegisterMachineFromIsoIfNotAlreadyExists.class).apply(sourceMachineSpec); + return injector.getInstance(CreateAndInstallVm.class).apply(masterSpecForTest); } catch (IllegalStateException e) { // already created - return manager.get().getVBox().findMachine(sourceMachineSpec.getVmSpec().getVmId()); + return manager.get().getVBox().findMachine(masterSpecForTest.getVmSpec().getVmId()); } } + + @Override + @AfterClass(groups = "live") + protected void tearDown() throws Exception { + for (String vmName : ImmutableSet.of(instanceName)) { + undoVm(vmName); + } + super.tearDown(); + } } \ No newline at end of file diff --git a/labs/virtualbox/src/test/java/org/jclouds/virtualbox/functions/CreateAndInstallVmLiveTest.java b/labs/virtualbox/src/test/java/org/jclouds/virtualbox/functions/CreateAndInstallVmLiveTest.java index d70ab876e3..eb28872e36 100644 --- a/labs/virtualbox/src/test/java/org/jclouds/virtualbox/functions/CreateAndInstallVmLiveTest.java +++ b/labs/virtualbox/src/test/java/org/jclouds/virtualbox/functions/CreateAndInstallVmLiveTest.java @@ -35,7 +35,7 @@ import org.jclouds.json.Json; import org.jclouds.json.config.GsonModule; import org.jclouds.ssh.SshClient; import org.jclouds.virtualbox.BaseVirtualBoxClientLiveTest; -import org.jclouds.virtualbox.domain.ExecutionType; +import org.jclouds.virtualbox.domain.CloneSpec; import org.jclouds.virtualbox.domain.HardDisk; import org.jclouds.virtualbox.domain.IsoSpec; import org.jclouds.virtualbox.domain.MasterSpec; @@ -73,13 +73,14 @@ public class CreateAndInstallVmLiveTest extends BaseVirtualBoxClientLiveTest { }.provideOsVersionMap(new ComputeServiceConstants.ReferenceData(), Guice.createInjector(new GsonModule()) .getInstance(Json.class)); - private VmSpec vmSpecification; - private MasterSpec masterSpec; private Injector injector; private Function sshClientForIMachine; private Predicate sshResponds; - private String vmName; + + private MasterSpec machineSpec; + private String instanceName; + /* @Override @BeforeClass(groups = "live") public void setupClient() { @@ -97,12 +98,13 @@ public class CreateAndInstallVmLiveTest extends BaseVirtualBoxClientLiveTest { injector = context.utils().injector(); Function configProperties = injector.getInstance(ValueOfConfigurationKeyOrNull.class); - NetworkAdapter networkAdapter = NetworkAdapter.builder().networkAttachmentType(NetworkAttachmentType.NAT) + NetworkAdapter natAdapter = NetworkAdapter.builder().networkAttachmentType(NetworkAttachmentType.NAT) .tcpRedirectRule("127.0.0.1", 2222, "", 22).build(); - NetworkInterfaceCard networkInterfaceCard = NetworkInterfaceCard.builder().addNetworkAdapter(networkAdapter) - .build(); - NetworkSpec networkSpec = NetworkSpec.builder().addNIC(networkInterfaceCard).build(); + NetworkInterfaceCard networkInterfaceCard1 = NetworkInterfaceCard.builder().slot(0l) + .addNetworkAdapter(natAdapter).build(); + + NetworkSpec networkSpec = NetworkSpec.builder().addNIC(networkInterfaceCard1).build(); masterSpec = MasterSpec .builder() @@ -113,25 +115,51 @@ public class CreateAndInstallVmLiveTest extends BaseVirtualBoxClientLiveTest { .installationScript( configProperties.apply(VIRTUALBOX_INSTALLATION_KEY_SEQUENCE).replace("HOSTNAME", vmSpecification.getVmName())).build()).network(networkSpec).build(); + }*/ + + @Override + @BeforeClass(groups = "live") + public void setupClient() { + super.setupClient(); + instanceName = VIRTUALBOX_IMAGE_PREFIX + + CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_HYPHEN, getClass().getSimpleName()); - undoVm(vmSpecification); - } + StorageController ideController = StorageController + .builder() + .name("IDE Controller") + .bus(StorageBus.IDE) + .attachISO(0, 0, operatingSystemIso) + .attachHardDisk( + HardDisk.builder().diskpath(adminDisk(instanceName)).controllerPort(0).deviceSlot(1) + .autoDelete(true).build()).attachISO(1, 1, guestAdditionsIso).build(); - @Test - public void testCreateImageMachineFromIso() throws Exception { - IMachine imageMachine = getVmWithGuestAdditionsInstalled(); - IMachineToImage iMachineToImage = new IMachineToImage(manager, map); - Image newImage = iMachineToImage.apply(imageMachine); - assertEquals(vmName, newImage.getName()); + VmSpec instanceVmSpec = VmSpec.builder().id(instanceName).name(instanceName).osTypeId("").memoryMB(512) + .cleanUpMode(CleanupMode.Full).controller(ideController).forceOverwrite(true).build(); + + injector = context.utils().injector(); + Function configProperties = injector.getInstance(ValueOfConfigurationKeyOrNull.class); + IsoSpec isoSpec = IsoSpec + .builder() + .sourcePath(operatingSystemIso) + .installationScript( + configProperties.apply(VIRTUALBOX_INSTALLATION_KEY_SEQUENCE).replace("HOSTNAME", + instanceVmSpec.getVmName())).build(); + + NetworkAdapter networkAdapter = NetworkAdapter.builder().networkAttachmentType(NetworkAttachmentType.NAT) + .tcpRedirectRule("127.0.0.1", 2222, "", 22).build(); + NetworkInterfaceCard networkInterfaceCard = NetworkInterfaceCard.builder().addNetworkAdapter(networkAdapter) + .build(); + + NetworkSpec networkSpec = NetworkSpec.builder().addNIC(networkInterfaceCard).build(); + machineSpec = MasterSpec.builder().iso(isoSpec).vm(instanceVmSpec).network(networkSpec).build(); } @Test public void testGuestAdditionsAreInstalled() throws Exception { try { - IMachine machine = getVmWithGuestAdditionsInstalled(); + IMachine machine = cloneFromMaster(); + machineController.ensureMachineIsLaunched(machine.getName()); - machineUtils.applyForMachine(machine.getName(), new LaunchMachineIfNotAlreadyRunning(manager.get(), - ExecutionType.GUI, "")); sshClientForIMachine = injector.getInstance(IMachineToSshClient.class); SshClient client = sshClientForIMachine.apply(machine); @@ -141,35 +169,44 @@ public class CreateAndInstallVmLiveTest extends BaseVirtualBoxClientLiveTest { String vboxVersion = Iterables.get( Splitter.on('r').split(context.getProviderSpecificContext().getBuildVersion()), 0); - assertEquals(vboxVersion, machineUtils.sharedLockMachineAndApplyToSession(machine.getName(), - new Function() { + assertEquals(vboxVersion, + machineUtils.sharedLockMachineAndApplyToSession(machine.getName(), new Function() { @Override public String apply(ISession session) { return session.getMachine().getGuestPropertyValue("/VirtualBox/GuestAdd/Version"); } })); } finally { - for (VmSpec spec : ImmutableSet.of(vmSpecification)) { - machineController.ensureMachineHasPowerDown(spec.getVmName()); + for (VmSpec spec : ImmutableSet.of(machineSpec.getVmSpec())) { + machineController.ensureMachineIsShutdown(spec.getVmName()); } } } + private IMachine cloneFromMaster() { + IMachine source = getVmWithGuestAdditionsInstalled(); + CloneSpec cloneSpec = CloneSpec.builder().vm(machineSpec.getVmSpec()).network(machineSpec.getNetworkSpec()) + .master(source).linked(true).build(); + return new CloneAndRegisterMachineFromIMachineIfNotAlreadyExists(manager, workingDir, machineUtils) + .apply(cloneSpec); + } + private IMachine getVmWithGuestAdditionsInstalled() { + MasterSpec masterSpecForTest = super.getMasterSpecForTest(); try { Injector injector = context.utils().injector(); - return injector.getInstance(CreateAndInstallVm.class).apply(masterSpec); + return injector.getInstance(CreateAndInstallVm.class).apply(masterSpecForTest); } catch (IllegalStateException e) { // already created - return manager.get().getVBox().findMachine(masterSpec.getVmSpec().getVmId()); + return manager.get().getVBox().findMachine(masterSpecForTest.getVmSpec().getVmId()); } } @Override @AfterClass(groups = "live") protected void tearDown() throws Exception { - for (VmSpec spec : ImmutableSet.of(vmSpecification)) { - undoVm(spec); + for (String vmName : ImmutableSet.of(instanceName)) { + undoVm(vmName); } super.tearDown(); } diff --git a/labs/virtualbox/src/test/java/org/jclouds/virtualbox/functions/CreateAndRegisterMachineFromIsoIfNotAlreadyExistsLiveTest.java b/labs/virtualbox/src/test/java/org/jclouds/virtualbox/functions/CreateAndRegisterMachineFromIsoIfNotAlreadyExistsLiveTest.java index 982a40529f..de5ae9c8a3 100644 --- a/labs/virtualbox/src/test/java/org/jclouds/virtualbox/functions/CreateAndRegisterMachineFromIsoIfNotAlreadyExistsLiveTest.java +++ b/labs/virtualbox/src/test/java/org/jclouds/virtualbox/functions/CreateAndRegisterMachineFromIsoIfNotAlreadyExistsLiveTest.java @@ -33,6 +33,7 @@ import org.jclouds.virtualbox.domain.NetworkInterfaceCard; import org.jclouds.virtualbox.domain.NetworkSpec; import org.jclouds.virtualbox.domain.StorageController; import org.jclouds.virtualbox.domain.VmSpec; +import org.testng.annotations.AfterMethod; import org.testng.annotations.Test; import org.virtualbox_4_1.CleanupMode; import org.virtualbox_4_1.IMachine; @@ -46,95 +47,82 @@ import com.google.inject.Injector; * @author Mattias Holmqvist */ @Test(groups = "live", singleThreaded = true, testName = "CreateAndRegisterMachineFromIsoIfNotAlreadyExistsLiveTest") -public class CreateAndRegisterMachineFromIsoIfNotAlreadyExistsLiveTest extends - BaseVirtualBoxClientLiveTest { +public class CreateAndRegisterMachineFromIsoIfNotAlreadyExistsLiveTest extends BaseVirtualBoxClientLiveTest { - private String ideControllerName; - private CleanupMode mode; + private String ideControllerName; + private CleanupMode mode; + private String vmName = ""; - @Override - public void setupClient() { - super.setupClient(); - ideControllerName = "IDE Controller"; - mode = CleanupMode.Full; - } + @Override + public void setupClient() { + super.setupClient(); + ideControllerName = "IDE Controller"; + mode = CleanupMode.Full; + } + + @Test + public void testCreateNewMachine() throws Exception { + vmName = "jclouds-test-create-1-node"; + String vmId = UUID.randomUUID().toString(); - @Test - public void testCreateNewMachine() throws Exception { - String vmName = "jclouds-test-create-1-node"; - String vmId = UUID.randomUUID().toString(); - StorageController ideController = StorageController.builder().name(ideControllerName).bus(StorageBus.IDE) .attachISO(0, 0, operatingSystemIso) .attachHardDisk(HardDisk.builder().diskpath(adminDisk(vmName)).controllerPort(0).deviceSlot(1).build()) .attachISO(1, 1, guestAdditionsIso).build(); - VmSpec vmSpec = VmSpec.builder().id(vmId).name(vmName).memoryMB(512) - .controller(ideController).cleanUpMode(mode).osTypeId("Debian") - .forceOverwrite(true).build(); + VmSpec vmSpec = VmSpec.builder().id(vmId).name(vmName).memoryMB(512).controller(ideController).cleanUpMode(mode) + .osTypeId("Debian").forceOverwrite(true).build(); - NetworkAdapter networkAdapter = NetworkAdapter.builder() - .networkAttachmentType(NetworkAttachmentType.NAT) - .tcpRedirectRule("127.0.0.1", 2222, "", 22).build(); - NetworkInterfaceCard networkInterfaceCard = NetworkInterfaceCard - .builder().addNetworkAdapter(networkAdapter).build(); + NetworkAdapter networkAdapter = NetworkAdapter.builder().networkAttachmentType(NetworkAttachmentType.NAT) + .tcpRedirectRule("127.0.0.1", 2222, "", 22).build(); + NetworkInterfaceCard networkInterfaceCard = NetworkInterfaceCard.builder().addNetworkAdapter(networkAdapter) + .build(); - NetworkSpec networkSpec = NetworkSpec.builder() - .addNIC(networkInterfaceCard).build(); + NetworkSpec networkSpec = NetworkSpec.builder().addNIC(networkInterfaceCard).build(); - MasterSpec machineSpec = MasterSpec - .builder() - .iso(IsoSpec.builder().sourcePath(operatingSystemIso) - .installationScript("").build()).vm(vmSpec) - .network(networkSpec).build(); - undoVm(vmSpec); - try { - IMachine debianNode = context.utils() - .injector() - .getInstance( - CreateAndRegisterMachineFromIsoIfNotAlreadyExists.class) - .apply(machineSpec); - IMachine machine = manager.get().getVBox().findMachine(vmName); - assertEquals(debianNode.getName(), machine.getName()); - } finally { - undoVm(vmSpec); - } - } + MasterSpec machineSpec = MasterSpec.builder() + .iso(IsoSpec.builder().sourcePath(operatingSystemIso).installationScript("").build()).vm(vmSpec) + .network(networkSpec).build(); + // undoVm(vmSpec); + IMachine debianNode = context.utils().injector() + .getInstance(CreateAndRegisterMachineFromIsoIfNotAlreadyExists.class).apply(machineSpec); + IMachine machine = manager.get().getVBox().findMachine(vmName); + assertEquals(debianNode.getName(), machine.getName()); - @Test - public void testCreateNewMachineWithBadOsType() throws Exception { - String vmName = "jclouds-test-create-2-node"; - String vmId = UUID.randomUUID().toString(); - - StorageController ideController = StorageController.builder().name(ideControllerName).bus(StorageBus.IDE) - .attachISO(0, 0, operatingSystemIso) - .attachHardDisk(HardDisk.builder().diskpath(adminDisk(vmName)).controllerPort(0).deviceSlot(1).build()) - .attachISO(1, 1, guestAdditionsIso).build(); + } - VmSpec vmSpec = VmSpec.builder().id(vmId).name(vmName).memoryMB(512) - .controller(ideController).cleanUpMode(mode) - .osTypeId("SomeWeirdUnknownOs").forceOverwrite(true).build(); - IsoSpec isoSpec = IsoSpec.builder().sourcePath(operatingSystemIso) - .installationScript("").build(); - NetworkSpec networkSpec = NetworkSpec.builder().build(); - MasterSpec machineSpec = MasterSpec.builder().iso(isoSpec).vm(vmSpec) - .network(networkSpec).build(); - undoVm(vmSpec); - try { - Injector injector = context.utils().injector(); - injector.getInstance( - CreateAndRegisterMachineFromIsoIfNotAlreadyExists.class) - .apply(machineSpec); - fail(); - } catch (VBoxException e) { - ErrorCode errorCode = ErrorCode.valueOf(e); - // According to the documentation VBOX_E_OBJECT_NOT_FOUND - // if osTypeId is not found. - assertEquals(errorCode, ErrorCode.VBOX_E_OBJECT_NOT_FOUND); - } finally { - undoVm(vmSpec); - } + @Test + public void testCreateNewMachineWithBadOsType() throws Exception { + vmName = "jclouds-test-create-2-node"; + String vmId = UUID.randomUUID().toString(); - } + StorageController ideController = StorageController.builder().name(ideControllerName).bus(StorageBus.IDE) + .attachISO(0, 0, operatingSystemIso) + .attachHardDisk(HardDisk.builder().diskpath(adminDisk(vmName)).controllerPort(0).deviceSlot(1).build()) + .attachISO(1, 1, guestAdditionsIso).build(); + + VmSpec vmSpec = VmSpec.builder().id(vmId).name(vmName).memoryMB(512).controller(ideController).cleanUpMode(mode) + .osTypeId("SomeWeirdUnknownOs").forceOverwrite(true).build(); + IsoSpec isoSpec = IsoSpec.builder().sourcePath(operatingSystemIso).installationScript("").build(); + NetworkSpec networkSpec = NetworkSpec.builder().build(); + MasterSpec machineSpec = MasterSpec.builder().iso(isoSpec).vm(vmSpec).network(networkSpec).build(); + try { + Injector injector = context.utils().injector(); + injector.getInstance(CreateAndRegisterMachineFromIsoIfNotAlreadyExists.class).apply(machineSpec); + fail(); + } catch (VBoxException e) { + ErrorCode errorCode = ErrorCode.valueOf(e); + // According to the documentation VBOX_E_OBJECT_NOT_FOUND + // if osTypeId is not found. + assertEquals(errorCode, ErrorCode.VBOX_E_OBJECT_NOT_FOUND); + } + } + + @Override + @AfterMethod(groups = "live") + protected void tearDown() throws Exception { + undoVm(vmName); + super.tearDown(); + } } diff --git a/labs/virtualbox/src/test/java/org/jclouds/virtualbox/functions/IMachineToNodeMetadataTest.java b/labs/virtualbox/src/test/java/org/jclouds/virtualbox/functions/IMachineToNodeMetadataTest.java index 221342acb9..9443c40965 100644 --- a/labs/virtualbox/src/test/java/org/jclouds/virtualbox/functions/IMachineToNodeMetadataTest.java +++ b/labs/virtualbox/src/test/java/org/jclouds/virtualbox/functions/IMachineToNodeMetadataTest.java @@ -29,6 +29,7 @@ import static org.jclouds.virtualbox.config.VirtualBoxConstants.VIRTUALBOX_NODE_ import static org.jclouds.virtualbox.config.VirtualBoxConstants.VIRTUALBOX_NODE_PREFIX; import org.jclouds.compute.domain.NodeMetadata; +import org.jclouds.virtualbox.util.MachineUtils; import org.testng.annotations.Test; import org.virtualbox_4_1.IMachine; import org.virtualbox_4_1.INATEngine; @@ -62,13 +63,14 @@ public class IMachineToNodeMetadataTest { expect(natEng.getRedirects()).andReturn(ImmutableList.of("0,1,127.0.0.1,2222,,22")); INetworkAdapter hostOnly = createNiceMock(INetworkAdapter.class); + MachineUtils machineUtils = createNiceMock(MachineUtils.class); - replay(vm, nat, natEng, hostOnly); + replay(vm, nat, natEng, hostOnly, machineUtils); - NodeMetadata node = new IMachineToNodeMetadata().apply(vm); + NodeMetadata node = new IMachineToNodeMetadata(machineUtils).apply(vm); assertEquals(MASTER_NAME, node.getName()); - assertEquals(0, node.getPrivateAddresses().size()); + assertEquals(1, node.getPrivateAddresses().size()); assertEquals(1, node.getPublicAddresses().size()); assertEquals("127.0.0.1", Iterables.get(node.getPublicAddresses(), 0)); assertEquals(MastersLoadingCache.MASTER_PORT, node.getLoginPort()); @@ -99,17 +101,14 @@ public class IMachineToNodeMetadataTest { expect(nat.getNatDriver()).andReturn(natEng).anyTimes(); expect(natEng.getHostIP()).andReturn("127.0.0.1").once(); expect(natEng.getRedirects()).andReturn(ImmutableList.of("0,1,127.0.0.1,3000,,22")); + MachineUtils machineUtils = createNiceMock(MachineUtils.class); - replay(vm, nat, natEng, hostOnly); + replay(vm, nat, natEng, hostOnly, machineUtils); - NodeMetadata node = new IMachineToNodeMetadata().apply(vm); + NodeMetadata node = new IMachineToNodeMetadata(machineUtils).apply(vm); assertEquals(name, node.getName()); assertEquals(group, node.getGroup()); - assertEquals(1, node.getPrivateAddresses().size()); - assertEquals((NodeCreator.VMS_NETWORK + 2), Iterables.get(node.getPrivateAddresses(), 0)); assertEquals(1, node.getPublicAddresses().size()); - assertEquals((NodeCreator.VMS_NETWORK + 2), Iterables.get(node.getPublicAddresses(), 0)); - assertEquals(22, node.getLoginPort()); } } diff --git a/labs/virtualbox/src/test/java/org/jclouds/virtualbox/functions/RetrieveActiveBridgedInterfacesLiveTest.java b/labs/virtualbox/src/test/java/org/jclouds/virtualbox/functions/RetrieveActiveBridgedInterfacesExpectTest.java similarity index 79% rename from labs/virtualbox/src/test/java/org/jclouds/virtualbox/functions/RetrieveActiveBridgedInterfacesLiveTest.java rename to labs/virtualbox/src/test/java/org/jclouds/virtualbox/functions/RetrieveActiveBridgedInterfacesExpectTest.java index c88c71c782..3e17be9400 100644 --- a/labs/virtualbox/src/test/java/org/jclouds/virtualbox/functions/RetrieveActiveBridgedInterfacesLiveTest.java +++ b/labs/virtualbox/src/test/java/org/jclouds/virtualbox/functions/RetrieveActiveBridgedInterfacesExpectTest.java @@ -26,6 +26,7 @@ import java.util.List; import org.jclouds.virtualbox.BaseVirtualBoxClientLiveTest; import org.jclouds.virtualbox.domain.BridgedIf; +import org.jclouds.virtualbox.domain.BridgedIf.Builder; import org.testng.annotations.Test; import com.google.common.collect.ImmutableList; @@ -33,8 +34,8 @@ import com.google.common.collect.ImmutableList; /** * @author Andrea Turli */ -@Test(groups = "live", singleThreaded = true, testName = "RetrieveActiveBridgedInterfacesLiveTest") -public class RetrieveActiveBridgedInterfacesLiveTest extends BaseVirtualBoxClientLiveTest { +@Test(singleThreaded = true, testName = "RetrieveActiveBridgedInterfacesExpectTest") +public class RetrieveActiveBridgedInterfacesExpectTest { public static final String TEST1 = "Name: eth0\n" + "GUID: 30687465-0000-4000-8000-00261834d0cb\n" + "Dhcp: Disabled\n" @@ -48,19 +49,16 @@ public class RetrieveActiveBridgedInterfacesLiveTest extends BaseVirtualBoxClien + "HardwareAddress: 5a:3d:ed:99:3f:ed\n" + "MediumType: Ethernet\n" + "Status: Down\n" + "VBoxNetworkName: HostInterfaceNetworking-vbox0\n"; - public static final List expectedBridgedInterfaces = ImmutableList.of("eth0", "vbox0"); + public static final List expectedBridgedInterfaces = ImmutableList.of( + BridgedIf.builder().name("eth0").ip("209.x.x.x").networkMask("255.255.255.0").mediumType("Ethernet") + .status("Up").build(), + BridgedIf.builder().name("vbox0").ip("192.168.56.1").networkMask("255.255.255.0").mediumType("Ethernet") + .status("Down").build()); @Test public void retrieveBridgedInterfaceNamesTest() { List activeBridgedInterfaces = retrieveBridgedInterfaceNames(TEST1); - assertEquals(activeBridgedInterfaces, expectedBridgedInterfaces); - } - - @Test - public void retrieveAvailableBridgedInterfaceInfoTest() { - List bridgedInterface = context.utils().injector().getInstance(RetrieveActiveBridgedInterfaces.class) - .apply(host.get()); - assertFalse(bridgedInterface.isEmpty()); + assertEquals(activeBridgedInterfaces, expectedBridgedInterfaces); } } \ No newline at end of file diff --git a/labs/virtualbox/src/test/java/org/jclouds/virtualbox/functions/admin/ImageFromYamlStringTest.java b/labs/virtualbox/src/test/java/org/jclouds/virtualbox/functions/admin/ImageFromYamlStringTest.java index 1a4dfb43cd..8998ceb560 100644 --- a/labs/virtualbox/src/test/java/org/jclouds/virtualbox/functions/admin/ImageFromYamlStringTest.java +++ b/labs/virtualbox/src/test/java/org/jclouds/virtualbox/functions/admin/ImageFromYamlStringTest.java @@ -28,9 +28,9 @@ import org.jclouds.compute.domain.Image; import org.jclouds.compute.domain.ImageBuilder; import org.jclouds.compute.domain.OperatingSystem; import org.jclouds.compute.domain.OsFamily; +import org.jclouds.virtualbox.functions.YamlImagesFromFileConfig; import org.testng.annotations.Test; -import com.google.common.base.Supplier; import com.google.common.collect.Iterables; /** @@ -39,29 +39,23 @@ import com.google.common.collect.Iterables; @Test(groups = "unit") public class ImageFromYamlStringTest { - public static final Image TEST1 = new ImageBuilder() - .id("default-ubuntu-11.04-i386") - .name("ubuntu-11.04-server-i386") - .description("ubuntu 11.04 server (i386)") - .operatingSystem( - OperatingSystem.builder().description("ubuntu").family(OsFamily.UBUNTU) - .version("11.04").build()).build(); + public static final Image TEST1 = new ImageBuilder() + .id("default-ubuntu-11.04-i386") + .name("ubuntu-11.04-server-i386") + .description("ubuntu 11.04 server (i386)") + .operatingSystem( + OperatingSystem.builder().description("ubuntu").family(OsFamily.UBUNTU).version("11.04").build()) + .build(); - @Test - public void testNodesParse() throws Exception { + @Test + public void testNodesParse() throws Exception { - final StringBuilder yamlFileLines = new StringBuilder(); - for (Object line : IOUtils.readLines(new InputStreamReader(getClass().getResourceAsStream("/default-images.yaml")))) { - yamlFileLines.append(line).append("\n"); - } - - ImagesToYamlImagesFromYamlDescriptor parser = new ImagesToYamlImagesFromYamlDescriptor(new Supplier() { - - @Override - public String get() { - return yamlFileLines.toString(); + final StringBuilder yamlFileLines = new StringBuilder(); + for (Object line : IOUtils + .readLines(new InputStreamReader(getClass().getResourceAsStream("/default-images.yaml")))) { + yamlFileLines.append(line).append("\n"); } - }); - assertEquals(Iterables.getFirst(parser.get().keySet(), null), TEST1); - } + ImagesToYamlImagesFromYamlDescriptor parser = new ImagesToYamlImagesFromYamlDescriptor(new YamlImagesFromFileConfig("/default-images.yaml")); + assertEquals(Iterables.getFirst(parser.get().keySet(), null), TEST1); + } } \ No newline at end of file diff --git a/labs/virtualbox/src/test/java/org/jclouds/virtualbox/functions/admin/StartVBoxIfNotAlreadyRunningLiveTest.java b/labs/virtualbox/src/test/java/org/jclouds/virtualbox/functions/admin/StartVBoxIfNotAlreadyRunningLiveTest.java index 5e30870f5b..6be7199b3b 100644 --- a/labs/virtualbox/src/test/java/org/jclouds/virtualbox/functions/admin/StartVBoxIfNotAlreadyRunningLiveTest.java +++ b/labs/virtualbox/src/test/java/org/jclouds/virtualbox/functions/admin/StartVBoxIfNotAlreadyRunningLiveTest.java @@ -57,10 +57,11 @@ public class StartVBoxIfNotAlreadyRunningLiveTest { URI provider = URI.create("http://localhost:18083/"); String identity = "adminstrator"; String credential = "12345"; + expect(client.seconds(3)).andReturn(client); expect(client.apply(new IPSocket(provider.getHost(), provider.getPort()))).andReturn(true); - manager.connect(provider.toASCIIString(), identity, credential); + manager.connect(provider.toASCIIString(), "", ""); replay(manager, runScriptOnNodeFactory, client); @@ -84,14 +85,15 @@ public class StartVBoxIfNotAlreadyRunningLiveTest { URI provider = URI.create("http://localhost:18083/"); String identity = "adminstrator"; String credential = "12345"; - + + expect(client.seconds(3)).andReturn(client); expect(client.apply(new IPSocket(provider.getHost(), provider.getPort()))).andReturn(false); expect( runScriptOnNodeFactory.create(host, Statements.exec("VBoxManage setproperty websrvauthlibrary null"), runAsRoot(false).wrapInInitScript(false))).andReturn(runScriptOnNode); expect(runScriptOnNode.init()).andReturn(runScriptOnNode); expect(runScriptOnNode.call()).andReturn(new ExecResponse("", "", 0)); - + expect(client.apply(new IPSocket(provider.getHost(), provider.getPort()))).andReturn(true); expect( runScriptOnNodeFactory.create(host, Statements.exec("vboxwebsrv -t 10000 -v -b"), runAsRoot(false) .wrapInInitScript(false).blockOnComplete(false).nameTask("vboxwebsrv"))).andReturn( @@ -99,7 +101,7 @@ public class StartVBoxIfNotAlreadyRunningLiveTest { expect(runScriptOnNode.init()).andReturn(runScriptOnNode); expect(runScriptOnNode.call()).andReturn(new ExecResponse("", "", 0)); - manager.connect(provider.toASCIIString(), identity, credential); + manager.connect(provider.toASCIIString(), "", ""); replay(manager, runScriptOnNodeFactory, runScriptOnNode, client); new StartVBoxIfNotAlreadyRunning((Function) Functions.constant(manager), runScriptOnNodeFactory, client, diff --git a/labs/virtualbox/src/test/java/org/jclouds/virtualbox/predicates/GuestAdditionsInstallerLiveTest.java b/labs/virtualbox/src/test/java/org/jclouds/virtualbox/predicates/GuestAdditionsInstallerLiveTest.java index c726cf2639..da7617d484 100644 --- a/labs/virtualbox/src/test/java/org/jclouds/virtualbox/predicates/GuestAdditionsInstallerLiveTest.java +++ b/labs/virtualbox/src/test/java/org/jclouds/virtualbox/predicates/GuestAdditionsInstallerLiveTest.java @@ -19,13 +19,18 @@ package org.jclouds.virtualbox.predicates; +import static com.google.common.base.Preconditions.checkState; import static org.jclouds.virtualbox.config.VirtualBoxConstants.VIRTUALBOX_IMAGE_PREFIX; import static org.jclouds.virtualbox.config.VirtualBoxConstants.VIRTUALBOX_INSTALLATION_KEY_SEQUENCE; import static org.testng.Assert.assertTrue; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + import org.jclouds.config.ValueOfConfigurationKeyOrNull; +import org.jclouds.ssh.SshClient; import org.jclouds.virtualbox.BaseVirtualBoxClientLiveTest; -import org.jclouds.virtualbox.domain.ExecutionType; +import org.jclouds.virtualbox.domain.CloneSpec; import org.jclouds.virtualbox.domain.HardDisk; import org.jclouds.virtualbox.domain.IsoSpec; import org.jclouds.virtualbox.domain.MasterSpec; @@ -34,8 +39,9 @@ import org.jclouds.virtualbox.domain.NetworkInterfaceCard; import org.jclouds.virtualbox.domain.NetworkSpec; import org.jclouds.virtualbox.domain.StorageController; import org.jclouds.virtualbox.domain.VmSpec; +import org.jclouds.virtualbox.functions.CloneAndRegisterMachineFromIMachineIfNotAlreadyExists; import org.jclouds.virtualbox.functions.CreateAndInstallVm; -import org.jclouds.virtualbox.functions.LaunchMachineIfNotAlreadyRunning; +import org.jclouds.virtualbox.functions.IMachineToSshClient; import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; import org.virtualbox_4_1.CleanupMode; @@ -46,6 +52,7 @@ import org.virtualbox_4_1.StorageBus; import com.google.common.base.CaseFormat; import com.google.common.base.Function; +import com.google.common.base.Predicate; import com.google.common.collect.ImmutableSet; import com.google.inject.Injector; @@ -53,18 +60,22 @@ import com.google.inject.Injector; * @author Andrea Turli */ @Test(groups = "live", singleThreaded = true, testName = "GuestAdditionsInstallerLiveTest") -public class GuestAdditionsInstallerLiveTest extends - BaseVirtualBoxClientLiveTest { +public class GuestAdditionsInstallerLiveTest extends BaseVirtualBoxClientLiveTest { - private MasterSpec sourceMachineSpec; + private Injector injector; + private Function sshClientForIMachine; + private Predicate sshResponds; - @Override - @BeforeClass(groups = "live") - public void setupClient() { - super.setupClient(); - String sourceName = VIRTUALBOX_IMAGE_PREFIX - + CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_HYPHEN, getClass() - .getSimpleName()); + private MasterSpec machineSpec; + + @Override + @BeforeClass(groups = "live") + public void setupClient() { + super.setupClient(); + injector = context.utils().injector(); + + String instanceName = VIRTUALBOX_IMAGE_PREFIX + + CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_HYPHEN, getClass().getSimpleName()); StorageController ideController = StorageController .builder() @@ -72,72 +83,81 @@ public class GuestAdditionsInstallerLiveTest extends .bus(StorageBus.IDE) .attachISO(0, 0, operatingSystemIso) .attachHardDisk( - HardDisk.builder().diskpath(adminDisk(sourceName)).controllerPort(0).deviceSlot(1) - .autoDelete(true).build()).attachISO(1, 0, guestAdditionsIso).build(); + HardDisk.builder().diskpath(adminDisk(instanceName)).controllerPort(0).deviceSlot(1) + .autoDelete(true).build()).attachISO(1, 1, guestAdditionsIso).build(); - VmSpec sourceVmSpec = VmSpec.builder().id(sourceName).name(sourceName) - .osTypeId("").memoryMB(512).cleanUpMode(CleanupMode.Full) - .controller(ideController).forceOverwrite(true).build(); + VmSpec instanceVmSpec = VmSpec.builder().id(instanceName).name(instanceName).osTypeId("").memoryMB(512) + .cleanUpMode(CleanupMode.Full).controller(ideController).forceOverwrite(true).build(); - Injector injector = context.utils().injector(); - Function configProperties = injector - .getInstance(ValueOfConfigurationKeyOrNull.class); - IsoSpec isoSpec = IsoSpec - .builder() - .sourcePath(operatingSystemIso) - .installationScript( - configProperties.apply( - VIRTUALBOX_INSTALLATION_KEY_SEQUENCE).replace( - "HOSTNAME", sourceVmSpec.getVmName())).build(); - - NetworkAdapter networkAdapter = NetworkAdapter.builder() - .networkAttachmentType(NetworkAttachmentType.NAT) - .tcpRedirectRule("127.0.0.1", 2222, "", 22).build(); - NetworkInterfaceCard networkInterfaceCard = NetworkInterfaceCard - .builder().addNetworkAdapter(networkAdapter).build(); + Function configProperties = injector.getInstance(ValueOfConfigurationKeyOrNull.class); + IsoSpec isoSpec = IsoSpec + .builder() + .sourcePath(operatingSystemIso) + .installationScript( + configProperties.apply(VIRTUALBOX_INSTALLATION_KEY_SEQUENCE).replace("HOSTNAME", + instanceVmSpec.getVmName())).build(); - NetworkSpec networkSpec = NetworkSpec.builder() - .addNIC(networkInterfaceCard).build(); - sourceMachineSpec = MasterSpec.builder().iso(isoSpec).vm(sourceVmSpec) - .network(networkSpec).build(); + NetworkAdapter networkAdapter = NetworkAdapter.builder().networkAttachmentType(NetworkAttachmentType.NAT) + .tcpRedirectRule("127.0.0.1", 2222, "", 22).build(); + NetworkInterfaceCard networkInterfaceCard = NetworkInterfaceCard.builder().addNetworkAdapter(networkAdapter) + .build(); - } + NetworkSpec networkSpec = NetworkSpec.builder().addNIC(networkInterfaceCard).build(); + machineSpec = MasterSpec.builder().iso(isoSpec).vm(instanceVmSpec).network(networkSpec).build(); + } - @Test - public void testGuestAdditionsAreInstalled() throws Exception { - try { - IMachine machine = getVmWithGuestAdditionsInstalled(); - machineUtils.applyForMachine(machine.getName(), - new LaunchMachineIfNotAlreadyRunning(manager.get(), - ExecutionType.GUI, "")); - assertTrue(machineUtils.sharedLockMachineAndApplyToSession( - machine.getName(), - new Function() { - @Override - public Boolean apply(ISession session) { - return session.getMachine().getGuestPropertyValue( - "/VirtualBox/GuestAdd/Version") != null; - } - })); - } finally { - for (VmSpec spec : ImmutableSet.of(sourceMachineSpec.getVmSpec())) { - machineController.ensureMachineHasPowerDown(spec.getVmName()); - undoVm(spec); - } - } + @Test + public void testGuestAdditionsAreInstalled() throws Exception { + IMachine machine = null; + try { + machine = cloneFromMaster(); + machineController.ensureMachineIsLaunched(machine.getName()); + sshClientForIMachine = injector.getInstance(IMachineToSshClient.class); + SshClient client = sshClientForIMachine.apply(machine); - } + sshResponds = injector.getInstance(SshResponds.class); + checkState(sshResponds.apply(client), "timed out waiting for guest %s to be accessible via ssh", + machine.getName()); - private IMachine getVmWithGuestAdditionsInstalled() { - try { - Injector injector = context.utils().injector(); - return injector.getInstance(CreateAndInstallVm.class).apply( - sourceMachineSpec); - } catch (IllegalStateException e) { - // already created - return manager.get().getVBox() - .findMachine(sourceMachineSpec.getVmSpec().getVmId()); - } - } + assertTrue(machineUtils.sharedLockMachineAndApplyToSession(machine.getName(), + new Function() { + @Override + public Boolean apply(ISession session) { + String s = session.getMachine().getGuestPropertyValue("/VirtualBox/GuestInfo/Net/0/V4/IP"); + return isIpv4(s); + } + + private boolean isIpv4(String s) { + Pattern pattern = Pattern.compile(machineUtils.IP_V4_ADDRESS_PATTERN); + Matcher matcher = pattern.matcher(s); + return matcher.matches(); + } + })); + } finally { + for (String vmNameOrId : ImmutableSet.of(machine.getName())) { + machineController.ensureMachineHasPowerDown(vmNameOrId); + undoVm(vmNameOrId); + } + } + } + + private IMachine cloneFromMaster() { + IMachine source = getVmWithGuestAdditionsInstalled(); + CloneSpec cloneSpec = CloneSpec.builder().vm(machineSpec.getVmSpec()).network(machineSpec.getNetworkSpec()) + .master(source).linked(true).build(); + return new CloneAndRegisterMachineFromIMachineIfNotAlreadyExists(manager, workingDir, machineUtils) + .apply(cloneSpec); + } + + private IMachine getVmWithGuestAdditionsInstalled() { + MasterSpec masterSpecForTest = super.getMasterSpecForTest(); + try { + Injector injector = context.utils().injector(); + return injector.getInstance(CreateAndInstallVm.class).apply(masterSpecForTest); + } catch (IllegalStateException e) { + // already created + return manager.get().getVBox().findMachine(masterSpecForTest.getVmSpec().getVmId()); + } + } } \ No newline at end of file diff --git a/labs/virtualbox/src/test/java/org/jclouds/virtualbox/predicates/IMachinePredicatesLiveTest.java b/labs/virtualbox/src/test/java/org/jclouds/virtualbox/predicates/IMachinePredicatesLiveTest.java index 26b1a6167f..830053e18e 100644 --- a/labs/virtualbox/src/test/java/org/jclouds/virtualbox/predicates/IMachinePredicatesLiveTest.java +++ b/labs/virtualbox/src/test/java/org/jclouds/virtualbox/predicates/IMachinePredicatesLiveTest.java @@ -20,11 +20,11 @@ package org.jclouds.virtualbox.predicates; import static org.jclouds.virtualbox.config.VirtualBoxConstants.VIRTUALBOX_IMAGE_PREFIX; +import static org.jclouds.virtualbox.config.VirtualBoxConstants.VIRTUALBOX_INSTALLATION_KEY_SEQUENCE; import static org.jclouds.virtualbox.predicates.IMachinePredicates.isLinkedClone; import static org.testng.Assert.assertTrue; -import java.util.Set; - +import org.jclouds.config.ValueOfConfigurationKeyOrNull; import org.jclouds.virtualbox.BaseVirtualBoxClientLiveTest; import org.jclouds.virtualbox.domain.CloneSpec; import org.jclouds.virtualbox.domain.HardDisk; @@ -36,10 +36,9 @@ import org.jclouds.virtualbox.domain.NetworkSpec; import org.jclouds.virtualbox.domain.StorageController; import org.jclouds.virtualbox.domain.VmSpec; import org.jclouds.virtualbox.functions.CloneAndRegisterMachineFromIMachineIfNotAlreadyExists; -import org.jclouds.virtualbox.functions.CreateAndRegisterMachineFromIsoIfNotAlreadyExists; -import org.testng.annotations.AfterMethod; +import org.jclouds.virtualbox.functions.CreateAndInstallVm; +import org.testng.annotations.AfterClass; import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeMethod; import org.testng.annotations.Test; import org.virtualbox_4_1.CleanupMode; import org.virtualbox_4_1.IMachine; @@ -47,6 +46,7 @@ import org.virtualbox_4_1.NetworkAttachmentType; import org.virtualbox_4_1.StorageBus; import com.google.common.base.CaseFormat; +import com.google.common.base.Function; import com.google.common.collect.ImmutableSet; import com.google.inject.Injector; @@ -56,68 +56,75 @@ import com.google.inject.Injector; */ @Test(groups = "live", singleThreaded = true, testName = "IMachinePredicatesLiveTest") public class IMachinePredicatesLiveTest extends BaseVirtualBoxClientLiveTest { + + private MasterSpec machineSpec; + private String instanceName; - private String osTypeId = ""; - private String ideControllerName = "IDE Controller"; - private String cloneName; - private String vmName; - private StorageController masterStorageController; - private MasterSpec masterMachineSpec; - private NetworkSpec networkSpec; - private CloneSpec cloneSpec; + @Override + @BeforeClass(groups = "live") + public void setupClient() { + super.setupClient(); + instanceName = VIRTUALBOX_IMAGE_PREFIX + + CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_HYPHEN, getClass().getSimpleName()); - @Override - @BeforeClass(groups = "live") - public void setupClient() { - super.setupClient(); - vmName = VIRTUALBOX_IMAGE_PREFIX + CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_HYPHEN, getClass().getSimpleName()); + StorageController ideController = StorageController + .builder() + .name("IDE Controller") + .bus(StorageBus.IDE) + .attachISO(0, 0, operatingSystemIso) + .attachHardDisk( + HardDisk.builder().diskpath(adminDisk(instanceName)).controllerPort(0).deviceSlot(1) + .autoDelete(true).build()).attachISO(1, 1, guestAdditionsIso).build(); - cloneName = VIRTUALBOX_IMAGE_PREFIX + "Clone#" - + CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_HYPHEN, getClass().getSimpleName()); + VmSpec instanceVmSpec = VmSpec.builder().id(instanceName).name(instanceName).osTypeId("").memoryMB(512) + .cleanUpMode(CleanupMode.Full).controller(ideController).forceOverwrite(true).build(); - HardDisk hardDisk = HardDisk.builder().diskpath(adminDisk(vmName)).autoDelete(true).controllerPort(0) - .deviceSlot(1).build(); - masterStorageController = StorageController.builder().name(ideControllerName).bus(StorageBus.IDE) - .attachISO(0, 0, operatingSystemIso).attachHardDisk(hardDisk).attachISO(1, 1, guestAdditionsIso).build(); - VmSpec masterSpec = VmSpec.builder().id(vmName).name(vmName).memoryMB(512).osTypeId(osTypeId) - .controller(masterStorageController).forceOverwrite(true).cleanUpMode(CleanupMode.Full).build(); - masterMachineSpec = MasterSpec.builder() - .iso(IsoSpec.builder().sourcePath(operatingSystemIso).installationScript("").build()).vm(masterSpec) - .network(NetworkSpec.builder().build()).build(); + Injector injector = context.utils().injector(); + Function configProperties = injector.getInstance(ValueOfConfigurationKeyOrNull.class); + IsoSpec isoSpec = IsoSpec + .builder() + .sourcePath(operatingSystemIso) + .installationScript( + configProperties.apply(VIRTUALBOX_INSTALLATION_KEY_SEQUENCE).replace("HOSTNAME", + instanceVmSpec.getVmName())).build(); - NetworkAdapter networkAdapter = NetworkAdapter.builder().networkAttachmentType(NetworkAttachmentType.Bridged) - .build(); - NetworkInterfaceCard networkInterfaceCard = NetworkInterfaceCard.builder().addNetworkAdapter(networkAdapter) - .build(); + NetworkAdapter networkAdapter = NetworkAdapter.builder().networkAttachmentType(NetworkAttachmentType.NAT) + .tcpRedirectRule("127.0.0.1", 2222, "", 22).build(); + NetworkInterfaceCard networkInterfaceCard = NetworkInterfaceCard.builder().addNetworkAdapter(networkAdapter) + .build(); - this.networkSpec = NetworkSpec.builder().addNIC(networkInterfaceCard).build(); + NetworkSpec networkSpec = NetworkSpec.builder().addNIC(networkInterfaceCard).build(); + machineSpec = MasterSpec.builder().iso(isoSpec).vm(instanceVmSpec).network(networkSpec).build(); - } + } + + @Test + public void testCloneMachineFromAnotherMachine() { + IMachine source = getVmWithGuestAdditionsInstalled(); + CloneSpec cloneSpec = CloneSpec.builder().vm(machineSpec.getVmSpec()).network(machineSpec.getNetworkSpec()) + .master(source).linked(true).build(); + IMachine clone = new CloneAndRegisterMachineFromIMachineIfNotAlreadyExists(manager, workingDir, machineUtils) + .apply(cloneSpec); + assertTrue(isLinkedClone().apply(clone)); + } - @Test - public void testLinkedClone() { - - Injector injector = context.utils().injector(); - IMachine master = injector.getInstance(CreateAndRegisterMachineFromIsoIfNotAlreadyExists.class).apply( - masterMachineSpec); - - VmSpec clonedVmSpec = VmSpec.builder().id(cloneName).name(cloneName).memoryMB(512).cleanUpMode(CleanupMode.Full) - .forceOverwrite(true).build(); - - this.cloneSpec = CloneSpec.builder().vm(clonedVmSpec).network(networkSpec).master(master).linked(true).build(); - - IMachine clone = new CloneAndRegisterMachineFromIMachineIfNotAlreadyExists(manager, workingDir, machineUtils) - .apply(cloneSpec); - - assertTrue(isLinkedClone().apply(clone)); - } - - @BeforeMethod - @AfterMethod - void cleanUpVms() { - Set specs = cloneSpec != null ? ImmutableSet.of(cloneSpec.getVmSpec(), masterMachineSpec.getVmSpec()) - : ImmutableSet.of(masterMachineSpec.getVmSpec()); - for (VmSpec spec : specs) - this.undoVm(spec); + private IMachine getVmWithGuestAdditionsInstalled() { + MasterSpec masterSpecForTest = super.getMasterSpecForTest(); + try { + Injector injector = context.utils().injector(); + return injector.getInstance(CreateAndInstallVm.class).apply(masterSpecForTest); + } catch (IllegalStateException e) { + // already created + return manager.get().getVBox().findMachine(masterSpecForTest.getVmSpec().getVmId()); + } + } + + @Override + @AfterClass(groups = "live") + protected void tearDown() throws Exception { + for (String vmName : ImmutableSet.of(instanceName)) { + undoVm(vmName); + } + super.tearDown(); } } diff --git a/labs/virtualbox/src/test/java/org/jclouds/virtualbox/statements/InstallGuestAdditionsLiveTest.java b/labs/virtualbox/src/test/java/org/jclouds/virtualbox/statements/InstallGuestAdditionsLiveTest.java index 0d21e5f036..58ceeba796 100644 --- a/labs/virtualbox/src/test/java/org/jclouds/virtualbox/statements/InstallGuestAdditionsLiveTest.java +++ b/labs/virtualbox/src/test/java/org/jclouds/virtualbox/statements/InstallGuestAdditionsLiveTest.java @@ -45,9 +45,15 @@ public class InstallGuestAdditionsLiveTest extends BaseVirtualBoxClientLiveTest InstallGuestAdditions installer = new InstallGuestAdditions(vmSpecification, "4.1.8"); String scripts = installer.render(OsFamily.UNIX); assertEquals("installModuleAssistantIfNeeded || return 1\n" + "mount -t iso9660 /dev/sr1 /mnt\n" - + "/mnt/VBoxLinuxAdditions.run\n" + "umount /mnt\n", scripts); + + "/mnt/VBoxLinuxAdditions.run\n" + + "service vboxadd setup\n" + + "VBoxService\n" + + "echo VBoxService > /etc/rc.local\n" + + "echo exit 0 >> /etc/rc.local\n" + + "umount /mnt\n" + , scripts); } - + public void testIsoNotPresent() { StorageController ideController = StorageController.builder().name("IDE Controller").bus(StorageBus.IDE).build(); @@ -61,7 +67,12 @@ public class InstallGuestAdditionsLiveTest extends BaseVirtualBoxClientLiveTest + "setupPublicCurl || return 1\n" + "(mkdir -p /tmp/ && cd /tmp/ && [ ! -f VBoxGuestAdditions_4.1.8.iso ] && curl -q -s -S -L --connect-timeout 10 --max-time 600 --retry 20 -C - -X GET http://download.virtualbox.org/virtualbox/4.1.8/VBoxGuestAdditions_4.1.8.iso >VBoxGuestAdditions_4.1.8.iso)\n" + "mount -o loop /tmp/VBoxGuestAdditions_4.1.8.iso /mnt\n" - + "/mnt/VBoxLinuxAdditions.run\n" + "umount /mnt\n", scripts); + + "/mnt/VBoxLinuxAdditions.run\n" + + "service vboxadd setup\n" + + "VBoxService\n" + + "echo VBoxService > /etc/rc.local\n" + + "echo exit 0 >> /etc/rc.local\n" + + "umount /mnt\n", scripts); } } \ No newline at end of file diff --git a/labs/virtualbox/src/test/java/org/jclouds/virtualbox/util/MachineControllerLiveTest.java b/labs/virtualbox/src/test/java/org/jclouds/virtualbox/util/MachineControllerLiveTest.java new file mode 100644 index 0000000000..c1da4d7121 --- /dev/null +++ b/labs/virtualbox/src/test/java/org/jclouds/virtualbox/util/MachineControllerLiveTest.java @@ -0,0 +1,140 @@ +/** + * 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.util; + +import static org.jclouds.virtualbox.config.VirtualBoxConstants.VIRTUALBOX_IMAGE_PREFIX; +import static org.jclouds.virtualbox.config.VirtualBoxConstants.VIRTUALBOX_INSTALLATION_KEY_SEQUENCE; +import static org.testng.AssertJUnit.assertTrue; + +import org.jclouds.config.ValueOfConfigurationKeyOrNull; +import org.jclouds.virtualbox.BaseVirtualBoxClientLiveTest; +import org.jclouds.virtualbox.domain.CloneSpec; +import org.jclouds.virtualbox.domain.HardDisk; +import org.jclouds.virtualbox.domain.IsoSpec; +import org.jclouds.virtualbox.domain.MasterSpec; +import org.jclouds.virtualbox.domain.NetworkAdapter; +import org.jclouds.virtualbox.domain.NetworkInterfaceCard; +import org.jclouds.virtualbox.domain.NetworkSpec; +import org.jclouds.virtualbox.domain.StorageController; +import org.jclouds.virtualbox.domain.VmSpec; +import org.jclouds.virtualbox.functions.CloneAndRegisterMachineFromIMachineIfNotAlreadyExists; +import org.jclouds.virtualbox.functions.CreateAndInstallVm; +import org.testng.annotations.AfterClass; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.Test; +import org.virtualbox_4_1.CleanupMode; +import org.virtualbox_4_1.IMachine; +import org.virtualbox_4_1.ISession; +import org.virtualbox_4_1.NetworkAttachmentType; +import org.virtualbox_4_1.SessionState; +import org.virtualbox_4_1.StorageBus; + +import com.google.common.base.CaseFormat; +import com.google.common.base.Function; +import com.google.common.collect.ImmutableSet; +import com.google.inject.Injector; + +@Test(groups = "live", testName = "MachineControllerLiveTest") +public class MachineControllerLiveTest extends BaseVirtualBoxClientLiveTest { + + private MasterSpec machineSpec; + private String instanceName; + + @Override + @BeforeClass(groups = "live") + public void setupClient() { + super.setupClient(); + instanceName = VIRTUALBOX_IMAGE_PREFIX + + CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_HYPHEN, getClass().getSimpleName()); + + StorageController ideController = StorageController + .builder() + .name("IDE Controller") + .bus(StorageBus.IDE) + .attachISO(0, 0, operatingSystemIso) + .attachHardDisk( + HardDisk.builder().diskpath(adminDisk(instanceName)).controllerPort(0).deviceSlot(1) + .autoDelete(true).build()).attachISO(1, 1, guestAdditionsIso).build(); + + VmSpec instanceVmSpec = VmSpec.builder().id(instanceName).name(instanceName).osTypeId("").memoryMB(512) + .cleanUpMode(CleanupMode.Full).controller(ideController).forceOverwrite(true).build(); + + Injector injector = context.utils().injector(); + Function configProperties = injector.getInstance(ValueOfConfigurationKeyOrNull.class); + IsoSpec isoSpec = IsoSpec + .builder() + .sourcePath(operatingSystemIso) + .installationScript( + configProperties.apply(VIRTUALBOX_INSTALLATION_KEY_SEQUENCE).replace("HOSTNAME", + instanceVmSpec.getVmName())).build(); + + NetworkAdapter networkAdapter = NetworkAdapter.builder().networkAttachmentType(NetworkAttachmentType.NAT) + .tcpRedirectRule("127.0.0.1", 2222, "", 22).build(); + NetworkInterfaceCard networkInterfaceCard = NetworkInterfaceCard.builder().addNetworkAdapter(networkAdapter) + .build(); + + NetworkSpec networkSpec = NetworkSpec.builder().addNIC(networkInterfaceCard).build(); + machineSpec = MasterSpec.builder().iso(isoSpec).vm(instanceVmSpec).network(networkSpec).build(); + } + + @Test + public void testEnsureMachineisLaunchedAndSessionIsUnlocked() { + cloneFromMaster(); + ISession cloneMachineSession = machineController.ensureMachineIsLaunched(instanceName); + assertTrue(cloneMachineSession.getState() == SessionState.Unlocked); + cloneMachineSession = machineController.ensureMachineHasPowerDown(instanceName); + assertTrue(cloneMachineSession.getState() == SessionState.Unlocked); + } + + @Test(dependsOnMethods="testEnsureMachineisLaunchedAndSessionIsUnlocked") + public void testEnsureMachineCanBePoweredOffMoreThanOneTimeAndSessionIsUnlocked() { + ISession cloneMachineSession = machineController.ensureMachineHasPowerDown(instanceName); + cloneMachineSession = machineController.ensureMachineHasPowerDown(instanceName); + assertTrue(cloneMachineSession.getState() == SessionState.Unlocked); + } + + private IMachine cloneFromMaster() { + IMachine source = getVmWithGuestAdditionsInstalled(); + CloneSpec cloneSpec = CloneSpec.builder().vm(machineSpec.getVmSpec()).network(machineSpec.getNetworkSpec()) + .master(source).linked(true).build(); + return new CloneAndRegisterMachineFromIMachineIfNotAlreadyExists(manager, workingDir, machineUtils) + .apply(cloneSpec); + } + + private IMachine getVmWithGuestAdditionsInstalled() { + MasterSpec masterSpecForTest = super.getMasterSpecForTest(); + try { + Injector injector = context.utils().injector(); + return injector.getInstance(CreateAndInstallVm.class).apply(masterSpecForTest); + } catch (IllegalStateException e) { + // already created + return manager.get().getVBox().findMachine(masterSpecForTest.getVmSpec().getVmId()); + } + } + + @Override + @AfterClass(groups = "live") + protected void tearDown() throws Exception { + for (String vmName : ImmutableSet.of(instanceName)) { + undoVm(vmName); + } + super.tearDown(); + } +} \ No newline at end of file diff --git a/labs/virtualbox/src/test/java/org/jclouds/virtualbox/util/MachineUtilsLiveTest.java b/labs/virtualbox/src/test/java/org/jclouds/virtualbox/util/MachineUtilsLiveTest.java new file mode 100644 index 0000000000..fba1fcd779 --- /dev/null +++ b/labs/virtualbox/src/test/java/org/jclouds/virtualbox/util/MachineUtilsLiveTest.java @@ -0,0 +1,144 @@ +/** + * 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.util; +import static com.google.common.base.Preconditions.checkState; +import static org.jclouds.virtualbox.config.VirtualBoxConstants.VIRTUALBOX_IMAGE_PREFIX; +import static org.jclouds.virtualbox.config.VirtualBoxConstants.VIRTUALBOX_INSTALLATION_KEY_SEQUENCE; + +import org.jclouds.config.ValueOfConfigurationKeyOrNull; +import org.jclouds.virtualbox.BaseVirtualBoxClientLiveTest; +import org.jclouds.virtualbox.domain.CloneSpec; +import org.jclouds.virtualbox.domain.ExecutionType; +import org.jclouds.virtualbox.domain.HardDisk; +import org.jclouds.virtualbox.domain.IsoSpec; +import org.jclouds.virtualbox.domain.MasterSpec; +import org.jclouds.virtualbox.domain.NetworkAdapter; +import org.jclouds.virtualbox.domain.NetworkInterfaceCard; +import org.jclouds.virtualbox.domain.NetworkSpec; +import org.jclouds.virtualbox.domain.StorageController; +import org.jclouds.virtualbox.domain.VmSpec; +import org.jclouds.virtualbox.functions.CloneAndRegisterMachineFromIMachineIfNotAlreadyExists; +import org.jclouds.virtualbox.functions.CreateAndInstallVm; +import org.jclouds.virtualbox.functions.LaunchMachineIfNotAlreadyRunning; +import org.testng.annotations.AfterClass; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.Test; +import org.virtualbox_4_1.CleanupMode; +import org.virtualbox_4_1.IMachine; +import org.virtualbox_4_1.ISession; +import org.virtualbox_4_1.LockType; +import org.virtualbox_4_1.NetworkAttachmentType; +import org.virtualbox_4_1.SessionState; +import org.virtualbox_4_1.StorageBus; + +import com.google.common.base.CaseFormat; +import com.google.common.base.Function; +import com.google.common.collect.ImmutableSet; +import com.google.inject.Injector; + +@Test(groups = "live", testName = "MachineControllerLiveTest") +public class MachineUtilsLiveTest extends BaseVirtualBoxClientLiveTest { + + private MasterSpec machineSpec; + private String instanceName; + + @Override + @BeforeClass(groups = "live") + public void setupClient() { + super.setupClient(); + instanceName = VIRTUALBOX_IMAGE_PREFIX + + CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_HYPHEN, getClass().getSimpleName()); + + StorageController ideController = StorageController + .builder() + .name("IDE Controller") + .bus(StorageBus.IDE) + .attachISO(0, 0, operatingSystemIso) + .attachHardDisk( + HardDisk.builder().diskpath(adminDisk(instanceName)).controllerPort(0).deviceSlot(1) + .autoDelete(true).build()).attachISO(1, 1, guestAdditionsIso).build(); + + VmSpec instanceVmSpec = VmSpec.builder().id(instanceName).name(instanceName).osTypeId("").memoryMB(512) + .cleanUpMode(CleanupMode.Full).controller(ideController).forceOverwrite(true).build(); + + Injector injector = context.utils().injector(); + Function configProperties = injector.getInstance(ValueOfConfigurationKeyOrNull.class); + IsoSpec isoSpec = IsoSpec + .builder() + .sourcePath(operatingSystemIso) + .installationScript( + configProperties.apply(VIRTUALBOX_INSTALLATION_KEY_SEQUENCE).replace("HOSTNAME", + instanceVmSpec.getVmName())).build(); + + NetworkAdapter networkAdapter = NetworkAdapter.builder().networkAttachmentType(NetworkAttachmentType.NAT) + .tcpRedirectRule("127.0.0.1", 2222, "", 22).build(); + NetworkInterfaceCard networkInterfaceCard = NetworkInterfaceCard.builder().addNetworkAdapter(networkAdapter) + .build(); + + NetworkSpec networkSpec = NetworkSpec.builder().addNIC(networkInterfaceCard).build(); + machineSpec = MasterSpec.builder().iso(isoSpec).vm(instanceVmSpec).network(networkSpec).build(); + } + + @Test + public void lockSessionOnMachine() { + IMachine machine = cloneFromMaster(); + ISession session = machineUtils.lockSessionOnMachineAndApply(instanceName, LockType.Shared, + new Function() { + + @Override + public ISession apply(ISession session) { + return session; + } + }); + checkState(session.getState().equals(SessionState.Unlocked)); + machine = manager.get().getVBox().findMachine(instanceName); + undoVm(instanceName); + + } + + + private IMachine cloneFromMaster() { + IMachine source = getVmWithGuestAdditionsInstalled(); + CloneSpec cloneSpec = CloneSpec.builder().vm(machineSpec.getVmSpec()).network(machineSpec.getNetworkSpec()) + .master(source).linked(true).build(); + return new CloneAndRegisterMachineFromIMachineIfNotAlreadyExists(manager, workingDir, machineUtils) + .apply(cloneSpec); + } + + private IMachine getVmWithGuestAdditionsInstalled() { + MasterSpec masterSpecForTest = super.getMasterSpecForTest(); + try { + Injector injector = context.utils().injector(); + return injector.getInstance(CreateAndInstallVm.class).apply(masterSpecForTest); + } catch (IllegalStateException e) { + // already created + return manager.get().getVBox().findMachine(masterSpecForTest.getVmSpec().getVmId()); + } + } + + @Override + @AfterClass(groups = "live") + protected void tearDown() throws Exception { + for (String vmName : ImmutableSet.of(instanceName)) { + undoVm(vmName); + } + super.tearDown(); + } +}