providers/virtualbox: IPv6 host only networks

This commit is contained in:
Mitchell Hashimoto 2015-09-30 17:23:25 -07:00
parent b721eb62cf
commit ec0b0fb7f9
6 changed files with 103 additions and 30 deletions

View File

@ -1,10 +1,21 @@
require "ipaddr"
module Vagrant module Vagrant
module Util module Util
module NetworkIP module NetworkIP
# Returns the network address of the given IP and subnet. # Returns the network address of the given IP and subnet.
# #
# If the IP address is an IPv6 address, subnet should be a prefix
# length such as "64".
#
# @return [String] # @return [String]
def network_address(ip, subnet) def network_address(ip, subnet)
# If this is an IPv6 address, then just mask it
if subnet.to_s =~ /^\d+$/
ip = IPAddr.new(ip)
return ip.mask(subnet.to_i).to_s
end
ip = ip_parts(ip) ip = ip_parts(ip)
netmask = ip_parts(subnet) netmask = ip_parts(subnet)

View File

@ -1,3 +1,4 @@
require "ipaddr"
require "set" require "set"
require "log4r" require "log4r"
@ -248,7 +249,6 @@ module VagrantPlugins
auto_config: true, auto_config: true,
mac: nil, mac: nil,
nic_type: nil, nic_type: nil,
netmask: "255.255.255.0",
type: :static type: :static
}.merge(options) }.merge(options)
@ -258,6 +258,10 @@ module VagrantPlugins
# Default IP is in the 20-bit private network block for DHCP based networks # Default IP is in the 20-bit private network block for DHCP based networks
options[:ip] = "172.28.128.1" if options[:type] == :dhcp && !options[:ip] options[:ip] = "172.28.128.1" if options[:type] == :dhcp && !options[:ip]
ip = IPAddr.new(options[:ip])
if !ip.ipv6?
options[:netmask] ||= "255.255.255.0"
# Calculate our network address for the given IP/netmask # Calculate our network address for the given IP/netmask
netaddr = network_address(options[:ip], options[:netmask]) netaddr = network_address(options[:ip], options[:netmask])
@ -282,6 +286,16 @@ module VagrantPlugins
adapter_ip = ip_parts.dup adapter_ip = ip_parts.dup
adapter_ip[3] += 1 adapter_ip[3] += 1
options[:adapter_ip] ||= adapter_ip.join(".") options[:adapter_ip] ||= adapter_ip.join(".")
else
# Default subnet prefix length
options[:netmask] ||= 64
# IPv6 we just mask the address and use that as the adapter
options[:adapter_ip] ||= ip.mask(options[:netmask].to_i).to_s
# Append a 6 to the end of the type
options[:type] = "#{options[:type]}6".to_sym
end
dhcp_options = {} dhcp_options = {}
if options[:type] == :dhcp if options[:type] == :dhcp
@ -456,10 +470,18 @@ module VagrantPlugins
@env[:machine].provider.driver.read_host_only_interfaces.each do |interface| @env[:machine].provider.driver.read_host_only_interfaces.each do |interface|
return interface if config[:name] && config[:name] == interface[:name] return interface if config[:name] && config[:name] == interface[:name]
if interface[:ip] != ""
return interface if this_netaddr == \ return interface if this_netaddr == \
network_address(interface[:ip], interface[:netmask]) network_address(interface[:ip], interface[:netmask])
end end
if interface[:ipv6] != ""
return interface if this_netaddr == \
network_address(interface[:ipv6], interface[:ipv6_prefix])
end
end
nil nil
end end

View File

@ -1,3 +1,4 @@
require 'ipaddr'
require 'log4r' require 'log4r'
require "vagrant/util/platform" require "vagrant/util/platform"
@ -48,10 +49,19 @@ module VagrantPlugins
execute("hostonlyif", "create") =~ /^Interface '(.+?)' was successfully created$/ execute("hostonlyif", "create") =~ /^Interface '(.+?)' was successfully created$/
name = $1.to_s name = $1.to_s
# Configure it # Get the IP so we can determine v4 vs v6
ip = IPAddr.new(options[:adapter_ip])
# Configure
if ip.ipv4?
execute("hostonlyif", "ipconfig", name, execute("hostonlyif", "ipconfig", name,
"--ip", options[:adapter_ip], "--ip", options[:adapter_ip],
"--netmask", options[:netmask]) "--netmask", options[:netmask])
elsif ip.ipv6?
execute("hostonlyif", "ipconfig", name,
"--ipv6", options[:adapter_ip],
"--netmasklengthv6", options[:netmask])
end
# Return the details # Return the details
return { return {
@ -366,6 +376,10 @@ module VagrantPlugins
info[:ip] = $1.to_s info[:ip] = $1.to_s
elsif line =~ /^NetworkMask:\s+(.+?)$/ elsif line =~ /^NetworkMask:\s+(.+?)$/
info[:netmask] = $1.to_s info[:netmask] = $1.to_s
elsif line =~ /^IPV6Address:\s+(.+?)$/
info[:ipv6] = $1.to_s.strip
elsif line =~ /^IPV6NetworkMaskPrefixLength:\s+(.+?)$/
info[:ipv6_prefix] = $1.to_s.strip
elsif line =~ /^Status:\s+(.+?)$/ elsif line =~ /^Status:\s+(.+?)$/
info[:status] = $1.to_s info[:status] = $1.to_s
end end

View File

@ -366,6 +366,10 @@ module VagrantPlugins
info[:ip] = $1.to_s info[:ip] = $1.to_s
elsif line =~ /^NetworkMask:\s+(.+?)$/ elsif line =~ /^NetworkMask:\s+(.+?)$/
info[:netmask] = $1.to_s info[:netmask] = $1.to_s
elsif line =~ /^IPV6Address:\s+(.+?)$/
info[:ipv6] = $1.to_s
elsif line =~ /^IPV6NetworkMaskPrefixLength:\s+(.+?)$/
info[:ipv6_prefix] = $1.to_s
elsif line =~ /^Status:\s+(.+?)$/ elsif line =~ /^Status:\s+(.+?)$/
info[:status] = $1.to_s info[:status] = $1.to_s
end end

View File

@ -0,0 +1,10 @@
#VAGRANT-BEGIN
# The contents below are automatically generated by Vagrant. Do not modify.
auto eth<%= options[:interface] %>
iface eth<%= options[:interface] %> inet6 static
address <%= options[:ip] %>
netmask <%= options[:netmask] %>
<% if options[:gateway] %>
gateway <%= options[:gateway] %>
<% end %>
#VAGRANT-END

View File

@ -13,5 +13,17 @@ describe Vagrant::Util::NetworkIP do
it "calculates it properly" do it "calculates it properly" do
expect(klass.network_address("192.168.2.234", "255.255.255.0")).to eq("192.168.2.0") expect(klass.network_address("192.168.2.234", "255.255.255.0")).to eq("192.168.2.0")
end end
it "calculates it properly with integer submask" do
expect(klass.network_address("192.168.2.234", "24")).to eq("192.168.2.0")
end
it "calculates it properly for IPv6" do
expect(klass.network_address("fde4:8dba:82e1::c4", "64")).to eq("fde4:8dba:82e1::")
end
it "calculates it properly for IPv6" do
expect(klass.network_address("fde4:8dba:82e1::c4", 64)).to eq("fde4:8dba:82e1::")
end
end end
end end