152 lines
4.6 KiB
PHP
152 lines
4.6 KiB
PHP
<?php
|
|
declare(strict_types=1);
|
|
|
|
namespace App\Repository;
|
|
|
|
use PDO;
|
|
|
|
/**
|
|
* Repository für das KEA DHCP Host-Management.
|
|
* Interagiert direkt mit der 'hosts' Tabelle in der KEA-Datenbank.
|
|
*/
|
|
final class KeaHostRepository
|
|
{
|
|
public function __construct(
|
|
private PDO $pdo,
|
|
private ?KeaHostMetadataRepository $metadata = null
|
|
) {}
|
|
|
|
/**
|
|
* Ruft eine Liste aller Host-Reservierungen ab (Geräte-Inventar).
|
|
*/
|
|
public function findAll(int $limit = 50): array
|
|
{
|
|
try {
|
|
// 'dhcp_identifier' ist in KEA i.d.R. die MAC-Adresse (bei type=1)
|
|
$stmt = $this->pdo->prepare(
|
|
'SELECT host_id, dhcp_identifier, ipv4_address, hostname, user_context
|
|
FROM hosts
|
|
ORDER BY host_id DESC
|
|
LIMIT :limit'
|
|
);
|
|
$stmt->bindValue(':limit', $limit, PDO::PARAM_INT);
|
|
$stmt->execute();
|
|
|
|
return $this->withMetadata($stmt->fetchAll(PDO::FETCH_ASSOC));
|
|
} catch (\PDOException $e) {
|
|
if ($this->isMissingTable($e)) {
|
|
throw new \RuntimeException(
|
|
'KEA schema not initialized. Enable APP_DB_AUTO_INIT or run kea-admin db-init pgsql.',
|
|
0,
|
|
$e
|
|
);
|
|
}
|
|
throw $e;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Sucht einen Host anhand der MAC-Adresse (dhcp_identifier).
|
|
*/
|
|
public function findByMac(string $mac): ?array
|
|
{
|
|
// Hinweis: KEA speichert MACs in PostgreSQL oft als BYTEA.
|
|
// Je nach Treiber-Konfiguration muss $mac hier ggf. als Hex-String (z.B. '\x...')
|
|
// formatiert übergeben werden.
|
|
try {
|
|
$stmt = $this->pdo->prepare(
|
|
'SELECT host_id, dhcp_identifier, ipv4_address, hostname, user_context
|
|
FROM hosts
|
|
WHERE dhcp_identifier = :mac
|
|
LIMIT 1'
|
|
);
|
|
$stmt->execute(['mac' => $mac]);
|
|
|
|
$row = $stmt->fetch(PDO::FETCH_ASSOC);
|
|
return $row ?: null;
|
|
} catch (\PDOException $e) {
|
|
if ($this->isMissingTable($e)) {
|
|
throw new \RuntimeException(
|
|
'KEA schema not initialized. Enable APP_DB_AUTO_INIT or run kea-admin db-init pgsql.',
|
|
0,
|
|
$e
|
|
);
|
|
}
|
|
throw $e;
|
|
}
|
|
}
|
|
|
|
private function isMissingTable(\PDOException $e): bool
|
|
{
|
|
return $e->getCode() === '42P01';
|
|
}
|
|
|
|
/**
|
|
* Erstellt eine neue Host-Reservierung inkl. Metadaten.
|
|
*
|
|
* @param string $mac MAC-Adresse
|
|
* @param string $ip IPv4-Adresse
|
|
* @param int $subnetId Die ID des Subnets (dhcp4_subnet_id), in dem die IP liegt
|
|
* @param string|null $hostname Optionaler Hostname
|
|
* @param array $metadata Zusätzliche Infos fuer die separate Nexus-DHCP-Metadatenbank.
|
|
*/
|
|
public function create(string $mac, string $ip, int $subnetId, ?string $hostname = null, array $metadata = []): int
|
|
{
|
|
// dhcp_identifier_type 1 = HW_ADDRESS (Ethernet)
|
|
$stmt = $this->pdo->prepare(
|
|
'INSERT INTO hosts (dhcp_identifier, dhcp_identifier_type, dhcp4_subnet_id, ipv4_address, hostname)
|
|
VALUES (:mac, 1, :subnetId, :ip, :hostname)'
|
|
);
|
|
|
|
$stmt->execute([
|
|
'mac' => $mac,
|
|
'subnetId' => $subnetId,
|
|
'ip' => $ip,
|
|
'hostname' => $hostname,
|
|
]);
|
|
|
|
$hostId = $this->lastInsertIdSafe();
|
|
if ($this->metadata !== null && $metadata !== []) {
|
|
$this->metadata->saveForHost($hostId, $mac, $ip, $metadata);
|
|
}
|
|
|
|
return $hostId;
|
|
}
|
|
|
|
private function withMetadata(array $hosts): array
|
|
{
|
|
if ($hosts === [] || $this->metadata === null) {
|
|
return $hosts;
|
|
}
|
|
|
|
$metadataByHost = $this->metadata->findByHostIds(array_column($hosts, 'host_id'));
|
|
foreach ($hosts as &$host) {
|
|
$hostId = (int)($host['host_id'] ?? 0);
|
|
$host['metadata'] = $metadataByHost[$hostId] ?? [];
|
|
}
|
|
unset($host);
|
|
|
|
return $hosts;
|
|
}
|
|
|
|
private function driver(): string
|
|
{
|
|
return (string)$this->pdo->getAttribute(PDO::ATTR_DRIVER_NAME);
|
|
}
|
|
|
|
private function lastInsertIdSafe(): int
|
|
{
|
|
$driver = $this->driver();
|
|
|
|
if ($driver === 'pgsql') {
|
|
// KEA Standard-Sequenz für die hosts Tabelle
|
|
$id = $this->pdo->lastInsertId('hosts_host_id_seq');
|
|
if ($id !== '') {
|
|
return (int)$id;
|
|
}
|
|
}
|
|
|
|
return (int)$this->pdo->lastInsertId();
|
|
}
|
|
}
|