vagrant/plugins/providers/virtualbox/action/forward_ports.rb

111 lines
3.8 KiB
Ruby

module VagrantPlugins
module ProviderVirtualBox
module Action
class ForwardPorts
def initialize(app, env)
@app = app
end
#--------------------------------------------------------------
# Execution
#--------------------------------------------------------------
def call(env)
@env = env
# Get the ports we're forwarding
ports = forward_port_definitions
# Warn if we're port forwarding to any privileged ports...
threshold_check(ports)
env[:ui].info I18n.t("vagrant.actions.vm.forward_ports.forwarding")
forward_ports(ports)
@app.call(env)
end
# This returns an array of forwarded ports with overrides properly
# squashed.
def forward_port_definitions
# Get all of the forwarded port definitions in the network and
# convert it to a forwarded port model for use in the rest of
# the action.
#
# Duplicate forward port definitions are treated as "last one wins"
# where the last host port definition wins.
fp_mapping = {}
@env[:machine].config.vm.networks.each do |type, args|
# We only care about forwarded ports currently
if type == :forwarded_port
options = args[2] || {}
host_port = args[0].to_i
guest_port = args[1].to_i
id = options[:id] || "#{guest_port.to_s(32)}-#{host_port.to_s(32)}"
fp_mapping[host_port] =
Model::ForwardedPort.new(id, host_port, guest_port, options)
end
end
# Return the values, since the order doesn't really matter
fp_mapping.values
end
# This method checks for any forwarded ports on the host below
# 1024, which causes the forwarded ports to fail.
def threshold_check(ports)
ports.each do |port|
if port.host_port <= 1024
@env[:ui].warn I18n.t("vagrant.actions.vm.forward_ports.privileged_ports")
return
end
end
end
def forward_ports(mappings)
ports = []
interfaces = @env[:machine].provider.driver.read_network_interfaces
mappings.each do |port|
message_attributes = {
:guest_port => port.guest_port,
:host_port => port.host_port,
:adapter => port.adapter
}
# Assuming the only reason to establish port forwarding is
# because the VM is using Virtualbox NAT networking. Host-only
# bridged networking don't require port-forwarding and establishing
# forwarded ports on these attachment types has uncertain behaviour.
@env[:ui].info(I18n.t("vagrant.actions.vm.forward_ports.forwarding_entry",
message_attributes))
# Port forwarding requires the network interface to be a NAT interface,
# so verify that that is the case.
if interfaces[port.adapter][:type] != :nat
@env[:ui].info(I18n.t("vagrant.actions.vm.forward_ports.non_nat",
message_attributes))
next
end
# Add the options to the ports array to send to the driver later
ports << {
:adapter => port.adapter,
:guestport => port.guest_port,
:hostport => port.host_port,
:name => port.id,
:protocol => port.protocol
}
end
if !ports.empty?
# We only need to forward ports if there are any to forward
@env[:machine].provider.driver.forward_ports(ports)
end
end
end
end
end
end