Host only networks now work with VBoxManage
This commit is contained in:
parent
79460f6122
commit
ecbf7df859
|
@ -8,10 +8,6 @@ module Vagrant
|
||||||
@app = app
|
@app = app
|
||||||
@env = env
|
@env = env
|
||||||
|
|
||||||
if enable_network? && Util::Platform.windows? && Util::Platform.bit64?
|
|
||||||
raise Errors::NetworkNotImplemented
|
|
||||||
end
|
|
||||||
|
|
||||||
env[:vm].config.vm.network_options.compact.each do |network_options|
|
env[:vm].config.vm.network_options.compact.each do |network_options|
|
||||||
raise Errors::NetworkCollision if !verify_no_bridge_collision(network_options)
|
raise Errors::NetworkCollision if !verify_no_bridge_collision(network_options)
|
||||||
end
|
end
|
||||||
|
@ -42,17 +38,8 @@ module Vagrant
|
||||||
# Verifies that there is no collision with a bridged network interface
|
# Verifies that there is no collision with a bridged network interface
|
||||||
# for the given network options.
|
# for the given network options.
|
||||||
def verify_no_bridge_collision(net_options)
|
def verify_no_bridge_collision(net_options)
|
||||||
interfaces = VirtualBox::Global.global.host.network_interfaces
|
@env[:vm].driver.read_bridged_interfaces.each do |interface|
|
||||||
interfaces.each do |ni|
|
return false if matching_network?(interface, net_options)
|
||||||
next if ni.interface_type == :host_only
|
|
||||||
|
|
||||||
result = if net_options[:name]
|
|
||||||
true if net_options[:name] == ni.name
|
|
||||||
else
|
|
||||||
true if matching_network?(ni, net_options)
|
|
||||||
end
|
|
||||||
|
|
||||||
return false if result
|
|
||||||
end
|
end
|
||||||
|
|
||||||
true
|
true
|
||||||
|
@ -67,51 +54,75 @@ module Vagrant
|
||||||
def assign_network
|
def assign_network
|
||||||
@env[:ui].info I18n.t("vagrant.actions.vm.network.preparing")
|
@env[:ui].info I18n.t("vagrant.actions.vm.network.preparing")
|
||||||
|
|
||||||
|
networks = @env[:vm].driver.read_host_only_interfaces
|
||||||
|
adapters = []
|
||||||
|
|
||||||
|
# Build the networks and the list of adapters we need to enable
|
||||||
@env[:vm].config.vm.network_options.compact.each do |network_options|
|
@env[:vm].config.vm.network_options.compact.each do |network_options|
|
||||||
adapter = @env["vm"].vm.network_adapters[network_options[:adapter]]
|
network = find_matching_network(networks, network_options)
|
||||||
adapter.enabled = true
|
|
||||||
adapter.attachment_type = :host_only
|
if !network
|
||||||
adapter.host_only_interface = network_name(network_options)
|
# It is an error case if a specific name was given but the network
|
||||||
adapter.mac_address = network_options[:mac].gsub(':', '') if network_options[:mac]
|
# doesn't exist.
|
||||||
adapter.save
|
if network_options[:name]
|
||||||
|
raise Errors::NetworkNotFound, :name => network_options[:name]
|
||||||
|
end
|
||||||
|
|
||||||
|
# Otherwise, we create a new network and put the net network
|
||||||
|
# in the list of available networks so other network definitions
|
||||||
|
# can use it!
|
||||||
|
network = create_network(network_options)
|
||||||
|
networks << network
|
||||||
|
end
|
||||||
|
|
||||||
|
adapters << {
|
||||||
|
:adapter => network_options[:adapter] + 1,
|
||||||
|
:type => :hostonly,
|
||||||
|
:hostonly => network[:name],
|
||||||
|
:mac_address => network_options[:mac]
|
||||||
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Enable the host only adapters!
|
||||||
|
@env[:vm].driver.enable_adapters(adapters)
|
||||||
end
|
end
|
||||||
|
|
||||||
# Returns the name of the proper host only network, or creates
|
# This looks through a list of available host only networks and
|
||||||
# it if it does not exist. Vagrant determines if the host only
|
# finds a matching network.
|
||||||
# network exists by comparing the netmask and the IP.
|
#
|
||||||
def network_name(net_options)
|
# If one is not available, `nil` is returned.
|
||||||
# First try to find a matching network
|
def find_matching_network(networks, needle_options)
|
||||||
interfaces = VirtualBox::Global.global.host.network_interfaces
|
networks.each do |network|
|
||||||
interfaces.each do |ni|
|
if needle_options[:name] && needle_options[:name] == network[:name]
|
||||||
# Ignore non-host only interfaces which may also match,
|
return network
|
||||||
# since they're not valid options.
|
elsif matching_network?(network, needle_options)
|
||||||
next if ni.interface_type != :host_only
|
return network
|
||||||
|
|
||||||
if net_options[:name]
|
|
||||||
return ni.name if net_options[:name] == ni.name
|
|
||||||
else
|
|
||||||
return ni.name if matching_network?(ni, net_options)
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
raise Errors::NetworkNotFound, :name => net_options[:name] if net_options[:name]
|
nil
|
||||||
|
end
|
||||||
|
|
||||||
# One doesn't exist, create it.
|
# Creates a host only network with the given options and returns
|
||||||
@env[:ui].info I18n.t("vagrant.actions.vm.network.creating")
|
# the hash of the options it was created with.
|
||||||
|
#
|
||||||
|
# @return [Hash]
|
||||||
|
def create_network(network_options)
|
||||||
|
# Create the options for the host only network, specifically
|
||||||
|
# figuring out the host only network IP based on the netmask.
|
||||||
|
options = network_options.merge({
|
||||||
|
:ip => network_ip(network_options[:ip], network_options[:netmask])
|
||||||
|
})
|
||||||
|
|
||||||
ni = interfaces.create
|
@env[:vm].driver.create_host_only_network(options)
|
||||||
ni.enable_static(network_ip(net_options[:ip], net_options[:netmask]),
|
|
||||||
net_options[:netmask])
|
|
||||||
ni.name
|
|
||||||
end
|
end
|
||||||
|
|
||||||
# Tests if a network matches the given options by applying the
|
# Tests if a network matches the given options by applying the
|
||||||
# netmask to the IP of the network and also to the IP of the
|
# netmask to the IP of the network and also to the IP of the
|
||||||
# virtual machine and see if they match.
|
# virtual machine and see if they match.
|
||||||
def matching_network?(interface, net_options)
|
def matching_network?(interface, net_options)
|
||||||
interface.network_mask == net_options[:netmask] &&
|
interface[:netmask] == net_options[:netmask] &&
|
||||||
apply_netmask(interface.ip_address, interface.network_mask) ==
|
apply_netmask(interface[:ip], interface[:netmask]) ==
|
||||||
apply_netmask(net_options[:ip], net_options[:netmask])
|
apply_netmask(net_options[:ip], net_options[:netmask])
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -47,6 +47,25 @@ module Vagrant
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Creates a host only network with the given options.
|
||||||
|
def create_host_only_network(options)
|
||||||
|
# Create the interface
|
||||||
|
execute("hostonlyif", "create") =~ /^Interface '(.+?)' was successfully created$/
|
||||||
|
name = $1.to_s
|
||||||
|
|
||||||
|
# Configure it
|
||||||
|
execute("hostonlyif", "ipconfig", name,
|
||||||
|
"--ip", options[:ip],
|
||||||
|
"--netmask", options[:netmask])
|
||||||
|
|
||||||
|
# Return the details
|
||||||
|
return {
|
||||||
|
:name => name,
|
||||||
|
:ip => options[:ip],
|
||||||
|
:netmask => options[:netmask]
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
# This deletes the VM with the given name.
|
# This deletes the VM with the given name.
|
||||||
def delete
|
def delete
|
||||||
execute("unregistervm", @uuid, "--delete")
|
execute("unregistervm", @uuid, "--delete")
|
||||||
|
@ -79,6 +98,26 @@ module Vagrant
|
||||||
raw(*command)
|
raw(*command)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Enables network adapters on this virtual machine.
|
||||||
|
def enable_adapters(adapters)
|
||||||
|
args = []
|
||||||
|
adapters.each do |adapter|
|
||||||
|
args.concat(["--nic#{adapter[:adapter]}", adapter[:type].to_s])
|
||||||
|
|
||||||
|
if adapter[:hostonly]
|
||||||
|
args.concat(["--hostonlyadapter#{adapter[:adapter]}",
|
||||||
|
adapter[:hostonly]])
|
||||||
|
end
|
||||||
|
|
||||||
|
if adapter[:mac_address]
|
||||||
|
args.concat(["--macaddress#{adapter[:adapter]}",
|
||||||
|
adapter[:mac_address]])
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
execute("modifyvm", @uuid, *args)
|
||||||
|
end
|
||||||
|
|
||||||
# Forwards a set of ports for a VM.
|
# Forwards a set of ports for a VM.
|
||||||
#
|
#
|
||||||
# This will not affect any previously set forwarded ports,
|
# This will not affect any previously set forwarded ports,
|
||||||
|
@ -173,6 +212,47 @@ module Vagrant
|
||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# This reads the list of host only networks.
|
||||||
|
def read_bridged_interfaces
|
||||||
|
execute("list", "bridgedifs").split("\n\n").collect do |block|
|
||||||
|
info = {}
|
||||||
|
|
||||||
|
block.split("\n").each do |line|
|
||||||
|
if line =~ /^Name:\s+(.+?)$/
|
||||||
|
info[:name] = $1.to_s
|
||||||
|
elsif line =~ /^IPAddress:\s+(.+?)$/
|
||||||
|
info[:ip] = $1.to_s
|
||||||
|
elsif line =~ /^NetworkMask:\s+(.+?)$/
|
||||||
|
info[:netmask] = $1.to_s
|
||||||
|
elsif line =~ /^Status:\s+(.+?)$/
|
||||||
|
info[:status] = $1.to_s
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# Return the info to build up the results
|
||||||
|
info
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# Reads and returns the available host only interfaces.
|
||||||
|
def read_host_only_interfaces
|
||||||
|
execute("list", "hostonlyifs").split("\n\n").collect do |block|
|
||||||
|
info = {}
|
||||||
|
|
||||||
|
block.split("\n").each do |line|
|
||||||
|
if line =~ /^Name:\s+(.+?)$/
|
||||||
|
info[:name] = $1.to_s
|
||||||
|
elsif line =~ /^IPAddress:\s+(.+?)$/
|
||||||
|
info[:ip] = $1.to_s
|
||||||
|
elsif line =~ /^NetworkMask:\s+(.+?)$/
|
||||||
|
info[:netmask] = $1.to_s
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
info
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
# This reads the folder where VirtualBox places it's VMs.
|
# This reads the folder where VirtualBox places it's VMs.
|
||||||
def read_machine_folder
|
def read_machine_folder
|
||||||
execute("list", "systemproperties").split("\n").each do |line|
|
execute("list", "systemproperties").split("\n").each do |line|
|
||||||
|
|
|
@ -208,13 +208,6 @@ module Vagrant
|
||||||
error_key(:not_found, "vagrant.actions.vm.network")
|
error_key(:not_found, "vagrant.actions.vm.network")
|
||||||
end
|
end
|
||||||
|
|
||||||
# Note: This is a temporary error for Windows users while host-only
|
|
||||||
# networking doesn't quite work.
|
|
||||||
class NetworkNotImplemented < VagrantError
|
|
||||||
status_code(49)
|
|
||||||
error_key(:windows_not_implemented, "vagrant.actions.vm.network")
|
|
||||||
end
|
|
||||||
|
|
||||||
class NFSHostRequired < VagrantError
|
class NFSHostRequired < VagrantError
|
||||||
status_code(31)
|
status_code(31)
|
||||||
error_key(:host_required, "vagrant.actions.vm.nfs")
|
error_key(:host_required, "vagrant.actions.vm.nfs")
|
||||||
|
|
|
@ -397,11 +397,6 @@ en:
|
||||||
host only network for you. Alternatively, please create the
|
host only network for you. Alternatively, please create the
|
||||||
specified network manually.
|
specified network manually.
|
||||||
preparing: "Preparing host only network..."
|
preparing: "Preparing host only network..."
|
||||||
windows_not_implemented: |-
|
|
||||||
Host only networking is currently broken on Windows due to a bug
|
|
||||||
in jruby-win32ole. When the bug is fixed, a patch release for Vagrant
|
|
||||||
will be released to remove this error. Until then, please just use
|
|
||||||
forwarded ports.
|
|
||||||
nfs:
|
nfs:
|
||||||
host_required: |-
|
host_required: |-
|
||||||
A host class is required for NFS shared folders. By default, these
|
A host class is required for NFS shared folders. By default, these
|
||||||
|
|
Loading…
Reference in New Issue