update storage.cfg
This commit is contained in:
parent
4a9bb2f0f2
commit
4bb9b93baf
40
README.md
40
README.md
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
||||||
73
migrator.py
73
migrator.py
|
|
@ -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."""
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue