Stop container with lxc-stop if lxc-shutdown does not succeed

This commit is contained in:
Fabio Rehm 2013-05-07 11:07:35 -03:00
parent 7a069957d7
commit 3cca168248
5 changed files with 39 additions and 16 deletions

View file

@ -9,9 +9,7 @@ module Vagrant
def call(env)
if env[:machine].provider.state.id == :running
env[:ui].info I18n.t("vagrant_lxc.messages.force_shutdown")
# TODO: Driver#halt is kinda graceful as well, if it doesn't
# work we can issue a lxc-stop.
env[:machine].provider.driver.halt
env[:machine].provider.driver.forced_halt
end
@app.call(env)

View file

@ -69,11 +69,11 @@ module Vagrant
@cli.transition_to(:running) { |c| c.start(customizations, (extra || nil)) }
end
def halt
def forced_halt
@logger.info('Shutting down container...')
# TODO: issue an lxc-stop if a timeout gets reached
@cli.transition_to(:stopped) { |c| c.shutdown }
rescue CLI::TargetStateNotReached
@cli.transition_to(:stopped) { |c| c.stop }
end
def destroy

View file

@ -10,6 +10,12 @@ module Vagrant
attr_accessor :name
class TransitionBlockNotProvided < RuntimeError; end
class TargetStateNotReached < RuntimeError
def initialize(target_state, state)
msg = "Target state '#{target_state}' not reached, currently on '#{state}'"
super(msg)
end
end
# Include this so we can use `Subprocess` more easily.
include Vagrant::Util::Retryable
@ -60,6 +66,10 @@ module Vagrant
run :start, '-d', '--name', @name, *options
end
def stop
run :stop, '--name', @name
end
def shutdown
run :shutdown, '--name', @name
end
@ -76,12 +86,20 @@ module Vagrant
run :attach, '--name', @name, *((extra || []) + cmd)
end
def transition_to(state, &block)
def transition_to(target_state, tries = 30, timeout = 1, &block)
raise TransitionBlockNotProvided unless block_given?
yield self
run :wait, '--name', @name, '--state', state.to_s.upcase
while (last_state = self.state) != target_state && tries > 0
@logger.debug "Target state '#{target_state}' not reached, currently on '#{last_state}'"
sleep timeout
tries -= 1
end
unless last_state == target_state
raise TargetStateNotReached.new target_state, last_state
end
end
private

View file

@ -157,9 +157,11 @@ describe Vagrant::LXC::Driver::CLI do
let(:name) { 'a-running-container' }
subject { described_class.new(name) }
before { subject.stub(:run) }
before do
subject.stub(run: true, sleep: true, state: :stopped)
end
it 'yields cli object' do
it 'yields a cli object' do
subject.stub(:shutdown)
subject.transition_to(:stopped) { |c| c.shutdown }
subject.should have_received(:shutdown)
@ -171,9 +173,6 @@ describe Vagrant::LXC::Driver::CLI do
}.to raise_error(described_class::TransitionBlockNotProvided)
end
it 'waits for the expected container state using lxc-wait' do
subject.transition_to(:running) { }
subject.should have_received(:run).with(:wait, '--name', name, '--state', 'RUNNING')
end
pending 'waits for the expected container state'
end
end

View file

@ -2,6 +2,7 @@ require 'unit_helper'
require 'vagrant'
require 'vagrant-lxc/driver'
require 'vagrant-lxc/driver/cli'
describe Vagrant::LXC::Driver do
describe 'container name validation' do
@ -101,12 +102,19 @@ describe Vagrant::LXC::Driver do
it 'delegates to cli shutdown' do
cli.should_receive(:shutdown)
subject.halt
subject.forced_halt
end
it 'expects a transition to running state to take place' do
cli.should_receive(:transition_to).with(:stopped)
subject.halt
subject.forced_halt
end
it 'attempts to force the container to stop in case a shutdown doesnt work' do
cli.stub(:shutdown).and_raise(Vagrant::LXC::Driver::CLI::TargetStateNotReached.new :target, :source)
cli.should_receive(:transition_to).with(:stopped).twice
cli.should_receive(:stop)
subject.forced_halt
end
end