fix merge conflict
This commit is contained in:
commit
9cd756f2dc
18 changed files with 126 additions and 56 deletions
|
@ -335,7 +335,7 @@ class CoreClient:
|
|||
self.parse_metadata(response.config)
|
||||
|
||||
except grpc.RpcError as e:
|
||||
self.app.after(0, show_grpc_error, e)
|
||||
self.app.after(0, show_grpc_error, e, self.app, self.app)
|
||||
|
||||
# update ui to represent current state
|
||||
self.app.after(0, self.app.joined_session_update)
|
||||
|
@ -423,16 +423,20 @@ class CoreClient:
|
|||
)
|
||||
self.join_session(response.session_id, query_location=False)
|
||||
except grpc.RpcError as e:
|
||||
self.app.after(0, show_grpc_error, e)
|
||||
self.app.after(0, show_grpc_error, e, self.app, self.app)
|
||||
|
||||
def delete_session(self, session_id: int = None):
|
||||
def delete_session(self, session_id: int = None, parent_frame=None):
|
||||
if session_id is None:
|
||||
session_id = self.session_id
|
||||
try:
|
||||
response = self.client.delete_session(session_id)
|
||||
logging.info("deleted session(%s), Result: %s", session_id, response)
|
||||
except grpc.RpcError as e:
|
||||
self.app.after(0, show_grpc_error, e)
|
||||
# use the right master widget so the error dialog displays right on top of it
|
||||
master = self.app
|
||||
if parent_frame:
|
||||
master = parent_frame
|
||||
self.app.after(0, show_grpc_error, e, master, self.app)
|
||||
|
||||
def set_up(self):
|
||||
"""
|
||||
|
@ -468,7 +472,7 @@ class CoreClient:
|
|||
x.node_type: set(x.services) for x in response.defaults
|
||||
}
|
||||
except grpc.RpcError as e:
|
||||
self.app.after(0, show_grpc_error, e)
|
||||
self.app.after(0, show_grpc_error, e, self.app, self.app)
|
||||
self.app.close()
|
||||
|
||||
def edit_node(self, core_node: core_pb2.Node):
|
||||
|
@ -477,7 +481,7 @@ class CoreClient:
|
|||
self.session_id, core_node.id, core_node.position, source=GUI_SOURCE
|
||||
)
|
||||
except grpc.RpcError as e:
|
||||
self.app.after(0, show_grpc_error, e)
|
||||
self.app.after(0, show_grpc_error, e, self.app, self.app)
|
||||
|
||||
def start_session(self) -> core_pb2.StartSessionResponse:
|
||||
nodes = [x.core_node for x in self.canvas_nodes.values()]
|
||||
|
@ -521,7 +525,7 @@ class CoreClient:
|
|||
if response.result:
|
||||
self.set_metadata()
|
||||
except grpc.RpcError as e:
|
||||
self.app.after(0, show_grpc_error, e)
|
||||
self.app.after(0, show_grpc_error, e, self.app, self.app)
|
||||
return response
|
||||
|
||||
def stop_session(self, session_id: int = None) -> core_pb2.StartSessionResponse:
|
||||
|
@ -532,7 +536,7 @@ class CoreClient:
|
|||
response = self.client.stop_session(session_id)
|
||||
logging.info("stopped session(%s), result: %s", session_id, response)
|
||||
except grpc.RpcError as e:
|
||||
self.app.after(0, show_grpc_error, e)
|
||||
self.app.after(0, show_grpc_error, e, self.app, self.app)
|
||||
return response
|
||||
|
||||
def show_mobility_players(self):
|
||||
|
@ -577,7 +581,7 @@ class CoreClient:
|
|||
logging.info("launching terminal %s", cmd)
|
||||
os.system(cmd)
|
||||
except grpc.RpcError as e:
|
||||
self.app.after(0, show_grpc_error, e)
|
||||
self.app.after(0, show_grpc_error, e, self.app, self.app)
|
||||
|
||||
def save_xml(self, file_path: str):
|
||||
"""
|
||||
|
@ -590,7 +594,7 @@ class CoreClient:
|
|||
response = self.client.save_xml(self.session_id, file_path)
|
||||
logging.info("saved xml file %s, result: %s", file_path, response)
|
||||
except grpc.RpcError as e:
|
||||
self.app.after(0, show_grpc_error, e)
|
||||
self.app.after(0, show_grpc_error, e, self.app, self.app)
|
||||
|
||||
def open_xml(self, file_path: str):
|
||||
"""
|
||||
|
@ -601,7 +605,7 @@ class CoreClient:
|
|||
logging.info("open xml file %s, response: %s", file_path, response)
|
||||
self.join_session(response.session_id)
|
||||
except grpc.RpcError as e:
|
||||
self.app.after(0, show_grpc_error, e)
|
||||
self.app.after(0, show_grpc_error, e, self.app, self.app)
|
||||
|
||||
def get_node_service(
|
||||
self, node_id: int, service_name: str
|
||||
|
|
BIN
daemon/core/gui/data/icons/error.png
Normal file
BIN
daemon/core/gui/data/icons/error.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 2.2 KiB |
|
@ -65,8 +65,13 @@ class ConfigServiceConfigDialog(Dialog):
|
|||
self.config_frame = None
|
||||
self.default_config = None
|
||||
self.config = None
|
||||
|
||||
self.has_error = False
|
||||
|
||||
self.load()
|
||||
self.draw()
|
||||
|
||||
if not self.has_error:
|
||||
self.draw()
|
||||
|
||||
def load(self):
|
||||
try:
|
||||
|
@ -106,7 +111,8 @@ class ConfigServiceConfigDialog(Dialog):
|
|||
self.modified_files.add(file)
|
||||
self.temp_service_files[file] = data
|
||||
except grpc.RpcError as e:
|
||||
show_grpc_error(e)
|
||||
self.has_error = True
|
||||
show_grpc_error(e, self.app, self.app)
|
||||
|
||||
def draw(self):
|
||||
self.top.columnconfigure(0, weight=1)
|
||||
|
@ -327,7 +333,7 @@ class ConfigServiceConfigDialog(Dialog):
|
|||
all_current = current_listbox.get(0, tk.END)
|
||||
current_listbox.itemconfig(all_current.index(self.service_name), bg="green")
|
||||
except grpc.RpcError as e:
|
||||
show_grpc_error(e)
|
||||
show_grpc_error(e, self.top, self.app)
|
||||
self.destroy()
|
||||
|
||||
def handle_template_changed(self, event: tk.Event):
|
||||
|
|
|
@ -65,14 +65,16 @@ class EmaneModelDialog(Dialog):
|
|||
self.model = f"emane_{model}"
|
||||
self.interface = interface
|
||||
self.config_frame = None
|
||||
self.has_error = False
|
||||
try:
|
||||
self.config = self.app.core.get_emane_model_config(
|
||||
self.node.id, self.model, self.interface
|
||||
)
|
||||
self.draw()
|
||||
except grpc.RpcError as e:
|
||||
show_grpc_error(e)
|
||||
show_grpc_error(e, self.app, self.app)
|
||||
self.has_error = True
|
||||
self.destroy()
|
||||
self.draw()
|
||||
|
||||
def draw(self):
|
||||
self.top.columnconfigure(0, weight=1)
|
||||
|
@ -225,7 +227,8 @@ class EmaneConfigDialog(Dialog):
|
|||
dialog = EmaneModelDialog(
|
||||
self, self.app, self.canvas_node.core_node, model_name
|
||||
)
|
||||
dialog.show()
|
||||
if not dialog.has_error:
|
||||
dialog.show()
|
||||
|
||||
def emane_model_change(self, event: tk.Event):
|
||||
"""
|
||||
|
|
|
@ -29,12 +29,14 @@ class MobilityConfigDialog(Dialog):
|
|||
self.canvas_node = canvas_node
|
||||
self.node = canvas_node.core_node
|
||||
self.config_frame = None
|
||||
self.has_error = False
|
||||
try:
|
||||
self.config = self.app.core.get_mobility_config(self.node.id)
|
||||
self.draw()
|
||||
except grpc.RpcError as e:
|
||||
show_grpc_error(e)
|
||||
self.has_error = True
|
||||
show_grpc_error(e, self.app, self.app)
|
||||
self.destroy()
|
||||
self.draw()
|
||||
|
||||
def draw(self):
|
||||
self.top.columnconfigure(0, weight=1)
|
||||
|
|
|
@ -153,7 +153,7 @@ class MobilityPlayerDialog(Dialog):
|
|||
session_id, self.node.id, MobilityAction.START
|
||||
)
|
||||
except grpc.RpcError as e:
|
||||
show_grpc_error(e)
|
||||
show_grpc_error(e, self.top, self.app)
|
||||
|
||||
def click_pause(self):
|
||||
self.set_pause()
|
||||
|
@ -163,7 +163,7 @@ class MobilityPlayerDialog(Dialog):
|
|||
session_id, self.node.id, MobilityAction.PAUSE
|
||||
)
|
||||
except grpc.RpcError as e:
|
||||
show_grpc_error(e)
|
||||
show_grpc_error(e, self.top, self.app)
|
||||
|
||||
def click_stop(self):
|
||||
self.set_stop()
|
||||
|
@ -173,4 +173,4 @@ class MobilityPlayerDialog(Dialog):
|
|||
session_id, self.node.id, MobilityAction.STOP
|
||||
)
|
||||
except grpc.RpcError as e:
|
||||
show_grpc_error(e)
|
||||
show_grpc_error(e, self.top, self.app)
|
||||
|
|
|
@ -124,7 +124,8 @@ class NodeConfigServiceDialog(Dialog):
|
|||
service_name=self.current.listbox.get(current_selection[0]),
|
||||
node_id=self.node_id,
|
||||
)
|
||||
dialog.show()
|
||||
if not dialog.has_error:
|
||||
dialog.show()
|
||||
else:
|
||||
messagebox.showinfo(
|
||||
"Node service configuration", "Select a service to configure"
|
||||
|
|
|
@ -140,7 +140,12 @@ class NodeServiceDialog(Dialog):
|
|||
service_name=self.current.listbox.get(current_selection[0]),
|
||||
node_id=self.node_id,
|
||||
)
|
||||
dialog.show()
|
||||
|
||||
# if error occurred when creating ServiceConfigDialog, don't show the dialog
|
||||
if not dialog.has_error:
|
||||
dialog.show()
|
||||
else:
|
||||
dialog.destroy()
|
||||
else:
|
||||
messagebox.showinfo(
|
||||
"Node service configuration", "Select a service to configure"
|
||||
|
|
|
@ -64,10 +64,14 @@ class ServiceConfigDialog(Dialog):
|
|||
self.original_service_files = {}
|
||||
self.temp_service_files = {}
|
||||
self.modified_files = set()
|
||||
self.load()
|
||||
self.draw()
|
||||
|
||||
def load(self):
|
||||
self.has_error = False
|
||||
|
||||
self.load()
|
||||
if not self.has_error:
|
||||
self.draw()
|
||||
|
||||
def load(self) -> bool:
|
||||
try:
|
||||
self.app.core.create_nodes_and_links()
|
||||
default_config = self.app.core.get_node_service(
|
||||
|
@ -109,7 +113,8 @@ class ServiceConfigDialog(Dialog):
|
|||
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)
|
||||
self.has_error = True
|
||||
show_grpc_error(e, self.master, self.app)
|
||||
|
||||
def draw(self):
|
||||
self.top.columnconfigure(0, weight=1)
|
||||
|
@ -444,7 +449,7 @@ class ServiceConfigDialog(Dialog):
|
|||
all_current = current_listbox.get(0, tk.END)
|
||||
current_listbox.itemconfig(all_current.index(self.service_name), bg="green")
|
||||
except grpc.RpcError as e:
|
||||
show_grpc_error(e)
|
||||
show_grpc_error(e, self.top, self.app)
|
||||
self.destroy()
|
||||
|
||||
def display_service_file_data(self, event: tk.Event):
|
||||
|
|
|
@ -17,8 +17,10 @@ class SessionOptionsDialog(Dialog):
|
|||
def __init__(self, master: "Application", app: "Application"):
|
||||
super().__init__(master, app, "Session Options", modal=True)
|
||||
self.config_frame = None
|
||||
self.has_error = False
|
||||
self.config = self.get_config()
|
||||
self.draw()
|
||||
if not self.has_error:
|
||||
self.draw()
|
||||
|
||||
def get_config(self):
|
||||
try:
|
||||
|
@ -26,7 +28,8 @@ class SessionOptionsDialog(Dialog):
|
|||
response = self.app.core.client.get_session_options(session_id)
|
||||
return response.config
|
||||
except grpc.RpcError as e:
|
||||
show_grpc_error(e)
|
||||
self.has_error = True
|
||||
show_grpc_error(e, self.app, self.app)
|
||||
self.destroy()
|
||||
|
||||
def draw(self):
|
||||
|
@ -53,5 +56,5 @@ class SessionOptionsDialog(Dialog):
|
|||
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)
|
||||
show_grpc_error(e, self.top, self.app)
|
||||
self.destroy()
|
||||
|
|
|
@ -25,8 +25,10 @@ class SessionsDialog(Dialog):
|
|||
self.selected = False
|
||||
self.selected_id = None
|
||||
self.tree = None
|
||||
self.has_error = False
|
||||
self.sessions = self.get_sessions()
|
||||
self.draw()
|
||||
if not self.has_error:
|
||||
self.draw()
|
||||
|
||||
def get_sessions(self) -> Iterable[core_pb2.SessionSummary]:
|
||||
try:
|
||||
|
@ -34,7 +36,8 @@ class SessionsDialog(Dialog):
|
|||
logging.info("sessions: %s", response)
|
||||
return response.sessions
|
||||
except grpc.RpcError as e:
|
||||
show_grpc_error(e)
|
||||
show_grpc_error(e, self.app, self.app)
|
||||
self.has_error = True
|
||||
self.destroy()
|
||||
|
||||
def draw(self):
|
||||
|
@ -211,7 +214,7 @@ class SessionsDialog(Dialog):
|
|||
item = self.tree.selection()
|
||||
if item:
|
||||
sid = int(self.tree.item(item, "text"))
|
||||
self.app.core.delete_session(sid)
|
||||
self.app.core.delete_session(sid, self.top)
|
||||
self.tree.delete(item[0])
|
||||
if sid == self.app.core.session_id:
|
||||
self.click_new()
|
||||
|
|
|
@ -27,12 +27,14 @@ class WlanConfigDialog(Dialog):
|
|||
self.canvas_node = canvas_node
|
||||
self.node = canvas_node.core_node
|
||||
self.config_frame = None
|
||||
self.has_error = False
|
||||
try:
|
||||
self.config = self.app.core.get_wlan_config(self.node.id)
|
||||
self.draw()
|
||||
except grpc.RpcError as e:
|
||||
show_grpc_error(e)
|
||||
show_grpc_error(e, self.app, self.app)
|
||||
self.has_error = True
|
||||
self.destroy()
|
||||
self.draw()
|
||||
|
||||
def draw(self):
|
||||
self.top.columnconfigure(0, weight=1)
|
||||
|
|
|
@ -1,12 +1,38 @@
|
|||
from tkinter import messagebox
|
||||
from tkinter import ttk
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
from core.gui.dialogs.dialog import Dialog
|
||||
from core.gui.images import ImageEnum, Images
|
||||
from core.gui.widgets import CodeText
|
||||
|
||||
if TYPE_CHECKING:
|
||||
import grpc
|
||||
from core.gui.app import Application
|
||||
|
||||
|
||||
def show_grpc_error(e: "grpc.RpcError"):
|
||||
class ErrorDialog(Dialog):
|
||||
def __init__(self, master, app: "Application", title: str, details: str):
|
||||
super().__init__(master, app, title, modal=True)
|
||||
self.error_message = None
|
||||
self.details = details
|
||||
self.draw()
|
||||
|
||||
def draw(self):
|
||||
self.top.columnconfigure(0, weight=1)
|
||||
self.top.rowconfigure(0, weight=1)
|
||||
image = Images.get(ImageEnum.ERROR, 36)
|
||||
label = ttk.Label(self.top, image=image)
|
||||
label.image = image
|
||||
label.grid(row=0, column=0)
|
||||
self.error_message = CodeText(self.top)
|
||||
self.error_message.text.insert("1.0", self.details)
|
||||
self.error_message.text.config(state="disabled")
|
||||
self.error_message.grid(row=1, column=0, sticky="nsew")
|
||||
|
||||
|
||||
def show_grpc_error(e: "grpc.RpcError", master, app: "Application"):
|
||||
title = [x.capitalize() for x in e.code().name.lower().split("_")]
|
||||
title = " ".join(title)
|
||||
title = f"GRPC {title}"
|
||||
messagebox.showerror(title, e.details())
|
||||
dialog = ErrorDialog(master, app, title, e.details())
|
||||
dialog.show()
|
||||
|
|
|
@ -163,7 +163,7 @@ class CanvasNode:
|
|||
output = self.app.core.run(self.core_node.id)
|
||||
self.tooltip.text.set(output)
|
||||
except grpc.RpcError as e:
|
||||
show_grpc_error(e)
|
||||
show_grpc_error(e, self.app, self.app)
|
||||
|
||||
def on_leave(self, event: tk.Event):
|
||||
self.tooltip.on_leave(event)
|
||||
|
@ -238,12 +238,14 @@ class CanvasNode:
|
|||
def show_wlan_config(self):
|
||||
self.canvas.context = None
|
||||
dialog = WlanConfigDialog(self.app, self.app, self)
|
||||
dialog.show()
|
||||
if not dialog.has_error:
|
||||
dialog.show()
|
||||
|
||||
def show_mobility_config(self):
|
||||
self.canvas.context = None
|
||||
dialog = MobilityConfigDialog(self.app, self.app, self)
|
||||
dialog.show()
|
||||
if not dialog.has_error:
|
||||
dialog.show()
|
||||
|
||||
def show_mobility_player(self):
|
||||
self.canvas.context = None
|
||||
|
|
|
@ -89,3 +89,4 @@ class ImageEnum(Enum):
|
|||
DELETE = "delete"
|
||||
SHUTDOWN = "shutdown"
|
||||
CANCEL = "cancel"
|
||||
ERROR = "error"
|
||||
|
|
|
@ -9,6 +9,8 @@ import webbrowser
|
|||
from tkinter import filedialog, messagebox
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
import grpc
|
||||
|
||||
from core.gui.appconfig import XMLS_PATH
|
||||
from core.gui.dialogs.about import AboutDialog
|
||||
from core.gui.dialogs.canvassizeandscale import SizeAndScaleDialog
|
||||
|
@ -34,12 +36,18 @@ class MenuAction:
|
|||
self.app = app
|
||||
self.canvas = app.canvas
|
||||
|
||||
def cleanup_old_session(self, session_id):
|
||||
response = self.app.core.stop_session()
|
||||
self.app.core.delete_session(session_id)
|
||||
logging.info(
|
||||
"Stop session(%s) and delete it, result: %s", session_id, response.result
|
||||
)
|
||||
def cleanup_old_session(self, session_id: int):
|
||||
try:
|
||||
res = self.app.core.client.get_session(session_id)
|
||||
logging.debug("retrieve session(%s), %s", session_id, res)
|
||||
stop_response = self.app.core.stop_session()
|
||||
logging.debug("stop session(%s), result: %s", session_id, stop_response)
|
||||
delete_response = self.app.core.delete_session(session_id)
|
||||
logging.debug(
|
||||
"deleted session(%s), result: %s", session_id, delete_response
|
||||
)
|
||||
except grpc.RpcError:
|
||||
logging.debug("session is not alive")
|
||||
|
||||
def prompt_save_running_session(self, quitapp: bool = False):
|
||||
"""
|
||||
|
@ -125,7 +133,8 @@ class MenuAction:
|
|||
def session_options(self):
|
||||
logging.debug("Click options")
|
||||
dialog = SessionOptionsDialog(self.app, self.app)
|
||||
dialog.show()
|
||||
if not dialog.has_error:
|
||||
dialog.show()
|
||||
|
||||
def session_change_sessions(self):
|
||||
logging.debug("Click change sessions")
|
||||
|
|
|
@ -3,7 +3,7 @@ import time
|
|||
import tkinter as tk
|
||||
from enum import Enum
|
||||
from functools import partial
|
||||
from tkinter import messagebox, ttk
|
||||
from tkinter import ttk
|
||||
from typing import TYPE_CHECKING, Callable
|
||||
|
||||
from core.api.grpc import core_pb2
|
||||
|
@ -302,9 +302,6 @@ class Toolbar(ttk.Frame):
|
|||
self.set_runtime()
|
||||
self.app.core.set_metadata()
|
||||
self.app.core.show_mobility_players()
|
||||
else:
|
||||
message = "\n".join(response.exceptions)
|
||||
messagebox.showerror("Start Error", message)
|
||||
|
||||
def set_runtime(self):
|
||||
self.runtime_frame.tkraise()
|
||||
|
@ -490,8 +487,6 @@ class Toolbar(ttk.Frame):
|
|||
message = f"Stopped in {total:.3f} seconds"
|
||||
self.app.statusbar.set_status(message)
|
||||
self.app.canvas.stopped_session()
|
||||
if not response.result:
|
||||
messagebox.showerror("Stop Error", "Errors stopping session")
|
||||
|
||||
def update_annotation(
|
||||
self, image: "ImageTk.PhotoImage", shape_type: ShapeType, image_enum
|
||||
|
|
|
@ -208,6 +208,9 @@ bootfrr()
|
|||
fi
|
||||
|
||||
bootdaemon "zebra"
|
||||
if grep -q "^ip route " $FRR_CONF; then
|
||||
bootdaemon "staticd"
|
||||
fi
|
||||
for r in rip ripng ospf6 ospf bgp babel; do
|
||||
if grep -q "^router \\<${r}\\>" $FRR_CONF; then
|
||||
bootdaemon "${r}d"
|
||||
|
|
Loading…
Reference in a new issue