fix code based on the new changes
This commit is contained in:
commit
7f2a2f8043
15 changed files with 278 additions and 724 deletions
|
@ -6,13 +6,6 @@ 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
|
||||||
|
|
||||||
# TODO, finish classifying node types
|
|
||||||
NODE_TO_TYPE = {
|
|
||||||
"router": core_pb2.NodeType.DEFAULT,
|
|
||||||
"wlan": core_pb2.NodeType.WIRELESS_LAN,
|
|
||||||
"emane": core_pb2.NodeType.EMANE,
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
class CanvasAction:
|
class CanvasAction:
|
||||||
def __init__(self, master, canvas):
|
def __init__(self, master, canvas):
|
||||||
|
@ -21,13 +14,13 @@ class CanvasAction:
|
||||||
self.node_to_show_config = None
|
self.node_to_show_config = None
|
||||||
|
|
||||||
def display_configuration(self, canvas_node):
|
def display_configuration(self, canvas_node):
|
||||||
pb_type = NODE_TO_TYPE[canvas_node.node_type]
|
node_type = canvas_node.core_node.type
|
||||||
self.node_to_show_config = canvas_node
|
self.node_to_show_config = canvas_node
|
||||||
if pb_type == core_pb2.NodeType.DEFAULT:
|
if node_type == core_pb2.NodeType.DEFAULT:
|
||||||
self.display_node_configuration()
|
self.display_node_configuration()
|
||||||
elif pb_type == core_pb2.NodeType.WIRELESS_LAN:
|
elif node_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:
|
elif node_type == core_pb2.NodeType.EMANE:
|
||||||
self.display_emane_configuration()
|
self.display_emane_configuration()
|
||||||
|
|
||||||
def display_node_configuration(self):
|
def display_node_configuration(self):
|
||||||
|
@ -36,8 +29,6 @@ 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)
|
|
||||||
wlan_config = self.master.core.wlanconfig_management.configurations[
|
wlan_config = self.master.core.wlanconfig_management.configurations[
|
||||||
canvas_node.core_id
|
canvas_node.core_id
|
||||||
]
|
]
|
||||||
|
|
|
@ -5,11 +5,10 @@ import logging
|
||||||
import os
|
import os
|
||||||
|
|
||||||
from core.api.grpc import client, core_pb2
|
from core.api.grpc import client, core_pb2
|
||||||
from coretk.coretocanvas import CoreToCanvasMapping
|
|
||||||
from coretk.dialogs.sessions import SessionsDialog
|
from coretk.dialogs.sessions import SessionsDialog
|
||||||
from coretk.emaneodelnodeconfig import EmaneModelNodeConfig
|
from coretk.emaneodelnodeconfig import EmaneModelNodeConfig
|
||||||
from coretk.images import NODE_WIDTH, Images
|
from coretk.images import NODE_WIDTH, Images
|
||||||
from coretk.interface import Interface, InterfaceManager
|
from coretk.interface import InterfaceManager
|
||||||
from coretk.mobilitynodeconfig import MobilityNodeConfig
|
from coretk.mobilitynodeconfig import MobilityNodeConfig
|
||||||
from coretk.servicefileconfig import ServiceFileConfig
|
from coretk.servicefileconfig import ServiceFileConfig
|
||||||
from coretk.servicenodeconfig import ServiceNodeConfig
|
from coretk.servicenodeconfig import ServiceNodeConfig
|
||||||
|
@ -30,47 +29,6 @@ OBSERVERS = {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class Node:
|
|
||||||
def __init__(self, session_id, node_id, node_type, model, x, y, name):
|
|
||||||
"""
|
|
||||||
Create an instance of a node
|
|
||||||
|
|
||||||
:param int session_id: session id
|
|
||||||
:param int node_id: node id
|
|
||||||
:param core_pb2.NodeType node_type: node type
|
|
||||||
:param int x: x coordinate
|
|
||||||
:param int y: coordinate
|
|
||||||
:param str name: node name
|
|
||||||
"""
|
|
||||||
self.session_id = session_id
|
|
||||||
self.node_id = node_id
|
|
||||||
self.type = node_type
|
|
||||||
self.x = x
|
|
||||||
self.y = y
|
|
||||||
self.model = model
|
|
||||||
self.name = name
|
|
||||||
self.interfaces = []
|
|
||||||
|
|
||||||
|
|
||||||
class Edge:
|
|
||||||
def __init__(self, session_id, node_id_1, node_type_1, node_id_2, node_type_2):
|
|
||||||
"""
|
|
||||||
Create an instance of an edge
|
|
||||||
:param int session_id: session id
|
|
||||||
:param int node_id_1: node 1 id
|
|
||||||
:param int node_type_1: node 1 type
|
|
||||||
:param core_pb2.NodeType node_id_2: node 2 id
|
|
||||||
:param core_pb2.NodeType node_type_2: node 2 type
|
|
||||||
"""
|
|
||||||
self.session_id = session_id
|
|
||||||
self.id1 = node_id_1
|
|
||||||
self.id2 = node_id_2
|
|
||||||
self.type1 = node_type_1
|
|
||||||
self.type2 = node_type_2
|
|
||||||
self.interface_1 = None
|
|
||||||
self.interface_2 = None
|
|
||||||
|
|
||||||
|
|
||||||
class CoreServer:
|
class CoreServer:
|
||||||
def __init__(self, name, address, port):
|
def __init__(self, name, address, port):
|
||||||
self.name = name
|
self.name = name
|
||||||
|
@ -113,15 +71,15 @@ class CoreClient:
|
||||||
self.read_config()
|
self.read_config()
|
||||||
|
|
||||||
# data for managing the current session
|
# data for managing the current session
|
||||||
|
self.canvas_nodes = {}
|
||||||
|
self.interface_to_edge = {}
|
||||||
self.state = None
|
self.state = None
|
||||||
self.nodes = {}
|
self.links = {}
|
||||||
self.edges = {}
|
|
||||||
self.hooks = {}
|
self.hooks = {}
|
||||||
self.id = 1
|
self.id = 1
|
||||||
self.reusable = []
|
self.reusable = []
|
||||||
self.preexisting = set()
|
self.preexisting = set()
|
||||||
self.interfaces_manager = InterfaceManager()
|
self.interfaces_manager = InterfaceManager()
|
||||||
self.core_mapping = CoreToCanvasMapping()
|
|
||||||
self.wlanconfig_management = WlanNodeConfig()
|
self.wlanconfig_management = WlanNodeConfig()
|
||||||
self.mobilityconfig_management = MobilityNodeConfig()
|
self.mobilityconfig_management = MobilityNodeConfig()
|
||||||
self.emaneconfig_management = EmaneModelNodeConfig(app)
|
self.emaneconfig_management = EmaneModelNodeConfig(app)
|
||||||
|
@ -183,8 +141,8 @@ class CoreClient:
|
||||||
# clear session data
|
# clear session data
|
||||||
self.reusable.clear()
|
self.reusable.clear()
|
||||||
self.preexisting.clear()
|
self.preexisting.clear()
|
||||||
self.nodes.clear()
|
self.canvas_nodes.clear()
|
||||||
self.edges.clear()
|
self.links.clear()
|
||||||
self.hooks.clear()
|
self.hooks.clear()
|
||||||
self.wlanconfig_management.configurations.clear()
|
self.wlanconfig_management.configurations.clear()
|
||||||
self.mobilityconfig_management.configurations.clear()
|
self.mobilityconfig_management.configurations.clear()
|
||||||
|
@ -207,14 +165,14 @@ class CoreClient:
|
||||||
for node in session.nodes:
|
for node in session.nodes:
|
||||||
if node.type == core_pb2.NodeType.WIRELESS_LAN:
|
if node.type == core_pb2.NodeType.WIRELESS_LAN:
|
||||||
response = self.client.get_wlan_config(self.session_id, node.id)
|
response = self.client.get_wlan_config(self.session_id, node.id)
|
||||||
logging.info("wlan config(%s): %s", node.id, response)
|
logging.debug("wlan config(%s): %s", node.id, response)
|
||||||
node_config = response.config
|
node_config = response.config
|
||||||
config = {x: node_config[x].value for x in node_config}
|
config = {x: node_config[x].value for x in node_config}
|
||||||
self.wlanconfig_management.configurations[node.id] = config
|
self.wlanconfig_management.configurations[node.id] = config
|
||||||
|
|
||||||
# get mobility configs
|
# get mobility configs
|
||||||
response = self.client.get_mobility_configs(self.session_id)
|
response = self.client.get_mobility_configs(self.session_id)
|
||||||
logging.info("mobility configs: %s", response)
|
logging.debug("mobility configs: %s", response)
|
||||||
for node_id in response.configs:
|
for node_id in response.configs:
|
||||||
node_config = response.configs[node_id].config
|
node_config = response.configs[node_id].config
|
||||||
config = {x: node_config[x].value for x in node_config}
|
config = {x: node_config[x].value for x in node_config}
|
||||||
|
@ -222,7 +180,7 @@ class CoreClient:
|
||||||
|
|
||||||
# get emane config
|
# get emane config
|
||||||
response = self.client.get_emane_config(self.session_id)
|
response = self.client.get_emane_config(self.session_id)
|
||||||
logging.info("emane config: %s", response)
|
logging.debug("emane config: %s", response)
|
||||||
self.emane_config = response.config
|
self.emane_config = response.config
|
||||||
|
|
||||||
# get emane model config
|
# get emane model config
|
||||||
|
@ -239,7 +197,7 @@ class CoreClient:
|
||||||
self.reusable.append(i)
|
self.reusable.append(i)
|
||||||
|
|
||||||
# draw session
|
# draw session
|
||||||
self.app.canvas.canvas_reset_and_redraw(session)
|
self.app.canvas.reset_and_redraw(session)
|
||||||
|
|
||||||
# draw tool bar appropritate with session state
|
# draw tool bar appropritate with session state
|
||||||
if self.is_runtime():
|
if self.is_runtime():
|
||||||
|
@ -343,8 +301,8 @@ class CoreClient:
|
||||||
logging.info("delete links %s", response)
|
logging.info("delete links %s", response)
|
||||||
|
|
||||||
def start_session(self):
|
def start_session(self):
|
||||||
nodes = self.get_nodes_proto()
|
nodes = [x.core_node for x in self.canvas_nodes.values()]
|
||||||
links = self.get_links_proto()
|
links = list(self.links.values())
|
||||||
wlan_configs = self.get_wlan_configs_proto()
|
wlan_configs = self.get_wlan_configs_proto()
|
||||||
mobility_configs = self.get_mobility_configs_proto()
|
mobility_configs = self.get_mobility_configs_proto()
|
||||||
emane_model_configs = self.get_emane_model_configs_proto()
|
emane_model_configs = self.get_emane_model_configs_proto()
|
||||||
|
@ -374,23 +332,6 @@ class CoreClient:
|
||||||
response = self.client.stop_session(session_id=self.session_id)
|
response = self.client.stop_session(session_id=self.session_id)
|
||||||
logging.debug("coregrpc.py Stop session, result: %s", response.result)
|
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
|
|
||||||
#
|
|
||||||
# :param int session_id: session id
|
|
||||||
# :param int id1: node 1 core id
|
|
||||||
# :param core_pb2.NodeType type1: node 1 core node type
|
|
||||||
# :param int id2: node 2 core id
|
|
||||||
# :param core_pb2.NodeType type2: node 2 core node type
|
|
||||||
# :return: nothing
|
|
||||||
# """
|
|
||||||
# if1 = self.create_interface(type1, edge.interface_1)
|
|
||||||
# if2 = self.create_interface(type2, edge.interface_2)
|
|
||||||
# response = self.client.add_link(self.session_id, id1, id2, if1, if2)
|
|
||||||
# logging.info("created link: %s", response)
|
|
||||||
|
|
||||||
def launch_terminal(self, node_id):
|
def launch_terminal(self, node_id):
|
||||||
response = self.client.get_node_terminal(self.session_id, node_id)
|
response = self.client.get_node_terminal(self.session_id, node_id)
|
||||||
logging.info("get terminal %s", response.terminal)
|
logging.info("get terminal %s", response.terminal)
|
||||||
|
@ -448,8 +389,10 @@ class CoreClient:
|
||||||
|
|
||||||
:return: nothing
|
:return: nothing
|
||||||
"""
|
"""
|
||||||
node_protos = self.get_nodes_proto()
|
|
||||||
link_protos = self.get_links_proto()
|
node_protos = [x.core_node for x in self.canvas_nodes.values()]
|
||||||
|
link_protos = list(self.links.values())
|
||||||
|
self.client.set_session_state(self.session_id, core_pb2.SessionState.DEFINITION)
|
||||||
for node_proto in node_protos:
|
for node_proto in node_protos:
|
||||||
if node_proto.id not in self.created_nodes:
|
if node_proto.id not in self.created_nodes:
|
||||||
response = self.client.add_node(self.session_id, node_proto)
|
response = self.client.add_node(self.session_id, node_proto)
|
||||||
|
@ -482,17 +425,6 @@ class CoreClient:
|
||||||
logging.debug("Close grpc")
|
logging.debug("Close grpc")
|
||||||
self.client.close()
|
self.client.close()
|
||||||
|
|
||||||
def peek_id(self):
|
|
||||||
"""
|
|
||||||
Peek the next id to be used
|
|
||||||
|
|
||||||
:return: nothing
|
|
||||||
"""
|
|
||||||
if len(self.reusable) == 0:
|
|
||||||
return self.id
|
|
||||||
else:
|
|
||||||
return self.reusable[0]
|
|
||||||
|
|
||||||
def get_id(self):
|
def get_id(self):
|
||||||
"""
|
"""
|
||||||
Get the next node id as well as update id status and reusable ids
|
Get the next node id as well as update id status and reusable ids
|
||||||
|
@ -510,106 +442,91 @@ class CoreClient:
|
||||||
def is_model_node(self, name):
|
def is_model_node(self, name):
|
||||||
return name in DEFAULT_NODES or name in self.custom_nodes
|
return name in DEFAULT_NODES or name in self.custom_nodes
|
||||||
|
|
||||||
def add_graph_node(self, session_id, canvas_id, x, y, name):
|
def create_node(self, x, y, node_type, model):
|
||||||
"""
|
"""
|
||||||
Add node, with information filled in, to grpc manager
|
Add node, with information filled in, to grpc manager
|
||||||
|
|
||||||
:param int session_id: session id
|
|
||||||
:param int canvas_id: node's canvas id
|
|
||||||
:param int x: x coord
|
:param int x: x coord
|
||||||
:param int y: y coord
|
:param int y: y coord
|
||||||
:param str name: node type
|
:param core_pb2.NodeType node_type: node type
|
||||||
|
:param str model: node model
|
||||||
:return: nothing
|
:return: nothing
|
||||||
"""
|
"""
|
||||||
node_type = None
|
node_id = self.get_id()
|
||||||
node_model = None
|
position = core_pb2.Position(x=x, y=y)
|
||||||
if name in NETWORK_NODES:
|
node = core_pb2.Node(
|
||||||
if name == "switch":
|
id=node_id,
|
||||||
node_type = core_pb2.NodeType.SWITCH
|
type=node_type,
|
||||||
elif name == "hub":
|
name=f"n{node_id}",
|
||||||
node_type = core_pb2.NodeType.HUB
|
model=model,
|
||||||
elif name == "wlan":
|
position=position,
|
||||||
node_type = core_pb2.NodeType.WIRELESS_LAN
|
)
|
||||||
elif name == "rj45":
|
|
||||||
node_type = core_pb2.NodeType.RJ45
|
|
||||||
elif name == "emane":
|
|
||||||
node_type = core_pb2.NodeType.EMANE
|
|
||||||
elif name == "tunnel":
|
|
||||||
node_type = core_pb2.NodeType.TUNNEL
|
|
||||||
elif name == "emane":
|
|
||||||
node_type = core_pb2.NodeType.EMANE
|
|
||||||
elif self.is_model_node(name):
|
|
||||||
node_type = core_pb2.NodeType.DEFAULT
|
|
||||||
node_model = name
|
|
||||||
else:
|
|
||||||
logging.error("invalid node name: %s", name)
|
|
||||||
nid = self.get_id()
|
|
||||||
create_node = Node(session_id, nid, node_type, node_model, x, y, name)
|
|
||||||
|
|
||||||
# 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, node_id)
|
||||||
self.mobilityconfig_management.set_default_configuration(node_type, nid)
|
self.mobilityconfig_management.set_default_configuration(node_type, node_id)
|
||||||
|
|
||||||
# set default emane configuration for emane node
|
# set default emane configuration for emane node
|
||||||
if node_type == core_pb2.NodeType.EMANE:
|
if node_type == core_pb2.NodeType.EMANE:
|
||||||
self.emaneconfig_management.set_default_config(nid)
|
self.emaneconfig_management.set_default_config(node_id)
|
||||||
|
|
||||||
# set default service configurations
|
# set default service configurations
|
||||||
if node_type == core_pb2.NodeType.DEFAULT:
|
if node_type == core_pb2.NodeType.DEFAULT:
|
||||||
self.serviceconfig_manager.node_default_services_configuration(
|
self.serviceconfig_manager.node_default_services_configuration(
|
||||||
node_id=nid, node_model=node_model
|
node_id=node_id, node_model=model
|
||||||
)
|
)
|
||||||
|
|
||||||
self.nodes[canvas_id] = create_node
|
|
||||||
self.core_mapping.map_core_id_to_canvas_id(nid, canvas_id)
|
|
||||||
logging.debug(
|
logging.debug(
|
||||||
"Adding node to core.. session id: %s, coords: (%s, %s), name: %s",
|
"adding node to core session: %s, coords: (%s, %s), name: %s",
|
||||||
session_id,
|
self.session_id,
|
||||||
x,
|
x,
|
||||||
y,
|
y,
|
||||||
name,
|
node.name,
|
||||||
)
|
)
|
||||||
|
return node
|
||||||
|
|
||||||
def delete_wanted_graph_nodes(self, canvas_ids, tokens):
|
def delete_wanted_graph_nodes(self, node_ids, edge_tokens):
|
||||||
"""
|
"""
|
||||||
remove the nodes selected by the user and anything related to that node
|
remove the nodes selected by the user and anything related to that node
|
||||||
such as link, configurations, interfaces
|
such as link, configurations, interfaces
|
||||||
|
|
||||||
:param list(int) canvas_ids: list of canvas node ids
|
:param list[int] node_ids: list of nodes to delete
|
||||||
|
:param list edge_tokens: list of edges to delete
|
||||||
:return: nothing
|
:return: nothing
|
||||||
"""
|
"""
|
||||||
# keep reference to the core ids
|
|
||||||
core_node_ids = [self.nodes[x].node_id for x in canvas_ids]
|
|
||||||
node_interface_pairs = []
|
|
||||||
|
|
||||||
# delete the nodes
|
# delete the nodes
|
||||||
for i in canvas_ids:
|
for node_id in node_ids:
|
||||||
try:
|
try:
|
||||||
n = self.nodes.pop(i)
|
del self.canvas_nodes[node_id]
|
||||||
self.reusable.append(n.node_id)
|
self.reusable.append(node_id)
|
||||||
except KeyError:
|
except KeyError:
|
||||||
logging.error("coreclient.py INVALID NODE CANVAS ID")
|
logging.error("invalid canvas id: %s", node_id)
|
||||||
|
|
||||||
self.reusable.sort()
|
self.reusable.sort()
|
||||||
|
|
||||||
# delete the edges and interfaces
|
# delete the edges and interfaces
|
||||||
for i in tokens:
|
node_interface_pairs = []
|
||||||
|
for i in edge_tokens:
|
||||||
try:
|
try:
|
||||||
e = self.edges.pop(i)
|
link = self.links.pop(i)
|
||||||
if e.interface_1 is not None:
|
if link.interface_one is not None:
|
||||||
node_interface_pairs.append(tuple([e.id1, e.interface_1.id]))
|
node_interface_pairs.append(
|
||||||
if e.interface_2 is not None:
|
(link.node_one_id, link.interface_one.id)
|
||||||
node_interface_pairs.append(tuple([e.id2, e.interface_2.id]))
|
)
|
||||||
|
if link.interface_two is not None:
|
||||||
|
node_interface_pairs.append(
|
||||||
|
(link.node_two_id, link.interface_two.id)
|
||||||
|
)
|
||||||
except KeyError:
|
except KeyError:
|
||||||
logging.error("coreclient.py invalid edge token ")
|
logging.error("coreclient.py invalid edge token ")
|
||||||
|
|
||||||
# delete global emane config if there no longer exist any emane cloud
|
# delete global emane config if there no longer exist any emane cloud
|
||||||
if core_pb2.NodeType.EMANE not in [x.type for x in self.nodes.values()]:
|
# TODO: should not need to worry about this
|
||||||
|
node_types = [x.core_node.type for x in self.canvas_nodes.values()]
|
||||||
|
if core_pb2.NodeType.EMANE not in node_types:
|
||||||
self.emane_config = None
|
self.emane_config = None
|
||||||
|
|
||||||
# delete any mobility configuration, wlan configuration
|
# delete any mobility configuration, wlan configuration
|
||||||
for i in core_node_ids:
|
for i in node_ids:
|
||||||
if i in self.mobilityconfig_management.configurations:
|
if i in self.mobilityconfig_management.configurations:
|
||||||
self.mobilityconfig_management.configurations.pop(i)
|
self.mobilityconfig_management.configurations.pop(i)
|
||||||
if i in self.wlanconfig_management.configurations:
|
if i in self.wlanconfig_management.configurations:
|
||||||
|
@ -619,214 +536,82 @@ class CoreClient:
|
||||||
for i in node_interface_pairs:
|
for i in node_interface_pairs:
|
||||||
if i in self.emaneconfig_management.configurations:
|
if i in self.emaneconfig_management.configurations:
|
||||||
self.emaneconfig_management.configurations.pop(i)
|
self.emaneconfig_management.configurations.pop(i)
|
||||||
for i in core_node_ids:
|
for i in node_ids:
|
||||||
if tuple([i, None]) in self.emaneconfig_management.configurations:
|
if tuple([i, None]) in self.emaneconfig_management.configurations:
|
||||||
self.emaneconfig_management.configurations.pop(tuple([i, None]))
|
self.emaneconfig_management.configurations.pop(tuple([i, None]))
|
||||||
|
|
||||||
def add_preexisting_node(self, canvas_node, session_id, core_node, name):
|
def create_interface(self, canvas_node):
|
||||||
"""
|
interface = None
|
||||||
Add preexisting nodes to grpc manager
|
core_node = canvas_node.core_node
|
||||||
|
if self.is_model_node(core_node.model):
|
||||||
:param str name: node_type
|
ifid = len(canvas_node.interfaces)
|
||||||
:param core_pb2.Node core_node: core node grpc message
|
name = f"eth{ifid}"
|
||||||
:param coretk.graph.CanvasNode canvas_node: canvas node
|
|
||||||
:param int session_id: session id
|
|
||||||
:return: nothing
|
|
||||||
"""
|
|
||||||
|
|
||||||
# update the next available id
|
|
||||||
core_id = core_node.id
|
|
||||||
if self.id is None or core_id >= self.id:
|
|
||||||
self.id = core_id + 1
|
|
||||||
self.preexisting.add(core_id)
|
|
||||||
n = Node(
|
|
||||||
session_id,
|
|
||||||
core_id,
|
|
||||||
core_node.type,
|
|
||||||
core_node.model,
|
|
||||||
canvas_node.x_coord,
|
|
||||||
canvas_node.y_coord,
|
|
||||||
name,
|
|
||||||
)
|
|
||||||
self.nodes[canvas_node.id] = n
|
|
||||||
|
|
||||||
def update_node_location(self, canvas_id, new_x, new_y):
|
|
||||||
"""
|
|
||||||
update node
|
|
||||||
|
|
||||||
:param int canvas_id: canvas id of that node
|
|
||||||
:param int new_x: new x coord
|
|
||||||
:param int new_y: new y coord
|
|
||||||
:return: nothing
|
|
||||||
"""
|
|
||||||
self.nodes[canvas_id].x = new_x
|
|
||||||
self.nodes[canvas_id].y = new_y
|
|
||||||
|
|
||||||
def update_reusable_id(self):
|
|
||||||
"""
|
|
||||||
Update available id for reuse
|
|
||||||
|
|
||||||
:return: nothing
|
|
||||||
"""
|
|
||||||
if len(self.preexisting) > 0:
|
|
||||||
for i in range(1, self.id):
|
|
||||||
if i not in self.preexisting:
|
|
||||||
self.reusable.append(i)
|
|
||||||
|
|
||||||
self.preexisting.clear()
|
|
||||||
logging.debug("Next id: %s, Reusable: %s", self.id, self.reusable)
|
|
||||||
|
|
||||||
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(
|
interface = core_pb2.Interface(
|
||||||
id=gui_interface.id,
|
id=ifid,
|
||||||
name=gui_interface.name,
|
name=name,
|
||||||
mac=gui_interface.mac,
|
ip4=str(self.interfaces_manager.get_address()),
|
||||||
ip4=gui_interface.ipv4,
|
ip4mask=24,
|
||||||
ip4mask=gui_interface.ip4prefix,
|
|
||||||
)
|
)
|
||||||
logging.debug("create interface: %s", interface)
|
canvas_node.interfaces.append(interface)
|
||||||
return interface
|
|
||||||
|
|
||||||
def create_edge_interface(self, edge, src_canvas_id, dst_canvas_id):
|
|
||||||
"""
|
|
||||||
Create the interface for the two end of an edge, add a copy to node's interfaces
|
|
||||||
|
|
||||||
:param coretk.coreclient.Edge edge: edge to add interfaces to
|
|
||||||
:param int src_canvas_id: canvas id for the source node
|
|
||||||
:param int dst_canvas_id: canvas id for the destination node
|
|
||||||
:return: nothing
|
|
||||||
"""
|
|
||||||
src_interface = None
|
|
||||||
dst_interface = None
|
|
||||||
print("create interface")
|
|
||||||
self.interfaces_manager.new_subnet()
|
|
||||||
|
|
||||||
src_node = self.nodes[src_canvas_id]
|
|
||||||
if self.is_model_node(src_node.model):
|
|
||||||
ifid = len(src_node.interfaces)
|
|
||||||
name = "eth" + str(ifid)
|
|
||||||
src_interface = Interface(
|
|
||||||
name=name, ifid=ifid, ipv4=str(self.interfaces_manager.get_address())
|
|
||||||
)
|
|
||||||
self.nodes[src_canvas_id].interfaces.append(src_interface)
|
|
||||||
logging.debug(
|
logging.debug(
|
||||||
"Create source interface 1... IP: %s, name: %s",
|
"create node(%s) interface IPv4: %s, name: %s",
|
||||||
src_interface.ipv4,
|
core_node.name,
|
||||||
src_interface.name,
|
interface.ip4,
|
||||||
|
interface.name,
|
||||||
)
|
)
|
||||||
|
return interface
|
||||||
|
|
||||||
dst_node = self.nodes[dst_canvas_id]
|
def create_link(self, token, canvas_node_one, canvas_node_two):
|
||||||
if self.is_model_node(dst_node.model):
|
|
||||||
ifid = len(dst_node.interfaces)
|
|
||||||
name = "eth" + str(ifid)
|
|
||||||
dst_interface = Interface(
|
|
||||||
name=name, ifid=ifid, ipv4=str(self.interfaces_manager.get_address())
|
|
||||||
)
|
|
||||||
self.nodes[dst_canvas_id].interfaces.append(dst_interface)
|
|
||||||
logging.debug(
|
|
||||||
"Create destination interface... IP: %s, name: %s",
|
|
||||||
dst_interface.ipv4,
|
|
||||||
dst_interface.name,
|
|
||||||
)
|
|
||||||
|
|
||||||
edge.interface_1 = src_interface
|
|
||||||
edge.interface_2 = dst_interface
|
|
||||||
return src_interface, dst_interface
|
|
||||||
|
|
||||||
def add_edge(self, session_id, token, canvas_id_1, canvas_id_2):
|
|
||||||
"""
|
"""
|
||||||
Add an edge to grpc manager
|
Create core link for a pair of canvas nodes, with token referencing
|
||||||
|
the canvas edge.
|
||||||
|
|
||||||
:param int session_id: core session id
|
|
||||||
:param tuple(int, int) token: edge's identification in the canvas
|
:param tuple(int, int) token: edge's identification in the canvas
|
||||||
:param int canvas_id_1: canvas id of source node
|
:param canvas_node_one: canvas node one
|
||||||
:param int canvas_id_2: canvas_id of destination node
|
:param canvas_node_two: canvas node two
|
||||||
|
|
||||||
:return: nothing
|
:return: nothing
|
||||||
"""
|
"""
|
||||||
node_one = self.nodes[canvas_id_1]
|
node_one = canvas_node_one.core_node
|
||||||
node_two = self.nodes[canvas_id_2]
|
node_two = canvas_node_two.core_node
|
||||||
if canvas_id_1 in self.nodes and canvas_id_2 in self.nodes:
|
|
||||||
edge = Edge(
|
|
||||||
session_id,
|
|
||||||
node_one.node_id,
|
|
||||||
node_one.type,
|
|
||||||
node_two.node_id,
|
|
||||||
node_two.type,
|
|
||||||
)
|
|
||||||
self.edges[token] = edge
|
|
||||||
src_interface, dst_interface = self.create_edge_interface(
|
|
||||||
edge, canvas_id_1, canvas_id_2
|
|
||||||
)
|
|
||||||
node_one_id = node_one.node_id
|
|
||||||
node_two_id = node_two.node_id
|
|
||||||
|
|
||||||
# provide a way to get an edge from a core node and an interface id
|
# create interfaces
|
||||||
if src_interface is not None:
|
self.interfaces_manager.new_subnet()
|
||||||
self.core_mapping.map_node_and_interface_to_canvas_edge(
|
interface_one = self.create_interface(canvas_node_one)
|
||||||
node_one_id, src_interface.id, token
|
if interface_one is not None:
|
||||||
|
self.interface_to_edge[(node_one.id, interface_one.id)] = token
|
||||||
|
interface_two = self.create_interface(canvas_node_two)
|
||||||
|
if interface_two is not None:
|
||||||
|
self.interface_to_edge[(node_two.id, interface_two.id)] = token
|
||||||
|
|
||||||
|
# emane setup
|
||||||
|
# TODO: determine if this is needed
|
||||||
|
if (
|
||||||
|
node_one.type == core_pb2.NodeType.EMANE
|
||||||
|
and node_two.type == core_pb2.NodeType.DEFAULT
|
||||||
|
):
|
||||||
|
if node_two.model == "mdr":
|
||||||
|
self.emaneconfig_management.set_default_for_mdr(
|
||||||
|
node_one.node_id, node_two.node_id, interface_two.id
|
||||||
|
)
|
||||||
|
elif (
|
||||||
|
node_two.type == core_pb2.NodeType.EMANE
|
||||||
|
and node_one.type == core_pb2.NodeType.DEFAULT
|
||||||
|
):
|
||||||
|
if node_one.model == "mdr":
|
||||||
|
self.emaneconfig_management.set_default_for_mdr(
|
||||||
|
node_two.node_id, node_one.node_id, interface_one.id
|
||||||
)
|
)
|
||||||
|
|
||||||
if dst_interface is not None:
|
link = core_pb2.Link(
|
||||||
self.core_mapping.map_node_and_interface_to_canvas_edge(
|
type=core_pb2.LinkType.WIRED,
|
||||||
node_two_id, dst_interface.id, token
|
node_one_id=node_one.id,
|
||||||
)
|
node_two_id=node_two.id,
|
||||||
|
interface_one=interface_one,
|
||||||
if (
|
interface_two=interface_two,
|
||||||
node_one.type == core_pb2.NodeType.EMANE
|
)
|
||||||
and node_two.type == core_pb2.NodeType.DEFAULT
|
self.links[token] = link
|
||||||
):
|
return link
|
||||||
if node_two.model == "mdr":
|
|
||||||
self.emaneconfig_management.set_default_for_mdr(
|
|
||||||
node_one.node_id, node_two.node_id, dst_interface.id
|
|
||||||
)
|
|
||||||
elif (
|
|
||||||
node_two.type == core_pb2.NodeType.EMANE
|
|
||||||
and node_one.type == core_pb2.NodeType.DEFAULT
|
|
||||||
):
|
|
||||||
if node_one.model == "mdr":
|
|
||||||
self.emaneconfig_management.set_default_for_mdr(
|
|
||||||
node_two.node_id, node_one.node_id, src_interface.id
|
|
||||||
)
|
|
||||||
|
|
||||||
else:
|
|
||||||
logging.error("grpcmanagement.py INVALID CANVAS NODE ID")
|
|
||||||
|
|
||||||
def get_nodes_proto(self):
|
|
||||||
nodes = []
|
|
||||||
for node in self.nodes.values():
|
|
||||||
pos = core_pb2.Position(x=int(node.x), y=int(node.y))
|
|
||||||
proto_node = core_pb2.Node(
|
|
||||||
id=node.node_id, type=node.type, position=pos, model=node.model
|
|
||||||
)
|
|
||||||
nodes.append(proto_node)
|
|
||||||
return nodes
|
|
||||||
|
|
||||||
def get_links_proto(self):
|
|
||||||
links = []
|
|
||||||
for edge in self.edges.values():
|
|
||||||
interface_one = self.create_interface(edge.type1, edge.interface_1)
|
|
||||||
interface_two = self.create_interface(edge.type2, edge.interface_2)
|
|
||||||
link = core_pb2.Link(
|
|
||||||
node_one_id=edge.id1,
|
|
||||||
node_two_id=edge.id2,
|
|
||||||
type=core_pb2.LinkType.WIRED,
|
|
||||||
interface_one=interface_one,
|
|
||||||
interface_two=interface_two,
|
|
||||||
)
|
|
||||||
links.append(link)
|
|
||||||
return links
|
|
||||||
|
|
||||||
def get_wlan_configs_proto(self):
|
def get_wlan_configs_proto(self):
|
||||||
configs = []
|
configs = []
|
||||||
|
|
|
@ -1,34 +0,0 @@
|
||||||
"""
|
|
||||||
provide mapping from core to canvas
|
|
||||||
"""
|
|
||||||
import logging
|
|
||||||
|
|
||||||
|
|
||||||
class CoreToCanvasMapping:
|
|
||||||
def __init__(self):
|
|
||||||
self.core_id_to_canvas_id = {}
|
|
||||||
self.core_node_and_interface_to_canvas_edge = {}
|
|
||||||
|
|
||||||
def map_node_and_interface_to_canvas_edge(self, nid, iid, edge_token):
|
|
||||||
self.core_node_and_interface_to_canvas_edge[tuple([nid, iid])] = edge_token
|
|
||||||
|
|
||||||
def get_token_from_node_and_interface(self, nid, iid):
|
|
||||||
key = tuple([nid, iid])
|
|
||||||
if key in self.core_node_and_interface_to_canvas_edge:
|
|
||||||
return self.core_node_and_interface_to_canvas_edge[key]
|
|
||||||
else:
|
|
||||||
logging.error("invalid key")
|
|
||||||
return None
|
|
||||||
|
|
||||||
def map_core_id_to_canvas_id(self, core_nid, canvas_nid):
|
|
||||||
if core_nid not in self.core_id_to_canvas_id:
|
|
||||||
self.core_id_to_canvas_id[core_nid] = canvas_nid
|
|
||||||
else:
|
|
||||||
logging.debug("key already existed")
|
|
||||||
|
|
||||||
def get_canvas_id_from_core_id(self, core_id):
|
|
||||||
if core_id in self.core_id_to_canvas_id:
|
|
||||||
return self.core_id_to_canvas_id[core_id]
|
|
||||||
else:
|
|
||||||
logging.debug("invalid key")
|
|
||||||
return None
|
|
|
@ -21,7 +21,7 @@ class NodeConfigDialog(Dialog):
|
||||||
self.image = canvas_node.image
|
self.image = canvas_node.image
|
||||||
self.image_button = None
|
self.image_button = None
|
||||||
self.name = tk.StringVar(value=canvas_node.name)
|
self.name = tk.StringVar(value=canvas_node.name)
|
||||||
self.type = tk.StringVar(value=canvas_node.node_type)
|
self.type = tk.StringVar(value=canvas_node.core_node.model)
|
||||||
self.server = tk.StringVar()
|
self.server = tk.StringVar()
|
||||||
self.draw()
|
self.draw()
|
||||||
|
|
||||||
|
|
|
@ -13,14 +13,13 @@ class NodeService(Dialog):
|
||||||
def __init__(self, master, app, canvas_node, services=None):
|
def __init__(self, master, app, canvas_node, services=None):
|
||||||
super().__init__(master, app, "Node Services", modal=True)
|
super().__init__(master, app, "Node Services", modal=True)
|
||||||
self.canvas_node = canvas_node
|
self.canvas_node = canvas_node
|
||||||
|
self.node_id = canvas_node.core_node.id
|
||||||
self.groups = None
|
self.groups = None
|
||||||
self.services = None
|
self.services = None
|
||||||
self.current = None
|
self.current = None
|
||||||
if services is None:
|
if services is None:
|
||||||
services = set(
|
services = set(
|
||||||
app.core.serviceconfig_manager.configurations[
|
app.core.serviceconfig_manager.configurations[self.node_id].keys()
|
||||||
canvas_node.core_id
|
|
||||||
].keys()
|
|
||||||
)
|
)
|
||||||
self.current_services = services
|
self.current_services = services
|
||||||
self.draw()
|
self.draw()
|
||||||
|
|
|
@ -15,7 +15,7 @@ class ServiceConfiguration(Dialog):
|
||||||
super().__init__(master, app, f"{service_name} service", modal=True)
|
super().__init__(master, app, f"{service_name} service", modal=True)
|
||||||
self.app = app
|
self.app = app
|
||||||
self.canvas_node = canvas_node
|
self.canvas_node = canvas_node
|
||||||
self.node_id = canvas_node.core_id
|
self.node_id = canvas_node.core_node.id
|
||||||
self.service_name = service_name
|
self.service_name = service_name
|
||||||
self.radiovar = tk.IntVar()
|
self.radiovar = tk.IntVar()
|
||||||
self.radiovar.set(2)
|
self.radiovar.set(2)
|
||||||
|
@ -73,22 +73,15 @@ class ServiceConfiguration(Dialog):
|
||||||
self.validation_mode = service_config.validation_mode
|
self.validation_mode = service_config.validation_mode
|
||||||
self.validation_time = service_config.validation_timer
|
self.validation_time = service_config.validation_timer
|
||||||
self.original_service_files = {
|
self.original_service_files = {
|
||||||
x: self.app.core.get_node_service_file(
|
x: self.app.core.get_node_service_file(self.node_id, self.service_name, x)
|
||||||
self.canvas_node.core_id, self.service_name, x
|
|
||||||
)
|
|
||||||
for x in self.filenames
|
for x in self.filenames
|
||||||
}
|
}
|
||||||
self.temp_service_files = {
|
self.temp_service_files = {
|
||||||
x: self.original_service_files[x] for x in self.original_service_files
|
x: self.original_service_files[x] for x in self.original_service_files
|
||||||
}
|
}
|
||||||
configs = self.app.core.servicefileconfig_manager.configurations
|
configs = self.app.core.servicefileconfig_manager.configurations
|
||||||
if (
|
if self.node_id in configs and self.service_name in configs[self.node_id]:
|
||||||
self.canvas_node.core_id in configs
|
for file, data in configs[self.node_id][self.service_name].items():
|
||||||
and self.service_name in configs[self.canvas_node.core_id]
|
|
||||||
):
|
|
||||||
for file, data in configs[self.canvas_node.core_id][
|
|
||||||
self.service_name
|
|
||||||
].items():
|
|
||||||
self.temp_service_files[file] = data
|
self.temp_service_files[file] = data
|
||||||
|
|
||||||
def draw(self):
|
def draw(self):
|
||||||
|
@ -371,7 +364,7 @@ class ServiceConfiguration(Dialog):
|
||||||
shutdown_commands = self.shutdown_commands_listbox.get(0, "end")
|
shutdown_commands = self.shutdown_commands_listbox.get(0, "end")
|
||||||
validate_commands = self.validate_commands_listbox.get(0, "end")
|
validate_commands = self.validate_commands_listbox.get(0, "end")
|
||||||
self.app.core.serviceconfig_manager.node_service_custom_configuration(
|
self.app.core.serviceconfig_manager.node_service_custom_configuration(
|
||||||
self.canvas_node.core_id,
|
self.node_id,
|
||||||
self.service_name,
|
self.service_name,
|
||||||
startup_commands,
|
startup_commands,
|
||||||
validate_commands,
|
validate_commands,
|
||||||
|
@ -379,16 +372,10 @@ class ServiceConfiguration(Dialog):
|
||||||
)
|
)
|
||||||
for file in self.modified_files:
|
for file in self.modified_files:
|
||||||
self.app.core.servicefileconfig_manager.set_custom_service_file_config(
|
self.app.core.servicefileconfig_manager.set_custom_service_file_config(
|
||||||
self.canvas_node.core_id,
|
self.node_id, self.service_name, file, self.temp_service_files[file]
|
||||||
self.service_name,
|
|
||||||
file,
|
|
||||||
self.temp_service_files[file],
|
|
||||||
)
|
)
|
||||||
self.app.core.set_node_service_file(
|
self.app.core.set_node_service_file(
|
||||||
self.canvas_node.core_id,
|
self.node_id, self.service_name, file, self.temp_service_files[file]
|
||||||
self.service_name,
|
|
||||||
file,
|
|
||||||
self.temp_service_files[file],
|
|
||||||
)
|
)
|
||||||
self.destroy()
|
self.destroy()
|
||||||
|
|
||||||
|
|
|
@ -9,7 +9,6 @@ from coretk.canvasaction import CanvasAction
|
||||||
from coretk.canvastooltip import CanvasTooltip
|
from coretk.canvastooltip import CanvasTooltip
|
||||||
from coretk.graph_helper import GraphHelper, WlanAntennaManager
|
from coretk.graph_helper import GraphHelper, WlanAntennaManager
|
||||||
from coretk.images import Images
|
from coretk.images import Images
|
||||||
from coretk.interface import Interface
|
|
||||||
from coretk.linkinfo import LinkInfo, Throughput
|
from coretk.linkinfo import LinkInfo, Throughput
|
||||||
from coretk.nodedelete import CanvasComponentManagement
|
from coretk.nodedelete import CanvasComponentManagement
|
||||||
from coretk.wirelessconnection import WirelessConnection
|
from coretk.wirelessconnection import WirelessConnection
|
||||||
|
@ -31,12 +30,6 @@ class ScaleOption(enum.Enum):
|
||||||
TILED = 4
|
TILED = 4
|
||||||
|
|
||||||
|
|
||||||
CORE_NODES = ["router"]
|
|
||||||
CORE_WIRED_NETWORK_NODES = []
|
|
||||||
CORE_WIRELESS_NODE = ["wlan"]
|
|
||||||
CORE_EMANE = ["emane"]
|
|
||||||
|
|
||||||
|
|
||||||
class CanvasGraph(tk.Canvas):
|
class CanvasGraph(tk.Canvas):
|
||||||
def __init__(self, master, core, cnf=None, **kwargs):
|
def __init__(self, master, core, cnf=None, **kwargs):
|
||||||
if cnf is None:
|
if cnf is None:
|
||||||
|
@ -45,7 +38,8 @@ class CanvasGraph(tk.Canvas):
|
||||||
super().__init__(master, cnf, **kwargs)
|
super().__init__(master, cnf, **kwargs)
|
||||||
self.mode = GraphMode.SELECT
|
self.mode = GraphMode.SELECT
|
||||||
self.draw_node_image = None
|
self.draw_node_image = None
|
||||||
self.draw_node_name = None
|
self.draw_node_type = None
|
||||||
|
self.draw_node_model = None
|
||||||
self.selected = None
|
self.selected = None
|
||||||
self.node_context = None
|
self.node_context = None
|
||||||
self.nodes = {}
|
self.nodes = {}
|
||||||
|
@ -89,7 +83,7 @@ class CanvasGraph(tk.Canvas):
|
||||||
self.node_context.add_command(label="Hide")
|
self.node_context.add_command(label="Hide")
|
||||||
self.node_context.add_command(label="Services")
|
self.node_context.add_command(label="Services")
|
||||||
|
|
||||||
def canvas_reset_and_redraw(self, session):
|
def reset_and_redraw(self, session):
|
||||||
"""
|
"""
|
||||||
Reset the private variables CanvasGraph object, redraw nodes given the new grpc
|
Reset the private variables CanvasGraph object, redraw nodes given the new grpc
|
||||||
client.
|
client.
|
||||||
|
@ -103,13 +97,14 @@ class CanvasGraph(tk.Canvas):
|
||||||
# set the private variables to default value
|
# set the private variables to default value
|
||||||
self.mode = GraphMode.SELECT
|
self.mode = GraphMode.SELECT
|
||||||
self.draw_node_image = None
|
self.draw_node_image = None
|
||||||
self.draw_node_name = None
|
self.draw_node_type = None
|
||||||
|
self.draw_node_model = None
|
||||||
self.selected = None
|
self.selected = None
|
||||||
self.node_context = None
|
self.node_context = None
|
||||||
self.nodes.clear()
|
self.nodes.clear()
|
||||||
self.edges.clear()
|
self.edges.clear()
|
||||||
self.drawing_edge = None
|
self.drawing_edge = None
|
||||||
self.draw_existing_component(session)
|
self.draw_session(session)
|
||||||
|
|
||||||
def setup_bindings(self):
|
def setup_bindings(self):
|
||||||
"""
|
"""
|
||||||
|
@ -149,95 +144,71 @@ class CanvasGraph(tk.Canvas):
|
||||||
self.tag_lower("gridline")
|
self.tag_lower("gridline")
|
||||||
self.tag_lower(self.grid)
|
self.tag_lower(self.grid)
|
||||||
|
|
||||||
def draw_existing_component(self, session):
|
def draw_session(self, session):
|
||||||
"""
|
"""
|
||||||
Draw existing node and update the information in grpc manager to match
|
Draw existing session.
|
||||||
|
|
||||||
:return: nothing
|
:return: nothing
|
||||||
"""
|
"""
|
||||||
core_id_to_canvas_id = {}
|
# draw existing nodes
|
||||||
# redraw existing nodes
|
for core_node in session.nodes:
|
||||||
for node in session.nodes:
|
|
||||||
# peer to peer node is not drawn on the GUI
|
# peer to peer node is not drawn on the GUI
|
||||||
if node.type != core_pb2.NodeType.PEER_TO_PEER:
|
if core_node.type == core_pb2.NodeType.PEER_TO_PEER:
|
||||||
# draw nodes on the canvas
|
continue
|
||||||
image, name = Images.node_icon(node.type, node.model)
|
|
||||||
n = CanvasNode(
|
|
||||||
node.position.x, node.position.y, image, name, self.master, node.id
|
|
||||||
)
|
|
||||||
self.nodes[n.id] = n
|
|
||||||
core_id_to_canvas_id[node.id] = n.id
|
|
||||||
|
|
||||||
# store the node in grpc manager
|
# draw nodes on the canvas
|
||||||
self.core.add_preexisting_node(n, session.id, node, name)
|
image = Images.node_icon(core_node.type, core_node.model)
|
||||||
|
position = core_node.position
|
||||||
|
node = CanvasNode(position.x, position.y, image, self.master, core_node)
|
||||||
|
self.nodes[node.id] = node
|
||||||
|
self.core.canvas_nodes[core_node.id] = node
|
||||||
|
|
||||||
# draw existing links
|
# draw existing links
|
||||||
for link in session.links:
|
for link in session.links:
|
||||||
n1 = self.nodes[core_id_to_canvas_id[link.node_one_id]]
|
canvas_node_one = self.core.canvas_nodes[link.node_one_id]
|
||||||
n2 = self.nodes[core_id_to_canvas_id[link.node_two_id]]
|
canvas_node_two = self.core.canvas_nodes[link.node_two_id]
|
||||||
if link.type == core_pb2.LinkType.WIRED:
|
is_wired = link.type == core_pb2.LinkType.WIRED
|
||||||
e = CanvasEdge(
|
edge = CanvasEdge(
|
||||||
n1.x_coord,
|
canvas_node_one.x_coord,
|
||||||
n1.y_coord,
|
canvas_node_one.y_coord,
|
||||||
n2.x_coord,
|
canvas_node_two.x_coord,
|
||||||
n2.y_coord,
|
canvas_node_two.y_coord,
|
||||||
n1.id,
|
canvas_node_one.id,
|
||||||
self,
|
self,
|
||||||
is_wired=True,
|
is_wired=is_wired,
|
||||||
)
|
)
|
||||||
elif link.type == core_pb2.LinkType.WIRELESS:
|
edge.token = tuple(sorted((canvas_node_one.id, canvas_node_two.id)))
|
||||||
e = CanvasEdge(
|
edge.dst = canvas_node_two.id
|
||||||
n1.x_coord,
|
canvas_node_one.edges.add(edge)
|
||||||
n1.y_coord,
|
canvas_node_two.edges.add(edge)
|
||||||
n2.x_coord,
|
self.edges[edge.token] = edge
|
||||||
n2.y_coord,
|
self.core.links[edge.token] = link
|
||||||
n1.id,
|
self.helper.redraw_antenna(link, canvas_node_one, canvas_node_two)
|
||||||
self,
|
|
||||||
is_wired=False,
|
|
||||||
)
|
|
||||||
edge_token = tuple(sorted((n1.id, n2.id)))
|
|
||||||
e.token = edge_token
|
|
||||||
e.dst = n2.id
|
|
||||||
n1.edges.add(e)
|
|
||||||
n2.edges.add(e)
|
|
||||||
self.edges[e.token] = e
|
|
||||||
self.core.add_edge(session.id, e.token, n1.id, n2.id)
|
|
||||||
|
|
||||||
self.helper.redraw_antenna(link, n1, n2)
|
|
||||||
|
|
||||||
# TODO add back the link info to grpc manager also redraw
|
# TODO add back the link info to grpc manager also redraw
|
||||||
grpc_if1 = link.interface_one
|
# TODO will include throughput and ipv6 in the future
|
||||||
grpc_if2 = link.interface_two
|
interface_one = link.interface_one
|
||||||
|
interface_two = link.interface_two
|
||||||
ip4_src = None
|
ip4_src = None
|
||||||
ip4_dst = None
|
ip4_dst = None
|
||||||
ip6_src = None
|
ip6_src = None
|
||||||
ip6_dst = None
|
ip6_dst = None
|
||||||
if grpc_if1 is not None:
|
if interface_one is not None:
|
||||||
ip4_src = grpc_if1.ip4
|
ip4_src = interface_one.ip4
|
||||||
ip6_src = grpc_if1.ip6
|
ip6_src = interface_one.ip6
|
||||||
if grpc_if2 is not None:
|
if interface_two is not None:
|
||||||
ip4_dst = grpc_if2.ip4
|
ip4_dst = interface_two.ip4
|
||||||
ip6_dst = grpc_if2.ip6
|
ip6_dst = interface_two.ip6
|
||||||
e.link_info = LinkInfo(
|
edge.link_info = LinkInfo(
|
||||||
canvas=self,
|
canvas=self,
|
||||||
edge=e,
|
edge=edge,
|
||||||
ip4_src=ip4_src,
|
ip4_src=ip4_src,
|
||||||
ip6_src=ip6_src,
|
ip6_src=ip6_src,
|
||||||
ip4_dst=ip4_dst,
|
ip4_dst=ip4_dst,
|
||||||
ip6_dst=ip6_dst,
|
ip6_dst=ip6_dst,
|
||||||
)
|
)
|
||||||
|
canvas_node_one.interfaces.append(interface_one)
|
||||||
# TODO will include throughput and ipv6 in the future
|
canvas_node_two.interfaces.append(interface_two)
|
||||||
if1 = Interface(grpc_if1.name, grpc_if1.ip4, ifid=grpc_if1.id)
|
|
||||||
if2 = Interface(grpc_if2.name, grpc_if2.ip4, ifid=grpc_if2.id)
|
|
||||||
self.core.edges[e.token].interface_1 = if1
|
|
||||||
self.core.edges[e.token].interface_2 = if2
|
|
||||||
self.core.nodes[core_id_to_canvas_id[link.node_one_id]].interfaces.append(
|
|
||||||
if1
|
|
||||||
)
|
|
||||||
self.core.nodes[core_id_to_canvas_id[link.node_two_id]].interfaces.append(
|
|
||||||
if2
|
|
||||||
)
|
|
||||||
|
|
||||||
# raise the nodes so they on top of the links
|
# raise the nodes so they on top of the links
|
||||||
self.tag_raise("node")
|
self.tag_raise("node")
|
||||||
|
@ -296,7 +267,13 @@ class CanvasGraph(tk.Canvas):
|
||||||
self.handle_edge_release(event)
|
self.handle_edge_release(event)
|
||||||
elif self.mode == GraphMode.NODE:
|
elif self.mode == GraphMode.NODE:
|
||||||
x, y = self.canvas_xy(event)
|
x, y = self.canvas_xy(event)
|
||||||
self.add_node(x, y, self.draw_node_image, self.draw_node_name)
|
self.add_node(
|
||||||
|
x,
|
||||||
|
y,
|
||||||
|
self.draw_node_image,
|
||||||
|
self.draw_node_type,
|
||||||
|
self.draw_node_model,
|
||||||
|
)
|
||||||
elif self.mode == GraphMode.PICKNODE:
|
elif self.mode == GraphMode.PICKNODE:
|
||||||
self.mode = GraphMode.NODE
|
self.mode = GraphMode.NODE
|
||||||
|
|
||||||
|
@ -319,6 +296,7 @@ class CanvasGraph(tk.Canvas):
|
||||||
# edge dst is same as src, delete edge
|
# edge dst is same as src, delete edge
|
||||||
if edge.src == self.selected:
|
if edge.src == self.selected:
|
||||||
edge.delete()
|
edge.delete()
|
||||||
|
return
|
||||||
|
|
||||||
# set dst node and snap edge to center
|
# set dst node and snap edge to center
|
||||||
x, y = self.coords(self.selected)
|
x, y = self.coords(self.selected)
|
||||||
|
@ -332,20 +310,17 @@ class CanvasGraph(tk.Canvas):
|
||||||
node_src.edges.add(edge)
|
node_src.edges.add(edge)
|
||||||
node_dst = self.nodes[edge.dst]
|
node_dst = self.nodes[edge.dst]
|
||||||
node_dst.edges.add(edge)
|
node_dst.edges.add(edge)
|
||||||
|
link = self.core.create_link(edge.token, node_src, node_dst)
|
||||||
self.core.add_edge(
|
|
||||||
self.core.session_id, edge.token, node_src.id, node_dst.id
|
|
||||||
)
|
|
||||||
|
|
||||||
# draw link info on the edge
|
# draw link info on the edge
|
||||||
if1 = self.core.edges[edge.token].interface_1
|
|
||||||
if2 = self.core.edges[edge.token].interface_2
|
|
||||||
ip4_and_prefix_1 = None
|
ip4_and_prefix_1 = None
|
||||||
ip4_and_prefix_2 = None
|
ip4_and_prefix_2 = None
|
||||||
if if1 is not None:
|
if link.HasField("interface_one"):
|
||||||
ip4_and_prefix_1 = if1.ip4_and_prefix
|
if1 = link.interface_one
|
||||||
if if2 is not None:
|
ip4_and_prefix_1 = f"{if1.ip4}/{if1.ip4mask}"
|
||||||
ip4_and_prefix_2 = if2.ip4_and_prefix
|
if link.HasField("interface_two"):
|
||||||
|
if2 = link.interface_two
|
||||||
|
ip4_and_prefix_2 = f"{if2.ip4}/{if2.ip4mask}"
|
||||||
edge.link_info = LinkInfo(
|
edge.link_info = LinkInfo(
|
||||||
self,
|
self,
|
||||||
edge,
|
edge,
|
||||||
|
@ -410,8 +385,10 @@ class CanvasGraph(tk.Canvas):
|
||||||
)
|
)
|
||||||
|
|
||||||
# delete nodes and link info stored in CanvasGraph object
|
# delete nodes and link info stored in CanvasGraph object
|
||||||
|
node_ids = []
|
||||||
for nid in to_delete_nodes:
|
for nid in to_delete_nodes:
|
||||||
self.nodes.pop(nid)
|
canvas_node = self.nodes.pop(nid)
|
||||||
|
node_ids.append(canvas_node.core_node.id)
|
||||||
for token in to_delete_edge_tokens:
|
for token in to_delete_edge_tokens:
|
||||||
self.edges.pop(token)
|
self.edges.pop(token)
|
||||||
|
|
||||||
|
@ -425,15 +402,16 @@ class CanvasGraph(tk.Canvas):
|
||||||
self.nodes[nid].edges.remove(edge)
|
self.nodes[nid].edges.remove(edge)
|
||||||
|
|
||||||
# delete the related data from core
|
# delete the related data from core
|
||||||
self.core.delete_wanted_graph_nodes(to_delete_nodes, to_delete_edge_tokens)
|
self.core.delete_wanted_graph_nodes(node_ids, to_delete_edge_tokens)
|
||||||
|
|
||||||
def add_node(self, x, y, image, node_name):
|
def add_node(self, x, y, image, node_type, model):
|
||||||
plot_id = self.find_all()[0]
|
plot_id = self.find_all()[0]
|
||||||
logging.info("add node event: %s - %s", plot_id, self.selected)
|
logging.info("add node event: %s - %s", plot_id, self.selected)
|
||||||
if self.selected == plot_id:
|
if self.selected == plot_id:
|
||||||
node = CanvasNode(x, y, image, node_name, self.master, self.core.peek_id())
|
core_node = self.core.create_node(int(x), int(y), node_type, model)
|
||||||
|
node = CanvasNode(x, y, image, self.master, core_node)
|
||||||
|
self.core.canvas_nodes[core_node.id] = node
|
||||||
self.nodes[node.id] = node
|
self.nodes[node.id] = node
|
||||||
self.core.add_graph_node(self.core.session_id, node.id, x, y, node_name)
|
|
||||||
return node
|
return node
|
||||||
|
|
||||||
def width_and_height(self):
|
def width_and_height(self):
|
||||||
|
@ -500,7 +478,6 @@ class CanvasGraph(tk.Canvas):
|
||||||
"""
|
"""
|
||||||
scale image based on canvas dimension
|
scale image based on canvas dimension
|
||||||
|
|
||||||
:param Image img: image object
|
|
||||||
:return: nothing
|
:return: nothing
|
||||||
"""
|
"""
|
||||||
canvas_w, canvas_h = self.width_and_height()
|
canvas_w, canvas_h = self.width_and_height()
|
||||||
|
@ -620,18 +597,17 @@ class CanvasEdge:
|
||||||
|
|
||||||
|
|
||||||
class CanvasNode:
|
class CanvasNode:
|
||||||
def __init__(self, x, y, image, node_type, app, core_id):
|
def __init__(self, x, y, image, app, core_node):
|
||||||
self.image = image
|
self.image = image
|
||||||
self.node_type = node_type
|
|
||||||
self.app = app
|
self.app = app
|
||||||
self.canvas = app.canvas
|
self.canvas = app.canvas
|
||||||
self.id = self.canvas.create_image(
|
self.id = self.canvas.create_image(
|
||||||
x, y, anchor=tk.CENTER, image=self.image, tags="node"
|
x, y, anchor=tk.CENTER, image=self.image, tags="node"
|
||||||
)
|
)
|
||||||
self.core_id = core_id
|
self.core_node = core_node
|
||||||
|
self.name = core_node.name
|
||||||
self.x_coord = x
|
self.x_coord = x
|
||||||
self.y_coord = y
|
self.y_coord = y
|
||||||
self.name = f"N{self.core_id}"
|
|
||||||
self.text_id = self.canvas.create_text(
|
self.text_id = self.canvas.create_text(
|
||||||
x, y + 20, text=self.name, tags="nodename"
|
x, y + 20, text=self.name, tags="nodename"
|
||||||
)
|
)
|
||||||
|
@ -647,6 +623,7 @@ class CanvasNode:
|
||||||
self.canvas.tag_bind(self.id, "<Leave>", self.on_leave)
|
self.canvas.tag_bind(self.id, "<Leave>", self.on_leave)
|
||||||
|
|
||||||
self.edges = set()
|
self.edges = set()
|
||||||
|
self.interfaces = []
|
||||||
self.wlans = []
|
self.wlans = []
|
||||||
self.moving = None
|
self.moving = None
|
||||||
|
|
||||||
|
@ -654,7 +631,7 @@ class CanvasNode:
|
||||||
if self.app.core.is_runtime() and self.app.core.observer:
|
if self.app.core.is_runtime() and self.app.core.observer:
|
||||||
self.tooltip.text.set("waiting...")
|
self.tooltip.text.set("waiting...")
|
||||||
self.tooltip.on_enter(event)
|
self.tooltip.on_enter(event)
|
||||||
output = self.app.core.run(self.core_id)
|
output = self.app.core.run(self.core_node.id)
|
||||||
self.tooltip.text.set(output)
|
self.tooltip.text.set(output)
|
||||||
|
|
||||||
def on_leave(self, event):
|
def on_leave(self, event):
|
||||||
|
@ -664,23 +641,15 @@ class CanvasNode:
|
||||||
print("click")
|
print("click")
|
||||||
|
|
||||||
def double_click(self, event):
|
def double_click(self, event):
|
||||||
node_id = self.canvas.core.nodes[self.id].node_id
|
if self.app.core.is_runtime():
|
||||||
state = self.canvas.core.get_session_state()
|
self.canvas.core.launch_terminal(self.core_node.id)
|
||||||
if state == core_pb2.SessionState.RUNTIME:
|
|
||||||
self.canvas.core.launch_terminal(node_id)
|
|
||||||
else:
|
else:
|
||||||
self.canvas.canvas_action.display_configuration(self)
|
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):
|
def update_coords(self):
|
||||||
self.x_coord, self.y_coord = self.canvas.coords(self.id)
|
self.x_coord, self.y_coord = self.canvas.coords(self.id)
|
||||||
|
self.core_node.position.x = int(self.x_coord)
|
||||||
|
self.core_node.position.y = int(self.y_coord)
|
||||||
|
|
||||||
def click_press(self, event):
|
def click_press(self, event):
|
||||||
logging.debug(f"node click press {self.name}: {event}")
|
logging.debug(f"node click press {self.name}: {event}")
|
||||||
|
@ -691,7 +660,6 @@ class CanvasNode:
|
||||||
def click_release(self, event):
|
def click_release(self, event):
|
||||||
logging.debug(f"node click release {self.name}: {event}")
|
logging.debug(f"node click release {self.name}: {event}")
|
||||||
self.update_coords()
|
self.update_coords()
|
||||||
self.canvas.core.update_node_location(self.id, self.x_coord, self.y_coord)
|
|
||||||
self.moving = None
|
self.moving = None
|
||||||
|
|
||||||
def motion(self, event):
|
def motion(self, event):
|
||||||
|
@ -711,7 +679,7 @@ class CanvasNode:
|
||||||
new_x, new_y = self.canvas.coords(self.id)
|
new_x, new_y = self.canvas.coords(self.id)
|
||||||
|
|
||||||
if self.canvas.core.get_session_state() == core_pb2.SessionState.RUNTIME:
|
if self.canvas.core.get_session_state() == core_pb2.SessionState.RUNTIME:
|
||||||
self.canvas.core.edit_node(self.core_id, int(new_x), int(new_y))
|
self.canvas.core.edit_node(self.core_node.id, int(new_x), int(new_y))
|
||||||
|
|
||||||
for edge in self.edges:
|
for edge in self.edges:
|
||||||
x1, y1, x2, y2 = self.canvas.coords(edge.id)
|
x1, y1, x2, y2 = self.canvas.coords(edge.id)
|
||||||
|
|
|
@ -29,29 +29,31 @@ class GraphHelper:
|
||||||
self.canvas.delete(i)
|
self.canvas.delete(i)
|
||||||
|
|
||||||
def draw_wireless_case(self, src_id, dst_id, edge):
|
def draw_wireless_case(self, src_id, dst_id, edge):
|
||||||
src_node_name = self.canvas.nodes[src_id].node_type
|
src_node_type = self.canvas.nodes[src_id].core_node.type
|
||||||
dst_node_name = self.canvas.nodes[dst_id].node_type
|
dst_node_type = self.canvas.nodes[dst_id].core_node.type
|
||||||
|
is_src_wlan = src_node_type == core_pb2.NodeType.WIRELESS_LAN
|
||||||
if src_node_name == "wlan" or dst_node_name == "wlan":
|
is_dst_wlan = dst_node_type == core_pb2.NodeType.WIRELESS_LAN
|
||||||
|
if is_src_wlan or is_dst_wlan:
|
||||||
self.canvas.itemconfig(edge.id, state=tk.HIDDEN)
|
self.canvas.itemconfig(edge.id, state=tk.HIDDEN)
|
||||||
edge.wired = False
|
edge.wired = False
|
||||||
if edge.token not in self.canvas.edges:
|
if edge.token not in self.canvas.edges:
|
||||||
if src_node_name == "wlan" and dst_node_name == "wlan":
|
if is_src_wlan and is_dst_wlan:
|
||||||
self.canvas.nodes[src_id].antenna_draw.add_antenna()
|
self.canvas.nodes[src_id].antenna_draw.add_antenna()
|
||||||
elif src_node_name == "wlan":
|
elif is_src_wlan:
|
||||||
self.canvas.nodes[dst_id].antenna_draw.add_antenna()
|
self.canvas.nodes[dst_id].antenna_draw.add_antenna()
|
||||||
else:
|
else:
|
||||||
self.canvas.nodes[src_id].antenna_draw.add_antenna()
|
self.canvas.nodes[src_id].antenna_draw.add_antenna()
|
||||||
|
|
||||||
edge.wired = True
|
edge.wired = True
|
||||||
|
|
||||||
def redraw_antenna(self, link, node_one, node_two):
|
def redraw_antenna(self, link, node_one, node_two):
|
||||||
|
is_node_one_wlan = node_one.core_node.type == core_pb2.NodeType.WIRELESS_LAN
|
||||||
|
is_node_two_wlan = node_two.core_node.type == core_pb2.NodeType.WIRELESS_LAN
|
||||||
if link.type == core_pb2.LinkType.WIRELESS:
|
if link.type == core_pb2.LinkType.WIRELESS:
|
||||||
if node_one.node_type == "wlan" and node_two.node_type == "wlan":
|
if is_node_one_wlan and is_node_two_wlan:
|
||||||
node_one.antenna_draw.add_antenna()
|
node_one.antenna_draw.add_antenna()
|
||||||
elif node_one.node_type == "wlan" and node_two.node_type != "wlan":
|
elif is_node_one_wlan and not is_node_two_wlan:
|
||||||
node_two.antenna_draw.add_antenna()
|
node_two.antenna_draw.add_antenna()
|
||||||
elif node_one.node_type != "wlan" and node_two.node_type == "wlan":
|
elif not is_node_one_wlan and is_node_two_wlan:
|
||||||
node_one.antenna_draw.add_antenna()
|
node_one.antenna_draw.add_antenna()
|
||||||
else:
|
else:
|
||||||
logging.error(
|
logging.error(
|
||||||
|
@ -122,91 +124,3 @@ class WlanAntennaManager:
|
||||||
"""
|
"""
|
||||||
for i in self.antennas:
|
for i in self.antennas:
|
||||||
self.canvas.delete(i)
|
self.canvas.delete(i)
|
||||||
|
|
||||||
|
|
||||||
# class WlanConnection:
|
|
||||||
# def __init__(self, canvas, grpc):
|
|
||||||
# """
|
|
||||||
# create in
|
|
||||||
# :param canvas:
|
|
||||||
# """
|
|
||||||
# self.canvas = canvas
|
|
||||||
# self.core_grpc = grpc
|
|
||||||
# self.throughput_on = False
|
|
||||||
# self.map_node_link = {}
|
|
||||||
# self.links = []
|
|
||||||
#
|
|
||||||
# def wireless_nodes(self):
|
|
||||||
# """
|
|
||||||
# retrieve all the wireless clouds in the canvas
|
|
||||||
#
|
|
||||||
# :return: list(coretk.graph.CanvasNode)
|
|
||||||
# """
|
|
||||||
# wireless_nodes = []
|
|
||||||
# for n in self.canvas.nodes.values():
|
|
||||||
# if n.node_type == "wlan":
|
|
||||||
# wireless_nodes.append(n)
|
|
||||||
# return wireless_nodes
|
|
||||||
#
|
|
||||||
# def draw_wireless_link(self, src, dst):
|
|
||||||
# """
|
|
||||||
# draw a line between 2 nodes that are connected to the same wireless cloud
|
|
||||||
#
|
|
||||||
# :param coretk.graph.CanvasNode src: source node
|
|
||||||
# :param coretk.graph.CanvasNode dst: destination node
|
|
||||||
# :return: nothing
|
|
||||||
# """
|
|
||||||
# cid = self.canvas.create_line(src.x_coord, src.y_coord, dst.x_coord, dst.y_coord, tags="wlanconnection")
|
|
||||||
# if src.id not in self.map_node_link:
|
|
||||||
# self.map_node_link[src.id] = []
|
|
||||||
# if dst.id not in self.map_node_link:
|
|
||||||
# self.map_node_link[dst.id] = []
|
|
||||||
# self.map_node_link[src.id].append(cid)
|
|
||||||
# self.map_node_link[dst.id].append(cid)
|
|
||||||
# self.links.append(cid)
|
|
||||||
#
|
|
||||||
# def subnet_wireless_connection(self, wlan_node):
|
|
||||||
# """
|
|
||||||
# retrieve all the non-wireless nodes connected to wireless_node and create line (represent wireless connection) between each pair of nodes
|
|
||||||
# :param coretk.grpah.CanvasNode wlan_node: wireless node
|
|
||||||
#
|
|
||||||
# :return: nothing
|
|
||||||
# """
|
|
||||||
# non_wlan_nodes = []
|
|
||||||
# for e in wlan_node.edges:
|
|
||||||
# src = self.canvas.nodes[e.src]
|
|
||||||
# dst = self.canvas.nodes[e.dst]
|
|
||||||
# if src.node_type == "wlan" and dst.node_type != "wlan":
|
|
||||||
# non_wlan_nodes.append(dst)
|
|
||||||
# elif src.node_type != "wlan" and dst.node_type == "wlan":
|
|
||||||
# non_wlan_nodes.append(src)
|
|
||||||
#
|
|
||||||
# size = len(non_wlan_nodes)
|
|
||||||
# for i in range(size):
|
|
||||||
# for j in range(i+1, size):
|
|
||||||
# self.draw_wireless_link(non_wlan_nodes[i], non_wlan_nodes[j])
|
|
||||||
#
|
|
||||||
# def session_wireless_connection(self):
|
|
||||||
# """
|
|
||||||
# draw all the wireless connection in the canvas
|
|
||||||
#
|
|
||||||
# :return: nothing
|
|
||||||
# """
|
|
||||||
# wlan_nodes = self.wireless_nodes()
|
|
||||||
# for n in wlan_nodes:
|
|
||||||
# self.subnet_wireless_connection(n)
|
|
||||||
#
|
|
||||||
# def show_links(self):
|
|
||||||
# """
|
|
||||||
# show all the links
|
|
||||||
# """
|
|
||||||
# for l in self.links:
|
|
||||||
# self.canvas.itemconfig(l, state=tk.NORMAL)
|
|
||||||
#
|
|
||||||
# def hide_links(self):
|
|
||||||
# """
|
|
||||||
# hide all the links
|
|
||||||
# :return:
|
|
||||||
# """
|
|
||||||
# for l in self.links:
|
|
||||||
# self.canvas.itemconfig(l, state=tk.HIDDEN)
|
|
||||||
|
|
BIN
coretk/coretk/icons/docker.gif
Normal file
BIN
coretk/coretk/icons/docker.gif
Normal file
Binary file not shown.
After Width: | Height: | Size: 719 B |
BIN
coretk/coretk/icons/lxc.gif
Normal file
BIN
coretk/coretk/icons/lxc.gif
Normal file
Binary file not shown.
After Width: | Height: | Size: 724 B |
|
@ -31,7 +31,7 @@ class Images:
|
||||||
return cls.create(file_path, width, height)
|
return cls.create(file_path, width, height)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def get_custom(cls, name, width, height):
|
def get_custom(cls, name, width, height=None):
|
||||||
file_path = cls.images[name]
|
file_path = cls.images[name]
|
||||||
return cls.create(file_path, width, height)
|
return cls.create(file_path, width, height)
|
||||||
|
|
||||||
|
@ -41,52 +41,38 @@ class Images:
|
||||||
Retrieve image based on type and model
|
Retrieve image based on type and model
|
||||||
:param core_pb2.NodeType node_type: core node type
|
:param core_pb2.NodeType node_type: core node type
|
||||||
:param string node_model: the node model
|
:param string node_model: the node model
|
||||||
|
:return: core node icon
|
||||||
:rtype: tuple(PhotoImage, str)
|
:rtype: PhotoImage
|
||||||
:return: the matching image and its name
|
|
||||||
"""
|
"""
|
||||||
image_enum = ImageEnum.ROUTER
|
image_enum = ImageEnum.ROUTER
|
||||||
name = "unknown"
|
|
||||||
if node_type == core_pb2.NodeType.SWITCH:
|
if node_type == core_pb2.NodeType.SWITCH:
|
||||||
image_enum = ImageEnum.SWITCH
|
image_enum = ImageEnum.SWITCH
|
||||||
name = "switch"
|
|
||||||
elif node_type == core_pb2.NodeType.HUB:
|
elif node_type == core_pb2.NodeType.HUB:
|
||||||
image_enum = ImageEnum.HUB
|
image_enum = ImageEnum.HUB
|
||||||
name = "hub"
|
|
||||||
elif node_type == core_pb2.NodeType.WIRELESS_LAN:
|
elif node_type == core_pb2.NodeType.WIRELESS_LAN:
|
||||||
image_enum = ImageEnum.WLAN
|
image_enum = ImageEnum.WLAN
|
||||||
name = "wlan"
|
|
||||||
elif node_type == core_pb2.NodeType.EMANE:
|
elif node_type == core_pb2.NodeType.EMANE:
|
||||||
image_enum = ImageEnum.EMANE
|
image_enum = ImageEnum.EMANE
|
||||||
name = "emane"
|
|
||||||
elif node_type == core_pb2.NodeType.RJ45:
|
elif node_type == core_pb2.NodeType.RJ45:
|
||||||
image_enum = ImageEnum.RJ45
|
image_enum = ImageEnum.RJ45
|
||||||
name = "rj45"
|
|
||||||
elif node_type == core_pb2.NodeType.TUNNEL:
|
elif node_type == core_pb2.NodeType.TUNNEL:
|
||||||
image_enum = ImageEnum.TUNNEL
|
image_enum = ImageEnum.TUNNEL
|
||||||
name = "tunnel"
|
|
||||||
elif node_type == core_pb2.NodeType.DEFAULT:
|
elif node_type == core_pb2.NodeType.DEFAULT:
|
||||||
if node_model == "router":
|
if node_model == "router":
|
||||||
image_enum = ImageEnum.ROUTER
|
image_enum = ImageEnum.ROUTER
|
||||||
name = "router"
|
|
||||||
elif node_model == "host":
|
elif node_model == "host":
|
||||||
image_enum = ImageEnum.HOST
|
image_enum = ImageEnum.HOST
|
||||||
name = "host"
|
|
||||||
elif node_model == "PC":
|
elif node_model == "PC":
|
||||||
image_enum = ImageEnum.PC
|
image_enum = ImageEnum.PC
|
||||||
name = "PC"
|
|
||||||
elif node_model == "mdr":
|
elif node_model == "mdr":
|
||||||
image_enum = ImageEnum.MDR
|
image_enum = ImageEnum.MDR
|
||||||
name = "mdr"
|
|
||||||
elif node_model == "prouter":
|
elif node_model == "prouter":
|
||||||
image_enum = ImageEnum.PROUTER
|
image_enum = ImageEnum.PROUTER
|
||||||
name = "prouter"
|
|
||||||
else:
|
else:
|
||||||
logging.error("invalid node model: %s", node_model)
|
logging.error("invalid node model: %s", node_model)
|
||||||
else:
|
else:
|
||||||
logging.error("invalid node type: %s", node_type)
|
logging.error("invalid node type: %s", node_type)
|
||||||
|
return Images.get(image_enum, NODE_WIDTH)
|
||||||
return Images.get(image_enum, NODE_WIDTH), name
|
|
||||||
|
|
||||||
|
|
||||||
class ImageEnum(Enum):
|
class ImageEnum(Enum):
|
||||||
|
@ -121,3 +107,5 @@ class ImageEnum(Enum):
|
||||||
FILEOPEN = "fileopen"
|
FILEOPEN = "fileopen"
|
||||||
EDITDELETE = "edit-delete"
|
EDITDELETE = "edit-delete"
|
||||||
ANTENNA = "antenna"
|
ANTENNA = "antenna"
|
||||||
|
DOCKER = "docker"
|
||||||
|
LXC = "lxc"
|
||||||
|
|
|
@ -1,35 +1,4 @@
|
||||||
import ipaddress
|
import ipaddress
|
||||||
import random
|
|
||||||
|
|
||||||
|
|
||||||
class Interface:
|
|
||||||
def __init__(self, name, ipv4, ifid=None):
|
|
||||||
"""
|
|
||||||
Create an interface instance
|
|
||||||
|
|
||||||
:param str name: interface name
|
|
||||||
:param str ip4: IPv4
|
|
||||||
:param str mac: MAC address
|
|
||||||
:param int ifid: interface id
|
|
||||||
"""
|
|
||||||
self.name = name
|
|
||||||
self.ipv4 = ipv4
|
|
||||||
self.ip4prefix = 24
|
|
||||||
self.ip4_and_prefix = ipv4 + "/" + str(self.ip4prefix)
|
|
||||||
self.mac = self.random_mac_address()
|
|
||||||
self.id = ifid
|
|
||||||
|
|
||||||
def random_mac_address(self):
|
|
||||||
"""
|
|
||||||
create a random MAC address for an interface
|
|
||||||
|
|
||||||
:return: nothing
|
|
||||||
"""
|
|
||||||
return "02:00:00:%02x:%02x:%02x" % (
|
|
||||||
random.randint(0, 255),
|
|
||||||
random.randint(0, 255),
|
|
||||||
random.randint(0, 225),
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
class SubnetAddresses:
|
class SubnetAddresses:
|
||||||
|
@ -46,18 +15,13 @@ class SubnetAddresses:
|
||||||
|
|
||||||
class InterfaceManager:
|
class InterfaceManager:
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
# self.prefix = None
|
|
||||||
self.core_subnets = list(
|
self.core_subnets = list(
|
||||||
ipaddress.ip_network("10.0.0.0/12").subnets(prefixlen_diff=12)
|
ipaddress.ip_network("10.0.0.0/12").subnets(prefixlen_diff=12)
|
||||||
)
|
)
|
||||||
self.subnet_index = 0
|
self.subnet_index = 0
|
||||||
self.address_index = 0
|
self.address_index = 0
|
||||||
|
|
||||||
# self.network = ipaddress.ip_network("10.0.0.0/24")
|
|
||||||
# self.addresses = list(self.network.hosts())
|
|
||||||
self.network = None
|
self.network = None
|
||||||
self.addresses = None
|
self.addresses = None
|
||||||
# self.start_interface_manager()
|
|
||||||
|
|
||||||
def start_interface_manager(self):
|
def start_interface_manager(self):
|
||||||
self.subnet_index = 0
|
self.subnet_index = 0
|
||||||
|
@ -72,24 +36,10 @@ class InterfaceManager:
|
||||||
|
|
||||||
:return:
|
:return:
|
||||||
"""
|
"""
|
||||||
# i = self.index
|
|
||||||
# self.address_index = self.index + 1
|
|
||||||
# return self.addresses[i]
|
|
||||||
ipaddr = self.addresses[self.address_index]
|
ipaddr = self.addresses[self.address_index]
|
||||||
self.address_index = self.address_index + 1
|
self.address_index = self.address_index + 1
|
||||||
return ipaddr
|
return ipaddr
|
||||||
|
|
||||||
def new_subnet(self):
|
def new_subnet(self):
|
||||||
self.network = self.core_subnets[self.subnet_index]
|
self.network = self.core_subnets[self.subnet_index]
|
||||||
# self.subnet_index = self.subnet_index + 1
|
|
||||||
self.addresses = list(self.network.hosts())
|
self.addresses = list(self.network.hosts())
|
||||||
# self.address_index = 0
|
|
||||||
|
|
||||||
# def new_subnet(self):
|
|
||||||
# """
|
|
||||||
# retrieve a new subnet
|
|
||||||
# :return:
|
|
||||||
# """
|
|
||||||
# if self.prefix is None:
|
|
||||||
# self.prefix =
|
|
||||||
# self.addresses = list(ipaddress.ip_network("10.0.0.0/24").hosts())
|
|
||||||
|
|
|
@ -4,8 +4,6 @@ Link information, such as IPv4, IPv6 and throughput drawn in the canvas
|
||||||
import logging
|
import logging
|
||||||
import math
|
import math
|
||||||
|
|
||||||
WIRELESS_DEF = ["mdr", "wlan"]
|
|
||||||
|
|
||||||
|
|
||||||
class LinkInfo:
|
class LinkInfo:
|
||||||
def __init__(self, canvas, edge, ip4_src, ip6_src, ip4_dst, ip6_dst):
|
def __init__(self, canvas, edge, ip4_src, ip6_src, ip4_dst, ip6_dst):
|
||||||
|
@ -129,8 +127,7 @@ class Throughput:
|
||||||
nid = t.node_id
|
nid = t.node_id
|
||||||
iid = t.interface_id
|
iid = t.interface_id
|
||||||
tp = t.throughput
|
tp = t.throughput
|
||||||
# token = self.grpc_manager.node_id_and_interface_to_edge_token[nid, iid]
|
token = self.core.interface_to_edge[(nid, iid)]
|
||||||
token = self.core.core_mapping.get_token_from_node_and_interface(nid, iid)
|
|
||||||
print(token)
|
print(token)
|
||||||
edge_id = self.canvas.edges[token].id
|
edge_id = self.canvas.edges[token].id
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,7 @@ import tkinter as tk
|
||||||
from functools import partial
|
from functools import partial
|
||||||
from tkinter import ttk
|
from tkinter import ttk
|
||||||
|
|
||||||
|
from core.api.grpc import core_pb2
|
||||||
from coretk.dialogs.customnodes import CustomNodesDialog
|
from coretk.dialogs.customnodes import CustomNodesDialog
|
||||||
from coretk.graph import GraphMode
|
from coretk.graph import GraphMode
|
||||||
from coretk.images import ImageEnum, Images
|
from coretk.images import ImageEnum, Images
|
||||||
|
@ -129,22 +130,32 @@ class Toolbar(ttk.Frame):
|
||||||
self.hide_pickers()
|
self.hide_pickers()
|
||||||
self.node_picker = ttk.Frame(self.master)
|
self.node_picker = ttk.Frame(self.master)
|
||||||
nodes = [
|
nodes = [
|
||||||
(ImageEnum.ROUTER, "router"),
|
(ImageEnum.ROUTER, core_pb2.NodeType.DEFAULT, "router"),
|
||||||
(ImageEnum.HOST, "host"),
|
(ImageEnum.HOST, core_pb2.NodeType.DEFAULT, "host"),
|
||||||
(ImageEnum.PC, "PC"),
|
(ImageEnum.PC, core_pb2.NodeType.DEFAULT, "PC"),
|
||||||
(ImageEnum.MDR, "mdr"),
|
(ImageEnum.MDR, core_pb2.NodeType.DEFAULT, "mdr"),
|
||||||
(ImageEnum.PROUTER, "prouter"),
|
(ImageEnum.PROUTER, core_pb2.NodeType.DEFAULT, "prouter"),
|
||||||
|
(ImageEnum.DOCKER, core_pb2.NodeType.DOCKER, "Docker"),
|
||||||
|
(ImageEnum.LXC, core_pb2.NodeType.LXC, "LXC"),
|
||||||
]
|
]
|
||||||
# draw default nodes
|
# draw default nodes
|
||||||
for image_enum, tooltip in nodes:
|
for image_enum, node_type, model in nodes:
|
||||||
image = icon(image_enum)
|
image = icon(image_enum)
|
||||||
func = partial(self.update_button, self.node_button, image, tooltip)
|
func = partial(
|
||||||
self.create_picker_button(image, func, self.node_picker, tooltip)
|
self.update_button, self.node_button, image, node_type, model
|
||||||
|
)
|
||||||
|
self.create_picker_button(image, func, self.node_picker, model)
|
||||||
# draw custom nodes
|
# draw custom nodes
|
||||||
for name in sorted(self.app.core.custom_nodes):
|
for name in sorted(self.app.core.custom_nodes):
|
||||||
custom_node = self.app.core.custom_nodes[name]
|
custom_node = self.app.core.custom_nodes[name]
|
||||||
image = custom_node.image
|
image = custom_node.image
|
||||||
func = partial(self.update_button, self.node_button, image, name)
|
func = partial(
|
||||||
|
self.update_button,
|
||||||
|
self.node_button,
|
||||||
|
image,
|
||||||
|
core_pb2.NodeType.DEFAULT,
|
||||||
|
name,
|
||||||
|
)
|
||||||
self.create_picker_button(image, func, self.node_picker, name)
|
self.create_picker_button(image, func, self.node_picker, name)
|
||||||
# draw edit node
|
# draw edit node
|
||||||
image = icon(ImageEnum.EDITNODE)
|
image = icon(ImageEnum.EDITNODE)
|
||||||
|
@ -216,14 +227,15 @@ class Toolbar(ttk.Frame):
|
||||||
dialog = CustomNodesDialog(self.app, self.app)
|
dialog = CustomNodesDialog(self.app, self.app)
|
||||||
dialog.show()
|
dialog.show()
|
||||||
|
|
||||||
def update_button(self, button, image, name):
|
def update_button(self, button, image, node_type, model=None):
|
||||||
logging.info("update button(%s): %s", button, name)
|
logging.info("update button(%s): %s", button, node_type)
|
||||||
self.hide_pickers()
|
self.hide_pickers()
|
||||||
button.configure(image=image)
|
button.configure(image=image)
|
||||||
button.image = image
|
button.image = image
|
||||||
self.app.canvas.mode = GraphMode.NODE
|
self.app.canvas.mode = GraphMode.NODE
|
||||||
self.app.canvas.draw_node_image = image
|
self.app.canvas.draw_node_image = image
|
||||||
self.app.canvas.draw_node_name = name
|
self.app.canvas.draw_node_type = node_type
|
||||||
|
self.app.canvas.draw_node_model = model
|
||||||
|
|
||||||
def hide_pickers(self):
|
def hide_pickers(self):
|
||||||
logging.info("hiding pickers")
|
logging.info("hiding pickers")
|
||||||
|
@ -260,18 +272,18 @@ class Toolbar(ttk.Frame):
|
||||||
self.hide_pickers()
|
self.hide_pickers()
|
||||||
self.network_picker = ttk.Frame(self.master)
|
self.network_picker = ttk.Frame(self.master)
|
||||||
nodes = [
|
nodes = [
|
||||||
(ImageEnum.HUB, "hub", "ethernet hub"),
|
(ImageEnum.HUB, core_pb2.NodeType.HUB, "ethernet hub"),
|
||||||
(ImageEnum.SWITCH, "switch", "ethernet switch"),
|
(ImageEnum.SWITCH, core_pb2.NodeType.SWITCH, "ethernet switch"),
|
||||||
(ImageEnum.WLAN, "wlan", "wireless LAN"),
|
(ImageEnum.WLAN, core_pb2.NodeType.WIRELESS_LAN, "wireless LAN"),
|
||||||
(ImageEnum.EMANE, "emane", "EMANE"),
|
(ImageEnum.EMANE, core_pb2.NodeType.EMANE, "EMANE"),
|
||||||
(ImageEnum.RJ45, "rj45", "rj45 physical interface tool"),
|
(ImageEnum.RJ45, core_pb2.NodeType.RJ45, "rj45 physical interface tool"),
|
||||||
(ImageEnum.TUNNEL, "tunnel", "tunnel tool"),
|
(ImageEnum.TUNNEL, core_pb2.NodeType.TUNNEL, "tunnel tool"),
|
||||||
]
|
]
|
||||||
for image_enum, name, tooltip in nodes:
|
for image_enum, node_type, tooltip in nodes:
|
||||||
image = icon(image_enum)
|
image = icon(image_enum)
|
||||||
self.create_picker_button(
|
self.create_picker_button(
|
||||||
image,
|
image,
|
||||||
partial(self.update_button, self.network_button, image, name),
|
partial(self.update_button, self.network_button, image, node_type),
|
||||||
self.network_picker,
|
self.network_picker,
|
||||||
tooltip,
|
tooltip,
|
||||||
)
|
)
|
||||||
|
@ -367,6 +379,7 @@ class Toolbar(ttk.Frame):
|
||||||
"""
|
"""
|
||||||
logging.debug("Click on STOP button ")
|
logging.debug("Click on STOP button ")
|
||||||
self.app.core.stop_session()
|
self.app.core.stop_session()
|
||||||
|
self.app.canvas.delete("wireless")
|
||||||
self.design_frame.tkraise()
|
self.design_frame.tkraise()
|
||||||
|
|
||||||
def update_annotation(self, image):
|
def update_annotation(self, image):
|
||||||
|
|
|
@ -7,35 +7,31 @@ from core.api.grpc import core_pb2
|
||||||
class WirelessConnection:
|
class WirelessConnection:
|
||||||
def __init__(self, canvas, core):
|
def __init__(self, canvas, core):
|
||||||
self.canvas = canvas
|
self.canvas = canvas
|
||||||
self.core_mapping = core.core_mapping
|
self.core = core
|
||||||
# map a (node_one_id, node_two_id) to a wlan canvas id
|
# map a (node_one_id, node_two_id) to a wlan canvas id
|
||||||
self.map = {}
|
self.map = {}
|
||||||
|
|
||||||
def add_wlan_connection(self, node_one_id, node_two_id):
|
def add_wlan_connection(self, node_one_id, node_two_id):
|
||||||
canvas_id_one = self.core_mapping.get_canvas_id_from_core_id(node_one_id)
|
canvas_node_one = self.core.canvas_nodes[node_one_id]
|
||||||
canvas_id_two = self.core_mapping.get_canvas_id_from_core_id(node_two_id)
|
canvas_node_two = self.core.canvas_nodes[node_two_id]
|
||||||
key = tuple(sorted((node_one_id, node_two_id)))
|
key = tuple(sorted((node_one_id, node_two_id)))
|
||||||
|
|
||||||
if key not in self.map:
|
if key not in self.map:
|
||||||
x1, y1 = self.canvas.coords(canvas_id_one)
|
x1, y1 = self.canvas.coords(canvas_node_one.id)
|
||||||
x2, y2 = self.canvas.coords(canvas_id_two)
|
x2, y2 = self.canvas.coords(canvas_node_two.id)
|
||||||
wlan_canvas_id = self.canvas.create_line(
|
wlan_canvas_id = self.canvas.create_line(
|
||||||
x1, y1, x2, y2, fill="#009933", tags="wlan", width=1.5
|
x1, y1, x2, y2, fill="#009933", tags="wireless", width=1.5
|
||||||
)
|
)
|
||||||
self.map[key] = wlan_canvas_id
|
self.map[key] = wlan_canvas_id
|
||||||
self.canvas.nodes[canvas_id_one].wlans.append(wlan_canvas_id)
|
canvas_node_one.wlans.append(wlan_canvas_id)
|
||||||
self.canvas.nodes[canvas_id_two].wlans.append(wlan_canvas_id)
|
canvas_node_two.wlans.append(wlan_canvas_id)
|
||||||
|
|
||||||
def delete_wlan_connection(self, node_one_id, node_two_id):
|
def delete_wlan_connection(self, node_one_id, node_two_id):
|
||||||
canvas_id_one = self.core_mapping.get_canvas_id_from_core_id(node_one_id)
|
canvas_node_one = self.core.canvas_nodes[node_one_id]
|
||||||
canvas_id_two = self.core_mapping.get_canvas_id_from_core_id(node_two_id)
|
canvas_node_two = self.core.canvas_nodes[node_two_id]
|
||||||
|
|
||||||
key = tuple(sorted((node_one_id, node_two_id)))
|
key = tuple(sorted((node_one_id, node_two_id)))
|
||||||
wlan_canvas_id = self.map[key]
|
wlan_canvas_id = self.map[key]
|
||||||
|
canvas_node_one.wlans.remove(wlan_canvas_id)
|
||||||
self.canvas.nodes[canvas_id_one].wlans.remove(wlan_canvas_id)
|
canvas_node_two.wlans.remove(wlan_canvas_id)
|
||||||
self.canvas.nodes[canvas_id_two].wlans.remove(wlan_canvas_id)
|
|
||||||
|
|
||||||
self.canvas.delete(wlan_canvas_id)
|
self.canvas.delete(wlan_canvas_id)
|
||||||
self.map.pop(key, None)
|
self.map.pop(key, None)
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue