diff --git a/app/Services/Snmp/SnmpServerStatusService.php b/app/Services/Snmp/SnmpServerStatusService.php index 13150ad..32a2d27 100644 --- a/app/Services/Snmp/SnmpServerStatusService.php +++ b/app/Services/Snmp/SnmpServerStatusService.php @@ -29,38 +29,134 @@ class SnmpServerStatusService // SNMP-Konfiguration in der Instanz speichern. $this->config = $snmpConfig; } - /** * Liefert den aktuellen Serverstatus zurück. * - * In dieser Version werden Demo-Daten auf Basis der Konfiguration erzeugt. - * Später können hier echte SNMP-Queries (z. B. über die PHP-SNMP-Extension) verwendet werden. - * * @return array Assoziatives Array mit Statuswerten (Hostname, CPU%, RAM%, etc.) * - * @throws RuntimeException wenn die SNMP-Konfiguration unvollständig ist (z. B. host fehlt) + * @throws RuntimeException wenn die SNMP-Konfiguration unvollständig ist oder Abfragen fehlschlagen */ public function getServerStatus(): array { - // Hostnamen aus der SNMP-Konfiguration lesen. - $host = (string)($this->config['host'] ?? ''); + // --- 1. Konfiguration auslesen --- + $host = (string)($this->config['host'] ?? 'itfa-proj-srv.itfa-proj-dom.local'); + $community = (string)($this->config['community'] ?? ''); + $oids = $this->config['oids'] ?? []; + $timeout = (int)($this->config['timeout'] ?? 1) * 1_000_000; // in Mikrosekunden + $retries = (int)($this->config['retries'] ?? 1); - // Ohne Host ist keine sinnvolle Abfrage möglich -> Konfigurationsfehler. + // --- Prüfungen für essentielle Konfig-Werte --- if ($host === '') { throw new RuntimeException('SNMP-Konfiguration ist unvollständig (host fehlt).'); } + if ($community === '') { + throw new RuntimeException('SNMP-Konfiguration ist unvollständig (community fehlt).'); + } + if (empty($oids)) { + throw new RuntimeException('SNMP-Konfiguration ist unvollständig (oids fehlen).'); + } + + // Helper-Funktion zum Bereinigen von SNMP-Antworten (z.B. "INTEGER: 123" -> 123) + $cleanSnmpValue = fn($v) => (int)filter_var($v, FILTER_SANITIZE_NUMBER_INT); - // TODO: Später hier echte SNMP-Abfragen einbauen (z. B. snmp2_get/snmp2_walk). - // Die OIDs können aus $this->config['oids'] gelesen werden. - // Für den Anfang verwenden wir dieselben Demo-Werte wie vorher im DashboardController. + // --- 2. Uptime abfragen (war vorher nicht implementiert) --- + $uptimeResult = snmpget($host, $community, $oids['uptime'], $timeout, $retries); + if ($uptimeResult === false) { + throw new RuntimeException("SNMP Uptime GET fehlgeschlagen."); + } + // Uptime (timeticks) in ein lesbares Format umwandeln (optional, hier als String) + // Format ist oft "Timeticks: (12345678) 1 day, 10:17:36.78" + // Wir extrahieren den Teil in Klammern (Hundertstelsekunden) + preg_match('/\((.*?)\)/', $uptimeResult, $matches); + $uptimeTicks = (int)($matches[1] ?? 0); + $uptimeSeconds = $uptimeTicks / 100; + $uptimeFormatted = sprintf( + '%d Tage, %02d:%02d:%02d', + floor($uptimeSeconds / 86400), + floor(($uptimeSeconds % 86400) / 3600), + floor(($uptimeSeconds % 3600) / 60), + $uptimeSeconds % 60 + ); + + + // --- 3. CPU --- + $cpuValues = snmpwalk($host, $community, $oids['cpu_table'], $timeout, $retries); + + if (!is_array($cpuValues) || empty($cpuValues)) { + throw new RuntimeException("SNMP CPU WALK fehlgeschlagen."); + } + + $cpuValues = array_map($cleanSnmpValue, $cpuValues); + $cpuAvg = array_sum($cpuValues) / count($cpuValues); + + + // --- 4. Memory --- + $memTotalResult = snmpget($host, $community, $oids['mem_size'], $timeout, $retries); + if($memTotalResult === false) { + throw new RuntimeException("SNMP MemTotal GET fehlgeschlagen."); + } + + // memTotal in Bytes berechnen (korrigierte Reihenfolge von filter/cast) + $memTotal = $cleanSnmpValue($memTotalResult) * 1024; // KB -> Bytes + + // Storage-Tabelle (RAM + Disks) + $descr = snmpwalk($host, $community, $oids['storage_descr'], $timeout, $retries); + $units = snmpwalk($host, $community, $oids['storage_units'], $timeout, $retries); + $size = snmpwalk($host, $community, $oids['storage_size'], $timeout, $retries); + $used = snmpwalk($host, $community, $oids['storage_used'], $timeout, $retries); + + if ($descr === false || $units === false || $size === false || $used === false) { + throw new RuntimeException("SNMP Storage WALK fehlgeschlagen."); + } + + // Werte bereinigen + // Die SNMP-Antwort enthält "STRING: " und Anführungszeichen, die wir entfernen müssen. + $descr = array_map(fn($v) => trim(str_ireplace('STRING:', '', $v), ' "'), $descr); + + $units = array_map($cleanSnmpValue, $units); // Ints + $size = array_map($cleanSnmpValue, $size); // Ints + $used = array_map($cleanSnmpValue, $used); // Ints + + + + // RAM + $ramIndex = array_search("Physical Memory", $descr); + if ($ramIndex === false) { + throw new RuntimeException("Konnte 'Physical Memory' in der SNMP Storage-Tabelle nicht finden."); + } + + $ramUsedBytes = $units[$ramIndex] * $used[$ramIndex]; + $ramPercent = ($memTotal > 0) ? ($ramUsedBytes / $memTotal) * 100 : 0; + + + // --- 5. Disk C: --- + $cIndex = false; + foreach ($descr as $index => $description) { + // str_starts_with prüft, ob der String mit C:\ beginnt + if (str_starts_with($description, 'C:\\')) { + $cIndex = $index; + break; + } + } + + if ($cIndex === false) { + throw new RuntimeException("Konnte Laufwerk 'C:\' in der SNMP Storage-Tabelle nicht finden."); + } + + $cUsed = $units[$cIndex] * $used[$cIndex]; + $cTotal = $units[$cIndex] * $size[$cIndex]; + + $diskCPercent = ($cTotal > 0) ? ($cUsed / $cTotal) * 100 : 0; + + // --- 6. Status-Array zusammenbauen --- $status = [ 'hostname' => $host, - 'os' => 'Windows Server 2025 Datacenter', - 'uptime' => '3 Tage 12 Stunden', - 'cpu_usage' => 23, // CPU-Auslastung in Prozent (Demo) - 'memory_usage' => 62, // RAM-Auslastung in Prozent (Demo) - 'disk_usage_c' => 71, // Datenträger C in Prozent (Demo) - 'last_update' => date('d.m.Y H:i:s'), // Zeitpunkt der letzten Aktualisierung + 'os' => 'Windows Server 2025 Datacenter', // TODO: OS dynamisch abfragen + 'uptime' => $uptimeFormatted, // Fehlende Variable hinzugefügt + 'cpu_usage' => round($cpuAvg), + 'memory_usage' => round($ramPercent), + 'disk_usage_c' => round($diskCPercent), + 'last_update' => date('d.m.Y H:i:s'), ]; return $status; diff --git a/config/config.php b/config/config.php index 3578ba1..583a776 100644 --- a/config/config.php +++ b/config/config.php @@ -26,17 +26,24 @@ return [ ], 'snmp' => [ - 'host' => 'itfa-proj-srv.itfa-proj-dom.local', + 'host' => '127.0.0.1', 'community' => 'public_ro', // später: sinnvoller Community-String 'timeout' => 2, // Sekunden 'retries' => 1, // Anzahl Wiederholungen // Platzhalter für OIDs – später können wir die auf echte Werte setzen 'oids' => [ - 'uptime' => '1.3.6.1.2.1.1.3.0', - 'cpu_usage' => '1.3.6.1.4.1.example.cpu.0', - 'memory_usage' => '1.3.6.1.4.1.example.memory.0', - 'disk_c' => '1.3.6.1.4.1.example.diskc.0', - ], + 'uptime' => '1.3.6.1.2.1.1.3.0', + + // CPU pro Kern + 'cpu_table' => '1.3.6.1.2.1.25.3.3.1.2', + + // Memory + 'mem_size' => '1.3.6.1.2.1.25.2.2.0', + 'storage_descr' => '1.3.6.1.2.1.25.2.3.1.3', + 'storage_units' => '1.3.6.1.2.1.25.2.3.1.4', + 'storage_size' => '1.3.6.1.2.1.25.2.3.1.5', + 'storage_used' => '1.3.6.1.2.1.25.2.3.1.6', + ], ], ];