feat(vm-ops): make reinstall/clone/change-password async via DeployTask
Backend:
- Add DeployTask.kind column ('deploy'|'reinstall'|'clone'|'change_password')
+ Migration 23: ALTER TABLE deploy_tasks ADD kind, drop NOT NULL on template_id
- Update DeployTask.to_dict() with kind-aware Russian descriptions
- New backend/app/api/proxmox/async_ops.py with three workers:
_do_reinstall_sync, _do_clone_sync, _do_change_password_sync
All run on shared _deploy_executor thread pool from templates.py and
report progress through _update_deploy_task (DB + WebSocket broadcast)
- Rewrite five vms.py endpoints to return 202 + DeployTaskStartResponse:
POST /vm/{vmid}/clone, /container/{vmid}/clone,
POST /vm/{vmid}/reinstall,
POST /vm/{vmid}/change-password, /container/{vmid}/change-password
Frontend:
- DeployTask: add 'kind' and 'server_id' fields
- useCloneInstance/useReinstallInstance/useChangePassword now return
AsyncTaskResponse {task_id, status, name}; remove invalidateQueries
- InstanceActionDialogs: each onSuccess pushes task to deploy-tasks-store
with appropriate kind, shows 'launched in background' toast
- InstancesPage:
* ghostRows only for kind in {deploy, clone}, deduped by (server_id, vmid)
* reinstall / change_password tasks shown as inline overlay (badge + ring)
on the existing VM row's status column
This commit is contained in:
@@ -1287,6 +1287,31 @@ def migrate_deploy_tasks(conn):
|
||||
logger.info("✓ deploy_tasks table created")
|
||||
|
||||
|
||||
def migrate_deploy_tasks_kind(conn):
|
||||
"""Migration 23: Add 'kind' column to deploy_tasks (deploy/reinstall/clone/change_password)"""
|
||||
# Check if column exists
|
||||
result = conn.execute(text("""
|
||||
SELECT column_name FROM information_schema.columns
|
||||
WHERE table_name = 'deploy_tasks' AND column_name = 'kind'
|
||||
"""))
|
||||
if result.fetchone():
|
||||
logger.info("✓ deploy_tasks.kind already exists")
|
||||
return
|
||||
conn.execute(text("""
|
||||
ALTER TABLE deploy_tasks
|
||||
ADD COLUMN kind VARCHAR(30) NOT NULL DEFAULT 'deploy'
|
||||
"""))
|
||||
conn.execute(text("""
|
||||
CREATE INDEX IF NOT EXISTS idx_deploy_tasks_kind
|
||||
ON deploy_tasks (kind)
|
||||
"""))
|
||||
# template_id may be NULL for non-deploy tasks (clone/reinstall don't always need it)
|
||||
conn.execute(text("""
|
||||
ALTER TABLE deploy_tasks ALTER COLUMN template_id DROP NOT NULL
|
||||
"""))
|
||||
logger.info("✓ deploy_tasks.kind column added")
|
||||
|
||||
|
||||
def run_all_migrations(engine, db_session=None):
|
||||
"""
|
||||
Run all migrations in order.
|
||||
@@ -1477,6 +1502,14 @@ def run_all_migrations(engine, db_session=None):
|
||||
logger.warning(f"Deploy tasks migration: {e}")
|
||||
conn.rollback()
|
||||
|
||||
# Migration 23: deploy_tasks.kind column
|
||||
try:
|
||||
migrate_deploy_tasks_kind(conn)
|
||||
conn.commit()
|
||||
except Exception as e:
|
||||
logger.warning(f"Deploy tasks kind migration: {e}")
|
||||
conn.rollback()
|
||||
|
||||
logger.info("=" * 50)
|
||||
logger.info("✓ All migrations completed successfully")
|
||||
logger.info("=" * 50)
|
||||
|
||||
Reference in New Issue
Block a user