Initial YakPanel commit
This commit is contained in:
101
YakPanel-server/backend/app/api/service.py
Normal file
101
YakPanel-server/backend/app/api/service.py
Normal file
@@ -0,0 +1,101 @@
|
||||
"""YakPanel - System services (systemctl)"""
|
||||
from fastapi import APIRouter, Depends, HTTPException
|
||||
|
||||
from app.core.utils import exec_shell_sync
|
||||
from app.api.auth import get_current_user
|
||||
from app.models.user import User
|
||||
|
||||
router = APIRouter(prefix="/service", tags=["service"])
|
||||
|
||||
# Common services (name -> systemd unit)
|
||||
SERVICES = [
|
||||
{"id": "nginx", "name": "Nginx", "unit": "nginx"},
|
||||
{"id": "mysql", "name": "MySQL", "unit": "mysql"},
|
||||
{"id": "mariadb", "name": "MariaDB", "unit": "mariadb"},
|
||||
{"id": "php-fpm", "name": "PHP-FPM", "unit": "php*-fpm"},
|
||||
{"id": "redis", "name": "Redis", "unit": "redis-server"},
|
||||
{"id": "pure-ftpd", "name": "Pure-FTPd", "unit": "pure-ftpd"},
|
||||
]
|
||||
|
||||
|
||||
def _get_unit(unit_pattern: str) -> str:
|
||||
"""Resolve unit pattern (e.g. php*-fpm) to actual unit name."""
|
||||
if "*" not in unit_pattern:
|
||||
return unit_pattern
|
||||
out, _ = exec_shell_sync("systemctl list-unit-files --type=service --no-legend 2>/dev/null | grep -E 'php[0-9.-]+-fpm' | head -1", timeout=5)
|
||||
if out:
|
||||
return out.split()[0]
|
||||
return "php8.2-fpm" # fallback
|
||||
|
||||
|
||||
def _service_status(unit: str) -> str:
|
||||
"""Get service status: active, inactive, failed, not-found."""
|
||||
resolved = _get_unit(unit)
|
||||
out, err = exec_shell_sync(f"systemctl is-active {resolved} 2>/dev/null", timeout=5)
|
||||
status = out.strip() if out else "inactive"
|
||||
if err or status not in ("active", "inactive", "failed", "activating"):
|
||||
return "inactive" if status else "not-found"
|
||||
return status
|
||||
|
||||
|
||||
@router.get("/list")
|
||||
async def service_list(current_user: User = Depends(get_current_user)):
|
||||
"""List services with status"""
|
||||
result = []
|
||||
for s in SERVICES:
|
||||
unit = _get_unit(s["unit"])
|
||||
status = _service_status(s["unit"])
|
||||
result.append({
|
||||
**s,
|
||||
"unit": unit,
|
||||
"status": status,
|
||||
})
|
||||
return {"services": result}
|
||||
|
||||
|
||||
@router.post("/{service_id}/start")
|
||||
async def service_start(
|
||||
service_id: str,
|
||||
current_user: User = Depends(get_current_user),
|
||||
):
|
||||
"""Start service"""
|
||||
s = next((x for x in SERVICES if x["id"] == service_id), None)
|
||||
if not s:
|
||||
raise HTTPException(status_code=404, detail="Service not found")
|
||||
unit = _get_unit(s["unit"])
|
||||
out, err = exec_shell_sync(f"systemctl start {unit}", timeout=30)
|
||||
if err and "Failed" in err:
|
||||
raise HTTPException(status_code=500, detail=err.strip() or out.strip())
|
||||
return {"status": True, "msg": "Started"}
|
||||
|
||||
|
||||
@router.post("/{service_id}/stop")
|
||||
async def service_stop(
|
||||
service_id: str,
|
||||
current_user: User = Depends(get_current_user),
|
||||
):
|
||||
"""Stop service"""
|
||||
s = next((x for x in SERVICES if x["id"] == service_id), None)
|
||||
if not s:
|
||||
raise HTTPException(status_code=404, detail="Service not found")
|
||||
unit = _get_unit(s["unit"])
|
||||
out, err = exec_shell_sync(f"systemctl stop {unit}", timeout=30)
|
||||
if err and "Failed" in err:
|
||||
raise HTTPException(status_code=500, detail=err.strip() or out.strip())
|
||||
return {"status": True, "msg": "Stopped"}
|
||||
|
||||
|
||||
@router.post("/{service_id}/restart")
|
||||
async def service_restart(
|
||||
service_id: str,
|
||||
current_user: User = Depends(get_current_user),
|
||||
):
|
||||
"""Restart service"""
|
||||
s = next((x for x in SERVICES if x["id"] == service_id), None)
|
||||
if not s:
|
||||
raise HTTPException(status_code=404, detail="Service not found")
|
||||
unit = _get_unit(s["unit"])
|
||||
out, err = exec_shell_sync(f"systemctl restart {unit}", timeout=30)
|
||||
if err and "Failed" in err:
|
||||
raise HTTPException(status_code=500, detail=err.strip() or out.strip())
|
||||
return {"status": True, "msg": "Restarted"}
|
||||
Reference in New Issue
Block a user