diff options
-rwxr-xr-x | upload-machine | 120 |
1 files changed, 120 insertions, 0 deletions
diff --git a/upload-machine b/upload-machine new file mode 100755 index 0000000..fa7aac9 --- /dev/null +++ b/upload-machine @@ -0,0 +1,120 @@ +#! /usr/bin/env bash + +# Upload new or upgrade existing machine subvolume on a Build OS build host. +# +# -k - keep the old subvolume on the build host +# +# <host> - build host to upload to (as user 'build') +# <new-subvol> - machine subvolume to upload +# <old-subvol> - previous machine subvolume (btrfs send -p) +# +usage="usage: $0 [<options>] <host> <new-subvol> [<old-subvol>]" + +machines=/build/machines/default + +owd="$(pwd)" +trap "{ cd '$owd'; exit 1; }" ERR +set -o errtrace # Trap in functions. + +function info () { echo "$*" 1>&2; } +function error () { info "$*"; exit 1; } + +keep=false + +while [ "$#" -gt 0 ]; do + case "$1" in + -k) + keep=true + shift + ;; + -*) + error "unknown option: $1" + ;; + *) + break + ;; + esac +done + +host="$1" +newsv="$2" +oldsv="$3" + +if [ -z "$host" -o -z "$newsv" ]; then + error "$usage" +fi + +host="build@$host" + +# Get the machine link (<name>-<P>) and name. +# +mlink="$(echo "$newsv" | sed -n -re 's/^(.+-[0-9]+)\.[0-9]+$/\1/p')" +mname="$(echo "$mlink" | sed -n -re 's/^(.+)-[0-9]+$/\1/p')" + +if [ -z "$mlink" -o -z "$mname" ]; then + error "unable to extract machine link/name from '$newsv'" +fi + +# Subvolume paths on build host. +# +newsv_path="$machines/$mname/$newsv" +oldsv_path="$machines/$mname/$oldsv" + +# Make sure subvolumes are read-only. +# +function check_ro () # <subvol> +{ + local r; + r="$(btrfs property get -ts "$1" ro)" + if [ "$r" != "ro=true" ]; then + info "subvolume '$1' is not read-only" + info "to change, run: btrfs property set -ts $1 ro true" + exit 1 + fi +} + +check_ro "$newsv" +if [ -n "$oldsv" ]; then + check_ro "$oldsv" +fi + +# btrfs send command +# +send=(sudo btrfs send) +if [ -n "$oldsv" ]; then + send+=(-p "$oldsv") +fi +send+=("$newsv") + +set -x + +# Make sure the machine directory exists. +# +ssh "$host" mkdir -p "$machines/$mname" + +# Send the snapshot over. +# +sudo "${send[@]}" | ssh "$host" sudo btrfs receive "$machines/$mname/" + +# Adjust machine ownership. +# +ssh "$host" sudo btrfs property set -ts "$newsv_path" ro false +ssh "$host" sudo chown build:build "$newsv_path" +ssh "$host" sudo chown build:build "$newsv_path/*" +ssh "$host" btrfs property set -ts "$newsv_path" ro true + +# Atomically switch the current machine. +# +ssh "$host" "cd $machines/$mname && ln -s $newsv new-$mlink" +ssh "$host" "cd $machines/$mname && mv -T new-$mlink $mlink" + +# Remove the old machine subvolume. +# +{ set +x; } 2>/dev/null +if [ -z "$oldsv" -o "$keep" = true ]; then + exit 0 +fi + +set -x +ssh "$host" btrfs property set -ts "$oldsv_path" ro false +ssh "$host" btrfs subvolume delete "$oldsv_path" |