From 42883cbd20d4df6cd795c1ee06da493e0e7d599b Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Sat, 31 Dec 2011 11:27:37 -0800 Subject: [PATCH] Bridged networking basics. --- lib/vagrant/action.rb | 1 + lib/vagrant/action/builtin.rb | 1 + lib/vagrant/action/vm/bridged_network.rb | 98 ++++++++++++++++++++++ lib/vagrant/action/vm/host_only_network.rb | 6 +- lib/vagrant/driver/virtualbox.rb | 5 ++ lib/vagrant/errors.rb | 4 +- templates/locales/en.yml | 9 +- 7 files changed, 118 insertions(+), 6 deletions(-) create mode 100644 lib/vagrant/action/vm/bridged_network.rb diff --git a/lib/vagrant/action.rb b/lib/vagrant/action.rb index 0cb7a664b..8c62ddc33 100644 --- a/lib/vagrant/action.rb +++ b/lib/vagrant/action.rb @@ -26,6 +26,7 @@ module Vagrant module VM autoload :Boot, 'vagrant/action/vm/boot' + autoload :BridgedNetwork, 'vagrant/action/vm/bridged_network' autoload :CheckAccessible, 'vagrant/action/vm/check_accessible' autoload :CheckBox, 'vagrant/action/vm/check_box' autoload :CheckGuestAdditions, 'vagrant/action/vm/check_guest_additions' diff --git a/lib/vagrant/action/builtin.rb b/lib/vagrant/action/builtin.rb index 1aa98a8f8..de3ebff00 100644 --- a/lib/vagrant/action/builtin.rb +++ b/lib/vagrant/action/builtin.rb @@ -29,6 +29,7 @@ module Vagrant use VM::ClearSharedFolders use VM::ShareFolders use VM::HostName + use VM::BridgedNetwork use VM::HostOnlyNetwork use VM::Customize use VM::Boot diff --git a/lib/vagrant/action/vm/bridged_network.rb b/lib/vagrant/action/vm/bridged_network.rb new file mode 100644 index 000000000..1a1a7b9c5 --- /dev/null +++ b/lib/vagrant/action/vm/bridged_network.rb @@ -0,0 +1,98 @@ +require 'log4r' + +module Vagrant + module Action + module VM + # This action sets up any bridged networking for the virtual + # machine. + class BridgedNetwork + def initialize(app, env) + @logger = Log4r::Logger.new("vagrant::action::vm::bridged_network") + + @app = app + end + + def call(env) + @env = env + + networks = bridged_networks + @logger.debug("Must configure #{networks.length} bridged networks") + + if !networks.empty? + # Determine what bridged interface to connect to for each + # network. This returns the same array with the `bridge` + # key available with the interface. + networks = determine_bridged_interface(networks) + + # Status output + env[:ui].info I18n.t("vagrant.actions.vm.bridged_networking.preparing") + networks.each do |options| + env[:ui].info I18n.t("vagrant.actions.vm.bridged_networking.bridging", + :adapter => options[:adapter], + :bridge => options[:bridge]) + end + + # Setup the network interfaces on the VM if we need to + setup_network_interfaces(networks) + end + + @app.call(env) + + if !networks.empty? + @env[:ui].info I18n.t("vagrant.actions.vm.bridged_networking.enabling") + + # Prepare for new networks + + # Enable the networks + end + end + + def bridged_networks + results = [] + @env[:vm].config.vm.networks.each do |type, args| + if type == :bridged + options = args[0] || {} + + results << { :adapter => 2 }.merge(options) + end + end + + results + end + + def determine_bridged_interface(networks) + bridgedifs = @env[:vm].driver.read_bridged_interfaces + + results = [] + networks.each do |network| + # TODO: Allow choosing the bridged interface. For now, we just use the + # first one blindly. + options = network.dup + options[:bridge] = bridgedifs[0][:name] + @logger.info("Bridging #{options[:adapter]} => #{options[:bridge]}") + + results << options + end + + results + end + + def setup_network_interfaces(networks) + adapters = [] + + networks.each do |options| + adapters << { + :adapter => options[:adapter] + 1, + :type => :bridged, + :bridge => options[:bridge] + } + end + + # Enable the adapters + @logger.info("Enabling bridged networking adapters") + @env[:vm].driver.enable_adapters(adapters) + end + end + end + end +end diff --git a/lib/vagrant/action/vm/host_only_network.rb b/lib/vagrant/action/vm/host_only_network.rb index d24e75d76..329a99477 100644 --- a/lib/vagrant/action/vm/host_only_network.rb +++ b/lib/vagrant/action/vm/host_only_network.rb @@ -7,7 +7,7 @@ module Vagrant # networking on VMs if configured as such. class HostOnlyNetwork def initialize(app, env) - @logger = Log4r::Logger.new("vagrant::action::vm::network") + @logger = Log4r::Logger.new("vagrant::action::vm::hostonly_network") @app = app end @@ -31,7 +31,7 @@ module Vagrant # Enable the network interfaces if !networks.empty? - @env[:ui].info I18n.t("vagrant.actions.vm.network.enabling") + @env[:ui].info I18n.t("vagrant.actions.vm.host_only_network.enabling") # Prepare for new networks... networks.each do |network_options| @@ -79,7 +79,7 @@ module Vagrant # Enables and assigns the host only network to the proper # adapter on the VM, and saves the adapter. def assign_network(networks) - @env[:ui].info I18n.t("vagrant.actions.vm.network.preparing") + @env[:ui].info I18n.t("vagrant.actions.vm.host_only_network.preparing") host_only_interfaces = @env[:vm].driver.read_host_only_interfaces adapters = [] diff --git a/lib/vagrant/driver/virtualbox.rb b/lib/vagrant/driver/virtualbox.rb index 930ad3046..d38be92b9 100644 --- a/lib/vagrant/driver/virtualbox.rb +++ b/lib/vagrant/driver/virtualbox.rb @@ -122,6 +122,11 @@ module Vagrant adapters.each do |adapter| args.concat(["--nic#{adapter[:adapter]}", adapter[:type].to_s]) + if adapter[:bridge] + args.concat(["--bridgeadapter#{adapter[:adapter]}", + adapter[:bridge]]) + end + if adapter[:hostonly] args.concat(["--hostonlyadapter#{adapter[:adapter]}", adapter[:hostonly]]) diff --git a/lib/vagrant/errors.rb b/lib/vagrant/errors.rb index 43ddddc9e..bcee636b4 100644 --- a/lib/vagrant/errors.rb +++ b/lib/vagrant/errors.rb @@ -205,12 +205,12 @@ module Vagrant class NetworkCollision < VagrantError status_code(29) - error_key(:collides, "vagrant.actions.vm.network") + error_key(:collides, "vagrant.actions.vm.host_only_network") end class NetworkNotFound < VagrantError status_code(30) - error_key(:not_found, "vagrant.actions.vm.network") + error_key(:not_found, "vagrant.actions.vm.host_only_network") end class NFSHostRequired < VagrantError diff --git a/templates/locales/en.yml b/templates/locales/en.yml index a18478971..de714feca 100644 --- a/templates/locales/en.yml +++ b/templates/locales/en.yml @@ -280,6 +280,13 @@ en: failed_to_boot: |- Failed to connect to VM via SSH. Please verify the VM successfully booted by looking at the VirtualBox GUI. + bridged_networking: + bridging: |- + Bridging adapter #%{adapter} to '%{bridge}' + enabling: |- + Enabling bridged network... + preparing: |- + Preparing bridged networking... check_box: not_found: Box %{name} was not found. Fetching box from specified URL... not_specified: |- @@ -383,7 +390,7 @@ en: to work properly (and hence port forwarding, SSH, etc.). Specifying this MAC address is typically up to the box and box maintiner. Please contact the relevant person to solve this issue. - network: + host_only_network: collides: |- The specified host network collides with a non-hostonly network! This will cause your specified IP to be inaccessible. Please change