Merge pull request #2560 from phinze/vbox-nfs-dhcp-support
providers/virtualbox: support DHCP interfaces for NFS
This commit is contained in:
commit
d2bc1dbc3b
|
@ -568,6 +568,10 @@ module Vagrant
|
||||||
error_key(:virtualbox_broken_version_040214)
|
error_key(:virtualbox_broken_version_040214)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
class VirtualBoxGuestPropertyNotFound < VagrantError
|
||||||
|
error_key(:virtualbox_guest_property_not_found)
|
||||||
|
end
|
||||||
|
|
||||||
class VirtualBoxInvalidVersion < VagrantError
|
class VirtualBoxInvalidVersion < VagrantError
|
||||||
error_key(:virtualbox_invalid_version)
|
error_key(:virtualbox_invalid_version)
|
||||||
end
|
end
|
||||||
|
|
|
@ -2,41 +2,56 @@ module VagrantPlugins
|
||||||
module ProviderVirtualBox
|
module ProviderVirtualBox
|
||||||
module Action
|
module Action
|
||||||
class PrepareNFSSettings
|
class PrepareNFSSettings
|
||||||
|
include Vagrant::Util::Retryable
|
||||||
|
|
||||||
def initialize(app,env)
|
def initialize(app,env)
|
||||||
@app = app
|
@app = app
|
||||||
@logger = Log4r::Logger.new("vagrant::action::vm::nfs")
|
@logger = Log4r::Logger.new("vagrant::action::vm::nfs")
|
||||||
end
|
end
|
||||||
|
|
||||||
def call(env)
|
def call(env)
|
||||||
|
@machine = env[:machine]
|
||||||
@app.call(env)
|
@app.call(env)
|
||||||
|
|
||||||
using_nfs = false
|
if using_nfs?
|
||||||
env[:machine].config.vm.synced_folders.each do |id, opts|
|
|
||||||
if opts[:type] == :nfs
|
|
||||||
using_nfs = true
|
|
||||||
break
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
if using_nfs
|
|
||||||
@logger.info("Using NFS, preparing NFS settings by reading host IP and machine IP")
|
@logger.info("Using NFS, preparing NFS settings by reading host IP and machine IP")
|
||||||
env[:nfs_host_ip] = read_host_ip(env[:machine])
|
add_nfs_settings_to_env!(env)
|
||||||
env[:nfs_machine_ip] = read_machine_ip(env[:machine])
|
|
||||||
|
|
||||||
raise Vagrant::Errors::NFSNoHostonlyNetwork if !env[:nfs_machine_ip]
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# Returns the IP address of the first host only network adapter
|
# We're using NFS if we have any synced folder with NFS configured. If
|
||||||
|
# we are not using NFS we don't need to do the extra work to
|
||||||
|
# populate these fields in the environment.
|
||||||
|
def using_nfs?
|
||||||
|
@machine.config.vm.synced_folders.any? { |_, opts| opts[:type] == :nfs }
|
||||||
|
end
|
||||||
|
|
||||||
|
# Extracts the proper host and guest IPs for NFS mounts and stores them
|
||||||
|
# in the environment for the SyncedFolder action to use them in
|
||||||
|
# mounting.
|
||||||
#
|
#
|
||||||
# @param [Machine] machine
|
# The ! indicates that this method modifies its argument.
|
||||||
# @return [String]
|
def add_nfs_settings_to_env!(env)
|
||||||
def read_host_ip(machine)
|
adapter, host_ip = find_host_only_adapter
|
||||||
machine.provider.driver.read_network_interfaces.each do |adapter, opts|
|
machine_ip = nil
|
||||||
|
machine_ip = read_machine_ip(adapter) if adapter
|
||||||
|
|
||||||
|
raise Vagrant::Errors::NFSNoHostonlyNetwork if !host_ip || !machine_ip
|
||||||
|
|
||||||
|
env[:nfs_host_ip] = host_ip
|
||||||
|
env[:nfs_machine_ip] = machine_ip
|
||||||
|
end
|
||||||
|
|
||||||
|
# Finds first host only network adapter and returns its adapter number
|
||||||
|
# and IP address
|
||||||
|
#
|
||||||
|
# @return [Integer, String] adapter number, ip address of found host-only adapter
|
||||||
|
def find_host_only_adapter
|
||||||
|
@machine.provider.driver.read_network_interfaces.each do |adapter, opts|
|
||||||
if opts[:type] == :hostonly
|
if opts[:type] == :hostonly
|
||||||
machine.provider.driver.read_host_only_interfaces.each do |interface|
|
@machine.provider.driver.read_host_only_interfaces.each do |interface|
|
||||||
if interface[:name] == opts[:hostonly]
|
if interface[:name] == opts[:hostonly]
|
||||||
return interface[:ip]
|
return adapter, interface[:ip]
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -45,23 +60,34 @@ module VagrantPlugins
|
||||||
nil
|
nil
|
||||||
end
|
end
|
||||||
|
|
||||||
# Returns the IP address of the guest by looking at the first
|
# Returns the IP address of the guest by looking at vbox guest property
|
||||||
# enabled host only network.
|
# for the appropriate guest adapter.
|
||||||
#
|
#
|
||||||
# @return [String]
|
# For DHCP interfaces, the guest property will not be present until the
|
||||||
def read_machine_ip(machine)
|
# guest completes
|
||||||
ips = []
|
#
|
||||||
machine.config.vm.networks.each do |type, options|
|
# @param [Integer] adapter number to read IP for
|
||||||
if type == :private_network && options[:ip].is_a?(String)
|
# @return [String] ip address of adapter
|
||||||
ips << options[:ip]
|
def read_machine_ip(adapter)
|
||||||
end
|
# vbox guest properties are 0-indexed, while showvminfo network
|
||||||
end
|
# interfaces are 1-indexed. go figure.
|
||||||
|
guestproperty_adapter = adapter - 1
|
||||||
|
|
||||||
if ips.empty?
|
# we need to wait for the guest's IP to show up as a guest property.
|
||||||
return nil
|
# retry thresholds are relatively high since we might need to wait
|
||||||
|
# for DHCP, but even static IPs can take a second or two to appear.
|
||||||
|
retryable(retry_options.merge(on: Vagrant::Errors::VirtualBoxGuestPropertyNotFound)) do
|
||||||
|
@machine.provider.driver.read_guest_ip(guestproperty_adapter)
|
||||||
end
|
end
|
||||||
|
rescue Vagrant::Errors::VirtualBoxGuestPropertyNotFound
|
||||||
|
# this error is more specific with a better error message directing
|
||||||
|
# the user towards the fact that it's probably a reportable bug
|
||||||
|
raise Vagrant::Errors::NFSNoGuestIP
|
||||||
|
end
|
||||||
|
|
||||||
ips
|
# Separating these out so we can stub out the sleep in tests
|
||||||
|
def retry_options
|
||||||
|
{tries: 15, sleep: 1}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -185,6 +185,14 @@ module VagrantPlugins
|
||||||
def read_guest_additions_version
|
def read_guest_additions_version
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Returns the value of a guest property on the current VM.
|
||||||
|
#
|
||||||
|
# @param [String] property the name of the guest property to read
|
||||||
|
# @return [String] value of the guest property
|
||||||
|
# @raise [VirtualBoxGuestPropertyNotFound] if the guest property does not have a value
|
||||||
|
def read_guest_property(property)
|
||||||
|
end
|
||||||
|
|
||||||
# Returns a list of available host only interfaces.
|
# Returns a list of available host only interfaces.
|
||||||
#
|
#
|
||||||
# @return [Hash]
|
# @return [Hash]
|
||||||
|
|
|
@ -93,6 +93,8 @@ module VagrantPlugins
|
||||||
:read_forwarded_ports,
|
:read_forwarded_ports,
|
||||||
:read_bridged_interfaces,
|
:read_bridged_interfaces,
|
||||||
:read_guest_additions_version,
|
:read_guest_additions_version,
|
||||||
|
:read_guest_ip,
|
||||||
|
:read_guest_property,
|
||||||
:read_host_only_interfaces,
|
:read_host_only_interfaces,
|
||||||
:read_mac_address,
|
:read_mac_address,
|
||||||
:read_mac_addresses,
|
:read_mac_addresses,
|
||||||
|
|
|
@ -269,6 +269,19 @@ module VagrantPlugins
|
||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def read_guest_ip(adapter_number)
|
||||||
|
read_guest_property("/VirtualBox/GuestInfo/Net/#{adapter_number}/V4/IP")
|
||||||
|
end
|
||||||
|
|
||||||
|
def read_guest_property(property)
|
||||||
|
output = execute("guestproperty", "get", @uuid, property)
|
||||||
|
if output =~ /^Value: (.+?)$/
|
||||||
|
$1.to_s
|
||||||
|
else
|
||||||
|
raise Vagrant::Errors::VirtualBoxGuestPropertyNotFound, :guest_property => property
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def read_host_only_interfaces
|
def read_host_only_interfaces
|
||||||
dhcp = {}
|
dhcp = {}
|
||||||
execute("list", "dhcpservers", :retryable => true).split("\n\n").each do |block|
|
execute("list", "dhcpservers", :retryable => true).split("\n\n").each do |block|
|
||||||
|
|
|
@ -274,6 +274,19 @@ module VagrantPlugins
|
||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def read_guest_ip(adapter_number)
|
||||||
|
read_guest_property("/VirtualBox/GuestInfo/Net/#{adapter_number}/V4/IP")
|
||||||
|
end
|
||||||
|
|
||||||
|
def read_guest_property(property)
|
||||||
|
output = execute("guestproperty", "get", @uuid, property)
|
||||||
|
if output =~ /^Value: (.+?)$/
|
||||||
|
$1.to_s
|
||||||
|
else
|
||||||
|
raise Vagrant::Errors::VirtualBoxGuestPropertyNotFound, :guest_property => property
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def read_host_only_interfaces
|
def read_host_only_interfaces
|
||||||
dhcp = {}
|
dhcp = {}
|
||||||
execute("list", "dhcpservers", :retryable => true).split("\n\n").each do |block|
|
execute("list", "dhcpservers", :retryable => true).split("\n\n").each do |block|
|
||||||
|
|
|
@ -298,6 +298,19 @@ module VagrantPlugins
|
||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def read_guest_ip(adapter_number)
|
||||||
|
read_guest_property("/VirtualBox/GuestInfo/Net/#{adapter_number}/V4/IP")
|
||||||
|
end
|
||||||
|
|
||||||
|
def read_guest_property(property)
|
||||||
|
output = execute("guestproperty", "get", @uuid, property)
|
||||||
|
if output =~ /^Value: (.+?)$/
|
||||||
|
$1.to_s
|
||||||
|
else
|
||||||
|
raise Vagrant::Errors::VirtualBoxGuestPropertyNotFound, :guest_property => property
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def read_host_only_interfaces
|
def read_host_only_interfaces
|
||||||
dhcp = {}
|
dhcp = {}
|
||||||
execute("list", "dhcpservers", :retryable => true).split("\n\n").each do |block|
|
execute("list", "dhcpservers", :retryable => true).split("\n\n").each do |block|
|
||||||
|
|
|
@ -304,6 +304,19 @@ module VagrantPlugins
|
||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def read_guest_ip(adapter_number)
|
||||||
|
read_guest_property("/VirtualBox/GuestInfo/Net/#{adapter_number}/V4/IP")
|
||||||
|
end
|
||||||
|
|
||||||
|
def read_guest_property(property)
|
||||||
|
output = execute("guestproperty", "get", @uuid, property)
|
||||||
|
if output =~ /^Value: (.+?)$/
|
||||||
|
$1.to_s
|
||||||
|
else
|
||||||
|
raise Vagrant::Errors::VirtualBoxGuestPropertyNotFound, :guest_property => property
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def read_host_only_interfaces
|
def read_host_only_interfaces
|
||||||
dhcp = {}
|
dhcp = {}
|
||||||
execute("list", "dhcpservers", :retryable => true).split("\n\n").each do |block|
|
execute("list", "dhcpservers", :retryable => true).split("\n\n").each do |block|
|
||||||
|
|
|
@ -402,9 +402,9 @@ en:
|
||||||
No host IP was given to the Vagrant core NFS helper. This is
|
No host IP was given to the Vagrant core NFS helper. This is
|
||||||
an internal error that should be reported as a bug.
|
an internal error that should be reported as a bug.
|
||||||
nfs_no_hostonly_network: |-
|
nfs_no_hostonly_network: |-
|
||||||
NFS requires a host-only network with a static IP to be created.
|
NFS requires a host-only network to be created.
|
||||||
Please add a host-only network with a static IP to the machine
|
Please add a host-only network to the machine (with either DHCP or a
|
||||||
for NFS to work.
|
static IP) for NFS to work.
|
||||||
no_default_synced_folder_impl: |-
|
no_default_synced_folder_impl: |-
|
||||||
No synced folder implementation is available for your synced folders!
|
No synced folder implementation is available for your synced folders!
|
||||||
Please consult the documentation to learn why this may be the case.
|
Please consult the documentation to learn why this may be the case.
|
||||||
|
@ -657,6 +657,10 @@ en:
|
||||||
4.2.14 contains a critical bug that causes it to not work with
|
4.2.14 contains a critical bug that causes it to not work with
|
||||||
Vagrant. VirtualBox 4.2.16+ fixes this problem. Please upgrade
|
Vagrant. VirtualBox 4.2.16+ fixes this problem. Please upgrade
|
||||||
VirtualBox.
|
VirtualBox.
|
||||||
|
virtualbox_guest_property_not_found: |-
|
||||||
|
Could not find a required VirtualBox guest property:
|
||||||
|
%{guest_property}
|
||||||
|
This is an internal error that should be reported as a bug.
|
||||||
virtualbox_invalid_version: |-
|
virtualbox_invalid_version: |-
|
||||||
Vagrant has detected that you have a version of VirtualBox installed
|
Vagrant has detected that you have a version of VirtualBox installed
|
||||||
that is not supported. Please install one of the supported versions
|
that is not supported. Please install one of the supported versions
|
||||||
|
|
|
@ -13,6 +13,7 @@ require "support/tempdir"
|
||||||
require "unit/support/dummy_communicator"
|
require "unit/support/dummy_communicator"
|
||||||
require "unit/support/dummy_provider"
|
require "unit/support/dummy_provider"
|
||||||
require "unit/support/shared/base_context"
|
require "unit/support/shared/base_context"
|
||||||
|
require "unit/support/shared/virtualbox_context"
|
||||||
|
|
||||||
# Do not buffer output
|
# Do not buffer output
|
||||||
$stdout.sync = true
|
$stdout.sync = true
|
||||||
|
|
|
@ -0,0 +1,121 @@
|
||||||
|
require_relative "../base"
|
||||||
|
|
||||||
|
describe VagrantPlugins::ProviderVirtualBox::Action::PrepareNFSSettings do
|
||||||
|
include_context "virtualbox"
|
||||||
|
|
||||||
|
let(:machine) {
|
||||||
|
environment = Vagrant::Environment.new
|
||||||
|
provider = :virtualbox
|
||||||
|
provider_cls, provider_options = Vagrant.plugin("2").manager.providers[provider]
|
||||||
|
provider_config = Vagrant.plugin("2").manager.provider_configs[provider]
|
||||||
|
|
||||||
|
Vagrant::Machine.new(
|
||||||
|
'test_machine',
|
||||||
|
provider,
|
||||||
|
provider_cls,
|
||||||
|
provider_config,
|
||||||
|
provider_options,
|
||||||
|
environment.config_global,
|
||||||
|
Pathname('data_dir'),
|
||||||
|
double('box'),
|
||||||
|
environment
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
let(:env) {{ machine: machine }}
|
||||||
|
let(:app) { lambda { |*args| }}
|
||||||
|
let(:driver) { env[:machine].provider.driver }
|
||||||
|
|
||||||
|
subject { described_class.new(app, env) }
|
||||||
|
|
||||||
|
it "calls the next action in the chain" do
|
||||||
|
called = false
|
||||||
|
app = lambda { |*args| called = true }
|
||||||
|
|
||||||
|
action = described_class.new(app, env)
|
||||||
|
action.call(env)
|
||||||
|
|
||||||
|
called.should == true
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "with an nfs synced folder" do
|
||||||
|
before do
|
||||||
|
env[:machine].config.vm.synced_folder("/host/path", "/guest/path", nfs: true)
|
||||||
|
env[:machine].config.finalize!
|
||||||
|
end
|
||||||
|
|
||||||
|
it "sets nfs_host_ip and nfs_machine_ip properly" do
|
||||||
|
adapter_number = 2
|
||||||
|
adapter_name = "vmnet2"
|
||||||
|
driver.stub(:read_network_interfaces).and_return(
|
||||||
|
adapter_number => {type: :hostonly, hostonly: adapter_name}
|
||||||
|
)
|
||||||
|
driver.stub(:read_host_only_interfaces).and_return([
|
||||||
|
{name: adapter_name, ip: "1.2.3.4"}
|
||||||
|
])
|
||||||
|
driver.should_receive(:read_guest_ip).with(adapter_number-1).
|
||||||
|
and_return("2.3.4.5")
|
||||||
|
|
||||||
|
subject.call(env)
|
||||||
|
|
||||||
|
env[:nfs_host_ip].should == "1.2.3.4"
|
||||||
|
env[:nfs_machine_ip].should == "2.3.4.5"
|
||||||
|
end
|
||||||
|
|
||||||
|
it "raises an error when no host only adapter is configured" do
|
||||||
|
driver.stub(:read_network_interfaces) {{}}
|
||||||
|
|
||||||
|
expect { subject.call(env) }.
|
||||||
|
to raise_error(Vagrant::Errors::NFSNoHostonlyNetwork)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "retries through guest property not found errors" do
|
||||||
|
adapter_number = 2
|
||||||
|
adapter_name = "vmnet2"
|
||||||
|
driver.stub(:read_network_interfaces).and_return({
|
||||||
|
adapter_number => {type: :hostonly, hostonly: adapter_name}
|
||||||
|
})
|
||||||
|
driver.stub(:read_host_only_interfaces).and_return([
|
||||||
|
{name: adapter_name, ip: "1.2.3.4"}
|
||||||
|
])
|
||||||
|
driver.should_receive(:read_guest_ip).with(adapter_number-1).
|
||||||
|
and_return("2.3.4.5")
|
||||||
|
|
||||||
|
raise_then_return = [
|
||||||
|
lambda { raise Vagrant::Errors::VirtualBoxGuestPropertyNotFound, :guest_property => 'stub' },
|
||||||
|
lambda { "2.3.4.5" }
|
||||||
|
]
|
||||||
|
driver.stub(:read_guest_ip) { raise_then_return.shift.call }
|
||||||
|
|
||||||
|
# override sleep to 0 so test does not take seconds
|
||||||
|
retry_options = subject.retry_options
|
||||||
|
subject.stub(:retry_options).and_return(retry_options.merge(sleep: 0))
|
||||||
|
|
||||||
|
subject.call(env)
|
||||||
|
|
||||||
|
env[:nfs_host_ip].should == "1.2.3.4"
|
||||||
|
env[:nfs_machine_ip].should == "2.3.4.5"
|
||||||
|
end
|
||||||
|
|
||||||
|
it "raises an error informing the user of a bug when the guest IP cannot be found" do
|
||||||
|
adapter_number = 2
|
||||||
|
adapter_name = "vmnet2"
|
||||||
|
driver.stub(:read_network_interfaces).and_return({
|
||||||
|
adapter_number => {type: :hostonly, hostonly: adapter_name}
|
||||||
|
})
|
||||||
|
driver.stub(:read_host_only_interfaces).and_return([
|
||||||
|
{name: adapter_name, ip: "1.2.3.4"}
|
||||||
|
])
|
||||||
|
driver.stub(:read_guest_ip) {
|
||||||
|
raise Vagrant::Errors::VirtualBoxGuestPropertyNotFound, :guest_property => 'stub'
|
||||||
|
}
|
||||||
|
|
||||||
|
# override sleep to 0 so test does not take seconds
|
||||||
|
retry_options = subject.retry_options
|
||||||
|
subject.stub(:retry_options).and_return(retry_options.merge(sleep: 0))
|
||||||
|
|
||||||
|
expect { subject.call(env) }.
|
||||||
|
to raise_error(Vagrant::Errors::NFSNoGuestIP)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,4 @@
|
||||||
|
# base test helper for virtualbox unit tests
|
||||||
|
|
||||||
|
require_relative "../../../base"
|
||||||
|
require_relative "support/shared/virtualbox_driver_version_4_x_examples"
|
|
@ -0,0 +1,9 @@
|
||||||
|
require_relative "../base"
|
||||||
|
|
||||||
|
describe VagrantPlugins::ProviderVirtualBox::Driver::Version_4_0 do
|
||||||
|
include_context "virtualbox"
|
||||||
|
let(:vbox_version) { "4.0.0" }
|
||||||
|
subject { VagrantPlugins::ProviderVirtualBox::Driver::Meta.new(uuid) }
|
||||||
|
|
||||||
|
it_behaves_like "a version 4.x virtualbox driver"
|
||||||
|
end
|
|
@ -0,0 +1,9 @@
|
||||||
|
require_relative "../base"
|
||||||
|
|
||||||
|
describe VagrantPlugins::ProviderVirtualBox::Driver::Version_4_1 do
|
||||||
|
include_context "virtualbox"
|
||||||
|
let(:vbox_version) { "4.1.0" }
|
||||||
|
subject { VagrantPlugins::ProviderVirtualBox::Driver::Meta.new(uuid) }
|
||||||
|
|
||||||
|
it_behaves_like "a version 4.x virtualbox driver"
|
||||||
|
end
|
|
@ -0,0 +1,9 @@
|
||||||
|
require_relative "../base"
|
||||||
|
|
||||||
|
describe VagrantPlugins::ProviderVirtualBox::Driver::Version_4_2 do
|
||||||
|
include_context "virtualbox"
|
||||||
|
let(:vbox_version) { "4.2.0" }
|
||||||
|
subject { VagrantPlugins::ProviderVirtualBox::Driver::Meta.new(uuid) }
|
||||||
|
|
||||||
|
it_behaves_like "a version 4.x virtualbox driver"
|
||||||
|
end
|
|
@ -0,0 +1,9 @@
|
||||||
|
require_relative "../base"
|
||||||
|
|
||||||
|
describe VagrantPlugins::ProviderVirtualBox::Driver::Version_4_3 do
|
||||||
|
include_context "virtualbox"
|
||||||
|
let(:vbox_version) { "4.3.0" }
|
||||||
|
subject { VagrantPlugins::ProviderVirtualBox::Driver::Meta.new(uuid) }
|
||||||
|
|
||||||
|
it_behaves_like "a version 4.x virtualbox driver"
|
||||||
|
end
|
|
@ -0,0 +1,42 @@
|
||||||
|
shared_examples "a version 4.x virtualbox driver" do |options|
|
||||||
|
before do
|
||||||
|
raise ArgumentError, "Need virtualbox context to use these shared examples." if !(defined? vbox_context)
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "read_guest_property" do
|
||||||
|
it "reads the guest property of the machine referenced by the UUID" do
|
||||||
|
key = "/Foo/Bar"
|
||||||
|
|
||||||
|
subprocess.should_receive(:execute).
|
||||||
|
with("VBoxManage", "guestproperty", "get", uuid, key, an_instance_of(Hash)).
|
||||||
|
and_return(subprocess_result(stdout: "Value: Baz\n"))
|
||||||
|
|
||||||
|
subject.read_guest_property(key).should == "Baz"
|
||||||
|
end
|
||||||
|
|
||||||
|
it "raises a virtualBoxGuestPropertyNotFound exception when the value is not set" do
|
||||||
|
key = "/Not/There"
|
||||||
|
|
||||||
|
subprocess.should_receive(:execute).
|
||||||
|
with("VBoxManage", "guestproperty", "get", uuid, key, an_instance_of(Hash)).
|
||||||
|
and_return(subprocess_result(stdout: "No value set!"))
|
||||||
|
|
||||||
|
expect { subject.read_guest_property(key) }.
|
||||||
|
to raise_error Vagrant::Errors::VirtualBoxGuestPropertyNotFound
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "read_guest_ip" do
|
||||||
|
it "reads the guest property for the provided adapter number" do
|
||||||
|
key = "/VirtualBox/GuestInfo/Net/1/V4/IP"
|
||||||
|
|
||||||
|
subprocess.should_receive(:execute).
|
||||||
|
with("VBoxManage", "guestproperty", "get", uuid, key, an_instance_of(Hash)).
|
||||||
|
and_return(subprocess_result(stdout: "Value: 127.1.2.3"))
|
||||||
|
|
||||||
|
value = subject.read_guest_ip(1)
|
||||||
|
|
||||||
|
value.should == "127.1.2.3"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,30 @@
|
||||||
|
shared_context "virtualbox" do
|
||||||
|
let(:vbox_context) { true }
|
||||||
|
let(:uuid) { "1234-abcd-5678-efgh" }
|
||||||
|
let(:vbox_version) { "4.3.4" }
|
||||||
|
let(:subprocess) { double("Vagrant::Util::Subprocess") }
|
||||||
|
|
||||||
|
# this is a helper that returns a duck type suitable from a system command
|
||||||
|
# execution; allows setting exit_code, stdout, and stderr in stubs.
|
||||||
|
def subprocess_result(options={})
|
||||||
|
defaults = {exit_code: 0, stdout: "", stderr: ""}
|
||||||
|
double("subprocess_result", defaults.merge(options))
|
||||||
|
end
|
||||||
|
|
||||||
|
before do
|
||||||
|
# we don't want unit tests to ever run commands on the system; so we wire
|
||||||
|
# in a double to ensure any unexpected messages raise exceptions
|
||||||
|
stub_const("Vagrant::Util::Subprocess", subprocess)
|
||||||
|
|
||||||
|
# drivers will blow up on instantiation if they cannot determine the
|
||||||
|
# virtualbox version, so wire this stub in automatically
|
||||||
|
subprocess.stub(:execute).
|
||||||
|
with("VBoxManage", "--version", an_instance_of(Hash)).
|
||||||
|
and_return(subprocess_result(stdout: vbox_version))
|
||||||
|
|
||||||
|
# drivers also call vm_exists? during init;
|
||||||
|
subprocess.stub(:execute).
|
||||||
|
with("VBoxManage", "showvminfo", kind_of(String), kind_of(Hash)).
|
||||||
|
and_return(subprocess_result(exit_code: 0))
|
||||||
|
end
|
||||||
|
end
|
Loading…
Reference in New Issue