ether3 ist Trunk, ap1 laeuft am Sideboard -- als offene Transaktion
Der Port trug keines der sieben VLANs, deshalb war ap1 nach dem Umpatchen tot. Sieben set-Zeilen ueber gc-manual-plan.py, und der erste Deploy zeigte gleich zwei bekannte Fallen von ihrer praktischen Seite: Der Plan meldete Failed, und der Teilzustand war real -- sechs VLANs hatten ether3 bekommen, VLAN 40 nicht. Der Grund ist sauber: ether3 war dort UNTAGGED-Mitglied, und ein Port kann in derselben VLAN nicht zugleich tagged und untagged sein. Nachtrag deployt (untagged=ether2,ether4,ether5), diesmal mit --assert, und der hat den Effekt am Geraet nachgewiesen statt dem Job zu glauben. Ergebnis: ap1 antwortet in 447 us und traegt wieder 12 Clients (ap2: 16). Die Aenderung bleibt bewusst UNCOMMITTED: sie steht am Geraet, nicht in der SoT, und die Compliance meldet den Drift auf bridge-vlan. Genau so soll es sein, solange offen ist, ob ap1 am Sideboard bleibt. Faellt die Entscheidung, wird entweder das Template nachgezogen (commit) oder aus dem Snapshot zurueckgebaut. Ein Bugfix im neuen Werkzeug faellt dabei gleich mit an: der Feature-Name steht bei depth=1 nicht ausgeschrieben in rule.feature, dort kommt nur eine URL. Verwendbar ist rule.display. Ohne das meldete status JEDEN Drift als "ausserhalb des Scopes" -- also ausgerechnet die Zuordnung falsch, fuer die es gebaut wurde. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,4 @@
|
|||||||
|
# Nachtrag zum ether3-Trunk: VLAN 40 hatte ether3 als UNTAGGED-Mitglied.
|
||||||
|
# Ein Port kann in derselben VLAN nicht zugleich tagged und untagged sein — deshalb ist
|
||||||
|
# genau diese eine Zeile im ersten Deploy gescheitert, waehrend die sechs anderen liefen.
|
||||||
|
/interface bridge vlan set [find where vlan-ids=40 and !dynamic] tagged=ether1,ether3,ether8,ether13,ether15 untagged=ether2,ether4,ether5
|
||||||
@@ -92,12 +92,16 @@ def compliance(device):
|
|||||||
"""Feature -> compliant? fuer ein Geraet."""
|
"""Feature -> compliant? fuer ein Geraet."""
|
||||||
d = nb_get("/api/plugins/golden-config/config-compliance/?limit=200&depth=1"
|
d = nb_get("/api/plugins/golden-config/config-compliance/?limit=200&depth=1"
|
||||||
"&device=%s" % device)
|
"&device=%s" % device)
|
||||||
|
# 🔴 Der Feature-Name steht bei depth=1 NICHT ausgeschrieben in rule.feature — dort
|
||||||
|
# kommt nur eine URL. Verwendbar ist rule.display ("RouterOS - bridge-vlan");
|
||||||
|
# der Teil nach dem letzten " - " ist der Regelname. Ohne das landete jeder Drift
|
||||||
|
# als "ausserhalb des Scopes" im Bericht, obwohl er genau der Scope war.
|
||||||
out = {}
|
out = {}
|
||||||
for r in d["results"]:
|
for r in d["results"]:
|
||||||
feat = r.get("rule") or {}
|
rule = r.get("rule") or {}
|
||||||
feat = (feat.get("feature") or {}) if isinstance(feat, dict) else {}
|
anzeige = rule.get("display") if isinstance(rule, dict) else str(rule)
|
||||||
name = feat.get("name") or feat.get("display") or r.get("rule")
|
name = (anzeige or "").split(" - ")[-1].strip()
|
||||||
out[str(name)] = bool(r.get("compliance"))
|
out[name] = bool(r.get("compliance"))
|
||||||
return out
|
return out
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user