Stop container with lxc-stop if lxc-shutdown does not succeed
This commit is contained in:
parent
7a069957d7
commit
3cca168248
5 changed files with 39 additions and 16 deletions
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
Loading…
Reference in a new issue