mirror of
https://github.com/hansjone/netx.git
synced 2026-10-15 04:53:20 +08:00
Optimize topology canvas per the 2026-10-12 plan.
Save path: one atomic POST /views/{id}/commit (edges, ports, styles, node
add/remove, positions) replaces the multi-request save. Edge styles and
manual-edge port edits now go through dirty/undo/save instead of writing
immediately; non-manual edge ports are read-only.
Data safety: UI saves no longer clear MCP node locks or freeze the device
name into the placement label (label_override + omit-means-keep semantics,
also applied to the MCP positions tool). Adding NEs/neighbors with unsaved
edits now saves first instead of silently dropping them. Positions no longer
bypass membership caps, except persisting synthesized child-region icons.
Fixes found in acceptance: nodes added in the same commit kept (40,40)
under autoflush=False; edits on edges deleted in the same save 404'd the
whole save; box-selection drags and arrow-key moves were not marked dirty;
large canvases far from the origin opened blank and locate did nothing
because fitView waits for measurement that onlyRenderVisibleElements never
does (now fitBounds from known geometry).
Also: batch N+1 lookups in graph/positions, deterministic truncation,
outside-peer scan excludes internal edges, split TopologyPage into hooks,
fix flaky UME/LLDP port test, add scripts/topology_clear_frozen_labels.py.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
60a0ea6021
commit
f301544b99
40 changed files with 5587 additions and 1916 deletions
79
scripts/topology_clear_frozen_labels.py
Normal file
79
scripts/topology_clear_frozen_labels.py
Normal file
|
|
@ -0,0 +1,79 @@
|
|||
"""Clear view-node labels that merely freeze the current fabric name/ip.
|
||||
|
||||
Default is dry-run. Pass --apply to write.
|
||||
|
||||
A placement label is considered frozen when it equals the fabric node's current
|
||||
name or IP (case-insensitive, stripped). Clearing it restores follow-device-name
|
||||
behavior on the next graph read.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
sys.path.insert(0, str(Path(__file__).resolve().parents[1]))
|
||||
|
||||
from sqlalchemy import or_
|
||||
|
||||
from netx_api.db import SessionLocal
|
||||
from netx_api.models import TopoFabricNode, TopoViewNode
|
||||
|
||||
|
||||
def _norm(s: str | None) -> str:
|
||||
return str(s or "").strip().casefold()
|
||||
|
||||
|
||||
def clear_frozen_labels(db, *, apply: bool) -> tuple[int, int]:
|
||||
"""Return (scanned_nonempty_labels, frozen_cleared). Caller commits/rolls back."""
|
||||
rows = (
|
||||
db.query(TopoViewNode, TopoFabricNode)
|
||||
.outerjoin(TopoFabricNode, TopoFabricNode.id == TopoViewNode.fabric_node_id)
|
||||
.filter(TopoViewNode.label != "")
|
||||
.filter(or_(TopoViewNode.label.isnot(None)))
|
||||
.all()
|
||||
)
|
||||
scanned = 0
|
||||
cleared = 0
|
||||
for vn, fn in rows:
|
||||
scanned += 1
|
||||
label = _norm(vn.label)
|
||||
if not label or fn is None:
|
||||
continue
|
||||
if label not in {_norm(fn.name), _norm(fn.ip)}:
|
||||
continue
|
||||
cleared += 1
|
||||
if apply:
|
||||
vn.label = ""
|
||||
return scanned, cleared
|
||||
|
||||
|
||||
def main(argv: list[str] | None = None) -> int:
|
||||
parser = argparse.ArgumentParser(description=__doc__)
|
||||
parser.add_argument(
|
||||
"--apply",
|
||||
action="store_true",
|
||||
help="Write changes (default: dry-run only)",
|
||||
)
|
||||
args = parser.parse_args(argv)
|
||||
|
||||
db = SessionLocal()
|
||||
try:
|
||||
scanned, cleared = clear_frozen_labels(db, apply=args.apply)
|
||||
if args.apply:
|
||||
db.commit()
|
||||
else:
|
||||
db.rollback()
|
||||
mode = "apply" if args.apply else "dry-run"
|
||||
print(f"mode={mode} scanned={scanned} frozen_labels={cleared}")
|
||||
return 0
|
||||
except Exception:
|
||||
db.rollback()
|
||||
raise
|
||||
finally:
|
||||
db.close()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
raise SystemExit(main())
|
||||
Loading…
Add table
Add a link
Reference in a new issue