This commit is contained in:
Huy Pham 2019-11-27 14:04:49 -08:00
commit 1a05571e50
71 changed files with 72 additions and 194 deletions

View file

@ -18,9 +18,10 @@ XML_PATH = HOME_PATH.joinpath("xml")
CONFIG_PATH = HOME_PATH.joinpath("gui.yaml")
# local paths
LOCAL_ICONS_PATH = Path(__file__).parent.joinpath("icons").absolute()
LOCAL_BACKGROUND_PATH = Path(__file__).parent.joinpath("backgrounds").absolute()
LOCAL_XMLS_PATH = Path(__file__).parent.joinpath("xmls").absolute()
DATA_PATH = Path(__file__).parent.joinpath("data")
LOCAL_ICONS_PATH = DATA_PATH.joinpath("icons").absolute()
LOCAL_BACKGROUND_PATH = DATA_PATH.joinpath("backgrounds").absolute()
LOCAL_XMLS_PATH = DATA_PATH.joinpath("xmls").absolute()
# configuration data
TERMINALS = [

View file

@ -141,15 +141,19 @@ class CoreClient:
else:
logging.warning("unknown session event: %s", session_event)
elif event.HasField("node_event"):
node_event = event.node_event
node_id = node_event.node.id
x = node_event.node.position.x
y = node_event.node.position.y
canvas_node = self.canvas_nodes[node_id]
canvas_node.move(x, y)
self.handle_node_event(event.node_event)
else:
logging.info("unhandled event: %s", event)
def handle_node_event(self, event):
if event.source == "gui":
return
node_id = event.node.id
x = event.node.position.x
y = event.node.position.y
canvas_node = self.canvas_nodes[node_id]
canvas_node.move(x, y)
def handle_throughputs(self, event):
interface_throughputs = event.interface_throughputs
for i in interface_throughputs:
@ -164,9 +168,6 @@ class CoreClient:
)
def join_session(self, session_id, query_location=True):
# self.master.config(cursor="watch")
# self.master.update()
# update session and title
self.session_id = session_id
self.master.title(f"CORE Session({self.session_id})")
@ -253,7 +254,6 @@ class CoreClient:
self.app.toolbar.runtime_frame.tkraise()
else:
self.app.toolbar.design_frame.tkraise()
# self.master.config(cursor="")
self.app.statusbar.progress_bar.stop()
def is_runtime(self):
@ -321,8 +321,7 @@ class CoreClient:
def edit_node(self, node_id, x, y):
position = core_pb2.Position(x=x, y=y)
response = self.client.edit_node(self.session_id, node_id, position)
logging.info("updated node id %s: %s", node_id, response)
self.client.edit_node(self.session_id, node_id, position, source="gui")
def start_session(self):
nodes = [x.core_node for x in self.canvas_nodes.values()]

View file

Before

Width:  |  Height:  |  Size: 312 KiB

After

Width:  |  Height:  |  Size: 312 KiB

View file

Before

Width:  |  Height:  |  Size: 196 KiB

After

Width:  |  Height:  |  Size: 196 KiB

View file

Before

Width:  |  Height:  |  Size: 744 B

After

Width:  |  Height:  |  Size: 744 B

View file

Before

Width:  |  Height:  |  Size: 230 B

After

Width:  |  Height:  |  Size: 230 B

View file

Before

Width:  |  Height:  |  Size: 2.9 KiB

After

Width:  |  Height:  |  Size: 2.9 KiB

View file

Before

Width:  |  Height:  |  Size: 2 KiB

After

Width:  |  Height:  |  Size: 2 KiB

View file

Before

Width:  |  Height:  |  Size: 1 KiB

After

Width:  |  Height:  |  Size: 1 KiB

View file

Before

Width:  |  Height:  |  Size: 635 B

After

Width:  |  Height:  |  Size: 635 B

View file

Before

Width:  |  Height:  |  Size: 1 KiB

After

Width:  |  Height:  |  Size: 1 KiB

View file

Before

Width:  |  Height:  |  Size: 1,006 B

After

Width:  |  Height:  |  Size: 1,006 B

View file

Before

Width:  |  Height:  |  Size: 3 KiB

After

Width:  |  Height:  |  Size: 3 KiB

View file

Before

Width:  |  Height:  |  Size: 3.3 KiB

After

Width:  |  Height:  |  Size: 3.3 KiB

View file

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

View file

Before

Width:  |  Height:  |  Size: 642 B

After

Width:  |  Height:  |  Size: 642 B

View file

Before

Width:  |  Height:  |  Size: 2.2 KiB

After

Width:  |  Height:  |  Size: 2.2 KiB

View file

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

View file

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 1.7 KiB

View file

Before

Width:  |  Height:  |  Size: 2.1 KiB

After

Width:  |  Height:  |  Size: 2.1 KiB

View file

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 1.2 KiB

View file

Before

Width:  |  Height:  |  Size: 2.7 KiB

After

Width:  |  Height:  |  Size: 2.7 KiB

View file

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

View file

Before

Width:  |  Height:  |  Size: 2.4 KiB

After

Width:  |  Height:  |  Size: 2.4 KiB

View file

Before

Width:  |  Height:  |  Size: 2.3 KiB

After

Width:  |  Height:  |  Size: 2.3 KiB

View file

Before

Width:  |  Height:  |  Size: 828 B

After

Width:  |  Height:  |  Size: 828 B

View file

Before

Width:  |  Height:  |  Size: 265 B

After

Width:  |  Height:  |  Size: 265 B

View file

Before

Width:  |  Height:  |  Size: 2.5 KiB

After

Width:  |  Height:  |  Size: 2.5 KiB

View file

Before

Width:  |  Height:  |  Size: 259 B

After

Width:  |  Height:  |  Size: 259 B

View file

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

View file

Before

Width:  |  Height:  |  Size: 2 KiB

After

Width:  |  Height:  |  Size: 2 KiB

View file

Before

Width:  |  Height:  |  Size: 1.8 KiB

After

Width:  |  Height:  |  Size: 1.8 KiB

View file

Before

Width:  |  Height:  |  Size: 1 KiB

After

Width:  |  Height:  |  Size: 1 KiB

View file

Before

Width:  |  Height:  |  Size: 2.9 KiB

After

Width:  |  Height:  |  Size: 2.9 KiB

View file

Before

Width:  |  Height:  |  Size: 2.3 KiB

After

Width:  |  Height:  |  Size: 2.3 KiB

View file

Before

Width:  |  Height:  |  Size: 314 B

After

Width:  |  Height:  |  Size: 314 B

View file

Before

Width:  |  Height:  |  Size: 799 B

After

Width:  |  Height:  |  Size: 799 B

View file

Before

Width:  |  Height:  |  Size: 2.4 KiB

After

Width:  |  Height:  |  Size: 2.4 KiB

View file

Before

Width:  |  Height:  |  Size: 3.4 KiB

After

Width:  |  Height:  |  Size: 3.4 KiB

View file

Before

Width:  |  Height:  |  Size: 719 B

After

Width:  |  Height:  |  Size: 719 B

View file

Before

Width:  |  Height:  |  Size: 337 B

After

Width:  |  Height:  |  Size: 337 B

View file

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 1.2 KiB

View file

Before

Width:  |  Height:  |  Size: 719 B

After

Width:  |  Height:  |  Size: 719 B

View file

Before

Width:  |  Height:  |  Size: 744 B

After

Width:  |  Height:  |  Size: 744 B

View file

Before

Width:  |  Height:  |  Size: 86 B

After

Width:  |  Height:  |  Size: 86 B

View file

Before

Width:  |  Height:  |  Size: 724 B

After

Width:  |  Height:  |  Size: 724 B

View file

Before

Width:  |  Height:  |  Size: 375 B

After

Width:  |  Height:  |  Size: 375 B

View file

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 1.2 KiB

View file

Before

Width:  |  Height:  |  Size: 174 B

After

Width:  |  Height:  |  Size: 174 B

View file

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 1.3 KiB

View file

Before

Width:  |  Height:  |  Size: 160 B

After

Width:  |  Height:  |  Size: 160 B

View file

Before

Width:  |  Height:  |  Size: 755 B

After

Width:  |  Height:  |  Size: 755 B

View file

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

View file

Before

Width:  |  Height:  |  Size: 753 B

After

Width:  |  Height:  |  Size: 753 B

View file

Before

Width:  |  Height:  |  Size: 324 B

After

Width:  |  Height:  |  Size: 324 B

View file

Before

Width:  |  Height:  |  Size: 925 B

After

Width:  |  Height:  |  Size: 925 B

View file

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

View file

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 1.2 KiB

View file

Before

Width:  |  Height:  |  Size: 127 B

After

Width:  |  Height:  |  Size: 127 B

View file

Before

Width:  |  Height:  |  Size: 220 B

After

Width:  |  Height:  |  Size: 220 B

View file

Before

Width:  |  Height:  |  Size: 173 B

After

Width:  |  Height:  |  Size: 173 B

View file

@ -85,9 +85,16 @@ class CanvasGraph(tk.Canvas):
context.add_command(
label="WLAN Config", command=canvas_node.show_wlan_config
)
context.add_command(
label="Mobility Config", command=canvas_node.show_mobility_config
)
if self.master.core.is_runtime():
if canvas_node.core_node.id in self.master.core.mobility_players:
context.add_command(
label="Mobility Player",
command=canvas_node.show_mobility_player,
)
else:
context.add_command(
label="Mobility Config", command=canvas_node.show_mobility_config
)
if node.type == NodeType.EMANE:
context.add_command(
label="EMANE Config", command=canvas_node.show_emane_config
@ -602,19 +609,20 @@ class CanvasNode:
old_y = self.core_node.position.y
x_offset = x - old_x
y_offset = y - old_y
self.core_node.position.x = x
self.core_node.position.y = y
for edge in self.edges:
x1, y1, x2, y2 = self.canvas.coords(edge.id)
if edge.src == self.id:
self.canvas.coords(edge.id, x_offset, y_offset, x2, y2)
else:
self.canvas.coords(edge.id, x1, y1, x_offset, y_offset)
edge.link_info.recalculate_info()
self.canvas.helper.update_wlan_connection(old_x, old_y, x, y, self.wlans)
self.core_node.position.x = int(x)
self.core_node.position.y = int(y)
self.canvas.move(self.id, x_offset, y_offset)
self.canvas.move(self.text_id, x_offset, y_offset)
self.antenna_draw.update_antennas_position(x_offset, y_offset)
self.canvas.canvas_management.node_drag(self, x_offset, y_offset)
for edge in self.edges:
x1, y1, x2, y2 = self.canvas.coords(edge.id)
if edge.src == self.id:
self.canvas.coords(edge.id, x, y, x2, y2)
else:
self.canvas.coords(edge.id, x1, y1, x, y)
edge.link_info.recalculate_info()
self.canvas.helper.update_wlan_connection(old_x, old_y, x, y, self.wlans)
def on_enter(self, event):
if self.app.core.is_runtime() and self.app.core.observer:
@ -654,32 +662,7 @@ class CanvasNode:
if self.canvas.mode == GraphMode.EDGE:
return
x, y = self.canvas.canvas_xy(event)
moving_x, moving_y = self.moving
offset_x, offset_y = x - moving_x, y - moving_y
self.moving = x, y
old_x, old_y = self.canvas.coords(self.id)
self.canvas.move(self.id, offset_x, offset_y)
self.canvas.move(self.text_id, offset_x, offset_y)
self.antenna_draw.update_antennas_position(offset_x, offset_y)
self.canvas.canvas_management.node_drag(self, offset_x, offset_y)
new_x, new_y = self.canvas.coords(self.id)
if self.canvas.core.is_runtime():
self.canvas.core.edit_node(self.core_node.id, int(new_x), int(new_y))
for edge in self.edges:
x1, y1, x2, y2 = self.canvas.coords(edge.id)
if x1 == old_x and y1 == old_y:
self.canvas.coords(edge.id, new_x, new_y, x2, y2)
else:
self.canvas.coords(edge.id, x1, y1, new_x, new_y)
edge.link_info.recalculate_info()
self.canvas.helper.update_wlan_connection(
old_x, old_y, new_x, new_y, self.wlans
)
self.move(x, y)
def select_multiple(self, event):
self.canvas.canvas_management.node_select(self, True)
@ -699,6 +682,9 @@ class CanvasNode:
dialog = MobilityConfigDialog(self.app, self.app, self)
dialog.show()
def show_mobility_player(self):
self.canvas.context = None
def show_emane_config(self):
self.canvas.context = None
dialog = EmaneConfigDialog(self.app, self.app, self)

View file

@ -35,7 +35,9 @@ class CanvasComponentManagement:
self.selected[canvas_node.id] = bbox_id
def node_drag(self, canvas_node, offset_x, offset_y):
self.canvas.move(self.selected[canvas_node.id], offset_x, offset_y)
select_id = self.selected.get(canvas_node.id)
if select_id is not None:
self.canvas.move(select_id, offset_x, offset_y)
def delete_current_bbox(self):
for bbid in self.selected.values():
@ -76,18 +78,17 @@ class CanvasComponentManagement:
if neighbor.core_node.type != core_pb2.NodeType.WIRELESS_LAN:
neighbor.antenna_draw.delete_antenna()
if canvas_node.core_node.id in node_to_wlink:
for link_tuple in node_to_wlink[canvas_node.core_node.id]:
nid_one, nid_two = link_tuple
if link_tuple in self.canvas.wireless_draw.map:
self.canvas.delete(self.canvas.wireless_draw.map[link_tuple])
link_cid = self.canvas.wireless_draw.map.pop(link_tuple, None)
canvas_node_one = self.app.canvas_nodes[nid_one]
canvas_node_two = self.app.canvas_nodes[nid_two]
if link_cid in canvas_node_one.wlans:
canvas_node_one.wlans.remove(link_cid)
if link_cid in canvas_node_two.wlans:
canvas_node_two.wlans.remove(link_cid)
for link_tuple in node_to_wlink.get(canvas_node.core_node.id, []):
nid_one, nid_two = link_tuple
if link_tuple in self.canvas.wireless_draw.map:
self.canvas.delete(self.canvas.wireless_draw.map[link_tuple])
link_cid = self.canvas.wireless_draw.map.pop(link_tuple, None)
canvas_node_one = self.app.canvas_nodes[nid_one]
canvas_node_two = self.app.canvas_nodes[nid_two]
if link_cid in canvas_node_one.wlans:
canvas_node_one.wlans.remove(link_cid)
if link_cid in canvas_node_two.wlans:
canvas_node_two.wlans.remove(link_cid)
for node_id in list(self.selected):
bbox_id = self.selected[node_id]

View file

@ -1,37 +0,0 @@
"""
service file configuration
"""
class ServiceFileConfig:
def __init__(self):
# dict(node_id:dict(service:dict(filename, data)))
self.configurations = {}
# def set_service_configs(self, node_id, service_name, file_configs):
# """
# store file configs
#
# :param int node_id: node id
# :param str service_name: service name
# :param dict(str, str) file_configs: map of service file to its data
# :return: nothing
# """
# for key, value in file_configs.items():
# self.configurations[node_id][service_name][key] = value
def set_custom_service_file_config(self, node_id, service_name, file_name, data):
"""
store file config
:param int node_id: node id
:param str service_name: service name
:param str file_name: file name
:param str data: data
:return: nothing
"""
if node_id not in self.configurations:
self.configurations[node_id] = {}
if service_name not in self.configurations[node_id]:
self.configurations[node_id][service_name] = {}
self.configurations[node_id][service_name][file_name] = data

View file

@ -1,85 +0,0 @@
"""
service node configuration
"""
import logging
from tkinter import messagebox
import grpc
class ServiceNodeConfig:
def __init__(self, app):
self.app = app
# dict(node_id:dict(service:node_service_config_proto))
# maps node to all of its service configuration
self.configurations = {}
# dict(node_id:set(str))
# maps node to current configurations
self.current_services = {}
self.default_services = {}
# todo rewrite, no need self.default services
def node_default_services_configuration(self, node_id, node_model):
"""
set the default configurations for the default services of a node
:param coretk.graph.CanvasNode canvas_node: canvas node object
:return: nothing
"""
session_id = self.app.core.session_id
client = self.app.core.client
if len(self.default_services) == 0:
response = client.get_service_defaults(session_id)
logging.info("session default services: %s", response)
for default in response.defaults:
self.default_services[default.node_type] = default.services
self.configurations[node_id] = {}
self.current_services[node_id] = set()
for default in self.default_services[node_model]:
response = client.get_node_service(session_id, node_id, default)
logging.info(
"servicenodeconfig.py get node service (%s), result: %s",
node_id,
response,
)
self.configurations[node_id][default] = response.service
self.current_services[node_id].add(default)
def node_new_service_configuration(self, node_id, service_name):
"""
store node's configuration if a new service is added from the GUI
:param int node_id: node id
:param str service_name: service name
:return: nothing
"""
try:
config = self.app.core.get_node_service(node_id, service_name)
except grpc.RpcError:
messagebox.showerror("Service problem", "Service not found")
return False
if node_id not in self.configurations:
self.configurations[node_id] = {}
if node_id not in self.current_services:
self.current_services[node_id] = set()
if service_name not in self.configurations[node_id]:
self.configurations[node_id][service_name] = config
self.current_services[node_id].add(service_name)
return True
def node_custom_service_configuration(self, node_id, service_name):
self.configurations[node_id][service_name] = self.app.core.get_node_service(
node_id, service_name
)
def node_service_custom_configuration(
self, node_id, service_name, startups, validates, shutdowns
):
self.app.core.set_node_service(
node_id, service_name, startups, validates, shutdowns
)
config = self.app.core.get_node_service(node_id, service_name)
self.configurations[node_id][service_name] = config

View file

@ -428,7 +428,7 @@ class CoreGrpcClient:
request = core_pb2.GetNodeRequest(session_id=session_id, node_id=node_id)
return self.stub.GetNode(request)
def edit_node(self, session_id, node_id, position, icon=None):
def edit_node(self, session_id, node_id, position, icon=None, source=None):
"""
Edit a node, currently only changes position.
@ -436,12 +436,17 @@ class CoreGrpcClient:
:param int node_id: node id
:param core_pb2.Position position: position to set node to
:param str icon: path to icon for gui to use for node
:param str source: application source editing node
:return: response with result of success or failure
:rtype: core_pb2.EditNodeResponse
:raises grpc.RpcError: when session or node doesn't exist
"""
request = core_pb2.EditNodeRequest(
session_id=session_id, node_id=node_id, position=position, icon=icon
session_id=session_id,
node_id=node_id,
position=position,
icon=icon,
source=source,
)
return self.stub.EditNode(request)

View file

@ -504,7 +504,7 @@ class CoreGrpcServer(core_pb2_grpc.CoreApiServicer):
position=position,
services=services,
)
return core_pb2.NodeEvent(node=node_proto)
return core_pb2.NodeEvent(node=node_proto, source=event.source)
def _handle_link_event(self, event):
"""
@ -800,7 +800,10 @@ class CoreGrpcServer(core_pb2_grpc.CoreApiServicer):
result = True
try:
session.edit_node(node.id, options)
node_data = node.data(0)
source = None
if request.source:
source = request.source
node_data = node.data(0, source=source)
session.broadcast_node(node_data)
except CoreError:
result = False

View file

@ -76,6 +76,7 @@ NodeData = collections.namedtuple(
"altitude",
"icon",
"opaque",
"source",
],
)
NodeData.__new__.__defaults__ = (None,) * len(NodeData._fields)

View file

@ -176,7 +176,7 @@ class NodeBase:
self.ifindex += 1
return ifindex
def data(self, message_type, lat=None, lon=None, alt=None):
def data(self, message_type, lat=None, lon=None, alt=None, source=None):
"""
Build a data object for this node.
@ -184,6 +184,7 @@ class NodeBase:
:param str lat: latitude
:param str lon: longitude
:param str alt: altitude
:param str source: source of node data
:return: node data object
:rtype: core.emulator.data.NodeData
"""
@ -217,6 +218,7 @@ class NodeBase:
model=model,
server=server,
services=services,
source=source,
)
return node_data

View file

@ -298,6 +298,7 @@ message Event {
message NodeEvent {
Node node = 1;
string source = 2;
}
message LinkEvent {
@ -378,6 +379,7 @@ message EditNodeRequest {
int32 node_id = 2;
Position position = 3;
string icon = 4;
string source = 5;
}
message EditNodeResponse {