Merge branch 'coretk' into coretk-config
This commit is contained in:
commit
a4055f84bd
8 changed files with 58 additions and 320 deletions
|
@ -8,7 +8,6 @@ from core.api.grpc import client, core_pb2
|
|||
from coretk.dialogs.sessions import SessionsDialog
|
||||
from coretk.emaneodelnodeconfig import EmaneModelNodeConfig
|
||||
from coretk.interface import InterfaceManager
|
||||
from coretk.mobilitynodeconfig import MobilityNodeConfig
|
||||
from coretk.nodeutils import NodeDraw, NodeUtils
|
||||
from coretk.servicefileconfig import ServiceFileConfig
|
||||
from coretk.servicenodeconfig import ServiceNodeConfig
|
||||
|
@ -70,7 +69,7 @@ class CoreClient:
|
|||
self.preexisting = set()
|
||||
self.interfaces_manager = InterfaceManager()
|
||||
self.wlan_configs = {}
|
||||
self.mobilityconfig_management = MobilityNodeConfig()
|
||||
self.mobility_configs = {}
|
||||
self.emaneconfig_management = EmaneModelNodeConfig(app)
|
||||
self.emane_config = None
|
||||
self.serviceconfig_manager = ServiceNodeConfig(app)
|
||||
|
@ -136,7 +135,7 @@ class CoreClient:
|
|||
self.links.clear()
|
||||
self.hooks.clear()
|
||||
self.wlan_configs.clear()
|
||||
self.mobilityconfig_management.configurations.clear()
|
||||
self.mobility_configs.clear()
|
||||
self.emane_config = None
|
||||
|
||||
# get session data
|
||||
|
@ -164,8 +163,7 @@ class CoreClient:
|
|||
logging.debug("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
|
||||
self.mobility_configs[node_id] = node_config
|
||||
|
||||
# get emane config
|
||||
response = self.client.get_emane_config(self.session_id)
|
||||
|
@ -454,9 +452,6 @@ class CoreClient:
|
|||
image=image,
|
||||
)
|
||||
|
||||
# set default configuration for wireless node
|
||||
self.mobilityconfig_management.set_default_configuration(node_type, node_id)
|
||||
|
||||
# set default emane configuration for emane node
|
||||
if node_type == core_pb2.NodeType.EMANE:
|
||||
self.emaneconfig_management.set_default_config(node_id)
|
||||
|
@ -519,8 +514,8 @@ class CoreClient:
|
|||
|
||||
# delete any mobility configuration, wlan configuration
|
||||
for i in node_ids:
|
||||
if i in self.mobilityconfig_management.configurations:
|
||||
self.mobilityconfig_management.configurations.pop(i)
|
||||
if i in self.mobility_configs:
|
||||
del self.mobility_configs[i]
|
||||
if i in self.wlan_configs:
|
||||
del self.wlan_configs[i]
|
||||
|
||||
|
@ -615,11 +610,10 @@ class CoreClient:
|
|||
|
||||
def get_mobility_configs_proto(self):
|
||||
configs = []
|
||||
mobility_configs = self.mobilityconfig_management.configurations
|
||||
for node_id in mobility_configs:
|
||||
config = mobility_configs[node_id]
|
||||
config_proto = core_pb2.MobilityConfig(node_id=node_id, config=config)
|
||||
configs.append(config_proto)
|
||||
for node_id, config in self.mobility_configs.items():
|
||||
config = {x: config[x].value for x in config}
|
||||
mobility_config = core_pb2.MobilityConfig(node_id=node_id, config=config)
|
||||
configs.append(mobility_config)
|
||||
return configs
|
||||
|
||||
def get_emane_model_configs_proto(self):
|
||||
|
@ -676,5 +670,11 @@ class CoreClient:
|
|||
if not config:
|
||||
response = self.client.get_wlan_config(self.session_id, node_id)
|
||||
config = response.config
|
||||
self.wlan_configs[node_id] = config
|
||||
return config
|
||||
|
||||
def get_mobility_config(self, node_id):
|
||||
config = self.mobility_configs.get(node_id)
|
||||
if not config:
|
||||
response = self.client.get_mobility_config(self.session_id, node_id)
|
||||
config = response.config
|
||||
return config
|
||||
|
|
|
@ -1,236 +1,48 @@
|
|||
"""
|
||||
mobility configuration
|
||||
"""
|
||||
import logging
|
||||
import tkinter as tk
|
||||
from tkinter import filedialog, ttk
|
||||
from tkinter import ttk
|
||||
|
||||
from coretk import appconfig
|
||||
from coretk.dialogs.dialog import Dialog
|
||||
from coretk.widgets import ConfigFrame
|
||||
|
||||
PAD = 5
|
||||
|
||||
|
||||
class MobilityConfigDialog(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)
|
||||
super().__init__(
|
||||
master,
|
||||
app,
|
||||
f"{canvas_node.core_node.name} Mobility Configuration",
|
||||
modal=True,
|
||||
)
|
||||
self.canvas_node = canvas_node
|
||||
self.node = canvas_node.core_node
|
||||
logging.info(app.canvas.core.mobilityconfig_management.configurations)
|
||||
self.node_config = app.canvas.core.mobilityconfig_management.configurations[
|
||||
self.node.id
|
||||
]
|
||||
self.config_frame = None
|
||||
self.config = self.app.core.get_mobility_config(self.node.id)
|
||||
self.draw()
|
||||
|
||||
self.mobility_script_parameters()
|
||||
self.ns2script_options()
|
||||
self.loop = "On"
|
||||
def draw(self):
|
||||
self.top.columnconfigure(0, weight=1)
|
||||
self.config_frame = ConfigFrame(self.top, self.app, self.config, borderwidth=0)
|
||||
self.config_frame.draw_config()
|
||||
self.config_frame.grid(sticky="nsew", pady=PAD)
|
||||
self.draw_apply_buttons()
|
||||
|
||||
def create_string_var(self, val):
|
||||
"""
|
||||
create string variable for entry widget
|
||||
def draw_apply_buttons(self):
|
||||
frame = ttk.Frame(self.top)
|
||||
frame.grid(sticky="ew")
|
||||
for i in range(2):
|
||||
frame.columnconfigure(i, weight=1)
|
||||
|
||||
:return: nothing
|
||||
"""
|
||||
var = tk.StringVar()
|
||||
var.set(val)
|
||||
return var
|
||||
button = ttk.Button(frame, text="Apply", command=self.click_apply)
|
||||
button.grid(row=0, column=0, padx=PAD, sticky="ew")
|
||||
|
||||
def open_file(self, entry):
|
||||
filename = filedialog.askopenfilename(
|
||||
initialdir=str(appconfig.MOBILITY_PATH), 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 = ttk.Frame(parent_frame)
|
||||
lbl = ttk.Label(f, text=text_label)
|
||||
lbl.grid(padx=3, pady=3)
|
||||
# f.grid()
|
||||
e = ttk.Entry(f, textvariable=self.create_string_var(entry_text))
|
||||
e.grid(row=0, column=1, padx=3, pady=3)
|
||||
if filebrowser:
|
||||
b = ttk.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 = ttk.Label(self.top, text="node ns2script")
|
||||
lbl.grid(sticky="ew")
|
||||
|
||||
sb = ttk.Scrollbar(self.top, orient=tk.VERTICAL)
|
||||
sb.grid(row=1, column=1, sticky="ns")
|
||||
|
||||
f = ttk.Frame(self.top)
|
||||
lbl = ttk.Label(f, text="ns-2 Mobility Scripts Parameters")
|
||||
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 = ttk.Frame(f1)
|
||||
#
|
||||
# lbl = ttk.Label(f12, text="Refresh time (ms)")
|
||||
# lbl.grid()
|
||||
#
|
||||
# e = ttk.Entry(f12, textvariable=self.create_string_var("50"))
|
||||
# e.grid(row=0, column=1)
|
||||
# f12.grid()
|
||||
|
||||
f13 = ttk.Frame(f1)
|
||||
|
||||
lbl = ttk.Label(f13, text="loop")
|
||||
lbl.grid()
|
||||
|
||||
om = ttk.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 = ttk.Frame(f1)
|
||||
#
|
||||
# lbl = ttk.Label(f14, text="auto-start seconds (0.0 for runtime)")
|
||||
# lbl.grid()
|
||||
#
|
||||
# e = ttk.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 = ttk.Frame(f1)
|
||||
#
|
||||
# lbl = ttk.Label(f15, text="node mapping (optional, e.g. 0:1, 1:2, 2:3)")
|
||||
# lbl.grid()
|
||||
#
|
||||
# e = ttk.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.node.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,
|
||||
)
|
||||
button = ttk.Button(frame, text="Cancel", command=self.destroy)
|
||||
button.grid(row=0, column=1, sticky="ew")
|
||||
|
||||
def click_apply(self):
|
||||
self.config_frame.parse_config()
|
||||
self.app.core.mobility_configs[self.node.id] = self.config
|
||||
self.destroy()
|
||||
|
||||
def ns2script_options(self):
|
||||
"""
|
||||
create the options for ns2script configuration
|
||||
|
||||
:return: nothing
|
||||
"""
|
||||
f = ttk.Frame(self.top)
|
||||
b = ttk.Button(f, text="Apply", command=self.ns2script_apply)
|
||||
b.grid()
|
||||
b = ttk.Button(f, text="Cancel", command=self.destroy)
|
||||
b.grid(row=0, column=1)
|
||||
f.grid()
|
||||
|
|
|
@ -5,7 +5,6 @@ wlan configuration
|
|||
from tkinter import ttk
|
||||
|
||||
from coretk.dialogs.dialog import Dialog
|
||||
from coretk.dialogs.mobilityconfig import MobilityConfigDialog
|
||||
from coretk.widgets import ConfigFrame
|
||||
|
||||
PAD = 5
|
||||
|
@ -46,10 +45,6 @@ class WlanConfigDialog(Dialog):
|
|||
button = ttk.Button(frame, text="Cancel", command=self.destroy)
|
||||
button.grid(row=0, column=1, sticky="ew")
|
||||
|
||||
def click_mobility(self):
|
||||
dialog = MobilityConfigDialog(self, self.app, self.canvas_node)
|
||||
dialog.show()
|
||||
|
||||
def click_apply(self):
|
||||
"""
|
||||
retrieve user's wlan configuration and store the new configuration values
|
||||
|
|
|
@ -1,75 +0,0 @@
|
|||
"""
|
||||
mobility configurations for all the nodes
|
||||
"""
|
||||
|
||||
import logging
|
||||
from collections import OrderedDict
|
||||
|
||||
from core.api.grpc import core_pb2
|
||||
|
||||
|
||||
class MobilityNodeConfig:
|
||||
def __init__(self):
|
||||
"""
|
||||
create an instance of MobilityConfig object
|
||||
"""
|
||||
# dict that maps node id to mobility configuration
|
||||
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")
|
|
@ -30,6 +30,8 @@ def add_node_data(node_proto):
|
|||
options.opaque = node_proto.opaque
|
||||
options.image = node_proto.image
|
||||
options.services = node_proto.services
|
||||
if node_proto.emane:
|
||||
options.emane = node_proto.emane
|
||||
if node_proto.server:
|
||||
options.server = node_proto.server
|
||||
|
||||
|
|
|
@ -713,10 +713,6 @@ class CoreGrpcServer(core_pb2_grpc.CoreApiServicer):
|
|||
session = self.get_session(request.session_id, context)
|
||||
_type, _id, options = grpcutils.add_node_data(request.node)
|
||||
node = session.add_node(_type=_type, _id=_id, options=options)
|
||||
# configure emane if provided
|
||||
emane_model = request.node.emane
|
||||
if emane_model:
|
||||
session.emane.set_model_config(id, emane_model)
|
||||
return core_pb2.AddNodeResponse(node_id=node.id)
|
||||
|
||||
def GetNode(self, request, context):
|
||||
|
|
|
@ -89,6 +89,7 @@ class NodeOptions:
|
|||
self.emulation_id = None
|
||||
self.server = None
|
||||
self.image = image
|
||||
self.emane = None
|
||||
|
||||
def set_position(self, x, y):
|
||||
"""
|
||||
|
|
|
@ -30,7 +30,7 @@ from core.emulator.sessionconfig import SessionConfig
|
|||
from core.errors import CoreError
|
||||
from core.location.corelocation import CoreLocation
|
||||
from core.location.event import EventLoop
|
||||
from core.location.mobility import MobilityManager
|
||||
from core.location.mobility import BasicRangeModel, MobilityManager
|
||||
from core.nodes.base import CoreNetworkBase, CoreNode, CoreNodeBase
|
||||
from core.nodes.docker import DockerNode
|
||||
from core.nodes.ipaddress import MacAddress
|
||||
|
@ -703,6 +703,13 @@ class Session:
|
|||
logging.debug("set node type: %s", node.type)
|
||||
self.services.add_services(node, node.type, options.services)
|
||||
|
||||
# ensure default emane configuration
|
||||
if _type == NodeTypes.EMANE:
|
||||
self.emane.set_model_config(_id, node.emane)
|
||||
# set default wlan config if needed
|
||||
if _type == NodeTypes.WIRELESS_LAN:
|
||||
self.mobility.set_model_config(_id, BasicRangeModel.name)
|
||||
|
||||
# boot nodes after runtime, CoreNodes, Physical, and RJ45 are all nodes
|
||||
is_boot_node = isinstance(node, CoreNodeBase) and not isinstance(node, Rj45Node)
|
||||
if self.state == EventTypes.RUNTIME_STATE.value and is_boot_node:
|
||||
|
|
Loading…
Add table
Reference in a new issue