--- /dev/null
+*.box
+packer_cache
+*_output
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
+
+vagrant:
+ vagrant up
--- /dev/null
+# -*- 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 = "packer/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
--- /dev/null
+compile:
+ gcc -shared -fPIC -ldl fake-uname.c -o fake-uname.so
+
+packer:
+ packer build debian64_wheezy.json
--- /dev/null
+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
--- /dev/null
+#!/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 ]]
+}
--- /dev/null
+#!/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
+
+echo "* Making sure we use latest grml-debootstrap version"
+apt-get update
+apt-get -y install grml-debootstrap
+
+# TODO - support testing the version provided by the ISO (without upgrading)
+if [ -r /tmp/grml-debootstrap ] ; then
+ echo "* Found /tmp/grml-debootstrap - considering for usage as main grml-debootstrap script"
+ GRML_DEBOOTSTRAP="bash /tmp/grml-debootstrap"
+else
+ GRML_DEBOOTSTRAP=grml-debootstrap
+fi
+
+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 user vagrant"
+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"
--- /dev/null
+{
+ "variables": {
+ "grml_type": "grml64-full",
+ "grml_version": "2014.03",
+ "grml_iso_checksum": "1d3a0adfa3d395746e9e7f8748faec536f5c7b84"
+ },
+
+ "builders": [
+ {
+ "type": "virtualbox-iso",
+ "vm_name": "{{ user `grml_type` }}_{{ user `grml_version` }}",
+ "guest_os_type": "Debian_64",
+ "hard_drive_interface": "sata",
+ "iso_url": "http://download.grml.org/{{ user `grml_type` }}_{{ user `grml_version` }}.iso",
+ "iso_checksum": "{{ user `grml_iso_checksum` }}",
+ "iso_checksum_type": "sha1",
+ "ssh_wait_timeout": "20m",
+ "ssh_username": "root",
+ "ssh_password": "grml",
+ "output_directory": "{{ user `grml_type` }}_output",
+ "headless": false,
+ "boot_wait": "5s",
+ "boot_command": [
+ "<tab> ssh=grml <enter>"
+ ],
+ "shutdown_command": "shutdown -h now"
+ }
+ ],
+ "provisioners": [
+ {
+ "type": "file",
+ "source": "fake-uname.so",
+ "destination": "/tmp/fake-uname.so"
+ },
+ {
+ "type": "file",
+ "source": "debian64.bats",
+ "destination": "/tmp/debian64.bats"
+ },
+ {
+ "type": "file",
+ "source": "../grml-debootstrap",
+ "destination": "/tmp/grml-debootstrap"
+ },
+ {
+ "type": "shell",
+ "scripts": [
+ "debian64_provision.sh"
+ ]
+ }
+ ],
+ "post-processors": [
+ {
+ "type": "vagrant",
+ "compression_level": 5,
+ "override": {
+ "virtualbox": {
+ "output": "debian64_wheezy.box"
+ }
+ }
+ }
+ ]
+}
--- /dev/null
+#include <stdio.h>
+#include <string.h>
+#include <dlfcn.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <sys/syslog.h>
+#include <sys/utsname.h>
+
+#ifndef UTS_RELEASE
+#define UTS_RELEASE "0.0.0"
+#endif
+
+#ifndef RTLD_NEXT
+#define RTLD_NEXT ((void *) -1l)
+#endif
+
+typedef int (*uname_t) (struct utsname * buf);
+
+static void *get_libc_func(const char *funcname)
+{
+ void *func;
+ char *error;
+
+ func = dlsym(RTLD_NEXT, funcname);
+ if ((error = dlerror()) != NULL) {
+ fprintf(stderr, "Can't locate libc function `%s' error: %s", funcname, error);
+ _exit(EXIT_FAILURE);
+ }
+ return func;
+}
+
+int uname(struct utsname *buf)
+{
+ int ret;
+ char *env = NULL;
+ uname_t real_uname = (uname_t) get_libc_func("uname");
+
+ ret = real_uname((struct utsname *) buf);
+ strncpy(buf->release, ((env = getenv("UTS_RELEASE")) == NULL) ? UTS_RELEASE : env, 65);
+ return ret;
+}