Class: HashiCorp::VagrantVMwareDesktop::Action::ForwardPorts

Inherits:
Object
  • Object
show all
Includes:
Common, Vagrant::Util::ScopedHashOverride
Defined in:
lib/vagrant-vmware-desktop/action/forward_ports.rb

Overview

This does NAT port forwarding on the VMware VM.

Instance Method Summary collapse

Methods included from Common

#to_s

Constructor Details

#initialize(app, env) ⇒ ForwardPorts

Returns a new instance of ForwardPorts.



19
20
21
22
# File 'lib/vagrant-vmware-desktop/action/forward_ports.rb', line 19

def initialize(app, env)
  @app    = app
  @logger = Log4r::Logger.new("hashicorp::provider::vmware::forward_ports")
end

Instance Method Details

#call(env) ⇒ Object



24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
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
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
# File 'lib/vagrant-vmware-desktop/action/forward_ports.rb', line 24

def call(env)
  # Build the definitions for our driver.
  @logger.debug("Building up ports to forward...")
  definitions = []
  env[:machine].config.vm.networks.each do |type, options|
    # Ignore anything but forwarded ports
    next if type != :forwarded_port
    options = scoped_hash_override(options, :vmware)

    # Ignore disabled ports
    next if options[:disabled]

    definitions << {
      device: env[:machine].provider_config.nat_device,
      guest_port: options[:guest],
      host_port: options[:host],
      protocol: options[:protocol],
    }
  end

  # Make sure we're not conflicting with any of the NAT forwarded
  # ports. Note that port collision detection/handling should fix
  # any collisions at a higher level, so this is more of an ASSERT
  # type statement.
  all_ports   = Set.new(env[:machine].provider.driver.all_forwarded_ports)
  all_defined = Set.new(definitions.map { |d| d[:host_port].to_i })
  intersection = all_ports & all_defined
  if !intersection.empty?
    raise Errors::ForwardedPortsCollideWithExistingNAT,
      :ports => intersection.to_a.sort.join(", ")
  end

  # Set the guest IP on all forwarded ports
  guest_ip = nil
  5.times do |_|
    guest_ip = env[:machine].provider.driver.read_ip(
      env[:machine].provider_config.enable_vmrun_ip_lookup
    )
    break if guest_ip
    sleep 2
  end

  if !guest_ip
    raise Errors::ForwardedPortNoGuestIP
  end

  definitions.each do |fp|
    fp[:guest_ip] = guest_ip
  end

  # UI
  env[:ui].info(I18n.t("hashicorp.vagrant_vmware_desktop.forwarding_ports"))
  definitions.each do |fp|
    env[:ui].detail(I18n.t(
      "hashicorp.vagrant_vmware_desktop.forward_port_entry",
      :guest_port => fp[:guest_port],
      :host_port => fp[:host_port]))
  end

  # Forward the ports!
  env[:machine].provider.driver.forward_ports(definitions)

  # Store the forwarded ports for later
  env[:machine].data_dir.join("forwarded_ports").open("w+") do |f|
    ports = {}
    definitions.each do |fp|
      ports[fp[:host_port].to_i] = fp[:guest_port].to_i
    end

    f.write(JSON.dump(ports))
  end

  # Because the network gets restarted when ports are forwarded the
  # guest may see that the network connection has been lost and then
  # regained. NetworkManager will some times see this and drop a
  # current DHCP lease and start the process over again which prevents
  # expected access to the guest. To prevent that, we just wait for a
  # bit until the network is ready.
  port_forward_network_pause = env[:machine].provider_config.port_forward_network_pause.to_i
  if port_forward_network_pause > 0
    env[:ui].info("Pausing for network to stabilize (#{port_forward_network_pause} seconds)")
    sleep(port_forward_network_pause)
  end

  @app.call(env)
end