vagrant-parallels 0.2.1 → 0.2.2.rc1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.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
|