commit
aa69226e44
11 changed files with 202 additions and 6 deletions
|
@ -78,8 +78,10 @@ EOF
|
|||
rm -f $rootfs/etc/init/tty{5,6}.conf
|
||||
fi
|
||||
|
||||
chroot $rootfs useradd --create-home -s /bin/bash vagrant
|
||||
echo "vagrant:vagrant" | chroot $rootfs chpasswd
|
||||
if ! (grep -q vagrant $rootfs/etc/passwd); then
|
||||
chroot $rootfs useradd --create-home -s /bin/bash vagrant
|
||||
echo "vagrant:vagrant" | chroot $rootfs chpasswd
|
||||
fi
|
||||
|
||||
return 0
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"provider": "lxc",
|
||||
"vagrant-lxc-version": "0.0.1",
|
||||
"provider": "lxc",
|
||||
"version": "1",
|
||||
|
||||
"template-opts": {
|
||||
"--arch": "amd64",
|
||||
|
|
|
@ -10,11 +10,13 @@ require 'vagrant-lxc/action/create'
|
|||
require 'vagrant-lxc/action/created'
|
||||
require 'vagrant-lxc/action/destroy'
|
||||
require 'vagrant-lxc/action/disconnect'
|
||||
require 'vagrant-lxc/action/compress_rootfs'
|
||||
require 'vagrant-lxc/action/forced_halt'
|
||||
require 'vagrant-lxc/action/forward_ports'
|
||||
require 'vagrant-lxc/action/handle_box_metadata'
|
||||
require 'vagrant-lxc/action/is_running'
|
||||
require 'vagrant-lxc/action/network'
|
||||
require 'vagrant-lxc/action/setup_package_files'
|
||||
require 'vagrant-lxc/action/share_folders'
|
||||
|
||||
module Vagrant
|
||||
|
@ -173,6 +175,25 @@ module Vagrant
|
|||
end
|
||||
end
|
||||
|
||||
# This action packages the virtual machine into a single box file.
|
||||
def self.action_package
|
||||
Vagrant::Action::Builder.new.tap do |b|
|
||||
# b.use CheckDependencies
|
||||
b.use Vagrant::Action::Builtin::Call, Created do |env1, b2|
|
||||
if !env1[:result]
|
||||
# TODO: Implement our own MessageNotCreated
|
||||
b2.use VagrantPlugins::ProviderVirtualBox::Action::MessageNotCreated
|
||||
next
|
||||
end
|
||||
|
||||
b2.use action_halt
|
||||
b2.use CompressRootFS
|
||||
b2.use SetupPackageFiles
|
||||
b2.use Vagrant::Action::General::Package
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# This is the action that will exec into an SSH shell.
|
||||
def self.action_ssh
|
||||
Vagrant::Action::Builder.new.tap do |b|
|
||||
|
|
30
lib/vagrant-lxc/action/compress_rootfs.rb
Normal file
30
lib/vagrant-lxc/action/compress_rootfs.rb
Normal file
|
@ -0,0 +1,30 @@
|
|||
require "fileutils"
|
||||
|
||||
module Vagrant
|
||||
module LXC
|
||||
module Action
|
||||
class CompressRootFS
|
||||
def initialize(app, env)
|
||||
@app = app
|
||||
end
|
||||
|
||||
def call(env)
|
||||
raise Vagrant::Errors::VMPowerOffToPackage if env[:machine].provider.state.id != :stopped
|
||||
|
||||
env[:ui].info I18n.t("vagrant.actions.lxc.compressing_rootfs")
|
||||
@rootfs = env['package.rootfs'] = env[:machine].provider.container.compress_rootfs
|
||||
|
||||
@app.call env
|
||||
|
||||
recover # called to remove the rootfs tarball
|
||||
end
|
||||
|
||||
def recover(*)
|
||||
if @rootfs && File.exist?(@rootfs)
|
||||
FileUtils.rm_rf(File.dirname @rootfs)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -29,7 +29,8 @@ module Vagrant
|
|||
system(%Q[sudo su root -c "cp #{lxc_template_src} #{dest}"])
|
||||
|
||||
@logger.debug('Extracting rootfs')
|
||||
system(%Q[sudo su root -c "cd #{box.directory} && tar xfz rootfs.tar.gz -C #{rootfs_cache}"])
|
||||
# TODO: Ideally the compressed rootfs should not output errors...
|
||||
system(%Q[sudo su root -c "cd #{box.directory} && tar xfz rootfs.tar.gz -C #{rootfs_cache} 2>/dev/null"])
|
||||
|
||||
box.metadata.merge!(
|
||||
'template-name' => template_name,
|
||||
|
|
52
lib/vagrant-lxc/action/setup_package_files.rb
Normal file
52
lib/vagrant-lxc/action/setup_package_files.rb
Normal file
|
@ -0,0 +1,52 @@
|
|||
require 'fileutils'
|
||||
|
||||
module Vagrant
|
||||
module LXC
|
||||
module Action
|
||||
class SetupPackageFiles
|
||||
def initialize(app, env)
|
||||
@app = app
|
||||
|
||||
env["package.include"] ||= []
|
||||
env["package.vagrantfile"] ||= nil
|
||||
end
|
||||
|
||||
def call(env)
|
||||
@env = env
|
||||
|
||||
create_package_temp_dir
|
||||
move_rootfs_to_pkg_dir
|
||||
copy_box_files_to_pkg_dir
|
||||
|
||||
@app.call env
|
||||
|
||||
recover # called to cleanup temp directory
|
||||
end
|
||||
|
||||
def recover(*)
|
||||
if @temp_dir && File.exist?(@temp_dir)
|
||||
FileUtils.rm_rf(@temp_dir)
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def create_package_temp_dir
|
||||
@env[:ui].info I18n.t("vagrant.actions.vm.export.create_dir")
|
||||
@temp_dir = @env["package.directory"] = @env[:tmp_path].join("container-export-#{Time.now.to_i.to_s}")
|
||||
FileUtils.mkpath(@temp_dir)
|
||||
end
|
||||
|
||||
def move_rootfs_to_pkg_dir
|
||||
FileUtils.mv @env['package.rootfs'].to_s, @env['package.directory'].to_s
|
||||
end
|
||||
|
||||
def copy_box_files_to_pkg_dir
|
||||
box_dir = @env[:machine].box.directory
|
||||
FileUtils.cp box_dir.join('lxc-template').to_s, @env['package.directory'].to_s
|
||||
FileUtils.cp box_dir.join('metadata.json').to_s, @env['package.directory'].to_s
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -93,6 +93,26 @@ module Vagrant
|
|||
@cli.destroy
|
||||
end
|
||||
|
||||
# TODO: This needs to be reviewed and specs needs to be written
|
||||
def compress_rootfs
|
||||
# TODO: Our template should not depend on container's arch
|
||||
arch = base_path.join('config').read.match(/^lxc\.arch\s+=\s+(.+)$/)[1]
|
||||
rootfs_dirname = File.dirname rootfs_path
|
||||
basename = rootfs_path.to_s.gsub(/^#{Regexp.escape rootfs_dirname}\//, '')
|
||||
# TODO: Pass in tmpdir so we can clean up from outside
|
||||
target_path = "#{Dir.mktmpdir}/rootfs.tar.gz"
|
||||
|
||||
Dir.chdir base_path do
|
||||
@logger.info "Compressing '#{rootfs_path}' rootfs to #{target_path}"
|
||||
system "sudo rm -f rootfs.tar.gz && sudo bsdtar -s /#{basename}/rootfs-#{arch}/ --numeric-owner -czf #{target_path} #{basename}/* 2>/dev/null"
|
||||
|
||||
@logger.info "Changing rootfs tarbal owner"
|
||||
system "sudo chown #{ENV['USER']}:#{ENV['USER']} #{target_path}"
|
||||
end
|
||||
|
||||
target_path
|
||||
end
|
||||
|
||||
def state
|
||||
if @name
|
||||
@cli.state
|
||||
|
|
|
@ -2,6 +2,8 @@ en:
|
|||
vagrant:
|
||||
actions:
|
||||
lxc:
|
||||
compressing_rootfs: Compressing container's rootfs...
|
||||
|
||||
share_folders:
|
||||
preparing: Setting up mount entries for shared folders...
|
||||
|
||||
|
|
27
spec/unit/action/compress_rootfs_spec.rb
Normal file
27
spec/unit/action/compress_rootfs_spec.rb
Normal file
|
@ -0,0 +1,27 @@
|
|||
require 'unit_helper'
|
||||
|
||||
require 'vagrant-lxc/action/compress_rootfs'
|
||||
|
||||
describe Vagrant::LXC::Action::CompressRootFS do
|
||||
let(:app) { mock(:app, call: true) }
|
||||
let(:env) { {machine: machine, ui: stub(info: true)} }
|
||||
let(:machine) { fire_double('Vagrant::Machine', provider: provider) }
|
||||
let(:provider) { fire_double('Vagrant::LXC::Provider', container: container) }
|
||||
let(:container) { fire_double('Vagrant::LXC::Container', compress_rootfs: compressed_rootfs_path) }
|
||||
let(:compressed_rootfs_path) { '/path/to/rootfs.tar.gz' }
|
||||
|
||||
subject { described_class.new(app, env) }
|
||||
|
||||
before do
|
||||
provider.stub_chain(:state, :id).and_return(:stopped)
|
||||
subject.call(env)
|
||||
end
|
||||
|
||||
it 'asks the container to compress its rootfs' do
|
||||
container.should have_received(:compress_rootfs)
|
||||
end
|
||||
|
||||
it 'sets export.temp_dir on action env' do
|
||||
env['package.rootfs'].should == compressed_rootfs_path
|
||||
end
|
||||
end
|
|
@ -39,6 +39,6 @@ describe Vagrant::LXC::Action::HandleBoxMetadata do
|
|||
|
||||
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}"])
|
||||
with(%Q[sudo su root -c "cd #{box_directory} && tar xfz rootfs.tar.gz -C #{tmpdir} 2>/dev/null"])
|
||||
end
|
||||
end
|
||||
|
|
41
spec/unit/action/setup_package_files_spec.rb
Normal file
41
spec/unit/action/setup_package_files_spec.rb
Normal file
|
@ -0,0 +1,41 @@
|
|||
require 'unit_helper'
|
||||
|
||||
require 'vagrant-lxc/action/setup_package_files'
|
||||
|
||||
describe Vagrant::LXC::Action::SetupPackageFiles do
|
||||
let(:app) { mock(:app, call: true) }
|
||||
let(:env) { {machine: machine, tmp_path: tmp_path, ui: stub(info: true), 'package.rootfs' => rootfs_path} }
|
||||
let(:machine) { fire_double('Vagrant::Machine', box: box) }
|
||||
let!(:tmp_path) { Pathname.new(Dir.mktmpdir) }
|
||||
let(:box) { fire_double('Vagrant::Box', directory: tmp_path.join('box')) }
|
||||
let(:rootfs_path) { tmp_path.join('rootfs-amd64.tar.gz') }
|
||||
|
||||
subject { described_class.new(app, env) }
|
||||
|
||||
before do
|
||||
box.directory.mkdir
|
||||
[box.directory.join('lxc-template'), box.directory.join('metadata.json'), rootfs_path].each do |file|
|
||||
file.open('w') { |f| f.puts file.to_s }
|
||||
end
|
||||
|
||||
subject.stub(recover: true) # Prevents files from being removed on specs
|
||||
subject.call(env)
|
||||
end
|
||||
|
||||
after do
|
||||
FileUtils.rm_rf(tmp_path.to_s)
|
||||
end
|
||||
|
||||
it 'copies box lxc-template to package directory' do
|
||||
env['package.directory'].join('lxc-template').should be_file
|
||||
end
|
||||
|
||||
it 'copies metadata.json to package directory' do
|
||||
env['package.directory'].join('metadata.json').should be_file
|
||||
end
|
||||
|
||||
it 'moves the compressed rootfs to package directory' do
|
||||
env['package.directory'].join(rootfs_path.basename).should be_file
|
||||
env['package.rootfs'].should_not be_file
|
||||
end
|
||||
end
|
Loading…
Reference in a new issue