vagrant-parallels 2.0.0 → 2.2.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: a40565034c3032c1536e75c37bd10287c87200e0
4
- data.tar.gz: fcf16876294f17f6843c1acbe698ba111cbfee5f
2
+ SHA256:
3
+ metadata.gz: d138c790174855049184943ea5dada1b980eee3755f88f5e20059a2851fb2aa9
4
+ data.tar.gz: 277e1c323a916c085f4b45fed9ede685b1587246ace3e703a89b33038b59147f
5
5
  SHA512:
6
- metadata.gz: f983701a46e36b8d189d80c6906868d91b3a35840b849cdcdc301ec8f660cc851de3ebbb045eb924dd8dd201b1aebe3fd2c8a69f1db8425b2bb2380d30b7b6b0
7
- data.tar.gz: bb2f8d87c5fa5b3332cdcbdea5a9e411ddf3941bfcc12cc4e8b5693edb114aa7295f3ab63f627721fe3a87c860d1a4a42b7e3f3a066e498b1861522cea1a1999
6
+ metadata.gz: ee07c96b1a45d301d37b2c633e71ac176ca4859cf40d92cfd772d5549892a1edb64a74897270d9819f2ea0fe3f9a2a3916a447a65b60fd084100e06bcf86ef45
7
+ data.tar.gz: b963b62e1d1b86e89eb7d78c088881a9ae399fb529928fdb030ba921cd0d32f9b660529e160b1bb8f229d077fcc2a71df4cb90518f4a067e7fe2269447ed96dd
data/CHANGELOG.md CHANGED
@@ -1,12 +1,45 @@
1
+ ## 2.2.2 (June 23, 2021)
2
+ BUG FIXES:
3
+ - Fixed shared folder mount on the VM reboot
4
+ [[GH-391](https://github.com/Parallels/vagrant-parallels/pull/391)]
5
+
6
+ ## 2.2.1 (April 14, 2021)
7
+ BUG FIXES:
8
+ - Fixed the compatibility with Vagrant 2.2.15
9
+ [[GH-386](https://github.com/Parallels/vagrant-parallels/pull/386)]
10
+
11
+ ## 2.2.0 (March 3, 2021)
12
+ IMPROVEMENTS:
13
+ - Mount shared folders after manual VM reboot
14
+ [[GH-377](https://github.com/Parallels/vagrant-parallels/pull/377)]
15
+
16
+ BUG FIXES:
17
+ - Fixed mount of shared folders with non-ASCII symbols in the name
18
+ [[GH-290](https://github.com/Parallels/vagrant-parallels/issues/290)]
19
+
20
+ ## 2.1.0 (November 25, 2020)
21
+ BUG FIXES:
22
+ - Fixed the private network adapter workflow on macOS 11.0 Big Sur
23
+ [[GH-371](https://github.com/Parallels/vagrant-parallels/pull/371)]
24
+ - Fixed the concurrency issue with box unregister in multi-vm environment
25
+ [[GH-370](https://github.com/Parallels/vagrant-parallels/pull/370)]
26
+ - Fixed the `vagrant package` with custom `Vagrantfile`
27
+ [[GH-368](https://github.com/Parallels/vagrant-parallels/pull/368)]
28
+
29
+ ## 2.0.1 (April 23, 2019)
30
+ BUG FIXES:
31
+ - Fixed the error message for host-only network collision
32
+ [[GH-340](https://github.com/Parallels/vagrant-parallels/issues/340)]
33
+
1
34
  ## 2.0.0 (November 19, 2018)
2
35
  BREAKING CHANGES:
3
36
  - **Linked Clone feature is enabled by default.**
4
37
  Now each time when you create a new virtual machine with `vagrant up` it is
5
38
  created as a linked clone of the box image (instead of the full clone, as it
6
39
  was before). Read more about it:
7
- [Full Clone vs Linked Clone](http://parallels.github.io/vagrant-parallels/docs/configuration.html#linked_clone).
40
+ [Full Clone vs Linked Clone](https://parallels.github.io/vagrant-parallels/docs/configuration.html#linked_clone).
8
41
  - **Dropped support of Parallels Desktop 10**. It reached
9
- [End-of-Life and End-of-Support](http://kb.parallels.com/eu/122533).
42
+ [End-of-Life and End-of-Support](https://kb.parallels.com/eu/122533).
10
43
 
11
44
  ## 1.7.8 (November 18, 2017)
12
45
  BUG FIXES:
@@ -82,7 +115,7 @@ BUG FIXES:
82
115
  ## 1.7.0 (November 15, 2016)
83
116
  BREAKING CHANGES:
84
117
  - **Dropped support of Parallels Desktop 8 and 9**. These versions have
85
- reached their [End-of-Life and End-of-Support](http://kb.parallels.com/eu/122533).
118
+ reached their [End-of-Life and End-of-Support](https://kb.parallels.com/eu/122533).
86
119
  - **Removed customization options, which were previously deprecated:** [[GH-271](https://github.com/Parallels/vagrant-parallels/pull/271)]
87
120
  - "use_linked_clone" - use `linked_clone` instead.
88
121
  - "regen_box_uuid" - use `regen_src_uuid` instead.
data/README.md CHANGED
@@ -3,16 +3,13 @@
3
3
  [![Build Status](https://travis-ci.org/Parallels/vagrant-parallels.svg?branch=master)](https://travis-ci.org/Parallels/vagrant-parallels)
4
4
  [![Code Climate](https://codeclimate.com/github/Parallels/vagrant-parallels.svg)](https://codeclimate.com/github/Parallels/vagrant-parallels)
5
5
 
6
- _Vagrant Parallels Provider_ is a plugin for [Vagrant](http://www.vagrantup.com),
7
- allowing to manage [Parallels Desktop](http://www.parallels.com/products/desktop/)
6
+ _Vagrant Parallels Provider_ is a plugin for [Vagrant](https://www.vagrantup.com),
7
+ allowing to manage [Parallels Desktop](https://www.parallels.com/products/desktop/)
8
8
  virtual machines on macOS hosts.
9
9
 
10
10
  ### Requirements
11
- - [Vagrant v1.8](http://www.vagrantup.com) or higher
12
- (_there are known issues with Vagrant v1.9.5
13
- [[GH-297](https://github.com/Parallels/vagrant-parallels/issues/297#issuecomment-304458691)]
14
- and v1.9.6 [[GH-301]](https://github.com/Parallels/vagrant-parallels/issues/301)_)
15
- - [Parallels Desktop 11 for Mac](http://www.parallels.com/products/desktop/) or higher
11
+ - [Vagrant v1.9.7](https://www.vagrantup.com) or higher
12
+ - [Parallels Desktop 11 for Mac](https://www.parallels.com/products/desktop/) or higher
16
13
 
17
14
  *Note:* Only **Pro** and **Business** editions of **Parallels Desktop for Mac**
18
15
  are compatible with this Vagrant provider.
@@ -24,11 +21,11 @@ The Parallels provider supports all basic Vagrant features, including Shared Fol
24
21
  Private and Public Networking, Forwarded ports and Vagrant Share.
25
22
 
26
23
  If you're just getting started with Vagrant, it is highly recommended that you
27
- read the official [Vagrant documentation](http://docs.vagrantup.com/v2/) first.
24
+ read the official [Vagrant documentation](https://docs.vagrantup.com/v2/) first.
28
25
 
29
26
  ## Installation
30
- Make sure that you have [Parallels Desktop for Mac](http://www.parallels.com/products/desktop/)
31
- and [Vagrant](http://www.vagrantup.com/downloads) properly installed.
27
+ Make sure that you have [Parallels Desktop for Mac](https://www.parallels.com/products/desktop/)
28
+ and [Vagrant](https://www.vagrantup.com/downloads.html) properly installed.
32
29
  We recommend that you use the latest versions of these products.
33
30
 
34
31
  Parallels provider is a plugin for Vagrant. Run this command to install it:
@@ -40,12 +37,12 @@ $ vagrant plugin install vagrant-parallels
40
37
  ## Provider Documentation
41
38
 
42
39
  More information about the Parallels provider is available in
43
- [Vagrant Parallels Documentation](http://parallels.github.io/vagrant-parallels/docs/)
40
+ [Vagrant Parallels Documentation](https://parallels.github.io/vagrant-parallels/docs/)
44
41
 
45
42
  We recommend you to start from these pages:
46
- * [Usage](http://parallels.github.io/vagrant-parallels/docs/usage.html)
47
- * [Getting Started](http://parallels.github.io/vagrant-parallels/docs/getting-started.html)
48
- * [Boxes](http://parallels.github.io/vagrant-parallels/docs/boxes/index.html)
43
+ * [Usage](https://parallels.github.io/vagrant-parallels/docs/usage.html)
44
+ * [Getting Started](https://parallels.github.io/vagrant-parallels/docs/getting-started.html)
45
+ * [Boxes](https://parallels.github.io/vagrant-parallels/docs/boxes/index.html)
49
46
 
50
47
  ## Getting Help
51
48
 
@@ -56,6 +53,6 @@ please report it on the [Issue Tracker](https://github.com/Parallels/vagrant-par
56
53
 
57
54
  * Author: Youssef Shahin <yshahin@gmail.com>
58
55
  * Author: Mikhail Zholobov <legal90@gmail.com>
59
- * Copyright 2013-2018, Parallels International GmbH.
56
+ * Copyright 2013-2020, Parallels International GmbH.
60
57
 
61
- Vagrant Parallels Provider is open-sourced software licensed under the [MIT license](http://opensource.org/licenses/MIT).
58
+ Vagrant Parallels Provider is open-sourced software licensed under the [MIT license](https://opensource.org/licenses/MIT).
@@ -113,6 +113,7 @@ module VagrantPlugins
113
113
  b1.use Package
114
114
  b1.use Export
115
115
  b1.use PackageConfigFiles
116
+ b1.use PackageVagrantfile
116
117
  end
117
118
  end
118
119
  end
@@ -413,6 +414,7 @@ module VagrantPlugins
413
414
  autoload :Network, File.expand_path('../action/network', __FILE__)
414
415
  autoload :Package, File.expand_path('../action/package', __FILE__)
415
416
  autoload :PackageConfigFiles, File.expand_path('../action/package_config_files', __FILE__)
417
+ autoload :PackageVagrantfile, File.expand_path('../action/package_vagrantfile', __FILE__)
416
418
  autoload :PrepareCloneSnapshot, File.expand_path('../action/prepare_clone_snapshot', __FILE__)
417
419
  autoload :PrepareForwardedPortCollisionParams, File.expand_path('../action/prepare_forwarded_port_collision_params', __FILE__)
418
420
  autoload :PrepareNFSSettings, File.expand_path('../action/prepare_nfs_settings', __FILE__)
@@ -53,9 +53,9 @@ module VagrantPlugins
53
53
  file.flush
54
54
  end
55
55
 
56
- # Delete the lease file if we are the last who need this box.
56
+ # Delete the lease file if we were the last who needed this box.
57
57
  # Then the box image will be unregistered.
58
- lease_file.delete if lease_file.read.chomp.to_i <= 1
58
+ lease_file.delete if lease_file.read.chomp.to_i <= 0
59
59
  end
60
60
 
61
61
  def unregister_box(env)
@@ -291,7 +291,12 @@ module VagrantPlugins
291
291
  @env[:machine].provider.driver.read_bridged_interfaces.each do |interface|
292
292
  next if interface[:status] == 'Down'
293
293
  that_netaddr = IPAddr.new("#{interface[:ip]}/#{interface[:netmask]}")
294
- raise Vagrant::Errors::NetworkCollision if netaddr.include? that_netaddr
294
+ if netaddr.include? that_netaddr
295
+ raise VagrantPlugins::Parallels::Errors::NetworkCollision,
296
+ hostonly_netaddr: netaddr,
297
+ bridge_netaddr: that_netaddr,
298
+ bridge_interface: interface[:name]
299
+ end
295
300
  end
296
301
  end
297
302
 
@@ -0,0 +1,33 @@
1
+ require 'vagrant/util/template_renderer'
2
+
3
+ module VagrantPlugins
4
+ module Parallels
5
+ module Action
6
+ class PackageVagrantfile
7
+ # For TemplateRenderer
8
+ include Vagrant::Util
9
+
10
+ def initialize(app, env)
11
+ @app = app
12
+ end
13
+
14
+ def call(env)
15
+ @env = env
16
+ create_vagrantfile
17
+ @app.call(env)
18
+ end
19
+
20
+ # This method creates the auto-generated Vagrantfile at the root of the
21
+ # box. This Vagrantfile contains the MAC address so that the user doesn't
22
+ # have to worry about it.
23
+ def create_vagrantfile
24
+ File.open(File.join(@env["export.temp_dir"], "Vagrantfile"), "w") do |f|
25
+ f.write(TemplateRenderer.render("package_Vagrantfile", {
26
+ base_mac: @env[:machine].provider.driver.read_mac_address
27
+ }))
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,50 @@
1
+ require_relative "../util/unix_mount_helpers"
2
+
3
+ module VagrantPlugins
4
+ module Parallels
5
+ module SyncedFolderCap
6
+ module MountOptions
7
+ extend VagrantPlugins::Parallels::Util::UnixMountHelpers
8
+
9
+ PRL_MOUNT_TYPE = "prl_fs".freeze
10
+
11
+ # Returns mount options for a parallels synced folder
12
+ #
13
+ # @param [Machine] machine
14
+ # @param [String] name of mount
15
+ # @param [String] path of mount on guest
16
+ # @param [Hash] hash of mount options
17
+ def self.mount_options(machine, name, guest_path, options)
18
+ mount_options = options.fetch(:mount_options, [])
19
+ detected_ids = detect_owner_group_ids(machine, guest_path, mount_options, options)
20
+ mount_uid = detected_ids[:uid]
21
+ mount_gid = detected_ids[:gid]
22
+
23
+ mount_options << "uid=#{mount_uid}"
24
+ mount_options << "gid=#{mount_gid}"
25
+ mount_options << "_netdev"
26
+ mount_options = mount_options.join(',')
27
+ return mount_options, mount_uid, mount_gid
28
+ end
29
+
30
+ def self.mount_type(machine)
31
+ return PRL_MOUNT_TYPE
32
+ end
33
+
34
+ ## We have to support 2 different expected interfaces of `mount_name` call:
35
+ ## Vagrant < 2.2.15: `def self.mount_name(machine, data)`
36
+ ## Vagrant >= 2.2.15: `def self.mount_name(machine, id, data)`
37
+ ## https://github.com/Parallels/vagrant-parallels/issues/384
38
+ def self.mount_name(*args)
39
+ if args.length >= 3
40
+ id = args[1]
41
+ else
42
+ id = args[-1][:guestpath]
43
+ end
44
+
45
+ id.gsub(/[*":<>?|\/\\]/,'_').sub(/^_/, '')
46
+ end
47
+ end
48
+ end
49
+ end
50
+ end
@@ -193,14 +193,13 @@ module VagrantPlugins
193
193
  end
194
194
  end
195
195
 
196
- # Deletes any host only networks that aren't being used for anything.
196
+ # Deletes host-only networks that aren't being used by any virtual machine.
197
197
  def delete_unused_host_only_networks
198
198
  networks = read_virtual_networks
199
- # 'Shared'(vnic0) and 'Host-Only'(vnic1) are default in Parallels Desktop
200
- # They should not be deleted anyway.
199
+
200
+ # Exclude all host-only network interfaces which were not created by vagrant provider.
201
201
  networks.keep_if do |net|
202
- net['Type'] == 'host-only' && net['Bound To'] &&
203
- net['Bound To'].match(/^(?>vnic|Parallels Host-Only #)(\d+)$/)[1].to_i >= 2
202
+ net['Type'] == 'host-only' && net['Network ID'] =~ /^vagrant-vnet(\d+)$/
204
203
  end
205
204
 
206
205
  read_vms_info.each do |vm|
@@ -210,8 +209,8 @@ module VagrantPlugins
210
209
  end
211
210
  end
212
211
 
212
+ # Delete all unused network interfaces.
213
213
  networks.each do |net|
214
- # Delete the actual host only network interface.
215
214
  execute_prlsrvctl('net', 'del', net['Network ID'])
216
215
  end
217
216
  end
@@ -496,7 +495,6 @@ module VagrantPlugins
496
495
  #
497
496
  # {
498
497
  # name: 'Host-Only', # Parallels Network ID
499
- # bound_to: 'vnic1', # interface name
500
498
  # ip: '10.37.129.2', # IP address of the interface
501
499
  # netmask: '255.255.255.0', # netmask associated with the interface
502
500
  # status: 'Up' # status of the interface
@@ -519,11 +517,9 @@ module VagrantPlugins
519
517
  }
520
518
 
521
519
  adapter = net_info['Parallels adapter']
522
- if adapter && net_info['Bound To']
523
- # In PD >= 10.1.2 there are new field names for an IP/Subnet
524
- iface[:ip] = adapter['IP address'] || adapter['IPv4 address']
525
- iface[:netmask] = adapter['Subnet mask'] || adapter['IPv4 subnet mask']
526
- iface[:bound_to] = net_info['Bound To']
520
+ if adapter
521
+ iface[:ip] = adapter['IPv4 address']
522
+ iface[:netmask] = adapter['IPv4 subnet mask']
527
523
  iface[:status] = 'Up'
528
524
 
529
525
  if adapter['IPv6 address'] && adapter['IPv6 subnet mask']
@@ -618,11 +614,9 @@ module VagrantPlugins
618
614
  }
619
615
  adapter = net_info['Parallels adapter']
620
616
 
621
- if adapter && net_info['Bound To']
622
- # In PD >= 10.1.2 there are new field names for an IP/Subnet
623
- iface[:ip] = adapter['IP address'] || adapter['IPv4 address']
624
- iface[:netmask] = adapter['Subnet mask'] || adapter['IPv4 subnet mask']
625
- iface[:bound_to] = net_info['Bound To']
617
+ if adapter
618
+ iface[:ip] = adapter['IPv4 address']
619
+ iface[:netmask] = adapter['IPv4 subnet mask']
626
620
  iface[:status] = 'Up'
627
621
  end
628
622
 
@@ -27,10 +27,6 @@ module VagrantPlugins
27
27
  error_key(:json_parse_error)
28
28
  end
29
29
 
30
- class LinuxMountFailed < VagrantParallelsError
31
- error_key(:linux_mount_failed)
32
- end
33
-
34
30
  class LinuxPrlFsInvalidOptions < VagrantParallelsError
35
31
  error_key(:linux_prl_fs_invalid_options)
36
32
  end
@@ -39,6 +35,10 @@ module VagrantPlugins
39
35
  error_key(:mac_os_x_required)
40
36
  end
41
37
 
38
+ class NetworkCollision < VagrantParallelsError
39
+ error_key(:network_collision)
40
+ end
41
+
42
42
  class NetworkInvalidAddress < VagrantParallelsError
43
43
  error_key(:network_invalid_address)
44
44
  end
@@ -55,6 +55,10 @@ module VagrantPlugins
55
55
  error_key(:parallels_invalid_version)
56
56
  end
57
57
 
58
+ class ParallelsMountFailed < VagrantParallelsError
59
+ error_key(:parallels_mount_failed)
60
+ end
61
+
58
62
  class ParallelsNotDetected < VagrantParallelsError
59
63
  error_key(:parallels_not_detected)
60
64
  end
@@ -104,4 +108,4 @@ module VagrantPlugins
104
108
  end
105
109
  end
106
110
  end
107
- end
111
+ end
@@ -1,7 +1,19 @@
1
+ require 'shellwords'
2
+
3
+ require_relative "../../util/unix_mount_helpers"
4
+
1
5
  module VagrantPlugins
2
6
  module Parallels
3
7
  module GuestLinuxCap
4
8
  class MountParallelsSharedFolder
9
+ extend VagrantPlugins::Parallels::Util::UnixMountHelpers
10
+
11
+ # Mounts Parallels Desktop shared folder on linux guest
12
+ #
13
+ # @param [Machine] machine
14
+ # @param [String] name of mount
15
+ # @param [String] path of mount on guest
16
+ # @param [Hash] hash of mount options
5
17
  def self.mount_parallels_shared_folder(machine, name, guestpath, options)
6
18
  # Sanity check for mount options: we are not supporting
7
19
  # VirtualBox-specific 'fmode' and 'dmode' options
@@ -15,83 +27,38 @@ module VagrantPlugins
15
27
  end
16
28
  end
17
29
 
18
- expanded_guest_path = machine.guest.capability(
19
- :shell_expand_guest_path, guestpath)
30
+ guest_path = Shellwords.escape(guestpath)
31
+ mount_type = options[:plugin].capability(:mount_type)
20
32
 
21
- mount_commands = []
33
+ @@logger.debug("Mounting #{name} (#{options[:hostpath]} to #{guestpath})")
22
34
 
23
- if options[:owner].is_a? Integer
24
- mount_uid = options[:owner]
25
- else
26
- mount_uid = "`id -u #{options[:owner]}`"
27
- end
28
-
29
- if options[:group].is_a? Integer
30
- mount_gid = options[:group]
31
- mount_gid_old = options[:group]
32
- else
33
- mount_gid = "`getent group #{options[:group]} | cut -d: -f3`"
34
- mount_gid_old = "`id -g #{options[:group]}`"
35
- end
36
-
37
- # First mount command uses getent to get the group
38
- mount_options = "-o uid=#{mount_uid},gid=#{mount_gid}"
39
- mount_options += ",#{options[:mount_options].join(',')}" if options[:mount_options]
40
- mount_commands << "mount -t prl_fs #{mount_options} #{name} #{expanded_guest_path}"
41
-
42
- # Second mount command uses the old style `id -g`
43
- mount_options = "-o uid=#{mount_uid},gid=#{mount_gid_old}"
44
- mount_options += ",#{options[:mount_options].join(',')}" if options[:mount_options]
45
- mount_commands << "mount -t prl_fs #{mount_options} #{name} #{expanded_guest_path}"
46
-
47
- # Clear prior symlink if exists
48
- if machine.communicate.test("test -L #{expanded_guest_path}")
49
- machine.communicate.sudo("rm #{expanded_guest_path}")
50
- end
35
+ mount_options, mount_uid, mount_gid = options[:plugin].capability(:mount_options, name, guest_path, options)
36
+ mount_command = "mount -t #{mount_type} -o #{mount_options} #{name} #{guest_path}"
51
37
 
52
38
  # Create the guest path if it doesn't exist
53
- machine.communicate.sudo("mkdir -p #{expanded_guest_path}")
39
+ machine.communicate.sudo("mkdir -p #{guest_path}")
54
40
 
55
41
  # Attempt to mount the folder. We retry here a few times because
56
42
  # it can fail early on.
57
- attempts = 0
58
- while true
59
- success = true
60
-
61
- mount_commands.each do |command|
62
- no_such_device = false
63
- status = machine.communicate.sudo(command, error_check: false) do |type, data|
64
- no_such_device = true if type == :stderr && data =~ /No such device/i
65
- end
66
-
67
- success = status == 0 && !no_such_device
68
- break if success
69
- end
70
-
71
- break if success
72
-
73
- attempts += 1
74
- if attempts > 10
75
- raise VagrantPlugins::Parallels::Errors::LinuxMountFailed,
76
- command: mount_commands.join("\n")
77
- end
78
-
79
- sleep 2
43
+ stderr = ""
44
+ retryable(on: Errors::ParallelsMountFailed, tries: 3, sleep: 5) do
45
+ machine.communicate.sudo(mount_command,
46
+ error_class: Errors::ParallelsMountFailed,
47
+ error_key: :parallels_mount_failed,
48
+ command: mount_command,
49
+ output: stderr,
50
+ ) { |type, data| stderr = data if type == :stderr }
80
51
  end
81
52
 
82
- # Emit an upstart event if we can
83
- machine.communicate.sudo <<-EOH.gsub(/^ {10}/, "")
84
- if command -v /sbin/init && /sbin/init 2>/dev/null --version | grep upstart; then
85
- /sbin/initctl emit --no-wait vagrant-mounted MOUNTPOINT=#{expanded_guest_path}
86
- fi
87
- EOH
53
+ emit_upstart_notification(machine, guest_path)
88
54
  end
89
55
 
90
56
  def self.unmount_parallels_shared_folder(machine, guestpath, options)
91
- result = machine.communicate.sudo(
92
- "umount #{guestpath}", error_check: false)
57
+ guest_path = Shellwords.escape(guestpath)
58
+
59
+ result = machine.communicate.sudo("umount #{guest_path}", error_check: false)
93
60
  if result == 0
94
- machine.communicate.sudo("rmdir #{guestpath}", error_check: false)
61
+ machine.communicate.sudo("rmdir #{guest_path}", error_check: false)
95
62
  end
96
63
  end
97
64
 
@@ -103,6 +103,21 @@ module VagrantPlugins
103
103
  SyncedFolder
104
104
  end
105
105
 
106
+ synced_folder_capability(:parallels, "mount_name") do
107
+ require_relative "cap/mount_options"
108
+ SyncedFolderCap::MountOptions
109
+ end
110
+
111
+ synced_folder_capability(:parallels, "mount_options") do
112
+ require_relative "cap/mount_options"
113
+ SyncedFolderCap::MountOptions
114
+ end
115
+
116
+ synced_folder_capability(:parallels, "mount_type") do
117
+ require_relative "cap/mount_options"
118
+ SyncedFolderCap::MountOptions
119
+ end
120
+
106
121
  # This initializes the internationalization strings.
107
122
  def self.setup_i18n
108
123
  I18n.load_path << File.expand_path('locales/en.yml', Parallels.source_root)
@@ -9,8 +9,8 @@ module VagrantPlugins
9
9
  machine.provider_config.functional_psf
10
10
  end
11
11
 
12
- def enable(machine, folders, _opts)
13
- # Export the shared folders to the VM
12
+ def prepare(machine, folders, _opts)
13
+ # Setup shared folder definitions in the VM config.
14
14
  defs = []
15
15
  folders.each do |id, data|
16
16
  hostpath = data[:hostpath]
@@ -19,16 +19,15 @@ module VagrantPlugins
19
19
  end
20
20
 
21
21
  defs << {
22
- name: os_friendly_id(id),
22
+ name: data[:plugin].capability(:mount_name, id, data),
23
23
  hostpath: hostpath.to_s,
24
24
  }
25
25
  end
26
26
 
27
- # We should prepare only folders with unique hostpath values.
28
- # Anyway, duplicates will be mounted later.
29
- defs.uniq! { |d| d[:hostpath] }
30
27
  driver(machine).share_folders(defs)
28
+ end
31
29
 
30
+ def enable(machine, folders, _opts)
32
31
  # short guestpaths first, so we don't step on ourselves
33
32
  folders = folders.sort_by do |id, data|
34
33
  if data[:guestpath]
@@ -39,8 +38,6 @@ module VagrantPlugins
39
38
  end
40
39
  end
41
40
 
42
- shf_config = driver(machine).read_shared_folders
43
-
44
41
  # Parallels Shared Folder services can override Vagrant synced folder
45
42
  # configuration. These services should be pre-configured.
46
43
  if machine.guest.capability?(:prepare_psf_services)
@@ -49,12 +46,8 @@ module VagrantPlugins
49
46
 
50
47
  # Go through each folder and mount
51
48
  machine.ui.output(I18n.t('vagrant.actions.vm.share_folders.mounting'))
52
- folders.each do |_ , data|
53
- # Parallels specific: get id from the VM setting
54
- # It allows to mount one host folder more then one time [GH-105]
55
- id = shf_config.key(data[:hostpath])
56
-
57
- if data[:guestpath] and id
49
+ folders.each do |id , data|
50
+ if data[:guestpath]
58
51
  # Guest path specified, so mount the folder to specified point
59
52
  machine.ui.detail(I18n.t('vagrant.actions.vm.share_folders.mounting_entry',
60
53
  guestpath: data[:guestpath],
@@ -70,7 +63,11 @@ module VagrantPlugins
70
63
 
71
64
  # Mount the actual folder
72
65
  machine.guest.capability(
73
- :mount_parallels_shared_folder, id, data[:guestpath], data)
66
+ :mount_parallels_shared_folder,
67
+ data[:plugin].capability(:mount_name, id, data),
68
+ data[:guestpath],
69
+ data
70
+ )
74
71
  else
75
72
  # If no guest path is specified, then automounting is disabled
76
73
  machine.ui.detail(I18n.t('vagrant.actions.vm.share_folders.nomount_entry',
@@ -89,7 +86,7 @@ module VagrantPlugins
89
86
  end
90
87
 
91
88
  # Remove the shared folders from the VM metadata
92
- names = folders.map { |id, _data| os_friendly_id(id) }
89
+ names = folders.map { |id, data| data[:plugin].capability(:mount_name, id, data) }
93
90
  driver(machine).unshare_folders(names)
94
91
  end
95
92
 
@@ -103,11 +100,6 @@ module VagrantPlugins
103
100
  def driver(machine)
104
101
  machine.provider.driver
105
102
  end
106
-
107
- def os_friendly_id(id)
108
- # Replace chars *, ", :, <, >, ?, |, /, \
109
- id.gsub(/[*":<>?|\/\\]/,'_').sub(/^_/, '')
110
- end
111
103
  end
112
104
  end
113
105
  end
@@ -0,0 +1,121 @@
1
+ require "shellwords"
2
+ require "vagrant/util/retryable"
3
+
4
+ module VagrantPlugins
5
+ module Parallels
6
+ module Util
7
+ module UnixMountHelpers
8
+
9
+ def self.extended(klass)
10
+ if !klass.class_variable_defined?(:@@logger)
11
+ klass.class_variable_set(:@@logger, Log4r::Logger.new(klass.name.downcase))
12
+ end
13
+ klass.extend Vagrant::Util::Retryable
14
+ end
15
+
16
+ def detect_owner_group_ids(machine, guest_path, mount_options, options)
17
+ mount_uid = find_mount_options_id("uid", mount_options)
18
+ mount_gid = find_mount_options_id("gid", mount_options)
19
+
20
+ if mount_uid.nil?
21
+ if options[:owner].to_i.to_s == options[:owner].to_s
22
+ mount_uid = options[:owner]
23
+ self.class_variable_get(:@@logger).debug("Owner user ID (provided): #{mount_uid}")
24
+ else
25
+ output = {stdout: '', stderr: ''}
26
+ uid_command = "id -u #{options[:owner]}"
27
+ machine.communicate.execute(uid_command,
28
+ error_class: Errors::ParallelsMountFailed,
29
+ error_key: :parallels_mount_failed,
30
+ command: uid_command,
31
+ output: output[:stderr]
32
+ ) { |type, data| output[type] << data if output[type] }
33
+ mount_uid = output[:stdout].chomp
34
+ self.class_variable_get(:@@logger).debug("Owner user ID (lookup): #{options[:owner]} -> #{mount_uid}")
35
+ end
36
+ else
37
+ machine.ui.warn "Detected mount owner ID within mount options. (uid: #{mount_uid} guestpath: #{guest_path})"
38
+ end
39
+
40
+ if mount_gid.nil?
41
+ if options[:group].to_i.to_s == options[:group].to_s
42
+ mount_gid = options[:group]
43
+ self.class_variable_get(:@@logger).debug("Owner group ID (provided): #{mount_gid}")
44
+ else
45
+ begin
46
+ output = {stdout: '', stderr: ''}
47
+ gid_command = "getent group #{options[:group]}"
48
+ machine.communicate.execute(gid_command,
49
+ error_class: Errors::ParallelsMountFailed,
50
+ error_key: :parallels_mount_failed,
51
+ command: gid_command,
52
+ output: output[:stderr]
53
+ ) { |type, data| output[type] << data if output[type] }
54
+ mount_gid = output[:stdout].split(':').at(2).to_s.chomp
55
+ self.class_variable_get(:@@logger).debug("Owner group ID (lookup): #{options[:group]} -> #{mount_gid}")
56
+ rescue Vagrant::Errors::ParallelsMountFailed
57
+ if options[:owner] == options[:group]
58
+ self.class_variable_get(:@@logger).debug("Failed to locate group `#{options[:group]}`. Group name matches owner. Fetching effective group ID.")
59
+ output = {stdout: ''}
60
+ result = machine.communicate.execute("id -g #{options[:owner]}",
61
+ error_check: false
62
+ ) { |type, data| output[type] << data if output[type] }
63
+ mount_gid = output[:stdout].chomp if result == 0
64
+ self.class_variable_get(:@@logger).debug("Owner group ID (effective): #{mount_gid}")
65
+ end
66
+ raise unless mount_gid
67
+ end
68
+ end
69
+ else
70
+ machine.ui.warn "Detected mount group ID within mount options. (gid: #{mount_gid} guestpath: #{guest_path})"
71
+ end
72
+ {:gid => mount_gid, :uid => mount_uid}
73
+ end
74
+
75
+ def find_mount_options_id(id_name, mount_options)
76
+ id_line = mount_options.detect{|line| line.include?("#{id_name}=")}
77
+ if id_line
78
+ match = id_line.match(/,?#{Regexp.escape(id_name)}=(?<option_id>\d+),?/)
79
+ found_id = match["option_id"]
80
+ updated_id_line = [
81
+ match.pre_match,
82
+ match.post_match
83
+ ].find_all{|string| !string.empty?}.join(',')
84
+ if updated_id_line.empty?
85
+ mount_options.delete(id_line)
86
+ else
87
+ idx = mount_options.index(id_line)
88
+ mount_options.delete(idx)
89
+ mount_options.insert(idx, updated_id_line)
90
+ end
91
+ end
92
+ found_id
93
+ end
94
+
95
+ def emit_upstart_notification(machine, guest_path)
96
+ # Emit an upstart event if we can
97
+ machine.communicate.sudo <<-EOH.gsub(/^ {12}/, "")
98
+ if command -v /sbin/init && /sbin/init 2>/dev/null --version | grep upstart; then
99
+ /sbin/initctl emit --no-wait vagrant-mounted MOUNTPOINT=#{guest_path}
100
+ fi
101
+ EOH
102
+ end
103
+
104
+ def merge_mount_options(base, overrides)
105
+ base = base.join(",").split(",")
106
+ overrides = overrides.join(",").split(",")
107
+ b_kv = Hash[base.map{|item| item.split("=", 2) }]
108
+ o_kv = Hash[overrides.map{|item| item.split("=", 2) }]
109
+ merged = {}.tap do |opts|
110
+ (b_kv.keys + o_kv.keys).uniq.each do |key|
111
+ opts[key] = o_kv.fetch(key, b_kv[key])
112
+ end
113
+ end
114
+ merged.map do |key, value|
115
+ [key, value].compact.join("=")
116
+ end
117
+ end
118
+ end
119
+ end
120
+ end
121
+ end
@@ -1,5 +1,5 @@
1
1
  module VagrantPlugins
2
2
  module Parallels
3
- VERSION = '2.0.0'
3
+ VERSION = '2.2.2'
4
4
  end
5
5
  end
data/locales/en.yml CHANGED
@@ -45,19 +45,19 @@ en:
45
45
  disk is inconsistent, please remove it from the VM configuration.
46
46
 
47
47
  Disk image path: %{path}
48
- linux_mount_failed: |-
49
- Failed to mount folders in Linux guest. This is usually because
50
- the "prl_fs" file system is not available. Please verify that
51
- Parallels Tools are properly installed in the guest and
52
- can work properly. If so, the VM reboot can solve a problem.
53
- The command attempted was:
54
-
55
- %{command}
56
48
  linux_prl_fs_invalid_options: |-
57
49
  Failed to mount folders in Linux guest. You've specified mount options
58
50
  which are not supported by "prl_fs" file system.
59
51
 
60
52
  Invalid mount options: %{options}
53
+ network_collision: |-
54
+ The specified host network collides with a non-hostonly network!
55
+ This will cause your specified IP to be inaccessible. Please change
56
+ the IP or name of your host only network so that it no longer matches that of
57
+ a bridged or non-hostonly network.
58
+
59
+ Host-only Network Address: '%{hostonly_netaddr}'
60
+ Bridged Network '%{bridge_interface}': '%{bridge_netaddr}'
61
61
  network_invalid_address: |-
62
62
  Network settings specified in your Vagrantfile are invalid:
63
63
 
@@ -73,6 +73,19 @@ en:
73
73
  %{output}
74
74
 
75
75
  This is an internal error that should be reported as a bug.
76
+ parallels_mount_failed: |-
77
+ Vagrant was unable to mount Parallels Desktop shared folders. This is usually
78
+ because the filesystem "prl_fs" is not available. This filesystem is
79
+ made available via the Parallels Tools and kernel module.
80
+ Please verify that these guest tools are properly installed in the
81
+ guest. This is not a bug in Vagrant and is usually caused by a faulty
82
+ Vagrant box. For context, the command attempted was:
83
+
84
+ %{command}
85
+
86
+ The error output from the command was:
87
+
88
+ %{output}
76
89
  parallels_no_room_for_high_level_network: |-
77
90
  There is no available slots on the Parallels Desktop VM for the configured
78
91
  high-level network interfaces. "private_network" and "public_network"
@@ -101,12 +114,12 @@ en:
101
114
  only with Pro and Business editions of Parallels Desktop. Other editions
102
115
  do not have command line functionality and can not be used with Vagrant.
103
116
 
104
- Please upgrade your installation: http://parallels.com/desktop
117
+ Please upgrade your installation: https://parallels.com/desktop
105
118
  parallels_unsupported_version: |-
106
119
  Vagrant has detected that you have a version of Parallels Desktop for Mac
107
120
  installed that is not supported. Vagrant Parallels provider is compatible
108
121
  only with Parallels Desktop 11 or later.
109
- Please upgrade your installation: http://parallels.com/desktop
122
+ Please upgrade your installation: https://parallels.com/desktop
110
123
 
111
124
  Note: Starting since Parallels Desktop 11 for Mac, Vagrant Parallels
112
125
  provider can be only used with Pro or Business edition of Parallels
metadata CHANGED
@@ -1,15 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: vagrant-parallels
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.0
4
+ version: 2.2.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Mikhail Zholobov
8
8
  - Youssef Shahin
9
- autorequire:
9
+ autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2018-11-19 00:00:00.000000000 Z
12
+ date: 2021-06-23 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: nokogiri
@@ -31,14 +31,14 @@ dependencies:
31
31
  requirements:
32
32
  - - "~>"
33
33
  - !ruby/object:Gem::Version
34
- version: 11.3.0
34
+ version: 12.3.3
35
35
  type: :development
36
36
  prerelease: false
37
37
  version_requirements: !ruby/object:Gem::Requirement
38
38
  requirements:
39
39
  - - "~>"
40
40
  - !ruby/object:Gem::Version
41
- version: 11.3.0
41
+ version: 12.3.3
42
42
  - !ruby/object:Gem::Dependency
43
43
  name: rspec
44
44
  requirement: !ruby/object:Gem::Requirement
@@ -59,14 +59,14 @@ dependencies:
59
59
  requirements:
60
60
  - - "~>"
61
61
  - !ruby/object:Gem::Version
62
- version: 1.2.0
62
+ version: 1.3.0
63
63
  type: :development
64
64
  prerelease: false
65
65
  version_requirements: !ruby/object:Gem::Requirement
66
66
  requirements:
67
67
  - - "~>"
68
68
  - !ruby/object:Gem::Version
69
- version: 1.2.0
69
+ version: 1.3.0
70
70
  description: Enables Vagrant to manage Parallels virtual machines.
71
71
  email:
72
72
  - mzholobov@parallels.com
@@ -98,6 +98,7 @@ files:
98
98
  - lib/vagrant-parallels/action/network.rb
99
99
  - lib/vagrant-parallels/action/package.rb
100
100
  - lib/vagrant-parallels/action/package_config_files.rb
101
+ - lib/vagrant-parallels/action/package_vagrantfile.rb
101
102
  - lib/vagrant-parallels/action/prepare_clone_snapshot.rb
102
103
  - lib/vagrant-parallels/action/prepare_forwarded_port_collision_params.rb
103
104
  - lib/vagrant-parallels/action/prepare_nfs_settings.rb
@@ -111,6 +112,7 @@ files:
111
112
  - lib/vagrant-parallels/action/snapshot_save.rb
112
113
  - lib/vagrant-parallels/action/suspend.rb
113
114
  - lib/vagrant-parallels/cap.rb
115
+ - lib/vagrant-parallels/cap/mount_options.rb
114
116
  - lib/vagrant-parallels/config.rb
115
117
  - lib/vagrant-parallels/driver/base.rb
116
118
  - lib/vagrant-parallels/driver/meta.rb
@@ -127,13 +129,14 @@ files:
127
129
  - lib/vagrant-parallels/provider.rb
128
130
  - lib/vagrant-parallels/synced_folder.rb
129
131
  - lib/vagrant-parallels/util/compile_forwarded_ports.rb
132
+ - lib/vagrant-parallels/util/unix_mount_helpers.rb
130
133
  - lib/vagrant-parallels/version.rb
131
134
  - locales/en.yml
132
- homepage: http://github.com/Parallels/vagrant-parallels
135
+ homepage: https://github.com/Parallels/vagrant-parallels
133
136
  licenses:
134
137
  - MIT
135
138
  metadata: {}
136
- post_install_message:
139
+ post_install_message:
137
140
  rdoc_options: []
138
141
  require_paths:
139
142
  - lib
@@ -148,9 +151,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
148
151
  - !ruby/object:Gem::Version
149
152
  version: 1.3.6
150
153
  requirements: []
151
- rubyforge_project: vagrant-parallels
152
- rubygems_version: 2.6.13
153
- signing_key:
154
+ rubygems_version: 3.0.3
155
+ signing_key:
154
156
  specification_version: 4
155
157
  summary: Parallels provider for Vagrant.
156
158
  test_files: []