From 4ca11c913fc3570a1afef1b650554ae66b0a97df Mon Sep 17 00:00:00 2001 From: Blake Harnden <32446120+bharnden@users.noreply.github.com> Date: Tue, 14 Nov 2023 12:46:22 -0800 Subject: [PATCH] daemon/grpc: refactoring session exceptions into alerts, since they are not exclusive for errors alone --- daemon/core/api/grpc/client.py | 2 +- daemon/core/api/grpc/events.py | 34 +++++++++++++-------------- daemon/core/api/grpc/server.py | 11 +++------ daemon/core/api/grpc/wrappers.py | 26 +++++++++----------- daemon/core/emulator/broadcast.py | 4 ++-- daemon/core/emulator/data.py | 11 +++------ daemon/core/emulator/enumerations.py | 4 ++-- daemon/core/emulator/session.py | 25 ++++++++------------ daemon/core/gui/coreclient.py | 10 ++++---- daemon/core/gui/dialogs/alerts.py | 12 +++++----- daemon/core/gui/statusbar.py | 12 +++++----- daemon/proto/core/api/grpc/core.proto | 10 ++++---- daemon/tests/test_grpc.py | 22 ++++++++--------- docs/grpc.md | 2 +- docs/gui.md | 6 ++--- docs/python.md | 6 ++--- 16 files changed, 89 insertions(+), 108 deletions(-) diff --git a/daemon/core/api/grpc/client.py b/daemon/core/api/grpc/client.py index 4e1c85a0..2d8adae4 100644 --- a/daemon/core/api/grpc/client.py +++ b/daemon/core/api/grpc/client.py @@ -338,7 +338,7 @@ def get_session(self, session_id: int) -> wrappers.Session: def alert( self, session_id: int, - level: wrappers.ExceptionLevel, + level: wrappers.AlertLevel, source: str, text: str, node_id: int = None, diff --git a/daemon/core/api/grpc/events.py b/daemon/core/api/grpc/events.py index b81191b3..9029fe98 100644 --- a/daemon/core/api/grpc/events.py +++ b/daemon/core/api/grpc/events.py @@ -5,7 +5,7 @@ from core.api.grpc import core_pb2, grpcutils from core.api.grpc.grpcutils import convert_link_data -from core.emulator.data import EventData, ExceptionData, LinkData, NodeData +from core.emulator.data import AlertData, EventData, LinkData, NodeData from core.emulator.session import Session logger = logging.getLogger(__name__) @@ -61,22 +61,22 @@ def handle_session_event(event_data: EventData) -> core_pb2.Event: return core_pb2.Event(session_event=session_event) -def handle_exception_event(exception_data: ExceptionData) -> core_pb2.Event: +def handle_alert_event(alert_data: AlertData) -> core_pb2.Event: """ - Handle exception event when there is exception event + Handle alert data, when there is an alert event. - :param exception_data: exception data - :return: exception event + :param alert_data: alert data + :return: alert event """ - exception_event = core_pb2.ExceptionEvent( - node_id=exception_data.node, - level=exception_data.level.value, - source=exception_data.source, - date=exception_data.date, - text=exception_data.text, - opaque=exception_data.opaque, + alert_event = core_pb2.AlertEvent( + node_id=alert_data.node, + level=alert_data.level.value, + source=alert_data.source, + date=alert_data.date, + text=alert_data.text, + opaque=alert_data.opaque, ) - return core_pb2.Event(exception_event=exception_event) + return core_pb2.Event(alert_event=alert_event) class EventStreamer: @@ -109,7 +109,7 @@ def add_handlers(self) -> None: if core_pb2.EventType.LINK in self.event_types: self.session.broadcast_manager.add_handler(LinkData, self.queue.put) if core_pb2.EventType.EXCEPTION in self.event_types: - self.session.broadcast_manager.add_handler(ExceptionData, self.queue.put) + self.session.broadcast_manager.add_handler(AlertData, self.queue.put) if core_pb2.EventType.SESSION in self.event_types: self.session.broadcast_manager.add_handler(EventData, self.queue.put) @@ -128,8 +128,8 @@ def process(self) -> Optional[core_pb2.Event]: event = handle_link_event(data) elif isinstance(data, EventData): event = handle_session_event(data) - elif isinstance(data, ExceptionData): - event = handle_exception_event(data) + elif isinstance(data, AlertData): + event = handle_alert_event(data) else: logger.error("unknown event: %s", data) except Empty: @@ -149,6 +149,6 @@ def remove_handlers(self) -> None: if core_pb2.EventType.LINK in self.event_types: self.session.broadcast_manager.remove_handler(LinkData, self.queue.put) if core_pb2.EventType.EXCEPTION in self.event_types: - self.session.broadcast_manager.remove_handler(ExceptionData, self.queue.put) + self.session.broadcast_manager.remove_handler(AlertData, self.queue.put) if core_pb2.EventType.SESSION in self.event_types: self.session.broadcast_manager.remove_handler(EventData, self.queue.put) diff --git a/daemon/core/api/grpc/server.py b/daemon/core/api/grpc/server.py index b882e440..60f183c8 100644 --- a/daemon/core/api/grpc/server.py +++ b/daemon/core/api/grpc/server.py @@ -76,12 +76,7 @@ from core.emane.modelmanager import EmaneModelManager from core.emulator.coreemu import CoreEmu from core.emulator.data import InterfaceData, LinkData, LinkOptions -from core.emulator.enumerations import ( - EventTypes, - ExceptionLevels, - MessageFlags, - NodeTypes, -) +from core.emulator.enumerations import AlertLevels, EventTypes, MessageFlags, NodeTypes from core.emulator.session import NT, Session from core.errors import CoreCommandError, CoreError from core.location.mobility import BasicRangeModel, Ns2ScriptedMobility @@ -440,9 +435,9 @@ def SessionAlert( self, request: core_pb2.SessionAlertRequest, context: ServicerContext ) -> core_pb2.SessionAlertResponse: session = self.get_session(request.session_id, context) - level = ExceptionLevels(request.level) + level = AlertLevels(request.level) node_id = request.node_id if request.node_id else None - session.broadcast_exception(level, request.source, request.text, node_id) + session.broadcast_alert(level, request.source, request.text, node_id) return core_pb2.SessionAlertResponse(result=True) def Events(self, request: core_pb2.EventsRequest, context: ServicerContext) -> None: diff --git a/daemon/core/api/grpc/wrappers.py b/daemon/core/api/grpc/wrappers.py index 5a00ac96..b7c9257c 100644 --- a/daemon/core/api/grpc/wrappers.py +++ b/daemon/core/api/grpc/wrappers.py @@ -65,7 +65,7 @@ class LinkType(Enum): WIRED = 1 -class ExceptionLevel(Enum): +class AlertLevel(Enum): DEFAULT = 0 FATAL = 1 ERROR = 2 @@ -292,23 +292,21 @@ def to_proto(self) -> core_pb2.SessionLocation: @dataclass -class ExceptionEvent: +class AlertEvent: session_id: int node_id: int - level: ExceptionLevel + level: AlertLevel source: str date: str text: str opaque: str @classmethod - def from_proto( - cls, session_id: int, proto: core_pb2.ExceptionEvent - ) -> "ExceptionEvent": - return ExceptionEvent( + def from_proto(cls, session_id: int, proto: core_pb2.AlertEvent) -> "AlertEvent": + return AlertEvent( session_id=session_id, node_id=proto.node_id, - level=ExceptionLevel(proto.level), + level=AlertLevel(proto.level), source=proto.source, date=proto.date, text=proto.text, @@ -922,23 +920,21 @@ class Event: session_event: SessionEvent = None node_event: NodeEvent = None link_event: LinkEvent = None - exception_event: ExceptionEvent = None + alert_event: AlertEvent = None @classmethod def from_proto(cls, proto: core_pb2.Event) -> "Event": source = proto.source if proto.source else None node_event = None link_event = None - exception_event = None + alert_event = None session_event = None if proto.HasField("node_event"): node_event = NodeEvent.from_proto(proto.node_event) elif proto.HasField("link_event"): link_event = LinkEvent.from_proto(proto.link_event) - elif proto.HasField("exception_event"): - exception_event = ExceptionEvent.from_proto( - proto.session_id, proto.exception_event - ) + elif proto.HasField("alert_event"): + alert_event = AlertEvent.from_proto(proto.session_id, proto.alert_event) elif proto.HasField("session_event"): session_event = SessionEvent.from_proto(proto.session_event) return Event( @@ -946,7 +942,7 @@ def from_proto(cls, proto: core_pb2.Event) -> "Event": source=source, node_event=node_event, link_event=link_event, - exception_event=exception_event, + alert_event=alert_event, session_event=session_event, ) diff --git a/daemon/core/emulator/broadcast.py b/daemon/core/emulator/broadcast.py index bbc75fff..666a9521 100644 --- a/daemon/core/emulator/broadcast.py +++ b/daemon/core/emulator/broadcast.py @@ -1,10 +1,10 @@ from collections.abc import Callable from typing import TypeVar, Union -from core.emulator.data import EventData, ExceptionData, LinkData, NodeData +from core.emulator.data import AlertData, EventData, LinkData, NodeData from core.errors import CoreError -T = TypeVar("T", bound=Union[EventData, ExceptionData, NodeData, LinkData]) +T = TypeVar("T", bound=Union[EventData, AlertData, NodeData, LinkData]) class BroadcastManager: diff --git a/daemon/core/emulator/data.py b/daemon/core/emulator/data.py index 5cc6d75e..525751ed 100644 --- a/daemon/core/emulator/data.py +++ b/daemon/core/emulator/data.py @@ -7,12 +7,7 @@ import netaddr from core import utils -from core.emulator.enumerations import ( - EventTypes, - ExceptionLevels, - LinkTypes, - MessageFlags, -) +from core.emulator.enumerations import AlertLevels, EventTypes, LinkTypes, MessageFlags if TYPE_CHECKING: from core.nodes.base import CoreNode, NodeBase @@ -29,10 +24,10 @@ class EventData: @dataclass -class ExceptionData: +class AlertData: node: int = None session: int = None - level: ExceptionLevels = None + level: AlertLevels = None source: str = None date: str = None text: str = None diff --git a/daemon/core/emulator/enumerations.py b/daemon/core/emulator/enumerations.py index 2102686c..2c431e76 100644 --- a/daemon/core/emulator/enumerations.py +++ b/daemon/core/emulator/enumerations.py @@ -104,9 +104,9 @@ def already_collected(self) -> bool: return self.value >= self.DATACOLLECT_STATE.value -class ExceptionLevels(Enum): +class AlertLevels(Enum): """ - Exception levels. + Alert levels. """ NONE = 0 diff --git a/daemon/core/emulator/session.py b/daemon/core/emulator/session.py index 2986f0cd..c1ad28ae 100644 --- a/daemon/core/emulator/session.py +++ b/daemon/core/emulator/session.py @@ -21,20 +21,15 @@ from core.emulator.broadcast import BroadcastManager from core.emulator.controlnets import ControlNetManager from core.emulator.data import ( + AlertData, EventData, - ExceptionData, InterfaceData, LinkData, LinkOptions, NodeData, ) from core.emulator.distributed import DistributedController -from core.emulator.enumerations import ( - EventTypes, - ExceptionLevels, - MessageFlags, - NodeTypes, -) +from core.emulator.enumerations import AlertLevels, EventTypes, MessageFlags, NodeTypes from core.emulator.hooks import HookManager from core.emulator.links import CoreLink, LinkManager from core.emulator.sessionconfig import SessionConfig @@ -646,19 +641,19 @@ def broadcast_event( ) self.broadcast_manager.send(event_data) - def broadcast_exception( - self, level: ExceptionLevels, source: str, text: str, node_id: int = None + def broadcast_alert( + self, level: AlertLevels, source: str, text: str, node_id: int = None ) -> None: """ - Generate and broadcast an exception event. + Generate and broadcast an alert event. - :param level: exception level + :param level: alert level :param source: source name - :param text: exception message - :param node_id: node related to exception, defaults to None + :param text: alert message + :param node_id: node related to alert, defaults to None :return: nothing """ - exception_data = ExceptionData( + alert_data = AlertData( node=node_id, session=self.id, level=level, @@ -666,7 +661,7 @@ def broadcast_exception( date=time.ctime(), text=text, ) - self.broadcast_manager.send(exception_data) + self.broadcast_manager.send(alert_data) def broadcast_node( self, diff --git a/daemon/core/gui/coreclient.py b/daemon/core/gui/coreclient.py index 326acde2..2924bd64 100644 --- a/daemon/core/gui/coreclient.py +++ b/daemon/core/gui/coreclient.py @@ -15,10 +15,10 @@ from core.api.grpc import client, core_pb2 from core.api.grpc.wrappers import ( + AlertEvent, ConfigOption, EmaneModelConfig, Event, - ExceptionEvent, Link, LinkEvent, LinkType, @@ -202,8 +202,8 @@ def handle_events(self, event: Event) -> None: logger.warning("unknown session event: %s", session_event) elif event.node_event: self.app.after(0, self.handle_node_event, event.node_event) - elif event.exception_event: - self.handle_exception_event(event.exception_event) + elif event.alert_event: + self.handle_alert_event(event.alert_event) else: logger.info("unhandled event: %s", event) @@ -308,8 +308,8 @@ def handle_throughputs(self, event: ThroughputsEvent) -> None: def handle_cpu_event(self, event: core_pb2.CpuUsageEvent) -> None: self.app.after(0, self.app.statusbar.set_cpu, event.usage) - def handle_exception_event(self, event: ExceptionEvent) -> None: - logger.info("exception event: %s", event) + def handle_alert_event(self, event: AlertEvent) -> None: + logger.info("alert event: %s", event) self.app.statusbar.add_alert(event) def update_session_title(self) -> None: diff --git a/daemon/core/gui/dialogs/alerts.py b/daemon/core/gui/dialogs/alerts.py index b13f0797..20cdbc60 100644 --- a/daemon/core/gui/dialogs/alerts.py +++ b/daemon/core/gui/dialogs/alerts.py @@ -5,7 +5,7 @@ from tkinter import ttk from typing import TYPE_CHECKING, Optional -from core.api.grpc.wrappers import ExceptionEvent, ExceptionLevel +from core.api.grpc.wrappers import AlertEvent, AlertLevel from core.gui.dialogs.dialog import Dialog from core.gui.themes import PADX, PADY from core.gui.widgets import CodeText @@ -19,7 +19,7 @@ def __init__(self, app: "Application") -> None: super().__init__(app, "Alerts") self.tree: Optional[ttk.Treeview] = None self.codetext: Optional[CodeText] = None - self.alarm_map: dict[int, ExceptionEvent] = {} + self.alarm_map: dict[int, AlertEvent] = {} self.draw() def draw(self) -> None: @@ -67,13 +67,13 @@ def draw(self) -> None: ) self.alarm_map[insert_id] = exception - error_name = ExceptionLevel.ERROR.name + error_name = AlertLevel.ERROR.name self.tree.tag_configure(error_name, background="#ff6666") - fatal_name = ExceptionLevel.FATAL.name + fatal_name = AlertLevel.FATAL.name self.tree.tag_configure(fatal_name, background="#d9d9d9") - warning_name = ExceptionLevel.WARNING.name + warning_name = AlertLevel.WARNING.name self.tree.tag_configure(warning_name, background="#ffff99") - notice_name = ExceptionLevel.NOTICE.name + notice_name = AlertLevel.NOTICE.name self.tree.tag_configure(notice_name, background="#85e085") yscrollbar = ttk.Scrollbar(frame, orient="vertical", command=self.tree.yview) diff --git a/daemon/core/gui/statusbar.py b/daemon/core/gui/statusbar.py index a4967cd6..e11f2902 100644 --- a/daemon/core/gui/statusbar.py +++ b/daemon/core/gui/statusbar.py @@ -5,7 +5,7 @@ from tkinter import ttk from typing import TYPE_CHECKING, Optional -from core.api.grpc.wrappers import ExceptionEvent, ExceptionLevel +from core.api.grpc.wrappers import AlertEvent, AlertLevel from core.gui.dialogs.alerts import AlertsDialog from core.gui.themes import Styles @@ -24,7 +24,7 @@ def __init__(self, master: tk.Widget, app: "Application") -> None: self.alerts_button: Optional[ttk.Button] = None self.alert_style = Styles.no_alert self.running: bool = False - self.core_alarms: list[ExceptionEvent] = [] + self.core_alarms: list[AlertEvent] = [] self.draw() def draw(self) -> None: @@ -66,17 +66,17 @@ def set_cpu(self, usage: float) -> None: def set_zoom(self, zoom: float) -> None: self.zoom.config(text=f"ZOOM {zoom * 100:.0f}%") - def add_alert(self, event: ExceptionEvent) -> None: + def add_alert(self, event: AlertEvent) -> None: self.core_alarms.append(event) level = event.level self._set_alert_style(level) label = f"Alerts ({len(self.core_alarms)})" self.alerts_button.config(text=label, style=self.alert_style) - def _set_alert_style(self, level: ExceptionLevel) -> None: - if level in [ExceptionLevel.FATAL, ExceptionLevel.ERROR]: + def _set_alert_style(self, level: AlertLevel) -> None: + if level in [AlertLevel.FATAL, AlertLevel.ERROR]: self.alert_style = Styles.red_alert - elif level == ExceptionLevel.WARNING and self.alert_style != Styles.red_alert: + elif level == AlertLevel.WARNING and self.alert_style != Styles.red_alert: self.alert_style = Styles.yellow_alert elif self.alert_style == Styles.no_alert: self.alert_style = Styles.green_alert diff --git a/daemon/proto/core/api/grpc/core.proto b/daemon/proto/core/api/grpc/core.proto index e68d3f10..b3a89d12 100644 --- a/daemon/proto/core/api/grpc/core.proto +++ b/daemon/proto/core/api/grpc/core.proto @@ -199,7 +199,7 @@ message GetSessionResponse { message SessionAlertRequest { int32 session_id = 1; - ExceptionLevel.Enum level = 2; + AlertLevel.Enum level = 2; string source = 3; string text = 4; int32 node_id = 5; @@ -248,7 +248,7 @@ message Event { SessionEvent session_event = 1; NodeEvent node_event = 2; LinkEvent link_event = 3; - ExceptionEvent exception_event = 5; + AlertEvent alert_event = 5; } int32 session_id = 7; string source = 8; @@ -272,9 +272,9 @@ message SessionEvent { float time = 5; } -message ExceptionEvent { +message AlertEvent { int32 node_id = 1; - ExceptionLevel.Enum level = 2; + AlertLevel.Enum level = 2; string source = 3; string date = 4; string text = 5; @@ -524,7 +524,7 @@ message ConfigOptionType { } } -message ExceptionLevel { +message AlertLevel { enum Enum { DEFAULT = 0; FATAL = 1; diff --git a/daemon/tests/test_grpc.py b/daemon/tests/test_grpc.py index 008a693c..40a2751e 100644 --- a/daemon/tests/test_grpc.py +++ b/daemon/tests/test_grpc.py @@ -34,7 +34,7 @@ from core.emane.models.ieee80211abg import EmaneIeee80211abgModel from core.emane.nodes import EmaneNet from core.emulator.data import IpPrefixes, NodeData -from core.emulator.enumerations import EventTypes, ExceptionLevels, MessageFlags +from core.emulator.enumerations import AlertLevels, EventTypes, MessageFlags from core.errors import CoreError from core.location.mobility import BasicRangeModel, Ns2ScriptedMobility from core.nodes.base import CoreNode @@ -723,31 +723,31 @@ def handle_event(event: Event) -> None: # then queue.get(timeout=5) - def test_exception_events(self, grpc_server: CoreGrpcServer): + def test_alert_events(self, grpc_server: CoreGrpcServer): # given client = CoreGrpcClient() session = grpc_server.coreemu.create_session() queue = Queue() - exception_level = ExceptionLevels.FATAL + alert_level = AlertLevels.FATAL source = "test" node_id = None - text = "exception message" + text = "alert message" def handle_event(event: Event) -> None: assert event.session_id == session.id - assert event.exception_event is not None - exception_event = event.exception_event - assert exception_event.level.value == exception_level.value - assert exception_event.node_id == 0 - assert exception_event.source == source - assert exception_event.text == text + assert event.alert_event is not None + alert_event = event.alert_event + assert alert_event.level.value == alert_level.value + assert alert_event.node_id == 0 + assert alert_event.source == source + assert alert_event.text == text queue.put(event) # then with client.context_connect(): client.events(session.id, handle_event) time.sleep(0.1) - session.broadcast_exception(exception_level, source, text, node_id) + session.broadcast_alert(alert_level, source, text, node_id) # then queue.get(timeout=5) diff --git a/docs/grpc.md b/docs/grpc.md index de8c1a93..bfb025d6 100644 --- a/docs/grpc.md +++ b/docs/grpc.md @@ -97,7 +97,7 @@ Event types: * node - events for node movements and icon changes * link - events for link configuration changes and wireless link add/delete * config - configuration events when legacy gui joins a session -* exception - alert/error events +* alert - alert events * file - file events when the legacy gui joins a session ```python diff --git a/docs/gui.md b/docs/gui.md index 93942ed6..b86dab81 100644 --- a/docs/gui.md +++ b/docs/gui.md @@ -460,11 +460,11 @@ create a bridge or namespace, or the failure to launch EMANE processes for an EMANE-based network. Clicking on an alert displays details for that -exceptio. The exception source is a text string -to help trace where the exception occurred; "service:UserDefined" for example, +alert. The alert source is a text string +to help trace where the alert occurred; "service:UserDefined" for example, would appear for a failed validation command with the UserDefined service. -A button is available at the bottom of the dialog for clearing the exception +A button is available at the bottom of the dialog for clearing the alert list. ## Customizing your Topology's Look diff --git a/docs/python.md b/docs/python.md index c4b0123f..200bd952 100644 --- a/docs/python.md +++ b/docs/python.md @@ -74,11 +74,11 @@ Event types: * node - events for node movements and icon changes * link - events for link configuration changes and wireless link add/delete * config - configuration events when legacy gui joins a session -* exception - alert/error events +* alert - alert events * file - file events when the legacy gui joins a session ```python -from core.emulator.data import EventData, ExceptionData, LinkData, NodeData +from core.emulator.data import EventData, AlertData, LinkData, NodeData def event_listener(event): @@ -90,7 +90,7 @@ def event_listener(event): session.broadcast_manager.add_handler(NodeData, event_listener) session.broadcast_manager.add_handler(LinkData, event_listener) session.broadcast_manager.add_handler(EventData, event_listener) -session.broadcast_manager.add_handler(ExceptionData, event_listener) +session.broadcast_manager.add_handler(AlertData, event_listener) ``` ### Configuring Links