Skip to content

Commit

Permalink
Initial packer/vagrant/autotest setup
Browse files Browse the repository at this point in the history
  • Loading branch information
mika committed Apr 19, 2014
1 parent bba7c19 commit fb40c28
Show file tree
Hide file tree
Showing 10 changed files with 487 additions and 0 deletions.
3 changes: 3 additions & 0 deletions .gitignore
@@ -0,0 +1,3 @@
*.box
packer_cache
*_output
3 changes: 3 additions & 0 deletions Makefile
Expand Up @@ -24,3 +24,6 @@ online: all

clean:
rm -rf grml-debootstrap.8.html grml-debootstrap.8.xml grml-debootstrap.8 html-stamp man-stamp

testrun:
cd ./packer && $(MAKE) compile && $(MAKE) packer
122 changes: 122 additions & 0 deletions Vagrantfile
@@ -0,0 +1,122 @@
# -*- mode: ruby -*-
# vi: set ft=ruby :

# Vagrantfile API/syntax version. Don't touch unless you know what you're doing!
VAGRANTFILE_API_VERSION = "2"

Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
# All Vagrant configuration is done here. The most common configuration
# options are documented and commented below. For a complete reference,
# please see the online documentation at vagrantup.com.

# Every Vagrant virtual environment requires a box to build off of.
config.vm.box = "debian64_wheezy.box"

# Disable automatic box update checking. If you disable this, then
# boxes will only be checked for updates when the user runs
# `vagrant box outdated`. This is not recommended.
# config.vm.box_check_update = false

# Create a forwarded port mapping which allows access to a specific port
# within the machine from a port on the host machine. In the example below,
# accessing "localhost:8080" will access port 80 on the guest machine.
# config.vm.network "forwarded_port", guest: 80, host: 8080

# Create a private network, which allows host-only access to the machine
# using a specific IP.
# config.vm.network "private_network", ip: "192.168.33.10"

# Create a public network, which generally matched to bridged network.
# Bridged networks make the machine appear as another physical device on
# your network.
# config.vm.network "public_network"

# If true, then any SSH connections made will enable agent forwarding.
# Default value: false
# config.ssh.forward_agent = true

# Share an additional folder to the guest VM. The first argument is
# the path on the host to the actual folder. The second argument is
# the path on the guest to mount the folder. And the optional third
# argument is a set of non-required options.
# config.vm.synced_folder "../data", "/vagrant_data"

# Provider-specific configuration so you can fine-tune various
# backing providers for Vagrant. These expose provider-specific options.
# Example for VirtualBox:
#
config.vm.provider "virtualbox" do |vb|
# Don't boot with headless mode
vb.gui = true

# Use VBoxManage to customize the VM. For example to change memory:
# vb.customize ["modifyvm", :id, "--memory", "1024"]
end
#
# View the documentation for the provider you're using for more
# information on available options.

# Enable provisioning with CFEngine. CFEngine Community packages are
# automatically installed. For example, configure the host as a
# policy server and optionally a policy file to run:
#
# config.vm.provision "cfengine" do |cf|
# cf.am_policy_hub = true
# # cf.run_file = "motd.cf"
# end
#
# You can also configure and bootstrap a client to an existing
# policy server:
#
# config.vm.provision "cfengine" do |cf|
# cf.policy_server_address = "10.0.2.15"
# end

# Enable provisioning with Puppet stand alone. Puppet manifests
# are contained in a directory path relative to this Vagrantfile.
# You will need to create the manifests directory and a manifest in
# the file default.pp in the manifests_path directory.
#
# config.vm.provision "puppet" do |puppet|
# puppet.manifests_path = "manifests"
# puppet.manifest_file = "site.pp"
# end

# Enable provisioning with chef solo, specifying a cookbooks path, roles
# path, and data_bags path (all relative to this Vagrantfile), and adding
# some recipes and/or roles.
#
# config.vm.provision "chef_solo" do |chef|
# chef.cookbooks_path = "../my-recipes/cookbooks"
# chef.roles_path = "../my-recipes/roles"
# chef.data_bags_path = "../my-recipes/data_bags"
# chef.add_recipe "mysql"
# chef.add_role "web"
#
# # You may also specify custom JSON attributes:
# chef.json = { :mysql_password => "foo" }
# end

# Enable provisioning with chef server, specifying the chef server URL,
# and the path to the validation key (relative to this Vagrantfile).
#
# The Opscode Platform uses HTTPS. Substitute your organization for
# ORGNAME in the URL and validation key.
#
# If you have your own Chef Server, use the appropriate URL, which may be
# HTTP instead of HTTPS depending on your configuration. Also change the
# validation key to validation.pem.
#
# config.vm.provision "chef_client" do |chef|
# chef.chef_server_url = "https://api.opscode.com/organizations/ORGNAME"
# chef.validation_key_path = "ORGNAME-validator.pem"
# end
#
# If you're using the Opscode platform, your validator client is
# ORGNAME-validator, replacing ORGNAME with your organization name.
#
# If you have your own Chef Server, the default validation client name is
# chef-validator, unless you changed the configuration.
#
# chef.validation_client_name = "ORGNAME-validator"
end
5 changes: 5 additions & 0 deletions packer/Makefile
@@ -0,0 +1,5 @@
compile:
gcc -shared -fPIC -ldl fake-uname.c -o fake-uname.so

packer:
packer build debian64_wheezy.json
30 changes: 30 additions & 0 deletions packer/README.md
@@ -0,0 +1,30 @@
Creating Vagrant baseboxes and testing grml-debootstrap
=======================================================

Purpose
-------

This directory provides configurations and scripts to

* test grml-debootstrap
* generate base.box for Virtualbox usage with Vagrant

Required software
-----------------

* [Packer](http://packer.io/) binary in $PATH
* [Vagrant](http://vagrantup.com/)
* [Virtualbox](https://www.virtualbox.org/)

Usage instructions
------------------

To create a Debian base box for usage with Vagrant
(and while at it run the grml-debootstrap tests):

% cd grml-debootstrap.git
% make testrun

Start resulting Debian system via Vagrant:

% vagrant up
95 changes: 95 additions & 0 deletions packer/debian64.bats
@@ -0,0 +1,95 @@
#!/usr/bin/env bats

# config
mountpath="/mnt"
device="/dev/sda"
disk="${device}1"

setup() {
mountpoint "$mountpath" &>/dev/null || mount "$disk" "$mountpath"
}

teardown() {
mountpoint "$mountpath" &>/dev/null && umount "$mountpath"
}

# tests
@test "debian_version exists" {
run cat "${mountpath}/etc/debian_version"
[ "$status" -eq 0 ]
[[ "$output" == [0-9].[0-9] ]]
}

@test "kernel exists" {
run ls "${mountpath}"/boot/vmlinuz-*
[ "$status" -eq 0 ]
[[ "$output" =~ ${mountpath}/boot/vmlinuz-* ]]
}

@test "initrd exists" {
run ls "${mountpath}"/boot/initrd.img-*
[ "$status" -eq 0 ]
[[ "$output" =~ ${mountpath}/boot/initrd.img-* ]]
}

@test "grub-pc installed" {
run chroot $mountpath dpkg-query --show --showformat='${Status}' grub-pc
[ "$status" -eq 0 ]
[[ "$output" == "install ok installed" ]]
}

@test "ext3/ext4 filesystem" {
fstype=$(blkid -o udev ${disk} | grep '^ID_FS_TYPE=')
run echo $fstype
[ "$status" -eq 0 ]
[[ $output =~ ID_FS_TYPE=ext[34] ]]
}

@test "partition table" {
table_info=$(parted -s ${device} 'unit s print' | grep -A1 '^Number.*Start.*End' | tail -1)
regex='1 2048s.*primary ext[34] boot'
run echo $table_info
echo "debug: table_info = $table_info"
echo "debug: output = $output"
[[ $output =~ $regex ]]
}

@test "tune2fs mount count setting" {
mount_count=$(tune2fs -l "$disk" | grep "^Maximum mount count:")
run echo "$mount_count"
[[ "$output" == "Maximum mount count: -1" ]]
}

@test "kernel entry in grub config" {
run grep "Debian GNU/Linux, with Linux" "${mountpath}/boot/grub/grub.cfg"
[ "$status" -eq 0 ]
}

@test "vim package is installed" {
run chroot "$mountpath" dpkg --list vim
[ "$status" -eq 0 ]
}

@test "home directory for user vagrant" {
run ls -d "$mountpath"/home/vagrant
[ "$status" -eq 0 ]
}

@test "home directory for user vagrant" {
run grep -q ssh-rsa "$mountpath"/home/vagrant/.ssh/authorized_keys
[ "$status" -eq 0 ]
}

@test "sudo setup for user vagrant" {
run grep -q '^vagrant ALL=(ALL) NOPASSWD: ALL' "${mountpath}/etc/sudoers.d/vagrant"
[ "$status" -eq 0 ]
}

@test "check for GRUB in MBR" {
regex='^00000180.*GRUB.*'
grub_string=$(dd if=${device} bs=512 count=1 2>/dev/null | hexdump -C | egrep "$regex")
run echo "$grub_string"
echo "debug: grub_string = $grub_string"
echo "debug: output = $output"
[[ $output =~ $regex ]]
}
127 changes: 127 additions & 0 deletions packer/debian64_provision.sh
@@ -0,0 +1,127 @@
#!/bin/bash

set -e

[ -f /etc/grml_cd ] || { echo "File /etc/grml_cd doesn't exist, not executing script to avoid data loss." >&2 ; exit 1 ; }

TARGET=/mnt

# if we notice an error then do NOT immediately return but provide
# user a chance to debug the VM
bailout() {
echo "* Noticed problem during execution, sleeping for 9999 seconds to provide debugging option"
sleep 9999
echo "* Finally exiting with return code 1"
exit 1
}
trap bailout ERR

echo "* Executing automated partition setup"
cat > /tmp/partition_setup.txt << EOF
disk_config sda disklabel:msdos bootable:1
primary / 800M- ext4 rw
EOF

export LOGDIR='/tmp/setup-storage'
mkdir -p $LOGDIR

export disklist=$(/usr/lib/fai/fai-disk-info | sort)
PATH=/usr/lib/fai:${PATH} setup-storage -f /tmp/partition_setup.txt -X

# TODO
# - support testing the version provided by the ISO (without upgrading)
# - support testing the grml-debootstrap version from .git
echo "* Making sure we use latest grml-debootstrap version"
apt-get update
apt-get -y install grml-debootstrap

echo "* Installing Debian"
grml-debootstrap --hostname wheezy --release wheezy --target /dev/sda1 --grub /dev/sda --password grml --force 2>&1 | tee -a /tmp/grml-debootstrap.log

echo "* Mounting target system"
mount /dev/sda1 ${TARGET}

echo "* Installing make + gcc packages for Virtualbox Guest Additions"
chroot ${TARGET} apt-get -y install make gcc dkms

echo "* Installing Virtualbox Guest Additions"
isofile="${HOME}/VBoxGuestAdditions.iso"

KERNELHEADERS=$(basename $(find $TARGET/usr/src/ -maxdepth 1 -name linux-headers\* ! -name \*common) | sort -u -r -V | head -1)
if [ -z "$KERNELHEADERS" ] ; then
echo "Error: no kernel headers found for building the VirtualBox Guest Additions kernel module." >&2
exit 1
fi

KERNELVERSION=${KERNELHEADERS##linux-headers-}
if [ -z "$KERNELVERSION" ] ; then
echo "Error: no kernel version could be identified." >&2
exit 1
fi

cp /tmp/fake-uname.so "${TARGET}/tmp/fake-uname.so"
mkdir -p "${TARGET}/media/cdrom"
mountpoint "${TARGET}/media/cdrom" >/dev/null && umount "${TARGET}/media/cdrom"
mount -t iso9660 $isofile "${TARGET}/media/cdrom/"
UTS_RELEASE=$KERNELVERSION LD_PRELOAD=/tmp/fake-uname.so grml-chroot "$TARGET" /media/cdrom/VBoxLinuxAdditions.run --nox11 || true
tail -10 "${TARGET}/var/log/VBoxGuestAdditions.log"
umount "${TARGET}/media/cdrom/"

# work around regression in virtualbox-guest-additions-iso 4.3.10
if [ -d ${TARGET}/opt/VBoxGuestAdditions-4.3.10 ] ; then
ln -s /opt/VBoxGuestAdditions-4.3.10/lib/VBoxGuestAdditions ${TARGET}/usr/lib/VBoxGuestAdditions
fi

echo "* Setting password for user root to 'vagrant'"
echo root:vagrant | chroot ${TARGET} chpasswd

echo "* Installing sudo package"
chroot ${TARGET} apt-get -y install sudo

echo "* Adding Vagrant user"
chroot ${TARGET} useradd -d /home/vagrant -m -u 1000 vagrant

echo "* Installing Vagrant ssh key"
mkdir -m 0700 -p ${TARGET}/home/vagrant/.ssh
echo "ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEA6NF8iallvQVp22WDkTkyrtvp9eWW6A8YVr+kz4TjGYe7gHzIw+niNltGEFHzD8+v1I2YJ6oXevct1YeS0o9HZyN1Q9qgCgzUFtdOKLv6IedplqoPkcmF0aYet2PkEDo3MlTBckFXPITAMzF8dJSIFo9D8HfdOV0IAdx4O7PtixWKn5y2hMNG0zQPyUecp4pzC6kivAIhyfHilFR61RGL+GPXQ2MWZWFYbAGjyiYJnAmCP3NOTd0jMZEnDkbUvxhMmBYSdETk1rRgm+R4LOzFUGaHqHDLKLX+FIPKcF96hrucXzcWyLbIbEgE98OHlnVYCzRdK8jlqm8tehUc9c9WhQ== vagrant insecure public key" >> ${TARGET}/home/vagrant/.ssh/authorized_keys
chmod 0600 ${TARGET}/home/vagrant/.ssh/authorized_keys
chroot ${TARGET} chown vagrant:vagrant /home/vagrant/.ssh /home/vagrant/.ssh/authorized_keys

echo "* Setting up sudo configuration for vagrant user"
echo "vagrant ALL=(ALL) NOPASSWD: ALL" > ${TARGET}/etc/sudoers.d/vagrant

if [ -f ${TARGET}/etc/ssh/sshd_config ] && ! grep -q '^UseDNS' ${TARGET}/etc/ssh/sshd_config ; then
echo "* Disabling UseDNS in sshd config"
echo "UseDNS no" >> ${TARGET}/etc/ssh/sshd_config
fi

echo "* Cleaning up apt stuff"
chroot ${TARGET} apt-get clean
rm -f ${TARGET}/var/lib/apt/lists/*Packages \
${TARGET}/var/lib/apt/lists/*Release \
${TARGET}/var/lib/apt/lists/*Sources \
${TARGET}/var/lib/apt/lists/*Index* \
${TARGET}/var/lib/apt/lists/*Translation* \
${TARGET}/var/lib/apt/lists/*.gpg \
${TARGET}/var/cache/apt-show-versions/* \
${TARGET}/var/cache/debconf/*.dat-old \
${TARGET}/var/cache/apt/*.bin \
${TARGET}/var/lib/aptitude/pkgstates.old

echo "* Unmounting target system"
umount ${TARGET}

echo "* Checking for bats"
if dpkg --list bats >/dev/null 2>&1 ; then
echo "* bats is already present, nothing to do."
else
echo "* Installing bats"
apt-get update
apt-get -y install bats
# dpkg -i /tmp/bats*deb
fi

echo "* Running tests to verify grml-debootstrap system"
bats /tmp/debian64.bats -t

echo "* Finished execution of $0"

0 comments on commit fb40c28

Please sign in to comment.