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 +5 -5
- data/CHANGELOG.md +36 -3
- data/README.md +13 -16
- data/lib/vagrant-parallels/action.rb +2 -0
- data/lib/vagrant-parallels/action/box_unregister.rb +2 -2
- data/lib/vagrant-parallels/action/network.rb +6 -1
- data/lib/vagrant-parallels/action/package_vagrantfile.rb +33 -0
- data/lib/vagrant-parallels/cap/mount_options.rb +50 -0
- data/lib/vagrant-parallels/driver/base.rb +11 -17
- data/lib/vagrant-parallels/errors.rb +9 -5
- data/lib/vagrant-parallels/guest_cap/linux/mount_parallels_shared_folder.rb +31 -64
- data/lib/vagrant-parallels/plugin.rb +15 -0
- data/lib/vagrant-parallels/synced_folder.rb +13 -21
- data/lib/vagrant-parallels/util/unix_mount_helpers.rb +121 -0
- data/lib/vagrant-parallels/version.rb +1 -1
- data/locales/en.yml +23 -10
- metadata +14 -12
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: d138c790174855049184943ea5dada1b980eee3755f88f5e20059a2851fb2aa9
|
4
|
+
data.tar.gz: 277e1c323a916c085f4b45fed9ede685b1587246ace3e703a89b33038b59147f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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](
|
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](
|
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](
|
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](
|
7
|
-
allowing to manage [Parallels 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.
|
12
|
-
|
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](
|
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](
|
31
|
-
and [Vagrant](
|
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](
|
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](
|
47
|
-
* [Getting Started](
|
48
|
-
* [Boxes](
|
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-
|
56
|
+
* Copyright 2013-2020, Parallels International GmbH.
|
60
57
|
|
61
|
-
Vagrant Parallels Provider is open-sourced software licensed under the [MIT license](
|
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
|
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 <=
|
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
|
-
|
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
|
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
|
-
|
200
|
-
#
|
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['
|
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
|
523
|
-
|
524
|
-
iface[:
|
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
|
622
|
-
|
623
|
-
iface[:
|
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
|
-
|
19
|
-
|
30
|
+
guest_path = Shellwords.escape(guestpath)
|
31
|
+
mount_type = options[:plugin].capability(:mount_type)
|
20
32
|
|
21
|
-
|
33
|
+
@@logger.debug("Mounting #{name} (#{options[:hostpath]} to #{guestpath})")
|
22
34
|
|
23
|
-
|
24
|
-
|
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 #{
|
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
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
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
|
-
|
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
|
-
|
92
|
-
|
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 #{
|
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
|
13
|
-
#
|
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:
|
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 |
|
53
|
-
|
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
|
-
|
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,
|
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
|
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:
|
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:
|
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.
|
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:
|
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:
|
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:
|
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.
|
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.
|
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:
|
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
|
-
|
152
|
-
|
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: []
|