update storage_cfg for cephfs mount and changed readme

This commit is contained in:
duffyduck 2026-03-05 08:12:38 +01:00
parent 9babedf6ca
commit 4a9bb2f0f2
2 changed files with 84 additions and 0 deletions

View File

@ -155,6 +155,7 @@ Wenn Ceph Public/Cluster auf separaten NICs liegen, werden die IPs einzeln pro N
| `/etc/hosts` | Jeder Node | Hostname-zu-IP-Zuordnung |
| `/etc/corosync/corosync.conf` | Jeder Node | Corosync Ring-Adressen |
| `/etc/pve/ceph.conf` | Cluster-FS | public_network, cluster_network, MON-Adressen |
| `/etc/pve/storage.cfg` | Cluster-FS | monhost-IPs für CephFS- und RBD-Storage |
## Migrationsablauf (Phase 4)
@ -468,6 +469,38 @@ ceph -s
> **Hinweis:** Falls zusätzlich `clock skew detected` angezeigt wird, NTP auf den betroffenen Nodes prüfen: `systemctl status chrony` oder `systemctl status ntp`. Nach einer Migration mit Neustarts kann die Uhrzeit kurzzeitig abweichen — das korrigiert sich in der Regel automatisch.
### Fehlerbehebung: CephFS/RBD-Storage nicht erreichbar nach Migration
Falls CephFS oder RBD-Storage nach der Migration nicht gemountet werden können, liegt es daran, dass in `/etc/pve/storage.cfg` noch die alten MON-IPs stehen. Aktuelle Versionen des Tools aktualisieren die `storage.cfg` automatisch.
**Symptom:** CephFS-Storage zeigt Fehler in der GUI, `mount | grep ceph` zeigt alte IPs:
```
172.0.4.1,172.0.4.2,172.0.4.3:/ on /mnt/pve/cephfs type ceph (...)
```
**Lösung:**
```bash
# 1. Prüfen welche IPs in storage.cfg stehen:
grep monhost /etc/pve/storage.cfg
# 2. monhost für CephFS aktualisieren (neue MON-IPs kommasepariert):
pvesm set cephfs --monhost 192.168.101.1,192.168.101.2,192.168.101.3
# 3. Falls RBD-Storage vorhanden:
pvesm set local-rbd --monhost 192.168.101.1,192.168.101.2,192.168.101.3
# 4. CephFS neu mounten:
umount /mnt/pve/cephfs
mount /mnt/pve/cephfs
# Oder auf allen Nodes per Neustart des Storage-Dienstes:
systemctl restart pve-ha-lrm
```
> **Hinweis:** Die Storage-Namen (`cephfs`, `local-rbd`) können bei jedem Setup anders heißen. Mit `pvesm status` werden alle konfigurierten Storages angezeigt.
## Hinweise
- Das Tool muss als **root** ausgeführt werden

View File

@ -391,6 +391,11 @@ class Migrator:
if configs.get('ceph'):
self._update_ceph(plan, configs)
# Update storage.cfg (CephFS/RBD monhost entries)
ip_mapping = {n.current_ip: n.new_ip for n in plan.nodes if n.new_ip}
if ip_mapping:
self._update_storage_cfg(ip_mapping)
# Cleanup staging directories
print("\n Staging-Verzeichnisse aufräumen...")
for node in plan.nodes:
@ -430,6 +435,52 @@ class Migrator:
print(" [Corosync] WARNUNG: /etc/pve nicht beschreibbar!")
print(" [Corosync] Manuell ausführen: cp /etc/corosync/corosync.conf /etc/pve/corosync.conf")
def _update_storage_cfg(self, ip_mapping: dict[str, str]):
"""Update /etc/pve/storage.cfg with new MON IPs.
CephFS and RBD storage entries contain a 'monhost' field with the
MON IP addresses. After a network migration these must be updated,
otherwise CephFS mounts and RBD connections fail.
"""
print("\n [Storage] /etc/pve/storage.cfg prüfen...")
# Check if /etc/pve is writable
rc, _, _ = self.ssh.execute_local(
"touch /etc/pve/.storage_test && rm -f /etc/pve/.storage_test"
)
if rc != 0:
print(" [Storage] WARNUNG: /etc/pve nicht beschreibbar!")
print(" [Storage] Manuell ausführen: pvesm set <storage> --monhost <neue-IPs>")
return
# Read current storage.cfg
rc, content, err = self.ssh.execute_local("cat /etc/pve/storage.cfg")
if rc != 0 or not content:
print(f" [Storage] WARNUNG: storage.cfg nicht lesbar: {err}")
return
# Check if any old IPs are present
needs_update = False
for old_ip in ip_mapping:
if old_ip in content:
needs_update = True
break
if not needs_update:
print(" [Storage] Keine alten IPs in storage.cfg gefunden")
return
# Replace old IPs with new IPs
new_content = content
for old_ip, new_ip in ip_mapping.items():
new_content = new_content.replace(old_ip, new_ip)
ok, msg = self.ssh.write_local_file("/etc/pve/storage.cfg", new_content)
if ok:
print(" [Storage] /etc/pve/storage.cfg aktualisiert (monhost IPs ersetzt)")
else:
print(f" [Storage] FEHLER: {msg}")
def _wait_for_quorum(self, timeout: int = 60) -> bool:
"""Wait for cluster quorum to be established."""
start = time.time()