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:
@@ -1049,6 +1049,74 @@ def migrate_ipam_network_node(conn):
|
||||
logger.info("✓ ipam_networks.proxmox_node already exists")
|
||||
|
||||
|
||||
def migrate_cluster_support(conn):
|
||||
"""Migration 17: Add cluster_name column to proxmox_servers table"""
|
||||
logger.info("Migration 17: Adding cluster support to proxmox_servers...")
|
||||
|
||||
if add_column_if_not_exists(conn, 'proxmox_servers', 'cluster_name', 'VARCHAR(100)'):
|
||||
conn.execute(text("""
|
||||
CREATE INDEX IF NOT EXISTS idx_proxmox_cluster_name
|
||||
ON proxmox_servers(cluster_name)
|
||||
"""))
|
||||
logger.info("✓ Added cluster_name column and index to proxmox_servers")
|
||||
else:
|
||||
logger.info("✓ proxmox_servers.cluster_name already exists")
|
||||
|
||||
# Add cluster:manage permission to admin role if not already present
|
||||
try:
|
||||
result = conn.execute(text("SELECT permissions FROM roles WHERE name = 'admin'")).fetchone()
|
||||
if result:
|
||||
import json as _json
|
||||
perms = _json.loads(result.permissions) if isinstance(result.permissions, str) else result.permissions
|
||||
if not perms.get('proxmox.cluster.manage'):
|
||||
perms['proxmox.cluster.manage'] = True
|
||||
conn.execute(
|
||||
text("UPDATE roles SET permissions = :p WHERE name = 'admin'"),
|
||||
{"p": _json.dumps(perms)}
|
||||
)
|
||||
logger.info("✓ Added proxmox.cluster.manage to admin role")
|
||||
except Exception as e:
|
||||
logger.warning(f"Could not update admin role permissions: {e}")
|
||||
|
||||
|
||||
# ==================== Migration 18: Proxmox Tasks (UPID) ====================
|
||||
|
||||
def migrate_proxmox_tasks(conn):
|
||||
"""Create proxmox_tasks table for tracking long-running Proxmox UPID tasks."""
|
||||
logger.info("Migration 18: Creating proxmox_tasks table...")
|
||||
|
||||
if table_exists(conn, 'proxmox_tasks'):
|
||||
logger.info("Table proxmox_tasks already exists, skipping")
|
||||
return
|
||||
|
||||
conn.execute(text("""
|
||||
CREATE TABLE proxmox_tasks (
|
||||
id SERIAL PRIMARY KEY,
|
||||
upid VARCHAR(200) NOT NULL,
|
||||
server_id INTEGER REFERENCES proxmox_servers(id) ON DELETE SET NULL,
|
||||
user_id INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
||||
node VARCHAR(100),
|
||||
vmid INTEGER,
|
||||
vm_type VARCHAR(10),
|
||||
action VARCHAR(100) NOT NULL,
|
||||
description VARCHAR(500),
|
||||
status VARCHAR(20) NOT NULL DEFAULT 'running',
|
||||
exit_status VARCHAR(100),
|
||||
log_text TEXT,
|
||||
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW() NOT NULL,
|
||||
completed_at TIMESTAMP WITH TIME ZONE
|
||||
)
|
||||
"""))
|
||||
|
||||
conn.execute(text("CREATE INDEX idx_proxmox_tasks_upid ON proxmox_tasks(upid)"))
|
||||
conn.execute(text("CREATE INDEX idx_proxmox_tasks_user_id ON proxmox_tasks(user_id)"))
|
||||
conn.execute(text("CREATE INDEX idx_proxmox_tasks_status ON proxmox_tasks(status)"))
|
||||
conn.execute(text("CREATE INDEX idx_proxmox_tasks_user_status ON proxmox_tasks(user_id, status)"))
|
||||
conn.execute(text("CREATE INDEX idx_proxmox_tasks_created ON proxmox_tasks(created_at DESC)"))
|
||||
|
||||
logger.info("✓ proxmox_tasks table created")
|
||||
|
||||
|
||||
def run_all_migrations(engine, db_session=None):
|
||||
"""
|
||||
Run all migrations in order.
|
||||
@@ -1191,6 +1259,22 @@ def run_all_migrations(engine, db_session=None):
|
||||
logger.warning(f"IPAM network node migration: {e}")
|
||||
conn.rollback()
|
||||
|
||||
# Migration 17: Cluster Support (cluster_name column)
|
||||
try:
|
||||
migrate_cluster_support(conn)
|
||||
conn.commit()
|
||||
except Exception as e:
|
||||
logger.warning(f"Cluster support migration: {e}")
|
||||
conn.rollback()
|
||||
|
||||
# Migration 18: Proxmox Tasks (UPID tracking)
|
||||
try:
|
||||
migrate_proxmox_tasks(conn)
|
||||
conn.commit()
|
||||
except Exception as e:
|
||||
logger.warning(f"Proxmox tasks migration: {e}")
|
||||
conn.rollback()
|
||||
|
||||
logger.info("=" * 50)
|
||||
logger.info("✓ All migrations completed successfully")
|
||||
logger.info("=" * 50)
|
||||
|
||||
Reference in New Issue
Block a user