Host only networks. Doesn't yet set them up within the OS but creates them on the guest.
This commit is contained in:
parent
b63c74fad9
commit
77f7b09a26
|
@ -0,0 +1,86 @@
|
|||
module Vagrant
|
||||
module Actions
|
||||
module VM
|
||||
class Network < Base
|
||||
def before_boot
|
||||
assign_network if enable_network?
|
||||
end
|
||||
|
||||
def after_boot
|
||||
|
||||
end
|
||||
|
||||
def enable_network?
|
||||
!runner.env.config.vm.network_options.nil?
|
||||
end
|
||||
|
||||
# Enables and assigns the host only network to the proper
|
||||
# adapter on the VM, and saves the adapter.
|
||||
def assign_network
|
||||
logger.info "Enabling host only network..."
|
||||
|
||||
options = runner.env.config.vm.network_options
|
||||
adapter = runner.vm.network_adapters[options[:adapter]]
|
||||
adapter.enabled = true
|
||||
adapter.attachment_type = :host_only
|
||||
adapter.host_interface = network_name(options)
|
||||
adapter.save
|
||||
end
|
||||
|
||||
# Returns the name of the proper host only network, or creates
|
||||
# it if it does not exist. Vagrant determines if the host only
|
||||
# network exists by comparing the netmask and the IP.
|
||||
def network_name(options)
|
||||
# First try to find a matching network
|
||||
interfaces = VirtualBox::Global.global.host.network_interfaces
|
||||
interfaces.each do |ni|
|
||||
return ni.name if matching_network?(ni, options)
|
||||
end
|
||||
|
||||
# One doesn't exist, create it.
|
||||
logger.info "Creating new host only network for environment..."
|
||||
|
||||
ni = interfaces.create
|
||||
ni.enable_static(network_ip(options[:ip], options[:netmask]),
|
||||
options[:netmask])
|
||||
ni.name
|
||||
end
|
||||
|
||||
# Tests if a network matches the given options by applying the
|
||||
# netmask to the IP of the network and also to the IP of the
|
||||
# virtual machine and see if they match.
|
||||
def matching_network?(interface, options)
|
||||
interface.network_mask == options[:netmask] &&
|
||||
apply_netmask(interface.ip_address, interface.network_mask) ==
|
||||
apply_netmask(options[:ip], options[:netmask])
|
||||
end
|
||||
|
||||
# Applies a netmask to an IP and returns the corresponding
|
||||
# parts.
|
||||
def apply_netmask(ip, netmask)
|
||||
ip = split_ip(ip)
|
||||
netmask = split_ip(netmask)
|
||||
|
||||
ip.map do |part|
|
||||
part & netmask.shift
|
||||
end
|
||||
end
|
||||
|
||||
# Splits an IP and converts each portion into an int.
|
||||
def split_ip(ip)
|
||||
ip.split(".").map do |i|
|
||||
i.to_i
|
||||
end
|
||||
end
|
||||
|
||||
# Returns a "network IP" which is a "good choice" for the IP
|
||||
# for the actual network based on the netmask.
|
||||
def network_ip(ip, netmask)
|
||||
parts = apply_netmask(ip, netmask)
|
||||
parts[3] += 1;
|
||||
parts.join(".")
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -7,7 +7,7 @@ module Vagrant
|
|||
# of other actions in its place:
|
||||
steps = [Boot]
|
||||
if !@runner.vm || !@runner.vm.saved?
|
||||
steps.unshift([Customize, ForwardPorts, SharedFolders])
|
||||
steps.unshift([Customize, ForwardPorts, SharedFolders, Network])
|
||||
steps << Provision if provision?
|
||||
end
|
||||
|
||||
|
|
|
@ -90,6 +90,7 @@ module Vagrant
|
|||
attr_reader :rsync_required
|
||||
attr_reader :forwarded_ports
|
||||
attr_reader :shared_folders
|
||||
attr_reader :network_options
|
||||
attr_accessor :hd_location
|
||||
attr_accessor :disk_image_format
|
||||
attr_accessor :provisioner
|
||||
|
@ -101,6 +102,7 @@ module Vagrant
|
|||
@forwarded_ports = {}
|
||||
@shared_folders = {}
|
||||
@provisioner = nil
|
||||
@network_options = nil
|
||||
end
|
||||
|
||||
def forward_port(name, guestport, hostport, options=nil)
|
||||
|
@ -130,6 +132,16 @@ module Vagrant
|
|||
}
|
||||
end
|
||||
|
||||
def network(ip, options=nil)
|
||||
options = {
|
||||
:ip => ip,
|
||||
:netmask => "255.255.255.0",
|
||||
:name => nil
|
||||
}.merge(options || {})
|
||||
|
||||
@network_options = options
|
||||
end
|
||||
|
||||
def hd_location=(val)
|
||||
raise Exception.new("disk_storage must be set to a directory") unless File.directory?(val)
|
||||
@hd_location=val
|
||||
|
|
|
@ -0,0 +1,168 @@
|
|||
require File.join(File.dirname(__FILE__), '..', '..', '..', 'test_helper')
|
||||
|
||||
class NetworkTest < Test::Unit::TestCase
|
||||
setup do
|
||||
@runner, @vm, @action = mock_action(Vagrant::Actions::VM::Network)
|
||||
@runner.stubs(:system).returns(linux_system(@vm))
|
||||
end
|
||||
|
||||
context "before boot" do
|
||||
setup do
|
||||
@action.stubs(:enable_network?).returns(false)
|
||||
end
|
||||
|
||||
should "do nothing if network should not be enabled" do
|
||||
@action.expects(:assign_network).never
|
||||
@action.before_boot
|
||||
end
|
||||
|
||||
should "assign the network if host only networking is enabled" do
|
||||
@action.stubs(:enable_network?).returns(true)
|
||||
@action.expects(:assign_network).once
|
||||
@action.before_boot
|
||||
end
|
||||
end
|
||||
|
||||
context "checking if network is enabled" do
|
||||
should "return true if the network options are set" do
|
||||
@runner.env.config.vm.network("foo")
|
||||
assert @action.enable_network?
|
||||
end
|
||||
|
||||
should "return false if the network was not set" do
|
||||
assert !@action.enable_network?
|
||||
end
|
||||
end
|
||||
|
||||
context "assigning the network" do
|
||||
setup do
|
||||
@network_name = "foo"
|
||||
@action.stubs(:network_name).returns(@network_name)
|
||||
|
||||
@network_adapters = []
|
||||
@vm.stubs(:network_adapters).returns(@network_adapters)
|
||||
|
||||
@options = {
|
||||
:ip => "foo",
|
||||
:adapter => 7
|
||||
}
|
||||
|
||||
@runner.env.config.vm.network(@options[:ip], @options)
|
||||
end
|
||||
|
||||
should "setup the specified network adapter" do
|
||||
adapter = mock("adapter")
|
||||
@network_adapters[@options[:adapter]] = adapter
|
||||
|
||||
adapter.expects(:enabled=).with(true).once
|
||||
adapter.expects(:attachment_type=).with(:host_only).once
|
||||
adapter.expects(:host_interface=).with(@network_name).once
|
||||
adapter.expects(:save).once
|
||||
|
||||
@action.assign_network
|
||||
end
|
||||
end
|
||||
|
||||
context "network name" do
|
||||
setup do
|
||||
@interfaces = []
|
||||
VirtualBox::Global.global.host.stubs(:network_interfaces).returns(@interfaces)
|
||||
|
||||
@action.stubs(:matching_network?).returns(false)
|
||||
|
||||
@options = { :ip => :foo, :netmask => :bar }
|
||||
end
|
||||
|
||||
should "return the network which matches" do
|
||||
result = mock("result")
|
||||
interface = mock("interface")
|
||||
interface.stubs(:name).returns(result)
|
||||
@interfaces << interface
|
||||
|
||||
@action.expects(:matching_network?).with(interface, @options).returns(true)
|
||||
assert_equal result, @action.network_name(@options)
|
||||
end
|
||||
|
||||
should "create a network for the IP and netmask" do
|
||||
result = mock("result")
|
||||
interface = mock("interface")
|
||||
network_ip = :foo
|
||||
@interfaces.expects(:create).returns(interface)
|
||||
@action.expects(:network_ip).with(@options[:ip], @options[:netmask]).once.returns(network_ip)
|
||||
interface.expects(:enable_static).with(network_ip, @options[:netmask])
|
||||
interface.expects(:name).returns(result)
|
||||
|
||||
assert_equal result, @action.network_name(@options)
|
||||
end
|
||||
end
|
||||
|
||||
context "checking for a matching network" do
|
||||
setup do
|
||||
@interface = mock("interface")
|
||||
@interface.stubs(:network_mask).returns("foo")
|
||||
@interface.stubs(:ip_address).returns("192.168.0.1")
|
||||
|
||||
@options = {
|
||||
:netmask => "foo",
|
||||
:ip => "baz"
|
||||
}
|
||||
end
|
||||
|
||||
should "return false if the netmasks don't match" do
|
||||
@options[:netmask] = "bar"
|
||||
assert @interface.network_mask != @options[:netmask] # sanity
|
||||
assert !@action.matching_network?(@interface, @options)
|
||||
end
|
||||
|
||||
should "return true if the netmasks yield the same IP" do
|
||||
tests = [["255.255.255.0", "192.168.0.1", "192.168.0.45"],
|
||||
["255.255.0.0", "192.168.45.1", "192.168.28.7"]]
|
||||
|
||||
tests.each do |netmask, interface_ip, guest_ip|
|
||||
@options[:netmask] = netmask
|
||||
@options[:ip] = guest_ip
|
||||
@interface.stubs(:network_mask).returns(netmask)
|
||||
@interface.stubs(:ip_address).returns(interface_ip)
|
||||
|
||||
assert @action.matching_network?(@interface, @options)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context "applying the netmask" do
|
||||
should "return the proper result" do
|
||||
tests = {
|
||||
["192.168.0.1","255.255.255.0"] => [192,168,0,0],
|
||||
["192.168.45.10","255.255.255.0"] => [192,168,45,0]
|
||||
}
|
||||
|
||||
tests.each do |k,v|
|
||||
assert_equal v, @action.apply_netmask(*k)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context "splitting an IP" do
|
||||
should "return the proper result" do
|
||||
tests = {
|
||||
"192.168.0.1" => [192,168,0,1]
|
||||
}
|
||||
|
||||
tests.each do |k,v|
|
||||
assert_equal v, @action.split_ip(k)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context "network IP" do
|
||||
should "return the proper result" do
|
||||
tests = {
|
||||
["192.168.0.45", "255.255.255.0"] => "192.168.0.1"
|
||||
}
|
||||
|
||||
tests.each do |args, result|
|
||||
assert_equal result, @action.network_ip(*args)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -30,14 +30,14 @@ class StartActionTest < Test::Unit::TestCase
|
|||
|
||||
should "add customize to the beginning if its not saved" do
|
||||
@vm.expects(:saved?).returns(false)
|
||||
@default_order.unshift([Vagrant::Actions::VM::Customize, Vagrant::Actions::VM::ForwardPorts, Vagrant::Actions::VM::SharedFolders])
|
||||
@default_order.unshift([Vagrant::Actions::VM::Customize, Vagrant::Actions::VM::ForwardPorts, Vagrant::Actions::VM::SharedFolders, Vagrant::Actions::VM::Network])
|
||||
setup_action_expectations
|
||||
@action.prepare
|
||||
end
|
||||
|
||||
should "add do additional if VM is not created yet" do
|
||||
@runner.stubs(:vm).returns(nil)
|
||||
@default_order.unshift([Vagrant::Actions::VM::Customize, Vagrant::Actions::VM::ForwardPorts, Vagrant::Actions::VM::SharedFolders])
|
||||
@default_order.unshift([Vagrant::Actions::VM::Customize, Vagrant::Actions::VM::ForwardPorts, Vagrant::Actions::VM::SharedFolders, Vagrant::Actions::VM::Network])
|
||||
setup_action_expectations
|
||||
@action.prepare
|
||||
end
|
||||
|
@ -46,7 +46,7 @@ class StartActionTest < Test::Unit::TestCase
|
|||
@vm.env.config.vm.provisioner = :chef_solo
|
||||
|
||||
@runner.stubs(:vm).returns(nil)
|
||||
@default_order.unshift([Vagrant::Actions::VM::Customize, Vagrant::Actions::VM::ForwardPorts, Vagrant::Actions::VM::SharedFolders])
|
||||
@default_order.unshift([Vagrant::Actions::VM::Customize, Vagrant::Actions::VM::ForwardPorts, Vagrant::Actions::VM::SharedFolders, Vagrant::Actions::VM::Network])
|
||||
@default_order << Vagrant::Actions::VM::Provision
|
||||
setup_action_expectations
|
||||
@action.prepare
|
||||
|
|
Loading…
Reference in New Issue