fix(agent): Cluster-Knoten mit QDevice richtig lesen (#042)
Der Agent nahm aus `pvecm nodes` blind die dritte Spalte als Knotennamen. Mit einem QDevice steht dort dessen Zustand (A,V,NMW oder NR), und der Name rutscht eine Spalte weiter - gemeldet wurden damit die Zustandskuerzel und das QDevice als zusaetzlicher vierter Knoten. Die Namensspalte wird jetzt aus der Kopfzeile bestimmt, die Zeile des QDevice (Nodeid 0) uebersprungen. Beide Ausgabeformen sind als Testfall hinterlegt. Agent-Version 0.2.2. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -17,6 +17,12 @@ und dieses Projekt folgt [Semantic Versioning](https://semver.org/lang/de/).
|
||||
|
||||
### Sicherheit
|
||||
|
||||
## [0.24.1] – 2026-10-03
|
||||
|
||||
### Behoben
|
||||
- **Cluster mit QDevice meldeten falsche Knotennamen** (`A,V,NMW`, `NR`) und das QDevice als zusätzlichen Knoten: `pvecm nodes` hat dann eine Spalte mehr. Die Namensspalte wird jetzt aus der Kopfzeile bestimmt (#042)
|
||||
- Agent-Version 0.2.2
|
||||
|
||||
## [0.24.0] – 2026-10-03
|
||||
|
||||
### Hinzugefügt
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
## Zeitübersicht
|
||||
|
||||
**Gesamt:** 22 h 33 min
|
||||
**Gesamt:** 22 h 53 min
|
||||
|
||||
| Issue | Zeit |
|
||||
|---|---|
|
||||
@@ -47,6 +47,7 @@
|
||||
| #039 Zugang zur Laufzeit | 0 h 30 min |
|
||||
| #040 Schlagworte sichtbar | 0 h 40 min |
|
||||
| #041 Doppelte Hosts | 0 h 50 min |
|
||||
| #042 QDevice im Cluster | 0 h 20 min |
|
||||
|
||||
| Meilenstein | Zeit |
|
||||
|---|---|
|
||||
@@ -69,7 +70,7 @@
|
||||
|
||||
## 2026-09-17 · Sitzung 1 · 19:36–laufend
|
||||
**Issue:** #001–#007 (Meilensteine v0.1.0 bis v0.4.0)
|
||||
**Version:** 0.24.0
|
||||
**Version:** 0.24.1
|
||||
|
||||
### Erledigt
|
||||
- Auftrag gelesen, Rückfragen gestellt
|
||||
@@ -212,6 +213,9 @@
|
||||
- Doppelte Hosts (#041): Zwei Einträge desselben Namens beim selben Kunden entstehen, wenn sich die Maschinenkennung ändert. Neue Warnregel plus die bis dahin fehlende Möglichkeit, einen Host überhaupt loszuwerden
|
||||
- Bewusst kein automatisches Zusammenführen: Es müsste raten, welcher Eintrag welche Rechnung erbt
|
||||
|
||||
- QDevice im Cluster (#042): Der Agent nahm blind die dritte Spalte von `pvecm nodes` als Namen. Mit QDevice steht dort der Zustand des QDevice
|
||||
- Dritter Fall dieser Art: Was beim Feldtest auf einem Cluster stimmte, stimmt nicht überall. Spalten gehören über ihre Überschrift angesprochen
|
||||
|
||||
### Nächster Schritt
|
||||
- #016 Benutzerhandbuch mit Screenshots, danach #017 Favicons und #019 CI-Pipeline
|
||||
- Für 1.0.0 fehlt noch: PMG (kein Host verfügbar) und der Fall „aktive Subscription auf PBS“ (#023)
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
set -o nounset
|
||||
set -o pipefail
|
||||
|
||||
AGENT_VERSION="0.2.1"
|
||||
AGENT_VERSION="0.2.2"
|
||||
CONFIG_DATEI="${PROXLEDGER_CONFIG:-/etc/proxledger/agent.conf}"
|
||||
SPOOL_VERZEICHNIS="${PROXLEDGER_SPOOL:-/var/lib/proxledger/spool}"
|
||||
SPOOL_MAXIMUM=30
|
||||
@@ -175,9 +175,24 @@ cluster_name() {
|
||||
|
||||
# Namen aller Cluster-Mitglieder laut corosync. Auch Knoten ohne Agent stehen hier –
|
||||
# daraus erkennt das Dashboard vergessene Knoten (#022).
|
||||
# Namen aller Cluster-Knoten aus `pvecm nodes`.
|
||||
#
|
||||
# Die Spaltenzahl ist nicht fest: Mit einem QDevice steht zwischen Votes und Name noch dessen
|
||||
# Zustand (A,V,NMW oder NR). Deshalb wird die Spalte "Name" aus der Kopfzeile bestimmt, statt
|
||||
# blind die dritte zu nehmen. Die Zeile des QDevice selbst traegt die Nodeid 0 und ist kein Knoten.
|
||||
cluster_mitglieder() {
|
||||
if command -v pvecm >/dev/null 2>&1; then
|
||||
pvecm nodes 2>/dev/null | awk '/^[[:space:]]*[0-9]+[[:space:]]+[0-9]+/ {print $3}' | sed 's/ *(local)//'
|
||||
pvecm nodes 2>/dev/null | awk '
|
||||
/Nodeid/ {
|
||||
for (i = 1; i <= NF; i++) if ($i == "Name") spalte = i
|
||||
next
|
||||
}
|
||||
/^[[:space:]]*[0-9]+[[:space:]]+[0-9]+/ {
|
||||
if ($1 == 0) next
|
||||
name = (spalte ? $spalte : $3)
|
||||
sub(/\(.*/, "", name)
|
||||
if (name != "") print name
|
||||
}'
|
||||
fi
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
# #042 Cluster-Knoten falsch gelesen, wenn ein QDevice im Spiel ist
|
||||
**Status:** erledigt
|
||||
**Meilenstein:** v0.24.1
|
||||
**Labels:** bug, agent
|
||||
**Geschätzt:** 1 h **Tatsächlich:** 0 h 20 min
|
||||
|
||||
## Auslöser
|
||||
Florians Cluster hat drei Knoten (`hv-pve-01`, `hv-pve-02`, `hv-pve-05`). ProxLedger zeigte vier
|
||||
„Cluster-Knoten“: `A,V,NMW`, `A,V,NMW`, `NR` und `Qdevice`.
|
||||
|
||||
## Ursache
|
||||
Der Agent nahm aus `pvecm nodes` blind die dritte Spalte als Namen. Ohne QDevice stimmt das:
|
||||
|
||||
```
|
||||
Nodeid Votes Name
|
||||
1 1 hv-rz5-pve-01 (local)
|
||||
```
|
||||
|
||||
Mit QDevice steht dort aber dessen Zustand, und der Name rutscht eine Spalte weiter:
|
||||
|
||||
```
|
||||
Nodeid Votes Qdevice Name
|
||||
1 1 A,V,NMW hv-pve-01
|
||||
0 1 Qdevice (votes 1)
|
||||
```
|
||||
|
||||
Gemeldet wurden damit die Zustandskürzel – und das QDevice selbst als vierter „Knoten“.
|
||||
|
||||
## Behebung
|
||||
Die Spalte „Name“ wird aus der Kopfzeile bestimmt, statt sie zu erraten. Die Zeile des QDevice trägt
|
||||
die Nodeid 0 und wird übersprungen. Beide Ausgabeformen sind als Testfall hinterlegt.
|
||||
|
||||
## Folgen
|
||||
Die Warnregel „Cluster-Knoten ohne Agent“ hatte dadurch Warnungen für Knoten erzeugt, die es nicht
|
||||
gibt. Sie schließen sich von selbst, sobald die Agents mit der neuen Fassung gemeldet haben.
|
||||
|
||||
## Lehre
|
||||
Dritter Fall in dieser Reihe: Eine Ausgabe, die beim Feldtest auf **einem** Cluster richtig gelesen
|
||||
wurde, ist nicht auf jedem Cluster gleich. Spalten gehören über ihre Überschrift angesprochen, nicht
|
||||
über ihre Position.
|
||||
@@ -45,4 +45,5 @@ Details und Architektur: [../architektur.md](../architektur.md). Zeiten werden a
|
||||
| [#039](039-zugang-zur-laufzeit.md) | Auf dem Telefon führte kein Weg zur Laufzeit | erledigt | v0.22.2 | 1 h | 0 h 30 min |
|
||||
| [#040](040-schlagworte-sichtbar.md) | Schlagworte und Notizen sichtbar machen | erledigt | v0.23.0 | 2 h | 0 h 40 min |
|
||||
| [#041](041-doppelte-hosts.md) | Gleichnamige Hosts erkennen und stilllegen | erledigt | v0.24.0 | 3 h | 0 h 50 min |
|
||||
| | **Summe** | | | **168 h** | **22 h 33 min** |
|
||||
| [#042](042-qdevice-cluster.md) | Cluster-Knoten falsch gelesen bei QDevice | erledigt | v0.24.1 | 1 h | 0 h 20 min |
|
||||
| | **Summe** | | | **169 h** | **22 h 53 min** |
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "proxledger",
|
||||
"version": "0.24.0",
|
||||
"version": "0.24.1",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"dev": "next dev",
|
||||
|
||||
@@ -4,7 +4,7 @@ import { tokenAusHeader } from "@/lib/tokens";
|
||||
import { AgentApiFehler } from "./service";
|
||||
|
||||
/** Version des Agent-Skripts, die das Dashboard ausliefert (siehe #005). */
|
||||
export const AGENT_VERSION = "0.2.1";
|
||||
export const AGENT_VERSION = "0.2.2";
|
||||
|
||||
export function fehlerAntwort(status: number, code: string, nachricht: string, extra?: HeadersInit) {
|
||||
return Response.json({ ok: false, code, fehler: nachricht }, { status, headers: extra });
|
||||
|
||||
@@ -241,6 +241,25 @@ productname: Proxmox "VE" \\ Subscription mit Tab`,
|
||||
expect(report.host.clusterMitglieder).toEqual(["hv-rz5-pve-01", "hv-rz5-pve-02", "hv-rz5-pve-03"]);
|
||||
});
|
||||
|
||||
it("liest die Knoten auch mit QDevice-Spalte richtig", () => {
|
||||
// Mit einem QDevice steht zwischen Votes und Name dessen Zustand. Vorher landeten
|
||||
// „A,V,NMW“ und „NR“ als Knotennamen im Report (#042).
|
||||
befehlErsetzen("pvesubscription", PVE_SUBSCRIPTION);
|
||||
befehlErsetzen(
|
||||
"pvecm",
|
||||
`Membership information
|
||||
----------------------
|
||||
Nodeid Votes Qdevice Name
|
||||
1 1 A,V,NMW hv-pve-01
|
||||
2 1 A,V,NMW hv-pve-02 (local)
|
||||
3 1 NR hv-pve-05
|
||||
0 1 Qdevice (votes 1)`,
|
||||
);
|
||||
|
||||
const report = reportErzeugen() as { host: { clusterMitglieder: string[] } };
|
||||
expect(report.host.clusterMitglieder).toEqual(["hv-pve-01", "hv-pve-02", "hv-pve-05"]);
|
||||
});
|
||||
|
||||
it("meldet eine leere Liste, wenn der Host in keinem Cluster ist", () => {
|
||||
befehlErsetzen("pvesubscription", PVE_SUBSCRIPTION);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user