Initial commit: Debian Manager — управление Debian-серверами
- SSH/SFTP управление без агентов - Пакеты (apt), Docker, файлы, systemd, ufw, cron - Плейбуки, групповые операции, планировщик - Бэкапы, отчёты, Portainer, Proxmox VE, Gitea Deploy - Терминал, Telegram-уведомления, тёмная/светлая тема
This commit is contained in:
@@ -0,0 +1,108 @@
|
||||
"""Агент-режим: установка/удаление агента, приём метрик."""
|
||||
import flet as ft
|
||||
|
||||
from app.core import agent as ag
|
||||
from app.core import servers as servers_core
|
||||
from app.ui.components import confirm_dialog, snack
|
||||
|
||||
|
||||
class AgentPage(ft.Column):
|
||||
def __init__(self, page: ft.Page, go):
|
||||
super().__init__(expand=True, scroll=ft.ScrollMode.AUTO, spacing=12)
|
||||
self._page = page
|
||||
self.cards_col = ft.Column(spacing=10)
|
||||
self.server_status = ft.Text("…", size=13)
|
||||
|
||||
self.controls = [
|
||||
ft.Text("Агент-режим", size=28, weight=ft.FontWeight.BOLD),
|
||||
ft.Text("Агент на сервере шлёт метрики каждые 5 сек по HTTP — "
|
||||
"real-time графики без SSH-поллинга. Приложение слушает порт "
|
||||
f"{ag.get_agent_port()}.",
|
||||
size=13, color=ft.Colors.GREY_500),
|
||||
ft.Row([
|
||||
ft.FilledButton("Запустить приёмник", icon=ft.Icons.PLAY_ARROW,
|
||||
on_click=self._start_server),
|
||||
self.server_status,
|
||||
]),
|
||||
ft.Divider(),
|
||||
self.cards_col,
|
||||
]
|
||||
self._reload()
|
||||
self._update_server_status()
|
||||
|
||||
def _update_server_status(self):
|
||||
self.server_status.value = (
|
||||
f"✅ приёмник запущен на порту {ag.get_agent_port()}"
|
||||
if ag.is_running() else "⚪ приёмник не запущен"
|
||||
)
|
||||
self._page.update()
|
||||
|
||||
def _start_server(self, e):
|
||||
async def _s():
|
||||
await ag.start()
|
||||
self._update_server_status()
|
||||
self._page.run_task(_s)
|
||||
|
||||
def _reload(self):
|
||||
self.cards_col.controls = []
|
||||
for srv in servers_core.list_servers():
|
||||
self.cards_col.controls.append(self._card(srv))
|
||||
self._page.update()
|
||||
for srv, card in zip(servers_core.list_servers(), self.cards_col.controls):
|
||||
self._page.run_task(self._fill, srv, card)
|
||||
|
||||
def _card(self, srv):
|
||||
return ft.Card(content=ft.Container(
|
||||
padding=14, width=560,
|
||||
content=ft.Column([
|
||||
ft.Text(srv.name, weight=ft.FontWeight.BOLD, size=16),
|
||||
ft.ProgressBar(height=3),
|
||||
]),
|
||||
))
|
||||
|
||||
async def _fill(self, srv, card):
|
||||
status = await ag.agent_status(srv)
|
||||
metrics = ag.agent_metrics.get(srv.id)
|
||||
running = status == "active"
|
||||
|
||||
rows = [ft.Text(f"статус: {status}", size=12,
|
||||
color=ft.Colors.GREEN_300 if running else ft.Colors.GREY_500)]
|
||||
if metrics:
|
||||
import time
|
||||
age = time.time() - metrics.get("ts", 0)
|
||||
rows.append(ft.Text(
|
||||
f"CPU {metrics.get('cpu')}% • RAM {metrics.get('mem_pct')}% • "
|
||||
f"Диск {metrics.get('disk')}% • load {metrics.get('load')} • "
|
||||
f"обновлено {age:.0f} сек назад",
|
||||
size=11, color=ft.Colors.BLUE_300))
|
||||
btns = []
|
||||
if not running:
|
||||
btns.append(ft.FilledButton("Установить агента", icon=ft.Icons.DOWNLOAD,
|
||||
on_click=lambda e, s=srv: self._install(s)))
|
||||
else:
|
||||
btns.append(ft.OutlinedButton("Удалить агента",
|
||||
on_click=lambda e, s=srv: self._uninstall(s)))
|
||||
rows.append(ft.Row(btns))
|
||||
card.content.content.controls[1] = ft.Column(rows, spacing=4)
|
||||
self._page.update()
|
||||
|
||||
def _install(self, srv):
|
||||
from app.core.tasks import tasks
|
||||
import socket
|
||||
app_host = socket.gethostbyname(socket.gethostname())
|
||||
async def job(log):
|
||||
log(f"адрес приложения для агента: {app_host}:{ag.get_agent_port()}")
|
||||
ok = await ag.install_agent(srv, app_host, log)
|
||||
log("готово" if ok else "ошибка установки")
|
||||
tasks.start("agent", "установка агента", srv.id, job,
|
||||
on_done=lambda r: self._reload())
|
||||
snack(self._page, f"Установка агента на {srv.name}…")
|
||||
|
||||
def _uninstall(self, srv):
|
||||
def do():
|
||||
async def _d():
|
||||
await ag.uninstall_agent(srv)
|
||||
self._reload()
|
||||
self._page.run_task(_d)
|
||||
confirm_dialog(self._page, "Удалить агента?",
|
||||
f"dm-agent будет остановлен и удалён с «{srv.name}».", do)
|
||||
Reference in New Issue
Block a user