Merge pull request #844 from andreaturli/virtualbox

issue 384: improved ISession management; added ubuntu 10.04.4 support;
This commit is contained in:
Adrian Cole 2012-09-19 09:01:16 -07:00
commit 9b5073710a
40 changed files with 1330 additions and 554 deletions

View File

@ -38,7 +38,7 @@
<test.virtualbox.endpoint>http://localhost:18083/</test.virtualbox.endpoint> <test.virtualbox.endpoint>http://localhost:18083/</test.virtualbox.endpoint>
<test.virtualbox.api-version>4.1.4</test.virtualbox.api-version> <test.virtualbox.api-version>4.1.4</test.virtualbox.api-version>
<test.virtualbox.build-version>4.1.20r80170</test.virtualbox.build-version> <test.virtualbox.build-version>4.1.20r80170</test.virtualbox.build-version>
<test.virtualbox.identity>administrator</test.virtualbox.identity> <test.virtualbox.identity>${user.name}</test.virtualbox.identity>
<test.virtualbox.credential>CHANGE_ME</test.virtualbox.credential> <test.virtualbox.credential>CHANGE_ME</test.virtualbox.credential>
<test.virtualbox.template>osFamily=UBUNTU,osVersionMatches=12.04.1,os64Bit=true,osArchMatches=amd64,loginUser=toor:password,authenticateSudo=true</test.virtualbox.template> <test.virtualbox.template>osFamily=UBUNTU,osVersionMatches=12.04.1,os64Bit=true,osArchMatches=amd64,loginUser=toor:password,authenticateSudo=true</test.virtualbox.template>
<jclouds.osgi.export>org.jclouds.virtualbox*;version="${project.version}"</jclouds.osgi.export> <jclouds.osgi.export>org.jclouds.virtualbox*;version="${project.version}"</jclouds.osgi.export>

View File

@ -20,12 +20,12 @@ package org.jclouds.virtualbox;
import static org.jclouds.compute.config.ComputeServiceProperties.TEMPLATE; import static org.jclouds.compute.config.ComputeServiceProperties.TEMPLATE;
import static org.jclouds.virtualbox.config.VirtualBoxConstants.VIRTUALBOX_DEFAULT_DIR; import static org.jclouds.virtualbox.config.VirtualBoxConstants.VIRTUALBOX_DEFAULT_DIR;
import static org.jclouds.virtualbox.config.VirtualBoxConstants.VIRTUALBOX_GUEST_CREDENTIAL;
import static org.jclouds.virtualbox.config.VirtualBoxConstants.VIRTUALBOX_GUEST_IDENTITY;
import static org.jclouds.virtualbox.config.VirtualBoxConstants.VIRTUALBOX_IMAGES_DESCRIPTOR; import static org.jclouds.virtualbox.config.VirtualBoxConstants.VIRTUALBOX_IMAGES_DESCRIPTOR;
import static org.jclouds.virtualbox.config.VirtualBoxConstants.VIRTUALBOX_INSTALLATION_KEY_SEQUENCE; import static org.jclouds.virtualbox.config.VirtualBoxConstants.VIRTUALBOX_INSTALLATION_KEY_SEQUENCE;
import static org.jclouds.virtualbox.config.VirtualBoxConstants.VIRTUALBOX_PRECONFIGURATION_URL; import static org.jclouds.virtualbox.config.VirtualBoxConstants.VIRTUALBOX_PRECONFIGURATION_URL;
import static org.jclouds.virtualbox.config.VirtualBoxConstants.VIRTUALBOX_WORKINGDIR; import static org.jclouds.virtualbox.config.VirtualBoxConstants.VIRTUALBOX_WORKINGDIR;
import static org.jclouds.virtualbox.config.VirtualBoxConstants.VIRTUALBOX_GUEST_MEMORY;
import java.io.File; import java.io.File;
import java.net.URI; import java.net.URI;
@ -74,22 +74,17 @@ public class VirtualBoxApiMetadata extends BaseApiMetadata {
+ "initrd=/install/initrd.gz -- <Enter>"); + "initrd=/install/initrd.gz -- <Enter>");
String workingDir = System.getProperty("test.virtualbox.workingDir", VIRTUALBOX_DEFAULT_DIR); String workingDir = System.getProperty("test.virtualbox.workingDir", VIRTUALBOX_DEFAULT_DIR);
properties.put(VIRTUALBOX_WORKINGDIR, workingDir); properties.put(VIRTUALBOX_WORKINGDIR, workingDir);
String ram = System.getProperty(VIRTUALBOX_GUEST_MEMORY, "1024");
properties.put(VIRTUALBOX_GUEST_MEMORY, ram);
String yamlDescriptor = System.getProperty("test.virtualbox.image.descriptor.yaml", VIRTUALBOX_WORKINGDIR String yamlDescriptor = System.getProperty("test.virtualbox.image.descriptor.yaml", VIRTUALBOX_WORKINGDIR
+ File.separator + "images.yaml"); + File.separator + "images.yaml");
properties.put(VIRTUALBOX_IMAGES_DESCRIPTOR, yamlDescriptor); properties.put(VIRTUALBOX_IMAGES_DESCRIPTOR, yamlDescriptor);
properties.put(VIRTUALBOX_PRECONFIGURATION_URL, "http://10.0.2.2:23232/preseed.cfg"); properties.put(VIRTUALBOX_PRECONFIGURATION_URL, "http://10.0.2.2:23232/preseed.cfg");
properties.setProperty(TEMPLATE, "osFamily=UBUNTU,osVersionMatches=12.04.1,os64Bit=true,osArchMatches=amd64");
properties.put(VIRTUALBOX_GUEST_IDENTITY, "toor");
properties.put(VIRTUALBOX_GUEST_CREDENTIAL, "password");
properties.setProperty(TEMPLATE,
String.format("osFamily=UBUNTU,osVersionMatches=12.04.1,os64Bit=true,osArchMatches=amd64,loginUser=%s:%s,authenticateSudo=true",
properties.getProperty(VIRTUALBOX_GUEST_IDENTITY),
properties.getProperty(VIRTUALBOX_GUEST_CREDENTIAL)));
return properties; return properties;
} }

View File

@ -28,6 +28,7 @@ import static org.jclouds.virtualbox.config.VirtualBoxConstants.VIRTUALBOX_NODE_
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.concurrent.TimeUnit;
import javax.annotation.Resource; import javax.annotation.Resource;
import javax.inject.Inject; import javax.inject.Inject;
@ -46,6 +47,7 @@ import org.jclouds.virtualbox.domain.Master;
import org.jclouds.virtualbox.domain.NodeSpec; import org.jclouds.virtualbox.domain.NodeSpec;
import org.jclouds.virtualbox.domain.YamlImage; import org.jclouds.virtualbox.domain.YamlImage;
import org.jclouds.virtualbox.functions.admin.UnregisterMachineIfExistsAndForceDeleteItsMedia; import org.jclouds.virtualbox.functions.admin.UnregisterMachineIfExistsAndForceDeleteItsMedia;
import org.jclouds.virtualbox.util.MachineController;
import org.virtualbox_4_1.IMachine; import org.virtualbox_4_1.IMachine;
import org.virtualbox_4_1.IProgress; import org.virtualbox_4_1.IProgress;
import org.virtualbox_4_1.ISession; import org.virtualbox_4_1.ISession;
@ -62,6 +64,7 @@ import com.google.common.cache.LoadingCache;
import com.google.common.collect.ImmutableSet; import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables; import com.google.common.collect.Iterables;
import com.google.common.collect.Sets; import com.google.common.collect.Sets;
import com.google.common.util.concurrent.Uninterruptibles;
import com.google.inject.Singleton; import com.google.inject.Singleton;
/** /**
@ -82,17 +85,20 @@ public class VirtualBoxComputeServiceAdapter implements ComputeServiceAdapter<IM
private final LoadingCache<Image, Master> mastersLoader; private final LoadingCache<Image, Master> mastersLoader;
private final Function<NodeSpec, NodeAndInitialCredentials<IMachine>> cloneCreator; private final Function<NodeSpec, NodeAndInitialCredentials<IMachine>> cloneCreator;
private final Function<IMachine, Image> imachineToImage; private final Function<IMachine, Image> imachineToImage;
private final MachineController machineController;
@Inject @Inject
public VirtualBoxComputeServiceAdapter(Supplier<VirtualBoxManager> manager, public VirtualBoxComputeServiceAdapter(Supplier<VirtualBoxManager> manager,
Supplier<Map<Image, YamlImage>> imagesMapper, LoadingCache<Image, Master> mastersLoader, Supplier<Map<Image, YamlImage>> imagesMapper, LoadingCache<Image, Master> mastersLoader,
Function<NodeSpec, NodeAndInitialCredentials<IMachine>> cloneCreator, Function<NodeSpec, NodeAndInitialCredentials<IMachine>> cloneCreator,
Function<IMachine, Image> imachineToImage) { Function<IMachine, Image> imachineToImage,
MachineController machineController) {
this.manager = checkNotNull(manager, "manager"); this.manager = checkNotNull(manager, "manager");
this.imagesToYamlImages = imagesMapper.get(); this.imagesToYamlImages = imagesMapper.get();
this.mastersLoader = mastersLoader; this.mastersLoader = mastersLoader;
this.cloneCreator = cloneCreator; this.cloneCreator = cloneCreator;
this.imachineToImage = imachineToImage; this.imachineToImage = imachineToImage;
this.machineController = machineController;
} }
@Override @Override
@ -199,7 +205,11 @@ public class VirtualBoxComputeServiceAdapter implements ComputeServiceAdapter<IM
public synchronized void destroyNode(String vmName) { public synchronized void destroyNode(String vmName) {
IMachine machine = manager.get().getVBox().findMachine(vmName); IMachine machine = manager.get().getVBox().findMachine(vmName);
powerDownMachine(machine); powerDownMachine(machine);
new UnregisterMachineIfExistsAndForceDeleteItsMedia().apply(machine); try {
new UnregisterMachineIfExistsAndForceDeleteItsMedia().apply(machine);
} catch (Exception e) {
logger.error("Machine (%s) not unregistered!", vmName);
}
} }
@Override @Override
@ -247,21 +257,10 @@ public class VirtualBoxComputeServiceAdapter implements ComputeServiceAdapter<IM
logger.debug("vm was already powered down: ", machine.getId()); logger.debug("vm was already powered down: ", machine.getId());
return; return;
} }
logger.debug("powering down vm: ", machine.getId()); logger.debug("powering down vm: %s", machine.getName());
ISession machineSession = manager.get().openMachineSession(machine); machineController.ensureMachineHasPowerDown(machine.getName());
IProgress progress = machineSession.getConsole().powerDown();
progress.waitForCompletion(-1);
machineSession.unlockMachine();
while (!machine.getSessionState().equals(SessionState.Unlocked)) {
try {
logger.info("waiting for unlocking session - session state: " + machine.getSessionState());
Thread.sleep(1000);
} catch (InterruptedException e) {
}
}
} catch (Exception e) { } catch (Exception e) {
logger.error(e, "problem in powering down the %s", machine.getName());
throw Throwables.propagate(e); throw Throwables.propagate(e);
} }
} }

View File

@ -236,4 +236,5 @@ public class VirtualBoxComputeServiceContextModule extends
protected Map<MachineState, Image.Status> toPortableImageStatus() { protected Map<MachineState, Image.Status> toPortableImageStatus() {
return toPortableImageStatus; return toPortableImageStatus;
} }
} }

View File

@ -50,6 +50,8 @@ public interface VirtualBoxConstants {
public static final String VIRTUALBOX_MACHINE_CREDENTIAL = "jclouds.virtualbox.credential"; public static final String VIRTUALBOX_MACHINE_CREDENTIAL = "jclouds.virtualbox.credential";
public static final String VIRTUALBOX_MACHINE_LOCATION = "jclouds.virtualbox.location"; public static final String VIRTUALBOX_MACHINE_LOCATION = "jclouds.virtualbox.location";
public static final String VIRTUALBOX_GUEST_MEMORY = "jclouds.virtualbox.guest.memory";
public static final String VIRTUALBOX_HOST_ID = "jclouds.virtualbox.hostid"; public static final String VIRTUALBOX_HOST_ID = "jclouds.virtualbox.hostid";
@ -62,7 +64,7 @@ public interface VirtualBoxConstants {
public static final String VIRTUALBOX_PROVIDER = "virtualbox"; public static final String VIRTUALBOX_PROVIDER = "virtualbox";
public static final String VIRTUALBOX_GUEST_IDENTITY = "jclouds.virtualbox.guest.identity"; public static final String GUEST_OS_PASSWORD = "guestPassword";
public static final String VIRTUALBOX_GUEST_CREDENTIAL = "jclouds.virtualbox.guest.credential";
public static final String GUEST_OS_USER = "guestUser";
} }

View File

@ -21,6 +21,8 @@ package org.jclouds.virtualbox.domain;
import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkNotNull;
import org.jclouds.domain.LoginCredentials;
import com.google.common.base.Objects; import com.google.common.base.Objects;
/** /**
@ -32,6 +34,7 @@ public class MasterSpec {
private VmSpec vmSpec; private VmSpec vmSpec;
private IsoSpec isoSpec; private IsoSpec isoSpec;
private NetworkSpec networkSpec; private NetworkSpec networkSpec;
private LoginCredentials loginCredentials;
public static Builder builder() { public static Builder builder() {
return new Builder(); return new Builder();
@ -42,6 +45,7 @@ public class MasterSpec {
private VmSpec vmSpec; private VmSpec vmSpec;
private IsoSpec isoSpec; private IsoSpec isoSpec;
private NetworkSpec networkSpec; private NetworkSpec networkSpec;
private LoginCredentials loginCredentials;
public Builder vm(VmSpec vmSpec) { public Builder vm(VmSpec vmSpec) {
this.vmSpec = vmSpec; this.vmSpec = vmSpec;
@ -58,19 +62,25 @@ public class MasterSpec {
return this; return this;
} }
public Builder credentials(LoginCredentials loginCredentials) {
this.loginCredentials = loginCredentials;
return this;
}
public MasterSpec build() { public MasterSpec build() {
return new MasterSpec(vmSpec, isoSpec, networkSpec); return new MasterSpec(vmSpec, isoSpec, networkSpec, loginCredentials);
} }
} }
private MasterSpec(VmSpec vmSpec, IsoSpec isoSpec, NetworkSpec networkSpec) { private MasterSpec(VmSpec vmSpec, IsoSpec isoSpec, NetworkSpec networkSpec, LoginCredentials loginCredentials) {
checkNotNull(vmSpec, "vmSpec"); checkNotNull(vmSpec, "vmSpec");
checkNotNull(isoSpec, "isoSpec"); checkNotNull(isoSpec, "isoSpec");
checkNotNull(networkSpec, "networkSpec"); checkNotNull(networkSpec, "networkSpec");
this.vmSpec = vmSpec; this.vmSpec = vmSpec;
this.isoSpec = isoSpec; this.isoSpec = isoSpec;
this.networkSpec = networkSpec; this.networkSpec = networkSpec;
this.loginCredentials = loginCredentials;
} }
public VmSpec getVmSpec() { public VmSpec getVmSpec() {
@ -84,6 +94,10 @@ public class MasterSpec {
public NetworkSpec getNetworkSpec() { public NetworkSpec getNetworkSpec() {
return networkSpec; return networkSpec;
} }
public LoginCredentials getLoginCredentials() {
return loginCredentials;
}
@Override @Override
public boolean equals(Object o) { public boolean equals(Object o) {

View File

@ -28,12 +28,13 @@ public class NetworkInterfaceCard {
private final long slot; private final long slot;
private final NetworkAdapter networkAdapter; private final NetworkAdapter networkAdapter;
private final String hostInterfaceName; private final String hostInterfaceName;
private final boolean enabled;
public NetworkInterfaceCard(long slot, NetworkAdapter networkAdapter, String hostInterfaceName) { public NetworkInterfaceCard(long slot, NetworkAdapter networkAdapter, String hostInterfaceName, boolean enabled) {
this.slot = checkNotNull(slot, "slot"); this.slot = checkNotNull(slot, "slot");
this.networkAdapter = checkNotNull(networkAdapter, "networkAdapter"); this.networkAdapter = checkNotNull(networkAdapter, "networkAdapter");
this.hostInterfaceName = hostInterfaceName; this.hostInterfaceName = hostInterfaceName;
this.enabled = enabled;
} }
public static Builder builder() { public static Builder builder() {
@ -45,6 +46,7 @@ public class NetworkInterfaceCard {
private long slot = 0L; private long slot = 0L;
private NetworkAdapter networkAdapter; private NetworkAdapter networkAdapter;
private String hostInterfaceName; private String hostInterfaceName;
private boolean enabled = true;
public Builder slot(long slot) { public Builder slot(long slot) {
checkArgument(slot >= 0 && slot < 4, "must be 0, 1, 2, 3: %s", slot); checkArgument(slot >= 0 && slot < 4, "must be 0, 1, 2, 3: %s", slot);
@ -62,10 +64,16 @@ public class NetworkInterfaceCard {
String hostInterfaceName) { String hostInterfaceName) {
this.hostInterfaceName = hostInterfaceName; this.hostInterfaceName = hostInterfaceName;
return this; return this;
} }
public Builder enabled(
boolean enabled) {
this.enabled = enabled;
return this;
}
public NetworkInterfaceCard build() { public NetworkInterfaceCard build() {
return new NetworkInterfaceCard(slot, networkAdapter, hostInterfaceName); return new NetworkInterfaceCard(slot, networkAdapter, hostInterfaceName, enabled);
} }
} }
@ -79,7 +87,11 @@ public class NetworkInterfaceCard {
public String getHostInterfaceName() { public String getHostInterfaceName() {
return hostInterfaceName; return hostInterfaceName;
} }
public boolean isEnabled() {
return enabled;
}
@Override @Override
public boolean equals(Object o) { public boolean equals(Object o) {
@ -89,14 +101,15 @@ public class NetworkInterfaceCard {
NetworkInterfaceCard other = (NetworkInterfaceCard) o; NetworkInterfaceCard other = (NetworkInterfaceCard) o;
return Objects.equal(slot, return Objects.equal(slot,
other.slot) && other.slot) &&
Objects.equal(networkAdapter, other.networkAdapter); Objects.equal(networkAdapter, other.networkAdapter)
&& Objects.equal(enabled, other.enabled);
} }
return false; return false;
} }
@Override @Override
public int hashCode() { public int hashCode() {
return Objects.hashCode(slot, networkAdapter); return Objects.hashCode(slot, networkAdapter, enabled);
} }
@Override @Override
@ -104,6 +117,7 @@ public class NetworkInterfaceCard {
return "NetworkInterfaceCard{slot="+ return "NetworkInterfaceCard{slot="+
slot + slot +
", networkAdapter=" + networkAdapter + ", networkAdapter=" + networkAdapter +
", enabled=" + enabled +
'}'; '}';
} }

View File

@ -42,7 +42,7 @@ public class VmSpec {
private final Set<StorageController> controllers; private final Set<StorageController> controllers;
private final CleanupMode cleanupMode; private final CleanupMode cleanupMode;
public VmSpec(String vmId, String vmName, String osTypeId, long memory, boolean forceOverwrite, public VmSpec(String vmId, String vmName, String osTypeId, long memory, String guestUser, String guestPassword, boolean forceOverwrite,
Set<StorageController> controllers, CleanupMode cleanupMode) { Set<StorageController> controllers, CleanupMode cleanupMode) {
this.vmId = checkNotNull(vmId, "vmId"); this.vmId = checkNotNull(vmId, "vmId");
this.vmName = checkNotNull(vmName, "vmName"); this.vmName = checkNotNull(vmName, "vmName");
@ -67,6 +67,8 @@ public class VmSpec {
private String osTypeId = ""; private String osTypeId = "";
private boolean forceOverwrite = true; private boolean forceOverwrite = true;
private long memory; private long memory;
private String guestUser;
private String guestPassword;
private CleanupMode cleanUpMode; private CleanupMode cleanUpMode;
public Builder controller(StorageController controller) { public Builder controller(StorageController controller) {
@ -103,13 +105,24 @@ public class VmSpec {
this.cleanUpMode = cleanupMode; this.cleanUpMode = cleanupMode;
return this; return this;
} }
public Builder guestUser(String guestUser) {
this.guestUser = guestUser;
return this;
}
public Builder guestPassword(String guestPassword) {
this.guestPassword = guestPassword;
return this;
}
public VmSpec build() { public VmSpec build() {
checkNotNull(name, "name"); checkNotNull(name, "name");
checkNotNull(id, "id"); checkNotNull(id, "id");
checkArgument(memory > 0, "Memory must be set"); checkArgument(memory > 0, "Memory must be set");
return new VmSpec(id, name, osTypeId, memory, forceOverwrite, controllers, cleanUpMode); return new VmSpec(id, name, osTypeId, memory, guestUser, guestPassword, forceOverwrite, controllers, cleanUpMode);
} }
} }
public String getVmId() { public String getVmId() {
@ -162,7 +175,8 @@ public class VmSpec {
@Override @Override
public String toString() { public String toString() {
return "VmSpecification{" + "vmName='" + vmName + '\'' + ", osTypeId='" + osTypeId + '\'' + ", memory='" + memory return "VmSpecification{" + "vmName='" + vmName + '\'' + ", osTypeId='" + osTypeId + '\'' + ", memory='" + memory
+ '\'' + ", vmId='" + vmId + '\'' + ", forceOverwrite=" + forceOverwrite + ", controllers=" + '\'' + ", vmId='" + vmId + '\'' + '\''
+ controllers + ", cleanupMode=" + cleanupMode + '}'; + ", forceOverwrite=" + forceOverwrite + ", controllers="
+ controllers + ", cleanupMode=" + cleanupMode + '}';
} }
} }

View File

@ -27,6 +27,7 @@ import org.jclouds.compute.domain.Image;
import org.jclouds.compute.domain.ImageBuilder; import org.jclouds.compute.domain.ImageBuilder;
import org.jclouds.compute.domain.OperatingSystem; import org.jclouds.compute.domain.OperatingSystem;
import org.jclouds.compute.domain.OsFamily; import org.jclouds.compute.domain.OsFamily;
import org.jclouds.domain.LoginCredentials;
import com.google.common.base.Function; import com.google.common.base.Function;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
@ -137,13 +138,16 @@ public class YamlImage {
public Image apply(YamlImage arg0) { public Image apply(YamlImage arg0) {
if (arg0 == null) if (arg0 == null)
return null; return null;
OsFamily family = parseOsFamilyOrUnrecognized(arg0.os_family); OsFamily family = parseOsFamilyOrUnrecognized(arg0.os_family);
OperatingSystem operatingSystem = OperatingSystem.builder().description(arg0.os_description).family(family) OperatingSystem operatingSystem = OperatingSystem.builder().description(arg0.os_description).family(family)
.version(arg0.os_version).is64Bit(arg0.os_64bit).arch(arg0.os_arch).build(); .version(arg0.os_version).is64Bit(arg0.os_64bit).arch(arg0.os_arch).build();
return new ImageBuilder().id(arg0.id).name(arg0.name).description(arg0.description) return new ImageBuilder().id(arg0.id).name(arg0.name).description(arg0.description)
.operatingSystem(operatingSystem).status(Image.Status.AVAILABLE).build(); .operatingSystem(operatingSystem).status(Image.Status.AVAILABLE)
.defaultCredentials(new LoginCredentials(arg0.username, arg0.credential, null, true))
.build();
} }
}; };

View File

@ -46,7 +46,7 @@ public class AttachBridgedAdapterToMachine implements Function<IMachine, Void> {
iNetworkAdapter.setAdapterType(Am79C973); iNetworkAdapter.setAdapterType(Am79C973);
iNetworkAdapter.setMACAddress(networkInterfaceCard.getNetworkAdapter().getMacAddress()); iNetworkAdapter.setMACAddress(networkInterfaceCard.getNetworkAdapter().getMacAddress());
iNetworkAdapter.setBridgedInterface(networkInterfaceCard.getHostInterfaceName()); iNetworkAdapter.setBridgedInterface(networkInterfaceCard.getHostInterfaceName());
iNetworkAdapter.setEnabled(true); iNetworkAdapter.setEnabled(networkInterfaceCard.isEnabled());
machine.saveSettings(); machine.saveSettings();
return null; return null;
} }

View File

@ -45,7 +45,7 @@ public class AttachHostOnlyAdapter implements Function<IMachine, Void> {
iNetworkAdapter.setAdapterType(Am79C973); iNetworkAdapter.setAdapterType(Am79C973);
iNetworkAdapter.setMACAddress(networkInterfaceCard.getNetworkAdapter().getMacAddress()); iNetworkAdapter.setMACAddress(networkInterfaceCard.getNetworkAdapter().getMacAddress());
iNetworkAdapter.setHostOnlyInterface(networkInterfaceCard.getHostInterfaceName()); iNetworkAdapter.setHostOnlyInterface(networkInterfaceCard.getHostInterfaceName());
iNetworkAdapter.setEnabled(true); iNetworkAdapter.setEnabled(networkInterfaceCard.isEnabled());
machine.saveSettings(); machine.saveSettings();
return null; return null;
} }

View File

@ -55,7 +55,7 @@ public class AttachNATAdapterToMachineIfNotAlreadyExists implements Function<IMa
throw e; throw e;
} }
} }
iNetworkAdapter.setEnabled(true); iNetworkAdapter.setEnabled(networkInterfaceCard.isEnabled());
machine.saveSettings(); machine.saveSettings();
return null; return null;
} }

View File

@ -19,9 +19,11 @@
package org.jclouds.virtualbox.functions; package org.jclouds.virtualbox.functions;
import static org.jclouds.virtualbox.config.VirtualBoxConstants.GUEST_OS_PASSWORD;
import static org.jclouds.virtualbox.config.VirtualBoxConstants.GUEST_OS_USER;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.concurrent.locks.ReentrantLock;
import javax.annotation.Resource; import javax.annotation.Resource;
import javax.inject.Named; import javax.inject.Named;
@ -62,8 +64,6 @@ public class CloneAndRegisterMachineFromIMachineIfNotAlreadyExists implements Fu
private final String workingDir; private final String workingDir;
private final MachineUtils machineUtils; private final MachineUtils machineUtils;
private final ReentrantLock lock = new ReentrantLock();
@Inject @Inject
public CloneAndRegisterMachineFromIMachineIfNotAlreadyExists(Supplier<VirtualBoxManager> manager, public CloneAndRegisterMachineFromIMachineIfNotAlreadyExists(Supplier<VirtualBoxManager> manager,
@Named(VirtualBoxConstants.VIRTUALBOX_WORKINGDIR) String workingDir, MachineUtils machineUtils) { @Named(VirtualBoxConstants.VIRTUALBOX_WORKINGDIR) String workingDir, MachineUtils machineUtils) {
@ -125,6 +125,13 @@ public class CloneAndRegisterMachineFromIMachineIfNotAlreadyExists implements Fu
for (NetworkInterfaceCard networkInterfaceCard : networkSpec.getNetworkInterfaceCards()) { for (NetworkInterfaceCard networkInterfaceCard : networkSpec.getNetworkInterfaceCards()) {
new AttachNicToMachine(vmSpec.getVmName(), machineUtils).apply(networkInterfaceCard); new AttachNicToMachine(vmSpec.getVmName(), machineUtils).apply(networkInterfaceCard);
} }
// set only once the creds for this machine, same coming from its master
logger.debug(">> storing guest credentials on vm %s as extra data", clonedMachine.getName());
String masterUsername = master.getExtraData(GUEST_OS_USER);
String masterPassword = master.getExtraData(GUEST_OS_PASSWORD);
clonedMachine.setExtraData(GUEST_OS_USER, masterUsername);
clonedMachine.setExtraData(GUEST_OS_PASSWORD, masterPassword);
return clonedMachine; return clonedMachine;
} }

View File

@ -21,9 +21,12 @@ package org.jclouds.virtualbox.functions;
import static com.google.common.base.Preconditions.checkState; import static com.google.common.base.Preconditions.checkState;
import static com.google.common.collect.Iterables.transform; import static com.google.common.collect.Iterables.transform;
import static org.jclouds.scriptbuilder.domain.Statements.call; import static org.jclouds.scriptbuilder.domain.Statements.call;
import static org.jclouds.virtualbox.config.VirtualBoxConstants.GUEST_OS_PASSWORD;
import static org.jclouds.virtualbox.config.VirtualBoxConstants.GUEST_OS_USER;
import static org.jclouds.virtualbox.config.VirtualBoxConstants.VIRTUALBOX_PRECONFIGURATION_URL; import static org.jclouds.virtualbox.config.VirtualBoxConstants.VIRTUALBOX_PRECONFIGURATION_URL;
import java.util.List; import java.util.List;
import java.util.concurrent.TimeUnit;
import javax.annotation.Resource; import javax.annotation.Resource;
import javax.inject.Named; import javax.inject.Named;
@ -49,10 +52,10 @@ import org.virtualbox_4_1.IMediumAttachment;
import com.google.common.base.Function; import com.google.common.base.Function;
import com.google.common.base.Predicate; import com.google.common.base.Predicate;
import com.google.common.base.Splitter; import com.google.common.base.Splitter;
import com.google.common.base.Throwables;
import com.google.common.collect.Iterables; import com.google.common.collect.Iterables;
import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture; import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.Uninterruptibles;
import com.google.inject.Inject; import com.google.inject.Inject;
@Singleton @Singleton
@ -70,7 +73,7 @@ public class CreateAndInstallVm implements Function<MasterSpec, IMachine> {
private final MachineController machineController; private final MachineController machineController;
private final String version; private final String version;
private final String preconfigurationUrl; private final String preconfigurationUrl;
@Inject @Inject
public CreateAndInstallVm( public CreateAndInstallVm(
CreateAndRegisterMachineFromIsoIfNotAlreadyExists CreateAndRegisterMachineFromIsoIfNotAlreadyExists, CreateAndRegisterMachineFromIsoIfNotAlreadyExists CreateAndRegisterMachineFromIsoIfNotAlreadyExists,
@ -92,49 +95,60 @@ public class CreateAndInstallVm implements Function<MasterSpec, IMachine> {
public IMachine apply(MasterSpec masterSpec) { public IMachine apply(MasterSpec masterSpec) {
VmSpec vmSpec = masterSpec.getVmSpec(); VmSpec vmSpec = masterSpec.getVmSpec();
IsoSpec isoSpec = masterSpec.getIsoSpec(); IsoSpec isoSpec = masterSpec.getIsoSpec();
String vmName = vmSpec.getVmName(); String masterName = vmSpec.getVmName();
IMachine vm = createAndRegisterMachineFromIsoIfNotAlreadyExists.apply(masterSpec); IMachine masterMachine = createAndRegisterMachineFromIsoIfNotAlreadyExists.apply(masterSpec);
// Launch machine and wait for it to come online // Launch machine and wait for it to come online
machineController.ensureMachineIsLaunched(vmName); machineController.ensureMachineIsLaunched(masterName);
String installationKeySequence = isoSpec.getInstallationKeySequence().replace("PRECONFIGURATION_URL", String installationKeySequence = isoSpec.getInstallationKeySequence().replace("PRECONFIGURATION_URL",
preconfigurationUrl); preconfigurationUrl);
configureOsInstallationWithKeyboardSequence(vmName, installationKeySequence);
configureOsInstallationWithKeyboardSequence(masterName, installationKeySequence);
// the OS installation is a long process: let's delay the check for ssh of 30 sec // the OS installation is a long process: let's delay the check for ssh of 40 sec
try { Uninterruptibles.sleepUninterruptibly(40, TimeUnit.SECONDS);
Thread.sleep(30000l);
} catch (InterruptedException e) { masterMachine.setExtraData(GUEST_OS_USER, masterSpec.getLoginCredentials().getUser());
Throwables.propagate(e); masterMachine.setExtraData(GUEST_OS_PASSWORD, masterSpec.getLoginCredentials().getPassword());
}
SshClient client = sshClientForIMachine.apply(vm); SshClient client = sshClientForIMachine.apply(masterMachine);
logger.debug(">> awaiting installation to finish node(%s)", vmName); logger.debug(">> awaiting installation to finish node(%s)", masterName);
checkState(sshResponds.apply(client), "timed out waiting for guest %s to be accessible via ssh", vmName); checkState(sshResponds.apply(client), "timed out waiting for guest %s to be accessible via ssh", masterName);
NodeMetadata nodeMetadata = imachineToNodeMetadata.apply(vm); NodeMetadata nodeMetadata = imachineToNodeMetadata.apply(masterMachine);
logger.debug(">> awaiting post-installation actions on vm: %s", vmName); logger.debug(">> awaiting post-installation actions on vm: %s", masterName);
ListenableFuture<ExecResponse> execCleanup = machineUtils.runScriptOnNode(nodeMetadata, ListenableFuture<ExecResponse> execCleanup = machineUtils.runScriptOnNode(nodeMetadata,
call("cleanupUdevIfNeeded"), RunScriptOptions.NONE); call("cleanupUdevIfNeeded"), RunScriptOptions.NONE);
ExecResponse cleanupResponse = Futures.getUnchecked(execCleanup); ExecResponse cleanupResponse = Futures.getUnchecked(execCleanup);
checkState(cleanupResponse.getExitStatus() == 0); checkState(cleanupResponse.getExitStatus() == 0);
logger.debug(">> awaiting installation of guest additions on vm: %s", vmName); logger.debug(">> awaiting installation of guest additions on vm: %s", masterName);
ListenableFuture<ExecResponse> execInstallGA = machineUtils.runScriptOnNode(nodeMetadata, ListenableFuture<ExecResponse> execInstallGA = machineUtils.runScriptOnNode(nodeMetadata,
new InstallGuestAdditions(vmSpec, version), RunScriptOptions.NONE); new InstallGuestAdditions(vmSpec, version), RunScriptOptions.NONE);
ExecResponse gaInstallationResponse = Futures.getUnchecked(execInstallGA); ExecResponse gaInstallationResponse = Futures.getUnchecked(execInstallGA);
checkState(gaInstallationResponse.getExitStatus() == 0); checkState(gaInstallationResponse.getExitStatus() == 0);
machineController.ensureMachineIsShutdown(vmName);
Iterable<IMediumAttachment> mediumAttachments = Iterables.filter(vm.getMediumAttachmentsOfController("IDE Controller"), machineController.ensureMachineIsShutdown(masterName);
new Predicate<IMediumAttachment>() {
public boolean apply(IMediumAttachment in) { // detach DVD and ISOs, if needed
return in.getMedium() != null && in.getMedium().getDeviceType().equals(DeviceType.DVD); Iterable<IMediumAttachment> mediumAttachments = Iterables.filter(
} masterMachine.getMediumAttachmentsOfController("IDE Controller"),
}); new Predicate<IMediumAttachment>() {
public boolean apply(IMediumAttachment in) {
return in.getMedium() != null
&& in.getMedium().getDeviceType()
.equals(DeviceType.DVD);
}
});
for (IMediumAttachment iMediumAttachment : mediumAttachments) { for (IMediumAttachment iMediumAttachment : mediumAttachments) {
machineUtils.writeLockMachineAndApply(vm.getName(), new DetachDistroMediumFromMachine( logger.debug("Detach %s from (%s)", iMediumAttachment.getMedium()
iMediumAttachment.getController(), iMediumAttachment.getPort(), iMediumAttachment.getDevice())); .getName(), masterMachine.getName());
} machineUtils.writeLockMachineAndApply(
return vm; masterMachine.getName(),
new DetachDistroMediumFromMachine(iMediumAttachment
.getController(), iMediumAttachment.getPort(),
iMediumAttachment.getDevice()));
}
return masterMachine;
} }
private void configureOsInstallationWithKeyboardSequence(String vmName, String installationKeySequence) { private void configureOsInstallationWithKeyboardSequence(String vmName, String installationKeySequence) {

View File

@ -77,30 +77,31 @@ public class CreateAndRegisterMachineFromIsoIfNotAlreadyExists implements Functi
} }
@Override @Override
public IMachine apply(MasterSpec launchSpecification) { public IMachine apply(MasterSpec masterSpec) {
final IVirtualBox vBox = manager.get().getVBox(); final IVirtualBox vBox = manager.get().getVBox();
String vmName = launchSpecification.getVmSpec().getVmName(); String vmName = masterSpec.getVmSpec().getVmName();
String vmId = launchSpecification.getVmSpec().getVmId(); String vmId = masterSpec.getVmSpec().getVmId();
try { try {
vBox.findMachine(vmId); vBox.findMachine(vmId);
throw new IllegalStateException("Machine " + vmName + " is already registered."); throw new IllegalStateException("Machine " + vmName + " is already registered.");
} catch (VBoxException e) { } catch (VBoxException e) {
if (machineNotFoundException(e)) if (machineNotFoundException(e))
return createMachine(vBox, launchSpecification); return createMachine(vBox, masterSpec);
else else
throw e; throw e;
} }
} }
private IMachine createMachine(IVirtualBox vBox, MasterSpec machineSpec) { private IMachine createMachine(IVirtualBox vBox, MasterSpec masterSpec) {
VmSpec vmSpec = machineSpec.getVmSpec(); VmSpec vmSpec = masterSpec.getVmSpec();
String settingsFile = vBox.composeMachineFilename(vmSpec.getVmName(), workingDir); String settingsFile = vBox.composeMachineFilename(vmSpec.getVmName(), workingDir);
IMachine newMachine = vBox.createMachine(settingsFile, vmSpec.getVmName(), vmSpec.getOsTypeId(), IMachine newMachine = vBox.createMachine(settingsFile, vmSpec.getVmName(), vmSpec.getOsTypeId(),
vmSpec.getVmId(), vmSpec.isForceOverwrite()); vmSpec.getVmId(), vmSpec.isForceOverwrite());
manager.get().getVBox().registerMachine(newMachine); manager.get().getVBox().registerMachine(newMachine);
ensureConfiguration(machineSpec); ensureConfiguration(masterSpec);
return newMachine; return newMachine;
} }

View File

@ -19,6 +19,8 @@
package org.jclouds.virtualbox.functions; package org.jclouds.virtualbox.functions;
import static org.jclouds.virtualbox.config.VirtualBoxConstants.GUEST_OS_PASSWORD;
import static org.jclouds.virtualbox.config.VirtualBoxConstants.GUEST_OS_USER;
import static org.jclouds.virtualbox.config.VirtualBoxConstants.VIRTUALBOX_NODE_NAME_SEPARATOR; import static org.jclouds.virtualbox.config.VirtualBoxConstants.VIRTUALBOX_NODE_NAME_SEPARATOR;
import static org.jclouds.virtualbox.config.VirtualBoxConstants.VIRTUALBOX_NODE_PREFIX; import static org.jclouds.virtualbox.config.VirtualBoxConstants.VIRTUALBOX_NODE_PREFIX;
@ -37,7 +39,7 @@ import org.jclouds.domain.LocationScope;
import org.jclouds.domain.LoginCredentials; import org.jclouds.domain.LoginCredentials;
import org.jclouds.javax.annotation.Nullable; import org.jclouds.javax.annotation.Nullable;
import org.jclouds.logging.Logger; import org.jclouds.logging.Logger;
import org.jclouds.virtualbox.util.MachineUtils; import org.jclouds.virtualbox.util.NetworkUtils;
import org.testng.collections.Lists; import org.testng.collections.Lists;
import org.virtualbox_4_1.IMachine; import org.virtualbox_4_1.IMachine;
import org.virtualbox_4_1.INetworkAdapter; import org.virtualbox_4_1.INetworkAdapter;
@ -58,12 +60,13 @@ public class IMachineToNodeMetadata implements Function<IMachine, NodeMetadata>
protected Logger logger = Logger.NULL; protected Logger logger = Logger.NULL;
private final Map<MachineState, Status> toPortableNodeStatus; private final Map<MachineState, Status> toPortableNodeStatus;
private final MachineUtils machineUtils; private final NetworkUtils networkUtils;
@Inject @Inject
public IMachineToNodeMetadata(Map<MachineState, NodeMetadata.Status> toPortableNodeStatus, MachineUtils machineUtils) { public IMachineToNodeMetadata(Map<MachineState, NodeMetadata.Status> toPortableNodeStatus,
NetworkUtils networkUtils) {
this.toPortableNodeStatus = toPortableNodeStatus; this.toPortableNodeStatus = toPortableNodeStatus;
this.machineUtils = machineUtils; this.networkUtils = networkUtils;
} }
@Override @Override
@ -95,8 +98,10 @@ public class IMachineToNodeMetadata implements Function<IMachine, NodeMetadata>
nodeState = Status.UNRECOGNIZED; nodeState = Status.UNRECOGNIZED;
nodeMetadataBuilder.status(nodeState); nodeMetadataBuilder.status(nodeState);
nodeMetadataBuilder = getIpAddresses(vm, nodeMetadataBuilder); nodeMetadataBuilder = getIpAddresses(vm, nodeMetadataBuilder);
LoginCredentials loginCredentials = new LoginCredentials("toor", "password", null, true); String guestOsUser = vm.getExtraData(GUEST_OS_USER);
String guestOsPassword = vm.getExtraData(GUEST_OS_PASSWORD);
LoginCredentials loginCredentials = new LoginCredentials(guestOsUser, guestOsPassword, null, true);
nodeMetadataBuilder.credentials(loginCredentials); nodeMetadataBuilder.credentials(loginCredentials);
return nodeMetadataBuilder.build(); return nodeMetadataBuilder.build();
@ -104,7 +109,7 @@ public class IMachineToNodeMetadata implements Function<IMachine, NodeMetadata>
private NodeMetadataBuilder getIpAddresses(IMachine vm, NodeMetadataBuilder nodeMetadataBuilder) { private NodeMetadataBuilder getIpAddresses(IMachine vm, NodeMetadataBuilder nodeMetadataBuilder) {
List<String> publicIpAddresses = Lists.newArrayList(); List<String> publicIpAddresses = Lists.newArrayList();
List<String> privateIpAddresses = Lists.newArrayList();
for(long slot = 0; slot < 4; slot ++) { for(long slot = 0; slot < 4; slot ++) {
INetworkAdapter adapter = vm.getNetworkAdapter(slot); INetworkAdapter adapter = vm.getNetworkAdapter(slot);
if(adapter != null) { if(adapter != null) {
@ -123,16 +128,15 @@ public class IMachineToNodeMetadata implements Function<IMachine, NodeMetadata>
publicIpAddresses.add(hostAddress); publicIpAddresses.add(hostAddress);
nodeMetadataBuilder.loginPort(inPort); nodeMetadataBuilder.loginPort(inPort);
} }
//privateIpAddresses.add((NodeCreator.VMS_NETWORK + ipTermination) + "");
} }
// TODO this could be a public and private address
} else if (adapter.getAttachmentType() == NetworkAttachmentType.Bridged) { } else if (adapter.getAttachmentType() == NetworkAttachmentType.Bridged) {
String clientIpAddress = machineUtils.getIpAddressFromFirstNIC(vm.getName()); // TODO quick test first
//privateIpAddresses.add(clientIpAddress); String clientIpAddress = networkUtils.getIpAddressFromNicSlot(vm.getName(), adapter.getSlot());
publicIpAddresses.add(clientIpAddress); privateIpAddresses.add(clientIpAddress);
} else if (adapter.getAttachmentType() == NetworkAttachmentType.HostOnly) { } else if (adapter.getAttachmentType() == NetworkAttachmentType.HostOnly) {
String clientIpAddress = machineUtils.getIpAddressFromFirstNIC(vm.getName()); // TODO quick test first
String clientIpAddress = networkUtils.getIpAddressFromNicSlot(vm.getName(), adapter.getSlot());
publicIpAddresses.add(clientIpAddress); publicIpAddresses.add(clientIpAddress);
} }
} }

View File

@ -19,36 +19,24 @@
package org.jclouds.virtualbox.functions; package org.jclouds.virtualbox.functions;
import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState; import static org.jclouds.virtualbox.config.VirtualBoxConstants.GUEST_OS_PASSWORD;
import static org.jclouds.virtualbox.config.VirtualBoxConstants.VIRTUALBOX_GUEST_CREDENTIAL; import static org.jclouds.virtualbox.config.VirtualBoxConstants.GUEST_OS_USER;
import static org.jclouds.virtualbox.config.VirtualBoxConstants.VIRTUALBOX_GUEST_IDENTITY;
import java.util.List;
import javax.annotation.Resource; import javax.annotation.Resource;
import javax.inject.Named; import javax.inject.Named;
import javax.inject.Singleton; import javax.inject.Singleton;
import org.jclouds.compute.callables.RunScriptOnNode;
import org.jclouds.compute.domain.ExecResponse;
import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.options.RunScriptOptions;
import org.jclouds.compute.reference.ComputeServiceConstants; import org.jclouds.compute.reference.ComputeServiceConstants;
import org.jclouds.domain.LoginCredentials; import org.jclouds.domain.LoginCredentials;
import org.jclouds.logging.Logger; import org.jclouds.logging.Logger;
import org.jclouds.ssh.SshClient; import org.jclouds.ssh.SshClient;
import org.jclouds.virtualbox.VirtualBoxApiMetadata; import org.jclouds.virtualbox.util.NetworkUtils;
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.IMachine;
import org.virtualbox_4_1.INetworkAdapter; import org.virtualbox_4_1.INetworkAdapter;
import org.virtualbox_4_1.NetworkAttachmentType; import org.virtualbox_4_1.NetworkAttachmentType;
import com.google.common.base.Function; import com.google.common.base.Function;
import com.google.common.base.Splitter; import com.google.common.base.Splitter;
import com.google.common.base.Supplier;
import com.google.common.collect.Iterables; import com.google.common.collect.Iterables;
import com.google.common.net.HostAndPort; import com.google.common.net.HostAndPort;
import com.google.inject.Inject; import com.google.inject.Inject;
@ -61,36 +49,30 @@ public class IMachineToSshClient implements Function<IMachine, SshClient> {
protected Logger logger = Logger.NULL; protected Logger logger = Logger.NULL;
private final SshClient.Factory sshClientFactory; private final SshClient.Factory sshClientFactory;
private final RunScriptOnNode.Factory scriptRunnerFactory; private final NetworkUtils networkUtils;
private final Supplier<NodeMetadata> hostSupplier;
private final MachineUtils machineUtils;
@Inject @Inject
public IMachineToSshClient(SshClient.Factory sshClientFactory, public IMachineToSshClient(SshClient.Factory sshClientFactory,
RunScriptOnNode.Factory scriptRunnerFactory, NetworkUtils networkUtils) {
Supplier<NodeMetadata> hostSupplier, MachineUtils machineUtils) {
this.sshClientFactory = sshClientFactory; this.sshClientFactory = sshClientFactory;
this.scriptRunnerFactory = scriptRunnerFactory; this.networkUtils = networkUtils;
this.hostSupplier = hostSupplier;
this.machineUtils = machineUtils;
} }
@Override @Override
public SshClient apply(final IMachine vm) { public SshClient apply(final IMachine vm) {
INetworkAdapter networkAdapter = vm.getNetworkAdapter(0L); INetworkAdapter networkAdapter = vm.getNetworkAdapter(0L);
SshClient client = null; SshClient client = null;
checkNotNull(networkAdapter); checkNotNull(networkAdapter);
String clientIpAddress = null; String clientIpAddress = null;
String sshPort = "22"; String sshPort = "22";
String guestIdentity = vm.getExtraData(GUEST_OS_USER);
String guestCredential = vm.getExtraData(GUEST_OS_PASSWORD);
String guestIdentity = VirtualBoxApiMetadata.defaultProperties().getProperty(VIRTUALBOX_GUEST_IDENTITY); LoginCredentials loginCredentials = LoginCredentials.builder()
String guestCredential = VirtualBoxApiMetadata.defaultProperties().getProperty(VIRTUALBOX_GUEST_CREDENTIAL); .user(guestIdentity).password(guestCredential)
LoginCredentials loginCredentials = LoginCredentials.builder() .authenticateSudo(true).build();
.user(guestIdentity)
.password(guestCredential).authenticateSudo(true)
.build();
if (networkAdapter.getAttachmentType() if (networkAdapter.getAttachmentType()
.equals(NetworkAttachmentType.NAT)) { .equals(NetworkAttachmentType.NAT)) {
@ -109,11 +91,10 @@ public class IMachineToSshClient implements Function<IMachine, SshClient> {
} }
} else if (networkAdapter.getAttachmentType().equals( } else if (networkAdapter.getAttachmentType().equals(
NetworkAttachmentType.Bridged)) { NetworkAttachmentType.Bridged)) {
String network = "1.1.1.1"; clientIpAddress = networkUtils.getIpAddressFromNicSlot(vm.getName(), networkAdapter.getSlot());
clientIpAddress = getIpAddressFromBridgedNIC(networkAdapter, network);
} else if (networkAdapter.getAttachmentType().equals( } else if (networkAdapter.getAttachmentType().equals(
NetworkAttachmentType.HostOnly)) { NetworkAttachmentType.HostOnly)) {
clientIpAddress = machineUtils.getIpAddressFromFirstNIC(vm.getName()); clientIpAddress = networkUtils.getIpAddressFromNicSlot(vm.getName(), networkAdapter.getSlot());
} }
checkNotNull(clientIpAddress, "clientIpAddress"); checkNotNull(clientIpAddress, "clientIpAddress");
@ -124,28 +105,4 @@ public class IMachineToSshClient implements Function<IMachine, SshClient> {
return client; return client;
} }
private String getIpAddressFromBridgedNIC(INetworkAdapter networkAdapter,
String network) {
// RetrieveActiveBridgedInterfaces
List<BridgedIf> activeBridgedInterfaces = new RetrieveActiveBridgedInterfaces(scriptRunnerFactory).apply(hostSupplier.get());
BridgedIf activeBridgedIf = checkNotNull(Iterables.get(activeBridgedInterfaces, 0), "activeBridgedInterfaces");
network = activeBridgedIf.getIpAddress();
// scan ip
RunScriptOnNode ipScanRunScript = scriptRunnerFactory.create(
hostSupplier.get(), new ScanNetworkWithPing(network),
RunScriptOptions.NONE);
ExecResponse execResponse = ipScanRunScript.init().call();
checkState(execResponse.getExitStatus() == 0);
// retrieve ip from mac
RunScriptOnNode getIpFromMACAddressRunScript = scriptRunnerFactory
.create(hostSupplier.get(), new GetIPAddressFromMAC(
networkAdapter.getMACAddress()),
RunScriptOptions.NONE);
ExecResponse ipExecResponse = getIpFromMACAddressRunScript.init()
.call();
checkState(ipExecResponse.getExitStatus() == 0);
return checkNotNull(ipExecResponse.getOutput(), "ipAddress");
}
} }

View File

@ -23,6 +23,7 @@ import static com.google.common.base.Preconditions.checkNotNull;
import java.util.Map; import java.util.Map;
import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import javax.annotation.Resource; import javax.annotation.Resource;
import javax.inject.Inject; import javax.inject.Inject;
@ -31,30 +32,33 @@ import javax.inject.Singleton;
import org.jclouds.compute.reference.ComputeServiceConstants; import org.jclouds.compute.reference.ComputeServiceConstants;
import org.jclouds.logging.Logger; import org.jclouds.logging.Logger;
import org.jclouds.virtualbox.util.MachineUtils; import org.jclouds.virtualbox.util.MachineNameOrIdAndNicSlot;
import org.jclouds.virtualbox.util.NetworkUtils;
import org.virtualbox_4_1.VirtualBoxManager; import org.virtualbox_4_1.VirtualBoxManager;
import com.google.common.base.Strings;
import com.google.common.base.Supplier; import com.google.common.base.Supplier;
import com.google.common.cache.AbstractLoadingCache; import com.google.common.cache.AbstractLoadingCache;
import com.google.common.cache.LoadingCache; import com.google.common.cache.LoadingCache;
import com.google.common.collect.Maps; import com.google.common.collect.Maps;
import com.google.common.util.concurrent.Uninterruptibles;
/** /**
* A {@link LoadingCache} for ip addresses. If the requested ip address has been * A {@link LoadingCache} for ip addresses. If the requested ip address has been
* previously extracted this returns it, if not it calls vbox api. * previously extracted this returns it, if not it calls vbox api.
* *
* @author andrea turli * @author Andrea Turli
* *
*/ */
@Singleton @Singleton
public class IpAddressesLoadingCache extends public class IpAddressesLoadingCache extends
AbstractLoadingCache<String, String> { AbstractLoadingCache<MachineNameOrIdAndNicSlot, String> {
@Resource @Resource
@Named(ComputeServiceConstants.COMPUTE_LOGGER) @Named(ComputeServiceConstants.COMPUTE_LOGGER)
protected Logger logger = Logger.NULL; protected Logger logger = Logger.NULL;
private final Map<String, String> masters = Maps.newHashMap(); private final Map<MachineNameOrIdAndNicSlot, String> masters = Maps.newHashMap();
private final Supplier<VirtualBoxManager> manager; private final Supplier<VirtualBoxManager> manager;
@Inject @Inject
@ -63,27 +67,23 @@ public class IpAddressesLoadingCache extends
} }
@Override @Override
public synchronized String get(String idOrName) throws ExecutionException { public synchronized String get(MachineNameOrIdAndNicSlot machineNameOrIdAndNicPort) throws ExecutionException {
if (masters.containsKey(idOrName)) { if (masters.containsKey(machineNameOrIdAndNicPort)) {
return masters.get(idOrName); return masters.get(machineNameOrIdAndNicPort);
} }
String query = String.format("/VirtualBox/GuestInfo/Net/%s/V4/IP", machineNameOrIdAndNicPort.getSlotText());
String currentIp = "", previousIp = ""; String currentIp = "";
int count = 0; while (!NetworkUtils.isIpv4(currentIp)) {
while (count < 3) { currentIp = manager.get().getVBox().findMachine(machineNameOrIdAndNicPort.getMachineNameOrId())
currentIp = ""; .getGuestPropertyValue(query);
while (!MachineUtils.isIpv4(currentIp)) { if(!Strings.nullToEmpty(currentIp).isEmpty())
currentIp = manager.get().getVBox().findMachine(idOrName) logger.debug("Found IP address %s for '%s' at slot %s", currentIp,
.getGuestPropertyValue("/VirtualBox/GuestInfo/Net/0/V4/IP"); machineNameOrIdAndNicPort.getMachineNameOrId(),
machineNameOrIdAndNicPort.getSlotText());
Uninterruptibles.sleepUninterruptibly(1, TimeUnit.SECONDS);
} }
if (previousIp.equals(currentIp)) { masters.put(machineNameOrIdAndNicPort, currentIp);
count++;
}
previousIp = currentIp;
}
masters.put(idOrName, currentIp);
return currentIp; return currentIp;
} }
@ -92,4 +92,9 @@ public class IpAddressesLoadingCache extends
return masters.get((String) key); return masters.get((String) key);
} }
@Override
public void invalidate(Object key) {
masters.remove(key);
}
} }

View File

@ -75,11 +75,6 @@ public class LaunchMachineIfNotAlreadyRunning implements Function<IMachine, ISes
final IProgress progress = machine final IProgress progress = machine
.launchVMProcess(session, type.stringValue(), environment); .launchVMProcess(session, type.stringValue(), environment);
progress.waitForCompletion(-1); progress.waitForCompletion(-1);
try {
Thread.sleep(3000l);
} catch (InterruptedException e) {
propagate(e);
}
} catch (VBoxException e) { } catch (VBoxException e) {
ErrorCode errorCode = ErrorCode.valueOf(e); ErrorCode errorCode = ErrorCode.valueOf(e);
switch (errorCode) { switch (errorCode) {

View File

@ -50,6 +50,7 @@ import org.jclouds.compute.domain.ExecResponse;
import org.jclouds.compute.domain.Image; import org.jclouds.compute.domain.Image;
import org.jclouds.compute.domain.NodeMetadata; import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.reference.ComputeServiceConstants; import org.jclouds.compute.reference.ComputeServiceConstants;
import org.jclouds.domain.LoginCredentials;
import org.jclouds.location.Provider; import org.jclouds.location.Provider;
import org.jclouds.logging.Logger; import org.jclouds.logging.Logger;
import org.jclouds.rest.annotations.BuildVersion; import org.jclouds.rest.annotations.BuildVersion;
@ -68,6 +69,7 @@ import org.jclouds.virtualbox.domain.VmSpec;
import org.jclouds.virtualbox.domain.YamlImage; import org.jclouds.virtualbox.domain.YamlImage;
import org.jclouds.virtualbox.functions.admin.PreseedCfgServer; import org.jclouds.virtualbox.functions.admin.PreseedCfgServer;
import org.jclouds.virtualbox.predicates.RetryIfSocketNotYetOpen; import org.jclouds.virtualbox.predicates.RetryIfSocketNotYetOpen;
import org.jclouds.virtualbox.util.NetworkUtils;
import org.testng.collections.Lists; import org.testng.collections.Lists;
import org.virtualbox_4_1.CleanupMode; import org.virtualbox_4_1.CleanupMode;
import org.virtualbox_4_1.IMachine; import org.virtualbox_4_1.IMachine;
@ -76,6 +78,7 @@ import org.virtualbox_4_1.StorageBus;
import org.virtualbox_4_1.VBoxException; import org.virtualbox_4_1.VBoxException;
import org.virtualbox_4_1.VirtualBoxManager; import org.virtualbox_4_1.VirtualBoxManager;
import com.google.common.base.CaseFormat;
import com.google.common.base.Function; import com.google.common.base.Function;
import com.google.common.base.Splitter; import com.google.common.base.Splitter;
import com.google.common.base.Supplier; import com.google.common.base.Supplier;
@ -98,9 +101,6 @@ import com.google.common.net.HostAndPort;
@Singleton @Singleton
public class MastersLoadingCache extends AbstractLoadingCache<Image, Master> { public class MastersLoadingCache extends AbstractLoadingCache<Image, Master> {
// TODO parameterize
public static final int MASTER_PORT = 2222;
@Resource @Resource
@Named(ComputeServiceConstants.COMPUTE_LOGGER) @Named(ComputeServiceConstants.COMPUTE_LOGGER)
protected Logger logger = Logger.NULL; protected Logger logger = Logger.NULL;
@ -197,18 +197,17 @@ public class MastersLoadingCache extends AbstractLoadingCache<Image, Master> {
server.start(preconfigurationUrl, currentImage.preseed_cfg); server.start(preconfigurationUrl, currentImage.preseed_cfg);
} }
} catch (URISyntaxException e1) { } catch (URISyntaxException e1) {
logger.error("Cannot start the preseed server", e);
throw e; throw e;
} }
MasterSpec masterSpec = buildMasterSpecFromYaml(currentImage, MasterSpec masterSpec = buildMasterSpecFromYaml(currentImage,
vmName); vmName);
// create the master machine if it can't be found
masterMachine = masterCreatorAndInstaller.apply(masterSpec); masterMachine = masterCreatorAndInstaller.apply(masterSpec);
// build the master
master = Master.builder().machine(masterMachine) master = Master.builder().machine(masterMachine)
.spec(masterSpec).build(); .spec(masterSpec).build();
} else { } else {
logger.error("Problem during master creation", e);
throw e; throw e;
} }
} finally { } finally {
@ -241,15 +240,16 @@ public class MastersLoadingCache extends AbstractLoadingCache<Image, Master> {
.attachISO(0, 0, localIsoUrl).attachHardDisk(hardDisk) .attachISO(0, 0, localIsoUrl).attachHardDisk(hardDisk)
.attachISO(1, 0, guestAdditionsIso).build(); .attachISO(1, 0, guestAdditionsIso).build();
VmSpec vmSpecification = VmSpec.builder().id(currentImage.id) VmSpec vmSpecification = VmSpec.builder().id(currentImage.id)
.name(vmName).memoryMB(512).osTypeId("") .name(vmName).memoryMB(512).osTypeId(getOsTypeId(currentImage.os_family, currentImage.os_64bit))
.controller(ideController).forceOverwrite(true) .controller(ideController).forceOverwrite(true)
.guestUser(currentImage.username).guestPassword(currentImage.credential)
.cleanUpMode(CleanupMode.Full).build(); .cleanUpMode(CleanupMode.Full).build();
NetworkAdapter networkAdapter = NetworkAdapter NetworkAdapter networkAdapter = NetworkAdapter
.builder() .builder()
.networkAttachmentType(NetworkAttachmentType.NAT) .networkAttachmentType(NetworkAttachmentType.NAT)
.tcpRedirectRule(providerSupplier.get().getHost(), MASTER_PORT, .tcpRedirectRule(providerSupplier.get().getHost(), NetworkUtils.MASTER_PORT,
"", 22).build(); "", 22).build();
NetworkInterfaceCard networkInterfaceCard = NetworkInterfaceCard NetworkInterfaceCard networkInterfaceCard = NetworkInterfaceCard
@ -257,7 +257,7 @@ public class MastersLoadingCache extends AbstractLoadingCache<Image, Master> {
NetworkSpec networkSpec = NetworkSpec.builder() NetworkSpec networkSpec = NetworkSpec.builder()
.addNIC(networkInterfaceCard).build(); .addNIC(networkInterfaceCard).build();
return MasterSpec return MasterSpec
.builder() .builder()
.vm(vmSpecification) .vm(vmSpecification)
@ -267,10 +267,12 @@ public class MastersLoadingCache extends AbstractLoadingCache<Image, Master> {
.installationScript( .installationScript(
installationKeySequence.replace("HOSTNAME", installationKeySequence.replace("HOSTNAME",
vmSpecification.getVmName())).build()) vmSpecification.getVmName())).build())
.network(networkSpec).build(); .network(networkSpec)
.credentials(new LoginCredentials(currentImage.username, currentImage.credential, null, true))
.build();
} }
@Override @Override
public synchronized Master getIfPresent(Object key) { public synchronized Master getIfPresent(Object key) {
checkArgument(key instanceof Image, checkArgument(key instanceof Image,
"this cache is for entries who's keys are Images"); "this cache is for entries who's keys are Images");
@ -315,4 +317,8 @@ public class MastersLoadingCache extends AbstractLoadingCache<Image, Master> {
return file.getAbsolutePath(); return file.getAbsolutePath();
} }
private String getOsTypeId(String os_family, boolean os_64bit) {
String osFamily = CaseFormat.LOWER_CAMEL.to(CaseFormat.UPPER_CAMEL, os_family);
return os_64bit ? osFamily + "_64" : osFamily;
}
} }

View File

@ -21,52 +21,42 @@ package org.jclouds.virtualbox.functions;
import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState; import static com.google.common.base.Preconditions.checkState;
import static org.jclouds.compute.options.RunScriptOptions.Builder.runAsRoot; import static org.jclouds.virtualbox.config.VirtualBoxConstants.GUEST_OS_PASSWORD;
import static org.jclouds.virtualbox.config.VirtualBoxConstants.VIRTUALBOX_GUEST_CREDENTIAL; import static org.jclouds.virtualbox.config.VirtualBoxConstants.GUEST_OS_USER;
import static org.jclouds.virtualbox.config.VirtualBoxConstants.VIRTUALBOX_GUEST_IDENTITY; import static org.jclouds.virtualbox.config.VirtualBoxConstants.VIRTUALBOX_GUEST_MEMORY;
import static org.jclouds.virtualbox.config.VirtualBoxConstants.VIRTUALBOX_IMAGE_PREFIX; 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_NAME_SEPARATOR;
import static org.jclouds.virtualbox.config.VirtualBoxConstants.VIRTUALBOX_NODE_PREFIX; import static org.jclouds.virtualbox.config.VirtualBoxConstants.VIRTUALBOX_NODE_PREFIX;
import java.net.URI; import javax.annotation.Resource;
import java.util.List;
import javax.inject.Inject; import javax.inject.Inject;
import javax.inject.Named;
import javax.inject.Singleton; import javax.inject.Singleton;
import org.jclouds.compute.ComputeServiceAdapter.NodeAndInitialCredentials; import org.jclouds.compute.ComputeServiceAdapter.NodeAndInitialCredentials;
import org.jclouds.compute.callables.RunScriptOnNode; 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.NodeMetadata;
import org.jclouds.compute.domain.NodeMetadataBuilder; import org.jclouds.compute.domain.NodeMetadataBuilder;
import org.jclouds.compute.options.RunScriptOptions; import org.jclouds.compute.options.RunScriptOptions;
import org.jclouds.compute.reference.ComputeServiceConstants;
import org.jclouds.domain.LoginCredentials; import org.jclouds.domain.LoginCredentials;
import org.jclouds.javax.annotation.Nullable; import org.jclouds.logging.Logger;
import org.jclouds.location.Provider;
import org.jclouds.rest.annotations.Credential;
import org.jclouds.rest.annotations.Identity;
import org.jclouds.scriptbuilder.domain.Statements;
import org.jclouds.virtualbox.VirtualBoxApiMetadata;
import org.jclouds.virtualbox.config.VirtualBoxComputeServiceContextModule; import org.jclouds.virtualbox.config.VirtualBoxComputeServiceContextModule;
import org.jclouds.virtualbox.domain.CloneSpec; import org.jclouds.virtualbox.domain.CloneSpec;
import org.jclouds.virtualbox.domain.Master; import org.jclouds.virtualbox.domain.Master;
import org.jclouds.virtualbox.domain.NetworkAdapter;
import org.jclouds.virtualbox.domain.NetworkInterfaceCard; import org.jclouds.virtualbox.domain.NetworkInterfaceCard;
import org.jclouds.virtualbox.domain.NetworkSpec; import org.jclouds.virtualbox.domain.NetworkSpec;
import org.jclouds.virtualbox.domain.NodeSpec; import org.jclouds.virtualbox.domain.NodeSpec;
import org.jclouds.virtualbox.domain.VmSpec; import org.jclouds.virtualbox.domain.VmSpec;
import org.jclouds.virtualbox.statements.DeleteGShadowLock; import org.jclouds.virtualbox.statements.DeleteGShadowLock;
import org.jclouds.virtualbox.statements.EnableNetworkInterface;
import org.jclouds.virtualbox.util.MachineController; import org.jclouds.virtualbox.util.MachineController;
import org.jclouds.virtualbox.util.MachineUtils; import org.jclouds.virtualbox.util.MachineUtils;
import org.jclouds.virtualbox.util.NetworkUtils;
import org.virtualbox_4_1.CleanupMode; 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.IMachine;
import org.virtualbox_4_1.IProgress; import org.virtualbox_4_1.IProgress;
import org.virtualbox_4_1.ISession; import org.virtualbox_4_1.ISession;
import org.virtualbox_4_1.LockType;
import org.virtualbox_4_1.NetworkAttachmentType; import org.virtualbox_4_1.NetworkAttachmentType;
import org.virtualbox_4_1.VirtualBoxManager; import org.virtualbox_4_1.VirtualBoxManager;
@ -74,7 +64,6 @@ import com.google.common.base.Function;
import com.google.common.base.Optional; import com.google.common.base.Optional;
import com.google.common.base.Predicate; import com.google.common.base.Predicate;
import com.google.common.base.Supplier; import com.google.common.base.Supplier;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet; import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables; import com.google.common.collect.Iterables;
@ -87,67 +76,65 @@ import com.google.common.collect.Iterables;
*/ */
@Singleton @Singleton
public class NodeCreator implements Function<NodeSpec, NodeAndInitialCredentials<IMachine>> { public class NodeCreator implements Function<NodeSpec, NodeAndInitialCredentials<IMachine>> {
@Resource
@Named(ComputeServiceConstants.COMPUTE_LOGGER)
protected Logger logger = Logger.NULL;
private final Supplier<VirtualBoxManager> manager; private final Supplier<VirtualBoxManager> manager;
private final Function<CloneSpec, IMachine> cloner; private final Function<CloneSpec, IMachine> cloner;
private final MachineUtils machineUtils; private final MachineUtils machineUtils;
private final MachineController machineController; private final MachineController machineController;
private final Factory runScriptOnNodeFactory; private final NetworkUtils networkUtils;
private final Supplier<NodeMetadata> host; private final int ram;
private final Supplier<URI> providerSupplier;
private final String username;
private final String password;
private int ram = 512;
private final String guestIdentity = VirtualBoxApiMetadata.defaultProperties().getProperty(VIRTUALBOX_GUEST_IDENTITY);
private final String guestCredential = VirtualBoxApiMetadata.defaultProperties().getProperty(VIRTUALBOX_GUEST_CREDENTIAL);
@Inject @Inject
public NodeCreator(Supplier<VirtualBoxManager> manager, Function<CloneSpec, IMachine> cloner, Factory runScriptOnNodeFactory, public NodeCreator(Supplier<VirtualBoxManager> manager, Function<CloneSpec, IMachine> cloner,
MachineUtils machineUtils, RunScriptOnNode.Factory scriptRunnerFactory, MachineController machineController, MachineUtils machineUtils, RunScriptOnNode.Factory scriptRunnerFactory, MachineController machineController,
Supplier<NodeMetadata> host, NetworkUtils networkUtils,
@Provider Supplier<URI> providerSupplier, @Named(VIRTUALBOX_GUEST_MEMORY) String ram) {
@Nullable @Identity String identity,
@Nullable @Credential String credential) {
this.manager = manager; this.manager = manager;
this.cloner = cloner; this.cloner = cloner;
this.runScriptOnNodeFactory = checkNotNull(runScriptOnNodeFactory, "runScriptOnNodeFactory"); this.networkUtils = networkUtils;
this.machineUtils = machineUtils; this.machineUtils = machineUtils;
this.machineController = machineController; this.machineController = machineController;
this.host = checkNotNull(host, "host"); this.ram = Integer.valueOf(ram);
this.providerSupplier = checkNotNull(providerSupplier,
"endpoint to virtualbox websrvd is needed");
this.username = identity;
this.password = credential;
} }
@Override @Override
public synchronized NodeAndInitialCredentials<IMachine> apply(NodeSpec nodeSpec) { public synchronized NodeAndInitialCredentials<IMachine> apply(NodeSpec nodeSpec) {
checkNotNull(nodeSpec, "NodeSpec"); checkNotNull(nodeSpec, "NodeSpec");
Master master = checkNotNull(nodeSpec.getMaster(), "Master"); Master master = checkNotNull(nodeSpec.getMaster(), "Master");
if (master.getMachine().getCurrentSnapshot() != null) { if (master.getMachine().getCurrentSnapshot() != null) {
ISession session; ISession session;
try { try {
session = manager.get().openMachineSession(master.getMachine()); session = manager.get().getSessionObject();
master.getMachine().lockMachine(session, LockType.Write);
IProgress progress = session.getConsole().deleteSnapshot(master.getMachine().getCurrentSnapshot().getId());
progress.waitForCompletion(-1);
session.unlockMachine();
} catch (Exception e) { } catch (Exception e) {
throw new RuntimeException("error opening vbox machine session: " + e.getMessage(), e); throw new RuntimeException("error opening vbox machine session: " + e.getMessage(), e);
} }
IProgress progress = session.getConsole().deleteSnapshot(master.getMachine().getCurrentSnapshot().getId()); logger.debug("Deleted an existing snapshot from %s", master.getMachine().getName());
progress.waitForCompletion(-1);
session.unlockMachine();
} }
String masterNameWithoutPrefix = master.getMachine().getName().replace(VIRTUALBOX_IMAGE_PREFIX, ""); String masterNameWithoutPrefix = master.getMachine().getName().replace(VIRTUALBOX_IMAGE_PREFIX, "");
String cloneName = VIRTUALBOX_NODE_PREFIX + masterNameWithoutPrefix + VIRTUALBOX_NODE_NAME_SEPARATOR String cloneName = VIRTUALBOX_NODE_PREFIX + masterNameWithoutPrefix + VIRTUALBOX_NODE_NAME_SEPARATOR
+ nodeSpec.getTag() + VIRTUALBOX_NODE_NAME_SEPARATOR + nodeSpec.getName(); + nodeSpec.getTag() + VIRTUALBOX_NODE_NAME_SEPARATOR + nodeSpec.getName();
if (nodeSpec.getTemplate() != null && nodeSpec.getTemplate().getHardware() != null
&& nodeSpec.getTemplate().getHardware().getRam() > 0) { IMachine masterMachine = master.getMachine();
ram = nodeSpec.getTemplate().getHardware().getRam(); String username = masterMachine.getExtraData(GUEST_OS_USER);
} String password = masterMachine.getExtraData(GUEST_OS_PASSWORD);
VmSpec cloneVmSpec = VmSpec.builder().id(cloneName).name(cloneName).memoryMB(ram) VmSpec cloneVmSpec = VmSpec.builder().id(cloneName).name(cloneName).memoryMB(ram)
.guestUser(username).guestPassword(password)
.cleanUpMode(CleanupMode.Full) .cleanUpMode(CleanupMode.Full)
.forceOverwrite(true).build(); .forceOverwrite(true).build();
// case 'vbox host is localhost': NAT + HOST-ONLY // case 'vbox host is localhost': NAT + HOST-ONLY
NetworkSpec networkSpec = createNetworkSpecWhenVboxIsLocalhost(); NetworkSpec networkSpec = networkUtils.createNetworkSpecWhenVboxIsLocalhost();
Optional<NetworkInterfaceCard> optionalNatIfaceCard = Iterables.tryFind( Optional<NetworkInterfaceCard> optionalNatIfaceCard = Iterables.tryFind(
networkSpec.getNetworkInterfaceCards(), networkSpec.getNetworkInterfaceCards(),
new Predicate<NetworkInterfaceCard>() { new Predicate<NetworkInterfaceCard>() {
@ -161,9 +148,10 @@ public class NodeCreator implements Function<NodeSpec, NodeAndInitialCredentials
CloneSpec cloneSpec = CloneSpec.builder().linked(true).master(master.getMachine()).network(networkSpec) CloneSpec cloneSpec = CloneSpec.builder().linked(true).master(master.getMachine()).network(networkSpec)
.vm(cloneVmSpec).build(); .vm(cloneVmSpec).build();
logger.debug("Cloning a new guest an existing snapshot from %s ...", master.getMachine().getName());
IMachine cloned = cloner.apply(cloneSpec); IMachine cloned = cloner.apply(cloneSpec);
machineController.ensureMachineIsLaunched(cloneVmSpec.getVmName()); machineController.ensureMachineIsLaunched(cloneVmSpec.getVmName());
// IMachineToNodeMetadata produces the final ip's but these need to be set before so we build a // IMachineToNodeMetadata produces the final ip's but these need to be set before so we build a
// NodeMetadata just for the sake of running the gshadow and setip scripts // NodeMetadata just for the sake of running the gshadow and setip scripts
NodeMetadata partialNodeMetadata = buildPartialNodeMetadata(cloned); NodeMetadata partialNodeMetadata = buildPartialNodeMetadata(cloned);
@ -172,139 +160,37 @@ public class NodeCreator implements Function<NodeSpec, NodeAndInitialCredentials
machineUtils.runScriptOnNode(partialNodeMetadata, new DeleteGShadowLock(), RunScriptOptions.NONE); machineUtils.runScriptOnNode(partialNodeMetadata, new DeleteGShadowLock(), RunScriptOptions.NONE);
if(optionalNatIfaceCard.isPresent()) if(optionalNatIfaceCard.isPresent())
machineUtils.runScriptOnNode(partialNodeMetadata, new EnableNetworkInterface(optionalNatIfaceCard.get()), RunScriptOptions.NONE); checkState(networkUtils.enableNetworkInterface(partialNodeMetadata, optionalNatIfaceCard.get()) == true,
"cannot enable Nat Interface");
LoginCredentials credentials = partialNodeMetadata.getCredentials();
return new NodeAndInitialCredentials<IMachine>(cloned, return new NodeAndInitialCredentials<IMachine>(cloned,
cloneName, LoginCredentials.builder() cloneName, credentials);
.user(guestIdentity)
.password(guestCredential)
.authenticateSudo(true)
.build());
} }
private NodeMetadata buildPartialNodeMetadata(IMachine clone) { private NodeMetadata buildPartialNodeMetadata(IMachine clone) {
NodeMetadataBuilder nodeMetadataBuilder = new NodeMetadataBuilder(); NodeMetadataBuilder nodeMetadataBuilder = new NodeMetadataBuilder();
nodeMetadataBuilder.id(clone.getName()); nodeMetadataBuilder.id(clone.getName());
nodeMetadataBuilder.status(VirtualBoxComputeServiceContextModule.toPortableNodeStatus.get(clone.getState())); nodeMetadataBuilder.status(VirtualBoxComputeServiceContextModule.toPortableNodeStatus.get(clone.getState()));
nodeMetadataBuilder.publicAddresses(ImmutableSet.of(machineUtils.getIpAddressFromFirstNIC(clone.getName()))); long slot = findSlotForNetworkAttachment(clone, NetworkAttachmentType.HostOnly);
LoginCredentials loginCredentials = new LoginCredentials(guestIdentity, guestCredential, null, true); nodeMetadataBuilder.publicAddresses(ImmutableSet.of(networkUtils.getIpAddressFromNicSlot(clone.getName(), slot)));
String guestOsUser = clone.getExtraData(GUEST_OS_USER);
String guestOsPassword = clone.getExtraData(GUEST_OS_PASSWORD);
LoginCredentials loginCredentials = new LoginCredentials(guestOsUser, guestOsPassword, null, true);
nodeMetadataBuilder.credentials(loginCredentials); nodeMetadataBuilder.credentials(loginCredentials);
return nodeMetadataBuilder.build(); return nodeMetadataBuilder.build();
} }
private NetworkSpec createNetworkSpecWhenVboxIsLocalhost() { private long findSlotForNetworkAttachment(IMachine clone, NetworkAttachmentType networkAttachmentType) {
NetworkAdapter natAdapter = NetworkAdapter.builder().networkAttachmentType(NetworkAttachmentType.NAT) long slot = -1, i = 0;
.build(); while (slot == -1 && i < 4) {
NetworkInterfaceCard natIfaceCard = NetworkInterfaceCard.builder() if(clone.getNetworkAdapter(i).getAttachmentType().equals(networkAttachmentType))
.addNetworkAdapter(natAdapter) slot = i;
.slot(1L) i++;
.build();
NetworkAdapter hostOnlyAdapter = NetworkAdapter.builder()
.networkAttachmentType(NetworkAttachmentType.HostOnly)
.build();
// create new hostOnly interface if needed, otherwise use the one already there with dhcp enabled ...
String hostOnlyIfName = getHostOnlyIfOrCreate();
NetworkInterfaceCard hostOnlyIfaceCard = NetworkInterfaceCard.builder().addNetworkAdapter(hostOnlyAdapter)
.addHostInterfaceName(hostOnlyIfName).slot(0L).build();
return createNetworkSpecForHostOnlyNATNICs(natIfaceCard, hostOnlyIfaceCard);
}
private NetworkSpec createNetworkSpecForHostOnlyNATNICs(NetworkInterfaceCard natIfaceCard,
NetworkInterfaceCard hostOnlyIfaceCard) {
return NetworkSpec.builder()
.addNIC(natIfaceCard)
.addNIC(hostOnlyIfaceCard)
.build();
}
private String getHostOnlyIfOrCreate() {
IHostNetworkInterface availableHostInterfaceIf = returnExistingHostNetworkInterfaceWithDHCPenabledOrNull(manager
.get().getVBox().getHost().getNetworkInterfaces());
if (availableHostInterfaceIf==null) {
final String hostOnlyIfName = createHostOnlyIf();
assignDHCPtoHostOnlyInterface(hostOnlyIfName);
return hostOnlyIfName;
} else {
return availableHostInterfaceIf.getName();
} }
checkState(slot!=-1);
return slot;
} }
private void assignDHCPtoHostOnlyInterface(final String hostOnlyIfName) {
List<IHostNetworkInterface> availableNetworkInterfaces = manager.get().getVBox().getHost()
.getNetworkInterfaces();
IHostNetworkInterface iHostNetworkInterfaceWithHostOnlyIfName = Iterables.getOnlyElement(Iterables.filter(availableNetworkInterfaces, new Predicate<IHostNetworkInterface>() {
@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";
NodeMetadata hostNodeMetadata = getHostNodeMetadata();
ExecResponse response = runScriptOnNodeFactory
.create(hostNodeMetadata,
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);
}
private String createHostOnlyIf() {
final String hostOnlyIfName;
NodeMetadata hostNodeMetadata = getHostNodeMetadata();
ExecResponse createHostOnlyResponse = runScriptOnNodeFactory
.create(hostNodeMetadata, Statements.exec("VBoxManage hostonlyif create"),
runAsRoot(false).wrapInInitScript(false)).init().call();
String output = createHostOnlyResponse.getOutput();
checkState(createHostOnlyResponse.getExitStatus()==0);
checkState(output.contains("'"), "cannot create hostonlyif");
hostOnlyIfName = output.substring(output.indexOf("'") + 1, output.lastIndexOf("'"));
return hostOnlyIfName;
}
private NodeMetadata getHostNodeMetadata() {
NodeMetadata hostNodeMetadata = NodeMetadataBuilder
.fromNodeMetadata(host.get())
.credentials(LoginCredentials.builder().user(username).password(password).build())
.publicAddresses(
ImmutableList.of(providerSupplier.get().getHost()))
.build();
return hostNodeMetadata;
}
private IHostNetworkInterface returnExistingHostNetworkInterfaceWithDHCPenabledOrNull(Iterable<IHostNetworkInterface> availableNetworkInterfaces) {
checkNotNull(availableNetworkInterfaces);
return Iterables.getFirst(filterAvailableNetworkInterfaceByHostOnlyAndDHCPenabled(availableNetworkInterfaces), null);
}
/**
* @param availableNetworkInterfaces
* @param hostOnlyIfIpAddress
* @return
*/
private Iterable<IHostNetworkInterface> filterAvailableNetworkInterfaceByHostOnlyAndDHCPenabled(Iterable<IHostNetworkInterface> availableNetworkInterfaces) {
Iterable<IHostNetworkInterface> filteredNetworkInterfaces = Iterables.filter(availableNetworkInterfaces, new Predicate<IHostNetworkInterface>() {
@Override
public boolean apply(IHostNetworkInterface iHostNetworkInterface) {
// this is an horrible workaround cause iHostNetworkInterface.getDhcpEnabled is working only for windows host
boolean match = false;
List<IDHCPServer> 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;
}
} }

View File

@ -19,13 +19,13 @@
package org.jclouds.virtualbox.functions; package org.jclouds.virtualbox.functions;
import static com.google.common.base.Predicates.in; import static com.google.common.base.Predicates.in;
import static com.google.common.base.Throwables.propagate;
import static com.google.common.collect.Iterables.any; import static com.google.common.collect.Iterables.any;
import static com.google.common.collect.Lists.partition; import static com.google.common.collect.Lists.partition;
import static org.jclouds.compute.reference.ComputeServiceConstants.COMPUTE_LOGGER; import static org.jclouds.compute.reference.ComputeServiceConstants.COMPUTE_LOGGER;
import static org.jclouds.virtualbox.settings.KeyboardScancodes.SPECIAL_KEYBOARD_BUTTON_MAP_LIST; import static org.jclouds.virtualbox.settings.KeyboardScancodes.SPECIAL_KEYBOARD_BUTTON_MAP_LIST;
import java.util.List; import java.util.List;
import java.util.concurrent.TimeUnit;
import javax.annotation.Resource; import javax.annotation.Resource;
import javax.inject.Named; import javax.inject.Named;
@ -34,6 +34,7 @@ import org.jclouds.logging.Logger;
import org.virtualbox_4_1.ISession; import org.virtualbox_4_1.ISession;
import com.google.common.base.Function; import com.google.common.base.Function;
import com.google.common.util.concurrent.Uninterruptibles;
class SendScancodes implements Function<ISession, Void> { class SendScancodes implements Function<ISession, Void> {
@ -56,9 +57,9 @@ class SendScancodes implements Function<ISession, Void> {
logger.debug("List of scancodes sent: ", maxOrLess); logger.debug("List of scancodes sent: ", maxOrLess);
assert (codesSent == maxOrLess.size()); assert (codesSent == maxOrLess.size());
if (any(maxOrLess, in(SPECIAL_KEYBOARD_BUTTON_MAP_LIST.values()))) { if (any(maxOrLess, in(SPECIAL_KEYBOARD_BUTTON_MAP_LIST.values()))) {
sleepOrPropagateInterrupt(300); Uninterruptibles.sleepUninterruptibly(300, TimeUnit.MILLISECONDS);
} else { } else {
sleepOrPropagateInterrupt(50); Uninterruptibles.sleepUninterruptibly(50, TimeUnit.MILLISECONDS);
} }
} }
return null; return null;
@ -68,12 +69,4 @@ class SendScancodes implements Function<ISession, Void> {
public String toString() { public String toString() {
return "sendScancodes(" + scancodes + ")"; return "sendScancodes(" + scancodes + ")";
} }
public void sleepOrPropagateInterrupt(long ms) {
try {
Thread.sleep(ms);
} catch (InterruptedException e) {
throw propagate(e);
}
}
} }

View File

@ -19,6 +19,8 @@
package org.jclouds.virtualbox.functions; package org.jclouds.virtualbox.functions;
import java.util.concurrent.TimeUnit;
import org.jclouds.logging.Logger; import org.jclouds.logging.Logger;
import org.virtualbox_4_1.IMachine; import org.virtualbox_4_1.IMachine;
import org.virtualbox_4_1.IProgress; import org.virtualbox_4_1.IProgress;
@ -30,6 +32,7 @@ import org.virtualbox_4_1.VirtualBoxManager;
import com.google.common.base.Function; import com.google.common.base.Function;
import com.google.common.base.Supplier; import com.google.common.base.Supplier;
import com.google.common.base.Throwables; import com.google.common.base.Throwables;
import com.google.common.util.concurrent.Uninterruptibles;
/** /**
* @author Andrea Turli * @author Andrea Turli
@ -93,7 +96,7 @@ public class TakeSnapshotIfNotAlreadyAttached implements Function<IMachine, ISna
snapshotName, snapshotDesc, machine.getName()); snapshotName, snapshotDesc, machine.getName());
throw Throwables.propagate(e); throw Throwables.propagate(e);
} }
Thread.sleep(1000L); Uninterruptibles.sleepUninterruptibly(1, TimeUnit.SECONDS);
continue; continue;
} }
logger.error(e, "Problem creating snapshot %s (description: %s) from machine %s", snapshotName, logger.error(e, "Problem creating snapshot %s (description: %s) from machine %s", snapshotName,

View File

@ -85,22 +85,8 @@ public class StartVBoxIfNotAlreadyRunning implements Supplier<VirtualBoxManager>
public synchronized void start() { public synchronized void start() {
URI provider = providerSupplier.get(); URI provider = providerSupplier.get();
NodeMetadata hostNodeMetadata = hardcodedHostToHostNodeMetadata.apply(host.get()); NodeMetadata hostNodeMetadata = hardcodedHostToHostNodeMetadata.apply(host.get());
// kill previously started vboxwebsrv (possibly dirty session) cleanUpHost(provider, hostNodeMetadata);
List<Statement> statements = Lists.newArrayList();
statements.add(Statements.findPid("vboxwebsrv"));
statements.add(Statements.kill());
StatementList statementList = new StatementList(statements);
if (socketTester.apply(HostAndPort.fromParts(provider.getHost(),
provider.getPort()))) {
logger.debug(String.format("shutting down previously started vboxwewbsrv at %s", provider));
ExecResponse execResponse = runScriptOnNodeFactory
.create(hostNodeMetadata, statementList, runAsRoot(false))
.init().call();
if(execResponse.getExitStatus()!=0)
throw new RuntimeException("Cannot execute jclouds");
}
logger.debug("disabling password access"); logger.debug("disabling password access");
runScriptOnNodeFactory runScriptOnNodeFactory
.create( .create(
@ -131,6 +117,24 @@ public class StartVBoxIfNotAlreadyRunning implements Supplier<VirtualBoxManager>
logger.warn("manager is not in unlocked state " logger.warn("manager is not in unlocked state "
+ manager.getSessionObject().getState()); + manager.getSessionObject().getState());
} }
private void cleanUpHost(URI provider, NodeMetadata hostNodeMetadata) {
// kill previously started vboxwebsrv (possibly dirty session)
List<Statement> statements = Lists.newArrayList();
statements.add(Statements.findPid("vboxwebsrv"));
statements.add(Statements.kill());
StatementList statementList = new StatementList(statements);
if (socketTester.apply(HostAndPort.fromParts(provider.getHost(),
provider.getPort()))) {
logger.debug(String.format("shutting down previously started vboxwewbsrv at %s", provider));
ExecResponse execResponse = runScriptOnNodeFactory
.create(hostNodeMetadata, statementList, runAsRoot(false))
.init().call();
if(execResponse.getExitStatus()!=0)
throw new RuntimeException("Cannot execute jclouds");
}
}
@Override @Override
public VirtualBoxManager get() { public VirtualBoxManager get() {

View File

@ -89,7 +89,7 @@ public class UnregisterMachineIfExistsAndForceDeleteItsMedia implements Function
if (!filteredMediaToBeDeleted.isEmpty()) { if (!filteredMediaToBeDeleted.isEmpty()) {
try { try {
IProgress deletion = machine.delete(filteredMediaToBeDeleted); IProgress deletion = machine.delete(filteredMediaToBeDeleted);
deletion.waitForCompletion(-1); deletion.waitForCompletion(100);
} catch (Exception e) { } catch (Exception e) {
logger.error(e, "Problem in deleting the media attached to %s", machine.getName()); logger.error(e, "Problem in deleting the media attached to %s", machine.getName());
Throwables.propagate(e); Throwables.propagate(e);

View File

@ -87,12 +87,7 @@ public class InstallGuestAdditions implements Statement {
statements.add(saveHttpResponseTo(download, "{tmp}{fs}", vboxGuestAdditionsIso));// statements.add(saveHttpResponseTo(download, "{tmp}{fs}", vboxGuestAdditionsIso));//
statements.add(exec(String.format("mount -o loop {tmp}{fs}%s %s", vboxGuestAdditionsIso, mountPoint))); 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(String.format("%s%s", mountPoint, "/VBoxLinuxAdditions.run --nox11"))); //
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; return statements;
} }

View File

@ -20,6 +20,9 @@ package org.jclouds.virtualbox.util;
import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkNotNull;
import java.util.List;
import java.util.concurrent.TimeUnit;
import javax.annotation.Resource; import javax.annotation.Resource;
import javax.inject.Named; import javax.inject.Named;
import javax.inject.Singleton; import javax.inject.Singleton;
@ -28,15 +31,25 @@ import org.jclouds.compute.reference.ComputeServiceConstants;
import org.jclouds.logging.Logger; import org.jclouds.logging.Logger;
import org.jclouds.virtualbox.domain.ExecutionType; import org.jclouds.virtualbox.domain.ExecutionType;
import org.jclouds.virtualbox.functions.LaunchMachineIfNotAlreadyRunning; import org.jclouds.virtualbox.functions.LaunchMachineIfNotAlreadyRunning;
import org.virtualbox_4_1.AdditionsFacilityStatus;
import org.virtualbox_4_1.AdditionsFacilityType;
import org.virtualbox_4_1.AdditionsRunLevelType;
import org.virtualbox_4_1.IAdditionsFacility;
import org.virtualbox_4_1.IMachine;
import org.virtualbox_4_1.IProgress; import org.virtualbox_4_1.IProgress;
import org.virtualbox_4_1.ISession; import org.virtualbox_4_1.ISession;
import org.virtualbox_4_1.LockType; import org.virtualbox_4_1.LockType;
import org.virtualbox_4_1.MachineState; import org.virtualbox_4_1.MachineState;
import org.virtualbox_4_1.SessionState;
import org.virtualbox_4_1.VirtualBoxManager; import org.virtualbox_4_1.VirtualBoxManager;
import com.google.common.base.Function; import com.google.common.base.Function;
import com.google.common.base.Optional;
import com.google.common.base.Predicate;
import com.google.common.base.Strings;
import com.google.common.base.Supplier; import com.google.common.base.Supplier;
import com.google.common.base.Throwables; import com.google.common.collect.Iterables;
import com.google.common.util.concurrent.Uninterruptibles;
import com.google.inject.Inject; import com.google.inject.Inject;
/** /**
@ -65,27 +78,57 @@ public class MachineController {
public ISession ensureMachineIsLaunched(String vmName) { public ISession ensureMachineIsLaunched(String vmName) {
ISession session = null; ISession session = null;
while (!manager.get().getVBox().findMachine(vmName).getState().equals(MachineState.Running)) { IMachine machine = manager.get().getVBox().findMachine(vmName);
while (!machine.getState().equals(MachineState.Running)) {
try { try {
session = machineUtils.applyForMachine(vmName, new LaunchMachineIfNotAlreadyRunning(manager.get(), session = machineUtils.applyForMachine(vmName,
executionType, "")); new LaunchMachineIfNotAlreadyRunning(manager.get(),
executionType, ""));
} catch (RuntimeException e) { } catch (RuntimeException e) {
if (e.getMessage().contains( if (e.getMessage()
"org.virtualbox_4_1.VBoxException: VirtualBox error: The given session is busy (0x80BB0007)")) { .contains(
"org.virtualbox_4_1.VBoxException: VirtualBox error: The given session is busy (0x80BB0007)")) {
throw e; throw e;
} else if (e.getMessage().contains("VirtualBox error: The object is not ready")) { } else if (e.getMessage().contains(
"VirtualBox error: The object is not ready")) {
continue; continue;
} else { } else {
throw e; throw e;
} }
} }
} }
// for scancode
Uninterruptibles.sleepUninterruptibly(5, TimeUnit.SECONDS);
String guestAdditionsInstalled = machineUtils.sharedLockMachineAndApplyToSession(vmName,
new Function<ISession, String>() {
@Override
public String apply(ISession session) {
int attempts = 0;
String guestAdditionsInstalled = null;
while (!!session.getConsole().getGuest()
.getAdditionsVersion().isEmpty() && attempts < 3) {
Uninterruptibles.sleepUninterruptibly(2, TimeUnit.SECONDS);
guestAdditionsInstalled = session.getConsole().getGuest()
.getAdditionsVersion();
attempts++;
}
return guestAdditionsInstalled;
}
});
if(!Strings.nullToEmpty(guestAdditionsInstalled).isEmpty()) {
waitVBoxServiceIsActive(vmName);
}
return checkNotNull(session, "session"); return checkNotNull(session, "session");
} }
public ISession ensureMachineHasPowerDown(String vmName) { public ISession ensureMachineHasPowerDown(String vmName) {
ISession session = manager.get().getSessionObject(); ISession session = manager.get().getSessionObject();
while (!manager.get().getVBox().findMachine(vmName).getState().equals(MachineState.PoweredOff)) { IMachine machine = manager.get().getVBox().findMachine(vmName);
while (!machine.getState().equals(MachineState.PoweredOff)) {
try { try {
session = machineUtils.lockSessionOnMachineAndApply(vmName, LockType.Shared, session = machineUtils.lockSessionOnMachineAndApply(vmName, LockType.Shared,
new Function<ISession, ISession>() { new Function<ISession, ISession>() {
@ -97,9 +140,6 @@ public class MachineController {
} }
}); });
} catch (RuntimeException e) { } 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")) { if (e.getMessage().contains("Invalid machine state: PoweredOff")) {
throw e; throw e;
} else if (e.getMessage().contains("VirtualBox error: The object is not ready")) { } else if (e.getMessage().contains("VirtualBox error: The object is not ready")) {
@ -109,6 +149,7 @@ public class MachineController {
} }
} }
} }
safeCheckMachineIsUnlocked(machine);
return checkNotNull(session, "session"); return checkNotNull(session, "session");
} }
@ -117,6 +158,7 @@ public class MachineController {
* http://askubuntu.com/questions/82015/shutting-down-ubuntu-server-running-in-headless-virtualbox * http://askubuntu.com/questions/82015/shutting-down-ubuntu-server-running-in-headless-virtualbox
*/ */
public ISession ensureMachineIsShutdown(String vmName) { public ISession ensureMachineIsShutdown(String vmName) {
IMachine machine = manager.get().getVBox().findMachine(vmName);
ISession session = machineUtils.lockSessionOnMachineAndApply(vmName, LockType.Shared, ISession session = machineUtils.lockSessionOnMachineAndApply(vmName, LockType.Shared,
new Function<ISession, ISession>() { new Function<ISession, ISession>() {
@Override @Override
@ -125,19 +167,12 @@ public class MachineController {
return session; return session;
} }
}); });
int count = 0; safeCheckMachineIsUnlocked(machine);
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"); return checkNotNull(session, "session");
} }
public void ensureMachineIsPaused(String vmName) { public void ensureMachineIsPaused(String vmName) {
IMachine machine = manager.get().getVBox().findMachine(vmName);
while (!manager.get().getVBox().findMachine(vmName).getState().equals(MachineState.Paused)) { while (!manager.get().getVBox().findMachine(vmName).getState().equals(MachineState.Paused)) {
try { try {
machineUtils.lockSessionOnMachineAndApply(vmName, LockType.Shared, new Function<ISession, Void>() { machineUtils.lockSessionOnMachineAndApply(vmName, LockType.Shared, new Function<ISession, Void>() {
@ -160,9 +195,11 @@ public class MachineController {
} }
} }
} }
safeCheckMachineIsUnlocked(machine);
} }
public void ensureMachineIsResumed(String vmName) { public void ensureMachineIsResumed(String vmName) {
IMachine machine = manager.get().getVBox().findMachine(vmName);
while (!manager.get().getVBox().findMachine(vmName).getState().equals(MachineState.Running)) { while (!manager.get().getVBox().findMachine(vmName).getState().equals(MachineState.Running)) {
try { try {
machineUtils.lockSessionOnMachineAndApply(vmName, LockType.Shared, new Function<ISession, Void>() { machineUtils.lockSessionOnMachineAndApply(vmName, LockType.Shared, new Function<ISession, Void>() {
@ -185,6 +222,58 @@ public class MachineController {
} }
} }
} }
safeCheckMachineIsUnlocked(machine);
}
private void safeCheckMachineIsUnlocked(IMachine machine) {
int guard = 0;
while (!machine.getSessionState().equals(SessionState.Unlocked)) {
if(guard >= 5) {
logger.warn("Machine session (%s) possibly still unlocked!!!", machine.getName());
break;
}
logger.debug("Machine session (%s) not unlocked - wait ...", machine.getName());
Uninterruptibles.sleepUninterruptibly(3, TimeUnit.SECONDS);
guard++;
}
logger.debug("Machine session (%s) is %s", machine.getName(), machine.getSessionState());
}
private void waitVBoxServiceIsActive(String vmName) {
machineUtils.sharedLockMachineAndApplyToSession(vmName, new Function<ISession, Void>() {
@Override
public Void apply(ISession session) {
session.getConsole().getGuest().setStatisticsUpdateInterval(1l);
while (!session.getConsole().getGuest().getAdditionsStatus(AdditionsRunLevelType.Userland)) {
Uninterruptibles.sleepUninterruptibly(200, TimeUnit.MILLISECONDS);
}
List<IAdditionsFacility> facilities = session.getConsole().getGuest().getFacilities();
while (facilities.size() != 4) {
Uninterruptibles.sleepUninterruptibly(200, TimeUnit.MILLISECONDS);
facilities = session.getConsole().getGuest().getFacilities();
}
facilities = session.getConsole().getGuest().getFacilities();
Optional<IAdditionsFacility> vboxServiceFacility = Optional.absent();
while (!vboxServiceFacility.isPresent()) {
vboxServiceFacility = Iterables.tryFind(session.getConsole().getGuest().getFacilities(),
new Predicate<IAdditionsFacility>() {
@Override
public boolean apply(IAdditionsFacility additionsFacility) {
return additionsFacility.getType().equals(AdditionsFacilityType.VBoxService);
};
});
}
while(!vboxServiceFacility.get().getStatus().equals(AdditionsFacilityStatus.Active)) {
Uninterruptibles.sleepUninterruptibly(1, TimeUnit.SECONDS);
}
Uninterruptibles.sleepUninterruptibly(3, TimeUnit.SECONDS);
return null;
}
});
} }
} }

View File

@ -0,0 +1,132 @@
package org.jclouds.virtualbox.util;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState;
import java.io.Serializable;
import com.google.common.base.Objects;
import com.google.common.base.Splitter;
import com.google.common.collect.Iterables;
/**
* An immutable representation of a MachineNameOrId and NIC port.
*
* <p>Example usage:
* <pre>
* MachineNameOrIdAndNicSlot mp = MachineNameOrIdAndNicSlot.fromString("myMachine:1");
* hp.getMachineNameOrId(); // returns "myMachine"
* hp.getSlot(); // returns 1
* hp.toString(); // returns "myMachine:1"
* </pre>
*
* @author Andrea Turli
*/
public final class MachineNameOrIdAndNicSlot implements Serializable {
private static final String SEPARATOR = ":";
/** IMachine name or id*/
private final String machineNameOrId;
/** Validated NIC slot number in the range [0..3] */
private final long slot;
private MachineNameOrIdAndNicSlot(String machineNameOrId, long slot) {
this.machineNameOrId = machineNameOrId;
this.slot = slot;
}
public String getMachineNameOrId() {
return machineNameOrId;
}
public boolean hasSlot() {
return slot >= 0;
}
public long getSlot() {
checkState(hasSlot());
return slot;
}
public String getSlotText() {
checkState(hasSlot());
return String.valueOf(slot);
}
public static MachineNameOrIdAndNicSlot fromParts(String machineNameOrId, long slot) {
checkArgument(isValidSlot(slot));
return new MachineNameOrIdAndNicSlot(checkNotNull(machineNameOrId, "machineNameOrId"), slot);
}
public static MachineNameOrIdAndNicSlot fromString(
String machineNameOrIdAndNicSlotString) {
checkNotNull(machineNameOrIdAndNicSlotString);
String machineNameOrId = null;
String nicSlotString = null;
Iterable<String> splittedString = Splitter.on(SEPARATOR).split(
machineNameOrIdAndNicSlotString);
checkState(Iterables.size(splittedString) == 2);
machineNameOrId = Iterables.get(splittedString, 0);
nicSlotString = Iterables.get(splittedString, 1);
long slot = -1;
if (nicSlotString != null) {
checkArgument(!nicSlotString.startsWith("+"),
"Unparseable slot number: %s", nicSlotString);
try {
slot = Long.parseLong(nicSlotString);
} catch (NumberFormatException e) {
throw new IllegalArgumentException("Unparseable slot number: "
+ nicSlotString);
}
checkArgument(isValidSlot(slot), "Slot number out of range: %s",
nicSlotString);
}
return new MachineNameOrIdAndNicSlot(machineNameOrId, slot);
}
public MachineNameOrIdAndNicSlot withDefaultSlot(int defaultSlot) {
checkArgument(isValidSlot(defaultSlot));
if (hasSlot() || slot == defaultSlot) {
return this;
}
return new MachineNameOrIdAndNicSlot(machineNameOrId, defaultSlot);
}
@Override
public boolean equals(Object other) {
if (this == other) {
return true;
}
if (other instanceof MachineNameOrIdAndNicSlot) {
MachineNameOrIdAndNicSlot that = (MachineNameOrIdAndNicSlot) other;
return Objects.equal(this.machineNameOrId, that.machineNameOrId)
&& this.slot == that.slot;
}
return false;
}
@Override
public int hashCode() {
return Objects.hashCode(machineNameOrId, slot);
}
@Override
public String toString() {
return Objects.toStringHelper(this)
.add("machineNameOrId", machineNameOrId)
.add("nicSlot", slot)
.toString();
}
private static boolean isValidSlot(long slot) {
return slot >= 0l && slot <= 3l;
}
private static final long serialVersionUID = 0;
}

View File

@ -21,9 +21,7 @@ package org.jclouds.virtualbox.util;
import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState; import static com.google.common.base.Preconditions.checkState;
import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.annotation.Resource; import javax.annotation.Resource;
import javax.inject.Named; import javax.inject.Named;
@ -48,8 +46,8 @@ import org.virtualbox_4_1.VirtualBoxManager;
import com.google.common.base.Function; import com.google.common.base.Function;
import com.google.common.base.Supplier; import com.google.common.base.Supplier;
import com.google.common.base.Throwables;
import com.google.common.util.concurrent.ListenableFuture; import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.Uninterruptibles;
import com.google.inject.Inject; import com.google.inject.Inject;
/** /**
@ -61,6 +59,8 @@ import com.google.inject.Inject;
@Singleton @Singleton
public class MachineUtils { public class MachineUtils {
public final String IP_V4_ADDRESS_PATTERN = "^([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\." 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])\\." + "([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])$";
@ -71,14 +71,13 @@ public class MachineUtils {
private final Supplier<VirtualBoxManager> manager; private final Supplier<VirtualBoxManager> manager;
private final Factory scriptRunner; private final Factory scriptRunner;
private final IpAddressesLoadingCache ipAddressesLoadingCache;
@Inject @Inject
public MachineUtils(Supplier<VirtualBoxManager> manager, RunScriptOnNode.Factory scriptRunner, public MachineUtils(Supplier<VirtualBoxManager> manager, RunScriptOnNode.Factory scriptRunner,
IpAddressesLoadingCache ipAddressesLoadingCache) { IpAddressesLoadingCache ipAddressesLoadingCache) {
this.manager = manager; this.manager = manager;
this.scriptRunner = scriptRunner; this.scriptRunner = scriptRunner;
this.ipAddressesLoadingCache = ipAddressesLoadingCache;
} }
public ListenableFuture<ExecResponse> runScriptOnNode(NodeMetadata metadata, Statement statement, public ListenableFuture<ExecResponse> runScriptOnNode(NodeMetadata metadata, Statement statement,
@ -183,7 +182,7 @@ public class MachineUtils {
* <p/> * <p/>
* Unlocks the machine before returning. * Unlocks the machine before returning.
* *
* Tries to obtain a lock 5 times before giving up waiting 1 sec between tries. When no machine * Tries to obtain a lock 15 times before giving up waiting 1 sec between tries. When no machine
* is found null is returned. * is found null is returned.
* *
* @param type * @param type
@ -196,30 +195,27 @@ public class MachineUtils {
*/ */
protected <T> T lockSessionOnMachineAndApply(String machineId, LockType type, Function<ISession, T> function) { protected <T> T lockSessionOnMachineAndApply(String machineId, LockType type, Function<ISession, T> function) {
int retries = 15; int retries = 15;
ISession session = lockSession(machineId, type, retries); ISession session = checkNotNull(lockSession(machineId, type, retries), "session");
try { try {
return function.apply(session); return function.apply(session);
} catch (VBoxException e) { } catch (VBoxException e) {
throw new RuntimeException(String.format("error applying %s to %s with %s lock: %s", function, machineId, throw new RuntimeException(String.format("error applying %s to %s with %s lock: %s", function, machineId,
type, e.getMessage()), e); type, e.getMessage()), e);
} finally { } finally {
if (session != null && session.getState().equals(SessionState.Locked)) if (session.getState().equals(SessionState.Locked)) {
session.unlockMachine(); session.unlockMachine();
while (!session.getState().equals(SessionState.Unlocked)) {
logger.debug("Session not unlocked - wait ...");
Uninterruptibles.sleepUninterruptibly(1, TimeUnit.SECONDS);
}
}
} }
} }
private ISession lockSession(String machineId, LockType type, int retries) { private ISession lockSession(String machineId, LockType type, int retries) {
int count = 0; int count = 0;
ISession session;
IMachine immutableMachine = manager.get().getVBox().findMachine(machineId); IMachine immutableMachine = manager.get().getVBox().findMachine(machineId);
ISession session = null;
try {
session = manager.get().openMachineSession(immutableMachine);
if (session.getState().equals(SessionState.Locked))
return checkNotNull(session, "session");
} catch (Exception e) {
logger.debug("machine %s is not locked). Error: %s", immutableMachine.getName(), e.getMessage());
}
while (true) { while (true) {
try { try {
@ -237,10 +233,7 @@ public class MachineUtils {
throw new RuntimeException(String.format("error locking %s with %s lock: %s", machineId, type, throw new RuntimeException(String.format("error locking %s with %s lock: %s", machineId, type,
e.getMessage()), e); e.getMessage()), e);
} }
try { Uninterruptibles.sleepUninterruptibly(1, TimeUnit.SECONDS);
Thread.sleep(count * 1000L);
} catch (InterruptedException e1) {
}
} }
} }
checkState(session.getState().equals(SessionState.Locked)); checkState(session.getState().equals(SessionState.Locked));
@ -278,24 +271,4 @@ public class MachineUtils {
|| e.getMessage().contains("Could not find a registered machine with UUID {"); || e.getMessage().contains("Could not find a registered machine with UUID {");
} }
public String getIpAddressFromFirstNIC(String machineName) {
try {
return ipAddressesLoadingCache.get(machineName);
} catch (ExecutionException e) {
logger.error("Problem in using the ipAddressCache", e.getCause());
throw Throwables.propagate(e);
}
}
public static boolean isIpv4(String s) {
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])$";
Pattern pattern = Pattern.compile(IP_V4_ADDRESS_PATTERN);
Matcher matcher = pattern.matcher(s);
return matcher.matches();
}
} }

View File

@ -0,0 +1,339 @@
/**
* 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.checkNotNull;
import static com.google.common.base.Preconditions.checkState;
import static org.jclouds.compute.options.RunScriptOptions.Builder.runAsRoot;
import java.net.URI;
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.annotation.Resource;
import javax.inject.Named;
import javax.inject.Singleton;
import org.jclouds.compute.callables.RunScriptOnNode;
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.compute.reference.ComputeServiceConstants;
import org.jclouds.location.Provider;
import org.jclouds.logging.Logger;
import org.jclouds.scriptbuilder.domain.Statements;
import org.jclouds.virtualbox.domain.BridgedIf;
import org.jclouds.virtualbox.domain.NetworkAdapter;
import org.jclouds.virtualbox.domain.NetworkInterfaceCard;
import org.jclouds.virtualbox.domain.NetworkSpec;
import org.jclouds.virtualbox.functions.IpAddressesLoadingCache;
import org.jclouds.virtualbox.functions.RetrieveActiveBridgedInterfaces;
import org.jclouds.virtualbox.statements.EnableNetworkInterface;
import org.jclouds.virtualbox.statements.GetIPAddressFromMAC;
import org.jclouds.virtualbox.statements.ScanNetworkWithPing;
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.ISession;
import org.virtualbox_4_1.LockType;
import org.virtualbox_4_1.NetworkAttachmentType;
import org.virtualbox_4_1.VirtualBoxManager;
import com.google.common.base.Function;
import com.google.common.base.Predicate;
import com.google.common.base.Supplier;
import com.google.common.base.Throwables;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterables;
import com.google.common.util.concurrent.Uninterruptibles;
import com.google.inject.Inject;
/**
* Utilities to manage VirtualBox networks on guests
*
* @author Andrea Turli
*/
@Singleton
public class NetworkUtils {
// TODO parameterize
public static final int MASTER_PORT = 2222;
private static final String VIRTUALBOX_HOST_GATEWAY = "10.0.2.15";
@Resource
@Named(ComputeServiceConstants.COMPUTE_LOGGER)
protected Logger logger = Logger.NULL;
private final Supplier<VirtualBoxManager> manager;
private final MachineUtils machineUtils;
private final Supplier<NodeMetadata> host;
private final Supplier<URI> providerSupplier;
private final IpAddressesLoadingCache ipAddressesLoadingCache;
private final RunScriptOnNode.Factory scriptRunnerFactory;
private final Supplier<NodeMetadata> hostSupplier;
@Inject
public NetworkUtils(Supplier<VirtualBoxManager> manager, MachineUtils machineUtils,
MachineController machineController,
Supplier<NodeMetadata> host,
@Provider Supplier<URI> providerSupplier,
IpAddressesLoadingCache ipAddressesLoadingCache,
Supplier<NodeMetadata> hostSupplier,
RunScriptOnNode.Factory scriptRunnerFactory) {
this.manager = manager;
this.machineUtils = machineUtils;
this.host = checkNotNull(host, "host");
this.providerSupplier = checkNotNull(providerSupplier,
"endpoint to virtualbox websrvd is needed");
this.ipAddressesLoadingCache = ipAddressesLoadingCache;
this.scriptRunnerFactory = scriptRunnerFactory;
this.hostSupplier = hostSupplier;
}
public NetworkSpec createNetworkSpecWhenVboxIsLocalhost() {
NetworkAdapter natAdapter = NetworkAdapter.builder()
.networkAttachmentType(NetworkAttachmentType.NAT)
.build();
NetworkInterfaceCard natIfaceCard = NetworkInterfaceCard.builder()
.addNetworkAdapter(natAdapter)
.slot(1L)
.build();
NetworkAdapter hostOnlyAdapter = NetworkAdapter.builder()
.networkAttachmentType(NetworkAttachmentType.HostOnly)
.build();
// create new hostOnly interface if needed, otherwise use the one already there with dhcp enabled ...
String hostOnlyIfName = getHostOnlyIfOrCreate();
NetworkInterfaceCard hostOnlyIfaceCard = NetworkInterfaceCard.builder().addNetworkAdapter(hostOnlyAdapter)
.addHostInterfaceName(hostOnlyIfName).slot(0L).build();
return createNetworkSpecForHostOnlyNATNICs(natIfaceCard, hostOnlyIfaceCard);
}
public boolean enableNetworkInterface(NodeMetadata nodeMetadata, NetworkInterfaceCard networkInterfaceCard) {
ExecResponse execResponse = null;
try {
execResponse = machineUtils.runScriptOnNode(nodeMetadata,
new EnableNetworkInterface(networkInterfaceCard), RunScriptOptions.NONE).get();
} catch (InterruptedException e) {
logger.error(e.getMessage());
} catch (ExecutionException e) {
logger.error(e.getMessage());
}
if(execResponse == null)
return false;
return execResponse.getExitStatus() == 0;
}
private NetworkSpec createNetworkSpecForHostOnlyNATNICs(NetworkInterfaceCard natIfaceCard,
NetworkInterfaceCard hostOnlyIfaceCard) {
return NetworkSpec.builder()
.addNIC(hostOnlyIfaceCard)
.addNIC(natIfaceCard)
.build();
}
public String getHostOnlyIfOrCreate() {
IHostNetworkInterface availableHostInterfaceIf = returnExistingHostNetworkInterfaceWithDHCPenabledOrNull(manager
.get().getVBox().getHost().getNetworkInterfaces());
if (availableHostInterfaceIf==null) {
final String hostOnlyIfName = createHostOnlyIf();
assignDHCPtoHostOnlyInterface(hostOnlyIfName);
return hostOnlyIfName;
} else {
return availableHostInterfaceIf.getName();
}
}
private void assignDHCPtoHostOnlyInterface(final String hostOnlyIfName) {
List<IHostNetworkInterface> availableNetworkInterfaces = manager.get().getVBox().getHost()
.getNetworkInterfaces();
IHostNetworkInterface iHostNetworkInterfaceWithHostOnlyIfName = Iterables.getOnlyElement(Iterables.filter(availableNetworkInterfaces, new Predicate<IHostNetworkInterface>() {
@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";
NodeMetadata hostNodeMetadata = getHostNodeMetadata();
ExecResponse response = scriptRunnerFactory
.create(hostNodeMetadata,
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);
}
private String createHostOnlyIf() {
final String hostOnlyIfName;
NodeMetadata hostNodeMetadata = getHostNodeMetadata();
ExecResponse createHostOnlyResponse = scriptRunnerFactory
.create(hostNodeMetadata, Statements.exec("VBoxManage hostonlyif create"),
runAsRoot(false).wrapInInitScript(false)).init().call();
String output = createHostOnlyResponse.getOutput();
checkState(createHostOnlyResponse.getExitStatus()==0);
checkState(output.contains("'"), "cannot create hostonlyif");
hostOnlyIfName = output.substring(output.indexOf("'") + 1, output.lastIndexOf("'"));
return hostOnlyIfName;
}
private NodeMetadata getHostNodeMetadata() {
NodeMetadata hostNodeMetadata = NodeMetadataBuilder
.fromNodeMetadata(host.get())
.publicAddresses(
ImmutableList.of(providerSupplier.get().getHost()))
.build();
return hostNodeMetadata;
}
private IHostNetworkInterface returnExistingHostNetworkInterfaceWithDHCPenabledOrNull(Iterable<IHostNetworkInterface> availableNetworkInterfaces) {
checkNotNull(availableNetworkInterfaces);
return Iterables.getFirst(filterAvailableNetworkInterfaceByHostOnlyAndDHCPenabled(availableNetworkInterfaces), null);
}
/**
* @param availableNetworkInterfaces
* @param hostOnlyIfIpAddress
* @return
*/
private Iterable<IHostNetworkInterface> filterAvailableNetworkInterfaceByHostOnlyAndDHCPenabled(Iterable<IHostNetworkInterface> availableNetworkInterfaces) {
Iterable<IHostNetworkInterface> filteredNetworkInterfaces = Iterables.filter(availableNetworkInterfaces, new Predicate<IHostNetworkInterface>() {
@Override
public boolean apply(IHostNetworkInterface iHostNetworkInterface) {
// this is an horrible workaround cause iHostNetworkInterface.getDhcpEnabled is working only for windows host
boolean match = false;
List<IDHCPServer> 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;
}
public String getIpAddressFromNicSlot(String machineNameOrId, long nicSlot) {
MachineNameOrIdAndNicSlot machineNameOrIdAndNicSlot =
MachineNameOrIdAndNicSlot.fromParts(machineNameOrId, nicSlot);
logger.debug("Looking for an available IP address for %s at slot %s ...",
machineNameOrIdAndNicSlot.getMachineNameOrId(),
machineNameOrIdAndNicSlot.getSlotText());
try {
String ipAddress = ipAddressesLoadingCache.get(machineNameOrIdAndNicSlot);
while(!isValidIpForHostOnly(machineNameOrIdAndNicSlot, ipAddress)) {
ipAddressesLoadingCache.invalidate(machineNameOrIdAndNicSlot);
ipAddress = ipAddressesLoadingCache.get(machineNameOrIdAndNicSlot);
}
logger.debug("Found an available IP address %s for guest: %s at slot: %s",
ipAddress,
machineNameOrIdAndNicSlot.getMachineNameOrId(),
machineNameOrIdAndNicSlot.getSlotText());
return ipAddress;
} catch (ExecutionException e) {
logger.error("Problem in using the ipAddressCache", e.getCause());
throw Throwables.propagate(e);
}
}
public static boolean isIpv4(String s) {
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])$";
Pattern pattern = Pattern.compile(IP_V4_ADDRESS_PATTERN);
Matcher matcher = pattern.matcher(s);
return matcher.matches();
}
public boolean isValidIpForHostOnly(MachineNameOrIdAndNicSlot machineNameOrIdAndNicSlot, String ip) {
final String vmNameOrId = machineNameOrIdAndNicSlot.getMachineNameOrId();
IMachine machine = manager.get().getVBox().findMachine(vmNameOrId);
long slot = machineNameOrIdAndNicSlot.getSlot();
if(ip.equals(VIRTUALBOX_HOST_GATEWAY) || !isValidHostOnlyIpAddress(ip, slot, machine)) {
// restart vm
logger.debug("reset node (%s) to refresh guest properties.", vmNameOrId);
machineUtils.lockSessionOnMachineAndApply(vmNameOrId, LockType.Shared,
new Function<ISession, Void>() {
@Override
public Void apply(ISession session) {
session.getConsole().reset();
long time = 15;
logger.debug("Waiting %s secs for the reset of (%s) ...", time, vmNameOrId);
Uninterruptibles.sleepUninterruptibly(time, TimeUnit.SECONDS);
return null;
}
});
return false;
}
return true;
}
public static boolean isValidHostOnlyIpAddress(String ip, long slot,
IMachine machine) {
boolean result = isIpv4(ip) && machine.getNetworkAdapter(slot).getAttachmentType().equals(NetworkAttachmentType.HostOnly)
&& !ipBelongsToNatRange(ip);
return result;
}
private static boolean ipBelongsToNatRange(String ip) {
return ip.startsWith("10.0.3");
}
protected String getIpAddressFromBridgedNIC(INetworkAdapter networkAdapter,
String network) {
// RetrieveActiveBridgedInterfaces
List<BridgedIf> activeBridgedInterfaces = new RetrieveActiveBridgedInterfaces(scriptRunnerFactory).apply(hostSupplier.get());
BridgedIf activeBridgedIf = checkNotNull(Iterables.get(activeBridgedInterfaces, 0), "activeBridgedInterfaces");
network = activeBridgedIf.getIpAddress();
// scan ip
RunScriptOnNode ipScanRunScript = scriptRunnerFactory.create(
hostSupplier.get(), new ScanNetworkWithPing(network),
RunScriptOptions.NONE);
ExecResponse execResponse = ipScanRunScript.init().call();
checkState(execResponse.getExitStatus() == 0);
// retrieve ip from mac
RunScriptOnNode getIpFromMACAddressRunScript = scriptRunnerFactory
.create(hostSupplier.get(), new GetIPAddressFromMAC(
networkAdapter.getMACAddress()),
RunScriptOptions.NONE);
ExecResponse ipExecResponse = getIpFromMACAddressRunScript.init()
.call();
checkState(ipExecResponse.getExitStatus() == 0);
return checkNotNull(ipExecResponse.getOutput(), "ipAddress");
}
}

View File

@ -1,4 +1,139 @@
images: images:
- id: ubuntu-10.04.4-server-i386
name: ubuntu-10.04-server-i386
description: ubuntu 10.04.4 server (i386)
os_arch: x86
os_family: ubuntu
os_description: ubuntu
os_version: 10.04.4
iso: http://releases.ubuntu.com/10.04.4/ubuntu-10.04.4-server-i386.iso
iso_md5: fc08a01e78348e3918180ea91a6883bb
username: toor
credential: password
keystroke_sequence: |
<Esc><Esc><Enter>
/install/vmlinuz noapic preseed/url=http://10.0.2.2:8080/src/test/resources/preseed.cfg
debian-installer=en_US auto locale=en_US kbd-chooser/method=us
hostname=vmName
fb=false debconf/frontend=noninteractive
console-setup/ask_detect=false console-setup/modelcode=pc105 console-setup/layoutcode=us
initrd=/install/initrd.gz -- <Enter>
preseed_cfg: |
## Options to set on the command line
d-i debian-installer/locale string en_US
d-i console-setup/ask_detect boolean false
d-i console-setup/layoutcode string us
d-i netcfg/get_hostname string unassigned-hostname
d-i netcfg/get_domain string unassigned-domain
d-i time/zone string UTC
d-i clock-setup/utc-auto boolean true
d-i clock-setup/utc boolean true
d-i kbd-chooser/method select American English
d-i netcfg/wireless_wep string
d-i base-installer/kernel/override-image string linux-server
d-i debconf debconf/frontend select Noninteractive
d-i pkgsel/install-language-support boolean false
tasksel tasksel/first multiselect standard, ubuntu-server
d-i partman-auto/method string lvm
#d-i partman-auto/purge_lvm_from_device boolean true
d-i partman-lvm/confirm boolean true
d-i partman-lvm/device_remove_lvm boolean true
d-i partman-auto/choose_recipe select atomic
d-i partman/confirm_write_new_label boolean true
d-i partman/confirm_nooverwrite boolean true
d-i partman/choose_partition select finish
d-i partman/confirm boolean true
# Write the changes to disks and configure LVM?
d-i partman-lvm/confirm boolean true
d-i partman-lvm/confirm_nooverwrite boolean true
d-i partman-auto-lvm/guided_size string max
## Default user, we can get away with a recipe to change this
d-i passwd/user-fullname string toor
d-i passwd/username string toor
d-i passwd/user-password password password
d-i passwd/user-password-again password password
d-i user-setup/encrypt-home boolean false
d-i user-setup/allow-password-weak boolean true
d-i pkgsel/include string openssh-server ntp
# Whether to upgrade packages after debootstrap.
# Allowed values: none, safe-upgrade, full-upgrade
d-i pkgsel/upgrade select full-upgrade
d-i grub-installer/only_debian boolean true
d-i grub-installer/with_other_os boolean true
d-i finish-install/reboot_in_progress note
#For the update
d-i pkgsel/update-policy select none
# debconf-get-selections --install
#Use mirror
choose-mirror-bin mirror/http/proxy string
- id: ubuntu-10.04.4-server-amd64
name: ubuntu-10.04-server-amd64
description: ubuntu 10.04.4 server (amd64)
os_arch: amd64
os_family: ubuntu
os_description: ubuntu
os_version: 10.04.4
os_64bit: true
iso: http://releases.ubuntu.com/10.04.4/ubuntu-10.04.4-server-amd64.iso
iso_md5: 9b218654cdcdf9722171648c52f8a088
username: toor
credential: password
keystroke_sequence: |
<Esc><Esc><Enter>
/install/vmlinuz noapic preseed/url=http://10.0.2.2:8080/src/test/resources/preseed.cfg
debian-installer=en_US auto locale=en_US kbd-chooser/method=us
hostname=vmName
fb=false debconf/frontend=noninteractive
console-setup/ask_detect=false console-setup/modelcode=pc105 console-setup/layoutcode=us
initrd=/install/initrd.gz -- <Enter>
preseed_cfg: |
## Options to set on the command line
d-i debian-installer/locale string en_US
d-i console-setup/ask_detect boolean false
d-i console-setup/layoutcode string us
d-i netcfg/get_hostname string unassigned-hostname
d-i netcfg/get_domain string unassigned-domain
d-i time/zone string UTC
d-i clock-setup/utc-auto boolean true
d-i clock-setup/utc boolean true
d-i kbd-chooser/method select American English
d-i netcfg/wireless_wep string
d-i base-installer/kernel/override-image string linux-server
d-i debconf debconf/frontend select Noninteractive
d-i pkgsel/install-language-support boolean false
tasksel tasksel/first multiselect standard, ubuntu-server
d-i partman-auto/method string lvm
#d-i partman-auto/purge_lvm_from_device boolean true
d-i partman-lvm/confirm boolean true
d-i partman-lvm/device_remove_lvm boolean true
d-i partman-auto/choose_recipe select atomic
d-i partman/confirm_write_new_label boolean true
d-i partman/confirm_nooverwrite boolean true
d-i partman/choose_partition select finish
d-i partman/confirm boolean true
# Write the changes to disks and configure LVM?
d-i partman-lvm/confirm boolean true
d-i partman-lvm/confirm_nooverwrite boolean true
d-i partman-auto-lvm/guided_size string max
## Default user, we can get away with a recipe to change this
d-i passwd/user-fullname string toor
d-i passwd/username string toor
d-i passwd/user-password password password
d-i passwd/user-password-again password password
d-i user-setup/encrypt-home boolean false
d-i user-setup/allow-password-weak boolean true
d-i pkgsel/include string openssh-server ntp
# Whether to upgrade packages after debootstrap.
# Allowed values: none, safe-upgrade, full-upgrade
d-i pkgsel/upgrade select full-upgrade
d-i grub-installer/only_debian boolean true
d-i grub-installer/with_other_os boolean true
d-i finish-install/reboot_in_progress note
#For the update
d-i pkgsel/update-policy select none
# debconf-get-selections --install
#Use mirror
choose-mirror-bin mirror/http/proxy string
- id: ubuntu-11.04-i386 - id: ubuntu-11.04-i386
name: ubuntu-11.04-server-i386 name: ubuntu-11.04-server-i386
description: ubuntu 11.04 server (i386) description: ubuntu 11.04 server (i386)
@ -27,7 +162,7 @@ images:
d-i time/zone string UTC d-i time/zone string UTC
d-i clock-setup/utc-auto boolean true d-i clock-setup/utc-auto boolean true
d-i clock-setup/utc boolean true d-i clock-setup/utc boolean true
d-i kbd-chooser/method select American English d-i kbd-chooser/method select American English
d-i netcfg/wireless_wep string d-i netcfg/wireless_wep string
d-i base-installer/kernel/override-image string linux-server d-i base-installer/kernel/override-image string linux-server
# Choices: Dialog, Readline, Gnome, Kde, Editor, Noninteractive # Choices: Dialog, Readline, Gnome, Kde, Editor, Noninteractive
@ -142,8 +277,9 @@ images:
os_version: 12.04.1 os_version: 12.04.1
os_64bit: true os_64bit: true
iso: http://releases.ubuntu.com/12.04/ubuntu-12.04.1-server-amd64.iso iso: http://releases.ubuntu.com/12.04/ubuntu-12.04.1-server-amd64.iso
iso_md5: a8c667e871f48f3a662f3fbf1c3ddb17
username: toor username: toor
credential: $user credential: password
keystroke_sequence: | keystroke_sequence: |
<Esc><Esc><Enter> <Esc><Esc><Enter>
/install/vmlinuz noapic preseed/url=http://10.0.2.2:8080/src/test/resources/preseed.cfg /install/vmlinuz noapic preseed/url=http://10.0.2.2:8080/src/test/resources/preseed.cfg

View File

@ -25,6 +25,7 @@ import static org.jclouds.virtualbox.config.VirtualBoxConstants.VIRTUALBOX_INSTA
import java.io.File; import java.io.File;
import java.util.concurrent.ExecutorService; import java.util.concurrent.ExecutorService;
import java.util.concurrent.TimeUnit;
import javax.inject.Inject; import javax.inject.Inject;
import javax.inject.Named; import javax.inject.Named;
@ -53,6 +54,7 @@ import org.jclouds.virtualbox.functions.IMachineToVmSpec;
import org.jclouds.virtualbox.functions.admin.UnregisterMachineIfExistsAndDeleteItsMedia; import org.jclouds.virtualbox.functions.admin.UnregisterMachineIfExistsAndDeleteItsMedia;
import org.jclouds.virtualbox.util.MachineController; import org.jclouds.virtualbox.util.MachineController;
import org.jclouds.virtualbox.util.MachineUtils; import org.jclouds.virtualbox.util.MachineUtils;
import org.jclouds.virtualbox.util.NetworkUtils;
import org.testng.annotations.AfterClass; import org.testng.annotations.AfterClass;
import org.testng.annotations.AfterSuite; import org.testng.annotations.AfterSuite;
import org.testng.annotations.BeforeClass; import org.testng.annotations.BeforeClass;
@ -71,6 +73,7 @@ import com.google.common.base.Supplier;
import com.google.common.cache.LoadingCache; import com.google.common.cache.LoadingCache;
import com.google.common.collect.ImmutableSet; import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables; import com.google.common.collect.Iterables;
import com.google.common.util.concurrent.Uninterruptibles;
import com.google.inject.Injector; import com.google.inject.Injector;
import com.google.inject.Key; import com.google.inject.Key;
import com.google.inject.Module; import com.google.inject.Module;
@ -103,6 +106,9 @@ public class BaseVirtualBoxClientLiveTest extends BaseComputeServiceContextLiveT
@Inject @Inject
protected MachineUtils machineUtils; protected MachineUtils machineUtils;
@Inject
protected NetworkUtils networkUtils;
protected String hostVersion; protected String hostVersion;
protected String operatingSystemIso; protected String operatingSystemIso;
@ -155,10 +161,7 @@ public class BaseVirtualBoxClientLiveTest extends BaseComputeServiceContextLiveT
int attempts = 0; int attempts = 0;
while (attempts < 10 && !vm.getSessionState().equals(SessionState.Unlocked)) { while (attempts < 10 && !vm.getSessionState().equals(SessionState.Unlocked)) {
attempts++; attempts++;
try { Uninterruptibles.sleepUninterruptibly(200, TimeUnit.MILLISECONDS);
Thread.sleep(200l);
} catch (InterruptedException e) {
}
} }
machineUtils.applyForMachine(vmNameOrId, new UnregisterMachineIfExistsAndDeleteItsMedia(vmSpec)); machineUtils.applyForMachine(vmNameOrId, new UnregisterMachineIfExistsAndDeleteItsMedia(vmSpec));

View File

@ -36,6 +36,7 @@ import org.jclouds.compute.options.TemplateOptions;
import org.jclouds.compute.reference.ComputeServiceConstants; import org.jclouds.compute.reference.ComputeServiceConstants;
import org.jclouds.logging.Logger; import org.jclouds.logging.Logger;
import org.jclouds.logging.slf4j.config.SLF4JLoggingModule; import org.jclouds.logging.slf4j.config.SLF4JLoggingModule;
import org.jclouds.scriptbuilder.statements.login.AdminAccess;
import org.jclouds.ssh.SshClient; import org.jclouds.ssh.SshClient;
import org.jclouds.sshj.config.SshjSshClientModule; import org.jclouds.sshj.config.SshjSshClientModule;
import org.jclouds.virtualbox.BaseVirtualBoxClientLiveTest; import org.jclouds.virtualbox.BaseVirtualBoxClientLiveTest;
@ -50,7 +51,7 @@ import com.google.inject.Module;
* *
* @author Adrian Cole * @author Adrian Cole
*/ */
@Test(groups = "live", singleThreaded = true, testName = "VirtualBoxExperimentLiveTest") @Test(groups = "live", testName = "VirtualBoxExperimentLiveTest")
public class VirtualBoxExperimentLiveTest extends BaseVirtualBoxClientLiveTest { public class VirtualBoxExperimentLiveTest extends BaseVirtualBoxClientLiveTest {
@Resource @Resource
@ -71,7 +72,7 @@ public class VirtualBoxExperimentLiveTest extends BaseVirtualBoxClientLiveTest {
int numNodes = 3; int numNodes = 3;
final String clusterName = "test-launch-cluster"; final String clusterName = "test-launch-cluster";
Set<? extends NodeMetadata> nodes = context.getComputeService().createNodesInGroup(clusterName, numNodes, Set<? extends NodeMetadata> nodes = context.getComputeService().createNodesInGroup(clusterName, numNodes,
TemplateOptions.Builder.overrideLoginUser("toor")); //TODO runScript(AdminAccess.standard())); TemplateOptions.Builder.overrideLoginUser("toor").runScript(AdminAccess.standard()));
assertEquals(numNodes, nodes.size(), "wrong number of nodes"); assertEquals(numNodes, nodes.size(), "wrong number of nodes");
for (NodeMetadata node : nodes) { for (NodeMetadata node : nodes) {
assertTrue(node.getGroup().equals("test-launch-cluster")); assertTrue(node.getGroup().equals("test-launch-cluster"));

View File

@ -30,7 +30,7 @@ import static org.testng.Assert.assertEquals;
import org.jclouds.compute.domain.NodeMetadata; import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.virtualbox.config.VirtualBoxComputeServiceContextModule; import org.jclouds.virtualbox.config.VirtualBoxComputeServiceContextModule;
import org.jclouds.virtualbox.util.MachineUtils; import org.jclouds.virtualbox.util.NetworkUtils;
import org.testng.annotations.Test; import org.testng.annotations.Test;
import org.virtualbox_4_1.IMachine; import org.virtualbox_4_1.IMachine;
import org.virtualbox_4_1.INATEngine; import org.virtualbox_4_1.INATEngine;
@ -64,18 +64,18 @@ public class IMachineToNodeMetadataTest {
expect(natEng.getRedirects()).andReturn(ImmutableList.of("0,1,127.0.0.1,2222,,22")); expect(natEng.getRedirects()).andReturn(ImmutableList.of("0,1,127.0.0.1,2222,,22"));
INetworkAdapter hostOnly = createNiceMock(INetworkAdapter.class); INetworkAdapter hostOnly = createNiceMock(INetworkAdapter.class);
MachineUtils machineUtils = createNiceMock(MachineUtils.class); NetworkUtils networkUtils = createNiceMock(NetworkUtils.class);
replay(vm, nat, natEng, hostOnly, machineUtils); replay(vm, nat, natEng, hostOnly, networkUtils);
NodeMetadata node = new IMachineToNodeMetadata(VirtualBoxComputeServiceContextModule.toPortableNodeStatus, NodeMetadata node = new IMachineToNodeMetadata(VirtualBoxComputeServiceContextModule.toPortableNodeStatus,
machineUtils).apply(vm); networkUtils).apply(vm);
assertEquals(MASTER_NAME, node.getName()); assertEquals(MASTER_NAME, node.getName());
assertEquals(1, node.getPrivateAddresses().size()); assertEquals(1, node.getPrivateAddresses().size());
assertEquals(1, node.getPublicAddresses().size()); assertEquals(1, node.getPublicAddresses().size());
assertEquals("127.0.0.1", Iterables.get(node.getPublicAddresses(), 0)); assertEquals("127.0.0.1", Iterables.get(node.getPublicAddresses(), 0));
assertEquals(MastersLoadingCache.MASTER_PORT, node.getLoginPort()); assertEquals(NetworkUtils.MASTER_PORT, node.getLoginPort());
assertEquals("", node.getGroup()); assertEquals("", node.getGroup());
} }
@ -103,12 +103,12 @@ public class IMachineToNodeMetadataTest {
expect(nat.getNatDriver()).andReturn(natEng).anyTimes(); expect(nat.getNatDriver()).andReturn(natEng).anyTimes();
expect(natEng.getHostIP()).andReturn("127.0.0.1").once(); expect(natEng.getHostIP()).andReturn("127.0.0.1").once();
expect(natEng.getRedirects()).andReturn(ImmutableList.of("0,1,127.0.0.1,3000,,22")); expect(natEng.getRedirects()).andReturn(ImmutableList.of("0,1,127.0.0.1,3000,,22"));
MachineUtils machineUtils = createNiceMock(MachineUtils.class); NetworkUtils networkUtils = createNiceMock(NetworkUtils.class);
replay(vm, nat, natEng, hostOnly, machineUtils); replay(vm, nat, natEng, hostOnly, networkUtils);
NodeMetadata node = new IMachineToNodeMetadata(VirtualBoxComputeServiceContextModule.toPortableNodeStatus, NodeMetadata node = new IMachineToNodeMetadata(VirtualBoxComputeServiceContextModule.toPortableNodeStatus,
machineUtils).apply(vm); networkUtils).apply(vm);
assertEquals(name, node.getName()); assertEquals(name, node.getName());
assertEquals(group, node.getGroup()); assertEquals(group, node.getGroup());

View File

@ -41,11 +41,11 @@ import com.google.common.collect.Iterables;
public class ImageFromYamlStringTest { public class ImageFromYamlStringTest {
public static final Image TEST1 = new ImageBuilder() public static final Image TEST1 = new ImageBuilder()
.id("ubuntu-11.04-i386") .id("ubuntu-10.04.4-server-i386")
.name("ubuntu-11.04-server-i386") .name("ubuntu-10.04-server-i386")
.description("ubuntu 11.04 server (i386)") .description("ubuntu")
.operatingSystem( .operatingSystem(
OperatingSystem.builder().description("ubuntu").family(OsFamily.UBUNTU).version("11.04") OperatingSystem.builder().description("ubuntu").family(OsFamily.UBUNTU).version("10.04.4")
.arch("x86").build()) .arch("x86").build())
.status(Image.Status.AVAILABLE).build(); .status(Image.Status.AVAILABLE).build();

View File

@ -39,8 +39,7 @@ import org.jclouds.virtualbox.domain.VmSpec;
import org.jclouds.virtualbox.functions.CloneAndRegisterMachineFromIMachineIfNotAlreadyExists; import org.jclouds.virtualbox.functions.CloneAndRegisterMachineFromIMachineIfNotAlreadyExists;
import org.jclouds.virtualbox.functions.CreateAndInstallVm; import org.jclouds.virtualbox.functions.CreateAndInstallVm;
import org.jclouds.virtualbox.functions.IMachineToSshClient; import org.jclouds.virtualbox.functions.IMachineToSshClient;
import org.jclouds.virtualbox.functions.IpAddressesLoadingCache; import org.jclouds.virtualbox.util.NetworkUtils;
import org.jclouds.virtualbox.util.MachineUtils;
import org.testng.annotations.BeforeClass; import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test; import org.testng.annotations.Test;
import org.virtualbox_4_1.CleanupMode; import org.virtualbox_4_1.CleanupMode;
@ -57,7 +56,7 @@ import com.google.inject.Injector;
/** /**
* @author Andrea Turli * @author Andrea Turli
*/ */
@Test(groups = "live", singleThreaded = true, testName = "GuestAdditionsInstallerLiveTest") @Test(groups = "live", singleThreaded = true, testName = "GuestAdditionsInstallerLiveTest", enabled=false)
public class GuestAdditionsInstallerLiveTest extends BaseVirtualBoxClientLiveTest { public class GuestAdditionsInstallerLiveTest extends BaseVirtualBoxClientLiveTest {
private Injector injector; private Injector injector;
@ -65,7 +64,6 @@ public class GuestAdditionsInstallerLiveTest extends BaseVirtualBoxClientLiveTes
private Predicate<SshClient> sshResponds; private Predicate<SshClient> sshResponds;
private MasterSpec machineSpec; private MasterSpec machineSpec;
private IpAddressesLoadingCache ipAddressesLoadingCache;
@Override @Override
@BeforeClass(groups = "live") @BeforeClass(groups = "live")
@ -117,9 +115,8 @@ public class GuestAdditionsInstallerLiveTest extends BaseVirtualBoxClientLiveTes
sshResponds = injector.getInstance(SshResponds.class); sshResponds = injector.getInstance(SshResponds.class);
checkState(sshResponds.apply(client), "timed out waiting for guest %s to be accessible via ssh", checkState(sshResponds.apply(client), "timed out waiting for guest %s to be accessible via ssh",
machine.getName()); machine.getName());
ipAddressesLoadingCache = injector.getInstance(IpAddressesLoadingCache.class);
assertTrue(MachineUtils.isIpv4(ipAddressesLoadingCache.apply(machine.getName()))); assertTrue(NetworkUtils.isIpv4(networkUtils.getIpAddressFromNicSlot(machine.getName(), 0l)));
} finally { } finally {
for (String vmNameOrId : ImmutableSet.of(machine.getName())) { for (String vmNameOrId : ImmutableSet.of(machine.getName())) {

View File

@ -45,13 +45,7 @@ public class InstallGuestAdditionsLiveTest extends BaseVirtualBoxClientLiveTest
InstallGuestAdditions installer = new InstallGuestAdditions(vmSpecification, "4.1.8"); InstallGuestAdditions installer = new InstallGuestAdditions(vmSpecification, "4.1.8");
String scripts = installer.render(OsFamily.UNIX); String scripts = installer.render(OsFamily.UNIX);
assertEquals("installModuleAssistantIfNeeded || return 1\n" + "mount -t iso9660 /dev/sr1 /mnt\n" assertEquals("installModuleAssistantIfNeeded || return 1\n" + "mount -t iso9660 /dev/sr1 /mnt\n"
+ "/mnt/VBoxLinuxAdditions.run\n" + "/mnt/VBoxLinuxAdditions.run --nox11\n", scripts);
+ "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() { public void testIsoNotPresent() {
@ -67,12 +61,7 @@ public class InstallGuestAdditionsLiveTest extends BaseVirtualBoxClientLiveTest
+ "setupPublicCurl || return 1\n" + "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" + "(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" + "mount -o loop /tmp/VBoxGuestAdditions_4.1.8.iso /mnt\n"
+ "/mnt/VBoxLinuxAdditions.run\n" + "/mnt/VBoxLinuxAdditions.run --nox11\n", scripts);
+ "service vboxadd setup\n"
+ "VBoxService\n"
+ "echo VBoxService > /etc/rc.local\n"
+ "echo exit 0 >> /etc/rc.local\n"
+ "umount /mnt\n", scripts);
} }
} }

View File

@ -18,9 +18,11 @@
*/ */
package org.jclouds.virtualbox.util; package org.jclouds.virtualbox.util;
import static com.google.common.base.Preconditions.checkState; 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_IMAGE_PREFIX;
import static org.jclouds.virtualbox.config.VirtualBoxConstants.VIRTUALBOX_INSTALLATION_KEY_SEQUENCE; 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.config.ValueOfConfigurationKeyOrNull;
import org.jclouds.virtualbox.BaseVirtualBoxClientLiveTest; import org.jclouds.virtualbox.BaseVirtualBoxClientLiveTest;
@ -35,20 +37,17 @@ import org.jclouds.virtualbox.domain.StorageController;
import org.jclouds.virtualbox.domain.VmSpec; import org.jclouds.virtualbox.domain.VmSpec;
import org.jclouds.virtualbox.functions.CloneAndRegisterMachineFromIMachineIfNotAlreadyExists; import org.jclouds.virtualbox.functions.CloneAndRegisterMachineFromIMachineIfNotAlreadyExists;
import org.jclouds.virtualbox.functions.CreateAndInstallVm; import org.jclouds.virtualbox.functions.CreateAndInstallVm;
import org.testng.annotations.AfterClass;
import org.testng.annotations.BeforeClass; import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test; import org.testng.annotations.Test;
import org.virtualbox_4_1.CleanupMode; import org.virtualbox_4_1.CleanupMode;
import org.virtualbox_4_1.IMachine; import org.virtualbox_4_1.IMachine;
import org.virtualbox_4_1.ISession; import org.virtualbox_4_1.ISession;
import org.virtualbox_4_1.LockType;
import org.virtualbox_4_1.NetworkAttachmentType; import org.virtualbox_4_1.NetworkAttachmentType;
import org.virtualbox_4_1.SessionState; import org.virtualbox_4_1.SessionState;
import org.virtualbox_4_1.StorageBus; import org.virtualbox_4_1.StorageBus;
import com.google.common.base.CaseFormat; import com.google.common.base.CaseFormat;
import com.google.common.base.Function; import com.google.common.base.Function;
import com.google.common.collect.ImmutableSet;
import com.google.inject.Injector; import com.google.inject.Injector;
@Test(groups = "live", testName = "MachineControllerLiveTest") @Test(groups = "live", testName = "MachineControllerLiveTest")
@ -62,62 +61,134 @@ public class MachineUtilsLiveTest extends BaseVirtualBoxClientLiveTest {
public void setupContext() { public void setupContext() {
super.setupContext(); super.setupContext();
instanceName = VIRTUALBOX_IMAGE_PREFIX instanceName = VIRTUALBOX_IMAGE_PREFIX
+ CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_HYPHEN, getClass().getSimpleName()); + CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_HYPHEN, getClass().getSimpleName());
StorageController ideController = StorageController StorageController ideController = StorageController
.builder() .builder()
.name("IDE Controller") .name("IDE Controller")
.bus(StorageBus.IDE) .bus(StorageBus.IDE)
.attachISO(0, 0, operatingSystemIso) .attachISO(0, 0, operatingSystemIso)
.attachHardDisk( .attachHardDisk(
HardDisk.builder().diskpath(adminDisk(instanceName)).controllerPort(0).deviceSlot(1) HardDisk.builder().diskpath(adminDisk(instanceName)).controllerPort(0).deviceSlot(1).autoDelete(true)
.autoDelete(true).build()).attachISO(1, 1, guestAdditionsIso).build(); .build()).attachISO(1, 1, guestAdditionsIso).build();
VmSpec instanceVmSpec = VmSpec.builder().id(instanceName).name(instanceName).osTypeId("").memoryMB(512) VmSpec instanceVmSpec = VmSpec.builder().id(instanceName).name(instanceName).osTypeId("").memoryMB(512)
.cleanUpMode(CleanupMode.Full).controller(ideController).forceOverwrite(true).build(); .cleanUpMode(CleanupMode.Full).controller(ideController).forceOverwrite(true).build();
Injector injector = view.utils().injector(); Injector injector = view.utils().injector();
Function<String, String> configProperties = injector.getInstance(ValueOfConfigurationKeyOrNull.class); Function<String, String> configProperties = injector.getInstance(ValueOfConfigurationKeyOrNull.class);
IsoSpec isoSpec = IsoSpec IsoSpec isoSpec = IsoSpec
.builder() .builder()
.sourcePath(operatingSystemIso) .sourcePath(operatingSystemIso)
.installationScript( .installationScript(
configProperties.apply(VIRTUALBOX_INSTALLATION_KEY_SEQUENCE).replace("HOSTNAME", configProperties.apply(VIRTUALBOX_INSTALLATION_KEY_SEQUENCE).replace("HOSTNAME",
instanceVmSpec.getVmName())).build(); instanceVmSpec.getVmName())).build();
NetworkAdapter networkAdapter = NetworkAdapter.builder().networkAttachmentType(NetworkAttachmentType.NAT) NetworkAdapter networkAdapter = NetworkAdapter.builder().networkAttachmentType(NetworkAttachmentType.NAT)
.tcpRedirectRule("127.0.0.1", 2222, "", 22).build(); .tcpRedirectRule("127.0.0.1", 2222, "", 22).build();
NetworkInterfaceCard networkInterfaceCard = NetworkInterfaceCard.builder().addNetworkAdapter(networkAdapter) NetworkInterfaceCard networkInterfaceCard = NetworkInterfaceCard.builder().addNetworkAdapter(networkAdapter)
.build(); .build();
NetworkSpec networkSpec = NetworkSpec.builder().addNIC(networkInterfaceCard).build(); NetworkSpec networkSpec = NetworkSpec.builder().addNIC(networkInterfaceCard).build();
machineSpec = MasterSpec.builder().iso(isoSpec).vm(instanceVmSpec).network(networkSpec).build(); machineSpec = MasterSpec.builder().iso(isoSpec).vm(instanceVmSpec).network(networkSpec).build();
} }
@Test @Test(description = "write lock is acquired and released correctly")
public void lockSessionOnMachine() { public void writeLockSessionOnMachine() {
IMachine machine = cloneFromMaster(); final IMachine clone = cloneFromMaster();
ISession session = machineUtils.lockSessionOnMachineAndApply(instanceName, LockType.Shared, ISession session = machineUtils.writeLockMachineAndApplyToSession(clone.getName(),
new Function<ISession, ISession>() { new Function<ISession, ISession>() {
@Override
public ISession apply(ISession session) {
assertTrue(session.getMachine().getName().equals(clone.getName()));
return session;
}
});
checkState(session.getState().equals(SessionState.Unlocked));
undoVm(clone.getName());
}
@Test(dependsOnMethods="writeLockSessionOnMachine", description = "shared lock is acquired and released correctly")
public void sharedLockSessionOnMachine() {
final IMachine clone = cloneFromMaster();
ISession session = machineUtils.sharedLockMachineAndApplyToSession(clone.getName(),
new Function<ISession, ISession>() {
@Override
public ISession apply(ISession session) {
assertTrue(session.getMachine().getName().equals(clone.getName()));
return session;
}
});
checkState(session.getState().equals(SessionState.Unlocked));
undoVm(clone.getName());
}
@Test(dependsOnMethods="sharedLockSessionOnMachine", description = "shared lock can be acquired after a write lock")
public void sharedLockCanBeAcquiredAfterWriteLockSessionOnMachine() {
final IMachine clone = cloneFromMaster();
try {
ISession writeSession = machineUtils.writeLockMachineAndApplyToSession(clone.getName(),
new Function<ISession, ISession>() {
@Override @Override
public ISession apply(ISession session) { public ISession apply(ISession writeSession) {
return session; checkState(writeSession.getState().equals(SessionState.Locked));
//ISession sharedSession = sharedSession(clone);
return writeSession;
} }
}); });
checkState(session.getState().equals(SessionState.Unlocked)); checkState(writeSession.getState().equals(SessionState.Unlocked));
machine = manager.get().getVBox().findMachine(instanceName); } finally {
undoVm(instanceName); undoVm(clone.getName());
}
}
private ISession sharedSession(final IMachine clone) {
ISession sharedSession = machineUtils.sharedLockMachineAndApplyToSession(clone.getName(),
new Function<ISession, ISession>() {
@Override
public ISession apply(ISession sharedSession) {
checkState(sharedSession.getState().equals(SessionState.Locked));
assertTrue(sharedSession.getMachine().getName().equals(clone.getName()));
return sharedSession;
}
});
return sharedSession;
}
@Test(dependsOnMethods="sharedLockCanBeAcquiredAfterWriteLockSessionOnMachine", description = "write lock cannot be acquired after a shared lock")
public void writeLockCannotBeAcquiredAfterSharedLockSessionOnMachine() {
final IMachine clone = cloneFromMaster();
try {
ISession sharedSession = machineUtils.sharedLockMachineAndApplyToSession(clone.getName(),
new Function<ISession, ISession>() {
@Override
public ISession apply(ISession sharedSession) {
checkState(sharedSession.getState().equals(SessionState.Locked));
return sharedSession;
}
});
checkState(sharedSession.getState().equals(SessionState.Unlocked));
ISession writeSession = machineUtils.writeLockMachineAndApplyToSession(clone.getName(),
new Function<ISession, ISession>() {
@Override
public ISession apply(ISession writeSession) {
checkState(writeSession.getState().equals(SessionState.Locked));
assertTrue(writeSession.getMachine().getName().equals(clone.getName()));
return writeSession;
}
});
checkState(writeSession.getState().equals(SessionState.Unlocked));
} finally {
undoVm(clone.getName());
}
} }
private IMachine cloneFromMaster() { private IMachine cloneFromMaster() {
IMachine source = getVmWithGuestAdditionsInstalled(); IMachine source = getVmWithGuestAdditionsInstalled();
CloneSpec cloneSpec = CloneSpec.builder().vm(machineSpec.getVmSpec()).network(machineSpec.getNetworkSpec()) CloneSpec cloneSpec = CloneSpec.builder().vm(machineSpec.getVmSpec()).network(machineSpec.getNetworkSpec())
.master(source).linked(true).build(); .master(source).linked(true).build();
return new CloneAndRegisterMachineFromIMachineIfNotAlreadyExists(manager, workingDir, machineUtils) return new CloneAndRegisterMachineFromIMachineIfNotAlreadyExists(manager, workingDir, machineUtils)
.apply(cloneSpec); .apply(cloneSpec);
} }
private IMachine getVmWithGuestAdditionsInstalled() { private IMachine getVmWithGuestAdditionsInstalled() {
@ -130,13 +201,4 @@ public class MachineUtilsLiveTest extends BaseVirtualBoxClientLiveTest {
return manager.get().getVBox().findMachine(masterSpecForTest.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();
}
} }

View File

@ -1,4 +1,139 @@
images: images:
- id: ubuntu-10.04.4-server-i386
name: ubuntu-10.04-server-i386
description: ubuntu 10.04.4 server (i386)
os_arch: x86
os_family: ubuntu
os_description: ubuntu
os_version: 10.04.4
iso: http://releases.ubuntu.com/10.04.4/ubuntu-10.04.4-server-i386.iso
iso_md5: fc08a01e78348e3918180ea91a6883bb
username: toor
credential: password
keystroke_sequence: |
<Esc><Esc><Enter>
/install/vmlinuz noapic preseed/url=http://10.0.2.2:8080/src/test/resources/preseed.cfg
debian-installer=en_US auto locale=en_US kbd-chooser/method=us
hostname=vmName
fb=false debconf/frontend=noninteractive
console-setup/ask_detect=false console-setup/modelcode=pc105 console-setup/layoutcode=us
initrd=/install/initrd.gz -- <Enter>
preseed_cfg: |
## Options to set on the command line
d-i debian-installer/locale string en_US
d-i console-setup/ask_detect boolean false
d-i console-setup/layoutcode string us
d-i netcfg/get_hostname string unassigned-hostname
d-i netcfg/get_domain string unassigned-domain
d-i time/zone string UTC
d-i clock-setup/utc-auto boolean true
d-i clock-setup/utc boolean true
d-i kbd-chooser/method select American English
d-i netcfg/wireless_wep string
d-i base-installer/kernel/override-image string linux-server
d-i debconf debconf/frontend select Noninteractive
d-i pkgsel/install-language-support boolean false
tasksel tasksel/first multiselect standard, ubuntu-server
d-i partman-auto/method string lvm
#d-i partman-auto/purge_lvm_from_device boolean true
d-i partman-lvm/confirm boolean true
d-i partman-lvm/device_remove_lvm boolean true
d-i partman-auto/choose_recipe select atomic
d-i partman/confirm_write_new_label boolean true
d-i partman/confirm_nooverwrite boolean true
d-i partman/choose_partition select finish
d-i partman/confirm boolean true
# Write the changes to disks and configure LVM?
d-i partman-lvm/confirm boolean true
d-i partman-lvm/confirm_nooverwrite boolean true
d-i partman-auto-lvm/guided_size string max
## Default user, we can get away with a recipe to change this
d-i passwd/user-fullname string toor
d-i passwd/username string toor
d-i passwd/user-password password password
d-i passwd/user-password-again password password
d-i user-setup/encrypt-home boolean false
d-i user-setup/allow-password-weak boolean true
d-i pkgsel/include string openssh-server ntp
# Whether to upgrade packages after debootstrap.
# Allowed values: none, safe-upgrade, full-upgrade
d-i pkgsel/upgrade select full-upgrade
d-i grub-installer/only_debian boolean true
d-i grub-installer/with_other_os boolean true
d-i finish-install/reboot_in_progress note
#For the update
d-i pkgsel/update-policy select none
# debconf-get-selections --install
#Use mirror
choose-mirror-bin mirror/http/proxy string
- id: ubuntu-10.04.4-server-amd64
name: ubuntu-10.04-server-amd64
description: ubuntu 10.04.4 server (amd64)
os_arch: amd64
os_family: ubuntu
os_description: ubuntu
os_version: 10.04.4
os_64bit: true
iso: http://releases.ubuntu.com/10.04.4/ubuntu-10.04.4-server-amd64.iso
iso_md5: 9b218654cdcdf9722171648c52f8a088
username: toor
credential: password
keystroke_sequence: |
<Esc><Esc><Enter>
/install/vmlinuz noapic preseed/url=http://10.0.2.2:8080/src/test/resources/preseed.cfg
debian-installer=en_US auto locale=en_US kbd-chooser/method=us
hostname=vmName
fb=false debconf/frontend=noninteractive
console-setup/ask_detect=false console-setup/modelcode=pc105 console-setup/layoutcode=us
initrd=/install/initrd.gz -- <Enter>
preseed_cfg: |
## Options to set on the command line
d-i debian-installer/locale string en_US
d-i console-setup/ask_detect boolean false
d-i console-setup/layoutcode string us
d-i netcfg/get_hostname string unassigned-hostname
d-i netcfg/get_domain string unassigned-domain
d-i time/zone string UTC
d-i clock-setup/utc-auto boolean true
d-i clock-setup/utc boolean true
d-i kbd-chooser/method select American English
d-i netcfg/wireless_wep string
d-i base-installer/kernel/override-image string linux-server
d-i debconf debconf/frontend select Noninteractive
d-i pkgsel/install-language-support boolean false
tasksel tasksel/first multiselect standard, ubuntu-server
d-i partman-auto/method string lvm
#d-i partman-auto/purge_lvm_from_device boolean true
d-i partman-lvm/confirm boolean true
d-i partman-lvm/device_remove_lvm boolean true
d-i partman-auto/choose_recipe select atomic
d-i partman/confirm_write_new_label boolean true
d-i partman/confirm_nooverwrite boolean true
d-i partman/choose_partition select finish
d-i partman/confirm boolean true
# Write the changes to disks and configure LVM?
d-i partman-lvm/confirm boolean true
d-i partman-lvm/confirm_nooverwrite boolean true
d-i partman-auto-lvm/guided_size string max
## Default user, we can get away with a recipe to change this
d-i passwd/user-fullname string toor
d-i passwd/username string toor
d-i passwd/user-password password password
d-i passwd/user-password-again password password
d-i user-setup/encrypt-home boolean false
d-i user-setup/allow-password-weak boolean true
d-i pkgsel/include string openssh-server ntp
# Whether to upgrade packages after debootstrap.
# Allowed values: none, safe-upgrade, full-upgrade
d-i pkgsel/upgrade select full-upgrade
d-i grub-installer/only_debian boolean true
d-i grub-installer/with_other_os boolean true
d-i finish-install/reboot_in_progress note
#For the update
d-i pkgsel/update-policy select none
# debconf-get-selections --install
#Use mirror
choose-mirror-bin mirror/http/proxy string
- id: ubuntu-11.04-i386 - id: ubuntu-11.04-i386
name: ubuntu-11.04-server-i386 name: ubuntu-11.04-server-i386
description: ubuntu 11.04 server (i386) description: ubuntu 11.04 server (i386)
@ -27,7 +162,7 @@ images:
d-i time/zone string UTC d-i time/zone string UTC
d-i clock-setup/utc-auto boolean true d-i clock-setup/utc-auto boolean true
d-i clock-setup/utc boolean true d-i clock-setup/utc boolean true
d-i kbd-chooser/method select American English d-i kbd-chooser/method select American English
d-i netcfg/wireless_wep string d-i netcfg/wireless_wep string
d-i base-installer/kernel/override-image string linux-server d-i base-installer/kernel/override-image string linux-server
# Choices: Dialog, Readline, Gnome, Kde, Editor, Noninteractive # Choices: Dialog, Readline, Gnome, Kde, Editor, Noninteractive
@ -143,6 +278,8 @@ images:
os_64bit: true os_64bit: true
iso: http://releases.ubuntu.com/12.04/ubuntu-12.04.1-server-amd64.iso iso: http://releases.ubuntu.com/12.04/ubuntu-12.04.1-server-amd64.iso
iso_md5: a8c667e871f48f3a662f3fbf1c3ddb17 iso_md5: a8c667e871f48f3a662f3fbf1c3ddb17
username: toor
credential: password
keystroke_sequence: | keystroke_sequence: |
<Esc><Esc><Enter> <Esc><Esc><Enter>
/install/vmlinuz noapic preseed/url=http://10.0.2.2:8080/src/test/resources/preseed.cfg /install/vmlinuz noapic preseed/url=http://10.0.2.2:8080/src/test/resources/preseed.cfg

View File

@ -42,6 +42,11 @@
<level value="DEBUG" /> <level value="DEBUG" />
<appender-ref ref="CONSOLE" /> <appender-ref ref="CONSOLE" />
</root> </root>
<logger name="net.schmizz.sshj">
<level value="ERROR" />
<appender-ref ref="CONSOLE" />
</logger>
<logger name="org.jclouds"> <logger name="org.jclouds">
<level value="DEBUG" /> <level value="DEBUG" />