aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xupload-machine120
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"