mirror of https://github.com/apache/jclouds.git
issue 384: bridged support
This commit is contained in:
parent
67d70fae62
commit
d10f45ad46
|
@ -0,0 +1,203 @@
|
|||
/**
|
||||
* 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.domain;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
import com.google.common.base.Objects;
|
||||
|
||||
/**
|
||||
* Name: en1: Wi-Fi (AirPort) GUID: 00316e65-0000-4000-8000-28cfdaf2917a Dhcp:
|
||||
* Disabled IPAddress: 192.168.57.1 NetworkMask: 255.255.255.0 IPV6Address:
|
||||
* IPV6NetworkMaskPrefixLength: 0 HardwareAddress: 28:cf:da:f2:91:7a MediumType:
|
||||
* Ethernet Status: Up VBoxNetworkName: HostInterfaceNetworking-en1: Wi-Fi
|
||||
* (AirPort)
|
||||
*
|
||||
* @author Andrea Turli
|
||||
*
|
||||
*/
|
||||
public class BridgedIf {
|
||||
|
||||
private final String name;
|
||||
private final String guid;
|
||||
private final String dhcp;
|
||||
private final String ipAddress;
|
||||
private final String networkMask;
|
||||
private final String ipv6Address;
|
||||
private final String ipv6NetworkMask;
|
||||
private final String mediumType;
|
||||
private final String status;
|
||||
|
||||
public static Builder builder() {
|
||||
return new Builder();
|
||||
}
|
||||
|
||||
public static class Builder {
|
||||
|
||||
private String name;
|
||||
private String guid;
|
||||
private String dhcp;
|
||||
private String ipAddress;
|
||||
private String networkMask;
|
||||
private String ipv6Address;
|
||||
private String iv6NetworkMask;
|
||||
private String mediumType;
|
||||
private String status;
|
||||
|
||||
public Builder name(String name) {
|
||||
this.name = name;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder guid(String guid) {
|
||||
this.guid = guid;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder dhcp(String dhcp) {
|
||||
this.dhcp = dhcp;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder ip(String ipAddress) {
|
||||
this.ipAddress = ipAddress;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder networkMask(String networkMask) {
|
||||
this.networkMask = networkMask;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder ipv6(String ipv6Address) {
|
||||
this.ipv6Address = ipv6Address;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder ipv6networkMask(String iv6NetworkMask) {
|
||||
this.iv6NetworkMask = iv6NetworkMask;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder mediumType(String mediumType) {
|
||||
this.mediumType = mediumType;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder status(String status) {
|
||||
this.status = status;
|
||||
return this;
|
||||
}
|
||||
|
||||
public BridgedIf build() {
|
||||
return new BridgedIf(name, guid, dhcp, ipAddress, networkMask,
|
||||
ipv6Address, iv6NetworkMask, mediumType, status);
|
||||
}
|
||||
}
|
||||
|
||||
public BridgedIf(String name, String guid, String dhcp, String ipAddress,
|
||||
String networkMask, String ipv6Address, String iv6NetworkMask,
|
||||
String mediumType, String status) {
|
||||
this.name = checkNotNull(name, "bridgedIf name");
|
||||
this.guid = guid;
|
||||
this.dhcp = dhcp;
|
||||
this.ipAddress = checkNotNull(ipAddress, "bridgedIf ipAddress");
|
||||
this.networkMask = networkMask;
|
||||
this.ipv6Address = ipv6Address;
|
||||
this.ipv6NetworkMask = iv6NetworkMask;
|
||||
this.mediumType = mediumType;
|
||||
this.status = checkNotNull(status, "bridgedIf status");
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public String getGuid() {
|
||||
return guid;
|
||||
}
|
||||
|
||||
public String getDhcp() {
|
||||
return dhcp;
|
||||
}
|
||||
|
||||
public String getIpAddress() {
|
||||
return ipAddress;
|
||||
}
|
||||
|
||||
public String getNetworkMask() {
|
||||
return networkMask;
|
||||
}
|
||||
|
||||
public String getIpv6Address() {
|
||||
return ipv6Address;
|
||||
}
|
||||
|
||||
public String getIpv6NetworkMask() {
|
||||
return ipv6NetworkMask;
|
||||
}
|
||||
|
||||
public String getMediumType() {
|
||||
return mediumType;
|
||||
}
|
||||
|
||||
public String getStatus() {
|
||||
return status;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o)
|
||||
return true;
|
||||
if (o instanceof VmSpec) {
|
||||
BridgedIf other = (BridgedIf) o;
|
||||
return Objects.equal(name, other.name)
|
||||
&& Objects.equal(guid, other.guid)
|
||||
&& Objects.equal(dhcp, other.dhcp)
|
||||
&& Objects.equal(ipAddress, other.ipAddress)
|
||||
&& Objects.equal(networkMask, other.networkMask)
|
||||
&& Objects.equal(ipv6Address, other.ipv6Address)
|
||||
&& Objects.equal(ipv6NetworkMask, other.ipv6NetworkMask)
|
||||
&& Objects.equal(mediumType, other.mediumType)
|
||||
&& Objects.equal(status, other.status);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hashCode(name, guid, dhcp, ipAddress, networkMask, ipv6Address, ipv6NetworkMask, mediumType, status);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "BridgedIf{" +
|
||||
"name=" + name +
|
||||
", dhcp=" + dhcp +
|
||||
", ipAddress=" + ipAddress +
|
||||
", networkMask=" + networkMask +
|
||||
", ipv6Address=" + ipv6Address +
|
||||
", ipv6NetworkMask=" + ipv6NetworkMask +
|
||||
", mediumType=" + mediumType +
|
||||
", status=" + status +
|
||||
'}';
|
||||
}
|
||||
|
||||
}
|
|
@ -117,6 +117,6 @@ public class CloneSpec {
|
|||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "IMachineSpec{" + "vmSpec= " + vmSpec + ", networkSpec= " + networkSpec + '}';
|
||||
return "CloneSpec{" + "vmSpec= " + vmSpec + ", networkSpec= " + networkSpec + '}';
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,100 @@
|
|||
/**
|
||||
* 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.functions;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import org.jclouds.virtualbox.domain.BridgedIf;
|
||||
|
||||
import com.google.common.base.Function;
|
||||
import com.google.common.base.Splitter;
|
||||
import com.google.common.collect.Iterables;
|
||||
|
||||
@Singleton
|
||||
public class BridgedIfStringToBridgedIf implements Function<String, BridgedIf> {
|
||||
|
||||
private static final String BRIDGED_IF_STATUS = "Status";
|
||||
private static final String BRIDGED_IF_MEDIUM_TYPE = "MediumType";
|
||||
private static final String BRIDGED_IF_NETWORK_MASK = "NetworkMask";
|
||||
private static final String BRIDGED_IF_IP_ADDRESS = "IPAddress";
|
||||
private static final String BRIDGED_IF_GUID = "GUID";
|
||||
private static final String BRIDGED_IF_NAME = "Name";
|
||||
|
||||
@Inject
|
||||
public BridgedIfStringToBridgedIf() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public BridgedIf apply(String rawBridgedIf) {
|
||||
checkNotNull(rawBridgedIf, "rawBridgedIf");
|
||||
|
||||
String transformedBridgedIf = transformRawBridgedIf(rawBridgedIf);
|
||||
Map<String, String> bridegedIfMap = Splitter.on("\n")
|
||||
.omitEmptyStrings().withKeyValueSeparator("=")
|
||||
.split(transformedBridgedIf);
|
||||
|
||||
return BridgedIf
|
||||
.builder()
|
||||
.name(getValueFromMap(bridegedIfMap, BRIDGED_IF_NAME))
|
||||
.guid(getValueFromMap(bridegedIfMap, BRIDGED_IF_GUID))
|
||||
.ip(getValueFromMap(bridegedIfMap, BRIDGED_IF_IP_ADDRESS))
|
||||
.networkMask(getValueFromMap(bridegedIfMap, BRIDGED_IF_NETWORK_MASK))
|
||||
.mediumType(getValueFromMap(bridegedIfMap, BRIDGED_IF_MEDIUM_TYPE))
|
||||
.status(getValueFromMap(bridegedIfMap, BRIDGED_IF_STATUS))
|
||||
.build();
|
||||
}
|
||||
|
||||
private String getValueFromMap(Map<String, String> map, String key) {
|
||||
return map.get(key).trim();
|
||||
}
|
||||
|
||||
/**
|
||||
* This is an helper to simplify the split step of the raw bridgedIf
|
||||
* Substitute first ':' with '='
|
||||
*
|
||||
* @param rawBridgedIf
|
||||
* @return
|
||||
*/
|
||||
private String transformRawBridgedIf(String rawBridgedIf) {
|
||||
Iterable<String> transformedLines = Iterables.transform(
|
||||
Splitter.on("\n").split(rawBridgedIf),
|
||||
new Function<String, String>() {
|
||||
|
||||
@Override
|
||||
public String apply(String line) {
|
||||
return line.replaceFirst(":", "=");
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
StringBuilder stringBuilder = new StringBuilder();
|
||||
|
||||
for (String line : transformedLines) {
|
||||
stringBuilder.append(line + "\n");
|
||||
}
|
||||
return stringBuilder.toString();
|
||||
}
|
||||
|
||||
}
|
|
@ -36,18 +36,15 @@ import org.jclouds.compute.reference.ComputeServiceConstants;
|
|||
import org.jclouds.logging.Logger;
|
||||
import org.jclouds.ssh.SshClient;
|
||||
import org.jclouds.virtualbox.Preconfiguration;
|
||||
import org.jclouds.virtualbox.domain.ExecutionType;
|
||||
import org.jclouds.virtualbox.domain.IsoSpec;
|
||||
import org.jclouds.virtualbox.domain.MasterSpec;
|
||||
import org.jclouds.virtualbox.domain.VmSpec;
|
||||
import org.jclouds.virtualbox.predicates.GuestAdditionsInstaller;
|
||||
import org.jclouds.virtualbox.util.MachineController;
|
||||
import org.jclouds.virtualbox.util.MachineUtils;
|
||||
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.VirtualBoxManager;
|
||||
import org.virtualbox_4_1.jaxws.MachineState;
|
||||
|
||||
import com.google.common.base.Function;
|
||||
import com.google.common.base.Predicate;
|
||||
|
@ -61,124 +58,99 @@ import com.google.inject.Inject;
|
|||
@Singleton
|
||||
public class CreateAndInstallVm implements Function<MasterSpec, IMachine> {
|
||||
|
||||
@Resource
|
||||
@Named(ComputeServiceConstants.COMPUTE_LOGGER)
|
||||
protected Logger logger = Logger.NULL;
|
||||
@Resource
|
||||
@Named(ComputeServiceConstants.COMPUTE_LOGGER)
|
||||
protected Logger logger = Logger.NULL;
|
||||
|
||||
private final Supplier<VirtualBoxManager> manager;
|
||||
private final CreateAndRegisterMachineFromIsoIfNotAlreadyExists createAndRegisterMachineFromIsoIfNotAlreadyExists;
|
||||
private final GuestAdditionsInstaller guestAdditionsInstaller;
|
||||
private final Predicate<SshClient> sshResponds;
|
||||
private final ExecutionType executionType;
|
||||
private LoadingCache<IsoSpec, URI> preConfiguration;
|
||||
private final Function<IMachine, SshClient> sshClientForIMachine;
|
||||
private final MachineUtils machineUtils;
|
||||
private final IMachineToNodeMetadata imachineToNodeMetadata;
|
||||
private final Supplier<VirtualBoxManager> manager;
|
||||
private final CreateAndRegisterMachineFromIsoIfNotAlreadyExists createAndRegisterMachineFromIsoIfNotAlreadyExists;
|
||||
private final GuestAdditionsInstaller guestAdditionsInstaller;
|
||||
private final Predicate<SshClient> sshResponds;
|
||||
private LoadingCache<IsoSpec, URI> preConfiguration;
|
||||
private final Function<IMachine, SshClient> sshClientForIMachine;
|
||||
private final MachineUtils machineUtils;
|
||||
private final IMachineToNodeMetadata imachineToNodeMetadata;
|
||||
private final MachineController machineController;
|
||||
|
||||
@Inject
|
||||
public CreateAndInstallVm(Supplier<VirtualBoxManager> manager,
|
||||
CreateAndRegisterMachineFromIsoIfNotAlreadyExists CreateAndRegisterMachineFromIsoIfNotAlreadyExists,
|
||||
GuestAdditionsInstaller guestAdditionsInstaller, IMachineToNodeMetadata imachineToNodeMetadata,
|
||||
Predicate<SshClient> sshResponds, Function<IMachine, SshClient> sshClientForIMachine,
|
||||
ExecutionType executionType, MachineUtils machineUtils,
|
||||
@Preconfiguration LoadingCache<IsoSpec, URI> preConfiguration) {
|
||||
this.manager = manager;
|
||||
this.createAndRegisterMachineFromIsoIfNotAlreadyExists = CreateAndRegisterMachineFromIsoIfNotAlreadyExists;
|
||||
this.sshResponds = sshResponds;
|
||||
this.sshClientForIMachine = sshClientForIMachine;
|
||||
this.executionType = executionType;
|
||||
this.machineUtils = machineUtils;
|
||||
this.preConfiguration = preConfiguration;
|
||||
this.guestAdditionsInstaller = guestAdditionsInstaller;
|
||||
this.imachineToNodeMetadata = imachineToNodeMetadata;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IMachine apply(MasterSpec masterSpec) {
|
||||
@Inject
|
||||
public CreateAndInstallVm(
|
||||
Supplier<VirtualBoxManager> manager,
|
||||
CreateAndRegisterMachineFromIsoIfNotAlreadyExists CreateAndRegisterMachineFromIsoIfNotAlreadyExists,
|
||||
GuestAdditionsInstaller guestAdditionsInstaller,
|
||||
IMachineToNodeMetadata imachineToNodeMetadata,
|
||||
Predicate<SshClient> sshResponds,
|
||||
Function<IMachine, SshClient> sshClientForIMachine,
|
||||
MachineUtils machineUtils,
|
||||
@Preconfiguration LoadingCache<IsoSpec, URI> preConfiguration, MachineController machineController) {
|
||||
this.manager = manager;
|
||||
this.createAndRegisterMachineFromIsoIfNotAlreadyExists = CreateAndRegisterMachineFromIsoIfNotAlreadyExists;
|
||||
this.sshResponds = sshResponds;
|
||||
this.sshClientForIMachine = sshClientForIMachine;
|
||||
this.machineUtils = machineUtils;
|
||||
this.preConfiguration = preConfiguration;
|
||||
this.guestAdditionsInstaller = guestAdditionsInstaller;
|
||||
this.imachineToNodeMetadata = imachineToNodeMetadata;
|
||||
this.machineController = machineController;
|
||||
}
|
||||
|
||||
VmSpec vmSpec = masterSpec.getVmSpec();
|
||||
IsoSpec isoSpec = masterSpec.getIsoSpec();
|
||||
String vmName = vmSpec.getVmName();
|
||||
@Override
|
||||
public IMachine apply(MasterSpec masterSpec) {
|
||||
|
||||
IMachine vm = createAndRegisterMachineFromIsoIfNotAlreadyExists.apply(masterSpec);
|
||||
VmSpec vmSpec = masterSpec.getVmSpec();
|
||||
IsoSpec isoSpec = masterSpec.getIsoSpec();
|
||||
String vmName = vmSpec.getVmName();
|
||||
|
||||
// Launch machine and wait for it to come online
|
||||
ensureMachineIsLaunched(vmName);
|
||||
IMachine vm = createAndRegisterMachineFromIsoIfNotAlreadyExists
|
||||
.apply(masterSpec);
|
||||
|
||||
URI uri = preConfiguration.getUnchecked(isoSpec);
|
||||
String installationKeySequence = isoSpec.getInstallationKeySequence().replace("PRECONFIGURATION_URL",
|
||||
uri.toASCIIString());
|
||||
// Launch machine and wait for it to come online
|
||||
machineController.ensureMachineIsLaunched(vmName);
|
||||
|
||||
configureOsInstallationWithKeyboardSequence(vmName, installationKeySequence);
|
||||
SshClient client = sshClientForIMachine.apply(vm);
|
||||
URI uri = preConfiguration.getUnchecked(isoSpec);
|
||||
String installationKeySequence = isoSpec.getInstallationKeySequence()
|
||||
.replace("PRECONFIGURATION_URL", uri.toASCIIString());
|
||||
|
||||
logger.debug(">> awaiting installation to finish node(%s)", vmName);
|
||||
configureOsInstallationWithKeyboardSequence(vmName,
|
||||
installationKeySequence);
|
||||
SshClient client = sshClientForIMachine.apply(vm);
|
||||
|
||||
checkState(sshResponds.apply(client), "timed out waiting for guest %s to be accessible via ssh", vmName);
|
||||
logger.debug(">> awaiting installation to finish node(%s)", vmName);
|
||||
|
||||
logger.debug(">> awaiting installation of guest additions on vm: %s", vmName);
|
||||
checkState(sshResponds.apply(client),
|
||||
"timed out waiting for guest %s to be accessible via ssh",
|
||||
vmName);
|
||||
|
||||
checkState(guestAdditionsInstaller.apply(vm));
|
||||
//logger.debug(">> awaiting installation of guest additions on vm: %s", vmName);
|
||||
//checkState(guestAdditionsInstaller.apply(vm));
|
||||
|
||||
logger.debug(">> awaiting post-installation actions on vm: %s", vmName);
|
||||
logger.debug(">> awaiting post-installation actions on vm: %s", vmName);
|
||||
|
||||
NodeMetadata vmMetadata = imachineToNodeMetadata.apply(vm);
|
||||
NodeMetadata vmMetadata = imachineToNodeMetadata.apply(vm);
|
||||
|
||||
// TODO for now this is executed on installModuleAssistantIfNeeded as a workaround to some transient execution issue.
|
||||
// ListenableFuture<ExecResponse> execFuture = machineUtils.runScriptOnNode(vmMetadata, call("cleanupUdevIfNeeded"),
|
||||
// RunScriptOptions.NONE);
|
||||
ListenableFuture<ExecResponse> execFuture =
|
||||
machineUtils.runScriptOnNode(vmMetadata, call("cleanupUdevIfNeeded"), RunScriptOptions.NONE);
|
||||
|
||||
// ExecResponse execResponse = Futures.getUnchecked(execFuture);
|
||||
// checkState(execResponse.getExitCode() == 0);
|
||||
ExecResponse execResponse = Futures.getUnchecked(execFuture);
|
||||
checkState(execResponse.getExitStatus() == 0);
|
||||
|
||||
logger.debug("<< installation of image complete. Powering down node(%s)", vmName);
|
||||
logger.debug(
|
||||
"<< installation of image complete. Powering down node(%s)",
|
||||
vmName);
|
||||
|
||||
ensureMachineHasPowerDown(vmName);
|
||||
return vm;
|
||||
}
|
||||
machineController.ensureMachineHasPowerDown(vmName);
|
||||
return vm;
|
||||
}
|
||||
|
||||
private void configureOsInstallationWithKeyboardSequence(String vmName, String installationKeySequence) {
|
||||
Iterable<List<Integer>> scancodelist = transform(Splitter.on(" ").split(installationKeySequence),
|
||||
new StringToKeyCode());
|
||||
private void configureOsInstallationWithKeyboardSequence(String vmName,
|
||||
String installationKeySequence) {
|
||||
Iterable<List<Integer>> scancodelist = transform(Splitter.on(" ")
|
||||
.split(installationKeySequence), new StringToKeyCode());
|
||||
|
||||
for (List<Integer> scancodes : scancodelist) {
|
||||
machineUtils.lockSessionOnMachineAndApply(vmName, LockType.Shared, new SendScancodes(scancodes));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* ensureMachineHasPowerDown needs to have this delay just to ensure that the machine is
|
||||
* completely powered off
|
||||
*
|
||||
* @param vmName
|
||||
*/
|
||||
private void ensureMachineHasPowerDown(String vmName) {
|
||||
while (!manager.get().getVBox().findMachine(vmName).getState().equals(MachineState.POWERED_OFF)) {
|
||||
try {
|
||||
machineUtils.lockSessionOnMachineAndApply(vmName, LockType.Shared, new Function<ISession, Void>() {
|
||||
@Override
|
||||
public Void apply(ISession session) {
|
||||
IProgress powerDownProgress = session.getConsole().powerDown();
|
||||
powerDownProgress.waitForCompletion(-1);
|
||||
return null;
|
||||
}
|
||||
});
|
||||
} catch (RuntimeException e) {
|
||||
// sometimes the machine might be powered of between the while test and the call to
|
||||
// lockSessionOnMachineAndApply
|
||||
if (e.getMessage().contains("Invalid machine state: PoweredOff")) {
|
||||
return;
|
||||
} else if (e.getMessage().contains("VirtualBox error: The object is not ready")) {
|
||||
continue;
|
||||
} else {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void ensureMachineIsLaunched(String vmName) {
|
||||
machineUtils.applyForMachine(vmName, new LaunchMachineIfNotAlreadyRunning(manager.get(), executionType, ""));
|
||||
}
|
||||
for (List<Integer> scancodes : scancodelist) {
|
||||
machineUtils.lockSessionOnMachineAndApply(vmName, LockType.Shared,
|
||||
new SendScancodes(scancodes));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -19,58 +19,123 @@
|
|||
package org.jclouds.virtualbox.functions;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
import static com.google.common.base.Preconditions.checkState;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
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.net.IPSocket;
|
||||
import org.jclouds.ssh.SshClient;
|
||||
import org.jclouds.virtualbox.domain.BridgedIf;
|
||||
import org.jclouds.virtualbox.statements.GetIPAddressFromMAC;
|
||||
import org.jclouds.virtualbox.statements.ScanNetworkWithPing;
|
||||
import org.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.inject.Inject;
|
||||
|
||||
@Singleton
|
||||
public class IMachineToSshClient implements Function<IMachine, SshClient> {
|
||||
|
||||
@Resource
|
||||
@Named(ComputeServiceConstants.COMPUTE_LOGGER)
|
||||
protected Logger logger = Logger.NULL;
|
||||
@Resource
|
||||
@Named(ComputeServiceConstants.COMPUTE_LOGGER)
|
||||
protected Logger logger = Logger.NULL;
|
||||
|
||||
private final SshClient.Factory sshClientFactory;
|
||||
private final SshClient.Factory sshClientFactory;
|
||||
private final RunScriptOnNode.Factory scriptRunnerFactory;
|
||||
private final Supplier<NodeMetadata> hostSupplier;
|
||||
|
||||
@Inject
|
||||
public IMachineToSshClient(SshClient.Factory sshClientFactory) {
|
||||
this.sshClientFactory = sshClientFactory;
|
||||
}
|
||||
@Inject
|
||||
public IMachineToSshClient(SshClient.Factory sshClientFactory,
|
||||
RunScriptOnNode.Factory scriptRunnerFactory,
|
||||
Supplier<NodeMetadata> hostSupplier) {
|
||||
this.sshClientFactory = sshClientFactory;
|
||||
this.scriptRunnerFactory = scriptRunnerFactory;
|
||||
this.hostSupplier = hostSupplier;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SshClient apply(final IMachine vm) {
|
||||
INetworkAdapter networkAdapter = vm.getNetworkAdapter(0L);
|
||||
@Override
|
||||
public SshClient apply(final IMachine vm) {
|
||||
INetworkAdapter networkAdapter = vm.getNetworkAdapter(0L);
|
||||
|
||||
SshClient client = null;
|
||||
checkNotNull(networkAdapter);
|
||||
for (String nameProtocolnumberAddressInboudportGuestTargetport : networkAdapter.getNatDriver().getRedirects()) {
|
||||
Iterable<String> stuff = Splitter.on(',').split(nameProtocolnumberAddressInboudportGuestTargetport);
|
||||
String protocolNumber = Iterables.get(stuff, 1);
|
||||
String hostAddress = Iterables.get(stuff, 2);
|
||||
String inboundPort = Iterables.get(stuff, 3);
|
||||
String targetPort = Iterables.get(stuff, 5);
|
||||
// TODO: we need a way to align the default login credentials from the iso with the
|
||||
// vmspec
|
||||
if ("1".equals(protocolNumber) && "22".equals(targetPort)) {
|
||||
client = sshClientFactory.create(new IPSocket(hostAddress, Integer.parseInt(inboundPort)), LoginCredentials
|
||||
.builder().user("toor").password("password").authenticateSudo(true).build());
|
||||
}
|
||||
}
|
||||
checkNotNull(client);
|
||||
return client;
|
||||
}
|
||||
SshClient client = null;
|
||||
checkNotNull(networkAdapter);
|
||||
|
||||
String clientIpAddress = null;
|
||||
String sshPort = "22";
|
||||
|
||||
// TODO: we need a way to align the default login credentials
|
||||
// from the iso with the vmspec -> IMachineToNodeMetadata using YamlImage ?
|
||||
LoginCredentials loginCredentials = LoginCredentials.builder()
|
||||
.user("toor").password("password").authenticateSudo(true)
|
||||
.build();
|
||||
|
||||
if (networkAdapter.getAttachmentType()
|
||||
.equals(NetworkAttachmentType.NAT)) {
|
||||
for (String nameProtocolnumberAddressInboudportGuestTargetport : networkAdapter
|
||||
.getNatDriver().getRedirects()) {
|
||||
Iterable<String> stuff = Splitter.on(',').split(
|
||||
nameProtocolnumberAddressInboudportGuestTargetport);
|
||||
String protocolNumber = Iterables.get(stuff, 1);
|
||||
String hostAddress = Iterables.get(stuff, 2);
|
||||
String inboundPort = Iterables.get(stuff, 3);
|
||||
String targetPort = Iterables.get(stuff, 5);
|
||||
if ("1".equals(protocolNumber) && "22".equals(targetPort)) {
|
||||
clientIpAddress = hostAddress;
|
||||
sshPort = inboundPort;
|
||||
}
|
||||
}
|
||||
} else if (networkAdapter.getAttachmentType().equals(
|
||||
NetworkAttachmentType.Bridged)) {
|
||||
String network = "1.1.1.1";
|
||||
clientIpAddress = getIpAddressFromBridgedNIC(networkAdapter, network);
|
||||
}
|
||||
|
||||
checkNotNull(clientIpAddress, "clientIpAddress");
|
||||
client = sshClientFactory.create(
|
||||
new IPSocket(clientIpAddress, Integer.parseInt(sshPort)),
|
||||
loginCredentials);
|
||||
checkNotNull(client);
|
||||
return client;
|
||||
}
|
||||
|
||||
private String getIpAddressFromBridgedNIC(INetworkAdapter networkAdapter,
|
||||
String network) {
|
||||
// RetrieveActiveBridgedInterfaces
|
||||
List<BridgedIf> activeBridgedInterfaces = new RetrieveActiveBridgedInterfaces(scriptRunnerFactory).apply(hostSupplier.get());
|
||||
BridgedIf activeBrigedIf = checkNotNull(Iterables.get(activeBridgedInterfaces, 0), "activeBridgrdIf");
|
||||
network = activeBrigedIf.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,15 +23,18 @@ import static com.google.common.base.Preconditions.checkNotNull;
|
|||
import static org.jclouds.virtualbox.config.VirtualBoxConstants.VIRTUALBOX_IMAGE_PREFIX;
|
||||
import static org.jclouds.virtualbox.config.VirtualBoxConstants.VIRTUALBOX_NODE_PREFIX;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import org.jclouds.compute.ComputeServiceAdapter.NodeAndInitialCredentials;
|
||||
import org.jclouds.compute.callables.RunScriptOnNode;
|
||||
import org.jclouds.compute.domain.NodeMetadata;
|
||||
import org.jclouds.compute.options.RunScriptOptions;
|
||||
import org.jclouds.domain.LoginCredentials;
|
||||
import org.jclouds.virtualbox.domain.BridgedIf;
|
||||
import org.jclouds.virtualbox.domain.CloneSpec;
|
||||
import org.jclouds.virtualbox.domain.ExecutionType;
|
||||
import org.jclouds.virtualbox.domain.Master;
|
||||
|
@ -52,95 +55,148 @@ import com.google.common.base.Function;
|
|||
import com.google.common.base.Supplier;
|
||||
|
||||
@Singleton
|
||||
public class NodeCreator implements Function<NodeSpec, NodeAndInitialCredentials<IMachine>> {
|
||||
public class NodeCreator implements
|
||||
Function<NodeSpec, NodeAndInitialCredentials<IMachine>> {
|
||||
|
||||
// TODO parameterize
|
||||
public static final int NODE_PORT_INIT = 3000;
|
||||
// TODO parameterize
|
||||
public static final int NODE_PORT_INIT = 3000;
|
||||
|
||||
// TODO parameterize
|
||||
public static final String VMS_NETWORK = "33.33.33.";
|
||||
// TODO parameterize
|
||||
public static final String VMS_NETWORK = "33.33.33.";
|
||||
|
||||
// TODO parameterize
|
||||
public static final String HOST_ONLY_IFACE_NAME = "vboxnet0";
|
||||
// TODO parameterize
|
||||
public static final String HOST_ONLY_IFACE_NAME = "vboxnet0";
|
||||
|
||||
// TODO parameterize
|
||||
public static final boolean USE_LINKED = true;
|
||||
// TODO parameterize
|
||||
public static final boolean USE_LINKED = true;
|
||||
|
||||
private final Supplier<VirtualBoxManager> manager;
|
||||
private final Function<CloneSpec, IMachine> cloner;
|
||||
private final AtomicInteger nodes;
|
||||
private MachineUtils machineUtils;
|
||||
private Function<IMachine, NodeMetadata> imachineToNodeMetadata;
|
||||
private final Supplier<VirtualBoxManager> manager;
|
||||
private final Function<CloneSpec, IMachine> cloner;
|
||||
private final AtomicInteger nodePorts;
|
||||
private final AtomicInteger nodeIps;
|
||||
private MachineUtils machineUtils;
|
||||
private Function<IMachine, NodeMetadata> imachineToNodeMetadata;
|
||||
|
||||
@Inject
|
||||
public NodeCreator(Supplier<VirtualBoxManager> manager, Function<CloneSpec, IMachine> cloner,
|
||||
MachineUtils machineUtils, Function<IMachine, NodeMetadata> imachineToNodeMetadata) {
|
||||
this.manager = manager;
|
||||
this.cloner = cloner;
|
||||
this.nodes = new AtomicInteger(0);
|
||||
this.machineUtils = machineUtils;
|
||||
this.imachineToNodeMetadata = imachineToNodeMetadata;
|
||||
}
|
||||
private final RunScriptOnNode.Factory scriptRunnerFactory;
|
||||
private final Supplier<NodeMetadata> hostSupplier;
|
||||
|
||||
/**
|
||||
* Creates a clone based on the {@link NodeSpec}. It is synchronized because it needs sole access
|
||||
* to the master. Could be improved by locking on a master basis (would allow concurrent cloning
|
||||
* as long as form different masters."
|
||||
*/
|
||||
@Override
|
||||
public synchronized NodeAndInitialCredentials<IMachine> apply(NodeSpec nodeSpec) {
|
||||
@Inject
|
||||
public NodeCreator(Supplier<VirtualBoxManager> manager,
|
||||
Function<CloneSpec, IMachine> cloner, MachineUtils machineUtils,
|
||||
Function<IMachine, NodeMetadata> imachineToNodeMetadata,
|
||||
RunScriptOnNode.Factory scriptRunnerFactory,
|
||||
Supplier<NodeMetadata> hostSupplier) {
|
||||
this.manager = manager;
|
||||
this.cloner = cloner;
|
||||
this.nodePorts = new AtomicInteger(NODE_PORT_INIT);
|
||||
this.nodeIps = new AtomicInteger(1);
|
||||
this.machineUtils = machineUtils;
|
||||
this.imachineToNodeMetadata = imachineToNodeMetadata;
|
||||
this.scriptRunnerFactory = scriptRunnerFactory;
|
||||
this.hostSupplier = hostSupplier;
|
||||
|
||||
checkNotNull(nodeSpec, "NodeSpec");
|
||||
}
|
||||
|
||||
Master master = nodeSpec.getMaster();
|
||||
checkNotNull(master, "Master");
|
||||
@Override
|
||||
public NodeAndInitialCredentials<IMachine> apply(NodeSpec nodeSpec) {
|
||||
|
||||
if (master.getMachine().getCurrentSnapshot() != null) {
|
||||
ISession session;
|
||||
try {
|
||||
session = manager.get().openMachineSession(master.getMachine());
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("error opening vbox machine session: " + e.getMessage(), e);
|
||||
}
|
||||
session.getConsole().deleteSnapshot(master.getMachine().getCurrentSnapshot().getId());
|
||||
session.unlockMachine();
|
||||
}
|
||||
checkNotNull(nodeSpec, "NodeSpec");
|
||||
|
||||
String masterNameWithoutPrefix = master.getSpec().getVmSpec().getVmName().replace(VIRTUALBOX_IMAGE_PREFIX, "");
|
||||
Master master = nodeSpec.getMaster();
|
||||
checkNotNull(master, "Master");
|
||||
|
||||
String cloneName = VIRTUALBOX_NODE_PREFIX + masterNameWithoutPrefix + "-" + nodeSpec.getTag() + "-"
|
||||
+ nodeSpec.getName();
|
||||
if (master.getMachine().getCurrentSnapshot() != null) {
|
||||
ISession session;
|
||||
try {
|
||||
session = manager.get().openMachineSession(master.getMachine());
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(
|
||||
"error opening vbox machine session: " + e.getMessage(),
|
||||
e);
|
||||
}
|
||||
session.getConsole().deleteSnapshot(
|
||||
master.getMachine().getCurrentSnapshot().getId());
|
||||
session.unlockMachine();
|
||||
}
|
||||
String masterNameWithoutPrefix = master.getSpec().getVmSpec()
|
||||
.getVmName().replace(VIRTUALBOX_IMAGE_PREFIX, "");
|
||||
|
||||
VmSpec cloneVmSpec = VmSpec.builder().id(cloneName).name(cloneName).memoryMB(512).cleanUpMode(CleanupMode.Full)
|
||||
.forceOverwrite(true).build();
|
||||
String cloneName = VIRTUALBOX_NODE_PREFIX + masterNameWithoutPrefix
|
||||
+ "-" + nodeSpec.getTag() + "-" + nodeSpec.getName();
|
||||
|
||||
NetworkAdapter natAdapter = NetworkAdapter.builder().networkAttachmentType(NetworkAttachmentType.NAT)
|
||||
.tcpRedirectRule("127.0.0.1", NODE_PORT_INIT + this.nodes.getAndIncrement(), "", 22).build();
|
||||
VmSpec cloneVmSpec = VmSpec.builder().id(cloneName).name(cloneName)
|
||||
.memoryMB(512).cleanUpMode(CleanupMode.Full)
|
||||
.forceOverwrite(true).build();
|
||||
|
||||
NetworkInterfaceCard natIfaceCard = NetworkInterfaceCard.builder().addNetworkAdapter(natAdapter).slot(0L).build();
|
||||
|
||||
NetworkAdapter hostOnlyAdapter = NetworkAdapter.builder().networkAttachmentType(NetworkAttachmentType.HostOnly)
|
||||
.staticIp(VMS_NETWORK + this.nodes.getAndIncrement()).build();
|
||||
// CASE NAT + HOST-ONLY
|
||||
NetworkAdapter natAdapter = NetworkAdapter
|
||||
.builder()
|
||||
.networkAttachmentType(NetworkAttachmentType.NAT)
|
||||
.tcpRedirectRule("127.0.0.1", this.nodePorts.getAndIncrement(),
|
||||
"", 22).build();
|
||||
NetworkInterfaceCard natIfaceCard = NetworkInterfaceCard.builder()
|
||||
.addNetworkAdapter(natAdapter).slot(0L).build();
|
||||
|
||||
NetworkInterfaceCard hostOnlyIfaceCard = NetworkInterfaceCard.builder().addNetworkAdapter(hostOnlyAdapter)
|
||||
.addHostInterfaceName(HOST_ONLY_IFACE_NAME).slot(1L).build();
|
||||
NetworkAdapter hostOnlyAdapter = NetworkAdapter.builder()
|
||||
.networkAttachmentType(NetworkAttachmentType.HostOnly)
|
||||
.staticIp(VMS_NETWORK + this.nodeIps.getAndIncrement()).build();
|
||||
|
||||
NetworkSpec networkSpec = NetworkSpec.builder().addNIC(natIfaceCard).addNIC(hostOnlyIfaceCard).build();
|
||||
NetworkInterfaceCard hostOnlyIfaceCard = NetworkInterfaceCard.builder()
|
||||
.addNetworkAdapter(hostOnlyAdapter)
|
||||
.addHostInterfaceName(HOST_ONLY_IFACE_NAME).slot(1L).build();
|
||||
|
||||
CloneSpec cloneSpec = CloneSpec.builder().linked(USE_LINKED).master(master.getMachine()).network(networkSpec)
|
||||
.vm(cloneVmSpec).build();
|
||||
NetworkSpec networkSpec = createNetworkSpecForHostOnlyNATNICs(natIfaceCard, hostOnlyIfaceCard);
|
||||
////
|
||||
|
||||
IMachine cloned = cloner.apply(cloneSpec);
|
||||
// CASE BRIDGED
|
||||
//NetworkSpec networkSpec = createNetworkSpecForBridgedNIC();
|
||||
|
||||
new LaunchMachineIfNotAlreadyRunning(manager.get(), ExecutionType.GUI, "").apply(cloned);
|
||||
CloneSpec cloneSpec = CloneSpec.builder().linked(USE_LINKED)
|
||||
.master(master.getMachine()).network(networkSpec)
|
||||
.vm(cloneVmSpec).build();
|
||||
|
||||
machineUtils.runScriptOnNode(imachineToNodeMetadata.apply(cloned), new SetIpAddress(hostOnlyIfaceCard),
|
||||
RunScriptOptions.NONE);
|
||||
IMachine cloned = cloner.apply(cloneSpec);
|
||||
|
||||
// TODO get credentials from somewhere else (they are also HC in IMachineToSshClient)
|
||||
NodeAndInitialCredentials<IMachine> nodeAndInitialCredentials = new NodeAndInitialCredentials<IMachine>(cloned,
|
||||
cloneName, LoginCredentials.builder().user("toor").password("password").authenticateSudo(true).build());
|
||||
new LaunchMachineIfNotAlreadyRunning(manager.get(), ExecutionType.GUI,
|
||||
"").apply(cloned);
|
||||
|
||||
return nodeAndInitialCredentials;
|
||||
}
|
||||
|
||||
// CASE NAT + HOST-ONLY
|
||||
machineUtils.runScriptOnNode(imachineToNodeMetadata.apply(cloned),
|
||||
new SetIpAddress(hostOnlyIfaceCard), RunScriptOptions.NONE);
|
||||
////
|
||||
|
||||
|
||||
// TODO get credentials from somewhere else (they are also HC in
|
||||
// IMachineToSshClient)
|
||||
NodeAndInitialCredentials<IMachine> nodeAndInitialCredentials = new NodeAndInitialCredentials<IMachine>(
|
||||
cloned, cloneName, LoginCredentials.builder().user("toor")
|
||||
.password("password").authenticateSudo(true).build());
|
||||
|
||||
return nodeAndInitialCredentials;
|
||||
}
|
||||
|
||||
private NetworkSpec createNetworkSpecForHostOnlyNATNICs(NetworkInterfaceCard natIfaceCard, NetworkInterfaceCard hostOnlyIfaceCard) {
|
||||
return NetworkSpec.builder().addNIC(natIfaceCard)
|
||||
.addNIC(hostOnlyIfaceCard).build();
|
||||
}
|
||||
|
||||
private NetworkSpec createNetworkSpecForBridgedNIC() {
|
||||
List<BridgedIf> activeBridgedInterfaces = new RetrieveActiveBridgedInterfaces(
|
||||
scriptRunnerFactory).apply(hostSupplier.get());
|
||||
BridgedIf bridgedActiveInterface = checkNotNull(
|
||||
activeBridgedInterfaces.get(0), "activeBridgedIf");
|
||||
|
||||
NetworkAdapter bridgedAdapter = NetworkAdapter.builder()
|
||||
.networkAttachmentType(NetworkAttachmentType.Bridged).build();
|
||||
NetworkInterfaceCard bridgedNIC = NetworkInterfaceCard.builder()
|
||||
.addNetworkAdapter(bridgedAdapter)
|
||||
.addHostInterfaceName(bridgedActiveInterface.getName())
|
||||
.slot(0L).build();
|
||||
|
||||
NetworkSpec networkSpec = NetworkSpec.builder().addNIC(bridgedNIC)
|
||||
.build();
|
||||
return networkSpec;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -37,6 +37,7 @@ import org.jclouds.compute.reference.ComputeServiceConstants;
|
|||
import org.jclouds.logging.Logger;
|
||||
import org.jclouds.scriptbuilder.domain.Statement;
|
||||
import org.jclouds.scriptbuilder.domain.Statements;
|
||||
import org.jclouds.virtualbox.domain.BridgedIf;
|
||||
|
||||
import com.google.common.base.Function;
|
||||
import com.google.common.base.Predicate;
|
||||
|
@ -50,9 +51,9 @@ import com.google.inject.name.Named;
|
|||
/**
|
||||
* @author Andrea Turli
|
||||
*/
|
||||
public class RetrieveActiveBridgedInterfaces implements Function<NodeMetadata, List<String>> {
|
||||
public class RetrieveActiveBridgedInterfaces implements Function<NodeMetadata, List<BridgedIf>> {
|
||||
|
||||
@Resource
|
||||
@Resource
|
||||
@Named(ComputeServiceConstants.COMPUTE_LOGGER)
|
||||
protected Logger logger = Logger.NULL;
|
||||
|
||||
|
@ -64,53 +65,42 @@ public class RetrieveActiveBridgedInterfaces implements Function<NodeMetadata, L
|
|||
}
|
||||
|
||||
@Override
|
||||
public List<String> apply(NodeMetadata host) {
|
||||
public List<BridgedIf> apply(NodeMetadata host) {
|
||||
// Bridged Network
|
||||
Statement command = Statements.exec("VBoxManage list bridgedifs");
|
||||
String bridgedIfBlocks = runScriptOnNodeFactory.create(host, command, runAsRoot(false).wrapInInitScript(false))
|
||||
.init().call().getOutput();
|
||||
|
||||
List<String> bridgedInterfaces = retrieveBridgedInterfaceNames(bridgedIfBlocks);
|
||||
List<BridgedIf> bridgedInterfaces = retrieveBridgedInterfaceNames(bridgedIfBlocks);
|
||||
checkNotNull(bridgedInterfaces);
|
||||
|
||||
// union of bridgedNetwork with inet up and !loopback
|
||||
List<String> activeNetworkInterfaceNames = Lists.newArrayList();
|
||||
List<BridgedIf> activeNetworkInterfaces = Lists.newArrayList();
|
||||
try {
|
||||
Enumeration<NetworkInterface> nets = NetworkInterface.getNetworkInterfaces();
|
||||
for (NetworkInterface inet : Collections.list(nets)) {
|
||||
Iterable<String> filteredBridgedInterface = filter(bridgedInterfaces, new IsActiveBridgedInterface(inet));
|
||||
Iterables.addAll(activeNetworkInterfaceNames, filteredBridgedInterface);
|
||||
Iterable<BridgedIf> filteredBridgedInterface = filter(bridgedInterfaces, new IsActiveBridgedInterface(inet));
|
||||
Iterables.addAll(activeNetworkInterfaces, filteredBridgedInterface);
|
||||
}
|
||||
} catch (SocketException e) {
|
||||
logger.error(e, "Problem in listing network interfaces.");
|
||||
Throwables.propagate(e);
|
||||
assert false;
|
||||
}
|
||||
return activeNetworkInterfaceNames;
|
||||
return activeNetworkInterfaces;
|
||||
}
|
||||
|
||||
protected static List<String> retrieveBridgedInterfaceNames(String bridgedIfBlocks) {
|
||||
List<String> bridgedInterfaceNames = Lists.newArrayList();
|
||||
protected static List<BridgedIf> retrieveBridgedInterfaceNames(String bridgedIfBlocks) {
|
||||
List<BridgedIf> bridgedInterfaces = Lists.newArrayList();
|
||||
// separate the different bridge block
|
||||
for (String bridgedIfBlock : Splitter.on(Pattern.compile("(?m)^[ \t]*\r?\n")).split(bridgedIfBlocks)) {
|
||||
|
||||
Iterable<String> bridgedIfName = filter(Splitter.on("\n").split(bridgedIfBlock), new Predicate<String>() {
|
||||
@Override
|
||||
public boolean apply(String arg0) {
|
||||
return arg0.startsWith("Name:");
|
||||
}
|
||||
});
|
||||
for (String bridgedInterfaceName : bridgedIfName) {
|
||||
for (String string : Splitter.on("Name:").split(bridgedInterfaceName)) {
|
||||
if (!string.isEmpty())
|
||||
bridgedInterfaceNames.add(string.trim());
|
||||
}
|
||||
}
|
||||
if(!bridgedIfBlock.isEmpty())
|
||||
bridgedInterfaces.add(new BridgedIfStringToBridgedIf().apply(bridgedIfBlock));
|
||||
}
|
||||
return bridgedInterfaceNames;
|
||||
return bridgedInterfaces;
|
||||
}
|
||||
|
||||
private class IsActiveBridgedInterface implements Predicate<String> {
|
||||
private class IsActiveBridgedInterface implements Predicate<BridgedIf> {
|
||||
|
||||
private NetworkInterface networkInterface;
|
||||
|
||||
|
@ -119,10 +109,12 @@ public class RetrieveActiveBridgedInterfaces implements Function<NodeMetadata, L
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(String bridgedInterfaceName) {
|
||||
public boolean apply(BridgedIf bridgedInterface) {
|
||||
try {
|
||||
return (bridgedInterfaceName.startsWith(networkInterface.getDisplayName()) && networkInterface.isUp() && !networkInterface
|
||||
.isLoopback());
|
||||
return (bridgedInterface.getName().startsWith(networkInterface.getDisplayName()) &&
|
||||
bridgedInterface.getStatus().equals("Up") &&
|
||||
networkInterface.isUp() &&
|
||||
!networkInterface.isLoopback());
|
||||
} catch (SocketException e) {
|
||||
logger.error(e, "Problem in listing network interfaces.");
|
||||
Throwables.propagate(e);
|
||||
|
|
|
@ -1,3 +1,22 @@
|
|||
/**
|
||||
* 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.predicates;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
|
|
@ -0,0 +1,92 @@
|
|||
/**
|
||||
* 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 javax.annotation.Resource;
|
||||
import javax.inject.Named;
|
||||
import javax.inject.Singleton;
|
||||
|
||||
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.IProgress;
|
||||
import org.virtualbox_4_1.ISession;
|
||||
import org.virtualbox_4_1.LockType;
|
||||
import org.virtualbox_4_1.VirtualBoxManager;
|
||||
import org.virtualbox_4_1.jaxws.MachineState;
|
||||
|
||||
import com.google.common.base.Function;
|
||||
import com.google.common.base.Supplier;
|
||||
import com.google.inject.Inject;
|
||||
|
||||
/**
|
||||
* Utilities to manage VirtualBox machine life cycle.
|
||||
*
|
||||
* @author Adrian Cole, Mattias Holmqvist, Andrea Turli
|
||||
*/
|
||||
|
||||
@Singleton
|
||||
public class MachineController {
|
||||
|
||||
@Resource
|
||||
@Named(ComputeServiceConstants.COMPUTE_LOGGER)
|
||||
protected Logger logger = Logger.NULL;
|
||||
|
||||
private final Supplier<VirtualBoxManager> manager;
|
||||
private final MachineUtils machineUtils;
|
||||
private final ExecutionType executionType;
|
||||
|
||||
|
||||
@Inject
|
||||
public MachineController(Supplier<VirtualBoxManager> manager, MachineUtils machineUtils, ExecutionType executionType) {
|
||||
this.manager = manager;
|
||||
this.machineUtils = machineUtils;
|
||||
this.executionType = executionType;
|
||||
}
|
||||
|
||||
public void ensureMachineIsLaunched(String vmName) {
|
||||
machineUtils.applyForMachine(vmName, new LaunchMachineIfNotAlreadyRunning(manager.get(), executionType, ""));
|
||||
}
|
||||
|
||||
public void ensureMachineHasPowerDown(String vmName) {
|
||||
while (!manager.get().getVBox().findMachine(vmName).getState().equals(MachineState.POWERED_OFF)) {
|
||||
try {
|
||||
machineUtils.lockSessionOnMachineAndApply(vmName, LockType.Shared, new Function<ISession, Void>() {
|
||||
@Override
|
||||
public Void apply(ISession session) {
|
||||
IProgress powerDownProgress = session.getConsole().powerDown();
|
||||
powerDownProgress.waitForCompletion(-1);
|
||||
return null;
|
||||
}
|
||||
});
|
||||
} catch (RuntimeException e) {
|
||||
// sometimes the machine might be powered of between the while test and the call to
|
||||
// lockSessionOnMachineAndApply
|
||||
if (e.getMessage().contains("Invalid machine state: PoweredOff")) {
|
||||
return;
|
||||
} else if (e.getMessage().contains("VirtualBox error: The object is not ready")) {
|
||||
continue;
|
||||
} else {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,9 +1,9 @@
|
|||
function cleanupUdevIfNeeded {
|
||||
unset OSNAME;
|
||||
local OSNAME=`lsb_release -d -s | cut -d ' ' -f 1`; shift
|
||||
if [ $OSNAME = 'Ubuntu' ]
|
||||
# unset OSNAME;
|
||||
# local OSNAME=`lsb_release -d -s | cut -d ' ' -f 1`; shift
|
||||
# if [ $OSNAME = 'Ubuntu' ]
|
||||
if [ -f '/etc/udev/rules.d/70-persistent-net.rules']
|
||||
then
|
||||
echo "OS is Ubuntu"
|
||||
rm /etc/udev/rules.d/70-persistent-net.rules;
|
||||
mkdir /etc/udev/rules.d/70-persistent-net.rules;
|
||||
rm -rf /dev/.udev/;
|
||||
|
|
|
@ -30,14 +30,11 @@ import javax.inject.Inject;
|
|||
import javax.inject.Named;
|
||||
|
||||
import org.jclouds.Constants;
|
||||
import org.jclouds.byon.Node;
|
||||
import org.jclouds.byon.config.CacheNodeStoreModule;
|
||||
import org.jclouds.compute.BaseVersionedServiceLiveTest;
|
||||
import org.jclouds.compute.ComputeServiceContext;
|
||||
import org.jclouds.compute.ComputeServiceContextFactory;
|
||||
import org.jclouds.compute.domain.Image;
|
||||
import org.jclouds.compute.domain.NodeMetadata;
|
||||
import org.jclouds.compute.domain.OsFamily;
|
||||
import org.jclouds.compute.domain.Template;
|
||||
import org.jclouds.compute.strategy.PrioritizeCredentialsFromTemplate;
|
||||
import org.jclouds.concurrent.MoreExecutors;
|
||||
|
@ -49,21 +46,16 @@ import org.jclouds.virtualbox.domain.IsoSpec;
|
|||
import org.jclouds.virtualbox.domain.Master;
|
||||
import org.jclouds.virtualbox.domain.VmSpec;
|
||||
import org.jclouds.virtualbox.functions.admin.UnregisterMachineIfExistsAndDeleteItsMedia;
|
||||
import org.jclouds.virtualbox.util.MachineController;
|
||||
import org.jclouds.virtualbox.util.MachineUtils;
|
||||
import org.testng.annotations.AfterClass;
|
||||
import org.testng.annotations.BeforeClass;
|
||||
import org.testng.annotations.Test;
|
||||
import org.virtualbox_4_1.IProgress;
|
||||
import org.virtualbox_4_1.ISession;
|
||||
import org.virtualbox_4_1.LockType;
|
||||
import org.virtualbox_4_1.VirtualBoxManager;
|
||||
import org.virtualbox_4_1.jaxws.MachineState;
|
||||
|
||||
import com.google.common.base.Function;
|
||||
import com.google.common.base.Splitter;
|
||||
import com.google.common.base.Supplier;
|
||||
import com.google.common.cache.LoadingCache;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.collect.Iterables;
|
||||
import com.google.inject.Module;
|
||||
|
@ -81,6 +73,9 @@ public class BaseVirtualBoxClientLiveTest extends BaseVersionedServiceLiveTest {
|
|||
|
||||
protected ComputeServiceContext context;
|
||||
|
||||
@Inject
|
||||
protected MachineController machineController;
|
||||
|
||||
@Inject
|
||||
protected Supplier<VirtualBoxManager> manager;
|
||||
|
||||
|
@ -160,30 +155,7 @@ public class BaseVirtualBoxClientLiveTest extends BaseVersionedServiceLiveTest {
|
|||
new UnregisterMachineIfExistsAndDeleteItsMedia(vmSpecification));
|
||||
}
|
||||
|
||||
protected void ensureMachineHasPowerDown(String vmName) {
|
||||
while (!manager.get().getVBox().findMachine(vmName).getState().equals(MachineState.POWERED_OFF)) {
|
||||
try {
|
||||
machineUtils.lockSessionOnMachineAndApply(vmName, LockType.Shared, new Function<ISession, Void>() {
|
||||
@Override
|
||||
public Void apply(ISession session) {
|
||||
IProgress powerDownProgress = session.getConsole().powerDown();
|
||||
powerDownProgress.waitForCompletion(-1);
|
||||
return null;
|
||||
}
|
||||
});
|
||||
} catch (RuntimeException e) {
|
||||
// sometimes the machine might be powered of between the while test and the call to
|
||||
// lockSessionOnMachineAndApply
|
||||
if (e.getMessage().contains("Invalid machine state: PoweredOff")) {
|
||||
return;
|
||||
} else if (e.getMessage().contains("VirtualBox error: The object is not ready")) {
|
||||
continue;
|
||||
} else {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public String adminDisk(String vmName) {
|
||||
return workingDir + File.separator + vmName + ".vdi";
|
||||
|
|
|
@ -0,0 +1,52 @@
|
|||
package org.jclouds.virtualbox.functions;
|
||||
|
||||
import static org.testng.Assert.assertEquals;
|
||||
|
||||
import org.jclouds.virtualbox.domain.BridgedIf;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
@Test(groups = "live", singleThreaded = true, testName = "BridgedIfStringToBridgedIfTest")
|
||||
public class BridgedIfStringToBridgedIfTest {
|
||||
|
||||
private static final String en0 = "Name: en0: Ethernet\n" +
|
||||
"GUID: 00306e65-0000-4000-8000-3c0754205d2f\n" +
|
||||
"Dhcp: Disabled\n" +
|
||||
"IPAddress: 192.168.56.1\n" +
|
||||
"NetworkMask: 255.255.255.0\n" +
|
||||
"IPV6Address: \n" +
|
||||
"IPV6NetworkMaskPrefixLength: 0\n" +
|
||||
"HardwareAddress: 3c:07:54:20:5d:2f\n" +
|
||||
"MediumType: Ethernet\n" +
|
||||
"Status: Up\n" +
|
||||
"VBoxNetworkName: HostInterfaceNetworking-en0: Ethernet\n";
|
||||
|
||||
private static final String en1 = "Name: en1: Wi-Fi (AirPort)\n" +
|
||||
"GUID: 00316e65-0000-4000-8000-28cfdaf2917a\n" +
|
||||
"Dhcp: Disabled\n" +
|
||||
"IPAddress: 192.168.57.1\n" +
|
||||
"NetworkMask: 255.255.255.0\n" +
|
||||
"IPV6Address: \n" +
|
||||
"IPV6NetworkMaskPrefixLength: 0\n" +
|
||||
"HardwareAddress: 28:cf:da:f2:91:7a\n" +
|
||||
"MediumType: Ethernet\n" +
|
||||
"Status: Up\n" +
|
||||
"VBoxNetworkName: HostInterfaceNetworking-en1: Wi-Fi (AirPort)\n";
|
||||
|
||||
private static final String p2p0 = "Name: p2p0\n" +
|
||||
"GUID: 30703270-0000-4000-8000-0acfdaf2917a\n" +
|
||||
"Dhcp: Disabled\n" +
|
||||
"IPAddress: 192.168.58.1\n" +
|
||||
"NetworkMask: 255.255.255.0\n" +
|
||||
"IPV6Address: \n" +
|
||||
"IPV6NetworkMaskPrefixLength: 0\n" +
|
||||
"HardwareAddress: 0a:cf:da:f2:91:7a\n" +
|
||||
"MediumType: Ethernet\n" +
|
||||
"Status: Down\n" +
|
||||
"VBoxNetworkName: HostInterfaceNetworking-p2p0\n";
|
||||
|
||||
@Test
|
||||
public void transformRawBridgedifToBridgedIf() {
|
||||
BridgedIf bridgedIfEn1 = new BridgedIfStringToBridgedIf().apply(en1);
|
||||
assertEquals(bridgedIfEn1.getName(), "en1: Wi-Fi (AirPort)");
|
||||
}
|
||||
}
|
|
@ -26,8 +26,6 @@ import static org.jclouds.virtualbox.config.VirtualBoxConstants.VIRTUALBOX_INSTA
|
|||
|
||||
import java.util.Map;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import org.jclouds.compute.config.BaseComputeServiceContextModule;
|
||||
import org.jclouds.compute.domain.Image;
|
||||
import org.jclouds.compute.domain.OsFamily;
|
||||
|
@ -153,21 +151,11 @@ public class CreateAndInstallVmLiveTest extends BaseVirtualBoxClientLiveTest {
|
|||
}));
|
||||
} finally {
|
||||
for (VmSpec spec : ImmutableSet.of(vmSpecification)) {
|
||||
ensureMachineHasPowerDown(spec.getVmName());
|
||||
machineController.ensureMachineHasPowerDown(spec.getVmName());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private Function<Image, String> extractId() {
|
||||
return new Function<Image, String>() {
|
||||
|
||||
@Override
|
||||
public String apply(@Nullable Image input) {
|
||||
return input.getId();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private IMachine getVmWithGuestAdditionsInstalled() {
|
||||
try {
|
||||
Injector injector = context.utils().injector();
|
||||
|
|
|
@ -25,6 +25,7 @@ import static org.testng.Assert.assertFalse;
|
|||
import java.util.List;
|
||||
|
||||
import org.jclouds.virtualbox.BaseVirtualBoxClientLiveTest;
|
||||
import org.jclouds.virtualbox.domain.BridgedIf;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
|
@ -51,13 +52,13 @@ public class RetrieveActiveBridgedInterfacesLiveTest extends BaseVirtualBoxClien
|
|||
|
||||
@Test
|
||||
public void retrieveBridgedInterfaceNamesTest() {
|
||||
List<String> activeBridgedInterfaceNames = retrieveBridgedInterfaceNames(TEST1);
|
||||
assertEquals(activeBridgedInterfaceNames, expectedBridgedInterfaces);
|
||||
List<BridgedIf> activeBridgedInterfaces = retrieveBridgedInterfaceNames(TEST1);
|
||||
assertEquals(activeBridgedInterfaces, expectedBridgedInterfaces);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void retrieveAvailableBridgedInterfaceInfoTest() {
|
||||
List<String> bridgedInterface = context.utils().injector().getInstance(RetrieveActiveBridgedInterfaces.class)
|
||||
List<BridgedIf> bridgedInterface = context.utils().injector().getInstance(RetrieveActiveBridgedInterfaces.class)
|
||||
.apply(host.get());
|
||||
assertFalse(bridgedInterface.isEmpty());
|
||||
}
|
||||
|
|
|
@ -40,7 +40,6 @@ 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.IProgress;
|
||||
import org.virtualbox_4_1.ISession;
|
||||
import org.virtualbox_4_1.LockType;
|
||||
import org.virtualbox_4_1.NetworkAttachmentType;
|
||||
|
@ -123,7 +122,7 @@ public class GuestAdditionsInstallerLiveTest extends
|
|||
}));
|
||||
} finally {
|
||||
for (VmSpec spec : ImmutableSet.of(sourceMachineSpec.getVmSpec())) {
|
||||
ensureMachineHasPowerDown(spec.getVmName());
|
||||
machineController.ensureMachineHasPowerDown(spec.getVmName());
|
||||
undoVm(spec);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue