165 lines
6.5 KiB
PHP
165 lines
6.5 KiB
PHP
<?php
|
|
|
|
// Strenge Typprüfung für Parameter- und Rückgabetypen aktivieren.
|
|
declare(strict_types=1);
|
|
|
|
namespace App\Services\Snmp;
|
|
|
|
use RuntimeException;
|
|
|
|
/**
|
|
* Service zur Ermittlung des Serverstatus.
|
|
*
|
|
* In dieser ersten Version werden noch statische Demo-Daten zurückgegeben.
|
|
* Später können hier echte SNMP-Abfragen eingebaut werden, ohne dass sich
|
|
* der DashboardController oder die Views ändern müssen.
|
|
*/
|
|
class SnmpServerStatusService
|
|
{
|
|
/** @var array<string, mixed> SNMP-spezifische Konfiguration (Host, Community, Timeout, OIDs, etc.) */
|
|
private array $config;
|
|
|
|
/**
|
|
* Erwartet den Teilbereich "snmp" aus der allgemeinen Konfiguration (config.php).
|
|
*
|
|
* @param array<string, mixed> $snmpConfig Konfiguration für die SNMP-Abfragen
|
|
*/
|
|
public function __construct(array $snmpConfig)
|
|
{
|
|
// SNMP-Konfiguration in der Instanz speichern.
|
|
$this->config = $snmpConfig;
|
|
}
|
|
/**
|
|
* Liefert den aktuellen Serverstatus zurück.
|
|
*
|
|
* @return array<string, mixed> Assoziatives Array mit Statuswerten (Hostname, CPU%, RAM%, etc.)
|
|
*
|
|
* @throws RuntimeException wenn die SNMP-Konfiguration unvollständig ist oder Abfragen fehlschlagen
|
|
*/
|
|
public function getServerStatus(): array
|
|
{
|
|
// --- 1. Konfiguration auslesen ---
|
|
$host = (string)($this->config['host'] ?? '127.0.0.1');
|
|
$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);
|
|
|
|
// --- 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);
|
|
|
|
// --- 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', // 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;
|
|
}
|
|
}
|