Retry VirtualBox commands. [GH-726]

This commit is contained in:
Mitchell Hashimoto 2012-02-10 21:56:59 -08:00
parent c50c7959f9
commit 9e427562ef
4 changed files with 70 additions and 42 deletions

View File

@ -15,6 +15,8 @@
as failing. [GH-720]
- It is now an error to specify the packaging `output` as a directory. [GH-730]
- Unix-style line endings are used properly for guest OS. [GH-727]
- Retry certain VirtualBox operations, since they intermittently fail.
[GH-726]
## 0.9.7 (February 9, 2012)

View File

@ -23,7 +23,8 @@ module Vagrant
end
def clear_shared_folders
execute("showvminfo", @uuid, "--machinereadable").split("\n").each do |line|
info = execute("showvminfo", @uuid, "--machinereadable", :retryable => true)
info.split("\n").each do |line|
if line =~ /^SharedFolderNameMachineMapping\d+="(.+?)"$/
execute("sharedfolder", "remove", @uuid, "--name", $1.to_s)
end
@ -70,8 +71,9 @@ module Vagrant
execute("list", "vms").split("\n").each do |line|
if line =~ /^".+?"\s+\{(.+?)\}$/
execute("showvminfo", $1.to_s, "--machinereadable").split("\n").each do |info|
if info =~ /^hostonlyadapter\d+="(.+?)"$/
info = execute("showvminfo", $1.to_s, "--machinereadable", :retryable => true)
info.split("\n").each do |line|
if line =~ /^hostonlyadapter\d+="(.+?)"$/
networks.delete($1.to_s)
end
end
@ -202,7 +204,8 @@ module Vagrant
results = []
current_nic = nil
execute("showvminfo", uuid, "--machinereadable").split("\n").each do |line|
info = execute("showvminfo", uuid, "--machinereadable", :retryable => true)
info.split("\n").each do |line|
# This is how we find the nic that a FP is attached to,
# since this comes first.
current_nic = $1.to_i if line =~ /^nic(\d+)=".+?"$/
@ -246,7 +249,8 @@ module Vagrant
end
def read_guest_additions_version
output = execute("guestproperty", "get", @uuid, "/VirtualBox/GuestAdd/Version")
output = execute("guestproperty", "get", @uuid, "/VirtualBox/GuestAdd/Version",
:retryable => true)
if output =~ /^Value: (.+?)$/
# Split the version by _ since some distro versions modify it
# to look like this: 4.1.2_ubuntu, and the distro part isn't
@ -260,7 +264,7 @@ module Vagrant
def read_host_only_interfaces
dhcp = {}
execute("list", "dhcpservers").split("\n\n").each do |block|
execute("list", "dhcpservers", :retryable => true).split("\n\n").each do |block|
info = {}
block.split("\n").each do |line|
@ -279,7 +283,7 @@ module Vagrant
dhcp[info[:network]] = info
end
execute("list", "hostonlyifs").split("\n\n").collect do |block|
execute("list", "hostonlyifs", :retryable => true).split("\n\n").collect do |block|
info = {}
block.split("\n").each do |line|
@ -302,7 +306,8 @@ module Vagrant
end
def read_mac_address
execute("showvminfo", @uuid, "--machinereadable").split("\n").each do |line|
info = execute("showvminfo", @uuid, "--machinereadable", :retryable => true)
info.split("\n").each do |line|
return $1.to_s if line =~ /^macaddress1="(.+?)"$/
end
@ -310,7 +315,7 @@ module Vagrant
end
def read_machine_folder
execute("list", "systemproperties").split("\n").each do |line|
execute("list", "systemproperties", :retryable => true).split("\n").each do |line|
if line =~ /^Default machine folder:\s+(.+?)$/i
return $1.to_s
end
@ -321,7 +326,8 @@ module Vagrant
def read_network_interfaces
nics = {}
execute("showvminfo", @uuid, "--machinereadable").split("\n").each do |line|
info = execute("showvminfo", @uuid, "--machinereadable", :retryable => true)
info.split("\n").each do |line|
if line =~ /^nic(\d+)="(.+?)"$/
adapter = $1.to_i
type = $2.to_sym
@ -347,7 +353,7 @@ module Vagrant
end
def read_state
output = execute("showvminfo", @uuid, "--machinereadable")
output = execute("showvminfo", @uuid, "--machinereadable", :retryable => true)
if output =~ /^name="<inaccessible>"$/
return :inaccessible
elsif output =~ /^VMState="(.+?)"$/
@ -359,7 +365,7 @@ module Vagrant
def read_used_ports
ports = []
execute("list", "vms").split("\n").each do |line|
execute("list", "vms", :retryable => true).split("\n").each do |line|
if line =~ /^".+?" \{(.+?)\}$/
uuid = $1.to_s
@ -377,7 +383,7 @@ module Vagrant
def read_vms
results = []
execute("list", "vms").split("\n").each do |line|
execute("list", "vms", :retryable => true).split("\n").each do |line|
if line =~ /^".+?" \{(.+?)\}$/
results << $1.to_s
end

View File

@ -23,7 +23,8 @@ module Vagrant
end
def clear_shared_folders
execute("showvminfo", @uuid, "--machinereadable").split("\n").each do |line|
info = execute("showvminfo", @uuid, "--machinereadable", :retryable => true)
info.split("\n").each do |line|
if line =~ /^SharedFolderNameMachineMapping\d+="(.+?)"$/
execute("sharedfolder", "remove", @uuid, "--name", $1.to_s)
end
@ -70,8 +71,9 @@ module Vagrant
execute("list", "vms").split("\n").each do |line|
if line =~ /^".+?"\s+\{(.+?)\}$/
execute("showvminfo", $1.to_s, "--machinereadable").split("\n").each do |info|
if info =~ /^hostonlyadapter\d+="(.+?)"$/
info = execute("showvminfo", $1.to_s, "--machinereadable", :retryable => true)
info.split("\n").each do |line|
if line =~ /^hostonlyadapter\d+="(.+?)"$/
networks.delete($1.to_s)
end
end
@ -202,7 +204,8 @@ module Vagrant
results = []
current_nic = nil
execute("showvminfo", uuid, "--machinereadable").split("\n").each do |line|
info = execute("showvminfo", uuid, "--machinereadable", :retryable => true)
info.split("\n").each do |line|
# This is how we find the nic that a FP is attached to,
# since this comes first.
current_nic = $1.to_i if line =~ /^nic(\d+)=".+?"$/
@ -246,7 +249,8 @@ module Vagrant
end
def read_guest_additions_version
output = execute("guestproperty", "get", @uuid, "/VirtualBox/GuestAdd/Version")
output = execute("guestproperty", "get", @uuid, "/VirtualBox/GuestAdd/Version",
:retryable => true)
if output =~ /^Value: (.+?)$/
# Split the version by _ since some distro versions modify it
# to look like this: 4.1.2_ubuntu, and the distro part isn't
@ -260,7 +264,7 @@ module Vagrant
def read_host_only_interfaces
dhcp = {}
execute("list", "dhcpservers").split("\n\n").each do |block|
execute("list", "dhcpservers", :retryable => true).split("\n\n").each do |block|
info = {}
block.split("\n").each do |line|
@ -279,7 +283,7 @@ module Vagrant
dhcp[info[:network]] = info
end
execute("list", "hostonlyifs").split("\n\n").collect do |block|
execute("list", "hostonlyifs", :retryable => true).split("\n\n").collect do |block|
info = {}
block.split("\n").each do |line|
@ -302,7 +306,8 @@ module Vagrant
end
def read_mac_address
execute("showvminfo", @uuid, "--machinereadable").split("\n").each do |line|
info = execute("showvminfo", @uuid, "--machinereadable", :retryable => true)
info.split("\n").each do |line|
return $1.to_s if line =~ /^macaddress1="(.+?)"$/
end
@ -310,7 +315,7 @@ module Vagrant
end
def read_machine_folder
execute("list", "systemproperties").split("\n").each do |line|
execute("list", "systemproperties", :retryable => true).split("\n").each do |line|
if line =~ /^Default machine folder:\s+(.+?)$/i
return $1.to_s
end
@ -321,7 +326,8 @@ module Vagrant
def read_network_interfaces
nics = {}
execute("showvminfo", @uuid, "--machinereadable").split("\n").each do |line|
info = execute("showvminfo", @uuid, "--machinereadable", :retryable => true)
info.split("\n").each do |line|
if line =~ /^nic(\d+)="(.+?)"$/
adapter = $1.to_i
type = $2.to_sym
@ -347,7 +353,7 @@ module Vagrant
end
def read_state
output = execute("showvminfo", @uuid, "--machinereadable")
output = execute("showvminfo", @uuid, "--machinereadable", :retryable => true)
if output =~ /^name="<inaccessible>"$/
return :inaccessible
elsif output =~ /^VMState="(.+?)"$/
@ -359,7 +365,7 @@ module Vagrant
def read_used_ports
ports = []
execute("list", "vms").split("\n").each do |line|
execute("list", "vms", :retryable => true).split("\n").each do |line|
if line =~ /^".+?" \{(.+?)\}$/
uuid = $1.to_s
@ -377,7 +383,7 @@ module Vagrant
def read_vms
results = []
execute("list", "vms").split("\n").each do |line|
execute("list", "vms", :retryable => true).split("\n").each do |line|
if line =~ /^".+?" \{(.+?)\}$/
results << $1.to_s
end

View File

@ -2,6 +2,7 @@ require 'log4r'
require 'vagrant/util/busy'
require 'vagrant/util/platform'
require 'vagrant/util/retryable'
require 'vagrant/util/subprocess'
module Vagrant
@ -13,6 +14,7 @@ module Vagrant
class VirtualBoxBase
# Include this so we can use `Subprocess` more easily.
include Vagrant::Util
include Vagrant::Util::Retryable
def initialize
@logger = Log4r::Logger.new("vagrant::driver::virtualbox_base")
@ -247,24 +249,36 @@ module Vagrant
# Execute the given subcommand for VBoxManage and return the output.
def execute(*command, &block)
# Execute the command
r = raw(*command, &block)
# Get the options hash if it exists
opts = {}
opts = command.pop if command.last.is_a?(Hash)
# If the command was a failure, then raise an exception that is
# nicely handled by Vagrant.
if r.exit_code != 0
if @interrupted
@logger.info("Exit code != 0, but interrupted. Ignoring.")
tries = 0
tries = 3 if opts[:retryable]
# Variable to store our execution result
r = nil
retryable(:on => Errors::VBoxManageError, :tries => tries, :sleep => 1) do
# Execute the command
r = raw(*command, &block)
# If the command was a failure, then raise an exception that is
# nicely handled by Vagrant.
if r.exit_code != 0
if @interrupted
@logger.info("Exit code != 0, but interrupted. Ignoring.")
else
raise Errors::VBoxManageError, :command => command.inspect
end
else
raise Errors::VBoxManageError, :command => command.inspect
end
else
# Sometimes, VBoxManage fails but doesn't actual return a non-zero
# exit code. For this we inspect the output and determine if an error
# occurred.
if r.stderr =~ /VBoxManage: error:/
@logger.info("VBoxManage error text found, assuming error.")
raise Errors::VBoxManageError, :command => command.inspect
# Sometimes, VBoxManage fails but doesn't actual return a non-zero
# exit code. For this we inspect the output and determine if an error
# occurred.
if r.stderr =~ /VBoxManage: error:/
@logger.info("VBoxManage error text found, assuming error.")
raise Errors::VBoxManageError, :command => command.inspect
end
end
end