Skip to content

Commit

Permalink
Merge pull request #226 from legal90/fix-fp-collisions
Browse files Browse the repository at this point in the history
Fix port forwarding collisions in parallel run of multi-machine env
  • Loading branch information
legal90 committed Nov 5, 2015
2 parents 09bb67f + 15e2121 commit b195868
Showing 1 changed file with 32 additions and 18 deletions.
50 changes: 32 additions & 18 deletions lib/vagrant-parallels/action/forward_ports.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ module Parallels
module Action
class ForwardPorts
include VagrantPlugins::Parallels::Util::CompileForwardedPorts
@@lock = Mutex.new

def initialize(app, env)
@app = app
Expand All @@ -21,13 +22,30 @@ def call(env)

# Get the ports we're forwarding
env[:forwarded_ports] ||= compile_forwarded_ports(env[:machine].config)
env[:ui].output(I18n.t('vagrant.actions.vm.forward_ports.forwarding'))
forward_ports

# Exit if there are no ports to forward
return @app.call(env) if env[:forwarded_ports].empty?

# Acquire both of class- and process-level locks so that we don't
# forward ports simultaneousely with someone else.
@@lock.synchronize do
begin
env[:machine].env.lock('forward_ports') do
env[:ui].output(I18n.t('vagrant.actions.vm.forward_ports.forwarding'))
forward_ports
end
rescue Errors::EnvironmentLockedError
sleep 1
retry
end
end

@app.call(env)
end

def forward_ports
all_rules = @env[:machine].provider.driver.read_forwarded_ports(true)
names_in_use = all_rules.collect { |r| r[:rule_name] }
ports = []

@env[:forwarded_ports].each do |fp|
Expand All @@ -43,11 +61,22 @@ def forward_ports
@env[:ui].detail(I18n.t('vagrant_parallels.actions.vm.forward_ports.forwarding_entry',
message_attributes))

# In Parallels Desktop the scope port forwarding rules is global,
# so we have to keep their names unique.
unique_id = fp.id
# Append random suffix to get the unique rule name
while names_in_use.include?(unique_id)
suffix = (0...4).map { ('a'..'z').to_a[rand(26)] }.join
unique_id = "#{fp.id}_#{suffix}"
end
# Mark this rule name as in use
names_in_use << unique_id

# Add the options to the ports array to send to the driver later
ports << {
guestport: fp.guest_port,
hostport: fp.host_port,
name: get_unique_name(fp.id),
name: unique_id,
protocol: fp.protocol
}
end
Expand All @@ -57,21 +86,6 @@ def forward_ports
@env[:machine].provider.driver.forward_ports(ports)
end
end

private

def get_unique_name(id)
all_rules = @env[:machine].provider.driver.read_forwarded_ports(true)
names_in_use = all_rules.collect { |r| r[:rule_name] }

# Append random suffix to get unique rule name
while names_in_use.include?(id)
suffix = (0...4).map { ('a'..'z').to_a[rand(26)] }.join
id = "#{id}_#{suffix}"
end

id
end
end
end
end
Expand Down

0 comments on commit b195868

Please sign in to comment.