update storage.cfg

This commit is contained in:
duffyduck 2026-03-05 08:27:01 +01:00
parent 4a9bb2f0f2
commit 4bb9b93baf
2 changed files with 95 additions and 32 deletions

View File

@ -471,7 +471,7 @@ ceph -s
### Fehlerbehebung: CephFS/RBD-Storage nicht erreichbar nach Migration ### 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. Nach der Migration kann CephFS nicht erreichbar sein, weil der Kernel-Mount noch die alten MON-IPs cached. Das passiert unabhängig davon, ob `monhost` in der `storage.cfg` steht oder nicht. Aktuelle Versionen des Tools machen den Remount automatisch.
**Symptom:** CephFS-Storage zeigt Fehler in der GUI, `mount | grep ceph` zeigt alte IPs: **Symptom:** CephFS-Storage zeigt Fehler in der GUI, `mount | grep ceph` zeigt alte IPs:
@ -479,27 +479,37 @@ Falls CephFS oder RBD-Storage nach der Migration nicht gemountet werden können,
172.0.4.1,172.0.4.2,172.0.4.3:/ on /mnt/pve/cephfs type ceph (...) 172.0.4.1,172.0.4.2,172.0.4.3:/ on /mnt/pve/cephfs type ceph (...)
``` ```
**Lösung:** **Fall 1: Keine `monhost`-Einträge in storage.cfg (Standard bei Proxmox)**
Proxmox holt sich die MON-IPs automatisch aus `/etc/ceph/ceph.conf`. Es reicht ein Remount:
```bash ```bash
# 1. Prüfen welche IPs in storage.cfg stehen: # Auf JEDEM Node:
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 umount /mnt/pve/cephfs
mount /mnt/pve/cephfs mount /mnt/pve/cephfs
# Oder auf allen Nodes per Neustart des Storage-Dienstes: # Prüfen ob die neuen IPs verwendet werden:
systemctl restart pve-ha-lrm mount | grep ceph
``` ```
> **Hinweis:** Die Storage-Namen (`cephfs`, `local-rbd`) können bei jedem Setup anders heißen. Mit `pvesm status` werden alle konfigurierten Storages angezeigt. **Fall 2: Explizite `monhost`-Einträge in storage.cfg**
```bash
# 1. Prüfen ob monhost-Einträge vorhanden sind:
grep monhost /etc/pve/storage.cfg
# 2. Falls ja, 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 data --monhost 192.168.101.1,192.168.101.2,192.168.101.3
# 4. Dann Remount auf JEDEM Node:
umount /mnt/pve/cephfs
mount /mnt/pve/cephfs
```
> **Hinweis:** Die Storage-Namen (`cephfs`, `data`) können bei jedem Setup anders heißen. Mit `pvesm status` werden alle konfigurierten Storages angezeigt.
## Hinweise ## Hinweise

View File

@ -391,10 +391,11 @@ class Migrator:
if configs.get('ceph'): if configs.get('ceph'):
self._update_ceph(plan, configs) self._update_ceph(plan, configs)
# Update storage.cfg (CephFS/RBD monhost entries) # Update storage.cfg (CephFS/RBD monhost entries) and remount CephFS
ip_mapping = {n.current_ip: n.new_ip for n in plan.nodes if n.new_ip} ip_mapping = {n.current_ip: n.new_ip for n in plan.nodes if n.new_ip}
if ip_mapping: if ip_mapping:
self._update_storage_cfg(ip_mapping) self._update_storage_cfg(ip_mapping)
self._remount_cephfs(plan)
# Cleanup staging directories # Cleanup staging directories
print("\n Staging-Verzeichnisse aufräumen...") print("\n Staging-Verzeichnisse aufräumen...")
@ -436,11 +437,12 @@ class Migrator:
print(" [Corosync] Manuell ausführen: cp /etc/corosync/corosync.conf /etc/pve/corosync.conf") print(" [Corosync] Manuell ausführen: cp /etc/corosync/corosync.conf /etc/pve/corosync.conf")
def _update_storage_cfg(self, ip_mapping: dict[str, str]): def _update_storage_cfg(self, ip_mapping: dict[str, str]):
"""Update /etc/pve/storage.cfg with new MON IPs. """Update /etc/pve/storage.cfg with new MON IPs and remount CephFS.
CephFS and RBD storage entries contain a 'monhost' field with the CephFS and RBD storage entries may contain a 'monhost' field with
MON IP addresses. After a network migration these must be updated, MON IP addresses. If present, these must be updated. Additionally,
otherwise CephFS mounts and RBD connections fail. active CephFS mounts use the old IPs in the kernel and need a remount
regardless of whether monhost is in storage.cfg or not.
""" """
print("\n [Storage] /etc/pve/storage.cfg prüfen...") print("\n [Storage] /etc/pve/storage.cfg prüfen...")
@ -459,17 +461,14 @@ class Migrator:
print(f" [Storage] WARNUNG: storage.cfg nicht lesbar: {err}") print(f" [Storage] WARNUNG: storage.cfg nicht lesbar: {err}")
return return
# Check if any old IPs are present # Check if any old IPs are present in storage.cfg
needs_update = False needs_update = False
for old_ip in ip_mapping: for old_ip in ip_mapping:
if old_ip in content: if old_ip in content:
needs_update = True needs_update = True
break break
if not needs_update: if needs_update:
print(" [Storage] Keine alten IPs in storage.cfg gefunden")
return
# Replace old IPs with new IPs # Replace old IPs with new IPs
new_content = content new_content = content
for old_ip, new_ip in ip_mapping.items(): for old_ip, new_ip in ip_mapping.items():
@ -480,6 +479,60 @@ class Migrator:
print(" [Storage] /etc/pve/storage.cfg aktualisiert (monhost IPs ersetzt)") print(" [Storage] /etc/pve/storage.cfg aktualisiert (monhost IPs ersetzt)")
else: else:
print(f" [Storage] FEHLER: {msg}") print(f" [Storage] FEHLER: {msg}")
else:
print(" [Storage] Keine alten IPs in storage.cfg (monhost wird aus ceph.conf gelesen)")
def _remount_cephfs(self, plan: MigrationPlan):
"""Remount CephFS on all nodes after migration.
The kernel CephFS mount caches the old MON IPs. Even if ceph.conf
is updated, the existing mount still uses the old addresses.
A remount picks up the new IPs from the updated config.
"""
# Check if any CephFS mounts exist on the local node
rc, mounts, _ = self.ssh.execute_local("mount -t ceph 2>/dev/null")
if rc != 0 or not mounts or not mounts.strip():
return
# Extract CephFS mount points (skip non-cephfs mounts)
mount_points = []
for line in mounts.strip().split('\n'):
# Format: 1.2.3.4,5.6.7.8:/ on /mnt/pve/cephfs type ceph (...)
if ' type ceph ' in line:
parts = line.split(' on ')
if len(parts) >= 2:
mp = parts[1].split(' type ')[0].strip()
mount_points.append(mp)
if not mount_points:
return
print(f"\n [CephFS] {len(mount_points)} Mount(s) gefunden, Remount auf allen Nodes...")
for node in plan.nodes:
if not node.is_reachable:
continue
new_host = node.new_ip if not node.is_local else node.ssh_host
for mp in mount_points:
if node.is_local or True: # Remount on all nodes
rc, _, err = self.ssh.run_on_node(
new_host,
f"umount {mp} 2>/dev/null; mount {mp}",
node.is_local, timeout=30,
)
if rc == 0:
print(f" [{node.name}] CephFS {mp} remounted")
else:
# Mount might not exist on this node yet, try just mount
rc2, _, _ = self.ssh.run_on_node(
new_host, f"mount {mp} 2>/dev/null",
node.is_local, timeout=30,
)
if rc2 == 0:
print(f" [{node.name}] CephFS {mp} mounted")
else:
print(f" [{node.name}] CephFS {mp} WARNUNG: Remount fehlgeschlagen: {err}")
def _wait_for_quorum(self, timeout: int = 60) -> bool: def _wait_for_quorum(self, timeout: int = 60) -> bool:
"""Wait for cluster quorum to be established.""" """Wait for cluster quorum to be established."""