Enhance Proxmox views with improved loading states and UI updates

- Updated serverplaceholder.blade.php to enhance loading skeletons for server details.
- Added navigation breadcrumbs to statistics, subdomain, and system views for better user experience.
- Improved loading indicators for CPU, network, memory, and disk charts in statistics.blade.php.
- Refined storage.blade.php layout with section dividers and improved drive display, including bus type indicators and quota usage.
- Enhanced VNC and Xterm popups with a new header design, loading animations, and reconnect functionality.
- Added error handling for VNC and Xterm connections to inform users when unable to connect.
This commit is contained in:
2026-02-24 19:51:46 -05:00
parent af62a16354
commit 16cd5f05de
40 changed files with 1423 additions and 475 deletions

View File

@@ -487,9 +487,21 @@ class Proxmox extends ClassServer
return;
}
$this->syncServerSettings($server, $settings, $password);
try {
$this->syncServerSettings($server, $settings, $password);
} catch (\Throwable $e) {
\Log::error('Proxmox VM sync settings failed for server ' . $server->id, [
'error' => $e->getMessage(),
'vm_id' => $server->vm_id,
'node' => $server->node->name,
]);
$server->status = 'error';
$server->save();
// Start the server
return;
}
// Mark server as active
$server->status = 'active';
$server->password = $password;
$server->save();
@@ -604,7 +616,14 @@ class Proxmox extends ClassServer
$diskNeeded = (int) $settings['disk'];
if ($location->server_placement == 'random') {
$node = $location->nodes()->inRandomOrder()->first();
$nodes = $location->nodes()->inRandomOrder()->get();
$node = null;
foreach ($nodes as $n) {
if ($n->canStoreServer($memoryNeeded, $diskNeeded, $cpuNeeded)) {
$node = $n;
break;
}
}
} elseif ($location->server_placement == 'fill') {
// Get the nodes that have enough resources
$nodes = $location->nodes()->get();
@@ -864,16 +883,11 @@ class Proxmox extends ClassServer
$ipv6 = $this->getAvailableIps($node, $settings['ipv6'], 'ipv6');
}
// Get the next VMID by finding the maximum existing VMID and adding 1
// This ensures we never reuse old VMIDs from deleted servers
$clusterResources = $this->request('/cluster/resources', 'get', ['type' => 'vm'])->json()['data'] ?? [];
$maxVmId = 99; // Default minimum VMID in Proxmox is 100
foreach ($clusterResources as $resource) {
if (isset($resource['vmid']) && $resource['vmid'] > $maxVmId) {
$maxVmId = (int) $resource['vmid'];
}
// Use Proxmox's atomic nextid API to avoid VMID collisions during concurrent provisioning
$vm_id = (int) ($this->request('/cluster/nextid')->json()['data'] ?? 0);
if ($vm_id < 100) {
throw new Exception('Failed to obtain a valid VMID from Proxmox (got: ' . $vm_id . ')');
}
$vm_id = $maxVmId + 1;
$password = Str::password(16);
@@ -926,10 +940,17 @@ class Proxmox extends ClassServer
return false;
}
// Stop server
$this->request('/nodes/' . $server->node->name . '/qemu/' . $server->vm_id . '/status/stop', 'post', [
if (!$server->node) {
\Log::error('Proxmox suspendServer: node relationship is null for server ' . $server->id);
$server->status = 'suspended';
$server->save();
return true;
}
// Stop server and wait for completion
$this->requestAndWait('/nodes/' . $server->node->name . '/qemu/' . $server->vm_id . '/status/stop', 'post', [
'vmid' => $server->vm_id,
]);
], $server->node->name);
$server->status = 'suspended';
$server->save();
@@ -973,12 +994,23 @@ class Proxmox extends ClassServer
}
$server = Server::where('service_id', $service->id)->first();
if (!$server->node) {
\Log::error('Proxmox terminateServer: node relationship is null for server ' . $server->id);
// Release IPs and delete server record even if node is gone
$server->ipAddresses()->update(['server_id' => null]);
$server->delete();
return true;
}
// Stop the VM and wait for completion before deleting
$this->requestAndWait('/nodes/' . $server->node->name . '/qemu/' . $server->vm_id . '/status/stop', 'post', [
'vmid' => $server->vm_id,
], $server->node->name);
// Delete proxmox server
$this->request('/nodes/' . $server->node->name . '/qemu/' . $server->vm_id, 'delete');
// Release IP addresses so they can be reallocated
$server->ipAddresses()->update(['server_id' => null]);
// Delete server
$server->delete();
@@ -994,11 +1026,16 @@ class Proxmox extends ClassServer
*/
public function upgradeServer(Service $service, $settings, $properties)
{
if (!Server::where('service_id', $service->id)->exists()) {
$server = Server::where('service_id', $service->id)->first();
if (!$server) {
return false;
}
$server = Server::where('service_id', $service->id)->first();
if (!$server->node) {
\Log::error('Proxmox upgradeServer: node relationship is null for server ' . $server->id);
return false;
}
// Update the server settings
$this->syncServerSettings($server, $settings, null);