mirror of https://github.com/apache/jclouds.git
Merge pull request #844 from andreaturli/virtualbox
issue 384: improved ISession management; added ubuntu 10.04.4 support;
This commit is contained in:
commit
9b5073710a
|
@ -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>
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -236,4 +236,5 @@ public class VirtualBoxComputeServiceContextModule extends
|
||||||
protected Map<MachineState, Image.Status> toPortableImageStatus() {
|
protected Map<MachineState, Image.Status> toPortableImageStatus() {
|
||||||
return toPortableImageStatus;
|
return toPortableImageStatus;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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";
|
||||||
}
|
}
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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 +
|
||||||
'}';
|
'}';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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 + '}';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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");
|
|
||||||
}
|
|
||||||
}
|
}
|
|
@ -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);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
|
@ -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,
|
||||||
|
|
|
@ -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() {
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
|
@ -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();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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");
|
||||||
|
}
|
||||||
|
}
|
|
@ -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
|
||||||
|
|
|
@ -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));
|
||||||
|
|
||||||
|
|
|
@ -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"));
|
||||||
|
|
|
@ -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());
|
||||||
|
|
|
@ -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();
|
||||||
|
|
||||||
|
|
|
@ -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())) {
|
||||||
|
|
|
@ -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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -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();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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" />
|
||||||
|
|
Loading…
Reference in New Issue