vagrant 0.9.7 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
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