diff --git a/README.md b/README.md index abcbc44..d66e5f4 100644 --- a/README.md +++ b/README.md @@ -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 diff --git a/migrator.py b/migrator.py index 0f0033f..fa2a24c 100644 --- a/migrator.py +++ b/migrator.py @@ -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 --monhost ") + 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()