+ {selectedVM && (
+ <>
+ {/* Basic Information */}
Basic Information
-
-
-
Name
-
{selectedVM.name}
-
-
-
Type
-
- {getTypeBadge(selectedVM.type).label}
-
-
+
-
-
Status
-
- {selectedVM.status.toUpperCase()}
-
-
CPU Usage
{(selectedVM.cpu * 100).toFixed(1)}%
@@ -492,6 +478,169 @@ export function VirtualMachines() {
+ {/* Resources Configuration */}
+ {detailsLoading ? (
+
Loading configuration...
+ ) : vmDetails?.config ? (
+ <>
+
+
Resources
+
+ {vmDetails.config.cores && (
+
+
CPU Cores
+
{vmDetails.config.cores}
+
+ )}
+ {vmDetails.config.sockets && (
+
+
CPU Sockets
+
{vmDetails.config.sockets}
+
+ )}
+ {vmDetails.config.memory && (
+
+
Memory
+
{vmDetails.config.memory} MB
+
+ )}
+ {vmDetails.config.swap && (
+
+
Swap
+
{vmDetails.config.swap} MB
+
+ )}
+ {vmDetails.config.rootfs && (
+
+
Root Filesystem
+
+ {vmDetails.config.rootfs}
+
+
+ )}
+ {vmDetails.config.scsi0 && (
+
+
SCSI Disk 0
+
+ {vmDetails.config.scsi0}
+
+
+ )}
+ {vmDetails.config.ide0 && (
+
+
IDE Disk 0
+
{vmDetails.config.ide0}
+
+ )}
+
+
+
+ {/* Network Configuration */}
+
+
Network
+
+ {vmDetails.config.net0 && (
+
+
Network Interface 0
+
{vmDetails.config.net0}
+
+ )}
+ {vmDetails.config.net1 && (
+
+
Network Interface 1
+
{vmDetails.config.net1}
+
+ )}
+ {vmDetails.config.net2 && (
+
+
Network Interface 2
+
{vmDetails.config.net2}
+
+ )}
+ {vmDetails.config.nameserver && (
+
+
DNS Nameserver
+
{vmDetails.config.nameserver}
+
+ )}
+ {vmDetails.config.searchdomain && (
+
+
Search Domain
+
{vmDetails.config.searchdomain}
+
+ )}
+ {vmDetails.config.hostname && (
+
+
Hostname
+
{vmDetails.config.hostname}
+
+ )}
+
+
+
+ {/* Options */}
+
+
Options
+
+ {vmDetails.config.onboot !== undefined && (
+
+
Start on Boot
+
+ {vmDetails.config.onboot ? "Yes" : "No"}
+
+
+ )}
+ {vmDetails.config.unprivileged !== undefined && (
+
+
Unprivileged
+
+ {vmDetails.config.unprivileged ? "Yes" : "No"}
+
+
+ )}
+ {vmDetails.config.ostype && (
+
+
OS Type
+
{vmDetails.config.ostype}
+
+ )}
+ {vmDetails.config.arch && (
+
+
Architecture
+
{vmDetails.config.arch}
+
+ )}
+ {vmDetails.config.boot && (
+
+
Boot Order
+
{vmDetails.config.boot}
+
+ )}
+ {vmDetails.config.features && (
+
+
Features
+
{vmDetails.config.features}
+
+ )}
+
+
+ >
+ ) : null}
+
{/* Control Actions */}
Control Actions
@@ -546,181 +695,9 @@ export function VirtualMachines() {
Download Logs
-
-
- {/* Resources Tab */}
-
- {detailsLoading ? (
- Loading configuration...
- ) : vmDetails?.config ? (
-
-
- {vmDetails.config.cores && (
-
-
CPU Cores
-
{vmDetails.config.cores}
-
- )}
- {vmDetails.config.sockets && (
-
-
CPU Sockets
-
{vmDetails.config.sockets}
-
- )}
- {vmDetails.config.memory && (
-
-
Memory
-
{vmDetails.config.memory} MB
-
- )}
- {vmDetails.config.swap && (
-
-
Swap
-
{vmDetails.config.swap} MB
-
- )}
- {vmDetails.config.rootfs && (
-
-
Root Filesystem
-
{vmDetails.config.rootfs}
-
- )}
- {vmDetails.config.scsi0 && (
-
-
SCSI Disk 0
-
{vmDetails.config.scsi0}
-
- )}
- {vmDetails.config.ide0 && (
-
-
IDE Disk 0
-
{vmDetails.config.ide0}
-
- )}
-
-
- ) : (
- No configuration data available
- )}
-
-
- {/* Network Tab */}
-
- {detailsLoading ? (
- Loading configuration...
- ) : vmDetails?.config ? (
-
-
- {vmDetails.config.net0 && (
-
-
Network Interface 0
-
{vmDetails.config.net0}
-
- )}
- {vmDetails.config.net1 && (
-
-
Network Interface 1
-
{vmDetails.config.net1}
-
- )}
- {vmDetails.config.net2 && (
-
-
Network Interface 2
-
{vmDetails.config.net2}
-
- )}
- {vmDetails.config.nameserver && (
-
-
DNS Nameserver
-
{vmDetails.config.nameserver}
-
- )}
- {vmDetails.config.searchdomain && (
-
-
Search Domain
-
{vmDetails.config.searchdomain}
-
- )}
- {vmDetails.config.hostname && (
-
-
Hostname
-
{vmDetails.config.hostname}
-
- )}
-
-
- ) : (
- No network configuration available
- )}
-
-
- {/* Options Tab */}
-
- {detailsLoading ? (
- Loading configuration...
- ) : vmDetails?.config ? (
-
-
- {vmDetails.config.onboot !== undefined && (
-
-
Start on Boot
-
- {vmDetails.config.onboot ? "Yes" : "No"}
-
-
- )}
- {vmDetails.config.unprivileged !== undefined && (
-
-
Unprivileged
-
- {vmDetails.config.unprivileged ? "Yes" : "No"}
-
-
- )}
- {vmDetails.config.ostype && (
-
-
OS Type
-
{vmDetails.config.ostype}
-
- )}
- {vmDetails.config.arch && (
-
-
Architecture
-
{vmDetails.config.arch}
-
- )}
- {vmDetails.config.boot && (
-
-
Boot Order
-
{vmDetails.config.boot}
-
- )}
- {vmDetails.config.features && (
-
-
Features
-
{vmDetails.config.features}
-
- )}
-
-
- ) : (
- No options available
- )}
-
-
- )}
+ >
+ )}
+
diff --git a/AppImage/scripts/flask_server.py b/AppImage/scripts/flask_server.py
index 75fe45c..3116710 100644
--- a/AppImage/scripts/flask_server.py
+++ b/AppImage/scripts/flask_server.py
@@ -1489,23 +1489,16 @@ def api_vm_logs(vmid):
# Get real logs from the container/VM (last 1000 lines)
log_result = subprocess.run(
- ['pvesh', 'get', f'/nodes/{node}/{vm_type}/{vmid}/log', '--limit', '1000', '--output-format', 'json'],
+ ['pvesh', 'get', f'/nodes/{node}/{vm_type}/{vmid}/log', '--start', '0', '--limit', '1000'],
capture_output=True, text=True, timeout=10
)
logs = []
if log_result.returncode == 0:
- try:
- log_data = json.loads(log_result.stdout)
- # The API returns an array of log line objects
- if isinstance(log_data, list):
- logs = log_data
- else:
- # Fallback: parse as text
- logs = [{'n': i, 't': line} for i, line in enumerate(log_result.stdout.split('\n')) if line]
- except json.JSONDecodeError:
- # Parse as plain text if JSON fails
- logs = [{'n': i, 't': line} for i, line in enumerate(log_result.stdout.split('\n')) if line]
+ # Parse as plain text (each line is a log entry)
+ for i, line in enumerate(log_result.stdout.split('\n')):
+ if line.strip():
+ logs.append({'n': i, 't': line})
return jsonify({
'vmid': vmid,