From 140fe3c7fe405933dbc1a6554f3960adf0290c4f Mon Sep 17 00:00:00 2001 From: Jeff Ahrenholz Date: Thu, 31 Oct 2019 13:11:09 -0700 Subject: [PATCH 1/4] remove sudo from init script, since it is already running as root --- scripts/core-daemon.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/core-daemon.in b/scripts/core-daemon.in index 263d980d..0a988f0f 100644 --- a/scripts/core-daemon.in +++ b/scripts/core-daemon.in @@ -35,7 +35,7 @@ corestart() { echo "$NAME already started" else echo "starting $NAME" - sudo $CMD 2>&1 >> "$LOG" & + $CMD 2>&1 >> "$LOG" & fi echo $! > "$PIDFILE" From 583df848683a9096f6f17de4685ac7a81328fde9 Mon Sep 17 00:00:00 2001 From: apwiggins Date: Fri, 6 Dec 2019 08:31:37 -0400 Subject: [PATCH 2/4] Update services.md Added FRR features as of version 7.2. Updated FRR installation notes for Ubuntu 19.10 and later which install from native repositories. Added new Fedora 31 installation note for native repository install. --- docs/services.md | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/docs/services.md b/docs/services.md index ec38c462..f2a1a38a 100644 --- a/docs/services.md +++ b/docs/services.md @@ -195,24 +195,29 @@ In order to be able to do use the Bird Internet Routing Protocol, you must modif ### FRRouting FRRouting is a routing software package that provides TCP/IP based routing services with routing protocols support such as BGP, RIP, OSPF, IS-IS and more. FRR also supports special BGP Route Reflector and Route Server behavior. In addition to traditional IPv4 routing protocols, FRR also supports IPv6 routing protocols. With an SNMP daemon that supports the AgentX protocol, FRR provides routing protocol MIB read-only access (SNMP Support). -FRR currently supports the following protocols: -* BGP +FRR (as of v7.2) currently supports the following protocols: +* BGPv4 * OSPFv2 * OSPFv3 -* RIPv1 -* RIPv2 -* RIPng +* RIPv1/v2/ng * IS-IS -* PIM-SM/MSDP +* PIM-SM/MSDP/BSM(AutoRP) * LDP * BFD * Babel * PBR * OpenFabric +* VRRPv2/v3 * EIGRP (alpha) * NHRP (alpha) #### FRRouting Package Install +Ubuntu 19.10 and later +```shell +sudo apt update && sudo apt install frr +``` + +Ubuntu 16.04 and Ubuntu 18.04 ```shell sudo apt install curl curl -s https://deb.frrouting.org/frr/keys.asc | sudo apt-key add - @@ -220,6 +225,10 @@ FRRVER="frr-stable" echo deb https://deb.frrouting.org/frr $(lsb_release -s -c) $FRRVER | sudo tee -a /etc/apt/sources.list.d/frr.list sudo apt update && sudo apt install frr frr-pythontools ``` +Fedora 31 +```shell +sudo dnf update && sudo dnf install frr +``` #### FRRouting Source Code Install Building FRR from source is the best way to ensure you have the latest features and bug fixes. Details for each supported platform, including dependency package listings, permissions, and other gotchas, are in the developer’s documentation. From d78ef86cef6a6e9b5f6a35fe20bf4e0943b54628 Mon Sep 17 00:00:00 2001 From: Blake Harnden <32446120+bharnden@users.noreply.github.com> Date: Mon, 9 Dec 2019 22:50:26 -0800 Subject: [PATCH 3/4] added grpc error display and updated grpc calls to catch and display grpc exceptions --- coretk/coretk/coreclient.py | 291 ++++++++++-------- coretk/coretk/dialogs/emaneconfig.py | 13 +- coretk/coretk/dialogs/mobilityconfig.py | 9 +- coretk/coretk/dialogs/mobilityplayer.py | 30 +- coretk/coretk/dialogs/serviceconfiguration.py | 132 ++++---- coretk/coretk/dialogs/sessionoptions.py | 28 +- coretk/coretk/dialogs/sessions.py | 17 +- coretk/coretk/dialogs/wlanconfig.py | 9 +- coretk/coretk/errors.py | 8 + coretk/coretk/graph/node.py | 10 +- coretk/coretk/menuaction.py | 10 +- 11 files changed, 329 insertions(+), 228 deletions(-) create mode 100644 coretk/coretk/errors.py diff --git a/coretk/coretk/coreclient.py b/coretk/coretk/coreclient.py index 376c739c..1b1a30da 100644 --- a/coretk/coretk/coreclient.py +++ b/coretk/coretk/coreclient.py @@ -6,7 +6,6 @@ import logging import os import time from pathlib import Path -from tkinter import messagebox import grpc @@ -14,6 +13,7 @@ from core.api.grpc import client, core_pb2 from coretk import appconfig from coretk.dialogs.mobilityplayer import MobilityPlayer from coretk.dialogs.sessions import SessionsDialog +from coretk.errors import show_grpc_error from coretk.graph import tags from coretk.graph.shape import AnnotationData, Shape from coretk.graph.shapeutils import ShapeType @@ -206,85 +206,92 @@ class CoreClient: self.reset() # get session data - response = self.client.get_session(self.session_id) - session = response.session - self.state = session.state - self.client.events(self.session_id, self.handle_events) - self.client.throughputs(self.handle_throughputs) + try: + response = self.client.get_session(self.session_id) + session = response.session + self.state = session.state + self.client.events(self.session_id, self.handle_events) + self.client.throughputs(self.handle_throughputs) - # get location - if query_location: - response = self.client.get_session_location(self.session_id) - self.location = response.location + # get location + if query_location: + response = self.client.get_session_location(self.session_id) + self.location = response.location - # get emane models - response = self.client.get_emane_models(self.session_id) - self.emane_models = response.models + # get emane models + response = self.client.get_emane_models(self.session_id) + self.emane_models = response.models - # get hooks - response = self.client.get_hooks(self.session_id) - for hook in response.hooks: - self.hooks[hook.file] = hook + # get hooks + response = self.client.get_hooks(self.session_id) + for hook in response.hooks: + self.hooks[hook.file] = hook - # get mobility configs - response = self.client.get_mobility_configs(self.session_id) - for node_id in response.configs: - node_config = response.configs[node_id].config - self.mobility_configs[node_id] = node_config + # get mobility configs + response = self.client.get_mobility_configs(self.session_id) + for node_id in response.configs: + node_config = response.configs[node_id].config + self.mobility_configs[node_id] = node_config - # get emane config - response = self.client.get_emane_config(self.session_id) - self.emane_config = response.config + # get emane config + response = self.client.get_emane_config(self.session_id) + self.emane_config = response.config - # get emane model config - response = self.client.get_emane_model_configs(self.session_id) - for _id in response.configs: - config = response.configs[_id] - interface = None - node_id = _id - if _id >= 1000: - interface = _id % 1000 - node_id = int(_id / 1000) - self.set_emane_model_config(node_id, config.model, config.config, interface) + # get emane model config + response = self.client.get_emane_model_configs(self.session_id) + for _id in response.configs: + config = response.configs[_id] + interface = None + node_id = _id + if _id >= 1000: + interface = _id % 1000 + node_id = int(_id / 1000) + self.set_emane_model_config( + node_id, config.model, config.config, interface + ) - # save and retrieve data, needed for session nodes - for node in session.nodes: - # get node service config and file config - self.created_nodes.add(node.id) + # save and retrieve data, needed for session nodes + for node in session.nodes: + # get node service config and file config + self.created_nodes.add(node.id) - # get wlan configs for wlan nodes - if node.type == core_pb2.NodeType.WIRELESS_LAN: - response = self.client.get_wlan_config(self.session_id, node.id) - self.wlan_configs[node.id] = response.config - # retrieve service configurations data for default nodes - elif node.type == core_pb2.NodeType.DEFAULT: - for service in node.services: - response = self.client.get_node_service( - self.session_id, node.id, service - ) - if node.id not in self.service_configs: - self.service_configs[node.id] = {} - self.service_configs[node.id][service] = response.service - for file in response.service.configs: - response = self.client.get_node_service_file( - self.session_id, node.id, service, file + # get wlan configs for wlan nodes + if node.type == core_pb2.NodeType.WIRELESS_LAN: + response = self.client.get_wlan_config(self.session_id, node.id) + self.wlan_configs[node.id] = response.config + # retrieve service configurations data for default nodes + elif node.type == core_pb2.NodeType.DEFAULT: + for service in node.services: + response = self.client.get_node_service( + self.session_id, node.id, service ) - if node.id not in self.file_configs: - self.file_configs[node.id] = {} - if service not in self.file_configs[node.id]: - self.file_configs[node.id][service] = {} - self.file_configs[node.id][service][file] = response.data + if node.id not in self.service_configs: + self.service_configs[node.id] = {} + self.service_configs[node.id][service] = response.service + for file in response.service.configs: + response = self.client.get_node_service_file( + self.session_id, node.id, service, file + ) + if node.id not in self.file_configs: + self.file_configs[node.id] = {} + if service not in self.file_configs[node.id]: + self.file_configs[node.id][service] = {} + self.file_configs[node.id][service][file] = response.data - # store links as created links - for link in session.links: - self.created_links.add(tuple(sorted([link.node_one_id, link.node_two_id]))) + # store links as created links + for link in session.links: + self.created_links.add( + tuple(sorted([link.node_one_id, link.node_two_id])) + ) - # draw session - self.app.canvas.reset_and_redraw(session) + # draw session + self.app.canvas.reset_and_redraw(session) - # get metadata - response = self.client.get_session_metadata(self.session_id) - self.parse_metadata(response.config) + # get metadata + response = self.client.get_session_metadata(self.session_id) + self.parse_metadata(response.config) + except grpc.RpcError as e: + show_grpc_error(e) # update ui to represent current state if self.is_runtime(): @@ -363,25 +370,31 @@ class CoreClient: :return: nothing """ - response = self.client.create_session() - logging.info("created session: %s", response) - location_config = self.app.guiconfig["location"] - self.location = core_pb2.SessionLocation( - x=location_config["x"], - y=location_config["y"], - z=location_config["z"], - lat=location_config["lat"], - lon=location_config["lon"], - alt=location_config["alt"], - scale=location_config["scale"], - ) - self.join_session(response.session_id, query_location=False) + try: + response = self.client.create_session() + logging.info("created session: %s", response) + location_config = self.app.guiconfig["location"] + self.location = core_pb2.SessionLocation( + x=location_config["x"], + y=location_config["y"], + z=location_config["z"], + lat=location_config["lat"], + lon=location_config["lon"], + alt=location_config["alt"], + scale=location_config["scale"], + ) + self.join_session(response.session_id, query_location=False) + except grpc.RpcError as e: + show_grpc_error(e) def delete_session(self, session_id=None): if session_id is None: session_id = self.session_id - response = self.client.delete_session(session_id) - logging.info("Deleted session result: %s", response) + try: + response = self.client.delete_session(session_id) + logging.info("deleted session result: %s", response) + except grpc.RpcError as e: + show_grpc_error(e) def set_up(self): """ @@ -413,21 +426,15 @@ class CoreClient: x.node_type: set(x.services) for x in response.defaults } except grpc.RpcError as e: - if e.code() == grpc.StatusCode.UNAVAILABLE: - - messagebox.showerror("Server Error", "CORE Daemon Unavailable") - else: - messagebox.showerror("GRPC Error", e.details()) + show_grpc_error(e) self.app.close() - def get_session_state(self): - response = self.client.get_session(self.session_id) - logging.info("get session: %s", response) - return response.session.state - def edit_node(self, node_id, x, y): position = core_pb2.Position(x=x, y=y) - self.client.edit_node(self.session_id, node_id, position, source="gui") + try: + self.client.edit_node(self.session_id, node_id, position, source="gui") + except grpc.RpcError as e: + show_grpc_error(e) def start_session(self): nodes = [x.core_node for x in self.canvas_nodes.values()] @@ -446,39 +453,51 @@ class CoreClient: emane_config = None start = time.perf_counter() - response = self.client.start_session( - self.session_id, - nodes, - links, - self.location, - hooks, - emane_config, - emane_model_configs, - wlan_configs, - mobility_configs, - service_configs, - file_configs, - ) - self.set_metadata() - process_time = time.perf_counter() - start - logging.debug("start session(%s), result: %s", self.session_id, response.result) - self.app.statusbar.start_session_callback(process_time) + try: + response = self.client.start_session( + self.session_id, + nodes, + links, + self.location, + hooks, + emane_config, + emane_model_configs, + wlan_configs, + mobility_configs, + service_configs, + file_configs, + ) + self.set_metadata() + process_time = time.perf_counter() - start + logging.debug( + "start session(%s), result: %s", self.session_id, response.result + ) + self.app.statusbar.start_session_callback(process_time) - # display mobility players - for node_id, config in self.mobility_configs.items(): - canvas_node = self.canvas_nodes[node_id] - mobility_player = MobilityPlayer(self.app, self.app, canvas_node, config) - mobility_player.show() - self.mobility_players[node_id] = mobility_player + # display mobility players + for node_id, config in self.mobility_configs.items(): + canvas_node = self.canvas_nodes[node_id] + mobility_player = MobilityPlayer( + self.app, self.app, canvas_node, config + ) + mobility_player.show() + self.mobility_players[node_id] = mobility_player + except grpc.RpcError as e: + show_grpc_error(e) def stop_session(self, session_id=None): if not session_id: session_id = self.session_id start = time.perf_counter() - response = self.client.stop_session(session_id) - process_time = time.perf_counter() - start - self.app.statusbar.stop_session_callback(process_time) - logging.debug("stopped session(%s), result: %s", session_id, response.result) + try: + response = self.client.stop_session(session_id) + logging.debug( + "stopped session(%s), result: %s", session_id, response.result + ) + process_time = time.perf_counter() - start + self.app.statusbar.stop_session_callback(process_time) + except grpc.RpcError as e: + show_grpc_error(e) def set_metadata(self): # create canvas data @@ -502,9 +521,12 @@ class CoreClient: logging.info("set session metadata: %s", response) def launch_terminal(self, node_id): - response = self.client.get_node_terminal(self.session_id, node_id) - logging.info("get terminal %s", response.terminal) - os.system(f"xterm -e {response.terminal} &") + try: + response = self.client.get_node_terminal(self.session_id, node_id) + logging.info("get terminal %s", response.terminal) + os.system(f"xterm -e {response.terminal} &") + except grpc.RpcError as e: + show_grpc_error(e) def save_xml(self, file_path): """ @@ -513,9 +535,11 @@ class CoreClient: :param str file_path: file path that user pick :return: nothing """ - response = self.client.save_xml(self.session_id, file_path) - logging.info("saved xml(%s): %s", file_path, response) - self.client.events(self.session_id, self.handle_events) + try: + response = self.client.save_xml(self.session_id, file_path) + logging.info("saved xml(%s): %s", file_path, response) + except grpc.RpcError as e: + show_grpc_error(e) def open_xml(self, file_path): """ @@ -524,9 +548,12 @@ class CoreClient: :param str file_path: file to open :return: session id """ - response = self.client.open_xml(file_path) - logging.debug("open xml: %s", response) - self.join_session(response.session_id) + try: + response = self.client.open_xml(file_path) + logging.debug("open xml: %s", response) + self.join_session(response.session_id) + except grpc.RpcError as e: + show_grpc_error(e) def get_node_service(self, node_id, service_name): response = self.client.get_node_service(self.session_id, node_id, service_name) @@ -563,7 +590,7 @@ class CoreClient: """ node_protos = [x.core_node for x in self.canvas_nodes.values()] link_protos = list(self.links.values()) - if self.get_session_state() != core_pb2.SessionState.DEFINITION: + if self.state != core_pb2.SessionState.DEFINITION: self.client.set_session_state( self.session_id, core_pb2.SessionState.DEFINITION ) @@ -596,7 +623,7 @@ class CoreClient: :return: nothing """ - logging.debug("Close grpc") + logging.debug("close grpc") self.client.close() def next_node_id(self): diff --git a/coretk/coretk/dialogs/emaneconfig.py b/coretk/coretk/dialogs/emaneconfig.py index 71ffe078..a9042ba3 100644 --- a/coretk/coretk/dialogs/emaneconfig.py +++ b/coretk/coretk/dialogs/emaneconfig.py @@ -6,7 +6,10 @@ import tkinter as tk import webbrowser from tkinter import ttk +import grpc + from coretk.dialogs.dialog import Dialog +from coretk.errors import show_grpc_error from coretk.images import ImageEnum, Images from coretk.widgets import ConfigFrame @@ -52,9 +55,13 @@ class EmaneModelDialog(Dialog): self.model = f"emane_{model}" self.interface = interface self.config_frame = None - self.config = self.app.core.get_emane_model_config( - self.node.id, self.model, self.interface - ) + try: + self.config = self.app.core.get_emane_model_config( + self.node.id, self.model, self.interface + ) + except grpc.RpcError as e: + show_grpc_error(e) + self.destroy() self.draw() def draw(self): diff --git a/coretk/coretk/dialogs/mobilityconfig.py b/coretk/coretk/dialogs/mobilityconfig.py index 21782ee6..4e9d9590 100644 --- a/coretk/coretk/dialogs/mobilityconfig.py +++ b/coretk/coretk/dialogs/mobilityconfig.py @@ -3,7 +3,10 @@ mobility configuration """ from tkinter import ttk +import grpc + from coretk.dialogs.dialog import Dialog +from coretk.errors import show_grpc_error from coretk.widgets import ConfigFrame PAD = 5 @@ -20,7 +23,11 @@ class MobilityConfigDialog(Dialog): self.canvas_node = canvas_node self.node = canvas_node.core_node self.config_frame = None - self.config = self.app.core.get_mobility_config(self.node.id) + try: + self.config = self.app.core.get_mobility_config(self.node.id) + except grpc.RpcError as e: + show_grpc_error(e) + self.destroy() self.draw() def draw(self): diff --git a/coretk/coretk/dialogs/mobilityplayer.py b/coretk/coretk/dialogs/mobilityplayer.py index 136e6179..3ccf0b5d 100644 --- a/coretk/coretk/dialogs/mobilityplayer.py +++ b/coretk/coretk/dialogs/mobilityplayer.py @@ -1,8 +1,11 @@ import tkinter as tk from tkinter import ttk +import grpc + from core.api.grpc.core_pb2 import MobilityAction from coretk.dialogs.dialog import Dialog +from coretk.errors import show_grpc_error from coretk.images import ImageEnum, Images PAD = 5 @@ -123,20 +126,29 @@ class MobilityPlayerDialog(Dialog): def click_play(self): self.set_play() session_id = self.app.core.session_id - self.app.core.client.mobility_action( - session_id, self.node.id, MobilityAction.START - ) + try: + self.app.core.client.mobility_action( + session_id, self.node.id, MobilityAction.START + ) + except grpc.RpcError as e: + show_grpc_error(e) def click_pause(self): self.set_pause() session_id = self.app.core.session_id - self.app.core.client.mobility_action( - session_id, self.node.id, MobilityAction.PAUSE - ) + try: + self.app.core.client.mobility_action( + session_id, self.node.id, MobilityAction.PAUSE + ) + except grpc.RpcError as e: + show_grpc_error(e) def click_stop(self): self.set_stop() session_id = self.app.core.session_id - self.app.core.client.mobility_action( - session_id, self.node.id, MobilityAction.STOP - ) + try: + self.app.core.client.mobility_action( + session_id, self.node.id, MobilityAction.STOP + ) + except grpc.RpcError as e: + show_grpc_error(e) diff --git a/coretk/coretk/dialogs/serviceconfiguration.py b/coretk/coretk/dialogs/serviceconfiguration.py index 446f9c12..354937e5 100644 --- a/coretk/coretk/dialogs/serviceconfiguration.py +++ b/coretk/coretk/dialogs/serviceconfiguration.py @@ -3,8 +3,11 @@ import logging import tkinter as tk from tkinter import ttk +import grpc + from core.api.grpc import core_pb2 from coretk.dialogs.dialog import Dialog +from coretk.errors import show_grpc_error from coretk.images import ImageEnum, Images from coretk.widgets import CodeText, ListboxScroll @@ -47,44 +50,48 @@ class ServiceConfiguration(Dialog): self.draw() def load(self): - # create nodes and links in definition state for getting and setting service file - self.app.core.create_nodes_and_links() - - service_configs = self.app.core.service_configs - if ( - self.node_id in service_configs - and self.service_name in service_configs[self.node_id] - ): - service_config = self.app.core.service_configs[self.node_id][ - self.service_name - ] - else: - service_config = self.app.core.get_node_service( - self.node_id, self.service_name - ) - self.dependencies = [x for x in service_config.dependencies] - self.executables = [x for x in service_config.executables] - self.metadata = service_config.meta - self.filenames = [x for x in service_config.configs] - self.startup_commands = [x for x in service_config.startup] - self.validation_commands = [x for x in service_config.validate] - self.shutdown_commands = [x for x in service_config.shutdown] - self.validation_mode = service_config.validation_mode - self.validation_time = service_config.validation_timer - self.original_service_files = { - x: self.app.core.get_node_service_file(self.node_id, self.service_name, x) - for x in self.filenames - } - self.temp_service_files = { - x: self.original_service_files[x] for x in self.original_service_files - } - file_configs = self.app.core.file_configs - if ( - self.node_id in file_configs - and self.service_name in file_configs[self.node_id] - ): - for file, data in file_configs[self.node_id][self.service_name].items(): - self.temp_service_files[file] = data + try: + # create nodes and links in definition state for getting and setting service file + self.app.core.create_nodes_and_links() + service_configs = self.app.core.service_configs + if ( + self.node_id in service_configs + and self.service_name in service_configs[self.node_id] + ): + service_config = self.app.core.service_configs[self.node_id][ + self.service_name + ] + else: + service_config = self.app.core.get_node_service( + self.node_id, self.service_name + ) + self.dependencies = [x for x in service_config.dependencies] + self.executables = [x for x in service_config.executables] + self.metadata = service_config.meta + self.filenames = [x for x in service_config.configs] + self.startup_commands = [x for x in service_config.startup] + self.validation_commands = [x for x in service_config.validate] + self.shutdown_commands = [x for x in service_config.shutdown] + self.validation_mode = service_config.validation_mode + self.validation_time = service_config.validation_timer + self.original_service_files = { + x: self.app.core.get_node_service_file( + self.node_id, self.service_name, x + ) + for x in self.filenames + } + self.temp_service_files = { + x: self.original_service_files[x] for x in self.original_service_files + } + file_configs = self.app.core.file_configs + if ( + self.node_id in file_configs + and self.service_name in file_configs[self.node_id] + ): + for file, data in file_configs[self.node_id][self.service_name].items(): + self.temp_service_files[file] = data + except grpc.RpcError as e: + show_grpc_error(e) def draw(self): # self.columnconfigure(1, weight=1) @@ -366,30 +373,33 @@ class ServiceConfiguration(Dialog): startup_commands = self.startup_commands_listbox.get(0, "end") shutdown_commands = self.shutdown_commands_listbox.get(0, "end") validate_commands = self.validate_commands_listbox.get(0, "end") - config = self.core.set_node_service( - self.node_id, - self.service_name, - startup_commands, - validate_commands, - shutdown_commands, - ) - if self.node_id not in service_configs: - service_configs[self.node_id] = {} - if self.service_name not in service_configs[self.node_id]: - self.app.core.service_configs[self.node_id][self.service_name] = config - for file in self.modified_files: - file_configs = self.app.core.file_configs - if self.node_id not in file_configs: - file_configs[self.node_id] = {} - if self.service_name not in file_configs[self.node_id]: - file_configs[self.node_id][self.service_name] = {} - file_configs[self.node_id][self.service_name][ - file - ] = self.temp_service_files[file] - - self.app.core.set_node_service_file( - self.node_id, self.service_name, file, self.temp_service_files[file] + try: + config = self.core.set_node_service( + self.node_id, + self.service_name, + startup_commands, + validate_commands, + shutdown_commands, ) + if self.node_id not in service_configs: + service_configs[self.node_id] = {} + if self.service_name not in service_configs[self.node_id]: + self.app.core.service_configs[self.node_id][self.service_name] = config + for file in self.modified_files: + file_configs = self.app.core.file_configs + if self.node_id not in file_configs: + file_configs[self.node_id] = {} + if self.service_name not in file_configs[self.node_id]: + file_configs[self.node_id][self.service_name] = {} + file_configs[self.node_id][self.service_name][ + file + ] = self.temp_service_files[file] + + self.app.core.set_node_service_file( + self.node_id, self.service_name, file, self.temp_service_files[file] + ) + except grpc.RpcError as e: + show_grpc_error(e) self.destroy() def display_service_file_data(self, event): diff --git a/coretk/coretk/dialogs/sessionoptions.py b/coretk/coretk/dialogs/sessionoptions.py index b2666015..7c77f9df 100644 --- a/coretk/coretk/dialogs/sessionoptions.py +++ b/coretk/coretk/dialogs/sessionoptions.py @@ -1,7 +1,10 @@ import logging from tkinter import ttk +import grpc + from coretk.dialogs.dialog import Dialog +from coretk.errors import show_grpc_error from coretk.widgets import ConfigFrame PAD_X = 2 @@ -12,17 +15,23 @@ class SessionOptionsDialog(Dialog): def __init__(self, master, app): super().__init__(master, app, "Session Options", modal=True) self.config_frame = None + self.config = self.get_config() self.draw() + def get_config(self): + try: + session_id = self.app.core.session_id + response = self.app.core.client.get_session_options(session_id) + return response.config + except grpc.RpcError as e: + show_grpc_error(e) + self.destroy() + def draw(self): self.top.columnconfigure(0, weight=1) self.top.rowconfigure(0, weight=1) - session_id = self.app.core.session_id - response = self.app.core.client.get_session_options(session_id) - logging.info("session options: %s", response) - - self.config_frame = ConfigFrame(self.top, self.app, config=response.config) + self.config_frame = ConfigFrame(self.top, self.app, config=self.config) self.config_frame.draw_config() self.config_frame.grid(sticky="nsew") @@ -37,7 +46,10 @@ class SessionOptionsDialog(Dialog): def save(self): config = self.config_frame.parse_config() - session_id = self.app.core.session_id - response = self.app.core.client.set_session_options(session_id, config) - logging.info("saved session config: %s", response) + try: + session_id = self.app.core.session_id + response = self.app.core.client.set_session_options(session_id, config) + logging.info("saved session config: %s", response) + except grpc.RpcError as e: + show_grpc_error(e) self.destroy() diff --git a/coretk/coretk/dialogs/sessions.py b/coretk/coretk/dialogs/sessions.py index 7a07c059..e3d9e696 100644 --- a/coretk/coretk/dialogs/sessions.py +++ b/coretk/coretk/dialogs/sessions.py @@ -3,8 +3,11 @@ import threading import tkinter as tk from tkinter import ttk +import grpc + from core.api.grpc import core_pb2 from coretk.dialogs.dialog import Dialog +from coretk.errors import show_grpc_error from coretk.images import ImageEnum, Images @@ -14,8 +17,18 @@ class SessionsDialog(Dialog): self.selected = False self.selected_id = None self.tree = None + self.sessions = self.get_sessions() self.draw() + def get_sessions(self): + try: + response = self.app.core.client.get_sessions() + logging.info("sessions: %s", response) + return response.sessions + except grpc.RpcError as e: + show_grpc_error(e) + self.destroy() + def draw(self): self.top.columnconfigure(0, weight=1) self.draw_description() @@ -48,9 +61,7 @@ class SessionsDialog(Dialog): self.tree.column("nodes", stretch=tk.YES) self.tree.heading("nodes", text="Node Count") - response = self.app.core.client.get_sessions() - logging.info("sessions: %s", response) - for index, session in enumerate(response.sessions): + for index, session in enumerate(self.sessions): state_name = core_pb2.SessionState.Enum.Name(session.state) self.tree.insert( "", diff --git a/coretk/coretk/dialogs/wlanconfig.py b/coretk/coretk/dialogs/wlanconfig.py index 3c118834..42adc49a 100644 --- a/coretk/coretk/dialogs/wlanconfig.py +++ b/coretk/coretk/dialogs/wlanconfig.py @@ -4,7 +4,10 @@ wlan configuration from tkinter import ttk +import grpc + from coretk.dialogs.dialog import Dialog +from coretk.errors import show_grpc_error from coretk.widgets import ConfigFrame PAD = 5 @@ -18,7 +21,11 @@ class WlanConfigDialog(Dialog): self.canvas_node = canvas_node self.node = canvas_node.core_node self.config_frame = None - self.config = self.app.core.get_wlan_config(self.node.id) + try: + self.config = self.app.core.get_wlan_config(self.node.id) + except grpc.RpcError as e: + show_grpc_error(e) + self.destroy() self.draw() def draw(self): diff --git a/coretk/coretk/errors.py b/coretk/coretk/errors.py new file mode 100644 index 00000000..936968ad --- /dev/null +++ b/coretk/coretk/errors.py @@ -0,0 +1,8 @@ +from tkinter import messagebox + + +def show_grpc_error(e): + title = [x.capitalize() for x in e.code().name.lower().split("_")] + title = " ".join(title) + title = f"GRPC {title}" + messagebox.showerror(title, e.details()) diff --git a/coretk/coretk/graph/node.py b/coretk/coretk/graph/node.py index 1dcb8959..79401c04 100644 --- a/coretk/coretk/graph/node.py +++ b/coretk/coretk/graph/node.py @@ -2,11 +2,14 @@ import logging import tkinter as tk from tkinter import font +import grpc + from core.api.grpc.core_pb2 import NodeType from coretk.dialogs.emaneconfig import EmaneConfigDialog from coretk.dialogs.mobilityconfig import MobilityConfigDialog from coretk.dialogs.nodeconfig import NodeConfigDialog from coretk.dialogs.wlanconfig import WlanConfigDialog +from coretk.errors import show_grpc_error from coretk.graph import tags from coretk.graph.enums import GraphMode from coretk.graph.tooltip import CanvasTooltip @@ -138,8 +141,11 @@ class CanvasNode: if self.app.core.is_runtime() and self.app.core.observer: self.tooltip.text.set("waiting...") self.tooltip.on_enter(event) - output = self.app.core.run(self.core_node.id) - self.tooltip.text.set(output) + try: + output = self.app.core.run(self.core_node.id) + self.tooltip.text.set(output) + except grpc.RpcError as e: + show_grpc_error(e) def on_leave(self, event): self.tooltip.on_leave(event) diff --git a/coretk/coretk/menuaction.py b/coretk/coretk/menuaction.py index f7f9c579..246020ba 100644 --- a/coretk/coretk/menuaction.py +++ b/coretk/coretk/menuaction.py @@ -10,7 +10,6 @@ from tkinter import filedialog, messagebox import grpc -from core.api.grpc import core_pb2 from coretk.appconfig import XML_PATH from coretk.dialogs.about import AboutDialog from coretk.dialogs.canvasbackground import CanvasBackgroundDialog @@ -52,12 +51,7 @@ class MenuAction: "menuaction.py: clean_nodes_links_and_set_configuration() Exiting the program" ) try: - state = self.app.core.get_session_state() - - if ( - state == core_pb2.SessionState.SHUTDOWN - or state == core_pb2.SessionState.DEFINITION - ): + if not self.app.core.is_runtime(): self.app.core.delete_session() if quitapp: self.app.quit() @@ -73,7 +67,7 @@ class MenuAction: elif quitapp: self.app.quit() except grpc.RpcError: - logging.error("error getting session state") + logging.exception("error deleting session") if quitapp: self.app.quit() From 21f0857e654170c49f15ec7972492acb2496ad30 Mon Sep 17 00:00:00 2001 From: Blake Harnden <32446120+bharnden@users.noreply.github.com> Date: Mon, 9 Dec 2019 23:09:39 -0800 Subject: [PATCH 4/4] reset mobility player to default dialog size --- coretk/coretk/dialogs/mobilityplayer.py | 1 + 1 file changed, 1 insertion(+) diff --git a/coretk/coretk/dialogs/mobilityplayer.py b/coretk/coretk/dialogs/mobilityplayer.py index 3ccf0b5d..6c9799b9 100644 --- a/coretk/coretk/dialogs/mobilityplayer.py +++ b/coretk/coretk/dialogs/mobilityplayer.py @@ -53,6 +53,7 @@ class MobilityPlayerDialog(Dialog): super().__init__( master, app, f"{canvas_node.core_node.name} Mobility Player", modal=False ) + self.geometry("") self.canvas_node = canvas_node self.node = canvas_node.core_node self.config = config