Skip to content

Instantly share code, notes, and snippets.

@ttilley
Created July 9, 2012 16:26
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save ttilley/3077455 to your computer and use it in GitHub Desktop.
Save ttilley/3077455 to your computer and use it in GitHub Desktop.
stackato vagrant bootstrap
# -*- mode: ruby -*-
# vi: set ft=ruby :
Vagrant::Config.run do |config|
config.vm.box = "vagrant-stackato-v2.0.5"
config.vm.boot_mode = :gui
end
date > /etc/vagrant_box_build_time
# Enable truly non interactive apt-get installs
export DEBIAN_FRONTEND=noninteractive
# update
apt-get -y update
# update the kernel (potentially) and install vbox guest additions (with dkms)
apt-get -y install linux-image-virtual linux-headers-virtual
apt-get -y install virtualbox-guest-dkms
# pin build-essential
apt-get -y install build-essential
# Install NFS client
apt-get -y install nfs-common
# install more complete ruby setup (parts of 1.8 should already be present)
apt-get -y install ruby1.8-full rubygems
# install chef and puppet via rubygems
gem install --no-ri --no-rdoc chef puppet
# create vagrant user, set passwords to "vagrant"
VAGRANTPW='$6$1k6w4jGE$/Iy/.CJxqFkpQu8PV2ZVKTLFF0rBojdysU7aHNb60p96tp/FwalTwJ4w039fybMJOUK9Ks4sEsv1nI586AST11'
useradd --password "${VAGRANTPW}" --create-home --shell /bin/bash vagrant
usermod --password "${VAGRANTPW}" root
# ensure that the vagrant user can access vbox shared filesystems
usermod --append --groups vboxsf vagrant
# setup sudo for passwordless "admin" group
groupadd -r admin
cp /etc/sudoers /etc/sudoers.orig
cat /etc/sudoers.orig | grep ^Defaults > /etc/sudoers
# more permissive entries need to follow less permissive ones, generally
echo -e 'root\tALL=(ALL:ALL) ALL' >> /etc/sudoers
echo -e '%sudo\tALL=(ALL:ALL) ALL' >> /etc/sudoers
echo -e '%admin\tALL=(ALL:ALL) NOPASSWD: ALL' >> /etc/sudoers
cat /etc/sudoers.orig | grep -v -e ^Defaults -e ^root -e '^%' -e '^#' -e '^$' >> /etc/sudoers
# add vagrant to admin group
usermod --append --groups admin vagrant
# install vagrant ssh key
mkdir /home/vagrant/.ssh
chmod 700 /home/vagrant/.ssh
cd /home/vagrant/.ssh
wget --no-check-certificate 'https://raw.github.com/mitchellh/vagrant/master/keys/vagrant.pub' -O authorized_keys
chmod 600 /home/vagrant/.ssh/authorized_keys
# ensure that vagrant owns its own files
chown -R vagrant:vagrant /home/vagrant
# tweak firstboot name the hard (easy) way
sed -i -e 's|HOSTNAME_SUFFIX=.*$|HOSTNAME_SUFFIX="vbox"|g' /home/stackato/stackato/etc/firstboot/tasks/10-rename.sh
# cleanup
apt-get -y autoremove
apt-get -y clean
dd if=/dev/zero of=/EMPTY bs=1M
sync
rm -f /EMPTY
# import the stackato VM, but don't boot it (and keep it using NAT)
# install ubuntu precise on a separate 'setup' VM, then shut it down
# add a new disk to the 'setup' VM, pointing to the stackato VM's disk
# boot up the 'setup' VM
CHROOTDIR="/mnt"
ROOTDEV="/dev/sdb3"
BOOTDEV="/dev/sdb1"
# mount the stackato drive's filesystems inside the setup VM:
mount -o ro $ROOTDEV $CHROOTDIR
mount -o ro $BOOTDEV $CHROOTDIR/boot
STACKATO_VERSION="$(cat "${CHROOTDIR}/home/stackato/stackato/vcap/GITDESCRIBE")"
# make a quick backup if you so desire:
tar --create --verbose --preserve-permissions --sparse --auto-compress \
--file stackato-$STACKATO_VERSION.tar.gz --directory $CHROOTDIR '.'
# remount the stackato partitions as rw and add other necessary filesystems:
mount $CHROOTDIR -o remount,rw,noatime
mount $CHROOTDIR/boot -o remount,rw,noatime
mount proc -t proc -o nodev,noexec,nosuid $CHROOTDIR/proc
mount sys -t sysfs $CHROOTDIR/sys
mount -o bind /dev $CHROOTDIR/dev
TTYGID="$(cat $CHROOTDIR/etc/group | grep ^tty | awk -F: '{ print $3 }')" # 5
mount devpts -t devpts -o noexec,nosuid,gid=$TTYGID,mode=0620 $CHROOTDIR/dev/pts
mount -o bind /run $CHROOTDIR/run # /etc/resolve.conf -> /run/resolvconf/resolv.conf
mount -o bind /run/lock $CHROOTDIR/run/lock
mount -o bind /run/shm $CHROOTDIR/run/shm
# you can now chroot into the fresh, unbooted, stackato environment and make
# changes without disturbing its normal firstboot process. you might want to
# change the shell prompt to make it more obvious which terminal is the chroot.
chroot $CHROOTDIR /bin/bash
#!/usr/bin/env ruby
# -*- coding: utf-8 -*-
Vagrant::Config.run do |config|
config.package.name = 'vagrant-stackato.box'
config.vm.guest = :ubuntu
config.ssh.forward_agent = true
# config.vm.forward_port 80, 8080, :name => "nginx", :protocol => :tcp, :auto => true
# config.vm.forward_port 443, 8443, :name => "nginx ssl", :protocol => :tcp, :auto => true
# config.vm.forward_port 2222, 12222, :name => "router", :protocol => :tcp, :auto => true
# config.vm.forward_port 4222, 4222, :name => "nats", :protocol => :tcp, :auto => true
# config.vm.forward_port 8000, 8000, :name => "doozerd web", :protocol => :tcp, :auto => true
# config.vm.forward_port 8046, 8046, :name => "doozerd", :protocol => :tcp, :auto => true
# config.vm.forward_port 8046, 8046, :name => "doozerd udp", :protocol => :udp, :auto => true
# config.vm.forward_port 9001, 9001, :name => "supervisord", :protocol => :tcp, :auto => true
# config.vm.forward_port 9022, 9022, :name => "cloud controller", :protocol => :tcp, :auto => true
# config.vm.forward_port 12345, 12345, :name => "dea filer", :protocol => :tcp, :auto => true
# config.vm.forward_port 12385, 12385, :name => "dea runner", :protocol => :tcp, :auto => true
end
# This small extension to Vagrant ensures that we don't attempt to provision
# the VM before Stackato's custom firstboot process has completed. While it
# might be tempting to disable firstboot and perform it manually as part
# of provisioning, that isn't a cheat you can use outside of Vagrant. By
# putting the responsibility on Vagrant itself, your recipes will be more
# consistent.
module VagrantStackato
STACKATO_HOME = Pathname.new('/home/stackato')
module Firstboot
IN_PROGRESS_FILE = STACKATO_HOME.join('.stackato-firstboot')
ERROR_FILE = STACKATO_HOME.join('.stackato-firstboot-error')
class Config < Vagrant::Config::Base
attr_writer :timeout
attr_writer :nap_length
def timeout
@timeout ||= 120
end
def nap_length
@nap_length ||= 1
end
end
Vagrant.config_keys.register(:stackato_firstboot, Config)
class Middleware
def initialize(app, env)
@app = app
@timeout = env[:vm].config.stackato_firstboot.timeout.to_i
@nap_length = env[:vm].config.stackato_firstboot.nap_length.to_f
end
def call(env)
@env = env
# we don't have anything to do until after the VM is booted
@app.call(env)
# the explicit return is for self-documentation purposes
return wait_for_firstboot
end
def wait_for_firstboot
@env[:vm].config.ssh.max_tries.to_i.times do |i|
if @env[:vm].channel.ready?
@env[:ui].info "Waiting for firstboot to finish..."
return poll
end
end
@env[:ui].error "Unable to check firstboot state over SSH"
false
end
def poll
Timeout.timeout(@timeout) do
loop do
case check_firstboot_state
when :error
@env[:ui].error "Stackato firstboot failed with an unrecoverable error"
return false
when :success
@env[:ui].info "Stackato firstboot completed successfully"
return true
else
sleep @nap_length
end
end
end
rescue Timeout::Error => e
@env[:ui].error "Timed out waiting for firstboot"
return false
rescue Net::SSH::Disconnect => e
@env[:ui].warn "Disconnected from SSH: #{e.inspect}"
retry
rescue Errors::SSHConnectionRefused => e
@env[:ui].error "Unable to connect to SSH: #{e.inspect}"
return false
rescue Exception => e
@env[:ui].error "An error occured: #{e.inspect}"
return false
end
def check_firstboot_state
if @env[:vm].channel.test "test -f #{ERROR_FILE}"
return :error
elsif @env[:vm].channel.test "test -f #{IN_PROGRESS_FILE}"
return :in_progress
else
return :success
end
end
end
# insert middleware BEFORE boot so that it's the first thing to happen
# AFTER the VM has booted (the call chain goes down to boot then back up)
Vagrant.actions[:start].insert(Vagrant::Action::VM::Boot, Middleware)
end
end
date > /etc/vagrant_box_build_time
# Enable truly non interactive apt-get installs
export DEBIAN_FRONTEND=noninteractive
# update
apt-get -y update
# update the kernel (potentially) and install vbox guest additions (with dkms)
apt-get -y install linux-image-virtual linux-headers-virtual
apt-get -y install virtualbox-guest-dkms
# pin build-essential
apt-get -y install build-essential
# Install NFS client
apt-get -y install nfs-common
# install more complete ruby setup (parts of 1.8 should already be present)
apt-get -y install ruby1.8-full rubygems
# install chef and puppet via rubygems
gem install --no-ri --no-rdoc chef puppet
# create vagrant user, set passwords to "vagrant"
VAGRANTPW='$6$1k6w4jGE$/Iy/.CJxqFkpQu8PV2ZVKTLFF0rBojdysU7aHNb60p96tp/FwalTwJ4w039fybMJOUK9Ks4sEsv1nI586AST11'
useradd --password "${VAGRANTPW}" --create-home --shell /bin/bash vagrant
usermod --password "${VAGRANTPW}" root
# ensure that the vagrant user can access vbox shared filesystems
usermod --append --groups vboxsf vagrant
# setup sudo for passwordless "admin" group
groupadd -r admin
cp /etc/sudoers /etc/sudoers.orig
cat /etc/sudoers.orig | grep ^Defaults > /etc/sudoers
# more permissive entries need to follow less permissive ones, generally
echo -e 'root\tALL=(ALL:ALL) ALL' >> /etc/sudoers
echo -e '%sudo\tALL=(ALL:ALL) ALL' >> /etc/sudoers
echo -e '%admin\tALL=(ALL:ALL) NOPASSWD: ALL' >> /etc/sudoers
cat /etc/sudoers.orig | grep -v -e ^Defaults -e ^root -e '^%' -e '^#' -e '^$' >> /etc/sudoers
# add vagrant to admin group
usermod --append --groups admin vagrant
# install vagrant ssh key
mkdir /home/vagrant/.ssh
chmod 700 /home/vagrant/.ssh
cd /home/vagrant/.ssh
wget --no-check-certificate 'https://raw.github.com/mitchellh/vagrant/master/keys/vagrant.pub' -O authorized_keys
chmod 600 /home/vagrant/.ssh/authorized_keys
# ensure that vagrant owns its own files
chown -R vagrant:vagrant /home/vagrant
# tweak firstboot name the hard (easy) way
sed -i -e 's|HOSTNAME_SUFFIX=.*$|HOSTNAME_SUFFIX="vbox"|g' /home/stackato/stackato/etc/firstboot/tasks/10-rename.sh
# cleanup
apt-get -y autoremove
apt-get -y clean
dd if=/dev/zero of=/EMPTY bs=1M
sync
rm -f /EMPTY
# import the stackato VM, but don't boot it (and keep it using NAT)
# install ubuntu precise on a separate 'setup' VM, then shut it down
# add a new disk to the 'setup' VM, pointing to the stackato VM's disk
# boot up the 'setup' VM
CHROOTDIR="/mnt"
ROOTDEV="/dev/sdb3"
BOOTDEV="/dev/sdb1"
# mount the stackato drive's filesystems inside the setup VM:
mount -o ro $ROOTDEV $CHROOTDIR
mount -o ro $BOOTDEV $CHROOTDIR/boot
STACKATO_VERSION="$(cat "${CHROOTDIR}/home/stackato/stackato/vcap/GITDESCRIBE")"
# make a quick backup if you so desire:
tar --create --verbose --preserve-permissions --sparse --auto-compress \
--file stackato-$STACKATO_VERSION.tar.gz --directory $CHROOTDIR '.'
# remount the stackato partitions as rw and add other necessary filesystems:
mount $CHROOTDIR -o remount,rw,noatime
mount $CHROOTDIR/boot -o remount,rw,noatime
mount proc -t proc -o nodev,noexec,nosuid $CHROOTDIR/proc
mount sys -t sysfs $CHROOTDIR/sys
mount -o bind /dev $CHROOTDIR/dev
TTYGID="$(cat $CHROOTDIR/etc/group | grep ^tty | awk -F: '{ print $3 }')" # 5
mount devpts -t devpts -o noexec,nosuid,gid=$TTYGID,mode=0620 $CHROOTDIR/dev/pts
mount -o bind /run $CHROOTDIR/run # /etc/resolve.conf -> /run/resolvconf/resolv.conf
mount -o bind /run/lock $CHROOTDIR/run/lock
mount -o bind /run/shm $CHROOTDIR/run/shm
# you can now chroot into the fresh, unbooted, stackato environment and make
# changes without disturbing its normal firstboot process. you might want to
# change the shell prompt to make it more obvious which terminal is the chroot.
chroot $CHROOTDIR /bin/bash
#!/usr/bin/env ruby
# -*- coding: utf-8 -*-
Vagrant::Config.run do |config|
config.package.name = 'vagrant-stackato.box'
config.vm.guest = :ubuntu
config.ssh.forward_agent = true
# config.vm.forward_port 80, 8080, :name => "nginx", :protocol => :tcp, :auto => true
# config.vm.forward_port 443, 8443, :name => "nginx ssl", :protocol => :tcp, :auto => true
# config.vm.forward_port 2222, 12222, :name => "router", :protocol => :tcp, :auto => true
# config.vm.forward_port 4222, 4222, :name => "nats", :protocol => :tcp, :auto => true
# config.vm.forward_port 8000, 8000, :name => "doozerd web", :protocol => :tcp, :auto => true
# config.vm.forward_port 8046, 8046, :name => "doozerd", :protocol => :tcp, :auto => true
# config.vm.forward_port 8046, 8046, :name => "doozerd udp", :protocol => :udp, :auto => true
# config.vm.forward_port 9001, 9001, :name => "supervisord", :protocol => :tcp, :auto => true
# config.vm.forward_port 9022, 9022, :name => "cloud controller", :protocol => :tcp, :auto => true
# config.vm.forward_port 12345, 12345, :name => "dea filer", :protocol => :tcp, :auto => true
# config.vm.forward_port 12385, 12385, :name => "dea runner", :protocol => :tcp, :auto => true
end
# This small extension to Vagrant ensures that we don't attempt to provision
# the VM before Stackato's custom firstboot process has completed. While it
# might be tempting to disable firstboot and perform it manually as part
# of provisioning, that isn't a cheat you can use outside of Vagrant. By
# putting the responsibility on Vagrant itself, your recipes will be more
# consistent.
module VagrantStackato
STACKATO_HOME = Pathname.new('/home/stackato')
module Firstboot
IN_PROGRESS_FILE = STACKATO_HOME.join('.stackato-firstboot')
ERROR_FILE = STACKATO_HOME.join('.stackato-firstboot-error')
class Config < Vagrant::Config::Base
attr_writer :timeout
attr_writer :nap_length
def timeout
@timeout ||= 120
end
def nap_length
@nap_length ||= 1
end
end
Vagrant.config_keys.register(:stackato_firstboot, Config)
class Middleware
def initialize(app, env)
@app = app
@timeout = env[:vm].config.stackato_firstboot.timeout.to_i
@nap_length = env[:vm].config.stackato_firstboot.nap_length.to_f
end
def call(env)
@env = env
# we don't have anything to do until after the VM is booted
@app.call(env)
# the explicit return is for self-documentation purposes
return wait_for_firstboot
end
def wait_for_firstboot
@env[:vm].config.ssh.max_tries.to_i.times do |i|
if @env[:vm].channel.ready?
@env[:ui].info "Waiting for firstboot to finish..."
return poll
end
end
@env[:ui].error "Unable to check firstboot state over SSH"
false
end
def poll
Timeout.timeout(@timeout) do
loop do
case check_firstboot_state
when :error
@env[:ui].error "Stackato firstboot failed with an unrecoverable error"
return false
when :success
@env[:ui].info "Stackato firstboot completed successfully"
return true
else
sleep @nap_length
end
end
end
rescue Timeout::Error => e
@env[:ui].error "Timed out waiting for firstboot"
return false
rescue Net::SSH::Disconnect => e
@env[:ui].warn "Disconnected from SSH: #{e.inspect}"
retry
rescue Errors::SSHConnectionRefused => e
@env[:ui].error "Unable to connect to SSH: #{e.inspect}"
return false
rescue Exception => e
@env[:ui].error "An error occured: #{e.inspect}"
return false
end
def check_firstboot_state
if @env[:vm].channel.test "test -f #{ERROR_FILE}"
return :error
elsif @env[:vm].channel.test "test -f #{IN_PROGRESS_FILE}"
return :in_progress
else
return :success
end
end
end
# insert middleware BEFORE boot so that it's the first thing to happen
# AFTER the VM has booted (the call chain goes down to boot then back up)
Vagrant.actions[:start].insert(Vagrant::Action::VM::Boot, Middleware)
end
end
# -*- mode: ruby -*-
# vi: set ft=ruby :
Vagrant::Config.run do |config|
config.vm.box = "vagrant-stackato-v2.0.5"
config.vm.boot_mode = :gui
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment