Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 26 additions & 3 deletions lib/vagrant-parallels/action/box_register.rb
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
require 'fileutils'
require 'log4r'

module VagrantPlugins
Expand Down Expand Up @@ -58,13 +59,35 @@ def box_id(env, box_path)
config: tpl_config
end

id
id.delete('{}')
end

def lease_box_lock(env)
lease_file = env[:machine].box.directory.join('box_lease_count')

# If the temporary file, verify it is not too old. If its older than
# 1 hour, delete it first because previous run may be failed.
if lease_file.file? && lease_file.mtime.to_i < Time.now.to_i - 60 * 60
lease_file.delete
end

# Increment a counter in the file. Create the file if it doesn't exist
FileUtils.touch(lease_file)
File.open(lease_file ,'r+') do |file|
num = file.gets.to_i
file.rewind
file.puts num.next
file.fsync
file.flush
end
end

def register_box(env)
box_id_file = env[:machine].box.directory.join('box_id')
# Increment the lock counter in the temporary lease file
lease_box_lock(env)

# Read the master ID if we have it in the file.
# Read the box ID if we have it in the file.
box_id_file = env[:machine].box.directory.join('box_id')
env[:clone_id] = box_id_file.read.chomp if box_id_file.file?

# If we have the ID and the VM exists already, then we
Expand Down
34 changes: 33 additions & 1 deletion lib/vagrant-parallels/action/box_unregister.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ module VagrantPlugins
module Parallels
module Action
class BoxUnregister
@@lock = Mutex.new

def initialize(app, env)
@app = app
@logger = Log4r::Logger.new('vagrant_parallels::action::box_unregister')
Expand All @@ -15,7 +17,12 @@ def call(env)
return @app.call(env)
end

unregister_box(env)
@@lock.synchronize do
lock_key = Digest::MD5.hexdigest(env[:machine].box.name)
env[:machine].env.lock(lock_key, retry: true) do
unregister_box(env)
end
end

# If we got interrupted, then the import could have been
# interrupted and its not a big deal. Just return out.
Expand All @@ -31,7 +38,32 @@ def recover(env)

private

def release_box_lock(lease_file)
return if !lease_file.file?

# Decrement the counter in the lease file
File.open(lease_file,'r+') do |file|
num = file.gets.to_i
file.rewind
file.puts(num - 1)
file.fsync
file.flush
end

# Delete the lease file if we are the last who need this box.
# Then the box image will be unregistered.
lease_file.delete if lease_file.read.chomp.to_i <= 1
end

def unregister_box(env)
# Release the box lock
lease_file = env[:machine].box.directory.join('box_lease_count')
release_box_lock(lease_file)

# Do not unregister the box image if the temporary lease file exists
# Most likely it is cloning to another Vagrant env (in parallel run)
return if lease_file.file?

if env[:clone_id] && env[:machine].provider.driver.vm_exists?(env[:clone_id])
env[:ui].info I18n.t('vagrant_parallels.actions.vm.box.unregister')
env[:machine].provider.driver.unregister(env[:clone_id])
Expand Down
40 changes: 2 additions & 38 deletions lib/vagrant-parallels/driver/base.rb
Original file line number Diff line number Diff line change
Expand Up @@ -529,25 +529,7 @@ def regenerate_src_uuid
# @param [String] pvm_file Path to the machine image (*.pvm)
# @param [Array<String>] opts List of options for "prlctl register"
def register(pvm_file, opts=[])
args = [@prlctl_path, 'register', pvm_file, *opts]

3.times do
result = raw(*args)
# Exit if everything is OK
return if result.exit_code == 0

# It may occur in the race condition with other Vagrant processes.
# It is OK, just exit.
return if result.stderr.include?('is already registered.')

# Sleep a bit though to give Parallels Desktop time to fix itself
sleep 2
end

# If we reach this point, it means that we consistently got the
# failure, do a standard execute now. This will raise an
# exception if it fails again.
execute(*args)
execute_prlctl('register', pvm_file, *opts)
end

# Switches the VM state to the specified snapshot
Expand Down Expand Up @@ -622,25 +604,7 @@ def suspend
# Virtual machine will be removed from the VM list, but its image will
# not be deleted from the disk. So, it can be registered again.
def unregister(uuid)
args = [@prlctl_path, 'unregister', uuid]
3.times do
result = raw(*args)
# Exit if everything is OK
return if result.exit_code == 0

# It may occur in the race condition with other Vagrant processes.
# Both are OK, just exit.
return if result.stderr.include?('is not registered')
return if result.stderr.include?('is being cloned')

# Sleep a bit though to give Parallels Desktop time to fix itself
sleep 2
end

# If we reach this point, it means that we consistently got the
# failure, do a standard execute now. This will raise an
# exception if it fails again.
execute(*args)
execute_prlctl('unregister', uuid)
end

# Unshare folders.
Expand Down