Mitchell Hashimoto 061a91d09b 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.
2015-09-30 18:19:37 -07:00

65 lines
1.9 KiB
Ruby

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