Merge branch 'coretk' of https://github.com/coreemu/core into coretk

This commit is contained in:
Blake Harnden 2019-11-05 16:18:11 -08:00
commit bff1c26c2a
37 changed files with 767 additions and 27 deletions

View file

@ -1,10 +1,8 @@
""" """
canvas graph action canvas graph action
""" """
# import tkinter as tk
from core.api.grpc import core_pb2 from core.api.grpc import core_pb2
from coretk.dialogs.emaneconfig import EmaneConfiguration
from coretk.dialogs.nodeconfig import NodeConfigDialog from coretk.dialogs.nodeconfig import NodeConfigDialog
from coretk.dialogs.wlanconfig import WlanConfigDialog from coretk.dialogs.wlanconfig import WlanConfigDialog
@ -12,6 +10,7 @@ from coretk.dialogs.wlanconfig import WlanConfigDialog
NODE_TO_TYPE = { NODE_TO_TYPE = {
"router": core_pb2.NodeType.DEFAULT, "router": core_pb2.NodeType.DEFAULT,
"wlan": core_pb2.NodeType.WIRELESS_LAN, "wlan": core_pb2.NodeType.WIRELESS_LAN,
"emane": core_pb2.NodeType.EMANE,
} }
@ -28,6 +27,8 @@ class CanvasAction:
self.display_node_configuration() self.display_node_configuration()
elif pb_type == core_pb2.NodeType.WIRELESS_LAN: elif pb_type == core_pb2.NodeType.WIRELESS_LAN:
self.display_wlan_configuration(canvas_node) self.display_wlan_configuration(canvas_node)
elif pb_type == core_pb2.NodeType.EMANE:
self.display_emane_configuration()
def display_node_configuration(self): def display_node_configuration(self):
dialog = NodeConfigDialog(self.master, self.master, self.node_to_show_config) dialog = NodeConfigDialog(self.master, self.master, self.node_to_show_config)
@ -35,6 +36,7 @@ class CanvasAction:
self.node_to_show_config = None self.node_to_show_config = None
def display_wlan_configuration(self, canvas_node): def display_wlan_configuration(self, canvas_node):
# print(self.canvas.grpc_manager.wlanconfig_management.configurations) # print(self.canvas.grpc_manager.wlanconfig_management.configurations)
wlan_config = self.master.core.wlanconfig_management.configurations[ wlan_config = self.master.core.wlanconfig_management.configurations[
canvas_node.core_id canvas_node.core_id
@ -44,3 +46,8 @@ class CanvasAction:
) )
dialog.show() dialog.show()
self.node_to_show_config = None self.node_to_show_config = None
def display_emane_configuration(self):
app = self.canvas.core.app
dialog = EmaneConfiguration(self.master, app, self.node_to_show_config)
dialog.show()

View file

@ -7,6 +7,7 @@ from tkinter import ttk
class ConfigType(enum.Enum): class ConfigType(enum.Enum):
STRING = 10 STRING = 10
BOOL = 11 BOOL = 11
EMANECONFIG = 7
def create_config(master, config, padx=2, pady=2): def create_config(master, config, padx=2, pady=2):
@ -52,8 +53,13 @@ def create_config(master, config, padx=2, pady=2):
else: else:
value.set("Off") value.set("Off")
elif config_type == ConfigType.STRING: elif config_type == ConfigType.STRING:
value.set(option.value)
entry = tk.Entry(frame, textvariable=value) entry = tk.Entry(frame, textvariable=value)
entry.grid(row=index, column=1, sticky="ew", pady=pady) entry.grid(row=index, column=1, sticky="ew", pady=pady)
elif config_type == ConfigType.EMANECONFIG:
value.set(option.value)
entry = tk.Entry(frame, textvariable=value, bg="white")
entry.grid(row=index, column=1, sticky="ew", pady=pady)
else: else:
logging.error("unhandled config option type: %s", config_type) logging.error("unhandled config option type: %s", config_type)
values[key] = value values[key] = value
@ -68,7 +74,6 @@ def create_config(master, config, padx=2, pady=2):
canvas.bind( canvas.bind(
"<Configure>", lambda event: canvas.itemconfig(frame_id, width=event.width) "<Configure>", lambda event: canvas.itemconfig(frame_id, width=event.width)
) )
return values return values

View file

@ -9,6 +9,7 @@ from core.api.grpc import client, core_pb2
from coretk.coretocanvas import CoreToCanvasMapping from coretk.coretocanvas import CoreToCanvasMapping
from coretk.dialogs.sessions import SessionsDialog from coretk.dialogs.sessions import SessionsDialog
from coretk.interface import Interface, InterfaceManager from coretk.interface import Interface, InterfaceManager
from coretk.mobilitynodeconfig import MobilityNodeConfig
from coretk.wlannodeconfig import WlanNodeConfig from coretk.wlannodeconfig import WlanNodeConfig
link_layer_nodes = ["switch", "hub", "wlan", "rj45", "tunnel"] link_layer_nodes = ["switch", "hub", "wlan", "rj45", "tunnel"]
@ -94,6 +95,8 @@ class CoreClient:
self.interfaces_manager = InterfaceManager() self.interfaces_manager = InterfaceManager()
self.core_mapping = CoreToCanvasMapping() self.core_mapping = CoreToCanvasMapping()
self.wlanconfig_management = WlanNodeConfig() self.wlanconfig_management = WlanNodeConfig()
self.mobilityconfig_management = MobilityNodeConfig()
self.emane_config = None
def handle_events(self, event): def handle_events(self, event):
logging.info("event: %s", event) logging.info("event: %s", event)
@ -124,11 +127,15 @@ class CoreClient:
self.nodes.clear() self.nodes.clear()
self.edges.clear() self.edges.clear()
self.hooks.clear() self.hooks.clear()
self.wlanconfig_management.configurations.clear()
self.mobilityconfig_management.configurations.clear()
self.emane_config = None
# get session data # get session data
response = self.client.get_session(self.session_id) response = self.client.get_session(self.session_id)
logging.info("joining session(%s): %s", self.session_id, response) logging.info("joining session(%s): %s", self.session_id, response)
session = response.session session = response.session
session_state = session.state
self.client.events(self.session_id, self.handle_events) self.client.events(self.session_id, self.handle_events)
# get hooks # get hooks
@ -137,6 +144,28 @@ class CoreClient:
for hook in response.hooks: for hook in response.hooks:
self.hooks[hook.file] = hook self.hooks[hook.file] = hook
# get wlan configs
for node in session.nodes:
if node.type == core_pb2.NodeType.WIRELESS_LAN:
response = self.client.get_wlan_config(self.session_id, node.id)
logging.info("wlan config(%s): %s", node.id, response)
node_config = response.config
config = {x: node_config[x].value for x in node_config}
self.wlanconfig_management.configurations[node.id] = config
# get mobility configs
response = self.client.get_mobility_configs(self.session_id)
logging.info("mobility configs: %s", response)
for node_id in response.configs:
node_config = response.configs[node_id].config
config = {x: node_config[x].value for x in node_config}
self.mobilityconfig_management.configurations[node_id] = config
# get emane config
response = self.client.get_emane_config(self.session_id)
logging.info("emane config: %s", response)
self.emane_config = response.config
# determine next node id and reusable nodes # determine next node id and reusable nodes
max_id = 1 max_id = 1
for node in session.nodes: for node in session.nodes:
@ -151,6 +180,14 @@ class CoreClient:
# draw session # draw session
self.app.canvas.canvas_reset_and_redraw(session) self.app.canvas.canvas_reset_and_redraw(session)
# draw tool bar appropritate with session state
if session_state == core_pb2.SessionState.RUNTIME:
self.app.core_editbar.destroy_children_widgets()
self.app.core_editbar.create_runtime_toolbar()
else:
self.app.core_editbar.destroy_children_widgets()
self.app.core_editbar.create_toolbar()
def create_new_session(self): def create_new_session(self):
""" """
Create a new session Create a new session
@ -302,6 +339,7 @@ class CoreClient:
links, links,
hooks=list(self.hooks.values()), hooks=list(self.hooks.values()),
wlan_configs=wlan_configs, wlan_configs=wlan_configs,
emane_config=emane_config,
) )
logging.debug("Start session %s, result: %s", self.session_id, response.result) logging.debug("Start session %s, result: %s", self.session_id, response.result)
@ -439,6 +477,8 @@ class CoreClient:
# set default configuration for wireless node # set default configuration for wireless node
self.wlanconfig_management.set_default_config(node_type, nid) self.wlanconfig_management.set_default_config(node_type, nid)
self.mobilityconfig_management.set_default_configuration(node_type, nid)
self.nodes[canvas_id] = create_node self.nodes[canvas_id] = create_node
self.core_mapping.map_core_id_to_canvas_id(nid, canvas_id) self.core_mapping.map_core_id_to_canvas_id(nid, canvas_id)
# self.core_id_to_canvas_id[nid] = canvas_id # self.core_id_to_canvas_id[nid] = canvas_id
@ -543,7 +583,7 @@ class CoreClient:
""" """
Create the interface for the two end of an edge, add a copy to node's interfaces 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 coretk.coreclient.Edge edge: edge to add interfaces to
:param int src_canvas_id: canvas id for the source node :param int src_canvas_id: canvas id for the source node
:param int dst_canvas_id: canvas id for the destination node :param int dst_canvas_id: canvas id for the destination node
:return: nothing :return: nothing

View file

@ -357,9 +357,9 @@ class CoreToolbar(object):
def pick_emane(self, main_button): def pick_emane(self, main_button):
self.link_layer_option_menu.destroy() self.link_layer_option_menu.destroy()
main_button.configure(image=Images.get(ImageEnum.EMANE.value)) main_button.configure(image=Images.get(ImageEnum.EMANE))
self.canvas.mode = GraphMode.PICKNODE self.canvas.mode = GraphMode.PICKNODE
self.canvas.draw_node_image = Images.get(ImageEnum.EMANE.value) self.canvas.draw_node_image = Images.get(ImageEnum.EMANE)
self.canvas.draw_node_name = "emane" self.canvas.draw_node_name = "emane"
def draw_link_layer_options(self, link_layer_button): def draw_link_layer_options(self, link_layer_button):

View file

@ -35,17 +35,17 @@ class CoreToolbarHelp:
interface_one = self.app.core.create_interface(edge.type1, edge.interface_1) interface_one = self.app.core.create_interface(edge.type1, edge.interface_1)
interface_two = self.app.core.create_interface(edge.type2, edge.interface_2) interface_two = self.app.core.create_interface(edge.type2, edge.interface_2)
# TODO for now only consider the basic cases # TODO for now only consider the basic cases
if ( # if (
edge.type1 == core_pb2.NodeType.WIRELESS_LAN # edge.type1 == core_pb2.NodeType.WIRELESS_LAN
or edge.type2 == core_pb2.NodeType.WIRELESS_LAN # or edge.type2 == core_pb2.NodeType.WIRELESS_LAN
): # ):
link_type = core_pb2.LinkType.WIRELESS # link_type = core_pb2.LinkType.WIRELESS
else: # else:
link_type = core_pb2.LinkType.WIRED # link_type = core_pb2.LinkType.WIRED
link = core_pb2.Link( link = core_pb2.Link(
node_one_id=edge.id1, node_one_id=edge.id1,
node_two_id=edge.id2, node_two_id=edge.id2,
type=link_type, type=core_pb2.LinkType.WIRED,
interface_one=interface_one, interface_one=interface_one,
interface_two=interface_two, interface_two=interface_two,
) )
@ -54,6 +54,11 @@ class CoreToolbarHelp:
return links return links
def get_wlan_configuration_list(self): def get_wlan_configuration_list(self):
"""
form a list of wlan configuration to pass to start_session
:return: nothing
"""
configs = [] configs = []
manager_configs = self.app.core.wlanconfig_management.configurations manager_configs = self.app.core.wlanconfig_management.configurations
for key in manager_configs: for key in manager_configs:
@ -61,8 +66,34 @@ class CoreToolbarHelp:
configs.append(cnf) configs.append(cnf)
return configs return configs
def get_mobility_configuration_list(self):
"""
form a list of mobility configuration to pass to start_session
:return: nothing
"""
configs = []
core = self.app.canvas.core
manager_configs = core.mobilityconfig_management.configurations
for key in manager_configs:
cnf = core_pb2.MobilityConfig(node_id=key, config=manager_configs[key])
configs.append(cnf)
return configs
def gui_start_session(self): def gui_start_session(self):
nodes = self.get_node_list() nodes = self.get_node_list()
links = self.get_link_list() links = self.get_link_list()
wlan_configs = self.get_wlan_configuration_list() wlan_configs = self.get_wlan_configuration_list()
self.app.core.start_session(nodes, links, wlan_configs=wlan_configs) mobility_configs = self.get_mobility_configuration_list()
# get emane config
pb_emane_config = self.app.core.emane_config
emane_config = {x: pb_emane_config[x].value for x in pb_emane_config}
self.app.core.start_session(
nodes,
links,
wlan_configs=wlan_configs,
mobility_configs=mobility_configs,
emane_config=emane_config,
)

View file

@ -0,0 +1,340 @@
"""
emane configuration
"""
import logging
import tkinter as tk
import webbrowser
from tkinter import ttk
from coretk import configutils
from coretk.dialogs.dialog import Dialog
from coretk.images import ImageEnum, Images
PAD_X = 2
PAD_Y = 2
class EmaneConfiguration(Dialog):
def __init__(self, master, app, canvas_node):
super().__init__(master, app, "emane configuration", modal=False)
self.app = app
self.canvas_node = canvas_node
self.radiovar = tk.IntVar()
self.radiovar.set(1)
self.columnconfigure(0, weight=1)
# list(string) of emane models
self.emane_models = None
self.emane_dialog = Dialog(self, app, "emane configuration", modal=False)
self.emane_model_dialog = None
self.emane_model_combobox = None
# draw
self.node_name_and_image()
self.emane_configuration()
self.draw_ip_subnets()
self.emane_options()
self.draw_apply_and_cancel()
self.values = None
self.options = app.core.emane_config
self.model_options = None
self.model_values = None
def create_text_variable(self, val):
"""
create a string variable for convenience
:param str val: entry text
:return: nothing
"""
var = tk.StringVar()
var.set(val)
return var
def choose_core(self):
print("not implemented")
def node_name_and_image(self):
f = tk.Frame(self, bg="#d9d9d9")
lbl = tk.Label(f, text="Node name:", bg="#d9d9d9")
lbl.grid(row=0, column=0, padx=2, pady=2)
e = tk.Entry(f, textvariable=self.create_text_variable(""), bg="white")
e.grid(row=0, column=1, padx=2, pady=2)
cbb = ttk.Combobox(f, values=["(none)", "core1", "core2"], state="readonly")
cbb.current(0)
cbb.grid(row=0, column=2, padx=2, pady=2)
b = tk.Button(f, image=self.canvas_node.image)
b.grid(row=0, column=3, padx=2, pady=2)
f.grid(row=0, column=0, sticky="nsew")
def save_emane_option(self):
configutils.parse_config(self.options, self.values)
self.emane_dialog.destroy()
def draw_emane_options(self):
if not self.emane_dialog.winfo_exists():
self.emane_dialog = Dialog(
self, self.app, "emane configuration", modal=False
)
b1 = tk.Button(self.emane_dialog, text="Appy", command=self.save_emane_option)
b2 = tk.Button(
self.emane_dialog, text="Cancel", command=self.emane_dialog.destroy
)
if self.options is None:
session_id = self.app.core.session_id
response = self.app.core.client.get_emane_config(session_id)
logging.info("emane config: %s", response)
self.options = response.config
self.values = configutils.create_config(
self.emane_dialog, self.options, PAD_X, PAD_Y
)
b1.grid(row=1, column=0)
b2.grid(row=1, column=1)
self.emane_dialog.show()
def save_emane_model_options(self):
"""
configure the node's emane model on the fly
:return: nothing
"""
# get model name
model_name = self.emane_models[self.emane_model_combobox.current()]
# parse configuration
configutils.parse_config(self.model_options, self.model_values)
config = {x: self.model_options[x].value for x in self.model_options}
# add string emane_ infront for grpc call
response = self.app.core.client.set_emane_model_config(
self.app.core.session_id,
self.canvas_node.core_id,
"emane_" + model_name,
config,
)
logging.info(
"emaneconfig.py config emane model (%s), result: %s",
self.canvas_node.core_id,
response,
)
self.emane_model_dialog.destroy()
def draw_model_options(self):
"""
draw emane model configuration
:return: nothing
"""
# get model name
model_name = self.emane_models[self.emane_model_combobox.current()]
# create the dialog and the necessry widget
if not self.emane_model_dialog or not self.emane_model_dialog.winfo_exists():
self.emane_model_dialog = Dialog(
self, self.app, model_name + " configuration", modal=False
)
b1 = tk.Button(
self.emane_model_dialog, text="Apply", command=self.save_emane_model_options
)
b2 = tk.Button(
self.emane_model_dialog,
text="Cancel",
command=self.emane_model_dialog.destroy,
)
# query for configurations
session_id = self.app.core.session_id
# add string emane_ before model name for grpc call
response = self.app.core.client.get_emane_model_config(
session_id, self.canvas_node.core_id, "emane_" + model_name
)
logging.info("emane model config %s", response)
self.model_options = response.config
self.model_values = configutils.create_config(
self.emane_model_dialog, self.model_options, PAD_X, PAD_Y
)
b1.grid(row=1, column=0, sticky="nsew")
b2.grid(row=1, column=1, sticky="nsew")
self.emane_model_dialog.show()
def draw_option_buttons(self, parent):
f = tk.Frame(parent, bg="#d9d9d9")
f.columnconfigure(0, weight=1)
f.columnconfigure(1, weight=1)
b = tk.Button(
f,
text=self.emane_models[0] + " options",
image=Images.get(ImageEnum.EDITNODE),
compound=tk.RIGHT,
bg="#d9d9d9",
command=self.draw_model_options,
)
b.grid(row=0, column=0, padx=10, pady=2, sticky="nsew")
b = tk.Button(
f,
text="EMANE options",
image=Images.get(ImageEnum.EDITNODE),
compound=tk.RIGHT,
bg="#d9d9d9",
command=self.draw_emane_options,
)
b.grid(row=0, column=1, padx=10, pady=2, sticky="nsew")
f.grid(row=4, column=0, sticky="nsew")
def combobox_select(self, event):
"""
update emane model options button
:param event:
:return: nothing
"""
# get model name
model_name = self.emane_models[self.emane_model_combobox.current()]
# get the button and configure button text
config_frame = self.grid_slaves(row=2, column=0)[0]
option_button_frame = config_frame.grid_slaves(row=4, column=0)[0]
b = option_button_frame.grid_slaves(row=0, column=0)[0]
b.config(text=model_name + " options")
def draw_emane_models(self, parent):
"""
create a combobox that has all the known emane models
:param parent: parent
:return: nothing
"""
# query for all the known model names
session_id = self.app.core.session_id
response = self.app.core.client.get_emane_models(session_id)
self.emane_models = [x.split("_")[1] for x in response.models]
# create combo box and its binding
f = tk.Frame(
parent,
bg="#d9d9d9",
highlightbackground="#b3b3b3",
highlightcolor="#b3b3b3",
highlightthickness=0.5,
bd=0,
)
self.emane_model_combobox = ttk.Combobox(
f, values=self.emane_models, state="readonly"
)
self.emane_model_combobox.grid()
self.emane_model_combobox.current(0)
self.emane_model_combobox.bind("<<ComboboxSelected>>", self.combobox_select)
f.grid(row=3, column=0, sticky=tk.W + tk.E)
def draw_text_label_and_entry(self, parent, label_text, entry_text):
"""
draw a label and an entry on a single row
:return: nothing
"""
var = tk.StringVar()
var.set(entry_text)
f = tk.Frame(parent)
lbl = tk.Label(f, text=label_text)
lbl.grid(row=0, column=0)
e = tk.Entry(f, textvariable=var, bg="white")
e.grid(row=0, column=1)
f.grid(stick=tk.W, padx=2, pady=2)
def emane_configuration(self):
"""
draw the main frame for emane configuration
:return: nothing
"""
# draw label
lbl = tk.Label(self, text="Emane")
lbl.grid(row=1, column=0)
# main frame that has emane wiki, a short description, emane models and the configure buttons
f = tk.Frame(
self,
bg="#d9d9d9",
highlightbackground="#b3b3b3",
highlightcolor="#b3b3b3",
highlightthickness=0.5,
bd=0,
relief=tk.RAISED,
)
f.columnconfigure(0, weight=1)
b = tk.Button(
f,
image=Images.get(ImageEnum.EDITNODE),
text="EMANE Wiki",
compound=tk.RIGHT,
relief=tk.RAISED,
bg="#d9d9d9",
command=lambda: webbrowser.open_new(
"https://github.com/adjacentlink/emane/wiki"
),
)
b.grid(row=0, column=0, sticky=tk.W)
lbl = tk.Label(
f,
text="The EMANE emulation system provides more complex wireless radio emulation "
"\nusing pluggable MAC and PHY modules. Refer to the wiki for configuration option details",
bg="#d9d9d9",
)
lbl.grid(row=1, column=0, sticky="nsew")
lbl = tk.Label(f, text="EMANE Models", bg="#d9d9d9")
lbl.grid(row=2, column=0, sticky=tk.W)
self.draw_emane_models(f)
self.draw_option_buttons(f)
f.grid(row=2, column=0, sticky="nsew")
def draw_ip_subnets(self):
self.draw_text_label_and_entry(self, "IPv4 subnet", "")
self.draw_text_label_and_entry(self, "IPv6 subnet", "")
def emane_options(self):
"""
create wireless node options
:return:
"""
f = tk.Frame(self, bg="#d9d9d9")
f.columnconfigure(0, weight=1)
f.columnconfigure(1, weight=1)
b = tk.Button(f, text="Link to all routers", bg="#d9d9d9")
b.grid(row=0, column=0, padx=10, pady=2, sticky="nsew")
b = tk.Button(f, text="Choose WLAN members", bg="#d9d9d9")
b.grid(row=0, column=1, padx=10, pady=2, sticky="nsew")
f.grid(row=5, column=0, sticky="nsew")
def apply(self):
# save emane configuration
self.app.core.emane_config = self.options
self.destroy()
def draw_apply_and_cancel(self):
f = tk.Frame(self, bg="#d9d9d9")
f.columnconfigure(0, weight=1)
f.columnconfigure(1, weight=1)
b = tk.Button(f, text="Apply", bg="#d9d9d9", command=self.apply)
b.grid(row=0, column=0, padx=10, pady=2, sticky="nsew")
b = tk.Button(f, text="Cancel", bg="#d9d9d9", command=self.destroy)
b.grid(row=0, column=1, padx=10, pady=2, sticky="nsew")
f.grid(sticky="nsew")

View file

@ -0,0 +1,238 @@
"""
mobility configuration
"""
import os
import tkinter as tk
from pathlib import Path
from tkinter import filedialog
from coretk.dialogs.dialog import Dialog
class MobilityConfiguration(Dialog):
def __init__(self, master, app, canvas_node):
"""
create an instance of mobility configuration
:param app: core application
:param root.master master:
"""
super().__init__(master, app, "ns2script configuration", modal=True)
self.canvas_node = canvas_node
print(app.canvas.core.mobilityconfig_management.configurations)
self.node_config = app.canvas.core.mobilityconfig_management.configurations[
canvas_node.core_id
]
self.mobility_script_parameters()
self.ns2script_options()
self.loop = "On"
def create_string_var(self, val):
"""
create string variable for entry widget
:return: nothing
"""
var = tk.StringVar()
var.set(val)
return var
def open_file(self, entry):
configs_dir = os.path.join(Path.home(), ".core/configs")
if os.path.isdir(configs_dir):
filename = filedialog.askopenfilename(initialdir=configs_dir, title="Open")
if filename:
entry.delete(0, tk.END)
entry.insert(0, filename)
def set_loop_value(self, value):
"""
set loop value when user changes the option
:param value:
:return:
"""
self.loop = value
def create_label_entry_filebrowser(
self, parent_frame, text_label, entry_text, filebrowser=False
):
f = tk.Frame(parent_frame, bg="#d9d9d9")
lbl = tk.Label(f, text=text_label, bg="#d9d9d9")
lbl.grid(padx=3, pady=3)
# f.grid()
e = tk.Entry(f, textvariable=self.create_string_var(entry_text), bg="#ffffff")
e.grid(row=0, column=1, padx=3, pady=3)
if filebrowser:
b = tk.Button(f, text="...", command=lambda: self.open_file(e))
b.grid(row=0, column=2, padx=3, pady=3)
f.grid(sticky=tk.E)
def mobility_script_parameters(self):
lbl = tk.Label(self, text="node ns2script")
lbl.grid(sticky=tk.W + tk.E)
sb = tk.Scrollbar(self, orient=tk.VERTICAL)
sb.grid(row=1, column=1, sticky=tk.N + tk.S + tk.E)
f = tk.Frame(self, bg="#d9d9d9")
lbl = tk.Label(
f, text="ns-2 Mobility Scripts Parameters", bg="#d9d9d9", relief=tk.RAISED
)
lbl.grid(row=0, column=0, sticky=tk.W)
f1 = tk.Canvas(
f,
yscrollcommand=sb.set,
bg="#d9d9d9",
relief=tk.RAISED,
highlightbackground="#b3b3b3",
highlightcolor="#b3b3b3",
highlightthickness=0.5,
bd=0,
)
self.create_label_entry_filebrowser(
f1, "mobility script file", self.node_config["file"], filebrowser=True
)
self.create_label_entry_filebrowser(
f1, "Refresh time (ms)", self.node_config["refresh_ms"]
)
# f12 = tk.Frame(f1)
#
# lbl = tk.Label(f12, text="Refresh time (ms)")
# lbl.grid()
#
# e = tk.Entry(f12, textvariable=self.create_string_var("50"))
# e.grid(row=0, column=1)
# f12.grid()
f13 = tk.Frame(f1)
lbl = tk.Label(f13, text="loop")
lbl.grid()
om = tk.OptionMenu(
f13, self.create_string_var("On"), "On", "Off", command=self.set_loop_value
)
om.grid(row=0, column=1)
f13.grid(sticky=tk.E)
self.create_label_entry_filebrowser(
f1, "auto-start seconds (0.0 for runtime)", self.node_config["autostart"]
)
# f14 = tk.Frame(f1)
#
# lbl = tk.Label(f14, text="auto-start seconds (0.0 for runtime)")
# lbl.grid()
#
# e = tk.Entry(f14, textvariable=self.create_string_var(""))
# e.grid(row=0, column=1)
#
# f14.grid()
self.create_label_entry_filebrowser(
f1, "node mapping (optional, e.g. 0:1, 1:2, 2:3)", self.node_config["map"]
)
# f15 = tk.Frame(f1)
#
# lbl = tk.Label(f15, text="node mapping (optional, e.g. 0:1, 1:2, 2:3)")
# lbl.grid()
#
# e = tk.Entry(f15, textvariable=self.create_string_var(""))
# e.grid(row=0, column=1)
#
# f15.grid()
self.create_label_entry_filebrowser(
f1,
"script file to run upon start",
self.node_config["script_start"],
filebrowser=True,
)
self.create_label_entry_filebrowser(
f1,
"script file to run upon pause",
self.node_config["script_pause"],
filebrowser=True,
)
self.create_label_entry_filebrowser(
f1,
"script file to run upon stop",
self.node_config["script_stop"],
filebrowser=True,
)
f1.grid()
sb.config(command=f1.yview)
f.grid(row=1, column=0)
def ns2script_apply(self):
"""
:return:
"""
config_frame = self.grid_slaves(row=1, column=0)[0]
canvas = config_frame.grid_slaves(row=1, column=0)[0]
file = (
canvas.grid_slaves(row=0, column=0)[0].grid_slaves(row=0, column=1)[0].get()
)
refresh_time = (
canvas.grid_slaves(row=1, column=0)[0].grid_slaves(row=0, column=1)[0].get()
)
auto_start_seconds = (
canvas.grid_slaves(row=3, column=0)[0].grid_slaves(row=0, column=1)[0].get()
)
node_mapping = (
canvas.grid_slaves(row=4, column=0)[0].grid_slaves(row=0, column=1)[0].get()
)
file_upon_start = (
canvas.grid_slaves(row=5, column=0)[0].grid_slaves(row=0, column=1)[0].get()
)
file_upon_pause = (
canvas.grid_slaves(row=6, column=0)[0].grid_slaves(row=0, column=1)[0].get()
)
file_upon_stop = (
canvas.grid_slaves(row=7, column=0)[0].grid_slaves(row=0, column=1)[0].get()
)
# print("mobility script file: ", file)
# print("refresh time: ", refresh_time)
# print("auto start seconds: ", auto_start_seconds)
# print("node mapping: ", node_mapping)
# print("script file to run upon start: ", file_upon_start)
# print("file upon pause: ", file_upon_pause)
# print("file upon stop: ", file_upon_stop)
if self.loop == "On":
loop = "1"
else:
loop = "0"
self.app.canvas.core.mobilityconfig_management.set_custom_configuration(
node_id=self.canvas_node.core_id,
file=file,
refresh_ms=refresh_time,
loop=loop,
autostart=auto_start_seconds,
node_mapping=node_mapping,
script_start=file_upon_start,
script_pause=file_upon_pause,
script_stop=file_upon_stop,
)
self.destroy()
def ns2script_options(self):
"""
create the options for ns2script configuration
:return: nothing
"""
f = tk.Frame(self)
b = tk.Button(f, text="Apply", command=self.ns2script_apply)
b.grid()
b = tk.Button(f, text="Cancel", command=self.destroy)
b.grid(row=0, column=1)
f.grid()

View file

@ -22,6 +22,7 @@ class WlanConfigDialog(Dialog):
self.image = canvas_node.image self.image = canvas_node.image
self.canvas_node = canvas_node self.canvas_node = canvas_node
self.config = config self.config = config
self.name = tk.StringVar(value=canvas_node.name) self.name = tk.StringVar(value=canvas_node.name)
self.range_var = tk.StringVar(value=config["basic_range"]) self.range_var = tk.StringVar(value=config["basic_range"])
self.bandwidth_var = tk.StringVar(value=config["bandwidth"]) self.bandwidth_var = tk.StringVar(value=config["bandwidth"])
@ -111,6 +112,7 @@ class WlanConfigDialog(Dialog):
:return: nothing :return: nothing
""" """
frame = tk.Frame(self) frame = tk.Frame(self)
frame.grid(pady=3, sticky="ew") frame.grid(pady=3, sticky="ew")
frame.columnconfigure(1, weight=1) frame.columnconfigure(1, weight=1)
@ -132,6 +134,7 @@ class WlanConfigDialog(Dialog):
:return: :return:
""" """
frame = tk.Frame(self) frame = tk.Frame(self)
frame.grid(pady=2, sticky="ew") frame.grid(pady=2, sticky="ew")
for i in range(3): for i in range(3):
@ -183,6 +186,7 @@ class WlanConfigDialog(Dialog):
jitter = self.jitter_var.get() jitter = self.jitter_var.get()
# set wireless node configuration here # set wireless node configuration here
wlanconfig_manager = self.app.core.wlanconfig_management wlanconfig_manager = self.app.core.wlanconfig_management
wlanconfig_manager.set_custom_config( wlanconfig_manager.set_custom_config(
node_id=self.canvas_node.core_id, node_id=self.canvas_node.core_id,

View file

@ -84,11 +84,13 @@ class CanvasGraph(tk.Canvas):
self.draw_node_name = None self.draw_node_name = None
self.selected = None self.selected = None
self.node_context = None self.node_context = None
self.nodes = {} self.nodes.clear()
self.edges = {} self.edges.clear()
self.drawing_edge = None self.drawing_edge = None
self.draw_existing_component(session) self.draw_existing_component(session)
# self.grpc_manager.wlanconfig_management.load_wlan_configurations(self.core_grpc)
def setup_bindings(self): def setup_bindings(self):
""" """
Bind any mouse events or hot keys to the matching action Bind any mouse events or hot keys to the matching action
@ -221,12 +223,6 @@ class CanvasGraph(tk.Canvas):
for i in self.find_withtag("node"): for i in self.find_withtag("node"):
self.lift(i) 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): def canvas_xy(self, event):
""" """
Convert window coordinate to canvas coordinate Convert window coordinate to canvas coordinate

View file

@ -0,0 +1,71 @@
"""
mobility configurations for all the nodes
"""
import logging
from collections import OrderedDict
from core.api.grpc import core_pb2
class MobilityNodeConfig:
def __init__(self):
self.configurations = {}
def set_default_configuration(self, node_type, node_id):
"""
set default mobility configuration for a node
:param core_pb2.NodeType node_type: protobuf node type
:param int node_id: node id
:return: nothing
"""
if node_type == core_pb2.NodeType.WIRELESS_LAN:
config = OrderedDict()
config["autostart"] = ""
config["file"] = ""
config["loop"] = "1"
config["map"] = ""
config["refresh_ms"] = "50"
config["script_pause"] = ""
config["script_start"] = ""
config["script_stop"] = ""
self.configurations[node_id] = config
def set_custom_configuration(
self,
node_id,
file,
refresh_ms,
loop,
autostart,
node_mapping,
script_start,
script_pause,
script_stop,
):
"""
set custom mobility configuration for a node
:param int node_id: node id
:param str file: path to mobility script file
:param str refresh_ms: refresh time
:param str loop: loop option
:param str autostart: auto-start seconds value
:param str node_mapping: node mapping
:param str script_start: path to script to run upon start
:param str script_pause: path to script to run upon pause
:param str script_stop: path to script to run upon stop
:return: nothing
"""
if node_id in self.configurations:
self.configurations[node_id]["autostart"] = autostart
self.configurations[node_id]["file"] = file
self.configurations[node_id]["loop"] = loop
self.configurations[node_id]["map"] = node_mapping
self.configurations[node_id]["refresh_ms"] = refresh_ms
self.configurations[node_id]["script_pause"] = script_pause
self.configurations[node_id]["script_start"] = script_start
self.configurations[node_id]["script_stop"] = script_stop
else:
logging.error("mobilitynodeconfig.py invalid node_id")

Binary file not shown.

Before

Width:  |  Height:  |  Size: 744 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 635 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 719 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 744 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 86 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 375 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 174 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 265 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 160 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 755 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 753 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 324 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 925 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 127 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 799 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 220 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 146 B

View file

@ -14,7 +14,7 @@ class WlanNodeConfig:
def set_default_config(self, node_type, node_id): def set_default_config(self, node_type, node_id):
if node_type == core_pb2.NodeType.WIRELESS_LAN: if node_type == core_pb2.NodeType.WIRELESS_LAN:
config = OrderedDict() config = OrderedDict()
config["basic_range"] = "275" config["range"] = "275"
config["bandwidth"] = "54000000" config["bandwidth"] = "54000000"
config["jitter"] = "0" config["jitter"] = "0"
config["delay"] = "20000" config["delay"] = "20000"
@ -22,8 +22,16 @@ class WlanNodeConfig:
self.configurations[node_id] = config self.configurations[node_id] = config
def set_custom_config(self, node_id, range, bandwidth, jitter, delay, error): def set_custom_config(self, node_id, range, bandwidth, jitter, delay, error):
self.configurations[node_id]["basic_range"] = range self.configurations[node_id]["range"] = range
self.configurations[node_id]["bandwidth"] = bandwidth self.configurations[node_id]["bandwidth"] = bandwidth
self.configurations[node_id]["jitter"] = jitter self.configurations[node_id]["jitter"] = jitter
self.configurations[node_id]["delay"] = delay self.configurations[node_id]["delay"] = delay
self.configurations[node_id]["error"] = error self.configurations[node_id]["error"] = error
def delete_node_config(self, node_id):
"""
not implemented
:param node_id:
:return:
"""
return

View file

@ -14,7 +14,7 @@
} }
}, },
"root": { "root": {
"level": "INFO", "level": "DEBUG",
"handlers": ["console"] "handlers": ["console"]
} }
} }