diff --git a/daemon/core/gui/coreclient.py b/daemon/core/gui/coreclient.py index dd7f8308..99966f02 100644 --- a/daemon/core/gui/coreclient.py +++ b/daemon/core/gui/coreclient.py @@ -330,6 +330,9 @@ class CoreClient: except grpc.RpcError as e: self.app.show_grpc_exception("Join Session Error", e) + # organize canvas + self.app.canvas.organize() + # update ui to represent current state self.app.after(0, self.app.joined_session_update) @@ -388,7 +391,6 @@ class CoreClient: self.app.canvas.shapes[shape.id] = shape except ValueError: logging.exception("unknown shape: %s", shape_type) - self.app.canvas.organize() def create_new_session(self): """ @@ -835,7 +837,7 @@ class CoreClient: ip4, ip6 = self.interfaces_manager.get_ips(node) ip4_mask = self.interfaces_manager.ip4_mask ip6_mask = self.interfaces_manager.ip6_mask - interface_id = len(canvas_node.interfaces) + interface_id = canvas_node.next_interface_id() name = f"eth{interface_id}" interface = core_pb2.Interface( id=interface_id, @@ -845,7 +847,8 @@ class CoreClient: ip6=ip6, ip6mask=ip6_mask, ) - logging.debug( + canvas_node.interfaces[interface.id] = interface + logging.info( "create node(%s) interface(%s) IPv4(%s) IPv6(%s)", node.name, interface.name, @@ -870,11 +873,13 @@ class CoreClient: src_interface = None if NodeUtils.is_container_node(src_node.type): src_interface = self.create_interface(canvas_src_node) + edge.src_interface = src_interface self.interface_to_edge[(src_node.id, src_interface.id)] = edge.token dst_interface = None if NodeUtils.is_container_node(dst_node.type): dst_interface = self.create_interface(canvas_dst_node) + edge.dst_interface = dst_interface self.interface_to_edge[(dst_node.id, dst_interface.id)] = edge.token link = core_pb2.Link( @@ -884,12 +889,6 @@ class CoreClient: interface_one=src_interface, interface_two=dst_interface, ) - if src_interface: - edge.src_interface = link.interface_one - canvas_src_node.interfaces.append(link.interface_one) - if dst_interface: - edge.dst_interface = link.interface_two - canvas_dst_node.interfaces.append(link.interface_two) edge.set_link(link) self.links[edge.token] = edge logging.info("Add link between %s and %s", src_node.name, dst_node.name) diff --git a/daemon/core/gui/dialogs/nodeconfig.py b/daemon/core/gui/dialogs/nodeconfig.py index 73f0ac09..0d46ae06 100644 --- a/daemon/core/gui/dialogs/nodeconfig.py +++ b/daemon/core/gui/dialogs/nodeconfig.py @@ -207,8 +207,8 @@ class NodeConfigDialog(Dialog): notebook.grid(sticky="nsew", pady=PADY) self.top.rowconfigure(notebook.grid_info()["row"], weight=1) state = tk.DISABLED if self.app.core.is_runtime() else tk.NORMAL - for interface in self.canvas_node.interfaces: - logging.info("interface: %s", interface) + for interface_id in sorted(self.canvas_node.interfaces): + interface = self.canvas_node.interfaces[interface_id] tab = ttk.Frame(notebook, padding=FRAME_PAD) tab.grid(sticky="nsew", pady=PADY) tab.columnconfigure(1, weight=1) @@ -309,7 +309,7 @@ class NodeConfigDialog(Dialog): self.canvas_node.image = self.image # update node interface data - for interface in self.canvas_node.interfaces: + for interface in self.canvas_node.interfaces.values(): data = self.interfaces[interface.id] # validate ip4 diff --git a/daemon/core/gui/graph/graph.py b/daemon/core/gui/graph/graph.py index eacbf1f4..fcc8c81b 100644 --- a/daemon/core/gui/graph/graph.py +++ b/daemon/core/gui/graph/graph.py @@ -322,26 +322,25 @@ class CanvasGraph(tk.Canvas): self.edges[edge.token] = edge self.core.links[edge.token] = edge if link.HasField("interface_one"): + interface_one = link.interface_one self.core.interface_to_edge[ - (node_one.id, link.interface_one.id) + (node_one.id, interface_one.id) ] = token - canvas_node_one.interfaces.append(link.interface_one) - edge.src_interface = link.interface_one + canvas_node_one.interfaces[interface_one.id] = interface_one + edge.src_interface = interface_one if link.HasField("interface_two"): + interface_two = link.interface_two self.core.interface_to_edge[ - (node_two.id, link.interface_two.id) + (node_two.id, interface_two.id) ] = edge.token - canvas_node_two.interfaces.append(link.interface_two) - edge.dst_interface = link.interface_two + canvas_node_two.interfaces[interface_two.id] = interface_two + edge.dst_interface = interface_two elif link.options.unidirectional: edge = self.edges[token] edge.asymmetric_link = link else: logging.error("duplicate link received: %s", link) - # raise the nodes so they on top of the links - self.tag_raise(tags.NODE) - def stopped_session(self): # clear wireless edges for edge in self.wireless_edges.values(): @@ -522,8 +521,8 @@ class CanvasGraph(tk.Canvas): other_interface = edge.dst_interface other_node = self.nodes[other_id] other_node.edges.remove(edge) - if other_interface in other_node.interfaces: - other_node.interfaces.remove(other_interface) + if other_interface: + del other_node.interfaces[other_interface.id] if is_wireless: other_node.delete_antenna() @@ -541,12 +540,12 @@ class CanvasGraph(tk.Canvas): del self.edges[edge.token] src_node = self.nodes[edge.src] src_node.edges.discard(edge) - if edge.src_interface in src_node.interfaces: - src_node.interfaces.remove(edge.src_interface) + if edge.src_interface: + del src_node.interfaces[edge.src_interface.id] dst_node = self.nodes[edge.dst] dst_node.edges.discard(edge) - if edge.dst_interface in dst_node.interfaces: - dst_node.interfaces.remove(edge.dst_interface) + if edge.dst_interface: + del dst_node.interfaces[edge.dst_interface.id] src_wireless = NodeUtils.is_wireless_node(src_node.core_node.type) if src_wireless: dst_node.delete_antenna() diff --git a/daemon/core/gui/graph/node.py b/daemon/core/gui/graph/node.py index 41b4704a..0b4f2bc9 100644 --- a/daemon/core/gui/graph/node.py +++ b/daemon/core/gui/graph/node.py @@ -55,7 +55,7 @@ class CanvasNode: ) self.tooltip = CanvasTooltip(self.canvas) self.edges = set() - self.interfaces = [] + self.interfaces = {} self.wireless_edges = set() self.antennas = [] self.antenna_images = {} @@ -70,6 +70,12 @@ class CanvasNode: self.context = tk.Menu(self.canvas) themes.style_menu(self.context) + def next_interface_id(self) -> int: + i = 0 + while i in self.interfaces: + i += 1 + return i + def setup_bindings(self): self.canvas.tag_bind(self.id, "", self.double_click) self.canvas.tag_bind(self.id, "", self.on_enter) diff --git a/daemon/core/gui/interface.py b/daemon/core/gui/interface.py index fc5185f5..437bd37c 100644 --- a/daemon/core/gui/interface.py +++ b/daemon/core/gui/interface.py @@ -105,12 +105,11 @@ class InterfaceManager: for interface in interfaces: subnets = self.get_subnets(interface) if subnets not in remaining_subnets: - if self.current_subnets == subnets: - self.current_subnets = None self.used_subnets.pop(subnets.key(), None) else: index = get_index(interface) subnets.used_indexes.discard(index) + self.current_subnets = None def joined(self, links: List["core_pb2.Link"]) -> None: interfaces = []