`vagrant halt` now attempts to gracefully shut down the machine (via System#halt)
This commit is contained in:
parent
0736f8582d
commit
d5866a1b54
|
@ -6,8 +6,12 @@ module Vagrant
|
||||||
raise ActionException.new(:vm_not_running) unless @runner.vm.running?
|
raise ActionException.new(:vm_not_running) unless @runner.vm.running?
|
||||||
|
|
||||||
@runner.invoke_around_callback(:halt) do
|
@runner.invoke_around_callback(:halt) do
|
||||||
logger.info "Forcing shutdown of VM..."
|
@runner.system.halt
|
||||||
@runner.vm.stop
|
|
||||||
|
if @runner.vm.state(true) != :powered_off
|
||||||
|
logger.info "Forcing shutdown of VM..."
|
||||||
|
@runner.vm.stop
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -27,6 +27,15 @@ module Vagrant
|
||||||
@vm = vm
|
@vm = vm
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Halt the machine. This method should gracefully shut down the
|
||||||
|
# operating system. This method will cause `vagrant halt` and associated
|
||||||
|
# commands to _block_, meaning that if the machine doesn't halt
|
||||||
|
# in a reasonable amount of time, this method should just return.
|
||||||
|
#
|
||||||
|
# If when this method returns, the machine's state isn't "powered_off,"
|
||||||
|
# Vagrant will proceed to forcefully shut the machine down.
|
||||||
|
def halt; end
|
||||||
|
|
||||||
# Mounts a shared folder. This method is called by the shared
|
# Mounts a shared folder. This method is called by the shared
|
||||||
# folder action with an open SSH session (passed in as `ssh`).
|
# folder action with an open SSH session (passed in as `ssh`).
|
||||||
# This method should create, mount, and properly set permissions
|
# This method should create, mount, and properly set permissions
|
||||||
|
|
|
@ -11,6 +11,24 @@ module Vagrant
|
||||||
#-------------------------------------------------------------------
|
#-------------------------------------------------------------------
|
||||||
# Overridden methods
|
# Overridden methods
|
||||||
#-------------------------------------------------------------------
|
#-------------------------------------------------------------------
|
||||||
|
def halt
|
||||||
|
logger.info "Attempting graceful shutdown of linux..."
|
||||||
|
vm.env.ssh.execute do |ssh|
|
||||||
|
ssh.exec!("sudo halt")
|
||||||
|
end
|
||||||
|
|
||||||
|
# Wait until the VM's state is actually powered off. If this doesn't
|
||||||
|
# occur within a reasonable amount of time (15 seconds by default),
|
||||||
|
# then simply return and allow Vagrant to kill the machine.
|
||||||
|
count = 0
|
||||||
|
while vm.vm.state(true) != :powered_off
|
||||||
|
count += 1
|
||||||
|
|
||||||
|
return if count >= 15
|
||||||
|
sleep 1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def mount_shared_folder(ssh, name, guestpath)
|
def mount_shared_folder(ssh, name, guestpath)
|
||||||
ssh.exec!("sudo mkdir -p #{guestpath}")
|
ssh.exec!("sudo mkdir -p #{guestpath}")
|
||||||
mount_folder(ssh, name, guestpath)
|
mount_folder(ssh, name, guestpath)
|
||||||
|
|
|
@ -87,9 +87,16 @@ class Test::Unit::TestCase
|
||||||
mock_vm.stubs(:actions).returns([action])
|
mock_vm.stubs(:actions).returns([action])
|
||||||
mock_vm.stubs(:env).returns(mock_environment)
|
mock_vm.stubs(:env).returns(mock_environment)
|
||||||
|
|
||||||
|
vm.stubs(:env).returns(mock_vm.env)
|
||||||
|
|
||||||
[mock_vm, vm, action]
|
[mock_vm, vm, action]
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Returns a linux system
|
||||||
|
def linux_system(vm)
|
||||||
|
Vagrant::Systems::Linux.new(vm)
|
||||||
|
end
|
||||||
|
|
||||||
def stub_default_action_dependecies(mock)
|
def stub_default_action_dependecies(mock)
|
||||||
mock.stubs(:precedes).returns([])
|
mock.stubs(:precedes).returns([])
|
||||||
mock.stubs(:follows).returns([])
|
mock.stubs(:follows).returns([])
|
||||||
|
|
|
@ -3,21 +3,35 @@ require File.join(File.dirname(__FILE__), '..', '..', '..', 'test_helper')
|
||||||
class HaltActionTest < Test::Unit::TestCase
|
class HaltActionTest < Test::Unit::TestCase
|
||||||
setup do
|
setup do
|
||||||
@runner, @vm, @action = mock_action(Vagrant::Actions::VM::Halt)
|
@runner, @vm, @action = mock_action(Vagrant::Actions::VM::Halt)
|
||||||
|
@runner.stubs(:system).returns(linux_system(@vm))
|
||||||
end
|
end
|
||||||
|
|
||||||
context "executing" do
|
context "executing" do
|
||||||
setup do
|
setup do
|
||||||
@vm.stubs(:running?).returns(true)
|
@vm.stubs(:running?).returns(true)
|
||||||
|
|
||||||
|
@runner.system.stubs(:halt)
|
||||||
|
@vm.stubs(:stop)
|
||||||
|
@vm.stubs(:state).returns(:powered_off)
|
||||||
end
|
end
|
||||||
|
|
||||||
should "invoke the 'halt' around callback" do
|
should "invoke the 'halt' around callback" do
|
||||||
halt_seq = sequence("halt_seq")
|
@runner.expects(:invoke_around_callback).with(:halt).once
|
||||||
@runner.expects(:invoke_around_callback).with(:halt).once.in_sequence(halt_seq).yields
|
|
||||||
@vm.expects(:stop).in_sequence(halt_seq)
|
|
||||||
@action.execute!
|
@action.execute!
|
||||||
end
|
end
|
||||||
|
|
||||||
should "force the VM to stop" do
|
should "halt with the system and NOT force VM to stop if powered off" do
|
||||||
|
@vm.expects(:state).with(true).returns(:powered_off)
|
||||||
|
|
||||||
|
@runner.system.expects(:halt).once
|
||||||
|
@vm.expects(:stop).never
|
||||||
|
@action.execute!
|
||||||
|
end
|
||||||
|
|
||||||
|
should "halt with the system and force VM to stop if NOT powered off" do
|
||||||
|
@vm.expects(:state).with(true).returns(:running)
|
||||||
|
|
||||||
|
@runner.system.expects(:halt).once
|
||||||
@vm.expects(:stop).once
|
@vm.expects(:stop).once
|
||||||
@action.execute!
|
@action.execute!
|
||||||
end
|
end
|
||||||
|
|
|
@ -3,7 +3,7 @@ require File.join(File.dirname(__FILE__), '..', '..', '..', 'test_helper')
|
||||||
class SharedFoldersActionTest < Test::Unit::TestCase
|
class SharedFoldersActionTest < Test::Unit::TestCase
|
||||||
setup do
|
setup do
|
||||||
@runner, @vm, @action = mock_action(Vagrant::Actions::VM::SharedFolders)
|
@runner, @vm, @action = mock_action(Vagrant::Actions::VM::SharedFolders)
|
||||||
@runner.stubs(:system).returns(Vagrant::Systems::Linux.new(@vm))
|
@runner.stubs(:system).returns(linux_system(@vm))
|
||||||
end
|
end
|
||||||
|
|
||||||
def stub_shared_folders
|
def stub_shared_folders
|
||||||
|
|
|
@ -9,6 +9,26 @@ class LinuxSystemTest < Test::Unit::TestCase
|
||||||
@instance = @klass.new(@vm)
|
@instance = @klass.new(@vm)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
context "halting" do
|
||||||
|
setup do
|
||||||
|
@ssh_session = mock("ssh_session")
|
||||||
|
@ssh = mock("ssh")
|
||||||
|
@ssh.stubs(:execute).yields(@ssh_session)
|
||||||
|
@vm.env.stubs(:ssh).returns(@ssh)
|
||||||
|
|
||||||
|
@real_vm = mock("real_vm")
|
||||||
|
@real_vm.stubs(:state).returns(:powered_off)
|
||||||
|
@vm.stubs(:vm).returns(@real_vm)
|
||||||
|
end
|
||||||
|
|
||||||
|
should "execute halt via SSH" do
|
||||||
|
@ssh_session.expects(:exec!).with("sudo halt").once
|
||||||
|
@instance.halt
|
||||||
|
end
|
||||||
|
|
||||||
|
# TODO: Sleep/timeout testing
|
||||||
|
end
|
||||||
|
|
||||||
context "mounting shared folders" do
|
context "mounting shared folders" do
|
||||||
setup do
|
setup do
|
||||||
@ssh = mock("ssh")
|
@ssh = mock("ssh")
|
||||||
|
|
Loading…
Reference in New Issue