diff --git a/plugins/providers/virtualbox/action.rb b/plugins/providers/virtualbox/action.rb index 83eb3aec9..0d8fc8e38 100644 --- a/plugins/providers/virtualbox/action.rb +++ b/plugins/providers/virtualbox/action.rb @@ -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 diff --git a/plugins/providers/virtualbox/action/network_fix_ipv6.rb b/plugins/providers/virtualbox/action/network_fix_ipv6.rb new file mode 100644 index 000000000..eb4ca48ef --- /dev/null +++ b/plugins/providers/virtualbox/action/network_fix_ipv6.rb @@ -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 diff --git a/plugins/providers/virtualbox/driver/base.rb b/plugins/providers/virtualbox/driver/base.rb index 112e97d5b..768bd9cef 100644 --- a/plugins/providers/virtualbox/driver/base.rb +++ b/plugins/providers/virtualbox/driver/base.rb @@ -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 diff --git a/plugins/providers/virtualbox/driver/meta.rb b/plugins/providers/virtualbox/driver/meta.rb index 10bef3f8f..242372452 100644 --- a/plugins/providers/virtualbox/driver/meta.rb +++ b/plugins/providers/virtualbox/driver/meta.rb @@ -109,6 +109,7 @@ module VagrantPlugins :read_state, :read_used_ports, :read_vms, + :reconfig_host_only, :remove_dhcp_server, :resume, :set_mac_address, diff --git a/plugins/providers/virtualbox/driver/version_4_3.rb b/plugins/providers/virtualbox/driver/version_4_3.rb index b3d29c6c8..3b08d43cd 100644 --- a/plugins/providers/virtualbox/driver/version_4_3.rb +++ b/plugins/providers/virtualbox/driver/version_4_3.rb @@ -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 diff --git a/plugins/providers/virtualbox/driver/version_5_0.rb b/plugins/providers/virtualbox/driver/version_5_0.rb index a9aad8442..c58bae3c0 100644 --- a/plugins/providers/virtualbox/driver/version_5_0.rb +++ b/plugins/providers/virtualbox/driver/version_5_0.rb @@ -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