move images files, create ip and mac for links, progress on node command and node terminal, progress on save and open xml

This commit is contained in:
Huy Pham 2019-10-10 17:02:28 -07:00
parent 8611106c93
commit ec2e959bda
61 changed files with 703 additions and 203 deletions

View file

@ -6,7 +6,8 @@ from coretk.coregrpc import CoreGrpc
from coretk.coremenubar import CoreMenubar
from coretk.coretoolbar import CoreToolbar
from coretk.graph import CanvasGraph
from coretk.images import Images
from coretk.images import ImageEnum, Images
from coretk.menuaction import MenuAction
class Application(tk.Frame):
@ -15,13 +16,15 @@ class Application(tk.Frame):
self.load_images()
self.setup_app()
self.menubar = None
self.core_menu = None
self.canvas = None
# start grpc
self.core_grpc = CoreGrpc()
self.core_editbar = None
self.core_grpc = None
self.create_menu()
self.create_widgets()
self.draw_canvas()
self.start_grpc()
def load_images(self):
"""
@ -33,23 +36,24 @@ class Application(tk.Frame):
def setup_app(self):
self.master.title("CORE")
self.master.geometry("1000x800")
image = Images.get("core")
image = Images.get(ImageEnum.CORE.value)
self.master.tk.call("wm", "iconphoto", self.master._w, image)
self.pack(fill=tk.BOTH, expand=True)
def create_menu(self):
self.master.option_add("*tearOff", tk.FALSE)
self.menubar = tk.Menu(self.master)
core_menu = CoreMenubar(self, self.master, self.menubar)
core_menu.create_core_menubar()
self.core_menu = CoreMenubar(self, self.master, self.menubar)
self.core_menu.create_core_menubar()
self.master.config(menu=self.menubar)
def create_widgets(self):
edit_frame = tk.Frame(self)
edit_frame.pack(side=tk.LEFT, fill=tk.Y, ipadx=2, ipady=2)
core_editbar = CoreToolbar(self.master, edit_frame, self.menubar)
core_editbar.create_toolbar()
self.core_editbar = CoreToolbar(self.master, edit_frame, self.menubar)
self.core_editbar.create_toolbar()
def draw_canvas(self):
self.canvas = CanvasGraph(
master=self,
grpc=self.core_grpc,
@ -58,7 +62,7 @@ class Application(tk.Frame):
)
self.canvas.pack(fill=tk.BOTH, expand=True)
core_editbar.update_canvas(self.canvas)
self.core_editbar.update_canvas(self.canvas)
scroll_x = tk.Scrollbar(
self.canvas, orient=tk.HORIZONTAL, command=self.canvas.xview
@ -78,8 +82,26 @@ class Application(tk.Frame):
b = tk.Button(status_bar, text="Button 3")
b.pack(side=tk.LEFT, padx=1)
def start_grpc(self):
"""
Conect client to grpc, query sessions and prompt use to choose an existing session if there exist any
:return: nothing
"""
self.master.update()
self.core_grpc = CoreGrpc(self.master)
self.core_grpc.set_up()
self.canvas.core_grpc = self.core_grpc
self.canvas.draw_existing_component()
def on_closing(self):
menu_action = MenuAction(self, self.master)
menu_action.on_quit()
# self.quit()
if __name__ == "__main__":
logging.basicConfig(level=logging.DEBUG)
app = Application()
app.master.protocol("WM_DELETE_WINDOW", app.on_closing)
app.mainloop()

View file

@ -2,26 +2,28 @@
Incorporate grpc into python tkinter GUI
"""
import logging
import os
import tkinter as tk
from core.api.grpc import client, core_pb2
class CoreGrpc:
def __init__(self):
def __init__(self, master):
"""
Create a CoreGrpc instance
"""
print("Create grpc instance")
self.core = client.CoreGrpcClient()
self.session_id = None
self.set_up()
self.master = master
# self.set_up()
self.interface_helper = None
def log_event(self, event):
logging.info("event: %s", event)
def redraw_canvas(self):
return
def create_new_session(self):
"""
Create a new session
@ -35,6 +37,29 @@ class CoreGrpc:
self.session_id = response.session_id
self.core.events(self.session_id, self.log_event)
def _enter_session(self, session_id, dialog):
"""
enter an existing session
:return:
"""
dialog.destroy()
response = self.core.get_session(session_id)
self.session_id = session_id
print("set session id: %s", session_id)
logging.info("Entering session_id %s.... Result: %s", session_id, response)
# self.master.canvas.draw_existing_component()
def _create_session(self, dialog):
"""
create a new session
:param tkinter.Toplevel dialog: save core session prompt dialog
:return: nothing
"""
dialog.destroy()
self.create_new_session()
def query_existing_sessions(self, sessions):
"""
Query for existing sessions and prompt to join one
@ -43,17 +68,30 @@ class CoreGrpc:
:return: nothing
"""
dialog = tk.Toplevel()
dialog.title("CORE sessions")
for session in sessions:
logging.info("Session id: %s, Session state: %s", session.id, session.state)
logging.info("Input a session you want to enter from the keyboard:")
usr_input = int(input())
if usr_input == 0:
self.create_new_session()
else:
response = self.core.get_session(usr_input)
self.session_id = usr_input
# self.core.events(self.session_id, self.log_event)
logging.info("Entering session_id %s.... Result: %s", usr_input, response)
b = tk.Button(
dialog,
text="Session " + str(session.id),
command=lambda sid=session.id: self._enter_session(sid, dialog),
)
b.pack(side=tk.TOP)
b = tk.Button(
dialog, text="create new", command=lambda: self._create_session(dialog)
)
b.pack(side=tk.TOP)
dialog.update()
x = (
self.master.winfo_x()
+ (self.master.winfo_width() - dialog.winfo_width()) / 2
)
y = (
self.master.winfo_y()
+ (self.master.winfo_height() / 2 - dialog.winfo_height()) / 2
)
dialog.geometry(f"+{int(x)}+{int(y)}")
dialog.wait_window()
def delete_session(self):
response = self.core.delete_session(self.session_id)
@ -61,9 +99,9 @@ class CoreGrpc:
def set_up(self):
"""
Query sessions, if there exist any, promt whether to join one
Query sessions, if there exist any, prompt whether to join one
:return: nothing
:return: existing sessions
"""
self.core.connect()
@ -76,12 +114,12 @@ class CoreGrpc:
if len(sessions) == 0:
self.create_new_session()
else:
# self.create_new_session()
self.query_existing_sessions(sessions)
def get_session_state(self):
response = self.core.get_session(self.session_id)
logging.info("get sessio: %s", response)
logging.info("get session: %s", response)
return response.session.state
def set_session_state(self, state):
@ -125,9 +163,6 @@ class CoreGrpc:
logging.info("set session state: %s", response)
def get_session_id(self):
return self.session_id
def add_node(self, node_type, model, x, y, name, node_id):
logging.info("coregrpc.py ADD NODE %s", name)
position = core_pb2.Position(x=x, y=y)
@ -136,9 +171,9 @@ class CoreGrpc:
logging.info("created node: %s", response)
return response.node_id
def edit_node(self, session_id, node_id, x, y):
def edit_node(self, node_id, x, y):
position = core_pb2.Position(x=x, y=y)
response = self.core.edit_node(session_id, node_id, position)
response = self.core.edit_node(self.session_id, node_id, position)
logging.info("updated node id %s: %s", node_id, response)
def delete_nodes(self):
@ -146,9 +181,6 @@ class CoreGrpc:
response = self.core.delete_node(self.session_id, node.id)
logging.info("delete node %s", response)
# def create_interface_helper(self):
# self.interface_helper = self.core.InterfaceHelper(ip4_prefix="10.83.0.0/16")
def delete_links(self):
for link in self.core.get_session(self.session_id).session.links:
response = self.core.delete_link(
@ -160,7 +192,7 @@ class CoreGrpc:
)
logging.info("delete link %s", response)
def add_link(self, id1, id2, type1, type2):
def add_link(self, id1, id2, type1, type2, edge):
"""
Grpc client request add link
@ -171,19 +203,64 @@ class CoreGrpc:
:param core_pb2.NodeType type2: node 2 core node type
:return: nothing
"""
if not self.interface_helper:
logging.debug("INTERFACE HELPER NOT CREATED YET, CREATING ONE...")
self.interface_helper = client.InterfaceHelper(ip4_prefix="10.83.0.0/16")
interface1 = None
interface2 = None
if1 = None
if2 = None
if type1 == core_pb2.NodeType.DEFAULT:
interface1 = self.interface_helper.create_interface(id1, 0)
interface = edge.interface_1
if1 = core_pb2.Interface(
id=interface.id,
name=interface.name,
mac=interface.mac,
ip4=interface.ipv4,
ip4mask=interface.ip4prefix,
)
# if1 = core_pb2.Interface(id=id1, name=edge.interface_1.name, ip4=edge.interface_1.ipv4, ip4mask=edge.interface_1.ip4prefix)
logging.debug("create interface 1 %s", if1)
# interface1 = self.interface_helper.create_interface(id1, 0)
if type2 == core_pb2.NodeType.DEFAULT:
interface2 = self.interface_helper.create_interface(id2, 0)
response = self.core.add_link(self.session_id, id1, id2, interface1, interface2)
interface = edge.interface_2
if2 = core_pb2.Interface(
id=interface.id,
name=interface.name,
mac=interface.mac,
ip4=interface.ipv4,
ip4mask=interface.ip4prefix,
)
# if2 = core_pb2.Interface(id=id2, name=edge.interface_2.name, ip4=edge.interface_2.ipv4, ip4mask=edge.interface_2.ip4prefix)
logging.debug("create interface 2: %s", if2)
# interface2 = self.interface_helper.create_interface(id2, 0)
# response = self.core.add_link(self.session_id, id1, id2, interface1, interface2)
response = self.core.add_link(self.session_id, id1, id2, if1, if2)
logging.info("created link: %s", response)
def launch_terminal(self, node_id):
response = self.core.get_node_terminal(self.session_id, node_id)
logging.info("get terminal %s", response.terminal)
os.system("xterm -e %s &" % response.terminal)
def save_xml(self, file_path):
"""
Save core session as to an xml file
:param str file_path: file path that user pick
:return: nothing
"""
response = self.core.save_xml(self.session_id, file_path)
logging.info("coregrpc.py save xml %s", response)
def open_xml(self, file_path):
"""
Open core xml
:param str file_path: file to open
:return: session id
"""
response = self.core.open_xml(file_path)
return response.session_id
# logging.info("coregrpc.py open_xml()", type(response))
def close(self):
"""
Clean ups when done using grpc

View file

@ -1,6 +1,7 @@
import tkinter as tk
import coretk.menuaction as action
from coretk.menuaction import MenuAction
class CoreMenubar(object):
@ -19,6 +20,33 @@ class CoreMenubar(object):
self.menubar = menubar
self.master = master
self.application = application
self.menuaction = action.MenuAction(application, master)
self.menu_action = MenuAction(self.application, self.master)
# def on_quit(self):
# """
# Prompt use to stop running session before application is closed
#
# :return: nothing
# """
# state = self.application.core_grpc.get_session_state()
#
# if state == core_pb2.SessionState.SHUTDOWN or state == core_pb2.SessionState.DEFINITION:
# self.application.core_grpc.delete_session()
# self.application.core_grpc.core.close()
# # self.application.quit()
# else:
# msgbox = tk.messagebox.askyesnocancel("stop", "Stop the running session?")
#
# if msgbox or msgbox == False:
# if msgbox:
# self.application.core_grpc.set_session_state("datacollect")
# self.application.core_grpc.delete_links()
# self.application.core_grpc.delete_nodes()
# self.application.core_grpc.delete_session()
#
# self.application.core_grpc.core.close()
# # self.application.quit()
def create_file_menu(self):
"""
@ -27,18 +55,24 @@ class CoreMenubar(object):
:return: nothing
"""
file_menu = tk.Menu(self.menubar)
# menu_action = MenuAction(self.application, self.master)
file_menu.add_command(
label="New", command=action.file_new, accelerator="Ctrl+N", underline=0
)
file_menu.add_command(
label="Open...", command=action.file_open, accelerator="Ctrl+O", underline=0
label="Open...",
command=self.menu_action.file_open_xml,
accelerator="Ctrl+O",
underline=0,
)
file_menu.add_command(label="Reload", command=action.file_reload, underline=0)
file_menu.add_command(
label="Save", command=action.file_save, accelerator="Ctrl+S", underline=0
)
file_menu.add_command(label="Save As XML...", command=action.file_save_as_xml)
file_menu.add_command(label="Save As imn...", command=action.file_save_as_imn)
# file_menu.add_command(label="Save As XML...", command=action.file_save_as_xml)
file_menu.add_command(
label="Save As XML...", command=self.menu_action.file_save_as_xml
)
file_menu.add_separator()
@ -68,13 +102,8 @@ class CoreMenubar(object):
file_menu.add_separator()
file_menu.add_command(
label="/home/ncs/.core/configs/sample1.imn",
command=action.file_example_link,
label="Quit", command=self.menuaction.on_quit, underline=0
)
file_menu.add_separator()
file_menu.add_command(label="Quit", command=self.master.quit, underline=0)
self.menubar.add_cascade(label="File", menu=file_menu, underline=0)
def create_edit_menu(self):
@ -560,9 +589,7 @@ class CoreMenubar(object):
:return: nothing
"""
session_menu = tk.Menu(self.menubar)
session_menu.add_command(
label="Start", command=action.session_start, underline=0
)
session_menu.add_command(
label="Change sessions...",
command=action.session_change_sessions,
@ -604,10 +631,11 @@ class CoreMenubar(object):
"""
help_menu = tk.Menu(self.menubar)
help_menu.add_command(
label="Core Github (www)", command=action.help_core_github
label="Core Github (www)", command=self.menu_action.help_core_github
)
help_menu.add_command(
label="Core Documentation (www)", command=action.help_core_documentation
label="Core Documentation (www)",
command=self.menu_action.help_core_documentation,
)
help_menu.add_command(label="About", command=action.help_about)

View file

@ -3,7 +3,7 @@ import tkinter as tk
from core.api.grpc import core_pb2
from coretk.graph import GraphMode
from coretk.images import Images
from coretk.images import ImageEnum, Images
from coretk.tooltip import CreateToolTip
@ -153,7 +153,6 @@ class CoreToolbar(object):
logging.debug("Click START STOP SESSION button")
self.destroy_children_widgets(self.edit_frame)
self.canvas.mode = GraphMode.SELECT
self.create_runtime_toolbar()
# set configuration state
if self.canvas.core_grpc.get_session_state() == core_pb2.SessionState.SHUTDOWN:
@ -166,10 +165,14 @@ class CoreToolbar(object):
)
for edge in self.canvas.grpc_manager.edges.values():
self.canvas.core_grpc.add_link(edge.id1, edge.id2, edge.type1, edge.type2)
self.canvas.core_grpc.add_link(
edge.id1, edge.id2, edge.type1, edge.type2, edge
)
self.canvas.core_grpc.set_session_state("instantiation")
self.create_runtime_toolbar()
def click_link_tool(self):
logging.debug("Click LINK button")
self.canvas.mode = GraphMode.EDGE
@ -177,55 +180,55 @@ class CoreToolbar(object):
def pick_router(self, main_button):
logging.debug("Pick router option")
self.network_layer_option_menu.destroy()
main_button.configure(image=Images.get("router"))
main_button.configure(image=Images.get(ImageEnum.ROUTER.value))
self.canvas.mode = GraphMode.PICKNODE
self.canvas.draw_node_image = Images.get("router")
self.canvas.draw_node_image = Images.get(ImageEnum.ROUTER.value)
self.canvas.draw_node_name = "router"
def pick_host(self, main_button):
logging.debug("Pick host option")
self.network_layer_option_menu.destroy()
main_button.configure(image=Images.get("host"))
main_button.configure(image=Images.get(ImageEnum.HOST.value))
self.canvas.mode = GraphMode.PICKNODE
self.canvas.draw_node_image = Images.get("host")
self.canvas.draw_node_image = Images.get(ImageEnum.HOST.value)
self.canvas.draw_node_name = "host"
def pick_pc(self, main_button):
logging.debug("Pick PC option")
self.network_layer_option_menu.destroy()
main_button.configure(image=Images.get("pc"))
main_button.configure(image=Images.get(ImageEnum.PC.value))
self.canvas.mode = GraphMode.PICKNODE
self.canvas.draw_node_image = Images.get("pc")
self.canvas.draw_node_image = Images.get(ImageEnum.PC.value)
self.canvas.draw_node_name = "PC"
def pick_mdr(self, main_button):
logging.debug("Pick MDR option")
self.network_layer_option_menu.destroy()
main_button.configure(image=Images.get("mdr"))
main_button.configure(image=Images.get(ImageEnum.MDR.value))
self.canvas.mode = GraphMode.PICKNODE
self.canvas.draw_node_image = Images.get("mdr")
self.canvas.draw_node_image = Images.get(ImageEnum.MD.value)
self.canvas.draw_node_name = "mdr"
def pick_prouter(self, main_button):
logging.debug("Pick prouter option")
self.network_layer_option_menu.destroy()
main_button.configure(image=Images.get("prouter"))
main_button.configure(image=Images.get(ImageEnum.PROUTER.value))
self.canvas.mode = GraphMode.PICKNODE
self.canvas.draw_node_image = Images.get("prouter")
self.canvas.draw_node_image = Images.get(ImageEnum.PROUTER.value)
self.canvas.draw_node_name = "prouter"
def pick_ovs(self, main_button):
logging.debug("Pick OVS option")
self.network_layer_option_menu.destroy()
main_button.configure(image=Images.get("ovs"))
main_button.configure(image=Images.get(ImageEnum.OVS.value))
self.canvas.mode = GraphMode.PICKNODE
self.canvas.draw_node_image = Images.get("ovs")
self.canvas.draw_node_image = Images.get(ImageEnum.OVS.value)
self.canvas.draw_node_name = "OVS"
# TODO what graph node is this
def pick_editnode(self, main_button):
self.network_layer_option_menu.destroy()
main_button.configure(image=Images.get("editnode"))
main_button.configure(image=Images.get(ImageEnum.EDITNODE.value))
logging.debug("Pick editnode option")
def draw_network_layer_options(self, network_layer_button):
@ -239,13 +242,13 @@ class CoreToolbar(object):
self.destroy_previous_frame()
option_frame = tk.Frame(self.master, padx=1, pady=1)
img_list = [
Images.get("router"),
Images.get("host"),
Images.get("pc"),
Images.get("mdr"),
Images.get("prouter"),
Images.get("ovs"),
Images.get("editnode"),
Images.get(ImageEnum.ROUTER.value),
Images.get(ImageEnum.HOST.value),
Images.get(ImageEnum.PC.value),
Images.get(ImageEnum.MDR.value),
Images.get(ImageEnum.PROUTER.value),
Images.get(ImageEnum.OVS.value),
Images.get(ImageEnum.EDITNODE.value),
]
func_list = [
self.pick_router,
@ -289,7 +292,7 @@ class CoreToolbar(object):
:return: nothing
"""
router_image = Images.get("router")
router_image = Images.get(ImageEnum.ROUTER.value)
network_layer_button = tk.Radiobutton(
self.edit_frame,
indicatoron=False,
@ -306,41 +309,41 @@ class CoreToolbar(object):
def pick_hub(self, main_button):
logging.debug("Pick link-layer node HUB")
self.link_layer_option_menu.destroy()
main_button.configure(image=Images.get("hub"))
main_button.configure(image=Images.get(ImageEnum.HUB.value))
self.canvas.mode = GraphMode.PICKNODE
self.canvas.draw_node_image = Images.get("hub")
self.canvas.draw_node_image = Images.get(ImageEnum.HUB.value)
self.canvas.draw_node_name = "hub"
def pick_switch(self, main_button):
logging.debug("Pick link-layer node SWITCH")
self.link_layer_option_menu.destroy()
main_button.configure(image=Images.get("switch"))
main_button.configure(image=Images.get(ImageEnum.SWITCH.value))
self.canvas.mode = GraphMode.PICKNODE
self.canvas.draw_node_image = Images.get("switch")
self.canvas.draw_node_image = Images.get(ImageEnum.SWITCH.value)
self.canvas.draw_node_name = "switch"
def pick_wlan(self, main_button):
logging.debug("Pick link-layer node WLAN")
self.link_layer_option_menu.destroy()
main_button.configure(image=Images.get("wlan"))
main_button.configure(image=Images.get(ImageEnum.WLAN.value))
self.canvas.mode = GraphMode.PICKNODE
self.canvas.draw_node_image = Images.get("wlan")
self.canvas.draw_node_image = Images.get(ImageEnum.WLAN.value)
self.canvas.draw_node_name = "wlan"
def pick_rj45(self, main_button):
logging.debug("Pick link-layer node RJ45")
self.link_layer_option_menu.destroy()
main_button.configure(image=Images.get("rj45"))
main_button.configure(image=Images.get(ImageEnum.RJ45.value))
self.canvas.mode = GraphMode.PICKNODE
self.canvas.draw_node_image = Images.get("rj45")
self.canvas.draw_node_image = Images.get(ImageEnum.RJ45.value)
self.canvas.draw_node_name = "rj45"
def pick_tunnel(self, main_button):
logging.debug("Pick link-layer node TUNNEL")
self.link_layer_option_menu.destroy()
main_button.configure(image=Images.get("tunnel"))
main_button.configure(image=Images.get(ImageEnum.TUNNEL.value))
self.canvas.mode = GraphMode.PICKNODE
self.canvas.draw_node_image = Images.get("tunnel")
self.canvas.draw_node_image = Images.get(ImageEnum.TUNNEL.value)
self.canvas.draw_node_name = "tunnel"
def draw_link_layer_options(self, link_layer_button):
@ -354,11 +357,11 @@ class CoreToolbar(object):
self.destroy_previous_frame()
option_frame = tk.Frame(self.master, padx=1, pady=1)
img_list = [
Images.get("hub"),
Images.get("switch"),
Images.get("wlan"),
Images.get("rj45"),
Images.get("tunnel"),
Images.get(ImageEnum.HUB.value),
Images.get(ImageEnum.SWITCH.value),
Images.get(ImageEnum.WLAN.value),
Images.get(ImageEnum.RJ45.value),
Images.get(ImageEnum.TUNNEL.value),
]
func_list = [
self.pick_hub,
@ -398,7 +401,7 @@ class CoreToolbar(object):
:return: nothing
"""
hub_image = Images.get("hub")
hub_image = Images.get(ImageEnum.HUB.value)
link_layer_button = tk.Radiobutton(
self.edit_frame,
indicatoron=False,
@ -414,22 +417,22 @@ class CoreToolbar(object):
def pick_marker(self, main_button):
self.marker_option_menu.destroy()
main_button.configure(image=Images.get("marker"))
main_button.configure(image=Images.get(ImageEnum.MARKER.value))
logging.debug("Pick MARKER")
def pick_oval(self, main_button):
self.marker_option_menu.destroy()
main_button.configure(image=Images.get("oval"))
main_button.configure(image=Images.get(ImageEnum.OVAL.value))
logging.debug("Pick OVAL")
def pick_rectangle(self, main_button):
self.marker_option_menu.destroy()
main_button.configure(image=Images.get("rectangle"))
main_button.configure(image=Images.get(ImageEnum.RECTANGLE.value))
logging.debug("Pick RECTANGLE")
def pick_text(self, main_button):
self.marker_option_menu.destroy()
main_button.configure(image=Images.get("text"))
main_button.configure(image=Images.get(ImageEnum.TEXT.value))
logging.debug("Pick TEXT")
def draw_marker_options(self, main_button):
@ -443,10 +446,10 @@ class CoreToolbar(object):
self.destroy_previous_frame()
option_frame = tk.Frame(self.master, padx=1, pady=1)
img_list = [
Images.get("marker"),
Images.get("oval"),
Images.get("rectangle"),
Images.get("text"),
Images.get(ImageEnum.MARKER.value),
Images.get(ImageEnum.OVAL.value),
Images.get(ImageEnum.RECTANGLE.value),
Images.get(ImageEnum.TEXT.value),
]
func_list = [
self.pick_marker,
@ -475,7 +478,7 @@ class CoreToolbar(object):
:return: nothing
"""
marker_image = Images.get("marker")
marker_image = Images.get(ImageEnum.MARKER.value)
marker_main_button = tk.Radiobutton(
self.edit_frame,
indicatoron=False,
@ -492,13 +495,13 @@ class CoreToolbar(object):
def create_toolbar(self):
self.create_regular_button(
self.edit_frame,
Images.get("start"),
Images.get(ImageEnum.START.value),
self.click_start_session_tool,
"start the session",
)
self.create_radio_button(
self.edit_frame,
Images.get("select"),
Images.get(ImageEnum.SELECT.value),
self.click_selection_tool,
self.radio_value,
1,
@ -506,7 +509,7 @@ class CoreToolbar(object):
)
self.create_radio_button(
self.edit_frame,
Images.get("link"),
Images.get(ImageEnum.LINK.value),
self.click_link_tool,
self.radio_value,
2,
@ -520,7 +523,7 @@ class CoreToolbar(object):
def create_observe_button(self):
menu_button = tk.Menubutton(
self.edit_frame,
image=Images.get("observe"),
image=Images.get(ImageEnum.OBSERVE.value),
width=self.width,
height=self.height,
direction=tk.RIGHT,
@ -550,10 +553,10 @@ class CoreToolbar(object):
def click_stop_button(self):
logging.debug("Click on STOP button ")
self.destroy_children_widgets(self.edit_frame)
self.create_toolbar()
self.canvas.core_grpc.set_session_state("datacollect")
self.canvas.core_grpc.delete_links()
self.canvas.core_grpc.delete_nodes()
self.create_toolbar()
def click_run_button(self):
logging.debug("Click on RUN button")
@ -570,13 +573,13 @@ class CoreToolbar(object):
def create_runtime_toolbar(self):
self.create_regular_button(
self.edit_frame,
Images.get("stop"),
Images.get(ImageEnum.STOP.value),
self.click_stop_button,
"stop the session",
)
self.create_radio_button(
self.edit_frame,
Images.get("select"),
Images.get(ImageEnum.SELECT.value),
self.click_selection_tool,
self.exec_radio_value,
1,
@ -585,7 +588,7 @@ class CoreToolbar(object):
self.create_observe_button()
self.create_radio_button(
self.edit_frame,
Images.get("plot"),
Images.get(ImageEnum.PLOT.value),
self.click_plot_button,
self.exec_radio_value,
2,
@ -593,7 +596,7 @@ class CoreToolbar(object):
)
self.create_radio_button(
self.edit_frame,
Images.get("marker"),
Images.get(ImageEnum.MARKER.value),
self.click_marker_button,
self.exec_radio_value,
3,
@ -601,13 +604,16 @@ class CoreToolbar(object):
)
self.create_radio_button(
self.edit_frame,
Images.get("twonode"),
Images.get(ImageEnum.TWONODE.value),
self.click_two_node_button,
self.exec_radio_value,
4,
"run command from one node to another",
)
self.create_regular_button(
self.edit_frame, Images.get("run"), self.click_run_button, "run"
self.edit_frame,
Images.get(ImageEnum.RUN.value),
self.click_run_button,
"run",
)
self.exec_radio_value.set(1)

View file

@ -1,10 +1,12 @@
import enum
import logging
import math
import tkinter as tk
from core.api.grpc import core_pb2
from coretk.grpcmanagement import GrpcManager
from coretk.images import Images
from coretk.interface import Interface
class GraphMode(enum.Enum):
@ -34,7 +36,7 @@ class CanvasGraph(tk.Canvas):
self.draw_grid()
self.core_grpc = grpc
self.grpc_manager = GrpcManager()
self.draw_existing_component()
# self.draw_existing_component()
def setup_menus(self):
self.node_context = tk.Menu(self.master)
@ -52,9 +54,6 @@ class CanvasGraph(tk.Canvas):
self.bind("<ButtonRelease-1>", self.click_release)
self.bind("<B1-Motion>", self.click_motion)
self.bind("<Button-3>", self.context)
# self.bind("e", self.set_mode)
# self.bind("s", self.set_mode)
# self.bind("n", self.set_mode)
def draw_grid(self, width=1000, height=750):
"""
@ -91,8 +90,7 @@ class CanvasGraph(tk.Canvas):
session_id = self.core_grpc.session_id
session = self.core_grpc.core.get_session(session_id).session
# nodes = response.session.nodes
# if len(nodes) > 0:
# redraw existing nodes
for node in session.nodes:
# peer to peer node is not drawn on the GUI
if node.type != core_pb2.NodeType.PEER_TO_PEER:
@ -104,18 +102,62 @@ class CanvasGraph(tk.Canvas):
core_id_to_canvas_id[node.id] = n.id
self.grpc_manager.add_preexisting_node(n, session_id, node, name)
self.grpc_manager.update_reusable_id()
# draw existing links
# links = response.session.links
for link in session.links:
n1 = self.nodes[core_id_to_canvas_id[link.node_one_id]]
n2 = self.nodes[core_id_to_canvas_id[link.node_two_id]]
e = CanvasEdge(n1.x_coord, n1.y_coord, n2.x_coord, n2.y_coord, n1.id, self)
n1.edges.add(e)
n2.edges.add(e)
self.edges[e.token] = e
self.grpc_manager.add_edge(session_id, e.token, n1.id, n2.id)
# TODO add back the link info to grpc manager also redraw
grpc_if1 = link.interface_one
grpc_if2 = link.interface_two
ip4_src = None
ip4_dst = None
ip6_src = None
ip6_dst = None
if grpc_if1 is not None:
ip4_src = grpc_if1.ip4
ip6_src = grpc_if1.ip6
if grpc_if2 is not None:
ip4_dst = grpc_if2.ip4
ip6_dst = grpc_if2.ip6
e.link_info = LinkInfo(
canvas=self,
edge_id=e.id,
ip4_src=ip4_src,
ip6_src=ip6_src,
ip4_dst=ip4_dst,
ip6_dst=ip6_dst,
throughput=None,
)
# TODO will include throughput and ipv6 in the future
if1 = Interface(grpc_if1.name, grpc_if1.ip4)
if2 = Interface(grpc_if2.name, grpc_if2.ip4)
self.grpc_manager.edges[e.token].interface_1 = if1
self.grpc_manager.edges[e.token].interface_2 = if2
self.grpc_manager.nodes[
core_id_to_canvas_id[link.node_one_id]
].interfaces.append(if1)
self.grpc_manager.nodes[
core_id_to_canvas_id[link.node_two_id]
].interfaces.append(if2)
# lift the nodes so they on top of the links
for i in core_id_to_canvas_id.values():
self.lift(i)
def delete_components(self):
tags = ["node", "edge", "linkinfo", "nodename"]
for i in tags:
for id in self.find_withtag(i):
self.delete(id)
def canvas_xy(self, event):
"""
Convert window coordinate to canvas coordinate
@ -171,6 +213,7 @@ class CanvasGraph(tk.Canvas):
self.mode = GraphMode.NODE
def handle_edge_release(self, event):
print("Calling edge release")
edge = self.drawing_edge
self.drawing_edge = None
@ -204,7 +247,20 @@ class CanvasGraph(tk.Canvas):
node_dst.edges.add(edge)
self.grpc_manager.add_edge(
self.core_grpc.get_session_id(), edge.token, node_src.id, node_dst.id
self.core_grpc.session_id, edge.token, node_src.id, node_dst.id
)
# draw link info on the edge
if1 = self.grpc_manager.edges[edge.token].interface_1
if2 = self.grpc_manager.edges[edge.token].interface_2
edge.link_info = LinkInfo(
self,
edge.id,
ip4_src=if1.ip4_and_prefix,
ip6_src=None,
ip4_dst=if2.ip4_and_prefix,
ip6_dst=None,
throughput=None,
)
logging.debug(f"edges: {self.find_withtag('edge')}")
@ -216,6 +272,7 @@ class CanvasGraph(tk.Canvas):
:param event: mouse event
:return: nothing
"""
print("click on the canvas")
logging.debug(f"click press: {event}")
selected = self.get_selected(event)
is_node = selected in self.find_withtag("node")
@ -243,14 +300,15 @@ class CanvasGraph(tk.Canvas):
self.node_context.post(event.x_root, event.y_root)
def add_node(self, x, y, image, node_name):
node = CanvasNode(
x=x, y=y, image=image, canvas=self, core_id=self.grpc_manager.peek_id()
)
self.nodes[node.id] = node
self.grpc_manager.add_node(
self.core_grpc.get_session_id(), node.id, x, y, node_name
)
return node
if self.selected == 1:
node = CanvasNode(
x=x, y=y, image=image, canvas=self, core_id=self.grpc_manager.peek_id()
)
self.nodes[node.id] = node
self.grpc_manager.add_node(
self.core_grpc.session_id, node.id, x, y, node_name
)
return node
class CanvasEdge:
@ -258,7 +316,7 @@ class CanvasEdge:
Canvas edge class
"""
width = 3
width = 1.3
def __init__(self, x1, y1, x2, y2, src, canvas):
"""
@ -273,9 +331,13 @@ class CanvasEdge:
self.src = src
self.dst = None
self.canvas = canvas
self.id = self.canvas.create_line(x1, y1, x2, y2, tags="edge", width=self.width)
self.id = self.canvas.create_line(
x1, y1, x2, y2, tags="edge", width=self.width, fill="#ff0000"
)
self.token = None
# link info object
self.link_info = None
# TODO resolve this
# self.canvas.tag_lower(self.id)
@ -301,29 +363,40 @@ class CanvasNode:
self.core_id = core_id
self.x_coord = x
self.y_coord = y
self.name = f"Node {self.core_id}"
self.text_id = self.canvas.create_text(x, y + 20, text=self.name)
self.name = f"N{self.core_id}"
self.text_id = self.canvas.create_text(
x, y + 20, text=self.name, tags="nodename"
)
self.canvas.tag_bind(self.id, "<ButtonPress-1>", self.click_press)
self.canvas.tag_bind(self.id, "<ButtonRelease-1>", self.click_release)
self.canvas.tag_bind(self.id, "<B1-Motion>", self.motion)
self.canvas.tag_bind(self.id, "<Button-3>", self.context)
self.canvas.tag_bind(self.id, "<Double-Button-1>", self.double_click)
self.edges = set()
self.moving = None
#
# def get_coords(self):
# return self.x_coord, self.y_coord
def double_click(self, event):
node_id = self.canvas.grpc_manager.nodes[self.id].node_id
state = self.canvas.core_grpc.get_session_state()
if state == core_pb2.SessionState.RUNTIME:
self.canvas.core_grpc.launch_terminal(node_id)
def update_coords(self):
self.x_coord, self.y_coord = self.canvas.coords(self.id)
def click_press(self, event):
print("click on the node")
logging.debug(f"click press {self.name}: {event}")
self.moving = self.canvas.canvas_xy(event)
# return "break"
def click_release(self, event):
logging.debug(f"click release {self.name}: {event}")
self.update_coords()
self.canvas.grpc_manager.update_node_location(
self.id, self.x_coord, self.y_coord
)
self.moving = None
def motion(self, event):
@ -344,6 +417,64 @@ class CanvasNode:
self.canvas.coords(edge.id, new_x, new_y, x2, y2)
else:
self.canvas.coords(edge.id, x1, y1, new_x, new_y)
edge.link_info.recalculate_info()
def context(self, event):
logging.debug(f"context click {self.name}: {event}")
class LinkInfo:
def __init__(self, canvas, edge_id, ip4_src, ip6_src, ip4_dst, ip6_dst, throughput):
self.canvas = canvas
self.edge_id = edge_id
self.radius = 37
self.ip4_address_1 = ip4_src
self.ip6_address_1 = ip6_src
self.ip4_address_2 = ip4_dst
self.ip6_address_2 = ip6_dst
self.throughput = throughput
self.id1 = self.create_edge_src_info()
self.id2 = self.create_edge_dst_info()
def slope_src_dst(self):
x1, y1, x2, y2 = self.canvas.coords(self.edge_id)
return (y2 - y1) / (x2 - x1)
def create_edge_src_info(self):
x1, y1, x2, _ = self.canvas.coords(self.edge_id)
m = self.slope_src_dst()
distance = math.cos(math.atan(m)) * self.radius
if x1 > x2:
distance = -distance
# id1 = self.canvas.create_text(x1, y1, text=self.ip4_address_1)
print(self.ip4_address_1)
id1 = self.canvas.create_text(
x1 + distance, y1 + distance * m, text=self.ip4_address_1, tags="linkinfo"
)
return id1
def create_edge_dst_info(self):
x1, _, x2, y2 = self.canvas.coords(self.edge_id)
m = self.slope_src_dst()
distance = math.cos(math.atan(m)) * self.radius
if x1 > x2:
distance = -distance
# id2 = self.canvas.create_text(x2, y2, text=self.ip4_address_2)
id2 = self.canvas.create_text(
x2 - distance, y2 - distance * m, text=self.ip4_address_2, tags="linkinfo"
)
return id2
def recalculate_info(self):
x1, y1, x2, y2 = self.canvas.coords(self.edge_id)
m = self.slope_src_dst()
distance = math.cos(math.atan(m)) * self.radius
if x1 > x2:
distance = -distance
new_x1 = x1 + distance
new_y1 = y1 + distance * m
new_x2 = x2 - distance
new_y2 = y2 - distance * m
self.canvas.coords(self.id1, new_x1, new_y1)
self.canvas.coords(self.id2, new_x2, new_y2)

View file

@ -5,6 +5,7 @@ that can be useful for grpc, acts like a session class
import logging
from core.api.grpc import core_pb2
from coretk.interface import Interface, InterfaceManager
link_layer_nodes = ["switch", "hub", "wlan", "rj45", "tunnel"]
network_layer_nodes = ["router", "host", "PC", "mdr", "prouter", "OVS"]
@ -29,6 +30,7 @@ class Node:
self.y = y
self.model = model
self.name = name
self.interfaces = []
class Edge:
@ -46,6 +48,8 @@ class Edge:
self.id2 = node_id_2
self.type1 = node_type_1
self.type2 = node_type_2
self.interface_1 = None
self.interface_2 = None
class GrpcManager:
@ -57,6 +61,7 @@ class GrpcManager:
self.reusable = []
self.preexisting = []
self.interfaces_manager = InterfaceManager()
def peek_id(self):
"""
@ -146,6 +151,18 @@ class GrpcManager:
)
self.nodes[canvas_node.id] = n
def update_node_location(self, canvas_id, new_x, new_y):
"""
update node
:param int canvas_id: canvas id of that node
:param int new_x: new x coord
:param int new_y: new y coord
:return: nothing
"""
self.nodes[canvas_id].x = new_x
self.nodes[canvas_id].y = new_y
def update_reusable_id(self):
"""
Update available id for reuse
@ -173,7 +190,60 @@ class GrpcManager:
except KeyError:
logging.error("grpcmanagement.py INVALID NODE CANVAS ID")
def create_interface(self, edge, src_canvas_id, dst_canvas_id):
"""
Create the interface for the two end of an edge, add a copy to node's interfaces
:param coretk.grpcmanagement.Edge edge: edge to add interfaces to
:param int src_canvas_id: canvas id for the source node
:param int dst_canvas_id: canvas id for the destination node
:return: nothing
"""
src_interface = None
dst_interface = None
src_node = self.nodes[src_canvas_id]
if src_node.model in network_layer_nodes:
ifid = len(src_node.interfaces)
name = "eth" + str(ifid)
src_interface = Interface(
name=name, ifid=ifid, ipv4=str(self.interfaces_manager.get_address())
)
self.nodes[src_canvas_id].interfaces.append(src_interface)
logging.debug(
"Create source interface 1... IP: %s, name: %s",
src_interface.ipv4,
src_interface.name,
)
dst_node = self.nodes[dst_canvas_id]
if dst_node.model in network_layer_nodes:
ifid = len(dst_node.interfaces)
name = "veth" + str(ifid)
dst_interface = Interface(
name=name, ifid=ifid, ipv4=str(self.interfaces_manager.get_address())
)
self.nodes[dst_canvas_id].interfaces.append(dst_interface)
logging.debug(
"Create destination interface... IP: %s, name: %s",
dst_interface.ipv4,
dst_interface.name,
)
edge.interface_1 = src_interface
edge.interface_2 = dst_interface
def add_edge(self, session_id, token, canvas_id_1, canvas_id_2):
"""
Add an edge to grpc manager
:param int session_id: core session id
:param tuple(int, int) token: edge's identification in the canvas
:param int canvas_id_1: canvas id of source node
:param int canvas_id_2: canvas_id of destination node
:return: nothing
"""
if canvas_id_1 in self.nodes and canvas_id_2 in self.nodes:
edge = Edge(
session_id,
@ -183,6 +253,7 @@ class GrpcManager:
self.nodes[canvas_id_2].type,
)
self.edges[token] = edge
self.create_interface(edge, canvas_id_1, canvas_id_2)
logging.debug("Adding edge to grpc manager...")
else:
logging.error("grpcmanagement.py INVALID CANVAS NODE ID")

View file

Before

Width:  |  Height:  |  Size: 744 B

After

Width:  |  Height:  |  Size: 744 B

View file

Before

Width:  |  Height:  |  Size: 2.9 KiB

After

Width:  |  Height:  |  Size: 2.9 KiB

View file

Before

Width:  |  Height:  |  Size: 635 B

After

Width:  |  Height:  |  Size: 635 B

View file

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 1.2 KiB

View file

Before

Width:  |  Height:  |  Size: 719 B

After

Width:  |  Height:  |  Size: 719 B

View file

Before

Width:  |  Height:  |  Size: 744 B

After

Width:  |  Height:  |  Size: 744 B

View file

Before

Width:  |  Height:  |  Size: 86 B

After

Width:  |  Height:  |  Size: 86 B

View file

Before

Width:  |  Height:  |  Size: 375 B

After

Width:  |  Height:  |  Size: 375 B

View file

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 1.2 KiB

View file

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

View file

Before

Width:  |  Height:  |  Size: 174 B

After

Width:  |  Height:  |  Size: 174 B

View file

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 1.3 KiB

View file

Before

Width:  |  Height:  |  Size: 265 B

After

Width:  |  Height:  |  Size: 265 B

View file

Before

Width:  |  Height:  |  Size: 160 B

After

Width:  |  Height:  |  Size: 160 B

View file

Before

Width:  |  Height:  |  Size: 755 B

After

Width:  |  Height:  |  Size: 755 B

View file

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

View file

Before

Width:  |  Height:  |  Size: 753 B

After

Width:  |  Height:  |  Size: 753 B

View file

Before

Width:  |  Height:  |  Size: 324 B

After

Width:  |  Height:  |  Size: 324 B

View file

Before

Width:  |  Height:  |  Size: 925 B

After

Width:  |  Height:  |  Size: 925 B

View file

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

View file

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 1.2 KiB

View file

Before

Width:  |  Height:  |  Size: 127 B

After

Width:  |  Height:  |  Size: 127 B

View file

Before

Width:  |  Height:  |  Size: 799 B

After

Width:  |  Height:  |  Size: 799 B

View file

Before

Width:  |  Height:  |  Size: 220 B

After

Width:  |  Height:  |  Size: 220 B

View file

Before

Width:  |  Height:  |  Size: 146 B

After

Width:  |  Height:  |  Size: 146 B

View file

@ -1,11 +1,13 @@
import logging
import os
from enum import Enum
from PIL import Image, ImageTk
from core.api.grpc import core_pb2
PATH = os.path.abspath(os.path.dirname(__file__))
ICONS_DIR = os.path.join(PATH, "icons")
class Images:
@ -13,7 +15,7 @@ class Images:
@classmethod
def load(cls, name, file_path):
file_path = os.path.join(PATH, file_path)
# file_path = os.path.join(PATH, file_path)
image = Image.open(file_path)
tk_image = ImageTk.PhotoImage(image)
cls.images[name] = tk_image
@ -33,55 +35,62 @@ class Images:
:return: the matching image and its name
"""
if node_type == core_pb2.NodeType.SWITCH:
return Images.get("switch"), "switch"
return Images.get(ImageEnum.SWITCH.value), "switch"
if node_type == core_pb2.NodeType.HUB:
return Images.get("hub"), "hub"
return Images.get(ImageEnum.HUB.value), "hub"
if node_type == core_pb2.NodeType.WIRELESS_LAN:
return Images.get("wlan"), "wlan"
return Images.get(ImageEnum.WLAN.value), "wlan"
if node_type == core_pb2.NodeType.RJ45:
return Images.get("rj45"), "rj45"
return Images.get(ImageEnum.RJ45.value), "rj45"
if node_type == core_pb2.NodeType.TUNNEL:
return Images.get("tunnel"), "tunnel"
return Images.get(ImageEnum.TUNNEL.value), "tunnel"
if node_type == core_pb2.NodeType.DEFAULT:
if node_model == "router":
return Images.get("router"), "router"
return Images.get(ImageEnum.ROUTER.value), "router"
if node_model == "host":
return Images.get(("host")), "host"
return Images.get((ImageEnum.HOST.value)), "host"
if node_model == "PC":
return Images.get("pc"), "PC"
return Images.get(ImageEnum.PC.value), "PC"
if node_model == "mdr":
return Images.get("mdr"), "mdr"
return Images.get(ImageEnum.MDR.value), "mdr"
if node_model == "prouter":
return Images.get("prouter"), "prouter"
return Images.get(ImageEnum.PROUTER.value), "prouter"
if node_model == "OVS":
return Images.get("ovs"), "ovs"
return Images.get(ImageEnum.OVS.value), "ovs"
else:
logging.debug("INVALID INPUT OR NOT CONSIDERED YET")
class ImageEnum(Enum):
SWITCH = "lanswitch"
CORE = "core-icon"
START = "start"
MARKER = "marker"
ROUTER = "router"
SELECT = "select"
LINK = "link"
HUB = "hub"
WLAN = "wlan"
RJ45 = "rj45"
TUNNEL = "tunnel"
OVAL = "oval"
RECTANGLE = "rectangle"
TEXT = "text"
HOST = "host"
PC = "pc"
MDR = "mdr"
PROUTER = "router_green"
OVS = "OVS"
EDITNODE = "document-properties"
PLOT = "plot"
TWONODE = "twonode"
STOP = "stop"
OBSERVE = "observe"
RUN = "run"
def load_core_images(images):
images.load("core", "core-icon.png")
images.load("start", "start.gif")
images.load("switch", "lanswitch.gif")
images.load("marker", "marker.gif")
images.load("router", "router.gif")
images.load("select", "select.gif")
images.load("link", "link.gif")
images.load("hub", "hub.gif")
images.load("wlan", "wlan.gif")
images.load("rj45", "rj45.gif")
images.load("tunnel", "tunnel.gif")
images.load("oval", "oval.gif")
images.load("rectangle", "rectangle.gif")
images.load("text", "text.gif")
images.load("host", "host.gif")
images.load("pc", "pc.gif")
images.load("mdr", "mdr.gif")
images.load("prouter", "router_green.gif")
images.load("ovs", "OVS.gif")
images.load("editnode", "document-properties.gif")
images.load("run", "run.gif")
images.load("plot", "plot.gif")
images.load("twonode", "twonode.gif")
images.load("stop", "stop.gif")
images.load("observe", "observe.gif")
for file_name in os.listdir(ICONS_DIR):
file_path = os.path.join(ICONS_DIR, file_name)
name = file_name.split(".")[0]
images.load(name, file_path)

View file

@ -0,0 +1,43 @@
import ipaddress
import random
class Interface:
def __init__(self, name, ipv4, ifid=None):
"""
Create an interface instance
:param str name: interface name
:param str ip4: IPv4
:param str mac: MAC address
:param int ifid: interface id
"""
self.name = name
self.ipv4 = ipv4
self.ip4prefix = 24
self.ip4_and_prefix = ipv4 + "/" + str(self.ip4prefix)
self.mac = self.random_mac_address()
self.id = ifid
def random_mac_address(self):
return "02:00:00:%02x:%02x:%02x" % (
random.randint(0, 255),
random.randint(0, 255),
random.randint(0, 225),
)
class InterfaceManager:
def __init__(self):
self.addresses = list(ipaddress.ip_network("10.0.0.0/24").hosts())
self.index = 0
def get_address(self):
"""
Retrieve a new ipv4 address
:return:
"""
i = self.index
self.index = self.index + 1
return self.addresses[i]

View file

@ -3,7 +3,14 @@ The actions taken when each menubar option is clicked
"""
import logging
import tkinter as tk
import webbrowser
from tkinter import messagebox
from core.api.grpc import core_pb2
from coretk.coregrpc import CoreGrpc
SAVEDIR = "/home/ncs/Desktop/"
def sub_menu_items():
@ -38,14 +45,6 @@ def file_save_shortcut(event):
logging.debug("Shortcut for file save")
def file_save_as_xml():
logging.debug("Click save as XML")
def file_save_as_imn():
logging.debug("Click save as imn")
def file_export_python_script():
logging.debug("Click file export python script")
@ -70,10 +69,6 @@ def file_save_screenshot():
logging.debug("Click file save screenshot")
def file_example_link():
logging.debug("Click file example link")
def edit_undo():
logging.debug("Click edit undo")
@ -294,10 +289,6 @@ def widgets_configure_throughput():
logging.debug("Click widgets configure throughput")
def session_start():
logging.debug("Click session start")
def session_change_sessions():
logging.debug("Click session change sessions")
@ -326,13 +317,107 @@ def session_options():
logging.debug("Click session options")
def help_core_github():
webbrowser.open_new("https://github.com/coreemu/core")
def help_core_documentation():
webbrowser.open_new("http://coreemu.github.io/core/")
# def help_core_github():
# webbrowser.open_new("https://github.com/coreemu/core")
#
#
# def help_core_documentation():
# webbrowser.open_new("http://coreemu.github.io/core/")
def help_about():
logging.debug("Click help About")
class MenuAction:
"""
Actions performed when choosing menu items
"""
def __init__(self, application, master):
self.master = master
self.application = application
self.core_grpc = application.core_grpc
def clean_nodes_links_and_set_configuarations(self):
"""
Prompt use to stop running session before application is closed
:return: nothing
"""
logging.info(
"menuaction.py: clean_nodes_links_and_set_configuration() Exiting the program"
)
grpc = self.application.core_grpc
state = grpc.get_session_state()
if (
state == core_pb2.SessionState.SHUTDOWN
or state == core_pb2.SessionState.DEFINITION
):
grpc.delete_session()
grpc.core.close()
# self.application.quit()
else:
msgbox = messagebox.askyesnocancel("stop", "Stop the running session?")
if msgbox or msgbox is False:
if msgbox:
grpc.set_session_state("datacollect")
grpc.delete_links()
grpc.delete_nodes()
grpc.delete_session()
grpc.core.close()
# self.application.quit()
def on_quit(self):
"""
Prompt user whether so save running session, and then close the application
:return: nothing
"""
self.clean_nodes_links_and_set_configuarations()
# self.application.core_grpc.close()
self.application.quit()
def file_save_as_xml(self):
logging.info("menuaction.py file_save_as_xml()")
grpc = self.application.core_grpc
file_path = tk.filedialog.asksaveasfilename(
initialdir=SAVEDIR,
title="Save As",
filetypes=(("EmulationScript XML files", "*.xml"), ("All files", "*")),
defaultextension=".xml",
)
with open("prev_saved_xml.txt", "a") as file:
file.write(file_path + "\n")
grpc.save_xml(file_path)
def file_open_xml(self):
logging.info("menuaction.py file_open_xml()")
# grpc = self.application.core_grpc
file_path = tk.filedialog.askopenfilename(
initialdir=SAVEDIR,
title="Open",
filetypes=(("EmulationScript XML File", "*.xml"), ("All Files", "*")),
)
# clean up before openning a new session
# t0 = time.clock()
self.clean_nodes_links_and_set_configuarations()
grpc = CoreGrpc(self.application.master)
grpc.core.connect()
session_id = grpc.open_xml(file_path)
grpc.session_id = session_id
self.application.core_grpc = grpc
self.application.canvas.core_grpc = grpc
self.application.canvas.delete_components()
self.application.canvas.draw_existing_component()
# t1 = time.clock()
# print(t1 - t0)
def help_core_github(self):
webbrowser.open_new("https://github.com/coreemu/core")
def help_core_documentation(self):
webbrowser.open_new("http://coreemu.github.io/core/")

BIN
coretk/coretk/oldimage/OVS.gif Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 744 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 635 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 719 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 744 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 86 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 375 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 174 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 265 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 160 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 755 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 753 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 324 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 925 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 127 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 799 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 220 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 146 B

View file

@ -0,0 +1,5 @@
/home/ncs/Desktop/random.xml/home/ncs/Desktop/untitled.xml/home/ncs/Desktop/test.xml
/home/ncs/Desktop/test1.xml
/home/ncs/Desktop/untitled.xml
/home/ncs/Desktop/test1.xml

23
output.txt Normal file

File diff suppressed because one or more lines are too long