1#!/bin/sh
2set -eu
3
4instance=${1:?usage: tools/import-source-index.sh clover-source-of-truth-preview-XXXXXXXX}
5printf '%s\n' "$instance" | grep -Eq '^clover-source-of-truth-preview-[0-9a-f]{8}$' || {
6 echo 'Expected a Clover Source of Truth preview ID' >&2
7 exit 1
8}
9
10source_host=${STUDIO_MIGRATION_SOURCE:-zenith}
11target_host=${STUDIO_DEPLOY_HOST:-root@127.0.0.1}
12target_port=${STUDIO_DEPLOY_PORT:-2222}
13root="/srv/staging/$instance/data"
14mount="/srv/staging/$instance"
15source_id=$(ssh -p "$target_port" "$target_host" "python3 -c 'import json; print(json.load(open(\"/var/lib/studio/stages/$instance.json\"))[\"sourceId\"])'")
16test "$source_id" = clover-source-of-truth || { echo 'Preview belongs to another service' >&2; exit 1; }
17dataset=$(ssh -p "$target_port" "$target_host" "findmnt -n -o SOURCE --mountpoint $mount")
18case $dataset in */staging/"$instance") ;; *) echo 'Preview dataset is not mounted' >&2; exit 1 ;; esac
19
20scratch=$(mktemp -d)
21source_backup=
22cleanup() {
23 rm -rf "$scratch"
24 if [ -n "$source_backup" ]; then
25 ssh "$source_host" "rm -rf '$source_backup'"
26 fi
27}
28trap cleanup EXIT
29
30source_backup=$(ssh "$source_host" sh -s <<'REMOTE'
31set -eu
32out=$(mktemp -d /tmp/studio-source-index-XXXXXX)
33trap 'rm -rf "$out"' EXIT
34source='/mnt/storage1/clover/Documents/Config/paper clover/cache.sqlite'
35sqlite3 -readonly "$source" ".backup '$out/cache.sqlite'"
36test "$(sqlite3 -readonly "$out/cache.sqlite" 'PRAGMA integrity_check;')" = ok
37trap - EXIT
38printf '%s\n' "$out"
39REMOTE
40)
41rsync -a "$source_host:$source_backup/cache.sqlite" "$scratch/cache.sqlite"
42python3 - "$scratch/cache.sqlite" <<'PY'
43import sqlite3
44import sys
45
46db = sqlite3.connect('file:' + sys.argv[1] + '?mode=ro&immutable=1', uri=True)
47assert db.execute('PRAGMA integrity_check').fetchone()[0] == 'ok'
48PY
49
50ssh -p "$target_port" "$target_host" "NOMAD_TOKEN=\$(cat /var/lib/studio/nomad.token) nomad job stop -yes $instance"
51snapshot="$dataset@before-source-index-import-$(date +%s)-$$"
52ssh -p "$target_port" "$target_host" "set -eu; for i in \$(seq 1 30); do running=\$(curl -fsS -H \"X-Nomad-Token: \$(cat /var/lib/studio/nomad.token)\" http://127.0.0.1:4646/v1/job/$instance/allocations | python3 -c 'import json,sys; print(sum(a[\"ClientStatus\"] == \"running\" for a in json.load(sys.stdin)))'); test \"\$running\" = 0 && break; sleep 2; done; test \"\$running\" = 0; zfs snapshot $snapshot"
53
54rsync -a -e "ssh -p $target_port" "$scratch/cache.sqlite" "$target_host:$root/cache.sqlite"
55owner=$(ssh -p "$target_port" "$target_host" "python3 -c 'import json; print(json.load(open(\"/var/lib/studio/identities.json\"))[\"clover-source-of-truth\"])'")
56ssh -p "$target_port" "$target_host" "chown $owner:$owner $root/cache.sqlite; rm -f $root/cache.sqlite-wal $root/cache.sqlite-shm $root/db-snapshot.sqlite"
57drift=$(rsync -rnc --out-format='%n' -e "ssh -p $target_port" "$scratch/cache.sqlite" "$target_host:$root/cache.sqlite")
58test -z "$drift" || { echo "Index copy differs from source backup; restore $snapshot" >&2; exit 1; }
59
60python3 "$(dirname "$0")/deploy.py" stage clover-source-of-truth
61ssh -p "$target_port" "$target_host" "python3 - <<'PY'
62import sqlite3
63source = sqlite3.connect('file:$root/cache.sqlite?mode=ro', uri=True)
64assert source.execute('PRAGMA integrity_check').fetchone()[0] == 'ok'
65for table in ('media_files', 'derived_files', 'derived_refs'):
66 print(table, source.execute('SELECT count(*) FROM ' + table).fetchone()[0])
67PY"
68echo "Imported the live SQLite index into $instance; previous dataset: $snapshot"