Compare commits

...
2 Commits
Author SHA1 Message Date
beatzaplentyandClaude Sonnet 4.6 e085d4707c fix(ha): add DRBD sync progress indicator and pre-flight sync gate
Check NixOS configurations / eval-hosts (push) Successful in 10m22s
cluster-init.sh: replace the fixed 300-iteration sync wait with an
indefinite loop that prints an in-place progress line (%done, ETA, speed)
from /proc/drbd every 3 s. Clears the line with printf \r before logging
completion, so the output stays clean alongside the [cluster-init] log
lines.

acceptance-tests.sh: add a pre-flight check that hard-exits if
drbdadm dstate is not UpToDate/UpToDate, with a hint to the watch
command for monitoring progress. Tests cannot give accurate results
while the initial full-sync is in progress.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-29 00:46:57 +10:00
beatzaplenty c8d4440787 secrets(ha): encrypt corosync authkey generated by cluster-init 2026-07-29 00:40:11 +10:00
3 changed files with 45 additions and 13 deletions

No files matched your search

+19
View File
@@ -34,6 +34,25 @@ echo "════════════════════════
echo " HA Cluster Acceptance Tests — $(date '+%Y-%m-%d %H:%M:%S')"
echo "════════════════════════════════════════════════════"
# ── Pre-flight: DRBD sync must be complete ────────────────────────────────
# Tests that check disk state, XFS mount, and iSCSI will fail or give false
# results while the initial full sync is in progress. Block until done.
echo ""
echo "Pre-flight: verifying DRBD sync is complete..."
DRBD_PREFLIGHT=$(n1 "drbdadm dstate ha-data 2>/dev/null" 2>/dev/null || echo "unknown")
if ! echo "$DRBD_PREFLIGHT" | grep -q "^UpToDate/UpToDate$"; then
echo ""
echo " ERROR: DRBD initial sync not complete."
echo " Current dstate on $NODE1: $DRBD_PREFLIGHT"
echo ""
echo " Monitor progress:"
echo " ssh nixos@$NODE1_IP 'sudo watch -n3 cat /proc/drbd'"
echo ""
echo " Re-run this script once dstate shows UpToDate/UpToDate."
exit 1
fi
echo " dstate: $DRBD_PREFLIGHT — ready."
# ── Detect Active/Standby nodes ────────────────────────────────────────────
# Use crm_mon to detect which node holds the Promoted (Primary) DRBD resource.
# Pacemaker is authoritative; DRBD role can briefly read as Secondary while
+20 -7
View File
@@ -239,15 +239,28 @@ crm_standby -N "$NODE2" -v off 2>/dev/null || true
log "Forcing $NODE1 to DRBD Primary for initial sync..."
drbdadm primary ha-data --force
log "Waiting for DRBD to finish initial sync (this may take several minutes)..."
for i in $(seq 1 300); do
state=$(drbdadm dstate ha-data 2>/dev/null || echo "unknown")
if echo "$state" | grep -q "UpToDate/UpToDate"; then
log "DRBD sync complete: $state"
log "Waiting for DRBD initial sync to complete (32 GB may take 10–20 min)..."
_sync_spin=0
_sync_chars=('|' '/' '-' $'\\')
while true; do
_dstate=$(drbdadm dstate ha-data 2>/dev/null || echo "unknown")
if echo "$_dstate" | grep -q "UpToDate/UpToDate"; then
printf "\r%-80s\r" "" # clear progress line
log "DRBD initial sync complete (dstate: $_dstate)"
break
fi
[[ $i -eq 300 ]] && warn "DRBD not UpToDate after 300 s — continuing anyway (check drbdadm status)"
sleep 1
_pct=$(grep -oE "sync'ed: [0-9.]+%" /proc/drbd 2>/dev/null | grep -oE "[0-9.]+" | head -1 || echo "")
_eta=$(grep -oE "finish: [0-9:]+" /proc/drbd 2>/dev/null | sed 's/finish: //' | head -1 || echo "")
_spd=$(grep -oE "speed: [0-9,]+" /proc/drbd 2>/dev/null | sed 's/speed: //' | head -1 || echo "")
_sc="${_sync_chars[$_sync_spin]}"
_sync_spin=$(( (_sync_spin + 1) % 4 ))
if [[ -n "$_pct" ]]; then
printf "\r [%s] syncing: %s%% done — ETA %s @ %s K/s " \
"$_sc" "$_pct" "${_eta:-??:??:??}" "${_spd:-?}"
else
printf "\r [%s] waiting for sync to start (dstate: %s) " "$_sc" "$_dstate"
fi
sleep 3
done
# ── 3. XFS filesystem ─────────────────────────────────────────────────────
+6 -6
View File
@@ -1,22 +1,22 @@
{
"data": "ENC[AES256_GCM,data:vQdlyhCx5MxkKejLp3lMqayk6/YtLwqPMLwEnfjIG6EJs9UOuFIwOMF8zA/vk4LtbzVwWaK5rv2tZgjbdm2Mkxr7HUxFvS0N20ctfzH0lti4TQWpMAIbN+D7RpcRrFg8lZb30hb2C81ilduQ+ONc0E7EXc8M/K2r4JJZzrX0k/L/pvn0GCTAvuj0GnLsGSLjEvpx1SGwzG5HGctBTALJGerGPhXpxySQqY6YljdQlvr2gYEfKaBjZTau1HDbrZD/8IM+K+nUOwgAR/VRpfYGOGmIBkHqD394WTPq0Z7L656TtIlX3wBsCXYlO2O9bdDSgwECCodXckWarkXBKJHOQQ==,iv:K8aEoqgtBLsICUOZt3lejhTlweTk0+rm8I/VP8cNitE=,tag:6xxwJFEcRkxKdTuqzIfVKg==,type:str]",
"data": "ENC[AES256_GCM,data:YajGibHC9pHqIF2pWd+DuHLXAy0syL+82TquEe45rZCYIp6ddmo4yo7MeaN/qyHaFKKKuQGluWJ48uyKzDJ3MsOihfUTB88tGDsE0aXtXjv52+tnhrS4AhfmyipGaq+AkKjwhrA9n9x0ap6mHvzxAt7xK7LOFpzfedtKIqaCuzbcoqIcy7G/D+X+1kFq0iE78NCjujfkCOXpDNfdQs4Tk/7+6uEr1wkYxNrQRA5K12Ni/Bqm5AfuteLPi5u3lRDnqOkqSGX7sOsV7rQIqy9+r+wrQLctmi33dEzKU4hZBJyxyccNyPEJa/8dDC57koGFvBrCPd/qO94iymH9nRAkqQ==,iv:wx4C7IUaf5zlUneNLKrQ3+xYfe0tdC+AJ6k8kRUnbwA=,tag:yldyFrDVFdCjGFAYel7JIg==,type:str]",
"sops": {
"age": [
{
"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBpNnRSUjFHL2I2N0craFp4\nNlBoRHNpbC93eC9qN2dOYnpJSllIV04yT0VzCkFBMEtoa0RzenJLNjlYT3QrcXMz\nS1hXZGszNkFIaUVpdVJYSmVVcTY1d3cKLS0tIG03bTRtWjlkQ2ZOTml1OFBLUVAv\nbTZnUStlOGdiVHlidXBXUXBtNm53MEkKdBtpkEVmymmbzuuBvnl4TwjOi+khaboO\nXSMlBkSkE7ynYAomtleUwt3WP6nVSok5TOCVCEn3S6h8ZZITiYNxVw==\n-----END AGE ENCRYPTED FILE-----\n",
"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBGaURiU3hMWmVHQ0JYZkxU\nRlRGV2ljckNyZHBlMWdJeDZHK3RBTC9HOVJjCmtiSlRXUFBpbFN5VDVHN1Q2N2dZ\ncHJTd0FQSUNpS2w4Q0tSV3phK0dNZkUKLS0tIEJZNnhPZWJGTXp3Qkl6MlFZekxl\nbW9jclZmV09yZWQwV2U4WFRzV3ZOT2MKi8lObEjaX/JLMU/U4BNt5o+GVKP9GBDa\nBqHL2xtkRIbe9MFp0hto+1qDGEek0Dj4sRAyiA1UBLm4cZjk3Np0CQ==\n-----END AGE ENCRYPTED FILE-----\n",
"recipient": "age1njap586hc0q43kr03g6c8eqhdsmk8zcafkl3f83xwlc2gqhlmfgs4tmwad"
},
{
"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBYWEdKbnducHcxY0d2Y1l5\nWE9TVFU2MEV2WndlNEQ0WGtNRnJZcVU0bUNrCmdlb3dnUnA3OXlXQ0dqZk5SR1hw\naUtBd2ZIZkQxMDIwbHp3UUhxd2FUamcKLS0tIEpjMHpiZjUwZlhSVitCbXZIK0Rw\nVXZwL1FsOFBjeXZZQjlrZ0NlNzdFTXMKe0kL289rbT7BAf9gduWZdoga87tLdJLP\nHhRUrDMta6FVFtJgk3gA+VcsIhVJV++1+Zb3YgHSzSvnRxhhH8CrLQ==\n-----END AGE ENCRYPTED FILE-----\n",
"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBrZkdsdlN3Q2docFZhaHdQ\nTlJjenVEQ2E0UHpOZ0YrelNYNkwvOFY4dDNJClk5Ymx3TllSQ2VPd3NGVGJQM0NZ\nY1dXaVRLZTlhRnBSYzJYbk4vdFZ0bm8KLS0tIG1pOWU4SVFrR25PZlEycmZYSGt1\nSlVNcFJUUFNZamppTjhKMlYrVThKQm8Ke2DwvBnDTKoCNrE6WX0KtPjMNd31uQxt\nEWyz/Bn8/TnilUQJambjGJ3vO/lxVcT0h/TLmTjbGFQ/HF0UAA150w==\n-----END AGE ENCRYPTED FILE-----\n",
"recipient": "age1k73g8x47hs93wcv7qh92n3htz8pl295g49hyvlrf3570mts0hgys5g04d6"
},
{
"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBUOTZ5S1VvTTNVK1dYVnI3\nL2dRdkN1bXZpSXJnRWR4bXFQeHcwSXdWK2w0CmlhWDl1cHdOek5BUi9Mb0ovaEZK\nVm9IQUhwYmIweFJzSGowUFNRVTZoWFkKLS0tIDlMZmY0MHJpdlFnMXJZK1dhZkhL\nRUZiZmE0YTNaU1hsUEwwWFVYUlpEQkUKWRHmltokpoZBPuSs3QibQ5W0ICs9gFrv\nYe3Kc2umaZemXOgs20isuxFLx/qsVnSwS1rS/SaUlyNN6aJvOZp7Uw==\n-----END AGE ENCRYPTED FILE-----\n",
"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSAxaEd4ajk5K1NKRkpOM1R5\nZ0t6dGYrbjhBbUh2WWF6NkwzNER3OURRWXlNCnMvOHFxUVNEVXpRbTVxWlY0Q2RC\nTUtOR0taMVhvR3lrZ08zSzVkRjJJK00KLS0tIHVUalV1cEsvMVp0NE84SEJjcFgw\nVmVRZUZiOUFhYXB3a3B5UzZxNG9xemcKeSuBschizNg/3KSkrQHARhQ6Vp8Yiofn\ngdnrXx6Ojb6lrlP1GalQqOck+CLclWU+lScsf91+dmaVm8cGVvZlgg==\n-----END AGE ENCRYPTED FILE-----\n",
"recipient": "age1fefy6dk8zn5c3edwmrs9vwx79quftnt784m628t9e34q3ft3cehqz8u72r"
}
],
"lastmodified": "2026-07-28T14:16:51Z",
"mac": "ENC[AES256_GCM,data:V6xUMnWIsy3umTlOOC4vwpwzwrSnFQS16VCgz8MAxYFDVe2dUPDYWrtXxERzzf+RHqKMfQyZ/LPitRwo3i376c9rb5qXBApF39YCsO69b/CG3C4jDXBDBIJbZ6HXFLO++DDScrxo1GaQHHWH/4Es4bZIjZib0YF1DJ5XSUSJHmU=,iv:fC5ymNvXB9fIDIxyeIPi/jHiYuf1xwFmcsFpiewSp5Q=,tag:0slrt9Xecg6AAT/+UP/PtQ==,type:str]",
"lastmodified": "2026-07-28T14:40:11Z",
"mac": "ENC[AES256_GCM,data:vm/cI0+z26VBe35ExS1Ak0XWGaNoFGWMBi0GfRWt9A+CH6rosBMQ+NXvdf8s1LP8ggUh00BPA8PwBzcq36N5N6vssm5XcDw0BWnqV4lCoK2v88E0i8WPmfOJ2b+3WTZc0CmdVBz9kHpA9rGMCleIhZa424AjY5Cbk1CV7fmLKg0=,iv:TiKMtsa/rns4Neiws61YQDH5KWbVxCQU/d65MkUm+xE=,tag:CsQOKi/XZVGjhYcHUgRrlA==,type:str]",
"version": "3.13.3"
}
}