feat: add LXC container support to Proxmox extension
- Add is_lxc boolean column to ext_proxmox_nodes (default false, existing nodes unaffected) - Add LXC checkbox to admin node creation form (disabled on edit) - Dynamic API path selection via Node::vmType() (returns 'lxc' or 'qemu') - LXC deployment: syncLxcSettings() for cores, memory, swap, hostname, rootfs, net config - LXC network uses name=eth0 format with applyLxcPoolSettings() for VLAN/firewall/MTU - All lifecycle operations LXC-aware: install, suspend, unsuspend, terminate, upgrade, reinstall - VNC/xterm console uses correct type (lxc vs kvm) - All 20+ Livewire components use vmType() for Proxmox API paths - LXC user interface shows basic-only view (no advanced toggle, no KVM-specific tabs) - Basic tabs for LXC: Overview, Network Configuration, Backups, Console
This commit is contained in:
@@ -10,16 +10,18 @@
|
||||
$vmStatus = optional($status)->status;
|
||||
$pollSuffix = $statusPollingInterval ? '.' . $statusPollingInterval : '';
|
||||
$pollAttribute = $statusPolling ? 'wire:poll' . $pollSuffix . '="loadVmStatus"' : '';
|
||||
$isLxc = $server->node?->is_lxc ?? false;
|
||||
@endphp
|
||||
|
||||
<div {!! $pollAttribute !!} class="flex flex-col" style="min-height: calc(100vh - 30rem);">
|
||||
@if($server->status === 'active')
|
||||
|
||||
<div class="flex flex-col flex-1" x-data="{
|
||||
isAdvancedView: localStorage.getItem('proxmox-view-mode') === 'advanced',
|
||||
isAdvancedView: {{ $isLxc ? 'false' : "localStorage.getItem('proxmox-view-mode') === 'advanced'" }},
|
||||
isAdvancedOnlyView: {{ in_array($view, ['boot-order', 'cloud-init', 'display', 'system', 'storage', 'subdomain', 'statistics', 'help', 'firewall']) ? 'true' : 'false' }},
|
||||
isLxc: {{ $isLxc ? 'true' : 'false' }},
|
||||
toggleView() {
|
||||
if (!this.isAdvancedOnlyView) {
|
||||
if (!this.isAdvancedOnlyView && !this.isLxc) {
|
||||
this.isAdvancedView = !this.isAdvancedView;
|
||||
localStorage.setItem('proxmox-view-mode', this.isAdvancedView ? 'advanced' : 'basic');
|
||||
window.dispatchEvent(new CustomEvent('proxmox-view-mode-changed', {
|
||||
@@ -28,7 +30,7 @@
|
||||
}
|
||||
}
|
||||
}" x-init="
|
||||
if (!localStorage.getItem('proxmox-view-mode')) {
|
||||
if (!isLxc && !localStorage.getItem('proxmox-view-mode')) {
|
||||
localStorage.setItem('proxmox-view-mode', 'basic');
|
||||
isAdvancedView = false;
|
||||
}">
|
||||
@@ -1631,6 +1633,29 @@
|
||||
];
|
||||
}
|
||||
$tabs[] = ['label' => 'Help', 'view' => 'help', 'route' => route('proxmox.server.help', ['server' => $server->id]), 'advanced' => true];
|
||||
|
||||
// For LXC containers, remove all advanced-only and KVM-specific tabs
|
||||
if ($isLxc) {
|
||||
$tabs = array_values(array_filter($tabs, function ($tab) {
|
||||
// Remove top-level advanced tabs
|
||||
if (!empty($tab['advanced'])) return false;
|
||||
// Remove Hardware dropdown entirely (Boot, Display, Storage, System are KVM-only)
|
||||
if (($tab['label'] ?? '') === 'Hardware') return false;
|
||||
// For Networking dropdown, keep only Configuration (remove Firewall, Subdomain)
|
||||
if (isset($tab['dropdown']) && $tab['dropdown'] && isset($tab['items'])) {
|
||||
$tab['items'] = array_values(array_filter($tab['items'], fn($item) => empty($item['advanced'])));
|
||||
return count($tab['items']) > 0;
|
||||
}
|
||||
return true;
|
||||
}));
|
||||
// Re-filter Networking dropdown items in-place
|
||||
foreach ($tabs as &$tab) {
|
||||
if (isset($tab['dropdown']) && $tab['dropdown'] && isset($tab['items'])) {
|
||||
$tab['items'] = array_values(array_filter($tab['items'], fn($item) => empty($item['advanced'])));
|
||||
}
|
||||
}
|
||||
unset($tab);
|
||||
}
|
||||
@endphp
|
||||
|
||||
<div class="mb-10 mt-3">
|
||||
@@ -2124,7 +2149,8 @@
|
||||
</div>
|
||||
|
||||
<div class="modern-toggle-container"
|
||||
:class="isAdvancedOnlyView ? 'opacity-50 cursor-not-allowed pointer-events-none' : ''">
|
||||
:class="isAdvancedOnlyView ? 'opacity-50 cursor-not-allowed pointer-events-none' : ''"
|
||||
x-show="!isLxc">
|
||||
<span class="modern-toggle-label"
|
||||
:class="!isAdvancedView ? 'active' : 'inactive'">
|
||||
Standard
|
||||
@@ -2145,10 +2171,11 @@
|
||||
|
||||
<div class="lg:hidden" x-data="{
|
||||
open: false,
|
||||
isAdvancedView: localStorage.getItem('proxmox-view-mode') === 'advanced',
|
||||
isAdvancedView: {{ $isLxc ? 'false' : "localStorage.getItem('proxmox-view-mode') === 'advanced'" }},
|
||||
isAdvancedOnlyView: {{ in_array($view, ['boot-order', 'cloud-init', 'display', 'system', 'storage', 'subdomain', 'statistics', 'help', 'firewall']) ? 'true' : 'false' }},
|
||||
isLxc: {{ $isLxc ? 'true' : 'false' }},
|
||||
toggleView() {
|
||||
if (!this.isAdvancedOnlyView) {
|
||||
if (!this.isAdvancedOnlyView && !this.isLxc) {
|
||||
this.isAdvancedView = !this.isAdvancedView;
|
||||
localStorage.setItem('proxmox-view-mode', this.isAdvancedView ? 'advanced' : 'basic');
|
||||
window.dispatchEvent(new CustomEvent('proxmox-view-mode-changed', {
|
||||
@@ -2157,11 +2184,11 @@
|
||||
}
|
||||
}
|
||||
}" x-init="
|
||||
if (!localStorage.getItem('proxmox-view-mode')) {
|
||||
if (!isLxc && !localStorage.getItem('proxmox-view-mode')) {
|
||||
localStorage.setItem('proxmox-view-mode', 'basic');
|
||||
isAdvancedView = false;
|
||||
}
|
||||
isAdvancedView = localStorage.getItem('proxmox-view-mode') === 'advanced';
|
||||
isAdvancedView = {{ $isLxc ? 'false' : "localStorage.getItem('proxmox-view-mode') === 'advanced'" }};
|
||||
$watch('open', () => {
|
||||
if (open) {
|
||||
isAdvancedView = localStorage.getItem('proxmox-view-mode') === 'advanced';
|
||||
@@ -2333,7 +2360,8 @@
|
||||
<x-ri-menu-line class="size-5" />
|
||||
</button>
|
||||
<div class="mobile-toggle-compact flex-shrink-0"
|
||||
:class="isAdvancedOnlyView ? 'opacity-50 pointer-events-none' : ''">
|
||||
:class="isAdvancedOnlyView ? 'opacity-50 pointer-events-none' : ''"
|
||||
x-show="!isLxc">
|
||||
<span class="mobile-toggle-label-compact"
|
||||
:class="!isAdvancedView ? 'text-base' : 'text-base/40'">
|
||||
Std
|
||||
|
||||
Reference in New Issue
Block a user