From bbb1b70e1d1d7f747b820b4425e3aa428ef3a026 Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Sun, 25 Apr 2010 16:42:12 -0700 Subject: [PATCH] Forceful halting with `vagrant halt --force` (or -f for short) --- lib/vagrant/actions/runner.rb | 1 - lib/vagrant/actions/vm/halt.rb | 9 ++++++++- lib/vagrant/commands/halt.rb | 11 ++++++++++- test/vagrant/actions/vm/halt_test.rb | 6 ++++++ test/vagrant/commands/halt_test.rb | 9 ++++++++- 5 files changed, 32 insertions(+), 4 deletions(-) diff --git a/lib/vagrant/actions/runner.rb b/lib/vagrant/actions/runner.rb index 3340bba66..22a29e42f 100644 --- a/lib/vagrant/actions/runner.rb +++ b/lib/vagrant/actions/runner.rb @@ -69,7 +69,6 @@ module Vagrant # to execute a single action on an instance. The syntax for executing a # single method on an instance is the same as the {execute!} class method. def execute!(single_action=nil, *args) - if single_action actions.clear add_action(single_action, *args) diff --git a/lib/vagrant/actions/vm/halt.rb b/lib/vagrant/actions/vm/halt.rb index f5d241481..bf8a46ef2 100644 --- a/lib/vagrant/actions/vm/halt.rb +++ b/lib/vagrant/actions/vm/halt.rb @@ -2,11 +2,18 @@ module Vagrant module Actions module VM class Halt < Base + attr_reader :force + + def initialize(vm, force=nil) + super + @force = force + end + def execute! raise ActionException.new(:vm_not_running) unless @runner.vm.running? @runner.invoke_around_callback(:halt) do - @runner.system.halt + @runner.system.halt if !force if @runner.vm.state(true) != :powered_off logger.info "Forcing shutdown of VM..." diff --git a/lib/vagrant/commands/halt.rb b/lib/vagrant/commands/halt.rb index 181de57b1..4572aa2b8 100644 --- a/lib/vagrant/commands/halt.rb +++ b/lib/vagrant/commands/halt.rb @@ -11,12 +11,21 @@ module Vagrant description "Halts the currently running vagrant environment" def execute(args=[]) + parse_options(args) + env.require_persisted_vm - env.vm.execute!(Actions::VM::Halt) + env.vm.execute!(Actions::VM::Halt, options[:force]) end def options_spec(opts) opts.banner = "Usage: vagrant halt" + + # Defaults + options[:force] = false + + opts.on("-f", "--force", "Forceful shutdown of virtual machine.") do |v| + options[:force] = true + end end end end diff --git a/test/vagrant/actions/vm/halt_test.rb b/test/vagrant/actions/vm/halt_test.rb index a96003713..eb814e776 100644 --- a/test/vagrant/actions/vm/halt_test.rb +++ b/test/vagrant/actions/vm/halt_test.rb @@ -36,6 +36,12 @@ class HaltActionTest < Test::Unit::TestCase @action.execute! end + should "not call halt on the system if forcing" do + @action.stubs(:force).returns(true) + @runner.system.expects(:halt).never + @action.execute! + end + should "raise an ActionException if VM is not running" do @vm.stubs(:running?).returns(false) @vm.expects(:stop).never diff --git a/test/vagrant/commands/halt_test.rb b/test/vagrant/commands/halt_test.rb index 291abf257..5b97f2273 100644 --- a/test/vagrant/commands/halt_test.rb +++ b/test/vagrant/commands/halt_test.rb @@ -21,8 +21,15 @@ class CommandsHaltTest < Test::Unit::TestCase end should "call the `halt` action on the VM" do - @persisted_vm.expects(:execute!).with(Vagrant::Actions::VM::Halt).once + @persisted_vm.expects(:execute!).with(Vagrant::Actions::VM::Halt, false).once @instance.execute end + + should "be forceful if -f flag is sent" do + %w{--force -f}.each do |flag| + @persisted_vm.expects(:execute!).with(Vagrant::Actions::VM::Halt, true).once + @instance.execute([flag]) + end + end end end