Files

109 lines
4.6 KiB
Python
Raw Permalink Normal View History

"""Агент-режим: установка/удаление агента, приём метрик."""
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)