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:
markmorado
2026-03-08 18:29:29 +01:00
parent 2c8becc6d4
commit b3db346cfb
21 changed files with 3676 additions and 93 deletions

View File

@@ -349,6 +349,25 @@ async def restore_backup(
# ==================== Scheduled Backup Jobs ====================
@router.get("/api/backups/proxmox-jobs/{server_id}")
def list_proxmox_native_jobs(
server_id: int,
db: Session = Depends(get_db),
current_user: User = Depends(PermissionChecker("backup:view")),
):
"""Fetch native vzdump backup schedules configured directly in Proxmox"""
server = db.query(ProxmoxServer).filter(ProxmoxServer.id == server_id).first()
if not server:
raise HTTPException(status_code=404, detail="Server not found")
try:
client = _get_proxmox_client(server)
jobs = client.get_cluster_backup_jobs()
return JSONResponse(content={"jobs": jobs, "server_name": server.name})
except Exception as e:
logger.error(f"Error fetching proxmox native jobs for server {server_id}: {e}")
return JSONResponse(content={"jobs": [], "error": str(e)})
@router.get("/api/backups/jobs")
def list_backup_jobs(
db: Session = Depends(get_db),
@@ -408,9 +427,10 @@ async def create_backup_job(
except Exception as e:
logger.warning(f"Could not register job {job.id} with scheduler: {e}")
LoggingService.log_action(
db=db, action="backup_job_create", resource_type="backup_job",
LoggingService.log_proxmox_action(
db=db, action="create", resource_type="backup_job",
resource_id=str(job.id), username=current_user.username, success=True,
server_id=job.server_id, node_name=job.node,
)
return JSONResponse(content={"success": True, "job": job.to_dict()})