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
|
rm -f $rootfs/etc/init/tty{5,6}.conf
|
||||||
fi
|
fi
|
||||||
|
|
||||||
chroot $rootfs useradd --create-home -s /bin/bash vagrant
|
if ! (grep -q vagrant $rootfs/etc/passwd); then
|
||||||
echo "vagrant:vagrant" | chroot $rootfs chpasswd
|
chroot $rootfs useradd --create-home -s /bin/bash vagrant
|
||||||
|
echo "vagrant:vagrant" | chroot $rootfs chpasswd
|
||||||
|
fi
|
||||||
|
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"provider": "lxc",
|
"provider": "lxc",
|
||||||
"vagrant-lxc-version": "0.0.1",
|
"version": "1",
|
||||||
|
|
||||||
"template-opts": {
|
"template-opts": {
|
||||||
"--arch": "amd64",
|
"--arch": "amd64",
|
||||||
|
|
|
@ -10,11 +10,13 @@ require 'vagrant-lxc/action/create'
|
||||||
require 'vagrant-lxc/action/created'
|
require 'vagrant-lxc/action/created'
|
||||||
require 'vagrant-lxc/action/destroy'
|
require 'vagrant-lxc/action/destroy'
|
||||||
require 'vagrant-lxc/action/disconnect'
|
require 'vagrant-lxc/action/disconnect'
|
||||||
|
require 'vagrant-lxc/action/compress_rootfs'
|
||||||
require 'vagrant-lxc/action/forced_halt'
|
require 'vagrant-lxc/action/forced_halt'
|
||||||
require 'vagrant-lxc/action/forward_ports'
|
require 'vagrant-lxc/action/forward_ports'
|
||||||
require 'vagrant-lxc/action/handle_box_metadata'
|
require 'vagrant-lxc/action/handle_box_metadata'
|
||||||
require 'vagrant-lxc/action/is_running'
|
require 'vagrant-lxc/action/is_running'
|
||||||
require 'vagrant-lxc/action/network'
|
require 'vagrant-lxc/action/network'
|
||||||
|
require 'vagrant-lxc/action/setup_package_files'
|
||||||
require 'vagrant-lxc/action/share_folders'
|
require 'vagrant-lxc/action/share_folders'
|
||||||
|
|
||||||
module Vagrant
|
module Vagrant
|
||||||
|
@ -173,6 +175,25 @@ module Vagrant
|
||||||
end
|
end
|
||||||
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.
|
# This is the action that will exec into an SSH shell.
|
||||||
def self.action_ssh
|
def self.action_ssh
|
||||||
Vagrant::Action::Builder.new.tap do |b|
|
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}"])
|
system(%Q[sudo su root -c "cp #{lxc_template_src} #{dest}"])
|
||||||
|
|
||||||
@logger.debug('Extracting rootfs')
|
@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!(
|
box.metadata.merge!(
|
||||||
'template-name' => template_name,
|
'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
|
@cli.destroy
|
||||||
end
|
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
|
def state
|
||||||
if @name
|
if @name
|
||||||
@cli.state
|
@cli.state
|
||||||
|
|
|
@ -2,6 +2,8 @@ en:
|
||||||
vagrant:
|
vagrant:
|
||||||
actions:
|
actions:
|
||||||
lxc:
|
lxc:
|
||||||
|
compressing_rootfs: Compressing container's rootfs...
|
||||||
|
|
||||||
share_folders:
|
share_folders:
|
||||||
preparing: Setting up mount entries for shared 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
|
it 'extracts rootfs into a tmp folder' do
|
||||||
subject.should have_received(:system).
|
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
|
||||||
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…
Add table
Reference in a new issue