diff --git a/lib/vagrant/actions/vm/down.rb b/lib/vagrant/actions/vm/down.rb index 2e9a7be1e..f8de682cf 100644 --- a/lib/vagrant/actions/vm/down.rb +++ b/lib/vagrant/actions/vm/down.rb @@ -6,6 +6,13 @@ module Vagrant @runner.add_action(Halt) if @runner.vm.running? @runner.add_action(Destroy) end + + def after_halt + # This sleep is necessary to wait for the GUI to clean itself up. + # There appears to be nothing in the API that does this "wait" + # for us. + Kernel.sleep(1) if @runner.env.config.vm.boot_mode == "gui" + end end end end diff --git a/lib/vagrant/actions/vm/halt.rb b/lib/vagrant/actions/vm/halt.rb index a05fed612..eec860f40 100644 --- a/lib/vagrant/actions/vm/halt.rb +++ b/lib/vagrant/actions/vm/halt.rb @@ -5,8 +5,10 @@ module Vagrant def execute! raise ActionException.new(:vm_not_running) unless @runner.vm.running? - logger.info "Forcing shutdown of VM..." - @runner.vm.stop + @runner.invoke_around_callback(:halt) do + logger.info "Forcing shutdown of VM..." + @runner.vm.stop + end end end end diff --git a/test/vagrant/actions/vm/down_test.rb b/test/vagrant/actions/vm/down_test.rb index 4966d355b..1795addb9 100644 --- a/test/vagrant/actions/vm/down_test.rb +++ b/test/vagrant/actions/vm/down_test.rb @@ -2,7 +2,7 @@ require File.join(File.dirname(__FILE__), '..', '..', '..', 'test_helper') class DownActionTest < Test::Unit::TestCase setup do - @mock_vm, @vm, @action = mock_action(Vagrant::Actions::VM::Down) + @runner, @vm, @action = mock_action(Vagrant::Actions::VM::Down) end context "preparing" do @@ -13,7 +13,7 @@ class DownActionTest < Test::Unit::TestCase def setup_action_expectations(order) default_seq = sequence("default_seq") order.each do |action| - @mock_vm.expects(:add_action).with(action).once.in_sequence(default_seq) + @runner.expects(:add_action).with(action).once.in_sequence(default_seq) end end @@ -28,4 +28,18 @@ class DownActionTest < Test::Unit::TestCase @action.prepare end end + + context "after halting" do + should "sleep if boot mode is GUI" do + @runner.env.config.vm.boot_mode = "gui" + Kernel.expects(:sleep).once + @action.after_halt + end + + should "not sleep if boot mode is anything else" do + @runner.env.config.vm.boot_mode = "vrdp" + Kernel.expects(:sleep).never + @action.after_halt + end + end end diff --git a/test/vagrant/actions/vm/halt_test.rb b/test/vagrant/actions/vm/halt_test.rb index b08e7ba8b..49470ac44 100644 --- a/test/vagrant/actions/vm/halt_test.rb +++ b/test/vagrant/actions/vm/halt_test.rb @@ -10,6 +10,13 @@ class HaltActionTest < Test::Unit::TestCase @vm.stubs(:running?).returns(true) end + should "invoke the 'halt' around callback" do + halt_seq = sequence("halt_seq") + @runner.expects(:invoke_around_callback).with(:halt).once.in_sequence(halt_seq).yields + @vm.expects(:stop).in_sequence(halt_seq) + @action.execute! + end + should "force the VM to stop" do @vm.expects(:stop).once @action.execute!