From aca88e2407a2417401d6d0748ab4cbd5cc940f9b Mon Sep 17 00:00:00 2001 From: Fabio Rehm Date: Wed, 5 Jun 2013 22:30:12 -0300 Subject: [PATCH 01/25] Extract a general purpose experimental lxc template --- boxes/common/lxc-template | 232 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 232 insertions(+) create mode 100644 boxes/common/lxc-template diff --git a/boxes/common/lxc-template b/boxes/common/lxc-template new file mode 100644 index 0000000..09a2dce --- /dev/null +++ b/boxes/common/lxc-template @@ -0,0 +1,232 @@ +#!/bin/bash + +# This is a modified version of /usr/share/lxc/templates/lxc-ubuntu +# that comes with Ubuntu 13.04 changed to suit vagrant-lxc needs + +# +# template script for generating ubuntu container for LXC +# +# This script consolidates and extends the existing lxc ubuntu scripts +# + +# Copyright © 2011 Serge Hallyn +# Copyright © 2010 Wilhelm Meier +# Author: Wilhelm Meier +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2, as +# published by the Free Software Foundation. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +# + +set -e + +if [ -r /etc/default/lxc ]; then + . /etc/default/lxc +fi + +extract_rootfs() +{ + tarball=$1 + arch=$2 + rootfs=$3 + + echo "Extracting $tarball ..." + mkdir -p $(dirname $rootfs) + (cd `dirname $rootfs` && tar xfz $tarball) + return 0 +} + +install_ubuntu() +{ + rootfs=$1 + release=$2 + tarball=$3 + mkdir -p /var/lock/subsys/ + + ( + flock -x 200 + if [ $? -ne 0 ]; then + echo "Cache repository is busy." + return 1 + fi + + extract_rootfs $tarball $arch $rootfs + if [ $? -ne 0 ]; then + echo "Failed to copy rootfs" + return 1 + fi + + return 0 + + ) 200>/var/lock/subsys/lxc + + return $? +} + +copy_configuration() +{ + path=$1 + rootfs=$2 + name=$3 + arch=$4 + + if [ $arch = "i386" ]; then + arch="i686" + fi + + # if there is exactly one veth network entry, make sure it has an + # associated hwaddr. + nics=`grep -e '^lxc\.network\.type[ \t]*=[ \t]*veth' $path/config | wc -l` + if [ $nics -eq 1 ]; then + grep -q "^lxc.network.hwaddr" $path/config || sed -i -e "/^lxc\.network\.type[ \t]*=[ \t]*veth/a lxc.network.hwaddr = 00:16:3e:$(openssl rand -hex 3| sed 's/\(..\)/\1:/g; s/.$//')" $path/config + fi + + if [ $? -ne 0 ]; then + echo "Failed to add configuration" + return 1 + fi + + return 0 +} + +post_process() +{ + rootfs=$1 + + # rmdir /dev/shm for containers that have /run/shm + # I'm afraid of doing rm -rf $rootfs/dev/shm, in case it did + # get bind mounted to the host's /run/shm. So try to rmdir + # it, and in case that fails move it out of the way. + if [ ! -L $rootfs/dev/shm ] && [ -d $rootfs/run/shm ] && [ -e $rootfs/dev/shm ]; then + mv $rootfs/dev/shm $rootfs/dev/shm.bak + ln -s /run/shm $rootfs/dev/shm + fi +} + +usage() +{ + cat <] [ -S | --auth-key ] +release: the ubuntu release (e.g. precise): defaults to host release on ubuntu, otherwise uses latest LTS +trim: make a minimal (faster, but not upgrade-safe) container +arch: the container architecture (e.g. amd64): defaults to host arch +auth-key: SSH Public key file to inject into container +EOF + return 0 +} + +options=$(getopt -o a:b:hp:r:xn:FS:d:C -l arch:,help,path:,release:,trim,name:,flush-cache,auth-key:,debug:,tarball: -- "$@") +if [ $? -ne 0 ]; then + usage $(basename $0) + exit 1 +fi +eval set -- "$options" + +release=precise # Default to the last Ubuntu LTS release for non-Ubuntu systems +if [ -f /etc/lsb-release ]; then + . /etc/lsb-release + if [ "$DISTRIB_ID" = "Ubuntu" ]; then + release=$DISTRIB_CODENAME + fi +fi + +arch=$(uname -m) + +# Code taken from debootstrap +if [ -x /usr/bin/dpkg ] && /usr/bin/dpkg --print-architecture >/dev/null 2>&1; then + arch=`/usr/bin/dpkg --print-architecture` +elif type udpkg >/dev/null 2>&1 && udpkg --print-architecture >/dev/null 2>&1; then + arch=`/usr/bin/udpkg --print-architecture` +else + arch=$(uname -m) + if [ "$arch" = "i686" ]; then + arch="i386" + elif [ "$arch" = "x86_64" ]; then + arch="amd64" + elif [ "$arch" = "armv7l" ]; then + arch="armel" + fi +fi + +debug=0 +trim_container=0 +hostarch=$arch +while true +do + case "$1" in + -h|--help) usage $0 && exit 0;; + -p|--path) path=$2; shift 2;; + -n|--name) name=$2; shift 2;; + -T|--tarball) tarball=$2; shift 2;; + -r|--release) release=$2; shift 2;; + -a|--arch) arch=$2; shift 2;; + -x|--trim) trim_container=1; shift 1;; + -S|--auth-key) auth_key=$2; shift 2;; + -d|--debug) debug=1; shift 1;; + --) shift 1; break ;; + *) break ;; + esac +done + +if [ $debug -eq 1 ]; then + set -x +fi + + +if [ "$arch" == "i686" ]; then + arch=i386 +fi + +if [ $hostarch = "i386" -a $arch = "amd64" ]; then + echo "can't create amd64 container on i386" + exit 1 +fi + +if [ -z "$path" ]; then + echo "'path' parameter is required" + exit 1 +fi + +if [ "$(id -u)" != "0" ]; then + echo "This script should be run as 'root'" + exit 1 +fi + +# detect rootfs +config="$path/config" +if grep -q '^lxc.rootfs' $config 2>/dev/null ; then + rootfs=`grep 'lxc.rootfs =' $config | awk -F= '{ print $2 }'` +else + rootfs=$path/rootfs +fi + +install_ubuntu $rootfs $release $tarball +if [ $? -ne 0 ]; then + echo "failed to install ubuntu $release" + exit 1 +fi + +copy_configuration $path $rootfs $name $arch +if [ $? -ne 0 ]; then + echo "failed write configuration file" + exit 1 +fi + +post_process $rootfs $release $trim_container + +echo "" +echo "##" +echo "# The default user is 'vagrant' with password 'vagrant'!" +echo "# Use the 'sudo' command to run tasks as root in the container." +echo "##" +echo "" From ba7bc580f590560c96dd6f29796d3002a6d43434 Mon Sep 17 00:00:00 2001 From: Fabio Rehm Date: Wed, 5 Jun 2013 23:14:44 -0300 Subject: [PATCH 02/25] Add new common metadata json file for v3 boxes --- boxes/common/metadata.json | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 boxes/common/metadata.json diff --git a/boxes/common/metadata.json b/boxes/common/metadata.json new file mode 100644 index 0000000..824c6fd --- /dev/null +++ b/boxes/common/metadata.json @@ -0,0 +1,4 @@ +{ + "provider": "lxc", + "version": "3" +} From 663ff1fc0df6a9294cdeffa3c0964cd76a8ffe5f Mon Sep 17 00:00:00 2001 From: Fabio Rehm Date: Wed, 5 Jun 2013 23:57:17 -0300 Subject: [PATCH 03/25] Add base lxc config file --- boxes/common/lxc.conf | 46 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) create mode 100644 boxes/common/lxc.conf diff --git a/boxes/common/lxc.conf b/boxes/common/lxc.conf new file mode 100644 index 0000000..7e5fc80 --- /dev/null +++ b/boxes/common/lxc.conf @@ -0,0 +1,46 @@ +lxc.network.type=veth +lxc.network.hwaddr = 00:16:3e:7f:04:b2 +lxc.network.link=lxcbr0 +lxc.network.flags=up + +lxc.pivotdir = lxc_putold + +lxc.devttydir = lxc +lxc.tty = 4 +lxc.pts = 1024 + +lxc.arch = amd64 +lxc.cap.drop = sys_module mac_admin mac_override + +# When using LXC with apparmor, uncomment the next line to run unconfined: +#lxc.aa_profile = unconfined + +lxc.cgroup.devices.deny = a +# Allow any mknod (but not using the node) +lxc.cgroup.devices.allow = c *:* m +lxc.cgroup.devices.allow = b *:* m +# /dev/null and zero +lxc.cgroup.devices.allow = c 1:3 rwm +lxc.cgroup.devices.allow = c 1:5 rwm +# consoles +lxc.cgroup.devices.allow = c 5:1 rwm +lxc.cgroup.devices.allow = c 5:0 rwm +#lxc.cgroup.devices.allow = c 4:0 rwm +#lxc.cgroup.devices.allow = c 4:1 rwm +# /dev/{,u}random +lxc.cgroup.devices.allow = c 1:9 rwm +lxc.cgroup.devices.allow = c 1:8 rwm +lxc.cgroup.devices.allow = c 136:* rwm +lxc.cgroup.devices.allow = c 5:2 rwm +# rtc +lxc.cgroup.devices.allow = c 254:0 rwm +#fuse +lxc.cgroup.devices.allow = c 10:229 rwm +#tun +lxc.cgroup.devices.allow = c 10:200 rwm +#full +lxc.cgroup.devices.allow = c 1:7 rwm +#hpet +lxc.cgroup.devices.allow = c 10:228 rwm +#kvm +lxc.cgroup.devices.allow = c 10:232 rwm From c6af4fab084cb1b920af513ef629d75745a152fc Mon Sep 17 00:00:00 2001 From: Fabio Rehm Date: Thu, 6 Jun 2013 00:03:02 -0300 Subject: [PATCH 04/25] Lets ensure the rootfs is always set before starting the container --- lib/vagrant-lxc/driver.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/vagrant-lxc/driver.rb b/lib/vagrant-lxc/driver.rb index c9ca4fe..fed94d5 100644 --- a/lib/vagrant-lxc/driver.rb +++ b/lib/vagrant-lxc/driver.rb @@ -30,7 +30,7 @@ module Vagrant end def rootfs_path - Pathname.new(base_path.join('config').read.match(/^lxc\.rootfs\s+=\s+(.+)$/)[1]) + Pathname.new(base_path.join('rootfs')) end def create(name, template_path, template_options = {}) @@ -65,6 +65,7 @@ module Vagrant extra = ['-o', ENV['LXC_START_LOG_FILE'], '-l', 'DEBUG'] end customizations = customizations + @customizations + customizations += [['rootfs', rootfs_path.to_s]] @cli.transition_to(:running) { |c| c.start(customizations, (extra || nil)) } end From 75a2d0c65d98e57e1ecb87e9cff2086a3bd70fe6 Mon Sep 17 00:00:00 2001 From: Fabio Rehm Date: Thu, 6 Jun 2013 00:03:37 -0300 Subject: [PATCH 05/25] Lets ensure the utsname is always set before starting the container --- lib/vagrant-lxc/action/boot.rb | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/vagrant-lxc/action/boot.rb b/lib/vagrant-lxc/action/boot.rb index 62b0271..9edb163 100644 --- a/lib/vagrant-lxc/action/boot.rb +++ b/lib/vagrant-lxc/action/boot.rb @@ -11,6 +11,8 @@ module Vagrant config = env[:machine].provider_config + config.customize 'utsname', env[:machine].id + env[:ui].info I18n.t("vagrant_lxc.messages.starting") env[:machine].provider.driver.start(config.customizations) raise Vagrant::Errors::VMFailedToBoot if !wait_for_boot From 5c2973108b67daca5e80e2e7a4f89215d0d67134 Mon Sep 17 00:00:00 2001 From: Fabio Rehm Date: Thu, 6 Jun 2013 00:04:59 -0300 Subject: [PATCH 06/25] Support bundling lxc config files with base boxes --- lib/vagrant-lxc/action/create.rb | 1 + lib/vagrant-lxc/action/handle_box_metadata.rb | 8 ++++++++ lib/vagrant-lxc/driver.rb | 4 ++-- lib/vagrant-lxc/driver/cli.rb | 7 ++++++- 4 files changed, 17 insertions(+), 3 deletions(-) diff --git a/lib/vagrant-lxc/action/create.rb b/lib/vagrant-lxc/action/create.rb index 0bce830..4a5f089 100644 --- a/lib/vagrant-lxc/action/create.rb +++ b/lib/vagrant-lxc/action/create.rb @@ -14,6 +14,7 @@ module Vagrant env[:machine].provider.driver.create( container_name, env[:lxc_template_src], + env[:lxc_template_config], env[:lxc_template_opts] ) diff --git a/lib/vagrant-lxc/action/handle_box_metadata.rb b/lib/vagrant-lxc/action/handle_box_metadata.rb index 1471369..e169d8e 100644 --- a/lib/vagrant-lxc/action/handle_box_metadata.rb +++ b/lib/vagrant-lxc/action/handle_box_metadata.rb @@ -22,6 +22,10 @@ module Vagrant @env[:lxc_template_opts] = template_opts @env[:lxc_template_src] = template_src + if template_config_file.exist? + @env[:lxc_template_config] = template_config_file.to_s + end + @app.call env end @@ -29,6 +33,10 @@ module Vagrant @template_src ||= @box.directory.join('lxc-template').to_s end + def template_config_file + @template_config_file ||= @box.directory.join('lxc.conf') + end + def template_opts @template_opts ||= @box.metadata.fetch('template-opts', {}).dup.merge!( '--tarball' => rootfs_tarball, diff --git a/lib/vagrant-lxc/driver.rb b/lib/vagrant-lxc/driver.rb index fed94d5..c9f5388 100644 --- a/lib/vagrant-lxc/driver.rb +++ b/lib/vagrant-lxc/driver.rb @@ -33,12 +33,12 @@ module Vagrant Pathname.new(base_path.join('rootfs')) end - def create(name, template_path, template_options = {}) + def create(name, template_path, config_file, template_options = {}) @cli.name = @container_name = name import_template(template_path) do |template_name| @logger.debug "Creating container..." - @cli.create template_name, template_options + @cli.create template_name, config_file, template_options end end diff --git a/lib/vagrant-lxc/driver/cli.rb b/lib/vagrant-lxc/driver/cli.rb index 0898595..133a828 100644 --- a/lib/vagrant-lxc/driver/cli.rb +++ b/lib/vagrant-lxc/driver/cli.rb @@ -46,13 +46,18 @@ module Vagrant end end - def create(template, template_opts = {}) + def create(template, config_file, template_opts = {}) + if config_file + config_opts = ['-f', config_file] + end + extra = template_opts.to_a.flatten extra.unshift '--' unless extra.empty? run :create, '--template', template, '--name', @name, + *(config_opts), *extra end From cb1f72923a7fe1819038385699cbedbbf7dd70c9 Mon Sep 17 00:00:00 2001 From: Fabio Rehm Date: Thu, 6 Jun 2013 00:05:34 -0300 Subject: [PATCH 07/25] Unleash V3 boxes! --- lib/vagrant-lxc/action/handle_box_metadata.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/vagrant-lxc/action/handle_box_metadata.rb b/lib/vagrant-lxc/action/handle_box_metadata.rb index e169d8e..9d8bf8a 100644 --- a/lib/vagrant-lxc/action/handle_box_metadata.rb +++ b/lib/vagrant-lxc/action/handle_box_metadata.rb @@ -49,7 +49,7 @@ module Vagrant end def validate_box - if @box.metadata.fetch('version').to_i != 2 + if @box.metadata.fetch('version').to_i < 2 raise Errors::InvalidBoxVersion.new name: @box.name end From ed4a8ae7292fd320616a84f0edd08983ced72d65 Mon Sep 17 00:00:00 2001 From: Fabio Rehm Date: Thu, 6 Jun 2013 00:12:40 -0300 Subject: [PATCH 08/25] Duplicate base boxes tasks and start versioning them too --- tasks/{boxes.rake => boxes.v2.rake} | 84 +++++++++++++++-------------- tasks/boxes.v3.rake | 80 +++++++++++++++++++++++++++ 2 files changed, 123 insertions(+), 41 deletions(-) rename tasks/{boxes.rake => boxes.v2.rake} (64%) create mode 100644 tasks/boxes.v3.rake diff --git a/tasks/boxes.rake b/tasks/boxes.v2.rake similarity index 64% rename from tasks/boxes.rake rename to tasks/boxes.v2.rake index 63f2df9..232ec59 100644 --- a/tasks/boxes.rake +++ b/tasks/boxes.v2.rake @@ -1,7 +1,7 @@ require 'pathname' require 'rake/tasklib' -class BuildGenericBoxTask < ::Rake::TaskLib +class BuildGenericBoxTaskV2 < ::Rake::TaskLib include ::Rake::DSL attr_reader :name @@ -110,13 +110,13 @@ class BuildGenericBoxTask < ::Rake::TaskLib end end -class BuildDebianBoxTask < BuildGenericBoxTask +class BuildDebianBoxTaskV2 < BuildGenericBoxTaskV2 def initialize(name, release, arch, opts = {}) super(name, 'debian', release, arch, opts) end end -class BuildUbuntuBoxTask < BuildGenericBoxTask +class BuildUbuntuBoxTaskV2 < BuildGenericBoxTaskV2 def initialize(name, release, arch, opts = {}) super(name, 'ubuntu', release, arch, opts) end @@ -127,53 +127,55 @@ puppet = ENV['PUPPET'] == '1' babushka = ENV['BABUSHKA'] == '1' namespace :boxes do - namespace :ubuntu do - namespace :build do + namespace :v2 do + namespace :ubuntu do + namespace :build do - desc 'Build an Ubuntu Precise 64 bits box' - BuildUbuntuBoxTask. - new(:precise64, - :precise, 'amd64', chef: chef, puppet: puppet, babushka: babushka) + desc 'Build an Ubuntu Precise 64 bits box' + BuildUbuntuBoxTaskV2. + new(:precise64, + :precise, 'amd64', chef: chef, puppet: puppet, babushka: babushka) - desc 'Build an Ubuntu Quantal 64 bits box' - BuildUbuntuBoxTask. - new(:quantal64, - :quantal, 'amd64', chef: chef, puppet: puppet, babushka: babushka) + desc 'Build an Ubuntu Quantal 64 bits box' + BuildUbuntuBoxTaskV2. + new(:quantal64, + :quantal, 'amd64', chef: chef, puppet: puppet, babushka: babushka) - # FIXME: Find out how to install chef on raring - desc 'Build an Ubuntu Raring 64 bits box' - BuildUbuntuBoxTask. - new(:raring64, - :raring, 'amd64', chef: false, puppet: puppet, babushka: babushka) + # FIXME: Find out how to install chef on raring + desc 'Build an Ubuntu Raring 64 bits box' + BuildUbuntuBoxTaskV2. + new(:raring64, + :raring, 'amd64', chef: false, puppet: puppet, babushka: babushka) - desc 'Build all Ubuntu boxes' - task :all => %w( precise64 quantal64 raring64 ) + desc 'Build all Ubuntu boxes' + task :all => %w( precise64 quantal64 raring64 ) + end end - end - # FIXME: Find out how to install chef on debian boxes - namespace :debian do - namespace :build do - desc 'Build an Debian Squeeze 64 bits box' - BuildDebianBoxTask. - new(:squeeze64, - :squeeze, 'amd64', chef: false, puppet: puppet, babushka: babushka) + # FIXME: Find out how to install chef on debian boxes + namespace :debian do + namespace :build do + desc 'Build an Debian Squeeze 64 bits box' + BuildDebianBoxTaskV2. + new(:squeeze64, + :squeeze, 'amd64', chef: false, puppet: puppet, babushka: babushka) - desc 'Build an Debian Wheezy 64 bits box' - BuildDebianBoxTask. - new(:wheezy64, - :wheezy, 'amd64', chef: false, puppet: puppet, babushka: babushka) + desc 'Build an Debian Wheezy 64 bits box' + BuildDebianBoxTaskV2. + new(:wheezy64, + :wheezy, 'amd64', chef: false, puppet: puppet, babushka: babushka) - desc 'Build an Debian Sid/unstable 64 bits box' - BuildDebianBoxTask. - new(:sid64, - :sid, 'amd64', chef: false, puppet: puppet, babushka: babushka) + desc 'Build an Debian Sid/unstable 64 bits box' + BuildDebianBoxTaskV2. + new(:sid64, + :sid, 'amd64', chef: false, puppet: puppet, babushka: babushka) - desc 'Build all Debian boxes' - task :all => %w( squeeze64 wheezy64 sid64 ) + desc 'Build all Debian boxes' + task :all => %w( squeeze64 wheezy64 sid64 ) + end end - end - desc 'Build all base boxes for release' - task :build_all => %w( ubuntu:build:all debian:build:all ) + desc 'Build all base boxes for release' + task :build_all => %w( ubuntu:build:all debian:build:all ) + end end diff --git a/tasks/boxes.v3.rake b/tasks/boxes.v3.rake new file mode 100644 index 0000000..115debd --- /dev/null +++ b/tasks/boxes.v3.rake @@ -0,0 +1,80 @@ +require 'pathname' +require 'rake/tasklib' +load 'tasks/boxes.v2.rake' + +class BuildGenericBoxTaskV3 < BuildGenericBoxTaskV2 + def build + # TODO: Build the base box and lxc-create it somehow + super + end +end + +class BuildDebianBoxTaskV3 < BuildGenericBoxTaskV3 + def initialize(name, release, arch, opts = {}) + super(name, 'debian', release, arch, opts) + end +end + +class BuildUbuntuBoxTaskV3 < BuildGenericBoxTaskV3 + def initialize(name, release, arch, opts = {}) + super(name, 'ubuntu', release, arch, opts) + end +end + +chef = ENV['CHEF'] == '1' +puppet = ENV['PUPPET'] == '1' +babushka = ENV['BABUSHKA'] == '1' + +namespace :boxes do + namespace :v3 do + namespace :ubuntu do + namespace :build do + + desc 'Build an Ubuntu Precise 64 bits box' + BuildUbuntuBoxTaskV3. + new(:precise64, + :precise, 'amd64', chef: chef, puppet: puppet, babushka: babushka) + + desc 'Build an Ubuntu Quantal 64 bits box' + BuildUbuntuBoxTaskV3. + new(:quantal64, + :quantal, 'amd64', chef: chef, puppet: puppet, babushka: babushka) + + # FIXME: Find out how to install chef on raring + desc 'Build an Ubuntu Raring 64 bits box' + BuildUbuntuBoxTaskV3. + new(:raring64, + :raring, 'amd64', chef: false, puppet: puppet, babushka: babushka) + + desc 'Build all Ubuntu boxes' + task :all => %w( precise64 quantal64 raring64 ) + end + end + + # FIXME: Find out how to install chef on debian boxes + namespace :debian do + namespace :build do + desc 'Build an Debian Squeeze 64 bits box' + BuildDebianBoxTaskV3. + new(:squeeze64, + :squeeze, 'amd64', chef: false, puppet: puppet, babushka: babushka) + + desc 'Build an Debian Wheezy 64 bits box' + BuildDebianBoxTaskV3. + new(:wheezy64, + :wheezy, 'amd64', chef: false, puppet: puppet, babushka: babushka) + + desc 'Build an Debian Sid/unstable 64 bits box' + BuildDebianBoxTaskV3. + new(:sid64, + :sid, 'amd64', chef: false, puppet: puppet, babushka: babushka) + + desc 'Build all Debian boxes' + task :all => %w( squeeze64 wheezy64 sid64 ) + end + end + + desc 'Build all base boxes for release' + task :build_all => %w( ubuntu:build:all debian:build:all ) + end +end From 06f2063d532912e947e9fc5eaddecc5890092592 Mon Sep 17 00:00:00 2001 From: Fabio Rehm Date: Fri, 7 Jun 2013 21:32:48 -0300 Subject: [PATCH 09/25] Fix error message when building boxes --- tasks/boxes.v2.rake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tasks/boxes.v2.rake b/tasks/boxes.v2.rake index 232ec59..0287897 100644 --- a/tasks/boxes.v2.rake +++ b/tasks/boxes.v2.rake @@ -39,7 +39,7 @@ class BuildGenericBoxTaskV2 < ::Rake::TaskLib if script.readable? sh "sudo #{script} #{args.join(' ')}" else - STDERR.puts "cannot execute #{install_path} (not found?)" + STDERR.puts "cannot execute #{script_name} (not found?)" exit 1 end end From bb51a51ecba94b9f8633430d6f7989f5ad357153 Mon Sep 17 00:00:00 2001 From: Fabio Rehm Date: Fri, 7 Jun 2013 21:40:39 -0300 Subject: [PATCH 10/25] Enable chef for raring base boxes --- tasks/boxes.v2.rake | 2 +- tasks/boxes.v3.rake | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tasks/boxes.v2.rake b/tasks/boxes.v2.rake index 0287897..147161d 100644 --- a/tasks/boxes.v2.rake +++ b/tasks/boxes.v2.rake @@ -145,7 +145,7 @@ namespace :boxes do desc 'Build an Ubuntu Raring 64 bits box' BuildUbuntuBoxTaskV2. new(:raring64, - :raring, 'amd64', chef: false, puppet: puppet, babushka: babushka) + :raring, 'amd64', chef: chef, puppet: puppet, babushka: babushka) desc 'Build all Ubuntu boxes' task :all => %w( precise64 quantal64 raring64 ) diff --git a/tasks/boxes.v3.rake b/tasks/boxes.v3.rake index 115debd..e54beca 100644 --- a/tasks/boxes.v3.rake +++ b/tasks/boxes.v3.rake @@ -44,7 +44,7 @@ namespace :boxes do desc 'Build an Ubuntu Raring 64 bits box' BuildUbuntuBoxTaskV3. new(:raring64, - :raring, 'amd64', chef: false, puppet: puppet, babushka: babushka) + :raring, 'amd64', chef: chef, puppet: puppet, babushka: babushka) desc 'Build all Ubuntu boxes' task :all => %w( precise64 quantal64 raring64 ) From 58435e34622b60341d76da2d70253c02f5d7e87f Mon Sep 17 00:00:00 2001 From: Fabio Rehm Date: Fri, 7 Jun 2013 21:41:25 -0300 Subject: [PATCH 11/25] Remove dead code from common lxc template --- boxes/common/lxc-template | 5 ----- 1 file changed, 5 deletions(-) mode change 100644 => 100755 boxes/common/lxc-template diff --git a/boxes/common/lxc-template b/boxes/common/lxc-template old mode 100644 new mode 100755 index 09a2dce..cf44ee3 --- a/boxes/common/lxc-template +++ b/boxes/common/lxc-template @@ -77,11 +77,6 @@ copy_configuration() path=$1 rootfs=$2 name=$3 - arch=$4 - - if [ $arch = "i386" ]; then - arch="i686" - fi # if there is exactly one veth network entry, make sure it has an # associated hwaddr. From 8e51384802cfed3183b1d87950c870efa82458a5 Mon Sep 17 00:00:00 2001 From: Fabio Rehm Date: Fri, 7 Jun 2013 21:43:17 -0300 Subject: [PATCH 12/25] Extract script to finalize ubuntu boxes --- boxes/ubuntu/finalize | 367 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 367 insertions(+) create mode 100755 boxes/ubuntu/finalize diff --git a/boxes/ubuntu/finalize b/boxes/ubuntu/finalize new file mode 100755 index 0000000..eddbe68 --- /dev/null +++ b/boxes/ubuntu/finalize @@ -0,0 +1,367 @@ +#!/bin/bash + +# This is a modified version of /usr/share/lxc/templates/lxc-ubuntu +# that comes with Ubuntu 13.04 changed to suit vagrant-lxc needs + +# +# template script for generating ubuntu container for LXC +# +# This script consolidates and extends the existing lxc ubuntu scripts +# + +# Copyright © 2011 Serge Hallyn +# Copyright © 2010 Wilhelm Meier +# Author: Wilhelm Meier +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2, as +# published by the Free Software Foundation. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +# + +set -e + +if [ -r /etc/default/lxc ]; then + . /etc/default/lxc +fi + +configure_ubuntu() +{ + rootfs=$1 + release=$2 + hostname=$2 + + # configure the network using the dhcp + cat < $rootfs/etc/network/interfaces +# This file describes the network interfaces available on your system +# and how to activate them. For more information, see interfaces(5). + +# The loopback network interface +auto lo +iface lo inet loopback + +auto eth0 +iface eth0 inet dhcp +EOF + + # set the hostname + cat < $rootfs/etc/hostname +$hostname +EOF + # set minimal hosts + cat < $rootfs/etc/hosts +127.0.0.1 localhost +127.0.1.1 $hostname + +# The following lines are desirable for IPv6 capable hosts +::1 ip6-localhost ip6-loopback +fe00::0 ip6-localnet +ff00::0 ip6-mcastprefix +ff02::1 ip6-allnodes +ff02::2 ip6-allrouters +EOF + + if [ ! -f $rootfs/etc/init/container-detect.conf ]; then + # suppress log level output for udev + sed -i "s/=\"err\"/=0/" $rootfs/etc/udev/udev.conf + + # remove jobs for consoles 5 and 6 since we only create 4 consoles in + # this template + rm -f $rootfs/etc/init/tty{5,6}.conf + fi + + if ! (grep -q vagrant $rootfs/etc/passwd); then + chroot $rootfs useradd --create-home -s /bin/bash vagrant + echo "vagrant:vagrant" | chroot $rootfs chpasswd + fi + + # make sure we have the current locale defined in the container + chroot $rootfs locale-gen en_US.UTF-8 + chroot $rootfs update-locale LANG=en_US.UTF-8 + + return 0 +} + +# finish setting up the user in the container by injecting ssh key and +# adding sudo group membership. +# passed-in user is 'vagrant' +finalize_user() +{ + user=$1 + + sudo_version=$(chroot $rootfs dpkg-query -W -f='${Version}' sudo) + + if chroot $rootfs dpkg --compare-versions $sudo_version gt "1.8.3p1-1"; then + groups="sudo" + else + groups="sudo admin" + fi + + for group in $groups; do + chroot $rootfs groupadd --system $group >/dev/null 2>&1 || true + chroot $rootfs adduser ${user} $group >/dev/null 2>&1 || true + done + + chroot $rootfs cp /etc/sudoers /etc/sudoers.orig >/dev/null 2>&1 || true + chroot $rootfs sed -i -e 's/%sudo\s\+ALL=(ALL:ALL)\s\+ALL/%sudo ALL=NOPASSWD:ALL/g' /etc/sudoers >/dev/null 2>&1 || true + + if [ -n "$auth_key" -a -f "$auth_key" ]; then + u_path="/home/${user}/.ssh" + root_u_path="$rootfs/$u_path" + + mkdir -p $root_u_path + cp $auth_key "$root_u_path/authorized_keys" + chroot $rootfs chown -R ${user}: "$u_path" + + echo "Inserted SSH public key from $auth_key into /home/${user}/.ssh/authorized_keys" + fi + return 0 +} + +write_sourceslist() +{ + # $1 => path to the rootfs + # $2 => architecture we want to add + # $3 => whether to use the multi-arch syntax or not + + case $2 in + amd64|i386) + MIRROR=${MIRROR:-http://archive.ubuntu.com/ubuntu} + SECURITY_MIRROR=${SECURITY_MIRROR:-http://security.ubuntu.com/ubuntu} + ;; + *) + MIRROR=${MIRROR:-http://ports.ubuntu.com/ubuntu-ports} + SECURITY_MIRROR=${SECURITY_MIRROR:-http://ports.ubuntu.com/ubuntu-ports} + ;; + esac + if [ -n "$3" ]; then + cat >> "$1/etc/apt/sources.list" << EOF +deb [arch=$2] $MIRROR ${release} main restricted universe multiverse +deb [arch=$2] $MIRROR ${release}-updates main restricted universe multiverse +deb [arch=$2] $SECURITY_MIRROR ${release}-security main restricted universe multiverse +EOF + else + cat >> "$1/etc/apt/sources.list" << EOF +deb $MIRROR ${release} main restricted universe multiverse +deb $MIRROR ${release}-updates main restricted universe multiverse +deb $SECURITY_MIRROR ${release}-security main restricted universe multiverse +EOF + fi +} + +trim() +{ + rootfs=$1 + release=$2 + + # provide the lxc service + cat < $rootfs/etc/init/lxc.conf +# fake some events needed for correct startup other services + +description "Container Upstart" + +start on startup + +script + rm -rf /var/run/*.pid + rm -rf /var/run/network/* + /sbin/initctl emit stopped JOB=udevtrigger --no-wait + /sbin/initctl emit started JOB=udev --no-wait +end script +EOF + + # fix buggus runlevel with sshd + cat < $rootfs/etc/init/ssh.conf +# ssh - OpenBSD Secure Shell server +# +# The OpenSSH server provides secure shell access to the system. + +description "OpenSSH server" + +start on filesystem +stop on runlevel [!2345] + +expect fork +respawn +respawn limit 10 5 +umask 022 +# replaces SSHD_OOM_ADJUST in /etc/default/ssh +oom never + +pre-start script + test -x /usr/sbin/sshd || { stop; exit 0; } + test -e /etc/ssh/sshd_not_to_be_run && { stop; exit 0; } + test -c /dev/null || { stop; exit 0; } + + mkdir -p -m0755 /var/run/sshd +end script + +# if you used to set SSHD_OPTS in /etc/default/ssh, you can change the +# 'exec' line here instead +exec /usr/sbin/sshd +EOF + + cat < $rootfs/etc/init/console.conf +# console - getty +# +# This service maintains a console on tty1 from the point the system is +# started until it is shut down again. + +start on stopped rc RUNLEVEL=[2345] +stop on runlevel [!2345] + +respawn +exec /sbin/getty -8 38400 /dev/console +EOF + + cat < $rootfs/lib/init/fstab +# /lib/init/fstab: cleared out for bare-bones lxc +EOF + + # remove pointless services in a container + chroot $rootfs /usr/sbin/update-rc.d -f ondemand remove + + chroot $rootfs /bin/bash -c 'cd /etc/init; for f in $(ls u*.conf); do mv $f $f.orig; done' + chroot $rootfs /bin/bash -c 'cd /etc/init; for f in $(ls tty[2-9].conf); do mv $f $f.orig; done' + chroot $rootfs /bin/bash -c 'cd /etc/init; for f in $(ls plymouth*.conf); do mv $f $f.orig; done' + chroot $rootfs /bin/bash -c 'cd /etc/init; for f in $(ls hwclock*.conf); do mv $f $f.orig; done' + chroot $rootfs /bin/bash -c 'cd /etc/init; for f in $(ls module*.conf); do mv $f $f.orig; done' + + # if this isn't lucid, then we need to twiddle the network upstart bits :( + if [ $release != "lucid" ]; then + sed -i 's/^.*emission handled.*$/echo Emitting lo/' $rootfs/etc/network/if-up.d/upstart + fi +} + +post_process() +{ + rootfs=$1 + release=$2 + trim_container=$3 + + if [ $trim_container -eq 1 ]; then + trim $rootfs $release + elif [ ! -f $rootfs/etc/init/container-detect.conf ]; then + # Make sure we have a working resolv.conf + cresolvonf="${rootfs}/etc/resolv.conf" + mv $cresolvonf ${cresolvonf}.lxcbak + cat /etc/resolv.conf > ${cresolvonf} + + # for lucid, if not trimming, then add the ubuntu-virt + # ppa and install lxcguest + if [ $release = "lucid" ]; then + chroot $rootfs apt-get update + chroot $rootfs apt-get install --force-yes -y python-software-properties + chroot $rootfs add-apt-repository ppa:ubuntu-virt/ppa + fi + + chroot $rootfs apt-get update + chroot $rootfs apt-get install --force-yes -y lxcguest + + # Restore old resolv.conf + rm -f ${cresolvonf} + mv ${cresolvonf}.lxcbak ${cresolvonf} + fi + + # If the container isn't running a native architecture, setup multiarch + if [ -x "$(ls -1 ${rootfs}/usr/bin/qemu-*-static 2>/dev/null)" ]; then + dpkg_version=$(chroot $rootfs dpkg-query -W -f='${Version}' dpkg) + if chroot $rootfs dpkg --compare-versions $dpkg_version ge "1.16.2"; then + chroot $rootfs dpkg --add-architecture ${hostarch} + else + mkdir -p ${rootfs}/etc/dpkg/dpkg.cfg.d + echo "foreign-architecture ${hostarch}" > ${rootfs}/etc/dpkg/dpkg.cfg.d/lxc-multiarch + fi + + # Save existing value of MIRROR and SECURITY_MIRROR + DEFAULT_MIRROR=$MIRROR + DEFAULT_SECURITY_MIRROR=$SECURITY_MIRROR + + # Write a new sources.list containing both native and multiarch entries + > ${rootfs}/etc/apt/sources.list + write_sourceslist $rootfs $arch "native" + + MIRROR=$DEFAULT_MIRROR + SECURITY_MIRROR=$DEFAULT_SECURITY_MIRROR + write_sourceslist $rootfs $hostarch "multiarch" + + # Finally update the lists and install upstart using the host architecture + chroot $rootfs apt-get update + chroot $rootfs apt-get install --force-yes -y --no-install-recommends upstart:${hostarch} mountall:${hostarch} iproute:${hostarch} isc-dhcp-client:${hostarch} + fi + + # rmdir /dev/shm for containers that have /run/shm + # I'm afraid of doing rm -rf $rootfs/dev/shm, in case it did + # get bind mounted to the host's /run/shm. So try to rmdir + # it, and in case that fails move it out of the way. + if [ ! -L $rootfs/dev/shm ] && [ -d $rootfs/run/shm ] && [ -e $rootfs/dev/shm ]; then + mv $rootfs/dev/shm $rootfs/dev/shm.bak + ln -s /run/shm $rootfs/dev/shm + fi +} + +release=precise # Default to the last Ubuntu LTS release for non-Ubuntu systems +if [ -f /etc/lsb-release ]; then + . /etc/lsb-release + if [ "$DISTRIB_ID" = "Ubuntu" ]; then + release=$DISTRIB_CODENAME + fi +fi + +arch=$(uname -m) + +# Code taken from debootstrap +if [ -x /usr/bin/dpkg ] && /usr/bin/dpkg --print-architecture >/dev/null 2>&1; then + arch=`/usr/bin/dpkg --print-architecture` +elif type udpkg >/dev/null 2>&1 && udpkg --print-architecture >/dev/null 2>&1; then + arch=`/usr/bin/udpkg --print-architecture` +else + arch=$(uname -m) + if [ "$arch" = "i686" ]; then + arch="i386" + elif [ "$arch" = "x86_64" ]; then + arch="amd64" + elif [ "$arch" = "armv7l" ]; then + arch="armel" + fi +fi + + +if [ "$(id -u)" != "0" ]; then + echo "This script should be run as 'root'" + exit 1 +fi + +declare cache=`readlink -f .` \ + arch=$1 \ + release=$2 \ + auth_key=$3 + +# detect rootfs +cache=`readlink -f .` +rootfs="${cache}/rootfs" + +configure_ubuntu $rootfs $release +if [ $? -ne 0 ]; then + echo "failed to configure ubuntu $release for a container" + exit 1 +fi + +post_process $rootfs $release $trim_container + +finalize_user vagrant + +echo "" +echo "##" +echo "# The default user is 'vagrant' with password 'vagrant'!" +echo "# Use the 'sudo' command to run tasks as root in the container." +echo "##" +echo "" From e159a9b53422ce57eb8ef8a2300713443695d354 Mon Sep 17 00:00:00 2001 From: Fabio Rehm Date: Fri, 7 Jun 2013 21:44:25 -0300 Subject: [PATCH 13/25] Looks like this is working... --- tasks/boxes.v3.rake | 37 +++++++++++++++++++++++++++++++++++-- 1 file changed, 35 insertions(+), 2 deletions(-) diff --git a/tasks/boxes.v3.rake b/tasks/boxes.v3.rake index e54beca..bc094dc 100644 --- a/tasks/boxes.v3.rake +++ b/tasks/boxes.v3.rake @@ -4,8 +4,41 @@ load 'tasks/boxes.v2.rake' class BuildGenericBoxTaskV3 < BuildGenericBoxTaskV2 def build - # TODO: Build the base box and lxc-create it somehow - super + check_if_box_has_been_built! + + FileUtils.mkdir_p 'boxes/temp' unless File.exist? 'base/temp' + check_for_partially_built_box! + + pwd = Dir.pwd + sh 'mkdir -p boxes/temp/' + Dir.chdir 'boxes/temp' do + download + install_cfg_engines + finalize + prepare_package_contents pwd + sh 'sudo rm -rf rootfs' + sh "tar -czf tmp-package.box ./*" + end + + sh 'mkdir -p boxes/output' + sh "cp boxes/temp/tmp-package.box boxes/output/#{@file}" + sh "rm -rf boxes/temp" + end + + def finalize + require 'vagrant' + auth_key = Vagrant.source_root.join('keys', 'vagrant.pub').expand_path.to_s + run 'finalize', @arch, @release, auth_key + end + + def prepare_package_contents(pwd) + run 'cleanup' + sh 'sudo rm -f rootfs.tar.gz' + sh 'sudo tar --numeric-owner -czf rootfs.tar.gz ./rootfs/*' + sh "sudo chown #{ENV['USER']}:#{`id -gn`.strip} rootfs.tar.gz" + sh "cp #{pwd}/boxes/common/lxc-template ." + sh "cp #{pwd}/boxes/common/lxc.conf ." + sh "cp #{pwd}/boxes/common/metadata.json ." end end From 93003caec389cd567ea9eb73bee3955d9fde69f7 Mon Sep 17 00:00:00 2001 From: Fabio Rehm Date: Sat, 8 Jun 2013 01:00:21 -0300 Subject: [PATCH 14/25] Better be cautious here --- lib/vagrant-lxc/action/handle_box_metadata.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/vagrant-lxc/action/handle_box_metadata.rb b/lib/vagrant-lxc/action/handle_box_metadata.rb index 9d8bf8a..e20613b 100644 --- a/lib/vagrant-lxc/action/handle_box_metadata.rb +++ b/lib/vagrant-lxc/action/handle_box_metadata.rb @@ -49,7 +49,7 @@ module Vagrant end def validate_box - if @box.metadata.fetch('version').to_i < 2 + if [2, 3].include? @box.metadata.fetch('version').to_i raise Errors::InvalidBoxVersion.new name: @box.name end From e4e64d69eb19fddfa562ae3da502b326c6caa193 Mon Sep 17 00:00:00 2001 From: Fabio Rehm Date: Sat, 8 Jun 2013 01:00:39 -0300 Subject: [PATCH 15/25] TODO --- lib/vagrant-lxc/action/handle_box_metadata.rb | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/vagrant-lxc/action/handle_box_metadata.rb b/lib/vagrant-lxc/action/handle_box_metadata.rb index e20613b..91fbd13 100644 --- a/lib/vagrant-lxc/action/handle_box_metadata.rb +++ b/lib/vagrant-lxc/action/handle_box_metadata.rb @@ -40,6 +40,8 @@ module Vagrant def template_opts @template_opts ||= @box.metadata.fetch('template-opts', {}).dup.merge!( '--tarball' => rootfs_tarball, + # TODO: Deprecate this, the rootfs should be ready for vagrant-lxc + # SSH access at this point '--auth-key' => Vagrant.source_root.join('keys', 'vagrant.pub').expand_path.to_s ) end From b8d58d8a1334e3e211d719c21f2a674a135c7529 Mon Sep 17 00:00:00 2001 From: Fabio Rehm Date: Sat, 8 Jun 2013 01:02:28 -0300 Subject: [PATCH 16/25] Add lxc.conf to box package --- lib/vagrant-lxc/action/setup_package_files.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/vagrant-lxc/action/setup_package_files.rb b/lib/vagrant-lxc/action/setup_package_files.rb index a1a8a73..652f507 100644 --- a/lib/vagrant-lxc/action/setup_package_files.rb +++ b/lib/vagrant-lxc/action/setup_package_files.rb @@ -45,6 +45,7 @@ module Vagrant 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 + FileUtils.cp box_dir.join('lxc.conf').to_s, @env['package.directory'].to_s end end end From dcc0ce281f7e8465fcf77be250847e78d79c0661 Mon Sep 17 00:00:00 2001 From: Fabio Rehm Date: Sat, 8 Jun 2013 01:13:51 -0300 Subject: [PATCH 17/25] Lets be clear about box version error --- lib/vagrant-lxc/action/handle_box_metadata.rb | 7 +++++-- lib/vagrant-lxc/errors.rb | 4 ++-- locales/en.yml | 4 ++++ 3 files changed, 11 insertions(+), 4 deletions(-) diff --git a/lib/vagrant-lxc/action/handle_box_metadata.rb b/lib/vagrant-lxc/action/handle_box_metadata.rb index 91fbd13..73ceeb8 100644 --- a/lib/vagrant-lxc/action/handle_box_metadata.rb +++ b/lib/vagrant-lxc/action/handle_box_metadata.rb @@ -3,6 +3,7 @@ module Vagrant module Action # Prepare arguments to be used for lxc-create class HandleBoxMetadata + SUPPORTED_VERSIONS = [2, 3] def initialize(app, env) @app = app @logger = Log4r::Logger.new("vagrant::lxc::action::handle_box_metadata") @@ -51,8 +52,10 @@ module Vagrant end def validate_box - if [2, 3].include? @box.metadata.fetch('version').to_i - raise Errors::InvalidBoxVersion.new name: @box.name + unless SUPPORTED_VERSIONS.include? @box.metadata.fetch('version').to_i + raise Errors::IncompatibleBox.new name: @box.name, + found: @box.metadata.fetch('version').to_i, + supported: SUPPORTED_VERSIONS.join(' and ') end unless File.exists?(template_src) diff --git a/lib/vagrant-lxc/errors.rb b/lib/vagrant-lxc/errors.rb index bb056ee..169e567 100644 --- a/lib/vagrant-lxc/errors.rb +++ b/lib/vagrant-lxc/errors.rb @@ -14,8 +14,8 @@ module Vagrant class RootFSTarballMissing < Vagrant::Errors::VagrantError error_key(:lxc_invalid_box_version) end - class InvalidBoxVersion < Vagrant::Errors::VagrantError - error_key(:lxc_invalid_box_version) + class IncompatibleBox < Vagrant::Errors::VagrantError + error_key(:lxc_incompatible_box) end end end diff --git a/locales/en.yml b/locales/en.yml index 1242a75..50edd3d 100644 --- a/locales/en.yml +++ b/locales/en.yml @@ -33,6 +33,10 @@ en: For more information on the failure, enable detailed logging by setting the environment variable VAGRANT_LOG to DEBUG. + lxc_incompatible_box: |- + The base box you are trying to use is not compatible with the installed + vagrant-lxc version. Supported box versions are %{supported} but %{found} was found. + lxc_template_file_missing: |- The template file used for creating the container was not found for %{name} box. From 433cf3f9dff192e91846267776e50c3dc4ae9de5 Mon Sep 17 00:00:00 2001 From: Fabio Rehm Date: Sat, 8 Jun 2013 01:16:25 -0300 Subject: [PATCH 18/25] Add entry about new box format to the changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9f159fb..58d8810 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,6 @@ ## [0.?.?](https://github.com/fgrehm/vagrant-lxc/compare/v0.3.4...master) (unreleased) + - New box format [#89](https://github.com/fgrehm/vagrant-lxc/issues/89) - BTRFS-friendly base boxes [#81](https://github.com/fgrehm/vagrant-lxc/issues/81) - Extended templates path lookup [#77](https://github.com/fgrehm/vagrant-lxc/issues/77) (tks to @aries1980) - Fix default group on the rake task [#82](https://github.com/fgrehm/vagrant-lxc/issues/82) (tks to @cduez) From 7bd9377fa667267ed15a32db354b8e99f50e881f Mon Sep 17 00:00:00 2001 From: Fabio Rehm Date: Sat, 8 Jun 2013 01:26:22 -0300 Subject: [PATCH 19/25] Add missing mount points to base lxc config file --- boxes/common/lxc.conf | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/boxes/common/lxc.conf b/boxes/common/lxc.conf index 7e5fc80..4b5962c 100644 --- a/boxes/common/lxc.conf +++ b/boxes/common/lxc.conf @@ -44,3 +44,7 @@ lxc.cgroup.devices.allow = c 1:7 rwm lxc.cgroup.devices.allow = c 10:228 rwm #kvm lxc.cgroup.devices.allow = c 10:232 rwm + +# mounts point +lxc.mount.entry = proc proc proc nodev,noexec,nosuid 0 0 +lxc.mount.entry = sysfs sys sysfs defaults 0 0 From a5eb824fa474222673e84fc6fd13a791bd4ea745 Mon Sep 17 00:00:00 2001 From: Fabio Rehm Date: Sat, 8 Jun 2013 01:30:02 -0300 Subject: [PATCH 20/25] Extract script to finalize debian base boxes --- boxes/debian/finalize | 207 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 207 insertions(+) create mode 100755 boxes/debian/finalize diff --git a/boxes/debian/finalize b/boxes/debian/finalize new file mode 100755 index 0000000..329f086 --- /dev/null +++ b/boxes/debian/finalize @@ -0,0 +1,207 @@ +#!/bin/bash + +# This is a modified version of /usr/share/lxc/templates/lxc-debian +# that comes with Ubuntu 13.04 changed to suit vagrant-lxc needs + +set -e + +if [ -r /etc/default/lxc ]; then + . /etc/default/lxc +fi + +SUITE=${SUITE:-wheezy} +MIRROR=${MIRROR:-http://ftp.debian.org/debian} + +configure_debian() +{ + rootfs=$1 + hostname=$2 + release=$2 + + # squeeze only has /dev/tty and /dev/tty0 by default, + # therefore creating missing device nodes for tty1-4. + for tty in $(seq 1 4); do + if [ ! -e $rootfs/dev/tty$tty ]; then + mknod $rootfs/dev/tty$tty c 4 $tty + fi + done + + # configure the inittab + cat < $rootfs/etc/inittab +id:3:initdefault: +si::sysinit:/etc/init.d/rcS +l0:0:wait:/etc/init.d/rc 0 +l1:1:wait:/etc/init.d/rc 1 +l2:2:wait:/etc/init.d/rc 2 +l3:3:wait:/etc/init.d/rc 3 +l4:4:wait:/etc/init.d/rc 4 +l5:5:wait:/etc/init.d/rc 5 +l6:6:wait:/etc/init.d/rc 6 +# Normally not reached, but fallthrough in case of emergency. +z6:6:respawn:/sbin/sulogin +1:2345:respawn:/sbin/getty 38400 console +#c1:12345:respawn:/sbin/getty 38400 tty1 linux +c2:12345:respawn:/sbin/getty 38400 tty2 linux +c3:12345:respawn:/sbin/getty 38400 tty3 linux +c4:12345:respawn:/sbin/getty 38400 tty4 linux +p6::ctrlaltdel:/sbin/init 6 +p0::powerfail:/sbin/init 0 +EOF + + # disable selinux in debian + mkdir -p $rootfs/selinux + echo 0 > $rootfs/selinux/enforce + + # configure the network using the dhcp + cat < $rootfs/etc/network/interfaces +auto lo +iface lo inet loopback + +auto eth0 +iface eth0 inet dhcp +EOF + + # set the hostname + cat < $rootfs/etc/hostname +$hostname +EOF + + # set the host in case it is not set so that sudo does not complain about the host + if ! (grep -q $hostname $rootfs/etc/hosts); then + chroot $rootfs sed -i -e \ + "s/^127.0.0.1\(\s\+\)localhost$/127.0.0.1\1localhost\n127.0.0.1\1${hostname}/g" \ + /etc/hosts >/dev/null 2>&1 || true + fi + + # set default locale + cat < $rootfs/etc/locale.gen +en_US.UTF-8 UTF-8 +EOF + echo "default locale set to en_US.UTF-8 UTF-8" + chroot $rootfs locale-gen 'en_US.UTF-8' > /dev/null 2>&1 + chroot $rootfs update-locale LANG='en_US.UTF-8' + echo 'update-locale done' + + # remove pointless services in a container + chroot $rootfs /usr/sbin/update-rc.d -f checkroot.sh remove + chroot $rootfs /usr/sbin/update-rc.d -f umountfs remove + chroot $rootfs /usr/sbin/update-rc.d -f hwclock.sh remove + chroot $rootfs /usr/sbin/update-rc.d -f hwclockfirst.sh remove + + echo "root: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 + chroot $rootfs adduser vagrant sudo >/dev/null 2>&1 || true + chroot $rootfs cp /etc/sudoers /etc/sudoers.orig >/dev/null 2>&1 || true + chroot $rootfs sed -i -e \ + 's/%sudo\s\+ALL=(ALL\(:ALL\)\?)\s\+ALL/%sudo ALL=NOPASSWD:ALL/g' \ + /etc/sudoers >/dev/null 2>&1 || true + fi + + return 0 +} + +cleanup() +{ + rm -rf ${cache}/partial + rm -rf ${cache}/rootfs +} + +add_ssh_key() +{ + user=$1 + + if [ -n "$auth_key" -a -f "$auth_key" ]; then + u_path="/home/${user}/.ssh" + root_u_path="$rootfs/$u_path" + + mkdir -p $root_u_path + cp $auth_key "$root_u_path/authorized_keys" + chroot $rootfs chown -R ${user}: "$u_path" + + echo "Inserted SSH public key from $auth_key into /home/${user}/.ssh/authorized_keys" + fi +} + +disable_tmp_cleanup() { + rootfs=$1 + chroot $rootfs /usr/sbin/update-rc.d -f checkroot-bootclean.sh remove + chroot $rootfs /usr/sbin/update-rc.d -f mountall-bootclean.sh remove + chroot $rootfs /usr/sbin/update-rc.d -f mountnfs-bootclean.sh remove +} + +usage() +{ + cat <] [ -S | --auth-key ] +release: the debian release (e.g. wheezy): defaults to host release on debian, otherwise uses latest stable +arch: the container architecture (e.g. amd64): defaults to host arch +auth-key: SSH Public key file to inject into container +EOF + return 0 +} + +options=$(getopt -o a:b:hp:r:xn:Fd:C -l arch:,help,path:,release:,name:,flush-cache,auth-key:,debug:,tarball: -- "$@") +if [ $? -ne 0 ]; then + usage $(basename $0) + exit 1 +fi +eval set -- "$options" + +release=wheezy # Default to the last Debian stable release + +arch=$(uname -m) + +# Code taken from debootstrap +if [ -x /usr/bin/dpkg ] && /usr/bin/dpkg --print-architecture >/dev/null 2>&1; then + arch=`/usr/bin/dpkg --print-architecture` +elif type udpkg >/dev/null 2>&1 && udpkg --print-architecture >/dev/null 2>&1; then + arch=`/usr/bin/udpkg --print-architecture` +else + arch=$(uname -m) + if [ "$arch" = "i686" ]; then + arch="i386" + elif [ "$arch" = "x86_64" ]; then + arch="amd64" + elif [ "$arch" = "armv7l" ]; then + arch="armel" + fi +fi + +if [ "$(id -u)" != "0" ]; then + echo "This script should be run as 'root'" + exit 1 +fi + +declare cache=`readlink -f .` \ + arch=$1 \ + release=$2 \ + auth_key=$3 + +# detect rootfs +cache=`readlink -f .` +rootfs="${cache}/rootfs" + +configure_debian $rootfs $release +if [ $? -ne 0 ]; then + echo "failed to configure debian $release for a container" + exit 1 +fi + +add_ssh_key vagrant + +# vagrant and / or plugins might mount some shared folders under /tmp by default +# (like puppet manifests) and we need to make sure no shared folder gets its +# contents removed because of it. For more information, please check: +# https://github.com/fgrehm/vagrant-lxc/issues/68 +disable_tmp_cleanup $rootfs + +echo "" +echo "##" +echo "# The default user is 'vagrant' with password 'vagrant'!" +echo "# Use the 'sudo' command to run tasks as root in the container." +echo "##" +echo "" From 51d26b00cd1daf005ce02e457ce0219704a36756 Mon Sep 17 00:00:00 2001 From: Fabio Rehm Date: Sat, 8 Jun 2013 02:01:50 -0300 Subject: [PATCH 21/25] Clean up the mess I left behind --- spec/unit/action/handle_box_metadata_spec.rb | 2 +- spec/unit/action/setup_package_files_spec.rb | 7 ++++++- spec/unit/driver/cli_spec.rb | 4 +++- spec/unit/driver_spec.rb | 7 +++++-- 4 files changed, 15 insertions(+), 5 deletions(-) diff --git a/spec/unit/action/handle_box_metadata_spec.rb b/spec/unit/action/handle_box_metadata_spec.rb index 2d3df93..578fbf9 100644 --- a/spec/unit/action/handle_box_metadata_spec.rb +++ b/spec/unit/action/handle_box_metadata_spec.rb @@ -50,7 +50,7 @@ describe Vagrant::LXC::Action::HandleBoxMetadata do metadata['version'] = '1' expect { subject.call(env) - }.to raise_error(Vagrant::LXC::Errors::InvalidBoxVersion) + }.to raise_error(Vagrant::LXC::Errors::IncompatibleBox) end it 'raises an error if the rootfs tarball cant be found' do diff --git a/spec/unit/action/setup_package_files_spec.rb b/spec/unit/action/setup_package_files_spec.rb index 4e50189..68d3133 100644 --- a/spec/unit/action/setup_package_files_spec.rb +++ b/spec/unit/action/setup_package_files_spec.rb @@ -14,7 +14,8 @@ describe Vagrant::LXC::Action::SetupPackageFiles do before do box.directory.mkdir - [box.directory.join('lxc-template'), box.directory.join('metadata.json'), rootfs_path].each do |file| + files = %w( lxc-template metadata.json lxc.conf ).map { |f| box.directory.join(f) } + (files + [rootfs_path]).each do |file| file.open('w') { |f| f.puts file.to_s } end @@ -34,6 +35,10 @@ describe Vagrant::LXC::Action::SetupPackageFiles do env['package.directory'].join('metadata.json').should be_file end + it 'copies box lxc.conf to package directory' do + env['package.directory'].join('lxc-template').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 diff --git a/spec/unit/driver/cli_spec.rb b/spec/unit/driver/cli_spec.rb index 9394459..3498b6a 100644 --- a/spec/unit/driver/cli_spec.rb +++ b/spec/unit/driver/cli_spec.rb @@ -38,13 +38,14 @@ describe Vagrant::LXC::Driver::CLI do describe 'create' do let(:template) { 'quantal-64' } let(:name) { 'quantal-container' } + let(:config_file) { 'config' } let(:template_args) { { '--extra-param' => 'param', '--other' => 'value' } } subject { described_class.new(name) } before do subject.stub(:run) { |*args| @run_args = args } - subject.create(template, template_args) + subject.create(template, config_file, template_args) end it 'issues a lxc-create with provided template, container name and hash of arguments' do @@ -52,6 +53,7 @@ describe Vagrant::LXC::Driver::CLI do :create, '--template', template, '--name', name, + '-f', config_file, '--', '--extra-param', 'param', '--other', 'value' diff --git a/spec/unit/driver_spec.rb b/spec/unit/driver_spec.rb index 1b0833d..f657648 100644 --- a/spec/unit/driver_spec.rb +++ b/spec/unit/driver_spec.rb @@ -35,6 +35,7 @@ describe Vagrant::LXC::Driver do let(:template_name) { 'auto-assigned-template-id' } let(:template_path) { '/path/to/lxc-template-from-box' } let(:template_opts) { {'--some' => 'random-option'} } + let(:config_file) { '/path/to/lxc-config-from-box' } let(:rootfs_tarball) { '/path/to/cache/rootfs.tar.gz' } let(:cli) { fire_double('Vagrant::LXC::Driver::CLI', :create => true, :name= => true) } @@ -42,7 +43,7 @@ describe Vagrant::LXC::Driver do before do subject.stub(:import_template).and_yield(template_name) - subject.create name, template_path, template_opts + subject.create name, template_path, config_file, template_opts end it 'sets the cli object container name' do @@ -52,6 +53,7 @@ describe Vagrant::LXC::Driver do it 'creates container with the right arguments' do cli.should have_received(:create).with( template_name, + config_file, template_opts ) end @@ -72,6 +74,7 @@ describe Vagrant::LXC::Driver do describe 'start' do let(:customizations) { [['a', '1'], ['b', '2']] } let(:internal_customization) { ['internal', 'customization'] } + let(:rootfs) { ['rootfs', subject.rootfs_path.to_s] } let(:cli) { fire_double('Vagrant::LXC::Driver::CLI', start: true) } subject { described_class.new('name', cli) } @@ -83,7 +86,7 @@ describe Vagrant::LXC::Driver do end it 'starts container with configured customizations' do - cli.should have_received(:start).with(customizations + [internal_customization], nil) + cli.should have_received(:start).with(customizations + [internal_customization, rootfs], nil) end it 'expects a transition to running state to take place' do From 8512c5ace776d0e9b429eaec1ba26562b866e640 Mon Sep 17 00:00:00 2001 From: Fabio Rehm Date: Sat, 8 Jun 2013 02:07:56 -0300 Subject: [PATCH 22/25] Prevent `vagrant package` from blowing up --- lib/vagrant-lxc/action/setup_package_files.rb | 4 +- spec/unit/action/setup_package_files_spec.rb | 39 ++++++++++++------- 2 files changed, 29 insertions(+), 14 deletions(-) diff --git a/lib/vagrant-lxc/action/setup_package_files.rb b/lib/vagrant-lxc/action/setup_package_files.rb index 652f507..8743861 100644 --- a/lib/vagrant-lxc/action/setup_package_files.rb +++ b/lib/vagrant-lxc/action/setup_package_files.rb @@ -45,7 +45,9 @@ module Vagrant 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 - FileUtils.cp box_dir.join('lxc.conf').to_s, @env['package.directory'].to_s + if (conf = box_dir.join('lxc.conf')).exist? + FileUtils.cp conf.to_s, @env['package.directory'].to_s + end end end end diff --git a/spec/unit/action/setup_package_files_spec.rb b/spec/unit/action/setup_package_files_spec.rb index 68d3133..c5a4c7b 100644 --- a/spec/unit/action/setup_package_files_spec.rb +++ b/spec/unit/action/setup_package_files_spec.rb @@ -20,27 +20,40 @@ describe Vagrant::LXC::Action::SetupPackageFiles do 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 + context 'when all files exist' do + before { subject.call(env) } + + 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 'copies box lxc.conf to package directory' do + env['package.directory'].join('lxc-template').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 - it 'copies metadata.json to package directory' do - env['package.directory'].join('metadata.json').should be_file - end + context 'when lxc.conf file is not present' do + before do + box.directory.join('lxc.conf').delete + end - it 'copies box lxc.conf to package directory' do - env['package.directory'].join('lxc-template').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 + it 'does not blow up' do + expect { subject.call(env) }.to_not raise_error + end end end From 1c5727dd7b22c9a4f94788b6f413beb5fbe3d3a0 Mon Sep 17 00:00:00 2001 From: Fabio Rehm Date: Sat, 8 Jun 2013 02:41:43 -0300 Subject: [PATCH 23/25] Remove dead code from debian finalize script --- boxes/debian/finalize | 19 ------------------- 1 file changed, 19 deletions(-) diff --git a/boxes/debian/finalize b/boxes/debian/finalize index 329f086..67681d4 100755 --- a/boxes/debian/finalize +++ b/boxes/debian/finalize @@ -132,25 +132,6 @@ disable_tmp_cleanup() { chroot $rootfs /usr/sbin/update-rc.d -f mountnfs-bootclean.sh remove } -usage() -{ - cat <] [ -S | --auth-key ] -release: the debian release (e.g. wheezy): defaults to host release on debian, otherwise uses latest stable -arch: the container architecture (e.g. amd64): defaults to host arch -auth-key: SSH Public key file to inject into container -EOF - return 0 -} - -options=$(getopt -o a:b:hp:r:xn:Fd:C -l arch:,help,path:,release:,name:,flush-cache,auth-key:,debug:,tarball: -- "$@") -if [ $? -ne 0 ]; then - usage $(basename $0) - exit 1 -fi -eval set -- "$options" - release=wheezy # Default to the last Debian stable release arch=$(uname -m) From f3ff5c9f24cdff258f71b444c6d833248fbd5068 Mon Sep 17 00:00:00 2001 From: Fabio Rehm Date: Sat, 8 Jun 2013 13:55:29 -0300 Subject: [PATCH 24/25] Remove hwaddr from base lxc.conf so that each container gets a different one when running the generic lxc template --- boxes/common/lxc.conf | 1 - 1 file changed, 1 deletion(-) diff --git a/boxes/common/lxc.conf b/boxes/common/lxc.conf index 4b5962c..610875c 100644 --- a/boxes/common/lxc.conf +++ b/boxes/common/lxc.conf @@ -1,5 +1,4 @@ lxc.network.type=veth -lxc.network.hwaddr = 00:16:3e:7f:04:b2 lxc.network.link=lxcbr0 lxc.network.flags=up From 83377bf8a4b0e5d2aa53dd6c8ce6abd111bc0426 Mon Sep 17 00:00:00 2001 From: Fabio Rehm Date: Sat, 8 Jun 2013 19:01:56 -0300 Subject: [PATCH 25/25] Mention Chef support for Raring base boxes on CHANGELOG --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 58d8810..81d0179 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,6 @@ ## [0.?.?](https://github.com/fgrehm/vagrant-lxc/compare/v0.3.4...master) (unreleased) + - Enable Chef for Ubuntu Raring base box - New box format [#89](https://github.com/fgrehm/vagrant-lxc/issues/89) - BTRFS-friendly base boxes [#81](https://github.com/fgrehm/vagrant-lxc/issues/81) - Extended templates path lookup [#77](https://github.com/fgrehm/vagrant-lxc/issues/77) (tks to @aries1980)