diff --git a/.gitignore b/.gitignore index 745dd5144..6d0a49403 100644 --- a/.gitignore +++ b/.gitignore @@ -10,5 +10,6 @@ _site/* .yardoc/ doc/ tags +Gemfile.lock .idea/* *.iml \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 09a9220f4..6c19ace27 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,8 @@ - Arbitrary options to puppet binary can be set with `config.puppet.options`. [GH-242] - BSD hosts use proper GNU sed syntax for clearing NFS shares. [GH-243] - Enumerate VMs in a multi-VM environment in order they were defined. [GH-244] + - Check for VM boot changed to use `timeout` library, which works better with Windows. + - Show special error if VirtualBox not detected on 64-bit Windows. ## 0.6.8 (November 30, 2010) diff --git a/Gemfile.lock b/Gemfile.lock deleted file mode 100644 index f1c307c81..000000000 --- a/Gemfile.lock +++ /dev/null @@ -1,76 +0,0 @@ -GIT - remote: git://github.com/mitchellh/virtualbox.git - revision: c79de55b05dd5703fa157e9900efecaaf1da5861 - specs: - virtualbox (0.7.8.dev) - ffi (~> 0.6.3) - -PATH - remote: . - specs: - vagrant (0.6.9.dev) - archive-tar-minitar (= 0.5.2) - erubis (~> 2.6.6) - i18n (~> 0.4.1) - json (~> 1.4.6) - mario (~> 0.0.6) - net-scp (~> 1.0.3) - net-ssh (~> 2.0.23) - thor (~> 0.14.2) - virtualbox (~> 0.7.6) - -GEM - remote: http://rubygems.org/ - specs: - abstract (1.0.0) - archive-tar-minitar (0.5.2) - bluecloth (2.0.9) - columnize (0.3.2) - contest (0.1.2) - erubis (2.6.6) - abstract (>= 1.0.0) - ffi (0.6.3) - rake (>= 0.8.7) - i18n (0.4.2) - json (1.4.6) - linecache (0.43) - linecache19 (0.5.11) - ruby_core_source (>= 0.1.4) - mario (0.0.6) - mocha (0.9.10) - rake - net-scp (1.0.4) - net-ssh (>= 1.99.1) - net-ssh (2.0.23) - rake (0.8.7) - ruby-debug (0.10.4) - columnize (>= 0.1) - ruby-debug-base (~> 0.10.4.0) - ruby-debug-base (0.10.4) - linecache (>= 0.3) - ruby-debug-base19 (0.11.24) - columnize (>= 0.3.1) - linecache19 (>= 0.5.11) - ruby_core_source (>= 0.1.4) - ruby-debug19 (0.11.6) - columnize (>= 0.3.1) - linecache19 (>= 0.5.11) - ruby-debug-base19 (>= 0.11.19) - ruby_core_source (0.1.4) - archive-tar-minitar (>= 0.5.2) - thor (0.14.6) - yard (0.6.3) - -PLATFORMS - ruby - -DEPENDENCIES - bluecloth - contest (>= 0.1.2) - mocha - rake - ruby-debug - ruby-debug19 - vagrant! - virtualbox! - yard (~> 0.6.1) diff --git a/lib/vagrant/environment.rb b/lib/vagrant/environment.rb index f3fe5c6e5..e2b450874 100644 --- a/lib/vagrant/environment.rb +++ b/lib/vagrant/environment.rb @@ -34,6 +34,14 @@ module Vagrant raise Errors::VirtualBoxNotDetected.new if version.nil? raise Errors::VirtualBoxInvalidVersion.new(:version => version.to_s) if version.to_f < 3.2 raise Errors::VirtualBoxInvalidOSE.new(:version => version.to_s) if version.to_s.downcase.include?("ose") + rescue Errors::VirtualBoxNotDetected + # On 64-bit Windows, show a special error. This error is a subclass + # of VirtualBoxNotDetected, so libraries which use Vagrant can just + # rescue VirtualBoxNotDetected. + raise Errors::VirtualBoxNotDetected_Win64 if Util::Platform.windows? && Util::Platform.bit64? + + # Otherwise, reraise the old error + raise end end diff --git a/lib/vagrant/errors.rb b/lib/vagrant/errors.rb index 3eac27f54..cf1447ef0 100644 --- a/lib/vagrant/errors.rb +++ b/lib/vagrant/errors.rb @@ -283,6 +283,15 @@ module Vagrant error_key(:virtualbox_not_detected) end + # Note that this is a subclass of VirtualBoxNotDetected, so developers + # who script Vagrant or use it as a library in any way can rescue from + # "VirtualBoxNotDetected" and catch both errors, which represent the + # same thing. This subclass simply has a specialized error message. + class VirtualBoxNotDetected_Win64 < VirtualBoxNotDetected + status_code(48) + error_key(:virtualbox_not_detected_win64) + end + class VMBaseMacNotSpecified < VagrantError status_code(47) error_key(:no_base_mac, "vagrant.actions.vm.match_mac") diff --git a/lib/vagrant/ssh.rb b/lib/vagrant/ssh.rb index 987d20e3d..472dc5a8e 100644 --- a/lib/vagrant/ssh.rb +++ b/lib/vagrant/ssh.rb @@ -1,3 +1,4 @@ +require 'timeout' require 'net/ssh' require 'net/scp' require 'mario' @@ -60,12 +61,12 @@ module Vagrant # Merge in any additional options opts = opts.dup opts[:forward_agent] = true if env.config.ssh.forward_agent + opts[:port] ||= port retryable(:tries => 5, :on => Errno::ECONNREFUSED) do Net::SSH.start(env.config.ssh.host, env.config.ssh.username, - opts.merge( :port => port, - :keys => [env.config.ssh.private_key_path], + opts.merge( :keys => [env.config.ssh.private_key_path], :user_known_hosts_file => [], :paranoid => false, :config => false)) do |ssh| @@ -92,21 +93,22 @@ module Vagrant # # @return [Boolean] def up? - check_thread = Thread.new do - begin - Thread.current[:result] = false - execute(:timeout => env.config.ssh.timeout) do |ssh| - Thread.current[:result] = true - end - rescue Errno::ECONNREFUSED, Net::SSH::Disconnect, Errors::SSHConnectionRefused - # False, its defaulted above - end + # We have to determine the port outside of the block since it uses + # API calls which can only be used from the main thread in JRuby on + # Windows + ssh_port = port + + Timeout.timeout(env.config.ssh.timeout) do + execute(:timeout => env.config.ssh.timeout, + :port => ssh_port) { |ssh| } end - check_thread.join(env.config.ssh.timeout) - return check_thread[:result] + true rescue Net::SSH::AuthenticationFailed raise Errors::SSHAuthenticationFailed.new + rescue Timeout::Error, Errno::ECONNREFUSED, Net::SSH::Disconnect, + Errors::SSHConnectionRefused, Net::SSH::AuthenticationFailed + return false end # Checks the file permissions for the private key, resetting them diff --git a/lib/vagrant/util/platform.rb b/lib/vagrant/util/platform.rb index 903136f02..b86b4b56c 100644 --- a/lib/vagrant/util/platform.rb +++ b/lib/vagrant/util/platform.rb @@ -1,3 +1,4 @@ +require 'rbconfig' require 'mario' module Vagrant @@ -27,13 +28,29 @@ module Vagrant false end + # Returns boolean noting whether this is a 64-bit CPU. This + # is not 100% accurate and there could easily be false negatives. + # + # @return [Boolean] + def bit64? + ["x86_64", "amd64"].include?(RbConfig::CONFIG["host_cpu"]) + end + + # Returns boolean noting whether this is a 32-bit CPU. This + # can easily throw false positives since it relies on {#bit64?}. + # + # @return [Boolean] + def bit32? + !bit64? + end + def tar_file_options # create, write only, fail if the file exists, binary if windows File::WRONLY|File::EXCL|File::CREAT|(Mario::Platform.windows? ? File::BINARY : 0) end def platform - RUBY_PLATFORM.to_s.downcase + RbConfig::CONFIG["host_os"].downcase end end end diff --git a/templates/locales/en.yml b/templates/locales/en.yml index 9f9749bf5..e7a08560d 100644 --- a/templates/locales/en.yml +++ b/templates/locales/en.yml @@ -14,7 +14,7 @@ en: the VM and is required for chef provisioning. Please verify that chef is installed and that the binary is available on the PATH. puppet_not_detected: |- - The `puppet` binary was not found on the VM and is required for Puppet provisioning. + The `puppet` binary was not found on the VM and is required for Puppet provisioning. Please verify that Puppet is installed and that the binary is available on the PATH. cli_missing_env: This command requires that a Vagrant environment be properly passed in as the last parameter. config_validation: |- @@ -70,7 +70,7 @@ en: For a more detailed guide please consult: - http://vagrantup.com/docs/getting-started/windows. + http://vagrantup.com/docs/getting-started/windows system: invalid_class: |- @@ -102,6 +102,18 @@ en: Vagrant could not detect VirtualBox! Make sure VirtualBox is properly installed. If VirtualBox is installed, it may be an incorrect version. Vagrant currently requires VirtualBox 3.2.x. Please install the proper version to continue. + virtualbox_not_detected_win64: |- + Vagrant could not detect VirtualBox! Make sure VirtualBox is properly installed + with version 3.2.0 or higher. + + Additionally, it appears you're on 64-bit Windows. If this is the case, and + VirtualBox is properly installed with the correct version, then please make + sure you're running Vagrant via JRuby on a 64-bit Java runtime. For more + information on how to set this up and how to verify it is properly setup, + please view the guide online at: + + http://vagrantup.com/docs/getting-started/setup/windows_x64.html + vm_creation_required: "VM must be created before running this command. Run `vagrant up` first." vm_not_found: "A VM by the name of %{name} was not found." vm_not_running: "VM must be running to open SSH connection." diff --git a/test/vagrant/ssh_test.rb b/test/vagrant/ssh_test.rb index 6aa970dd0..f63c38788 100644 --- a/test/vagrant/ssh_test.rb +++ b/test/vagrant/ssh_test.rb @@ -195,16 +195,15 @@ class SshTest < Test::Unit::TestCase end should "return false if SSH connection times out" do - Net::SSH.expects(:start) - assert !@ssh.up? - end + @env.config.ssh.timeout = 0.5 - should "allow the thread the configured timeout time" do - @thread = mock("thread") - @thread.stubs(:[]) - Thread.expects(:new).returns(@thread) - @thread.expects(:join).with(@env.config.ssh.timeout).once - @ssh.up? + Net::SSH.stubs(:start).with() do + # Sleep here to artificially fake timeout + sleep 1 + true + end + + assert !@ssh.up? end should "return false if the connection is refused" do @@ -222,7 +221,11 @@ class SshTest < Test::Unit::TestCase end should "specifity the timeout as an option to execute" do - @ssh.expects(:execute).with(:timeout => @env.config.ssh.timeout).yields(true) + @ssh.expects(:execute).yields(true).with() do |opts| + assert_equal @env.config.ssh.timeout, opts[:timeout] + true + end + assert @ssh.up? end @@ -230,6 +233,11 @@ class SshTest < Test::Unit::TestCase @ssh.expects(:execute).raises(Net::SSH::AuthenticationFailed) assert_raises(Vagrant::Errors::SSHAuthenticationFailed) { @ssh.up? } end + + should "only get the port once (in the main thread)" do + @ssh.expects(:port).once.returns(2222) + @ssh.up? + end end context "getting the ssh port" do