From fa76bbf01b55bc9a1e28c4e3fe098e288600cf9c Mon Sep 17 00:00:00 2001 From: bharnden <32446120+bharnden@users.noreply.github.com> Date: Thu, 14 Nov 2019 21:39:44 -0800 Subject: [PATCH 1/4] removed unused code in graph and coreclient --- coretk/coretk/coreclient.py | 17 ----------------- coretk/coretk/graph.py | 14 -------------- 2 files changed, 31 deletions(-) diff --git a/coretk/coretk/coreclient.py b/coretk/coretk/coreclient.py index 0d562f8a..2bf047d7 100644 --- a/coretk/coretk/coreclient.py +++ b/coretk/coretk/coreclient.py @@ -372,23 +372,6 @@ class CoreClient: response = self.client.stop_session(session_id=self.session_id) logging.debug("coregrpc.py Stop session, result: %s", response.result) - # # TODO no need, might get rid of this - # def add_link(self, id1, id2, type1, type2, edge): - # """ - # Grpc client request add link - # - # :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): response = self.client.get_node_terminal(self.session_id, node_id) logging.info("get terminal %s", response.terminal) diff --git a/coretk/coretk/graph.py b/coretk/coretk/graph.py index e5bab65b..f7c45e63 100644 --- a/coretk/coretk/graph.py +++ b/coretk/coretk/graph.py @@ -31,12 +31,6 @@ class ScaleOption(enum.Enum): TILED = 4 -CORE_NODES = ["router"] -CORE_WIRED_NETWORK_NODES = [] -CORE_WIRELESS_NODE = ["wlan"] -CORE_EMANE = ["emane"] - - class CanvasGraph(tk.Canvas): def __init__(self, master, core, cnf=None, **kwargs): if cnf is None: @@ -670,14 +664,6 @@ class CanvasNode: self.canvas.core.launch_terminal(node_id) else: self.canvas.canvas_action.display_configuration(self) - # if self.node_type in CORE_NODES: - # self.canvas.canvas_action.node_to_show_config = self - # self.canvas.canvas_action.display_node_configuration() - # elif self.node_type in CORE_WIRED_NETWORK_NODES: - # return - # elif self.node_type in CORE_WIRELESS_NODE: - # return - # elif self def update_coords(self): self.x_coord, self.y_coord = self.canvas.coords(self.id) From 6d38058887b9f8d9af47850d6fb1f8c019766c64 Mon Sep 17 00:00:00 2001 From: bharnden <32446120+bharnden@users.noreply.github.com> Date: Fri, 15 Nov 2019 10:22:30 -0800 Subject: [PATCH 2/4] update node creation and storage to leverage protobufs directly --- coretk/coretk/canvasaction.py | 2 - coretk/coretk/coreclient.py | 343 ++++++++-------------------- coretk/coretk/coretocanvas.py | 34 --- coretk/coretk/dialogs/nodeconfig.py | 2 +- coretk/coretk/graph.py | 154 ++++++------- coretk/coretk/graph_helper.py | 110 +-------- coretk/coretk/images.py | 22 +- coretk/coretk/linkinfo.py | 3 +- coretk/coretk/toolbar.py | 36 +-- coretk/coretk/wirelessconnection.py | 26 +-- 10 files changed, 216 insertions(+), 516 deletions(-) delete mode 100644 coretk/coretk/coretocanvas.py diff --git a/coretk/coretk/canvasaction.py b/coretk/coretk/canvasaction.py index decf43f3..8f217833 100644 --- a/coretk/coretk/canvasaction.py +++ b/coretk/coretk/canvasaction.py @@ -36,8 +36,6 @@ class CanvasAction: self.node_to_show_config = None def display_wlan_configuration(self, canvas_node): - - # print(self.canvas.grpc_manager.wlanconfig_management.configurations) wlan_config = self.master.core.wlanconfig_management.configurations[ canvas_node.core_id ] diff --git a/coretk/coretk/coreclient.py b/coretk/coretk/coreclient.py index 2bf047d7..d80f6e5c 100644 --- a/coretk/coretk/coreclient.py +++ b/coretk/coretk/coreclient.py @@ -5,7 +5,6 @@ import logging import os from core.api.grpc import client, core_pb2 -from coretk.coretocanvas import CoreToCanvasMapping from coretk.dialogs.sessions import SessionsDialog from coretk.emaneodelnodeconfig import EmaneModelNodeConfig from coretk.images import NODE_WIDTH, Images @@ -29,28 +28,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): """ @@ -112,15 +89,15 @@ class CoreClient: self.read_config() # data for managing the current session + self.canvas_nodes = {} + self.interface_to_edge = {} self.state = None - self.nodes = {} self.edges = {} self.hooks = {} self.id = 1 self.reusable = [] self.preexisting = set() self.interfaces_manager = InterfaceManager() - self.core_mapping = CoreToCanvasMapping() self.wlanconfig_management = WlanNodeConfig() self.mobilityconfig_management = MobilityNodeConfig() self.emaneconfig_management = EmaneModelNodeConfig(app) @@ -179,7 +156,7 @@ class CoreClient: # clear session data self.reusable.clear() self.preexisting.clear() - self.nodes.clear() + self.canvas_nodes.clear() self.edges.clear() self.hooks.clear() self.wlanconfig_management.configurations.clear() @@ -203,14 +180,14 @@ class CoreClient: for node in session.nodes: if node.type == core_pb2.NodeType.WIRELESS_LAN: response = self.client.get_wlan_config(self.session_id, node.id) - logging.info("wlan config(%s): %s", node.id, response) + logging.debug("wlan config(%s): %s", node.id, response) node_config = response.config config = {x: node_config[x].value for x in node_config} self.wlanconfig_management.configurations[node.id] = config # get mobility configs response = self.client.get_mobility_configs(self.session_id) - logging.info("mobility configs: %s", response) + logging.debug("mobility configs: %s", response) for node_id in response.configs: node_config = response.configs[node_id].config config = {x: node_config[x].value for x in node_config} @@ -218,7 +195,7 @@ class CoreClient: # get emane config 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 # get emane model config @@ -339,7 +316,7 @@ class CoreClient: logging.info("delete links %s", response) 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() wlan_configs = self.get_wlan_configs_proto() mobility_configs = self.get_mobility_configs_proto() @@ -411,7 +388,7 @@ class CoreClient: logging.debug("set node service %s", response) def create_nodes_and_links(self): - node_protos = self.get_nodes_proto() + node_protos = [x.core_node for x in self.canvas_nodes.values()] link_protos = self.get_links_proto() self.client.set_session_state(self.session_id, core_pb2.SessionState.DEFINITION) for node_proto in node_protos: @@ -437,17 +414,6 @@ class CoreClient: logging.debug("Close grpc") 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): """ Get the next node id as well as update id status and reusable ids @@ -465,106 +431,87 @@ class CoreClient: def is_model_node(self, name): 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 - :param int session_id: session id - :param int canvas_id: node's canvas id :param int x: x 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 """ - node_type = None - node_model = None - if name in NETWORK_NODES: - if name == "switch": - node_type = core_pb2.NodeType.SWITCH - elif name == "hub": - node_type = core_pb2.NodeType.HUB - elif name == "wlan": - 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) + node_id = self.get_id() + position = core_pb2.Position(x=x, y=y) + node = core_pb2.Node( + id=node_id, + type=node_type, + name=f"n{node_id}", + model=model, + position=position, + ) # set default configuration for wireless node - self.wlanconfig_management.set_default_config(node_type, nid) - self.mobilityconfig_management.set_default_configuration(node_type, nid) + self.wlanconfig_management.set_default_config(node_type, node_id) + self.mobilityconfig_management.set_default_configuration(node_type, node_id) # set default emane configuration for emane node if node_type == core_pb2.NodeType.EMANE: - self.emaneconfig_management.set_default_config(nid) + self.emaneconfig_management.set_default_config(node_id) # set default service configurations if node_type == core_pb2.NodeType.DEFAULT: 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( - "Adding node to core.. session id: %s, coords: (%s, %s), name: %s", - session_id, + "adding node to core session: %s, coords: (%s, %s), name: %s", + self.session_id, x, 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 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 """ - # 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 - for i in canvas_ids: + for node_id in node_ids: try: - n = self.nodes.pop(i) - self.reusable.append(n.node_id) + del self.canvas_nodes[node_id] + self.reusable.append(node_id) except KeyError: - logging.error("coreclient.py INVALID NODE CANVAS ID") - + logging.error("invalid canvas id: %s", node_id) self.reusable.sort() # delete the edges and interfaces - for i in tokens: + node_interface_pairs = [] + for i in edge_tokens: try: e = self.edges.pop(i) if e.interface_1 is not None: node_interface_pairs.append(tuple([e.id1, e.interface_1.id])) if e.interface_2 is not None: node_interface_pairs.append(tuple([e.id2, e.interface_2.id])) - except KeyError: logging.error("coreclient.py invalid edge token ") # 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 # delete any mobility configuration, wlan configuration - for i in core_node_ids: + for i in node_ids: if i in self.mobilityconfig_management.configurations: self.mobilityconfig_management.configurations.pop(i) if i in self.wlanconfig_management.configurations: @@ -574,69 +521,16 @@ class CoreClient: for i in node_interface_pairs: if i in self.emaneconfig_management.configurations: 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: self.emaneconfig_management.configurations.pop(tuple([i, None])) - def add_preexisting_node(self, canvas_node, session_id, core_node, name): - """ - Add preexisting nodes to grpc manager - - :param str name: node_type - :param core_pb2.Node core_node: core node grpc message - :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 + :param core_bp2.NodeType node_type: node type + :param coretk.interface.Interface gui_interface: the programmer's interface :rtype: core_bp2.Interface :return: protobuf interface object """ @@ -653,120 +547,71 @@ class CoreClient: logging.debug("create interface: %s", 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( + def create_edge_interface(self, canvas_node): + interface = None + core_node = canvas_node.core_node + if self.is_model_node(core_node.model): + ifid = len(canvas_node.interfaces) + name = f"eth{ifid}" + interface = Interface( name=name, ifid=ifid, ipv4=str(self.interfaces_manager.get_address()) ) - self.nodes[src_canvas_id].interfaces.append(src_interface) + canvas_node.interfaces.append(interface) logging.debug( - "Create source interface 1... IP: %s, name: %s", - src_interface.ipv4, - src_interface.name, + "create node(%s) interface IP: %s, name: %s", + core_node.name, + interface.ipv4, + interface.name, ) + return interface - dst_node = self.nodes[dst_canvas_id] - 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): + def create_edge(self, token, canvas_node_one, canvas_node_two): """ Add an edge to grpc manager - :param int session_id: core session id :param tuple(int, int) token: edge's identification in the canvas - :param int canvas_id_1: canvas id of source node - :param int canvas_id_2: canvas_id of destination node + :param canvas_node_one: canvas node one + :param canvas_node_two: canvas node two :return: nothing """ - node_one = self.nodes[canvas_id_1] - node_two = self.nodes[canvas_id_2] - 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 + node_one = canvas_node_one.core_node + node_two = canvas_node_two.core_node - # provide a way to get an edge from a core node and an interface id - if src_interface is not None: - self.core_mapping.map_node_and_interface_to_canvas_edge( - node_one_id, src_interface.id, token + # create interfaces + self.interfaces_manager.new_subnet() + interface_one = self.create_edge_interface(canvas_node_one) + if interface_one is not None: + self.interface_to_edge[(node_one.id, interface_one.id)] = token + interface_two = self.create_edge_interface(canvas_node_two) + if interface_two is not None: + self.interface_to_edge[(node_two.id, interface_two.id)] = token + + # emane setup + 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: - self.core_mapping.map_node_and_interface_to_canvas_edge( - node_two_id, dst_interface.id, token - ) - - 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, 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 + edge = Edge( + self.session_id, node_one.id, node_one.type, node_two.id, node_two.type + ) + edge.interface_1 = interface_one + edge.interface_2 = interface_two + self.edges[token] = edge + return edge def get_links_proto(self): links = [] diff --git a/coretk/coretk/coretocanvas.py b/coretk/coretk/coretocanvas.py deleted file mode 100644 index 6e767db3..00000000 --- a/coretk/coretk/coretocanvas.py +++ /dev/null @@ -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 diff --git a/coretk/coretk/dialogs/nodeconfig.py b/coretk/coretk/dialogs/nodeconfig.py index 48233762..14e9de03 100644 --- a/coretk/coretk/dialogs/nodeconfig.py +++ b/coretk/coretk/dialogs/nodeconfig.py @@ -21,7 +21,7 @@ class NodeConfigDialog(Dialog): self.image = canvas_node.image self.image_button = None 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.draw() diff --git a/coretk/coretk/graph.py b/coretk/coretk/graph.py index f7c45e63..1fcafac1 100644 --- a/coretk/coretk/graph.py +++ b/coretk/coretk/graph.py @@ -39,7 +39,8 @@ class CanvasGraph(tk.Canvas): super().__init__(master, cnf, **kwargs) self.mode = GraphMode.SELECT self.draw_node_image = None - self.draw_node_name = None + self.draw_node_type = None + self.draw_node_model = None self.selected = None self.node_context = None self.nodes = {} @@ -97,13 +98,14 @@ class CanvasGraph(tk.Canvas): # set the private variables to default value self.mode = GraphMode.SELECT self.draw_node_image = None - self.draw_node_name = None + self.draw_node_type = None + self.draw_node_model = None self.selected = None self.node_context = None self.nodes.clear() self.edges.clear() self.drawing_edge = None - self.draw_existing_component(session) + self.draw_session(session) def setup_bindings(self): """ @@ -143,61 +145,46 @@ class CanvasGraph(tk.Canvas): self.tag_lower("gridline") 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 """ - core_id_to_canvas_id = {} - # redraw existing nodes - for node in session.nodes: + # draw existing nodes + for core_node in session.nodes: # peer to peer node is not drawn on the GUI - if node.type != core_pb2.NodeType.PEER_TO_PEER: - # draw nodes on the canvas - image, name = Images.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 + if core_node.type == core_pb2.NodeType.PEER_TO_PEER: + continue - # store the node in grpc manager - self.core.add_preexisting_node(n, session.id, node, name) + # draw nodes on the canvas + 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 for link in session.links: - n1 = self.nodes[core_id_to_canvas_id[link.node_one_id]] - n2 = self.nodes[core_id_to_canvas_id[link.node_two_id]] - if link.type == core_pb2.LinkType.WIRED: - e = CanvasEdge( - n1.x_coord, - n1.y_coord, - n2.x_coord, - n2.y_coord, - n1.id, - self, - is_wired=True, - ) - elif link.type == core_pb2.LinkType.WIRELESS: - e = CanvasEdge( - n1.x_coord, - n1.y_coord, - n2.x_coord, - n2.y_coord, - n1.id, - 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) + canvas_node_one = self.core.canvas_nodes[link.node_one_id] + canvas_node_two = self.core.canvas_nodes[link.node_two_id] + is_wired = link.type == core_pb2.LinkType.WIRED + edge = CanvasEdge( + canvas_node_one.x_coord, + canvas_node_one.y_coord, + canvas_node_two.x_coord, + canvas_node_two.y_coord, + canvas_node_one.id, + self, + is_wired=is_wired, + ) + edge.token = tuple(sorted((canvas_node_one.id, canvas_node_two.id))) + edge.dst = canvas_node_two.id + canvas_node_one.edges.add(edge) + canvas_node_two.edges.add(edge) + self.edges[edge.token] = edge + self.core.create_edge(edge.token, canvas_node_one, canvas_node_two) + self.helper.redraw_antenna(link, canvas_node_one, canvas_node_two) # TODO add back the link info to grpc manager also redraw grpc_if1 = link.interface_one @@ -212,9 +199,9 @@ class CanvasGraph(tk.Canvas): if grpc_if2 is not None: ip4_dst = grpc_if2.ip4 ip6_dst = grpc_if2.ip6 - e.link_info = LinkInfo( + edge.link_info = LinkInfo( canvas=self, - edge=e, + edge=edge, ip4_src=ip4_src, ip6_src=ip6_src, ip4_dst=ip4_dst, @@ -224,14 +211,10 @@ class CanvasGraph(tk.Canvas): # TODO will include throughput and ipv6 in the future 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 - ) + self.core.edges[edge.token].interface_1 = if1 + self.core.edges[edge.token].interface_2 = if2 + canvas_node_one.interfaces.append(if1) + canvas_node_two.interfaces.append(if2) # raise the nodes so they on top of the links self.tag_raise("node") @@ -290,7 +273,13 @@ class CanvasGraph(tk.Canvas): self.handle_edge_release(event) elif self.mode == GraphMode.NODE: x, y = self.canvas_xy(event) - self.add_node(x, y, self.draw_node_image, self.draw_node_name) + self.add_node( + x, + y, + self.draw_node_image, + self.draw_node_type, + self.draw_node_model, + ) elif self.mode == GraphMode.PICKNODE: self.mode = GraphMode.NODE @@ -313,6 +302,7 @@ class CanvasGraph(tk.Canvas): # edge dst is same as src, delete edge if edge.src == self.selected: edge.delete() + return # set dst node and snap edge to center x, y = self.coords(self.selected) @@ -326,14 +316,11 @@ class CanvasGraph(tk.Canvas): node_src.edges.add(edge) node_dst = self.nodes[edge.dst] node_dst.edges.add(edge) - - self.core.add_edge( - self.core.session_id, edge.token, node_src.id, node_dst.id - ) + core_edge = self.core.create_edge(edge.token, node_src, node_dst) # draw link info on the edge - if1 = self.core.edges[edge.token].interface_1 - if2 = self.core.edges[edge.token].interface_2 + if1 = core_edge.interface_1 + if2 = core_edge.interface_2 ip4_and_prefix_1 = None ip4_and_prefix_2 = None if if1 is not None: @@ -404,8 +391,10 @@ class CanvasGraph(tk.Canvas): ) # delete nodes and link info stored in CanvasGraph object + node_ids = [] 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: self.edges.pop(token) @@ -419,15 +408,16 @@ class CanvasGraph(tk.Canvas): self.nodes[nid].edges.remove(edge) # 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] logging.info("add node event: %s - %s", plot_id, self.selected) 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.core.add_graph_node(self.core.session_id, node.id, x, y, node_name) return node def width_and_height(self): @@ -494,7 +484,6 @@ class CanvasGraph(tk.Canvas): """ scale image based on canvas dimension - :param Image img: image object :return: nothing """ canvas_w, canvas_h = self.width_and_height() @@ -614,18 +603,17 @@ class CanvasEdge: 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.node_type = node_type self.app = app self.canvas = app.canvas self.id = self.canvas.create_image( 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.y_coord = y - self.name = f"N{self.core_id}" self.text_id = self.canvas.create_text( x, y + 20, text=self.name, tags="nodename" ) @@ -641,6 +629,7 @@ class CanvasNode: self.canvas.tag_bind(self.id, "", self.on_leave) self.edges = set() + self.interfaces = [] self.wlans = [] self.moving = None @@ -648,7 +637,7 @@ class CanvasNode: if self.app.core.is_runtime() and self.app.core.observer: self.tooltip.text.set("waiting...") 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) def on_leave(self, event): @@ -658,15 +647,15 @@ class CanvasNode: print("click") def double_click(self, event): - node_id = self.canvas.core.nodes[self.id].node_id - state = self.canvas.core.get_session_state() - if state == core_pb2.SessionState.RUNTIME: - self.canvas.core.launch_terminal(node_id) + if self.app.core.is_runtime(): + self.canvas.core.launch_terminal(self.core_node.id) else: self.canvas.canvas_action.display_configuration(self) def update_coords(self): 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): logging.debug(f"node click press {self.name}: {event}") @@ -677,7 +666,6 @@ class CanvasNode: def click_release(self, event): logging.debug(f"node click release {self.name}: {event}") self.update_coords() - self.canvas.core.update_node_location(self.id, self.x_coord, self.y_coord) self.moving = None def motion(self, event): @@ -697,7 +685,7 @@ class CanvasNode: new_x, new_y = self.canvas.coords(self.id) 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: x1, y1, x2, y2 = self.canvas.coords(edge.id) diff --git a/coretk/coretk/graph_helper.py b/coretk/coretk/graph_helper.py index c1f59815..476c0182 100644 --- a/coretk/coretk/graph_helper.py +++ b/coretk/coretk/graph_helper.py @@ -29,29 +29,31 @@ class GraphHelper: self.canvas.delete(i) def draw_wireless_case(self, src_id, dst_id, edge): - src_node_name = self.canvas.nodes[src_id].node_type - dst_node_name = self.canvas.nodes[dst_id].node_type - - if src_node_name == "wlan" or dst_node_name == "wlan": + src_node_type = self.canvas.nodes[src_id].core_node.type + dst_node_type = self.canvas.nodes[dst_id].core_node.type + is_src_wlan = src_node_type == core_pb2.NodeType.WIRELESS_LAN + 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) edge.wired = False 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() - elif src_node_name == "wlan": + elif is_src_wlan: self.canvas.nodes[dst_id].antenna_draw.add_antenna() else: self.canvas.nodes[src_id].antenna_draw.add_antenna() - edge.wired = True 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 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() - 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() - 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() else: logging.error( @@ -122,91 +124,3 @@ class WlanAntennaManager: """ for i in self.antennas: 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) diff --git a/coretk/coretk/images.py b/coretk/coretk/images.py index 7335e14e..6ce4732f 100644 --- a/coretk/coretk/images.py +++ b/coretk/coretk/images.py @@ -31,7 +31,7 @@ class Images: return cls.create(file_path, width, height) @classmethod - def get_custom(cls, name, width, height): + def get_custom(cls, name, width, height=None): file_path = cls.images[name] return cls.create(file_path, width, height) @@ -41,52 +41,38 @@ class Images: Retrieve image based on type and model :param core_pb2.NodeType node_type: core node type :param string node_model: the node model - - :rtype: tuple(PhotoImage, str) - :return: the matching image and its name + :return: core node icon + :rtype: PhotoImage """ image_enum = ImageEnum.ROUTER - name = "unknown" if node_type == core_pb2.NodeType.SWITCH: image_enum = ImageEnum.SWITCH - name = "switch" elif node_type == core_pb2.NodeType.HUB: image_enum = ImageEnum.HUB - name = "hub" elif node_type == core_pb2.NodeType.WIRELESS_LAN: image_enum = ImageEnum.WLAN - name = "wlan" elif node_type == core_pb2.NodeType.EMANE: image_enum = ImageEnum.EMANE - name = "emane" elif node_type == core_pb2.NodeType.RJ45: image_enum = ImageEnum.RJ45 - name = "rj45" elif node_type == core_pb2.NodeType.TUNNEL: image_enum = ImageEnum.TUNNEL - name = "tunnel" elif node_type == core_pb2.NodeType.DEFAULT: if node_model == "router": image_enum = ImageEnum.ROUTER - name = "router" elif node_model == "host": image_enum = ImageEnum.HOST - name = "host" elif node_model == "PC": image_enum = ImageEnum.PC - name = "PC" elif node_model == "mdr": image_enum = ImageEnum.MDR - name = "mdr" elif node_model == "prouter": image_enum = ImageEnum.PROUTER - name = "prouter" else: logging.error("invalid node model: %s", node_model) else: logging.error("invalid node type: %s", node_type) - - return Images.get(image_enum, NODE_WIDTH), name + return Images.get(image_enum, NODE_WIDTH) class ImageEnum(Enum): diff --git a/coretk/coretk/linkinfo.py b/coretk/coretk/linkinfo.py index 916e8dfb..29430deb 100644 --- a/coretk/coretk/linkinfo.py +++ b/coretk/coretk/linkinfo.py @@ -129,8 +129,7 @@ class Throughput: nid = t.node_id iid = t.interface_id tp = t.throughput - # token = self.grpc_manager.node_id_and_interface_to_edge_token[nid, iid] - token = self.core.core_mapping.get_token_from_node_and_interface(nid, iid) + token = self.core.interface_to_edge[(nid, iid)] print(token) edge_id = self.canvas.edges[token].id diff --git a/coretk/coretk/toolbar.py b/coretk/coretk/toolbar.py index 89393c3e..a049c321 100644 --- a/coretk/coretk/toolbar.py +++ b/coretk/coretk/toolbar.py @@ -3,6 +3,7 @@ import tkinter as tk from functools import partial from tkinter import ttk +from core.api.grpc import core_pb2 from coretk.dialogs.customnodes import CustomNodesDialog from coretk.graph import GraphMode from coretk.images import ImageEnum, Images @@ -136,10 +137,16 @@ class Toolbar(ttk.Frame): (ImageEnum.PROUTER, "prouter"), ] # draw default nodes - for image_enum, tooltip in nodes: + for image_enum, model in nodes: image = icon(image_enum) - func = partial(self.update_button, self.node_button, image, tooltip) - self.create_picker_button(image, func, self.node_picker, tooltip) + func = partial( + self.update_button, + self.node_button, + image, + core_pb2.NodeType.DEFAULT, + model, + ) + self.create_picker_button(image, func, self.node_picker, model) # draw custom nodes for name in sorted(self.app.core.custom_nodes): custom_node = self.app.core.custom_nodes[name] @@ -216,14 +223,15 @@ class Toolbar(ttk.Frame): dialog = CustomNodesDialog(self.app, self.app) dialog.show() - def update_button(self, button, image, name): - logging.info("update button(%s): %s", button, name) + def update_button(self, button, image, node_type, model=None): + logging.info("update button(%s): %s", button, node_type) self.hide_pickers() button.configure(image=image) button.image = image self.app.canvas.mode = GraphMode.NODE 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): logging.info("hiding pickers") @@ -260,18 +268,18 @@ class Toolbar(ttk.Frame): self.hide_pickers() self.network_picker = ttk.Frame(self.master) nodes = [ - (ImageEnum.HUB, "hub", "ethernet hub"), - (ImageEnum.SWITCH, "switch", "ethernet switch"), - (ImageEnum.WLAN, "wlan", "wireless LAN"), - (ImageEnum.EMANE, "emane", "EMANE"), - (ImageEnum.RJ45, "rj45", "rj45 physical interface tool"), - (ImageEnum.TUNNEL, "tunnel", "tunnel tool"), + (ImageEnum.HUB, core_pb2.NodeType.HUB, "ethernet hub"), + (ImageEnum.SWITCH, core_pb2.NodeType.SWITCH, "ethernet switch"), + (ImageEnum.WLAN, core_pb2.NodeType.WIRELESS_LAN, "wireless LAN"), + (ImageEnum.EMANE, core_pb2.NodeType.EMANE, "EMANE"), + (ImageEnum.RJ45, core_pb2.NodeType.RJ45, "rj45 physical interface 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) self.create_picker_button( image, - partial(self.update_button, self.network_button, image, name), + partial(self.update_button, self.network_button, image, node_type), self.network_picker, tooltip, ) diff --git a/coretk/coretk/wirelessconnection.py b/coretk/coretk/wirelessconnection.py index d1e17bc5..b864ce38 100644 --- a/coretk/coretk/wirelessconnection.py +++ b/coretk/coretk/wirelessconnection.py @@ -7,35 +7,31 @@ from core.api.grpc import core_pb2 class WirelessConnection: def __init__(self, canvas, core): 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 self.map = {} 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_id_two = self.core_mapping.get_canvas_id_from_core_id(node_two_id) + canvas_node_one = self.core.canvas_nodes[node_one_id] + canvas_node_two = self.core.canvas_nodes[node_two_id] key = tuple(sorted((node_one_id, node_two_id))) - if key not in self.map: - x1, y1 = self.canvas.coords(canvas_id_one) - x2, y2 = self.canvas.coords(canvas_id_two) + x1, y1 = self.canvas.coords(canvas_node_one.id) + x2, y2 = self.canvas.coords(canvas_node_two.id) wlan_canvas_id = self.canvas.create_line( x1, y1, x2, y2, fill="#009933", tags="wlan", width=1.5 ) self.map[key] = wlan_canvas_id - self.canvas.nodes[canvas_id_one].wlans.append(wlan_canvas_id) - self.canvas.nodes[canvas_id_two].wlans.append(wlan_canvas_id) + canvas_node_one.wlans.append(wlan_canvas_id) + canvas_node_two.wlans.append(wlan_canvas_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_id_two = self.core_mapping.get_canvas_id_from_core_id(node_two_id) - + canvas_node_one = self.core.canvas_nodes[node_one_id] + canvas_node_two = self.core.canvas_nodes[node_two_id] key = tuple(sorted((node_one_id, node_two_id))) wlan_canvas_id = self.map[key] - - self.canvas.nodes[canvas_id_one].wlans.remove(wlan_canvas_id) - self.canvas.nodes[canvas_id_two].wlans.remove(wlan_canvas_id) - + canvas_node_one.wlans.remove(wlan_canvas_id) + canvas_node_two.wlans.remove(wlan_canvas_id) self.canvas.delete(wlan_canvas_id) self.map.pop(key, None) From 814d35d7dda1e2a774ab45663d4a503dec93d148 Mon Sep 17 00:00:00 2001 From: bharnden <32446120+bharnden@users.noreply.github.com> Date: Fri, 15 Nov 2019 12:39:08 -0800 Subject: [PATCH 3/4] removed coreclient edge and updated code to save and use link protobuf data structures --- coretk/coretk/canvasaction.py | 15 +--- coretk/coretk/coreclient.py | 119 +++++++++------------------- coretk/coretk/graph.py | 46 +++++------ coretk/coretk/interface.py | 50 ------------ coretk/coretk/linkinfo.py | 2 - coretk/coretk/toolbar.py | 1 + coretk/coretk/wirelessconnection.py | 2 +- 7 files changed, 63 insertions(+), 172 deletions(-) diff --git a/coretk/coretk/canvasaction.py b/coretk/coretk/canvasaction.py index 8f217833..5b9c08c3 100644 --- a/coretk/coretk/canvasaction.py +++ b/coretk/coretk/canvasaction.py @@ -6,13 +6,6 @@ from coretk.dialogs.emaneconfig import EmaneConfiguration from coretk.dialogs.nodeconfig import NodeConfigDialog 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: def __init__(self, master, canvas): @@ -21,13 +14,13 @@ class CanvasAction: self.node_to_show_config = None 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 - if pb_type == core_pb2.NodeType.DEFAULT: + if node_type == core_pb2.NodeType.DEFAULT: 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) - elif pb_type == core_pb2.NodeType.EMANE: + elif node_type == core_pb2.NodeType.EMANE: self.display_emane_configuration() def display_node_configuration(self): diff --git a/coretk/coretk/coreclient.py b/coretk/coretk/coreclient.py index d80f6e5c..5dd0a621 100644 --- a/coretk/coretk/coreclient.py +++ b/coretk/coretk/coreclient.py @@ -8,7 +8,7 @@ from core.api.grpc import client, core_pb2 from coretk.dialogs.sessions import SessionsDialog from coretk.emaneodelnodeconfig import EmaneModelNodeConfig 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.servicenodeconfig import ServiceNodeConfig from coretk.wlannodeconfig import WlanNodeConfig @@ -28,25 +28,6 @@ OBSERVERS = { } -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: def __init__(self, name, address, port): self.name = name @@ -92,7 +73,7 @@ class CoreClient: self.canvas_nodes = {} self.interface_to_edge = {} self.state = None - self.edges = {} + self.links = {} self.hooks = {} self.id = 1 self.reusable = [] @@ -157,7 +138,7 @@ class CoreClient: self.reusable.clear() self.preexisting.clear() self.canvas_nodes.clear() - self.edges.clear() + self.links.clear() self.hooks.clear() self.wlanconfig_management.configurations.clear() self.mobilityconfig_management.configurations.clear() @@ -212,7 +193,7 @@ class CoreClient: self.reusable.append(i) # draw session - self.app.canvas.canvas_reset_and_redraw(session) + self.app.canvas.reset_and_redraw(session) # draw tool bar appropritate with session state if self.is_runtime(): @@ -317,7 +298,7 @@ class CoreClient: def start_session(self): 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() mobility_configs = self.get_mobility_configs_proto() emane_model_configs = self.get_emane_model_configs_proto() @@ -389,7 +370,7 @@ class CoreClient: def create_nodes_and_links(self): node_protos = [x.core_node for x in self.canvas_nodes.values()] - link_protos = self.get_links_proto() + link_protos = list(self.links.values()) self.client.set_session_state(self.session_id, core_pb2.SessionState.DEFINITION) for node_proto in node_protos: response = self.client.add_node(self.session_id, node_proto) @@ -496,11 +477,15 @@ class CoreClient: node_interface_pairs = [] for i in edge_tokens: try: - e = self.edges.pop(i) - if e.interface_1 is not None: - node_interface_pairs.append(tuple([e.id1, e.interface_1.id])) - if e.interface_2 is not None: - node_interface_pairs.append(tuple([e.id2, e.interface_2.id])) + link = self.links.pop(i) + if link.interface_one is not None: + node_interface_pairs.append( + (link.node_one_id, link.interface_one.id) + ) + if link.interface_two is not None: + node_interface_pairs.append( + (link.node_two_id, link.interface_two.id) + ) except KeyError: logging.error("coreclient.py invalid edge token ") @@ -525,49 +510,31 @@ class CoreClient: if tuple([i, None]) in self.emaneconfig_management.configurations: self.emaneconfig_management.configurations.pop(tuple([i, None])) - def create_interface(self, node_type, gui_interface): - """ - create a protobuf interface given the interface object stored by the programmer - - :param core_bp2.NodeType node_type: node type - :param coretk.interface.Interface gui_interface: the programmer's interface - :rtype: core_bp2.Interface - :return: protobuf interface object - """ - if node_type != core_pb2.NodeType.DEFAULT: - return None - else: - interface = core_pb2.Interface( - id=gui_interface.id, - name=gui_interface.name, - mac=gui_interface.mac, - ip4=gui_interface.ipv4, - ip4mask=gui_interface.ip4prefix, - ) - logging.debug("create interface: %s", interface) - return interface - - def create_edge_interface(self, canvas_node): + def create_interface(self, canvas_node): interface = None core_node = canvas_node.core_node if self.is_model_node(core_node.model): ifid = len(canvas_node.interfaces) name = f"eth{ifid}" - interface = Interface( - name=name, ifid=ifid, ipv4=str(self.interfaces_manager.get_address()) + interface = core_pb2.Interface( + id=ifid, + name=name, + ip4=str(self.interfaces_manager.get_address()), + ip4mask=24, ) canvas_node.interfaces.append(interface) logging.debug( - "create node(%s) interface IP: %s, name: %s", + "create node(%s) interface IPv4: %s, name: %s", core_node.name, - interface.ipv4, + interface.ip4, interface.name, ) return interface - def create_edge(self, token, canvas_node_one, canvas_node_two): + def create_link(self, token, canvas_node_one, canvas_node_two): """ - Add an edge to grpc manager + Create core link for a pair of canvas nodes, with token referencing + the canvas edge. :param tuple(int, int) token: edge's identification in the canvas :param canvas_node_one: canvas node one @@ -580,14 +547,15 @@ class CoreClient: # create interfaces self.interfaces_manager.new_subnet() - interface_one = self.create_edge_interface(canvas_node_one) + interface_one = self.create_interface(canvas_node_one) if interface_one is not None: self.interface_to_edge[(node_one.id, interface_one.id)] = token - interface_two = self.create_edge_interface(canvas_node_two) + 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 @@ -605,28 +573,15 @@ class CoreClient: node_two.node_id, node_one.node_id, interface_one.id ) - edge = Edge( - self.session_id, node_one.id, node_one.type, node_two.id, node_two.type + link = core_pb2.Link( + type=core_pb2.LinkType.WIRED, + node_one_id=node_one.id, + node_two_id=node_two.id, + interface_one=interface_one, + interface_two=interface_two, ) - edge.interface_1 = interface_one - edge.interface_2 = interface_two - self.edges[token] = edge - return edge - - 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 + self.links[token] = link + return link def get_wlan_configs_proto(self): configs = [] diff --git a/coretk/coretk/graph.py b/coretk/coretk/graph.py index 1fcafac1..c1be859d 100644 --- a/coretk/coretk/graph.py +++ b/coretk/coretk/graph.py @@ -9,7 +9,6 @@ from coretk.canvasaction import CanvasAction from coretk.canvastooltip import CanvasTooltip from coretk.graph_helper import GraphHelper, WlanAntennaManager from coretk.images import Images -from coretk.interface import Interface from coretk.linkinfo import LinkInfo, Throughput from coretk.nodedelete import CanvasComponentManagement from coretk.wirelessconnection import WirelessConnection @@ -84,7 +83,7 @@ class CanvasGraph(tk.Canvas): self.node_context.add_command(label="Hide") 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 client. @@ -183,22 +182,23 @@ class CanvasGraph(tk.Canvas): canvas_node_one.edges.add(edge) canvas_node_two.edges.add(edge) self.edges[edge.token] = edge - self.core.create_edge(edge.token, canvas_node_one, canvas_node_two) + self.core.links[edge.token] = link self.helper.redraw_antenna(link, canvas_node_one, canvas_node_two) # TODO add back the link info to grpc manager also redraw - grpc_if1 = link.interface_one - grpc_if2 = link.interface_two + # TODO will include throughput and ipv6 in the future + interface_one = link.interface_one + interface_two = link.interface_two ip4_src = None ip4_dst = None ip6_src = None ip6_dst = None - if grpc_if1 is not None: - ip4_src = grpc_if1.ip4 - ip6_src = grpc_if1.ip6 - if grpc_if2 is not None: - ip4_dst = grpc_if2.ip4 - ip6_dst = grpc_if2.ip6 + if interface_one is not None: + ip4_src = interface_one.ip4 + ip6_src = interface_one.ip6 + if interface_two is not None: + ip4_dst = interface_two.ip4 + ip6_dst = interface_two.ip6 edge.link_info = LinkInfo( canvas=self, edge=edge, @@ -207,14 +207,8 @@ class CanvasGraph(tk.Canvas): ip4_dst=ip4_dst, ip6_dst=ip6_dst, ) - - # TODO will include throughput and ipv6 in the future - 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[edge.token].interface_1 = if1 - self.core.edges[edge.token].interface_2 = if2 - canvas_node_one.interfaces.append(if1) - canvas_node_two.interfaces.append(if2) + canvas_node_one.interfaces.append(interface_one) + canvas_node_two.interfaces.append(interface_two) # raise the nodes so they on top of the links self.tag_raise("node") @@ -316,17 +310,17 @@ class CanvasGraph(tk.Canvas): node_src.edges.add(edge) node_dst = self.nodes[edge.dst] node_dst.edges.add(edge) - core_edge = self.core.create_edge(edge.token, node_src, node_dst) + link = self.core.create_link(edge.token, node_src, node_dst) # draw link info on the edge - if1 = core_edge.interface_1 - if2 = core_edge.interface_2 ip4_and_prefix_1 = None ip4_and_prefix_2 = None - if if1 is not None: - ip4_and_prefix_1 = if1.ip4_and_prefix - if if2 is not None: - ip4_and_prefix_2 = if2.ip4_and_prefix + if link.HasField("interface_one"): + if1 = link.interface_one + ip4_and_prefix_1 = f"{if1.ip4}/{if1.ip4mask}" + if link.HasField("interface_two"): + if2 = link.interface_two + ip4_and_prefix_2 = f"{if2.ip4}/{if2.ip4mask}" edge.link_info = LinkInfo( self, edge, diff --git a/coretk/coretk/interface.py b/coretk/coretk/interface.py index 5df26e26..b0fcd346 100644 --- a/coretk/coretk/interface.py +++ b/coretk/coretk/interface.py @@ -1,35 +1,4 @@ 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: @@ -46,18 +15,13 @@ class SubnetAddresses: class InterfaceManager: def __init__(self): - # self.prefix = None self.core_subnets = list( ipaddress.ip_network("10.0.0.0/12").subnets(prefixlen_diff=12) ) self.subnet_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.addresses = None - # self.start_interface_manager() def start_interface_manager(self): self.subnet_index = 0 @@ -72,24 +36,10 @@ class InterfaceManager: :return: """ - # i = self.index - # self.address_index = self.index + 1 - # return self.addresses[i] ipaddr = self.addresses[self.address_index] self.address_index = self.address_index + 1 return ipaddr def new_subnet(self): self.network = self.core_subnets[self.subnet_index] - # self.subnet_index = self.subnet_index + 1 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()) diff --git a/coretk/coretk/linkinfo.py b/coretk/coretk/linkinfo.py index 29430deb..1e0363cf 100644 --- a/coretk/coretk/linkinfo.py +++ b/coretk/coretk/linkinfo.py @@ -4,8 +4,6 @@ Link information, such as IPv4, IPv6 and throughput drawn in the canvas import logging import math -WIRELESS_DEF = ["mdr", "wlan"] - class LinkInfo: def __init__(self, canvas, edge, ip4_src, ip6_src, ip4_dst, ip6_dst): diff --git a/coretk/coretk/toolbar.py b/coretk/coretk/toolbar.py index a049c321..6017cbb1 100644 --- a/coretk/coretk/toolbar.py +++ b/coretk/coretk/toolbar.py @@ -375,6 +375,7 @@ class Toolbar(ttk.Frame): """ logging.debug("Click on STOP button ") self.app.core.stop_session() + self.app.canvas.delete("wireless") self.design_frame.tkraise() def update_annotation(self, image): diff --git a/coretk/coretk/wirelessconnection.py b/coretk/coretk/wirelessconnection.py index b864ce38..e8d03126 100644 --- a/coretk/coretk/wirelessconnection.py +++ b/coretk/coretk/wirelessconnection.py @@ -19,7 +19,7 @@ class WirelessConnection: x1, y1 = self.canvas.coords(canvas_node_one.id) x2, y2 = self.canvas.coords(canvas_node_two.id) 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 canvas_node_one.wlans.append(wlan_canvas_id) From 7981340b13f85c37ccfc90dfe20359d209d03ddc Mon Sep 17 00:00:00 2001 From: bharnden <32446120+bharnden@users.noreply.github.com> Date: Fri, 15 Nov 2019 13:09:53 -0800 Subject: [PATCH 4/4] added path for creating non core container based nodes --- coretk/coretk/icons/docker.gif | Bin 0 -> 719 bytes coretk/coretk/icons/lxc.gif | Bin 0 -> 724 bytes coretk/coretk/images.py | 2 ++ coretk/coretk/toolbar.py | 28 ++++++++++++++++------------ 4 files changed, 18 insertions(+), 12 deletions(-) create mode 100644 coretk/coretk/icons/docker.gif create mode 100644 coretk/coretk/icons/lxc.gif diff --git a/coretk/coretk/icons/docker.gif b/coretk/coretk/icons/docker.gif new file mode 100644 index 0000000000000000000000000000000000000000..dde25750d31c0f3ce9329dd5dd26f33ec3ebd0bf GIT binary patch literal 719 zcmZ?wbhEHblxGlSIOfgZtdQWYnC7jV<)f10tCAb2Rve;H5w2Mit=$x>)10K&ovh!R zYA_+qU}C1>v@E0P*+w&SjA!MW%q=jTUu3qZ#C&O)#fox^m6eujsw~&lSZ}Pg-qdKj zz1eP8i{0*4`@QWB`@38YcDo(y@i^4ud8p6l@Wj9)lY)*;4mma@^w`w!+e$?woLI z*Th?Ur{38&@hcMr_DcW~~#!wc>oS@huevWF*EK03YT@!9oHE^K{var^WCgBvLR zWMSlDsAte&00K~)FtGn?sBda+X>DuoXcp@3>Fw)m>6&ZbT_)L+Qh)j+bfo|;6p&-%r>DD zDiID3o8lQ5*(7wL%@~_IM0KS8F@Bifz{t!gX4A2u$BC6!)@_DIW1zA-qa3e{!vu$e zOziwBGP@@vGPm<9xJ`(-c}ek1zj5}xGnqooZ1Wvjh0bP}qy^2kC=Dy%GJO#+EyTRc z#Y>7;s=2E^o{yNRn>sz~>8dcT8{6vp4u#Iznt5wQyrI-4sqOl=)|Dy#-Klk5 SKj~;kf!l(FgPKnq7_0#ge~iHZ literal 0 HcmV?d00001 diff --git a/coretk/coretk/icons/lxc.gif b/coretk/coretk/icons/lxc.gif new file mode 100644 index 0000000000000000000000000000000000000000..e9f57aa30d3e2092b7de3f074146985272accd7b GIT binary patch literal 724 zcmZ?wbhEHblxGlSI2OW?Y^9KCr=07kQsAsw=&V-ere5K$QSGTw@2%D9uhS8z+ZUog zG0b3cxWTkY!2~R9E8Z-jp+asb?o-oSm3;Zc@(qDf#E87F?K7 zd~s&Ur8$+C=ha+W(sF%y$E~#!ZmpYmd&87F8>imgGV9*fIrp~Dy}x7r{hbRQ?pgA1 z@3KexS3W+t`pJ>?&yH_-erm^yGrRr|0-*Slg^`P)o2=Jx;6p9&Kkl-LBYXZ8aFmIu}pS- z7G&0Ipkv`46kvTrw~2w7uh-~BgCi5OF~6>s&MAh+Zu=RS_)HRx^)R)Im}FV}VP;Tj zWMUUFXi#X3WaW`_TT>vY{PFMDa3YoW# ztlWHvl~1mYO*Sgzao|j^{AYK5nrH