diff --git a/.gitignore b/.gitignore index 202482cd..a423386f 100644 --- a/.gitignore +++ b/.gitignore @@ -4,16 +4,16 @@ # Vagrant stuff acceptance_config.yml boxes/* -/Vagrantfile -/.vagrant -/vagrant-spec.config.rb +Vagrantfile +.vagrant +vagrant-spec.config.rb # Bundler/Rubygems *.gem .bundle pkg/* tags -/Gemfile.lock +Gemfile.lock test/tmp/ # Python diff --git a/lib/vagrant-parallels/action.rb b/lib/vagrant-parallels/action.rb index b9937557..b807b0a2 100644 --- a/lib/vagrant-parallels/action.rb +++ b/lib/vagrant-parallels/action.rb @@ -168,6 +168,7 @@ def self.action_resume b2.use EnvSet, :port_collision_repair => false b2.use Resume b2.use WaitForCommunicator, [:resuming, :running] + b2.use ForcePrlFsMount else b2.use MessageNotCreated end @@ -283,6 +284,7 @@ def self.action_up autoload :DestroyUnusedNetworkInterfaces, File.expand_path("../action/destroy_unused_network_interfaces", __FILE__) autoload :Export, File.expand_path("../action/export", __FILE__) autoload :ForcedHalt, File.expand_path("../action/forced_halt", __FILE__) + autoload :ForcePrlFsMount, File.expand_path("../action/force_prl_fs_mount", __FILE__) autoload :Import, File.expand_path("../action/import", __FILE__) autoload :IsSuspended, File.expand_path("../action/is_suspended", __FILE__) autoload :IsRunning, File.expand_path("../action/is_running", __FILE__) diff --git a/lib/vagrant-parallels/action/force_prl_fs_mount.rb b/lib/vagrant-parallels/action/force_prl_fs_mount.rb new file mode 100644 index 00000000..f6e0cb67 --- /dev/null +++ b/lib/vagrant-parallels/action/force_prl_fs_mount.rb @@ -0,0 +1,55 @@ +require "log4r" +require 'vagrant/util/platform' + +module VagrantPlugins + module Parallels + module Action + class ForcePrlFsMount + # This middleware forces the prl_fs mount after the Resume, because + # there is bug in Linux guests - custom shared folders are missed after + # the resume [GH-102] + include Vagrant::Action::Builtin::MixinSyncedFolders + + def initialize(app, env) + @app = app + @logger = Log4r::Logger.new("vagrant::plugins::parallels::force_prl_fs_mount") + end + + def call(env) + # Only for Linux guests! + if env[:machine].communicate.test("uname -s | grep 'Linux'") + folders = synced_folders(env[:machine])[:parallels] + + # Go through each folder and make sure to create it if + # it does not exist on host + folders.each do |id, data| + data[:hostpath] = File.expand_path(data[:hostpath], env[:root_path]) + + # Create the hostpath if it doesn't exist and we've been told to + if !File.directory?(data[:hostpath]) && data[:create] + @logger.info("Creating shared folder host directory: #{data[:hostpath]}") + begin + Pathname.new(data[:hostpath]).mkpath + rescue Errno::EACCES + raise Vagrant::Errors::SharedFolderCreateFailed, + path: data[:hostpath] + end + end + + if File.directory?(data[:hostpath]) + data[:hostpath] = File.realpath(data[:hostpath]) + data[:hostpath] = Vagrant::Util::Platform.fs_real_path(data[:hostpath]).to_s + end + end + + opts = nil + instance = VagrantPlugins::Parallels::SyncedFolder.new + instance.enable(env[:machine], folders, opts) + end + + @app.call(env) + end + end + end + end +end diff --git a/lib/vagrant-parallels/driver/base.rb b/lib/vagrant-parallels/driver/base.rb index 144537e9..ac160c11 100644 --- a/lib/vagrant-parallels/driver/base.rb +++ b/lib/vagrant-parallels/driver/base.rb @@ -41,6 +41,10 @@ def initialize def clear_shared_folders end + # Compacts all disk drives of virtual machine + def compact + end + # Creates a host only network with the given options. # # @param [Hash] options Options to create the host only network. @@ -100,7 +104,7 @@ def export(path) end # Halts the virtual machine (pulls the plug). - def halt + def halt(force) end # Imports the VM by cloning from registered template. @@ -157,6 +161,13 @@ def read_network_interfaces def read_shared_interface end + # Returns a list of shared folders in format: + # { id => hostpath, ... } + # + # @return [Hash] + def read_shared_folders + end + # Returns the current state of this VM. # # @return [Symbol] @@ -170,9 +181,13 @@ def read_state def read_vms end + # Registers the virtual machine + def register(pvm_file) + end + # Resumes the virtual machine. # - def resume(mac) + def resume end # Sets the MAC address of the first network adapter. @@ -181,7 +196,7 @@ def resume(mac) def set_mac_address(mac) end - # Sets the VM name. + # Sets the name of the virtual machine. # # @param [String] name New VM name. def set_name(name) diff --git a/lib/vagrant-parallels/driver/meta.rb b/lib/vagrant-parallels/driver/meta.rb index 12c59dfb..14f0cac2 100644 --- a/lib/vagrant-parallels/driver/meta.rb +++ b/lib/vagrant-parallels/driver/meta.rb @@ -92,6 +92,7 @@ def initialize(uuid=nil) :read_mac_address, :read_network_interfaces, :read_shared_interface, + :read_shared_folders, :read_settings, :read_state, :read_used_ports, diff --git a/lib/vagrant-parallels/driver/pd_8.rb b/lib/vagrant-parallels/driver/pd_8.rb index 89ffe897..941df384 100644 --- a/lib/vagrant-parallels/driver/pd_8.rb +++ b/lib/vagrant-parallels/driver/pd_8.rb @@ -32,10 +32,9 @@ def compact(uuid) end def clear_shared_folders - shf = read_settings.fetch("Host Shared Folders", {}).keys - shf.delete("enabled") - shf.each do |folder| - execute("set", @uuid, "--shf-host-del", folder) + share_ids = read_shared_folders.keys + share_ids.each do |id| + execute("set", @uuid, "--shf-host-del", id) end end @@ -335,6 +334,16 @@ def read_shared_interface info end + def read_shared_folders + shf_info = read_settings.fetch("Host Shared Folders", {}) + list = {} + shf_info.delete_if {|k,v| k == "enabled"}.each do |id, data| + list[id] = data.fetch("path") + end + + list + end + def read_state vm = json { execute('list', @uuid, '--json', retryable: true).gsub(/^INFO/, '') } return nil if !vm.last diff --git a/lib/vagrant-parallels/driver/pd_9.rb b/lib/vagrant-parallels/driver/pd_9.rb index 4023de87..be18ea1e 100644 --- a/lib/vagrant-parallels/driver/pd_9.rb +++ b/lib/vagrant-parallels/driver/pd_9.rb @@ -32,10 +32,9 @@ def compact(uuid) end def clear_shared_folders - shf = read_settings.fetch("Host Shared Folders", {}).keys - shf.delete("enabled") - shf.each do |folder| - execute("set", @uuid, "--shf-host-del", folder) + share_ids = read_shared_folders.keys + share_ids.each do |id| + execute("set", @uuid, "--shf-host-del", id) end end @@ -335,6 +334,16 @@ def read_shared_interface info end + def read_shared_folders + shf_info = read_settings.fetch("Host Shared Folders", {}) + list = {} + shf_info.delete_if {|k,v| k == "enabled"}.each do |id, data| + list[id] = data.fetch("path") + end + + list + end + def read_state vm = json { execute('list', @uuid, '--json', retryable: true) } return nil if !vm.last diff --git a/lib/vagrant-parallels/synced_folder.rb b/lib/vagrant-parallels/synced_folder.rb index 6f2c465b..b5a79a0f 100644 --- a/lib/vagrant-parallels/synced_folder.rb +++ b/lib/vagrant-parallels/synced_folder.rb @@ -4,7 +4,7 @@ module VagrantPlugins module Parallels class SyncedFolder < Vagrant.plugin("2", :synced_folder) def usable?(machine) - # These synced folders only work if the provider if VirtualBox + # These synced folders only work if the provider is Parallels machine.provider_name == :parallels end @@ -21,6 +21,9 @@ def prepare(machine, folders, _opts) } end + # We should prepare only folders with unique hostpath values. + # Anyway, duplicates will be mounted later. + defs.uniq! { |d| d[:hostpath] } driver(machine).share_folders(defs) end @@ -35,10 +38,16 @@ def enable(machine, folders, _opts) end end + shf_config = driver(machine).read_shared_folders + # Go through each folder and mount machine.ui.output(I18n.t("vagrant.actions.vm.share_folders.mounting")) - folders.each do |id, data| - if data[:guestpath] + folders.each do |_ , data| + # Parallels specific: get id from the VM setting + # It allows to mount one host folder more then one time [GH-105] + id = shf_config.key(data[:hostpath]) + + if data[:guestpath] and id id = Pathname.new(id).to_s.split('/').drop_while{|i| i.empty?}.join('_') # Guest path specified, so mount the folder to specified point diff --git a/lib/vagrant-parallels/version.rb b/lib/vagrant-parallels/version.rb index 1b589d41..105b8c26 100644 --- a/lib/vagrant-parallels/version.rb +++ b/lib/vagrant-parallels/version.rb @@ -1,5 +1,5 @@ module VagrantPlugins module Parallels - VERSION = "1.0.4" + VERSION = "1.0.5" end end