vagrant-parallels 1.6.3 → 1.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +17 -1
- data/README.md +7 -18
- data/lib/vagrant-parallels/action/box_register.rb +3 -5
- data/lib/vagrant-parallels/action/clear_forwarded_ports.rb +0 -5
- data/lib/vagrant-parallels/action/destroy.rb +2 -6
- data/lib/vagrant-parallels/action/forward_ports.rb +0 -5
- data/lib/vagrant-parallels/action/import.rb +3 -6
- data/lib/vagrant-parallels/action/network.rb +55 -43
- data/lib/vagrant-parallels/action/prepare_forwarded_port_collision_params.rb +0 -5
- data/lib/vagrant-parallels/action/sane_defaults.rb +2 -10
- data/lib/vagrant-parallels/action.rb +0 -1
- data/lib/vagrant-parallels/config.rb +0 -23
- data/lib/vagrant-parallels/driver/base.rb +186 -10
- data/lib/vagrant-parallels/driver/meta.rb +3 -4
- data/lib/vagrant-parallels/driver/pd_10.rb +2 -212
- data/lib/vagrant-parallels/driver/pd_12.rb +56 -0
- data/lib/vagrant-parallels/errors.rb +4 -0
- data/lib/vagrant-parallels/plugin.rb +1 -2
- data/lib/vagrant-parallels/version.rb +1 -1
- data/locales/en.yml +6 -1
- metadata +3 -5
- data/lib/vagrant-parallels/action/handle_forwarded_port_collisions.rb +0 -30
- data/lib/vagrant-parallels/driver/pd_8.rb +0 -183
- data/lib/vagrant-parallels/driver/pd_9.rb +0 -25
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0e014ab2a7c2e81aebb3325f22e60334982cceed
|
4
|
+
data.tar.gz: 180a1225025aa7b162173b7f46ab7eb695db30ce
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3c932834e0ef5d2e4ae6cc91b17569b0f56c9c6246b23e228a966ffbd1932bb9a0760383382331b9bb985f5f226b4f96a75025f2b5f762a33d40c8732fb45c5b
|
7
|
+
data.tar.gz: 5c55c0dd9852a23133bd4dce45fd395e19790529f1de6b486ccf6cd07737606f170a7fd929af07f1e7b8eeaf8524f77bcc9e659c762221b3c73a507823275dcb
|
data/CHANGELOG.md
CHANGED
@@ -1,6 +1,22 @@
|
|
1
|
+
## 1.7.0 (November 15, 2016)
|
2
|
+
BREAKING CHANGES:
|
3
|
+
- **Dropped support of Parallels Desktop 8 and 9**. These versions have
|
4
|
+
reached their [End-of-Life and End-of-Support](http://kb.parallels.com/eu/122533).
|
5
|
+
- **Removed customization options, which were previously deprecated:**
|
6
|
+
[[GH-271](https://github.com/Parallels/vagrant-parallels/pull/271)]
|
7
|
+
- "use_linked_clone" - use `linked_clone` instead.
|
8
|
+
- "regen_box_uuid" - use `regen_src_uuid` instead.
|
9
|
+
- "optimize_power_consumption".
|
10
|
+
|
11
|
+
FEATURES:
|
12
|
+
- **IPv6 Private Networks:** Private networking now supports IPv6.
|
13
|
+
This only works with Parallels Desktop 12 and higher.
|
14
|
+
[[GH-273](https://github.com/Parallels/vagrant-parallels/pull/273)]
|
15
|
+
|
16
|
+
|
1
17
|
## 1.6.3 (July 11, 2016)
|
2
18
|
DEPRECATIONS:
|
3
|
-
- The following provider options
|
19
|
+
- The following provider options were renamed:
|
4
20
|
- `regen_box_uuid` was renamed to `regen_src_uuid`
|
5
21
|
- `use_linked_clone` was renamed to `linked clone`
|
6
22
|
|
data/README.md
CHANGED
@@ -4,15 +4,15 @@
|
|
4
4
|
[](https://codeclimate.com/github/Parallels/vagrant-parallels)
|
5
5
|
|
6
6
|
This is a plugin for [Vagrant](http://www.vagrantup.com),
|
7
|
-
allowing to
|
8
|
-
|
7
|
+
allowing to manage [Parallels Desktop](http://www.parallels.com/products/desktop/)
|
8
|
+
virtual machines on OS X hosts.
|
9
9
|
|
10
10
|
### Requirements
|
11
11
|
- [Vagrant v1.8](http://www.vagrantup.com) or higher
|
12
|
-
- [Parallels Desktop
|
12
|
+
- [Parallels Desktop 10 for Mac](http://www.parallels.com/products/desktop/) or higher
|
13
13
|
|
14
|
-
*Note:*
|
15
|
-
|
14
|
+
*Note:* Only **Pro** and **Business** editions of **Parallels Desktop for Mac**
|
15
|
+
are compatible with this Vagrant provider.
|
16
16
|
Standard edition doesn't have a command line functionality and can not be used
|
17
17
|
with Vagrant.
|
18
18
|
|
@@ -55,17 +55,6 @@ please report it on the [Issue Tracker](https://github.com/Parallels/vagrant-par
|
|
55
55
|
|
56
56
|
* Author: Youssef Shahin <yshahin@gmail.com>
|
57
57
|
* Author: Mikhail Zholobov <legal90@gmail.com>
|
58
|
-
* Copyright 2013-
|
58
|
+
* Copyright 2013-2016, Parallels IP Holdings GmbH.
|
59
59
|
|
60
|
-
|
61
|
-
Licensed under the Apache License, Version 2.0 (the "License");
|
62
|
-
you may not use this file except in compliance with the License.
|
63
|
-
You may obtain a copy of the License at
|
64
|
-
|
65
|
-
http://www.apache.org/licenses/LICENSE-2.0
|
66
|
-
|
67
|
-
Unless required by applicable law or agreed to in writing, software
|
68
|
-
distributed under the License is distributed on an "AS IS" BASIS,
|
69
|
-
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
70
|
-
See the License for the specific language governing permissions and
|
71
|
-
```
|
60
|
+
Vagrant Parallels Provider is open-sourced software licensed under the [MIT license](http://opensource.org/licenses/MIT).
|
@@ -119,11 +119,9 @@ module VagrantPlugins
|
|
119
119
|
f.write(env[:clone_id])
|
120
120
|
end
|
121
121
|
|
122
|
-
|
123
|
-
|
124
|
-
env[:
|
125
|
-
'set', env[:clone_id], '--template', 'off')
|
126
|
-
end
|
122
|
+
# Convert template to VM (compatibility with old-styled boxes)
|
123
|
+
env[:machine].provider.driver.execute_prlctl(
|
124
|
+
'set', env[:clone_id], '--template', 'off')
|
127
125
|
end
|
128
126
|
end
|
129
127
|
end
|
@@ -7,11 +7,6 @@ module VagrantPlugins
|
|
7
7
|
end
|
8
8
|
|
9
9
|
def call(env)
|
10
|
-
# Port Forwarding feature is available only with PD >= 10
|
11
|
-
if !env[:machine].provider.pd_version_satisfies?('>= 10')
|
12
|
-
return @app.call(env)
|
13
|
-
end
|
14
|
-
|
15
10
|
ports = env[:machine].provider.driver.read_forwarded_ports
|
16
11
|
if !ports.empty?
|
17
12
|
env[:ui].info I18n.t('vagrant.actions.vm.clear_forward_ports.deleting')
|
@@ -8,12 +8,8 @@ module VagrantPlugins
|
|
8
8
|
end
|
9
9
|
|
10
10
|
def call(env)
|
11
|
-
|
12
|
-
|
13
|
-
if env[:machine].provider.pd_version_satisfies?('>= 10')
|
14
|
-
@logger.info('Disabling password restrictions: remove-vm')
|
15
|
-
env[:machine].provider.driver.disable_password_restrictions(['remove-vm'])
|
16
|
-
end
|
11
|
+
@logger.info('Disabling password restrictions: remove-vm')
|
12
|
+
env[:machine].provider.driver.disable_password_restrictions(['remove-vm'])
|
17
13
|
|
18
14
|
env[:ui].info I18n.t('vagrant.actions.vm.destroy.destroying')
|
19
15
|
env[:machine].provider.driver.delete
|
@@ -13,11 +13,6 @@ module VagrantPlugins
|
|
13
13
|
# Execution
|
14
14
|
#--------------------------------------------------------------
|
15
15
|
def call(env)
|
16
|
-
# Port Forwarding feature is available only with PD >= 10
|
17
|
-
if !env[:machine].provider.pd_version_satisfies?('>= 10')
|
18
|
-
return @app.call(env)
|
19
|
-
end
|
20
|
-
|
21
16
|
@env = env
|
22
17
|
|
23
18
|
# Get the ports we're forwarding
|
@@ -17,12 +17,9 @@ module VagrantPlugins
|
|
17
17
|
options = {}
|
18
18
|
|
19
19
|
# Disable requiring password for register and clone actions [GH-67].
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
@logger.info("Disabling password restrictions: #{acts.join(', ')}")
|
24
|
-
env[:machine].provider.driver.disable_password_restrictions(acts)
|
25
|
-
end
|
20
|
+
acts = ['clone-vm']
|
21
|
+
@logger.info("Disabling password restrictions: #{acts.join(', ')}")
|
22
|
+
env[:machine].provider.driver.disable_password_restrictions(acts)
|
26
23
|
|
27
24
|
if env[:machine].provider_config.regen_src_uuid \
|
28
25
|
&& env[:machine].provider.pd_version_satisfies?('>= 10.1.2')
|
@@ -1,8 +1,7 @@
|
|
1
|
+
require 'ipaddr'
|
1
2
|
require 'set'
|
2
|
-
|
3
3
|
require 'log4r'
|
4
4
|
|
5
|
-
require 'vagrant/util/network_ip'
|
6
5
|
require 'vagrant/util/scoped_hash_override'
|
7
6
|
|
8
7
|
module VagrantPlugins
|
@@ -14,7 +13,6 @@ module VagrantPlugins
|
|
14
13
|
#
|
15
14
|
# This handles all the `config.vm.network` configurations.
|
16
15
|
class Network
|
17
|
-
include Vagrant::Util::NetworkIP
|
18
16
|
include Vagrant::Util::ScopedHashOverride
|
19
17
|
@@lock = Mutex.new
|
20
18
|
|
@@ -253,7 +251,6 @@ module VagrantPlugins
|
|
253
251
|
mac: nil,
|
254
252
|
name: nil,
|
255
253
|
nic_type: nil,
|
256
|
-
netmask: '255.255.255.0',
|
257
254
|
type: :static
|
258
255
|
}.merge(options)
|
259
256
|
|
@@ -263,47 +260,57 @@ module VagrantPlugins
|
|
263
260
|
# Default IP is in the 20-bit private network block for DHCP based networks
|
264
261
|
options[:ip] = '10.37.129.1' if options[:type] == :dhcp && !options[:ip]
|
265
262
|
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
263
|
+
begin
|
264
|
+
ip = IPAddr.new(options[:ip])
|
265
|
+
if ip.ipv4?
|
266
|
+
options[:netmask] ||= '255.255.255.0'
|
267
|
+
elsif ip.ipv6?
|
268
|
+
options[:netmask] ||= 64
|
269
|
+
|
270
|
+
# Append a 6 to the end of the type
|
271
|
+
options[:type] = "#{options[:type]}6".to_sym
|
272
|
+
else
|
273
|
+
raise IPAddr::AddressFamilyError, 'unknown address family'
|
274
|
+
end
|
275
|
+
|
276
|
+
# Calculate our network address for the given IP/netmask
|
277
|
+
netaddr = IPAddr.new("#{options[:ip]}/#{options[:netmask]}")
|
278
|
+
rescue IPAddr::Error => e
|
279
|
+
raise VagrantPlugins::Parallels::Errors::NetworkInvalidAddress,
|
280
|
+
options: options, error: e.message
|
280
281
|
end
|
281
282
|
|
282
|
-
|
283
|
-
|
283
|
+
if ip.ipv4?
|
284
|
+
# Verify that a host-only network subnet would not collide
|
285
|
+
# with a bridged networking interface.
|
286
|
+
#
|
287
|
+
# If the subnets overlap in any way then the host only network
|
288
|
+
# will not work because the routing tables will force the
|
289
|
+
# traffic onto the real interface rather than the virtual
|
290
|
+
# network interface.
|
291
|
+
@env[:machine].provider.driver.read_bridged_interfaces.each do |interface|
|
292
|
+
next if interface[:status] == 'Down'
|
293
|
+
that_netaddr = IPAddr.new("#{interface[:ip]}/#{interface[:netmask]}")
|
294
|
+
raise Vagrant::Errors::NetworkCollision if netaddr.include? that_netaddr
|
295
|
+
end
|
296
|
+
end
|
284
297
|
|
285
|
-
# Calculate the adapter IP
|
286
|
-
#
|
287
|
-
|
288
|
-
adapter_ip
|
289
|
-
options[:adapter_ip] ||= adapter_ip.join('.')
|
298
|
+
# Calculate the adapter IP which is the network address with the final
|
299
|
+
# bit group appended by 1. Usually it is "x.x.x.1" for IPv4 and
|
300
|
+
# "<prefix>::1" for IPv6
|
301
|
+
options[:adapter_ip] ||= (netaddr | 1).to_s
|
290
302
|
|
291
303
|
dhcp_options = {}
|
292
304
|
if options[:type] == :dhcp
|
293
|
-
# Calculate the
|
294
|
-
#
|
295
|
-
dhcp_ip
|
296
|
-
|
297
|
-
|
298
|
-
|
299
|
-
|
300
|
-
dhcp_lower
|
301
|
-
|
302
|
-
dhcp_options[:dhcp_lower] = options[:dhcp_lower] || dhcp_lower.join('.')
|
303
|
-
|
304
|
-
dhcp_upper = ip_parts.dup
|
305
|
-
dhcp_upper[3] = 254
|
306
|
-
dhcp_options[:dhcp_upper] = options[:dhcp_upper] || dhcp_upper.join('.')
|
305
|
+
# Calculate the IP and lower & upper bound for the DHCP server
|
306
|
+
# Example: for "192.168.22.64/26" network range it wil be:
|
307
|
+
# dhcp_ip: "192.168.22.65",
|
308
|
+
# dhcp_lower: "192.168.22.66"
|
309
|
+
# dhcp_upper: "192.168.22.126"
|
310
|
+
ip_range = netaddr.to_range
|
311
|
+
dhcp_options[:dhcp_ip] = options[:dhcp_ip] || (ip_range.first | 1).to_s
|
312
|
+
dhcp_options[:dhcp_lower] = options[:dhcp_lower] || (ip_range.first | 2).to_s
|
313
|
+
dhcp_options[:dhcp_upper] = options[:dhcp_upper] || (ip_range.last(2).first).to_s
|
307
314
|
end
|
308
315
|
|
309
316
|
{
|
@@ -444,14 +451,19 @@ module VagrantPlugins
|
|
444
451
|
|
445
452
|
# This finds a matching host only network for the given configuration.
|
446
453
|
def hostonly_find_matching_network(config)
|
447
|
-
this_netaddr =
|
454
|
+
this_netaddr = IPAddr.new("#{config[:ip]}/#{config[:netmask]}")
|
448
455
|
|
449
456
|
@env[:machine].provider.driver.read_host_only_interfaces.each do |interface|
|
450
457
|
return interface if config[:name] && config[:name] == interface[:name]
|
451
458
|
|
452
|
-
if interface[:ip]
|
453
|
-
|
454
|
-
|
459
|
+
if interface[:ip] && this_netaddr.ipv4?
|
460
|
+
netaddr = IPAddr.new("#{interface[:ip]}/#{interface[:netmask]}")
|
461
|
+
return interface if netaddr.include? this_netaddr
|
462
|
+
end
|
463
|
+
|
464
|
+
if interface[:ipv6] && this_netaddr.ipv6?
|
465
|
+
netaddr = IPAddr.new("#{interface[:ipv6]}/#{interface[:ipv6_prefix]}")
|
466
|
+
return interface if netaddr.include? this_netaddr
|
455
467
|
end
|
456
468
|
end
|
457
469
|
|
@@ -7,11 +7,6 @@ module VagrantPlugins
|
|
7
7
|
end
|
8
8
|
|
9
9
|
def call(env)
|
10
|
-
# Port Forwarding feature is available only with PD >= 10
|
11
|
-
if !env[:machine].provider.pd_version_satisfies?('>= 10')
|
12
|
-
return @app.call(env)
|
13
|
-
end
|
14
|
-
|
15
10
|
# Get the forwarded ports used by other virtual machines and
|
16
11
|
# consider those in use as well.
|
17
12
|
env[:port_collision_extra_in_use] =
|
@@ -30,22 +30,14 @@ module VagrantPlugins
|
|
30
30
|
private
|
31
31
|
|
32
32
|
def default_settings
|
33
|
-
settings = {
|
34
|
-
|
35
|
-
return settings if @env[:machine].provider.pd_version_satisfies?('< 9')
|
36
|
-
settings.merge!(
|
33
|
+
settings = {
|
37
34
|
startup_view: 'same',
|
38
35
|
on_shutdown: 'close',
|
39
36
|
on_window_close: 'keep-running',
|
40
37
|
auto_share_camera: 'off',
|
41
38
|
smart_guard: 'off',
|
42
39
|
longer_battery_life: 'on'
|
43
|
-
|
44
|
-
|
45
|
-
# Check the legacy option
|
46
|
-
if !@env[:machine].provider_config.optimize_power_consumption
|
47
|
-
settings[:longer_battery_life] = 'off'
|
48
|
-
end
|
40
|
+
}
|
49
41
|
|
50
42
|
return settings if @env[:machine].provider.pd_version_satisfies?('< 10.1.2')
|
51
43
|
settings.merge!(
|
@@ -394,7 +394,6 @@ module VagrantPlugins
|
|
394
394
|
autoload :BoxRegister, File.expand_path('../action/box_register', __FILE__)
|
395
395
|
autoload :BoxUnregister, File.expand_path('../action/box_unregister', __FILE__)
|
396
396
|
autoload :HandleGuestTools, File.expand_path('../action/handle_guest_tools', __FILE__)
|
397
|
-
autoload :HandleForwardedPortCollisions, File.expand_path('../action/handle_forwarded_port_collisions.rb', __FILE__)
|
398
397
|
autoload :CheckSharedInterface, File.expand_path('../action/check_shared_interface', __FILE__)
|
399
398
|
autoload :ClearNetworkInterfaces, File.expand_path('../action/clear_network_interfaces', __FILE__)
|
400
399
|
autoload :ClearForwardedPorts, File.expand_path('../action/clear_forwarded_ports', __FILE__)
|
@@ -13,10 +13,6 @@ module VagrantPlugins
|
|
13
13
|
attr_accessor :regen_src_uuid
|
14
14
|
attr_accessor :update_guest_tools
|
15
15
|
|
16
|
-
# Deprecated options
|
17
|
-
attr_accessor :regen_box_uuid
|
18
|
-
attr_accessor :use_linked_clone
|
19
|
-
|
20
16
|
# Compatibility with virtualbox provider's syntax
|
21
17
|
alias :check_guest_additions= :check_guest_tools=
|
22
18
|
|
@@ -29,15 +25,10 @@ module VagrantPlugins
|
|
29
25
|
@linked_clone_snapshot = UNSET_VALUE
|
30
26
|
@network_adapters = {}
|
31
27
|
@name = UNSET_VALUE
|
32
|
-
@optimize_power_consumption = UNSET_VALUE
|
33
28
|
@regen_src_uuid = UNSET_VALUE
|
34
29
|
@update_guest_tools = UNSET_VALUE
|
35
30
|
|
36
31
|
network_adapter(0, :shared)
|
37
|
-
|
38
|
-
# Deprecated options
|
39
|
-
@regen_box_uuid = UNSET_VALUE
|
40
|
-
@use_linked_clone = UNSET_VALUE
|
41
32
|
end
|
42
33
|
|
43
34
|
def customize(*command)
|
@@ -68,16 +59,6 @@ module VagrantPlugins
|
|
68
59
|
end
|
69
60
|
|
70
61
|
def finalize!
|
71
|
-
if @regen_box_uuid != UNSET_VALUE
|
72
|
-
puts "Parallels provider: Vagrantfile option 'regen_box_uuid' is deprecated and will be removed. Please, use 'regen_src_uuid' instead"
|
73
|
-
@regen_src_uuid = @regen_box_uuid if @regen_src_uuid == UNSET_VALUE
|
74
|
-
end
|
75
|
-
|
76
|
-
if @use_linked_clone != UNSET_VALUE
|
77
|
-
puts "Parallels provider: Vagrantfile option 'use_linked_clone' is deprecated and will be removed. Please, use 'linked_clone' instead"
|
78
|
-
@linked_clone = @use_linked_clone if @linked_clone == UNSET_VALUE
|
79
|
-
end
|
80
|
-
|
81
62
|
if @check_guest_tools == UNSET_VALUE
|
82
63
|
@check_guest_tools = true
|
83
64
|
end
|
@@ -118,10 +99,6 @@ module VagrantPlugins
|
|
118
99
|
end
|
119
100
|
end
|
120
101
|
|
121
|
-
if @optimize_power_consumption != UNSET_VALUE
|
122
|
-
machine.env.ui.warn I18n.t('vagrant_parallels.config.deprecate_power_consumption')
|
123
|
-
end
|
124
|
-
|
125
102
|
{ 'Parallels Provider' => errors }
|
126
103
|
end
|
127
104
|
end
|
@@ -54,7 +54,14 @@ module VagrantPlugins
|
|
54
54
|
# }
|
55
55
|
#
|
56
56
|
def clear_forwarded_ports(ports)
|
57
|
-
|
57
|
+
args = []
|
58
|
+
ports.each do |r|
|
59
|
+
args.concat(["--nat-#{r[:protocol]}-del", r[:name]])
|
60
|
+
end
|
61
|
+
|
62
|
+
if !args.empty?
|
63
|
+
execute_prlsrvctl('net', 'set', read_shared_network_id, *args)
|
64
|
+
end
|
58
65
|
end
|
59
66
|
|
60
67
|
# Clears the shared folders that have been set on the virtual machine.
|
@@ -187,7 +194,25 @@ module VagrantPlugins
|
|
187
194
|
|
188
195
|
# Deletes any host only networks that aren't being used for anything.
|
189
196
|
def delete_unused_host_only_networks
|
190
|
-
|
197
|
+
networks = read_virtual_networks
|
198
|
+
# 'Shared'(vnic0) and 'Host-Only'(vnic1) are default in Parallels Desktop
|
199
|
+
# They should not be deleted anyway.
|
200
|
+
networks.keep_if do |net|
|
201
|
+
net['Type'] == 'host-only' && net['Bound To'] &&
|
202
|
+
net['Bound To'].match(/^(?>vnic|Parallels Host-Only #)(\d+)$/)[1].to_i >= 2
|
203
|
+
end
|
204
|
+
|
205
|
+
read_vms_info.each do |vm|
|
206
|
+
used_nets = vm.fetch('Hardware', {}).select { |name, _| name.start_with? 'net' }
|
207
|
+
used_nets.each_value do |net_params|
|
208
|
+
networks.delete_if { |net| net['Network ID'] == net_params.fetch('iface', nil) }
|
209
|
+
end
|
210
|
+
end
|
211
|
+
|
212
|
+
networks.each do |net|
|
213
|
+
# Delete the actual host only network interface.
|
214
|
+
execute_prlsrvctl('net', 'del', net['Network ID'])
|
215
|
+
end
|
191
216
|
end
|
192
217
|
|
193
218
|
# Disables requiring password on such operations as creating, adding,
|
@@ -196,7 +221,10 @@ module VagrantPlugins
|
|
196
221
|
# @param [Array<String>] acts List of actions. Available values:
|
197
222
|
# ['create-vm', 'add-vm', 'remove-vm', 'clone-vm']
|
198
223
|
def disable_password_restrictions(acts)
|
199
|
-
|
224
|
+
server_info = json { execute_prlsrvctl('info', '--json') }
|
225
|
+
server_info.fetch('Require password to',[]).each do |act|
|
226
|
+
execute_prlsrvctl('set', '--require-pwd', "#{act}:off") if acts.include? act
|
227
|
+
end
|
200
228
|
end
|
201
229
|
|
202
230
|
# Enables network adapters on the VM.
|
@@ -215,7 +243,45 @@ module VagrantPlugins
|
|
215
243
|
# @param [Array<Symbol => Symbol, String>] adapters
|
216
244
|
# Array of adapters to be enabled.
|
217
245
|
def enable_adapters(adapters)
|
218
|
-
|
246
|
+
# Get adapters which have already configured for this VM
|
247
|
+
# Such adapters will be just overridden
|
248
|
+
existing_adapters = read_settings.fetch('Hardware', {}).keys.select do |name|
|
249
|
+
name.start_with? 'net'
|
250
|
+
end
|
251
|
+
|
252
|
+
# Disable all previously existing adapters (except shared 'vnet0')
|
253
|
+
existing_adapters.each do |adapter|
|
254
|
+
if adapter != 'vnet0'
|
255
|
+
execute_prlctl('set', @uuid, '--device-set', adapter, '--disable')
|
256
|
+
end
|
257
|
+
end
|
258
|
+
|
259
|
+
adapters.each do |adapter|
|
260
|
+
args = []
|
261
|
+
if existing_adapters.include? "net#{adapter[:adapter]}"
|
262
|
+
args.concat(['--device-set',"net#{adapter[:adapter]}", '--enable'])
|
263
|
+
else
|
264
|
+
args.concat(['--device-add', 'net'])
|
265
|
+
end
|
266
|
+
|
267
|
+
if adapter[:type] == :hostonly
|
268
|
+
args.concat(['--type', 'host', '--iface', adapter[:hostonly]])
|
269
|
+
elsif adapter[:type] == :bridged
|
270
|
+
args.concat(['--type', 'bridged', '--iface', adapter[:bridge]])
|
271
|
+
elsif adapter[:type] == :shared
|
272
|
+
args.concat(['--type', 'shared'])
|
273
|
+
end
|
274
|
+
|
275
|
+
if adapter[:mac_address]
|
276
|
+
args.concat(['--mac', adapter[:mac_address]])
|
277
|
+
end
|
278
|
+
|
279
|
+
if adapter[:nic_type]
|
280
|
+
args.concat(['--adapter-type', adapter[:nic_type].to_s])
|
281
|
+
end
|
282
|
+
|
283
|
+
execute_prlctl('set', @uuid, *args)
|
284
|
+
end
|
219
285
|
end
|
220
286
|
|
221
287
|
# Create a set of port forwarding rules for a virtual machine.
|
@@ -237,7 +303,20 @@ module VagrantPlugins
|
|
237
303
|
# @param [Array<Hash>] ports An array of ports to set. See documentation
|
238
304
|
# for more information on the format.
|
239
305
|
def forward_ports(ports)
|
240
|
-
|
306
|
+
args = []
|
307
|
+
ports.each do |options|
|
308
|
+
protocol = options[:protocol] || 'tcp'
|
309
|
+
pf_builder = [
|
310
|
+
options[:name],
|
311
|
+
options[:hostport],
|
312
|
+
@uuid,
|
313
|
+
options[:guestport]
|
314
|
+
]
|
315
|
+
|
316
|
+
args.concat(["--nat-#{protocol}-add", pf_builder.join(',')])
|
317
|
+
end
|
318
|
+
|
319
|
+
execute_prlsrvctl('net', 'set', read_shared_network_id, *args)
|
241
320
|
end
|
242
321
|
|
243
322
|
# Lists all snapshots for the specified VM. Returns an empty hash if
|
@@ -328,7 +407,13 @@ module VagrantPlugins
|
|
328
407
|
# Otherwise only rules related to the context VM will be returned.
|
329
408
|
# @return [Array<Symbol => String>]
|
330
409
|
def read_forwarded_ports(global=false)
|
331
|
-
|
410
|
+
all_rules = read_shared_interface[:nat]
|
411
|
+
|
412
|
+
if global
|
413
|
+
all_rules
|
414
|
+
else
|
415
|
+
all_rules.select { |r| r[:guest].include?(@uuid) }
|
416
|
+
end
|
332
417
|
end
|
333
418
|
|
334
419
|
# Returns an IP of the virtual machine. It requires that Shared network
|
@@ -418,7 +503,37 @@ module VagrantPlugins
|
|
418
503
|
#
|
419
504
|
# @return [Array<Symbol => String>]
|
420
505
|
def read_host_only_interfaces
|
421
|
-
|
506
|
+
net_list = read_virtual_networks
|
507
|
+
net_list.keep_if { |net| net['Type'] == 'host-only' }
|
508
|
+
|
509
|
+
hostonly_ifaces = []
|
510
|
+
net_list.each do |iface|
|
511
|
+
net_info = json do
|
512
|
+
execute_prlsrvctl('net', 'info', iface['Network ID'], '--json')
|
513
|
+
end
|
514
|
+
|
515
|
+
iface = {
|
516
|
+
name: net_info['Network ID'],
|
517
|
+
status: 'Down'
|
518
|
+
}
|
519
|
+
|
520
|
+
adapter = net_info['Parallels adapter']
|
521
|
+
if adapter && net_info['Bound To']
|
522
|
+
# In PD >= 10.1.2 there are new field names for an IP/Subnet
|
523
|
+
iface[:ip] = adapter['IP address'] || adapter['IPv4 address']
|
524
|
+
iface[:netmask] = adapter['Subnet mask'] || adapter['IPv4 subnet mask']
|
525
|
+
iface[:bound_to] = net_info['Bound To']
|
526
|
+
iface[:status] = 'Up'
|
527
|
+
|
528
|
+
if adapter['IPv6 address'] && adapter['IPv6 subnet mask']
|
529
|
+
iface[:ipv6] = adapter['IPv6 address']
|
530
|
+
iface[:ipv6_prefix] = adapter['IPv6 subnet mask']
|
531
|
+
end
|
532
|
+
end
|
533
|
+
|
534
|
+
hostonly_ifaces << iface
|
535
|
+
end
|
536
|
+
hostonly_ifaces
|
422
537
|
end
|
423
538
|
|
424
539
|
# Returns the MAC address of the first Shared network interface.
|
@@ -448,7 +563,27 @@ module VagrantPlugins
|
|
448
563
|
#
|
449
564
|
# @return [<Integer => Hash>]
|
450
565
|
def read_network_interfaces
|
451
|
-
|
566
|
+
nics = {}
|
567
|
+
|
568
|
+
# Get enabled VM's network interfaces
|
569
|
+
ifaces = read_settings.fetch('Hardware', {}).keep_if do |dev, params|
|
570
|
+
dev.start_with?('net') and params.fetch('enabled', true)
|
571
|
+
end
|
572
|
+
ifaces.each do |name, params|
|
573
|
+
adapter = name.match(/^net(\d+)$/)[1].to_i
|
574
|
+
nics[adapter] ||= {}
|
575
|
+
|
576
|
+
if params['type'] == 'shared'
|
577
|
+
nics[adapter][:type] = :shared
|
578
|
+
elsif params['type'] == 'host'
|
579
|
+
nics[adapter][:type] = :hostonly
|
580
|
+
nics[adapter][:hostonly] = params.fetch('iface','')
|
581
|
+
elsif params['type'] == 'bridged'
|
582
|
+
nics[adapter][:type] = :bridged
|
583
|
+
nics[adapter][:bridge] = params.fetch('iface','')
|
584
|
+
end
|
585
|
+
end
|
586
|
+
nics
|
452
587
|
end
|
453
588
|
|
454
589
|
# Returns virtual machine settings
|
@@ -472,7 +607,45 @@ module VagrantPlugins
|
|
472
607
|
#
|
473
608
|
# @return [<Symbol => String, Hash>]
|
474
609
|
def read_shared_interface
|
475
|
-
|
610
|
+
net_info = json do
|
611
|
+
execute_prlsrvctl('net', 'info', read_shared_network_id, '--json')
|
612
|
+
end
|
613
|
+
|
614
|
+
iface = {
|
615
|
+
nat: [],
|
616
|
+
status: 'Down'
|
617
|
+
}
|
618
|
+
adapter = net_info['Parallels adapter']
|
619
|
+
|
620
|
+
if adapter && net_info['Bound To']
|
621
|
+
# In PD >= 10.1.2 there are new field names for an IP/Subnet
|
622
|
+
iface[:ip] = adapter['IP address'] || adapter['IPv4 address']
|
623
|
+
iface[:netmask] = adapter['Subnet mask'] || adapter['IPv4 subnet mask']
|
624
|
+
iface[:bound_to] = net_info['Bound To']
|
625
|
+
iface[:status] = 'Up'
|
626
|
+
end
|
627
|
+
|
628
|
+
if net_info.key?('DHCPv4 server')
|
629
|
+
iface[:dhcp] = {
|
630
|
+
ip: net_info['DHCPv4 server']['Server address'],
|
631
|
+
lower: net_info['DHCPv4 server']['IP scope start address'],
|
632
|
+
upper: net_info['DHCPv4 server']['IP scope end address']
|
633
|
+
}
|
634
|
+
end
|
635
|
+
|
636
|
+
net_info['NAT server'].each do |group, rules|
|
637
|
+
rules.each do |name, params|
|
638
|
+
iface[:nat] << {
|
639
|
+
name: name,
|
640
|
+
protocol: group == 'TCP rules' ? 'tcp' : 'udp',
|
641
|
+
guest: params['destination IP/VM id'],
|
642
|
+
hostport: params['source port'],
|
643
|
+
guestport: params['destination port']
|
644
|
+
}
|
645
|
+
end
|
646
|
+
end
|
647
|
+
|
648
|
+
iface
|
476
649
|
end
|
477
650
|
|
478
651
|
# Returns a list of shared folders in format:
|
@@ -501,6 +674,8 @@ module VagrantPlugins
|
|
501
674
|
#
|
502
675
|
# @return [Array]
|
503
676
|
def read_used_ports
|
677
|
+
# Ignore our own used ports
|
678
|
+
read_forwarded_ports(true).reject { |r| r[:guest].include?(@uuid) }
|
504
679
|
end
|
505
680
|
|
506
681
|
# Returns the configuration of all virtual networks in Parallels Desktop.
|
@@ -603,7 +778,8 @@ module VagrantPlugins
|
|
603
778
|
# @param [Boolean] optimized Use "Longer Battery Life"
|
604
779
|
# instead "Better Performance"
|
605
780
|
def set_power_consumption_mode(optimized)
|
606
|
-
|
781
|
+
state = optimized ? 'on' : 'off'
|
782
|
+
execute_prlctl('set', @uuid, '--longer-battery-life', state)
|
607
783
|
end
|
608
784
|
|
609
785
|
# Share a set of folders on this VM.
|
@@ -44,11 +44,10 @@ module VagrantPlugins
|
|
44
44
|
major_ver = @@version.split('.').first.to_i
|
45
45
|
driver_klass =
|
46
46
|
case major_ver
|
47
|
-
when 1..
|
48
|
-
when 8 then PD_8
|
49
|
-
when 9 then PD_9
|
47
|
+
when 1..9 then raise Errors::ParallelsUnsupportedVersion
|
50
48
|
when 10 then PD_10
|
51
|
-
|
49
|
+
when 11 then PD_11
|
50
|
+
else PD_12
|
52
51
|
end
|
53
52
|
|
54
53
|
# Starting since PD 11 only Pro and Business editions have CLI
|
@@ -2,228 +2,18 @@ require 'log4r'
|
|
2
2
|
|
3
3
|
require 'vagrant/util/platform'
|
4
4
|
|
5
|
-
require_relative '
|
5
|
+
require_relative 'base'
|
6
6
|
|
7
7
|
module VagrantPlugins
|
8
8
|
module Parallels
|
9
9
|
module Driver
|
10
10
|
# Driver for Parallels Desktop 10.
|
11
|
-
class PD_10 <
|
11
|
+
class PD_10 < Base
|
12
12
|
def initialize(uuid)
|
13
13
|
super(uuid)
|
14
14
|
|
15
15
|
@logger = Log4r::Logger.new('vagrant_parallels::driver::pd_10')
|
16
16
|
end
|
17
|
-
|
18
|
-
def clear_forwarded_ports(ports)
|
19
|
-
args = []
|
20
|
-
ports.each do |r|
|
21
|
-
args.concat(["--nat-#{r[:protocol]}-del", r[:name]])
|
22
|
-
end
|
23
|
-
|
24
|
-
if !args.empty?
|
25
|
-
execute_prlsrvctl('net', 'set', read_shared_network_id, *args)
|
26
|
-
end
|
27
|
-
end
|
28
|
-
|
29
|
-
|
30
|
-
def delete_unused_host_only_networks
|
31
|
-
networks = read_virtual_networks
|
32
|
-
# 'Shared'(vnic0) and 'Host-Only'(vnic1) are default in Parallels Desktop
|
33
|
-
# They should not be deleted anyway.
|
34
|
-
networks.keep_if do |net|
|
35
|
-
net['Type'] == 'host-only' && net['Bound To'] &&
|
36
|
-
net['Bound To'].match(/^(?>vnic|Parallels Host-Only #)(\d+)$/)[1].to_i >= 2
|
37
|
-
end
|
38
|
-
|
39
|
-
read_vms_info.each do |vm|
|
40
|
-
used_nets = vm.fetch('Hardware', {}).select { |name, _| name.start_with? 'net' }
|
41
|
-
used_nets.each_value do |net_params|
|
42
|
-
networks.delete_if { |net| net['Network ID'] == net_params.fetch('iface', nil) }
|
43
|
-
end
|
44
|
-
end
|
45
|
-
|
46
|
-
networks.each do |net|
|
47
|
-
# Delete the actual host only network interface.
|
48
|
-
execute_prlsrvctl('net', 'del', net['Network ID'])
|
49
|
-
end
|
50
|
-
end
|
51
|
-
|
52
|
-
def disable_password_restrictions(acts)
|
53
|
-
server_info = json { execute_prlsrvctl('info', '--json') }
|
54
|
-
server_info.fetch('Require password to',[]).each do |act|
|
55
|
-
execute_prlsrvctl('set', '--require-pwd', "#{act}:off") if acts.include? act
|
56
|
-
end
|
57
|
-
end
|
58
|
-
|
59
|
-
def enable_adapters(adapters)
|
60
|
-
# Get adapters which have already configured for this VM
|
61
|
-
# Such adapters will be just overridden
|
62
|
-
existing_adapters = read_settings.fetch('Hardware', {}).keys.select do |name|
|
63
|
-
name.start_with? 'net'
|
64
|
-
end
|
65
|
-
|
66
|
-
# Disable all previously existing adapters (except shared 'vnet0')
|
67
|
-
existing_adapters.each do |adapter|
|
68
|
-
if adapter != 'vnet0'
|
69
|
-
execute_prlctl('set', @uuid, '--device-set', adapter, '--disable')
|
70
|
-
end
|
71
|
-
end
|
72
|
-
|
73
|
-
adapters.each do |adapter|
|
74
|
-
args = []
|
75
|
-
if existing_adapters.include? "net#{adapter[:adapter]}"
|
76
|
-
args.concat(['--device-set',"net#{adapter[:adapter]}", '--enable'])
|
77
|
-
else
|
78
|
-
args.concat(['--device-add', 'net'])
|
79
|
-
end
|
80
|
-
|
81
|
-
if adapter[:type] == :hostonly
|
82
|
-
args.concat(['--type', 'host', '--iface', adapter[:hostonly]])
|
83
|
-
elsif adapter[:type] == :bridged
|
84
|
-
args.concat(['--type', 'bridged', '--iface', adapter[:bridge]])
|
85
|
-
elsif adapter[:type] == :shared
|
86
|
-
args.concat(['--type', 'shared'])
|
87
|
-
end
|
88
|
-
|
89
|
-
if adapter[:mac_address]
|
90
|
-
args.concat(['--mac', adapter[:mac_address]])
|
91
|
-
end
|
92
|
-
|
93
|
-
if adapter[:nic_type]
|
94
|
-
args.concat(['--adapter-type', adapter[:nic_type].to_s])
|
95
|
-
end
|
96
|
-
|
97
|
-
execute_prlctl('set', @uuid, *args)
|
98
|
-
end
|
99
|
-
end
|
100
|
-
|
101
|
-
def forward_ports(ports)
|
102
|
-
args = []
|
103
|
-
ports.each do |options|
|
104
|
-
protocol = options[:protocol] || 'tcp'
|
105
|
-
pf_builder = [
|
106
|
-
options[:name],
|
107
|
-
options[:hostport],
|
108
|
-
@uuid,
|
109
|
-
options[:guestport]
|
110
|
-
]
|
111
|
-
|
112
|
-
args.concat(["--nat-#{protocol}-add", pf_builder.join(',')])
|
113
|
-
end
|
114
|
-
|
115
|
-
execute_prlsrvctl('net', 'set', read_shared_network_id, *args)
|
116
|
-
end
|
117
|
-
|
118
|
-
def read_forwarded_ports(global=false)
|
119
|
-
all_rules = read_shared_interface[:nat]
|
120
|
-
|
121
|
-
if global
|
122
|
-
all_rules
|
123
|
-
else
|
124
|
-
all_rules.select { |r| r[:guest].include?(@uuid) }
|
125
|
-
end
|
126
|
-
end
|
127
|
-
|
128
|
-
def read_host_only_interfaces
|
129
|
-
net_list = read_virtual_networks
|
130
|
-
net_list.keep_if { |net| net['Type'] == 'host-only' }
|
131
|
-
|
132
|
-
hostonly_ifaces = []
|
133
|
-
net_list.each do |iface|
|
134
|
-
net_info = json do
|
135
|
-
execute_prlsrvctl('net', 'info', iface['Network ID'], '--json')
|
136
|
-
end
|
137
|
-
|
138
|
-
iface = {
|
139
|
-
name: net_info['Network ID'],
|
140
|
-
status: 'Down'
|
141
|
-
}
|
142
|
-
|
143
|
-
adapter = net_info['Parallels adapter']
|
144
|
-
if adapter && net_info['Bound To']
|
145
|
-
# In PD >= 10.1.2 there are new field names for an IP/Subnet
|
146
|
-
iface[:ip] = adapter['IP address'] || adapter['IPv4 address']
|
147
|
-
iface[:netmask] = adapter['Subnet mask'] || adapter['IPv4 subnet mask']
|
148
|
-
iface[:bound_to] = net_info['Bound To']
|
149
|
-
iface[:status] = 'Up'
|
150
|
-
end
|
151
|
-
|
152
|
-
hostonly_ifaces << iface
|
153
|
-
end
|
154
|
-
hostonly_ifaces
|
155
|
-
end
|
156
|
-
|
157
|
-
def read_network_interfaces
|
158
|
-
nics = {}
|
159
|
-
|
160
|
-
# Get enabled VM's network interfaces
|
161
|
-
ifaces = read_settings.fetch('Hardware', {}).keep_if do |dev, params|
|
162
|
-
dev.start_with?('net') and params.fetch('enabled', true)
|
163
|
-
end
|
164
|
-
ifaces.each do |name, params|
|
165
|
-
adapter = name.match(/^net(\d+)$/)[1].to_i
|
166
|
-
nics[adapter] ||= {}
|
167
|
-
|
168
|
-
if params['type'] == 'shared'
|
169
|
-
nics[adapter][:type] = :shared
|
170
|
-
elsif params['type'] == 'host'
|
171
|
-
nics[adapter][:type] = :hostonly
|
172
|
-
nics[adapter][:hostonly] = params.fetch('iface','')
|
173
|
-
elsif params['type'] == 'bridged'
|
174
|
-
nics[adapter][:type] = :bridged
|
175
|
-
nics[adapter][:bridge] = params.fetch('iface','')
|
176
|
-
end
|
177
|
-
end
|
178
|
-
nics
|
179
|
-
end
|
180
|
-
|
181
|
-
def read_shared_interface
|
182
|
-
net_info = json do
|
183
|
-
execute_prlsrvctl('net', 'info', read_shared_network_id, '--json')
|
184
|
-
end
|
185
|
-
|
186
|
-
iface = {
|
187
|
-
nat: [],
|
188
|
-
status: 'Down'
|
189
|
-
}
|
190
|
-
adapter = net_info['Parallels adapter']
|
191
|
-
|
192
|
-
if adapter && net_info['Bound To']
|
193
|
-
# In PD >= 10.1.2 there are new field names for an IP/Subnet
|
194
|
-
iface[:ip] = adapter['IP address'] || adapter['IPv4 address']
|
195
|
-
iface[:netmask] = adapter['Subnet mask'] || adapter['IPv4 subnet mask']
|
196
|
-
iface[:bound_to] = net_info['Bound To']
|
197
|
-
iface[:status] = 'Up'
|
198
|
-
end
|
199
|
-
|
200
|
-
if net_info.key?('DHCPv4 server')
|
201
|
-
iface[:dhcp] = {
|
202
|
-
ip: net_info['DHCPv4 server']['Server address'],
|
203
|
-
lower: net_info['DHCPv4 server']['IP scope start address'],
|
204
|
-
upper: net_info['DHCPv4 server']['IP scope end address']
|
205
|
-
}
|
206
|
-
end
|
207
|
-
|
208
|
-
net_info['NAT server'].each do |group, rules|
|
209
|
-
rules.each do |name, params|
|
210
|
-
iface[:nat] << {
|
211
|
-
name: name,
|
212
|
-
protocol: group == 'TCP rules' ? 'tcp' : 'udp',
|
213
|
-
guest: params['destination IP/VM id'],
|
214
|
-
hostport: params['source port'],
|
215
|
-
guestport: params['destination port']
|
216
|
-
}
|
217
|
-
end
|
218
|
-
end
|
219
|
-
|
220
|
-
iface
|
221
|
-
end
|
222
|
-
|
223
|
-
def read_used_ports
|
224
|
-
# Ignore our own used ports
|
225
|
-
read_forwarded_ports(true).reject { |r| r[:guest].include?(@uuid) }
|
226
|
-
end
|
227
17
|
end
|
228
18
|
end
|
229
19
|
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
require 'log4r'
|
2
|
+
|
3
|
+
require 'vagrant/util/platform'
|
4
|
+
|
5
|
+
require_relative 'pd_11'
|
6
|
+
|
7
|
+
module VagrantPlugins
|
8
|
+
module Parallels
|
9
|
+
module Driver
|
10
|
+
# Driver for Parallels Desktop 12.
|
11
|
+
class PD_12 < PD_11
|
12
|
+
def initialize(uuid)
|
13
|
+
super(uuid)
|
14
|
+
|
15
|
+
@logger = Log4r::Logger.new('vagrant_parallels::driver::pd_12')
|
16
|
+
end
|
17
|
+
|
18
|
+
def create_host_only_network(options)
|
19
|
+
# Create the interface
|
20
|
+
execute_prlsrvctl('net', 'add', options[:network_id], '--type', 'host-only')
|
21
|
+
|
22
|
+
# Get the IP so we can determine v4 vs v6
|
23
|
+
ip = IPAddr.new(options[:adapter_ip])
|
24
|
+
if ip.ipv4?
|
25
|
+
args = ['--ip', "#{options[:adapter_ip]}/#{options[:netmask]}"]
|
26
|
+
if options[:dhcp]
|
27
|
+
args.concat(['--dhcp-ip', options[:dhcp][:ip],
|
28
|
+
'--ip-scope-start', options[:dhcp][:lower],
|
29
|
+
'--ip-scope-end', options[:dhcp][:upper]])
|
30
|
+
end
|
31
|
+
elsif ip.ipv6?
|
32
|
+
# Convert prefix length to netmask ("32" -> "ffff:ffff::")
|
33
|
+
options[:netmask] = IPAddr.new(IPAddr::IN6MASK, Socket::AF_INET6)
|
34
|
+
.mask(options[:netmask]).to_s
|
35
|
+
|
36
|
+
args = ['--host-assign-ip6', 'on',
|
37
|
+
'--ip6', "#{options[:adapter_ip]}/#{options[:netmask]}"]
|
38
|
+
# DHCPv6 setting is not supported by Vagrant yet.
|
39
|
+
else
|
40
|
+
raise IPAddr::AddressFamilyError, 'BUG: unknown address family'
|
41
|
+
end
|
42
|
+
|
43
|
+
execute_prlsrvctl('net', 'set', options[:network_id], *args)
|
44
|
+
|
45
|
+
# Return the details
|
46
|
+
{
|
47
|
+
name: options[:network_id],
|
48
|
+
ip: options[:adapter_ip],
|
49
|
+
netmask: options[:netmask],
|
50
|
+
dhcp: options[:dhcp]
|
51
|
+
}
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
@@ -138,10 +138,9 @@ module VagrantPlugins
|
|
138
138
|
# our drivers only when they are needed.
|
139
139
|
module Driver
|
140
140
|
autoload :Meta, File.expand_path('../driver/meta', __FILE__)
|
141
|
-
autoload :PD_8, File.expand_path('../driver/pd_8', __FILE__)
|
142
|
-
autoload :PD_9, File.expand_path('../driver/pd_9', __FILE__)
|
143
141
|
autoload :PD_10, File.expand_path('../driver/pd_10', __FILE__)
|
144
142
|
autoload :PD_11, File.expand_path('../driver/pd_11', __FILE__)
|
143
|
+
autoload :PD_12, File.expand_path('../driver/pd_12', __FILE__)
|
145
144
|
end
|
146
145
|
|
147
146
|
module Model
|
data/locales/en.yml
CHANGED
@@ -58,6 +58,11 @@ en:
|
|
58
58
|
which are not supported by "prl_fs" file system.
|
59
59
|
|
60
60
|
Invalid mount options: %{options}
|
61
|
+
network_invalid_address: |-
|
62
|
+
Network settings specified in your Vagrantfile are invalid:
|
63
|
+
|
64
|
+
Network settings: %{options}
|
65
|
+
Error: %{error}
|
61
66
|
mac_os_x_required: |-
|
62
67
|
Parallels provider works only on OS X (Mac OS X) systems.
|
63
68
|
parallels_install_incomplete: |-
|
@@ -100,7 +105,7 @@ en:
|
|
100
105
|
parallels_unsupported_version: |-
|
101
106
|
Vagrant has detected that you have a version of Parallels Desktop for Mac
|
102
107
|
installed that is not supported. Vagrant Parallels provider is compatible
|
103
|
-
only with Parallels Desktop
|
108
|
+
only with Parallels Desktop 10 or later.
|
104
109
|
Please upgrade your installation: http://parallels.com/desktop
|
105
110
|
|
106
111
|
Note: Starting since Parallels Desktop 11 for Mac, Vagrant Parallels
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: vagrant-parallels
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.7.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Mikhail Zholobov
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2016-
|
12
|
+
date: 2016-11-15 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: bundler
|
@@ -93,7 +93,6 @@ files:
|
|
93
93
|
- lib/vagrant-parallels/action/export.rb
|
94
94
|
- lib/vagrant-parallels/action/forced_halt.rb
|
95
95
|
- lib/vagrant-parallels/action/forward_ports.rb
|
96
|
-
- lib/vagrant-parallels/action/handle_forwarded_port_collisions.rb
|
97
96
|
- lib/vagrant-parallels/action/handle_guest_tools.rb
|
98
97
|
- lib/vagrant-parallels/action/import.rb
|
99
98
|
- lib/vagrant-parallels/action/network.rb
|
@@ -117,8 +116,7 @@ files:
|
|
117
116
|
- lib/vagrant-parallels/driver/meta.rb
|
118
117
|
- lib/vagrant-parallels/driver/pd_10.rb
|
119
118
|
- lib/vagrant-parallels/driver/pd_11.rb
|
120
|
-
- lib/vagrant-parallels/driver/
|
121
|
-
- lib/vagrant-parallels/driver/pd_9.rb
|
119
|
+
- lib/vagrant-parallels/driver/pd_12.rb
|
122
120
|
- lib/vagrant-parallels/errors.rb
|
123
121
|
- lib/vagrant-parallels/guest_cap/darwin/install_parallels_tools.rb
|
124
122
|
- lib/vagrant-parallels/guest_cap/darwin/mount_parallels_shared_folder.rb
|
@@ -1,30 +0,0 @@
|
|
1
|
-
module VagrantPlugins
|
2
|
-
module Parallels
|
3
|
-
module Action
|
4
|
-
class HandleForwardedPortCollisions < Vagrant::Action::Builtin::HandleForwardedPortCollisions
|
5
|
-
def initialize(app, env)
|
6
|
-
@app = app
|
7
|
-
@logger = Log4r::Logger.new('vagrant_parallels::action::handle_port_collisions')
|
8
|
-
end
|
9
|
-
|
10
|
-
# This middleware just wraps the builtin action and allows to skip it if
|
11
|
-
# port forwarding is not supported for current Parallels Desktop version.
|
12
|
-
def call(env)
|
13
|
-
if env[:machine].provider.pd_version_satisfies?('>= 10')
|
14
|
-
super
|
15
|
-
else
|
16
|
-
# Just continue if port forwarding is not supported
|
17
|
-
@app.call(env)
|
18
|
-
end
|
19
|
-
end
|
20
|
-
|
21
|
-
def recover(env)
|
22
|
-
if env[:machine].provider.pd_version_satisfies?('>= 10')
|
23
|
-
super
|
24
|
-
end
|
25
|
-
# Do nothing if port forwarding is not supported
|
26
|
-
end
|
27
|
-
end
|
28
|
-
end
|
29
|
-
end
|
30
|
-
end
|
@@ -1,183 +0,0 @@
|
|
1
|
-
require 'log4r'
|
2
|
-
require 'nokogiri'
|
3
|
-
require 'securerandom'
|
4
|
-
|
5
|
-
require 'vagrant/util/platform'
|
6
|
-
|
7
|
-
require_relative 'base'
|
8
|
-
|
9
|
-
module VagrantPlugins
|
10
|
-
module Parallels
|
11
|
-
module Driver
|
12
|
-
# Driver for Parallels Desktop 8.
|
13
|
-
class PD_8 < Base
|
14
|
-
def initialize(uuid)
|
15
|
-
super(uuid)
|
16
|
-
|
17
|
-
@logger = Log4r::Logger.new('vagrant_parallels::driver::pd_8')
|
18
|
-
end
|
19
|
-
|
20
|
-
def delete_unused_host_only_networks
|
21
|
-
networks = read_virtual_networks
|
22
|
-
|
23
|
-
# 'Shared'(vnic0) and 'Host-Only'(vnic1) are default in Parallels Desktop
|
24
|
-
# They should not be deleted anyway.
|
25
|
-
networks.keep_if do |net|
|
26
|
-
net['Type'] == 'host-only' &&
|
27
|
-
net['Bound To'].match(/^(?>vnic|Parallels Host-Only #)(\d+)$/)[1].to_i >= 2
|
28
|
-
end
|
29
|
-
|
30
|
-
read_vms_info.each do |vm|
|
31
|
-
used_nets = vm.fetch('Hardware', {}).select { |name, _| name.start_with? 'net' }
|
32
|
-
used_nets.each_value do |net_params|
|
33
|
-
networks.delete_if { |net| net['Bound To'] == net_params.fetch('iface', nil) }
|
34
|
-
end
|
35
|
-
|
36
|
-
end
|
37
|
-
|
38
|
-
networks.each do |net|
|
39
|
-
# Delete the actual host only network interface.
|
40
|
-
execute_prlsrvctl('net', 'del', net['Network ID'])
|
41
|
-
end
|
42
|
-
end
|
43
|
-
|
44
|
-
def enable_adapters(adapters)
|
45
|
-
# Get adapters which have already configured for this VM
|
46
|
-
# Such adapters will be just overridden
|
47
|
-
existing_adapters = read_settings.fetch('Hardware', {}).keys.select do |name|
|
48
|
-
name.start_with? 'net'
|
49
|
-
end
|
50
|
-
|
51
|
-
# Disable all previously existing adapters (except shared 'vnet0')
|
52
|
-
existing_adapters.each do |adapter|
|
53
|
-
if adapter != 'vnet0'
|
54
|
-
execute_prlctl('set', @uuid, '--device-set', adapter, '--disable')
|
55
|
-
end
|
56
|
-
end
|
57
|
-
|
58
|
-
adapters.each do |adapter|
|
59
|
-
args = []
|
60
|
-
if existing_adapters.include? "net#{adapter[:adapter]}"
|
61
|
-
args.concat(['--device-set',"net#{adapter[:adapter]}", '--enable'])
|
62
|
-
else
|
63
|
-
args.concat(['--device-add', 'net'])
|
64
|
-
end
|
65
|
-
|
66
|
-
if adapter[:type] == :hostonly
|
67
|
-
# Determine interface to which it has been bound
|
68
|
-
net_info = json do
|
69
|
-
execute_prlsrvctl('net', 'info', adapter[:hostonly], '--json')
|
70
|
-
end
|
71
|
-
|
72
|
-
# Oddly enough, but there is a 'bridge' type anyway.
|
73
|
-
# The only difference is the destination interface:
|
74
|
-
# - in host-only (private) network it will be bridged to the 'vnicX' device
|
75
|
-
# - in real bridge (public) network it will be bridged to the assigned device
|
76
|
-
args.concat(['--type', 'bridged', '--iface', net_info['Bound To']])
|
77
|
-
elsif adapter[:type] == :bridged
|
78
|
-
args.concat(['--type', 'bridged', '--iface', adapter[:bridge]])
|
79
|
-
elsif adapter[:type] == :shared
|
80
|
-
args.concat(['--type', 'shared'])
|
81
|
-
end
|
82
|
-
|
83
|
-
if adapter[:mac_address]
|
84
|
-
args.concat(['--mac', adapter[:mac_address]])
|
85
|
-
end
|
86
|
-
|
87
|
-
if adapter[:nic_type]
|
88
|
-
args.concat(['--adapter-type', adapter[:nic_type].to_s])
|
89
|
-
end
|
90
|
-
|
91
|
-
execute_prlctl('set', @uuid, *args)
|
92
|
-
end
|
93
|
-
end
|
94
|
-
|
95
|
-
def read_host_only_interfaces
|
96
|
-
net_list = read_virtual_networks
|
97
|
-
net_list.keep_if { |net| net['Type'] == 'host-only' }
|
98
|
-
|
99
|
-
hostonly_ifaces = []
|
100
|
-
net_list.each do |iface|
|
101
|
-
net_info = json do
|
102
|
-
execute_prlsrvctl('net', 'info', iface['Network ID'], '--json')
|
103
|
-
end
|
104
|
-
|
105
|
-
iface = {
|
106
|
-
name: net_info['Network ID'],
|
107
|
-
status: 'Down'
|
108
|
-
}
|
109
|
-
|
110
|
-
adapter = net_info['Parallels adapter']
|
111
|
-
if adapter && net_info['Bound To']
|
112
|
-
iface[:ip] = adapter['IP address']
|
113
|
-
iface[:netmask] = adapter['Subnet mask']
|
114
|
-
iface[:bound_to] = net_info['Bound To']
|
115
|
-
iface[:status] = 'Up'
|
116
|
-
end
|
117
|
-
|
118
|
-
hostonly_ifaces << iface
|
119
|
-
end
|
120
|
-
hostonly_ifaces
|
121
|
-
end
|
122
|
-
|
123
|
-
def read_network_interfaces
|
124
|
-
nics = {}
|
125
|
-
|
126
|
-
# Get enabled VM's network interfaces
|
127
|
-
ifaces = read_settings.fetch('Hardware', {}).keep_if do |dev, params|
|
128
|
-
dev.start_with?('net') and params.fetch('enabled', true)
|
129
|
-
end
|
130
|
-
ifaces.each do |name, params|
|
131
|
-
adapter = name.match(/^net(\d+)$/)[1].to_i
|
132
|
-
nics[adapter] ||= {}
|
133
|
-
|
134
|
-
if params['type'] == 'shared'
|
135
|
-
nics[adapter][:type] = :shared
|
136
|
-
elsif params['type'] == 'host'
|
137
|
-
# It is PD internal host-only network and it is bounded to 'vnic1'
|
138
|
-
nics[adapter][:type] = :hostonly
|
139
|
-
nics[adapter][:hostonly] = 'vnic1'
|
140
|
-
elsif params['type'] == 'bridged' and params.fetch('iface','').start_with?('vnic')
|
141
|
-
# Bridged to the 'vnicXX'? Then it is a host-only, actually.
|
142
|
-
nics[adapter][:type] = :hostonly
|
143
|
-
nics[adapter][:hostonly] = params.fetch('iface','')
|
144
|
-
elsif params['type'] == 'bridged'
|
145
|
-
nics[adapter][:type] = :bridged
|
146
|
-
nics[adapter][:bridge] = params.fetch('iface','')
|
147
|
-
end
|
148
|
-
end
|
149
|
-
nics
|
150
|
-
end
|
151
|
-
|
152
|
-
def read_shared_interface
|
153
|
-
net_info = json do
|
154
|
-
execute_prlsrvctl('net', 'info', read_shared_network_id, '--json')
|
155
|
-
end
|
156
|
-
|
157
|
-
iface = {
|
158
|
-
nat: [],
|
159
|
-
status: 'Down'
|
160
|
-
}
|
161
|
-
|
162
|
-
adapter = net_info['Parallels adapter']
|
163
|
-
if adapter && net_info['Bound To']
|
164
|
-
iface[:ip] = adapter['IP address']
|
165
|
-
iface[:netmask] = adapter['Subnet mask']
|
166
|
-
iface[:bound_to] = net_info['Bound To']
|
167
|
-
iface[:status] = 'Up'
|
168
|
-
end
|
169
|
-
|
170
|
-
if net_info.key?('DHCPv4 server')
|
171
|
-
iface[:dhcp] = {
|
172
|
-
ip: net_info['DHCPv4 server']['Server address'],
|
173
|
-
lower: net_info['DHCPv4 server']['IP scope start address'],
|
174
|
-
upper: net_info['DHCPv4 server']['IP scope end address']
|
175
|
-
}
|
176
|
-
end
|
177
|
-
|
178
|
-
iface
|
179
|
-
end
|
180
|
-
end
|
181
|
-
end
|
182
|
-
end
|
183
|
-
end
|
@@ -1,25 +0,0 @@
|
|
1
|
-
require 'log4r'
|
2
|
-
|
3
|
-
require 'vagrant/util/platform'
|
4
|
-
|
5
|
-
require_relative 'pd_8'
|
6
|
-
|
7
|
-
module VagrantPlugins
|
8
|
-
module Parallels
|
9
|
-
module Driver
|
10
|
-
# Driver for Parallels Desktop 9.
|
11
|
-
class PD_9 < PD_8
|
12
|
-
def initialize(uuid)
|
13
|
-
super(uuid)
|
14
|
-
|
15
|
-
@logger = Log4r::Logger.new('vagrant_parallels::driver::pd_9')
|
16
|
-
end
|
17
|
-
|
18
|
-
def set_power_consumption_mode(optimized)
|
19
|
-
state = optimized ? 'on' : 'off'
|
20
|
-
execute_prlctl('set', @uuid, '--longer-battery-life', state)
|
21
|
-
end
|
22
|
-
end
|
23
|
-
end
|
24
|
-
end
|
25
|
-
end
|