some work on grpc add nodes and links, some work on query session, redraw nodes
This commit is contained in:
parent
cbd593eed6
commit
cb03aa261a
6 changed files with 387 additions and 137 deletions
|
@ -16,16 +16,20 @@ class Application(tk.Frame):
|
||||||
self.setup_app()
|
self.setup_app()
|
||||||
self.menubar = None
|
self.menubar = None
|
||||||
self.canvas = None
|
self.canvas = None
|
||||||
|
|
||||||
|
# start grpc
|
||||||
self.core_grpc = CoreGrpc()
|
self.core_grpc = CoreGrpc()
|
||||||
|
|
||||||
self.create_menu()
|
self.create_menu()
|
||||||
self.create_widgets()
|
self.create_widgets()
|
||||||
|
|
||||||
def load_images(self):
|
def load_images(self):
|
||||||
|
"""
|
||||||
|
Load core images
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
images.load_core_images(Images)
|
images.load_core_images(Images)
|
||||||
|
|
||||||
def close_grpc(self):
|
|
||||||
self.core_grpc.close()
|
|
||||||
|
|
||||||
def setup_app(self):
|
def setup_app(self):
|
||||||
self.master.title("CORE")
|
self.master.title("CORE")
|
||||||
self.master.geometry("1000x800")
|
self.master.geometry("1000x800")
|
||||||
|
@ -47,8 +51,8 @@ class Application(tk.Frame):
|
||||||
core_editbar.create_toolbar()
|
core_editbar.create_toolbar()
|
||||||
|
|
||||||
self.canvas = CanvasGraph(
|
self.canvas = CanvasGraph(
|
||||||
grpc=self.core_grpc,
|
|
||||||
master=self,
|
master=self,
|
||||||
|
grpc=self.core_grpc,
|
||||||
background="#cccccc",
|
background="#cccccc",
|
||||||
scrollregion=(0, 0, 1000, 1000),
|
scrollregion=(0, 0, 1000, 1000),
|
||||||
)
|
)
|
||||||
|
@ -79,4 +83,3 @@ if __name__ == "__main__":
|
||||||
logging.basicConfig(level=logging.DEBUG)
|
logging.basicConfig(level=logging.DEBUG)
|
||||||
app = Application()
|
app = Application()
|
||||||
app.mainloop()
|
app.mainloop()
|
||||||
app.close_grpc()
|
|
||||||
|
|
|
@ -14,18 +14,20 @@ class CoreGrpc:
|
||||||
self.core = client.CoreGrpcClient()
|
self.core = client.CoreGrpcClient()
|
||||||
self.session_id = None
|
self.session_id = None
|
||||||
self.set_up()
|
self.set_up()
|
||||||
|
self.interface_helper = None
|
||||||
|
|
||||||
def log_event(self, event):
|
def log_event(self, event):
|
||||||
logging.info("event: %s", event)
|
logging.info("event: %s", event)
|
||||||
|
|
||||||
def set_up(self):
|
def redraw_canvas(self):
|
||||||
|
return
|
||||||
|
|
||||||
|
def create_new_session(self):
|
||||||
"""
|
"""
|
||||||
Create session, handle events session may broadcast, change session state
|
Create a new session
|
||||||
|
|
||||||
:return: nothing
|
:return: nothing
|
||||||
"""
|
"""
|
||||||
self.core.connect()
|
|
||||||
# create session
|
|
||||||
response = self.core.create_session()
|
response = self.core.create_session()
|
||||||
logging.info("created session: %s", response)
|
logging.info("created session: %s", response)
|
||||||
|
|
||||||
|
@ -33,39 +35,67 @@ class CoreGrpc:
|
||||||
self.session_id = response.session_id
|
self.session_id = response.session_id
|
||||||
self.core.events(self.session_id, self.log_event)
|
self.core.events(self.session_id, self.log_event)
|
||||||
|
|
||||||
# change session state
|
def query_existing_sessions(self, sessions):
|
||||||
|
"""
|
||||||
|
Query for existing sessions and prompt to join one
|
||||||
|
|
||||||
|
:param repeated core_pb2.SessionSummary sessions: summaries of all the existing sessions
|
||||||
|
|
||||||
|
:return: nothing
|
||||||
|
"""
|
||||||
|
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)
|
||||||
|
|
||||||
|
def set_up(self):
|
||||||
|
"""
|
||||||
|
Query sessions, if there exist any, promt whether to join one
|
||||||
|
|
||||||
|
:return: nothing
|
||||||
|
"""
|
||||||
|
self.core.connect()
|
||||||
|
|
||||||
|
response = self.core.get_sessions()
|
||||||
|
logging.info("all sessions: %s", response)
|
||||||
|
|
||||||
|
# if there are no sessions, create a new session, else join a session
|
||||||
|
sessions = response.sessions
|
||||||
|
|
||||||
|
if len(sessions) == 0:
|
||||||
|
self.create_new_session()
|
||||||
|
else:
|
||||||
|
# self.create_new_session()
|
||||||
|
self.query_existing_sessions(sessions)
|
||||||
|
|
||||||
|
def set_configuration_state(self):
|
||||||
response = self.core.set_session_state(
|
response = self.core.set_session_state(
|
||||||
self.session_id, core_pb2.SessionState.CONFIGURATION
|
self.session_id, core_pb2.SessionState.CONFIGURATION
|
||||||
)
|
)
|
||||||
logging.info("set session state: %s", response)
|
logging.info("set session state: %s", response)
|
||||||
|
|
||||||
|
def set_instantiate_state(self):
|
||||||
|
response = self.core.set_session_state(
|
||||||
|
self.session_id, core_pb2.SessionState.INSTANTIATION
|
||||||
|
)
|
||||||
|
logging.info("set session state: %s", response)
|
||||||
|
|
||||||
def get_session_id(self):
|
def get_session_id(self):
|
||||||
return self.session_id
|
return self.session_id
|
||||||
|
|
||||||
# TODO add checkings to the function
|
def add_node(self, node_type, model, x, y, name):
|
||||||
def add_node(self, x, y, node_name):
|
logging.info("ADD NODE %s", name)
|
||||||
link_layer_nodes = ["switch", "hub", "wlan", "rj45", "tunnel"]
|
|
||||||
network_layer_nodes = ["default"]
|
|
||||||
node = None
|
|
||||||
if node_name in link_layer_nodes:
|
|
||||||
if node_name == "switch":
|
|
||||||
node = core_pb2.Node(type=core_pb2.NodeType.SWITCH)
|
|
||||||
elif node_name == "hub":
|
|
||||||
node = core_pb2.Node(type=core_pb2.NodeType.HUB)
|
|
||||||
elif node_name == "wlan":
|
|
||||||
node = core_pb2.Node(type=core_pb2.NodeType.WIRELESS_LAN)
|
|
||||||
elif node_name == "rj45":
|
|
||||||
node = core_pb2.Node(type=core_pb2.NodeType.RJ45)
|
|
||||||
elif node_name == "tunnel":
|
|
||||||
node = core_pb2.Node(type=core_pb2.NodeType.TUNNEL)
|
|
||||||
|
|
||||||
elif node_name in network_layer_nodes:
|
|
||||||
position = core_pb2.Position(x=x, y=y)
|
position = core_pb2.Position(x=x, y=y)
|
||||||
node = core_pb2.Node(position=position)
|
node = core_pb2.Node(type=node_type, position=position, model=model, image=name)
|
||||||
else:
|
|
||||||
return
|
|
||||||
response = self.core.add_node(self.session_id, node)
|
response = self.core.add_node(self.session_id, node)
|
||||||
logging.info("created %s: %s", node_name, response)
|
logging.info("created node: %s", response)
|
||||||
return response.node_id
|
return response.node_id
|
||||||
|
|
||||||
def edit_node(self, session_id, node_id, x, y):
|
def edit_node(self, session_id, node_id, x, y):
|
||||||
|
@ -73,6 +103,34 @@ class CoreGrpc:
|
||||||
response = self.core.edit_node(session_id, node_id, position)
|
response = self.core.edit_node(session_id, node_id, position)
|
||||||
logging.info("updated node id %s: %s", node_id, response)
|
logging.info("updated node id %s: %s", node_id, response)
|
||||||
|
|
||||||
|
# def create_interface_helper(self):
|
||||||
|
# self.interface_helper = self.core.InterfaceHelper(ip4_prefix="10.83.0.0/16")
|
||||||
|
|
||||||
|
# TODO case for other core_pb2.NodeType
|
||||||
|
def add_link(self, id1, id2, type1, type2):
|
||||||
|
"""
|
||||||
|
Grpc client request add link
|
||||||
|
|
||||||
|
:param int session_id: session id
|
||||||
|
:param int id1: node 1 core id
|
||||||
|
:param core_pb2.NodeType type1: node 1 core node type
|
||||||
|
:param int id2: node 2 core id
|
||||||
|
: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
|
||||||
|
if type1 == core_pb2.NodeType.DEFAULT:
|
||||||
|
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)
|
||||||
|
logging.info("created link: %s", response)
|
||||||
|
|
||||||
def close(self):
|
def close(self):
|
||||||
"""
|
"""
|
||||||
Clean ups when done using grpc
|
Clean ups when done using grpc
|
||||||
|
|
|
@ -27,7 +27,6 @@ class CoreToolbar(object):
|
||||||
self.width = 32
|
self.width = 32
|
||||||
self.height = 32
|
self.height = 32
|
||||||
|
|
||||||
# Used for drawing the horizontally displayed menu items for network-layer nodes and link-layer node
|
|
||||||
self.selection_tool_button = None
|
self.selection_tool_button = None
|
||||||
|
|
||||||
# Reference to the option menus
|
# Reference to the option menus
|
||||||
|
@ -35,8 +34,6 @@ class CoreToolbar(object):
|
||||||
self.marker_option_menu = None
|
self.marker_option_menu = None
|
||||||
self.network_layer_option_menu = None
|
self.network_layer_option_menu = None
|
||||||
|
|
||||||
# variables used by canvas graph
|
|
||||||
self.image_to_draw = None
|
|
||||||
self.canvas = None
|
self.canvas = None
|
||||||
|
|
||||||
def update_canvas(self, canvas):
|
def update_canvas(self, canvas):
|
||||||
|
@ -151,63 +148,79 @@ class CoreToolbar(object):
|
||||||
logging.debug("Click SELECTION TOOL")
|
logging.debug("Click SELECTION TOOL")
|
||||||
self.canvas.mode = GraphMode.SELECT
|
self.canvas.mode = GraphMode.SELECT
|
||||||
|
|
||||||
def click_start_stop_session_tool(self):
|
def click_start_session_tool(self):
|
||||||
logging.debug("Click START STOP SESSION button")
|
logging.debug("Click START STOP SESSION button")
|
||||||
self.destroy_children_widgets(self.edit_frame)
|
self.destroy_children_widgets(self.edit_frame)
|
||||||
self.canvas.set_canvas_mode(GraphMode.SELECT)
|
self.canvas.mode = GraphMode.SELECT
|
||||||
self.create_runtime_toolbar()
|
self.create_runtime_toolbar()
|
||||||
|
|
||||||
|
# set configuration state
|
||||||
|
self.canvas.core_grpc.set_configuration_state()
|
||||||
|
|
||||||
|
# grpc client requests creating nodes
|
||||||
|
for node in self.canvas.grpc_manager.nodes_to_create.values():
|
||||||
|
self.canvas.core_grpc.add_node(
|
||||||
|
node.type, node.model, int(node.x), int(node.y), node.name
|
||||||
|
)
|
||||||
|
self.canvas.grpc_manager.nodes_to_create.clear()
|
||||||
|
|
||||||
|
for edge in self.canvas.grpc_manager.edges_to_create.values():
|
||||||
|
self.canvas.core_grpc.add_link(edge.id1, edge.id2, edge.type1, edge.type2)
|
||||||
|
self.canvas.grpc_manager.edges_to_create.clear()
|
||||||
|
|
||||||
|
self.canvas.core_grpc.set_instantiate_state()
|
||||||
|
|
||||||
def click_link_tool(self):
|
def click_link_tool(self):
|
||||||
logging.debug("Click LINK button")
|
logging.debug("Click LINK button")
|
||||||
self.canvas.set_canvas_mode(GraphMode.EDGE)
|
self.canvas.mode = GraphMode.EDGE
|
||||||
|
|
||||||
def pick_router(self, main_button):
|
def pick_router(self, main_button):
|
||||||
logging.debug("Pick router option")
|
logging.debug("Pick router option")
|
||||||
self.network_layer_option_menu.destroy()
|
self.network_layer_option_menu.destroy()
|
||||||
main_button.configure(image=Images.get("router"))
|
main_button.configure(image=Images.get("router"))
|
||||||
self.canvas.set_canvas_mode(GraphMode.PICKNODE)
|
self.canvas.mode = GraphMode.PICKNODE
|
||||||
self.canvas.set_drawing_image(Images.get("router"))
|
self.canvas.draw_node_image = Images.get("router")
|
||||||
self.canvas.set_drawing_name("default")
|
self.canvas.draw_node_name = "router"
|
||||||
|
|
||||||
def pick_host(self, main_button):
|
def pick_host(self, main_button):
|
||||||
logging.debug("Pick host option")
|
logging.debug("Pick host option")
|
||||||
self.network_layer_option_menu.destroy()
|
self.network_layer_option_menu.destroy()
|
||||||
main_button.configure(image=Images.get("host"))
|
main_button.configure(image=Images.get("host"))
|
||||||
self.canvas.set_canvas_mode(GraphMode.PICKNODE)
|
self.canvas.mode = GraphMode.PICKNODE
|
||||||
self.canvas.set_drawing_image(Images.get("host"))
|
self.canvas.draw_node_image = Images.get("host")
|
||||||
self.canvas.set_drawing_name("default")
|
self.canvas.draw_node_name = "host"
|
||||||
|
|
||||||
def pick_pc(self, main_button):
|
def pick_pc(self, main_button):
|
||||||
logging.debug("Pick PC option")
|
logging.debug("Pick PC option")
|
||||||
self.network_layer_option_menu.destroy()
|
self.network_layer_option_menu.destroy()
|
||||||
main_button.configure(image=Images.get("pc"))
|
main_button.configure(image=Images.get("pc"))
|
||||||
self.canvas.set_canvas_mode(GraphMode.PICKNODE)
|
self.canvas.mode = GraphMode.PICKNODE
|
||||||
self.canvas.set_drawing_image(Images.get("pc"))
|
self.canvas.draw_node_image = Images.get("pc")
|
||||||
self.canvas.set_drawing_name("default")
|
self.canvas.draw_node_name = "PC"
|
||||||
|
|
||||||
def pick_mdr(self, main_button):
|
def pick_mdr(self, main_button):
|
||||||
logging.debug("Pick MDR option")
|
logging.debug("Pick MDR option")
|
||||||
self.network_layer_option_menu.destroy()
|
self.network_layer_option_menu.destroy()
|
||||||
main_button.configure(image=Images.get("mdr"))
|
main_button.configure(image=Images.get("mdr"))
|
||||||
self.canvas.set_canvas_mode(GraphMode.PICKNODE)
|
self.canvas.mode = GraphMode.PICKNODE
|
||||||
self.canvas.set_drawing_image(Images.get("mdr"))
|
self.canvas.draw_node_image = Images.get("mdr")
|
||||||
self.canvas.set_drawing_name("default")
|
self.canvas.draw_node_name = "mdr"
|
||||||
|
|
||||||
def pick_prouter(self, main_button):
|
def pick_prouter(self, main_button):
|
||||||
logging.debug("Pick prouter option")
|
logging.debug("Pick prouter option")
|
||||||
self.network_layer_option_menu.destroy()
|
self.network_layer_option_menu.destroy()
|
||||||
main_button.configure(image=Images.get("prouter"))
|
main_button.configure(image=Images.get("prouter"))
|
||||||
self.canvas.set_canvas_mode(GraphMode.PICKNODE)
|
self.canvas.mode = GraphMode.PICKNODE
|
||||||
self.canvas.set_drawing_image(Images.get("prouter"))
|
self.canvas.draw_node_image = Images.get("prouter")
|
||||||
self.canvas.set_drawing_name("default")
|
self.canvas.draw_node_name = "prouter"
|
||||||
|
|
||||||
def pick_ovs(self, main_button):
|
def pick_ovs(self, main_button):
|
||||||
logging.debug("Pick OVS option")
|
logging.debug("Pick OVS option")
|
||||||
self.network_layer_option_menu.destroy()
|
self.network_layer_option_menu.destroy()
|
||||||
main_button.configure(image=Images.get("ovs"))
|
main_button.configure(image=Images.get("ovs"))
|
||||||
self.canvas.set_canvas_mode(GraphMode.PICKNODE)
|
self.canvas.mode = GraphMode.PICKNODE
|
||||||
self.canvas.set_drawing_image(Images.get("ovs"))
|
self.canvas.draw_node_image = Images.get("ovs")
|
||||||
self.canvas.set_drawing_name("default")
|
self.canvas.draw_node_name = "OVS"
|
||||||
|
|
||||||
# TODO what graph node is this
|
# TODO what graph node is this
|
||||||
def pick_editnode(self, main_button):
|
def pick_editnode(self, main_button):
|
||||||
|
@ -294,40 +307,41 @@ class CoreToolbar(object):
|
||||||
logging.debug("Pick link-layer node HUB")
|
logging.debug("Pick link-layer node HUB")
|
||||||
self.link_layer_option_menu.destroy()
|
self.link_layer_option_menu.destroy()
|
||||||
main_button.configure(image=Images.get("hub"))
|
main_button.configure(image=Images.get("hub"))
|
||||||
self.canvas.set_canvas_mode(GraphMode.PICKNODE)
|
self.canvas.mode = GraphMode.PICKNODE
|
||||||
self.canvas.set_drawing_image(Images.get("hub"))
|
self.canvas.draw_node_image = Images.get("hub")
|
||||||
self.canvas.set_drawing_name("hub")
|
self.canvas.draw_node_name = "hub"
|
||||||
|
|
||||||
def pick_switch(self, main_button):
|
def pick_switch(self, main_button):
|
||||||
logging.debug("Pick link-layer node SWITCH")
|
logging.debug("Pick link-layer node SWITCH")
|
||||||
self.link_layer_option_menu.destroy()
|
self.link_layer_option_menu.destroy()
|
||||||
main_button.configure(image=Images.get("switch"))
|
main_button.configure(image=Images.get("switch"))
|
||||||
self.canvas.set_canvas_mode(GraphMode.PICKNODE)
|
self.canvas.mode = GraphMode.PICKNODE
|
||||||
self.canvas.set_drawing_image(Images.get("switch"))
|
self.canvas.draw_node_image = Images.get("switch")
|
||||||
self.canvas.set_drawing_name("switch")
|
self.canvas.draw_node_name = "switch"
|
||||||
|
|
||||||
def pick_wlan(self, main_button):
|
def pick_wlan(self, main_button):
|
||||||
logging.debug("Pick link-layer node WLAN")
|
logging.debug("Pick link-layer node WLAN")
|
||||||
self.link_layer_option_menu.destroy()
|
self.link_layer_option_menu.destroy()
|
||||||
main_button.configure(image=Images.get("wlan"))
|
main_button.configure(image=Images.get("wlan"))
|
||||||
self.canvas.set_canvas_mode(GraphMode.PICKNODE)
|
self.canvas.mode = GraphMode.PICKNODE
|
||||||
self.canvas.set_drawing_image(Images.get("wlan"))
|
self.canvas.draw_node_image = Images.get("wlan")
|
||||||
self.canvas.set_drawing_name("wlan")
|
self.canvas.draw_node_name = "wlan"
|
||||||
|
|
||||||
def pick_rj45(self, main_button):
|
def pick_rj45(self, main_button):
|
||||||
logging.debug("Pick link-layer node RJ45")
|
logging.debug("Pick link-layer node RJ45")
|
||||||
self.link_layer_option_menu.destroy()
|
self.link_layer_option_menu.destroy()
|
||||||
main_button.configure(image=Images.get("rj45"))
|
main_button.configure(image=Images.get("rj45"))
|
||||||
self.canvas.set_canvas_mode(GraphMode.PICKNODE)
|
self.canvas.mode = GraphMode.PICKNODE
|
||||||
self.canvas.set_drawing_image(Images.get("rj45"))
|
self.canvas.draw_node_image = Images.get("rj45")
|
||||||
|
self.canvas.draw_node_name = "rj45"
|
||||||
|
|
||||||
def pick_tunnel(self, main_button):
|
def pick_tunnel(self, main_button):
|
||||||
logging.debug("Pick link-layer node TUNNEL")
|
logging.debug("Pick link-layer node TUNNEL")
|
||||||
self.link_layer_option_menu.destroy()
|
self.link_layer_option_menu.destroy()
|
||||||
main_button.configure(image=Images.get("tunnel"))
|
main_button.configure(image=Images.get("tunnel"))
|
||||||
self.canvas.set_canvas_mode(GraphMode.PICKNODE)
|
self.canvas.mode = GraphMode.PICKNODE
|
||||||
self.canvas.set_drawing_image(Images.get("tunnel"))
|
self.canvas.draw_node_image = Images.get("tunnel")
|
||||||
self.canvas.set_drawing_image(Images.get("tunnel"))
|
self.canvas.draw_node_name = "tunnel"
|
||||||
|
|
||||||
def draw_link_layer_options(self, link_layer_button):
|
def draw_link_layer_options(self, link_layer_button):
|
||||||
"""
|
"""
|
||||||
|
@ -476,11 +490,10 @@ class CoreToolbar(object):
|
||||||
CreateToolTip(marker_main_button, "background annotation tools")
|
CreateToolTip(marker_main_button, "background annotation tools")
|
||||||
|
|
||||||
def create_toolbar(self):
|
def create_toolbar(self):
|
||||||
# self.load_toolbar_images()
|
|
||||||
self.create_regular_button(
|
self.create_regular_button(
|
||||||
self.edit_frame,
|
self.edit_frame,
|
||||||
Images.get("start"),
|
Images.get("start"),
|
||||||
self.click_start_stop_session_tool,
|
self.click_start_session_tool,
|
||||||
"start the session",
|
"start the session",
|
||||||
)
|
)
|
||||||
self.create_radio_button(
|
self.create_radio_button(
|
||||||
|
|
|
@ -2,6 +2,9 @@ import enum
|
||||||
import logging
|
import logging
|
||||||
import tkinter as tk
|
import tkinter as tk
|
||||||
|
|
||||||
|
from coretk.grpcmanagement import GrpcManager
|
||||||
|
from coretk.images import Images
|
||||||
|
|
||||||
|
|
||||||
class GraphMode(enum.Enum):
|
class GraphMode(enum.Enum):
|
||||||
SELECT = 0
|
SELECT = 0
|
||||||
|
@ -12,12 +15,11 @@ class GraphMode(enum.Enum):
|
||||||
|
|
||||||
|
|
||||||
class CanvasGraph(tk.Canvas):
|
class CanvasGraph(tk.Canvas):
|
||||||
def __init__(self, grpc=None, master=None, cnf=None, **kwargs):
|
def __init__(self, master=None, grpc=None, cnf=None, **kwargs):
|
||||||
if cnf is None:
|
if cnf is None:
|
||||||
cnf = {}
|
cnf = {}
|
||||||
kwargs["highlightthickness"] = 0
|
kwargs["highlightthickness"] = 0
|
||||||
super().__init__(master, cnf, **kwargs)
|
super().__init__(master, cnf, **kwargs)
|
||||||
self.core_grpc = grpc
|
|
||||||
self.mode = GraphMode.SELECT
|
self.mode = GraphMode.SELECT
|
||||||
self.draw_node_image = None
|
self.draw_node_image = None
|
||||||
self.draw_node_name = None
|
self.draw_node_name = None
|
||||||
|
@ -26,19 +28,32 @@ class CanvasGraph(tk.Canvas):
|
||||||
self.nodes = {}
|
self.nodes = {}
|
||||||
self.edges = {}
|
self.edges = {}
|
||||||
self.drawing_edge = None
|
self.drawing_edge = None
|
||||||
|
|
||||||
self.setup_menus()
|
self.setup_menus()
|
||||||
self.setup_bindings()
|
self.setup_bindings()
|
||||||
self.draw_grid()
|
self.draw_grid()
|
||||||
|
self.core_grpc = grpc
|
||||||
|
self.grpc_manager = GrpcManager()
|
||||||
|
self.draw_existing_node()
|
||||||
|
|
||||||
def set_canvas_mode(self, mode):
|
def setup_menus(self):
|
||||||
self.mode = mode
|
self.node_context = tk.Menu(self.master)
|
||||||
|
self.node_context.add_command(label="One")
|
||||||
|
self.node_context.add_command(label="Two")
|
||||||
|
self.node_context.add_command(label="Three")
|
||||||
|
|
||||||
def set_drawing_image(self, img):
|
def setup_bindings(self):
|
||||||
self.draw_node_image = img
|
"""
|
||||||
|
Bind any mouse events or hot keys to the matching action
|
||||||
|
|
||||||
def set_drawing_name(self, name):
|
:return: nothing
|
||||||
self.draw_node_name = name
|
"""
|
||||||
|
self.bind("<ButtonPress-1>", self.click_press)
|
||||||
|
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):
|
def draw_grid(self, width=1000, height=750):
|
||||||
"""
|
"""
|
||||||
|
@ -65,25 +80,20 @@ class CanvasGraph(tk.Canvas):
|
||||||
for i in range(0, height, 27):
|
for i in range(0, height, 27):
|
||||||
self.create_line(0, i, width, i, dash=(2, 4), tags="grid line")
|
self.create_line(0, i, width, i, dash=(2, 4), tags="grid line")
|
||||||
|
|
||||||
def setup_menus(self):
|
def draw_existing_node(self):
|
||||||
self.node_context = tk.Menu(self.master)
|
|
||||||
self.node_context.add_command(label="One")
|
|
||||||
self.node_context.add_command(label="Two")
|
|
||||||
self.node_context.add_command(label="Three")
|
|
||||||
|
|
||||||
def setup_bindings(self):
|
|
||||||
"""
|
"""
|
||||||
Bind any mouse events or hot keys to the matching action
|
Draw existing node while updating the grpc manager based on that
|
||||||
|
|
||||||
:return: nothing
|
:return: nothing
|
||||||
"""
|
"""
|
||||||
self.bind("<ButtonPress-1>", self.click_press)
|
session_id = self.core_grpc.session_id
|
||||||
self.bind("<ButtonRelease-1>", self.click_release)
|
response = self.core_grpc.core.get_session(session_id)
|
||||||
self.bind("<B1-Motion>", self.click_motion)
|
nodes = response.session.nodes
|
||||||
self.bind("<Button-3>", self.context)
|
if len(nodes) > 0:
|
||||||
# self.bind("e", self.set_mode)
|
for node in nodes:
|
||||||
# self.bind("s", self.set_mode)
|
image = Images.convert_type_and_model_to_image(node.type, node.model)
|
||||||
# self.bind("n", self.set_mode)
|
return image
|
||||||
|
# n = CanvasNode(node.position.x, node.position.y, image, self, node.id)
|
||||||
|
|
||||||
def canvas_xy(self, event):
|
def canvas_xy(self, event):
|
||||||
"""
|
"""
|
||||||
|
@ -172,6 +182,10 @@ class CanvasGraph(tk.Canvas):
|
||||||
node_dst = self.nodes[edge.dst]
|
node_dst = self.nodes[edge.dst]
|
||||||
node_dst.edges.add(edge)
|
node_dst.edges.add(edge)
|
||||||
|
|
||||||
|
self.grpc_manager.add_edge(
|
||||||
|
self.core_grpc.get_session_id(), edge.token, node_src.id, node_dst.id
|
||||||
|
)
|
||||||
|
|
||||||
logging.debug(f"edges: {self.find_withtag('edge')}")
|
logging.debug(f"edges: {self.find_withtag('edge')}")
|
||||||
|
|
||||||
def click_press(self, event):
|
def click_press(self, event):
|
||||||
|
@ -207,40 +221,14 @@ class CanvasGraph(tk.Canvas):
|
||||||
logging.debug(f"node context: {selected}")
|
logging.debug(f"node context: {selected}")
|
||||||
self.node_context.post(event.x_root, event.y_root)
|
self.node_context.post(event.x_root, event.y_root)
|
||||||
|
|
||||||
# def set_mode(self, event):
|
|
||||||
# """
|
|
||||||
# Set canvas mode according to the hot key that has been pressed
|
|
||||||
#
|
|
||||||
# :param event: key event
|
|
||||||
# :return: nothing
|
|
||||||
# """
|
|
||||||
# logging.debug(f"mode event: {event}")
|
|
||||||
# if event.char == "e":
|
|
||||||
# self.mode = GraphMode.EDGE
|
|
||||||
# elif event.char == "s":
|
|
||||||
# self.mode = GraphMode.SELECT
|
|
||||||
# elif event.char == "n":
|
|
||||||
# self.mode = GraphMode.NODE
|
|
||||||
# logging.debug(f"graph mode: {self.mode}")
|
|
||||||
|
|
||||||
# def add_node(self, x, y, image_name):
|
|
||||||
# image = Images.get(image_name)
|
|
||||||
# node = CanvasNode(x, y, image, self)
|
|
||||||
# self.nodes[node.id] = node
|
|
||||||
# return node
|
|
||||||
|
|
||||||
def add_node(self, x, y, image, node_name):
|
def add_node(self, x, y, image, node_name):
|
||||||
core_session_id = self.core_grpc.get_session_id()
|
|
||||||
core_node_id = self.core_grpc.add_node(int(x), int(y), node_name)
|
|
||||||
node = CanvasNode(
|
node = CanvasNode(
|
||||||
core_session_id=core_session_id,
|
x=x, y=y, image=image, canvas=self, core_id=self.grpc_manager.peek_id()
|
||||||
core_node_id=core_node_id,
|
|
||||||
x=x,
|
|
||||||
y=y,
|
|
||||||
image=image,
|
|
||||||
canvas=self,
|
|
||||||
)
|
)
|
||||||
self.nodes[node.id] = node
|
self.nodes[node.id] = node
|
||||||
|
self.grpc_manager.add_node(
|
||||||
|
self.core_grpc.get_session_id(), node.id, x, y, node_name
|
||||||
|
)
|
||||||
return node
|
return node
|
||||||
|
|
||||||
|
|
||||||
|
@ -283,17 +271,16 @@ class CanvasEdge:
|
||||||
|
|
||||||
|
|
||||||
class CanvasNode:
|
class CanvasNode:
|
||||||
def __init__(self, core_session_id, core_node_id, x, y, image, canvas):
|
def __init__(self, x, y, image, canvas, core_id):
|
||||||
self.image = image
|
self.image = image
|
||||||
self.canvas = canvas
|
self.canvas = canvas
|
||||||
self.id = self.canvas.create_image(
|
self.id = self.canvas.create_image(
|
||||||
x, y, anchor=tk.CENTER, image=self.image, tags="node"
|
x, y, anchor=tk.CENTER, image=self.image, tags="node"
|
||||||
)
|
)
|
||||||
|
self.core_id = core_id
|
||||||
self.x_coord = x
|
self.x_coord = x
|
||||||
self.y_coord = y
|
self.y_coord = y
|
||||||
self.core_session_id = core_session_id
|
self.name = f"Node {self.core_id}"
|
||||||
self.core_node_id = core_node_id
|
|
||||||
self.name = f"Node {self.core_node_id}"
|
|
||||||
self.text_id = self.canvas.create_text(x, y + 20, text=self.name)
|
self.text_id = self.canvas.create_text(x, y + 20, text=self.name)
|
||||||
self.canvas.tag_bind(self.id, "<ButtonPress-1>", self.click_press)
|
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, "<ButtonRelease-1>", self.click_release)
|
||||||
|
@ -315,12 +302,6 @@ class CanvasNode:
|
||||||
def click_release(self, event):
|
def click_release(self, event):
|
||||||
logging.debug(f"click release {self.name}: {event}")
|
logging.debug(f"click release {self.name}: {event}")
|
||||||
self.update_coords()
|
self.update_coords()
|
||||||
self.canvas.core_grpc.edit_node(
|
|
||||||
self.core_session_id,
|
|
||||||
self.core_node_id,
|
|
||||||
int(self.x_coord),
|
|
||||||
int(self.y_coord),
|
|
||||||
)
|
|
||||||
self.moving = None
|
self.moving = None
|
||||||
|
|
||||||
def motion(self, event):
|
def motion(self, event):
|
||||||
|
|
157
coretk/coretk/grpcmanagement.py
Normal file
157
coretk/coretk/grpcmanagement.py
Normal file
|
@ -0,0 +1,157 @@
|
||||||
|
"""
|
||||||
|
Manage useful informations about the nodes, edges and configuration
|
||||||
|
that can be useful for grpc, acts like a session class
|
||||||
|
"""
|
||||||
|
import logging
|
||||||
|
|
||||||
|
from core.api.grpc import core_pb2
|
||||||
|
|
||||||
|
link_layer_nodes = ["switch", "hub", "wlan", "rj45", "tunnel"]
|
||||||
|
network_layer_nodes = ["router", "host", "PC", "mdr", "prouter", "OVS"]
|
||||||
|
|
||||||
|
|
||||||
|
class Node:
|
||||||
|
def __init__(self, session_id, node_id, type, model, x, y, name):
|
||||||
|
"""
|
||||||
|
Create an instance of a node
|
||||||
|
|
||||||
|
:param int session_id: session id
|
||||||
|
:param int node_id: node id
|
||||||
|
:param core_pb2.NodeType type: node type
|
||||||
|
:param int x: x coordinate
|
||||||
|
:param int y: coordinate
|
||||||
|
"""
|
||||||
|
self.session_id = session_id
|
||||||
|
self.node_id = node_id
|
||||||
|
self.type = type
|
||||||
|
self.x = x
|
||||||
|
self.y = y
|
||||||
|
self.model = model
|
||||||
|
self.name = name
|
||||||
|
|
||||||
|
|
||||||
|
class Edge:
|
||||||
|
def __init__(self, session_id, node_id_1, node_type_1, node_id_2, node_type_2):
|
||||||
|
"""
|
||||||
|
Create an instance of an edge
|
||||||
|
:param int session_id: session id
|
||||||
|
:param int node_id_1: node 1 id
|
||||||
|
:param int node_type_1: node 1 type
|
||||||
|
:param core_pb2.NodeType node_id_2: node 2 id
|
||||||
|
:param core_pb2.NodeType node_type_2: node 2 type
|
||||||
|
"""
|
||||||
|
self.session_id = session_id
|
||||||
|
self.id1 = node_id_1
|
||||||
|
self.id2 = node_id_2
|
||||||
|
self.type1 = node_type_1
|
||||||
|
self.type2 = node_type_2
|
||||||
|
|
||||||
|
|
||||||
|
class GrpcManager:
|
||||||
|
def __init__(self):
|
||||||
|
self.nodes = {}
|
||||||
|
self.edges = {}
|
||||||
|
self.id = 1
|
||||||
|
# A list of id for re-use, keep in increasing order
|
||||||
|
self.reusable = []
|
||||||
|
self.nodes_to_create = {}
|
||||||
|
self.edges_to_create = {}
|
||||||
|
|
||||||
|
def peek_id(self):
|
||||||
|
"""
|
||||||
|
Peek the next id to be used
|
||||||
|
|
||||||
|
:return: nothing
|
||||||
|
"""
|
||||||
|
if len(self.reusable) == 0:
|
||||||
|
return self.id
|
||||||
|
else:
|
||||||
|
return self.reusable[0]
|
||||||
|
|
||||||
|
def get_id(self):
|
||||||
|
"""
|
||||||
|
Get the next node id as well as update id status and reusable ids
|
||||||
|
|
||||||
|
:rtype: int
|
||||||
|
:return: the next id to be used
|
||||||
|
"""
|
||||||
|
if len(self.reusable) == 0:
|
||||||
|
new_id = self.id
|
||||||
|
self.id = self.id + 1
|
||||||
|
return new_id
|
||||||
|
else:
|
||||||
|
return self.reusable.pop(0)
|
||||||
|
|
||||||
|
# TODO figure out the name of ovs node
|
||||||
|
def add_node(self, session_id, canvas_id, x, y, name):
|
||||||
|
"""
|
||||||
|
Add node, with information filled in, to grpc manager
|
||||||
|
|
||||||
|
:param int session_id: session id
|
||||||
|
:param int canvas_id: node's canvas id
|
||||||
|
:param int x: x coord
|
||||||
|
:param int y: y coord
|
||||||
|
:param str name: node type
|
||||||
|
:return: nothing
|
||||||
|
"""
|
||||||
|
node_type = None
|
||||||
|
node_model = None
|
||||||
|
if name in link_layer_nodes:
|
||||||
|
if name == "switch":
|
||||||
|
node_type = core_pb2.NodeType.SWITCH
|
||||||
|
elif name == "hub":
|
||||||
|
node_type = core_pb2.NodeType.HUB
|
||||||
|
elif name == "wlan":
|
||||||
|
node_type = core_pb2.NodeType.WIRELESS_LAN
|
||||||
|
elif name == "rj45":
|
||||||
|
node_type = core_pb2.NodeType.RJ45
|
||||||
|
elif name == "tunnel":
|
||||||
|
node_type = core_pb2.NodeType.TUNNEL
|
||||||
|
elif name in network_layer_nodes:
|
||||||
|
node_type = core_pb2.NodeType.DEFAULT
|
||||||
|
# TODO what is the model name for ovs
|
||||||
|
node_model = name
|
||||||
|
else:
|
||||||
|
logging.error("grpcmanagemeny.py INVALID node name")
|
||||||
|
create_node = Node(session_id, self.get_id(), node_type, node_model, x, y, name)
|
||||||
|
self.nodes[canvas_id] = create_node
|
||||||
|
self.nodes_to_create[canvas_id] = create_node
|
||||||
|
logging.debug(
|
||||||
|
"Adding node to GrpcManager.. Session id: %s, Coords: (%s, %s), Name: %s",
|
||||||
|
session_id,
|
||||||
|
x,
|
||||||
|
y,
|
||||||
|
name,
|
||||||
|
)
|
||||||
|
|
||||||
|
def add_preexisting_node(self):
|
||||||
|
return
|
||||||
|
|
||||||
|
def delete_node(self, canvas_id):
|
||||||
|
"""
|
||||||
|
Delete a node from the session
|
||||||
|
|
||||||
|
:param int canvas_id: node's id in the canvas
|
||||||
|
:return: thing
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
self.nodes.pop(canvas_id)
|
||||||
|
self.reuseable.append(canvas_id)
|
||||||
|
self.reuseable.sort()
|
||||||
|
except KeyError:
|
||||||
|
logging.error("grpcmanagement.py INVALID NODE CANVAS ID")
|
||||||
|
|
||||||
|
def add_edge(self, session_id, token, canvas_id_1, canvas_id_2):
|
||||||
|
if canvas_id_1 in self.nodes and canvas_id_2 in self.nodes:
|
||||||
|
edge = Edge(
|
||||||
|
session_id,
|
||||||
|
self.nodes[canvas_id_1].node_id,
|
||||||
|
self.nodes[canvas_id_1].type,
|
||||||
|
self.nodes[canvas_id_2].node_id,
|
||||||
|
self.nodes[canvas_id_2].type,
|
||||||
|
)
|
||||||
|
self.edges[token] = edge
|
||||||
|
self.edges_to_create[token] = edge
|
||||||
|
logging.debug("Adding edge to grpc manager...")
|
||||||
|
else:
|
||||||
|
logging.error("grpcmanagement.py INVALID CANVAS NODE ID")
|
|
@ -1,7 +1,10 @@
|
||||||
|
import logging
|
||||||
import os
|
import os
|
||||||
|
|
||||||
from PIL import Image, ImageTk
|
from PIL import Image, ImageTk
|
||||||
|
|
||||||
|
from core.api.grpc import core_pb2
|
||||||
|
|
||||||
PATH = os.path.abspath(os.path.dirname(__file__))
|
PATH = os.path.abspath(os.path.dirname(__file__))
|
||||||
|
|
||||||
|
|
||||||
|
@ -19,6 +22,41 @@ class Images:
|
||||||
def get(cls, name):
|
def get(cls, name):
|
||||||
return cls.images[name]
|
return cls.images[name]
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def convert_type_and_model_to_image(cls, node_type, node_model):
|
||||||
|
"""
|
||||||
|
Retrieve image based on type and model
|
||||||
|
:param core_pb2.NodeType node_type: core node type
|
||||||
|
:param string node_model: the node model
|
||||||
|
|
||||||
|
:return: the matching image
|
||||||
|
"""
|
||||||
|
if node_type == core_pb2.NodeType.SWITCH:
|
||||||
|
return Images.get("switch")
|
||||||
|
if node_type == core_pb2.NodeType.HUB:
|
||||||
|
return Images.get("hub")
|
||||||
|
if node_type == core_pb2.NodeType.WIRELESS_LAN:
|
||||||
|
return Images.get("wlan")
|
||||||
|
if node_type == core_pb2.NodeType.RJ45:
|
||||||
|
return Images.get("rj45")
|
||||||
|
if node_type == core_pb2.NodeType.TUNNEL:
|
||||||
|
return Images.get("tunnel")
|
||||||
|
if node_type == core_pb2.NodeType.DEFAULT:
|
||||||
|
if node_model == "router":
|
||||||
|
return Images.get("router")
|
||||||
|
if node_model == "host":
|
||||||
|
return Images.get(("host"))
|
||||||
|
if node_model == "PC":
|
||||||
|
return Images.get("pc")
|
||||||
|
if node_model == "mdr":
|
||||||
|
return Images.get("mdr")
|
||||||
|
if node_model == "prouter":
|
||||||
|
return Images.get("prouter")
|
||||||
|
if node_model == "OVS":
|
||||||
|
return Images.get("ovs")
|
||||||
|
else:
|
||||||
|
logging.debug("INVALID INPUT OR NOT CONSIDERED YET")
|
||||||
|
|
||||||
|
|
||||||
def load_core_images(images):
|
def load_core_images(images):
|
||||||
images.load("core", "core-icon.png")
|
images.load("core", "core-icon.png")
|
||||||
|
|
Loading…
Reference in a new issue