diff --git a/BOXES.md b/BOXES.md index 2fd1de1..10ebde3 100644 --- a/BOXES.md +++ b/BOXES.md @@ -14,7 +14,7 @@ For example: ``` git clone https://github.com/fgrehm/vagrant-lxc.git cd vagrant-lxc/boxes -PUPPET=1 CHEF=1 sudo -E ./build-ubuntu-box.sh precise amd64 +PUPPET=1 CHEF=1 make precise ``` Will build a Ubuntu Precise x86_64 box with latest Puppet and Chef pre-installed, please refer to the scripts for more information. @@ -30,15 +30,16 @@ on knowing what makes a base box for vagrant-lxc, here's what's needed: | --- | --- | | `lxc-template` | Script responsible for creating and setting up the container (used with `lxc-create`), a ["generic script"]() is provided along with project's source. | | `rootfs.tar.gz` | Compressed container rootfs tarball (need to remeber to pass in `--numeric-owner` when creating it) | -| `lxc.conf` | | -| `metadata.json` | | +| `lxc.conf` | File passed in to `lxc-create -f` | +| `lxc-config` | Box specific configuration to be _appended_ to the container's config file | +| `metadata.json` | Required by Vagrant | ### metadata.json ```json { "provider": "lxc", - "version": "3", + "version": "1.0.0", "built-on": "Sat Sep 21 21:10:00 UTC 2013", "template-opts": { "--arch": "amd64", diff --git a/CHANGELOG.md b/CHANGELOG.md index 9e2052a..6c887dc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,41 @@ ## [0.8.1](https://github.com/fgrehm/vagrant-lxc/compare/v0.8.0...master) (unreleased) +DEPRECATIONS: + + - Support to **all Vagrant versions prior to 1.5 are now deprecated**, there is a + [small layer](lib/vagrant-backports) that ensures compatibility with versions + starting with 1.1.5 but there is no guarantee that it will stick for too long. + - Boxes released prior to this version are now deprecated and won't be available + after the final 1.0.0 release. + - `--auth-key` argument is no longer provided to `lxc-template`. This will cause + all official base boxes prior to 09/28/2013 to break. + +BASE BOXES: + + - Switched to [`lxc-download`](https://github.com/lxc/lxc/blob/master/templates/lxc-download.in) + as the "reference implementation" for the generic `lxc-template` script [[GH-236]] + - Added support for _appending_ custom boxes configs with the `lxc-config` file, + allowing usage of host's specific configs from `/etc/lxc/default.conf` [[GH-222]] + - Include NFS client on Ubuntu and Debian base boxes [[GH-218]] + - Improved output for building base boxes + - Improved `vagrant` user `sudo` rights [[GH-231]] [[GH-188]] + - Locale configuration may follow builder's LANG environment variable [[GH-221]] + - Enable bash completion for Debian base boxes [[GH-220]] + - Fix broken locale in Ubuntu boxes [[GH-201]] + - Install `python-software-properties` by default [[GH-155]] + - Fix apt-get error when building Ubuntu boxes [[GH-200]] + +[GH-236]: https://github.com/fgrehm/vagrant-lxc/issues/236 +[GH-222]: https://github.com/fgrehm/vagrant-lxc/issues/222 +[GH-218]: https://github.com/fgrehm/vagrant-lxc/issues/218 +[GH-231]: https://github.com/fgrehm/vagrant-lxc/issues/231 +[GH-221]: https://github.com/fgrehm/vagrant-lxc/issues/221 +[GH-220]: https://github.com/fgrehm/vagrant-lxc/issues/220 +[GH-201]: https://github.com/fgrehm/vagrant-lxc/issues/201 +[GH-188]: https://github.com/fgrehm/vagrant-lxc/issues/188 +[GH-155]: https://github.com/fgrehm/vagrant-lxc/issues/155 +[GH-200]: https://github.com/fgrehm/vagrant-lxc/issues/200 + ## [0.8.0](https://github.com/fgrehm/vagrant-lxc/compare/v0.7.0...v0.8.0) (Feb 26, 2014) diff --git a/boxes/.gitignore b/boxes/.gitignore new file mode 100644 index 0000000..31dbbff --- /dev/null +++ b/boxes/.gitignore @@ -0,0 +1 @@ +/log diff --git a/boxes/Makefile b/boxes/Makefile new file mode 100644 index 0000000..0e66145 --- /dev/null +++ b/boxes/Makefile @@ -0,0 +1,34 @@ +UBUNTU_BOXES= precise quantal raring saucy trusty +DEBIAN_BOXES= squeeze wheezy sid jessie +TODAY=$(shell date -u +"%Y-%m-%d") + +default: + +all: ubuntu debian + +ubuntu: $(UBUNTU_BOXES) +debian: $(DEBIAN_BOXES) + +# REFACTOR: Figure out how can we reduce duplicated code +$(UBUNTU_BOXES): CONTAINER = "vagrant-lxc-base-${@}-amd64" +$(UBUNTU_BOXES): PACKAGE = "output/${TODAY}/vagrant-lxc-${@}-amd64.box" +$(UBUNTU_BOXES): + @mkdir -p $$(dirname $(PACKAGE)) + @sudo -E ./mk-debian.sh ubuntu $(@) amd64 $(CONTAINER) $(PACKAGE) + @sudo chmod +rw $(PACKAGE) + @sudo chown ${USER}: $(PACKAGE) +$(DEBIAN_BOXES): CONTAINER = "vagrant-lxc-base-${@}-amd64" +$(DEBIAN_BOXES): PACKAGE = "output/${TODAY}/vagrant-lxc-${@}-amd64.box" +$(DEBIAN_BOXES): + @mkdir -p $$(dirname $(PACKAGE)) + @sudo -E ./mk-debian.sh debian $(@) amd64 $(CONTAINER) $(PACKAGE) + @sudo chmod +rw $(PACKAGE) + @sudo chown ${USER}: $(PACKAGE) + +clean: ALL_BOXES = ${DEBIAN_BOXES} ${UBUNTU_BOXES} +clean: + @for r in $(ALL_BOXES); do \ + sudo -E ./clean.sh $${r}\ + vagrant-lxc-base-$${r}-amd64 \ + output/${TODAY}/vagrant-lxc-$${r}-amd64.box; \ + done diff --git a/boxes/build-all.sh b/boxes/build-all.sh deleted file mode 100755 index 59ff2b2..0000000 --- a/boxes/build-all.sh +++ /dev/null @@ -1,22 +0,0 @@ -#!/bin/bash - -# set -x -set -e - -# Convenience script used for building all of the base boxes available - -# Ubuntu boxes -sudo -E ./build-ubuntu-box.sh precise -sudo -E ./build-ubuntu-box.sh quantal -sudo -E ./build-ubuntu-box.sh raring -sudo -E ./build-ubuntu-box.sh saucy - -# Debian boxes -sudo -E ./build-debian-box.sh squeeze -sudo -E ./build-debian-box.sh wheezy -sudo -E ./build-debian-box.sh sid - -for box in precise raring quantal saucy squeeze wheezy sid; do - box="vagrant-lxc-${box}-amd64-`date +%Y-%m-%d`.box" - ~/bin/dropbox_uploader.sh upload output/${box} Public/ -done diff --git a/boxes/build-debian-box.sh b/boxes/build-debian-box.sh deleted file mode 100755 index 4b467bb..0000000 --- a/boxes/build-debian-box.sh +++ /dev/null @@ -1,167 +0,0 @@ -#!/bin/bash - -# set -x -set -e - -# Script used to build Debian base vagrant-lxc containers, currently limited to -# host's arch -# -# USAGE: -# $ cd boxes && sudo ./build-debian-box.sh DEBIAN_RELEASE -# -# To enable Chef or any other configuration management tool pass '1' to the -# corresponding env var: -# $ CHEF=1 sudo -E ./build-debian-box.sh DEBIAN_RELEASE -# $ PUPPET=1 sudo -E ./build-debian-box.sh DEBIAN_RELEASE -# $ SALT=1 sudo -E ./build-debian-box.sh DEBIAN_RELEASE -# $ BABUSHKA=1 sudo -E ./build-debian-box.sh DEBIAN_RELEASE - -################################################################################## -# 0 - Initial setup and sanity checks - -TODAY=$(date -u +"%Y-%m-%d") -NOW=$(date -u) -RELEASE=${1:-"wheezy"} -ARCH=$(dpkg --print-architecture) # This is what the Debian template will use under the hood -PKG=vagrant-lxc-${RELEASE}-${ARCH}-${TODAY}.box -WORKING_DIR=/tmp/vagrant-lxc-${RELEASE} -VAGRANT_KEY="ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEA6NF8iallvQVp22WDkTkyrtvp9eWW6A8YVr+kz4TjGYe7gHzIw+niNltGEFHzD8+v1I2YJ6oXevct1YeS0o9HZyN1Q9qgCgzUFtdOKLv6IedplqoPkcmF0aYet2PkEDo3MlTBckFXPITAMzF8dJSIFo9D8HfdOV0IAdx4O7PtixWKn5y2hMNG0zQPyUecp4pzC6kivAIhyfHilFR61RGL+GPXQ2MWZWFYbAGjyiYJnAmCP3NOTd0jMZEnDkbUvxhMmBYSdETk1rRgm+R4LOzFUGaHqHDLKLX+FIPKcF96hrucXzcWyLbIbEgE98OHlnVYCzRdK8jlqm8tehUc9c9WhQ== vagrant insecure public key" -ROOTFS=/var/lib/lxc/${RELEASE}-base/rootfs - -# Providing '1' will enable these tools -CHEF=${CHEF:-0} -PUPPET=${PUPPET:-0} -SALT=${SALT:-0} -BABUSHKA=${BABUSHKA:-0} - -# Path to files bundled with the box -CWD=`readlink -f .` -LXC_TEMPLATE=${CWD}/common/lxc-template -LXC_CONF=${CWD}/common/lxc.conf -METATADA_JSON=${CWD}/common/metadata.json - -# Set up a working dir -mkdir -p $WORKING_DIR - -if [ -f "${WORKING_DIR}/${PKG}" ]; then - echo "Found a box on ${WORKING_DIR}/${PKG} already!" - exit 1 -fi - -################################################################################## -# 1 - Create the base container - -if $(lxc-ls | grep -q "${RELEASE}-base"); then - echo "Base container already exists, please remove it with \`lxc-destroy -n ${RELEASE}-base\`!" - exit 1 -else - export SUITE=$RELEASE - lxc-create -n ${RELEASE}-base -t debian -fi - - -###################################### -# 2 - Fix some known issues - -# Fixes some networking issues -# See https://github.com/fgrehm/vagrant-lxc/issues/91 for more info -sed -i -e "s/\(127.0.0.1\s\+localhost\)/\1\n127.0.1.1\t${RELEASE}-base\n/g" ${ROOTFS}/etc/hosts - -# Ensures that `/tmp` does not get cleared on halt -# See https://github.com/fgrehm/vagrant-lxc/issues/68 for more info -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 - -# Ensure locales are properly set, based on http://linux.livejournal.com/1880366.html -sed -i "s/^# en_US/en_US/" ${ROOTFS}/etc/locale.gen -chroot $ROOTFS /usr/sbin/locale-gen -chroot $ROOTFS update-locale LANG=en_US.UTF-8 - - -################################################################################## -# 3 - Prepare vagrant user -sudo chroot ${ROOTFS} useradd --create-home -s /bin/bash vagrant - -echo -n 'vagrant:vagrant' | chroot ${ROOTFS} chpasswd - - -################################################################################## -# 4 - Setup SSH access and passwordless sudo - -# Configure SSH access -mkdir -p ${ROOTFS}/home/vagrant/.ssh -echo $VAGRANT_KEY > ${ROOTFS}/home/vagrant/.ssh/authorized_keys -chroot ${ROOTFS} chown -R vagrant: /home/vagrant/.ssh - -chroot ${ROOTFS} apt-get install sudo -y --force-yes -chroot ${ROOTFS} adduser vagrant sudo - -# Enable passwordless sudo for users under the "sudo" group -cp ${ROOTFS}/etc/sudoers{,.orig} -sed -i -e \ - 's/%sudo\s\+ALL=(ALL\(:ALL\)\?)\s\+ALL/%sudo ALL=NOPASSWD:ALL/g' \ - ${ROOTFS}/etc/sudoers - - -################################################################################## -# 5 - Add some goodies and update packages - -PACKAGES=(vim curl wget man-db bash-completion ca-certificates) -chroot ${ROOTFS} apt-get install ${PACKAGES[*]} -y --force-yes -chroot ${ROOTFS} apt-get upgrade -y --force-yes - - -################################################################################## -# 6 - Configuration management tools - -if [ $CHEF = 1 ]; then - ./common/install-chef $ROOTFS -fi - -if [ $PUPPET = 1 ]; then - ./common/install-puppet $ROOTFS -fi - -if [ $SALT = 1 ]; then - ./common/install-salt-debian $ROOTFS -fi - -if [ $BABUSHKA = 1 ]; then - ./common/install-babushka $ROOTFS -fi - - -################################################################################## -# 7 - Free up some disk space - -rm -rf ${ROOTFS}/tmp/* -chroot ${ROOTFS} apt-get clean - - -################################################################################## -# 8 - Build box package - -# Compress container's rootfs -cd $(dirname $ROOTFS) -tar --numeric-owner -czf /tmp/vagrant-lxc-${RELEASE}/rootfs.tar.gz ./rootfs/* - -# Prepare package contents -cd $WORKING_DIR -cp $LXC_TEMPLATE . -cp $LXC_CONF . -cp $METATADA_JSON . -chmod +x lxc-template -sed -i "s//${NOW}/" metadata.json - -# Vagrant box! -tar -czf $PKG ./* - -chmod +rw ${WORKING_DIR}/${PKG} -mkdir -p ${CWD}/output -mv ${WORKING_DIR}/${PKG} ${CWD}/output - -# Clean up after ourselves -rm -rf ${WORKING_DIR} - -echo "The base box was built successfully to ${CWD}/output/${PKG}" diff --git a/boxes/build-openmandriva-box.sh b/boxes/build-openmandriva-box.sh index 1e091f0..332aba7 100644 --- a/boxes/build-openmandriva-box.sh +++ b/boxes/build-openmandriva-box.sh @@ -92,7 +92,7 @@ sed -i 's/Defaults requiretty/\# Defaults requiretty/' ${ROOTFS}/etc/sudoers sed -i 's/\#%wheel/\%wheel/' ${ROOTFS}/etc/sudoers sed -i 's/\# %wheel/\%wheel/' ${ROOTFS}/etc/sudoers # sed -i -e \ -# 's/%sudo\s\+ALL=(ALL\(:ALL\)\?)\s\+ALL/%sudo ALL=NOPASSWD:ALL/g' \ +# 's/%sudo\s\+ALL=(ALL\(:ALL\)\?)\s\+ALL/%sudo ALL=(ALL) NOPASSWD:ALL/g' \ # ${ROOTFS}/etc/sudoers diff --git a/boxes/build-ubuntu-box.sh b/boxes/build-ubuntu-box.sh deleted file mode 100755 index dd72def..0000000 --- a/boxes/build-ubuntu-box.sh +++ /dev/null @@ -1,151 +0,0 @@ -#!/bin/bash - -# set -x -set -e - -# Script used to build Ubuntu base vagrant-lxc containers -# -# USAGE: -# $ cd boxes && sudo ./build-ubuntu-box.sh UBUNTU_RELEASE BOX_ARCH -# -# To enable Chef or any other configuration management tool pass '1' to the -# corresponding env var: -# $ CHEF=1 sudo -E ./build-ubuntu-box.sh UBUNTU_RELEASE BOX_ARCH -# $ PUPPET=1 sudo -E ./build-ubuntu-box.sh UBUNTU_RELEASE BOX_ARCH -# $ SALT=1 sudo -E ./build-ubuntu-box.sh UBUNTU_RELEASE BOX_ARCH -# $ BABUSHKA=1 sudo -E ./build-ubuntu-box.sh UBUNTU_RELEASE BOX_ARCH - -################################################################################## -# 0 - Initial setup and sanity checks - -TODAY=$(date -u +"%Y-%m-%d") -NOW=$(date -u) -RELEASE=${1:-"raring"} -ARCH=${2:-"amd64"} -PKG=vagrant-lxc-${RELEASE}-${ARCH}-${TODAY}.box -WORKING_DIR=/tmp/vagrant-lxc-${RELEASE} -VAGRANT_KEY="ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEA6NF8iallvQVp22WDkTkyrtvp9eWW6A8YVr+kz4TjGYe7gHzIw+niNltGEFHzD8+v1I2YJ6oXevct1YeS0o9HZyN1Q9qgCgzUFtdOKLv6IedplqoPkcmF0aYet2PkEDo3MlTBckFXPITAMzF8dJSIFo9D8HfdOV0IAdx4O7PtixWKn5y2hMNG0zQPyUecp4pzC6kivAIhyfHilFR61RGL+GPXQ2MWZWFYbAGjyiYJnAmCP3NOTd0jMZEnDkbUvxhMmBYSdETk1rRgm+R4LOzFUGaHqHDLKLX+FIPKcF96hrucXzcWyLbIbEgE98OHlnVYCzRdK8jlqm8tehUc9c9WhQ== vagrant insecure public key" -ROOTFS=/var/lib/lxc/${RELEASE}-base/rootfs - -# Providing '1' will enable these tools -CHEF=${CHEF:-0} -PUPPET=${PUPPET:-0} -SALT=${SALT:-0} -BABUSHKA=${BABUSHKA:-0} - -# Path to files bundled with the box -CWD=`readlink -f .` -LXC_TEMPLATE=${CWD}/common/lxc-template -LXC_CONF=${CWD}/common/lxc.conf -METATADA_JSON=${CWD}/common/metadata.json - -# Set up a working dir -mkdir -p $WORKING_DIR - -if [ -f "${WORKING_DIR}/${PKG}" ]; then - echo "Found a box on ${WORKING_DIR}/${PKG} already!" - exit 1 -fi - -################################################################################## -# 1 - Create the base container - -if $(lxc-ls | grep -q "${RELEASE}-base"); then - echo "Base container already exists, please remove it with \`lxc-destroy -n ${RELEASE}-base\`!" - exit 1 -else - lxc-create -n ${RELEASE}-base -t ubuntu -- --release ${RELEASE} --arch ${ARCH} -fi - -# Fixes some networking issues -# See https://github.com/fgrehm/vagrant-lxc/issues/91 for more info -echo 'ff02::3 ip6-allhosts' >> ${ROOTFS}/etc/hosts - - -################################################################################## -# 2 - Prepare vagrant user - -mv ${ROOTFS}/home/{ubuntu,vagrant} -chroot ${ROOTFS} usermod -l vagrant -d /home/vagrant ubuntu -chroot ${ROOTFS} groupmod -n vagrant ubuntu - -echo -n 'vagrant:vagrant' | chroot ${ROOTFS} chpasswd - - -################################################################################## -# 3 - Setup SSH access and passwordless sudo - -# Configure SSH access -mkdir -p ${ROOTFS}/home/vagrant/.ssh -echo $VAGRANT_KEY > ${ROOTFS}/home/vagrant/.ssh/authorized_keys -chroot ${ROOTFS} chown -R vagrant: /home/vagrant/.ssh - -# Enable passwordless sudo for users under the "sudo" group -cp ${ROOTFS}/etc/sudoers{,.orig} -sed -i -e \ - 's/%sudo\s\+ALL=(ALL\(:ALL\)\?)\s\+ALL/%sudo ALL=NOPASSWD:ALL/g' \ - ${ROOTFS}/etc/sudoers - - -################################################################################## -# 4 - Add some goodies and update packages - -PACKAGES=(vim curl wget man-db bash-completion) -chroot ${ROOTFS} apt-get install ${PACKAGES[*]} -y --force-yes -chroot ${ROOTFS} apt-get upgrade -y --force-yes - - -################################################################################## -# 5 - Configuration management tools - -if [ $CHEF = 1 ]; then - ./common/install-chef $ROOTFS -fi - -if [ $PUPPET = 1 ]; then - ./common/install-puppet $ROOTFS -fi - -if [ $SALT = 1 ]; then - ./common/install-salt $ROOTFS -fi - -if [ $BABUSHKA = 1 ]; then - ./common/install-babushka $ROOTFS -fi - - -################################################################################## -# 6 - Free up some disk space - -rm -rf ${ROOTFS}/tmp/* -chroot ${ROOTFS} apt-get clean - - -################################################################################## -# 7 - Build box package - -# Compress container's rootfs -cd $(dirname $ROOTFS) -tar --numeric-owner -czf /tmp/vagrant-lxc-${RELEASE}/rootfs.tar.gz ./rootfs/* - -# Prepare package contents -cd $WORKING_DIR -cp $LXC_TEMPLATE . -cp $LXC_CONF . -cp $METATADA_JSON . -chmod +x lxc-template -sed -i "s//${NOW}/" metadata.json - -# Vagrant box! -tar -czf $PKG ./* - -chmod +rw ${WORKING_DIR}/${PKG} -mkdir -p ${CWD}/output -mv ${WORKING_DIR}/${PKG} ${CWD}/output - -# Clean up after ourselves -rm -rf ${WORKING_DIR} -lxc-destroy -n ${RELEASE}-base - -echo "The base box was built successfully to ${CWD}/output/${PKG}" diff --git a/boxes/clean.sh b/boxes/clean.sh new file mode 100755 index 0000000..079498e --- /dev/null +++ b/boxes/clean.sh @@ -0,0 +1,27 @@ +#!/bin/bash +set -e + +source common/ui.sh + +export RELEASE=$1 +export CONTAINER=$2 +export PACKAGE=$3 +export LOG=$(readlink -f .)/log/${CONTAINER}.log + +info "Cleaning ${RELEASE} artifacts..." + +# If container exists, check if want to continue +if $(lxc-ls | grep -q ${CONTAINER}); then + log "Removing '${CONTAINER}' container" + lxc-stop -n ${CONTAINER} &>/dev/null || true + lxc-destroy -n ${CONTAINER} +else + log "The container '${CONTAINER}' does not exist" +fi + +if [ -e ${PACKAGE} ]; then + log "Removing '${PACKAGE}'" + rm -f ${PACKAGE} +else + log "The package '${PACKAGE}' does not exist" +fi diff --git a/boxes/common/cleanup b/boxes/common/cleanup deleted file mode 100755 index bfa6653..0000000 --- a/boxes/common/cleanup +++ /dev/null @@ -1,7 +0,0 @@ -#!/bin/bash - -cache=`readlink -f .` -rootfs="${cache}/rootfs" - -rm -rf $rootfs/tmp/* -chroot $rootfs apt-get clean diff --git a/boxes/common/download.sh b/boxes/common/download.sh new file mode 100755 index 0000000..f20b4d1 --- /dev/null +++ b/boxes/common/download.sh @@ -0,0 +1,43 @@ +#!/bin/bash +set -e + +source common/ui.sh +source common/utils.sh + +# If container exists, check if want to continue +if $(lxc-ls | grep -q ${CONTAINER}); then + if ! $(confirm "The '${CONTAINER}' container already exists, do you want to continue building the box?" 'y'); then + log 'Aborting...' + exit 1 + fi +fi + +# If container exists and wants to continue building the box +if $(lxc-ls | grep -q ${CONTAINER}); then + if $(confirm "Do you want to rebuild the '${CONTAINER}' container?" 'n'); then + log "Destroying container ${CONTAINER}..." + utils.lxc.stop + utils.lxc.destroy + else + log "Reusing existing container..." + exit 0 + fi +fi + +# If we got to this point, we need to create the container +log "Creating container..." +if [ $RELEASE = 'raring' ]; then + utils.lxc.create -t ubuntu -- \ + --release ${RELEASE} \ + --arch ${ARCH} +elif [ $RELEASE = 'squeeze' ]; then + utils.lxc.create -t debian -- \ + --release ${RELEASE} \ + --arch ${ARCH} +else + utils.lxc.create -t download -- \ + --dist ${DISTRIBUTION} \ + --release ${RELEASE} \ + --arch ${ARCH} +fi +log "Container created!" diff --git a/boxes/common/install-babushka b/boxes/common/install-babushka deleted file mode 100755 index a770bbb..0000000 --- a/boxes/common/install-babushka +++ /dev/null @@ -1,16 +0,0 @@ -#!/bin/bash - -set -e - -rootfs=$1 - -echo "installing babushka" -cat > $rootfs/tmp/install-babushka.sh << EOF -#!/bin/sh -curl https://babushka.me/up | sudo bash - -EOF -chmod +x $rootfs/tmp/install-babushka.sh -chroot $rootfs /tmp/install-babushka.sh - -rm -rf $rootfs/tmp/* diff --git a/boxes/common/install-chef b/boxes/common/install-chef deleted file mode 100755 index 2eeda2f..0000000 --- a/boxes/common/install-chef +++ /dev/null @@ -1,15 +0,0 @@ -#!/bin/bash - -set -e - -rootfs=$1 - -echo "installing chef" -cat > $rootfs/tmp/install-chef.sh << EOF -#!/bin/sh -curl -L https://www.opscode.com/chef/install.sh -k | sudo bash -EOF -chmod +x $rootfs/tmp/install-chef.sh -chroot $rootfs /tmp/install-chef.sh - -rm -rf $rootfs/tmp/* diff --git a/boxes/common/install-puppet b/boxes/common/install-puppet deleted file mode 100755 index d159d4f..0000000 --- a/boxes/common/install-puppet +++ /dev/null @@ -1,13 +0,0 @@ -#!/bin/bash - -set -e - -rootfs=$1 - -echo "installing puppet" -wget http://apt.puppetlabs.com/puppetlabs-release-stable.deb -O "${rootfs}/tmp/puppetlabs-release-stable.deb" -chroot $rootfs dpkg -i "/tmp/puppetlabs-release-stable.deb" -chroot $rootfs apt-get update -chroot $rootfs apt-get install puppet -y --force-yes - -rm -rf $rootfs/tmp/* diff --git a/boxes/common/install-salt b/boxes/common/install-salt deleted file mode 100755 index b982117..0000000 --- a/boxes/common/install-salt +++ /dev/null @@ -1,12 +0,0 @@ -#!/bin/bash - -set -e - -rootfs=$1 - -echo "installing salt" -chroot $rootfs apt-add-repository -y ppa:saltstack/salt -chroot $rootfs apt-get update -chroot $rootfs apt-get install salt-minion -y --force-yes - -rm -rf $rootfs/tmp/* diff --git a/boxes/common/install-salt-debian b/boxes/common/install-salt-debian deleted file mode 100755 index 20209da..0000000 --- a/boxes/common/install-salt-debian +++ /dev/null @@ -1,28 +0,0 @@ -#!/bin/bash - -set -e - -rootfs=$1 - -echo "installing salt" - -if [ $SUITE == "squeeze" ]; then - SALT_SOURCE="deb http://debian.saltstack.com/debian squeeze-saltstack main\ndeb http://backports.debian.org/debian-backports squeeze-backports main contrib non-free" -elif [ $SUITE == "sid" ]; then - SALT_SOURCE="deb http://debian.saltstack.com/debian unstable main" -else - SALT_SOURCE="deb http://debian.saltstack.com/debian wheezy-saltstack main" -fi - -cat > $rootfs/tmp/install-salt << EOF -#!/bin/sh -echo "$SALT_SOURCE" > /etc/apt/sources.list.d/saltstack.list -wget -q -O- "http://debian.saltstack.com/debian-salt-team-joehealy.gpg.key" | apt-key add - -apt-get update -apt-get install -y salt-minion -apt-get clean -EOF - -chroot $rootfs sh /tmp/install-salt - -rm -rf $rootfs/tmp/* diff --git a/boxes/common/lxc-template b/boxes/common/lxc-template index 202d068..1899ad3 100755 --- a/boxes/common/lxc-template +++ b/boxes/common/lxc-template @@ -1,226 +1,164 @@ #!/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 - +# This is a modified version of /usr/share/lxc/templates/lxc-download +# that comes with ubuntu-lxc 1.0.0 stable from ppa 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 © 2014 Stéphane Graber +# Copyright © 2014 Fábio Rehm # +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. -# 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 library 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 +# Lesser General Public License for more details. -# 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 Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 +# USA -# 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 -eu -set -e +LXC_HOOK_DIR="/usr/share/lxc/hooks" +LXC_TEMPLATE_CONFIG="/usr/share/lxc/config" -if [ -r /etc/default/lxc ]; then - . /etc/default/lxc -fi +LXC_MAPPED_GID= +LXC_MAPPED_UID= +LXC_NAME= +LXC_PATH= +LXC_ROOTFS= +LXC_TARBALL= +LXC_CONFIG= -extract_rootfs() -{ - tarball=$1 - arch=$2 - rootfs=$3 - - echo "Extracting $tarball ..." - mkdir -p $rootfs - (cd $rootfs && tar xfz $tarball --strip-components=2) - 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 - - grep -q "^lxc.rootfs" $path/config 2>/dev/null || echo "lxc.rootfs = $rootfs" >> $path/config - - # 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() -{ +usage() { cat <] [-T|--tarball -arch: the container architecture (e.g. amd64): defaults to host arch +vagrant-lxc default template + +Required arguments: +[ --tarball ]: The full path of the rootfs tarball + +Optional arguments: +[ --config ]: Configuration file to be used when building the container +[ -h | --help ]: This help message + +LXC internal arguments (do not pass manually!): +[ --name ]: The container name +[ --path ]: The path to the container +[ --rootfs ]: The path to the container's rootfs +[ --mapped-uid ]: A uid map (user namespaces) +[ --mapped-gid ]: A gid map (user namespaces) 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:,rootfs: -- "$@") +options=$(getopt -o h -l tarball:,config:,help:,name:,path:,rootfs:,mapped-uid:,mapped-gid: -- "$@")SS + 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;; - --rootfs) rootfs=$2; shift 2;; - -p|--path) path=$2; shift 2;; - -n|--name) name=$2; shift 2;; - -T|--tarball) tarball=$2; shift 2;; - -a|--arch) arch=$2; shift 2;; - -S|--auth-key) auth_key=$2; shift 2;; - -d|--debug) debug=1; shift 1;; - --) shift 1; break ;; - *) break ;; + -h|--help) usage $0 && exit 0;; + --config) LXC_CONFIG=$2; shift 2;; + --tarball) LXC_TARBALL=$2; shift 2;; + --name) LXC_NAME=$2; shift 2;; + --path) LXC_PATH=$2; shift 2;; + --rootfs) LXC_ROOTFS=$2; shift 2;; + --mapped-uid) LXC_MAPPED_UID=$2; shift 2;; + --mapped-gid) LXC_MAPPED_GID=$2; shift 2;; + *) 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" +if [ -z "${LXC_NAME}" ]; then + echo "'name' parameter is required" exit 1 fi -if [ -z "$path" ]; then +if [ -z "${LXC_TARBALL}" ]; then + echo "'tarball' parameter is required" + exit 1 +fi + +if [ -z "${LXC_ROOTFS}" ]; then + echo "'rootfs' parameter is required" + exit 1 +fi + +if [ -z "${LXC_CONFIG}" ]; then + echo "'config' parameter is required" + exit 1 +fi + +if [ -z "${LXC_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 +# Unpack the rootfs +echo "Unpacking the rootfs" -# detect rootfs -config="$path/config" -# if $rootfs exists here, it was passed in with --rootfs -if [ -z "$rootfs" ]; then - if grep -q '^lxc.rootfs' $config 2>/dev/null ; then - rootfs=`grep 'lxc.rootfs =' $config | awk -F= '{ print $2 }'` - else - rootfs=$path/rootfs +( + flock -x 200 + if [ $? -ne 0 ]; then + echo "Cache repository is busy." + exit 1 fi + + mkdir -p ${LXC_ROOTFS} + (cd ${LXC_ROOTFS} && tar xfz ${LXC_TARBALL} --strip-components=2) + if [ $? -ne 0 ]; then + echo "Failed to extract rootfs" + exit 1 + fi + +) 200>/var/lock/subsys/lxc + +mkdir -p ${LXC_ROOTFS}/dev/pts/ + +## Extract all the network config entries +sed -i -e "/lxc.network/{w ${LXC_PATH}/config-network" -e "d}" \ + ${LXC_PATH}/config + +## Extract any other config entry +sed -i -e "/lxc./{w ${LXC_PATH}/config-auto" -e "d}" ${LXC_PATH}/config + +## Add the container-specific config +echo "" >> ${LXC_PATH}/config +echo "##############################################" >> ${LXC_PATH}/config +echo "# Container specific configuration (automatically set)" >> ${LXC_PATH}/config +if [ -e "${LXC_PATH}/config-auto" ]; then + cat ${LXC_PATH}/config-auto >> ${LXC_PATH}/config + rm ${LXC_PATH}/config-auto +fi +echo "lxc.utsname = ${LXC_NAME}" >> ${LXC_PATH}/config + +## Re-add the previously removed network config +if [ -e "${LXC_PATH}/config-network" ]; then + echo "" >> ${LXC_PATH}/config + echo "##############################################" >> ${LXC_PATH}/config + echo "# Network configuration (automatically set)" >> ${LXC_PATH}/config + cat ${LXC_PATH}/config-network >> ${LXC_PATH}/config + rm ${LXC_PATH}/config-network fi -install_ubuntu $rootfs $release $tarball -if [ $? -ne 0 ]; then - echo "failed to install ubuntu $release" - exit 1 -fi +## Append the defaults +echo "" >> ${LXC_PATH}/config +echo "##############################################" >> ${LXC_PATH}/config +echo "# vagrant-lxc base box specific configuration" >> ${LXC_PATH}/config +cat ${LXC_CONFIG} >> ${LXC_PATH}/config -copy_configuration $path $rootfs $name $arch -if [ $? -ne 0 ]; then - echo "failed write configuration file" - exit 1 -fi +# Empty section for lxc.customize calls from vagrantfile +echo "" >> ${LXC_PATH}/config +echo "##############################################" >> ${LXC_PATH}/config +echo "# vagrant-lxc container specific configuration" >> ${LXC_PATH}/config -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 "" +exit 0 diff --git a/boxes/common/lxc.conf b/boxes/common/lxc.conf deleted file mode 100644 index 610875c..0000000 --- a/boxes/common/lxc.conf +++ /dev/null @@ -1,49 +0,0 @@ -lxc.network.type=veth -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 - -# mounts point -lxc.mount.entry = proc proc proc nodev,noexec,nosuid 0 0 -lxc.mount.entry = sysfs sys sysfs defaults 0 0 diff --git a/boxes/common/package.sh b/boxes/common/package.sh new file mode 100755 index 0000000..853f653 --- /dev/null +++ b/boxes/common/package.sh @@ -0,0 +1,34 @@ +#!/bin/bash +set -e + +source common/ui.sh + +# TODO: Create file with build date / time on container + +info "Packaging '${CONTAINER}' to '${PACKAGE}'..." + +debug 'Stopping container' +lxc-stop -n ${CONTAINER} &>/dev/null || true + +if [ -f ${WORKING_DIR}/rootfs.tar.gz ]; then + log "Removing previous rootfs tarball" + rm -f ${WORKING_DIR}/rootfs.tar.gz +fi + +log "Compressing container's rootfs" +pushd $(dirname ${ROOTFS}) &>>${LOG} + tar --numeric-owner --anchored --exclude=./rootfs/dev/log -czf \ + ${WORKING_DIR}/rootfs.tar.gz ./rootfs/* +popd &>>${LOG} + +# Prepare package contents +log 'Preparing box package contents' +cp common/lxc-template ${WORKING_DIR} +cp conf/${DISTRIBUTION} ${WORKING_DIR}/lxc-config +cp conf/metadata.json ${WORKING_DIR} +sed -i "s//${NOW}/" ${WORKING_DIR}/metadata.json + +# Vagrant box! +log 'Packaging box' +TARBALL=$(readlink -f ${PACKAGE}) +(cd ${WORKING_DIR} && tar -czf $TARBALL ./*) diff --git a/boxes/common/prepare-vagrant-user.sh b/boxes/common/prepare-vagrant-user.sh new file mode 100755 index 0000000..fdeebaf --- /dev/null +++ b/boxes/common/prepare-vagrant-user.sh @@ -0,0 +1,46 @@ +#!/bin/bash +set -e + +source common/ui.sh + +export VAGRANT_KEY="ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEA6NF8iallvQVp22WDkTkyrtvp9eWW6A8YVr+kz4TjGYe7gHzIw+niNltGEFHzD8+v1I2YJ6oXevct1YeS0o9HZyN1Q9qgCgzUFtdOKLv6IedplqoPkcmF0aYet2PkEDo3MlTBckFXPITAMzF8dJSIFo9D8HfdOV0IAdx4O7PtixWKn5y2hMNG0zQPyUecp4pzC6kivAIhyfHilFR61RGL+GPXQ2MWZWFYbAGjyiYJnAmCP3NOTd0jMZEnDkbUvxhMmBYSdETk1rRgm+R4LOzFUGaHqHDLKLX+FIPKcF96hrucXzcWyLbIbEgE98OHlnVYCzRdK8jlqm8tehUc9c9WhQ== vagrant insecure public key" + +info "Preparing vagrant user..." + +# Create vagrant user +if $(grep -q 'vagrant' ${ROOTFS}/etc/shadow); then + log 'Skipping vagrant user creation' +elif $(grep -q 'ubuntu' ${ROOTFS}/etc/shadow); then + debug 'vagrant user does not exist, renaming ubuntu user...' + mv ${ROOTFS}/home/{ubuntu,vagrant} + chroot ${ROOTFS} usermod -l vagrant -d /home/vagrant ubuntu &>> ${LOG} + chroot ${ROOTFS} groupmod -n vagrant ubuntu &>> ${LOG} + echo -n 'vagrant:vagrant' | chroot ${ROOTFS} chpasswd + log 'Renamed ubuntu user to vagrant and changed password.' +else + debug 'Creating vagrant user...' + chroot ${ROOTFS} useradd --create-home -s /bin/bash vagrant &>> ${LOG} + chroot ${ROOTFS} adduser vagrant sudo &>> ${LOG} + echo -n 'vagrant:vagrant' | chroot ${ROOTFS} chpasswd +fi + +# Configure SSH access +if [ -d ${ROOTFS}/home/vagrant/.ssh ]; then + log 'Skipping vagrant SSH credentials configuration' +else + debug 'SSH key has not been set' + mkdir -p ${ROOTFS}/home/vagrant/.ssh + echo $VAGRANT_KEY > ${ROOTFS}/home/vagrant/.ssh/authorized_keys + chroot ${ROOTFS} chown -R vagrant: /home/vagrant/.ssh + log 'SSH credentials configured for the vagrant user.' +fi + +# Enable passwordless sudo for the vagrant user +if [ -f ${ROOTFS}/etc/sudoers.d/vagrant ]; then + log 'Skipping sudoers file creation.' +else + debug 'Sudoers file was not found' + echo "vagrant ALL=(ALL) NOPASSWD:ALL" > ${ROOTFS}/etc/sudoers.d/vagrant + chmod 0440 ${ROOTFS}/etc/sudoers.d/vagrant + log 'Sudoers file created.' +fi diff --git a/boxes/common/ui.sh b/boxes/common/ui.sh new file mode 100644 index 0000000..6372a8d --- /dev/null +++ b/boxes/common/ui.sh @@ -0,0 +1,53 @@ +#!/bin/bash + +export NO_COLOR='\033[0m' +export OK_COLOR='\033[32;01m' +export ERROR_COLOR='\033[31;01m' +export WARN_COLOR='\033[33;01m' + +log() { + echo " [${RELEASE}] ${1}" >>${LOG} + echo " [${RELEASE}] ${1}" >&2 +} + +warn() { + echo "==> [${RELEASE}] [WARN] ${1}" >>${LOG} + echo -e "${WARN_COLOR}==> [${RELEASE}] ${1}${NO_COLOR}" +} + +info() { + echo "==> [${RELEASE}] [INFO] ${1}" >>${LOG} + echo -e "${OK_COLOR}==> [${RELEASE}] ${1}${NO_COLOR}" +} + +confirm() { + question=${1} + default=${2} + default_prompt= + + if [ $default = 'n' ]; then + default_prompt="y/N" + default='No' + else + default_prompt="Y/n" + default='Yes' + fi + + echo -e -n "${WARN_COLOR}==> [${RELEASE}] ${question} [${default_prompt}] ${NO_COLOR}" >&2 + read answer + + if [ -z $answer ]; then + debug "Answer not provided, assuming '${default}'" + answer=${default} + fi + + if $(echo ${answer} | grep -q -i '^y'); then + return 0 + else + return 1 + fi +} + +debug() { + [ ! $DEBUG ] || echo " [${RELEASE}] [DEBUG] ${1}" >&2 +} diff --git a/boxes/common/utils.sh b/boxes/common/utils.sh new file mode 100644 index 0000000..e7a7f9f --- /dev/null +++ b/boxes/common/utils.sh @@ -0,0 +1,23 @@ +#!/bin/bash + +utils.lxc.attach() { + cmd="$@" + log "Running [${cmd}] inside '${CONTAINER}' container..." + (lxc-attach -n ${CONTAINER} -- $cmd) &>> ${LOG} +} + +utils.lxc.start() { + lxc-start -d -n ${CONTAINER} &>>${LOG} || true +} + +utils.lxc.stop() { + lxc-stop -n ${CONTAINER} &>>${LOG} || true +} + +utils.lxc.destroy() { + lxc-destroy -n ${CONTAINER} &>>${LOG} +} + +utils.lxc.create() { + lxc-create -n ${CONTAINER} "$@" &>>${LOG} +} diff --git a/boxes/conf/debian b/boxes/conf/debian new file mode 100644 index 0000000..09e5c40 --- /dev/null +++ b/boxes/conf/debian @@ -0,0 +1,62 @@ +# Default pivot location +lxc.pivotdir = lxc_putold + +# Default mount entries +lxc.mount.entry = proc proc proc nodev,noexec,nosuid 0 0 +lxc.mount.entry = sysfs sys sysfs defaults 0 0 +lxc.mount.entry = /sys/fs/fuse/connections sys/fs/fuse/connections none bind,optional 0 0 + +# Default console settings +lxc.tty = 4 +lxc.pts = 1024 + +# Default capabilities +lxc.cap.drop = sys_module mac_admin mac_override sys_time + +# When using LXC with apparmor, the container will be confined by default. +# If you wish for it to instead run unconfined, copy the following line +# (uncommented) to the container's configuration file. +#lxc.aa_profile = unconfined + +# To support container nesting on an Ubuntu host while retaining most of +# apparmor's added security, use the following two lines instead. +#lxc.aa_profile = lxc-container-default-with-nesting +#lxc.hook.mount = /usr/share/lxc/hooks/mountcgroups + +# If you wish to allow mounting block filesystems, then use the following +# line instead, and make sure to grant access to the block device and/or loop +# devices below in lxc.cgroup.devices.allow. +#lxc.aa_profile = lxc-container-default-with-mounting + +# Default cgroup limits +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:0 rwm +lxc.cgroup.devices.allow = c 5:1 rwm +## /dev/{,u}random +lxc.cgroup.devices.allow = c 1:8 rwm +lxc.cgroup.devices.allow = c 1:9 rwm +## /dev/pts/* +lxc.cgroup.devices.allow = c 5:2 rwm +lxc.cgroup.devices.allow = c 136:* rwm +## rtc +lxc.cgroup.devices.allow = c 254:0 rm +## 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 +## To use loop devices, copy the following line to the container's +## configuration file (uncommented). +#lxc.cgroup.devices.allow = b 7:* rwm diff --git a/boxes/common/metadata.json b/boxes/conf/metadata.json similarity index 68% rename from boxes/common/metadata.json rename to boxes/conf/metadata.json index 4ae0cd3..f313050 100644 --- a/boxes/common/metadata.json +++ b/boxes/conf/metadata.json @@ -1,5 +1,5 @@ { "provider": "lxc", - "version": "3", + "version": "1.0.0", "built-on": "" } diff --git a/boxes/conf/ubuntu b/boxes/conf/ubuntu new file mode 100644 index 0000000..1ec323f --- /dev/null +++ b/boxes/conf/ubuntu @@ -0,0 +1,70 @@ +# Default pivot location +lxc.pivotdir = lxc_putold + +# Default mount entries +lxc.mount.entry = proc proc proc nodev,noexec,nosuid 0 0 +lxc.mount.entry = sysfs sys sysfs defaults 0 0 +lxc.mount.entry = /sys/fs/fuse/connections sys/fs/fuse/connections none bind,optional 0 0 +lxc.mount.entry = /sys/kernel/debug sys/kernel/debug none bind,optional 0 0 +lxc.mount.entry = /sys/kernel/security sys/kernel/security none bind,optional 0 0 +lxc.mount.entry = /sys/fs/pstore sys/fs/pstore none bind,optional 0 0 + +# Default console settings +lxc.devttydir = lxc +lxc.tty = 4 +lxc.pts = 1024 + +# Default capabilities +lxc.cap.drop = sys_module mac_admin mac_override sys_time + +# When using LXC with apparmor, the container will be confined by default. +# If you wish for it to instead run unconfined, copy the following line +# (uncommented) to the container's configuration file. +#lxc.aa_profile = unconfined + +# To support container nesting on an Ubuntu host while retaining most of +# apparmor's added security, use the following two lines instead. +#lxc.aa_profile = lxc-container-default-with-nesting +#lxc.hook.mount = /usr/share/lxc/hooks/mountcgroups + +# Uncomment the following line to autodetect squid-deb-proxy configuration on the +# host and forward it to the guest at start time. +#lxc.hook.pre-start = /usr/share/lxc/hooks/squid-deb-proxy-client + +# If you wish to allow mounting block filesystems, then use the following +# line instead, and make sure to grant access to the block device and/or loop +# devices below in lxc.cgroup.devices.allow. +#lxc.aa_profile = lxc-container-default-with-mounting + +# Default cgroup limits +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:0 rwm +lxc.cgroup.devices.allow = c 5:1 rwm +## /dev/{,u}random +lxc.cgroup.devices.allow = c 1:8 rwm +lxc.cgroup.devices.allow = c 1:9 rwm +## /dev/pts/* +lxc.cgroup.devices.allow = c 5:2 rwm +lxc.cgroup.devices.allow = c 136:* rwm +## rtc +lxc.cgroup.devices.allow = c 254:0 rm +## 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 +## To use loop devices, copy the following line to the container's +## configuration file (uncommented). +#lxc.cgroup.devices.allow = b 7:* rwm diff --git a/boxes/debian/clean.sh b/boxes/debian/clean.sh new file mode 100755 index 0000000..0bdd2fb --- /dev/null +++ b/boxes/debian/clean.sh @@ -0,0 +1,16 @@ +#!/bin/bash +set -e + +source common/ui.sh +source common/utils.sh + +debug 'Bringing container up' +utils.lxc.start + +info "Cleaning up '${CONTAINER}'..." + +log 'Removing temporary files...' +rm -rf ${ROOTFS}/tmp/* + +log 'Removing downloaded packages...' +utils.lxc.attach apt-get clean diff --git a/boxes/debian/install-extras.sh b/boxes/debian/install-extras.sh new file mode 100755 index 0000000..cdfe36e --- /dev/null +++ b/boxes/debian/install-extras.sh @@ -0,0 +1,116 @@ +#!/bin/bash +set -e + +source common/ui.sh +source common/utils.sh + +info 'Installing extra packages and upgrading' + +debug 'Bringing container up' +utils.lxc.start + +# Sleep for a bit so that the container can get an IP +log 'Sleeping for 5 seconds...' +sleep 5 + +# TODO: Support for appending to this list from outside +PACKAGES=(vim curl wget man-db bash-completion python-software-properties ca-certificates sudo nfs-common) +if [ $DISTRIBUTION = 'ubuntu' ]; then + PACKAGES+=' software-properties-common' +fi +utils.lxc.attach apt-get update +utils.lxc.attach apt-get install ${PACKAGES[*]} -y --force-yes +utils.lxc.attach apt-get upgrade -y --force-yes + +CHEF=${CHEF:-0} +PUPPET=${PUPPET:-0} +SALT=${SALT:-0} +BABUSHKA=${BABUSHKA:-0} + +if [ $DISTRIBUTION = 'debian' ]; then + # Enable bash-completion + sed -e '/^#if ! shopt -oq posix; then/,/^#fi/ s/^#\(.*\)/\1/g' \ + -i ${ROOTFS}/etc/bash.bashrc +fi + +if [ $CHEF = 1 ]; then + if $(lxc-attach -n ${CONTAINER} -- which chef-solo &>/dev/null); then + log "Chef has been installed on container, skipping" + else + log "Installing Chef" + cat > ${ROOTFS}/tmp/install-chef.sh << EOF +#!/bin/sh +curl -L https://www.opscode.com/chef/install.sh -k | sudo bash +EOF + chmod +x ${ROOTFS}/tmp/install-chef.sh + utils.lxc.attach /tmp/install-chef.sh + fi +else + log "Skipping Chef installation" +fi + +if [ $PUPPET = 1 ]; then + if $(lxc-attach -n ${CONTAINER} -- which puppet &>/dev/null); then + log "Puppet has been installed on container, skipping" + elif [ ${RELEASE} = 'trusty' ]; then + warn "Puppet can't be installed on Ubuntu Trusty 14.04, skipping" + elif [ ${RELEASE} = 'sid' ]; then + warn "Puppet can't be installed on Debian sid, skipping" + else + log "Installing Puppet" + wget http://apt.puppetlabs.com/puppetlabs-release-stable.deb -O "${ROOTFS}/tmp/puppetlabs-release-stable.deb" &>>${LOG} + utils.lxc.attach dpkg -i "/tmp/puppetlabs-release-stable.deb" + utils.lxc.attach apt-get update + utils.lxc.attach apt-get install puppet -y --force-yes + fi +else + log "Skipping Puppet installation" +fi + +if [ $SALT = 1 ]; then + if $(lxc-attach -n ${CONTAINER} -- which salt-minion &>/dev/null); then + log "Salt has been installed on container, skipping" + elif [ ${RELEASE} = 'raring' ]; then + warn "Salt can't be installed on Ubuntu Raring 13.04, skipping" + else + if [ $DISTRIBUTION = 'ubuntu' ]; then + utils.lxc.attach add-apt-repository -y ppa:saltstack/salt + else # DEBIAN + if [ $RELEASE == "squeeze" ]; then + SALT_SOURCE_1="deb http://debian.saltstack.com/debian squeeze-saltstack main" + SALT_SOURCE_2="deb http://backports.debian.org/debian-backports squeeze-backports main contrib non-free" + elif [ $RELEASE == "wheezy" ]; then + SALT_SOURCE_1="deb http://debian.saltstack.com/debian wheezy-saltstack main" + else + SALT_SOURCE_1="deb http://debian.saltstack.com/debian unstable main" + fi + echo $SALT_SOURCE_1 > ${ROOTFS}/etc/apt/sources.list.d/saltstack.list + echo $SALT_SOURCE_2 >> ${ROOTFS}/etc/apt/sources.list.d/saltstack.list + + utils.lxc.attach wget -q -O /tmp/salt.key "http://debian.saltstack.com/debian-salt-team-joehealy.gpg.key" + utils.lxc.attach apt-key add /tmp/salt.key + fi + utils.lxc.attach apt-get update + utils.lxc.attach apt-get install salt-minion -y --force-yes + fi +else + log "Skipping Salt installation" +fi + +if [ $BABUSHKA = 1 ]; then + if $(lxc-attach -n ${CONTAINER} -- which babushka &>/dev/null); then + log "Babushka has been installed on container, skipping" + elif [ ${RELEASE} = 'trusty' ]; then + warn "Babushka can't be installed on Ubuntu Trusty 14.04, skipping" + else + log "Installing Babushka" + cat > $ROOTFS/tmp/install-babushka.sh << EOF +#!/bin/sh +curl https://babushka.me/up | sudo bash +EOF + chmod +x $ROOTFS/tmp/install-babushka.sh + utils.lxc.attach /tmp/install-babushka.sh + fi +else + log "Skipping Babushka installation" +fi diff --git a/boxes/debian/vagrant-lxc-fixes.sh b/boxes/debian/vagrant-lxc-fixes.sh new file mode 100755 index 0000000..fb2d58c --- /dev/null +++ b/boxes/debian/vagrant-lxc-fixes.sh @@ -0,0 +1,33 @@ +#!/bin/bash +set -e + +source common/ui.sh +source common/utils.sh + +# Fixes some networking issues +# See https://github.com/fgrehm/vagrant-lxc/issues/91 for more info +if ! $(grep -q 'ip6-allhosts' ${ROOTFS}/etc/hosts); then + log "Adding ipv6 allhosts entry to container's /etc/hosts" + echo 'ff02::3 ip6-allhosts' >> ${ROOTFS}/etc/hosts +fi + +utils.lxc.start + +if [ ${DISTRIBUTION} = 'debian' ]; then + # Ensure locales are properly set, based on http://askubuntu.com/a/238063 + LANG=${LANG:-en_US.UTF-8} + sed -i "s/^# ${LANG}/${LANG}/" ${ROOTFS}/etc/locale.gen + + # Fixes some networking issues + # See https://github.com/fgrehm/vagrant-lxc/issues/91 for more info + sed -i -e "s/\(127.0.0.1\s\+localhost\)/\1\n127.0.1.1\t${RELEASE}-base\n/g" ${ROOTFS}/etc/hosts + + # Ensures that `/tmp` does not get cleared on halt + # See https://github.com/fgrehm/vagrant-lxc/issues/68 for more info + utils.lxc.attach /usr/sbin/update-rc.d -f checkroot-bootclean.sh remove + utils.lxc.attach /usr/sbin/update-rc.d -f mountall-bootclean.sh remove + utils.lxc.attach /usr/sbin/update-rc.d -f mountnfs-bootclean.sh remove +fi + +utils.lxc.attach /usr/sbin/locale-gen ${LANG} +utils.lxc.attach update-locale LANG=${LANG} diff --git a/boxes/mk-debian.sh b/boxes/mk-debian.sh new file mode 100755 index 0000000..c93aac5 --- /dev/null +++ b/boxes/mk-debian.sh @@ -0,0 +1,47 @@ +#!/bin/bash +set -e + +source common/ui.sh + +if [ "$(id -u)" != "0" ]; then + echo "You should run this script as root (sudo)." + exit 1 +fi + +export DISTRIBUTION=$1 +export RELEASE=$2 +export ARCH=$3 +export CONTAINER=$4 +export PACKAGE=$5 +export ROOTFS="/var/lib/lxc/${CONTAINER}/rootfs" +export WORKING_DIR="/tmp/${CONTAINER}" +export NOW=$(date -u) +export LOG=$(readlink -f .)/log/${CONTAINER}.log + +mkdir -p $(dirname $LOG) +echo '############################################' > ${LOG} +echo "# Beginning build at $(date)" >> ${LOG} +touch ${LOG} +chmod +rw ${LOG} + +if [ -f ${PACKAGE} ]; then + warn "The box '${PACKAGE}' already exists, skipping..." + echo + exit +fi + +debug "Creating ${WORKING_DIR}" +mkdir -p ${WORKING_DIR} + +info "Building box to '${PACKAGE}'..." + +./common/download.sh ${DISTRIBUTION} ${RELEASE} ${ARCH} ${CONTAINER} +./debian/vagrant-lxc-fixes.sh ${DISTRIBUTION} ${RELEASE} ${ARCH} ${CONTAINER} +./debian/install-extras.sh ${CONTAINER} +./common/prepare-vagrant-user.sh ${CONTAINER} +./debian/clean.sh ${CONTAINER} +./common/package.sh ${CONTAINER} ${PACKAGE} + +info "Finished building '${PACKAGE}'!" +log "Run \`sudo lxc-destroy -n ${CONTAINER}\` or \`make clean\` to remove the container that was created along the way" +echo diff --git a/lib/vagrant-lxc/action/handle_box_metadata.rb b/lib/vagrant-lxc/action/handle_box_metadata.rb index 73ceeb8..fccc9b5 100644 --- a/lib/vagrant-lxc/action/handle_box_metadata.rb +++ b/lib/vagrant-lxc/action/handle_box_metadata.rb @@ -3,7 +3,8 @@ module Vagrant module Action # Prepare arguments to be used for lxc-create class HandleBoxMetadata - SUPPORTED_VERSIONS = [2, 3] + SUPPORTED_VERSIONS = ['1.0.0', '2', '3'] + def initialize(app, env) @app = app @logger = Log4r::Logger.new("vagrant::lxc::action::handle_box_metadata") @@ -16,15 +17,25 @@ module Vagrant @env[:ui].info I18n.t("vagrant.actions.vm.import.importing", :name => @env[:machine].box.name) - @logger.debug 'Validating box contents' + @logger.info 'Validating box contents' validate_box - @logger.debug 'Setting box options on environment' - @env[:lxc_template_opts] = template_opts + @logger.info 'Setting box options on environment' @env[:lxc_template_src] = template_src + @env[:lxc_template_opts] = template_opts + + # FIXME: Remove support for pre 1.0.0 boxes + if box_version != '1.0.0' + @env[:ui].warn "WARNING: You are using a base box that has a format that has been deprecated, please upgrade to a new one." + @env[:lxc_template_opts].merge!( + '--auth-key' => Vagrant.source_root.join('keys', 'vagrant.pub').expand_path.to_s + ) + end if template_config_file.exist? - @env[:lxc_template_config] = template_config_file.to_s + @env[:lxc_template_opts].merge!('--config' => template_config_file.to_s) + elsif old_template_config_file.exist? + @env[:lxc_template_config] = old_template_config_file.to_s end @app.call env @@ -35,15 +46,17 @@ module Vagrant end def template_config_file - @template_config_file ||= @box.directory.join('lxc.conf') + @template_config_file ||= @box.directory.join('lxc-config') + end + + # TODO: Remove this once we remove compatibility for < 1.0.0 boxes + def old_template_config_file + @old_template_config_file ||= @box.directory.join('lxc.conf') end 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 + '--tarball' => rootfs_tarball ) end @@ -52,10 +65,10 @@ module Vagrant end def validate_box - unless SUPPORTED_VERSIONS.include? @box.metadata.fetch('version').to_i + unless SUPPORTED_VERSIONS.include? box_version raise Errors::IncompatibleBox.new name: @box.name, - found: @box.metadata.fetch('version').to_i, - supported: SUPPORTED_VERSIONS.join(' and ') + found: box_version, + supported: SUPPORTED_VERSIONS.join(', ') end unless File.exists?(template_src) @@ -66,6 +79,10 @@ module Vagrant raise Errors::RootFSTarballMissing.new name: @box.name end end + + def box_version + @box.metadata.fetch('version') + end end end end diff --git a/spec/unit/action/handle_box_metadata_spec.rb b/spec/unit/action/handle_box_metadata_spec.rb index 973948b..3208355 100644 --- a/spec/unit/action/handle_box_metadata_spec.rb +++ b/spec/unit/action/handle_box_metadata_spec.rb @@ -6,7 +6,7 @@ require 'vagrant-lxc/action/handle_box_metadata' describe Vagrant::LXC::Action::HandleBoxMetadata do let(:app) { double(:app, call: true) } - let(:env) { {machine: machine, ui: double(info: true)} } + let(:env) { {machine: machine, ui: double(info: true, warn: true)} } let(:machine) { double(:machine, box: box) } let(:box) { double(:box, name: 'box-name', metadata: metadata, directory: box_directory) } let(:box_directory) { Pathname.new('/path/to/box') } @@ -16,9 +16,54 @@ describe Vagrant::LXC::Action::HandleBoxMetadata do subject { described_class.new(app, env) } - context 'with valid contents' do + context 'with 1.0.0 box' do + let(:version) { '1.0.0' } + before do File.stub(exists?: true) + # REFACTOR: This is pretty bad + subject.stub_chain(:template_config_file, :exist?).and_return(true) + subject.stub_chain(:template_config_file, :to_s).and_return(box_directory.join('lxc-config').to_s) + subject.call(env) + end + + it 'sets the tarball argument for the template' do + env[:lxc_template_opts].should include( + '--tarball' => box_directory.join('rootfs.tar.gz').to_s + ) + end + + it 'sets the template --config parameter' do + env[:lxc_template_opts].should include( + '--config' => box_directory.join('lxc-config').to_s + ) + end + + it 'does not set the auth key argument for the template' do + env[:lxc_template_opts].should_not include( + '--auth-key' => vagrant_key + ) + end + + it 'sets the template options from metadata on env hash' do + env[:lxc_template_opts].should include(metadata['template-opts']) + end + + it 'sets the template source path on env hash' do + env[:lxc_template_src].should == box_directory.join('lxc-template').to_s + end + + it 'does not warn about deprecation' do + env[:ui].should_not have_received(:warn) + end + end + + context 'with valid pre 1.0.0 box' do + before do + File.stub(exists?: true) + # REFACTOR: This is pretty bad + subject.stub_chain(:old_template_config_file, :exist?).and_return(true) + subject.stub_chain(:old_template_config_file, :to_s).and_return(box_directory.join('lxc.conf').to_s) subject.call(env) end @@ -34,6 +79,10 @@ describe Vagrant::LXC::Action::HandleBoxMetadata do ) end + it 'sets the lxc config file parameter' do + env[:lxc_template_config].should == box_directory.join('lxc.conf').to_s + end + it 'sets the template options from metadata on env hash' do env[:lxc_template_opts].should include(metadata['template-opts']) end @@ -41,12 +90,23 @@ describe Vagrant::LXC::Action::HandleBoxMetadata do it 'sets the template source path on env hash' do env[:lxc_template_src].should == box_directory.join('lxc-template').to_s end + + it 'warns about deprecation' do + env[:ui].should have_received(:warn) + end end describe 'with invalid contents' do before { File.stub(exists?: true) } - it 'raises an error if the version is != 2' do + it 'validates box versions' do + %w( 2 3 1.0.0 ).each do |v| + metadata['version'] = v + expect { + subject.call(env) + }.to_not raise_error(Vagrant::LXC::Errors::IncompatibleBox) + end + metadata['version'] = '1' expect { subject.call(env)