From 4e32c9c13cf934d93b90cccf9feaf50103a1c6d5 Mon Sep 17 00:00:00 2001 From: bharnden <32446120+bharnden@users.noreply.github.com> Date: Fri, 22 Nov 2019 23:48:10 -0800 Subject: [PATCH] updates to add reuse of deleted subnets --- coretk/coretk/coreclient.py | 76 +++++++++++++++++++++++++------------ coretk/coretk/graph.py | 4 +- coretk/coretk/interface.py | 35 +++++++++++------ coretk/coretk/nodedelete.py | 11 ++++-- 4 files changed, 83 insertions(+), 43 deletions(-) diff --git a/coretk/coretk/coreclient.py b/coretk/coretk/coreclient.py index cd10a073..d5a2f854 100644 --- a/coretk/coretk/coreclient.py +++ b/coretk/coretk/coreclient.py @@ -469,38 +469,64 @@ class CoreClient: ) return node - def delete_graph_nodes(self, node_ids, edges): + def delete_graph_nodes(self, canvas_nodes): """ remove the nodes selected by the user and anything related to that node such as link, configurations, interfaces - :param list[int] node_ids: list of nodes to delete - :param list edges: list of edges to delete + :param list canvas_nodes: list of nodes to delete :return: nothing """ - # delete the nodes - for i in node_ids: - try: - del self.canvas_nodes[i] - self.reusable.append(i) - if i in self.mobility_configs: - del self.mobility_configs[i] - if i in self.wlan_configs: - del self.wlan_configs[i] - for key in list(self.emane_model_configs): - node_id, _, _ = key - if node_id == i: - del self.emane_model_configs[key] - except KeyError: - logging.error("invalid canvas id: %s", i) - self.reusable.sort() + edges = set() + for canvas_node in canvas_nodes: + node_id = canvas_node.core_node.id + if node_id not in self.canvas_nodes: + logging.error("unknown node: %s", node_id) + continue + del self.canvas_nodes[node_id] + self.reusable.append(node_id) + if node_id in self.mobility_configs: + del self.mobility_configs[node_id] + if node_id in self.wlan_configs: + del self.wlan_configs[node_id] + for key in list(self.emane_model_configs): + node_id, _, _ = key + if node_id == node_id: + del self.emane_model_configs[key] - # delete the edges and interfaces - for edge in edges: - try: - self.links.pop(edge.token) - except KeyError: - logging.error("invalid edge token: %s", edge.token) + deleted_cidrs = set() + keep_cidrs = set() + for edge in canvas_node.edges: + if edge in edges: + continue + edges.add(edge) + if edge.token not in self.links: + logging.error("unknown edge: %s", edge.token) + del self.links[edge.token] + other_id = edge.src + other_interface = edge.src_interface + interface = edge.dst_interface + if canvas_node.id == edge.src: + other_id = edge.dst + other_interface = edge.dst_interface + interface = edge.src_interface + other_node = self.app.canvas.nodes.get(other_id) + if not other_node: + continue + if other_interface: + cidr = self.interfaces_manager.get_cidr(other_interface) + deleted_cidrs.add(cidr) + else: + cidr = self.interfaces_manager.find_subnet(other_node) + if cidr: + keep_cidrs.add(cidr) + else: + cidr = self.interfaces_manager.get_cidr(interface) + deleted_cidrs.add(cidr) + deleted_cidrs = deleted_cidrs - keep_cidrs + for cidr in deleted_cidrs: + self.interfaces_manager.deleted_cidr(cidr) + self.reusable.sort() def create_interface(self, canvas_node): node = canvas_node.core_node diff --git a/coretk/coretk/graph.py b/coretk/coretk/graph.py index 3f140261..14e978be 100644 --- a/coretk/coretk/graph.py +++ b/coretk/coretk/graph.py @@ -389,10 +389,10 @@ class CanvasGraph(tk.Canvas): :return: """ # delete canvas data - node_ids, edges = self.canvas_management.delete_selected_nodes() + nodes = self.canvas_management.delete_selected_nodes() # delete core data - self.core.delete_graph_nodes(node_ids, edges) + self.core.delete_graph_nodes(nodes) def add_node(self, x, y): plot_id = self.find_all()[0] diff --git a/coretk/coretk/interface.py b/coretk/coretk/interface.py index 7d0c374c..4b56f3a8 100644 --- a/coretk/coretk/interface.py +++ b/coretk/coretk/interface.py @@ -29,12 +29,22 @@ class InterfaceManager: return str(ip4), str(ip6), self.current.prefixlen def next_subnet(self): - if self.current: - self.cidr = self.cidr.next() - return self.cidr + if self.deleted: + return self.deleted.pop(0) + else: + if self.current: + self.cidr = self.cidr.next() + return self.cidr - def deleted_interface(self, interface): - logging.info("deleted interface: %s", interface) + def deleted_cidr(self, cidr): + logging.info("deleted cidr: %s", cidr) + if cidr not in self.deleted: + self.deleted.append(cidr) + self.deleted.sort() + + @classmethod + def get_cidr(cls, interface): + return IPNetwork(f"{interface.ip4}/{interface.ip4mask}").cidr def determine_subnet(self, canvas_src_node, canvas_dst_node): src_node = canvas_src_node.core_node @@ -49,21 +59,21 @@ class InterfaceManager: self.current = cidr else: self.current = self.next_subnet() - # else: - # self.current = self.cidr elif not is_src_container and is_dst_container: cidr = self.find_subnet(canvas_src_node, visited={dst_node.id}) if cidr: - self.current = self.cidr + self.current = cidr else: self.current = self.next_subnet() else: logging.info("ignoring subnet change for link between network nodes") - def find_subnet(self, canvas_node, visited): + def find_subnet(self, canvas_node, visited=None): logging.info("finding subnet for node: %s", canvas_node.core_node.name) canvas = self.app.canvas cidr = None + if not visited: + visited = set() visited.add(canvas_node.core_node.id) for edge in canvas_node.edges: src_node = canvas.nodes[edge.src] @@ -77,9 +87,10 @@ class InterfaceManager: continue visited.add(check_node.core_node.id) if interface: - logging.info("found interface: %s", interface) - cidr = IPNetwork(f"{interface.ip4}/{interface.ip4mask}").cidr - break + cidr = self.get_cidr(interface) else: cidr = self.find_subnet(check_node, visited) + if cidr: + logging.info("found subnet: %s", cidr) + break return cidr diff --git a/coretk/coretk/nodedelete.py b/coretk/coretk/nodedelete.py index 496bbc6d..165fde53 100644 --- a/coretk/coretk/nodedelete.py +++ b/coretk/coretk/nodedelete.py @@ -40,11 +40,11 @@ class CanvasComponentManagement: def delete_selected_nodes(self): edges = set() - node_ids = [] + nodes = [] for node_id in list(self.selected): bbox_id = self.selected[node_id] canvas_node = self.canvas.nodes.pop(node_id) - node_ids.append(canvas_node.core_node.id) + nodes.append(canvas_node) self.canvas.delete(node_id) self.canvas.delete(bbox_id) self.canvas.delete(canvas_node.text_id) @@ -63,6 +63,9 @@ class CanvasComponentManagement: other_interface = edge.dst_interface other_node = self.canvas.nodes[other_id] other_node.edges.remove(edge) - other_node.interfaces.remove(other_interface) + try: + other_node.interfaces.remove(other_interface) + except ValueError: + pass self.selected.clear() - return node_ids, edges + return nodes