diff --git a/lib/vagrant/action/builtin.rb b/lib/vagrant/action/builtin.rb index bd8c93771..ea4387155 100644 --- a/lib/vagrant/action/builtin.rb +++ b/lib/vagrant/action/builtin.rb @@ -18,6 +18,7 @@ module Vagrant use VM::Customize use VM::ClearForwardedPorts use VM::ForwardPorts + use VM::NFS use VM::Provision use VM::ClearSharedFolders use VM::ShareFolders diff --git a/lib/vagrant/action/vm/nfs.rb b/lib/vagrant/action/vm/nfs.rb index 4f3a0b744..af80e3785 100644 --- a/lib/vagrant/action/vm/nfs.rb +++ b/lib/vagrant/action/vm/nfs.rb @@ -20,7 +20,7 @@ module Vagrant @app = app @env = env - verify_host + verify_settings end def call(env) @@ -62,6 +62,8 @@ module Vagrant # involves adding a line to `/etc/exports` for this VM, but it is # up to the host class to define the specific behavior. def export_folders + @env.logger.info "Exporting NFS shared folders..." + catch_action_exception(@env) do @env["host"].nfs_export(folders) end @@ -69,12 +71,30 @@ module Vagrant # Uses the system class to mount the NFS folders. def mount_folders + @env.logger.info "Mounting NFS shared folders..." + + catch_action_exception(@env) do + @env["vm"].system.mount_nfs(host_ip, folders) + end + end + + # Returns the IP address of the first host only network adapter + # + # @return [String] + def host_ip + interface = @env["vm"].vm.network_adapters.find do |adapter| + adapter.host_interface_object + end + + return nil if !interface + interface.host_interface_object.ip_address end # Verifies that the host is set and supports NFS. - def verify_host + def verify_settings return @env.error!(:nfs_host_required) if @env["host"].nil? return @env.error!(:nfs_not_supported) if !@env["host"].nfs? + return @env.error!(:nfs_no_host_network) if @env["config"].vm.network_options.empty? end end end diff --git a/lib/vagrant/hosts/bsd.rb b/lib/vagrant/hosts/bsd.rb index 9aa02dd62..5e5260bd1 100644 --- a/lib/vagrant/hosts/bsd.rb +++ b/lib/vagrant/hosts/bsd.rb @@ -2,6 +2,10 @@ module Vagrant module Hosts # Represents a BSD host, such as FreeBSD and Darwin (Mac OS X). class BSD < Base + def nfs? + # TODO: verify it exists + true + end end end end diff --git a/lib/vagrant/systems/base.rb b/lib/vagrant/systems/base.rb index 31824c357..113a58a50 100644 --- a/lib/vagrant/systems/base.rb +++ b/lib/vagrant/systems/base.rb @@ -55,6 +55,10 @@ module Vagrant # wants the folder mounted. def mount_shared_folder(ssh, name, guestpath); end + # Mounts a shared folder via NFS. This assumes that the exports + # via the host are already done. + def mount_nfs(ip, folders); end + # Prepares the system for unison folder syncing. This is called # once once prior to any `create_unison` calls. def prepare_unison(ssh); end diff --git a/templates/strings.yml b/templates/strings.yml index 72457406b..3aceb62c0 100644 --- a/templates/strings.yml +++ b/templates/strings.yml @@ -145,6 +145,9 @@ The host class is reporting that NFS is not supported by this host, or `nfsd` may not be installed. Please verify that `nfsd` is installed on your machine, and retry. +:nfs_no_host_network: |- + NFS shared folders requires that host only networking is enabled. + Please enable host only networking via `config.vm.network`. :network_not_found: |- The specified host network could not be found: <%= name %>. If the name specification is removed, Vagrant will create a new diff --git a/test/vagrant/action/vm/nfs_test.rb b/test/vagrant/action/vm/nfs_test.rb index a37933f10..41a76901c 100644 --- a/test/vagrant/action/vm/nfs_test.rb +++ b/test/vagrant/action/vm/nfs_test.rb @@ -6,7 +6,9 @@ class NFSVMActionTest < Test::Unit::TestCase @app, @env = mock_action_data @vm = mock("vm") + @vm.stubs(:system).returns(mock("system")) @env.env.stubs(:host).returns(Vagrant::Hosts::Base.new(@env)) + @env.env.config.vm.network("192.168.55.1") @env["vm"] = @vm @internal_vm = mock("internal") @@ -16,8 +18,8 @@ class NFSVMActionTest < Test::Unit::TestCase context "with an instance" do setup do # Kind of dirty but not sure of a way around this - @klass.send(:alias_method, :verify_host_real, :verify_host) - @klass.any_instance.stubs(:verify_host) + @klass.send(:alias_method, :verify_settings_real, :verify_settings) + @klass.any_instance.stubs(:verify_settings) @instance = @klass.new(@app, @env) end @@ -109,24 +111,75 @@ class NFSVMActionTest < Test::Unit::TestCase end end - context "verifying host" do + context "mounting folders" do + setup do + @instance.stubs(:host_ip).returns("foo") + @instance.stubs(:folders).returns(["bar"]) + end + + should "mount the folders on the system" do + @vm.system.expects(:mount_nfs).with(@instance.host_ip, @instance.folders) + @instance.mount_folders + end + end + + context "getting the host IP" do + setup do + @network_adapters = [] + @internal_vm.stubs(:network_adapters).returns(@network_adapters) + end + + def stub_interface(ip) + interface = mock("interface") + adapter = mock("adapter") + adapter.stubs(:host_interface_object).returns(interface) + interface.stubs(:ip_address).returns(ip) + + @network_adapters << adapter + interface + end + + should "return the IP of the first interface" do + ip = "192.168.1.1" + stub_interface(ip) + + assert_equal ip, @instance.host_ip + end + + should "return nil if no IP is found" do + assert_nil @instance.host_ip + end + end + + context "verifying settings" do + setup do + @env.env.host.stubs(:nfs?).returns(true) + end + should "error environment if host is nil" do @env.env.stubs(:host).returns(nil) - @instance.verify_host_real + @instance.verify_settings_real assert @env.error? assert_equal :nfs_host_required, @env.error.first end should "error environment if host does not support NFS" do @env.env.host.stubs(:nfs?).returns(false) - @instance.verify_host_real + @instance.verify_settings_real assert @env.error? assert_equal :nfs_not_supported, @env.error.first end + should "error environment if host only networking is not enabled" do + @env.env.config.vm.network_options.clear + @instance.verify_settings_real + assert @env.error? + assert_equal :nfs_no_host_network, @env.error.first + end + should "be fine if everything passes" do @env.env.host.stubs(:nfs?).returns(true) - @instance.verify_host_real + @instance.verify_settings_real assert !@env.error? end end diff --git a/vagrant.gemspec b/vagrant.gemspec index 27ba07434..509354404 100644 --- a/vagrant.gemspec +++ b/vagrant.gemspec @@ -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.authors = ["Mitchell Hashimoto", "John Bender"] - s.date = %q{2010-07-09} + s.date = %q{2010-07-11} s.default_executable = %q{vagrant} 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"] @@ -58,6 +58,7 @@ Gem::Specification.new do |s| "lib/vagrant/action/vm/import.rb", "lib/vagrant/action/vm/match_mac_address.rb", "lib/vagrant/action/vm/network.rb", + "lib/vagrant/action/vm/nfs.rb", "lib/vagrant/action/vm/package.rb", "lib/vagrant/action/vm/persist.rb", "lib/vagrant/action/vm/provision.rb", @@ -90,6 +91,8 @@ Gem::Specification.new do |s| "lib/vagrant/downloaders/file.rb", "lib/vagrant/downloaders/http.rb", "lib/vagrant/environment.rb", + "lib/vagrant/hosts/base.rb", + "lib/vagrant/hosts/bsd.rb", "lib/vagrant/provisioners/base.rb", "lib/vagrant/provisioners/chef.rb", "lib/vagrant/provisioners/chef_server.rb", @@ -140,6 +143,7 @@ Gem::Specification.new do |s| "test/vagrant/action/vm/import_test.rb", "test/vagrant/action/vm/match_mac_address_test.rb", "test/vagrant/action/vm/network_test.rb", + "test/vagrant/action/vm/nfs_test.rb", "test/vagrant/action/vm/package_test.rb", "test/vagrant/action/vm/persist_test.rb", "test/vagrant/action/vm/provision_test.rb", @@ -172,6 +176,7 @@ Gem::Specification.new do |s| "test/vagrant/downloaders/file_test.rb", "test/vagrant/downloaders/http_test.rb", "test/vagrant/environment_test.rb", + "test/vagrant/hosts/base_test.rb", "test/vagrant/provisioners/base_test.rb", "test/vagrant/provisioners/chef_server_test.rb", "test/vagrant/provisioners/chef_solo_test.rb", @@ -220,6 +225,7 @@ Gem::Specification.new do |s| "test/vagrant/action/vm/import_test.rb", "test/vagrant/action/vm/match_mac_address_test.rb", "test/vagrant/action/vm/network_test.rb", + "test/vagrant/action/vm/nfs_test.rb", "test/vagrant/action/vm/package_test.rb", "test/vagrant/action/vm/persist_test.rb", "test/vagrant/action/vm/provision_test.rb", @@ -252,6 +258,7 @@ Gem::Specification.new do |s| "test/vagrant/downloaders/file_test.rb", "test/vagrant/downloaders/http_test.rb", "test/vagrant/environment_test.rb", + "test/vagrant/hosts/base_test.rb", "test/vagrant/provisioners/base_test.rb", "test/vagrant/provisioners/chef_server_test.rb", "test/vagrant/provisioners/chef_solo_test.rb",