Skip to content
This repository has been archived by the owner on Nov 24, 2022. It is now read-only.

Commit

Permalink
Stop container with lxc-stop if lxc-shutdown does not succeed
Browse files Browse the repository at this point in the history
  • Loading branch information
fgrehm committed May 7, 2013
1 parent 7a06995 commit 3cca168
Show file tree
Hide file tree
Showing 5 changed files with 39 additions and 16 deletions.
4 changes: 1 addition & 3 deletions lib/vagrant-lxc/action/forced_halt.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,7 @@ def initialize(app, env)
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)
Expand Down
6 changes: 3 additions & 3 deletions lib/vagrant-lxc/driver.rb
Original file line number Diff line number Diff line change
Expand Up @@ -69,11 +69,11 @@ def start(customizations)
@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
Expand Down
22 changes: 20 additions & 2 deletions lib/vagrant-lxc/driver/cli.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,12 @@ class CLI
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
Expand Down Expand Up @@ -60,6 +66,10 @@ def start(overrides = [], extra_opts = [])
run :start, '-d', '--name', @name, *options
end

def stop
run :stop, '--name', @name
end

def shutdown
run :shutdown, '--name', @name
end
Expand All @@ -76,12 +86,20 @@ def attach(*cmd)
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
Expand Down
11 changes: 5 additions & 6 deletions spec/unit/driver/cli_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -157,9 +157,11 @@
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)
Expand All @@ -171,9 +173,6 @@
}.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
12 changes: 10 additions & 2 deletions spec/unit/driver_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

require 'vagrant'
require 'vagrant-lxc/driver'
require 'vagrant-lxc/driver/cli'

describe Vagrant::LXC::Driver do
describe 'container name validation' do
Expand Down Expand Up @@ -101,12 +102,19 @@

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

Expand Down

0 comments on commit 3cca168

Please sign in to comment.