Clean up Container object by making use of the CLI

This commit is contained in:
Fabio Rehm 2013-03-10 21:13:29 -03:00
parent 228e03ecbe
commit 550b926497
2 changed files with 68 additions and 164 deletions

View file

@ -46,19 +46,13 @@ module Vagrant
@name = SecureRandom.hex(6)
public_key = Vagrant.source_root.join('keys', 'vagrant.pub').expand_path.to_s
meta_opts = metadata.fetch('template-opts', {}).merge(
'--auth-key' => public_key,
'--cache' => metadata.fetch('rootfs-cache-path')
)
meta_opts = metadata.fetch('template-opts', {}).to_a.flatten
# TODO: Handle errors
lxc :create,
# lxc-create options
'--template', metadata.fetch('template-name'),
'--name', @name,
'--',
# Template options
'--auth-key', public_key,
'--cache', metadata.fetch('rootfs-cache-path'),
*meta_opts
@cli.name = @name
@cli.create(metadata.fetch('template-name'), meta_opts)
@name
end
@ -75,44 +69,36 @@ module Vagrant
end
end
# http://blog.smartlogicsolutions.com/2009/06/04/mount-options-to-improve-ext4-file-system-performance/
config.start_opts << "lxc.mount.entry=#{folder[:hostpath]} #{guestpath} none bind 0 0"
end
end
def start(config)
# @logger.info('Starting container...')
opts = config.start_opts.map { |opt| ["-s", opt] }.flatten
opts += ['-o', ENV['LXC_START_LOG_FILE'], '-l', 'DEBUG'] if ENV['LXC_START_LOG_FILE']
lxc :start, '-d', '--name', @name, *opts
wait_until :running
@logger.info('Starting container...')
opts = config.start_opts.dup
if ENV['LXC_START_LOG_FILE']
opts.merge!('-o' => ENV['LXC_START_LOG_FILE'], '-l' => 'DEBUG')
end
@cli.transition_to(:running) { |c| c.start(opts) }
end
def halt
lxc :shutdown, '--name', @name
wait_until :stopped
@logger.info('Shutting down container...')
# TODO: issue an lxc-stop if a timeout gets reached
@cli.transition_to(:stopped) { |c| c.shutdown }
end
def destroy
lxc :destroy, '--name', @name
end
# REFACTOR:
# transition_to :state do
# ... code ...
def wait_until(state)
lxc :wait, '--name', @name, '--state', state.to_s.upcase
end
def lxc(command, *args)
execute('sudo', "lxc-#{command}", *args)
@cli.destroy
end
def state
if @name && lxc(:info, '--name', @name) =~ /^state:[^A-Z]+([A-Z]+)$/
$1.downcase.to_sym
elsif @name
:unknown
if @name
@cli.state
end
end
@ -122,7 +108,7 @@ module Vagrant
end
mac_addr = $1
#`ip neigh flush all > /dev/null`
# TODO: We might need to `ip neigh flush all > /dev/null` before running `arp`
ip = ''
# See: http://programminglinuxblog.blogspot.com.br/2007/11/detecting-ip-address-from-mac-address.html
@ -157,36 +143,6 @@ module Vagrant
end
# TODO: Review code below this line, it was pretty much a copy and paste from VirtualBox base driver
def execute(*command, &block)
# Get the options hash if it exists
opts = {}
opts = command.pop if command.last.is_a?(Hash)
tries = 0
tries = 3 if opts[:retryable]
# Variable to store our execution result
r = nil
retryable(:on => LXC::Errors::ExecuteError, :tries => tries, :sleep => 1) do
# Execute the command
r = raw(*command, &block)
# If the command was a failure, then raise an exception that is
# nicely handled by Vagrant.
if r.exit_code != 0
if @interrupted
@logger.info("Exit code != 0, but interrupted. Ignoring.")
else
raise LXC::Errors::ExecuteError, :command => command.inspect
end
end
end
# Return the output, making sure to replace any Windows-style
# newlines with Unix-style.
r.stdout.gsub("\r\n", "\n")
end
# Executes a command and returns the raw result object.
def raw(*command, &block)

View file

@ -11,7 +11,7 @@ describe Vagrant::LXC::Container do
let(:unknown_container) { described_class.new('unknown', cli) }
let(:valid_container) { described_class.new('valid', cli) }
let(:new_container) { described_class.new(nil) }
let(:cli) { fire_double('Vagrant::LXC::CLI', list: ['valid']) }
let(:cli) { fire_double('Vagrant::LXC::Container::CLI', list: ['valid']) }
it 'raises a NotFound error if an unknown container name gets provided' do
expect {
@ -32,147 +32,95 @@ describe Vagrant::LXC::Container do
end
end
describe 'lxc commands execution' do
let(:args) { @args }
before do
subject.stub(:execute) { |*args| @args = args }
subject.lxc :command, '--state', 'RUNNING'
end
it 'prepends sudo' do
args[0].should == 'sudo'
end
it 'uses the first argument as lxc command suffix' do
args[1].should == 'lxc-command'
end
it 'pass through remaining arguments' do
args[2].should == '--state'
args[3].should == 'RUNNING'
end
end
describe 'guard for container state' do
let(:name) { 'random-container-name' }
before do
subject.stub :lxc
subject.wait_until :running
end
it 'runs lxc-wait with the machine id and upcased state' do
subject.should have_received(:lxc).with(
:wait,
'--name', name,
'--state', 'RUNNING'
)
end
end
describe 'creation' do
let(:name) { 'random-container-name' }
let(:template_name) { 'template-name' }
let(:rootfs_cache) { '/path/to/cache' }
let(:public_key_path) { Vagrant.source_root.join('keys', 'vagrant.pub').expand_path.to_s }
let(:cli) { fire_double('Vagrant::LXC::Container::CLI', :create => true, :name= => true) }
subject { described_class.new(name, cli) }
before do
subject.stub(lxc: true)
SecureRandom.stub(hex: name)
subject.create 'template-name' => template_name, 'rootfs-cache-path' => rootfs_cache, 'template-opts' => { '--foo' => 'bar'}
end
it 'calls lxc-create with the right arguments' do
subject.should have_received(:lxc).with(
:create,
'--template', template_name,
'--name', name,
'--',
'--auth-key', public_key_path,
'--cache', rootfs_cache,
'--foo', 'bar'
it 'creates container with the right arguments' do
cli.should have_received(:create).with(
template_name,
'--auth-key' => public_key_path,
'--cache' => rootfs_cache,
'--foo' => 'bar'
)
end
end
describe 'destruction' do
let(:name) { 'container-name' }
let(:cli) { fire_double('Vagrant::LXC::Container::CLI', destroy: true) }
before do
subject.stub(lxc: true)
subject.destroy
end
subject { described_class.new(name, cli) }
it 'calls lxc-destroy with the right arguments' do
subject.should have_received(:lxc).with(
:destroy,
'--name', name,
)
before { subject.destroy }
it 'delegates to cli object' do
cli.should have_received(:destroy)
end
end
describe 'start' do
let(:config) { mock(:config, start_opts: ['a=1', 'b=2']) }
let(:config) { mock(:config, start_opts: {'a' => '1', 'b' => '2'}) }
let(:name) { 'container-name' }
let(:cli) { fire_double('Vagrant::LXC::Container::CLI', start: true) }
subject { described_class.new(name, cli) }
before do
subject.stub(lxc: true, wait_until: true)
cli.stub(:transition_to).and_yield(cli)
end
it 'starts container with configured lxc settings' do
cli.should_receive(:start).with('a' => '1', 'b' => '2')
subject.start(config)
end
it 'calls lxc-start with the right arguments' do
subject.should have_received(:lxc).with(
:start,
'-d',
'--name', name,
'-s', 'a=1',
'-s', 'b=2'
)
end
it 'waits for container state to be RUNNING' do
subject.should have_received(:wait_until).with(:running)
it 'expects a transition to running state to take place' do
cli.should_receive(:transition_to).with(:running)
subject.start(config)
end
end
describe 'halt' do
let(:name) { 'random-container-name' }
let(:name) { 'container-name' }
let(:cli) { fire_double('Vagrant::LXC::Container::CLI', shutdown: true) }
subject { described_class.new(name, cli) }
before do
subject.stub(lxc: true, wait_until: true)
cli.stub(:transition_to).and_yield(cli)
end
it 'delegates to cli shutdown' do
cli.should_receive(:shutdown)
subject.halt
end
it 'calls lxc-shutdown with the right arguments' do
subject.should have_received(:lxc).with(
:shutdown,
'--name', name
)
end
it 'waits for container state to be STOPPED' do
subject.should have_received(:wait_until).with(:stopped)
it 'expects a transition to running state to take place' do
cli.should_receive(:transition_to).with(:stopped)
subject.halt
end
end
describe 'state' do
let(:name) { 'random-container-name' }
let(:name) { 'random-container-name' }
let(:cli_state) { :something }
let(:cli) { fire_double('Vagrant::LXC::Container::CLI', state: cli_state) }
before do
subject.stub(lxc: "state: STOPPED\npid: 2")
end
subject { described_class.new(name, cli) }
it 'calls lxc-info with the right arguments' do
subject.state
subject.should have_received(:lxc).with(
:info,
'--name', name
)
end
it 'maps the output of lxc-info status out to a symbol' do
subject.state.should == :stopped
it 'delegates to cli' do
subject.state.should == cli_state
end
end