Skip to content

Instantly share code, notes, and snippets.

@amcgregor
Last active December 13, 2015 17:19
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save amcgregor/4947201 to your computer and use it in GitHub Desktop.
Save amcgregor/4947201 to your computer and use it in GitHub Desktop.
Gentoo server automation using Git and automatic RAID configuration for superfast ephemeral storage.
#!/bin/bash
# This goes in /etc/local.d
# Called on boot to either construct a new local storage array (first boot) or re-create the array (subsequent).
source /lib/rc/sh/functions.sh
ROOT=$(readlink /dev/root)
DRIVE_A=/dev/sdb
DRIVE_B=/dev/sdc
# More modern Amazon runtimes use the Xen-specific device names.
if [ "$ROOT" == "xvda1" ]; then
DRIVE_A=/dev/xvdb
DRIVE_B=/dev/xvdc
fi
# Sanity checks.
ebegin "Ensuring no array currently exists"
if [[ -e /dev/md0 ]]; then
eend 1
eerror "Existing /dev/md0 device found!"
exit 1
fi
eend
ebegin "Ensuring underlying disks are available"
if [[ ! -e $DRIVE_A ]]; then
eend 1
eerror "Unable to find disk: $DRIVE_A"
exit 1
fi
if [[ ! -e $DRIVE_B ]]; then
eend 1
eerror "Unable to find disk: $DRIVE_B"
exit 1
fi
eend
# If we're mounted, the .keep file from the root filesystem won't be present.
ebegin "Clearing mount point"
if [[ ! -e /mnt/.keep ]]; then
umount /mnt
eend $?; [[ $? -gt 0 ]] && exit 1
else
eend
fi
# Try to recreate an existing array, if possible.
ebegin "Attempting to recreate existing array (failure is OK on first boot)"
mdadm -q --assemble /dev/md0 $DRIVE_A $DRIVE_B 2> /dev/null
eend $?
if [ $? == 0 ]; then
# We found an existing array!
ebegin "Mounting existing array"
mount -L data -o noatime,nodiratime /mnt
eend $?; exit $?
fi
# Since we didn't find an existing array, construct a new one.
# Clean the drives of any filesystem or partition information.
# Amazon may automatically format these as ext4, for example.
ebegin "Scrubbing underlying disk: $DRIVE_A"
dd if=/dev/zero of=${DRIVE_A} bs=4096 count=1024 2> /dev/null
eend $?; [[ $? -gt 0 ]] && exit $?
ebegin "Scrubbing underlying disk: $DRIVE_A"
dd if=/dev/zero of=${DRIVE_B} bs=4096 count=1024 2> /dev/null
eend $?; [[ $? -gt 0 ]] && exit $?
# Inform the kernel of potential changes to the partition table.
ebegin "Informing kernel of changes"
partprobe ${DRIVE_A}
partprobe ${DRIVE_B}
eend
# Construct a new stripe array.
# We want stripe for performance even if it does double the risk of catastrophic failure.
ebegin "Constructing new array"
mdadm --create --verbose /dev/md0 --level=stripe -c256 --raid-devices=2 $DRIVE_A $DRIVE_B 2> /dev/null
eend $?; [[ $? -gt 0 ]] && exit $?
# Increase the amount of read-ahead done on this composite device.
ebegin "Increasing read-ahead value on array"
blockdev --setra 65536 /dev/md0
eend $?; [[ $? -gt 0 ]] && exit $?
ebegin "Configuring mdadm"
echo DEVICE $DRIVE_A $DRIVE_B >> /etc/mdadm.conf
mdadm --detail --scan >> /etc/mdadm.conf
eend $?; [[ $? -gt 0 ]] && exit $?
ebegin "Constructing filesystem (this may take some time)"
mkreiserfs -q -b 4096 -l data -f -f /dev/md0 2> /dev/null
eend $?; [[ $? -gt 0 ]] && exit $?
ebegin "Mounting filesystem"
mount -L data -o noatime,nodiratime /mnt
eend $?; [[ $? -gt 0 ]] && exit $?
einfo "Building complete."
einfo "You can check the status of the array by running:"
einfo " mdadm -D /dev/md0"
einfo "Additionally, here's the contents of /etc/mdadm.conf:"
cat /etc/mdadm.conf
#!/bin/bash
# This is placed in /usr/local/sbin
# Called by an RPC handler when getting notification of update from GitHub.
# It is assumed you already have the root initialized with a remote, and re-named .git to .git-root.
source /lib/rc/sh/functions.sh
# Git doesn't emit leading slashes, so we need to be in the root to be safe.
cd /
GIT_DIR=/.git-root
BRANCH=$(git name-rev --name-only HEAD)
ebegin "Fetching and fast-forwarding to latest on branch: ${BRANCH}"
git pull --ff-only 2>&1 > /var/log/root-git-pull.log
STATUS=$?
eend $STATUS
[[ $STATUS -gt 0 ]] && cat /var/log/root-git-pull.log && exit $?
grep "Already up-to-date." /var/log/root-git-pull.log 2>&1 > /dev/null
[[ $? -eq 0 ]] && ewarn "Already up-to-date." && exit 0
ebegin "Calculating reloadable packages"
INITS=$(git diff --name-only @{1}.. | xargs qfile -Cq | xargs --no-run-if-empty equery files | grep init.d/ | sort -u)
eend $?
FAIL=0
for script in ${INITS}; do
ewarn "Reloading: ${script}"
if [ -x "$script" ]; then
grep '^reload(' ${script} 2>&1 > /dev/null
if [[ $? == 0 ]]; then
${script} -s reload
else
${script} -s restart
fi
[[ $? -gt 0 ]] && FAIL=1
fi
done
exit $FAILURES
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment