merged latest from coretk

This commit is contained in:
bharnden 2019-11-01 11:34:38 -07:00
commit 5369694797
15 changed files with 991 additions and 168 deletions

View file

@ -0,0 +1,43 @@
"""
canvas graph action
"""
# import tkinter as tk
from core.api.grpc import core_pb2
from coretk.nodeconfigtable import NodeConfig
from coretk.wlanconfiguration import WlanConfiguration
# TODO, finish classifying node types
NODE_TO_TYPE = {
"router": core_pb2.NodeType.DEFAULT,
"wlan": core_pb2.NodeType.WIRELESS_LAN,
}
class CanvasAction:
def __init__(self, master, canvas):
self.master = master
self.canvas = canvas
self.node_to_show_config = None
def display_configuration(self, canvas_node):
pb_type = NODE_TO_TYPE[canvas_node.node_type]
self.node_to_show_config = canvas_node
if pb_type == core_pb2.NodeType.DEFAULT:
self.display_node_configuration()
elif pb_type == core_pb2.NodeType.WIRELESS_LAN:
self.display_wlan_configuration(canvas_node)
def display_node_configuration(self):
NodeConfig(self.canvas, self.node_to_show_config)
self.node_to_show_config = None
def display_wlan_configuration(self, canvas_node):
# print(self.canvas.grpc_manager.wlanconfig_management.configurations)
wlan_config = self.canvas.grpc_manager.wlanconfig_management.configurations[
canvas_node.core_id
]
WlanConfiguration(self.canvas, self.node_to_show_config, wlan_config)
self.node_to_show_config = None

View file

@ -64,7 +64,7 @@ class CoreGrpc:
self.manager.reusable.append(i)
# draw session
self.app.canvas.draw_existing_component(session)
self.app.canvas.canvas_reset_and_redraw(session)
def create_new_session(self):
"""
@ -213,6 +213,54 @@ class CoreGrpc:
)
logging.info("delete links %s", response)
def create_interface(self, node_type, gui_interface):
"""
create a protobuf interface given the interface object stored by the programmer
:param core_bp2.NodeType type: node type
:param coretk.interface.Interface gui_interface: the programmer's interface object
:rtype: core_bp2.Interface
:return: protobuf interface object
"""
if node_type != core_pb2.NodeType.DEFAULT:
return None
else:
interface = core_pb2.Interface(
id=gui_interface.id,
name=gui_interface.name,
mac=gui_interface.mac,
ip4=gui_interface.ipv4,
ip4mask=gui_interface.ip4prefix,
)
logging.debug("create interface 1 %s", interface)
return interface
# TODO add location, hooks, emane_config, etc...
def start_session(
self,
nodes,
links,
location=None,
hooks=None,
emane_config=None,
emane_model_configs=None,
wlan_configs=None,
mobility_configs=None,
):
response = self.core.start_session(
session_id=self.session_id,
nodes=nodes,
links=links,
wlan_configs=wlan_configs,
)
logging.debug("Start session %s, result: %s", self.session_id, response.result)
def stop_session(self):
response = self.core.stop_session(session_id=self.session_id)
logging.debug("coregrpc.py Stop session, result: %s", response.result)
# TODO no need, might get rid of this
def add_link(self, id1, id2, type1, type2, edge):
"""
Grpc client request add link
@ -224,30 +272,30 @@ class CoreGrpc:
:param core_pb2.NodeType type2: node 2 core node type
:return: nothing
"""
if1 = None
if2 = None
if type1 == core_pb2.NodeType.DEFAULT:
interface = edge.interface_1
if1 = core_pb2.Interface(
id=interface.id,
name=interface.name,
mac=interface.mac,
ip4=interface.ipv4,
ip4mask=interface.ip4prefix,
)
logging.debug("create interface 1 %s", if1)
# interface1 = self.interface_helper.create_interface(id1, 0)
if type2 == core_pb2.NodeType.DEFAULT:
interface = edge.interface_2
if2 = core_pb2.Interface(
id=interface.id,
name=interface.name,
mac=interface.mac,
ip4=interface.ipv4,
ip4mask=interface.ip4prefix,
)
logging.debug("create interface 2: %s", if2)
if1 = self.create_interface(type1, edge.interface_1)
if2 = self.create_interface(type2, edge.interface_2)
# if type1 == core_pb2.NodeType.DEFAULT:
# interface = edge.interface_1
# if1 = core_pb2.Interface(
# id=interface.id,
# name=interface.name,
# mac=interface.mac,
# ip4=interface.ipv4,
# ip4mask=interface.ip4prefix,
# )
# logging.debug("create interface 1 %s", if1)
# # interface1 = self.interface_helper.create_interface(id1, 0)
#
# if type2 == core_pb2.NodeType.DEFAULT:
# interface = edge.interface_2
# if2 = core_pb2.Interface(
# id=interface.id,
# name=interface.name,
# mac=interface.mac,
# ip4=interface.ipv4,
# ip4mask=interface.ip4prefix,
# )
# logging.debug("create interface 2: %s", if2)
response = self.core.add_link(self.session_id, id1, id2, if1, if2)
logging.info("created link: %s", response)
@ -276,8 +324,8 @@ class CoreGrpc:
:return: session id
"""
response = self.core.open_xml(file_path)
self.session_id = response.session_id
logging.debug("coreprgc.py open_xml(): %s", response.result)
logging.debug("open xml: %s", response)
self.join_session(response.session_id)
def close(self):
"""

View file

@ -1,22 +1,23 @@
import logging
import tkinter as tk
from enum import Enum
from core.api.grpc import core_pb2
# from core.api.grpc import core_pb2
from coretk.coretoolbarhelp import CoreToolbarHelp
from coretk.graph import GraphMode
from coretk.images import ImageEnum, Images
from coretk.tooltip import CreateToolTip
# from enum import Enum
class SessionStateEnum(Enum):
NONE = "none"
DEFINITION = "definition"
CONFIGURATION = "configuration"
RUNTIME = "runtime"
DATACOLLECT = "datacollect"
SHUTDOWN = "shutdown"
INSTANTIATION = "instantiation"
# class SessionStateEnum(Enum):
# NONE = "none"
# DEFINITION = "definition"
# CONFIGURATION = "configuration"
# RUNTIME = "runtime"
# DATACOLLECT = "datacollect"
# SHUTDOWN = "shutdown"
# INSTANTIATION = "instantiation"
class CoreToolbar(object):
@ -161,21 +162,22 @@ class CoreToolbar(object):
"""
logging.debug("Click START STOP SESSION button")
helper = CoreToolbarHelp(self.application)
# self.destroy_children_widgets(self.edit_frame)
self.destroy_children_widgets()
self.canvas.mode = GraphMode.SELECT
# set configuration state
state = self.canvas.core_grpc.get_session_state()
# state = self.canvas.core_grpc.get_session_state()
# if state == core_pb2.SessionState.SHUTDOWN or self.application.is_open_xml:
# self.canvas.core_grpc.set_session_state(SessionStateEnum.DEFINITION.value)
# self.application.is_open_xml = False
#
# self.canvas.core_grpc.set_session_state(SessionStateEnum.CONFIGURATION.value)
# helper.add_nodes()
# helper.add_edges()
# self.canvas.core_grpc.set_session_state(SessionStateEnum.INSTANTIATION.value)
helper.gui_start_session()
self.create_runtime_toolbar()
if state == core_pb2.SessionState.SHUTDOWN or self.application.is_open_xml:
self.canvas.core_grpc.set_session_state(SessionStateEnum.DEFINITION.value)
self.application.is_open_xml = False
self.canvas.core_grpc.set_session_state(SessionStateEnum.CONFIGURATION.value)
helper.add_nodes()
helper.add_edges()
# for node in self.canvas.grpc_manager.nodes.values():
# print(node.type, node.model, int(node.x), int(node.y), node.name, node.node_id)
# self.canvas.core_grpc.add_node(
@ -188,10 +190,8 @@ class CoreToolbar(object):
# self.canvas.core_grpc.add_link(
# edge.id1, edge.id2, edge.type1, edge.type2, edge
# )
self.canvas.core_grpc.set_session_state(SessionStateEnum.INSTANTIATION.value)
# self.canvas.core_grpc.get_session()
# self.application.is_open_xml = False
self.create_runtime_toolbar()
def click_link_tool(self):
logging.debug("Click LINK button")
@ -366,6 +366,13 @@ class CoreToolbar(object):
self.canvas.draw_node_image = Images.get(ImageEnum.TUNNEL)
self.canvas.draw_node_name = "tunnel"
def pick_emane(self, main_button):
self.link_layer_option_menu.destroy()
main_button.configure(image=Images.get(ImageEnum.EMANE.value))
self.canvas.mode = GraphMode.PICKNODE
self.canvas.draw_node_image = Images.get(ImageEnum.EMANE.value)
self.canvas.draw_node_name = "emane"
def draw_link_layer_options(self, link_layer_button):
"""
Draw the options for link-layer button
@ -380,6 +387,7 @@ class CoreToolbar(object):
Images.get(ImageEnum.HUB),
Images.get(ImageEnum.SWITCH),
Images.get(ImageEnum.WLAN),
Images.get(ImageEnum.EMANE),
Images.get(ImageEnum.RJ45),
Images.get(ImageEnum.TUNNEL),
]
@ -387,6 +395,7 @@ class CoreToolbar(object):
self.pick_hub,
self.pick_switch,
self.pick_wlan,
self.pick_emane,
self.pick_rj45,
self.pick_tunnel,
]
@ -394,6 +403,7 @@ class CoreToolbar(object):
"ethernet hub",
"ethernet switch",
"wireless LAN",
"emane",
"rj45 physical interface tool",
"tunnel tool",
]
@ -582,12 +592,12 @@ class CoreToolbar(object):
:return: nothing
"""
logging.debug("Click on STOP button ")
# self.destroy_children_widgets(self.edit_frame)
self.destroy_children_widgets()
self.canvas.core_grpc.set_session_state(SessionStateEnum.DATACOLLECT.value)
self.canvas.core_grpc.delete_links()
self.canvas.core_grpc.delete_nodes()
# self.canvas.core_grpc.set_session_state(SessionStateEnum.DATACOLLECT.value)
# self.canvas.core_grpc.delete_links()
# self.canvas.core_grpc.delete_nodes()
self.canvas.core_grpc.stop_session()
self.create_toolbar()
def click_run_button(self):

View file

@ -1,30 +1,116 @@
"""
CoreToolbar help to draw on canvas, and make grpc client call
"""
from core.api.grpc.client import core_pb2
class CoreToolbarHelp:
def __init__(self, app):
self.app = app
def add_nodes(self):
def get_node_list(self):
"""
add the nodes stored in grpc manager
form a list node protobuf nodes to pass in start_session in grpc
:return: nothing
"""
nodes = []
manager = self.app.core_grpc.manager
for node in manager.nodes.values():
self.app.core_grpc.add_node(
node.type, node.model, int(node.x), int(node.y), node.name, node.node_id
pos = core_pb2.Position(x=int(node.x), y=int(node.y))
n = core_pb2.Node(
id=node.node_id, type=node.type, position=pos, model=node.model
)
nodes.append(n)
return nodes
def add_edges(self):
def get_link_list(self):
"""
add the edges stored in grpc manager
:return:
form a list of links to pass into grpc start session
:rtype: list(core_pb2.Link)
:return: list of protobuf links
"""
links = []
manager = self.app.core_grpc.manager
for edge in manager.edges.values():
self.app.core_grpc.add_link(
edge.id1, edge.id2, edge.type1, edge.type2, edge
interface_one = self.app.core_grpc.create_interface(
edge.type1, edge.interface_1
)
interface_two = self.app.core_grpc.create_interface(
edge.type2, edge.interface_2
)
# TODO for now only consider the basic cases
if (
edge.type1 == core_pb2.NodeType.WIRELESS_LAN
or edge.type2 == core_pb2.NodeType.WIRELESS_LAN
):
link_type = core_pb2.LinkType.WIRELESS
else:
link_type = core_pb2.LinkType.WIRED
link = core_pb2.Link(
node_one_id=edge.id1,
node_two_id=edge.id2,
type=link_type,
interface_one=interface_one,
interface_two=interface_two,
)
links.append(link)
# self.id1 = edge.id1
# self.id2 = edge.id2
# self.type = link_type
# self.if1 = interface_one
# self.if2 = interface_two
return links
def get_wlan_configuration_list(self):
configs = []
manager = self.app.core_grpc.manager
manager_configs = manager.wlanconfig_management.configurations
for key in manager_configs:
cnf = core_pb2.WlanConfig(node_id=key, config=manager_configs[key])
configs.append(cnf)
return configs
def gui_start_session(self):
# list(core_pb2.Node)
nodes = self.get_node_list()
# list(core_bp2.Link)
links = self.get_link_list()
# print(links[0])
wlan_configs = self.get_wlan_configuration_list()
# print(wlan_configs)
self.app.core_grpc.start_session(nodes, links, wlan_configs=wlan_configs)
# self.core_grpc.core.add_link(self.core_grpc.session_id, self.id1, self.id2, self.if1, self.if2)
# res = self.core_grpc.core.get_wlan_config(self.core_grpc.session_id, 1)
# res = self.core_grpc.core.get_session(self.core_grpc.session_id).session
# print(res)
# res = self.core_grpc.core.get_wlan_config(self.core_grpc.session_id, 1)
# print(res)
# def add_nodes(self):
# """
# add the nodes stored in grpc manager
# :return: nothing
# """
# grpc_manager = self.application.canvas.grpc_manager
# for node in grpc_manager.nodes.values():
# self.application.core_grpc.add_node(
# node.type, node.model, int(node.x), int(node.y), node.name, node.node_id
# )
#
# def add_edges(self):
# """
# add the edges stored in grpc manager
# :return:
# """
# grpc_manager = self.application.canvas.grpc_manager
# for edge in grpc_manager.edges.values():
# self.application.core_grpc.add_link(
# edge.id1, edge.id2, edge.type1, edge.type2, edge
# )

View file

@ -3,11 +3,11 @@ import logging
import tkinter as tk
from core.api.grpc import core_pb2
from coretk.canvasaction import CanvasAction
from coretk.graph_helper import GraphHelper, WlanAntennaManager
from coretk.images import Images
from coretk.interface import Interface
from coretk.linkinfo import LinkInfo, Throughput
from coretk.nodeconfigtable import NodeConfig
from coretk.wirelessconnection import WirelessConnection
@ -19,6 +19,12 @@ class GraphMode(enum.Enum):
OTHER = 4
CORE_NODES = ["router"]
CORE_WIRED_NETWORK_NODES = []
CORE_WIRELESS_NODE = ["wlan"]
CORE_EMANE = ["emane"]
class CanvasGraph(tk.Canvas):
def __init__(self, master, core_grpc, cnf=None, **kwargs):
if cnf is None:
@ -35,6 +41,7 @@ class CanvasGraph(tk.Canvas):
self.drawing_edge = None
self.grid = None
self.meters_per_pixel = 1.5
self.canvas_action = CanvasAction(master, self)
self.setup_menus()
self.setup_bindings()
self.draw_grid()
@ -42,23 +49,33 @@ class CanvasGraph(tk.Canvas):
self.helper = GraphHelper(self, core_grpc)
self.throughput_draw = Throughput(self, core_grpc)
self.wireless_draw = WirelessConnection(self, core_grpc)
self.is_node_context_opened = False
def setup_menus(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")
self.node_context.add_command(
label="Configure", command=self.canvas_action.display_node_configuration
)
self.node_context.add_command(label="Select adjacent")
self.node_context.add_command(label="Create link to")
self.node_context.add_command(label="Assign to")
self.node_context.add_command(label="Move to")
self.node_context.add_command(label="Cut")
self.node_context.add_command(label="Copy")
self.node_context.add_command(label="Paste")
self.node_context.add_command(label="Delete")
self.node_context.add_command(label="Hide")
self.node_context.add_command(label="Services")
def canvas_reset_and_redraw(self, new_grpc):
def canvas_reset_and_redraw(self, session):
"""
Reset the private variables CanvasGraph object, redraw nodes given the new grpc
client.
:param new_grpc:
:return:
:param core.api.grpc.core_pb2.Session session: session to draw
:return: nothing
"""
# delete any existing drawn items
# self.delete_components()
self.helper.delete_canvas_components()
# set the private variables to default value
@ -70,11 +87,7 @@ class CanvasGraph(tk.Canvas):
self.nodes = {}
self.edges = {}
self.drawing_edge = None
# new grpc
self.core_grpc = new_grpc
print("grpah.py draw existing component")
self.draw_existing_component()
print(self.core_grpc.manager.edges)
self.draw_existing_component(session)
def setup_bindings(self):
"""
@ -123,7 +136,6 @@ class CanvasGraph(tk.Canvas):
for node in session.nodes:
# peer to peer node is not drawn on the GUI
if node.type != core_pb2.NodeType.PEER_TO_PEER:
# draw nodes on the canvas
image, name = Images.convert_type_and_model_to_image(
node.type, node.model
@ -206,8 +218,6 @@ class CanvasGraph(tk.Canvas):
].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)
for i in self.find_withtag("node"):
self.lift(i)
@ -260,16 +270,20 @@ class CanvasGraph(tk.Canvas):
:param event: mouse event
:return: nothing
"""
self.focus_set()
self.selected = self.get_selected(event)
logging.debug(f"click release selected: {self.selected}")
if self.mode == GraphMode.EDGE:
self.handle_edge_release(event)
elif self.mode == GraphMode.NODE:
x, y = self.canvas_xy(event)
self.add_node(x, y, self.draw_node_image, self.draw_node_name)
elif self.mode == GraphMode.PICKNODE:
self.mode = GraphMode.NODE
if self.is_node_context_opened:
self.node_context.unpost()
self.is_node_context_opened = False
else:
self.focus_set()
self.selected = self.get_selected(event)
logging.debug(f"click release selected: {self.selected}")
if self.mode == GraphMode.EDGE:
self.handle_edge_release(event)
elif self.mode == GraphMode.NODE:
x, y = self.canvas_xy(event)
self.add_node(x, y, self.draw_node_image, self.draw_node_name)
elif self.mode == GraphMode.PICKNODE:
self.mode = GraphMode.NODE
def handle_edge_release(self, event):
edge = self.drawing_edge
@ -355,11 +369,17 @@ class CanvasGraph(tk.Canvas):
self.coords(self.drawing_edge.id, x1, y1, x2, y2)
def context(self, event):
selected = self.get_selected(event)
nodes = self.find_withtag("node")
if selected in nodes:
logging.debug(f"node context: {selected}")
self.node_context.post(event.x_root, event.y_root)
if not self.is_node_context_opened:
selected = self.get_selected(event)
nodes = self.find_withtag("node")
if selected in nodes:
logging.debug(f"node context: {selected}")
self.node_context.post(event.x_root, event.y_root)
self.canvas_action.node_to_show_config = self.nodes[selected]
self.is_node_context_opened = True
else:
self.node_context.unpost()
self.is_node_context_opened = False
def add_node(self, x, y, image, node_name):
plot_id = self.find_all()[0]
@ -470,8 +490,15 @@ class CanvasNode:
if state == core_pb2.SessionState.RUNTIME:
self.canvas.core_grpc.launch_terminal(node_id)
else:
print("config table show up")
NodeConfig(self, self.image, self.node_type, self.name)
self.canvas.canvas_action.display_configuration(self)
# if self.node_type in CORE_NODES:
# self.canvas.canvas_action.node_to_show_config = self
# self.canvas.canvas_action.display_node_configuration()
# elif self.node_type in CORE_WIRED_NETWORK_NODES:
# return
# elif self.node_type in CORE_WIRELESS_NODE:
# return
# elif self
def update_coords(self):
self.x_coord, self.y_coord = self.canvas.coords(self.id)

View file

@ -7,6 +7,7 @@ import logging
from core.api.grpc import core_pb2
from coretk.coretocanvas import CoreToCanvasMapping
from coretk.interface import Interface, InterfaceManager
from coretk.wlannodeconfig import WlanNodeConfig
link_layer_nodes = ["switch", "hub", "wlan", "rj45", "tunnel"]
network_layer_nodes = ["router", "host", "PC", "mdr", "prouter", "OVS"]
@ -68,6 +69,7 @@ class GrpcManager:
# map tuple(core_node_id, interface_id) to and edge
# self.node_id_and_interface_to_edge_token = {}
self.core_mapping = CoreToCanvasMapping()
self.wlanconfig_management = WlanNodeConfig()
def update_preexisting_ids(self):
"""
@ -142,6 +144,10 @@ class GrpcManager:
logging.error("grpcmanagemeny.py INVALID node name")
nid = self.get_id()
create_node = Node(session_id, nid, node_type, node_model, x, y, name)
# set default configuration for wireless node
self.wlanconfig_management.set_default_config(node_type, nid)
self.nodes[canvas_id] = create_node
self.core_mapping.map_core_id_to_canvas_id(nid, canvas_id)
# self.core_id_to_canvas_id[nid] = canvas_id
@ -166,7 +172,6 @@ class GrpcManager:
# update the next available id
core_id = core_node.id
print(core_id)
if self.id is None or core_id >= self.id:
self.id = core_id + 1
self.preexisting.add(core_id)

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

View file

@ -0,0 +1,91 @@
"""
node image modification
"""
import os
import tkinter as tk
from tkinter import filedialog
from PIL import Image, ImageTk
PATH = os.path.abspath(os.path.dirname(__file__))
ICONS_DIR = os.path.join(PATH, "icons")
class ImageModification:
def __init__(self, canvas, canvas_node, node_config):
"""
create an instance of ImageModification
:param coretk.graph.CanvasGraph canvas: canvas object
:param coretk.graph.CanvasNode canvas_node: node object
:param coretk.nodeconfigtable.NodeConfig node_config: node configuration object
"""
self.canvas = canvas
self.image = canvas_node.image
self.node_type = canvas_node.node_type
self.name = canvas_node.name
self.canvas_node = canvas_node
self.node_configuration = node_config
self.p_top = node_config.top
self.top = tk.Toplevel()
self.top.title(self.name + " image")
self.image_modification()
def open_icon_dir(self, toplevel, entry_text):
filename = filedialog.askopenfilename(
initialdir=ICONS_DIR,
title="Open",
filetypes=(
("images", "*.gif *.jpg *.png *.bmp *pcx *.tga ..."),
("All Files", "*"),
),
)
if len(filename) > 0:
img = Image.open(filename)
tk_img = ImageTk.PhotoImage(img)
lb = toplevel.grid_slaves(1, 0)[0]
lb.configure(image=tk_img)
lb.image = tk_img
entry_text.set(filename)
def click_apply(self, toplevel, entry_text):
imgfile = entry_text.get()
if imgfile:
img = Image.open(imgfile)
tk_img = ImageTk.PhotoImage(img)
f = self.p_top.grid_slaves(row=0, column=0)[0]
lb = f.grid_slaves(row=0, column=3)[0]
lb.configure(image=tk_img)
lb.image = tk_img
self.image = tk_img
self.node_configuration.image = tk_img
toplevel.destroy()
def image_modification(self):
f = tk.Frame(self.top)
entry_text = tk.StringVar()
image_file_label = tk.Label(f, text="Image file: ")
image_file_label.grid(row=0, column=0)
image_file_entry = tk.Entry(f, textvariable=entry_text, width=32, bg="white")
image_file_entry.grid(row=0, column=1)
image_file_button = tk.Button(
f, text="...", command=lambda: self.open_icon_dir(self.top, entry_text)
)
image_file_button.grid(row=0, column=2)
f.grid()
img = tk.Label(self.top, image=self.image)
img.grid()
f = tk.Frame(self.top)
apply_button = tk.Button(
f, text="Apply", command=lambda: self.click_apply(self.top, entry_text)
)
apply_button.grid(row=0, column=0)
apply_to_multiple_button = tk.Button(f, text="Apply to multiple...")
apply_to_multiple_button.grid(row=0, column=1)
cancel_button = tk.Button(f, text="Cancel", command=self.top.destroy)
cancel_button.grid(row=0, column=2)
f.grid()

View file

@ -46,7 +46,10 @@ class Images:
if node_type == core_pb2.NodeType.HUB:
return Images.get(ImageEnum.HUB), "hub"
if node_type == core_pb2.NodeType.WIRELESS_LAN:
return Images.get(ImageEnum.WLAN), "wlan"
return Images.get(ImageEnum.WLAN.value), "wlan"
if node_type == core_pb2.NodeType.EMANE:
return Images.get(ImageEnum.EMANE.value), "emane"
if node_type == core_pb2.NodeType.RJ45:
return Images.get(ImageEnum.RJ45), "rj45"
if node_type == core_pb2.NodeType.TUNNEL:
@ -78,6 +81,7 @@ class ImageEnum(Enum):
LINK = "link"
HUB = "hub"
WLAN = "wlan"
EMANE = "emane"
RJ45 = "rj45"
TUNNEL = "tunnel"
OVAL = "oval"

View file

@ -51,7 +51,7 @@ class InterfaceManager:
ipaddress.ip_network("10.0.0.0/12").subnets(prefixlen_diff=12)
)
self.subnet_index = 0
self.address_index = None
self.address_index = 0
# self.network = ipaddress.ip_network("10.0.0.0/24")
# self.addresses = list(self.network.hosts())
@ -81,9 +81,9 @@ class InterfaceManager:
def new_subnet(self):
self.network = self.core_subnets[self.subnet_index]
self.subnet_index = self.subnet_index + 1
# self.subnet_index = self.subnet_index + 1
self.addresses = list(self.network.hosts())
self.address_index = 0
# self.address_index = 0
# def new_subnet(self):
# """

View file

@ -326,7 +326,7 @@ class MenuAction:
self.application = application
self.core_grpc = application.core_grpc
def clean_nodes_links_and_set_configuarations(self):
def prompt_save_running_session(self):
"""
Prompt use to stop running session before application is closed
@ -343,21 +343,13 @@ class MenuAction:
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.stop_session()
grpc.delete_session()
# else:
# grpc.set_session_state("definition")
grpc.core.close()
# self.application.quit()
def on_quit(self):
"""
@ -365,7 +357,7 @@ class MenuAction:
:return: nothing
"""
self.clean_nodes_links_and_set_configuarations()
self.prompt_save_running_session()
# self.application.core_grpc.close()
self.application.quit()
@ -378,8 +370,6 @@ class MenuAction:
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):
@ -391,30 +381,12 @@ class MenuAction:
filetypes=(("EmulationScript XML File", "*.xml"), ("All Files", "*")),
)
# clean up before opening a new session
self.clean_nodes_links_and_set_configuarations()
# grpc = CoreGrpc(self.application.master)
# grpc.core.connect()
core_grpc = self.application.core_grpc
core_grpc.core.connect()
# session_id = core_grpc.open_xml(file_path)
# core_grpc.session_id = session_id
core_grpc.open_xml(file_path)
# print("Print session state")
# print(grpc.get_session_state())
self.application.canvas.canvas_reset_and_redraw(core_grpc)
self.prompt_save_running_session()
self.application.core_grpc.open_xml(file_path)
# Todo might not need
self.application.core_grpc = core_grpc
self.application.core_editbar.destroy_children_widgets()
self.application.core_editbar.create_toolbar()
# self.application.is_open_xml = False
# self.application.core_editbar.create_runtime_toolbar()
# self.application.canvas.draw_existing_component()
# t1 = time.clock()
# print(t1 - t0)
# self.application.core_editbar.destroy_children_widgets()
# self.application.core_editbar.create_toolbar()
def canvas_size_and_scale(self):
self.application.size_and_scale = SizeAndScale(self.application)

View file

@ -8,6 +8,9 @@ from tkinter import filedialog
from PIL import Image, ImageTk
from coretk.imagemodification import ImageModification
from coretk.nodeservice import NodeServices
PATH = os.path.abspath(os.path.dirname(__file__))
ICONS_DIR = os.path.join(PATH, "icons")
@ -16,14 +19,21 @@ DEFAULTNODES = ["router", "host", "PC"]
class NodeConfig:
def __init__(self, canvas_node, image, node_type, name):
self.image = image
self.node_type = node_type
self.name = name
def __init__(self, canvas, canvas_node):
"""
create an instance of node configuration
:param coretk.graph.CanvasGraph canvas: canvas object
:param coretk.graph.CanvasNode canvas_node: canvas node object
"""
self.canvas = canvas
self.image = canvas_node.image
self.node_type = canvas_node.node_type
self.name = canvas_node.name
self.canvas_node = canvas_node
self.top = tk.Toplevel()
self.top.title(node_type + " configuration")
self.top.title(canvas_node.node_type + " configuration")
self.namevar = tk.StringVar(self.top, value="default name")
self.name_and_image_definition()
self.type_and_service_definition()
@ -58,65 +68,69 @@ class NodeConfig:
toplevel.destroy()
def img_modification(self):
print("image modification")
t = tk.Toplevel()
t.title(self.name + " image")
f = tk.Frame(t)
entry_text = tk.StringVar()
image_file_label = tk.Label(f, text="Image file: ")
image_file_label.pack(side=tk.LEFT, padx=2, pady=2)
image_file_entry = tk.Entry(f, textvariable=entry_text, width=60)
image_file_entry.pack(side=tk.LEFT, padx=2, pady=2)
image_file_label.grid(row=0, column=0)
image_file_entry = tk.Entry(f, textvariable=entry_text, width=32, bg="white")
image_file_entry.grid(row=0, column=1)
image_file_button = tk.Button(
f, text="...", command=lambda: self.open_icon_dir(t, entry_text)
)
image_file_button.pack(side=tk.LEFT, padx=2, pady=2)
f.grid(sticky=tk.W + tk.E)
image_file_button.grid(row=0, column=2)
f.grid()
img = tk.Label(t, image=self.image)
img.grid(sticky=tk.W + tk.E)
img.grid()
f = tk.Frame(t)
apply_button = tk.Button(
f, text="Apply", command=lambda: self.click_apply(t, entry_text)
)
apply_button.pack(side=tk.LEFT, padx=2, pady=2)
apply_button.grid(row=0, column=0)
apply_to_multiple_button = tk.Button(f, text="Apply to multiple...")
apply_to_multiple_button.pack(side=tk.LEFT, padx=2, pady=2)
apply_to_multiple_button.grid(row=0, column=1)
cancel_button = tk.Button(f, text="Cancel", command=t.destroy)
cancel_button.pack(side=tk.LEFT, padx=2, pady=2)
f.grid(sticky=tk.E + tk.W)
cancel_button.grid(row=0, column=2)
f.grid()
def name_and_image_definition(self):
name_label = tk.Label(self.top, text="Node name: ")
name_label.grid()
name_entry = tk.Entry(self.top, textvariable=self.namevar)
name_entry.grid(row=0, column=1)
f = tk.Frame(self.top, bg="#d9d9d9")
name_label = tk.Label(f, text="Node name: ", bg="#d9d9d9")
name_label.grid(padx=2, pady=2)
name_entry = tk.Entry(f, textvariable=self.namevar)
name_entry.grid(row=0, column=1, padx=2, pady=2)
core_button = tk.Button(self.top, text="None")
core_button.grid(row=0, column=2)
core_button = tk.Button(f, text="None")
core_button.grid(row=0, column=2, padx=2, pady=2)
img_button = tk.Button(
self.top,
f,
image=self.image,
width=40,
height=40,
command=self.img_modification,
command=lambda: ImageModification(self.canvas, self.canvas_node, self),
bg="#d9d9d9",
)
img_button.grid(row=0, column=3)
img_button.grid(row=0, column=3, padx=4, pady=4)
f.grid(padx=4, pady=4)
def type_and_service_definition(self):
f = tk.Frame(self.top)
type_label = tk.Label(f, text="Type: ")
type_label.pack(side=tk.LEFT)
type_label.grid(row=0, column=0)
type_button = tk.Button(f, text="None")
type_button.pack(side=tk.LEFT)
type_button.grid(row=0, column=1)
service_button = tk.Button(f, text="Services...")
service_button.pack(side=tk.LEFT)
service_button = tk.Button(
f, text="Services...", command=lambda: NodeServices()
)
service_button.grid(row=0, column=2)
f.grid(row=1, column=1, columnspan=2, sticky=tk.W)
f.grid(padx=2, pady=2)
def config_apply(self):
"""
@ -140,10 +154,10 @@ class NodeConfig:
def select_definition(self):
f = tk.Frame(self.top)
apply_button = tk.Button(f, text="Apply", command=self.config_apply)
apply_button.pack(side=tk.LEFT)
apply_button.grid(row=0, column=0)
cancel_button = tk.Button(f, text="Cancel", command=self.config_cancel)
cancel_button.pack(side=tk.LEFT)
f.grid(row=3, column=1, sticky=tk.W)
cancel_button.grid(row=0, column=1)
f.grid()
def network_node_config(self):
self.name_and_image_definition()

View file

@ -0,0 +1,195 @@
"""
core node services
"""
import tkinter as tk
from tkinter import messagebox
CORE_DEFAULT_GROUPS = ["EMANE", "FRR", "ProtoSvc", "Quagga", "Security", "Utility"]
DEFAULT_GROUP_RADIO_VALUE = {
"EMANE": 1,
"FRR": 2,
"ProtoSvc": 3,
"Quagga": 4,
"Security": 5,
"Utility": 6,
}
DEFAULT_GROUP_SERVICES = {
"EMANE": ["transportd"],
"FRR": [
"FRRBable",
"FRRBGP",
"FRROSPFv2",
"FRROSPFv3",
"FRRpimd",
"FRRRIP",
"FRRRIPNG",
"FRRzebra",
],
"ProtoSvc": ["MGEN_Sink", "MgenActor", "SMF"],
"Quagga": [
"Babel",
"BGP",
"OSPFv2",
"OSPFv3",
"OSPFv3MDR",
"RIP",
"RIPNG",
"Xpimd",
"zebra",
],
"Security": ["Firewall", "IPsec", "NAT", "VPNClient", "VPNServer"],
"Utility": [
"atd",
"DefaultMulticastRoute",
"DefaultRoute",
"DHCP",
"DHCPClient",
"FTP",
"HTTP",
"IPForward ",
"pcap",
"radvd",
"SSH",
"StaticRoute",
"ucarp",
"UserDefined",
],
}
class NodeServices:
def __init__(self):
self.core_groups = []
self.service_to_config = None
self.top = tk.Toplevel()
self.top.title("Node services")
self.config_frame = tk.Frame(self.top)
self.config_frame.grid()
self.draw_group()
self.group_services()
self.current_services()
self.node_service_options()
def display_group_services(self, group_name):
group_services_frame = self.config_frame.grid_slaves(row=0, column=1)[0]
listbox = group_services_frame.grid_slaves(row=1, column=0)[0]
listbox.delete(0, tk.END)
for s in DEFAULT_GROUP_SERVICES[group_name]:
listbox.insert(tk.END, s)
for i in range(listbox.size()):
listbox.itemconfig(i, selectbackground="white")
def group_select(self, event):
listbox = event.widget
cur_selection = listbox.curselection()
if cur_selection:
s = listbox.get(listbox.curselection())
self.display_group_services(s)
def draw_group(self):
"""
draw the group tab
:return: nothing
"""
f = tk.Frame(self.config_frame)
lbl = tk.Label(f, text="Group")
lbl.grid()
sb = tk.Scrollbar(f, orient=tk.VERTICAL)
sb.grid(row=1, column=1, sticky=tk.S + tk.N)
listbox = tk.Listbox(
f,
selectmode=tk.SINGLE,
yscrollcommand=sb.set,
relief=tk.FLAT,
highlightbackground="#b3b3b3",
highlightcolor="#b3b3b3",
highlightthickness=0.5,
bd=0,
)
for grp in CORE_DEFAULT_GROUPS:
listbox.insert(tk.END, grp)
for i in range(0, listbox.size()):
listbox.itemconfig(i, selectbackground="white")
listbox.grid(row=1, column=0)
sb.config(command=listbox.yview)
f.grid(padx=3, pady=3)
listbox.bind("<<ListboxSelect>>", self.group_select)
def group_service_select(self, event):
print("select group service")
listbox = event.widget
cur_selection = listbox.curselection()
if cur_selection:
s = listbox.get(listbox.curselection())
self.service_to_config = s
else:
self.service_to_config = None
def group_services(self):
f = tk.Frame(self.config_frame)
lbl = tk.Label(f, text="Group services")
lbl.grid()
sb = tk.Scrollbar(f, orient=tk.VERTICAL)
sb.grid(row=1, column=1, sticky=tk.S + tk.N)
listbox = tk.Listbox(
f,
selectmode=tk.SINGLE,
yscrollcommand=sb.set,
relief=tk.FLAT,
highlightbackground="#b3b3b3",
highlightcolor="#b3b3b3",
highlightthickness=0.5,
bd=0,
)
listbox.grid(row=1, column=0)
sb.config(command=listbox.yview)
f.grid(padx=3, pady=3, row=0, column=1)
listbox.bind("<<ListboxSelect>>", self.group_service_select)
def current_services(self):
f = tk.Frame(self.config_frame)
lbl = tk.Label(f, text="Current services")
lbl.grid()
sb = tk.Scrollbar(f, orient=tk.VERTICAL)
sb.grid(row=1, column=1, sticky=tk.S + tk.N)
listbox = tk.Listbox(
f,
selectmode=tk.MULTIPLE,
yscrollcommand=sb.set,
relief=tk.FLAT,
highlightbackground="#b3b3b3",
highlightcolor="#b3b3b3",
highlightthickness=0.5,
bd=0,
)
listbox.grid(row=1, column=0)
sb.config(command=listbox.yview)
f.grid(padx=3, pady=3, row=0, column=2)
def config_service(self):
if self.service_to_config is None:
messagebox.showinfo("CORE info", "Choose a service to configure.")
else:
print(self.service_to_config)
def node_service_options(self):
f = tk.Frame(self.top)
b = tk.Button(f, text="Connfigure", command=self.config_service)
b.grid(row=0, column=0)
b = tk.Button(f, text="Apply")
b.grid(row=0, column=1)
b = tk.Button(f, text="Cancel", command=self.top.destroy)
b.grid(row=0, column=2)
f.grid(sticky=tk.E)

View file

@ -0,0 +1,299 @@
"""
wlan configuration
"""
import tkinter as tk
from functools import partial
from coretk.imagemodification import ImageModification
class WlanConfiguration:
def __init__(self, canvas, canvas_node, config):
"""
create an instance of WlanConfiguration
:param coretk.grpah.CanvasGraph canvas: canvas object
:param coretk.graph.CanvasNode canvas_node: canvas node object
"""
self.canvas = canvas
self.image = canvas_node.image
self.node_type = canvas_node.node_type
self.name = canvas_node.name
self.canvas_node = canvas_node
self.top = tk.Toplevel()
self.top.title("wlan configuration")
self.node_name = tk.StringVar()
# self.range_var = tk.DoubleVar()
# self.range_var.set(275.0)
self.config = config
self.range_var = tk.StringVar()
self.range_var.set(config["basic_range"])
# self.bandwidth_var = tk.IntVar()
self.bandwidth_var = tk.StringVar()
self.bandwidth_var.set(config["bandwidth"])
self.delay_var = tk.StringVar()
self.image_modification()
self.wlan_configuration()
self.subnet()
self.wlan_options()
self.config_option()
def image_modification(self):
"""
draw image modification part
:return: nothing
"""
f = tk.Frame(self.top, bg="#d9d9d9")
lbl = tk.Label(f, text="Node name: ", bg="#d9d9d9")
lbl.grid(row=0, column=0, padx=3, pady=3)
e = tk.Entry(f, textvariable=self.node_name, bg="white")
e.grid(row=0, column=1, padx=3, pady=3)
b = tk.Button(f, text="None")
b.grid(row=0, column=2, padx=3, pady=3)
b = tk.Button(
f,
image=self.image,
command=lambda: ImageModification(
canvas=self.canvas, canvas_node=self.canvas_node, node_config=self
),
)
b.grid(row=0, column=3, padx=3, pady=3)
f.grid(padx=2, pady=2, ipadx=2, ipady=2)
def create_string_var(self, val):
"""
create string variable for convenience
:param str val: text value
:return: nothing
"""
v = tk.StringVar()
v.set(val)
return v
def scrollbar_command(self, entry_widget, delta, event):
"""
change text in entry based on scrollbar action (click up or down)
:param tkinter.Entry entry_widget: entry needed for changing text
:param int or float delta: the amount to change
:param event: scrollbar event
:return: nothing
"""
try:
value = int(entry_widget.get())
except ValueError:
value = float(entry_widget.get())
entry_widget.delete(0, tk.END)
if event == "-1":
entry_widget.insert(tk.END, str(round(value + delta, 1)))
elif event == "1":
entry_widget.insert(tk.END, str(round(value - delta, 1)))
def wlan_configuration(self):
"""
create wireless configuration table
:return: nothing
"""
lbl = tk.Label(self.top, text="Wireless")
lbl.grid(sticky=tk.W, padx=3, pady=3)
f = tk.Frame(
self.top,
highlightbackground="#b3b3b3",
highlightcolor="#b3b3b3",
highlightthickness=0.5,
bd=0,
bg="#d9d9d9",
)
lbl = tk.Label(
f,
text="The basic range model calculates on/off connectivity based on pixel distance between nodes.",
bg="#d9d9d9",
)
lbl.grid(padx=4, pady=4)
f1 = tk.Frame(f, bg="#d9d9d9")
lbl = tk.Label(f1, text="Range: ", bg="#d9d9d9")
lbl.grid(row=0, column=0)
e = tk.Entry(
f1,
textvariable=self.create_string_var(self.config["basic_range"]),
width=5,
bg="white",
)
e.grid(row=0, column=1)
lbl = tk.Label(f1, text="Bandwidth (bps): ", bg="#d9d9d9")
lbl.grid(row=0, column=2)
f11 = tk.Frame(f1, bg="#d9d9d9")
sb = tk.Scrollbar(f11, orient=tk.VERTICAL)
e = tk.Entry(
f11,
textvariable=self.create_string_var(self.config["bandwidth"]),
width=10,
bg="white",
)
sb.config(command=partial(self.scrollbar_command, e, 1000000))
e.grid()
sb.grid(row=0, column=1)
f11.grid(row=0, column=3)
# e = tk.Entry(f1, textvariable=self.bandwidth_var, width=10)
# e.grid(row=0, column=4)
f1.grid(sticky=tk.W, padx=4, pady=4)
f2 = tk.Frame(f, bg="#d9d9d9")
lbl = tk.Label(f2, text="Delay (us): ", bg="#d9d9d9")
lbl.grid(row=0, column=0)
f21 = tk.Frame(f2, bg="#d9d9d9")
sb = tk.Scrollbar(f21, orient=tk.VERTICAL)
e = tk.Entry(
f21, textvariable=self.create_string_var(self.config["delay"]), bg="white"
)
sb.config(command=partial(self.scrollbar_command, e, 5000))
e.grid()
sb.grid(row=0, column=1)
f21.grid(row=0, column=1)
lbl = tk.Label(f2, text="Loss (%): ", bg="#d9d9d9")
lbl.grid(row=0, column=2)
f22 = tk.Frame(f2, bg="#d9d9d9")
sb = tk.Scrollbar(f22, orient=tk.VERTICAL)
e = tk.Entry(
f22, textvariable=self.create_string_var(self.config["error"]), bg="white"
)
sb.config(command=partial(self.scrollbar_command, e, 0.1))
e.grid()
sb.grid(row=0, column=1)
f22.grid(row=0, column=3)
# e = tk.Entry(f2, textvariable=self.create_string_var(0))
# e.grid(row=0, column=3)
f2.grid(sticky=tk.W, padx=4, pady=4)
f3 = tk.Frame(f, bg="#d9d9d9")
lbl = tk.Label(f3, text="Jitter (us): ", bg="#d9d9d9")
lbl.grid()
f31 = tk.Frame(f3, bg="#d9d9d9")
sb = tk.Scrollbar(f31, orient=tk.VERTICAL)
e = tk.Entry(
f31, textvariable=self.create_string_var(self.config["jitter"]), bg="white"
)
sb.config(command=partial(self.scrollbar_command, e, 5000))
e.grid()
sb.grid(row=0, column=1)
f31.grid(row=0, column=1)
f3.grid(sticky=tk.W, padx=4, pady=4)
f.grid(padx=3, pady=3)
def subnet(self):
"""
create the entries for ipv4 subnet and ipv6 subnet
:return: nothing
"""
f = tk.Frame(self.top)
f1 = tk.Frame(f)
lbl = tk.Label(f1, text="IPv4 subnet")
lbl.grid()
e = tk.Entry(f1, width=30, bg="white", textvariable=self.create_string_var(""))
e.grid(row=0, column=1)
f1.grid()
f2 = tk.Frame(f)
lbl = tk.Label(f2, text="IPv6 subnet")
lbl.grid()
e = tk.Entry(f2, width=30, bg="white", textvariable=self.create_string_var(""))
e.grid(row=0, column=1)
f2.grid()
f.grid(sticky=tk.W, padx=3, pady=3)
def wlan_options(self):
"""
create wireless node options
:return:
"""
f = tk.Frame(self.top)
b = tk.Button(f, text="ns-2 mobility script...")
b.pack(side=tk.LEFT, padx=1)
b = tk.Button(f, text="Link to all routers")
b.pack(side=tk.LEFT, padx=1)
b = tk.Button(f, text="Choose WLAN members")
b.pack(side=tk.LEFT, padx=1)
f.grid(sticky=tk.W)
def wlan_config_apply(self):
"""
retrieve user's wlan configuration and store the new configuration values
:return: nothing
"""
config_frame = self.top.grid_slaves(row=2, column=0)[0]
range_and_bandwidth_frame = config_frame.grid_slaves(row=1, column=0)[0]
range_val = range_and_bandwidth_frame.grid_slaves(row=0, column=1)[0].get()
bandwidth = (
range_and_bandwidth_frame.grid_slaves(row=0, column=3)[0]
.grid_slaves(row=0, column=0)[0]
.get()
)
delay_and_loss_frame = config_frame.grid_slaves(row=2, column=0)[0]
delay = (
delay_and_loss_frame.grid_slaves(row=0, column=1)[0]
.grid_slaves(row=0, column=0)[0]
.get()
)
loss = (
delay_and_loss_frame.grid_slaves(row=0, column=3)[0]
.grid_slaves(row=0, column=0)[0]
.get()
)
jitter_frame = config_frame.grid_slaves(row=3, column=0)[0]
jitter_val = (
jitter_frame.grid_slaves(row=0, column=1)[0]
.grid_slaves(row=0, column=0)[0]
.get()
)
# set wireless node configuration here
wlanconfig_manager = self.canvas.grpc_manager.wlanconfig_management
wlanconfig_manager.set_custom_config(
node_id=self.canvas_node.core_id,
range=range_val,
bandwidth=bandwidth,
jitter=jitter_val,
delay=delay,
error=loss,
)
self.top.destroy()
def config_option(self):
"""
create node configuration options
:return: nothing
"""
f = tk.Frame(self.top, bg="#d9d9d9")
b = tk.Button(f, text="Apply", bg="#d9d9d9", command=self.wlan_config_apply)
b.grid(padx=2, pady=2)
b = tk.Button(f, text="Cancel", bg="#d9d9d9", command=self.top.destroy)
b.grid(row=0, column=1, padx=2, pady=2)
f.grid(padx=4, pady=4)

View file

@ -0,0 +1,29 @@
"""
wireless node configuration for all the wireless node
"""
from collections import OrderedDict
from core.api.grpc import core_pb2
class WlanNodeConfig:
def __init__(self):
# maps node id to wlan configuration
self.configurations = {}
def set_default_config(self, node_type, node_id):
if node_type == core_pb2.NodeType.WIRELESS_LAN:
config = OrderedDict()
config["basic_range"] = "275"
config["bandwidth"] = "54000000"
config["jitter"] = "0"
config["delay"] = "20000"
config["error"] = "0"
self.configurations[node_id] = config
def set_custom_config(self, node_id, range, bandwidth, jitter, delay, error):
self.configurations[node_id]["basic_range"] = range
self.configurations[node_id]["bandwidth"] = bandwidth
self.configurations[node_id]["jitter"] = jitter
self.configurations[node_id]["delay"] = delay
self.configurations[node_id]["error"] = error