Fix for #4608
Added support for Port forwarding in an IP aliased environment. The change makes the following forwarding rule(s) possible. Ex: eth0 is ip aliased to have a range of IP addresses 10.20.30.0/24. In the Vagrant file, we can now have an entry like the following and it will just work! Note the host port 8081 is the same for both .1 and .2. Vagrant.configure("2") do |config| config.vm.network "forwarded_port", guest: 80, host: 8080 config.vm.network "forwarded_port", guest: 81, host: 8081, host_ip: 10.20.30.1 config.vm.network "forwarded_port", guest: 82, host: 8081, host_ip: 10.20.30.2 end
This commit is contained in:
parent
b99ed21506
commit
af9d0df635
|
@ -62,7 +62,7 @@ module Vagrant
|
|||
@logger.info("Detecting any forwarded port collisions...")
|
||||
|
||||
# Get the extra ports we consider in use
|
||||
extra_in_use = env[:port_collision_extra_in_use] || []
|
||||
extra_in_use = env[:port_collision_extra_in_use] || {}
|
||||
|
||||
# Get the remap
|
||||
remap = env[:port_collision_remap] || {}
|
||||
|
@ -81,7 +81,7 @@ module Vagrant
|
|||
|
||||
# Determine a list of usable ports for repair
|
||||
usable_ports = Set.new(env[:machine].config.vm.usable_port_range)
|
||||
usable_ports.subtract(extra_in_use)
|
||||
usable_ports.subtract(extra_in_use.keys)
|
||||
|
||||
# Pass one, remove all defined host ports from usable ports
|
||||
with_forwarded_ports(env) do |options|
|
||||
|
@ -92,6 +92,7 @@ module Vagrant
|
|||
with_forwarded_ports(env) do |options|
|
||||
guest_port = options[:guest]
|
||||
host_port = options[:host]
|
||||
host_ip = options[:host_ip]
|
||||
|
||||
if options[:protocol] && options[:protocol] != "tcp"
|
||||
@logger.debug("Skipping #{host_port} because UDP protocol.")
|
||||
|
@ -105,9 +106,9 @@ module Vagrant
|
|||
end
|
||||
|
||||
# If the port is open (listening for TCP connections)
|
||||
in_use = extra_in_use.include?(host_port) ||
|
||||
port_checker[host_port] ||
|
||||
lease_check(host_port)
|
||||
in_use = is_forwarded_already(extra_in_use, host_port, host_ip) ||
|
||||
port_checker[host_ip, host_port] ||
|
||||
lease_check(host_ip, host_port)
|
||||
if in_use
|
||||
if !repair || !options[:auto_correct]
|
||||
raise Errors::ForwardPortCollision,
|
||||
|
@ -124,9 +125,9 @@ module Vagrant
|
|||
usable_ports.delete(repaired_port)
|
||||
|
||||
# If the port is in use, then we can't use this either...
|
||||
in_use = extra_in_use.include?(repaired_port) ||
|
||||
port_checker[repaired_port] ||
|
||||
lease_check(repaired_port)
|
||||
in_use = is_forwarded_already(extra_in_use, repaired_port, host_ip) ||
|
||||
port_checker[host_ip, repaired_port] ||
|
||||
lease_check(host_ip, repaired_port)
|
||||
if in_use
|
||||
@logger.info("Repaired port also in use: #{repaired_port}. Trying another...")
|
||||
next
|
||||
|
@ -158,13 +159,19 @@ module Vagrant
|
|||
end
|
||||
end
|
||||
|
||||
def lease_check(port)
|
||||
def lease_check(host_ip=nil, host_port)
|
||||
# Check if this port is "leased". We use a leasing system of
|
||||
# about 60 seconds to avoid any forwarded port collisions in
|
||||
# a highly parallelized environment.
|
||||
leasedir = @machine.env.data_dir.join("fp-leases")
|
||||
leasedir.mkpath
|
||||
|
||||
if host_ip.nil?
|
||||
lease_file_name = host_port.to_s
|
||||
else
|
||||
lease_file_name = "#{host_ip.gsub('.','_')}_#{host_port.to_s}"
|
||||
end
|
||||
|
||||
invalid = false
|
||||
oldest = Time.now.to_i - 60
|
||||
leasedir.children.each do |child|
|
||||
|
@ -173,7 +180,7 @@ module Vagrant
|
|||
child.delete
|
||||
end
|
||||
|
||||
if child.basename.to_s == port.to_s
|
||||
if child.basename.to_s == lease_file_name
|
||||
invalid = true
|
||||
end
|
||||
end
|
||||
|
@ -182,13 +189,13 @@ module Vagrant
|
|||
return true if invalid
|
||||
|
||||
# Otherwise, create the lease
|
||||
leasedir.join(port.to_s).open("w+") do |f|
|
||||
leasedir.join(lease_file_name).open("w+") do |f|
|
||||
f.binmode
|
||||
f.write(Time.now.to_i.to_s + "\n")
|
||||
end
|
||||
|
||||
# Add to the leased array so we unlease it right away
|
||||
@leased << port.to_s
|
||||
@leased << lease_file_name
|
||||
|
||||
# Things look good to us!
|
||||
false
|
||||
|
@ -203,8 +210,32 @@ module Vagrant
|
|||
end
|
||||
end
|
||||
|
||||
def port_check(port)
|
||||
is_port_open?("127.0.0.1", port)
|
||||
# This functions checks to see if the current instance's hostport and
|
||||
# hostip for forwarding is in use by the virtual machines created
|
||||
# previously.
|
||||
def is_forwarded_already(extra_in_use, hostport, hostip)
|
||||
hostip = '*' if hostip.nil? || hostip.empty?
|
||||
# ret. false if none of the VMs we spun up had this port forwarded.
|
||||
return false if not extra_in_use.has_key?(hostport)
|
||||
|
||||
# ret. true if the user has requested to bind on all interfaces but
|
||||
# we already have a rule in one the VMs we spun up.
|
||||
if hostip == '*'
|
||||
if extra_in_use.fetch(hostport).size != 0
|
||||
return true
|
||||
else
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
return extra_in_use.fetch(hostport).include?(hostip)
|
||||
end
|
||||
|
||||
def port_check(host_ip, host_port)
|
||||
# If the user hasn't specified a host_ip, his/her intention is taken to be
|
||||
# to listen on all interfaces.
|
||||
return is_port_open?("0.0.0.0", host_port) if host_ip.nil?
|
||||
return is_port_open?(host_ip, host_port)
|
||||
end
|
||||
|
||||
def with_forwarded_ports(env)
|
||||
|
|
|
@ -244,9 +244,11 @@ module VagrantPlugins
|
|||
default_id = nil
|
||||
|
||||
if type == :forwarded_port
|
||||
# For forwarded ports, set the default ID to the
|
||||
# host port so that host ports overwrite each other.
|
||||
default_id = "#{options[:protocol]}#{options[:host]}"
|
||||
# For forwarded ports, set the default ID to be the
|
||||
# concat of host_ip, proto and host_port. This would ensure Vagrant
|
||||
# caters for port forwarding in an IP aliased environment where
|
||||
# different host IP addresses are to be listened on the same port.
|
||||
default_id = "#{options[:host_ip]}#{options[:protocol]}#{options[:host]}"
|
||||
end
|
||||
|
||||
options[:id] = default_id || SecureRandom.uuid
|
||||
|
@ -676,7 +678,7 @@ module VagrantPlugins
|
|||
end
|
||||
|
||||
if options[:host]
|
||||
key = "#{options[:protocol]}#{options[:host]}"
|
||||
key = "#{options[:host_ip]}#{options[:protocol]}#{options[:host]}"
|
||||
if fp_used.include?(key)
|
||||
errors << I18n.t("vagrant.config.vm.network_fp_host_not_unique",
|
||||
host: options[:host].to_s,
|
||||
|
|
|
@ -366,8 +366,10 @@ module VagrantPlugins
|
|||
end
|
||||
|
||||
# Parse out the forwarded port information
|
||||
if line =~ /^Forwarding.+?="(.+?),.+?,.*?,(.+?),.*?,(.+?)"$/
|
||||
result = [current_nic, $1.to_s, $2.to_i, $3.to_i]
|
||||
# Forwarding(1)="172.22.8.201tcp32977,tcp,172.22.8.201,32977,,3777"
|
||||
# Forwarding(2)="tcp32978,tcp,,32978,,3777"
|
||||
if line =~ /^Forwarding.+?="(.+?),.+?,(.*?),(.+?),.*?,(.+?)"$/
|
||||
result = [current_nic, $1.to_s, $3.to_i, $4.to_i, $2]
|
||||
@logger.debug(" - #{result.inspect}")
|
||||
results << result
|
||||
end
|
||||
|
@ -556,7 +558,7 @@ module VagrantPlugins
|
|||
end
|
||||
|
||||
def read_used_ports
|
||||
ports = []
|
||||
used_ports = Hash.new{|hash, key| hash[key] = Set.new}
|
||||
execute("list", "vms", retryable: true).split("\n").each do |line|
|
||||
if line =~ /^".+?" \{(.+?)\}$/
|
||||
uuid = $1.to_s
|
||||
|
@ -564,13 +566,14 @@ module VagrantPlugins
|
|||
# Ignore our own used ports
|
||||
next if uuid == @uuid
|
||||
|
||||
read_forwarded_ports(uuid, true).each do |_, _, hostport, _|
|
||||
ports << hostport
|
||||
read_forwarded_ports(uuid, true).each do |_, _, hostport, _, hostip|
|
||||
hostip = '*' if hostip.nil? || hostip.empty?
|
||||
used_ports[hostport].add?(hostip)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
ports
|
||||
used_ports
|
||||
end
|
||||
|
||||
def read_vms
|
||||
|
|
|
@ -15,6 +15,7 @@ module VagrantPlugins
|
|||
if type == :forwarded_port
|
||||
guest_port = options[:guest]
|
||||
host_port = options[:host]
|
||||
host_ip = options[:host_ip]
|
||||
protocol = options[:protocol] || "tcp"
|
||||
options = scoped_hash_override(options, :virtualbox)
|
||||
id = options[:id]
|
||||
|
@ -22,7 +23,8 @@ module VagrantPlugins
|
|||
# If the forwarded port was marked as disabled, ignore.
|
||||
next if options[:disabled]
|
||||
|
||||
mappings[host_port.to_s + protocol.to_s] =
|
||||
key = "#{host_ip}#{protocol}#{host_port}"
|
||||
mappings[key] =
|
||||
Model::ForwardedPort.new(id, host_port, guest_port, options)
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Reference in New Issue