mirror of
https://github.com/GNS3/gns3-server.git
synced 2026-08-27 12:30:13 +03:00
feat(marker): add optional color field to marker data model
Add a user-chosen hex color (e.g. '#ff5722') to each marker, stored in Link._markers alongside bpf/tag/enabled. The color: - Is serialized with the link (asdict) and persisted in the topology, so it survives project reload and is consistent across devices. - Never reaches uBridge (compute ignores it) — it is purely a Web UI concern. - Can be updated independently of the BPF (color-only changes skip the ubridge round-trip). MarkerCreate schema gains color: Optional[str]; start_marker and update_marker carry it through; REST create/update endpoints pass it. The marker.match WebSocket event stays lean (no color) — the Web UI maps filter -> color from the link state it already holds.
This commit is contained in:
parent
b8f49696cc
commit
3f15ac38f6
@ -454,12 +454,14 @@ async def create_marker(
|
||||
Required privilege: Link.Modify
|
||||
"""
|
||||
|
||||
name = marker_data.name or f"marker-{link.id[:8]}"
|
||||
await link.start_marker(
|
||||
name=marker_data.name or f"marker-{link.id[:8]}",
|
||||
name=name,
|
||||
bpf=marker_data.bpf,
|
||||
tag=marker_data.tag,
|
||||
color=marker_data.color,
|
||||
)
|
||||
return link.markers.get(marker_data.name, {})
|
||||
return link.markers.get(name, {})
|
||||
|
||||
|
||||
@router.delete(
|
||||
@ -499,6 +501,7 @@ async def update_marker(
|
||||
name=marker_name,
|
||||
bpf=marker_data.bpf if marker_data.bpf else None,
|
||||
tag=marker_data.tag,
|
||||
color=marker_data.color,
|
||||
)
|
||||
return link.markers.get(marker_name, {})
|
||||
|
||||
|
||||
@ -335,13 +335,15 @@ class UDPLink(Link):
|
||||
}
|
||||
self._marker_capture_nodes[name] = capture_side
|
||||
|
||||
async def start_marker(self, name, bpf, tag=None):
|
||||
async def start_marker(self, name, bpf, tag=None, color=None):
|
||||
"""
|
||||
Attach a traffic-insight marker to this link.
|
||||
|
||||
:param name: stable filter name — echoed in MARK signals + pcap identity
|
||||
:param bpf: libpcap BPF expression
|
||||
:param tag: optional correlation id
|
||||
:param color: optional hex color for the Web UI (e.g. '#ff5722'); stored
|
||||
with the link and persisted in the topology, never sent to uBridge
|
||||
"""
|
||||
|
||||
if name in self._markers:
|
||||
@ -361,7 +363,7 @@ class UDPLink(Link):
|
||||
data=data,
|
||||
)
|
||||
self._store_capture_node_for_marker(name, marker_side)
|
||||
self._markers[name].update({"bpf": bpf, "tag": tag, "enabled": True})
|
||||
self._markers[name].update({"bpf": bpf, "tag": tag, "enabled": True, "color": color})
|
||||
self._project.emit_notification("link.updated", self.asdict())
|
||||
self._project.dump()
|
||||
|
||||
@ -389,7 +391,7 @@ class UDPLink(Link):
|
||||
self._project.emit_notification("link.updated", self.asdict())
|
||||
self._project.dump()
|
||||
|
||||
async def update_marker(self, name, bpf=None, tag=None, enabled=None):
|
||||
async def update_marker(self, name, bpf=None, tag=None, enabled=None, color=None):
|
||||
"""
|
||||
Update an existing marker. A BPF change requires delete+re-add so the
|
||||
ubridge side flushes the pcap and the new filter takes effect.
|
||||
@ -398,6 +400,7 @@ class UDPLink(Link):
|
||||
:param bpf: new BPF expression (None = keep existing)
|
||||
:param tag: new tag id (None = keep existing)
|
||||
:param enabled: toggle (None = keep existing)
|
||||
:param color: new hex color (None = keep existing)
|
||||
"""
|
||||
|
||||
marker_info = self._markers.get(name)
|
||||
@ -407,11 +410,15 @@ class UDPLink(Link):
|
||||
new_bpf = bpf if bpf is not None else marker_info["bpf"]
|
||||
new_tag = tag if tag is not None else marker_info.get("tag")
|
||||
new_enabled = enabled if enabled is not None else marker_info.get("enabled", True)
|
||||
new_color = color if color is not None else marker_info.get("color")
|
||||
|
||||
if not new_enabled and marker_info.get("enabled", True):
|
||||
# Toggle off: remove from ubridge but keep state.
|
||||
await self.stop_marker(name)
|
||||
self._markers[name] = {**marker_info, "bpf": new_bpf, "tag": new_tag, "enabled": False}
|
||||
self._markers[name] = {
|
||||
**marker_info, "bpf": new_bpf, "tag": new_tag,
|
||||
"enabled": False, "color": new_color,
|
||||
}
|
||||
self._project.emit_notification("link.updated", self.asdict())
|
||||
self._project.dump()
|
||||
return
|
||||
@ -441,7 +448,13 @@ class UDPLink(Link):
|
||||
),
|
||||
data=data,
|
||||
)
|
||||
self._markers[name] = {**marker_info, "bpf": new_bpf, "tag": new_tag, "enabled": True}
|
||||
self._markers[name] = {
|
||||
**marker_info, "bpf": new_bpf, "tag": new_tag,
|
||||
"enabled": True, "color": new_color,
|
||||
}
|
||||
elif new_color != marker_info.get("color"):
|
||||
# Color-only change: no ubridge round-trip, just update state.
|
||||
self._markers[name] = {**marker_info, "color": new_color}
|
||||
|
||||
self._project.emit_notification("link.updated", self.asdict())
|
||||
self._project.dump()
|
||||
|
||||
@ -153,6 +153,10 @@ class MarkerCreate(BaseModel):
|
||||
bpf: str
|
||||
tag: Optional[int] = None
|
||||
link_id: Optional[str] = None
|
||||
color: Optional[str] = Field(
|
||||
None,
|
||||
description="User-chosen hex color for this marker in the Web UI, e.g. '#ff5722'"
|
||||
)
|
||||
|
||||
|
||||
class MarkerDelete(BaseModel):
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user