From 981be3b7ffae6a4cbfd448d9ef00ed5a85b77286 Mon Sep 17 00:00:00 2001 From: bharnden <32446120+bharnden@users.noreply.github.com> Date: Fri, 22 Nov 2019 14:58:41 -0800 Subject: [PATCH 1/4] small cleanup with stopping sessions --- coretk/coretk/coreclient.py | 93 ++++++++++--------------------- coretk/coretk/dialogs/sessions.py | 2 +- coretk/coretk/interface.py | 6 ++ 3 files changed, 36 insertions(+), 65 deletions(-) diff --git a/coretk/coretk/coreclient.py b/coretk/coretk/coreclient.py index 46d1cdad..08003dcf 100644 --- a/coretk/coretk/coreclient.py +++ b/coretk/coretk/coreclient.py @@ -74,10 +74,25 @@ class CoreClient: self.emane_config = None self.created_nodes = set() self.created_links = set() - self.service_configs = {} self.file_configs = {} + def reset(self): + self.id = 1 + self.reusable.clear() + self.preexisting.clear() + self.canvas_nodes.clear() + self.links.clear() + self.hooks.clear() + self.wlan_configs.clear() + self.mobility_configs.clear() + self.emane_config = None + self.location = None + self.service_configs.clear() + self.file_configs.clear() + self.interfaces_manager.reset() + self.interface_to_edge.clear() + def set_observer(self, value): self.observer = value @@ -130,16 +145,7 @@ class CoreClient: self.master.title(f"CORE Session({self.session_id})") # clear session data - self.reusable.clear() - self.preexisting.clear() - self.canvas_nodes.clear() - self.links.clear() - self.hooks.clear() - self.wlan_configs.clear() - self.mobility_configs.clear() - self.emane_config = None - self.service_configs.clear() - self.file_configs.clear() + self.reset() # get session data response = self.client.get_session(self.session_id) @@ -224,29 +230,12 @@ class CoreClient: ) self.join_session(response.session_id, query_location=False) - def delete_session(self, custom_sid=None): - if custom_sid is None: - sid = self.session_id - else: - sid = custom_sid - response = self.client.delete_session(sid) + def delete_session(self, session_id=None): + if session_id is None: + session_id = self.session_id + response = self.client.delete_session(session_id) logging.info("Deleted session result: %s", response) - def shutdown_session(self, custom_sid=None): - if custom_sid is None: - sid = self.session_id - else: - sid = custom_sid - s = self.client.get_session(sid).session - # delete links and nodes from running session - if s.state == core_pb2.SessionState.RUNTIME: - self.client.set_session_state( - self.session_id, core_pb2.SessionState.DATACOLLECT - ) - self.delete_links(sid) - self.delete_nodes(sid) - self.delete_session(sid) - def set_up(self): """ Query sessions, if there exist any, prompt whether to join one @@ -287,31 +276,6 @@ class CoreClient: response = self.client.edit_node(self.session_id, node_id, position) logging.info("updated node id %s: %s", node_id, response) - def delete_nodes(self, delete_session=None): - if delete_session is None: - sid = self.session_id - else: - sid = delete_session - for node in self.client.get_session(sid).session.nodes: - response = self.client.delete_node(self.session_id, node.id) - logging.info("delete nodes %s", response) - - def delete_links(self, delete_session=None): - if delete_session is None: - sid = self.session_id - else: - sid = delete_session - - for link in self.client.get_session(sid).session.links: - response = self.client.delete_link( - self.session_id, - link.node_one_id, - link.node_two_id, - link.interface_one.id, - link.interface_two.id, - ) - logging.info("delete links %s", response) - def start_session(self): nodes = [x.core_node for x in self.canvas_nodes.values()] links = list(self.links.values()) @@ -340,17 +304,18 @@ class CoreClient: service_configs, file_configs, ) - logging.debug("Start session %s, result: %s", self.session_id, response.result) - print(self.client.get_session(self.session_id)) + logging.debug("start session(%s), result: %s", self.session_id, response.result) - def stop_session(self): - response = self.client.stop_session(session_id=self.session_id) - logging.debug("coregrpc.py Stop session, result: %s", response.result) + def stop_session(self, session_id=None): + if not session_id: + session_id = self.session_id + response = self.client.stop_session(session_id) + logging.debug("stopped session(%s), result: %s", session_id, response.result) def launch_terminal(self, node_id): response = self.client.get_node_terminal(self.session_id, node_id) logging.info("get terminal %s", response.terminal) - os.system("xterm -e %s &" % response.terminal) + os.system(f"xterm -e {response.terminal} &") def save_xml(self, file_path): """ @@ -360,7 +325,7 @@ class CoreClient: :return: nothing """ response = self.client.save_xml(self.session_id, file_path) - logging.info("coregrpc.py save xml %s", response) + logging.info("saved xml(%s): %s", file_path, response) self.client.events(self.session_id, self.handle_events) def open_xml(self, file_path): diff --git a/coretk/coretk/dialogs/sessions.py b/coretk/coretk/dialogs/sessions.py index 6ea66973..6f299dfc 100644 --- a/coretk/coretk/dialogs/sessions.py +++ b/coretk/coretk/dialogs/sessions.py @@ -155,6 +155,6 @@ class SessionsDialog(Dialog): self.join_session(sid) def shutdown_session(self, sid): - self.app.core.shutdown_session(sid) + self.app.core.stop_session(sid) self.click_new() self.destroy() diff --git a/coretk/coretk/interface.py b/coretk/coretk/interface.py index 9b58e7e6..e1203389 100644 --- a/coretk/coretk/interface.py +++ b/coretk/coretk/interface.py @@ -13,10 +13,16 @@ def random_mac(): class InterfaceManager: def __init__(self, app, cidr="10.0.0.0/24"): self.app = app + self.default = cidr self.cidr = IPNetwork(cidr) self.deleted = [] self.current = None + def reset(self): + self.cidr = IPNetwork(self.default) + self.deleted.clear() + self.current = None + def get_ips(self, node_id): ip4 = self.current[node_id] ip6 = ip4.ipv6() From 46627aad11e7befabf8f28ebcc93ae324970a855 Mon Sep 17 00:00:00 2001 From: bharnden <32446120+bharnden@users.noreply.github.com> Date: Fri, 22 Nov 2019 15:43:43 -0800 Subject: [PATCH 2/4] renamed coreclient delete graph nodes func --- coretk/coretk/coreclient.py | 33 ++++++++++++++++++++------------- coretk/coretk/graph.py | 2 +- 2 files changed, 21 insertions(+), 14 deletions(-) diff --git a/coretk/coretk/coreclient.py b/coretk/coretk/coreclient.py index 08003dcf..309fcba2 100644 --- a/coretk/coretk/coreclient.py +++ b/coretk/coretk/coreclient.py @@ -57,41 +57,48 @@ class CoreClient: self.custom_observers = {} self.read_config() - # data for managing the current session - self.canvas_nodes = {} - self.location = None + # helpers self.interface_to_edge = {} - self.state = None - self.links = {} - self.hooks = {} - self.id = 1 self.reusable = [] self.preexisting = set() self.interfaces_manager = InterfaceManager(self.app) + self.created_nodes = set() + self.created_links = set() + + # session data + self.id = 1 + self.state = None + self.canvas_nodes = {} + self.location = None + self.links = {} + self.hooks = {} self.wlan_configs = {} self.mobility_configs = {} self.emane_model_configs = {} self.emane_config = None - self.created_nodes = set() - self.created_links = set() self.service_configs = {} self.file_configs = {} def reset(self): self.id = 1 + # helpers + self.created_nodes.clear() + self.created_links.clear() self.reusable.clear() self.preexisting.clear() + self.interfaces_manager.reset() + self.interface_to_edge.clear() + # session data self.canvas_nodes.clear() + self.location = None self.links.clear() self.hooks.clear() self.wlan_configs.clear() self.mobility_configs.clear() + self.emane_model_configs.clear() self.emane_config = None - self.location = None self.service_configs.clear() self.file_configs.clear() - self.interfaces_manager.reset() - self.interface_to_edge.clear() def set_observer(self, value): self.observer = value @@ -462,7 +469,7 @@ class CoreClient: ) return node - def delete_wanted_graph_nodes(self, node_ids, edge_tokens): + def delete_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 diff --git a/coretk/coretk/graph.py b/coretk/coretk/graph.py index fc14246d..b87bccbf 100644 --- a/coretk/coretk/graph.py +++ b/coretk/coretk/graph.py @@ -411,7 +411,7 @@ class CanvasGraph(tk.Canvas): self.nodes[nid].edges.remove(edge) # delete the related data from core - self.core.delete_wanted_graph_nodes(node_ids, to_delete_edge_tokens) + self.core.delete_graph_nodes(node_ids, to_delete_edge_tokens) def add_node(self, x, y): plot_id = self.find_all()[0] From e8f8fa3bd5a376bc58646407b8c12d4893feba40 Mon Sep 17 00:00:00 2001 From: bharnden <32446120+bharnden@users.noreply.github.com> Date: Fri, 22 Nov 2019 16:30:25 -0800 Subject: [PATCH 3/4] cleaned up some of the logic for deleting nodes/edges --- coretk/coretk/coreclient.py | 10 ++++----- coretk/coretk/graph.py | 27 ++++------------------- coretk/coretk/interface.py | 3 +++ coretk/coretk/nodedelete.py | 43 +++++++++++++++++++++---------------- 4 files changed, 37 insertions(+), 46 deletions(-) diff --git a/coretk/coretk/coreclient.py b/coretk/coretk/coreclient.py index 309fcba2..cd10a073 100644 --- a/coretk/coretk/coreclient.py +++ b/coretk/coretk/coreclient.py @@ -469,13 +469,13 @@ class CoreClient: ) return node - def delete_graph_nodes(self, node_ids, edge_tokens): + def delete_graph_nodes(self, node_ids, edges): """ 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 edge_tokens: list of edges to delete + :param list edges: list of edges to delete :return: nothing """ # delete the nodes @@ -496,11 +496,11 @@ class CoreClient: self.reusable.sort() # delete the edges and interfaces - for i in edge_tokens: + for edge in edges: try: - self.links.pop(i) + self.links.pop(edge.token) except KeyError: - logging.error("invalid edge token: %s", i) + logging.error("invalid edge token: %s", edge.token) def create_interface(self, canvas_node): node = canvas_node.core_node diff --git a/coretk/coretk/graph.py b/coretk/coretk/graph.py index b87bccbf..3f140261 100644 --- a/coretk/coretk/graph.py +++ b/coretk/coretk/graph.py @@ -388,30 +388,11 @@ class CanvasGraph(tk.Canvas): :param event: :return: """ - # hide nodes, links, link information that shows on the GUI - to_delete_nodes, to_delete_edge_tokens = ( - self.canvas_management.delete_selected_nodes() - ) + # delete canvas data + node_ids, edges = self.canvas_management.delete_selected_nodes() - # delete nodes and link info stored in CanvasGraph object - node_ids = [] - for nid in to_delete_nodes: - 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) - - # delete the edge data inside of canvas node - canvas_node_link_to_delete = [] - for canvas_id, node in self.nodes.items(): - for e in node.edges: - if e.token in to_delete_edge_tokens: - canvas_node_link_to_delete.append(tuple([canvas_id, e])) - for nid, edge in canvas_node_link_to_delete: - self.nodes[nid].edges.remove(edge) - - # delete the related data from core - self.core.delete_graph_nodes(node_ids, to_delete_edge_tokens) + # delete core data + self.core.delete_graph_nodes(node_ids, edges) 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 e1203389..7d0c374c 100644 --- a/coretk/coretk/interface.py +++ b/coretk/coretk/interface.py @@ -33,6 +33,9 @@ class InterfaceManager: self.cidr = self.cidr.next() return self.cidr + def deleted_interface(self, interface): + logging.info("deleted interface: %s", interface) + def determine_subnet(self, canvas_src_node, canvas_dst_node): src_node = canvas_src_node.core_node dst_node = canvas_dst_node.core_node diff --git a/coretk/coretk/nodedelete.py b/coretk/coretk/nodedelete.py index 6ce3a6f9..496bbc6d 100644 --- a/coretk/coretk/nodedelete.py +++ b/coretk/coretk/nodedelete.py @@ -39,23 +39,30 @@ class CanvasComponentManagement: self.selected.clear() def delete_selected_nodes(self): - selected_nodes = list(self.selected.keys()) edges = set() - for n in selected_nodes: - edges = edges.union(self.canvas.nodes[n].edges) - edge_canvas_ids = [x.id for x in edges] - edge_tokens = [x.token for x in edges] - link_infos = [x.link_info.id1 for x in edges] + [x.link_info.id2 for x in edges] - - for i in edge_canvas_ids: - self.canvas.itemconfig(i, state="hidden") - - for i in link_infos: - self.canvas.itemconfig(i, state="hidden") - - for cnid, bbid in self.selected.items(): - self.canvas.itemconfig(cnid, state="hidden") - self.canvas.itemconfig(bbid, state="hidden") - self.canvas.itemconfig(self.canvas.nodes[cnid].text_id, state="hidden") + node_ids = [] + 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) + self.canvas.delete(node_id) + self.canvas.delete(bbox_id) + self.canvas.delete(canvas_node.text_id) + for edge in canvas_node.edges: + if edge in edges: + continue + edges.add(edge) + self.canvas.edges.pop(edge.token) + self.canvas.delete(edge.id) + self.canvas.delete(edge.link_info.id1) + self.canvas.delete(edge.link_info.id2) + other_id = edge.src + other_interface = edge.src_interface + if edge.src == node_id: + other_id = edge.dst + other_interface = edge.dst_interface + other_node = self.canvas.nodes[other_id] + other_node.edges.remove(edge) + other_node.interfaces.remove(other_interface) self.selected.clear() - return selected_nodes, edge_tokens + return node_ids, edges 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 4/4] 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