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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 96a1ffdfb9901688a2af90776e4c7f86c1ea5d27
4
- data.tar.gz: dedfe0e23fbcaf6b429f31f422bb96b32ad2c7da
3
+ metadata.gz: 0e014ab2a7c2e81aebb3325f22e60334982cceed
4
+ data.tar.gz: 180a1225025aa7b162173b7f46ab7eb695db30ce
5
5
  SHA512:
6
- metadata.gz: 20bc34e6060d31b4af5656c360146104f90fad6d967797c2f6d674f50f5ab5da2c9505dd97cb6c9f919f79e9fe6309412e7a1582ffe8f5587b4c52a1c05e574c
7
- data.tar.gz: 9ced0b39362f1f48a7bffb36f7b5477ddac77ef37ff475fc1dd836f066aefd5912a146e729962a7658ffe6222dd8dc0723b64993cd24a5bee73ef8e4095a3529
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 was renamed:
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 power [Parallels Desktop for Mac](http://www.parallels.com/products/desktop/)
8
- based virtual machines.
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 8 for Mac](http://www.parallels.com/products/desktop/) or higher
12
+ - [Parallels Desktop 10 for Mac](http://www.parallels.com/products/desktop/) or higher
13
13
 
14
- *Note:* In [**Parallels Desktop 11 for Mac**](http://www.parallels.com/products/desktop/),
15
- only **Pro** and **Business** editions are compatible with this Vagrant provider.
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-2015, Parallels IP Holdings GmbH.
58
+ * Copyright 2013-2016, Parallels IP Holdings GmbH.
59
59
 
60
- ```text
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
- if env[:machine].provider.pd_version_satisfies?('>= 10')
123
- # Convert template to VM (compatibility with old-styled boxes)
124
- env[:machine].provider.driver.execute_prlctl(
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
- # Disable requiring password for delete action [GH-67].
12
- # It is available only since PD 10.
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
- # It is available only since PD 10.
21
- if env[:machine].provider.pd_version_satisfies?('>= 10')
22
- acts = ['clone-vm']
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
- # Calculate our network address for the given IP/netmask
267
- netaddr = network_address(options[:ip], options[:netmask])
268
-
269
- # Verify that a host-only network subnet would not collide
270
- # with a bridged networking interface.
271
- #
272
- # If the subnets overlap in any way then the host only network
273
- # will not work because the routing tables will force the
274
- # traffic onto the real interface rather than the virtual
275
- # network interface.
276
- @env[:machine].provider.driver.read_bridged_interfaces.each do |interface|
277
- that_netaddr = network_address(interface[:ip], interface[:netmask])
278
- raise Vagrant::Errors::NetworkCollision if \
279
- netaddr == that_netaddr && interface[:status] != 'Down'
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
- # Split the IP address into its components
283
- ip_parts = netaddr.split('.').map { |i| i.to_i }
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, which we assume is the IP ".1" at
286
- # the end usually.
287
- adapter_ip = ip_parts.dup
288
- adapter_ip[3] += 1
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 DHCP server IP, which is the network address
294
- # with the final octet + 1. So "172.28.0.0" turns into "172.28.0.1"
295
- dhcp_ip = ip_parts.dup
296
- dhcp_ip[3] += 1
297
- dhcp_options[:dhcp_ip] = options[:dhcp_ip] || dhcp_ip.join('.')
298
-
299
- # Calculate the lower and upper bound for the DHCP server
300
- dhcp_lower = ip_parts.dup
301
- dhcp_lower[3] += 2
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 = network_address(config[:ip], config[:netmask])
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
- return interface if this_netaddr == \
454
- network_address(interface[:ip], interface[:netmask])
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
- raise NotImplementedError
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
- raise NotImplementedError
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
- raise NotImplementedError
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
- raise NotImplementedError
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
- raise NotImplementedError
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
- raise NotImplementedError
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
- raise NotImplementedError
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
- raise NotImplementedError
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
- raise NotImplementedError
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
- raise NotImplementedError
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..7 then raise Errors::ParallelsUnsupportedVersion
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
- else PD_11
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 'pd_9'
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 < PD_9
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
@@ -39,6 +39,10 @@ module VagrantPlugins
39
39
  error_key(:mac_os_x_required)
40
40
  end
41
41
 
42
+ class NetworkInvalidAddress < VagrantParallelsError
43
+ error_key(:network_invalid_address)
44
+ end
45
+
42
46
  class ExecutionError < VagrantParallelsError
43
47
  error_key(:execution_error)
44
48
  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
@@ -1,5 +1,5 @@
1
1
  module VagrantPlugins
2
2
  module Parallels
3
- VERSION = '1.6.3'
3
+ VERSION = '1.7.0'
4
4
  end
5
5
  end
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 8 or later.
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.6.3
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-07-11 00:00:00.000000000 Z
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/pd_8.rb
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