Merge branch 'coretk' into coretk-config
This commit is contained in:
commit
2cc4ef5ac0
13 changed files with 491 additions and 647 deletions
|
@ -65,12 +65,6 @@ class Application(tk.Frame):
|
|||
def draw_status(self):
|
||||
self.statusbar = tk.Frame(self)
|
||||
self.statusbar.pack(side=tk.BOTTOM, fill=tk.X)
|
||||
button = tk.Button(self.statusbar, text="Button 1")
|
||||
button.pack(side=tk.LEFT, padx=1)
|
||||
button = tk.Button(self.statusbar, text="Button 2")
|
||||
button.pack(side=tk.LEFT, padx=1)
|
||||
button = tk.Button(self.statusbar, text="Button 3")
|
||||
button.pack(side=tk.LEFT, padx=1)
|
||||
|
||||
def on_closing(self):
|
||||
menu_action = MenuAction(self, self.master)
|
||||
|
@ -78,7 +72,8 @@ class Application(tk.Frame):
|
|||
|
||||
|
||||
if __name__ == "__main__":
|
||||
logging.basicConfig(level=logging.DEBUG)
|
||||
log_format = "%(asctime)s - %(levelname)s - %(module)s:%(funcName)s - %(message)s"
|
||||
logging.basicConfig(level=logging.DEBUG, format=log_format)
|
||||
appdirs.check_directory()
|
||||
app = Application()
|
||||
app.mainloop()
|
||||
|
|
134
coretk/coretk/canvastooltip.py
Normal file
134
coretk/coretk/canvastooltip.py
Normal file
|
@ -0,0 +1,134 @@
|
|||
import tkinter as tk
|
||||
from tkinter import ttk
|
||||
|
||||
|
||||
class CanvasTooltip:
|
||||
"""
|
||||
It creates a tooltip for a given canvas tag or id as the mouse is
|
||||
above it.
|
||||
|
||||
This class has been derived from the original Tooltip class updated
|
||||
and posted back to StackOverflow at the following link:
|
||||
|
||||
https://stackoverflow.com/questions/3221956/
|
||||
what-is-the-simplest-way-to-make-tooltips-in-tkinter/
|
||||
41079350#41079350
|
||||
|
||||
Alberto Vassena on 2016.12.10.
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
canvas,
|
||||
tag_or_id,
|
||||
*,
|
||||
bg="#FFFFEA",
|
||||
pad=(5, 3, 5, 3),
|
||||
text="canvas info",
|
||||
waittime=400,
|
||||
wraplength=250
|
||||
):
|
||||
# in miliseconds, originally 500
|
||||
self.waittime = waittime
|
||||
# in pixels, originally 180
|
||||
self.wraplength = wraplength
|
||||
self.canvas = canvas
|
||||
self.text = text
|
||||
self.canvas.tag_bind(tag_or_id, "<Enter>", self.on_enter)
|
||||
self.canvas.tag_bind(tag_or_id, "<Leave>", self.on_leave)
|
||||
self.canvas.tag_bind(tag_or_id, "<ButtonPress>", self.on_leave)
|
||||
self.bg = bg
|
||||
self.pad = pad
|
||||
self.id = None
|
||||
self.tw = None
|
||||
|
||||
def on_enter(self, event=None):
|
||||
self.schedule()
|
||||
|
||||
def on_leave(self, event=None):
|
||||
self.unschedule()
|
||||
self.hide()
|
||||
|
||||
def schedule(self):
|
||||
self.unschedule()
|
||||
self.id = self.canvas.after(self.waittime, self.show)
|
||||
|
||||
def unschedule(self):
|
||||
id_ = self.id
|
||||
self.id = None
|
||||
if id_:
|
||||
self.canvas.after_cancel(id_)
|
||||
|
||||
def show(self, event=None):
|
||||
def tip_pos_calculator(canvas, label, *, tip_delta=(10, 5), pad=(5, 3, 5, 3)):
|
||||
|
||||
c = canvas
|
||||
|
||||
s_width, s_height = c.winfo_screenwidth(), c.winfo_screenheight()
|
||||
|
||||
width, height = (
|
||||
pad[0] + label.winfo_reqwidth() + pad[2],
|
||||
pad[1] + label.winfo_reqheight() + pad[3],
|
||||
)
|
||||
|
||||
mouse_x, mouse_y = c.winfo_pointerxy()
|
||||
|
||||
x1, y1 = mouse_x + tip_delta[0], mouse_y + tip_delta[1]
|
||||
x2, y2 = x1 + width, y1 + height
|
||||
|
||||
x_delta = x2 - s_width
|
||||
if x_delta < 0:
|
||||
x_delta = 0
|
||||
y_delta = y2 - s_height
|
||||
if y_delta < 0:
|
||||
y_delta = 0
|
||||
|
||||
offscreen = (x_delta, y_delta) != (0, 0)
|
||||
|
||||
if offscreen:
|
||||
|
||||
if x_delta:
|
||||
x1 = mouse_x - tip_delta[0] - width
|
||||
|
||||
if y_delta:
|
||||
y1 = mouse_y - tip_delta[1] - height
|
||||
|
||||
offscreen_again = y1 < 0 # out on the top
|
||||
|
||||
if offscreen_again:
|
||||
y1 = 0
|
||||
|
||||
return x1, y1
|
||||
|
||||
bg = self.bg
|
||||
pad = self.pad
|
||||
canvas = self.canvas
|
||||
|
||||
# creates a toplevel window
|
||||
self.tw = tk.Toplevel(canvas.master)
|
||||
|
||||
# Leaves only the label and removes the app window
|
||||
self.tw.wm_overrideredirect(True)
|
||||
|
||||
win = tk.Frame(self.tw, background=bg, borderwidth=0)
|
||||
label = ttk.Label(
|
||||
win,
|
||||
text=self.text,
|
||||
justify=tk.LEFT,
|
||||
background=bg,
|
||||
relief=tk.SOLID,
|
||||
borderwidth=0,
|
||||
wraplength=self.wraplength,
|
||||
)
|
||||
|
||||
label.grid(padx=(pad[0], pad[2]), pady=(pad[1], pad[3]), sticky=tk.NSEW)
|
||||
win.grid()
|
||||
|
||||
x, y = tip_pos_calculator(canvas, label)
|
||||
|
||||
self.tw.wm_geometry("+%d+%d" % (x, y))
|
||||
|
||||
def hide(self):
|
||||
if self.tw:
|
||||
self.tw.destroy()
|
||||
self.tw = None
|
|
@ -14,8 +14,8 @@ from coretk.mobilitynodeconfig import MobilityNodeConfig
|
|||
from coretk.servicenodeconfig import ServiceNodeConfig
|
||||
from coretk.wlannodeconfig import WlanNodeConfig
|
||||
|
||||
link_layer_nodes = ["switch", "hub", "wlan", "rj45", "tunnel", "emane"]
|
||||
network_layer_nodes = ["router", "host", "PC", "mdr", "prouter"]
|
||||
NETWORK_NODES = {"switch", "hub", "wlan", "rj45", "tunnel", "emane"}
|
||||
DEFAULT_NODES = {"router", "host", "PC", "mdr", "prouter"}
|
||||
|
||||
|
||||
class Node:
|
||||
|
@ -418,6 +418,9 @@ class CoreClient:
|
|||
else:
|
||||
return self.reusable.pop(0)
|
||||
|
||||
def is_model_node(self, name):
|
||||
return name in DEFAULT_NODES or name in self.custom_nodes
|
||||
|
||||
def add_graph_node(self, session_id, canvas_id, x, y, name):
|
||||
"""
|
||||
Add node, with information filled in, to grpc manager
|
||||
|
@ -431,7 +434,7 @@ class CoreClient:
|
|||
"""
|
||||
node_type = None
|
||||
node_model = None
|
||||
if name in link_layer_nodes:
|
||||
if name in NETWORK_NODES:
|
||||
if name == "switch":
|
||||
node_type = core_pb2.NodeType.SWITCH
|
||||
elif name == "hub":
|
||||
|
@ -446,7 +449,7 @@ class CoreClient:
|
|||
node_type = core_pb2.NodeType.TUNNEL
|
||||
elif name == "emane":
|
||||
node_type = core_pb2.NodeType.EMANE
|
||||
elif name in network_layer_nodes:
|
||||
elif self.is_model_node(name):
|
||||
node_type = core_pb2.NodeType.DEFAULT
|
||||
node_model = name
|
||||
else:
|
||||
|
@ -621,7 +624,7 @@ class CoreClient:
|
|||
self.interfaces_manager.new_subnet()
|
||||
|
||||
src_node = self.nodes[src_canvas_id]
|
||||
if src_node.model in network_layer_nodes:
|
||||
if self.is_model_node(src_node.model):
|
||||
ifid = len(src_node.interfaces)
|
||||
name = "eth" + str(ifid)
|
||||
src_interface = Interface(
|
||||
|
@ -635,7 +638,7 @@ class CoreClient:
|
|||
)
|
||||
|
||||
dst_node = self.nodes[dst_canvas_id]
|
||||
if dst_node.model in network_layer_nodes:
|
||||
if self.is_model_node(dst_node.model):
|
||||
ifid = len(dst_node.interfaces)
|
||||
name = "eth" + str(ifid)
|
||||
dst_interface = Interface(
|
||||
|
|
|
@ -15,7 +15,7 @@ class ServicesSelectDialog(Dialog):
|
|||
self.groups = None
|
||||
self.services = None
|
||||
self.current = None
|
||||
self.current_services = current_services
|
||||
self.current_services = set(current_services)
|
||||
self.draw()
|
||||
|
||||
def draw(self):
|
||||
|
@ -48,7 +48,7 @@ class ServicesSelectDialog(Dialog):
|
|||
frame.grid(stick="ew")
|
||||
for i in range(2):
|
||||
frame.columnconfigure(i, weight=1)
|
||||
button = tk.Button(frame, text="Save", command=self.click_cancel)
|
||||
button = tk.Button(frame, text="Save", command=self.destroy)
|
||||
button.grid(row=0, column=0, sticky="ew")
|
||||
button = tk.Button(frame, text="Cancel", command=self.click_cancel)
|
||||
button.grid(row=0, column=1, sticky="ew")
|
||||
|
@ -174,7 +174,8 @@ class CustomNodesDialog(Dialog):
|
|||
dialog = ServicesSelectDialog(self, self.app, self.services)
|
||||
dialog.show()
|
||||
if dialog.current_services is not None:
|
||||
self.services = dialog.current_services
|
||||
self.services.clear()
|
||||
self.services.update(dialog.current_services)
|
||||
|
||||
def click_save(self):
|
||||
self.app.config["nodes"].clear()
|
||||
|
@ -208,7 +209,7 @@ class CustomNodesDialog(Dialog):
|
|||
custom_node = self.app.core.custom_nodes.pop(previous_name)
|
||||
custom_node.name = name
|
||||
custom_node.image = self.image
|
||||
custom_node.image_file = Path(self.image_file).name
|
||||
custom_node.image_file = Path(self.image_file).stem
|
||||
custom_node.services = self.services
|
||||
self.app.core.custom_nodes[name] = custom_node
|
||||
self.nodes_list.listbox.delete(self.selected_index)
|
||||
|
|
|
@ -4,6 +4,7 @@ import tkinter as tk
|
|||
|
||||
from core.api.grpc import core_pb2
|
||||
from coretk.canvasaction import CanvasAction
|
||||
from coretk.canvastooltip import CanvasTooltip
|
||||
from coretk.graph_helper import GraphHelper, WlanAntennaManager
|
||||
from coretk.images import Images
|
||||
from coretk.interface import Interface
|
||||
|
@ -512,6 +513,7 @@ class CanvasNode:
|
|||
self.canvas.tag_bind(self.id, "<Button-3>", self.context)
|
||||
self.canvas.tag_bind(self.id, "<Double-Button-1>", self.double_click)
|
||||
self.canvas.tag_bind(self.id, "<Control-1>", self.select_multiple)
|
||||
self.tooltip = CanvasTooltip(self.canvas, self.id, text=self.name)
|
||||
|
||||
self.edges = set()
|
||||
self.wlans = []
|
||||
|
|
|
@ -17,214 +17,6 @@ from coretk.dialogs.sessionoptions import SessionOptionsDialog
|
|||
from coretk.dialogs.sessions import SessionsDialog
|
||||
|
||||
|
||||
def sub_menu_items():
|
||||
logging.debug("Click on sub menu items")
|
||||
|
||||
|
||||
def file_new(event=None):
|
||||
logging.debug("Click file New")
|
||||
|
||||
|
||||
def file_reload():
|
||||
logging.debug("Click file Reload")
|
||||
|
||||
|
||||
def file_export_python_script():
|
||||
logging.debug("Click file export python script")
|
||||
|
||||
|
||||
def file_execute_xml_or_python_script():
|
||||
logging.debug("Execute XML or Python script")
|
||||
|
||||
|
||||
def file_execute_python_script_with_options():
|
||||
logging.debug("Click execute Python script with options")
|
||||
|
||||
|
||||
def file_open_current_file_in_editor():
|
||||
logging.debug("Click file open current in editor")
|
||||
|
||||
|
||||
def file_print():
|
||||
logging.debug("Click file Print")
|
||||
|
||||
|
||||
def file_save_screenshot():
|
||||
logging.debug("Click file save screenshot")
|
||||
|
||||
|
||||
def edit_undo(event=None):
|
||||
logging.debug("Click edit undo")
|
||||
|
||||
|
||||
def edit_redo(event=None):
|
||||
logging.debug("Click edit redo")
|
||||
|
||||
|
||||
def edit_cut(event=None):
|
||||
logging.debug("Click edit cut")
|
||||
|
||||
|
||||
def edit_copy(event=None):
|
||||
logging.debug("Click edit copy")
|
||||
|
||||
|
||||
def edit_paste(event=None):
|
||||
logging.debug("Click edit paste")
|
||||
|
||||
|
||||
def edit_select_all(event=None):
|
||||
logging.debug("Click edit select all")
|
||||
|
||||
|
||||
def edit_select_adjacent(event=None):
|
||||
logging.debug("Click edit select adjacent")
|
||||
|
||||
|
||||
def edit_find(event=None):
|
||||
logging.debug("CLick edit find")
|
||||
|
||||
|
||||
def edit_clear_marker():
|
||||
logging.debug("Click edit clear marker")
|
||||
|
||||
|
||||
def edit_preferences():
|
||||
logging.debug("Click preferences")
|
||||
|
||||
|
||||
def canvas_new():
|
||||
logging.debug("Click canvas new")
|
||||
|
||||
|
||||
def canvas_manage():
|
||||
logging.debug("Click canvas manage")
|
||||
|
||||
|
||||
def canvas_delete():
|
||||
logging.debug("Click canvas delete")
|
||||
|
||||
|
||||
def canvas_previous(event=None):
|
||||
logging.debug("Click canvas previous")
|
||||
|
||||
|
||||
def canvas_next(event=None):
|
||||
logging.debug("Click canvas next")
|
||||
|
||||
|
||||
def canvas_first(event=None):
|
||||
logging.debug("CLick canvas first")
|
||||
|
||||
|
||||
def canvas_last(event=None):
|
||||
logging.debug("CLick canvas last")
|
||||
|
||||
|
||||
def view_show():
|
||||
logging.debug("Click view show")
|
||||
|
||||
|
||||
def view_show_hidden_nodes():
|
||||
logging.debug("Click view show hidden nodes")
|
||||
|
||||
|
||||
def view_locked():
|
||||
logging.debug("Click view locked")
|
||||
|
||||
|
||||
def view_3d_gui():
|
||||
logging.debug("CLick view 3D GUI")
|
||||
|
||||
|
||||
def view_zoom_in(event=None):
|
||||
logging.debug("Click view zoom in")
|
||||
|
||||
|
||||
def view_zoom_out(event=None):
|
||||
logging.debug("Click view zoom out")
|
||||
|
||||
|
||||
def tools_auto_rearrange_all():
|
||||
logging.debug("Click tools, auto rearrange all")
|
||||
|
||||
|
||||
def tools_auto_rearrange_selected():
|
||||
logging.debug("CLick tools auto rearrange selected")
|
||||
|
||||
|
||||
def tools_align_to_grid():
|
||||
logging.debug("Click tools align to grid")
|
||||
|
||||
|
||||
def tools_traffic():
|
||||
logging.debug("Click tools traffic")
|
||||
|
||||
|
||||
def tools_ip_addresses():
|
||||
logging.debug("Click tools ip addresses")
|
||||
|
||||
|
||||
def tools_mac_addresses():
|
||||
logging.debug("Click tools mac addresses")
|
||||
|
||||
|
||||
def tools_build_hosts_file():
|
||||
logging.debug("Click tools build hosts file")
|
||||
|
||||
|
||||
def tools_renumber_nodes():
|
||||
logging.debug("Click tools renumber nodes")
|
||||
|
||||
|
||||
def tools_experimental():
|
||||
logging.debug("Click tools experimental")
|
||||
|
||||
|
||||
def tools_topology_generator():
|
||||
logging.debug("Click tools topology generator")
|
||||
|
||||
|
||||
def tools_debugger():
|
||||
logging.debug("Click tools debugger")
|
||||
|
||||
|
||||
def widgets_observer_widgets():
|
||||
logging.debug("Click widgets observer widgets")
|
||||
|
||||
|
||||
def widgets_adjacency():
|
||||
logging.debug("Click widgets adjacency")
|
||||
|
||||
|
||||
def widgets_throughput():
|
||||
logging.debug("Click widgets throughput")
|
||||
|
||||
|
||||
def widgets_configure_adjacency():
|
||||
logging.debug("Click widgets configure adjacency")
|
||||
|
||||
|
||||
def widgets_configure_throughput():
|
||||
logging.debug("Click widgets configure throughput")
|
||||
|
||||
|
||||
def session_node_types():
|
||||
logging.debug("Click session node types")
|
||||
|
||||
|
||||
def session_comments():
|
||||
logging.debug("Click session comments")
|
||||
|
||||
|
||||
def session_reset_node_positions():
|
||||
logging.debug("Click session reset node positions")
|
||||
|
||||
|
||||
def help_about():
|
||||
logging.debug("Click help About")
|
||||
|
||||
|
||||
class MenuAction:
|
||||
"""
|
||||
Actions performed when choosing menu items
|
||||
|
@ -258,7 +50,7 @@ class MenuAction:
|
|||
self.app.core.stop_session()
|
||||
self.app.core.delete_session()
|
||||
|
||||
def on_quit(self):
|
||||
def on_quit(self, event=None):
|
||||
"""
|
||||
Prompt user whether so save running session, and then close the application
|
||||
|
||||
|
|
|
@ -43,52 +43,33 @@ class Menubar(tk.Menu):
|
|||
|
||||
:return: nothing
|
||||
"""
|
||||
file_menu = tk.Menu(self)
|
||||
file_menu.add_command(
|
||||
label="New Session",
|
||||
command=action.file_new,
|
||||
accelerator="Ctrl+N",
|
||||
underline=0,
|
||||
)
|
||||
self.app.bind_all("<Control-n>", action.file_new)
|
||||
file_menu.add_command(
|
||||
label="Open...",
|
||||
command=self.menuaction.file_open_xml,
|
||||
accelerator="Ctrl+O",
|
||||
underline=0,
|
||||
menu = tk.Menu(self)
|
||||
menu.add_command(label="New Session", accelerator="Ctrl+N", state=tk.DISABLED)
|
||||
menu.add_command(
|
||||
label="Open...", command=self.menuaction.file_open_xml, accelerator="Ctrl+O"
|
||||
)
|
||||
self.app.bind_all("<Control-o>", self.menuaction.file_open_xml)
|
||||
file_menu.add_command(label="Reload", command=action.file_reload, underline=0)
|
||||
file_menu.add_command(
|
||||
menu.add_command(label="Reload", underline=0, state=tk.DISABLED)
|
||||
menu.add_command(
|
||||
label="Save", accelerator="Ctrl+S", command=self.menuaction.file_save_as_xml
|
||||
)
|
||||
self.app.bind_all("<Control-s>", self.menuaction.file_save_as_xml)
|
||||
file_menu.add_separator()
|
||||
file_menu.add_command(
|
||||
label="Export Python script...", command=action.file_export_python_script
|
||||
menu.add_separator()
|
||||
menu.add_command(label="Export Python script...", state=tk.DISABLED)
|
||||
menu.add_command(label="Execute XML or Python script...", state=tk.DISABLED)
|
||||
menu.add_command(
|
||||
label="Execute Python script with options...", state=tk.DISABLED
|
||||
)
|
||||
file_menu.add_command(
|
||||
label="Execute XML or Python script...",
|
||||
command=action.file_execute_xml_or_python_script,
|
||||
menu.add_separator()
|
||||
menu.add_command(label="Open current file in editor...", state=tk.DISABLED)
|
||||
menu.add_command(label="Print...", underline=0, state=tk.DISABLED)
|
||||
menu.add_command(label="Save screenshot...", state=tk.DISABLED)
|
||||
menu.add_separator()
|
||||
menu.add_command(
|
||||
label="Quit", accelerator="Ctrl+Q", command=self.menuaction.on_quit
|
||||
)
|
||||
file_menu.add_command(
|
||||
label="Execute Python script with options...",
|
||||
command=action.file_execute_python_script_with_options,
|
||||
)
|
||||
file_menu.add_separator()
|
||||
file_menu.add_command(
|
||||
label="Open current file in editor...",
|
||||
command=action.file_open_current_file_in_editor,
|
||||
)
|
||||
file_menu.add_command(label="Print...", command=action.file_print, underline=0)
|
||||
file_menu.add_command(
|
||||
label="Save screenshot...", command=action.file_save_screenshot
|
||||
)
|
||||
file_menu.add_separator()
|
||||
file_menu.add_command(
|
||||
label="Quit", command=self.menuaction.on_quit, underline=0
|
||||
)
|
||||
self.add_cascade(label="File", menu=file_menu, underline=0)
|
||||
self.app.bind_all("<Control-q>", self.menuaction.on_quit)
|
||||
self.add_cascade(label="File", menu=menu)
|
||||
|
||||
def draw_edit_menu(self):
|
||||
"""
|
||||
|
@ -96,47 +77,23 @@ class Menubar(tk.Menu):
|
|||
|
||||
:return: nothing
|
||||
"""
|
||||
edit_menu = tk.Menu(self)
|
||||
edit_menu.add_command(
|
||||
label="Undo", command=action.edit_undo, accelerator="Ctrl+Z", underline=0
|
||||
menu = tk.Menu(self)
|
||||
menu.add_command(label="Undo", accelerator="Ctrl+Z", state=tk.DISABLED)
|
||||
menu.add_command(label="Redo", accelerator="Ctrl+Y", state=tk.DISABLED)
|
||||
menu.add_separator()
|
||||
menu.add_command(label="Cut", accelerator="Ctrl+X", state=tk.DISABLED)
|
||||
menu.add_command(label="Copy", accelerator="Ctrl+C", state=tk.DISABLED)
|
||||
menu.add_command(label="Paste", accelerator="Ctrl+V", state=tk.DISABLED)
|
||||
menu.add_separator()
|
||||
menu.add_command(label="Select all", accelerator="Ctrl+A", state=tk.DISABLED)
|
||||
menu.add_command(
|
||||
label="Select Adjacent", accelerator="Ctrl+J", state=tk.DISABLED
|
||||
)
|
||||
self.app.bind_all("<Control-z>", action.edit_undo)
|
||||
edit_menu.add_command(
|
||||
label="Redo", command=action.edit_redo, accelerator="Ctrl+Y", underline=0
|
||||
)
|
||||
self.app.bind_all("<Control-y>", action.edit_redo)
|
||||
edit_menu.add_separator()
|
||||
edit_menu.add_command(
|
||||
label="Cut", command=action.edit_cut, accelerator="Ctrl+X", underline=0
|
||||
)
|
||||
self.app.bind_all("<Control-x>", action.edit_cut)
|
||||
edit_menu.add_command(
|
||||
label="Copy", command=action.edit_copy, accelerator="Ctrl+C", underline=0
|
||||
)
|
||||
self.app.bind_all("<Control-c>", action.edit_copy)
|
||||
edit_menu.add_command(
|
||||
label="Paste", command=action.edit_paste, accelerator="Ctrl+V", underline=0
|
||||
)
|
||||
self.app.bind_all("<Control-v>", action.edit_paste)
|
||||
edit_menu.add_separator()
|
||||
edit_menu.add_command(
|
||||
label="Select all", command=action.edit_select_all, accelerator="Ctrl+A"
|
||||
)
|
||||
self.app.bind_all("<Control-a>", action.edit_select_all)
|
||||
edit_menu.add_command(
|
||||
label="Select Adjacent",
|
||||
command=action.edit_select_adjacent,
|
||||
accelerator="Ctrl+J",
|
||||
)
|
||||
self.app.bind_all("<Control-j>", action.edit_select_adjacent)
|
||||
edit_menu.add_separator()
|
||||
edit_menu.add_command(
|
||||
label="Find...", command=action.edit_find, accelerator="Ctrl+F", underline=0
|
||||
)
|
||||
self.app.bind_all("<Control-f>", action.edit_find)
|
||||
edit_menu.add_command(label="Clear marker", command=action.edit_clear_marker)
|
||||
edit_menu.add_command(label="Preferences...", command=action.edit_preferences)
|
||||
self.add_cascade(label="Edit", menu=edit_menu, underline=0)
|
||||
menu.add_separator()
|
||||
menu.add_command(label="Find...", accelerator="Ctrl+F", state=tk.DISABLED)
|
||||
menu.add_command(label="Clear marker", state=tk.DISABLED)
|
||||
menu.add_command(label="Preferences...", state=tk.DISABLED)
|
||||
self.add_cascade(label="Edit", menu=menu)
|
||||
|
||||
def draw_canvas_menu(self):
|
||||
"""
|
||||
|
@ -144,55 +101,23 @@ class Menubar(tk.Menu):
|
|||
|
||||
:return: nothing
|
||||
"""
|
||||
canvas_menu = tk.Menu(self)
|
||||
canvas_menu.add_command(label="New", command=action.canvas_new)
|
||||
canvas_menu.add_command(label="Manage...", command=action.canvas_manage)
|
||||
canvas_menu.add_command(label="Delete", command=action.canvas_delete)
|
||||
canvas_menu.add_separator()
|
||||
canvas_menu.add_command(
|
||||
menu = tk.Menu(self)
|
||||
menu.add_command(label="New", state=tk.DISABLED)
|
||||
menu.add_command(label="Manage...", state=tk.DISABLED)
|
||||
menu.add_command(label="Delete", state=tk.DISABLED)
|
||||
menu.add_separator()
|
||||
menu.add_command(
|
||||
label="Size/scale...", command=self.menuaction.canvas_size_and_scale
|
||||
)
|
||||
canvas_menu.add_command(
|
||||
menu.add_command(
|
||||
label="Wallpaper...", command=self.menuaction.canvas_set_wallpaper
|
||||
)
|
||||
canvas_menu.add_separator()
|
||||
canvas_menu.add_command(
|
||||
label="Previous", command=action.canvas_previous, accelerator="PgUp"
|
||||
)
|
||||
self.app.bind_all("<Prior>", action.canvas_previous)
|
||||
canvas_menu.add_command(
|
||||
label="Next", command=action.canvas_next, accelerator="PgDown"
|
||||
)
|
||||
self.app.bind_all("<Next>", action.canvas_next)
|
||||
canvas_menu.add_command(
|
||||
label="First", command=action.canvas_first, accelerator="Home"
|
||||
)
|
||||
self.app.bind_all("<Home>", action.canvas_first)
|
||||
canvas_menu.add_command(
|
||||
label="Last", command=action.canvas_last, accelerator="End"
|
||||
)
|
||||
self.app.bind_all("<End>", action.canvas_last)
|
||||
self.add_cascade(label="Canvas", menu=canvas_menu, underline=0)
|
||||
|
||||
def create_show_menu(self, view_menu):
|
||||
"""
|
||||
Create the menu items in View/Show
|
||||
|
||||
:param tkinter.Menu view_menu: the view menu
|
||||
:return: nothing
|
||||
"""
|
||||
show_menu = tk.Menu(view_menu)
|
||||
show_menu.add_command(label="All", command=action.sub_menu_items)
|
||||
show_menu.add_command(label="None", command=action.sub_menu_items)
|
||||
show_menu.add_separator()
|
||||
show_menu.add_command(label="Interface Names", command=action.sub_menu_items)
|
||||
show_menu.add_command(label="IPv4 Addresses", command=action.sub_menu_items)
|
||||
show_menu.add_command(label="IPv6 Addresses", command=action.sub_menu_items)
|
||||
show_menu.add_command(label="Node Labels", command=action.sub_menu_items)
|
||||
show_menu.add_command(label="Annotations", command=action.sub_menu_items)
|
||||
show_menu.add_command(label="Grid", command=action.sub_menu_items)
|
||||
show_menu.add_command(label="API Messages", command=action.sub_menu_items)
|
||||
view_menu.add_cascade(label="Show", menu=show_menu)
|
||||
menu.add_separator()
|
||||
menu.add_command(label="Previous", accelerator="PgUp", state=tk.DISABLED)
|
||||
menu.add_command(label="Next", accelerator="PgDown", state=tk.DISABLED)
|
||||
menu.add_command(label="First", accelerator="Home", state=tk.DISABLED)
|
||||
menu.add_command(label="Last", accelerator="End", state=tk.DISABLED)
|
||||
self.add_cascade(label="Canvas", menu=menu)
|
||||
|
||||
def draw_view_menu(self):
|
||||
"""
|
||||
|
@ -202,21 +127,33 @@ class Menubar(tk.Menu):
|
|||
"""
|
||||
view_menu = tk.Menu(self)
|
||||
self.create_show_menu(view_menu)
|
||||
view_menu.add_command(
|
||||
label="Show hidden nodes", command=action.view_show_hidden_nodes
|
||||
)
|
||||
view_menu.add_command(label="Locked", command=action.view_locked)
|
||||
view_menu.add_command(label="3D GUI...", command=action.view_3d_gui)
|
||||
view_menu.add_command(label="Show hidden nodes", state=tk.DISABLED)
|
||||
view_menu.add_command(label="Locked", state=tk.DISABLED)
|
||||
view_menu.add_command(label="3D GUI...", state=tk.DISABLED)
|
||||
view_menu.add_separator()
|
||||
view_menu.add_command(
|
||||
label="Zoom in", command=action.view_zoom_in, accelerator="+"
|
||||
)
|
||||
self.app.bind_all("<Control-Shift-plus>", action.view_zoom_in)
|
||||
view_menu.add_command(
|
||||
label="Zoom out", command=action.view_zoom_out, accelerator="-"
|
||||
)
|
||||
self.app.bind_all("<Control-minus>", action.view_zoom_out)
|
||||
self.add_cascade(label="View", menu=view_menu, underline=0)
|
||||
view_menu.add_command(label="Zoom in", accelerator="+", state=tk.DISABLED)
|
||||
view_menu.add_command(label="Zoom out", accelerator="-", state=tk.DISABLED)
|
||||
self.add_cascade(label="View", menu=view_menu)
|
||||
|
||||
def create_show_menu(self, view_menu):
|
||||
"""
|
||||
Create the menu items in View/Show
|
||||
|
||||
:param tkinter.Menu view_menu: the view menu
|
||||
:return: nothing
|
||||
"""
|
||||
menu = tk.Menu(view_menu)
|
||||
menu.add_command(label="All", state=tk.DISABLED)
|
||||
menu.add_command(label="None", state=tk.DISABLED)
|
||||
menu.add_separator()
|
||||
menu.add_command(label="Interface Names", state=tk.DISABLED)
|
||||
menu.add_command(label="IPv4 Addresses", state=tk.DISABLED)
|
||||
menu.add_command(label="IPv6 Addresses", state=tk.DISABLED)
|
||||
menu.add_command(label="Node Labels", state=tk.DISABLED)
|
||||
menu.add_command(label="Annotations", state=tk.DISABLED)
|
||||
menu.add_command(label="Grid", state=tk.DISABLED)
|
||||
menu.add_command(label="API Messages", state=tk.DISABLED)
|
||||
view_menu.add_cascade(label="Show", menu=menu)
|
||||
|
||||
def create_experimental_menu(self, tools_menu):
|
||||
"""
|
||||
|
@ -225,19 +162,11 @@ class Menubar(tk.Menu):
|
|||
:param tkinter.Menu tools_menu: tools menu
|
||||
:return: nothing
|
||||
"""
|
||||
experimental_menu = tk.Menu(tools_menu)
|
||||
experimental_menu.add_command(
|
||||
label="Plugins...", command=action.sub_menu_items, underline=0
|
||||
)
|
||||
experimental_menu.add_command(
|
||||
label="ns2immunes converter...", command=action.sub_menu_items, underline=0
|
||||
)
|
||||
experimental_menu.add_command(
|
||||
label="Topology partitioning...", command=action.sub_menu_items
|
||||
)
|
||||
tools_menu.add_cascade(
|
||||
label="Experimental", menu=experimental_menu, underline=0
|
||||
)
|
||||
menu = tk.Menu(tools_menu)
|
||||
menu.add_command(label="Plugins...", state=tk.DISABLED)
|
||||
menu.add_command(label="ns2immunes converter...", state=tk.DISABLED)
|
||||
menu.add_command(label="Topology partitioning...", state=tk.DISABLED)
|
||||
tools_menu.add_cascade(label="Experimental", menu=menu)
|
||||
|
||||
def create_random_menu(self, topology_generator_menu):
|
||||
"""
|
||||
|
@ -246,15 +175,13 @@ class Menubar(tk.Menu):
|
|||
:param tkinter.Menu topology_generator_menu: topology generator menu
|
||||
:return: nothing
|
||||
"""
|
||||
random_menu = tk.Menu(topology_generator_menu)
|
||||
menu = tk.Menu(topology_generator_menu)
|
||||
# list of number of random nodes to create
|
||||
nums = [1, 5, 10, 15, 20, 30, 40, 50, 75, 100]
|
||||
for i in nums:
|
||||
the_label = "R(" + str(i) + ")"
|
||||
random_menu.add_command(label=the_label, command=action.sub_menu_items)
|
||||
topology_generator_menu.add_cascade(
|
||||
label="Random", menu=random_menu, underline=0
|
||||
)
|
||||
label = f"R({i})"
|
||||
menu.add_command(label=label, state=tk.DISABLED)
|
||||
topology_generator_menu.add_cascade(label="Random", menu=menu)
|
||||
|
||||
def create_grid_menu(self, topology_generator_menu):
|
||||
"""
|
||||
|
@ -263,13 +190,13 @@ class Menubar(tk.Menu):
|
|||
:param tkinter.Menu topology_generator_menu: topology_generator_menu
|
||||
:return: nothing
|
||||
"""
|
||||
grid_menu = tk.Menu(topology_generator_menu)
|
||||
menu = tk.Menu(topology_generator_menu)
|
||||
# list of number of nodes to create
|
||||
nums = [1, 5, 10, 15, 20, 25, 30, 35, 40, 50, 60, 70, 80, 90, 100]
|
||||
for i in nums:
|
||||
the_label = "G(" + str(i) + ")"
|
||||
grid_menu.add_command(label=the_label, command=action.sub_menu_items)
|
||||
topology_generator_menu.add_cascade(label="Grid", menu=grid_menu, underline=0)
|
||||
label = f"G({i})"
|
||||
menu.add_command(label=label, state=tk.DISABLED)
|
||||
topology_generator_menu.add_cascade(label="Grid", menu=menu)
|
||||
|
||||
def create_connected_grid_menu(self, topology_generator_menu):
|
||||
"""
|
||||
|
@ -278,17 +205,15 @@ class Menubar(tk.Menu):
|
|||
:param tkinter.Menu topology_generator_menu: topology generator menu
|
||||
:return: nothing
|
||||
"""
|
||||
grid_menu = tk.Menu(topology_generator_menu)
|
||||
menu = tk.Menu(topology_generator_menu)
|
||||
for i in range(1, 11, 1):
|
||||
i_n_menu = tk.Menu(grid_menu)
|
||||
submenu = tk.Menu(menu)
|
||||
for j in range(1, 11, 1):
|
||||
i_j_label = str(i) + " X " + str(j)
|
||||
i_n_menu.add_command(label=i_j_label, command=action.sub_menu_items)
|
||||
i_n_label = str(i) + " X N"
|
||||
grid_menu.add_cascade(label=i_n_label, menu=i_n_menu)
|
||||
topology_generator_menu.add_cascade(
|
||||
label="Connected Grid", menu=grid_menu, underline=0
|
||||
)
|
||||
label = f"{i} X {j}"
|
||||
submenu.add_command(label=label, state=tk.DISABLED)
|
||||
label = str(i) + " X N"
|
||||
menu.add_cascade(label=label, menu=submenu)
|
||||
topology_generator_menu.add_cascade(label="Connected Grid", menu=menu)
|
||||
|
||||
def create_chain_menu(self, topology_generator_menu):
|
||||
"""
|
||||
|
@ -297,13 +222,13 @@ class Menubar(tk.Menu):
|
|||
:param tkinter.Menu topology_generator_menu: topology generator menu
|
||||
:return: nothing
|
||||
"""
|
||||
chain_menu = tk.Menu(topology_generator_menu)
|
||||
menu = tk.Menu(topology_generator_menu)
|
||||
# number of nodes to create
|
||||
nums = list(range(2, 25, 1)) + [32, 64, 128]
|
||||
for i in nums:
|
||||
the_label = "P(" + str(i) + ")"
|
||||
chain_menu.add_command(label=the_label, command=action.sub_menu_items)
|
||||
topology_generator_menu.add_cascade(label="Chain", menu=chain_menu, underline=0)
|
||||
label = f"P({i})"
|
||||
menu.add_command(label=label, state=tk.DISABLED)
|
||||
topology_generator_menu.add_cascade(label="Chain", menu=menu)
|
||||
|
||||
def create_star_menu(self, topology_generator_menu):
|
||||
"""
|
||||
|
@ -312,11 +237,11 @@ class Menubar(tk.Menu):
|
|||
:param tkinter.Menu topology_generator_menu: topology generator menu
|
||||
:return: nothing
|
||||
"""
|
||||
star_menu = tk.Menu(topology_generator_menu)
|
||||
menu = tk.Menu(topology_generator_menu)
|
||||
for i in range(3, 26, 1):
|
||||
the_label = "C(" + str(i) + ")"
|
||||
star_menu.add_command(label=the_label, command=action.sub_menu_items)
|
||||
topology_generator_menu.add_cascade(label="Star", menu=star_menu, underline=0)
|
||||
label = f"C({i})"
|
||||
menu.add_command(label=label, state=tk.DISABLED)
|
||||
topology_generator_menu.add_cascade(label="Star", menu=menu)
|
||||
|
||||
def create_cycle_menu(self, topology_generator_menu):
|
||||
"""
|
||||
|
@ -325,11 +250,11 @@ class Menubar(tk.Menu):
|
|||
:param tkinter.Menu topology_generator_menu: topology generator menu
|
||||
:return: nothing
|
||||
"""
|
||||
cycle_menu = tk.Menu(topology_generator_menu)
|
||||
menu = tk.Menu(topology_generator_menu)
|
||||
for i in range(3, 25, 1):
|
||||
the_label = "C(" + str(i) + ")"
|
||||
cycle_menu.add_command(label=the_label, command=action.sub_menu_items)
|
||||
topology_generator_menu.add_cascade(label="Cycle", menu=cycle_menu, underline=0)
|
||||
label = f"C({i})"
|
||||
menu.add_command(label=label, state=tk.DISABLED)
|
||||
topology_generator_menu.add_cascade(label="Cycle", menu=menu)
|
||||
|
||||
def create_wheel_menu(self, topology_generator_menu):
|
||||
"""
|
||||
|
@ -338,11 +263,11 @@ class Menubar(tk.Menu):
|
|||
:param tkinter.Menu topology_generator_menu: topology generator menu
|
||||
:return: nothing
|
||||
"""
|
||||
wheel_menu = tk.Menu(topology_generator_menu)
|
||||
menu = tk.Menu(topology_generator_menu)
|
||||
for i in range(4, 26, 1):
|
||||
the_label = "W(" + str(i) + ")"
|
||||
wheel_menu.add_command(label=the_label, command=action.sub_menu_items)
|
||||
topology_generator_menu.add_cascade(label="Wheel", menu=wheel_menu, underline=0)
|
||||
label = f"W({i})"
|
||||
menu.add_command(label=label, state=tk.DISABLED)
|
||||
topology_generator_menu.add_cascade(label="Wheel", menu=menu)
|
||||
|
||||
def create_cube_menu(self, topology_generator_menu):
|
||||
"""
|
||||
|
@ -351,11 +276,11 @@ class Menubar(tk.Menu):
|
|||
:param tkinter.Menu topology_generator_menu: topology generator menu
|
||||
:return: nothing
|
||||
"""
|
||||
cube_menu = tk.Menu(topology_generator_menu)
|
||||
menu = tk.Menu(topology_generator_menu)
|
||||
for i in range(2, 7, 1):
|
||||
the_label = "Q(" + str(i) + ")"
|
||||
cube_menu.add_command(label=the_label, command=action.sub_menu_items)
|
||||
topology_generator_menu.add_cascade(label="Cube", menu=cube_menu, underline=0)
|
||||
label = f"Q({i})"
|
||||
menu.add_command(label=label, state=tk.DISABLED)
|
||||
topology_generator_menu.add_cascade(label="Cube", menu=menu)
|
||||
|
||||
def create_clique_menu(self, topology_generator_menu):
|
||||
"""
|
||||
|
@ -364,13 +289,11 @@ class Menubar(tk.Menu):
|
|||
:param tkinter.Menu topology_generator_menu: topology generator menu
|
||||
:return: nothing
|
||||
"""
|
||||
clique_menu = tk.Menu(topology_generator_menu)
|
||||
menu = tk.Menu(topology_generator_menu)
|
||||
for i in range(3, 25, 1):
|
||||
the_label = "K(" + str(i) + ")"
|
||||
clique_menu.add_command(label=the_label, command=action.sub_menu_items)
|
||||
topology_generator_menu.add_cascade(
|
||||
label="Clique", menu=clique_menu, underline=0
|
||||
)
|
||||
label = f"K({i})"
|
||||
menu.add_command(label=label, state=tk.DISABLED)
|
||||
topology_generator_menu.add_cascade(label="Clique", menu=menu)
|
||||
|
||||
def create_bipartite_menu(self, topology_generator_menu):
|
||||
"""
|
||||
|
@ -379,19 +302,17 @@ class Menubar(tk.Menu):
|
|||
:param tkinter.Menu topology_generator_menu: topology_generator_menu
|
||||
:return: nothing
|
||||
"""
|
||||
bipartite_menu = tk.Menu(topology_generator_menu)
|
||||
menu = tk.Menu(topology_generator_menu)
|
||||
temp = 24
|
||||
for i in range(1, 13, 1):
|
||||
i_n_menu = tk.Menu(bipartite_menu)
|
||||
submenu = tk.Menu(menu)
|
||||
for j in range(i, temp, 1):
|
||||
i_j_label = "K(" + str(i) + " X " + str(j) + ")"
|
||||
i_n_menu.add_command(label=i_j_label, command=action.sub_menu_items)
|
||||
i_n_label = "K(" + str(i) + " X N)"
|
||||
bipartite_menu.add_cascade(label=i_n_label, menu=i_n_menu)
|
||||
label = f"K({i} X {j})"
|
||||
submenu.add_command(label=label, state=tk.DISABLED)
|
||||
label = f"K({i})"
|
||||
menu.add_cascade(label=label, menu=submenu)
|
||||
temp = temp - 1
|
||||
topology_generator_menu.add_cascade(
|
||||
label="Bipartite", menu=bipartite_menu, underline=0
|
||||
)
|
||||
topology_generator_menu.add_cascade(label="Bipartite", menu=menu)
|
||||
|
||||
def create_topology_generator_menu(self, tools_menu):
|
||||
"""
|
||||
|
@ -401,20 +322,18 @@ class Menubar(tk.Menu):
|
|||
|
||||
:return: nothing
|
||||
"""
|
||||
topology_generator_menu = tk.Menu(tools_menu)
|
||||
self.create_random_menu(topology_generator_menu)
|
||||
self.create_grid_menu(topology_generator_menu)
|
||||
self.create_connected_grid_menu(topology_generator_menu)
|
||||
self.create_chain_menu(topology_generator_menu)
|
||||
self.create_star_menu(topology_generator_menu)
|
||||
self.create_cycle_menu(topology_generator_menu)
|
||||
self.create_wheel_menu(topology_generator_menu)
|
||||
self.create_cube_menu(topology_generator_menu)
|
||||
self.create_clique_menu(topology_generator_menu)
|
||||
self.create_bipartite_menu(topology_generator_menu)
|
||||
tools_menu.add_cascade(
|
||||
label="Topology generator", menu=topology_generator_menu, underline=0
|
||||
)
|
||||
menu = tk.Menu(tools_menu)
|
||||
self.create_random_menu(menu)
|
||||
self.create_grid_menu(menu)
|
||||
self.create_connected_grid_menu(menu)
|
||||
self.create_chain_menu(menu)
|
||||
self.create_star_menu(menu)
|
||||
self.create_cycle_menu(menu)
|
||||
self.create_wheel_menu(menu)
|
||||
self.create_cube_menu(menu)
|
||||
self.create_clique_menu(menu)
|
||||
self.create_bipartite_menu(menu)
|
||||
tools_menu.add_cascade(label="Topology generator", menu=menu)
|
||||
|
||||
def draw_tools_menu(self):
|
||||
"""
|
||||
|
@ -422,41 +341,21 @@ class Menubar(tk.Menu):
|
|||
|
||||
:return: nothing
|
||||
"""
|
||||
tools_menu = tk.Menu(self)
|
||||
tools_menu.add_command(
|
||||
label="Auto rearrange all",
|
||||
command=action.tools_auto_rearrange_all,
|
||||
underline=0,
|
||||
)
|
||||
tools_menu.add_command(
|
||||
label="Auto rearrange selected",
|
||||
command=action.tools_auto_rearrange_selected,
|
||||
underline=0,
|
||||
)
|
||||
tools_menu.add_separator()
|
||||
tools_menu.add_command(
|
||||
label="Align to grid", command=action.tools_align_to_grid, underline=0
|
||||
)
|
||||
tools_menu.add_separator()
|
||||
tools_menu.add_command(label="Traffic...", command=action.tools_traffic)
|
||||
tools_menu.add_command(
|
||||
label="IP addresses...", command=action.tools_ip_addresses, underline=0
|
||||
)
|
||||
tools_menu.add_command(
|
||||
label="MAC addresses...", command=action.tools_mac_addresses, underline=0
|
||||
)
|
||||
tools_menu.add_command(
|
||||
label="Build hosts file...",
|
||||
command=action.tools_build_hosts_file,
|
||||
underline=0,
|
||||
)
|
||||
tools_menu.add_command(
|
||||
label="Renumber nodes...", command=action.tools_renumber_nodes, underline=0
|
||||
)
|
||||
self.create_experimental_menu(tools_menu)
|
||||
self.create_topology_generator_menu(tools_menu)
|
||||
tools_menu.add_command(label="Debugger...", command=action.tools_debugger)
|
||||
self.add_cascade(label="Tools", menu=tools_menu, underline=0)
|
||||
menu = tk.Menu(self)
|
||||
menu.add_command(label="Auto rearrange all", state=tk.DISABLED)
|
||||
menu.add_command(label="Auto rearrange selected", state=tk.DISABLED)
|
||||
menu.add_separator()
|
||||
menu.add_command(label="Align to grid", state=tk.DISABLED)
|
||||
menu.add_separator()
|
||||
menu.add_command(label="Traffic...", state=tk.DISABLED)
|
||||
menu.add_command(label="IP addresses...", state=tk.DISABLED)
|
||||
menu.add_command(label="MAC addresses...", state=tk.DISABLED)
|
||||
menu.add_command(label="Build hosts file...", state=tk.DISABLED)
|
||||
menu.add_command(label="Renumber nodes...", state=tk.DISABLED)
|
||||
self.create_experimental_menu(menu)
|
||||
self.create_topology_generator_menu(menu)
|
||||
menu.add_command(label="Debugger...", state=tk.DISABLED)
|
||||
self.add_cascade(label="Tools", menu=menu)
|
||||
|
||||
def create_observer_widgets_menu(self, widget_menu):
|
||||
"""
|
||||
|
@ -465,54 +364,24 @@ class Menubar(tk.Menu):
|
|||
:param tkinter.Menu widget_menu: widget_menu
|
||||
:return: nothing
|
||||
"""
|
||||
observer_widget_menu = tk.Menu(widget_menu)
|
||||
observer_widget_menu.add_command(label="None", command=action.sub_menu_items)
|
||||
observer_widget_menu.add_command(
|
||||
label="processes", command=action.sub_menu_items
|
||||
)
|
||||
observer_widget_menu.add_command(
|
||||
label="ifconfig", command=action.sub_menu_items
|
||||
)
|
||||
observer_widget_menu.add_command(
|
||||
label="IPv4 routes", command=action.sub_menu_items
|
||||
)
|
||||
observer_widget_menu.add_command(
|
||||
label="IPv6 routes", command=action.sub_menu_items
|
||||
)
|
||||
observer_widget_menu.add_command(
|
||||
label="OSPFv2 neighbors", command=action.sub_menu_items
|
||||
)
|
||||
observer_widget_menu.add_command(
|
||||
label="OSPFv3 neighbors", command=action.sub_menu_items
|
||||
)
|
||||
observer_widget_menu.add_command(
|
||||
label="Listening sockets", command=action.sub_menu_items
|
||||
)
|
||||
observer_widget_menu.add_command(
|
||||
label="IPv4 MFC entries", command=action.sub_menu_items
|
||||
)
|
||||
observer_widget_menu.add_command(
|
||||
label="IPv6 MFC entries", command=action.sub_menu_items
|
||||
)
|
||||
observer_widget_menu.add_command(
|
||||
label="firewall rules", command=action.sub_menu_items
|
||||
)
|
||||
observer_widget_menu.add_command(
|
||||
label="IPsec policies", command=action.sub_menu_items
|
||||
)
|
||||
observer_widget_menu.add_command(
|
||||
label="docker logs", command=action.sub_menu_items
|
||||
)
|
||||
observer_widget_menu.add_command(
|
||||
label="OSPFv3 MDR level", command=action.sub_menu_items
|
||||
)
|
||||
observer_widget_menu.add_command(
|
||||
label="PIM neighbors", command=action.sub_menu_items
|
||||
)
|
||||
observer_widget_menu.add_command(
|
||||
label="Edit...", command=self.menuaction.edit_observer_widgets
|
||||
)
|
||||
widget_menu.add_cascade(label="Observer Widgets", menu=observer_widget_menu)
|
||||
menu = tk.Menu(widget_menu)
|
||||
menu.add_command(label="None", state=tk.DISABLED)
|
||||
menu.add_command(label="processes", state=tk.DISABLED)
|
||||
menu.add_command(label="ifconfig", state=tk.DISABLED)
|
||||
menu.add_command(label="IPv4 routes", state=tk.DISABLED)
|
||||
menu.add_command(label="IPv6 routes", state=tk.DISABLED)
|
||||
menu.add_command(label="OSPFv2 neighbors", state=tk.DISABLED)
|
||||
menu.add_command(label="OSPFv3 neighbors", state=tk.DISABLED)
|
||||
menu.add_command(label="Listening sockets", state=tk.DISABLED)
|
||||
menu.add_command(label="IPv4 MFC entries", state=tk.DISABLED)
|
||||
menu.add_command(label="IPv6 MFC entries", state=tk.DISABLED)
|
||||
menu.add_command(label="firewall rules", state=tk.DISABLED)
|
||||
menu.add_command(label="IPsec policies", state=tk.DISABLED)
|
||||
menu.add_command(label="docker logs", state=tk.DISABLED)
|
||||
menu.add_command(label="OSPFv3 MDR level", state=tk.DISABLED)
|
||||
menu.add_command(label="PIM neighbors", state=tk.DISABLED)
|
||||
menu.add_command(label="Edit...", command=self.menuaction.edit_observer_widgets)
|
||||
widget_menu.add_cascade(label="Observer Widgets", menu=menu)
|
||||
|
||||
def create_adjacency_menu(self, widget_menu):
|
||||
"""
|
||||
|
@ -521,12 +390,12 @@ class Menubar(tk.Menu):
|
|||
:param tkinter.Menu widget_menu: widget menu
|
||||
:return: nothing
|
||||
"""
|
||||
adjacency_menu = tk.Menu(widget_menu)
|
||||
adjacency_menu.add_command(label="OSPFv2", command=action.sub_menu_items)
|
||||
adjacency_menu.add_command(label="OSPFv3", command=action.sub_menu_items)
|
||||
adjacency_menu.add_command(label="OSLR", command=action.sub_menu_items)
|
||||
adjacency_menu.add_command(label="OSLRv2", command=action.sub_menu_items)
|
||||
widget_menu.add_cascade(label="Adjacency", menu=adjacency_menu)
|
||||
menu = tk.Menu(widget_menu)
|
||||
menu.add_command(label="OSPFv2", state=tk.DISABLED)
|
||||
menu.add_command(label="OSPFv3", state=tk.DISABLED)
|
||||
menu.add_command(label="OSLR", state=tk.DISABLED)
|
||||
menu.add_command(label="OSLRv2", state=tk.DISABLED)
|
||||
widget_menu.add_cascade(label="Adjacency", menu=menu)
|
||||
|
||||
def draw_widgets_menu(self):
|
||||
"""
|
||||
|
@ -534,18 +403,14 @@ class Menubar(tk.Menu):
|
|||
|
||||
:return: nothing
|
||||
"""
|
||||
widget_menu = tk.Menu(self)
|
||||
self.create_observer_widgets_menu(widget_menu)
|
||||
self.create_adjacency_menu(widget_menu)
|
||||
widget_menu.add_command(label="Throughput", command=action.widgets_throughput)
|
||||
widget_menu.add_separator()
|
||||
widget_menu.add_command(
|
||||
label="Configure Adjacency...", command=action.widgets_configure_adjacency
|
||||
)
|
||||
widget_menu.add_command(
|
||||
label="Configure Throughput...", command=action.widgets_configure_throughput
|
||||
)
|
||||
self.add_cascade(label="Widgets", menu=widget_menu, underline=0)
|
||||
menu = tk.Menu(self)
|
||||
self.create_observer_widgets_menu(menu)
|
||||
self.create_adjacency_menu(menu)
|
||||
menu.add_command(label="Throughput", state=tk.DISABLED)
|
||||
menu.add_separator()
|
||||
menu.add_command(label="Configure Adjacency...", state=tk.DISABLED)
|
||||
menu.add_command(label="Configure Throughput...", state=tk.DISABLED)
|
||||
self.add_cascade(label="Widgets", menu=menu)
|
||||
|
||||
def draw_session_menu(self):
|
||||
"""
|
||||
|
@ -553,36 +418,21 @@ class Menubar(tk.Menu):
|
|||
|
||||
:return: nothing
|
||||
"""
|
||||
session_menu = tk.Menu(self)
|
||||
session_menu.add_command(
|
||||
menu = tk.Menu(self)
|
||||
menu.add_command(
|
||||
label="Change sessions...",
|
||||
command=self.menuaction.session_change_sessions,
|
||||
underline=0,
|
||||
)
|
||||
session_menu.add_separator()
|
||||
session_menu.add_command(
|
||||
label="Node types...", command=action.session_node_types, underline=0
|
||||
menu.add_separator()
|
||||
menu.add_command(label="Comments...", state=tk.DISABLED)
|
||||
menu.add_command(label="Hooks...", command=self.menuaction.session_hooks)
|
||||
menu.add_command(label="Reset node positions", state=tk.DISABLED)
|
||||
menu.add_command(
|
||||
label="Emulation servers...", command=self.menuaction.session_servers
|
||||
)
|
||||
session_menu.add_command(
|
||||
label="Comments...", command=action.session_comments, underline=0
|
||||
)
|
||||
session_menu.add_command(
|
||||
label="Hooks...", command=self.menuaction.session_hooks, underline=0
|
||||
)
|
||||
session_menu.add_command(
|
||||
label="Reset node positions",
|
||||
command=action.session_reset_node_positions,
|
||||
underline=0,
|
||||
)
|
||||
session_menu.add_command(
|
||||
label="Emulation servers...",
|
||||
command=self.menuaction.session_servers,
|
||||
underline=0,
|
||||
)
|
||||
session_menu.add_command(
|
||||
label="Options...", command=self.menuaction.session_options, underline=0
|
||||
)
|
||||
self.add_cascade(label="Session", menu=session_menu, underline=0)
|
||||
menu.add_command(label="Options...", command=self.menuaction.session_options)
|
||||
self.add_cascade(label="Session", menu=menu)
|
||||
|
||||
def draw_help_menu(self):
|
||||
"""
|
||||
|
@ -590,13 +440,13 @@ class Menubar(tk.Menu):
|
|||
|
||||
:return: nothing
|
||||
"""
|
||||
help_menu = tk.Menu(self)
|
||||
help_menu.add_command(
|
||||
menu = tk.Menu(self)
|
||||
menu.add_command(
|
||||
label="Core Github (www)", command=self.menuaction.help_core_github
|
||||
)
|
||||
help_menu.add_command(
|
||||
menu.add_command(
|
||||
label="Core Documentation (www)",
|
||||
command=self.menuaction.help_core_documentation,
|
||||
)
|
||||
help_menu.add_command(label="About", command=action.help_about)
|
||||
self.add_cascade(label="Help", menu=help_menu)
|
||||
menu.add_command(label="About", state=tk.DISABLED)
|
||||
self.add_cascade(label="Help", menu=menu)
|
||||
|
|
|
@ -83,8 +83,8 @@ class Toolbar(tk.Frame):
|
|||
"link tool",
|
||||
)
|
||||
self.create_node_button()
|
||||
self.create_link_layer_button()
|
||||
self.create_marker_button()
|
||||
self.create_network_button()
|
||||
self.create_annotation_button()
|
||||
self.radio_value.set(1)
|
||||
|
||||
def draw_runtime_frame(self):
|
||||
|
@ -145,14 +145,22 @@ class Toolbar(tk.Frame):
|
|||
(ImageEnum.PC, "PC"),
|
||||
(ImageEnum.MDR, "mdr"),
|
||||
(ImageEnum.PROUTER, "prouter"),
|
||||
(ImageEnum.EDITNODE, "custom node types"),
|
||||
]
|
||||
# draw default nodes
|
||||
for image_enum, tooltip in nodes:
|
||||
image = Images.get(image_enum)
|
||||
func = partial(self.update_button, self.node_button, image, tooltip)
|
||||
self.create_button(image, func, self.node_picker, tooltip)
|
||||
# draw custom nodes
|
||||
for name in sorted(self.app.core.custom_nodes):
|
||||
custom_node = self.app.core.custom_nodes[name]
|
||||
image = custom_node.image
|
||||
func = partial(self.update_button, self.node_button, image, name)
|
||||
self.create_button(image, func, self.node_picker, name)
|
||||
# draw edit node
|
||||
image = Images.get(ImageEnum.EDITNODE)
|
||||
self.create_button(
|
||||
Images.get(image_enum),
|
||||
partial(self.update_button, self.node_button, image_enum, tooltip),
|
||||
self.node_picker,
|
||||
tooltip,
|
||||
image, self.click_edit_node, self.node_picker, "custom nodes"
|
||||
)
|
||||
self.show_picker(self.node_button, self.node_picker)
|
||||
|
||||
|
@ -161,22 +169,24 @@ class Toolbar(tk.Frame):
|
|||
x = button.winfo_rootx() - first_button.winfo_rootx() + 40
|
||||
y = button.winfo_rooty() - first_button.winfo_rooty() - 1
|
||||
picker.place(x=x, y=y)
|
||||
self.app.bind_all("<Button-1>", lambda e: self.hide_pickers())
|
||||
self.app.bind_all("<ButtonRelease-1>", lambda e: self.hide_pickers())
|
||||
picker.wait_visibility()
|
||||
picker.grab_set()
|
||||
self.wait_window(picker)
|
||||
self.app.unbind_all("<Button-1>")
|
||||
self.app.unbind_all("<ButtonRelease-1>")
|
||||
|
||||
def create_button(self, img, func, frame, tooltip):
|
||||
def create_button(self, image, func, frame, tooltip):
|
||||
"""
|
||||
Create button and put it on the frame
|
||||
|
||||
:param PIL.Image img: button image
|
||||
:param PIL.Image image: button image
|
||||
:param func: the command that is executed when button is clicked
|
||||
:param tkinter.Frame frame: frame that contains the button
|
||||
:param str tooltip: tooltip text
|
||||
:return: nothing
|
||||
"""
|
||||
button = tk.Button(frame, width=self.width, height=self.height, image=img)
|
||||
button.bind("<Button-1>", lambda e: func())
|
||||
button = tk.Button(frame, width=self.width, height=self.height, image=image)
|
||||
button.bind("<ButtonRelease-1>", lambda e: func())
|
||||
button.grid(pady=1)
|
||||
CreateToolTip(button, tooltip)
|
||||
|
||||
|
@ -221,15 +231,14 @@ class Toolbar(tk.Frame):
|
|||
logging.debug("Click LINK button")
|
||||
self.app.canvas.mode = GraphMode.EDGE
|
||||
|
||||
def update_button(self, button, image_enum, name):
|
||||
logging.info("update button(%s): %s, %s", button, image_enum, name)
|
||||
def click_edit_node(self):
|
||||
self.hide_pickers()
|
||||
if image_enum == ImageEnum.EDITNODE:
|
||||
dialog = CustomNodesDialog(self.app, self.app)
|
||||
dialog.show()
|
||||
else:
|
||||
image = Images.get(image_enum)
|
||||
logging.info("updating button(%s): %s", button, name)
|
||||
|
||||
def update_button(self, button, image, name):
|
||||
logging.info("update button(%s): %s", button, name)
|
||||
self.hide_pickers()
|
||||
button.configure(image=image)
|
||||
self.app.canvas.mode = GraphMode.NODE
|
||||
self.app.canvas.draw_node_image = image
|
||||
|
@ -262,8 +271,8 @@ class Toolbar(tk.Frame):
|
|||
width=self.width,
|
||||
height=self.height,
|
||||
image=router_image,
|
||||
command=self.draw_node_picker,
|
||||
)
|
||||
self.node_button.bind("<ButtonRelease-1>", lambda e: self.draw_node_picker())
|
||||
self.node_button.grid()
|
||||
CreateToolTip(self.node_button, "Network-layer virtual nodes")
|
||||
|
||||
|
@ -285,15 +294,16 @@ class Toolbar(tk.Frame):
|
|||
(ImageEnum.TUNNEL, "tunnel", "tunnel tool"),
|
||||
]
|
||||
for image_enum, name, tooltip in nodes:
|
||||
image = Images.get(image_enum)
|
||||
self.create_button(
|
||||
Images.get(image_enum),
|
||||
partial(self.update_button, self.network_button, image_enum, name),
|
||||
image,
|
||||
partial(self.update_button, self.network_button, image, name),
|
||||
self.network_picker,
|
||||
tooltip,
|
||||
)
|
||||
self.show_picker(self.network_button, self.network_picker)
|
||||
|
||||
def create_link_layer_button(self):
|
||||
def create_network_button(self):
|
||||
"""
|
||||
Create link-layer node button and the options that represent different link-layer node types
|
||||
|
||||
|
@ -308,7 +318,9 @@ class Toolbar(tk.Frame):
|
|||
width=self.width,
|
||||
height=self.height,
|
||||
image=hub_image,
|
||||
command=self.draw_network_picker,
|
||||
)
|
||||
self.network_button.bind(
|
||||
"<ButtonRelease-1>", lambda e: self.draw_network_picker()
|
||||
)
|
||||
self.network_button.grid()
|
||||
CreateToolTip(self.network_button, "link-layer nodes")
|
||||
|
@ -337,7 +349,7 @@ class Toolbar(tk.Frame):
|
|||
)
|
||||
self.show_picker(self.annotation_button, self.annotation_picker)
|
||||
|
||||
def create_marker_button(self):
|
||||
def create_annotation_button(self):
|
||||
"""
|
||||
Create marker button and options that represent different marker types
|
||||
|
||||
|
@ -352,7 +364,9 @@ class Toolbar(tk.Frame):
|
|||
width=self.width,
|
||||
height=self.height,
|
||||
image=marker_image,
|
||||
command=self.draw_annotation_picker,
|
||||
)
|
||||
self.annotation_button.bind(
|
||||
"<ButtonRelease-1>", lambda e: self.draw_annotation_picker()
|
||||
)
|
||||
self.annotation_button.grid()
|
||||
CreateToolTip(self.annotation_button, "background annotation tools")
|
||||
|
|
|
@ -159,6 +159,8 @@ class CoreGrpcClient:
|
|||
emane_model_configs=None,
|
||||
wlan_configs=None,
|
||||
mobility_configs=None,
|
||||
service_configs=None,
|
||||
service_file_configs=None,
|
||||
):
|
||||
"""
|
||||
Start a session.
|
||||
|
@ -169,9 +171,11 @@ class CoreGrpcClient:
|
|||
:param core_pb2.SessionLocation location: location to set
|
||||
:param list[core_pb2.Hook] hooks: session hooks to set
|
||||
:param dict emane_config: emane configuration to set
|
||||
:param list emane_model_configs: emane model configurations to set
|
||||
:param list wlan_configs: wlan configurations to set
|
||||
:param list mobility_configs: mobility configurations to set
|
||||
:param list emane_model_configs: node emane model configurations
|
||||
:param list wlan_configs: node wlan configurations
|
||||
:param list mobility_configs: node mobility configurations
|
||||
:param list service_configs: node service configurations
|
||||
:param list service_file_configs: node service file configurations
|
||||
:return: start session response
|
||||
:rtype: core_pb2.StartSessionResponse
|
||||
"""
|
||||
|
@ -185,6 +189,8 @@ class CoreGrpcClient:
|
|||
emane_model_configs=emane_model_configs,
|
||||
wlan_configs=wlan_configs,
|
||||
mobility_configs=mobility_configs,
|
||||
service_configs=service_configs,
|
||||
service_file_configs=service_file_configs,
|
||||
)
|
||||
return self.stub.StartSession(request)
|
||||
|
||||
|
@ -768,14 +774,14 @@ class CoreGrpcClient:
|
|||
:rtype: core_pb2.SetNodeServiceResponse
|
||||
:raises grpc.RpcError: when session or node doesn't exist
|
||||
"""
|
||||
request = core_pb2.SetNodeServiceRequest(
|
||||
session_id=session_id,
|
||||
config = core_pb2.ServiceConfig(
|
||||
node_id=node_id,
|
||||
service=service,
|
||||
startup=startup,
|
||||
validate=validate,
|
||||
shutdown=shutdown,
|
||||
)
|
||||
request = core_pb2.SetNodeServiceRequest(session_id=session_id, config=config)
|
||||
return self.stub.SetNodeService(request)
|
||||
|
||||
def set_node_service_file(self, session_id, node_id, service, file_name, data):
|
||||
|
@ -791,12 +797,11 @@ class CoreGrpcClient:
|
|||
:rtype: core_pb2.SetNodeServiceFileResponse
|
||||
:raises grpc.RpcError: when session or node doesn't exist
|
||||
"""
|
||||
config = core_pb2.ServiceFileConfig(
|
||||
node_id=node_id, service=service, file=file_name, data=data
|
||||
)
|
||||
request = core_pb2.SetNodeServiceFileRequest(
|
||||
session_id=session_id,
|
||||
node_id=node_id,
|
||||
service=service,
|
||||
file=file_name,
|
||||
data=data,
|
||||
session_id=session_id, config=config
|
||||
)
|
||||
return self.stub.SetNodeServiceFile(request)
|
||||
|
||||
|
|
|
@ -319,3 +319,18 @@ def session_location(session, location):
|
|||
session.location.refxyz = (location.x, location.y, location.z)
|
||||
session.location.setrefgeo(location.lat, location.lon, location.alt)
|
||||
session.location.refscale = location.scale
|
||||
|
||||
|
||||
def service_configuration(session, config):
|
||||
"""
|
||||
Convenience method for setting a node service configuration.
|
||||
|
||||
:param core.emulator.session.Session session: session for service configuration
|
||||
:param core_pb2.ServiceConfig config: service configuration
|
||||
:return:
|
||||
"""
|
||||
session.services.set_service(config.node_id, config.service)
|
||||
service = session.services.get_service(config.node_id, config.service)
|
||||
service.startup = tuple(config.startup)
|
||||
service.validate = tuple(config.validate)
|
||||
service.shutdown = tuple(config.shutdown)
|
||||
|
|
|
@ -153,6 +153,16 @@ class CoreGrpcServer(core_pb2_grpc.CoreApiServicer):
|
|||
config.node_id, Ns2ScriptedMobility.name, config.config
|
||||
)
|
||||
|
||||
# service configs
|
||||
for config in request.service_configs:
|
||||
grpcutils.service_configuration(session, config)
|
||||
|
||||
# service file configs
|
||||
for config in request.service_file_configs:
|
||||
session.services.set_service_file(
|
||||
config.node_id, config.service, config.file, config.data
|
||||
)
|
||||
|
||||
# create links
|
||||
grpcutils.create_links(session, request.links)
|
||||
|
||||
|
@ -1172,11 +1182,8 @@ class CoreGrpcServer(core_pb2_grpc.CoreApiServicer):
|
|||
"""
|
||||
logging.debug("set node service: %s", request)
|
||||
session = self.get_session(request.session_id, context)
|
||||
session.services.set_service(request.node_id, request.service)
|
||||
service = session.services.get_service(request.node_id, request.service)
|
||||
service.startup = tuple(request.startup)
|
||||
service.validate = tuple(request.validate)
|
||||
service.shutdown = tuple(request.shutdown)
|
||||
config = request.config
|
||||
grpcutils.service_configuration(session, config)
|
||||
return core_pb2.SetNodeServiceResponse(result=True)
|
||||
|
||||
def SetNodeServiceFile(self, request, context):
|
||||
|
@ -1191,8 +1198,9 @@ class CoreGrpcServer(core_pb2_grpc.CoreApiServicer):
|
|||
"""
|
||||
logging.debug("set node service file: %s", request)
|
||||
session = self.get_session(request.session_id, context)
|
||||
config = request.config
|
||||
session.services.set_service_file(
|
||||
request.node_id, request.service, request.file, request.data
|
||||
config.node_id, config.service, config.file, config.data
|
||||
)
|
||||
return core_pb2.SetNodeServiceFileResponse(result=True)
|
||||
|
||||
|
|
|
@ -144,6 +144,8 @@ message StartSessionRequest {
|
|||
repeated WlanConfig wlan_configs = 7;
|
||||
repeated EmaneModelConfig emane_model_configs = 8;
|
||||
repeated MobilityConfig mobility_configs = 9;
|
||||
repeated ServiceConfig service_configs = 10;
|
||||
repeated ServiceFileConfig service_file_configs = 11;
|
||||
}
|
||||
|
||||
message StartSessionResponse {
|
||||
|
@ -554,11 +556,7 @@ message GetNodeServiceFileResponse {
|
|||
|
||||
message SetNodeServiceRequest {
|
||||
int32 session_id = 1;
|
||||
int32 node_id = 2;
|
||||
string service = 3;
|
||||
repeated string startup = 4;
|
||||
repeated string validate = 5;
|
||||
repeated string shutdown = 6;
|
||||
ServiceConfig config = 2;
|
||||
}
|
||||
|
||||
message SetNodeServiceResponse {
|
||||
|
@ -567,10 +565,7 @@ message SetNodeServiceResponse {
|
|||
|
||||
message SetNodeServiceFileRequest {
|
||||
int32 session_id = 1;
|
||||
int32 node_id = 2;
|
||||
string service = 3;
|
||||
string file = 4;
|
||||
string data = 5;
|
||||
ServiceFileConfig config = 2;
|
||||
}
|
||||
|
||||
message SetNodeServiceFileResponse {
|
||||
|
@ -718,6 +713,21 @@ message EmaneModelConfig {
|
|||
map<string, string> config = 4;
|
||||
}
|
||||
|
||||
message ServiceConfig {
|
||||
int32 node_id = 1;
|
||||
string service = 2;
|
||||
repeated string startup = 3;
|
||||
repeated string validate = 4;
|
||||
repeated string shutdown = 5;
|
||||
}
|
||||
|
||||
message ServiceFileConfig {
|
||||
int32 node_id = 1;
|
||||
string service = 2;
|
||||
string file = 3;
|
||||
string data = 4;
|
||||
}
|
||||
|
||||
message MessageType {
|
||||
enum Enum {
|
||||
NONE = 0;
|
||||
|
|
|
@ -27,7 +27,6 @@ class TestGrpc:
|
|||
# given
|
||||
client = CoreGrpcClient()
|
||||
session = grpc_server.coreemu.create_session()
|
||||
nodes = []
|
||||
position = core_pb2.Position(x=50, y=100)
|
||||
node_one = core_pb2.Node(id=1, position=position, model="PC")
|
||||
position = core_pb2.Position(x=100, y=100)
|
||||
|
@ -36,8 +35,7 @@ class TestGrpc:
|
|||
wlan_node = core_pb2.Node(
|
||||
id=3, type=NodeTypes.WIRELESS_LAN.value, position=position
|
||||
)
|
||||
nodes.extend([node_one, node_two, wlan_node])
|
||||
links = []
|
||||
nodes = [node_one, node_two, wlan_node]
|
||||
interface_helper = InterfaceHelper(ip4_prefix="10.83.0.0/16")
|
||||
interface_one = interface_helper.create_interface(node_one.id, 0)
|
||||
interface_two = interface_helper.create_interface(node_two.id, 0)
|
||||
|
@ -48,12 +46,11 @@ class TestGrpc:
|
|||
interface_one=interface_one,
|
||||
interface_two=interface_two,
|
||||
)
|
||||
links.append(link)
|
||||
hooks = []
|
||||
links = [link]
|
||||
hook = core_pb2.Hook(
|
||||
state=core_pb2.SessionState.RUNTIME, file="echo.sh", data="echo hello"
|
||||
)
|
||||
hooks.append(hook)
|
||||
hooks = [hook]
|
||||
location_x = 5
|
||||
location_y = 10
|
||||
location_z = 15
|
||||
|
@ -73,7 +70,6 @@ class TestGrpc:
|
|||
emane_config_key = "platform_id_start"
|
||||
emane_config_value = "2"
|
||||
emane_config = {emane_config_key: emane_config_value}
|
||||
model_configs = []
|
||||
model_node_id = 20
|
||||
model_config_key = "bandwidth"
|
||||
model_config_value = "500000"
|
||||
|
@ -83,21 +79,30 @@ class TestGrpc:
|
|||
model=EmaneIeee80211abgModel.name,
|
||||
config={model_config_key: model_config_value},
|
||||
)
|
||||
model_configs.append(model_config)
|
||||
wlan_configs = []
|
||||
model_configs = [model_config]
|
||||
wlan_config_key = "range"
|
||||
wlan_config_value = "333"
|
||||
wlan_config = core_pb2.WlanConfig(
|
||||
node_id=wlan_node.id, config={wlan_config_key: wlan_config_value}
|
||||
)
|
||||
wlan_configs.append(wlan_config)
|
||||
wlan_configs = [wlan_config]
|
||||
mobility_config_key = "refresh_ms"
|
||||
mobility_config_value = "60"
|
||||
mobility_configs = []
|
||||
mobility_config = core_pb2.MobilityConfig(
|
||||
node_id=wlan_node.id, config={mobility_config_key: mobility_config_value}
|
||||
)
|
||||
mobility_configs.append(mobility_config)
|
||||
mobility_configs = [mobility_config]
|
||||
service_config = core_pb2.ServiceConfig(
|
||||
node_id=node_one.id, service="DefaultRoute", validate=["echo hello"]
|
||||
)
|
||||
service_configs = [service_config]
|
||||
service_file_config = core_pb2.ServiceFileConfig(
|
||||
node_id=node_one.id,
|
||||
service="DefaultRoute",
|
||||
file="defaultroute.sh",
|
||||
data="echo hello",
|
||||
)
|
||||
service_file_configs = [service_file_config]
|
||||
|
||||
# when
|
||||
with patch.object(CoreXmlWriter, "write"):
|
||||
|
@ -112,6 +117,8 @@ class TestGrpc:
|
|||
model_configs,
|
||||
wlan_configs,
|
||||
mobility_configs,
|
||||
service_configs,
|
||||
service_file_configs,
|
||||
)
|
||||
|
||||
# then
|
||||
|
@ -139,6 +146,14 @@ class TestGrpc:
|
|||
model_node_id, EmaneIeee80211abgModel.name
|
||||
)
|
||||
assert set_model_config[model_config_key] == model_config_value
|
||||
service = session.services.get_service(
|
||||
node_one.id, service_config.service, default_service=True
|
||||
)
|
||||
assert service.validate == tuple(service_config.validate)
|
||||
service_file = session.services.get_service_file(
|
||||
node_one, service_file_config.service, service_file_config.file
|
||||
)
|
||||
assert service_file.data == service_file_config.data
|
||||
|
||||
@pytest.mark.parametrize("session_id", [None, 6013])
|
||||
def test_create_session(self, grpc_server, session_id):
|
||||
|
|
Loading…
Add table
Reference in a new issue