mirror of https://github.com/apache/jclouds.git
issue 384: improved ISession management; managed to start VBoxExperimentLiveTest with 30 guests; added ubuntu 10.04.4 support; paramentrized guest memory
This commit is contained in:
parent
28d766b9df
commit
fa93b39c3d
|
@ -38,7 +38,7 @@
|
|||
<test.virtualbox.endpoint>http://localhost:18083/</test.virtualbox.endpoint>
|
||||
<test.virtualbox.api-version>4.1.4</test.virtualbox.api-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.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>
|
||||
|
|
|
@ -20,12 +20,12 @@ package org.jclouds.virtualbox;
|
|||
|
||||
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_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_INSTALLATION_KEY_SEQUENCE;
|
||||
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_GUEST_MEMORY;
|
||||
|
||||
|
||||
import java.io.File;
|
||||
import java.net.URI;
|
||||
|
@ -74,22 +74,17 @@ public class VirtualBoxApiMetadata extends BaseApiMetadata {
|
|||
+ "initrd=/install/initrd.gz -- <Enter>");
|
||||
|
||||
String workingDir = System.getProperty("test.virtualbox.workingDir", VIRTUALBOX_DEFAULT_DIR);
|
||||
|
||||
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
|
||||
+ File.separator + "images.yaml");
|
||||
|
||||
properties.put(VIRTUALBOX_IMAGES_DESCRIPTOR, yamlDescriptor);
|
||||
|
||||
properties.put(VIRTUALBOX_PRECONFIGURATION_URL, "http://10.0.2.2:23232/preseed.cfg");
|
||||
|
||||
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)));
|
||||
properties.setProperty(TEMPLATE, "osFamily=UBUNTU,osVersionMatches=12.04.1,os64Bit=true,osArchMatches=amd64");
|
||||
return properties;
|
||||
}
|
||||
|
||||
|
|
|
@ -28,6 +28,7 @@ import static org.jclouds.virtualbox.config.VirtualBoxConstants.VIRTUALBOX_NODE_
|
|||
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
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.YamlImage;
|
||||
import org.jclouds.virtualbox.functions.admin.UnregisterMachineIfExistsAndForceDeleteItsMedia;
|
||||
import org.jclouds.virtualbox.util.MachineController;
|
||||
import org.virtualbox_4_1.IMachine;
|
||||
import org.virtualbox_4_1.IProgress;
|
||||
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.Iterables;
|
||||
import com.google.common.collect.Sets;
|
||||
import com.google.common.util.concurrent.Uninterruptibles;
|
||||
import com.google.inject.Singleton;
|
||||
|
||||
/**
|
||||
|
@ -82,17 +85,20 @@ public class VirtualBoxComputeServiceAdapter implements ComputeServiceAdapter<IM
|
|||
private final LoadingCache<Image, Master> mastersLoader;
|
||||
private final Function<NodeSpec, NodeAndInitialCredentials<IMachine>> cloneCreator;
|
||||
private final Function<IMachine, Image> imachineToImage;
|
||||
private final MachineController machineController;
|
||||
|
||||
@Inject
|
||||
public VirtualBoxComputeServiceAdapter(Supplier<VirtualBoxManager> manager,
|
||||
Supplier<Map<Image, YamlImage>> imagesMapper, LoadingCache<Image, Master> mastersLoader,
|
||||
Function<NodeSpec, NodeAndInitialCredentials<IMachine>> cloneCreator,
|
||||
Function<IMachine, Image> imachineToImage) {
|
||||
Function<IMachine, Image> imachineToImage,
|
||||
MachineController machineController) {
|
||||
this.manager = checkNotNull(manager, "manager");
|
||||
this.imagesToYamlImages = imagesMapper.get();
|
||||
this.mastersLoader = mastersLoader;
|
||||
this.cloneCreator = cloneCreator;
|
||||
this.imachineToImage = imachineToImage;
|
||||
this.machineController = machineController;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -199,7 +205,11 @@ public class VirtualBoxComputeServiceAdapter implements ComputeServiceAdapter<IM
|
|||
public synchronized void destroyNode(String vmName) {
|
||||
IMachine machine = manager.get().getVBox().findMachine(vmName);
|
||||
powerDownMachine(machine);
|
||||
new UnregisterMachineIfExistsAndForceDeleteItsMedia().apply(machine);
|
||||
try {
|
||||
new UnregisterMachineIfExistsAndForceDeleteItsMedia().apply(machine);
|
||||
} catch (Exception e) {
|
||||
logger.error("Machine (%s) not unregistered!", vmName);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -247,21 +257,10 @@ public class VirtualBoxComputeServiceAdapter implements ComputeServiceAdapter<IM
|
|||
logger.debug("vm was already powered down: ", machine.getId());
|
||||
return;
|
||||
}
|
||||
logger.debug("powering down vm: ", machine.getId());
|
||||
ISession machineSession = manager.get().openMachineSession(machine);
|
||||
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) {
|
||||
}
|
||||
}
|
||||
|
||||
logger.debug("powering down vm: %s", machine.getName());
|
||||
machineController.ensureMachineHasPowerDown(machine.getName());
|
||||
} catch (Exception e) {
|
||||
logger.error(e, "problem in powering down the %s", machine.getName());
|
||||
throw Throwables.propagate(e);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -236,4 +236,5 @@ public class VirtualBoxComputeServiceContextModule extends
|
|||
protected Map<MachineState, Image.Status> toPortableImageStatus() {
|
||||
return toPortableImageStatus;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -51,6 +51,8 @@ public interface VirtualBoxConstants {
|
|||
|
||||
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_WEBSERVER_IDENTITY = "jclouds.virtualbox.webserver.identity";
|
||||
|
@ -62,7 +64,7 @@ public interface VirtualBoxConstants {
|
|||
|
||||
public static final String VIRTUALBOX_PROVIDER = "virtualbox";
|
||||
|
||||
public static final String VIRTUALBOX_GUEST_IDENTITY = "jclouds.virtualbox.guest.identity";
|
||||
public static final String VIRTUALBOX_GUEST_CREDENTIAL = "jclouds.virtualbox.guest.credential";
|
||||
public static final String GUEST_OS_PASSWORD = "guestPassword";
|
||||
|
||||
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 org.jclouds.domain.LoginCredentials;
|
||||
|
||||
import com.google.common.base.Objects;
|
||||
|
||||
/**
|
||||
|
@ -32,6 +34,7 @@ public class MasterSpec {
|
|||
private VmSpec vmSpec;
|
||||
private IsoSpec isoSpec;
|
||||
private NetworkSpec networkSpec;
|
||||
private LoginCredentials loginCredentials;
|
||||
|
||||
public static Builder builder() {
|
||||
return new Builder();
|
||||
|
@ -42,6 +45,7 @@ public class MasterSpec {
|
|||
private VmSpec vmSpec;
|
||||
private IsoSpec isoSpec;
|
||||
private NetworkSpec networkSpec;
|
||||
private LoginCredentials loginCredentials;
|
||||
|
||||
public Builder vm(VmSpec vmSpec) {
|
||||
this.vmSpec = vmSpec;
|
||||
|
@ -58,19 +62,25 @@ public class MasterSpec {
|
|||
return this;
|
||||
}
|
||||
|
||||
public Builder credentials(LoginCredentials loginCredentials) {
|
||||
this.loginCredentials = loginCredentials;
|
||||
return this;
|
||||
}
|
||||
|
||||
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(isoSpec, "isoSpec");
|
||||
checkNotNull(networkSpec, "networkSpec");
|
||||
this.vmSpec = vmSpec;
|
||||
this.isoSpec = isoSpec;
|
||||
this.networkSpec = networkSpec;
|
||||
this.loginCredentials = loginCredentials;
|
||||
}
|
||||
|
||||
public VmSpec getVmSpec() {
|
||||
|
@ -85,6 +95,10 @@ public class MasterSpec {
|
|||
return networkSpec;
|
||||
}
|
||||
|
||||
public LoginCredentials getLoginCredentials() {
|
||||
return loginCredentials;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o)
|
||||
|
|
|
@ -28,12 +28,13 @@ public class NetworkInterfaceCard {
|
|||
private final long slot;
|
||||
private final NetworkAdapter networkAdapter;
|
||||
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.networkAdapter = checkNotNull(networkAdapter, "networkAdapter");
|
||||
this.hostInterfaceName = hostInterfaceName;
|
||||
this.enabled = enabled;
|
||||
}
|
||||
|
||||
public static Builder builder() {
|
||||
|
@ -45,6 +46,7 @@ public class NetworkInterfaceCard {
|
|||
private long slot = 0L;
|
||||
private NetworkAdapter networkAdapter;
|
||||
private String hostInterfaceName;
|
||||
private boolean enabled = true;
|
||||
|
||||
public Builder slot(long slot) {
|
||||
checkArgument(slot >= 0 && slot < 4, "must be 0, 1, 2, 3: %s", slot);
|
||||
|
@ -64,8 +66,14 @@ public class NetworkInterfaceCard {
|
|||
return this;
|
||||
}
|
||||
|
||||
public Builder enabled(
|
||||
boolean enabled) {
|
||||
this.enabled = enabled;
|
||||
return this;
|
||||
}
|
||||
|
||||
public NetworkInterfaceCard build() {
|
||||
return new NetworkInterfaceCard(slot, networkAdapter, hostInterfaceName);
|
||||
return new NetworkInterfaceCard(slot, networkAdapter, hostInterfaceName, enabled);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -81,6 +89,10 @@ public class NetworkInterfaceCard {
|
|||
return hostInterfaceName;
|
||||
}
|
||||
|
||||
public boolean isEnabled() {
|
||||
return enabled;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o)
|
||||
|
@ -89,14 +101,15 @@ public class NetworkInterfaceCard {
|
|||
NetworkInterfaceCard other = (NetworkInterfaceCard) o;
|
||||
return Objects.equal(slot,
|
||||
other.slot) &&
|
||||
Objects.equal(networkAdapter, other.networkAdapter);
|
||||
Objects.equal(networkAdapter, other.networkAdapter)
|
||||
&& Objects.equal(enabled, other.enabled);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hashCode(slot, networkAdapter);
|
||||
return Objects.hashCode(slot, networkAdapter, enabled);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -104,6 +117,7 @@ public class NetworkInterfaceCard {
|
|||
return "NetworkInterfaceCard{slot="+
|
||||
slot +
|
||||
", networkAdapter=" + networkAdapter +
|
||||
", enabled=" + enabled +
|
||||
'}';
|
||||
}
|
||||
|
||||
|
|
|
@ -42,7 +42,7 @@ public class VmSpec {
|
|||
private final Set<StorageController> controllers;
|
||||
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) {
|
||||
this.vmId = checkNotNull(vmId, "vmId");
|
||||
this.vmName = checkNotNull(vmName, "vmName");
|
||||
|
@ -67,6 +67,8 @@ public class VmSpec {
|
|||
private String osTypeId = "";
|
||||
private boolean forceOverwrite = true;
|
||||
private long memory;
|
||||
private String guestUser;
|
||||
private String guestPassword;
|
||||
private CleanupMode cleanUpMode;
|
||||
|
||||
public Builder controller(StorageController controller) {
|
||||
|
@ -104,12 +106,23 @@ public class VmSpec {
|
|||
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() {
|
||||
checkNotNull(name, "name");
|
||||
checkNotNull(id, "id");
|
||||
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() {
|
||||
|
@ -162,7 +175,8 @@ public class VmSpec {
|
|||
@Override
|
||||
public String toString() {
|
||||
return "VmSpecification{" + "vmName='" + vmName + '\'' + ", osTypeId='" + osTypeId + '\'' + ", memory='" + memory
|
||||
+ '\'' + ", vmId='" + vmId + '\'' + ", forceOverwrite=" + forceOverwrite + ", controllers="
|
||||
+ controllers + ", cleanupMode=" + cleanupMode + '}';
|
||||
+ '\'' + ", vmId='" + vmId + '\'' + '\''
|
||||
+ ", 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.OperatingSystem;
|
||||
import org.jclouds.compute.domain.OsFamily;
|
||||
import org.jclouds.domain.LoginCredentials;
|
||||
|
||||
import com.google.common.base.Function;
|
||||
import com.google.common.collect.Lists;
|
||||
|
@ -137,13 +138,16 @@ public class YamlImage {
|
|||
public Image apply(YamlImage arg0) {
|
||||
if (arg0 == null)
|
||||
return null;
|
||||
|
||||
OsFamily family = parseOsFamilyOrUnrecognized(arg0.os_family);
|
||||
|
||||
OperatingSystem operatingSystem = OperatingSystem.builder().description(arg0.os_description).family(family)
|
||||
.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)
|
||||
.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.setMACAddress(networkInterfaceCard.getNetworkAdapter().getMacAddress());
|
||||
iNetworkAdapter.setBridgedInterface(networkInterfaceCard.getHostInterfaceName());
|
||||
iNetworkAdapter.setEnabled(true);
|
||||
iNetworkAdapter.setEnabled(networkInterfaceCard.isEnabled());
|
||||
machine.saveSettings();
|
||||
return null;
|
||||
}
|
||||
|
|
|
@ -45,7 +45,7 @@ public class AttachHostOnlyAdapter implements Function<IMachine, Void> {
|
|||
iNetworkAdapter.setAdapterType(Am79C973);
|
||||
iNetworkAdapter.setMACAddress(networkInterfaceCard.getNetworkAdapter().getMacAddress());
|
||||
iNetworkAdapter.setHostOnlyInterface(networkInterfaceCard.getHostInterfaceName());
|
||||
iNetworkAdapter.setEnabled(true);
|
||||
iNetworkAdapter.setEnabled(networkInterfaceCard.isEnabled());
|
||||
machine.saveSettings();
|
||||
return null;
|
||||
}
|
||||
|
|
|
@ -55,7 +55,7 @@ public class AttachNATAdapterToMachineIfNotAlreadyExists implements Function<IMa
|
|||
throw e;
|
||||
}
|
||||
}
|
||||
iNetworkAdapter.setEnabled(true);
|
||||
iNetworkAdapter.setEnabled(networkInterfaceCard.isEnabled());
|
||||
machine.saveSettings();
|
||||
return null;
|
||||
}
|
||||
|
|
|
@ -19,9 +19,11 @@
|
|||
|
||||
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.List;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.inject.Named;
|
||||
|
@ -62,8 +64,6 @@ public class CloneAndRegisterMachineFromIMachineIfNotAlreadyExists implements Fu
|
|||
private final String workingDir;
|
||||
private final MachineUtils machineUtils;
|
||||
|
||||
private final ReentrantLock lock = new ReentrantLock();
|
||||
|
||||
@Inject
|
||||
public CloneAndRegisterMachineFromIMachineIfNotAlreadyExists(Supplier<VirtualBoxManager> manager,
|
||||
@Named(VirtualBoxConstants.VIRTUALBOX_WORKINGDIR) String workingDir, MachineUtils machineUtils) {
|
||||
|
@ -126,6 +126,13 @@ public class CloneAndRegisterMachineFromIMachineIfNotAlreadyExists implements Fu
|
|||
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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,9 +21,12 @@ package org.jclouds.virtualbox.functions;
|
|||
import static com.google.common.base.Preconditions.checkState;
|
||||
import static com.google.common.collect.Iterables.transform;
|
||||
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 java.util.List;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
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.Predicate;
|
||||
import com.google.common.base.Splitter;
|
||||
import com.google.common.base.Throwables;
|
||||
import com.google.common.collect.Iterables;
|
||||
import com.google.common.util.concurrent.Futures;
|
||||
import com.google.common.util.concurrent.ListenableFuture;
|
||||
import com.google.common.util.concurrent.Uninterruptibles;
|
||||
import com.google.inject.Inject;
|
||||
|
||||
@Singleton
|
||||
|
@ -92,49 +95,60 @@ public class CreateAndInstallVm implements Function<MasterSpec, IMachine> {
|
|||
public IMachine apply(MasterSpec masterSpec) {
|
||||
VmSpec vmSpec = masterSpec.getVmSpec();
|
||||
IsoSpec isoSpec = masterSpec.getIsoSpec();
|
||||
String vmName = vmSpec.getVmName();
|
||||
IMachine vm = createAndRegisterMachineFromIsoIfNotAlreadyExists.apply(masterSpec);
|
||||
String masterName = vmSpec.getVmName();
|
||||
IMachine masterMachine = createAndRegisterMachineFromIsoIfNotAlreadyExists.apply(masterSpec);
|
||||
// Launch machine and wait for it to come online
|
||||
machineController.ensureMachineIsLaunched(vmName);
|
||||
machineController.ensureMachineIsLaunched(masterName);
|
||||
String installationKeySequence = isoSpec.getInstallationKeySequence().replace("PRECONFIGURATION_URL",
|
||||
preconfigurationUrl);
|
||||
configureOsInstallationWithKeyboardSequence(vmName, installationKeySequence);
|
||||
|
||||
// the OS installation is a long process: let's delay the check for ssh of 30 sec
|
||||
try {
|
||||
Thread.sleep(30000l);
|
||||
} catch (InterruptedException e) {
|
||||
Throwables.propagate(e);
|
||||
}
|
||||
configureOsInstallationWithKeyboardSequence(masterName, installationKeySequence);
|
||||
|
||||
SshClient client = sshClientForIMachine.apply(vm);
|
||||
logger.debug(">> awaiting installation to finish node(%s)", vmName);
|
||||
checkState(sshResponds.apply(client), "timed out waiting for guest %s to be accessible via ssh", vmName);
|
||||
NodeMetadata nodeMetadata = imachineToNodeMetadata.apply(vm);
|
||||
// the OS installation is a long process: let's delay the check for ssh of 40 sec
|
||||
Uninterruptibles.sleepUninterruptibly(40, TimeUnit.SECONDS);
|
||||
|
||||
logger.debug(">> awaiting post-installation actions on vm: %s", vmName);
|
||||
masterMachine.setExtraData(GUEST_OS_USER, masterSpec.getLoginCredentials().getUser());
|
||||
masterMachine.setExtraData(GUEST_OS_PASSWORD, masterSpec.getLoginCredentials().getPassword());
|
||||
|
||||
SshClient client = sshClientForIMachine.apply(masterMachine);
|
||||
logger.debug(">> awaiting installation to finish node(%s)", masterName);
|
||||
checkState(sshResponds.apply(client), "timed out waiting for guest %s to be accessible via ssh", masterName);
|
||||
NodeMetadata nodeMetadata = imachineToNodeMetadata.apply(masterMachine);
|
||||
|
||||
logger.debug(">> awaiting post-installation actions on vm: %s", masterName);
|
||||
ListenableFuture<ExecResponse> execCleanup = machineUtils.runScriptOnNode(nodeMetadata,
|
||||
call("cleanupUdevIfNeeded"), RunScriptOptions.NONE);
|
||||
ExecResponse cleanupResponse = Futures.getUnchecked(execCleanup);
|
||||
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,
|
||||
new InstallGuestAdditions(vmSpec, version), RunScriptOptions.NONE);
|
||||
ExecResponse gaInstallationResponse = Futures.getUnchecked(execInstallGA);
|
||||
checkState(gaInstallationResponse.getExitStatus() == 0);
|
||||
machineController.ensureMachineIsShutdown(vmName);
|
||||
Iterable<IMediumAttachment> mediumAttachments = Iterables.filter(vm.getMediumAttachmentsOfController("IDE Controller"),
|
||||
new Predicate<IMediumAttachment>() {
|
||||
public boolean apply(IMediumAttachment in) {
|
||||
return in.getMedium() != null && in.getMedium().getDeviceType().equals(DeviceType.DVD);
|
||||
}
|
||||
});
|
||||
|
||||
machineController.ensureMachineIsShutdown(masterName);
|
||||
|
||||
// detach DVD and ISOs, if needed
|
||||
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) {
|
||||
machineUtils.writeLockMachineAndApply(vm.getName(), new DetachDistroMediumFromMachine(
|
||||
iMediumAttachment.getController(), iMediumAttachment.getPort(), iMediumAttachment.getDevice()));
|
||||
}
|
||||
return vm;
|
||||
logger.debug("Detach %s from (%s)", iMediumAttachment.getMedium()
|
||||
.getName(), masterMachine.getName());
|
||||
machineUtils.writeLockMachineAndApply(
|
||||
masterMachine.getName(),
|
||||
new DetachDistroMediumFromMachine(iMediumAttachment
|
||||
.getController(), iMediumAttachment.getPort(),
|
||||
iMediumAttachment.getDevice()));
|
||||
}
|
||||
return masterMachine;
|
||||
}
|
||||
|
||||
private void configureOsInstallationWithKeyboardSequence(String vmName, String installationKeySequence) {
|
||||
|
|
|
@ -77,30 +77,31 @@ public class CreateAndRegisterMachineFromIsoIfNotAlreadyExists implements Functi
|
|||
}
|
||||
|
||||
@Override
|
||||
public IMachine apply(MasterSpec launchSpecification) {
|
||||
public IMachine apply(MasterSpec masterSpec) {
|
||||
final IVirtualBox vBox = manager.get().getVBox();
|
||||
String vmName = launchSpecification.getVmSpec().getVmName();
|
||||
String vmId = launchSpecification.getVmSpec().getVmId();
|
||||
String vmName = masterSpec.getVmSpec().getVmName();
|
||||
String vmId = masterSpec.getVmSpec().getVmId();
|
||||
|
||||
try {
|
||||
vBox.findMachine(vmId);
|
||||
throw new IllegalStateException("Machine " + vmName + " is already registered.");
|
||||
} catch (VBoxException e) {
|
||||
if (machineNotFoundException(e))
|
||||
return createMachine(vBox, launchSpecification);
|
||||
return createMachine(vBox, masterSpec);
|
||||
else
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
private IMachine createMachine(IVirtualBox vBox, MasterSpec machineSpec) {
|
||||
VmSpec vmSpec = machineSpec.getVmSpec();
|
||||
private IMachine createMachine(IVirtualBox vBox, MasterSpec masterSpec) {
|
||||
VmSpec vmSpec = masterSpec.getVmSpec();
|
||||
String settingsFile = vBox.composeMachineFilename(vmSpec.getVmName(), workingDir);
|
||||
|
||||
IMachine newMachine = vBox.createMachine(settingsFile, vmSpec.getVmName(), vmSpec.getOsTypeId(),
|
||||
vmSpec.getVmId(), vmSpec.isForceOverwrite());
|
||||
|
||||
manager.get().getVBox().registerMachine(newMachine);
|
||||
ensureConfiguration(machineSpec);
|
||||
ensureConfiguration(masterSpec);
|
||||
return newMachine;
|
||||
}
|
||||
|
||||
|
|
|
@ -19,6 +19,8 @@
|
|||
|
||||
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_PREFIX;
|
||||
|
||||
|
@ -37,7 +39,7 @@ import org.jclouds.domain.LocationScope;
|
|||
import org.jclouds.domain.LoginCredentials;
|
||||
import org.jclouds.javax.annotation.Nullable;
|
||||
import org.jclouds.logging.Logger;
|
||||
import org.jclouds.virtualbox.util.MachineUtils;
|
||||
import org.jclouds.virtualbox.util.NetworkUtils;
|
||||
import org.testng.collections.Lists;
|
||||
import org.virtualbox_4_1.IMachine;
|
||||
import org.virtualbox_4_1.INetworkAdapter;
|
||||
|
@ -58,12 +60,13 @@ public class IMachineToNodeMetadata implements Function<IMachine, NodeMetadata>
|
|||
protected Logger logger = Logger.NULL;
|
||||
|
||||
private final Map<MachineState, Status> toPortableNodeStatus;
|
||||
private final MachineUtils machineUtils;
|
||||
private final NetworkUtils networkUtils;
|
||||
|
||||
@Inject
|
||||
public IMachineToNodeMetadata(Map<MachineState, NodeMetadata.Status> toPortableNodeStatus, MachineUtils machineUtils) {
|
||||
public IMachineToNodeMetadata(Map<MachineState, NodeMetadata.Status> toPortableNodeStatus,
|
||||
NetworkUtils networkUtils) {
|
||||
this.toPortableNodeStatus = toPortableNodeStatus;
|
||||
this.machineUtils = machineUtils;
|
||||
this.networkUtils = networkUtils;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -96,7 +99,9 @@ public class IMachineToNodeMetadata implements Function<IMachine, NodeMetadata>
|
|||
nodeMetadataBuilder.status(nodeState);
|
||||
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);
|
||||
|
||||
return nodeMetadataBuilder.build();
|
||||
|
@ -104,7 +109,7 @@ public class IMachineToNodeMetadata implements Function<IMachine, NodeMetadata>
|
|||
|
||||
private NodeMetadataBuilder getIpAddresses(IMachine vm, NodeMetadataBuilder nodeMetadataBuilder) {
|
||||
List<String> publicIpAddresses = Lists.newArrayList();
|
||||
|
||||
List<String> privateIpAddresses = Lists.newArrayList();
|
||||
for(long slot = 0; slot < 4; slot ++) {
|
||||
INetworkAdapter adapter = vm.getNetworkAdapter(slot);
|
||||
if(adapter != null) {
|
||||
|
@ -123,16 +128,15 @@ public class IMachineToNodeMetadata implements Function<IMachine, NodeMetadata>
|
|||
publicIpAddresses.add(hostAddress);
|
||||
nodeMetadataBuilder.loginPort(inPort);
|
||||
}
|
||||
//privateIpAddresses.add((NodeCreator.VMS_NETWORK + ipTermination) + "");
|
||||
}
|
||||
// TODO this could be a public and private address
|
||||
} else if (adapter.getAttachmentType() == NetworkAttachmentType.Bridged) {
|
||||
String clientIpAddress = machineUtils.getIpAddressFromFirstNIC(vm.getName());
|
||||
//privateIpAddresses.add(clientIpAddress);
|
||||
publicIpAddresses.add(clientIpAddress);
|
||||
// TODO quick test first
|
||||
String clientIpAddress = networkUtils.getIpAddressFromNicSlot(vm.getName(), adapter.getSlot());
|
||||
privateIpAddresses.add(clientIpAddress);
|
||||
|
||||
} 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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,36 +19,24 @@
|
|||
package org.jclouds.virtualbox.functions;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
import static com.google.common.base.Preconditions.checkState;
|
||||
import static org.jclouds.virtualbox.config.VirtualBoxConstants.VIRTUALBOX_GUEST_CREDENTIAL;
|
||||
import static org.jclouds.virtualbox.config.VirtualBoxConstants.VIRTUALBOX_GUEST_IDENTITY;
|
||||
|
||||
import java.util.List;
|
||||
import static org.jclouds.virtualbox.config.VirtualBoxConstants.GUEST_OS_PASSWORD;
|
||||
import static org.jclouds.virtualbox.config.VirtualBoxConstants.GUEST_OS_USER;
|
||||
|
||||
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.options.RunScriptOptions;
|
||||
import org.jclouds.compute.reference.ComputeServiceConstants;
|
||||
import org.jclouds.domain.LoginCredentials;
|
||||
import org.jclouds.logging.Logger;
|
||||
import org.jclouds.ssh.SshClient;
|
||||
import org.jclouds.virtualbox.VirtualBoxApiMetadata;
|
||||
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.jclouds.virtualbox.util.NetworkUtils;
|
||||
import org.virtualbox_4_1.IMachine;
|
||||
import org.virtualbox_4_1.INetworkAdapter;
|
||||
import org.virtualbox_4_1.NetworkAttachmentType;
|
||||
|
||||
import com.google.common.base.Function;
|
||||
import com.google.common.base.Splitter;
|
||||
import com.google.common.base.Supplier;
|
||||
import com.google.common.collect.Iterables;
|
||||
import com.google.common.net.HostAndPort;
|
||||
import com.google.inject.Inject;
|
||||
|
@ -61,36 +49,30 @@ public class IMachineToSshClient implements Function<IMachine, SshClient> {
|
|||
protected Logger logger = Logger.NULL;
|
||||
|
||||
private final SshClient.Factory sshClientFactory;
|
||||
private final RunScriptOnNode.Factory scriptRunnerFactory;
|
||||
private final Supplier<NodeMetadata> hostSupplier;
|
||||
private final MachineUtils machineUtils;
|
||||
private final NetworkUtils networkUtils;
|
||||
|
||||
@Inject
|
||||
public IMachineToSshClient(SshClient.Factory sshClientFactory,
|
||||
RunScriptOnNode.Factory scriptRunnerFactory,
|
||||
Supplier<NodeMetadata> hostSupplier, MachineUtils machineUtils) {
|
||||
NetworkUtils networkUtils) {
|
||||
this.sshClientFactory = sshClientFactory;
|
||||
this.scriptRunnerFactory = scriptRunnerFactory;
|
||||
this.hostSupplier = hostSupplier;
|
||||
this.machineUtils = machineUtils;
|
||||
this.networkUtils = networkUtils;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SshClient apply(final IMachine vm) {
|
||||
INetworkAdapter networkAdapter = vm.getNetworkAdapter(0L);
|
||||
public SshClient apply(final IMachine vm) {
|
||||
INetworkAdapter networkAdapter = vm.getNetworkAdapter(0L);
|
||||
|
||||
SshClient client = null;
|
||||
checkNotNull(networkAdapter);
|
||||
SshClient client = null;
|
||||
checkNotNull(networkAdapter);
|
||||
|
||||
String clientIpAddress = null;
|
||||
String sshPort = "22";
|
||||
String clientIpAddress = null;
|
||||
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);
|
||||
String guestCredential = VirtualBoxApiMetadata.defaultProperties().getProperty(VIRTUALBOX_GUEST_CREDENTIAL);
|
||||
LoginCredentials loginCredentials = LoginCredentials.builder()
|
||||
.user(guestIdentity)
|
||||
.password(guestCredential).authenticateSudo(true)
|
||||
.build();
|
||||
LoginCredentials loginCredentials = LoginCredentials.builder()
|
||||
.user(guestIdentity).password(guestCredential)
|
||||
.authenticateSudo(true).build();
|
||||
|
||||
if (networkAdapter.getAttachmentType()
|
||||
.equals(NetworkAttachmentType.NAT)) {
|
||||
|
@ -109,11 +91,10 @@ public class IMachineToSshClient implements Function<IMachine, SshClient> {
|
|||
}
|
||||
} else if (networkAdapter.getAttachmentType().equals(
|
||||
NetworkAttachmentType.Bridged)) {
|
||||
String network = "1.1.1.1";
|
||||
clientIpAddress = getIpAddressFromBridgedNIC(networkAdapter, network);
|
||||
clientIpAddress = networkUtils.getIpAddressFromNicSlot(vm.getName(), networkAdapter.getSlot());
|
||||
} else if (networkAdapter.getAttachmentType().equals(
|
||||
NetworkAttachmentType.HostOnly)) {
|
||||
clientIpAddress = machineUtils.getIpAddressFromFirstNIC(vm.getName());
|
||||
clientIpAddress = networkUtils.getIpAddressFromNicSlot(vm.getName(), networkAdapter.getSlot());
|
||||
}
|
||||
|
||||
checkNotNull(clientIpAddress, "clientIpAddress");
|
||||
|
@ -124,28 +105,4 @@ public class IMachineToSshClient implements Function<IMachine, SshClient> {
|
|||
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.concurrent.ExecutionException;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.inject.Inject;
|
||||
|
@ -31,30 +32,33 @@ import javax.inject.Singleton;
|
|||
|
||||
import org.jclouds.compute.reference.ComputeServiceConstants;
|
||||
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 com.google.common.base.Strings;
|
||||
import com.google.common.base.Supplier;
|
||||
import com.google.common.cache.AbstractLoadingCache;
|
||||
import com.google.common.cache.LoadingCache;
|
||||
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
|
||||
* previously extracted this returns it, if not it calls vbox api.
|
||||
*
|
||||
* @author andrea turli
|
||||
* @author Andrea Turli
|
||||
*
|
||||
*/
|
||||
@Singleton
|
||||
public class IpAddressesLoadingCache extends
|
||||
AbstractLoadingCache<String, String> {
|
||||
AbstractLoadingCache<MachineNameOrIdAndNicSlot, String> {
|
||||
|
||||
@Resource
|
||||
@Named(ComputeServiceConstants.COMPUTE_LOGGER)
|
||||
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;
|
||||
|
||||
@Inject
|
||||
|
@ -63,27 +67,23 @@ public class IpAddressesLoadingCache extends
|
|||
}
|
||||
|
||||
@Override
|
||||
public synchronized String get(String idOrName) throws ExecutionException {
|
||||
if (masters.containsKey(idOrName)) {
|
||||
return masters.get(idOrName);
|
||||
public synchronized String get(MachineNameOrIdAndNicSlot machineNameOrIdAndNicPort) throws ExecutionException {
|
||||
if (masters.containsKey(machineNameOrIdAndNicPort)) {
|
||||
return masters.get(machineNameOrIdAndNicPort);
|
||||
}
|
||||
|
||||
String currentIp = "", previousIp = "";
|
||||
int count = 0;
|
||||
while (count < 3) {
|
||||
currentIp = "";
|
||||
while (!MachineUtils.isIpv4(currentIp)) {
|
||||
currentIp = manager.get().getVBox().findMachine(idOrName)
|
||||
.getGuestPropertyValue("/VirtualBox/GuestInfo/Net/0/V4/IP");
|
||||
String query = String.format("/VirtualBox/GuestInfo/Net/%s/V4/IP", machineNameOrIdAndNicPort.getSlotText());
|
||||
String currentIp = "";
|
||||
while (!NetworkUtils.isIpv4(currentIp)) {
|
||||
currentIp = manager.get().getVBox().findMachine(machineNameOrIdAndNicPort.getMachineNameOrId())
|
||||
.getGuestPropertyValue(query);
|
||||
if(!Strings.nullToEmpty(currentIp).isEmpty())
|
||||
logger.debug("Found IP address %s for '%s' at slot %s", currentIp,
|
||||
machineNameOrIdAndNicPort.getMachineNameOrId(),
|
||||
machineNameOrIdAndNicPort.getSlotText());
|
||||
Uninterruptibles.sleepUninterruptibly(1, TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
if (previousIp.equals(currentIp)) {
|
||||
count++;
|
||||
}
|
||||
previousIp = currentIp;
|
||||
}
|
||||
|
||||
masters.put(idOrName, currentIp);
|
||||
masters.put(machineNameOrIdAndNicPort, currentIp);
|
||||
return currentIp;
|
||||
}
|
||||
|
||||
|
@ -92,4 +92,9 @@ public class IpAddressesLoadingCache extends
|
|||
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
|
||||
.launchVMProcess(session, type.stringValue(), environment);
|
||||
progress.waitForCompletion(-1);
|
||||
try {
|
||||
Thread.sleep(3000l);
|
||||
} catch (InterruptedException e) {
|
||||
propagate(e);
|
||||
}
|
||||
} catch (VBoxException e) {
|
||||
ErrorCode errorCode = ErrorCode.valueOf(e);
|
||||
switch (errorCode) {
|
||||
|
|
|
@ -50,6 +50,7 @@ import org.jclouds.compute.domain.ExecResponse;
|
|||
import org.jclouds.compute.domain.Image;
|
||||
import org.jclouds.compute.domain.NodeMetadata;
|
||||
import org.jclouds.compute.reference.ComputeServiceConstants;
|
||||
import org.jclouds.domain.LoginCredentials;
|
||||
import org.jclouds.location.Provider;
|
||||
import org.jclouds.logging.Logger;
|
||||
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.functions.admin.PreseedCfgServer;
|
||||
import org.jclouds.virtualbox.predicates.RetryIfSocketNotYetOpen;
|
||||
import org.jclouds.virtualbox.util.NetworkUtils;
|
||||
import org.testng.collections.Lists;
|
||||
import org.virtualbox_4_1.CleanupMode;
|
||||
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.VirtualBoxManager;
|
||||
|
||||
import com.google.common.base.CaseFormat;
|
||||
import com.google.common.base.Function;
|
||||
import com.google.common.base.Splitter;
|
||||
import com.google.common.base.Supplier;
|
||||
|
@ -98,9 +101,6 @@ import com.google.common.net.HostAndPort;
|
|||
@Singleton
|
||||
public class MastersLoadingCache extends AbstractLoadingCache<Image, Master> {
|
||||
|
||||
// TODO parameterize
|
||||
public static final int MASTER_PORT = 2222;
|
||||
|
||||
@Resource
|
||||
@Named(ComputeServiceConstants.COMPUTE_LOGGER)
|
||||
protected Logger logger = Logger.NULL;
|
||||
|
@ -197,18 +197,17 @@ public class MastersLoadingCache extends AbstractLoadingCache<Image, Master> {
|
|||
server.start(preconfigurationUrl, currentImage.preseed_cfg);
|
||||
}
|
||||
} catch (URISyntaxException e1) {
|
||||
logger.error("Cannot start the preseed server", e);
|
||||
throw e;
|
||||
}
|
||||
|
||||
MasterSpec masterSpec = buildMasterSpecFromYaml(currentImage,
|
||||
vmName);
|
||||
|
||||
// create the master machine if it can't be found
|
||||
masterMachine = masterCreatorAndInstaller.apply(masterSpec);
|
||||
// build the master
|
||||
master = Master.builder().machine(masterMachine)
|
||||
.spec(masterSpec).build();
|
||||
} else {
|
||||
logger.error("Problem during master creation", e);
|
||||
throw e;
|
||||
}
|
||||
} finally {
|
||||
|
@ -241,15 +240,16 @@ public class MastersLoadingCache extends AbstractLoadingCache<Image, Master> {
|
|||
.attachISO(0, 0, localIsoUrl).attachHardDisk(hardDisk)
|
||||
.attachISO(1, 0, guestAdditionsIso).build();
|
||||
|
||||
VmSpec vmSpecification = VmSpec.builder().id(currentImage.id)
|
||||
.name(vmName).memoryMB(512).osTypeId("")
|
||||
VmSpec vmSpecification = VmSpec.builder().id(currentImage.id)
|
||||
.name(vmName).memoryMB(512).osTypeId(getOsTypeId(currentImage.os_family, currentImage.os_64bit))
|
||||
.controller(ideController).forceOverwrite(true)
|
||||
.guestUser(currentImage.username).guestPassword(currentImage.credential)
|
||||
.cleanUpMode(CleanupMode.Full).build();
|
||||
|
||||
NetworkAdapter networkAdapter = NetworkAdapter
|
||||
.builder()
|
||||
.networkAttachmentType(NetworkAttachmentType.NAT)
|
||||
.tcpRedirectRule(providerSupplier.get().getHost(), MASTER_PORT,
|
||||
.tcpRedirectRule(providerSupplier.get().getHost(), NetworkUtils.MASTER_PORT,
|
||||
"", 22).build();
|
||||
|
||||
NetworkInterfaceCard networkInterfaceCard = NetworkInterfaceCard
|
||||
|
@ -267,10 +267,12 @@ public class MastersLoadingCache extends AbstractLoadingCache<Image, Master> {
|
|||
.installationScript(
|
||||
installationKeySequence.replace("HOSTNAME",
|
||||
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) {
|
||||
checkArgument(key instanceof Image,
|
||||
"this cache is for entries who's keys are Images");
|
||||
|
@ -315,4 +317,8 @@ public class MastersLoadingCache extends AbstractLoadingCache<Image, Master> {
|
|||
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.checkState;
|
||||
import static org.jclouds.compute.options.RunScriptOptions.Builder.runAsRoot;
|
||||
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.GUEST_OS_PASSWORD;
|
||||
import static org.jclouds.virtualbox.config.VirtualBoxConstants.GUEST_OS_USER;
|
||||
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_NODE_NAME_SEPARATOR;
|
||||
import static org.jclouds.virtualbox.config.VirtualBoxConstants.VIRTUALBOX_NODE_PREFIX;
|
||||
|
||||
import java.net.URI;
|
||||
import java.util.List;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Named;
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import org.jclouds.compute.ComputeServiceAdapter.NodeAndInitialCredentials;
|
||||
import org.jclouds.compute.callables.RunScriptOnNode;
|
||||
import org.jclouds.compute.callables.RunScriptOnNode.Factory;
|
||||
import org.jclouds.compute.domain.ExecResponse;
|
||||
import org.jclouds.compute.domain.NodeMetadata;
|
||||
import org.jclouds.compute.domain.NodeMetadataBuilder;
|
||||
import org.jclouds.compute.options.RunScriptOptions;
|
||||
import org.jclouds.compute.reference.ComputeServiceConstants;
|
||||
import org.jclouds.domain.LoginCredentials;
|
||||
import org.jclouds.javax.annotation.Nullable;
|
||||
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.logging.Logger;
|
||||
import org.jclouds.virtualbox.config.VirtualBoxComputeServiceContextModule;
|
||||
import org.jclouds.virtualbox.domain.CloneSpec;
|
||||
import org.jclouds.virtualbox.domain.Master;
|
||||
import org.jclouds.virtualbox.domain.NetworkAdapter;
|
||||
import org.jclouds.virtualbox.domain.NetworkInterfaceCard;
|
||||
import org.jclouds.virtualbox.domain.NetworkSpec;
|
||||
import org.jclouds.virtualbox.domain.NodeSpec;
|
||||
import org.jclouds.virtualbox.domain.VmSpec;
|
||||
import org.jclouds.virtualbox.statements.DeleteGShadowLock;
|
||||
import org.jclouds.virtualbox.statements.EnableNetworkInterface;
|
||||
import org.jclouds.virtualbox.util.MachineController;
|
||||
import org.jclouds.virtualbox.util.MachineUtils;
|
||||
import org.jclouds.virtualbox.util.NetworkUtils;
|
||||
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.IProgress;
|
||||
import org.virtualbox_4_1.ISession;
|
||||
import org.virtualbox_4_1.LockType;
|
||||
import org.virtualbox_4_1.NetworkAttachmentType;
|
||||
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.Predicate;
|
||||
import com.google.common.base.Supplier;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.collect.Iterables;
|
||||
|
||||
|
@ -88,66 +77,64 @@ import com.google.common.collect.Iterables;
|
|||
@Singleton
|
||||
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 Function<CloneSpec, IMachine> cloner;
|
||||
private final MachineUtils machineUtils;
|
||||
private final MachineController machineController;
|
||||
private final Factory runScriptOnNodeFactory;
|
||||
private final Supplier<NodeMetadata> host;
|
||||
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);
|
||||
private final NetworkUtils networkUtils;
|
||||
private final int ram;
|
||||
|
||||
|
||||
@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,
|
||||
Supplier<NodeMetadata> host,
|
||||
@Provider Supplier<URI> providerSupplier,
|
||||
@Nullable @Identity String identity,
|
||||
@Nullable @Credential String credential) {
|
||||
NetworkUtils networkUtils,
|
||||
@Named(VIRTUALBOX_GUEST_MEMORY) String ram) {
|
||||
this.manager = manager;
|
||||
this.cloner = cloner;
|
||||
this.runScriptOnNodeFactory = checkNotNull(runScriptOnNodeFactory, "runScriptOnNodeFactory");
|
||||
this.networkUtils = networkUtils;
|
||||
this.machineUtils = machineUtils;
|
||||
this.machineController = machineController;
|
||||
this.host = checkNotNull(host, "host");
|
||||
this.providerSupplier = checkNotNull(providerSupplier,
|
||||
"endpoint to virtualbox websrvd is needed");
|
||||
this.username = identity;
|
||||
this.password = credential;
|
||||
this.ram = Integer.valueOf(ram);
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized NodeAndInitialCredentials<IMachine> apply(NodeSpec nodeSpec) {
|
||||
checkNotNull(nodeSpec, "NodeSpec");
|
||||
Master master = checkNotNull(nodeSpec.getMaster(), "Master");
|
||||
|
||||
if (master.getMachine().getCurrentSnapshot() != null) {
|
||||
ISession session;
|
||||
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) {
|
||||
throw new RuntimeException("error opening vbox machine session: " + e.getMessage(), e);
|
||||
}
|
||||
IProgress progress = session.getConsole().deleteSnapshot(master.getMachine().getCurrentSnapshot().getId());
|
||||
progress.waitForCompletion(-1);
|
||||
session.unlockMachine();
|
||||
logger.debug("Deleted an existing snapshot from %s", master.getMachine().getName());
|
||||
}
|
||||
String masterNameWithoutPrefix = master.getMachine().getName().replace(VIRTUALBOX_IMAGE_PREFIX, "");
|
||||
String cloneName = VIRTUALBOX_NODE_PREFIX + masterNameWithoutPrefix + VIRTUALBOX_NODE_NAME_SEPARATOR
|
||||
+ nodeSpec.getTag() + VIRTUALBOX_NODE_NAME_SEPARATOR + nodeSpec.getName();
|
||||
if (nodeSpec.getTemplate() != null && nodeSpec.getTemplate().getHardware() != null
|
||||
&& nodeSpec.getTemplate().getHardware().getRam() > 0) {
|
||||
ram = nodeSpec.getTemplate().getHardware().getRam();
|
||||
}
|
||||
|
||||
IMachine masterMachine = master.getMachine();
|
||||
String username = masterMachine.getExtraData(GUEST_OS_USER);
|
||||
String password = masterMachine.getExtraData(GUEST_OS_PASSWORD);
|
||||
|
||||
VmSpec cloneVmSpec = VmSpec.builder().id(cloneName).name(cloneName).memoryMB(ram)
|
||||
.guestUser(username).guestPassword(password)
|
||||
.cleanUpMode(CleanupMode.Full)
|
||||
.forceOverwrite(true).build();
|
||||
.forceOverwrite(true).build();
|
||||
|
||||
// case 'vbox host is localhost': NAT + HOST-ONLY
|
||||
NetworkSpec networkSpec = createNetworkSpecWhenVboxIsLocalhost();
|
||||
NetworkSpec networkSpec = networkUtils.createNetworkSpecWhenVboxIsLocalhost();
|
||||
Optional<NetworkInterfaceCard> optionalNatIfaceCard = Iterables.tryFind(
|
||||
networkSpec.getNetworkInterfaceCards(),
|
||||
new Predicate<NetworkInterfaceCard>() {
|
||||
|
@ -161,6 +148,7 @@ public class NodeCreator implements Function<NodeSpec, NodeAndInitialCredentials
|
|||
CloneSpec cloneSpec = CloneSpec.builder().linked(true).master(master.getMachine()).network(networkSpec)
|
||||
.vm(cloneVmSpec).build();
|
||||
|
||||
logger.debug("Cloning a new guest an existing snapshot from %s ...", master.getMachine().getName());
|
||||
IMachine cloned = cloner.apply(cloneSpec);
|
||||
machineController.ensureMachineIsLaunched(cloneVmSpec.getVmName());
|
||||
|
||||
|
@ -172,139 +160,37 @@ public class NodeCreator implements Function<NodeSpec, NodeAndInitialCredentials
|
|||
machineUtils.runScriptOnNode(partialNodeMetadata, new DeleteGShadowLock(), RunScriptOptions.NONE);
|
||||
|
||||
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,
|
||||
cloneName, LoginCredentials.builder()
|
||||
.user(guestIdentity)
|
||||
.password(guestCredential)
|
||||
.authenticateSudo(true)
|
||||
.build());
|
||||
cloneName, credentials);
|
||||
}
|
||||
|
||||
private NodeMetadata buildPartialNodeMetadata(IMachine clone) {
|
||||
NodeMetadataBuilder nodeMetadataBuilder = new NodeMetadataBuilder();
|
||||
nodeMetadataBuilder.id(clone.getName());
|
||||
nodeMetadataBuilder.status(VirtualBoxComputeServiceContextModule.toPortableNodeStatus.get(clone.getState()));
|
||||
nodeMetadataBuilder.publicAddresses(ImmutableSet.of(machineUtils.getIpAddressFromFirstNIC(clone.getName())));
|
||||
LoginCredentials loginCredentials = new LoginCredentials(guestIdentity, guestCredential, null, true);
|
||||
long slot = findSlotForNetworkAttachment(clone, NetworkAttachmentType.HostOnly);
|
||||
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);
|
||||
return nodeMetadataBuilder.build();
|
||||
}
|
||||
|
||||
private 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);
|
||||
}
|
||||
|
||||
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();
|
||||
private long findSlotForNetworkAttachment(IMachine clone, NetworkAttachmentType networkAttachmentType) {
|
||||
long slot = -1, i = 0;
|
||||
while (slot == -1 && i < 4) {
|
||||
if(clone.getNetworkAdapter(i).getAttachmentType().equals(networkAttachmentType))
|
||||
slot = i;
|
||||
i++;
|
||||
}
|
||||
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;
|
||||
|
||||
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.Lists.partition;
|
||||
import static org.jclouds.compute.reference.ComputeServiceConstants.COMPUTE_LOGGER;
|
||||
import static org.jclouds.virtualbox.settings.KeyboardScancodes.SPECIAL_KEYBOARD_BUTTON_MAP_LIST;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.inject.Named;
|
||||
|
@ -34,6 +34,7 @@ import org.jclouds.logging.Logger;
|
|||
import org.virtualbox_4_1.ISession;
|
||||
|
||||
import com.google.common.base.Function;
|
||||
import com.google.common.util.concurrent.Uninterruptibles;
|
||||
|
||||
class SendScancodes implements Function<ISession, Void> {
|
||||
|
||||
|
@ -56,9 +57,9 @@ class SendScancodes implements Function<ISession, Void> {
|
|||
logger.debug("List of scancodes sent: ", maxOrLess);
|
||||
assert (codesSent == maxOrLess.size());
|
||||
if (any(maxOrLess, in(SPECIAL_KEYBOARD_BUTTON_MAP_LIST.values()))) {
|
||||
sleepOrPropagateInterrupt(300);
|
||||
Uninterruptibles.sleepUninterruptibly(300, TimeUnit.MILLISECONDS);
|
||||
} else {
|
||||
sleepOrPropagateInterrupt(50);
|
||||
Uninterruptibles.sleepUninterruptibly(50, TimeUnit.MILLISECONDS);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
|
@ -68,12 +69,4 @@ class SendScancodes implements Function<ISession, Void> {
|
|||
public String toString() {
|
||||
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;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.jclouds.logging.Logger;
|
||||
import org.virtualbox_4_1.IMachine;
|
||||
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.Supplier;
|
||||
import com.google.common.base.Throwables;
|
||||
import com.google.common.util.concurrent.Uninterruptibles;
|
||||
|
||||
/**
|
||||
* @author Andrea Turli
|
||||
|
@ -93,7 +96,7 @@ public class TakeSnapshotIfNotAlreadyAttached implements Function<IMachine, ISna
|
|||
snapshotName, snapshotDesc, machine.getName());
|
||||
throw Throwables.propagate(e);
|
||||
}
|
||||
Thread.sleep(1000L);
|
||||
Uninterruptibles.sleepUninterruptibly(1, TimeUnit.SECONDS);
|
||||
continue;
|
||||
}
|
||||
logger.error(e, "Problem creating snapshot %s (description: %s) from machine %s", snapshotName,
|
||||
|
|
|
@ -85,21 +85,7 @@ public class StartVBoxIfNotAlreadyRunning implements Supplier<VirtualBoxManager>
|
|||
public synchronized void start() {
|
||||
URI provider = providerSupplier.get();
|
||||
NodeMetadata hostNodeMetadata = hardcodedHostToHostNodeMetadata.apply(host.get());
|
||||
// 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");
|
||||
}
|
||||
cleanUpHost(provider, hostNodeMetadata);
|
||||
|
||||
logger.debug("disabling password access");
|
||||
runScriptOnNodeFactory
|
||||
|
@ -132,6 +118,24 @@ public class StartVBoxIfNotAlreadyRunning implements Supplier<VirtualBoxManager>
|
|||
+ 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
|
||||
public VirtualBoxManager get() {
|
||||
checkState(manager != null, "start not called");
|
||||
|
|
|
@ -89,7 +89,7 @@ public class UnregisterMachineIfExistsAndForceDeleteItsMedia implements Function
|
|||
if (!filteredMediaToBeDeleted.isEmpty()) {
|
||||
try {
|
||||
IProgress deletion = machine.delete(filteredMediaToBeDeleted);
|
||||
deletion.waitForCompletion(-1);
|
||||
deletion.waitForCompletion(100);
|
||||
} catch (Exception e) {
|
||||
logger.error(e, "Problem in deleting the media attached to %s", machine.getName());
|
||||
Throwables.propagate(e);
|
||||
|
|
|
@ -87,12 +87,7 @@ public class InstallGuestAdditions implements Statement {
|
|||
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("%s%s", mountPoint, "/VBoxLinuxAdditions.run"))); //
|
||||
statements.add(exec("service vboxadd setup")); //
|
||||
statements.add(exec("VBoxService")); //
|
||||
statements.add(exec(String.format("echo VBoxService > /etc/rc.local"))); //
|
||||
statements.add(exec(String.format("echo exit 0 >> /etc/rc.local"))); //
|
||||
statements.add(exec(String.format("umount %s", mountPoint)));
|
||||
statements.add(exec(String.format("%s%s", mountPoint, "/VBoxLinuxAdditions.run --nox11"))); //
|
||||
return statements;
|
||||
}
|
||||
|
||||
|
|
|
@ -20,6 +20,9 @@ package org.jclouds.virtualbox.util;
|
|||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.inject.Named;
|
||||
import javax.inject.Singleton;
|
||||
|
@ -28,15 +31,25 @@ import org.jclouds.compute.reference.ComputeServiceConstants;
|
|||
import org.jclouds.logging.Logger;
|
||||
import org.jclouds.virtualbox.domain.ExecutionType;
|
||||
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.ISession;
|
||||
import org.virtualbox_4_1.LockType;
|
||||
import org.virtualbox_4_1.MachineState;
|
||||
import org.virtualbox_4_1.SessionState;
|
||||
import org.virtualbox_4_1.VirtualBoxManager;
|
||||
|
||||
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.Throwables;
|
||||
import com.google.common.collect.Iterables;
|
||||
import com.google.common.util.concurrent.Uninterruptibles;
|
||||
import com.google.inject.Inject;
|
||||
|
||||
/**
|
||||
|
@ -65,27 +78,57 @@ public class MachineController {
|
|||
|
||||
public ISession ensureMachineIsLaunched(String vmName) {
|
||||
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 {
|
||||
session = machineUtils.applyForMachine(vmName, new LaunchMachineIfNotAlreadyRunning(manager.get(),
|
||||
executionType, ""));
|
||||
session = machineUtils.applyForMachine(vmName,
|
||||
new LaunchMachineIfNotAlreadyRunning(manager.get(),
|
||||
executionType, ""));
|
||||
} catch (RuntimeException e) {
|
||||
if (e.getMessage().contains(
|
||||
"org.virtualbox_4_1.VBoxException: VirtualBox error: The given session is busy (0x80BB0007)")) {
|
||||
if (e.getMessage()
|
||||
.contains(
|
||||
"org.virtualbox_4_1.VBoxException: VirtualBox error: The given session is busy (0x80BB0007)")) {
|
||||
throw e;
|
||||
} else if (e.getMessage().contains("VirtualBox error: The object is not ready")) {
|
||||
} else if (e.getMessage().contains(
|
||||
"VirtualBox error: The object is not ready")) {
|
||||
continue;
|
||||
} else {
|
||||
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");
|
||||
}
|
||||
|
||||
public ISession ensureMachineHasPowerDown(String vmName) {
|
||||
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 {
|
||||
session = machineUtils.lockSessionOnMachineAndApply(vmName, LockType.Shared,
|
||||
new Function<ISession, ISession>() {
|
||||
|
@ -97,9 +140,6 @@ public class MachineController {
|
|||
}
|
||||
});
|
||||
} catch (RuntimeException e) {
|
||||
// sometimes the machine might be powered of between the while
|
||||
// test and the call to
|
||||
// lockSessionOnMachineAndApply
|
||||
if (e.getMessage().contains("Invalid machine state: PoweredOff")) {
|
||||
throw e;
|
||||
} else if (e.getMessage().contains("VirtualBox error: The object is not ready")) {
|
||||
|
@ -109,6 +149,7 @@ public class MachineController {
|
|||
}
|
||||
}
|
||||
}
|
||||
safeCheckMachineIsUnlocked(machine);
|
||||
return checkNotNull(session, "session");
|
||||
}
|
||||
|
||||
|
@ -117,6 +158,7 @@ public class MachineController {
|
|||
* http://askubuntu.com/questions/82015/shutting-down-ubuntu-server-running-in-headless-virtualbox
|
||||
*/
|
||||
public ISession ensureMachineIsShutdown(String vmName) {
|
||||
IMachine machine = manager.get().getVBox().findMachine(vmName);
|
||||
ISession session = machineUtils.lockSessionOnMachineAndApply(vmName, LockType.Shared,
|
||||
new Function<ISession, ISession>() {
|
||||
@Override
|
||||
|
@ -125,19 +167,12 @@ public class MachineController {
|
|||
return session;
|
||||
}
|
||||
});
|
||||
int count = 0;
|
||||
while (!manager.get().getVBox().findMachine(vmName).getState().equals(MachineState.PoweredOff) && count < 10) {
|
||||
try {
|
||||
Thread.sleep(500l * count);
|
||||
} catch (InterruptedException e) {
|
||||
Throwables.propagate(e);
|
||||
}
|
||||
count++;
|
||||
}
|
||||
safeCheckMachineIsUnlocked(machine);
|
||||
return checkNotNull(session, "session");
|
||||
}
|
||||
|
||||
public void ensureMachineIsPaused(String vmName) {
|
||||
IMachine machine = manager.get().getVBox().findMachine(vmName);
|
||||
while (!manager.get().getVBox().findMachine(vmName).getState().equals(MachineState.Paused)) {
|
||||
try {
|
||||
machineUtils.lockSessionOnMachineAndApply(vmName, LockType.Shared, new Function<ISession, Void>() {
|
||||
|
@ -160,9 +195,11 @@ public class MachineController {
|
|||
}
|
||||
}
|
||||
}
|
||||
safeCheckMachineIsUnlocked(machine);
|
||||
}
|
||||
|
||||
public void ensureMachineIsResumed(String vmName) {
|
||||
IMachine machine = manager.get().getVBox().findMachine(vmName);
|
||||
while (!manager.get().getVBox().findMachine(vmName).getState().equals(MachineState.Running)) {
|
||||
try {
|
||||
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.checkState;
|
||||
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
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.Supplier;
|
||||
import com.google.common.base.Throwables;
|
||||
import com.google.common.util.concurrent.ListenableFuture;
|
||||
import com.google.common.util.concurrent.Uninterruptibles;
|
||||
import com.google.inject.Inject;
|
||||
|
||||
/**
|
||||
|
@ -61,6 +59,8 @@ import com.google.inject.Inject;
|
|||
@Singleton
|
||||
public class MachineUtils {
|
||||
|
||||
|
||||
|
||||
public final String IP_V4_ADDRESS_PATTERN = "^([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\."
|
||||
+ "([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\." + "([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\."
|
||||
+ "([01]?\\d\\d?|2[0-4]\\d|25[0-5])$";
|
||||
|
@ -71,14 +71,13 @@ public class MachineUtils {
|
|||
|
||||
private final Supplier<VirtualBoxManager> manager;
|
||||
private final Factory scriptRunner;
|
||||
private final IpAddressesLoadingCache ipAddressesLoadingCache;
|
||||
|
||||
|
||||
@Inject
|
||||
public MachineUtils(Supplier<VirtualBoxManager> manager, RunScriptOnNode.Factory scriptRunner,
|
||||
IpAddressesLoadingCache ipAddressesLoadingCache) {
|
||||
this.manager = manager;
|
||||
this.scriptRunner = scriptRunner;
|
||||
this.ipAddressesLoadingCache = ipAddressesLoadingCache;
|
||||
}
|
||||
|
||||
public ListenableFuture<ExecResponse> runScriptOnNode(NodeMetadata metadata, Statement statement,
|
||||
|
@ -183,7 +182,7 @@ public class MachineUtils {
|
|||
* <p/>
|
||||
* 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.
|
||||
*
|
||||
* @param type
|
||||
|
@ -196,30 +195,27 @@ public class MachineUtils {
|
|||
*/
|
||||
protected <T> T lockSessionOnMachineAndApply(String machineId, LockType type, Function<ISession, T> function) {
|
||||
int retries = 15;
|
||||
ISession session = lockSession(machineId, type, retries);
|
||||
ISession session = checkNotNull(lockSession(machineId, type, retries), "session");
|
||||
try {
|
||||
return function.apply(session);
|
||||
} catch (VBoxException e) {
|
||||
throw new RuntimeException(String.format("error applying %s to %s with %s lock: %s", function, machineId,
|
||||
type, e.getMessage()), e);
|
||||
} finally {
|
||||
if (session != null && session.getState().equals(SessionState.Locked))
|
||||
session.unlockMachine();
|
||||
if (session.getState().equals(SessionState.Locked)) {
|
||||
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) {
|
||||
int count = 0;
|
||||
ISession session;
|
||||
IMachine immutableMachine = manager.get().getVBox().findMachine(machineId);
|
||||
|
||||
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());
|
||||
}
|
||||
ISession session = null;
|
||||
|
||||
while (true) {
|
||||
try {
|
||||
|
@ -237,10 +233,7 @@ public class MachineUtils {
|
|||
throw new RuntimeException(String.format("error locking %s with %s lock: %s", machineId, type,
|
||||
e.getMessage()), e);
|
||||
}
|
||||
try {
|
||||
Thread.sleep(count * 1000L);
|
||||
} catch (InterruptedException e1) {
|
||||
}
|
||||
Uninterruptibles.sleepUninterruptibly(1, TimeUnit.SECONDS);
|
||||
}
|
||||
}
|
||||
checkState(session.getState().equals(SessionState.Locked));
|
||||
|
@ -278,24 +271,4 @@ public class MachineUtils {
|
|||
|| 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:
|
||||
- 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
|
||||
name: ubuntu-11.04-server-i386
|
||||
description: ubuntu 11.04 server (i386)
|
||||
|
@ -27,7 +162,7 @@ images:
|
|||
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 kbd-chooser/method select American English
|
||||
d-i netcfg/wireless_wep string
|
||||
d-i base-installer/kernel/override-image string linux-server
|
||||
# Choices: Dialog, Readline, Gnome, Kde, Editor, Noninteractive
|
||||
|
@ -142,8 +277,9 @@ images:
|
|||
os_version: 12.04.1
|
||||
os_64bit: true
|
||||
iso: http://releases.ubuntu.com/12.04/ubuntu-12.04.1-server-amd64.iso
|
||||
iso_md5: a8c667e871f48f3a662f3fbf1c3ddb17
|
||||
username: toor
|
||||
credential: $user
|
||||
credential: password
|
||||
keystroke_sequence: |
|
||||
<Esc><Esc><Enter>
|
||||
/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.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import javax.inject.Inject;
|
||||
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.util.MachineController;
|
||||
import org.jclouds.virtualbox.util.MachineUtils;
|
||||
import org.jclouds.virtualbox.util.NetworkUtils;
|
||||
import org.testng.annotations.AfterClass;
|
||||
import org.testng.annotations.AfterSuite;
|
||||
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.collect.ImmutableSet;
|
||||
import com.google.common.collect.Iterables;
|
||||
import com.google.common.util.concurrent.Uninterruptibles;
|
||||
import com.google.inject.Injector;
|
||||
import com.google.inject.Key;
|
||||
import com.google.inject.Module;
|
||||
|
@ -104,6 +107,9 @@ public class BaseVirtualBoxClientLiveTest extends BaseComputeServiceContextLiveT
|
|||
@Inject
|
||||
protected MachineUtils machineUtils;
|
||||
|
||||
@Inject
|
||||
protected NetworkUtils networkUtils;
|
||||
|
||||
protected String hostVersion;
|
||||
protected String operatingSystemIso;
|
||||
protected String guestAdditionsIso;
|
||||
|
@ -155,10 +161,7 @@ public class BaseVirtualBoxClientLiveTest extends BaseComputeServiceContextLiveT
|
|||
int attempts = 0;
|
||||
while (attempts < 10 && !vm.getSessionState().equals(SessionState.Unlocked)) {
|
||||
attempts++;
|
||||
try {
|
||||
Thread.sleep(200l);
|
||||
} catch (InterruptedException e) {
|
||||
}
|
||||
Uninterruptibles.sleepUninterruptibly(200, TimeUnit.MILLISECONDS);
|
||||
}
|
||||
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.logging.Logger;
|
||||
import org.jclouds.logging.slf4j.config.SLF4JLoggingModule;
|
||||
import org.jclouds.scriptbuilder.statements.login.AdminAccess;
|
||||
import org.jclouds.ssh.SshClient;
|
||||
import org.jclouds.sshj.config.SshjSshClientModule;
|
||||
import org.jclouds.virtualbox.BaseVirtualBoxClientLiveTest;
|
||||
|
@ -50,7 +51,7 @@ import com.google.inject.Module;
|
|||
*
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
@Test(groups = "live", singleThreaded = true, testName = "VirtualBoxExperimentLiveTest")
|
||||
@Test(groups = "live", testName = "VirtualBoxExperimentLiveTest")
|
||||
public class VirtualBoxExperimentLiveTest extends BaseVirtualBoxClientLiveTest {
|
||||
|
||||
@Resource
|
||||
|
@ -71,7 +72,7 @@ public class VirtualBoxExperimentLiveTest extends BaseVirtualBoxClientLiveTest {
|
|||
int numNodes = 3;
|
||||
final String clusterName = "test-launch-cluster";
|
||||
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");
|
||||
for (NodeMetadata node : nodes) {
|
||||
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.virtualbox.config.VirtualBoxComputeServiceContextModule;
|
||||
import org.jclouds.virtualbox.util.MachineUtils;
|
||||
import org.jclouds.virtualbox.util.NetworkUtils;
|
||||
import org.testng.annotations.Test;
|
||||
import org.virtualbox_4_1.IMachine;
|
||||
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"));
|
||||
|
||||
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,
|
||||
machineUtils).apply(vm);
|
||||
networkUtils).apply(vm);
|
||||
|
||||
assertEquals(MASTER_NAME, node.getName());
|
||||
assertEquals(1, node.getPrivateAddresses().size());
|
||||
assertEquals(1, node.getPublicAddresses().size());
|
||||
assertEquals("127.0.0.1", Iterables.get(node.getPublicAddresses(), 0));
|
||||
assertEquals(MastersLoadingCache.MASTER_PORT, node.getLoginPort());
|
||||
assertEquals(NetworkUtils.MASTER_PORT, node.getLoginPort());
|
||||
assertEquals("", node.getGroup());
|
||||
}
|
||||
|
||||
|
@ -103,12 +103,12 @@ public class IMachineToNodeMetadataTest {
|
|||
expect(nat.getNatDriver()).andReturn(natEng).anyTimes();
|
||||
expect(natEng.getHostIP()).andReturn("127.0.0.1").once();
|
||||
expect(natEng.getRedirects()).andReturn(ImmutableList.of("0,1,127.0.0.1,3000,,22"));
|
||||
MachineUtils machineUtils = createNiceMock(MachineUtils.class);
|
||||
NetworkUtils networkUtils = createNiceMock(NetworkUtils.class);
|
||||
|
||||
replay(vm, nat, natEng, hostOnly, machineUtils);
|
||||
replay(vm, nat, natEng, hostOnly, networkUtils);
|
||||
|
||||
NodeMetadata node = new IMachineToNodeMetadata(VirtualBoxComputeServiceContextModule.toPortableNodeStatus,
|
||||
machineUtils).apply(vm);
|
||||
networkUtils).apply(vm);
|
||||
|
||||
assertEquals(name, node.getName());
|
||||
assertEquals(group, node.getGroup());
|
||||
|
|
|
@ -41,11 +41,11 @@ import com.google.common.collect.Iterables;
|
|||
public class ImageFromYamlStringTest {
|
||||
|
||||
public static final Image TEST1 = new ImageBuilder()
|
||||
.id("ubuntu-11.04-i386")
|
||||
.name("ubuntu-11.04-server-i386")
|
||||
.description("ubuntu 11.04 server (i386)")
|
||||
.id("ubuntu-10.04.4-server-i386")
|
||||
.name("ubuntu-10.04-server-i386")
|
||||
.description("ubuntu")
|
||||
.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())
|
||||
.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.CreateAndInstallVm;
|
||||
import org.jclouds.virtualbox.functions.IMachineToSshClient;
|
||||
import org.jclouds.virtualbox.functions.IpAddressesLoadingCache;
|
||||
import org.jclouds.virtualbox.util.MachineUtils;
|
||||
import org.jclouds.virtualbox.util.NetworkUtils;
|
||||
import org.testng.annotations.BeforeClass;
|
||||
import org.testng.annotations.Test;
|
||||
import org.virtualbox_4_1.CleanupMode;
|
||||
|
@ -57,7 +56,7 @@ import com.google.inject.Injector;
|
|||
/**
|
||||
* @author Andrea Turli
|
||||
*/
|
||||
@Test(groups = "live", singleThreaded = true, testName = "GuestAdditionsInstallerLiveTest")
|
||||
@Test(groups = "live", singleThreaded = true, testName = "GuestAdditionsInstallerLiveTest", enabled=false)
|
||||
public class GuestAdditionsInstallerLiveTest extends BaseVirtualBoxClientLiveTest {
|
||||
|
||||
private Injector injector;
|
||||
|
@ -65,7 +64,6 @@ public class GuestAdditionsInstallerLiveTest extends BaseVirtualBoxClientLiveTes
|
|||
private Predicate<SshClient> sshResponds;
|
||||
|
||||
private MasterSpec machineSpec;
|
||||
private IpAddressesLoadingCache ipAddressesLoadingCache;
|
||||
|
||||
@Override
|
||||
@BeforeClass(groups = "live")
|
||||
|
@ -117,9 +115,8 @@ public class GuestAdditionsInstallerLiveTest extends BaseVirtualBoxClientLiveTes
|
|||
sshResponds = injector.getInstance(SshResponds.class);
|
||||
checkState(sshResponds.apply(client), "timed out waiting for guest %s to be accessible via ssh",
|
||||
machine.getName());
|
||||
ipAddressesLoadingCache = injector.getInstance(IpAddressesLoadingCache.class);
|
||||
|
||||
assertTrue(MachineUtils.isIpv4(ipAddressesLoadingCache.apply(machine.getName())));
|
||||
assertTrue(NetworkUtils.isIpv4(networkUtils.getIpAddressFromNicSlot(machine.getName(), 0l)));
|
||||
|
||||
} finally {
|
||||
for (String vmNameOrId : ImmutableSet.of(machine.getName())) {
|
||||
|
|
|
@ -45,13 +45,7 @@ public class InstallGuestAdditionsLiveTest extends BaseVirtualBoxClientLiveTest
|
|||
InstallGuestAdditions installer = new InstallGuestAdditions(vmSpecification, "4.1.8");
|
||||
String scripts = installer.render(OsFamily.UNIX);
|
||||
assertEquals("installModuleAssistantIfNeeded || return 1\n" + "mount -t iso9660 /dev/sr1 /mnt\n"
|
||||
+ "/mnt/VBoxLinuxAdditions.run\n"
|
||||
+ "service vboxadd setup\n"
|
||||
+ "VBoxService\n"
|
||||
+ "echo VBoxService > /etc/rc.local\n"
|
||||
+ "echo exit 0 >> /etc/rc.local\n"
|
||||
+ "umount /mnt\n"
|
||||
, scripts);
|
||||
+ "/mnt/VBoxLinuxAdditions.run --nox11\n", scripts);
|
||||
}
|
||||
|
||||
public void testIsoNotPresent() {
|
||||
|
@ -67,12 +61,7 @@ public class InstallGuestAdditionsLiveTest extends BaseVirtualBoxClientLiveTest
|
|||
+ "setupPublicCurl || return 1\n"
|
||||
+ "(mkdir -p /tmp/ && cd /tmp/ && [ ! -f VBoxGuestAdditions_4.1.8.iso ] && curl -q -s -S -L --connect-timeout 10 --max-time 600 --retry 20 -C - -X GET http://download.virtualbox.org/virtualbox/4.1.8/VBoxGuestAdditions_4.1.8.iso >VBoxGuestAdditions_4.1.8.iso)\n"
|
||||
+ "mount -o loop /tmp/VBoxGuestAdditions_4.1.8.iso /mnt\n"
|
||||
+ "/mnt/VBoxLinuxAdditions.run\n"
|
||||
+ "service vboxadd setup\n"
|
||||
+ "VBoxService\n"
|
||||
+ "echo VBoxService > /etc/rc.local\n"
|
||||
+ "echo exit 0 >> /etc/rc.local\n"
|
||||
+ "umount /mnt\n", scripts);
|
||||
+ "/mnt/VBoxLinuxAdditions.run --nox11\n", scripts);
|
||||
}
|
||||
|
||||
}
|
|
@ -18,9 +18,11 @@
|
|||
*/
|
||||
|
||||
package org.jclouds.virtualbox.util;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkState;
|
||||
import static org.jclouds.virtualbox.config.VirtualBoxConstants.VIRTUALBOX_IMAGE_PREFIX;
|
||||
import static org.jclouds.virtualbox.config.VirtualBoxConstants.VIRTUALBOX_INSTALLATION_KEY_SEQUENCE;
|
||||
import static org.testng.AssertJUnit.assertTrue;
|
||||
|
||||
import org.jclouds.config.ValueOfConfigurationKeyOrNull;
|
||||
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.functions.CloneAndRegisterMachineFromIMachineIfNotAlreadyExists;
|
||||
import org.jclouds.virtualbox.functions.CreateAndInstallVm;
|
||||
import org.testng.annotations.AfterClass;
|
||||
import org.testng.annotations.BeforeClass;
|
||||
import org.testng.annotations.Test;
|
||||
import org.virtualbox_4_1.CleanupMode;
|
||||
import org.virtualbox_4_1.IMachine;
|
||||
import org.virtualbox_4_1.ISession;
|
||||
import org.virtualbox_4_1.LockType;
|
||||
import org.virtualbox_4_1.NetworkAttachmentType;
|
||||
import org.virtualbox_4_1.SessionState;
|
||||
import org.virtualbox_4_1.StorageBus;
|
||||
|
||||
import com.google.common.base.CaseFormat;
|
||||
import com.google.common.base.Function;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.inject.Injector;
|
||||
|
||||
@Test(groups = "live", testName = "MachineControllerLiveTest")
|
||||
|
@ -62,62 +61,134 @@ public class MachineUtilsLiveTest extends BaseVirtualBoxClientLiveTest {
|
|||
public void setupContext() {
|
||||
super.setupContext();
|
||||
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
|
||||
.builder()
|
||||
.name("IDE Controller")
|
||||
.bus(StorageBus.IDE)
|
||||
.attachISO(0, 0, operatingSystemIso)
|
||||
.attachHardDisk(
|
||||
HardDisk.builder().diskpath(adminDisk(instanceName)).controllerPort(0).deviceSlot(1)
|
||||
.autoDelete(true).build()).attachISO(1, 1, guestAdditionsIso).build();
|
||||
.builder()
|
||||
.name("IDE Controller")
|
||||
.bus(StorageBus.IDE)
|
||||
.attachISO(0, 0, operatingSystemIso)
|
||||
.attachHardDisk(
|
||||
HardDisk.builder().diskpath(adminDisk(instanceName)).controllerPort(0).deviceSlot(1).autoDelete(true)
|
||||
.build()).attachISO(1, 1, guestAdditionsIso).build();
|
||||
|
||||
VmSpec instanceVmSpec = VmSpec.builder().id(instanceName).name(instanceName).osTypeId("").memoryMB(512)
|
||||
.cleanUpMode(CleanupMode.Full).controller(ideController).forceOverwrite(true).build();
|
||||
.cleanUpMode(CleanupMode.Full).controller(ideController).forceOverwrite(true).build();
|
||||
|
||||
Injector injector = view.utils().injector();
|
||||
Function<String, String> configProperties = injector.getInstance(ValueOfConfigurationKeyOrNull.class);
|
||||
IsoSpec isoSpec = IsoSpec
|
||||
.builder()
|
||||
.sourcePath(operatingSystemIso)
|
||||
.installationScript(
|
||||
configProperties.apply(VIRTUALBOX_INSTALLATION_KEY_SEQUENCE).replace("HOSTNAME",
|
||||
instanceVmSpec.getVmName())).build();
|
||||
.builder()
|
||||
.sourcePath(operatingSystemIso)
|
||||
.installationScript(
|
||||
configProperties.apply(VIRTUALBOX_INSTALLATION_KEY_SEQUENCE).replace("HOSTNAME",
|
||||
instanceVmSpec.getVmName())).build();
|
||||
|
||||
NetworkAdapter networkAdapter = NetworkAdapter.builder().networkAttachmentType(NetworkAttachmentType.NAT)
|
||||
.tcpRedirectRule("127.0.0.1", 2222, "", 22).build();
|
||||
.tcpRedirectRule("127.0.0.1", 2222, "", 22).build();
|
||||
NetworkInterfaceCard networkInterfaceCard = NetworkInterfaceCard.builder().addNetworkAdapter(networkAdapter)
|
||||
.build();
|
||||
.build();
|
||||
|
||||
NetworkSpec networkSpec = NetworkSpec.builder().addNIC(networkInterfaceCard).build();
|
||||
machineSpec = MasterSpec.builder().iso(isoSpec).vm(instanceVmSpec).network(networkSpec).build();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void lockSessionOnMachine() {
|
||||
IMachine machine = cloneFromMaster();
|
||||
ISession session = machineUtils.lockSessionOnMachineAndApply(instanceName, LockType.Shared,
|
||||
new Function<ISession, ISession>() {
|
||||
|
||||
@Override
|
||||
public ISession apply(ISession session) {
|
||||
return session;
|
||||
}
|
||||
});
|
||||
@Test(description = "write lock is acquired and released correctly")
|
||||
public void writeLockSessionOnMachine() {
|
||||
final IMachine clone = cloneFromMaster();
|
||||
ISession session = machineUtils.writeLockMachineAndApplyToSession(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));
|
||||
machine = manager.get().getVBox().findMachine(instanceName);
|
||||
undoVm(instanceName);
|
||||
|
||||
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
|
||||
public ISession apply(ISession writeSession) {
|
||||
checkState(writeSession.getState().equals(SessionState.Locked));
|
||||
//ISession sharedSession = sharedSession(clone);
|
||||
return writeSession;
|
||||
}
|
||||
});
|
||||
checkState(writeSession.getState().equals(SessionState.Unlocked));
|
||||
} finally {
|
||||
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() {
|
||||
IMachine source = getVmWithGuestAdditionsInstalled();
|
||||
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)
|
||||
.apply(cloneSpec);
|
||||
.apply(cloneSpec);
|
||||
}
|
||||
|
||||
private IMachine getVmWithGuestAdditionsInstalled() {
|
||||
|
@ -130,13 +201,4 @@ public class MachineUtilsLiveTest extends BaseVirtualBoxClientLiveTest {
|
|||
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:
|
||||
- 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
|
||||
name: ubuntu-11.04-server-i386
|
||||
description: ubuntu 11.04 server (i386)
|
||||
|
@ -27,7 +162,7 @@ images:
|
|||
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 kbd-chooser/method select American English
|
||||
d-i netcfg/wireless_wep string
|
||||
d-i base-installer/kernel/override-image string linux-server
|
||||
# Choices: Dialog, Readline, Gnome, Kde, Editor, Noninteractive
|
||||
|
@ -143,6 +278,8 @@ images:
|
|||
os_64bit: true
|
||||
iso: http://releases.ubuntu.com/12.04/ubuntu-12.04.1-server-amd64.iso
|
||||
iso_md5: a8c667e871f48f3a662f3fbf1c3ddb17
|
||||
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
|
||||
|
|
|
@ -43,6 +43,11 @@
|
|||
<appender-ref ref="CONSOLE" />
|
||||
</root>
|
||||
|
||||
<logger name="net.schmizz.sshj">
|
||||
<level value="ERROR" />
|
||||
<appender-ref ref="CONSOLE" />
|
||||
</logger>
|
||||
|
||||
<logger name="org.jclouds">
|
||||
<level value="DEBUG" />
|
||||
<appender-ref ref="FILE" />
|
||||
|
|
Loading…
Reference in New Issue