diff --git a/coretk/coretk/canvasaction.py b/coretk/coretk/canvasaction.py index decf43f3..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): @@ -36,8 +29,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 52a45140..16fc6cbc 100644 --- a/coretk/coretk/coreclient.py +++ b/coretk/coretk/coreclient.py @@ -5,11 +5,10 @@ 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 -from coretk.interface import Interface, InterfaceManager +from coretk.interface import InterfaceManager from coretk.mobilitynodeconfig import MobilityNodeConfig from coretk.servicefileconfig import ServiceFileConfig 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: def __init__(self, name, address, port): self.name = name @@ -113,15 +71,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.links = {} 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) @@ -183,8 +141,8 @@ class CoreClient: # clear session data self.reusable.clear() self.preexisting.clear() - self.nodes.clear() - self.edges.clear() + self.canvas_nodes.clear() + self.links.clear() self.hooks.clear() self.wlanconfig_management.configurations.clear() self.mobilityconfig_management.configurations.clear() @@ -207,14 +165,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} @@ -222,7 +180,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 @@ -239,7 +197,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(): @@ -343,8 +301,8 @@ class CoreClient: logging.info("delete links %s", response) def start_session(self): - nodes = self.get_nodes_proto() - links = self.get_links_proto() + nodes = [x.core_node for x in self.canvas_nodes.values()] + 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() @@ -374,23 +332,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) @@ -448,8 +389,10 @@ class CoreClient: :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: if node_proto.id not in self.created_nodes: response = self.client.add_node(self.session_id, node_proto) @@ -482,17 +425,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 @@ -510,106 +442,91 @@ 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])) - + 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 ") # 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: @@ -619,214 +536,82 @@ 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 - :rtype: core_bp2.Interface - :return: protobuf interface object - """ - if node_type != core_pb2.NodeType.DEFAULT: - return None - else: + 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 = core_pb2.Interface( - id=gui_interface.id, - name=gui_interface.name, - mac=gui_interface.mac, - ip4=gui_interface.ipv4, - ip4mask=gui_interface.ip4prefix, + id=ifid, + name=name, + ip4=str(self.interfaces_manager.get_address()), + ip4mask=24, ) - 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( - 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 IPv4: %s, name: %s", + core_node.name, + interface.ip4, + 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_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 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_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_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: - 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 - - 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 + 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, + ) + self.links[token] = link + return link def get_wlan_configs_proto(self): configs = [] 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/dialogs/nodeservice.py b/coretk/coretk/dialogs/nodeservice.py index d791cc0e..67d9a0b3 100644 --- a/coretk/coretk/dialogs/nodeservice.py +++ b/coretk/coretk/dialogs/nodeservice.py @@ -13,14 +13,13 @@ class NodeService(Dialog): def __init__(self, master, app, canvas_node, services=None): super().__init__(master, app, "Node Services", modal=True) self.canvas_node = canvas_node + self.node_id = canvas_node.core_node.id self.groups = None self.services = None self.current = None if services is None: services = set( - app.core.serviceconfig_manager.configurations[ - canvas_node.core_id - ].keys() + app.core.serviceconfig_manager.configurations[self.node_id].keys() ) self.current_services = services self.draw() diff --git a/coretk/coretk/dialogs/serviceconfiguration.py b/coretk/coretk/dialogs/serviceconfiguration.py index da0c0736..195dc913 100644 --- a/coretk/coretk/dialogs/serviceconfiguration.py +++ b/coretk/coretk/dialogs/serviceconfiguration.py @@ -15,7 +15,7 @@ class ServiceConfiguration(Dialog): super().__init__(master, app, f"{service_name} service", modal=True) self.app = app 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.radiovar = tk.IntVar() self.radiovar.set(2) @@ -73,22 +73,15 @@ class ServiceConfiguration(Dialog): self.validation_mode = service_config.validation_mode self.validation_time = service_config.validation_timer self.original_service_files = { - x: self.app.core.get_node_service_file( - self.canvas_node.core_id, self.service_name, x - ) + x: self.app.core.get_node_service_file(self.node_id, self.service_name, x) for x in self.filenames } self.temp_service_files = { x: self.original_service_files[x] for x in self.original_service_files } configs = self.app.core.servicefileconfig_manager.configurations - if ( - self.canvas_node.core_id in configs - 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(): + if self.node_id in configs and self.service_name in configs[self.node_id]: + for file, data in configs[self.node_id][self.service_name].items(): self.temp_service_files[file] = data def draw(self): @@ -371,7 +364,7 @@ class ServiceConfiguration(Dialog): shutdown_commands = self.shutdown_commands_listbox.get(0, "end") validate_commands = self.validate_commands_listbox.get(0, "end") self.app.core.serviceconfig_manager.node_service_custom_configuration( - self.canvas_node.core_id, + self.node_id, self.service_name, startup_commands, validate_commands, @@ -379,16 +372,10 @@ class ServiceConfiguration(Dialog): ) for file in self.modified_files: self.app.core.servicefileconfig_manager.set_custom_service_file_config( - self.canvas_node.core_id, - self.service_name, - file, - self.temp_service_files[file], + self.node_id, self.service_name, file, self.temp_service_files[file] ) self.app.core.set_node_service_file( - self.canvas_node.core_id, - self.service_name, - file, - self.temp_service_files[file], + self.node_id, self.service_name, file, self.temp_service_files[file] ) self.destroy() diff --git a/coretk/coretk/graph.py b/coretk/coretk/graph.py index e5bab65b..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 @@ -31,12 +30,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: @@ -45,7 +38,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 = {} @@ -89,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. @@ -103,13 +97,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): """ @@ -149,95 +144,71 @@ 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.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 - e.link_info = LinkInfo( + 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=e, + edge=edge, ip4_src=ip4_src, ip6_src=ip6_src, 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[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 - ) + 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") @@ -296,7 +267,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 @@ -319,6 +296,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) @@ -332,20 +310,17 @@ 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 - ) + link = self.core.create_link(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 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, @@ -410,8 +385,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) @@ -425,15 +402,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): @@ -500,7 +478,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() @@ -620,18 +597,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" ) @@ -647,6 +623,7 @@ class CanvasNode: self.canvas.tag_bind(self.id, "", self.on_leave) self.edges = set() + self.interfaces = [] self.wlans = [] self.moving = None @@ -654,7 +631,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): @@ -664,23 +641,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) - # 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) + 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}") @@ -691,7 +660,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): @@ -711,7 +679,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/icons/docker.gif b/coretk/coretk/icons/docker.gif new file mode 100644 index 00000000..dde25750 Binary files /dev/null and b/coretk/coretk/icons/docker.gif differ diff --git a/coretk/coretk/icons/lxc.gif b/coretk/coretk/icons/lxc.gif new file mode 100644 index 00000000..e9f57aa3 Binary files /dev/null and b/coretk/coretk/icons/lxc.gif differ diff --git a/coretk/coretk/images.py b/coretk/coretk/images.py index 7335e14e..1a377253 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): @@ -121,3 +107,5 @@ class ImageEnum(Enum): FILEOPEN = "fileopen" EDITDELETE = "edit-delete" ANTENNA = "antenna" + DOCKER = "docker" + LXC = "lxc" 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 916e8dfb..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): @@ -129,8 +127,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..7fe675a4 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 @@ -129,22 +130,32 @@ class Toolbar(ttk.Frame): self.hide_pickers() self.node_picker = ttk.Frame(self.master) nodes = [ - (ImageEnum.ROUTER, "router"), - (ImageEnum.HOST, "host"), - (ImageEnum.PC, "PC"), - (ImageEnum.MDR, "mdr"), - (ImageEnum.PROUTER, "prouter"), + (ImageEnum.ROUTER, core_pb2.NodeType.DEFAULT, "router"), + (ImageEnum.HOST, core_pb2.NodeType.DEFAULT, "host"), + (ImageEnum.PC, core_pb2.NodeType.DEFAULT, "PC"), + (ImageEnum.MDR, core_pb2.NodeType.DEFAULT, "mdr"), + (ImageEnum.PROUTER, core_pb2.NodeType.DEFAULT, "prouter"), + (ImageEnum.DOCKER, core_pb2.NodeType.DOCKER, "Docker"), + (ImageEnum.LXC, core_pb2.NodeType.LXC, "LXC"), ] # draw default nodes - for image_enum, tooltip in nodes: + for image_enum, node_type, 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, node_type, 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] 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) # draw edit node image = icon(ImageEnum.EDITNODE) @@ -216,14 +227,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 +272,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, ) @@ -367,6 +379,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 d1e17bc5..e8d03126 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 + x1, y1, x2, y2, fill="#009933", tags="wireless", 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)