diff --git a/extensions/Servers/Proxmox/Livewire/Firewall.php b/extensions/Servers/Proxmox/Livewire/Firewall.php index 4a9a5ebb8..23eb9c38e 100644 --- a/extensions/Servers/Proxmox/Livewire/Firewall.php +++ b/extensions/Servers/Proxmox/Livewire/Firewall.php @@ -49,12 +49,26 @@ class Firewall extends Component { parent::mount($server); $this->server->loadMissing('ipAddresses'); + $this->loadAvailableIps(); $this->loadFirewallOptions(); $this->loadFirewallRules(); - $this->loadAliases(); - $this->loadIpsets(); $this->loadNetworkAdapters(); - $this->loadFirewallLogs(); + // Don't load logs on mount - only load when user clicks refresh + } + + protected function loadAvailableIps(): void + { + $allIps = collect(); + if ($this->server->primaryIpv4) { + $allIps->push(['ip' => $this->server->primaryIpv4->ip, 'type' => 'IPv4', 'label' => 'Primary']); + } + if ($this->server->primaryIpv6) { + $allIps->push(['ip' => $this->server->primaryIpv6->ip, 'type' => 'IPv6', 'label' => 'Primary']); + } + foreach ($this->server->ipAddresses as $ipAddress) { + $allIps->push(['ip' => $ipAddress->ip, 'type' => strtoupper($ipAddress->type), 'label' => 'Assigned']); + } + $this->availableIps = $allIps->unique('ip')->values()->toArray(); } /** @@ -197,19 +211,8 @@ class Firewall extends Component $this->resetRuleForm(); // Set default destination to first IP address - $allIps = collect(); - if ($this->server->primaryIpv4) { - $allIps->push($this->server->primaryIpv4->ip); - } - if ($this->server->primaryIpv6) { - $allIps->push($this->server->primaryIpv6->ip); - } - foreach ($this->server->ipAddresses as $ipAddress) { - $allIps->push($ipAddress->ip); - } - $uniqueIps = $allIps->unique(); - if ($uniqueIps->isNotEmpty()) { - $this->ruleDest = $uniqueIps->first(); + if (!empty($this->availableIps)) { + $this->ruleDest = $this->availableIps[0]['ip']; } // Set default interface to first network adapter @@ -655,7 +658,6 @@ class Firewall extends Component $segments = array_filter(array_map('trim', explode(',', $configString))); $model = 'virtio'; $mac = null; - $bridge = null; $firewallEnabled = false; foreach ($segments as $segment) { @@ -669,18 +671,15 @@ class Firewall extends Component if (in_array($segmentKeyLower, ['virtio', 'e1000', 'e1000e', 'rtl8139', 'vmxnet3', 'pcnet'], true)) { $model = $segmentKeyLower; $mac = $segmentValue; - } elseif ($segmentKeyLower === 'bridge') { - $bridge = $segmentValue; } elseif ($segmentKeyLower === 'firewall') { $firewallEnabled = ($segmentValue == '1' || $segmentValue === '1'); } } - $this->networkAdapters[$key] = [ + $this->networkAdapters[] = [ 'name' => $key, 'model' => $model, 'mac' => $mac, - 'bridge' => $bridge, ]; $this->adapterFirewallStates[$key] = $firewallEnabled; } @@ -766,33 +765,23 @@ class Firewall extends Component public function loadFirewallLogs(): void { try { - // Try the firewall log endpoint $response = $this->firewallRequest( '/nodes/' . $this->server->node->name . '/qemu/' . $this->server->vm_id . '/firewall/log', 'get', ['limit' => $this->logLimit] ); - // Check if response is successful if (!$response->successful()) { - \Log::warning('Firewall log API returned non-success status', [ - 'status' => $response->status(), - 'body' => $response->body() - ]); $this->firewallLogs = []; return; } $responseData = $response->json(); - - // Proxmox firewall log API can return data in different formats - // Try multiple possible response structures $rawLogs = []; if (isset($responseData['data']) && is_array($responseData['data'])) { $rawLogs = $responseData['data']; } elseif (is_array($responseData) && !isset($responseData['data'])) { - // Response might be the array directly $rawLogs = $responseData; } @@ -800,12 +789,10 @@ class Firewall extends Component if (empty($rawLogs)) { $body = $response->body(); if (!empty($body) && is_string($body)) { - // Try to parse as JSON first $jsonData = json_decode($body, true); if (json_last_error() === JSON_ERROR_NONE && is_array($jsonData)) { $rawLogs = $jsonData['data'] ?? $jsonData; } else { - // If not JSON, try to split by newlines (plain text format) $lines = explode("\n", trim($body)); $rawLogs = array_filter($lines, function($line) { return !empty(trim($line)); @@ -814,25 +801,16 @@ class Firewall extends Component } } - \Log::debug('Firewall logs raw response', [ - 'raw_logs_count' => count($rawLogs), - 'sample_entry' => !empty($rawLogs) ? (is_array($rawLogs[0]) ? $rawLogs[0] : substr($rawLogs[0], 0, 100)) : null - ]); - $this->firewallLogs = []; foreach ($rawLogs as $logEntry) { $logText = null; - // Try different possible field names for the log text if (is_string($logEntry)) { - // If the entry is a string directly, use it $logText = trim($logEntry); } elseif (is_array($logEntry)) { - // Try common field names $logText = $logEntry['n'] ?? $logEntry['t'] ?? $logEntry['text'] ?? $logEntry['log'] ?? $logEntry['message'] ?? $logEntry['line'] ?? ''; - // If still empty, try to get the first string value if (empty($logText)) { foreach ($logEntry as $value) { if (is_string($value) && !empty(trim($value))) { @@ -847,24 +825,12 @@ class Firewall extends Component continue; } - // Parse the log entry to extract simplified information $parsed = $this->parseFirewallLog($logText); if ($parsed) { $this->firewallLogs[] = $parsed; } } - - \Log::debug('Firewall logs parsed', [ - 'parsed_count' => count($this->firewallLogs) - ]); } catch (\Exception $e) { - // Log the error for debugging - \Log::error('Failed to load firewall logs: ' . $e->getMessage(), [ - 'server_id' => $this->server->id, - 'vm_id' => $this->server->vm_id, - 'node' => $this->server->node->name ?? 'unknown', - 'trace' => $e->getTraceAsString() - ]); $this->firewallLogs = []; } } diff --git a/extensions/Servers/Proxmox/views/firewall.blade.php b/extensions/Servers/Proxmox/views/firewall.blade.php index 1cf6b907f..323972d7c 100644 --- a/extensions/Servers/Proxmox/views/firewall.blade.php +++ b/extensions/Servers/Proxmox/views/firewall.blade.php @@ -261,20 +261,7 @@