added grpc error display and updated grpc calls to catch and display grpc exceptions

This commit is contained in:
Blake Harnden 2019-12-09 22:50:26 -08:00
parent 33e3a46146
commit d78ef86cef
11 changed files with 329 additions and 228 deletions

View file

@ -6,7 +6,6 @@ import logging
import os import os
import time import time
from pathlib import Path from pathlib import Path
from tkinter import messagebox
import grpc import grpc
@ -14,6 +13,7 @@ from core.api.grpc import client, core_pb2
from coretk import appconfig from coretk import appconfig
from coretk.dialogs.mobilityplayer import MobilityPlayer from coretk.dialogs.mobilityplayer import MobilityPlayer
from coretk.dialogs.sessions import SessionsDialog from coretk.dialogs.sessions import SessionsDialog
from coretk.errors import show_grpc_error
from coretk.graph import tags from coretk.graph import tags
from coretk.graph.shape import AnnotationData, Shape from coretk.graph.shape import AnnotationData, Shape
from coretk.graph.shapeutils import ShapeType from coretk.graph.shapeutils import ShapeType
@ -206,6 +206,7 @@ class CoreClient:
self.reset() self.reset()
# get session data # get session data
try:
response = self.client.get_session(self.session_id) response = self.client.get_session(self.session_id)
session = response.session session = response.session
self.state = session.state self.state = session.state
@ -245,7 +246,9 @@ class CoreClient:
if _id >= 1000: if _id >= 1000:
interface = _id % 1000 interface = _id % 1000
node_id = int(_id / 1000) node_id = int(_id / 1000)
self.set_emane_model_config(node_id, config.model, config.config, interface) self.set_emane_model_config(
node_id, config.model, config.config, interface
)
# save and retrieve data, needed for session nodes # save and retrieve data, needed for session nodes
for node in session.nodes: for node in session.nodes:
@ -277,7 +280,9 @@ class CoreClient:
# store links as created links # store links as created links
for link in session.links: for link in session.links:
self.created_links.add(tuple(sorted([link.node_one_id, link.node_two_id]))) self.created_links.add(
tuple(sorted([link.node_one_id, link.node_two_id]))
)
# draw session # draw session
self.app.canvas.reset_and_redraw(session) self.app.canvas.reset_and_redraw(session)
@ -285,6 +290,8 @@ class CoreClient:
# get metadata # get metadata
response = self.client.get_session_metadata(self.session_id) response = self.client.get_session_metadata(self.session_id)
self.parse_metadata(response.config) self.parse_metadata(response.config)
except grpc.RpcError as e:
show_grpc_error(e)
# update ui to represent current state # update ui to represent current state
if self.is_runtime(): if self.is_runtime():
@ -363,6 +370,7 @@ class CoreClient:
:return: nothing :return: nothing
""" """
try:
response = self.client.create_session() response = self.client.create_session()
logging.info("created session: %s", response) logging.info("created session: %s", response)
location_config = self.app.guiconfig["location"] location_config = self.app.guiconfig["location"]
@ -376,12 +384,17 @@ class CoreClient:
scale=location_config["scale"], scale=location_config["scale"],
) )
self.join_session(response.session_id, query_location=False) 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): def delete_session(self, session_id=None):
if session_id is None: if session_id is None:
session_id = self.session_id session_id = self.session_id
try:
response = self.client.delete_session(session_id) response = self.client.delete_session(session_id)
logging.info("Deleted session result: %s", response) logging.info("deleted session result: %s", response)
except grpc.RpcError as e:
show_grpc_error(e)
def set_up(self): def set_up(self):
""" """
@ -413,21 +426,15 @@ class CoreClient:
x.node_type: set(x.services) for x in response.defaults x.node_type: set(x.services) for x in response.defaults
} }
except grpc.RpcError as e: except grpc.RpcError as e:
if e.code() == grpc.StatusCode.UNAVAILABLE: show_grpc_error(e)
messagebox.showerror("Server Error", "CORE Daemon Unavailable")
else:
messagebox.showerror("GRPC Error", e.details())
self.app.close() 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): def edit_node(self, node_id, x, y):
position = core_pb2.Position(x=x, y=y) position = core_pb2.Position(x=x, y=y)
try:
self.client.edit_node(self.session_id, node_id, position, source="gui") 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): def start_session(self):
nodes = [x.core_node for x in self.canvas_nodes.values()] nodes = [x.core_node for x in self.canvas_nodes.values()]
@ -446,6 +453,7 @@ class CoreClient:
emane_config = None emane_config = None
start = time.perf_counter() start = time.perf_counter()
try:
response = self.client.start_session( response = self.client.start_session(
self.session_id, self.session_id,
nodes, nodes,
@ -461,24 +469,35 @@ class CoreClient:
) )
self.set_metadata() self.set_metadata()
process_time = time.perf_counter() - start process_time = time.perf_counter() - start
logging.debug("start session(%s), result: %s", self.session_id, response.result) logging.debug(
"start session(%s), result: %s", self.session_id, response.result
)
self.app.statusbar.start_session_callback(process_time) self.app.statusbar.start_session_callback(process_time)
# display mobility players # display mobility players
for node_id, config in self.mobility_configs.items(): for node_id, config in self.mobility_configs.items():
canvas_node = self.canvas_nodes[node_id] canvas_node = self.canvas_nodes[node_id]
mobility_player = MobilityPlayer(self.app, self.app, canvas_node, config) mobility_player = MobilityPlayer(
self.app, self.app, canvas_node, config
)
mobility_player.show() mobility_player.show()
self.mobility_players[node_id] = mobility_player self.mobility_players[node_id] = mobility_player
except grpc.RpcError as e:
show_grpc_error(e)
def stop_session(self, session_id=None): def stop_session(self, session_id=None):
if not session_id: if not session_id:
session_id = self.session_id session_id = self.session_id
start = time.perf_counter() start = time.perf_counter()
try:
response = self.client.stop_session(session_id) response = self.client.stop_session(session_id)
logging.debug(
"stopped session(%s), result: %s", session_id, response.result
)
process_time = time.perf_counter() - start process_time = time.perf_counter() - start
self.app.statusbar.stop_session_callback(process_time) self.app.statusbar.stop_session_callback(process_time)
logging.debug("stopped session(%s), result: %s", session_id, response.result) except grpc.RpcError as e:
show_grpc_error(e)
def set_metadata(self): def set_metadata(self):
# create canvas data # create canvas data
@ -502,9 +521,12 @@ class CoreClient:
logging.info("set session metadata: %s", response) logging.info("set session metadata: %s", response)
def launch_terminal(self, node_id): def launch_terminal(self, node_id):
try:
response = self.client.get_node_terminal(self.session_id, node_id) response = self.client.get_node_terminal(self.session_id, node_id)
logging.info("get terminal %s", response.terminal) logging.info("get terminal %s", response.terminal)
os.system(f"xterm -e {response.terminal} &") os.system(f"xterm -e {response.terminal} &")
except grpc.RpcError as e:
show_grpc_error(e)
def save_xml(self, file_path): def save_xml(self, file_path):
""" """
@ -513,9 +535,11 @@ class CoreClient:
:param str file_path: file path that user pick :param str file_path: file path that user pick
:return: nothing :return: nothing
""" """
try:
response = self.client.save_xml(self.session_id, file_path) response = self.client.save_xml(self.session_id, file_path)
logging.info("saved xml(%s): %s", file_path, response) logging.info("saved xml(%s): %s", file_path, response)
self.client.events(self.session_id, self.handle_events) except grpc.RpcError as e:
show_grpc_error(e)
def open_xml(self, file_path): def open_xml(self, file_path):
""" """
@ -524,9 +548,12 @@ class CoreClient:
:param str file_path: file to open :param str file_path: file to open
:return: session id :return: session id
""" """
try:
response = self.client.open_xml(file_path) response = self.client.open_xml(file_path)
logging.debug("open xml: %s", response) logging.debug("open xml: %s", response)
self.join_session(response.session_id) self.join_session(response.session_id)
except grpc.RpcError as e:
show_grpc_error(e)
def get_node_service(self, node_id, service_name): def get_node_service(self, node_id, service_name):
response = self.client.get_node_service(self.session_id, 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()] node_protos = [x.core_node for x in self.canvas_nodes.values()]
link_protos = list(self.links.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.client.set_session_state(
self.session_id, core_pb2.SessionState.DEFINITION self.session_id, core_pb2.SessionState.DEFINITION
) )
@ -596,7 +623,7 @@ class CoreClient:
:return: nothing :return: nothing
""" """
logging.debug("Close grpc") logging.debug("close grpc")
self.client.close() self.client.close()
def next_node_id(self): def next_node_id(self):

View file

@ -6,7 +6,10 @@ import tkinter as tk
import webbrowser import webbrowser
from tkinter import ttk from tkinter import ttk
import grpc
from coretk.dialogs.dialog import Dialog from coretk.dialogs.dialog import Dialog
from coretk.errors import show_grpc_error
from coretk.images import ImageEnum, Images from coretk.images import ImageEnum, Images
from coretk.widgets import ConfigFrame from coretk.widgets import ConfigFrame
@ -52,9 +55,13 @@ class EmaneModelDialog(Dialog):
self.model = f"emane_{model}" self.model = f"emane_{model}"
self.interface = interface self.interface = interface
self.config_frame = None self.config_frame = None
try:
self.config = self.app.core.get_emane_model_config( self.config = self.app.core.get_emane_model_config(
self.node.id, self.model, self.interface self.node.id, self.model, self.interface
) )
except grpc.RpcError as e:
show_grpc_error(e)
self.destroy()
self.draw() self.draw()
def draw(self): def draw(self):

View file

@ -3,7 +3,10 @@ mobility configuration
""" """
from tkinter import ttk from tkinter import ttk
import grpc
from coretk.dialogs.dialog import Dialog from coretk.dialogs.dialog import Dialog
from coretk.errors import show_grpc_error
from coretk.widgets import ConfigFrame from coretk.widgets import ConfigFrame
PAD = 5 PAD = 5
@ -20,7 +23,11 @@ class MobilityConfigDialog(Dialog):
self.canvas_node = canvas_node self.canvas_node = canvas_node
self.node = canvas_node.core_node self.node = canvas_node.core_node
self.config_frame = None self.config_frame = None
try:
self.config = self.app.core.get_mobility_config(self.node.id) self.config = self.app.core.get_mobility_config(self.node.id)
except grpc.RpcError as e:
show_grpc_error(e)
self.destroy()
self.draw() self.draw()
def draw(self): def draw(self):

View file

@ -1,8 +1,11 @@
import tkinter as tk import tkinter as tk
from tkinter import ttk from tkinter import ttk
import grpc
from core.api.grpc.core_pb2 import MobilityAction from core.api.grpc.core_pb2 import MobilityAction
from coretk.dialogs.dialog import Dialog from coretk.dialogs.dialog import Dialog
from coretk.errors import show_grpc_error
from coretk.images import ImageEnum, Images from coretk.images import ImageEnum, Images
PAD = 5 PAD = 5
@ -123,20 +126,29 @@ class MobilityPlayerDialog(Dialog):
def click_play(self): def click_play(self):
self.set_play() self.set_play()
session_id = self.app.core.session_id session_id = self.app.core.session_id
try:
self.app.core.client.mobility_action( self.app.core.client.mobility_action(
session_id, self.node.id, MobilityAction.START session_id, self.node.id, MobilityAction.START
) )
except grpc.RpcError as e:
show_grpc_error(e)
def click_pause(self): def click_pause(self):
self.set_pause() self.set_pause()
session_id = self.app.core.session_id session_id = self.app.core.session_id
try:
self.app.core.client.mobility_action( self.app.core.client.mobility_action(
session_id, self.node.id, MobilityAction.PAUSE session_id, self.node.id, MobilityAction.PAUSE
) )
except grpc.RpcError as e:
show_grpc_error(e)
def click_stop(self): def click_stop(self):
self.set_stop() self.set_stop()
session_id = self.app.core.session_id session_id = self.app.core.session_id
try:
self.app.core.client.mobility_action( self.app.core.client.mobility_action(
session_id, self.node.id, MobilityAction.STOP session_id, self.node.id, MobilityAction.STOP
) )
except grpc.RpcError as e:
show_grpc_error(e)

View file

@ -3,8 +3,11 @@ import logging
import tkinter as tk import tkinter as tk
from tkinter import ttk from tkinter import ttk
import grpc
from core.api.grpc import core_pb2 from core.api.grpc import core_pb2
from coretk.dialogs.dialog import Dialog from coretk.dialogs.dialog import Dialog
from coretk.errors import show_grpc_error
from coretk.images import ImageEnum, Images from coretk.images import ImageEnum, Images
from coretk.widgets import CodeText, ListboxScroll from coretk.widgets import CodeText, ListboxScroll
@ -47,9 +50,9 @@ class ServiceConfiguration(Dialog):
self.draw() self.draw()
def load(self): def load(self):
try:
# create nodes and links in definition state for getting and setting service file # create nodes and links in definition state for getting and setting service file
self.app.core.create_nodes_and_links() self.app.core.create_nodes_and_links()
service_configs = self.app.core.service_configs service_configs = self.app.core.service_configs
if ( if (
self.node_id in service_configs self.node_id in service_configs
@ -72,7 +75,9 @@ class ServiceConfiguration(Dialog):
self.validation_mode = service_config.validation_mode self.validation_mode = service_config.validation_mode
self.validation_time = service_config.validation_timer self.validation_time = service_config.validation_timer
self.original_service_files = { self.original_service_files = {
x: self.app.core.get_node_service_file(self.node_id, self.service_name, x) x: self.app.core.get_node_service_file(
self.node_id, self.service_name, x
)
for x in self.filenames for x in self.filenames
} }
self.temp_service_files = { self.temp_service_files = {
@ -85,6 +90,8 @@ class ServiceConfiguration(Dialog):
): ):
for file, data in file_configs[self.node_id][self.service_name].items(): for file, data in file_configs[self.node_id][self.service_name].items():
self.temp_service_files[file] = data self.temp_service_files[file] = data
except grpc.RpcError as e:
show_grpc_error(e)
def draw(self): def draw(self):
# self.columnconfigure(1, weight=1) # self.columnconfigure(1, weight=1)
@ -366,6 +373,7 @@ class ServiceConfiguration(Dialog):
startup_commands = self.startup_commands_listbox.get(0, "end") startup_commands = self.startup_commands_listbox.get(0, "end")
shutdown_commands = self.shutdown_commands_listbox.get(0, "end") shutdown_commands = self.shutdown_commands_listbox.get(0, "end")
validate_commands = self.validate_commands_listbox.get(0, "end") validate_commands = self.validate_commands_listbox.get(0, "end")
try:
config = self.core.set_node_service( config = self.core.set_node_service(
self.node_id, self.node_id,
self.service_name, self.service_name,
@ -390,6 +398,8 @@ class ServiceConfiguration(Dialog):
self.app.core.set_node_service_file( self.app.core.set_node_service_file(
self.node_id, self.service_name, file, self.temp_service_files[file] self.node_id, self.service_name, file, self.temp_service_files[file]
) )
except grpc.RpcError as e:
show_grpc_error(e)
self.destroy() self.destroy()
def display_service_file_data(self, event): def display_service_file_data(self, event):

View file

@ -1,7 +1,10 @@
import logging import logging
from tkinter import ttk from tkinter import ttk
import grpc
from coretk.dialogs.dialog import Dialog from coretk.dialogs.dialog import Dialog
from coretk.errors import show_grpc_error
from coretk.widgets import ConfigFrame from coretk.widgets import ConfigFrame
PAD_X = 2 PAD_X = 2
@ -12,17 +15,23 @@ class SessionOptionsDialog(Dialog):
def __init__(self, master, app): def __init__(self, master, app):
super().__init__(master, app, "Session Options", modal=True) super().__init__(master, app, "Session Options", modal=True)
self.config_frame = None self.config_frame = None
self.config = self.get_config()
self.draw() 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): def draw(self):
self.top.columnconfigure(0, weight=1) self.top.columnconfigure(0, weight=1)
self.top.rowconfigure(0, weight=1) self.top.rowconfigure(0, weight=1)
session_id = self.app.core.session_id self.config_frame = ConfigFrame(self.top, self.app, config=self.config)
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.draw_config() self.config_frame.draw_config()
self.config_frame.grid(sticky="nsew") self.config_frame.grid(sticky="nsew")
@ -37,7 +46,10 @@ class SessionOptionsDialog(Dialog):
def save(self): def save(self):
config = self.config_frame.parse_config() config = self.config_frame.parse_config()
try:
session_id = self.app.core.session_id session_id = self.app.core.session_id
response = self.app.core.client.set_session_options(session_id, config) response = self.app.core.client.set_session_options(session_id, config)
logging.info("saved session config: %s", response) logging.info("saved session config: %s", response)
except grpc.RpcError as e:
show_grpc_error(e)
self.destroy() self.destroy()

View file

@ -3,8 +3,11 @@ import threading
import tkinter as tk import tkinter as tk
from tkinter import ttk from tkinter import ttk
import grpc
from core.api.grpc import core_pb2 from core.api.grpc import core_pb2
from coretk.dialogs.dialog import Dialog from coretk.dialogs.dialog import Dialog
from coretk.errors import show_grpc_error
from coretk.images import ImageEnum, Images from coretk.images import ImageEnum, Images
@ -14,8 +17,18 @@ class SessionsDialog(Dialog):
self.selected = False self.selected = False
self.selected_id = None self.selected_id = None
self.tree = None self.tree = None
self.sessions = self.get_sessions()
self.draw() 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): def draw(self):
self.top.columnconfigure(0, weight=1) self.top.columnconfigure(0, weight=1)
self.draw_description() self.draw_description()
@ -48,9 +61,7 @@ class SessionsDialog(Dialog):
self.tree.column("nodes", stretch=tk.YES) self.tree.column("nodes", stretch=tk.YES)
self.tree.heading("nodes", text="Node Count") self.tree.heading("nodes", text="Node Count")
response = self.app.core.client.get_sessions() for index, session in enumerate(self.sessions):
logging.info("sessions: %s", response)
for index, session in enumerate(response.sessions):
state_name = core_pb2.SessionState.Enum.Name(session.state) state_name = core_pb2.SessionState.Enum.Name(session.state)
self.tree.insert( self.tree.insert(
"", "",

View file

@ -4,7 +4,10 @@ wlan configuration
from tkinter import ttk from tkinter import ttk
import grpc
from coretk.dialogs.dialog import Dialog from coretk.dialogs.dialog import Dialog
from coretk.errors import show_grpc_error
from coretk.widgets import ConfigFrame from coretk.widgets import ConfigFrame
PAD = 5 PAD = 5
@ -18,7 +21,11 @@ class WlanConfigDialog(Dialog):
self.canvas_node = canvas_node self.canvas_node = canvas_node
self.node = canvas_node.core_node self.node = canvas_node.core_node
self.config_frame = None self.config_frame = None
try:
self.config = self.app.core.get_wlan_config(self.node.id) self.config = self.app.core.get_wlan_config(self.node.id)
except grpc.RpcError as e:
show_grpc_error(e)
self.destroy()
self.draw() self.draw()
def draw(self): def draw(self):

8
coretk/coretk/errors.py Normal file
View file

@ -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())

View file

@ -2,11 +2,14 @@ import logging
import tkinter as tk import tkinter as tk
from tkinter import font from tkinter import font
import grpc
from core.api.grpc.core_pb2 import NodeType from core.api.grpc.core_pb2 import NodeType
from coretk.dialogs.emaneconfig import EmaneConfigDialog from coretk.dialogs.emaneconfig import EmaneConfigDialog
from coretk.dialogs.mobilityconfig import MobilityConfigDialog from coretk.dialogs.mobilityconfig import MobilityConfigDialog
from coretk.dialogs.nodeconfig import NodeConfigDialog from coretk.dialogs.nodeconfig import NodeConfigDialog
from coretk.dialogs.wlanconfig import WlanConfigDialog from coretk.dialogs.wlanconfig import WlanConfigDialog
from coretk.errors import show_grpc_error
from coretk.graph import tags from coretk.graph import tags
from coretk.graph.enums import GraphMode from coretk.graph.enums import GraphMode
from coretk.graph.tooltip import CanvasTooltip from coretk.graph.tooltip import CanvasTooltip
@ -138,8 +141,11 @@ class CanvasNode:
if self.app.core.is_runtime() and self.app.core.observer: if self.app.core.is_runtime() and self.app.core.observer:
self.tooltip.text.set("waiting...") self.tooltip.text.set("waiting...")
self.tooltip.on_enter(event) self.tooltip.on_enter(event)
try:
output = self.app.core.run(self.core_node.id) output = self.app.core.run(self.core_node.id)
self.tooltip.text.set(output) self.tooltip.text.set(output)
except grpc.RpcError as e:
show_grpc_error(e)
def on_leave(self, event): def on_leave(self, event):
self.tooltip.on_leave(event) self.tooltip.on_leave(event)

View file

@ -10,7 +10,6 @@ from tkinter import filedialog, messagebox
import grpc import grpc
from core.api.grpc import core_pb2
from coretk.appconfig import XML_PATH from coretk.appconfig import XML_PATH
from coretk.dialogs.about import AboutDialog from coretk.dialogs.about import AboutDialog
from coretk.dialogs.canvasbackground import CanvasBackgroundDialog from coretk.dialogs.canvasbackground import CanvasBackgroundDialog
@ -52,12 +51,7 @@ class MenuAction:
"menuaction.py: clean_nodes_links_and_set_configuration() Exiting the program" "menuaction.py: clean_nodes_links_and_set_configuration() Exiting the program"
) )
try: try:
state = self.app.core.get_session_state() if not self.app.core.is_runtime():
if (
state == core_pb2.SessionState.SHUTDOWN
or state == core_pb2.SessionState.DEFINITION
):
self.app.core.delete_session() self.app.core.delete_session()
if quitapp: if quitapp:
self.app.quit() self.app.quit()
@ -73,7 +67,7 @@ class MenuAction:
elif quitapp: elif quitapp:
self.app.quit() self.app.quit()
except grpc.RpcError: except grpc.RpcError:
logging.error("error getting session state") logging.exception("error deleting session")
if quitapp: if quitapp:
self.app.quit() self.app.quit()