def save_edge(self, edge: CanvasEdge) -> None: self.links[edge.token] = edge src_node = edge.src.core_node dst_node = edge.dst.core_node if nutils.is_container(src_node): src_iface_id = edge.link.iface1.id self.iface_to_edge[(src_node.id, src_iface_id)] = edge if nutils.is_container(dst_node): dst_iface_id = edge.link.iface2.id self.iface_to_edge[(dst_node.id, dst_iface_id)] = edge
def click_apply(self) -> None: error = False # update core node self.node.name = self.name.get() if nutils.has_image(self.node.type): self.node.image = self.container_image.get() server = self.server.get() if nutils.is_container(self.node): if server == DEFAULT_SERVER: self.node.server = None else: self.node.server = server # set custom icon if self.image_file: self.node.icon = self.image_file # update canvas node self.canvas_node.image = self.image # update node interface data for iface in self.canvas_node.ifaces.values(): data = self.ifaces[iface.id] error = not data.validate(self, iface) if error: break # redraw if not error: self.canvas_node.redraw() self.destroy()
def store_nodes(self) -> None: """ store all CORE nodes (nodes that execute commands) from all existing nodes """ for node in self.app.core.session.nodes.values(): if nutils.is_container(node): self.executable_nodes[node.name] = node.id
def on_enter(self, event: tk.Event) -> None: is_runtime = self.app.core.is_runtime() has_observer = self.app.core.observer is not None is_container = nutils.is_container(self.core_node) if is_runtime and has_observer and is_container: self.tooltip.text.set("waiting...") self.tooltip.on_enter(event) try: output = self.app.core.run(self.core_node.id) self.tooltip.text.set(output) except grpc.RpcError as e: self.app.show_grpc_exception("Observer Error", e)
def get_service_file_configs(self) -> List[ServiceFileConfig]: configs = [] for node in self.session.nodes.values(): if not nutils.is_container(node): continue if not node.service_file_configs: continue for service, file_configs in node.service_file_configs.items(): for file, data in file_configs.items(): config = ServiceFileConfig(node.id, service, file, data) configs.append(config) return configs
def create_link(self, edge: CanvasEdge) -> Link: """ Create core link for a given edge based on src/dst nodes. """ src_node = edge.src.core_node dst_node = edge.dst.core_node self.determine_subnets(edge.src, edge.dst) src_iface = None if nutils.is_container(src_node): src_iface = self.create_iface(edge.src, edge.linked_wireless) dst_iface = None if nutils.is_container(dst_node): dst_iface = self.create_iface(edge.dst, edge.linked_wireless) link = Link( type=LinkType.WIRED, node1_id=src_node.id, node2_id=dst_node.id, iface1=src_iface, iface2=dst_iface, ) logger.info("added link between %s and %s", src_node.name, dst_node.name) return link
def draw(self) -> None: self.columnconfigure(0, weight=1) node = self.canvas_node.core_node frame = DetailsFrame(self) frame.grid(sticky=tk.EW) frame.add_detail("ID", str(node.id)) frame.add_detail("Name", node.name) if nutils.is_model(node): frame.add_detail("Type", node.model) if nutils.is_container(node): for index, service in enumerate(sorted(node.services)): if index == 0: frame.add_detail("Services", service) else: frame.add_detail("", service) if node.type == NodeType.EMANE: emane = "".join(node.emane.split("_")[1:]) frame.add_detail("EMANE", emane) if nutils.has_image(node.type): frame.add_detail("Image", node.image) if nutils.is_container(node): server = node.server if node.server else "localhost" frame.add_detail("Server", server)
def determine_subnets( self, canvas_src_node: CanvasNode, canvas_dst_node: CanvasNode ) -> None: src_node = canvas_src_node.core_node dst_node = canvas_dst_node.core_node is_src_container = nutils.is_container(src_node) is_dst_container = nutils.is_container(dst_node) if is_src_container and is_dst_container: self.current_subnets = self.next_subnets() elif is_src_container and not is_dst_container: subnets = self.find_subnets(canvas_dst_node, visited={src_node.id}) if subnets: self.current_subnets = subnets else: self.current_subnets = self.next_subnets() elif not is_src_container and is_dst_container: subnets = self.find_subnets(canvas_src_node, visited={dst_node.id}) if subnets: self.current_subnets = subnets else: self.current_subnets = self.next_subnets() else: logger.info("ignoring subnet change for link between network nodes")
def get_service_file_configs_proto( self) -> List[services_pb2.ServiceFileConfig]: configs = [] for node in self.session.nodes.values(): if not nutils.is_container(node): continue if not node.service_file_configs: continue for service, file_configs in node.service_file_configs.items(): for file, data in file_configs.items(): config_proto = services_pb2.ServiceFileConfig( node_id=node.id, service=service, file=file, data=data) configs.append(config_proto) return configs
def get_config_service_configs_proto( self) -> List[configservices_pb2.ConfigServiceConfig]: config_service_protos = [] for node in self.session.nodes.values(): if not nutils.is_container(node): continue if not node.config_service_configs: continue for name, service_config in node.config_service_configs.items(): config_proto = configservices_pb2.ConfigServiceConfig( node_id=node.id, name=name, templates=service_config.templates, config=service_config.config, ) config_service_protos.append(config_proto) return config_service_protos
def get_service_configs(self) -> List[ServiceConfig]: configs = [] for node in self.session.nodes.values(): if not nutils.is_container(node): continue if not node.service_configs: continue for name, config in node.service_configs.items(): config = ServiceConfig( node_id=node.id, service=name, files=config.configs, directories=config.dirs, startup=config.startup, validate=config.validate, shutdown=config.shutdown, ) configs.append(config) return configs
def show_context(self, event: tk.Event) -> None: # clear existing menu self.context.delete(0, tk.END) is_wlan = self.core_node.type == NodeType.WIRELESS_LAN is_emane = self.core_node.type == NodeType.EMANE is_mobility = is_wlan or is_emane if self.app.core.is_runtime(): self.context.add_command(label="Configure", command=self.show_config) if is_emane: self.context.add_command( label="EMANE Config", command=self.show_emane_config ) if is_wlan: self.context.add_command( label="WLAN Config", command=self.show_wlan_config ) if is_mobility and self.core_node.id in self.app.core.mobility_players: self.context.add_command( label="Mobility Player", command=self.show_mobility_player ) if nutils.is_container(self.core_node): services_menu = tk.Menu(self.context) for service in sorted(self.core_node.config_services): service_menu = tk.Menu(services_menu) themes.style_menu(service_menu) start_func = functools.partial(self.start_service, service) service_menu.add_command(label="Start", command=start_func) stop_func = functools.partial(self.stop_service, service) service_menu.add_command(label="Stop", command=stop_func) restart_func = functools.partial(self.restart_service, service) service_menu.add_command(label="Restart", command=restart_func) validate_func = functools.partial(self.validate_service, service) service_menu.add_command(label="Validate", command=validate_func) services_menu.add_cascade(label=service, menu=service_menu) themes.style_menu(services_menu) self.context.add_cascade(label="Services", menu=services_menu) else: self.context.add_command(label="Configure", command=self.show_config) if nutils.is_container(self.core_node): self.context.add_command( label="Config Services", command=self.show_config_services ) self.context.add_command( label="Services (Deprecated)", command=self.show_services ) if is_emane: self.context.add_command( label="EMANE Config", command=self.show_emane_config ) if is_wlan: self.context.add_command( label="WLAN Config", command=self.show_wlan_config ) if is_mobility: self.context.add_command( label="Mobility Config", command=self.show_mobility_config ) if nutils.is_wireless(self.core_node): self.context.add_command( label="Link To Selected", command=self.wireless_link_selected ) link_menu = tk.Menu(self.context) for canvas in self.app.manager.all(): canvas_menu = tk.Menu(link_menu) themes.style_menu(canvas_menu) for node in canvas.nodes.values(): if not self.is_linkable(node): continue func_link = functools.partial(self.click_link, node) canvas_menu.add_command( label=node.core_node.name, command=func_link ) link_menu.add_cascade(label=f"Canvas {canvas.id}", menu=canvas_menu) themes.style_menu(link_menu) self.context.add_cascade(label="Link", menu=link_menu) unlink_menu = tk.Menu(self.context) for edge in self.edges: other_node = edge.other_node(self) other_iface = edge.other_iface(self) label = other_node.core_node.name if other_iface: label = f"{label}:{other_iface.name}" func_unlink = functools.partial(self.click_unlink, edge) unlink_menu.add_command(label=label, command=func_unlink) themes.style_menu(unlink_menu) self.context.add_cascade(label="Unlink", menu=unlink_menu) edit_menu = tk.Menu(self.context) themes.style_menu(edit_menu) edit_menu.add_command(label="Cut", command=self.click_cut) edit_menu.add_command(label="Copy", command=self.canvas_copy) edit_menu.add_command(label="Delete", command=self.canvas_delete) edit_menu.add_command(label="Hide", command=self.click_hide) self.context.add_cascade(label="Edit", menu=edit_menu) self.context.tk_popup(event.x_root, event.y_root)
def double_click(self, event: tk.Event) -> None: if self.app.core.is_runtime(): if nutils.is_container(self.core_node): self.canvas.core.launch_terminal(self.core_node.id) else: self.show_config()
def draw(self) -> None: self.top.columnconfigure(0, weight=1) row = 0 # field states state = tk.DISABLED if self.app.core.is_runtime() else tk.NORMAL combo_state = tk.DISABLED if self.app.core.is_runtime() else "readonly" # field frame frame = ttk.Frame(self.top) frame.grid(sticky=tk.EW) frame.columnconfigure(1, weight=1) # icon field label = ttk.Label(frame, text="Icon") label.grid(row=row, column=0, sticky=tk.EW, padx=PADX, pady=PADY) self.image_button = ttk.Button( frame, text="Icon", image=self.image, compound=tk.NONE, command=self.click_icon, ) self.image_button.grid(row=row, column=1, sticky=tk.EW) row += 1 # name field label = ttk.Label(frame, text="Name") label.grid(row=row, column=0, sticky=tk.EW, padx=PADX, pady=PADY) entry = validation.NodeNameEntry(frame, textvariable=self.name, state=state) entry.grid(row=row, column=1, sticky=tk.EW) row += 1 # node type field if nutils.is_model(self.node): label = ttk.Label(frame, text="Type") label.grid(row=row, column=0, sticky=tk.EW, padx=PADX, pady=PADY) combobox = ttk.Combobox( frame, textvariable=self.type, values=list(nutils.NODE_MODELS), state=combo_state, ) combobox.grid(row=row, column=1, sticky=tk.EW) row += 1 # container image field if nutils.has_image(self.node.type): label = ttk.Label(frame, text="Image") label.grid(row=row, column=0, sticky=tk.EW, padx=PADX, pady=PADY) entry = ttk.Entry(frame, textvariable=self.container_image, state=state) entry.grid(row=row, column=1, sticky=tk.EW) row += 1 if nutils.is_container(self.node): # server frame.grid(sticky=tk.EW) frame.columnconfigure(1, weight=1) label = ttk.Label(frame, text="Server") label.grid(row=row, column=0, sticky=tk.EW, padx=PADX, pady=PADY) servers = [DEFAULT_SERVER] servers.extend(list(sorted(self.app.core.servers.keys()))) combobox = ttk.Combobox(frame, textvariable=self.server, values=servers, state=combo_state) combobox.grid(row=row, column=1, sticky=tk.EW) row += 1 if nutils.is_rj45(self.node): ifaces = self.app.core.client.get_ifaces() logger.debug("host machine available interfaces: %s", ifaces) ifaces_scroll = ListboxScroll(frame) ifaces_scroll.listbox.config(state=state) ifaces_scroll.grid(row=row, column=0, columnspan=2, sticky=tk.EW, padx=PADX, pady=PADY) for inf in sorted(ifaces): ifaces_scroll.listbox.insert(tk.END, inf) row += 1 ifaces_scroll.listbox.bind("<<ListboxSelect>>", self.iface_select) # interfaces if self.canvas_node.ifaces: self.draw_ifaces() self.draw_spacer() self.draw_buttons()