Compare commits

...
2 Commits
Author SHA1 Message Date
florian.wilde f076f49631 Merge branch 'phase/042-qdevice'
Prüfung / pruefung (push) Canceled after 0s
2026-10-03 18:11:38 +02:00
florian.wildeandClaude Opus 5 8e5bf74a30 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>
2026-10-03 18:11:38 +02:00
8 changed files with 92 additions and 7 deletions
+6
View File
@@ -17,6 +17,12 @@ und dieses Projekt folgt [Semantic Versioning](https://semver.org/lang/de/).
### Sicherheit ### 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 ## [0.24.0] – 2026-10-03
### Hinzugefügt ### Hinzugefügt
+6 -2
View File
@@ -2,7 +2,7 @@
## Zeitübersicht ## Zeitübersicht
**Gesamt:** 22 h 33 min **Gesamt:** 22 h 53 min
| Issue | Zeit | | Issue | Zeit |
|---|---| |---|---|
@@ -47,6 +47,7 @@
| #039 Zugang zur Laufzeit | 0 h 30 min | | #039 Zugang zur Laufzeit | 0 h 30 min |
| #040 Schlagworte sichtbar | 0 h 40 min | | #040 Schlagworte sichtbar | 0 h 40 min |
| #041 Doppelte Hosts | 0 h 50 min | | #041 Doppelte Hosts | 0 h 50 min |
| #042 QDevice im Cluster | 0 h 20 min |
| Meilenstein | Zeit | | Meilenstein | Zeit |
|---|---| |---|---|
@@ -69,7 +70,7 @@
## 2026-09-17 · Sitzung 1 · 19:36–laufend ## 2026-09-17 · Sitzung 1 · 19:36–laufend
**Issue:** #001–#007 (Meilensteine v0.1.0 bis v0.4.0) **Issue:** #001–#007 (Meilensteine v0.1.0 bis v0.4.0)
**Version:** 0.24.0 **Version:** 0.24.1
### Erledigt ### Erledigt
- Auftrag gelesen, Rückfragen gestellt - 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 - 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 - 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 ### Nächster Schritt
- #016 Benutzerhandbuch mit Screenshots, danach #017 Favicons und #019 CI-Pipeline - #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) - Für 1.0.0 fehlt noch: PMG (kein Host verfügbar) und der Fall „aktive Subscription auf PBS“ (#023)
+17 -2
View File
@@ -12,7 +12,7 @@
set -o nounset set -o nounset
set -o pipefail set -o pipefail
AGENT_VERSION="0.2.1" AGENT_VERSION="0.2.2"
CONFIG_DATEI="${PROXLEDGER_CONFIG:-/etc/proxledger/agent.conf}" CONFIG_DATEI="${PROXLEDGER_CONFIG:-/etc/proxledger/agent.conf}"
SPOOL_VERZEICHNIS="${PROXLEDGER_SPOOL:-/var/lib/proxledger/spool}" SPOOL_VERZEICHNIS="${PROXLEDGER_SPOOL:-/var/lib/proxledger/spool}"
SPOOL_MAXIMUM=30 SPOOL_MAXIMUM=30
@@ -175,9 +175,24 @@ cluster_name() {
# Namen aller Cluster-Mitglieder laut corosync. Auch Knoten ohne Agent stehen hier – # Namen aller Cluster-Mitglieder laut corosync. Auch Knoten ohne Agent stehen hier –
# daraus erkennt das Dashboard vergessene Knoten (#022). # 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() { cluster_mitglieder() {
if command -v pvecm >/dev/null 2>&1; then 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 fi
} }
+40
View File
@@ -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.
+2 -1
View File
@@ -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 | | [#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 | | [#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 | | [#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
View File
@@ -1,6 +1,6 @@
{ {
"name": "proxledger", "name": "proxledger",
"version": "0.24.0", "version": "0.24.1",
"private": true, "private": true,
"scripts": { "scripts": {
"dev": "next dev", "dev": "next dev",
+1 -1
View File
@@ -4,7 +4,7 @@ import { tokenAusHeader } from "@/lib/tokens";
import { AgentApiFehler } from "./service"; import { AgentApiFehler } from "./service";
/** Version des Agent-Skripts, die das Dashboard ausliefert (siehe #005). */ /** 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) { export function fehlerAntwort(status: number, code: string, nachricht: string, extra?: HeadersInit) {
return Response.json({ ok: false, code, fehler: nachricht }, { status, headers: extra }); return Response.json({ ok: false, code, fehler: nachricht }, { status, headers: extra });
+19
View File
@@ -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"]); 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", () => { it("meldet eine leere Liste, wenn der Host in keinem Cluster ist", () => {
befehlErsetzen("pvesubscription", PVE_SUBSCRIPTION); befehlErsetzen("pvesubscription", PVE_SUBSCRIPTION);