Fix five quality findings; expand recovery and restore documentation
patch_ui.py: - Write Angular bundle atomically via tmp + os.replace, matching the pattern already used by _record_status. Prevents a corrupt bundle if the write is interrupted mid-boot. sitecustomize.py: - Tighten _record_status count barrier comment to name _Finder._targets as the canonical count, making the coupling visible to future editors. uninstall.sh: - Verify middlewared restarted cleanly after uninstall, with journalctl guidance on failure — matching recover.sh's existing pattern. apply.sh: - Change second line of site-packages error block from WARNING: prefix (misleading for an instructional message) to a plain Run: hint. create_task.py: - Guard __doc__ against None in epilog extraction so -OO does not crash. README.md: - Split Emergency recovery into three named subsections: middlewared won't start, web UI is blank or broken (corrupt bundle recovery), and backend verify shows FAIL. Each gives direct commands and escalation steps. - Add Restoring from a TrueCloud Backup section: finding the restic binary, gathering credentials, provider-specific env var setup for B2 and S3, listing and restoring snapshots, and operational notes on restore hygiene. - Clarify that hook_status.json is written once both target modules have loaded (not necessarily at the instant middlewared starts).
This commit is contained in:
+1
-1
@@ -77,7 +77,7 @@ SITE_PKG=$("$PYTHON" -c "import site; print(site.getsitepackages()[0])" 2>/dev/n
|
||||
|
||||
if [ -z "$SITE_PKG" ]; then
|
||||
echo "WARNING: Cannot determine site-packages directory; skipping backend patch."
|
||||
echo "WARNING: Verify that '$PYTHON -c \"import site; print(site.getsitepackages())\"' works."
|
||||
echo " Run: $PYTHON -c \"import site; print(site.getsitepackages())\""
|
||||
else
|
||||
# Back up any pre-existing sitecustomize.py that isn't ours.
|
||||
if [ -f "$SITE_PKG/sitecustomize.py" ] && \
|
||||
|
||||
@@ -188,7 +188,7 @@ def main():
|
||||
p = argparse.ArgumentParser(
|
||||
description="Manage TrueNAS TrueCloud Backup tasks (S3 / B2 / Storj)",
|
||||
formatter_class=argparse.RawDescriptionHelpFormatter,
|
||||
epilog=__doc__.split("Examples")[1] if "Examples" in __doc__ else "",
|
||||
epilog=__doc__.split("Examples")[1] if __doc__ and "Examples" in __doc__ else "",
|
||||
)
|
||||
p.add_argument("--host", default=None, metavar="HOST",
|
||||
help="TrueNAS hostname or IP address (required except for verify)")
|
||||
|
||||
+7
-1
@@ -109,11 +109,17 @@ def main():
|
||||
|
||||
patched, count = FIND.subn(REPLACE, content)
|
||||
|
||||
tmp = path + ".tmp"
|
||||
try:
|
||||
with open(path, "w", encoding="utf-8") as fh:
|
||||
with open(tmp, "w", encoding="utf-8") as fh:
|
||||
fh.write(patched)
|
||||
os.replace(tmp, path)
|
||||
except OSError as exc:
|
||||
print(f"[truecloud-patch] ERROR: Could not write {path}: {exc}")
|
||||
try:
|
||||
os.unlink(tmp)
|
||||
except OSError:
|
||||
pass
|
||||
return
|
||||
|
||||
print(f"[truecloud-patch] UI bundle patched ({count} replacement(s)): {path}")
|
||||
|
||||
@@ -189,7 +189,7 @@ def _record_status(fullname: str, ok: bool, detail: str = "") -> None:
|
||||
return # idempotent: first call wins
|
||||
_hook_status[fullname] = {"ok": ok, "detail": detail}
|
||||
if len(_hook_status) < len(_Finder._targets):
|
||||
return # wait until all patches have reported before writing
|
||||
return # wait for all patches; _Finder._targets is the canonical count
|
||||
|
||||
payload = {
|
||||
"patched_at": time.strftime("%Y-%m-%dT%H:%M:%SZ", time.gmtime()),
|
||||
|
||||
Reference in New Issue
Block a user