providers/virtualbox: workaround IPv6 routing bug in VB
VirtualBox has a bug where the IPv6 route is lost on every other configuration of a host-only network. This is also triggered when a VM is booted. To fix this, we test the route-ability of all IPv6 networks, and reconfigure if necessary. This is very fast but we still only do this if we have any IPv6 networks.
This commit is contained in:
parent
0d50f454ea
commit
061a91d09b
|
@ -30,6 +30,7 @@ module VagrantPlugins
|
|||
autoload :MessageNotRunning, File.expand_path("../action/message_not_running", __FILE__)
|
||||
autoload :MessageWillNotDestroy, File.expand_path("../action/message_will_not_destroy", __FILE__)
|
||||
autoload :Network, File.expand_path("../action/network", __FILE__)
|
||||
autoload :NetworkFixIPv6, File.expand_path("../action/network_fix_ipv6", __FILE__)
|
||||
autoload :Package, File.expand_path("../action/package", __FILE__)
|
||||
autoload :PackageVagrantfile, File.expand_path("../action/package_vagrantfile", __FILE__)
|
||||
autoload :PrepareNFSSettings, File.expand_path("../action/prepare_nfs_settings", __FILE__)
|
||||
|
@ -63,6 +64,7 @@ module VagrantPlugins
|
|||
b.use PrepareNFSSettings
|
||||
b.use ClearNetworkInterfaces
|
||||
b.use Network
|
||||
b.use NetworkFixIPv6
|
||||
b.use ForwardPorts
|
||||
b.use SetHostname
|
||||
b.use SaneDefaults
|
||||
|
|
|
@ -0,0 +1,64 @@
|
|||
require "ipaddr"
|
||||
require "socket"
|
||||
|
||||
require "log4r"
|
||||
|
||||
require "vagrant/util/scoped_hash_override"
|
||||
|
||||
module VagrantPlugins
|
||||
module ProviderVirtualBox
|
||||
module Action
|
||||
# This middleware works around a bug in VirtualBox where booting
|
||||
# a VM with an IPv6 host-only network will someties lose the
|
||||
# route to that machine.
|
||||
class NetworkFixIPv6
|
||||
include Vagrant::Util::ScopedHashOverride
|
||||
|
||||
def initialize(app, env)
|
||||
@logger = Log4r::Logger.new("vagrant::plugins::virtualbox::network")
|
||||
@app = app
|
||||
end
|
||||
|
||||
def call(env)
|
||||
@env = env
|
||||
|
||||
# Determine if we have an IPv6 network
|
||||
has_v6 = false
|
||||
env[:machine].config.vm.networks.each do |type, options|
|
||||
next if type != :private_network
|
||||
options = scoped_hash_override(options, :virtualbox)
|
||||
next if options[:ip] == ""
|
||||
if IPAddr.new(options[:ip]).ipv6?
|
||||
has_v6 = true
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
# Call up
|
||||
@app.call(env)
|
||||
|
||||
# If we have no IPv6, forget it
|
||||
return if !has_v6
|
||||
|
||||
# We do, so fix them if we must
|
||||
env[:machine].provider.driver.read_host_only_interfaces.each do |interface|
|
||||
# Ignore interfaces without an IPv6 address
|
||||
next if interface[:ipv6] == ""
|
||||
|
||||
# Make the test IP. This is just the highest value IP
|
||||
ip = IPAddr.new(interface[:ipv6])
|
||||
ip |= IPAddr.new(":#{":FFFF" * (interface[:ipv6_prefix].to_i / 16)}")
|
||||
|
||||
@logger.info("testing IPv6: #{ip}")
|
||||
begin
|
||||
UDPSocket.new(Socket::AF_INET6).connect(ip.to_s, 80)
|
||||
rescue Errno::EHOSTUNREACH
|
||||
@logger.info("IPv6 host unreachable. Fixing: #{ip}")
|
||||
env[:machine].provider.driver.reconfig_host_only(interface)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -263,6 +263,14 @@ module VagrantPlugins
|
|||
def read_vms
|
||||
end
|
||||
|
||||
# Reconfigure the hostonly network given by interface (the result
|
||||
# of read_host_only_networks). This is a sad function that only
|
||||
# exists to work around VirtualBox bugs.
|
||||
#
|
||||
# @return nil
|
||||
def reconfig_host_only(interface)
|
||||
end
|
||||
|
||||
# Removes the DHCP server identified by the provided network name.
|
||||
#
|
||||
# @param [String] network_name The the full network name associated
|
||||
|
|
|
@ -109,6 +109,7 @@ module VagrantPlugins
|
|||
:read_state,
|
||||
:read_used_ports,
|
||||
:read_vms,
|
||||
:reconfig_host_only,
|
||||
:remove_dhcp_server,
|
||||
:resume,
|
||||
:set_mac_address,
|
||||
|
|
|
@ -72,6 +72,11 @@ module VagrantPlugins
|
|||
}
|
||||
end
|
||||
|
||||
def reconfig_host_only(interface)
|
||||
execute("hostonlyif", "ipconfig", interface[:name],
|
||||
"--ipv6", interface[:ipv6])
|
||||
end
|
||||
|
||||
def delete
|
||||
execute("unregistervm", @uuid, "--delete")
|
||||
end
|
||||
|
|
|
@ -488,6 +488,11 @@ module VagrantPlugins
|
|||
results
|
||||
end
|
||||
|
||||
def reconfig_host_only(interface)
|
||||
execute("hostonlyif", "ipconfig", interface[:name],
|
||||
"--ipv6", interface[:ipv6])
|
||||
end
|
||||
|
||||
def remove_dhcp_server(network_name)
|
||||
execute("dhcpserver", "remove", "--netname", network_name)
|
||||
end
|
||||
|
|
Loading…
Reference in New Issue