Extract rootfs tar contents into a tmp folder to avoid headaches and
check if a lxc-template file was included on .box
This commit is contained in:
parent
3d30418e53
commit
759b1c5f80
6 changed files with 58 additions and 27 deletions
|
@ -4,6 +4,7 @@ module Vagrant
|
||||||
# Prepare arguments to be used for lxc-create
|
# Prepare arguments to be used for lxc-create
|
||||||
class HandleBoxMetadata < BaseAction
|
class HandleBoxMetadata < BaseAction
|
||||||
LXC_TEMPLATES_PATH = Pathname.new("/usr/share/lxc/templates")
|
LXC_TEMPLATES_PATH = Pathname.new("/usr/share/lxc/templates")
|
||||||
|
TEMP_PREFIX = "vagrant-lxc-rootfs-temp-"
|
||||||
|
|
||||||
def initialize(app, env)
|
def initialize(app, env)
|
||||||
super
|
super
|
||||||
|
@ -11,25 +12,40 @@ module Vagrant
|
||||||
end
|
end
|
||||||
|
|
||||||
def call(env)
|
def call(env)
|
||||||
|
# We _could_ extract the rootfs to a folder under ~/.vagrant.d/boxes
|
||||||
|
# but it would open up for a few issues:
|
||||||
|
# * The rootfs owner is the root user, so we'd need to prepend "sudo" to
|
||||||
|
# `vagrant box remove`
|
||||||
|
# * We'd waste a lot of disk space: a compressed Ubuntu rootfs fits 80mb,
|
||||||
|
# extracted it takes 262mb
|
||||||
|
# * If something goes wrong during the Container creation process and
|
||||||
|
# somehow we don't handle, writing to /tmp means that things will get
|
||||||
|
# flushed on next reboot
|
||||||
|
rootfs_cache = Dir.mktmpdir(TEMP_PREFIX)
|
||||||
box = env[:machine].box
|
box = env[:machine].box
|
||||||
metadata = box.metadata
|
template_name = "vagrant-#{box.name}"
|
||||||
|
|
||||||
metadata.merge!(
|
|
||||||
'template-name' => "vagrant-#{box.name}",
|
|
||||||
'lxc-cache-path' => box.directory.to_s
|
|
||||||
)
|
|
||||||
|
|
||||||
# Prepends "lxc-" to the template file so that `lxc-create` is able to find it
|
# Prepends "lxc-" to the template file so that `lxc-create` is able to find it
|
||||||
src = box.directory.join('lxc-template').to_s
|
lxc_template_src = box.directory.join('lxc-template').to_s
|
||||||
dest = LXC_TEMPLATES_PATH.join("lxc-#{metadata['template-name']}").to_s
|
unless File.exists?(lxc_template_src)
|
||||||
|
raise Errors::TemplateFileMissing.new name: box.name
|
||||||
|
end
|
||||||
|
dest = LXC_TEMPLATES_PATH.join("lxc-#{template_name}").to_s
|
||||||
@logger.debug('Copying LXC template into place')
|
@logger.debug('Copying LXC template into place')
|
||||||
# This should only ask for administrative permission once, even
|
system(%Q[sudo su root -c "cp #{lxc_template_src} #{dest}"])
|
||||||
# though its executed in multiple subshells.
|
|
||||||
system(%Q[sudo su root -c "cp #{src} #{dest}"])
|
@logger.debug('Extracting rootfs')
|
||||||
system(%Q[sudo su root -c "cd #{box.directory} && tar xfz rootfs.tar.gz"])
|
system(%Q[sudo su root -c "cd #{box.directory} && tar xfz rootfs.tar.gz -C #{rootfs_cache}"])
|
||||||
|
|
||||||
|
box.metadata.merge!(
|
||||||
|
'template-name' => template_name,
|
||||||
|
'rootfs-cache-path' => rootfs_cache
|
||||||
|
)
|
||||||
|
|
||||||
@app.call(env)
|
@app.call(env)
|
||||||
|
|
||||||
|
ensure
|
||||||
|
system %Q[sudo su root -c "rm -rf #{rootfs_cache}"]
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -33,13 +33,12 @@ module Vagrant
|
||||||
|
|
||||||
def create(metadata = {})
|
def create(metadata = {})
|
||||||
# FIXME: Ruby 1.8 users dont have SecureRandom
|
# FIXME: Ruby 1.8 users dont have SecureRandom
|
||||||
# @logger.info('Creating container...')
|
@logger.debug('Creating container using lxc-create...')
|
||||||
|
|
||||||
@name = SecureRandom.hex(6)
|
@name = SecureRandom.hex(6)
|
||||||
public_key = Vagrant.source_root.join('keys', 'vagrant.pub').expand_path.to_s
|
public_key = Vagrant.source_root.join('keys', 'vagrant.pub').expand_path.to_s
|
||||||
|
|
||||||
meta_opts = metadata.fetch('template-opts', {}).map do |opt, value|
|
meta_opts = metadata.fetch('template-opts', {}).to_a.flatten
|
||||||
[opt, value]
|
|
||||||
end.flatten
|
|
||||||
|
|
||||||
# TODO: Handle errors
|
# TODO: Handle errors
|
||||||
lxc :create,
|
lxc :create,
|
||||||
|
@ -49,7 +48,7 @@ module Vagrant
|
||||||
'--',
|
'--',
|
||||||
# Template options
|
# Template options
|
||||||
'--auth-key', public_key,
|
'--auth-key', public_key,
|
||||||
'--cache', metadata['lxc-cache-path'],
|
'--cache', metadata['rootfs-cache-path'],
|
||||||
*meta_opts
|
*meta_opts
|
||||||
|
|
||||||
@name
|
@name
|
||||||
|
|
|
@ -4,6 +4,9 @@ module Vagrant
|
||||||
class ExecuteError < Vagrant::Errors::VagrantError
|
class ExecuteError < Vagrant::Errors::VagrantError
|
||||||
error_key(:lxc_execute_error)
|
error_key(:lxc_execute_error)
|
||||||
end
|
end
|
||||||
|
class TemplateFileMissing < Vagrant::Errors::VagrantError
|
||||||
|
error_key(:lxc_template_file_missing)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -6,3 +6,7 @@ en:
|
||||||
|
|
||||||
For more information on the failure, enable detailed logging by setting
|
For more information on the failure, enable detailed logging by setting
|
||||||
the environment variable VAGRANT_LOG to DEBUG.
|
the environment variable VAGRANT_LOG to DEBUG.
|
||||||
|
|
||||||
|
lxc_template_file_missing: |-
|
||||||
|
The template file used for creating the container was not found for %{name}
|
||||||
|
box.
|
||||||
|
|
|
@ -5,20 +5,24 @@ require 'vagrant-lxc/action/handle_box_metadata'
|
||||||
|
|
||||||
describe Vagrant::LXC::Action::HandleBoxMetadata do
|
describe Vagrant::LXC::Action::HandleBoxMetadata do
|
||||||
let(:metadata) { {'template-opts' => {'--foo' => 'bar'}} }
|
let(:metadata) { {'template-opts' => {'--foo' => 'bar'}} }
|
||||||
let(:box) { mock(:box, name: 'box-name', metadata: metadata, directory: Pathname.new('/path/to/box')) }
|
let(:box) { mock(:box, name: 'box-name', metadata: metadata, directory: box_directory) }
|
||||||
|
let(:box_directory) { Pathname.new('/path/to/box') }
|
||||||
let(:machine) { mock(:machine, box: box) }
|
let(:machine) { mock(:machine, box: box) }
|
||||||
let(:app) { mock(:app, call: true) }
|
let(:app) { mock(:app, call: true) }
|
||||||
let(:env) { {machine: machine} }
|
let(:env) { {machine: machine} }
|
||||||
|
let(:tmpdir) { '/tmp/rootfs/dir' }
|
||||||
|
|
||||||
subject { described_class.new(app, env) }
|
subject { described_class.new(app, env) }
|
||||||
|
|
||||||
before do
|
before do
|
||||||
|
Dir.stub(mktmpdir: tmpdir)
|
||||||
|
File.stub(exists?: true)
|
||||||
subject.stub(:system)
|
subject.stub(:system)
|
||||||
subject.call(env)
|
subject.call(env)
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'sets box directory as lxc-cache-path' do
|
it 'creates a tmp directory to store rootfs-cache-path' do
|
||||||
metadata['lxc-cache-path'].should == box.directory.to_s
|
metadata['rootfs-cache-path'].should == tmpdir
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'prepends vagrant and box name to template-name' do
|
it 'prepends vagrant and box name to template-name' do
|
||||||
|
@ -26,10 +30,15 @@ describe Vagrant::LXC::Action::HandleBoxMetadata do
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'copies box template file to the right folder' do
|
it 'copies box template file to the right folder' do
|
||||||
src = box.directory.join('lxc-template').to_s
|
src = box_directory.join('lxc-template').to_s
|
||||||
dest = "/usr/share/lxc/templates/lxc-#{metadata['template-name']}"
|
dest = "/usr/share/lxc/templates/lxc-#{metadata['template-name']}"
|
||||||
subject.should have_received(:system).with("sudo su root -c \"cp #{src} #{dest}\"")
|
|
||||||
|
subject.should have_received(:system).
|
||||||
|
with("sudo su root -c \"cp #{src} #{dest}\"")
|
||||||
end
|
end
|
||||||
|
|
||||||
pending 'extracts rootfs'
|
it 'extracts rootfs into a tmp folder' do
|
||||||
|
subject.should have_received(:system).
|
||||||
|
with(%Q[sudo su root -c "cd #{box_directory} && tar xfz rootfs.tar.gz -C #{tmpdir}"])
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -78,13 +78,13 @@ describe Vagrant::LXC::Container do
|
||||||
describe 'creation' do
|
describe 'creation' do
|
||||||
let(:name) { 'random-container-name' }
|
let(:name) { 'random-container-name' }
|
||||||
let(:template_name) { 'template-name' }
|
let(:template_name) { 'template-name' }
|
||||||
let(:lxc_cache) { '/path/to/cache' }
|
let(:rootfs_cache) { '/path/to/cache' }
|
||||||
let(:public_key_path) { Vagrant.source_root.join('keys', 'vagrant.pub').expand_path.to_s }
|
let(:public_key_path) { Vagrant.source_root.join('keys', 'vagrant.pub').expand_path.to_s }
|
||||||
|
|
||||||
before do
|
before do
|
||||||
subject.stub(lxc: true)
|
subject.stub(lxc: true)
|
||||||
SecureRandom.stub(hex: name)
|
SecureRandom.stub(hex: name)
|
||||||
subject.create 'template-name' => template_name, 'lxc-cache-path' => lxc_cache, 'template-opts' => { '--foo' => 'bar'}
|
subject.create 'template-name' => template_name, 'rootfs-cache-path' => rootfs_cache, 'template-opts' => { '--foo' => 'bar'}
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'calls lxc-create with the right arguments' do
|
it 'calls lxc-create with the right arguments' do
|
||||||
|
@ -94,7 +94,7 @@ describe Vagrant::LXC::Container do
|
||||||
'--name', name,
|
'--name', name,
|
||||||
'--',
|
'--',
|
||||||
'--auth-key', public_key_path,
|
'--auth-key', public_key_path,
|
||||||
'--cache', lxc_cache,
|
'--cache', rootfs_cache,
|
||||||
'--foo', 'bar'
|
'--foo', 'bar'
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in a new issue