vagrant 0.9.7 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (61) hide show
  1. data/CHANGELOG.md +41 -0
  2. data/config/default.rb +0 -1
  3. data/lib/vagrant.rb +9 -5
  4. data/lib/vagrant/action.rb +1 -0
  5. data/lib/vagrant/action/builtin.rb +10 -0
  6. data/lib/vagrant/action/general/check_virtualbox.rb +28 -0
  7. data/lib/vagrant/action/general/package.rb +10 -7
  8. data/lib/vagrant/action/general/validate.rb +2 -3
  9. data/lib/vagrant/action/vm/customize.rb +1 -1
  10. data/lib/vagrant/action/vm/network.rb +10 -9
  11. data/lib/vagrant/action/vm/nfs.rb +7 -0
  12. data/lib/vagrant/command.rb +1 -0
  13. data/lib/vagrant/command/base.rb +8 -2
  14. data/lib/vagrant/command/destroy.rb +29 -3
  15. data/lib/vagrant/command/gem.rb +35 -0
  16. data/lib/vagrant/command/package.rb +1 -1
  17. data/lib/vagrant/command/ssh.rb +1 -1
  18. data/lib/vagrant/command/ssh_config.rb +1 -1
  19. data/lib/vagrant/config/loader.rb +2 -0
  20. data/lib/vagrant/config/ssh.rb +0 -20
  21. data/lib/vagrant/config/vm.rb +0 -48
  22. data/lib/vagrant/data_store.rb +18 -9
  23. data/lib/vagrant/driver/virtualbox.rb +1 -0
  24. data/lib/vagrant/driver/virtualbox_4_0.rb +36 -14
  25. data/lib/vagrant/driver/virtualbox_4_1.rb +36 -14
  26. data/lib/vagrant/driver/virtualbox_base.rb +37 -19
  27. data/lib/vagrant/environment.rb +21 -2
  28. data/lib/vagrant/errors.rb +10 -0
  29. data/lib/vagrant/guest.rb +1 -0
  30. data/lib/vagrant/guest/arch.rb +10 -2
  31. data/lib/vagrant/guest/base.rb +1 -1
  32. data/lib/vagrant/guest/debian.rb +5 -2
  33. data/lib/vagrant/guest/fedora.rb +66 -0
  34. data/lib/vagrant/guest/freebsd.rb +18 -7
  35. data/lib/vagrant/guest/gentoo.rb +6 -0
  36. data/lib/vagrant/guest/linux.rb +1 -0
  37. data/lib/vagrant/guest/redhat.rb +1 -0
  38. data/lib/vagrant/guest/ubuntu.rb +1 -1
  39. data/lib/vagrant/hosts.rb +1 -0
  40. data/lib/vagrant/hosts/opensuse.rb +30 -0
  41. data/lib/vagrant/plugin.rb +21 -19
  42. data/lib/vagrant/provisioners/chef.rb +3 -1
  43. data/lib/vagrant/provisioners/puppet.rb +18 -7
  44. data/lib/vagrant/util/line_ending_helpers.rb +14 -0
  45. data/lib/vagrant/util/subprocess.rb +9 -0
  46. data/lib/vagrant/version.rb +1 -1
  47. data/lib/vagrant/vm.rb +6 -6
  48. data/templates/commands/init/Vagrantfile.erb +1 -1
  49. data/templates/guests/fedora/network_dhcp.erb +6 -0
  50. data/templates/guests/fedora/network_static.erb +13 -0
  51. data/templates/guests/freebsd/network_dhcp.erb +3 -0
  52. data/templates/guests/freebsd/network_static.erb +3 -0
  53. data/templates/locales/en.yml +26 -0
  54. data/templates/nfs/exports_linux.erb +1 -1
  55. data/test/acceptance/networking/host_only_test.rb +2 -2
  56. data/test/unit/vagrant/config/vm_test.rb +4 -4
  57. data/test/unit/vagrant/data_store_test.rb +12 -0
  58. data/test/unit/vagrant/environment_test.rb +20 -0
  59. data/test/unit/vagrant/util/line_endings_helper_test.rb +16 -0
  60. data/vagrant.gemspec +1 -1
  61. metadata +37 -27
@@ -51,7 +51,7 @@ module Vagrant
51
51
  end
52
52
 
53
53
  def package_target(name, options)
54
- with_target_vms(name, true) do |vm|
54
+ with_target_vms(name, :single_target => true) do |vm|
55
55
  raise Errors::VMNotCreatedError if !vm.created?
56
56
  @logger.debug("Packaging VM: #{vm.name}")
57
57
  package_vm(vm, options)
@@ -36,7 +36,7 @@ module Vagrant
36
36
  argv = [] if argv == ssh_args
37
37
 
38
38
  # Execute the actual SSH
39
- with_target_vms(argv[0], true) do |vm|
39
+ with_target_vms(argv[0], :single_target => true) do |vm|
40
40
  # Basic checks that are required for proper SSH
41
41
  raise Errors::VMNotCreatedError if !vm.created?
42
42
  raise Errors::VMInaccessible if !vm.state == :inaccessible
@@ -19,7 +19,7 @@ module Vagrant
19
19
  argv = parse_options(opts)
20
20
  return if !argv
21
21
 
22
- with_target_vms(argv[0], true) do |vm|
22
+ with_target_vms(argv[0], :single_target => true) do |vm|
23
23
  raise Errors::VMNotCreatedError if !vm.created?
24
24
  raise Errors::VMInaccessible if !vm.state == :inaccessible
25
25
 
@@ -82,6 +82,8 @@ module Vagrant
82
82
  current = Top.new
83
83
  proc.call(current)
84
84
  @config_cache[proc] = current
85
+ else
86
+ @logger.debug("Loading from: #{key} (cache)")
85
87
  end
86
88
 
87
89
  # Merge in the results of this proc's configuration
@@ -13,26 +13,6 @@ module Vagrant
13
13
  attr_accessor :forward_x11
14
14
  attr_accessor :shell
15
15
 
16
- def forwarded_port_key=(value)
17
- raise Errors::DeprecationError, :message => <<-MESSAGE
18
- `config.ssh.forwarded_port_key` is now gone. You must now use
19
- `config.ssh.guest_port` which is expected to be the port on the
20
- guest that SSH is listening on. Vagrant will automatically scan
21
- the forwarded ports to look for a forwarded port from this port
22
- and use it.
23
- MESSAGE
24
- end
25
-
26
- def forwarded_port_destination=(value)
27
- raise Errors::DeprecationError, :message => <<-MESSAGE
28
- `config.ssh.forwarded_port_destination` is now gone. You must now use
29
- `config.ssh.guest_port` which is expected to be the port on the
30
- guest that SSH is listening on. Vagrant will automatically scan
31
- the forwarded ports to look for a forwarded port from this port
32
- and use it.
33
- MESSAGE
34
- end
35
-
36
16
  def validate(env, errors)
37
17
  [:username, :host, :max_tries, :timeout].each do |field|
38
18
  errors.add(I18n.t("vagrant.config.common.error_empty", :field => field)) if !instance_variable_get("@#{field}".to_sym)
@@ -39,28 +39,7 @@ module Vagrant
39
39
  result
40
40
  end
41
41
 
42
- def system=(value)
43
- raise Errors::DeprecationError, :message => <<-MESSAGE
44
- `config.vm.system` has changed to `config.vm.guest` in Vagrant 0.9,
45
- since this is more clear about the use of the configuration key.
46
- Please change all references of `config.vm.system` to `config.vm.guest`.
47
- MESSAGE
48
- end
49
-
50
42
  def forward_port(guestport, hostport, options=nil)
51
- if !guestport.kind_of?(Integer)
52
- raise Errors::DeprecationError, :message => <<-MESSAGE
53
- `config.vm.forward_port` changed in 0.9.0 where the required name
54
- argument is now removed. Vagrant will now automatically generate
55
- a unique name for your forwarded port. For example, to forward
56
- port 80 to port 8080 you now do the following:
57
-
58
- config.vm.forward_port 80, 8080
59
-
60
- Please change your configurations to match this new syntax.
61
- MESSAGE
62
- end
63
-
64
43
  @forwarded_ports << {
65
44
  :name => "#{guestport.to_s(32)}-#{hostport.to_s(32)}",
66
45
  :guestport => guestport,
@@ -85,19 +64,6 @@ Please change your configurations to match this new syntax.
85
64
  end
86
65
 
87
66
  def network(type, *args)
88
- if !type.kind_of?(Symbol)
89
- raise Errors::DeprecationError, :message => <<-MESSAGE
90
- `config.vm.network` changed in 0.9.0 where the first argument is
91
- now the type of network and the remaining arguments are options for
92
- that type. For example, host only networks are now configured like
93
- so:
94
-
95
- config.vm.network :hostonly, "172.24.24.24"
96
-
97
- Please change your configurations to match this new syntax.
98
- MESSAGE
99
- end
100
-
101
67
  @networks << [type, args]
102
68
  end
103
69
 
@@ -109,20 +75,6 @@ Please change your configurations to match this new syntax.
109
75
  # It is only defaulted to nil so that the deprecation error
110
76
  # can be properly shown.
111
77
  def customize(command=nil)
112
- if block_given?
113
- raise Errors::DeprecationError, :message => <<-MESSAGE
114
- `config.vm.customize` now takes an array of arguments to send to
115
- `VBoxManage` instead of having a block which gets a virtual machine
116
- object. Example of the new usage:
117
-
118
- config.vm.customize ["modifyvm", :id, "--memory", "1024"]
119
-
120
- The above will run `VBoxManage modifyvm 1234 --memory 1024` where
121
- "1234" is the ID of your current virtual machine. Anything you could
122
- do before is certainly still possible with `VBoxManage` as well.
123
- MESSAGE
124
- end
125
-
126
78
  @customizations << command if command
127
79
  end
128
80
 
@@ -21,25 +21,34 @@ module Vagrant
21
21
 
22
22
  def initialize(file_path)
23
23
  @logger = Log4r::Logger.new("vagrant::datastore")
24
- @logger.info("Created: #{file_path}")
25
24
 
26
- @file_path = Pathname.new(file_path)
25
+ if file_path
26
+ @logger.info("Created: #{file_path}")
27
27
 
28
- if @file_path.exist?
29
- raise Errors::DotfileIsDirectory if @file_path.directory?
28
+ @file_path = Pathname.new(file_path)
29
+ if @file_path.exist?
30
+ raise Errors::DotfileIsDirectory if @file_path.directory?
30
31
 
31
- begin
32
- merge!(JSON.parse(@file_path.read))
33
- rescue JSON::ParserError
34
- # Ignore if the data is invalid in the file.
35
- @logger.error("Data store contained invalid JSON. Ignoring.")
32
+ begin
33
+ merge!(JSON.parse(@file_path.read))
34
+ rescue JSON::ParserError
35
+ # Ignore if the data is invalid in the file.
36
+ @logger.error("Data store contained invalid JSON. Ignoring.")
37
+ end
36
38
  end
39
+ else
40
+ @logger.info("No file path. In-memory data store.")
41
+ @file_path = nil
37
42
  end
38
43
  end
39
44
 
40
45
  # Commits any changes to the data to disk. Even if the data
41
46
  # hasn't changed, it will be reserialized and written to disk.
42
47
  def commit
48
+ if !@file_path
49
+ raise StandardError, "In-memory data stores can't be committed."
50
+ end
51
+
43
52
  clean_nil_and_empties
44
53
 
45
54
  if empty?
@@ -99,6 +99,7 @@ module Vagrant
99
99
  :ssh_port,
100
100
  :start,
101
101
  :suspend,
102
+ :verify!,
102
103
  :verify_image,
103
104
  :vm_exists?
104
105
 
@@ -23,7 +23,8 @@ module Vagrant
23
23
  end
24
24
 
25
25
  def clear_shared_folders
26
- execute("showvminfo", @uuid, "--machinereadable").split("\n").each do |line|
26
+ info = execute("showvminfo", @uuid, "--machinereadable", :retryable => true)
27
+ info.split("\n").each do |line|
27
28
  if line =~ /^SharedFolderNameMachineMapping\d+="(.+?)"$/
28
29
  execute("sharedfolder", "remove", @uuid, "--name", $1.to_s)
29
30
  end
@@ -70,8 +71,9 @@ module Vagrant
70
71
 
71
72
  execute("list", "vms").split("\n").each do |line|
72
73
  if line =~ /^".+?"\s+\{(.+?)\}$/
73
- execute("showvminfo", $1.to_s, "--machinereadable").split("\n").each do |info|
74
- if info =~ /^hostonlyadapter\d+="(.+?)"$/
74
+ info = execute("showvminfo", $1.to_s, "--machinereadable", :retryable => true)
75
+ info.split("\n").each do |line|
76
+ if line =~ /^hostonlyadapter\d+="(.+?)"$/
75
77
  networks.delete($1.to_s)
76
78
  end
77
79
  end
@@ -202,7 +204,8 @@ module Vagrant
202
204
 
203
205
  results = []
204
206
  current_nic = nil
205
- execute("showvminfo", uuid, "--machinereadable").split("\n").each do |line|
207
+ info = execute("showvminfo", uuid, "--machinereadable", :retryable => true)
208
+ info.split("\n").each do |line|
206
209
  # This is how we find the nic that a FP is attached to,
207
210
  # since this comes first.
208
211
  current_nic = $1.to_i if line =~ /^nic(\d+)=".+?"$/
@@ -246,7 +249,8 @@ module Vagrant
246
249
  end
247
250
 
248
251
  def read_guest_additions_version
249
- output = execute("guestproperty", "get", @uuid, "/VirtualBox/GuestAdd/Version")
252
+ output = execute("guestproperty", "get", @uuid, "/VirtualBox/GuestAdd/Version",
253
+ :retryable => true)
250
254
  if output =~ /^Value: (.+?)$/
251
255
  # Split the version by _ since some distro versions modify it
252
256
  # to look like this: 4.1.2_ubuntu, and the distro part isn't
@@ -260,7 +264,7 @@ module Vagrant
260
264
 
261
265
  def read_host_only_interfaces
262
266
  dhcp = {}
263
- execute("list", "dhcpservers").split("\n\n").each do |block|
267
+ execute("list", "dhcpservers", :retryable => true).split("\n\n").each do |block|
264
268
  info = {}
265
269
 
266
270
  block.split("\n").each do |line|
@@ -279,7 +283,7 @@ module Vagrant
279
283
  dhcp[info[:network]] = info
280
284
  end
281
285
 
282
- execute("list", "hostonlyifs").split("\n\n").collect do |block|
286
+ execute("list", "hostonlyifs", :retryable => true).split("\n\n").collect do |block|
283
287
  info = {}
284
288
 
285
289
  block.split("\n").each do |line|
@@ -302,7 +306,8 @@ module Vagrant
302
306
  end
303
307
 
304
308
  def read_mac_address
305
- execute("showvminfo", @uuid, "--machinereadable").split("\n").each do |line|
309
+ info = execute("showvminfo", @uuid, "--machinereadable", :retryable => true)
310
+ info.split("\n").each do |line|
306
311
  return $1.to_s if line =~ /^macaddress1="(.+?)"$/
307
312
  end
308
313
 
@@ -310,7 +315,7 @@ module Vagrant
310
315
  end
311
316
 
312
317
  def read_machine_folder
313
- execute("list", "systemproperties").split("\n").each do |line|
318
+ execute("list", "systemproperties", :retryable => true).split("\n").each do |line|
314
319
  if line =~ /^Default machine folder:\s+(.+?)$/i
315
320
  return $1.to_s
316
321
  end
@@ -321,7 +326,8 @@ module Vagrant
321
326
 
322
327
  def read_network_interfaces
323
328
  nics = {}
324
- execute("showvminfo", @uuid, "--machinereadable").split("\n").each do |line|
329
+ info = execute("showvminfo", @uuid, "--machinereadable", :retryable => true)
330
+ info.split("\n").each do |line|
325
331
  if line =~ /^nic(\d+)="(.+?)"$/
326
332
  adapter = $1.to_i
327
333
  type = $2.to_sym
@@ -347,7 +353,7 @@ module Vagrant
347
353
  end
348
354
 
349
355
  def read_state
350
- output = execute("showvminfo", @uuid, "--machinereadable")
356
+ output = execute("showvminfo", @uuid, "--machinereadable", :retryable => true)
351
357
  if output =~ /^name="<inaccessible>"$/
352
358
  return :inaccessible
353
359
  elsif output =~ /^VMState="(.+?)"$/
@@ -359,7 +365,7 @@ module Vagrant
359
365
 
360
366
  def read_used_ports
361
367
  ports = []
362
- execute("list", "vms").split("\n").each do |line|
368
+ execute("list", "vms", :retryable => true).split("\n").each do |line|
363
369
  if line =~ /^".+?" \{(.+?)\}$/
364
370
  uuid = $1.to_s
365
371
 
@@ -377,7 +383,7 @@ module Vagrant
377
383
 
378
384
  def read_vms
379
385
  results = []
380
- execute("list", "vms").split("\n").each do |line|
386
+ execute("list", "vms", :retryable => true).split("\n").each do |line|
381
387
  if line =~ /^".+?" \{(.+?)\}$/
382
388
  results << $1.to_s
383
389
  end
@@ -417,13 +423,29 @@ module Vagrant
417
423
  end
418
424
 
419
425
  def start(mode)
420
- execute("startvm", @uuid, "--type", mode.to_s)
426
+ command = ["startvm", @uuid, "--type", mode.to_s]
427
+ r = raw(*command)
428
+
429
+ if r.exit_code == 0 || r.stdout =~ /VM ".+?" has been successfully started/
430
+ # Some systems return an exit code 1 for some reason. For that
431
+ # we depend on the output.
432
+ return true
433
+ end
434
+
435
+ # If we reached this point then it didn't work out.
436
+ raise Errors::VBoxManageError, :command => command.inspect
421
437
  end
422
438
 
423
439
  def suspend
424
440
  execute("controlvm", @uuid, "savestate")
425
441
  end
426
442
 
443
+ def verify!
444
+ # This command sometimes fails if kernel drivers aren't properly loaded
445
+ # so we just run the command and verify that it succeeded.
446
+ execute("list", "hostonlyifs")
447
+ end
448
+
427
449
  def verify_image(path)
428
450
  r = raw("import", path.to_s, "--dry-run")
429
451
  return r.exit_code == 0
@@ -23,7 +23,8 @@ module Vagrant
23
23
  end
24
24
 
25
25
  def clear_shared_folders
26
- execute("showvminfo", @uuid, "--machinereadable").split("\n").each do |line|
26
+ info = execute("showvminfo", @uuid, "--machinereadable", :retryable => true)
27
+ info.split("\n").each do |line|
27
28
  if line =~ /^SharedFolderNameMachineMapping\d+="(.+?)"$/
28
29
  execute("sharedfolder", "remove", @uuid, "--name", $1.to_s)
29
30
  end
@@ -70,8 +71,9 @@ module Vagrant
70
71
 
71
72
  execute("list", "vms").split("\n").each do |line|
72
73
  if line =~ /^".+?"\s+\{(.+?)\}$/
73
- execute("showvminfo", $1.to_s, "--machinereadable").split("\n").each do |info|
74
- if info =~ /^hostonlyadapter\d+="(.+?)"$/
74
+ info = execute("showvminfo", $1.to_s, "--machinereadable", :retryable => true)
75
+ info.split("\n").each do |line|
76
+ if line =~ /^hostonlyadapter\d+="(.+?)"$/
75
77
  networks.delete($1.to_s)
76
78
  end
77
79
  end
@@ -202,7 +204,8 @@ module Vagrant
202
204
 
203
205
  results = []
204
206
  current_nic = nil
205
- execute("showvminfo", uuid, "--machinereadable").split("\n").each do |line|
207
+ info = execute("showvminfo", uuid, "--machinereadable", :retryable => true)
208
+ info.split("\n").each do |line|
206
209
  # This is how we find the nic that a FP is attached to,
207
210
  # since this comes first.
208
211
  current_nic = $1.to_i if line =~ /^nic(\d+)=".+?"$/
@@ -246,7 +249,8 @@ module Vagrant
246
249
  end
247
250
 
248
251
  def read_guest_additions_version
249
- output = execute("guestproperty", "get", @uuid, "/VirtualBox/GuestAdd/Version")
252
+ output = execute("guestproperty", "get", @uuid, "/VirtualBox/GuestAdd/Version",
253
+ :retryable => true)
250
254
  if output =~ /^Value: (.+?)$/
251
255
  # Split the version by _ since some distro versions modify it
252
256
  # to look like this: 4.1.2_ubuntu, and the distro part isn't
@@ -260,7 +264,7 @@ module Vagrant
260
264
 
261
265
  def read_host_only_interfaces
262
266
  dhcp = {}
263
- execute("list", "dhcpservers").split("\n\n").each do |block|
267
+ execute("list", "dhcpservers", :retryable => true).split("\n\n").each do |block|
264
268
  info = {}
265
269
 
266
270
  block.split("\n").each do |line|
@@ -279,7 +283,7 @@ module Vagrant
279
283
  dhcp[info[:network]] = info
280
284
  end
281
285
 
282
- execute("list", "hostonlyifs").split("\n\n").collect do |block|
286
+ execute("list", "hostonlyifs", :retryable => true).split("\n\n").collect do |block|
283
287
  info = {}
284
288
 
285
289
  block.split("\n").each do |line|
@@ -302,7 +306,8 @@ module Vagrant
302
306
  end
303
307
 
304
308
  def read_mac_address
305
- execute("showvminfo", @uuid, "--machinereadable").split("\n").each do |line|
309
+ info = execute("showvminfo", @uuid, "--machinereadable", :retryable => true)
310
+ info.split("\n").each do |line|
306
311
  return $1.to_s if line =~ /^macaddress1="(.+?)"$/
307
312
  end
308
313
 
@@ -310,7 +315,7 @@ module Vagrant
310
315
  end
311
316
 
312
317
  def read_machine_folder
313
- execute("list", "systemproperties").split("\n").each do |line|
318
+ execute("list", "systemproperties", :retryable => true).split("\n").each do |line|
314
319
  if line =~ /^Default machine folder:\s+(.+?)$/i
315
320
  return $1.to_s
316
321
  end
@@ -321,7 +326,8 @@ module Vagrant
321
326
 
322
327
  def read_network_interfaces
323
328
  nics = {}
324
- execute("showvminfo", @uuid, "--machinereadable").split("\n").each do |line|
329
+ info = execute("showvminfo", @uuid, "--machinereadable", :retryable => true)
330
+ info.split("\n").each do |line|
325
331
  if line =~ /^nic(\d+)="(.+?)"$/
326
332
  adapter = $1.to_i
327
333
  type = $2.to_sym
@@ -347,7 +353,7 @@ module Vagrant
347
353
  end
348
354
 
349
355
  def read_state
350
- output = execute("showvminfo", @uuid, "--machinereadable")
356
+ output = execute("showvminfo", @uuid, "--machinereadable", :retryable => true)
351
357
  if output =~ /^name="<inaccessible>"$/
352
358
  return :inaccessible
353
359
  elsif output =~ /^VMState="(.+?)"$/
@@ -359,7 +365,7 @@ module Vagrant
359
365
 
360
366
  def read_used_ports
361
367
  ports = []
362
- execute("list", "vms").split("\n").each do |line|
368
+ execute("list", "vms", :retryable => true).split("\n").each do |line|
363
369
  if line =~ /^".+?" \{(.+?)\}$/
364
370
  uuid = $1.to_s
365
371
 
@@ -377,7 +383,7 @@ module Vagrant
377
383
 
378
384
  def read_vms
379
385
  results = []
380
- execute("list", "vms").split("\n").each do |line|
386
+ execute("list", "vms", :retryable => true).split("\n").each do |line|
381
387
  if line =~ /^".+?" \{(.+?)\}$/
382
388
  results << $1.to_s
383
389
  end
@@ -417,13 +423,29 @@ module Vagrant
417
423
  end
418
424
 
419
425
  def start(mode)
420
- execute("startvm", @uuid, "--type", mode.to_s)
426
+ command = ["startvm", @uuid, "--type", mode.to_s]
427
+ r = raw(*command)
428
+
429
+ if r.exit_code == 0 || r.stdout =~ /VM ".+?" has been successfully started/
430
+ # Some systems return an exit code 1 for some reason. For that
431
+ # we depend on the output.
432
+ return true
433
+ end
434
+
435
+ # If we reached this point then it didn't work out.
436
+ raise Errors::VBoxManageError, :command => command.inspect
421
437
  end
422
438
 
423
439
  def suspend
424
440
  execute("controlvm", @uuid, "savestate")
425
441
  end
426
442
 
443
+ def verify!
444
+ # This command sometimes fails if kernel drivers aren't properly loaded
445
+ # so we just run the command and verify that it succeeded.
446
+ execute("list", "hostonlyifs")
447
+ end
448
+
427
449
  def verify_image(path)
428
450
  r = raw("import", path.to_s, "--dry-run")
429
451
  return r.exit_code == 0