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)
|
def call(env)
|
||||||
if env[:machine].provider.state.id == :running
|
if env[:machine].provider.state.id == :running
|
||||||
env[:ui].info I18n.t("vagrant_lxc.messages.force_shutdown")
|
env[:ui].info I18n.t("vagrant_lxc.messages.force_shutdown")
|
||||||
# TODO: Driver#halt is kinda graceful as well, if it doesn't
|
env[:machine].provider.driver.forced_halt
|
||||||
# work we can issue a lxc-stop.
|
|
||||||
env[:machine].provider.driver.halt
|
|
||||||
end
|
end
|
||||||
|
|
||||||
@app.call(env)
|
@app.call(env)
|
||||||
|
|
|
@ -69,11 +69,11 @@ module Vagrant
|
||||||
@cli.transition_to(:running) { |c| c.start(customizations, (extra || nil)) }
|
@cli.transition_to(:running) { |c| c.start(customizations, (extra || nil)) }
|
||||||
end
|
end
|
||||||
|
|
||||||
def halt
|
def forced_halt
|
||||||
@logger.info('Shutting down container...')
|
@logger.info('Shutting down container...')
|
||||||
|
|
||||||
# TODO: issue an lxc-stop if a timeout gets reached
|
|
||||||
@cli.transition_to(:stopped) { |c| c.shutdown }
|
@cli.transition_to(:stopped) { |c| c.shutdown }
|
||||||
|
rescue CLI::TargetStateNotReached
|
||||||
|
@cli.transition_to(:stopped) { |c| c.stop }
|
||||||
end
|
end
|
||||||
|
|
||||||
def destroy
|
def destroy
|
||||||
|
|
|
@ -10,6 +10,12 @@ module Vagrant
|
||||||
attr_accessor :name
|
attr_accessor :name
|
||||||
|
|
||||||
class TransitionBlockNotProvided < RuntimeError; end
|
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 this so we can use `Subprocess` more easily.
|
||||||
include Vagrant::Util::Retryable
|
include Vagrant::Util::Retryable
|
||||||
|
@ -60,6 +66,10 @@ module Vagrant
|
||||||
run :start, '-d', '--name', @name, *options
|
run :start, '-d', '--name', @name, *options
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def stop
|
||||||
|
run :stop, '--name', @name
|
||||||
|
end
|
||||||
|
|
||||||
def shutdown
|
def shutdown
|
||||||
run :shutdown, '--name', @name
|
run :shutdown, '--name', @name
|
||||||
end
|
end
|
||||||
|
@ -76,12 +86,20 @@ module Vagrant
|
||||||
run :attach, '--name', @name, *((extra || []) + cmd)
|
run :attach, '--name', @name, *((extra || []) + cmd)
|
||||||
end
|
end
|
||||||
|
|
||||||
def transition_to(state, &block)
|
def transition_to(target_state, tries = 30, timeout = 1, &block)
|
||||||
raise TransitionBlockNotProvided unless block_given?
|
raise TransitionBlockNotProvided unless block_given?
|
||||||
|
|
||||||
yield self
|
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
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
|
@ -157,9 +157,11 @@ describe Vagrant::LXC::Driver::CLI do
|
||||||
let(:name) { 'a-running-container' }
|
let(:name) { 'a-running-container' }
|
||||||
subject { described_class.new(name) }
|
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.stub(:shutdown)
|
||||||
subject.transition_to(:stopped) { |c| c.shutdown }
|
subject.transition_to(:stopped) { |c| c.shutdown }
|
||||||
subject.should have_received(:shutdown)
|
subject.should have_received(:shutdown)
|
||||||
|
@ -171,9 +173,6 @@ describe Vagrant::LXC::Driver::CLI do
|
||||||
}.to raise_error(described_class::TransitionBlockNotProvided)
|
}.to raise_error(described_class::TransitionBlockNotProvided)
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'waits for the expected container state using lxc-wait' do
|
pending 'waits for the expected container state'
|
||||||
subject.transition_to(:running) { }
|
|
||||||
subject.should have_received(:run).with(:wait, '--name', name, '--state', 'RUNNING')
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -2,6 +2,7 @@ require 'unit_helper'
|
||||||
|
|
||||||
require 'vagrant'
|
require 'vagrant'
|
||||||
require 'vagrant-lxc/driver'
|
require 'vagrant-lxc/driver'
|
||||||
|
require 'vagrant-lxc/driver/cli'
|
||||||
|
|
||||||
describe Vagrant::LXC::Driver do
|
describe Vagrant::LXC::Driver do
|
||||||
describe 'container name validation' do
|
describe 'container name validation' do
|
||||||
|
@ -101,12 +102,19 @@ describe Vagrant::LXC::Driver do
|
||||||
|
|
||||||
it 'delegates to cli shutdown' do
|
it 'delegates to cli shutdown' do
|
||||||
cli.should_receive(:shutdown)
|
cli.should_receive(:shutdown)
|
||||||
subject.halt
|
subject.forced_halt
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'expects a transition to running state to take place' do
|
it 'expects a transition to running state to take place' do
|
||||||
cli.should_receive(:transition_to).with(:stopped)
|
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
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue