Quelltext des aktuellen Standes
<?php
$this->layout('layouts/admin', [
'page_title' => 'Einrichtungsanleitungen',
'current_admin_page' => 'vm-setup-guide',
]);
?>
<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="M2 3h6a4 4 0 0 1 4 4v14a3 3 0 0 0-3-3H2z"/><path d="M22 3h-6a4 4 0 0 0-4 4v14a3 3 0 0 1 3-3h7z"/></svg>
</span>
<div>
<h2><?= $this->te('Hypervisor-Einrichtungsanleitungen') ?></h2>
<p class="settings-card-desc">
<?= $this->te('Schritt-für-Schritt-Anleitung für VMware vSphere, Proxmox VE, Microsoft Hyper-V, KVM und Xen/XCP-ng. Nach der Einrichtung können VMs und Host-Ressourcen automatisch synchronisiert werden.') ?>
</p>
</div>
</div>
<div class="settings-card-body" style="padding:0;">
<!-- Tab-Navigation -->
<div class="sg-tabs" role="tablist">
<button type="button" class="sg-tab sg-tab-active" role="tab" aria-selected="true" data-tab="vmware" aria-controls="tab-vmware">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" width="14" height="14"><rect x="2" y="3" width="20" height="14" rx="2"/><line x1="8" y1="21" x2="16" y2="21"/><line x1="12" y1="17" x2="12" y2="21"/></svg>
<?= $this->te('VMware vSphere') ?>
</button>
<button type="button" class="sg-tab" role="tab" aria-selected="false" data-tab="proxmox" aria-controls="tab-proxmox">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" width="14" height="14"><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>
<?= $this->te('Proxmox VE') ?>
</button>
<button type="button" class="sg-tab" role="tab" aria-selected="false" data-tab="hyperv" aria-controls="tab-hyperv">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" width="14" height="14"><path d="M21 16V8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73l7 4a2 2 0 0 0 2 0l7-4A2 2 0 0 0 21 16z"/></svg>
<?= $this->te('Hyper-V') ?>
</button>
<button type="button" class="sg-tab" role="tab" aria-selected="false" data-tab="kvm" aria-controls="tab-kvm">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" width="14" height="14"><circle cx="12" cy="12" r="10"/><polyline points="12 6 12 12 16 14"/></svg>
<?= $this->te('KVM / QEMU') ?>
</button>
<button type="button" class="sg-tab" role="tab" aria-selected="false" data-tab="xen" aria-controls="tab-xen">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" width="14" height="14"><polygon points="13 2 3 14 12 14 11 22 21 10 12 10 13 2"/></svg>
<?= $this->te('Xen / XCP-ng') ?>
</button>
</div>
<!-- ================================================================
VMWARE
================================================================ -->
<div class="sg-panel sg-panel-active" id="tab-vmware" role="tabpanel">
<div class="sg-section">
<h3 class="sg-h3"><?= $this->te('Voraussetzungen') ?></h3>
<ul class="sg-list">
<li><?= $this->t('vCenter Server <strong>6.5 oder neuer</strong> (empfohlen) <em>oder</em> ESXi 6.5+ Standalone') ?></li>
<li><?= $this->t('ESXi 6.0 wird <strong>nicht</strong> unterstützt (keine REST-API, nur veraltete SOAP-API)') ?></li>
<li><?= $this->t('Netzwerkzugang von diesem Server zu vCenter/ESXi auf Port <strong>443</strong>') ?></li>
</ul>
</div>
<div class="sg-section">
<h3 class="sg-h3"><?= $this->te('Schritt 1 – API-URL eintragen') ?></h3>
<p><?= $this->t('Nur die Basis-URL des vCenter Servers oder ESXi-Hosts eintragen – keine Pfade, kein <code>/api</code>. Der Connector prüft selbst, ob die REST-API (v6.5–6.7) oder Automation API (v7+) verfügbar ist.') ?></p>
<div class="sg-code">https://vcenter.example.com
https://192.168.1.10 ← ESXi Standalone</div>
</div>
<div class="sg-section">
<h3 class="sg-h3"><?= $this->te('Schritt 2 – Benutzer und Berechtigungen') ?></h3>
<p><?= $this->te('Ein dedizierter Read-Only-Benutzer reicht vollständig aus. Im vSphere Client:') ?></p>
<ol class="sg-steps">
<li>
<?= $this->t('<strong>Menu → Administration → Users and Groups → Users</strong><br> Neuen Benutzer anlegen, z. B. <code>monitoring@vsphere.local</code>') ?>
</li>
<li>
<?= $this->t('<strong>Menu → Administration → Access Control → Roles</strong><br> Entweder die eingebaute Rolle <em>Read-Only</em> verwenden oder eigene Rolle mit:') ?>
<div class="sg-code">Virtual machine → View configuration details
Host → Query
Global → Cancel tasks (optional)</div>
</li>
<li>
<?= $this->t('<strong>Hosts and Clusters → Datacenter → rechte Maustaste → Add Permission</strong><br> Benutzer zuweisen, Rolle wählen, <em>Propagate to children</em> aktivieren.') ?>
</li>
</ol>
</div>
<div class="sg-section">
<h3 class="sg-h3"><?= $this->te('Schritt 3 – SSL-Zertifikat') ?></h3>
<table class="sg-table">
<tr><th scope="col"><?= $this->te('Szenario') ?></th><th scope="col"><?= $this->te('Einstellung') ?></th></tr>
<tr><td><?= $this->te('Offizielles oder intern signiertes Zertifikat') ?></td><td class="sg-ok"><?= $this->te('SSL-Verifizierung aktivieren') ?></td></tr>
<tr><td><?= $this->te('VMware Self-Signed (Standard bei Neuinstallation)') ?></td><td class="sg-warn"><?= $this->te('SSL-Verifizierung deaktivieren') ?></td></tr>
</table>
<div class="sg-note"><?= $this->t('Das Zertifikat lässt sich unter <em>Administration → Certificate Management</em> ersetzen. Danach SSL-Verifizierung aktivieren.') ?></div>
</div>
<div class="sg-section">
<h3 class="sg-h3"><?= $this->te('Was wird automatisch ausgelesen?') ?></h3>
<table class="sg-table">
<tr><th scope="col"><?= $this->te('Daten') ?></th><th scope="col"><?= $this->te('Status') ?></th></tr>
<tr><td><?= $this->te('VM-Liste, Name, Status (running/stopped/paused)') ?></td><td class="sg-ok"><?= $this->te('✓ automatisch') ?></td></tr>
<tr><td><?= $this->te('CPU-Kerne, RAM je VM') ?></td><td class="sg-ok"><?= $this->te('✓ automatisch') ?></td></tr>
<tr><td><?= $this->te('Storage je VM (Summe aller virtuellen Festplatten)') ?></td><td class="sg-ok"><?= $this->te('✓ automatisch (über VM-Detail-API)') ?></td></tr>
<tr><td><?= $this->te('IP-Adresse je VM') ?></td><td class="sg-ok"><?= $this->te('✓ wenn VMware Tools installiert sind') ?></td></tr>
<tr><td><?= $this->te('Betriebssystem') ?></td><td class="sg-ok"><?= $this->te('✓ aus vSphere Guest-OS-Feld') ?></td></tr>
<tr><td><?= $this->te('Host-CPU, Host-RAM') ?></td><td class="sg-ok"><?= $this->te('✓ automatisch') ?></td></tr>
<tr><td><?= $this->te('Host-Storage (Datastores gesamt)') ?></td><td class="sg-ok"><?= $this->te('✓ automatisch') ?></td></tr>
</table>
</div>
<div class="sg-section">
<h3 class="sg-h3"><?= $this->te('Node-ID / Datacenter (optional)') ?></h3>
<p><?= $this->te('Leer lassen → alle Hosts werden abgefragt. Eintragen, um die Abfrage auf einen bestimmten ESXi-Host oder Datacenter-Namen zu beschränken:') ?></p>
<div class="sg-code">esxi-prod-01.example.com
Datacenter-München</div>
</div>
<div class="sg-section">
<h3 class="sg-h3"><?= $this->te('Verbindung testen') ?></h3>
<p><?= $this->t('Nach dem Speichern der Einstellungen auf der Host-Konfigurationsseite den Button <strong>„Verbindung testen"</strong> klicken. Bei Erfolg wird die erkannte vSphere-Version angezeigt.') ?></p>
</div>
</div><!-- /#tab-vmware -->
<!-- ================================================================
PROXMOX
================================================================ -->
<div class="sg-panel" id="tab-proxmox" role="tabpanel" hidden>
<div class="sg-section">
<h3 class="sg-h3"><?= $this->te('Voraussetzungen') ?></h3>
<ul class="sg-list">
<li><?= $this->t('Proxmox VE <strong>7.x oder 8.x</strong>') ?></li>
<li><?= $this->t('Netzwerkzugang zu Proxmox auf Port <strong>8006</strong>') ?></li>
<li><?= $this->t('Authentifizierung per <strong>API-Token</strong> (empfohlen) oder Benutzername/Passwort') ?></li>
</ul>
</div>
<div class="sg-section">
<h3 class="sg-h3"><?= $this->te('Schritt 1 – API-URL eintragen') ?></h3>
<p><?= $this->te('Einfach die URL der Proxmox-Weboberfläche eingeben. Port 8006 wird automatisch ergänzt, falls nicht angegeben.') ?></p>
<div class="sg-code">https://192.168.1.10
https://proxmox.example.com
https://proxmox.example.com:8006 ← auch explizit möglich</div>
</div>
<div class="sg-section">
<h3 class="sg-h3"><?= $this->te('Schritt 2a – API-Token anlegen') ?> <span class="sg-badge-recommended"><?= $this->te('Empfohlen') ?></span></h3>
<ol class="sg-steps">
<li>
<?= $this->t('<strong>Datacenter → Permissions → Users → Add</strong><br> Neuen Benutzer anlegen, z. B. <code>monitoring</code>, Realm: <code>pam</code>') ?>
</li>
<li>
<strong><?= $this->te('Datacenter → Permissions → Add → User Permission') ?></strong>
<ul style="margin:.35rem 0 0 1rem;">
<li><?= $this->t('Path: <code>/</code>') ?></li>
<li><?= $this->t('User: <code>monitoring@pam</code>') ?></li>
<li><?= $this->t('Role: <code>PVEAuditor</code>') ?></li>
<li><?= $this->t('Propagate: <strong>aktiviert</strong>') ?></li>
</ul>
</li>
<li>
<strong><?= $this->te('Datacenter → Permissions → API Tokens → Add') ?></strong>
<ul style="margin:.35rem 0 0 1rem;">
<li><?= $this->t('User: <code>monitoring@pam</code>') ?></li>
<li><?= $this->t('Token ID: z. B. <code>openNIT</code>') ?></li>
<li><?= $this->t('Privilege Separation: <strong>aktiviert</strong>') ?></li>
</ul>
<?= $this->t('Den Token-String <strong>sofort kopieren</strong> – er wird nur einmalig angezeigt!') ?>
</li>
<li>
<?= $this->t('Token ins Feld <em>API-Token</em> eintragen. Format:') ?>
<div class="sg-code">monitoring@pam!openNIT=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx</div>
<?= $this->te('Das Passwort-Feld kann dann leer bleiben.') ?>
</li>
</ol>
</div>
<div class="sg-section">
<h3 class="sg-h3"><?= $this->te('Schritt 2b – Benutzername / Passwort (Alternative)') ?></h3>
<p><?= $this->t('Benutzername immer im Format <code>user@realm</code>') ?>:</p>
<div class="sg-code">root@pam ← lokaler root (nicht empfohlen)
monitoring@pam ← lokaler PAM-Benutzer
admin@pve ← Proxmox VE-interner Benutzer</div>
</div>
<div class="sg-section">
<h3 class="sg-h3"><?= $this->te('Schritt 3 – Node-ID (optional)') ?></h3>
<p><?= $this->te('Leer lassen → erster verfügbarer Node wird automatisch gewählt. Bei Multi-Node-Cluster den gewünschten Node-Namen eintragen:') ?></p>
<div class="sg-code">pve ← Standard bei Einzelinstallation
proxmox-node1 ← bei Cluster</div>
</div>
<div class="sg-section">
<h3 class="sg-h3"><?= $this->te('Schritt 4 – SSL-Zertifikat') ?></h3>
<table class="sg-table">
<tr><th scope="col"><?= $this->te('Szenario') ?></th><th scope="col"><?= $this->te('Einstellung') ?></th></tr>
<tr><td><?= $this->te('Proxmox Self-Signed (Standard)') ?></td><td class="sg-warn"><?= $this->te('SSL-Verifizierung deaktivieren') ?></td></tr>
<tr><td><?= $this->te('Let\'s Encrypt oder eigene CA') ?></td><td class="sg-ok"><?= $this->te('SSL-Verifizierung aktivieren') ?></td></tr>
</table>
<div class="sg-note"><?= $this->te("Let's Encrypt einrichten:") ?> <em><?= $this->te('Node → System → Certificates → ACME') ?></em>. <?= $this->te('Danach SSL-Verifizierung aktivierbar.') ?></div>
</div>
<div class="sg-section">
<h3 class="sg-h3"><?= $this->te('Was wird automatisch ausgelesen?') ?></h3>
<table class="sg-table">
<tr><th scope="col"><?= $this->te('Daten') ?></th><th scope="col"><?= $this->te('Status') ?></th></tr>
<tr><td><?= $this->te('QEMU/KVM VM-Liste, Name, Status') ?></td><td class="sg-ok"><?= $this->te('✓ automatisch') ?></td></tr>
<tr><td><?= $this->te('LXC Container (als eigene Einträge)') ?></td><td class="sg-ok"><?= $this->te('✓ automatisch') ?></td></tr>
<tr><td><?= $this->te('CPU, RAM, Storage je VM/CT') ?></td><td class="sg-ok"><?= $this->te('✓ automatisch') ?></td></tr>
<tr><td><?= $this->te('IP-Adresse QEMU-VM') ?></td><td class="sg-ok"><?= $this->te('✓ wenn QEMU Guest Agent installiert') ?></td></tr>
<tr><td><?= $this->te('IP-Adresse LXC Container') ?></td><td class="sg-ok"><?= $this->te('✓ automatisch aus Netzwerk-Konfiguration') ?></td></tr>
<tr><td><?= $this->te('Host-CPU, Host-RAM, Host-Storage') ?></td><td class="sg-ok"><?= $this->te('✓ automatisch') ?></td></tr>
<tr><td><?= $this->te('Betriebssystem') ?></td><td class="sg-warn"><?= $this->te('– nicht über API verfügbar') ?></td></tr>
</table>
<div class="sg-note">
<?= $this->t('QEMU Guest Agent in der VM installieren (Debian/Ubuntu):<br> <code>apt install qemu-guest-agent && systemctl enable --now qemu-guest-agent</code><br> Danach in Proxmox: VM → Options → QEMU Guest Agent → <strong>Enabled</strong>.') ?>
</div>
</div>
</div><!-- /#tab-proxmox -->
<!-- ================================================================
HYPER-V
================================================================ -->
<div class="sg-panel" id="tab-hyperv" role="tabpanel" hidden>
<div class="sg-section">
<h3 class="sg-h3"><?= $this->te('Voraussetzungen') ?></h3>
<ul class="sg-list">
<li><?= $this->te('Windows Server 2016 / 2019 / 2022 mit Hyper-V-Rolle') ?></li>
<li><?= $this->t('Netzwerkzugang auf Port <strong>5985</strong> (HTTP/WinRM) oder <strong>5986</strong> (HTTPS/WinRM)') ?></li>
<li><?= $this->te('Lokales Administrator- oder Hyper-V-Admin-Konto') ?></li>
</ul>
</div>
<div class="sg-section">
<h3 class="sg-h3"><?= $this->te('Schritt 1 – WinRM auf dem Hyper-V-Host aktivieren') ?></h3>
<p><?= $this->t('Auf dem Hyper-V-Server <strong>PowerShell als Administrator</strong> ausführen:') ?></p>
<div class="sg-code"># WinRM aktivieren
Enable-PSRemoting -Force
# Basic-Authentifizierung erlauben (immer erforderlich – auch bei HTTPS)
Set-Item WSMan:\localhost\Service\Auth\Basic $true
# Klartext-Übertragung erlauben (nur für HTTP / Port 5985 nötig)
Set-Item WSMan:\localhost\Service\AllowUnencrypted $true
# Firewall-Regel
netsh advfirewall firewall add rule name="WinRM HTTP OpenNIT" `
protocol=TCP dir=in localport=5985 action=allow</div>
<div class="sg-note"><?= $this->t('<strong>Wichtig:</strong> OpenNIT authentifiziert sich an der WinRM-API per Basic-Auth – <code>Auth\\Basic $true</code> ist deshalb <strong>auch bei HTTPS erforderlich</strong> (sonst HTTP 401). <code>AllowUnencrypted</code> betrifft dagegen nur HTTP.') ?></div>
<div class="sg-note"><?= $this->t('<strong>Sicherheitshinweis:</strong> Basic-Auth über HTTP überträgt Credentials Base64-kodiert (unverschlüsselt). Für Produktionsumgebungen HTTPS (Port 5986) verwenden – siehe Schritt 4; dort werden die Zugangsdaten TLS-verschlüsselt übertragen.') ?></div>
</div>
<div class="sg-section">
<h3 class="sg-h3"><?= $this->te('Schritt 2 – URL eintragen') ?></h3>
<p><?= $this->t('Nur IP-Adresse oder Hostname des Hyper-V-Hosts. Port und Pfad (<code>:5985/wsman</code>) werden automatisch ergänzt.') ?></p>
<div class="sg-code">http://192.168.1.20
http://hyperv-server.example.com
https://hyperv-server.example.com ← für HTTPS / Port 5986</div>
<div class="sg-note"><?= $this->t('Das Präfix <code>http://</code> vs. <code>https://</code> entscheidet, ob Port 5985 oder 5986 verwendet wird.') ?></div>
</div>
<div class="sg-section">
<h3 class="sg-h3"><?= $this->te('Schritt 3 – Benutzer anlegen') ?></h3>
<p><?= $this->te('Empfohlen: dedizierter lokaler Monitoring-Benutzer statt Administrator.') ?></p>
<div class="sg-code"># Lokalen Benutzer erstellen
$pw = ConvertTo-SecureString "SicheresPasswort!" -AsPlainText -Force
New-LocalUser "monitoring" -Password $pw -FullName "OpenNIT Monitoring"
# Zur Gruppe "Hyper-V Administrators" hinzufügen
Add-LocalGroupMember -Group "Hyper-V Administrators" -Member "monitoring"</div>
<p style="margin-top:.6rem;"><?= $this->te('Benutzername in den Einstellungen:') ?></p>
<div class="sg-code">.\monitoring ← lokaler Benutzer
DOMAIN\monitoring ← Domänenbenutzer</div>
</div>
<div class="sg-section">
<h3 class="sg-h3"><?= $this->te('Schritt 4 – HTTPS / Port 5986 einrichten (optional, empfohlen)') ?></h3>
<div class="sg-code"># Selbst-signiertes Zertifikat erstellen
$cert = New-SelfSignedCertificate -DnsName "hyperv-server" `
-CertStoreLocation "cert:\LocalMachine\My"
# HTTPS-WinRM-Listener anlegen
New-Item -Path WSMan:\localhost\Listener `
-Transport HTTPS -Address * `
-CertificateThumbprint $cert.Thumbprint -Force
# Firewall-Regel für HTTPS
netsh advfirewall firewall add rule name="WinRM HTTPS OpenNIT" `
protocol=TCP dir=in localport=5986 action=allow</div>
<div class="sg-note"><?= $this->t('Bei selbst-signiertem Zertifikat: SSL-Verifizierung <strong>deaktivieren</strong>. Bei CA-signiertem Zertifikat: <strong>aktivieren</strong>.') ?></div>
</div>
<div class="sg-section">
<h3 class="sg-h3"><?= $this->te('Was wird automatisch ausgelesen?') ?></h3>
<table class="sg-table">
<tr><th scope="col"><?= $this->te('Daten') ?></th><th scope="col"><?= $this->te('Status') ?></th></tr>
<tr><td><?= $this->te('VM-Liste, Name, Status') ?></td><td class="sg-ok"><?= $this->te('✓ automatisch') ?></td></tr>
<tr><td><?= $this->te('CPU, RAM je VM') ?></td><td class="sg-ok"><?= $this->te('✓ automatisch') ?></td></tr>
<tr><td><?= $this->te('Storage je VM (Summe VHD-Größen)') ?></td><td class="sg-ok"><?= $this->te('✓ automatisch') ?></td></tr>
<tr><td><?= $this->te('IP-Adresse je VM') ?></td><td class="sg-ok"><?= $this->te('✓ wenn Integration Services aktiv sind') ?></td></tr>
<tr><td><?= $this->te('Host-CPU, Host-RAM, Host-Storage') ?></td><td class="sg-ok"><?= $this->te('✓ automatisch') ?></td></tr>
<tr><td><?= $this->te('Betriebssystem') ?></td><td class="sg-warn"><?= $this->te('– nicht über WinRM verfügbar') ?></td></tr>
</table>
<div class="sg-note">
<?= $this->te('Integration Services-Status prüfen:') ?><br>
<code>Get-VMIntegrationService -VMName "VM-Name" | Format-Table Name, Enabled</code>
</div>
</div>
</div><!-- /#tab-hyperv -->
<!-- ================================================================
KVM
================================================================ -->
<div class="sg-panel" id="tab-kvm" role="tabpanel" hidden>
<div class="sg-section">
<h3 class="sg-h3"><?= $this->te('Voraussetzungen') ?></h3>
<ul class="sg-list">
<li><?= $this->t('Linux-Host mit KVM/QEMU und <code>libvirt</code>') ?></li>
<li><?= $this->t('SSH-Zugang von diesem Server auf Port <strong>22</strong>') ?></li>
<li><?= $this->t('<code>virsh</code> auf dem KVM-Host verfügbar (Teil von <code>libvirt-clients</code>)') ?></li>
<li><?= $this->t('Benutzerkonto in der Gruppe <code>libvirt</code> oder <code>kvm</code>') ?></li>
</ul>
</div>
<div class="sg-section">
<h3 class="sg-h3"><?= $this->te('Schritt 1 – SSH-Zugang einrichten') ?></h3>
<p><?= $this->t('Der KVM-Connector verbindet sich per SSH und führt <code>virsh</code>-Befehle aus. Empfohlen: SSH-Key-Authentifizierung.') ?></p>
<div class="sg-code"># Auf dem KVM-Host: Monitoring-Benutzer anlegen
useradd -m -s /bin/bash monitoring
usermod -aG libvirt monitoring
usermod -aG kvm monitoring
# SSH-Key vom OpenNIT-Server hinterlegen
mkdir -p /home/monitoring/.ssh
echo "ssh-ed25519 AAAA... openNIT" >> /home/monitoring/.ssh/authorized_keys
chmod 700 /home/monitoring/.ssh
chmod 600 /home/monitoring/.ssh/authorized_keys
chown -R monitoring:monitoring /home/monitoring/.ssh</div>
</div>
<div class="sg-section">
<h3 class="sg-h3"><?= $this->te('Schritt 2 – URL und Zugangsdaten eintragen') ?></h3>
<div class="sg-code">http://192.168.1.30 ← IP des KVM-Hosts (http-Präfix → Port 22)
http://kvm-server.local</div>
<p style="margin-top:.6rem;"><?= $this->te('Felder:') ?></p>
<ul class="sg-list">
<li><?= $this->t('<strong>Benutzername:</strong> SSH-Benutzer, z. B. <code>monitoring</code>') ?></li>
<li><?= $this->t('<strong>Passwort:</strong> SSH-Passwort <em>oder</em> leer lassen bei Key-Auth') ?></li>
<li><?= $this->t('<strong>API-Token:</strong> Pfad zum privaten SSH-Key auf diesem Server, z. B. <code>/var/www/.ssh/id_ed25519</code>') ?></li>
</ul>
<div class="sg-note"><?= $this->t('Wenn ein SSH-Key-Pfad im API-Token-Feld eingetragen ist, wird Key-Auth verwendet und das Passwort ignoriert. Ohne Key-Pfad wird Passwort-Auth per <code>sshpass</code> versucht (<code>apt install sshpass</code> auf diesem Server).') ?></div>
</div>
<div class="sg-section">
<h3 class="sg-h3"><?= $this->te('Schritt 3 – libvirt verifizieren') ?></h3>
<div class="sg-code"># Auf dem KVM-Host prüfen:
virsh list --all # Alle VMs anzeigen
virsh nodeinfo # CPU/RAM des Hosts
virsh dominfo VM-Name # Details einer VM</div>
</div>
<div class="sg-section">
<h3 class="sg-h3"><?= $this->te('Was wird automatisch ausgelesen?') ?></h3>
<table class="sg-table">
<tr><th scope="col"><?= $this->te('Daten') ?></th><th scope="col"><?= $this->te('Status') ?></th></tr>
<tr><td><?= $this->te('VM-Liste, Name, Status') ?></td><td class="sg-ok"><?= $this->te('✓ automatisch (virsh list)') ?></td></tr>
<tr><td><?= $this->te('CPU-Kerne, RAM je VM') ?></td><td class="sg-ok"><?= $this->te('✓ automatisch (virsh dominfo)') ?></td></tr>
<tr><td><?= $this->te('Storage je VM') ?></td><td class="sg-ok"><?= $this->te('✓ automatisch (virsh domblkinfo)') ?></td></tr>
<tr><td><?= $this->te('IP-Adresse je VM') ?></td><td class="sg-ok"><?= $this->te('✓ wenn QEMU Guest Agent aktiv (virsh domifaddr)') ?></td></tr>
<tr><td><?= $this->te('Host-CPU, Host-RAM') ?></td><td class="sg-ok"><?= $this->te('✓ automatisch (virsh nodeinfo)') ?></td></tr>
<tr><td><?= $this->te('Betriebssystem') ?></td><td class="sg-warn"><?= $this->te('– nicht über virsh verfügbar') ?></td></tr>
</table>
</div>
</div><!-- /#tab-kvm -->
<!-- ================================================================
XEN / XCP-ng
================================================================ -->
<div class="sg-panel" id="tab-xen" role="tabpanel" hidden>
<div class="sg-section">
<h3 class="sg-h3"><?= $this->te('Voraussetzungen') ?></h3>
<ul class="sg-list">
<li><?= $this->t('<strong>XCP-ng 8.x</strong> oder <strong>XenServer 8.x / Citrix Hypervisor</strong>') ?></li>
<li><?= $this->t('Netzwerkzugang auf Port <strong>443</strong> (HTTPS)') ?></li>
<li><?= $this->te('Admin- oder Read-Only-Konto (XAPI-Authentifizierung)') ?></li>
</ul>
</div>
<div class="sg-section">
<h3 class="sg-h3"><?= $this->te('Schritt 1 – URL eintragen') ?></h3>
<p><?= $this->te('URL des XCP-ng / XenServer-Hosts. Die XAPI lauscht auf Port 443.') ?></p>
<div class="sg-code">https://192.168.1.40
https://xen-host.example.com</div>
</div>
<div class="sg-section">
<h3 class="sg-h3"><?= $this->te('Schritt 2 – Benutzer anlegen (optional, empfohlen)') ?></h3>
<p><?= $this->t('Über die XCP-ng Center-Konsole oder <code>xe</code> CLI einen dedizierten Benutzer anlegen:') ?></p>
<div class="sg-code"># Auf dem XCP-ng Host per SSH:
xe subject-add subject-name=monitoring
# Passwort setzen (XCP-ng nutzt PAM / lokale Benutzer)
# Alternativ: root-Zugang verwenden, aber nicht empfohlen</div>
<div class="sg-note"><?= $this->t('XCP-ng unterstützt RBAC: Rolle <em>Read-Only</em> reicht für den Sync aus. Zuweisung über <em>XCP-ng Center → Pool → Users</em>.') ?></div>
</div>
<div class="sg-section">
<h3 class="sg-h3"><?= $this->te('Schritt 3 – SSL-Zertifikat') ?></h3>
<table class="sg-table">
<tr><th scope="col"><?= $this->te('Szenario') ?></th><th scope="col"><?= $this->te('Einstellung') ?></th></tr>
<tr><td><?= $this->te('XCP-ng Self-Signed (Standard)') ?></td><td class="sg-warn"><?= $this->te('SSL-Verifizierung deaktivieren') ?></td></tr>
<tr><td><?= $this->te('Eigenes / CA-signiertes Zertifikat') ?></td><td class="sg-ok"><?= $this->te('SSL-Verifizierung aktivieren') ?></td></tr>
</table>
<div class="sg-note"><?= $this->t('Eigenes Zertifikat installieren: <code>xe pool-certificate-install filename=cert.pem</code>') ?></div>
</div>
<div class="sg-section">
<h3 class="sg-h3"><?= $this->te('Was wird automatisch ausgelesen?') ?></h3>
<table class="sg-table">
<tr><th scope="col"><?= $this->te('Daten') ?></th><th scope="col"><?= $this->te('Status') ?></th></tr>
<tr><td><?= $this->te('VM-Liste, Name, Status') ?></td><td class="sg-ok"><?= $this->te('✓ automatisch (XAPI VM.get_all_records)') ?></td></tr>
<tr><td><?= $this->te('CPU-Kerne, RAM je VM') ?></td><td class="sg-ok"><?= $this->te('✓ automatisch') ?></td></tr>
<tr><td><?= $this->te('Storage je VM (VDI-Größen)') ?></td><td class="sg-ok"><?= $this->te('✓ automatisch') ?></td></tr>
<tr><td><?= $this->te('IP-Adresse je VM') ?></td><td class="sg-ok"><?= $this->te('✓ wenn Xen Guest Tools installiert') ?></td></tr>
<tr><td><?= $this->te('Host-CPU, Host-RAM, Host-Storage') ?></td><td class="sg-ok"><?= $this->te('✓ automatisch') ?></td></tr>
<tr><td><?= $this->te('Betriebssystem') ?></td><td class="sg-ok"><?= $this->te('✓ aus XAPI Guest-Metrics') ?></td></tr>
</table>
<div class="sg-note">
<?= $this->t('Xen Guest Tools (xe-guest-utilities) in der VM installieren (Debian/Ubuntu):<br> <code>apt install xe-guest-utilities</code><br> Danach sind IP-Adresse und OS automatisch sichtbar.') ?>
</div>
</div>
</div><!-- /#tab-xen -->
</div><!-- /.settings-card-body -->
</section>
<div style="margin-top:.5rem;font-size:.8rem;color:var(--gray-400);">
<a href="/admin/vms/hypervisor" style="color:var(--gray-500);text-decoration:none;"><?= $this->te('← Zurück zu Hypervisor-APIs') ?></a>
</div>
</div>
<style>
/* Tabs */
.sg-tabs {
display:flex; gap:0; border-bottom:1px solid var(--gray-200);
overflow-x:auto; -webkit-overflow-scrolling:touch;
}
.sg-tab {
display:inline-flex; align-items:center; gap:.4rem;
padding:.65rem 1.1rem; font-size:.82rem; font-weight:600; color:var(--gray-500);
background:none; border:none; border-bottom:2px solid transparent;
cursor:pointer; white-space:nowrap; transition:all .15s;
margin-bottom:-1px;
}
.sg-tab:hover { color:var(--gray-700); background:var(--gray-50); }
.sg-tab-active { color:var(--blue-700); border-bottom-color:var(--blue-700); background:var(--color-bg); }
/* Panels */
.sg-panel { padding:1.75rem 1.75rem 2rem; display:none; }
.sg-panel-active { display:block; }
.sg-section { margin-bottom:1.75rem; }
.sg-section:last-child { margin-bottom:0; }
.sg-h3 {
font-size:.78rem; font-weight:700; text-transform:uppercase; letter-spacing:.05em;
color:var(--gray-700); margin:0 0 .7rem; padding-bottom:.5rem; border-bottom:2px solid var(--gray-100);
}
.sg-list { margin:.35rem 0 0 1.25rem; padding:0; font-size:.875rem; color:var(--gray-700); line-height:1.75; }
.sg-list li { margin-bottom:.2rem; }
.sg-steps { margin:.35rem 0 0 1.25rem; padding:0; font-size:.875rem; color:var(--gray-700); line-height:1.7; }
.sg-steps li { margin-bottom:.9rem; }
.sg-code {
background:var(--slate-800); color:var(--slate-200);
font-family:ui-monospace,SFMono-Regular,Menlo,monospace;
font-size:.775rem; line-height:1.65; padding:.8rem 1rem;
border-radius:.3rem; margin:.5rem 0; white-space:pre-wrap; overflow-x:auto;
}
.sg-note {
background:var(--amber-50); border:1px solid var(--amber-200); border-radius:.25rem;
padding:.55rem .85rem; font-size:.78rem; color:var(--amber-800); line-height:1.6; margin-top:.65rem;
}
.sg-table { width:100%; border-collapse:collapse; font-size:.825rem; margin:.5rem 0; }
.sg-table th {
background:var(--slate-50); padding:.45rem .85rem; text-align:left;
font-size:.7rem; font-weight:600; color:var(--gray-500);
text-transform:uppercase; letter-spacing:.04em; border-bottom:1px solid var(--gray-200);
}
.sg-table td { padding:.5rem .85rem; border-bottom:1px solid var(--gray-100); color:var(--gray-700); }
.sg-table tr:last-child td { border-bottom:none; }
.sg-ok { color:var(--green-700); font-weight:500; }
.sg-warn { color:var(--amber-800); font-weight:500; }
.sg-badge-recommended {
display:inline-block; font-size:.68rem; font-weight:600; padding:.1rem .4rem;
border-radius:9999px; background:var(--green-100); color:var(--green-700);
vertical-align:middle; margin-left:.4rem;
}
</style>
<script>
(function () {
var tabs = document.querySelectorAll('.sg-tab');
var panels = document.querySelectorAll('.sg-panel');
tabs.forEach(function (tab) {
tab.addEventListener('click', function () {
var target = tab.dataset.tab;
tabs.forEach(function (t) {
t.classList.remove('sg-tab-active');
t.setAttribute('aria-selected', 'false');
});
panels.forEach(function (p) {
p.classList.remove('sg-panel-active');
p.hidden = true;
});
tab.classList.add('sg-tab-active');
tab.setAttribute('aria-selected', 'true');
var panel = document.getElementById('tab-' + target);
if (panel) { panel.classList.add('sg-panel-active'); panel.hidden = false; }
});
});
}());
</script>