2011-12-25 17:48:49 +00:00
|
|
|
module Vagrant
|
|
|
|
module Action
|
|
|
|
module VM
|
|
|
|
# Action that checks to make sure there are no forwarded port collisions,
|
|
|
|
# and raises an exception if there is.
|
|
|
|
class CheckPortCollisions
|
|
|
|
def initialize(app, env)
|
|
|
|
@app = app
|
|
|
|
end
|
|
|
|
|
|
|
|
def call(env)
|
2011-12-25 18:13:08 +00:00
|
|
|
# For the handlers...
|
|
|
|
@env = env
|
|
|
|
|
|
|
|
# Figure out how we handle port collisions. By default we error.
|
|
|
|
handler = env[:port_collision_handler] || :error
|
2011-12-25 17:48:49 +00:00
|
|
|
|
2011-12-25 21:13:01 +00:00
|
|
|
# Read our forwarded ports, if we have any, to override what
|
|
|
|
# we have configured.
|
|
|
|
current = {}
|
|
|
|
env[:vm].driver.read_forwarded_ports.each do |nic, name, hostport, guestport|
|
|
|
|
current[name] = hostport.to_i
|
|
|
|
end
|
|
|
|
|
2011-12-25 18:13:08 +00:00
|
|
|
existing = env[:vm].driver.read_used_ports
|
2012-01-03 18:34:35 +00:00
|
|
|
env[:vm].config.vm.forwarded_ports.each do |options|
|
2011-12-25 21:13:01 +00:00
|
|
|
# Use the proper port, whether that be the configured port or the
|
|
|
|
# port that is currently on use of the VM.
|
|
|
|
hostport = options[:hostport].to_i
|
2012-01-03 18:34:35 +00:00
|
|
|
hostport = current[options[:name]] if current.has_key?(options[:name])
|
2011-12-25 21:13:01 +00:00
|
|
|
|
|
|
|
if existing.include?(hostport)
|
2011-12-25 18:13:08 +00:00
|
|
|
# We have a collision! Handle it
|
2012-01-03 18:34:35 +00:00
|
|
|
send("handle_#{handler}".to_sym, options, existing)
|
2011-12-25 17:48:49 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
@app.call(env)
|
|
|
|
end
|
2011-12-25 18:13:08 +00:00
|
|
|
|
|
|
|
# Handles a port collision by raising an exception.
|
2012-01-03 18:34:35 +00:00
|
|
|
def handle_error(options, existing_ports)
|
2011-12-25 18:13:08 +00:00
|
|
|
raise Errors::ForwardPortCollisionResume
|
|
|
|
end
|
|
|
|
|
|
|
|
# Handles a port collision by attempting to fix it.
|
2012-01-03 18:34:35 +00:00
|
|
|
def handle_correct(options, existing_ports)
|
|
|
|
# We need to keep this for messaging purposes
|
|
|
|
original_hostport = options[:hostport]
|
|
|
|
|
2011-12-25 18:13:08 +00:00
|
|
|
if !options[:auto]
|
|
|
|
# Auto fixing is disabled for this port forward, so we
|
|
|
|
# must throw an error so the user can fix it.
|
2012-01-03 18:34:35 +00:00
|
|
|
raise Errors::ForwardPortCollision, :host_port => options[:hostport].to_s,
|
2011-12-25 18:13:08 +00:00
|
|
|
:guest_port => options[:guestport].to_s
|
|
|
|
end
|
|
|
|
|
|
|
|
# Get the auto port range and get rid of the used ports and
|
|
|
|
# ports which are being used in other forwards so we're just
|
|
|
|
# left with available ports.
|
|
|
|
range = @env[:vm].config.vm.auto_port_range.to_a
|
2012-01-05 00:47:03 +00:00
|
|
|
range -= @env[:vm].config.vm.forwarded_ports.collect { |opts| opts[:hostport].to_i }
|
2011-12-25 18:13:08 +00:00
|
|
|
range -= existing_ports
|
|
|
|
|
|
|
|
if range.empty?
|
|
|
|
raise Errors::ForwardPortAutolistEmpty, :vm_name => @env[:vm].name,
|
|
|
|
:host_port => options[:hostport].to_s,
|
|
|
|
:guest_port => options[:guestport].to_s
|
|
|
|
end
|
|
|
|
|
|
|
|
# Set the port up to be the first one and add that port to
|
|
|
|
# the used list.
|
|
|
|
options[:hostport] = range.shift
|
|
|
|
existing_ports << options[:hostport]
|
|
|
|
|
|
|
|
# Notify the user
|
|
|
|
@env[:ui].info(I18n.t("vagrant.actions.vm.forward_ports.fixed_collision",
|
2012-01-03 18:34:35 +00:00
|
|
|
:host_port => original_hostport.to_s,
|
|
|
|
:guest_port => options[:guestport].to_s,
|
2011-12-25 18:13:08 +00:00
|
|
|
:new_port => options[:hostport]))
|
|
|
|
end
|
2011-12-25 17:48:49 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|