Run apply/rollback in background via systemd-run and add CLI modes
This commit is contained in:
57
pikit-api.py
57
pikit-api.py
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env python3
|
||||
import json, os, subprocess, socket, shutil, pathlib, datetime, tarfile
|
||||
import json, os, subprocess, socket, shutil, pathlib, datetime, tarfile, sys, argparse
|
||||
from http.server import BaseHTTPRequestHandler, HTTPServer
|
||||
import re
|
||||
import urllib.request
|
||||
@@ -741,6 +741,28 @@ def rollback_update_stub():
|
||||
return state
|
||||
|
||||
|
||||
def start_background_task(mode: str):
|
||||
"""
|
||||
Kick off a background update/rollback via systemd-run so nginx/API restarts
|
||||
do not break the caller connection.
|
||||
mode: "apply" or "rollback"
|
||||
"""
|
||||
assert mode in ("apply", "rollback"), "invalid mode"
|
||||
unit = f"pikit-update-{mode}"
|
||||
flag = f"--{mode}-update"
|
||||
cmd = [
|
||||
"systemd-run",
|
||||
"--unit",
|
||||
unit,
|
||||
"--quiet",
|
||||
"/usr/bin/env",
|
||||
"python3",
|
||||
str(API_PATH),
|
||||
flag,
|
||||
]
|
||||
subprocess.run(cmd, check=False)
|
||||
|
||||
|
||||
def acquire_lock():
|
||||
try:
|
||||
ensure_dir(UPDATE_LOCK.parent)
|
||||
@@ -899,11 +921,20 @@ class Handler(BaseHTTPRequestHandler):
|
||||
state = check_for_update()
|
||||
return self._send(200, state)
|
||||
if self.path.startswith("/api/update/apply"):
|
||||
state = apply_update_stub()
|
||||
return self._send(200, state)
|
||||
# Start background apply to avoid breaking caller during service restart
|
||||
start_background_task("apply")
|
||||
state = load_update_state()
|
||||
state["status"] = "in_progress"
|
||||
state["message"] = "Starting background apply"
|
||||
save_update_state(state)
|
||||
return self._send(202, state)
|
||||
if self.path.startswith("/api/update/rollback"):
|
||||
state = rollback_update_stub()
|
||||
return self._send(200, state)
|
||||
start_background_task("rollback")
|
||||
state = load_update_state()
|
||||
state["status"] = "in_progress"
|
||||
state["message"] = "Starting rollback"
|
||||
save_update_state(state)
|
||||
return self._send(202, state)
|
||||
if self.path.startswith("/api/update/auto"):
|
||||
state = load_update_state()
|
||||
state["auto_check"] = bool(payload.get("enable"))
|
||||
@@ -1043,4 +1074,20 @@ def main():
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
parser = argparse.ArgumentParser(description="Pi-Kit API / updater")
|
||||
parser.add_argument("--apply-update", action="store_true", help="Apply latest release (non-HTTP mode)")
|
||||
parser.add_argument("--check-update", action="store_true", help="Check for latest release (non-HTTP mode)")
|
||||
parser.add_argument("--rollback-update", action="store_true", help="Rollback to last backup (non-HTTP mode)")
|
||||
args = parser.parse_args()
|
||||
|
||||
if args.apply_update:
|
||||
apply_update_stub()
|
||||
sys.exit(0)
|
||||
if args.check_update:
|
||||
check_for_update()
|
||||
sys.exit(0)
|
||||
if args.rollback_update:
|
||||
rollback_update_stub()
|
||||
sys.exit(0)
|
||||
|
||||
main()
|
||||
|
||||
Reference in New Issue
Block a user