Интегрирован wesp в сайт
CI / quality (push) Canceled after 0s

This commit is contained in:
влад
2026-07-17 12:57:18 +03:00
parent 5dfa06ddbe
commit 355c0ef9f1
883 changed files with 194576 additions and 177 deletions
@@ -0,0 +1,148 @@
"""Отложенный перезапуск службы WESP и перезагрузка Pi (админка / OTA)."""
from __future__ import annotations
import logging
import shlex
import subprocess
import time
from typing import Any, Dict, Optional, Tuple
logger = logging.getLogger(__name__)
def _env_bool(value: Any, default: bool = True) -> bool:
if value is None:
return default
if isinstance(value, bool):
return value
return str(value).strip().lower() not in ("0", "false", "no", "off", "")
def _delay_sec(app_config: Dict[str, Any]) -> float:
try:
return max(1.0, float(app_config.get("WESP_AUTO_REBOOT_DELAY_SEC", 3)))
except (TypeError, ValueError):
return 3.0
def default_systemd_restart_cmd(app_config: Dict[str, Any]) -> str:
raw = app_config.get("WESP_SYSTEMD_UNIT")
if raw is None:
unit = "myscript"
else:
unit = str(raw).strip()
if not unit:
return ""
return f"systemctl restart {unit}"
def resolve_admin_restart_cmd(app_config: Dict[str, Any]) -> str:
explicit = (app_config.get("WESP_ADMIN_RESTART_CMD") or "").strip()
if explicit:
return explicit
return default_systemd_restart_cmd(app_config)
def resolve_update_restart_cmd(app_config: Dict[str, Any]) -> str:
explicit = (app_config.get("UPDATE_RESTART_CMD") or "").strip()
if explicit:
return explicit
base = (app_config.get("BASE_DIR") or "").strip()
if base:
script = f"{base}/scripts/post_update.sh"
return f'bash "{script}"'
return ""
def _spawn_shell(cmd: str, *, label: str) -> Tuple[bool, str]:
cmd = (cmd or "").strip()
if not cmd:
return False, f"Команда не задана ({label})"
try:
wrapped = f"nohup bash -c {shlex.quote(cmd)} >/dev/null 2>&1 &"
subprocess.Popen(
["bash", "-c", wrapped],
stdin=subprocess.DEVNULL,
stdout=subprocess.DEVNULL,
stderr=subprocess.DEVNULL,
start_new_session=True,
)
logger.info("Запланировано в фоне (%s): %s", label, cmd)
return True, cmd
except OSError as exc:
logger.warning("Не удалось запустить %s: %s", label, exc)
return False, str(exc)
def schedule_delayed_command(cmd: str, *, delay_sec: float, label: str) -> Dict[str, Any]:
delay = max(1.0, float(delay_sec))
inner = f"sleep {int(delay)}; {cmd}"
ok, detail = _spawn_shell(inner, label=label)
return {
"scheduled": ok,
"delay_sec": delay,
"command": cmd,
"detail": detail,
}
def schedule_service_restart(
app_config: Dict[str, Any],
*,
delay_sec: Optional[float] = None,
) -> Dict[str, Any]:
cmd = resolve_admin_restart_cmd(app_config)
delay = delay_sec if delay_sec is not None else _delay_sec(app_config)
result = schedule_delayed_command(cmd, delay_sec=delay, label="service_restart")
if result.get("scheduled"):
result["message"] = (
f"Перезапуск WESP через {int(delay)} с ({cmd})."
)
else:
result["message"] = (
"Задайте WESP_ADMIN_RESTART_CMD или WESP_SYSTEMD_UNIT (например myscript)."
)
return result
def schedule_system_reboot(
app_config: Dict[str, Any],
*,
delay_sec: Optional[float] = None,
reason: str = "",
) -> Dict[str, Any]:
if not _env_bool(app_config.get("WESP_AUTO_REBOOT_ENABLED"), True):
return {
"scheduled": False,
"message": "Автоперезагрузка отключена (WESP_AUTO_REBOOT_ENABLED=0).",
}
cmd = (app_config.get("WESP_ADMIN_REBOOT_CMD") or "sudo /sbin/reboot").strip()
delay = delay_sec if delay_sec is not None else _delay_sec(app_config)
result = schedule_delayed_command(cmd, delay_sec=delay, label="reboot")
if result.get("scheduled"):
suffix = f" ({reason})" if reason else ""
result["message"] = (
f"Перезагрузка устройства через {int(delay)} с{suffix}."
)
else:
result["message"] = "Не удалось запланировать reboot (WESP_ADMIN_REBOOT_CMD)."
return result
def maybe_auto_reboot_after_kiosk_change(app_config: Dict[str, Any]) -> Dict[str, Any]:
if not _env_bool(app_config.get("WESP_KIOSK_AUTO_REBOOT"), True):
return {"scheduled": False}
return schedule_system_reboot(app_config, reason="киоск")
def maybe_auto_reboot_after_pi_boot_change(app_config: Dict[str, Any]) -> Dict[str, Any]:
if not _env_bool(app_config.get("WESP_PI_BOOT_AUTO_REBOOT"), True):
return {"scheduled": False}
return schedule_system_reboot(app_config, reason="config.txt")
def maybe_auto_reboot_after_plymouth_install(app_config: Dict[str, Any]) -> Dict[str, Any]:
if not _env_bool(app_config.get("WESP_PLYMOUTH_AUTO_REBOOT"), True):
return {"scheduled": False}
return schedule_system_reboot(app_config, reason="Plymouth")