Class: Vagrant::Action::VM::CheckPortCollisions

Inherits:
Object
  • Object
show all
Includes:
Util::IsPortOpen
Defined in:
lib/vagrant/action/vm/check_port_collisions.rb

Overview

Action that checks to make sure there are no forwarded port collisions, and raises an exception if there is.

Instance Method Summary collapse

Methods included from Util::IsPortOpen

#is_port_open?

Constructor Details

#initialize(app, env) ⇒ CheckPortCollisions

Returns a new instance of CheckPortCollisions.



11
12
13
# File 'lib/vagrant/action/vm/check_port_collisions.rb', line 11

def initialize(app, env)
  @app = app
end

Instance Method Details

#call(env) ⇒ Object



15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
# File 'lib/vagrant/action/vm/check_port_collisions.rb', line 15

def call(env)
  # For the handlers...
  @env = env

  # Figure out how we handle port collisions. By default we error.
  handler  = env[:port_collision_handler] || :error

  # 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

  existing = env[:vm].driver.read_used_ports
  env[:vm].config.vm.forwarded_ports.each do |options|
    # 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
    hostport = current[options[:name]] if current.has_key?(options[:name])

    if existing.include?(hostport) || is_port_open?("127.0.0.1", hostport)
      # We have a collision! Handle it
      send("handle_#{handler}".to_sym, options, existing)
    end
  end

  @app.call(env)
end

#handle_correct(options, existing_ports) ⇒ Object

Handles a port collision by attempting to fix it.



51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
# File 'lib/vagrant/action/vm/check_port_collisions.rb', line 51

def handle_correct(options, existing_ports)
  # We need to keep this for messaging purposes
  original_hostport = options[:hostport]

  if !options[:auto]
    # Auto fixing is disabled for this port forward, so we
    # must throw an error so the user can fix it.
    raise Errors::ForwardPortCollision, :host_port => options[:hostport].to_s,
                                        :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
  range -= @env[:vm].config.vm.forwarded_ports.collect { |opts| opts[:hostport].to_i }
  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",
                        :host_port => original_hostport.to_s,
                        :guest_port => options[:guestport].to_s,
                        :new_port => options[:hostport]))
end

#handle_error(options, existing_ports) ⇒ Object

Handles a port collision by raising an exception.



46
47
48
# File 'lib/vagrant/action/vm/check_port_collisions.rb', line 46

def handle_error(options, existing_ports)
  raise Errors::ForwardPortCollisionResume
end