vagrant-parallels 0.2.1 → 0.2.2.rc1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +21 -13
- data/.travis.yml +1 -0
- data/README.md +43 -54
- data/config/i18n-tasks.yml.erb +1 -1
- data/debug.log +941 -0
- data/lib/vagrant-parallels/action.rb +0 -7
- data/lib/vagrant-parallels/action/check_accessible.rb +1 -1
- data/lib/vagrant-parallels/action/check_guest_tools.rb +10 -2
- data/lib/vagrant-parallels/action/clear_network_interfaces.rb +1 -1
- data/lib/vagrant-parallels/action/customize.rb +6 -4
- data/lib/vagrant-parallels/action/export.rb +56 -12
- data/lib/vagrant-parallels/action/import.rb +49 -30
- data/lib/vagrant-parallels/action/network.rb +137 -48
- data/lib/vagrant-parallels/action/package_config_files.rb +0 -12
- data/lib/vagrant-parallels/action/prepare_nfs_valid_ids.rb +1 -1
- data/lib/vagrant-parallels/action/set_name.rb +2 -2
- data/lib/vagrant-parallels/config.rb +11 -2
- data/lib/vagrant-parallels/driver/base.rb +281 -0
- data/lib/vagrant-parallels/driver/meta.rb +138 -0
- data/lib/vagrant-parallels/driver/{prl_ctl.rb → pd_8.rb} +116 -256
- data/lib/vagrant-parallels/driver/pd_9.rb +417 -0
- data/lib/vagrant-parallels/errors.rb +15 -7
- data/lib/vagrant-parallels/plugin.rb +7 -7
- data/lib/vagrant-parallels/provider.rb +33 -3
- data/lib/vagrant-parallels/version.rb +1 -1
- data/locales/en.yml +30 -16
- data/test/unit/base.rb +1 -5
- data/test/unit/config_test.rb +13 -2
- data/test/unit/driver/pd_8_test.rb +196 -0
- data/test/unit/driver/pd_9_test.rb +196 -0
- data/test/unit/locales/locales_test.rb +1 -1
- data/test/unit/support/shared/parallels_context.rb +2 -2
- data/test/unit/support/shared/pd_driver_examples.rb +243 -0
- data/test/unit/synced_folder_test.rb +37 -0
- data/vagrant-parallels.gemspec +5 -5
- metadata +39 -32
- data/lib/vagrant-parallels/action/match_mac_address.rb +0 -28
- data/lib/vagrant-parallels/action/register_template.rb +0 -24
- data/lib/vagrant-parallels/action/unregister_template.rb +0 -26
- data/test/support/isolated_environment.rb +0 -46
- data/test/support/tempdir.rb +0 -43
- data/test/unit/driver/prl_ctl_test.rb +0 -148
@@ -1,54 +1,41 @@
|
|
1
1
|
require 'log4r'
|
2
|
-
require 'json'
|
3
2
|
|
4
|
-
require 'vagrant/util/busy'
|
5
|
-
require "vagrant/util/network_ip"
|
6
3
|
require 'vagrant/util/platform'
|
7
|
-
|
8
|
-
require
|
4
|
+
|
5
|
+
require File.expand_path("../base", __FILE__)
|
9
6
|
|
10
7
|
module VagrantPlugins
|
11
8
|
module Parallels
|
12
9
|
module Driver
|
13
|
-
#
|
14
|
-
|
15
|
-
# This class provides useful tools for things such as executing
|
16
|
-
# PrlCtl and handling SIGINTs and so on.
|
17
|
-
class PrlCtl
|
18
|
-
# Include this so we can use `Subprocess` more easily.
|
19
|
-
include Vagrant::Util::Retryable
|
20
|
-
include Vagrant::Util::NetworkIP
|
21
|
-
|
22
|
-
attr_reader :uuid
|
23
|
-
|
10
|
+
# Driver for Parallels Desktop 8.
|
11
|
+
class PD_8 < Base
|
24
12
|
def initialize(uuid)
|
25
|
-
|
13
|
+
super()
|
26
14
|
|
27
|
-
|
28
|
-
@interrupted = false
|
29
|
-
|
30
|
-
# Store machine id
|
15
|
+
@logger = Log4r::Logger.new("vagrant::provider::parallels::pd_8")
|
31
16
|
@uuid = uuid
|
17
|
+
end
|
32
18
|
|
33
|
-
# Set the path to prlctl
|
34
|
-
@prlctl_path = "prlctl"
|
35
|
-
@prlsrvctl_path = "prlsrvctl"
|
36
19
|
|
37
|
-
|
38
|
-
|
20
|
+
def compact(uuid)
|
21
|
+
used_drives = read_settings.fetch('Hardware', {}).select { |name, _| name.start_with? 'hdd' }
|
22
|
+
used_drives.each_value do |drive_params|
|
23
|
+
execute(:prl_disk_tool, 'compact', '--hdd', drive_params["image"]) do |type, data|
|
24
|
+
lines = data.split("\r")
|
25
|
+
# The progress of the compact will be in the last line. Do a greedy
|
26
|
+
# regular expression to find what we're looking for.
|
27
|
+
if lines.last =~ /.+?(\d{,3}) ?%/
|
28
|
+
yield $1.to_i if block_given?
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
39
32
|
end
|
40
33
|
|
41
|
-
def
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
lines = data.split("\r")
|
47
|
-
# The progress of the import will be in the last line. Do a greedy
|
48
|
-
# regular expression to find what we're looking for.
|
49
|
-
if lines.last =~ /.+?(\d{,3}) ?%/
|
50
|
-
yield $1.to_i if block_given?
|
51
|
-
end
|
34
|
+
def clear_shared_folders
|
35
|
+
shf = read_settings.fetch("Host Shared Folders", {}).keys
|
36
|
+
shf.delete("enabled")
|
37
|
+
shf.each do |folder|
|
38
|
+
execute("set", @uuid, "--shf-host-del", folder)
|
52
39
|
end
|
53
40
|
end
|
54
41
|
|
@@ -72,27 +59,19 @@ module VagrantPlugins
|
|
72
59
|
|
73
60
|
# Return the details
|
74
61
|
return {
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
62
|
+
:name => options[:name],
|
63
|
+
:bound_to => bound_to,
|
64
|
+
:ip => options[:adapter_ip],
|
65
|
+
:netmask => options[:netmask],
|
66
|
+
:dhcp => options[:dhcp]
|
80
67
|
}
|
81
68
|
end
|
82
69
|
|
83
|
-
def clear_shared_folders
|
84
|
-
shf = read_settings.fetch("Host Shared Folders", {}).keys
|
85
|
-
shf.delete("enabled")
|
86
|
-
shf.each do |folder|
|
87
|
-
execute("set", @uuid, "--shf-host-del", folder)
|
88
|
-
end
|
89
|
-
end
|
90
|
-
|
91
70
|
def delete
|
92
71
|
execute('delete', @uuid)
|
93
72
|
end
|
94
73
|
|
95
|
-
def
|
74
|
+
def delete_disabled_adapters
|
96
75
|
read_settings.fetch('Hardware', {}).each do |adapter, params|
|
97
76
|
if adapter.start_with?('net') and !params.fetch("enabled", true)
|
98
77
|
execute('set', @uuid, '--device-del', adapter)
|
@@ -101,19 +80,19 @@ module VagrantPlugins
|
|
101
80
|
end
|
102
81
|
|
103
82
|
def delete_unused_host_only_networks
|
104
|
-
networks = read_virtual_networks
|
83
|
+
networks = read_virtual_networks
|
105
84
|
|
106
85
|
# 'Shared'(vnic0) and 'Host-Only'(vnic1) are default in Parallels Desktop
|
107
86
|
# They should not be deleted anyway.
|
108
87
|
networks.keep_if do |net|
|
109
88
|
net['Type'] == "host-only" &&
|
110
|
-
|
89
|
+
net['Bound To'].match(/^(?>vnic|Parallels Host-Only #)(\d+)$/)[1].to_i >= 2
|
111
90
|
end
|
112
91
|
|
113
|
-
|
92
|
+
read_vms_info.each do |vm|
|
114
93
|
used_nets = vm.fetch('Hardware', {}).select { |name, _| name.start_with? 'net' }
|
115
94
|
used_nets.each_value do |net_params|
|
116
|
-
networks.delete_if { |net| net['Bound To'] == net_params.fetch('iface', nil)}
|
95
|
+
networks.delete_if { |net| net['Bound To'] == net_params.fetch('iface', nil) }
|
117
96
|
end
|
118
97
|
|
119
98
|
end
|
@@ -152,18 +131,10 @@ module VagrantPlugins
|
|
152
131
|
args.concat(["--type", "bridged", "--iface", adapter[:bound_to]])
|
153
132
|
end
|
154
133
|
|
155
|
-
if adapter[:shared
|
134
|
+
if adapter[:type] == :shared
|
156
135
|
args.concat(["--type", "shared"])
|
157
136
|
end
|
158
137
|
|
159
|
-
if adapter[:dhcp]
|
160
|
-
args.concat(["--dhcp", "yes"])
|
161
|
-
elsif adapter[:ip]
|
162
|
-
args.concat(["--ipdel", "all", "--ipadd", "#{adapter[:ip]}/#{adapter[:netmask]}"])
|
163
|
-
else
|
164
|
-
args.concat(["--dhcp", "no"])
|
165
|
-
end
|
166
|
-
|
167
138
|
if adapter[:mac_address]
|
168
139
|
args.concat(["--mac", adapter[:mac_address]])
|
169
140
|
end
|
@@ -176,17 +147,20 @@ module VagrantPlugins
|
|
176
147
|
end
|
177
148
|
end
|
178
149
|
|
179
|
-
def
|
180
|
-
execute(
|
150
|
+
def execute_command(command)
|
151
|
+
execute(*command)
|
152
|
+
end
|
153
|
+
|
154
|
+
def export(path, tpl_name)
|
155
|
+
execute("clone", @uuid, "--name", tpl_name, "--template", "--dst", path.to_s) do |type, data|
|
181
156
|
lines = data.split("\r")
|
182
|
-
# The progress of the
|
157
|
+
# The progress of the export will be in the last line. Do a greedy
|
183
158
|
# regular expression to find what we're looking for.
|
184
159
|
if lines.last =~ /.+?(\d{,3}) ?%/
|
185
160
|
yield $1.to_i if block_given?
|
186
161
|
end
|
187
162
|
end
|
188
|
-
|
189
|
-
read_settings(vm_name).fetch('ID', vm_name)
|
163
|
+
read_vms[tpl_name]
|
190
164
|
end
|
191
165
|
|
192
166
|
def halt(force=false)
|
@@ -195,7 +169,10 @@ module VagrantPlugins
|
|
195
169
|
execute(*args)
|
196
170
|
end
|
197
171
|
|
198
|
-
def import(template_uuid
|
172
|
+
def import(template_uuid)
|
173
|
+
template_name = read_vms.key(template_uuid)
|
174
|
+
vm_name = "#{template_name}_#{(Time.now.to_f * 1000.0).to_i}_#{rand(100000)}"
|
175
|
+
|
199
176
|
execute("clone", template_uuid, '--name', vm_name) do |type, data|
|
200
177
|
lines = data.split("\r")
|
201
178
|
# The progress of the import will be in the last line. Do a greedy
|
@@ -204,71 +181,23 @@ module VagrantPlugins
|
|
204
181
|
yield $1.to_i if block_given?
|
205
182
|
end
|
206
183
|
end
|
207
|
-
|
208
|
-
end
|
209
|
-
|
210
|
-
def ip
|
211
|
-
mac_addr = read_mac_address.downcase
|
212
|
-
File.foreach("/Library/Preferences/Parallels/parallels_dhcp_leases") do |line|
|
213
|
-
if line.include? mac_addr
|
214
|
-
ip = line[/^(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})/]
|
215
|
-
return ip
|
216
|
-
end
|
217
|
-
end
|
218
|
-
end
|
219
|
-
|
220
|
-
|
221
|
-
def mac_in_use?(mac)
|
222
|
-
all_macs_in_use = []
|
223
|
-
read_all_info.each do |vm|
|
224
|
-
all_macs_in_use << vm.fetch('Hardware', {}).fetch('net0',{}).fetch('mac', '')
|
225
|
-
end
|
226
|
-
|
227
|
-
valid_mac = mac.upcase.tr('^A-F0-9', '')
|
228
|
-
|
229
|
-
all_macs_in_use.include?(valid_mac)
|
230
|
-
end
|
231
|
-
|
232
|
-
# Returns a hash of all UUIDs assigned to VMs and templates currently
|
233
|
-
# known by Parallels. Keys are 'name' values
|
234
|
-
#
|
235
|
-
# @return [Hash]
|
236
|
-
def read_all_names
|
237
|
-
list = {}
|
238
|
-
read_all_info.each do |item|
|
239
|
-
list[item.fetch('Name')] = item.fetch('ID')
|
240
|
-
end
|
241
|
-
|
242
|
-
list
|
243
|
-
end
|
244
|
-
|
245
|
-
# Returns a hash of all UUIDs assigned to VMs and templates currently
|
246
|
-
# known by Parallels. Keys are 'Home' directories
|
247
|
-
#
|
248
|
-
# @return [Hash]
|
249
|
-
def read_all_paths
|
250
|
-
list = {}
|
251
|
-
read_all_info.each do |item|
|
252
|
-
if Dir.exists? item.fetch('Home')
|
253
|
-
list[File.realpath item.fetch('Home')] = item.fetch('ID')
|
254
|
-
end
|
255
|
-
end
|
256
|
-
|
257
|
-
list
|
184
|
+
read_vms[vm_name]
|
258
185
|
end
|
259
186
|
|
260
187
|
def read_bridged_interfaces
|
261
|
-
net_list = read_virtual_networks
|
188
|
+
net_list = read_virtual_networks
|
262
189
|
|
263
190
|
# Skip 'vnicXXX' and 'Default' interfaces
|
264
191
|
net_list.delete_if do |net|
|
265
|
-
net['Type'] != "bridged" or
|
192
|
+
net['Type'] != "bridged" or
|
193
|
+
net['Bound To'] =~ /^(vnic(.+?))$/ or
|
194
|
+
net['Network ID'] == "Default"
|
266
195
|
end
|
267
196
|
|
268
197
|
bridged_ifaces = []
|
269
198
|
net_list.collect do |iface|
|
270
199
|
info = {}
|
271
|
-
ifconfig =
|
200
|
+
ifconfig = execute(:ifconfig, iface['Bound To'])
|
272
201
|
# Assign default values
|
273
202
|
info[:name] = iface['Network ID'].gsub(/\s\(.*?\)$/, '')
|
274
203
|
info[:bound_to] = iface['Bound To']
|
@@ -298,7 +227,7 @@ module VagrantPlugins
|
|
298
227
|
end
|
299
228
|
|
300
229
|
def read_host_only_interfaces
|
301
|
-
net_list = read_virtual_networks
|
230
|
+
net_list = read_virtual_networks
|
302
231
|
net_list.keep_if { |net| net['Type'] == "host-only" }
|
303
232
|
|
304
233
|
hostonly_ifaces = []
|
@@ -325,7 +254,17 @@ module VagrantPlugins
|
|
325
254
|
end
|
326
255
|
hostonly_ifaces << info
|
327
256
|
end
|
328
|
-
|
257
|
+
hostonly_ifaces
|
258
|
+
end
|
259
|
+
|
260
|
+
def read_ip_dhcp
|
261
|
+
mac_addr = read_mac_address.downcase
|
262
|
+
File.foreach("/Library/Preferences/Parallels/parallels_dhcp_leases") do |line|
|
263
|
+
if line.include? mac_addr
|
264
|
+
ip = line[/^(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})/]
|
265
|
+
return ip
|
266
|
+
end
|
267
|
+
end
|
329
268
|
end
|
330
269
|
|
331
270
|
def read_mac_address
|
@@ -361,46 +300,77 @@ module VagrantPlugins
|
|
361
300
|
nics
|
362
301
|
end
|
363
302
|
|
364
|
-
|
365
|
-
|
366
|
-
|
303
|
+
def read_settings
|
304
|
+
vm = json { execute('list', @uuid, '--info', '--json', retryable: true).gsub(/^INFO/, '') }
|
305
|
+
vm.last
|
306
|
+
end
|
307
|
+
|
367
308
|
def read_state
|
368
|
-
|
309
|
+
vm = json { execute('list', @uuid, '--json', retryable: true).gsub(/^INFO/, '') }
|
310
|
+
return nil if !vm.last
|
311
|
+
vm.last.fetch('status').to_sym
|
369
312
|
end
|
370
313
|
|
371
314
|
def read_virtual_networks
|
372
315
|
json { execute(:prlsrvctl, 'net', 'list', '--json', retryable: true) }
|
373
316
|
end
|
374
317
|
|
375
|
-
def
|
376
|
-
|
318
|
+
def read_vms
|
319
|
+
results = {}
|
320
|
+
vms_arr = json([]) do
|
321
|
+
execute('list', '--all', '--json', retryable: true).gsub(/^INFO/, '')
|
322
|
+
end
|
323
|
+
templates_arr = json([]) do
|
324
|
+
execute('list', '--all', '--json', '--template', retryable: true).gsub(/^INFO/, '')
|
325
|
+
end
|
326
|
+
vms = vms_arr | templates_arr
|
327
|
+
vms.each do |item|
|
328
|
+
results[item.fetch('name')] = item.fetch('uuid')
|
329
|
+
end
|
330
|
+
|
331
|
+
results
|
332
|
+
end
|
333
|
+
|
334
|
+
# Parse the JSON from *all* VMs and templates. Then return an array of objects (without duplicates)
|
335
|
+
def read_vms_info
|
336
|
+
vms_arr = json([]) do
|
337
|
+
execute('list', '--all','--info', '--json', retryable: true).gsub(/^INFO/, '')
|
338
|
+
end
|
339
|
+
templates_arr = json([]) do
|
340
|
+
execute('list', '--all','--info', '--json', '--template', retryable: true).gsub(/^INFO/, '')
|
341
|
+
end
|
342
|
+
vms_arr | templates_arr
|
343
|
+
end
|
344
|
+
|
345
|
+
def read_vms_paths
|
346
|
+
list = {}
|
347
|
+
read_vms_info.each do |item|
|
348
|
+
if Dir.exists? item.fetch('Home')
|
349
|
+
list[File.realpath item.fetch('Home')] = item.fetch('ID')
|
350
|
+
end
|
351
|
+
end
|
352
|
+
|
353
|
+
list
|
377
354
|
end
|
378
355
|
|
379
356
|
def register(pvm_file)
|
380
357
|
execute("register", pvm_file)
|
381
358
|
end
|
382
359
|
|
383
|
-
def registered?(
|
384
|
-
|
385
|
-
# Need a way to get the UUID from unregistered templates though (config.pvs XML parsing/regex?)
|
386
|
-
read_all_paths.has_key?(path)
|
360
|
+
def registered?(uuid)
|
361
|
+
read_vms.has_value?(uuid)
|
387
362
|
end
|
388
363
|
|
389
364
|
def resume
|
390
365
|
execute('resume', @uuid)
|
391
366
|
end
|
392
367
|
|
393
|
-
def set_name(name)
|
394
|
-
execute('set', @uuid, '--name', name, :retryable => true)
|
395
|
-
end
|
396
|
-
|
397
368
|
def set_mac_address(mac)
|
398
369
|
execute('set', @uuid, '--device-set', 'net0', '--type', 'shared', '--mac', mac)
|
399
370
|
end
|
400
371
|
|
401
|
-
|
402
|
-
|
403
|
-
raw(@prlctl_path, *command)
|
372
|
+
def set_name(name)
|
373
|
+
execute('set', @uuid, '--name', name, :retryable => true)
|
404
374
|
end
|
405
375
|
|
406
376
|
def share_folders(folders)
|
@@ -411,7 +381,7 @@ module VagrantPlugins
|
|
411
381
|
end
|
412
382
|
|
413
383
|
def ssh_port(expected_port)
|
414
|
-
|
384
|
+
expected_port
|
415
385
|
end
|
416
386
|
|
417
387
|
def start
|
@@ -426,9 +396,6 @@ module VagrantPlugins
|
|
426
396
|
execute("unregister", uuid)
|
427
397
|
end
|
428
398
|
|
429
|
-
# Verifies that the driver is ready to accept work.
|
430
|
-
#
|
431
|
-
# This should raise a VagrantError if things are not ready.
|
432
399
|
def verify!
|
433
400
|
version
|
434
401
|
end
|
@@ -441,115 +408,8 @@ module VagrantPlugins
|
|
441
408
|
end
|
442
409
|
end
|
443
410
|
|
444
|
-
|
445
|
-
|
446
|
-
def guest_execute(*command)
|
447
|
-
execute('exec', @uuid, *command)
|
448
|
-
end
|
449
|
-
|
450
|
-
def json(default=nil)
|
451
|
-
data = yield
|
452
|
-
JSON.parse(data) rescue default
|
453
|
-
end
|
454
|
-
|
455
|
-
# Parse the JSON from *all* VMs and templates. Then return an array of objects (without duplicates)
|
456
|
-
def read_all_info
|
457
|
-
vms_arr = json({}) do
|
458
|
-
execute('list', '--info', '--json', retryable: true).gsub(/^(INFO)?/, '')
|
459
|
-
end
|
460
|
-
templates_arr = json({}) do
|
461
|
-
execute('list', '--info', '--json', '--template', retryable: true).gsub(/^(INFO)?/, '')
|
462
|
-
end
|
463
|
-
vms_arr | templates_arr
|
464
|
-
end
|
465
|
-
|
466
|
-
def read_settings(uuid=nil)
|
467
|
-
uuid ||= @uuid
|
468
|
-
json({}) { execute('list', uuid, '--info', '--json', retryable: true).gsub(/^(INFO)?\[/, '').gsub(/\]$/, '') }
|
469
|
-
end
|
470
|
-
|
471
|
-
def error_detection(command_response)
|
472
|
-
errored = false
|
473
|
-
# If the command was a failure, then raise an exception that is
|
474
|
-
# nicely handled by Vagrant.
|
475
|
-
if command_response.exit_code != 0
|
476
|
-
if @interrupted
|
477
|
-
@logger.info("Exit code != 0, but interrupted. Ignoring.")
|
478
|
-
elsif command_response.exit_code == 126
|
479
|
-
# This exit code happens if PrlCtl is on the PATH,
|
480
|
-
# but another executable it tries to execute is missing.
|
481
|
-
# This is usually indicative of a corrupted Parallels install.
|
482
|
-
raise VagrantPlugins::Parallels::Errors::ParallelsErrorNotFoundError
|
483
|
-
else
|
484
|
-
errored = true
|
485
|
-
end
|
486
|
-
elsif command_response.stderr =~ /failed to open \/dev\/prlctl/i
|
487
|
-
# This catches an error message that only shows when kernel
|
488
|
-
# drivers aren't properly installed.
|
489
|
-
@logger.error("Error message about unable to open prlctl")
|
490
|
-
raise VagrantPlugins::Parallels::Errors::ParallelsErrorKernelModuleNotLoaded
|
491
|
-
elsif command_response.stderr =~ /Unable to perform/i
|
492
|
-
@logger.info("VM not running for command to work.")
|
493
|
-
errored = true
|
494
|
-
elsif command_response.stderr =~ /Invalid usage/i
|
495
|
-
@logger.info("PrlCtl error text found, assuming error.")
|
496
|
-
errored = true
|
497
|
-
end
|
498
|
-
errored
|
499
|
-
end
|
500
|
-
|
501
|
-
# Execute the given subcommand for PrlCtl and return the output.
|
502
|
-
def execute(*command, &block)
|
503
|
-
# Get the utility to execute: 'prlctl' by default and 'prlsrvctl' if it set as a first argument in command
|
504
|
-
if command.first == :prlsrvctl
|
505
|
-
cli = @prlsrvctl_path
|
506
|
-
command.delete_at(0)
|
507
|
-
else
|
508
|
-
cli = @prlctl_path
|
509
|
-
end
|
510
|
-
|
511
|
-
# Get the options hash if it exists
|
512
|
-
opts = {}
|
513
|
-
opts = command.pop if command.last.is_a?(Hash)
|
514
|
-
|
515
|
-
tries = opts[:retryable] ? 3 : 0
|
516
|
-
|
517
|
-
# Variable to store our execution result
|
518
|
-
r = nil
|
519
|
-
|
520
|
-
# If there is an error with PrlCtl, this gets set to true
|
521
|
-
errored = false
|
522
|
-
|
523
|
-
retryable(on: VagrantPlugins::Parallels::Errors::ParallelsError, tries: tries, sleep: 1) do
|
524
|
-
# Execute the command
|
525
|
-
r = raw(cli, *command, &block)
|
526
|
-
errored = error_detection(r)
|
527
|
-
end
|
528
|
-
|
529
|
-
# If there was an error running PrlCtl, show the error and the
|
530
|
-
# output.
|
531
|
-
if errored
|
532
|
-
raise VagrantPlugins::Parallels::Errors::ParallelsError,
|
533
|
-
command: command.inspect,
|
534
|
-
stderr: r.stderr
|
535
|
-
end
|
536
|
-
|
537
|
-
r.stdout
|
538
|
-
end
|
539
|
-
|
540
|
-
# Executes a command and returns the raw result object.
|
541
|
-
def raw(cli, *command, &block)
|
542
|
-
int_callback = lambda do
|
543
|
-
@interrupted = true
|
544
|
-
@logger.info("Interrupted.")
|
545
|
-
end
|
546
|
-
|
547
|
-
# Append in the options for subprocess
|
548
|
-
command << { notify: [:stdout, :stderr] }
|
549
|
-
|
550
|
-
Vagrant::Util::Busy.busy(int_callback) do
|
551
|
-
Vagrant::Util::Subprocess.execute(cli, *command, &block)
|
552
|
-
end
|
411
|
+
def vm_exists?(uuid)
|
412
|
+
raw("list", uuid).exit_code == 0
|
553
413
|
end
|
554
414
|
end
|
555
415
|
end
|