230 lines
9.1 KiB
PHP
230 lines
9.1 KiB
PHP
<?php
|
|
/**
|
|
* @var array $hosts Die Liste der KEA-Hosts.
|
|
* @var string|null $error Eine Fehlermeldung, falls vorhanden.
|
|
* @var array $warnings Hinweise, falls Zusatzdaten nicht geladen werden konnten.
|
|
* @var array $stats Kennzahlen fuer die Uebersicht.
|
|
*/
|
|
?>
|
|
<?= module_shell_header('kea', [
|
|
'title' => 'KEA DHCP Hosts',
|
|
'description' => 'Reservierungen und aktuelle Leases aus der KEA-Datenbank.',
|
|
]) ?>
|
|
<section class="kea-page">
|
|
<div class="section-head">
|
|
<div>
|
|
<h2 class="section-title">KEA DHCP Hosts</h2>
|
|
<p>Reservierungen und aktuelle Leases aus der KEA-Datenbank.</p>
|
|
<p class="muted kea-refresh-state" data-kea-refresh-state>
|
|
Automatische Aktualisierung alle 5 Sekunden.
|
|
</p>
|
|
</div>
|
|
</div>
|
|
|
|
<?php if ($error): ?>
|
|
<div class="kea-message kea-message--error" role="alert">
|
|
<strong>Fehler</strong>
|
|
<p><?= e($error) ?></p>
|
|
</div>
|
|
<?php endif; ?>
|
|
|
|
<?php foreach (($warnings ?? []) as $warning): ?>
|
|
<div class="kea-message kea-message--warning" role="alert">
|
|
<p><?= e((string)$warning) ?></p>
|
|
</div>
|
|
<?php endforeach; ?>
|
|
|
|
<div class="stats">
|
|
<div class="stat-card">
|
|
<span class="stat-label">Einträge</span>
|
|
<span class="stat-value" data-kea-stat="total"><?= e((string)($stats['total'] ?? 0)) ?></span>
|
|
</div>
|
|
<div class="stat-card">
|
|
<span class="stat-label">Reservierungen</span>
|
|
<span class="stat-value" data-kea-stat="reservations"><?= e((string)($stats['reservations'] ?? 0)) ?></span>
|
|
</div>
|
|
<div class="stat-card">
|
|
<span class="stat-label">Leases</span>
|
|
<span class="stat-value" data-kea-stat="leases"><?= e((string)($stats['leases'] ?? 0)) ?></span>
|
|
</div>
|
|
<div class="stat-card">
|
|
<span class="stat-label">Gruppen</span>
|
|
<span class="stat-value" data-kea-stat="groups"><?= e((string)count($stats['groups'] ?? [])) ?></span>
|
|
</div>
|
|
<div class="stat-card">
|
|
<span class="stat-label">Freie Gruppen-IPs</span>
|
|
<span class="stat-value" data-kea-stat="free_ips"><?= e((string)array_sum($stats['free_ips'] ?? [])) ?></span>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="kea-panel">
|
|
<div class="kea-panel__head">
|
|
<div>
|
|
<span class="pill">Inventar</span>
|
|
<h3>Registrierte Geräte</h3>
|
|
<p class="muted">Zusatzdaten werden in der separaten Nexus-DHCP-Datenbank gespeichert.</p>
|
|
</div>
|
|
</div>
|
|
<div class="kea-table-wrap">
|
|
<table class="kea-table">
|
|
<thead>
|
|
<tr>
|
|
<th>Quelle</th>
|
|
<th>Hostname</th>
|
|
<th>IP Adresse</th>
|
|
<th>MAC Adresse</th>
|
|
<th>Zuletzt gesehen</th>
|
|
<th>Lease bis</th>
|
|
<th>Echter Name</th>
|
|
<th>Standort</th>
|
|
<th>Gruppe</th>
|
|
<th>Aktion</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody data-kea-host-rows>
|
|
<?php if (empty($hosts)): ?>
|
|
<tr>
|
|
<td colspan="10" class="kea-empty">
|
|
Keine Reservierungen oder aktiven Leases gefunden.
|
|
</td>
|
|
</tr>
|
|
<?php else: ?>
|
|
<?php foreach ($hosts as $host): ?>
|
|
<tr>
|
|
<td>
|
|
<span class="pill"><?= ($host['source'] ?? '') === 'lease' ? 'Lease' : 'Reservierung' ?></span>
|
|
</td>
|
|
<td>
|
|
<?= e((string)($host['metadata']['device_name'] ?? $host['metadata']['real_name'] ?? $host['display_name'] ?? $host['hostname'] ?? 'Unbekannt')) ?>
|
|
</td>
|
|
<td class="mono">
|
|
<?= e($host['ipv4_address']) ?>
|
|
</td>
|
|
<td class="mono">
|
|
<?= e($host['dhcp_identifier']) ?>
|
|
</td>
|
|
<td>
|
|
<?= e((string)($host['last_seen_at'] ?? '-')) ?>
|
|
</td>
|
|
<td>
|
|
<?= e((string)($host['lease_expires_at'] ?? '-')) ?>
|
|
</td>
|
|
<td>
|
|
<?= e((string)($host['metadata']['real_name'] ?? '-')) ?>
|
|
</td>
|
|
<td>
|
|
<?= e((string)($host['metadata']['location'] ?? '-')) ?>
|
|
</td>
|
|
<td>
|
|
<?= e((string)($host['metadata']['group_name'] ?? '-')) ?>
|
|
</td>
|
|
<td>
|
|
<a class="nav-link" href="/module/kea/edit?source=<?= e((string)($host['source'] ?? 'reservation')) ?>&id=<?= e((string)($host['host_id'] ?? '0')) ?>">
|
|
Bearbeiten
|
|
</a>
|
|
</td>
|
|
</tr>
|
|
<?php endforeach; ?>
|
|
<?php endif; ?>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
<script>
|
|
(() => {
|
|
const rowsTarget = document.querySelector('[data-kea-host-rows]');
|
|
const stateTarget = document.querySelector('[data-kea-refresh-state]');
|
|
if (!rowsTarget) {
|
|
return;
|
|
}
|
|
|
|
const setText = (selector, value) => {
|
|
const target = document.querySelector(selector);
|
|
if (target) {
|
|
target.textContent = String(value ?? '0');
|
|
}
|
|
};
|
|
|
|
const cell = (value, className = '') => {
|
|
const td = document.createElement('td');
|
|
if (className) {
|
|
td.className = className;
|
|
}
|
|
td.textContent = value || '-';
|
|
return td;
|
|
};
|
|
|
|
const renderRows = (rows) => {
|
|
rowsTarget.textContent = '';
|
|
if (!Array.isArray(rows) || rows.length === 0) {
|
|
const tr = document.createElement('tr');
|
|
const td = cell('Keine Reservierungen oder aktiven Leases gefunden.', 'kea-empty');
|
|
td.colSpan = 10;
|
|
tr.appendChild(td);
|
|
rowsTarget.appendChild(tr);
|
|
return;
|
|
}
|
|
|
|
for (const row of rows) {
|
|
const tr = document.createElement('tr');
|
|
const source = document.createElement('td');
|
|
const pill = document.createElement('span');
|
|
pill.className = 'pill';
|
|
pill.textContent = row.source === 'lease' ? 'Lease' : 'Reservierung';
|
|
source.appendChild(pill);
|
|
tr.appendChild(source);
|
|
|
|
tr.appendChild(cell(row.display_name));
|
|
tr.appendChild(cell(row.ipv4_address, 'mono'));
|
|
tr.appendChild(cell(row.dhcp_identifier, 'mono'));
|
|
tr.appendChild(cell(row.last_seen_at));
|
|
tr.appendChild(cell(row.lease_expires_at));
|
|
tr.appendChild(cell(row.real_name));
|
|
tr.appendChild(cell(row.location));
|
|
tr.appendChild(cell(row.group_name));
|
|
|
|
const action = document.createElement('td');
|
|
const link = document.createElement('a');
|
|
link.className = 'nav-link';
|
|
link.href = `/module/kea/edit?source=${encodeURIComponent(row.source || 'reservation')}&id=${encodeURIComponent(row.host_id || '0')}`;
|
|
link.textContent = 'Bearbeiten';
|
|
action.appendChild(link);
|
|
tr.appendChild(action);
|
|
|
|
rowsTarget.appendChild(tr);
|
|
}
|
|
};
|
|
|
|
const refresh = async () => {
|
|
try {
|
|
const response = await fetch('/module/kea/data', {
|
|
headers: {Accept: 'application/json'},
|
|
cache: 'no-store',
|
|
});
|
|
const payload = await response.json();
|
|
if (!response.ok || !payload.ok) {
|
|
throw new Error(payload.error || 'Aktualisierung fehlgeschlagen.');
|
|
}
|
|
|
|
setText('[data-kea-stat="total"]', payload.stats?.total);
|
|
setText('[data-kea-stat="reservations"]', payload.stats?.reservations);
|
|
setText('[data-kea-stat="leases"]', payload.stats?.leases);
|
|
setText('[data-kea-stat="groups"]', payload.stats?.groups);
|
|
setText('[data-kea-stat="free_ips"]', payload.stats?.free_ips);
|
|
renderRows(payload.rows);
|
|
if (stateTarget) {
|
|
stateTarget.textContent = `Automatische Aktualisierung aktiv. Zuletzt aktualisiert: ${payload.updated_at || '-'}`;
|
|
}
|
|
} catch (error) {
|
|
if (stateTarget) {
|
|
stateTarget.textContent = `Automatische Aktualisierung fehlgeschlagen: ${error.message}`;
|
|
}
|
|
}
|
|
};
|
|
|
|
window.setInterval(refresh, 5000);
|
|
})();
|
|
</script>
|
|
<?= module_shell_footer() ?>
|