diff --git a/install.sh b/install.sh index 4b59482..653587b 100755 --- a/install.sh +++ b/install.sh @@ -15,6 +15,14 @@ set -euo pipefail PATCH_DIR="/data/truecloud-patch" REPO_DIR="$(cd "$(dirname "$0")" && pwd)" +if [ ! -f "$REPO_DIR/patch/sitecustomize.py" ]; then + echo "ERROR: patch files not found at $REPO_DIR/patch/" >&2 + echo "Run install.sh from the cloned repository, not via pipe:" >&2 + echo " git clone https://github.com/sudolulo/truenas-truecloud-patch" >&2 + echo " cd truenas-truecloud-patch && bash install.sh" >&2 + exit 1 +fi + echo "=== TrueNAS TrueCloud Provider Patch — Install ===" echo "" @@ -98,7 +106,15 @@ fi # ── Restart middlewared ─────────────────────────────────────────────────────── echo "Restarting middlewared so the backend patch takes effect ..." -systemctl restart middlewared +if ! systemctl restart middlewared; then + echo "" >&2 + echo "ERROR: middlewared failed to restart. The patch files are installed but" >&2 + echo "the hook is not yet active. Check the system log for the root cause:" >&2 + echo " journalctl -u middlewared -n 50" >&2 + echo "If the problem is unrelated to this patch, recover with:" >&2 + echo " bash $PATCH_DIR/recover.sh" >&2 + exit 1 +fi echo "Done." echo "" echo "Refresh your browser to pick up the UI change." diff --git a/patch/apply.sh b/patch/apply.sh index d63287e..9fd9fa8 100755 --- a/patch/apply.sh +++ b/patch/apply.sh @@ -22,7 +22,7 @@ PATCH_DIR="/data/truecloud-patch" LOG="$PATCH_DIR/apply.log" # Rotate log at 512 KB to avoid unbounded growth on a system volume. -# Keep one prior generation (.1) so the last two boots are always available. +# Keep two prior generations (.1 and .2) so the last three boots are always available. if [ -f "$LOG" ] && [ "$(wc -c < "$LOG")" -gt 524288 ]; then [ -f "${LOG}.1" ] && mv "${LOG}.1" "${LOG}.2" mv "$LOG" "${LOG}.1" @@ -85,17 +85,24 @@ if [ -z "$SITE_PKG" ]; then echo " Run: $PYTHON -c \"import site; print(site.getsitepackages())\"" else # Back up any pre-existing sitecustomize.py that isn't ours. + _can_install=true if [ -f "$SITE_PKG/sitecustomize.py" ] && \ ! grep -q "truecloud-patch" "$SITE_PKG/sitecustomize.py" 2>/dev/null; then - cp "$SITE_PKG/sitecustomize.py" \ - "$SITE_PKG/sitecustomize.py.pre-truecloud-patch" - echo "OK: Backed up existing sitecustomize.py" + if cp "$SITE_PKG/sitecustomize.py" \ + "$SITE_PKG/sitecustomize.py.pre-truecloud-patch"; then + echo "OK: Backed up existing sitecustomize.py" + else + echo "WARNING: Could not back up existing sitecustomize.py; skipping install to avoid data loss." + _can_install=false + fi fi - if cp "$PATCH_DIR/sitecustomize.py" "$SITE_PKG/sitecustomize.py" 2>/dev/null; then - echo "OK: Installed sitecustomize.py → $SITE_PKG/sitecustomize.py" - else - echo "WARNING: Failed to write $SITE_PKG/sitecustomize.py (permission error?)" + if $_can_install; then + if cp "$PATCH_DIR/sitecustomize.py" "$SITE_PKG/sitecustomize.py" 2>/dev/null; then + echo "OK: Installed sitecustomize.py → $SITE_PKG/sitecustomize.py" + else + echo "WARNING: Failed to write $SITE_PKG/sitecustomize.py (permission error?)" + fi fi fi diff --git a/patch/create_task.py b/patch/create_task.py index 7cb8116..cd3dfcd 100755 --- a/patch/create_task.py +++ b/patch/create_task.py @@ -179,7 +179,10 @@ def cmd_create(client, args): } result = client("POST", "/cloud_backup", body) - print(f"Created task id={result['id']} name={result['description']!r}") + try: + print(f"Created task id={result['id']} name={result['description']!r}") + except (KeyError, TypeError): + print(f"Task created but response schema was unexpected: {result}") # ── CLI ─────────────────────────────────────────────────────────────────────── @@ -195,7 +198,9 @@ def main(): p.add_argument("--api-key", default=None, metavar="KEY", help="TrueNAS API key — System → API Keys (required except for verify)") p.add_argument("--insecure", action="store_true", - help="Skip TLS certificate verification (self-signed certs)") + help="Skip TLS certificate verification (self-signed certs). " + "WARNING: exposes your API key to network interception. " + "Prefer adding your cert to the trust store instead.") sub = p.add_subparsers(dest="cmd", required=True) diff --git a/patch/patch_ui.py b/patch/patch_ui.py index b93f73b..cc65625 100644 --- a/patch/patch_ui.py +++ b/patch/patch_ui.py @@ -90,7 +90,11 @@ def main(): backup = path + ".pre-truecloud-patch" if not os.path.exists(backup): - shutil.copy2(path, backup) + try: + shutil.copy2(path, backup) + except OSError as exc: + print(f"[truecloud-patch] ERROR: Could not create backup {backup}: {exc}") + return patched, count = FIND.subn(REPLACE, content) if count != 1: diff --git a/uninstall.sh b/uninstall.sh index b7a0426..41ac44d 100755 --- a/uninstall.sh +++ b/uninstall.sh @@ -104,9 +104,13 @@ echo "Restoring UI bundle backup ..." RESTORED=0 while IFS= read -r backup; do original="${backup%.pre-truecloud-patch}" - mv "$backup" "$original" - echo " Restored: $original" - RESTORED=1 + if mv "$backup" "$original"; then + echo " Restored: $original" + RESTORED=1 + else + echo " WARNING: Could not restore $original — backup left at $backup" + fi +# Keep these paths in sync with WEBUI_CANDIDATES in patch/patch_ui.py done < <(find /usr/share/truenas /usr/share/truenas-ui /var/www/truenas \ -name "*.js.pre-truecloud-patch" 2>/dev/null)