Created
June 28, 2017 00:42
-
-
Save ColonelBundy/9844cbe53bce1829387f385b499a4605 to your computer and use it in GitHub Desktop.
Flynn install with manual ZFS install
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
# | |
# A script to install Flynn from a TUF repository. | |
FLYNN_HOST_CHECKSUM="${FLYNN_HOST_CHECKSUM:="35f61a5a014108614b9a97a85424759ee71818b3f4ea02e75cee5bbb8c143c98dc5c273dfbcd21199f2eea0558605b16e3a78d39202f1adea06c080af2161eb3"}" | |
usage() { | |
cat <<USAGE >&2 | |
usage: $0 [options] | |
A script to install Flynn on Ubuntu 14.04 or 16.04. | |
See https://flynn.io/docs/installation/manual for further information. | |
OPTIONS: | |
-h, --help Show this message | |
-v, --version VERSION Install explicit VERSION (e.g. v20160512.0) | |
-c, --channel CHANNEL Fetch updates from CHANNEL (either "stable" or "nightly") [default: stable] | |
--clean Install from a clean state (implies --remove) [DANGER: this will remove all associated data] | |
--remove Remove existing Flynn installation [DANGER: this will remove all associated data] | |
--yes Automatic yes to prompts | |
--no-ntp Don't install ntp package | |
-r, --repo URL The TUF repository to download files from [default: https://dl.flynn.io] | |
--zpool-create-device DEVICE Device to create the flynn-default zpool on | |
--zpool-create-options OPTIONS Options to pass to 'zpool create' | |
VARIABLES: | |
FLYNN_UPDATE_CHANNEL The release channel to fetch updates from (either "nightly" or "stable") [default: stable] | |
FLYNN_VERSION An explicit version to install (e.g. v20151104.1) | |
USAGE | |
} | |
main() { | |
if ! is_root; then | |
fail "this script must be executed as the root user" | |
fi | |
if ! is_ubuntu_xenial && ! is_ubuntu_trusty; then | |
fail "this script is only compatible with Ubuntu 16.04 or 14.04" | |
fi | |
if ! check_overlayfs; then | |
fail "OverlayFS is either missing or does not support multiple lower directories, consider upgrading your kernel to at least 3.19" | |
fi | |
check_installed "curl" "sha512sum" | |
local install=true | |
local remove=false | |
local assume_yes=false | |
local install_ntp=true | |
local channel="${FLYNN_UPDATE_CHANNEL:-"stable"}" | |
local repo_url | |
local zpool_dev | |
local zpool_opts | |
export DEBIAN_FRONTEND=noninteractive | |
while true; do | |
case "$1" in | |
-v | --version) | |
if [[ -z "$2" ]]; then | |
fail "--version requires an argument" | |
fi | |
export FLYNN_VERSION="$2" | |
shift 2 | |
;; | |
-c | --channel) | |
if [[ -z "$2" ]]; then | |
fail "--channel requires an argument" | |
fi | |
channel="$2" | |
shift 2 | |
;; | |
--clean) | |
remove=true | |
shift | |
;; | |
--remove) | |
remove=true | |
install=false | |
shift | |
;; | |
--yes) | |
assume_yes=true | |
shift | |
;; | |
--no-ntp) | |
install_ntp=false | |
shift | |
;; | |
--zpool-create-device) | |
if [[ -z "$2" ]]; then | |
fail "--zpool-create-device requires an argument" | |
fi | |
zpool_dev="$2" | |
shift 2 | |
;; | |
--zpool-create-options) | |
if [[ -z "$2" ]]; then | |
fail "--zpool-create-options requires an argument" | |
fi | |
zpool_opts="$2" | |
shift 2 | |
;; | |
-h | --help) | |
usage | |
exit 1 | |
;; | |
-r | --repo) | |
if [[ -z "$2" ]]; then | |
fail "--repo requires an argument" | |
fi | |
repo_url="$2" | |
shift 2 | |
;; | |
*) | |
break | |
;; | |
esac | |
done | |
if [[ $# -ne 0 ]]; then | |
usage | |
exit 1 | |
fi | |
if $remove; then | |
do_remove $assume_yes | |
fi | |
if [[ -e "/usr/local/bin/flynn-host" ]]; then | |
fail "Flynn is already installed. Run 'flynn-host update' to update to a more recent version, or use --clean to remove the existing Flynn install first" | |
fi | |
if ! $install; then | |
exit | |
fi | |
repo_url="${repo_url:="https://dl.flynn.io"}" | |
info "installing runtime dependencies" | |
run apt-get install --yes ${packages[@]} | |
info "loading zfs kernel module" | |
run modprobe zfs | |
info "downloading flynn-host binary to tmp dir" | |
local tmp="$(mktemp --directory)" | |
trap "rm -rf ${tmp}" EXIT | |
cd "${tmp}" | |
if ! curl -fsSL -o "${tmp}/flynn-host.gz" "${repo_url}/tuf/targets/${FLYNN_HOST_CHECKSUM}.flynn-host.gz"; then | |
fail "failed to download flynn-host binary from ${repo_url}" | |
fi | |
info "verifying flynn-host binary checksum" | |
if ! echo "${FLYNN_HOST_CHECKSUM} *flynn-host.gz" | sha512sum --check --status; then | |
fail "failed to verify flynn-host binary checksum!" | |
fi | |
run gunzip "flynn-host.gz" | |
run chmod +x "flynn-host" | |
info "setting release update channel to \"${channel}\"" | |
mkdir -p "/etc/flynn" | |
echo "${channel}" > "/etc/flynn/channel.txt" | |
if [[ -n "${zpool_dev}" ]]; then | |
info "creating flynn-default zpool" | |
run zpool create ${zpool_opts} "flynn-default" ${zpool_dev} | |
fi | |
info "downloading Flynn components" | |
mkdir -p "/etc/flynn" | |
run ./flynn-host download \ | |
--repository "${repo_url}/tuf" \ | |
--tuf-db "/etc/flynn/tuf.db" \ | |
--config-dir "/etc/flynn" \ | |
--bin-dir "/usr/local/bin" | |
if is_ubuntu_xenial; then | |
install_systemd_unit | |
elif is_ubuntu_trusty; then | |
install_upstart_job | |
fi | |
info "installation complete!" | |
} | |
is_root() { | |
[[ $(id -u) -eq 0 ]] | |
} | |
is_ubuntu_trusty() { | |
grep -qF "Ubuntu 14.04" /etc/os-release &>/dev/null | |
} | |
is_ubuntu_xenial() { | |
grep -qF "Ubuntu 16.04" /etc/os-release &>/dev/null | |
} | |
install_systemd_unit() { | |
info "installing systemd unit" | |
cat > /lib/systemd/system/flynn-host.service <<EOF | |
[Unit] | |
Description=Flynn host daemon | |
Documentation=https://flynn.io/docs | |
After=network.target | |
[Service] | |
Type=simple | |
ExecStart=/usr/local/bin/flynn-host daemon | |
Restart=on-failure | |
# set delegate yes so that systemd does not reset the cgroups of containers | |
Delegate=yes | |
# kill only the flynn-host process, not all processes in the cgroup | |
KillMode=process | |
[Install] | |
WantedBy=multi-user.target | |
EOF | |
systemctl enable flynn-host.service | |
} | |
install_upstart_job() { | |
info "installing Upstart job" | |
cat > /etc/init/flynn-host.conf <<EOF | |
description "Flynn host daemon" | |
start on runlevel [2345] | |
stop on runlevel [!2345] | |
respawn | |
respawn limit 100 60 | |
exec /usr/local/bin/flynn-host daemon | |
EOF | |
initctl reload-configuration | |
} | |
do_remove() { | |
local assume_yes=$1 | |
warn "*** WARNING ***" | |
warn "About to stop Flynn and remove all existing data" | |
if ! $assume_yes; then | |
warn "Are you sure this is what you want?" | |
echo -n "(yes/no): " | |
while read answer; do | |
case "${answer}" in | |
yes) assume_yes=true; break ;; | |
no) break ;; | |
*) echo -n "Please type 'yes' or 'no': " ;; | |
esac | |
done | |
if ! $assume_yes; then | |
exit | |
fi | |
fi | |
info "stopping flynn-host daemon" | |
if is_ubuntu_xenial; then | |
systemctl stop flynn-host | |
systemctl disable flynn-host | |
elif is_ubuntu_trusty; then | |
local status="$(status flynn-host)" | |
if [[ "${status:0:16}" = "flynn-host start" ]]; then | |
run stop flynn-host | |
fi | |
fi | |
info "killing old containers" | |
sudo start-stop-daemon \ | |
--stop \ | |
--oknodo \ | |
--retry 5 \ | |
--name ".containerinit" | |
info "destroying ZFS volumes" | |
for path in $(grep zfs /proc/mounts | cut -d ' ' -f2); do | |
run sudo umount "${path}" | |
done | |
if which flynn-host &>/dev/null; then | |
run flynn-host destroy-volumes --include-data | |
fi | |
if zpool list | grep -q "flynn-default"; then | |
run zpool destroy flynn-default | |
fi | |
info "removing Flynn files and directories" | |
run rm -rf \ | |
/usr/local/bin/flynn* \ | |
/var/lib/flynn \ | |
/etc/flynn \ | |
/etc/init/flynn-host.conf \ | |
/lib/systemd/system/flynn-host.service | |
info "Flynn successfully removed" | |
} | |
# check_overlayfs checks that OverlayFS is present and supports multiple | |
# lower directories | |
check_overlayfs() { | |
if ! modprobe "overlay"; then | |
return 1 | |
fi | |
if ! grep -q "overlay$" /proc/filesystems; then | |
return 1 | |
fi | |
local dir="$(mktemp --directory)" | |
trap "rm -rf ${dir}" EXIT | |
local lower1="${dir}/lower1" | |
mkdir "${lower1}" | |
echo "1" > "${lower1}/1" | |
local lower2="${dir}/lower2" | |
mkdir "${lower2}" | |
echo "2" > "${lower2}/2" | |
local upper="${dir}/upper" | |
mkdir "${upper}" | |
local work="${dir}/work" | |
mkdir "${work}" | |
local mnt="${dir}/mnt" | |
mkdir "${mnt}" | |
if ! mount -t overlay -o "lowerdir=${lower2}:${lower1},upperdir=${upper},workdir=${work}" overlay "${mnt}"; then | |
return 1 | |
fi | |
trap "umount ${mnt}" EXIT | |
# check that both lower files are accessible via the mount | |
[[ -s "${mnt}/1" ]] && [[ -s "${mnt}/2" ]] | |
} | |
check_installed() { | |
local missing=() | |
for bin in $@; do | |
if ! which "${bin}" &>/dev/null; then | |
missing+=("${bin}") | |
fi | |
done | |
if [[ ${#missing[@]} -gt 0 ]]; then | |
fail "this script requires: ${missing[@]}" | |
fi | |
} | |
run() { | |
local cmd=$@ | |
info "running \"${cmd}\"" | |
$cmd | |
local status=$? | |
if [[ $status -ne 0 ]]; then | |
fail "failed to run \"${cmd}\", exit status ${status}" | |
fi | |
} | |
timestamp() { | |
date "+%H:%M:%S.%3N" | |
} | |
info() { | |
local msg=$1 | |
echo -e "\e[1;32m===> $(timestamp) ${msg}\e[0m" | |
} | |
warn() { | |
local msg=$1 | |
echo -e "\e[1;33m===> $(timestamp) ${msg}\e[0m" | |
} | |
fail() { | |
local msg=$1 | |
echo -e "\e[1;31m===> $(timestamp) ERROR: ${msg}\e[0m" | |
exit 1 | |
} | |
main "$@" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment