mirror of https://github.com/apache/jclouds.git
issue 384: added support for creation of hostOnly interface with DHCP enabled
This commit is contained in:
parent
af309232ad
commit
50815d2483
|
@ -172,7 +172,7 @@ public class IMachineToNodeMetadata implements Function<IMachine, NodeMetadata>
|
|||
}
|
||||
}
|
||||
nodeMetadataBuilder.publicAddresses(publicIpAddresses);
|
||||
nodeMetadataBuilder.privateAddresses(privateIpAddresses);
|
||||
nodeMetadataBuilder.privateAddresses(publicIpAddresses);
|
||||
|
||||
return nodeMetadataBuilder;
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/**
|
||||
/**
|
||||
* Licensed to jclouds, Inc. (jclouds) under one or more
|
||||
* contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
|
@ -20,19 +20,26 @@
|
|||
package org.jclouds.virtualbox.functions;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
import static com.google.common.base.Preconditions.checkState;
|
||||
import static org.jclouds.compute.options.RunScriptOptions.Builder.runAsRoot;
|
||||
import static org.jclouds.virtualbox.config.VirtualBoxConstants.VIRTUALBOX_IMAGE_PREFIX;
|
||||
import static org.jclouds.virtualbox.config.VirtualBoxConstants.VIRTUALBOX_NODE_NAME_SEPARATOR;
|
||||
import static org.jclouds.virtualbox.config.VirtualBoxConstants.VIRTUALBOX_NODE_PREFIX;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import org.jclouds.compute.ComputeServiceAdapter.NodeAndInitialCredentials;
|
||||
import org.jclouds.compute.callables.RunScriptOnNode;
|
||||
import org.jclouds.compute.callables.RunScriptOnNode.Factory;
|
||||
import org.jclouds.compute.domain.ExecResponse;
|
||||
import org.jclouds.compute.domain.NodeMetadata;
|
||||
import org.jclouds.compute.domain.NodeMetadataBuilder;
|
||||
import org.jclouds.compute.options.RunScriptOptions;
|
||||
import org.jclouds.domain.LoginCredentials;
|
||||
import org.jclouds.scriptbuilder.domain.Statements;
|
||||
import org.jclouds.virtualbox.config.VirtualBoxComputeServiceContextModule;
|
||||
import org.jclouds.virtualbox.domain.CloneSpec;
|
||||
import org.jclouds.virtualbox.domain.Master;
|
||||
|
@ -46,6 +53,9 @@ import org.jclouds.virtualbox.statements.EnableNetworkInterface;
|
|||
import org.jclouds.virtualbox.util.MachineController;
|
||||
import org.jclouds.virtualbox.util.MachineUtils;
|
||||
import org.virtualbox_4_1.CleanupMode;
|
||||
import org.virtualbox_4_1.HostNetworkInterfaceType;
|
||||
import org.virtualbox_4_1.IDHCPServer;
|
||||
import org.virtualbox_4_1.IHostNetworkInterface;
|
||||
import org.virtualbox_4_1.IMachine;
|
||||
import org.virtualbox_4_1.IProgress;
|
||||
import org.virtualbox_4_1.ISession;
|
||||
|
@ -53,8 +63,10 @@ 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.collect.ImmutableSet;
|
||||
import com.google.common.collect.Iterables;
|
||||
|
||||
/**
|
||||
* Creates nodes, by cloning a master vm and based on the provided {@link NodeSpec}. Must be
|
||||
|
@ -66,19 +78,23 @@ import com.google.common.collect.ImmutableSet;
|
|||
@Singleton
|
||||
public class NodeCreator implements Function<NodeSpec, NodeAndInitialCredentials<IMachine>> {
|
||||
|
||||
// TODO parameterize
|
||||
public static final String HOST_ONLY_IFACE_NAME = "vboxnet0";
|
||||
|
||||
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;
|
||||
|
||||
|
||||
@Inject
|
||||
public NodeCreator(Supplier<VirtualBoxManager> manager, Function<CloneSpec, IMachine> cloner,
|
||||
public NodeCreator(Supplier<VirtualBoxManager> manager, Function<CloneSpec, IMachine> cloner, Factory runScriptOnNodeFactory,
|
||||
Supplier<NodeMetadata> host,
|
||||
MachineUtils machineUtils, RunScriptOnNode.Factory scriptRunnerFactory, MachineController machineController) {
|
||||
this.manager = manager;
|
||||
this.cloner = cloner;
|
||||
this.runScriptOnNodeFactory = checkNotNull(runScriptOnNodeFactory, "runScriptOnNodeFactory");
|
||||
this.host = checkNotNull(host, "host");
|
||||
|
||||
this.machineUtils = machineUtils;
|
||||
this.machineController = machineController;
|
||||
}
|
||||
|
@ -118,8 +134,11 @@ public class NodeCreator implements Function<NodeSpec, NodeAndInitialCredentials
|
|||
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(HOST_ONLY_IFACE_NAME).slot(0L).build();
|
||||
.addHostInterfaceName(hostOnlyIfName).slot(0L).build();
|
||||
|
||||
NetworkSpec networkSpec = createNetworkSpecForHostOnlyNATNICs(natIfaceCard, hostOnlyIfaceCard);
|
||||
|
||||
|
@ -166,4 +185,93 @@ public class NodeCreator implements Function<NodeSpec, NodeAndInitialCredentials
|
|||
return NetworkSpec.builder().addNIC(natIfaceCard).addNIC(hostOnlyIfaceCard).build();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return
|
||||
*/
|
||||
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 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";
|
||||
|
||||
ExecResponse response = runScriptOnNodeFactory
|
||||
.create(host.get(),
|
||||
Statements.exec(String
|
||||
.format("VBoxManage dhcpserver add --ifname %s --ip %s --netmask %s --lowerip %s --upperip %s --enable",
|
||||
hostOnlyIfName, dhcpIpAddress, dhcpNetmask, dhcpLowerIp, dhcpUpperIp)), runAsRoot(false).wrapInInitScript(false)).init().call();
|
||||
checkState(response.getExitStatus()==0);
|
||||
/*
|
||||
runScriptOnNodeFactory
|
||||
.create(host.get(),
|
||||
Statements.exec(String.format("VBoxManage hostonlyif ipconfig %s --ip %s",
|
||||
hostOnlyIfName, hostOnlyIfIpAddress)), runAsRoot(false).wrapInInitScript(false)).init().call();
|
||||
*/
|
||||
}
|
||||
|
||||
private String createHostOnlyIf() {
|
||||
final String hostOnlyIfName;
|
||||
ExecResponse createHostOnyResponse = runScriptOnNodeFactory
|
||||
.create(host.get(), Statements.exec("VBoxManage hostonlyif create"),
|
||||
runAsRoot(false).wrapInInitScript(false)).init().call();
|
||||
String output = createHostOnyResponse.getOutput();
|
||||
checkState(createHostOnyResponse.getExitStatus()==0);
|
||||
checkState(output.contains("'"), "cannot create hostonlyif");
|
||||
hostOnlyIfName = output.substring(output.indexOf("'") + 1, output.lastIndexOf("'"));
|
||||
return hostOnlyIfName;
|
||||
}
|
||||
|
||||
private IHostNetworkInterface returnExistingHostNetworkInterfaceWithDHCPenabledOrNull(Iterable<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;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue