diff --git a/CHANGELOG.md b/CHANGELOG.md index 87c71f1..2710f2a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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 diff --git a/DEVLOG.md b/DEVLOG.md index 74592b6..b229db1 100644 --- a/DEVLOG.md +++ b/DEVLOG.md @@ -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) diff --git a/agent/proxledger-agent.sh b/agent/proxledger-agent.sh index 482ba7f..6d6ef5e 100755 --- a/agent/proxledger-agent.sh +++ b/agent/proxledger-agent.sh @@ -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 } diff --git a/docs/issues/042-qdevice-cluster.md b/docs/issues/042-qdevice-cluster.md new file mode 100644 index 0000000..a0179e5 --- /dev/null +++ b/docs/issues/042-qdevice-cluster.md @@ -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. diff --git a/docs/issues/README.md b/docs/issues/README.md index 18de0b4..37acc06 100644 --- a/docs/issues/README.md +++ b/docs/issues/README.md @@ -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** | diff --git a/package.json b/package.json index 74806be..c2f2db5 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "proxledger", - "version": "0.24.0", + "version": "0.24.1", "private": true, "scripts": { "dev": "next dev", diff --git a/src/server/agent/http.ts b/src/server/agent/http.ts index 33a415e..d9cca5e 100644 --- a/src/server/agent/http.ts +++ b/src/server/agent/http.ts @@ -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 }); diff --git a/tests/agent-skript.test.ts b/tests/agent-skript.test.ts index a55c0ad..f450006 100644 --- a/tests/agent-skript.test.ts +++ b/tests/agent-skript.test.ts @@ -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);