diff --git a/AppImage/components/virtual-machines.tsx b/AppImage/components/virtual-machines.tsx
index 56d19dc6..d44a402c 100644
--- a/AppImage/components/virtual-machines.tsx
+++ b/AppImage/components/virtual-machines.tsx
@@ -224,6 +224,28 @@ const getUsageColor = (percent: number): string => {
return "text-foreground"
}
+// Generate consistent color for storage names
+const storageColors = [
+ { bg: "bg-blue-500/20", text: "text-blue-400", border: "border-blue-500/30" },
+ { bg: "bg-emerald-500/20", text: "text-emerald-400", border: "border-emerald-500/30" },
+ { bg: "bg-purple-500/20", text: "text-purple-400", border: "border-purple-500/30" },
+ { bg: "bg-amber-500/20", text: "text-amber-400", border: "border-amber-500/30" },
+ { bg: "bg-pink-500/20", text: "text-pink-400", border: "border-pink-500/30" },
+ { bg: "bg-cyan-500/20", text: "text-cyan-400", border: "border-cyan-500/30" },
+ { bg: "bg-rose-500/20", text: "text-rose-400", border: "border-rose-500/30" },
+ { bg: "bg-indigo-500/20", text: "text-indigo-400", border: "border-indigo-500/30" },
+]
+
+const getStorageColor = (storageName: string) => {
+ // Generate a consistent hash from storage name
+ let hash = 0
+ for (let i = 0; i < storageName.length; i++) {
+ hash = storageName.charCodeAt(i) + ((hash << 5) - hash)
+ }
+ const index = Math.abs(hash) % storageColors.length
+ return storageColors[index]
+}
+
const getIconColor = (percent: number): string => {
if (percent >= 95) return "text-red-500"
if (percent >= 86) return "text-orange-500"
@@ -1423,7 +1445,10 @@ const handleDownloadLogs = async (vmid: number, vmName: string) => {
{backup.date}
-
+
{backup.storage}
diff --git a/AppImage/scripts/flask_server.py b/AppImage/scripts/flask_server.py
index dca5ea77..8635fa0a 100644
--- a/AppImage/scripts/flask_server.py
+++ b/AppImage/scripts/flask_server.py
@@ -5650,11 +5650,9 @@ def api_create_backup(vmid):
notes = notes.replace('{{vmid}}', str(vmid))
notes = notes.replace('{{node}}', node or '')
- # Build pvesh command to create backup via Proxmox API
- # This creates a vzdump task through the API which handles clustering properly
+ # Build vzdump command directly (more reliable than pvesh for backups)
cmd = [
- 'pvesh', 'create', f'/nodes/{node}/vzdump',
- '--vmid', str(vmid),
+ 'vzdump', str(vmid),
'--storage', storage,
'--mode', mode,
'--compress', compress
@@ -5664,12 +5662,7 @@ def api_create_backup(vmid):
if protected:
cmd.extend(['--protected', '1'])
- # Add notification mode (mailnotification for older versions, notification-mode for newer)
- if notification and notification != 'auto':
- # Try notification-mode first (newer Proxmox versions)
- cmd.extend(['--notification-mode', notification])
-
- # Add notes if provided
+ # Add notes if provided (use --description for compatibility)
if notes:
cmd.extend(['--notes-template', notes])
@@ -5677,14 +5670,26 @@ def api_create_backup(vmid):
if pbs_change_detection and pbs_change_detection != 'default' and vm_type == 'lxc':
cmd.extend(['--pbs-change-detection-mode', pbs_change_detection])
- # Execute the backup command
- result = subprocess.run(cmd, capture_output=True, text=True, timeout=30)
+ # Execute vzdump - it will create a Proxmox task automatically
+ # Using Popen to not block and let vzdump manage the task
+ process = subprocess.Popen(
+ cmd,
+ stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE,
+ start_new_session=True # Detach from parent process
+ )
- if result.returncode != 0:
- error_msg = result.stderr or result.stdout or 'Unknown error'
+ # Give it a moment to start and check if it failed immediately
+ import time
+ time.sleep(0.5)
+
+ # Check if process failed immediately
+ poll_result = process.poll()
+ if poll_result is not None and poll_result != 0:
+ _, stderr = process.communicate(timeout=5)
return jsonify({
'success': False,
- 'error': f'Backup failed: {error_msg}',
+ 'error': f'Backup failed to start: {stderr.decode() if stderr else "Unknown error"}',
'command': ' '.join(cmd)
}), 500
@@ -5695,9 +5700,7 @@ def api_create_backup(vmid):
'mode': mode,
'compress': compress,
'protected': protected,
- 'notification': notification,
- 'notes': notes,
- 'task_output': result.stdout
+ 'notes': notes
})
except subprocess.TimeoutExpired: