feat: v1.1.0 — backup module, IPAM node binding, HA, task queue, theme CSS
- Backup module: full CRUD for storages, backup files, scheduled jobs (APScheduler) - Proxmox client: storage/backup/restore/HA methods - IPAM: proxmox_node field, server+node binding for networks and allocations - Task queue service: improvements and new task types - Monitoring worker: extended metrics and alerts - HA support: add/remove VMs from Proxmox HA groups - tasks.html: new task tracking page - proxmox_vms.html: major UI update (bulk ops, HA, snapshots) - backups.html: full backup management UI (3 tabs) - base.html: sidebar backup link, websocket manager - theme.css: full CSS variables theme, 395 lines added - migrations: migration #15 (BackupJob), #16 (proxmox_node) - RBAC: backup resource permissions - websocket_manager.py: new module for WS connections
This commit is contained in:
@@ -156,7 +156,8 @@ async def run_backup_job(job_id: int) -> None:
|
||||
storage=job.storage,
|
||||
mode=job.mode,
|
||||
compress=job.compress,
|
||||
remove=job.keep_last,
|
||||
remove=1 if job.keep_last else 0,
|
||||
keep_last=job.keep_last,
|
||||
notes=job.notes,
|
||||
)
|
||||
if result.get("success"):
|
||||
|
||||
@@ -18,10 +18,22 @@ try:
|
||||
from backend.app.db import SessionLocal
|
||||
from backend.app.models import TaskQueue, ProxmoxServer, User
|
||||
from backend.app.proxmox_client import ProxmoxClient
|
||||
from backend.app.websocket_manager import broadcast_task_update
|
||||
except ImportError:
|
||||
from app.db import SessionLocal
|
||||
from app.models import TaskQueue, ProxmoxServer, User
|
||||
from app.proxmox_client import ProxmoxClient
|
||||
from app.websocket_manager import broadcast_task_update
|
||||
|
||||
|
||||
def _ws_broadcast(task: TaskQueue, event: str = "task_update") -> None:
|
||||
"""Fire-and-forget WS broadcast for a TaskQueue update."""
|
||||
try:
|
||||
data = task.to_dict()
|
||||
data["kind"] = "bulk"
|
||||
broadcast_task_update(task.user_id, event, data)
|
||||
except Exception as e:
|
||||
logger.debug(f"[TASK QUEUE] WS broadcast skipped: {e}")
|
||||
|
||||
|
||||
class TaskQueueService:
|
||||
@@ -114,6 +126,7 @@ class TaskQueueService:
|
||||
task.completed_at = utcnow()
|
||||
db.commit()
|
||||
|
||||
_ws_broadcast(task, "task_update")
|
||||
logger.info(f"[TASK QUEUE] Task #{task_id} cancelled by user {user_id}")
|
||||
return True
|
||||
|
||||
@@ -220,6 +233,7 @@ class TaskQueueProcessor:
|
||||
task.started_at = utcnow()
|
||||
db.commit()
|
||||
|
||||
_ws_broadcast(task, "task_update")
|
||||
logger.info(f"[TASK QUEUE] Starting task #{task.id}: {task.task_type}")
|
||||
|
||||
# Determine action from task type
|
||||
@@ -276,12 +290,14 @@ class TaskQueueProcessor:
|
||||
# Update progress
|
||||
task.results = results
|
||||
db.commit()
|
||||
_ws_broadcast(task, "task_update")
|
||||
|
||||
# Mark as completed
|
||||
task.status = 'completed'
|
||||
task.completed_at = utcnow()
|
||||
db.commit()
|
||||
|
||||
_ws_broadcast(task, "task_update")
|
||||
logger.info(f"[TASK QUEUE] Completed task #{task.id}: {task.completed_items} success, {task.failed_items} failed")
|
||||
|
||||
except Exception as e:
|
||||
@@ -291,6 +307,7 @@ class TaskQueueProcessor:
|
||||
task.error_message = str(e)
|
||||
task.completed_at = utcnow()
|
||||
db.commit()
|
||||
_ws_broadcast(task, "task_update")
|
||||
except Exception:
|
||||
pass
|
||||
finally:
|
||||
|
||||
Reference in New Issue
Block a user