vagrant-parallels 1.6.3 → 1.7.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
[![Code Climate](https://codeclimate.com/github/Parallels/vagrant-parallels.png)](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
|