Detect if any collisions with non-hostonly networks for networking. [closes GH-102]

This commit is contained in:
Mitchell Hashimoto 2010-07-02 08:37:13 -07:00
parent 0896f096e9
commit ae0d9935a7
4 changed files with 81 additions and 17 deletions

View File

@ -2,6 +2,13 @@ module Vagrant
module Actions module Actions
module VM module VM
class Network < Base class Network < Base
def prepare
# Verify that the given network options are valid
runner.env.config.vm.network_options.compact.each do |network_options|
verify_no_bridge_collision(network_options)
end
end
def before_destroy def before_destroy
# We need to check if the host only network specified by any # We need to check if the host only network specified by any
# of the adapters would not have any more clients if it was # of the adapters would not have any more clients if it was
@ -55,6 +62,24 @@ module Vagrant
end end
end end
# Verifies that there is no collision with a bridged network interface
# for the given network options.
def verify_no_bridge_collision(net_options)
# First try to find a matching network
interfaces = VirtualBox::Global.global.host.network_interfaces
interfaces.each do |ni|
next if ni.interface_type == :host_only
result = if net_options[:name]
true if net_options[:name] == ni.name
else
true if matching_network?(ni, net_options)
end
raise ActionException.new(:network_collides) if result
end
end
# Returns the name of the proper host only network, or creates # Returns the name of the proper host only network, or creates
# it if it does not exist. Vagrant determines if the host only # it if it does not exist. Vagrant determines if the host only
# network exists by comparing the netmask and the IP. # network exists by comparing the netmask and the IP.

View File

@ -142,6 +142,11 @@
If the name specification is removed, Vagrant will create a new If the name specification is removed, Vagrant will create a new
host only network for you. Alternatively, please create the host only network for you. Alternatively, please create the
specified network manually. specified network manually.
:network_collides: |-
The specified host network collides with a non-hostonly network!
This will cause your specified IP to be inaccessible. Please change
the IP or name of your host only network to not match that of
a bridged or non-hostonly network.
:package_include_file_doesnt_exist: |- :package_include_file_doesnt_exist: |-
File specified to include: '<%= filename %>' does not exist! File specified to include: '<%= filename %>' does not exist!
:package_multivm: |- :package_multivm: |-

View File

@ -4,6 +4,36 @@ class NetworkTest < Test::Unit::TestCase
setup do setup do
@runner, @vm, @action = mock_action(Vagrant::Actions::VM::Network) @runner, @vm, @action = mock_action(Vagrant::Actions::VM::Network)
@runner.stubs(:system).returns(linux_system(@vm)) @runner.stubs(:system).returns(linux_system(@vm))
@interfaces = []
VirtualBox::Global.global.host.stubs(:network_interfaces).returns(@interfaces)
end
def mock_interface(options=nil)
options = {
:interface_type => :host_only,
:name => "foo"
}.merge(options || {})
interface = mock("interface")
options.each do |k,v|
interface.stubs(k).returns(v)
end
@interfaces << interface
interface
end
context "preparing" do
should "verify no bridge collisions for each network enabled" do
@runner.env.config.vm.network("foo")
@action.expects(:verify_no_bridge_collision).once.with() do |options|
assert_equal "foo", options[:ip]
true
end
@action.prepare
end
end end
context "before destroy" do context "before destroy" do
@ -112,29 +142,33 @@ class NetworkTest < Test::Unit::TestCase
end end
end end
context "network name" do context "verify no bridge collision" do
setup do setup do
@interfaces = []
VirtualBox::Global.global.host.stubs(:network_interfaces).returns(@interfaces)
@action.stubs(:matching_network?).returns(false) @action.stubs(:matching_network?).returns(false)
@options = { :ip => :foo, :netmask => :bar, :name => nil } @options = { :ip => :foo, :netmask => :bar, :name => nil }
end end
def mock_interface(options=nil) should "do nothing if everything is okay" do
options = { mock_interface
:interface_type => :host_only,
:name => "foo"
}.merge(options || {})
interface = mock("interface") assert_nothing_raised { @action.verify_no_bridge_collision(@options) }
options.each do |k,v|
interface.stubs(k).returns(v)
end end
@interfaces << interface should "raise an exception if a collision is found" do
interface mock_interface(:interface_type => :bridged)
@action.stubs(:matching_network?).returns(true)
assert_raises(Vagrant::Actions::ActionException) {
@action.verify_no_bridge_collision(@options)
}
end
end
context "network name" do
setup do
@action.stubs(:matching_network?).returns(false)
@options = { :ip => :foo, :netmask => :bar, :name => nil }
end end
should "return the network which matches" do should "return the network which matches" do

View File

@ -9,7 +9,7 @@ Gem::Specification.new do |s|
s.required_rubygems_version = Gem::Requirement.new("> 1.3.1") if s.respond_to? :required_rubygems_version= s.required_rubygems_version = Gem::Requirement.new("> 1.3.1") if s.respond_to? :required_rubygems_version=
s.authors = ["Mitchell Hashimoto", "John Bender"] s.authors = ["Mitchell Hashimoto", "John Bender"]
s.date = %q{2010-07-01} s.date = %q{2010-07-02}
s.default_executable = %q{vagrant} s.default_executable = %q{vagrant}
s.description = %q{Vagrant is a tool for building and distributing virtualized development environments.} s.description = %q{Vagrant is a tool for building and distributing virtualized development environments.}
s.email = ["mitchell.hashimoto@gmail.com", "john.m.bender@gmail.com"] s.email = ["mitchell.hashimoto@gmail.com", "john.m.bender@gmail.com"]