diff --git a/lib/vagrant/environment.rb b/lib/vagrant/environment.rb index ad9110db8..c6ecdee13 100644 --- a/lib/vagrant/environment.rb +++ b/lib/vagrant/environment.rb @@ -13,6 +13,7 @@ module Vagrant # access to the VMs, CLI, etc. all in the scope of this environment. class Environment DEFAULT_HOME = "~/.vagrant.d" + DEFAULT_LOCAL_DATA = ".vagrant" DEFAULT_RC = "~/.vagrantrc" # This is the global config, comprised of loading configuration from @@ -34,6 +35,10 @@ module Vagrant # global state. attr_reader :home_path + # The directory to the directory where local, environment-specific + # data is stored. + attr_reader :local_data_path + # The directory where temporary files for Vagrant go. attr_reader :tmp_path @@ -58,10 +63,11 @@ module Vagrant def initialize(opts=nil) opts = { :cwd => nil, - :vagrantfile_name => nil, + :home_path => nil, + :local_data_path => nil, :lock_path => nil, :ui_class => nil, - :home_path => nil + :vagrantfile_name => nil }.merge(opts || {}) # Set the default working directory to look for the vagrantfile @@ -70,6 +76,9 @@ module Vagrant opts[:cwd] = Pathname.new(opts[:cwd]) raise Errors::EnvironmentNonExistentCWD if !opts[:cwd].directory? + # Set the default ui class + opts[:ui_class] ||= UI::Silent + # Set the Vagrantfile name up. We append "Vagrantfile" and "vagrantfile" so that # those continue to work as well, but anything custom will take precedence. opts[:vagrantfile_name] ||= [] @@ -77,15 +86,12 @@ module Vagrant opts[:vagrantfile_name] += ["Vagrantfile", "vagrantfile"] # Set instance variables for all the configuration parameters. - @cwd = opts[:cwd] + @cwd = opts[:cwd] + @home_path = opts[:home_path] + @lock_path = opts[:lock_path] @vagrantfile_name = opts[:vagrantfile_name] - @lock_path = opts[:lock_path] - @home_path = opts[:home_path] + @ui = opts[:ui_class].new("vagrant") - ui_class = opts[:ui_class] || UI::Silent - @ui = ui_class.new("vagrant") - - @loaded = false @lock_acquired = false @logger = Log4r::Logger.new("vagrant::environment") @@ -94,10 +100,22 @@ module Vagrant # Setup the home directory setup_home_path - @tmp_path = @home_path.join("tmp") + @tmp_path = @home_path.join("tmp") @boxes_path = @home_path.join("boxes") @gems_path = @home_path.join("gems") + # Setup the local data directory. If a configuration path is given, + # then it is expanded relative to the working directory. Otherwise, + # we use the default which is expanded relative to the root path. + @local_data_path = nil + if opts[:local_data_path] + @local_data_path = Pathname.new(File.expand_path(opts[:local_data_path], @cwd)) + elsif !root_path.nil? + @local_data_path = root_path.join(DEFAULT_LOCAL_DATA) + end + + setup_local_data_path + # Setup the default private key @default_private_key_path = @home_path.join("insecure_private_key") copy_insecure_private_key @@ -131,15 +149,6 @@ module Vagrant :virtualbox end - # The path to the `dotfile`, which contains the persisted UUID of - # the VM if it exists. - # - # @return [Pathname] - def dotfile_path - return nil if !root_path - root_path.join(config_global.vagrant.dotfile_name) - end - # Returns the collection of boxes for the environment. # # @return [BoxCollection] @@ -315,7 +324,7 @@ module Vagrant # # @return [DataStore] def local_data - @local_data ||= DataStore.new(dotfile_path) + @local_data ||= DataStore.new(@local_data_path.join("environment_data")) end # The root path is the path where the top-most (loaded last) @@ -433,6 +442,25 @@ module Vagrant end end + # This creates the local data directory and show an error if it + # couldn't properly be created. + def setup_local_data_path + if @local_data_path.nil? + @logger.warn("No local data path is set. Local data cannot be stored.") + return + end + + @logger.info("Local data path: #{@local_data_path}") + + begin + @logger.debug("Creating: #{@local_data_path}") + FileUtils.mkdir_p(@local_data_path) + rescue Errno::EACCES + raise Errors::LocalDataDirectoryNotAccessible, + :local_data_path => @local_data_path.to_s + end + end + protected # This method copies the private key into the home directory if it diff --git a/lib/vagrant/errors.rb b/lib/vagrant/errors.rb index 690afa86d..f4961b45e 100644 --- a/lib/vagrant/errors.rb +++ b/lib/vagrant/errors.rb @@ -230,6 +230,10 @@ module Vagrant error_key(:port_collision_resume) end + class LocalDataDirectoryNotAccessible < VagrantError + error_key(:local_data_dir_not_accessible) + end + class MachineGuestNotReady < VagrantError error_key(:machine_guest_not_ready) end diff --git a/templates/locales/en.yml b/templates/locales/en.yml index 8712e41fd..6adf62cf4 100644 --- a/templates/locales/en.yml +++ b/templates/locales/en.yml @@ -85,6 +85,13 @@ en: You specified: %{home_path} interrupted: |- Vagrant exited after cleanup due to external interrupt. + local_data_dir_not_accessible: |- + The directory Vagrant will use to store local environment-specific + state is not accessible. The directory specified as the local data + directory must be both readable and writable for the user that is + running Vagrant. + + Local data directory: %{local_data_path} machine_guest_not_ready: |- Guest-specific operations were attempted on a machine that is not ready for guest communication. This should not happen and a bug diff --git a/test/unit/vagrant/environment_test.rb b/test/unit/vagrant/environment_test.rb index 6ab1e29be..b4e1e4b8a 100644 --- a/test/unit/vagrant/environment_test.rb +++ b/test/unit/vagrant/environment_test.rb @@ -23,19 +23,22 @@ describe Vagrant::Environment do describe "current working directory" do it "is the cwd by default" do - with_temp_env("VAGRANT_CWD" => nil) do - described_class.new.cwd.should == Pathname.new(Dir.pwd) + temp_dir = Tempdir.new.path + Dir.chdir(temp_dir) do + with_temp_env("VAGRANT_CWD" => nil) do + described_class.new.cwd.should == Pathname.new(Dir.pwd) + end end end it "is set to the cwd given" do - directory = File.dirname(__FILE__) + directory = Tempdir.new.path instance = described_class.new(:cwd => directory) instance.cwd.should == Pathname.new(directory) end it "is set to the environmental variable VAGRANT_CWD" do - directory = File.dirname(__FILE__) + directory = Tempdir.new.path instance = with_temp_env("VAGRANT_CWD" => directory) do described_class.new end @@ -72,6 +75,24 @@ describe Vagrant::Environment do end end + describe "local data path" do + it "is set to the proper default" do + default = instance.root_path.join(described_class::DEFAULT_LOCAL_DATA) + instance.local_data_path.should == default + end + + it "is expanded relative to the cwd" do + instance = described_class.new(:local_data_path => "foo") + instance.local_data_path.should == instance.cwd.join("foo") + end + + it "is set to the given value" do + dir = Tempdir.new.path + instance = described_class.new(:local_data_path => dir) + instance.local_data_path.to_s.should == dir + end + end + describe "default provider" do it "should return virtualbox" do instance.default_provider.should == :virtualbox