Quelltext des aktuellen Standes
<?php
$hosts = $hosts ?? [];
$hypLabels = [
'vmware_esxi' => 'VMware ESXi',
'proxmox' => 'Proxmox VE',
'hyper_v' => 'Hyper-V',
'kvm' => 'KVM',
'xen' => 'Xen',
'other' => 'Sonstige',
];
$syncColors = [
'ok' => ['bg' => '#dcfce7', 'color' => '#15803d', 'label' => 'OK'],
'error' => ['bg' => '#fee2e2', 'color' => '#b91c1c', 'label' => 'Fehler'],
'never' => ['bg' => '#f3f4f6', 'color' => '#6b7280', 'label' => 'Noch nie'],
];
$this->layout('layouts/admin', [
'page_title' => 'Hypervisor-APIs',
'current_admin_page' => 'vm-hypervisor',
]);
?>
<div class="settings-page">
<section class="settings-card">
<div class="settings-card-header">
<span class="settings-card-icon">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" width="24" height="24"><path d="M5 12.55a11 11 0 0 1 14.08 0"/><path d="M1.42 9a16 16 0 0 1 21.16 0"/><path d="M8.53 16.11a6 6 0 0 1 6.95 0"/><line x1="12" y1="20" x2="12.01" y2="20"/></svg>
</span>
<div>
<h2><?= $this->te('Hypervisor-API-Verbindungen') ?></h2>
<p class="settings-card-desc">
<?= $this->te('Konfiguriere API-Zugangsdaten für die automatische Synchronisierung von VMs und Ressourcen pro Host. Zugangsdaten werden AES-256-GCM verschlüsselt gespeichert.') ?>
</p>
</div>
</div>
<div class="settings-card-body" style="padding:0;">
<?php if (empty($hosts)): ?>
<div style="padding:2.5rem 1.5rem;text-align:center;color:var(--gray-400);">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.25" width="40" height="40" style="margin-bottom:.75rem;display:block;margin-left:auto;margin-right:auto;"><rect x="2" y="2" width="20" height="8" rx="2"/><rect x="2" y="14" width="20" height="8" rx="2"/><line x1="6" y1="6" x2="6.01" y2="6"/><line x1="6" y1="18" x2="6.01" y2="18"/></svg>
<p style="margin:.25rem 0 .75rem;font-size:.875rem;"><?= $this->te('Noch keine Hosts angelegt.') ?></p>
<a href="/vms/hosts/create" class="btn btn-primary btn-sm"><?= $this->te('Host anlegen') ?></a>
</div>
<?php else: ?>
<table style="width:100%;border-collapse:collapse;font-size:.875rem;">
<thead>
<tr style="background:var(--gray-50);border-bottom:1px solid var(--gray-200);">
<th scope="col" style="padding:.65rem 1.25rem;text-align:left;font-size:.72rem;font-weight:600;color:var(--gray-500);text-transform:uppercase;letter-spacing:.05em;"><?= $this->te('Host') ?></th>
<th scope="col" style="padding:.65rem 1rem;text-align:left;font-size:.72rem;font-weight:600;color:var(--gray-500);text-transform:uppercase;letter-spacing:.05em;"><?= $this->te('Hypervisor') ?></th>
<th scope="col" style="padding:.65rem 1rem;text-align:left;font-size:.72rem;font-weight:600;color:var(--gray-500);text-transform:uppercase;letter-spacing:.05em;">API-URL</th>
<th scope="col" style="padding:.65rem 1rem;text-align:left;font-size:.72rem;font-weight:600;color:var(--gray-500);text-transform:uppercase;letter-spacing:.05em;"><?= $this->te('Sync-Status') ?></th>
<th scope="col" style="padding:.65rem 1rem;text-align:left;font-size:.72rem;font-weight:600;color:var(--gray-500);text-transform:uppercase;letter-spacing:.05em;"><?= $this->te('Letzter Sync') ?></th>
<th scope="col" style="padding:.65rem 1.25rem;width:120px;"></th>
</tr>
</thead>
<tbody>
<?php foreach ($hosts as $h): ?>
<?php
$sc = $h['sync_status'] ?? 'never';
$scf = $syncColors[$sc] ?? $syncColors['never'];
$configured = !empty($h['hypervisor_url']);
?>
<tr style="border-bottom:1px solid var(--gray-100);">
<td style="padding:.75rem 1.25rem;">
<a href="/vms/hosts/<?= $h['id'] ?>" style="font-weight:600;color:var(--gray-900);text-decoration:none;">
<?= $this->e($h['name']) ?>
</a>
<?php if (!empty($h['cluster_name'])): ?>
<div style="font-size:.72rem;color:var(--gray-400);margin-top:.1rem;"><?= $this->e($h['cluster_name']) ?></div>
<?php endif; ?>
</td>
<td style="padding:.75rem 1rem;">
<span style="display:inline-block;font-size:.72rem;font-weight:600;padding:.15rem .5rem;border-radius:.2rem;background:var(--color-primary-pale);color:var(--blue-700);">
<?= $this->e($hypLabels[$h['hypervisor'] ?? ''] ?? ($h['hypervisor'] ?? '—')) ?>
</span>
</td>
<td style="padding:.75rem 1rem;">
<?php if ($configured): ?>
<code style="font-size:.78rem;color:var(--gray-700);"><?= $this->e($h['hypervisor_url']) ?></code>
<?php else: ?>
<span style="color:var(--gray-400);font-size:.82rem;"><?= $this->te('Nicht konfiguriert') ?></span>
<?php endif; ?>
</td>
<td style="padding:.75rem 1rem;">
<?php if ($configured): ?>
<span style="display:inline-flex;align-items:center;padding:.15rem .5rem;border-radius:9999px;font-size:.7rem;font-weight:700;background:<?= $this->e($scf['bg']) ?>;color:<?= $this->e($scf['color']) ?>;">
<?= $scf['label'] ?>
</span>
<?php else: ?>
<span style="color:var(--gray-300);font-size:.82rem;">—</span>
<?php endif; ?>
</td>
<td style="padding:.75rem 1rem;color:var(--gray-500);font-size:.78rem;">
<?= $h['last_sync_at'] ? substr($h['last_sync_at'], 0, 16) : '—' ?>
</td>
<td style="padding:.75rem 1.25rem;text-align:right;">
<a href="/admin/vms/hosts/<?= $h['id'] ?>/sync-settings"
class="btn btn-<?= $configured ? 'default' : 'primary' ?> btn-sm">
<?= $configured ? 'Konfigurieren' : 'Einrichten' ?>
</a>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
<?php endif; ?>
</div>
</section>
<section class="settings-card">
<div class="settings-card-header">
<span class="settings-card-icon">💾</span>
<div>
<h2><?= $this->te('Snapshots') ?></h2>
<p class="settings-card-desc"><?= $this->te('Ab wann ein Snapshot als alt gilt.') ?></p>
</div>
</div>
<div class="settings-card-body">
<form method="POST" action="/admin/vms/snapshot-settings">
<input type="hidden" name="_csrf" value="<?= $this->csrf() ?>">
<div class="form-group">
<label for="vm-snap-days"><?= $this->te('Snapshot gilt als alt ab') ?></label>
<input type="number" id="vm-snap-days" name="vm_snapshot_warn_days"
class="form-control form-control-sm" style="width:160px;"
min="0" max="3650" value="<?= (int)($snapshot_warn_days ?? 30) ?>">
<small class="form-hint">
<?= $this->t('Angabe in Tagen. <strong>0</strong> schaltet die Warnung ab. Ein lange gehaltener Snapshot belegt Speicher und macht die Wiederherstellung langsamer; die Kennzeichnung steht an der jeweiligen VM. Angelegt und gelöscht werden Snapshots im Hypervisor – OpenNIT zeigt nur den Stand.') ?>
</small>
</div>
<button type="submit" class="btn btn-primary"><?= $this->te('Speichern') ?></button>
</form>
</div>
</section>
</div>