hashicorp / vagrant

Vagrant is a tool for building and distributing development environments.
https://www.vagrantup.com
Other
26.05k stars 4.42k forks source link

Multiple ports incorrectly stated as being in use #13228

Open peterdutton opened 1 year ago

peterdutton commented 1 year ago

Debug output

vagrant.log

Expected behavior

Vagrant maps the ports to the intended target

Actual behavior

The ports are stated as being in use and Vagrant attempts to use ports from the usable_port_range. It seems as though only the final port in the specified range gets used.

Reproduction information

The port clash happens even on the built-in ssh mapping to the VM. I removed my other port mappings and this clash still remained.

Vagrant version

2.3.7

Host operating system

Ubuntu 22.04.2LTS

Guest operating system

Ubuntu 20.04

Steps to reproduce

  1. create empty box and set config.vm.box to "ubuntu/focal64"
  2. check port 2222 using sudo lsof -i :2222 - note no output
  3. run vagrant up - note that 2222 is stated as being in use and the port is remapped to 2250. Note in logs many other ports are tried ("repaired port also in use") before this port is reached.

Vagrantfile

Vagrant.configure("2") do |config|
  config.vm.box = "ubuntu/focal64"
end
peterdutton commented 1 year ago

I overrode lib/vagrant/util/is_port_open.rb so I can continue to work with my VMs:

require "socket"

module Vagrant
  module Util
    # Contains the method {#is_port_open?} to check if a port is open
    # (listening) or closed (not in use). This method isn't completely
    # fool-proof, but it works enough of the time to be useful.
    module IsPortOpen
      # Checks if a port is open (listening) on a given host and port.
      #
      # @param [String] host Hostname or IP address.
      # @param [Integer] port Port to check.
      # @return [Boolean] `true` if the port is open (listening), `false`
      #   otherwise.
      def is_port_open?(host, port)
        system("sudo lsof -i:#{port}", out: '/dev/null')
      end

      extend IsPortOpen
    end
  end
end

This works for me, and also seems to detect port clashes if other VMs are running. The built in method (Socket.tcp(host, port, connect_timeout: 0.1).close) seems to be reporting false positives though.

Electromorphosis commented 7 months ago

I replicated this issue and the solution provided helped in my use case. For two ports forwarded, the first one wrongly detected all but the last in range as used and for the second port the check seem to didn't start at all.

I used: Vagrant 2.4.0 VirtualBox 6.1.38 Ubuntu 20.04.1