def __init__(self, app: "Application", proxy: bool) -> None: """ Create a CoreGrpc instance """ self.app: "Application" = app self.master: tk.Tk = app.master self._client: client.CoreGrpcClient = client.CoreGrpcClient( proxy=proxy) self.session: Optional[Session] = None self.user = getpass.getuser() # global service settings self.services: Dict[str, Set[str]] = {} self.config_services_groups: Dict[str, Set[str]] = {} self.config_services: Dict[str, ConfigService] = {} # loaded configuration data self.servers: Dict[str, CoreServer] = {} self.custom_nodes: Dict[str, NodeDraw] = {} self.custom_observers: Dict[str, Observer] = {} self.read_config() # helpers self.iface_to_edge: Dict[Tuple[int, ...], CanvasEdge] = {} self.ifaces_manager: InterfaceManager = InterfaceManager(self.app) self.observer: Optional[str] = None # session data self.mobility_players: Dict[int, MobilityPlayer] = {} self.canvas_nodes: Dict[int, CanvasNode] = {} self.links: Dict[str, CanvasEdge] = {} self.handling_throughputs: Optional[grpc.Future] = None self.handling_cpu_usage: Optional[grpc.Future] = None self.handling_events: Optional[grpc.Future] = None
def __init__(self, app: "Application", proxy: bool): """ Create a CoreGrpc instance """ self._client = client.CoreGrpcClient(proxy=proxy) self.session_id = None self.node_ids = [] self.app = app self.master = app.master self.services = {} self.config_services_groups = {} self.config_services = {} self.default_services = {} self.emane_models = [] self.observer = None # loaded configuration data self.servers = {} self.custom_nodes = {} self.custom_observers = {} self.read_config() # helpers self.interface_to_edge = {} self.interfaces_manager = InterfaceManager(self.app) # session data 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.service_configs = {} self.config_service_configs = {} self.file_configs = {} self.mobility_players = {} self.handling_throughputs = None self.handling_events = None self.xml_dir = None self.xml_file = None self.modified_service_nodes = set()
def __init__(self, app: "Application", proxy: bool) -> None: """ Create a CoreGrpc instance """ self.app: "Application" = app self.master: tk.Tk = app.master self._client: client.CoreGrpcClient = client.CoreGrpcClient(proxy=proxy) self.session_id: Optional[int] = None self.services: Dict[str, Set[str]] = {} self.config_services_groups: Dict[str, Set[str]] = {} self.config_services: Dict[str, ConfigService] = {} self.default_services: Dict[NodeType, Set[str]] = {} self.emane_models: List[str] = [] self.observer: Optional[str] = None self.user = getpass.getuser() # loaded configuration data self.servers: Dict[str, CoreServer] = {} self.custom_nodes: Dict[str, NodeDraw] = {} self.custom_observers: Dict[str, Observer] = {} self.read_config() # helpers self.iface_to_edge: Dict[Tuple[int, ...], Tuple[int, ...]] = {} self.ifaces_manager: InterfaceManager = InterfaceManager(self.app) # session data self.state: Optional[SessionState] = None self.canvas_nodes: Dict[int, CanvasNode] = {} self.location: Optional[SessionLocation] = None self.links: Dict[Tuple[int, int], CanvasEdge] = {} self.hooks: Dict[str, Hook] = {} self.emane_config: Dict[str, ConfigOption] = {} self.mobility_players: Dict[int, MobilityPlayer] = {} self.handling_throughputs: Optional[grpc.Future] = None self.handling_cpu_usage: Optional[grpc.Future] = None self.handling_events: Optional[grpc.Future] = None self.xml_dir: Optional[str] = None self.xml_file: Optional[str] = None
class CoreClient: def __init__(self, app: "Application", proxy: bool): """ Create a CoreGrpc instance """ self._client = client.CoreGrpcClient(proxy=proxy) self.session_id = None self.node_ids = [] self.app = app self.master = app.master self.services = {} self.config_services_groups = {} self.config_services = {} self.default_services = {} self.emane_models = [] self.observer = None # loaded configuration data self.servers = {} self.custom_nodes = {} self.custom_observers = {} self.read_config() # helpers self.interface_to_edge = {} self.interfaces_manager = InterfaceManager(self.app) # session data self.state = None self.canvas_nodes = {} self.location = None self.links = {} self.hooks = {} self.emane_config = None self.mobility_players = {} self.handling_throughputs = None self.handling_events = None self.xml_dir = None self.xml_file = None @property def client(self): if self.session_id: response = self._client.check_session(self.session_id) if not response.result: throughputs_enabled = self.handling_throughputs is not None self.cancel_throughputs() self.cancel_events() self._client.create_session(self.session_id) self.handling_events = self._client.events( self.session_id, self.handle_events ) if throughputs_enabled: self.enable_throughputs() return self._client def reset(self): # helpers self.interfaces_manager.reset() self.interface_to_edge.clear() # session data self.canvas_nodes.clear() self.links.clear() self.hooks.clear() self.emane_config = None self.close_mobility_players() self.mobility_players.clear() # clear streams self.cancel_throughputs() self.cancel_events() def close_mobility_players(self): for mobility_player in self.mobility_players.values(): mobility_player.close() def set_observer(self, value: str): self.observer = value def read_config(self): # read distributed servers for server in self.app.guiconfig.servers: self.servers[server.name] = server # read custom nodes for custom_node in self.app.guiconfig.nodes: node_draw = NodeDraw.from_custom(custom_node) self.custom_nodes[custom_node.name] = node_draw # read observers for observer in self.app.guiconfig.observers: self.custom_observers[observer.name] = observer def handle_events(self, event: core_pb2.Event): if event.session_id != self.session_id: logging.warning( "ignoring event session(%s) current(%s)", event.session_id, self.session_id, ) return if event.HasField("link_event"): self.handle_link_event(event.link_event) elif event.HasField("session_event"): logging.info("session event: %s", event) session_event = event.session_event if session_event.event <= core_pb2.SessionState.SHUTDOWN: self.state = event.session_event.event elif session_event.event in {7, 8, 9}: node_id = session_event.node_id dialog = self.mobility_players.get(node_id) if dialog: if session_event.event == 7: dialog.set_play() elif session_event.event == 8: dialog.set_stop() else: dialog.set_pause() else: logging.warning("unknown session event: %s", session_event) elif event.HasField("node_event"): self.handle_node_event(event.node_event) elif event.HasField("config_event"): logging.info("config event: %s", event) elif event.HasField("exception_event"): self.handle_exception_event(event) else: logging.info("unhandled event: %s", event) def handle_link_event(self, event: core_pb2.LinkEvent): logging.debug("Link event: %s", event) node_one_id = event.link.node_one_id node_two_id = event.link.node_two_id if node_one_id == node_two_id: logging.warning("ignoring links with loops: %s", event) return canvas_node_one = self.canvas_nodes[node_one_id] canvas_node_two = self.canvas_nodes[node_two_id] if event.message_type == core_pb2.MessageType.ADD: self.app.canvas.add_wireless_edge( canvas_node_one, canvas_node_two, event.link ) elif event.message_type == core_pb2.MessageType.DELETE: self.app.canvas.delete_wireless_edge( canvas_node_one, canvas_node_two, event.link ) elif event.message_type == core_pb2.MessageType.NONE: self.app.canvas.update_wireless_edge( canvas_node_one, canvas_node_two, event.link ) else: logging.warning("unknown link event: %s", event) def handle_node_event(self, event: core_pb2.NodeEvent): logging.debug("node event: %s", event) if event.source == GUI_SOURCE: return node_id = event.node.id x = event.node.position.x y = event.node.position.y canvas_node = self.canvas_nodes[node_id] canvas_node.move(x, y) def enable_throughputs(self): self.handling_throughputs = self.client.throughputs( self.session_id, self.handle_throughputs ) def cancel_throughputs(self): if self.handling_throughputs: self.handling_throughputs.cancel() self.handling_throughputs = None def cancel_events(self): if self.handling_events: self.handling_events.cancel() self.handling_events = None def handle_throughputs(self, event: core_pb2.ThroughputsEvent): if event.session_id != self.session_id: logging.warning( "ignoring throughput event session(%s) current(%s)", event.session_id, self.session_id, ) return logging.debug("handling throughputs event: %s", event) self.app.canvas.set_throughputs(event) def handle_exception_event(self, event: core_pb2.ExceptionEvent): logging.info("exception event: %s", event) self.app.statusbar.core_alarms.append(event) def join_session(self, session_id: int, query_location: bool = True): logging.info("join session(%s)", session_id) # update session and title self.session_id = session_id self.master.title(f"CORE Session({self.session_id})") # clear session data self.reset() # get session data try: response = self.client.get_session(self.session_id) session = response.session self.state = session.state self.handling_events = self.client.events( self.session_id, self.handle_events ) # get session service defaults response = self.client.get_service_defaults(self.session_id) self.default_services = { x.node_type: set(x.services) for x in response.defaults } # get location if query_location: response = self.client.get_session_location(self.session_id) self.location = response.location # get emane models response = self.client.get_emane_models(self.session_id) self.emane_models = response.models # get hooks response = self.client.get_hooks(self.session_id) for hook in response.hooks: self.hooks[hook.file] = hook # get emane config response = self.client.get_emane_config(self.session_id) self.emane_config = response.config # update interface manager self.interfaces_manager.joined(session.links) # draw session self.app.canvas.reset_and_redraw(session) # get mobility configs response = self.client.get_mobility_configs(self.session_id) for node_id in response.configs: config = response.configs[node_id].config canvas_node = self.canvas_nodes[node_id] canvas_node.mobility_config = dict(config) # get emane model config response = self.client.get_emane_model_configs(self.session_id) for config in response.configs: interface = None if config.interface != -1: interface = config.interface canvas_node = self.canvas_nodes[config.node_id] canvas_node.emane_model_configs[(config.model, interface)] = dict( config.config ) # get wlan configurations response = self.client.get_wlan_configs(self.session_id) for _id in response.configs: mapped_config = response.configs[_id] canvas_node = self.canvas_nodes[_id] canvas_node.wlan_config = dict(mapped_config.config) # get service configurations response = self.client.get_node_service_configs(self.session_id) for config in response.configs: canvas_node = self.canvas_nodes[config.node_id] canvas_node.service_configs[config.service] = config.data logging.debug("service file configs: %s", config.files) for file_name in config.files: data = config.files[file_name] files = canvas_node.service_file_configs.setdefault( config.service, {} ) files[file_name] = data # get config service configurations response = self.client.get_node_config_service_configs(self.session_id) for config in response.configs: canvas_node = self.canvas_nodes[config.node_id] service_config = canvas_node.config_service_configs.setdefault( config.name, {} ) if config.templates: service_config["templates"] = config.templates if config.config: service_config["config"] = config.config # get metadata response = self.client.get_session_metadata(self.session_id) self.parse_metadata(response.config) except grpc.RpcError as e: self.app.show_grpc_exception("Join Session Error", e) # update ui to represent current state self.app.after(0, self.app.joined_session_update) def is_runtime(self) -> bool: return self.state == core_pb2.SessionState.RUNTIME def parse_metadata(self, config: Dict[str, str]): # canvas setting canvas_config = config.get("canvas") logging.debug("canvas metadata: %s", canvas_config) if canvas_config: canvas_config = json.loads(canvas_config) gridlines = canvas_config.get("gridlines", True) self.app.canvas.show_grid.set(gridlines) fit_image = canvas_config.get("fit_image", False) self.app.canvas.adjust_to_dim.set(fit_image) wallpaper_style = canvas_config.get("wallpaper-style", 1) self.app.canvas.scale_option.set(wallpaper_style) width = self.app.guiconfig.preferences.width height = self.app.guiconfig.preferences.height dimensions = canvas_config.get("dimensions", [width, height]) self.app.canvas.redraw_canvas(dimensions) wallpaper = canvas_config.get("wallpaper") if wallpaper: wallpaper = str(appconfig.BACKGROUNDS_PATH.joinpath(wallpaper)) self.app.canvas.set_wallpaper(wallpaper) else: self.app.canvas.redraw_canvas() self.app.canvas.set_wallpaper(None) # load saved shapes shapes_config = config.get("shapes") if shapes_config: shapes_config = json.loads(shapes_config) for shape_config in shapes_config: logging.info("loading shape: %s", shape_config) shape_type = shape_config["type"] try: shape_type = ShapeType(shape_type) coords = shape_config["iconcoords"] data = AnnotationData( shape_config["label"], shape_config["fontfamily"], shape_config["fontsize"], shape_config["labelcolor"], shape_config["color"], shape_config["border"], shape_config["width"], shape_config["bold"], shape_config["italic"], shape_config["underline"], ) shape = Shape( self.app, self.app.canvas, shape_type, *coords, data=data ) self.app.canvas.shapes[shape.id] = shape except ValueError: logging.exception("unknown shape: %s", shape_type) for tag in tags.ABOVE_WALLPAPER_TAGS: self.app.canvas.tag_raise(tag) def create_new_session(self): """ Create a new session """ try: response = self.client.create_session() logging.info("created session: %s", response) location_config = self.app.guiconfig.location self.location = core_pb2.SessionLocation( x=location_config.x, y=location_config.y, z=location_config.z, lat=location_config.lat, lon=location_config.lon, alt=location_config.alt, scale=location_config.scale, ) self.join_session(response.session_id, query_location=False) except grpc.RpcError as e: self.app.show_grpc_exception("New Session Error", e) def delete_session(self, session_id: int = None): if session_id is None: session_id = self.session_id try: response = self.client.delete_session(session_id) logging.info("deleted session(%s), Result: %s", session_id, response) except grpc.RpcError as e: self.app.show_grpc_exception("Delete Session Error", e) def setup(self): """ Query sessions, if there exist any, prompt whether to join one """ try: self.client.connect() # get service information response = self.client.get_services() for service in response.services: group_services = self.services.setdefault(service.group, set()) group_services.add(service.name) # get config service informations response = self.client.get_config_services() for service in response.services: self.config_services[service.name] = service group_services = self.config_services_groups.setdefault( service.group, set() ) group_services.add(service.name) # if there are no sessions, create a new session, else join a session response = self.client.get_sessions() sessions = response.sessions if len(sessions) == 0: self.create_new_session() else: dialog = SessionsDialog(self.app, True) dialog.show() except grpc.RpcError as e: logging.exception("core setup error") dialog = ErrorDialog(self.app, "Setup Error", e.details()) dialog.show() self.app.close() def edit_node(self, core_node: core_pb2.Node): try: self.client.edit_node( self.session_id, core_node.id, core_node.position, source=GUI_SOURCE ) except grpc.RpcError as e: self.app.show_grpc_exception("Edit Node Error", e) def start_session(self) -> core_pb2.StartSessionResponse: self.interfaces_manager.reset_mac() nodes = [x.core_node for x in self.canvas_nodes.values()] links = [] for edge in self.links.values(): link = core_pb2.Link() link.CopyFrom(edge.link) if link.HasField("interface_one") and not link.interface_one.mac: link.interface_one.mac = self.interfaces_manager.next_mac() if link.HasField("interface_two") and not link.interface_two.mac: link.interface_two.mac = self.interfaces_manager.next_mac() links.append(link) wlan_configs = self.get_wlan_configs_proto() mobility_configs = self.get_mobility_configs_proto() emane_model_configs = self.get_emane_model_configs_proto() hooks = list(self.hooks.values()) service_configs = self.get_service_configs_proto() file_configs = self.get_service_file_configs_proto() asymmetric_links = [ x.asymmetric_link for x in self.links.values() if x.asymmetric_link ] config_service_configs = self.get_config_service_configs_proto() if self.emane_config: emane_config = {x: self.emane_config[x].value for x in self.emane_config} else: emane_config = None response = core_pb2.StartSessionResponse(result=False) try: response = self.client.start_session( self.session_id, nodes, links, self.location, hooks, emane_config, emane_model_configs, wlan_configs, mobility_configs, service_configs, file_configs, asymmetric_links, config_service_configs, ) logging.info( "start session(%s), result: %s", self.session_id, response.result ) if response.result: self.set_metadata() except grpc.RpcError as e: self.app.show_grpc_exception("Start Session Error", e) return response def stop_session(self, session_id: int = None) -> core_pb2.StartSessionResponse: if not session_id: session_id = self.session_id response = core_pb2.StopSessionResponse(result=False) try: response = self.client.stop_session(session_id) logging.info("stopped session(%s), result: %s", session_id, response) except grpc.RpcError as e: self.app.show_grpc_exception("Stop Session Error", e) return response def show_mobility_players(self): for canvas_node in self.canvas_nodes.values(): if canvas_node.core_node.type != core_pb2.NodeType.WIRELESS_LAN: continue if canvas_node.mobility_config: mobility_player = MobilityPlayer( self.app, canvas_node, canvas_node.mobility_config ) node_id = canvas_node.core_node.id self.mobility_players[node_id] = mobility_player mobility_player.show() def set_metadata(self): # create canvas data wallpaper = None if self.app.canvas.wallpaper_file: wallpaper = Path(self.app.canvas.wallpaper_file).name canvas_config = { "wallpaper": wallpaper, "wallpaper-style": self.app.canvas.scale_option.get(), "gridlines": self.app.canvas.show_grid.get(), "fit_image": self.app.canvas.adjust_to_dim.get(), "dimensions": self.app.canvas.current_dimensions, } canvas_config = json.dumps(canvas_config) # create shapes data shapes = [] for shape in self.app.canvas.shapes.values(): shapes.append(shape.metadata()) shapes = json.dumps(shapes) metadata = {"canvas": canvas_config, "shapes": shapes} response = self.client.set_session_metadata(self.session_id, metadata) logging.info("set session metadata %s, result: %s", metadata, response) def launch_terminal(self, node_id: int): try: terminal = self.app.guiconfig.preferences.terminal if not terminal: messagebox.showerror( "Terminal Error", "No terminal set, please set within the preferences menu", parent=self.app, ) return response = self.client.get_node_terminal(self.session_id, node_id) cmd = f"{terminal} {response.terminal} &" logging.info("launching terminal %s", cmd) os.system(cmd) except grpc.RpcError as e: self.app.show_grpc_exception("Node Terminal Error", e) def save_xml(self, file_path: str): """ Save core session as to an xml file """ try: if self.state != core_pb2.SessionState.RUNTIME: logging.debug("Send session data to the daemon") self.send_data() response = self.client.save_xml(self.session_id, file_path) logging.info("saved xml file %s, result: %s", file_path, response) except grpc.RpcError as e: self.app.show_grpc_exception("Save XML Error", e) def open_xml(self, file_path: str): """ Open core xml """ try: response = self._client.open_xml(file_path) logging.info("open xml file %s, response: %s", file_path, response) self.join_session(response.session_id) except grpc.RpcError as e: self.app.show_grpc_exception("Open XML Error", e) def get_node_service(self, node_id: int, service_name: str) -> NodeServiceData: response = self.client.get_node_service(self.session_id, node_id, service_name) logging.debug( "get node(%s) %s service, response: %s", node_id, service_name, response ) return response.service def set_node_service( self, node_id: int, service_name: str, dirs: List[str], files: List[str], startups: List[str], validations: List[str], shutdowns: List[str], ) -> NodeServiceData: response = self.client.set_node_service( self.session_id, node_id, service_name, directories=dirs, files=files, startup=startups, validate=validations, shutdown=shutdowns, ) logging.info( "Set %s service for node(%s), files: %s, Startup: %s, Validation: %s, Shutdown: %s, Result: %s", service_name, node_id, files, startups, validations, shutdowns, response, ) response = self.client.get_node_service(self.session_id, node_id, service_name) return response.service def get_node_service_file( self, node_id: int, service_name: str, file_name: str ) -> str: response = self.client.get_node_service_file( self.session_id, node_id, service_name, file_name ) logging.debug( "get service file for node(%s), service: %s, file: %s, result: %s", node_id, service_name, file_name, response, ) return response.data def set_node_service_file( self, node_id: int, service_name: str, file_name: str, data: str ): response = self.client.set_node_service_file( self.session_id, node_id, service_name, file_name, data ) logging.info( "set node(%s) service file, service: %s, file: %s, data: %s, result: %s", node_id, service_name, file_name, data, response, ) def create_nodes_and_links(self): """ create nodes and links that have not been created yet """ node_protos = [x.core_node for x in self.canvas_nodes.values()] link_protos = [x.link for x in self.links.values()] if self.state != core_pb2.SessionState.DEFINITION: self.client.set_session_state( self.session_id, core_pb2.SessionState.DEFINITION ) self.client.set_session_state(self.session_id, core_pb2.SessionState.DEFINITION) for node_proto in node_protos: response = self.client.add_node(self.session_id, node_proto) logging.debug("create node: %s", response) for link_proto in link_protos: response = self.client.add_link( self.session_id, link_proto.node_one_id, link_proto.node_two_id, link_proto.interface_one, link_proto.interface_two, link_proto.options, ) logging.debug("create link: %s", response) def send_data(self): """ send to daemon all session info, but don't start the session """ self.create_nodes_and_links() for config_proto in self.get_wlan_configs_proto(): self.client.set_wlan_config( self.session_id, config_proto.node_id, config_proto.config ) for config_proto in self.get_mobility_configs_proto(): self.client.set_mobility_config( self.session_id, config_proto.node_id, config_proto.config ) for config_proto in self.get_service_configs_proto(): self.client.set_node_service( self.session_id, config_proto.node_id, config_proto.service, startup=config_proto.startup, validate=config_proto.validate, shutdown=config_proto.shutdown, ) for config_proto in self.get_service_file_configs_proto(): self.client.set_node_service_file( self.session_id, config_proto.node_id, config_proto.service, config_proto.file, config_proto.data, ) for hook in self.hooks.values(): self.client.add_hook(self.session_id, hook.state, hook.file, hook.data) for config_proto in self.get_emane_model_configs_proto(): self.client.set_emane_model_config( self.session_id, config_proto.node_id, config_proto.model, config_proto.config, config_proto.interface_id, ) if self.emane_config: config = {x: self.emane_config[x].value for x in self.emane_config} self.client.set_emane_config(self.session_id, config) self.set_metadata() def close(self): """ Clean ups when done using grpc """ logging.debug("close grpc") self.client.close() def next_node_id(self) -> int: """ Get the next usable node id. """ i = 1 while True: if i not in self.canvas_nodes: break i += 1 return i def create_node( self, x: float, y: float, node_type: core_pb2.NodeType, model: str ) -> Optional[core_pb2.Node]: """ Add node, with information filled in, to grpc manager """ node_id = self.next_node_id() position = core_pb2.Position(x=x, y=y) image = None if NodeUtils.is_image_node(node_type): image = "ubuntu:latest" emane = None if node_type == core_pb2.NodeType.EMANE: if not self.emane_models: dialog = EmaneInstallDialog(self.app) dialog.show() return emane = self.emane_models[0] name = f"EMANE{node_id}" elif node_type == core_pb2.NodeType.WIRELESS_LAN: name = f"WLAN{node_id}" elif node_type in [core_pb2.NodeType.RJ45, core_pb2.NodeType.TUNNEL]: name = "UNASSIGNED" else: name = f"n{node_id}" node = core_pb2.Node( id=node_id, type=node_type, name=name, model=model, position=position, image=image, emane=emane, ) if NodeUtils.is_custom(node_type, model): services = NodeUtils.get_custom_node_services(self.app.guiconfig, model) node.services[:] = services # assign default services to CORE node else: services = self.default_services.get(model) if services: node.services[:] = services logging.info( "add node(%s) to session(%s), coordinates(%s, %s)", node.name, self.session_id, x, y, ) return node def deleted_graph_nodes(self, canvas_nodes: List[core_pb2.Node]): """ remove the nodes selected by the user and anything related to that node such as link, configurations, interfaces """ for canvas_node in canvas_nodes: node_id = canvas_node.core_node.id del self.canvas_nodes[node_id] def deleted_graph_edges(self, edges: Iterable[CanvasEdge]) -> None: links = [] for edge in edges: del self.links[edge.token] links.append(edge.link) self.interfaces_manager.removed(links) def create_interface(self, canvas_node: CanvasNode) -> core_pb2.Interface: node = canvas_node.core_node 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) name = f"eth{interface_id}" interface = core_pb2.Interface( id=interface_id, name=name, ip4=ip4, ip4mask=ip4_mask, ip6=ip6, ip6mask=ip6_mask, ) logging.debug( "create node(%s) interface(%s) IPv4(%s) IPv6(%s)", node.name, interface.name, interface.ip4, interface.ip6, ) return interface def create_link( self, edge: CanvasEdge, canvas_src_node: CanvasNode, canvas_dst_node: CanvasNode ): """ Create core link for a pair of canvas nodes, with token referencing the canvas edge. """ src_node = canvas_src_node.core_node dst_node = canvas_dst_node.core_node # determine subnet self.interfaces_manager.determine_subnets(canvas_src_node, canvas_dst_node) src_interface = None if NodeUtils.is_container_node(src_node.type): src_interface = self.create_interface(canvas_src_node) 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) self.interface_to_edge[(dst_node.id, dst_interface.id)] = edge.token link = core_pb2.Link( type=core_pb2.LinkType.WIRED, node_one_id=src_node.id, node_two_id=dst_node.id, 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) def get_wlan_configs_proto(self) -> List[WlanConfig]: configs = [] for canvas_node in self.canvas_nodes.values(): if canvas_node.core_node.type != core_pb2.NodeType.WIRELESS_LAN: continue if not canvas_node.wlan_config: continue config = canvas_node.wlan_config config = {x: config[x].value for x in config} node_id = canvas_node.core_node.id wlan_config = WlanConfig(node_id=node_id, config=config) configs.append(wlan_config) return configs def get_mobility_configs_proto(self) -> List[MobilityConfig]: configs = [] for canvas_node in self.canvas_nodes.values(): if canvas_node.core_node.type != core_pb2.NodeType.WIRELESS_LAN: continue if not canvas_node.mobility_config: continue config = canvas_node.mobility_config config = {x: config[x].value for x in config} node_id = canvas_node.core_node.id mobility_config = MobilityConfig(node_id=node_id, config=config) configs.append(mobility_config) return configs def get_emane_model_configs_proto(self) -> List[EmaneModelConfig]: configs = [] for canvas_node in self.canvas_nodes.values(): if canvas_node.core_node.type != core_pb2.NodeType.EMANE: continue node_id = canvas_node.core_node.id for key, config in canvas_node.emane_model_configs.items(): model, interface = key config = {x: config[x].value for x in config} if interface is None: interface = -1 config_proto = EmaneModelConfig( node_id=node_id, interface_id=interface, model=model, config=config ) configs.append(config_proto) return configs def get_service_configs_proto(self) -> List[ServiceConfig]: configs = [] for canvas_node in self.canvas_nodes.values(): if not NodeUtils.is_container_node(canvas_node.core_node.type): continue if not canvas_node.service_configs: continue node_id = canvas_node.core_node.id for name, config in canvas_node.service_configs.items(): config_proto = ServiceConfig( node_id=node_id, service=name, directories=config.dirs, files=config.configs, startup=config.startup, validate=config.validate, shutdown=config.shutdown, ) configs.append(config_proto) return configs def get_service_file_configs_proto(self) -> List[ServiceFileConfig]: configs = [] for canvas_node in self.canvas_nodes.values(): if not NodeUtils.is_container_node(canvas_node.core_node.type): continue if not canvas_node.service_file_configs: continue node_id = canvas_node.core_node.id for service, file_configs in canvas_node.service_file_configs.items(): for file, data in file_configs.items(): config_proto = 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 canvas_node in self.canvas_nodes.values(): if not NodeUtils.is_container_node(canvas_node.core_node.type): continue if not canvas_node.config_service_configs: continue node_id = canvas_node.core_node.id for name, service_config in canvas_node.config_service_configs.items(): config = service_config.get("config", {}) config_proto = configservices_pb2.ConfigServiceConfig( node_id=node_id, name=name, templates=service_config["templates"], config=config, ) config_service_protos.append(config_proto) return config_service_protos def run(self, node_id: int) -> str: logging.info("running node(%s) cmd: %s", node_id, self.observer) return self.client.node_command(self.session_id, node_id, self.observer).output def get_wlan_config(self, node_id: int) -> Dict[str, common_pb2.ConfigOption]: response = self.client.get_wlan_config(self.session_id, node_id) config = response.config logging.debug( "get wlan configuration from node %s, result configuration: %s", node_id, config, ) return dict(config) def get_mobility_config(self, node_id: int) -> Dict[str, common_pb2.ConfigOption]: response = self.client.get_mobility_config(self.session_id, node_id) config = response.config logging.debug( "get mobility config from node %s, result configuration: %s", node_id, config, ) return dict(config) def get_emane_model_config( self, node_id: int, model: str, interface: int = None ) -> Dict[str, common_pb2.ConfigOption]: if interface is None: interface = -1 response = self.client.get_emane_model_config( self.session_id, node_id, model, interface ) config = response.config logging.debug( "get emane model config: node id: %s, EMANE model: %s, interface: %s, config: %s", node_id, model, interface, config, ) return dict(config) def execute_script(self, script): response = self.client.execute_script(script) logging.info("execute python script %s", response) if response.session_id != -1: self.join_session(response.session_id)
class CoreClient: def __init__(self, app): """ Create a CoreGrpc instance """ self.client = client.CoreGrpcClient() self.session_id = None self.node_ids = [] self.app = app self.master = app.master self.services = {} self.default_services = {} self.emane_models = [] self.observer = None # loaded configuration data self.servers = {} self.custom_nodes = {} self.custom_observers = {} self.read_config() # helpers self.interface_to_edge = {} self.interfaces_manager = InterfaceManager(self.app) # session data 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.service_configs = {} self.file_configs = {} self.mobility_players = {} self.handling_throughputs = None self.handling_events = None def reset(self): # helpers self.interfaces_manager.reset() self.interface_to_edge.clear() # session data self.canvas_nodes.clear() self.links.clear() self.hooks.clear() self.wlan_configs.clear() self.mobility_configs.clear() self.emane_model_configs.clear() self.emane_config = None self.service_configs.clear() self.file_configs.clear() self.mobility_players.clear() # clear streams if self.handling_throughputs: self.handling_throughputs.cancel() self.handling_throughputs = None if self.handling_events: self.handling_events.cancel() self.handling_events = None def set_observer(self, value): self.observer = value def read_config(self): # read distributed server for config in self.app.guiconfig.get("servers", []): server = CoreServer(config["name"], config["address"], config["port"]) self.servers[server.name] = server # read custom nodes for config in self.app.guiconfig.get("nodes", []): name = config["name"] image_file = config["image"] services = set(config["services"]) node_draw = NodeDraw.from_custom(name, image_file, services) self.custom_nodes[name] = node_draw # read observers for config in self.app.guiconfig.get("observers", []): observer = Observer(config["name"], config["cmd"]) self.custom_observers[observer.name] = observer def handle_events(self, event): if event.session_id != self.session_id: logging.warn( "ignoring event session(%s) current(%s)", event.session_id, self.session_id, ) return if event.HasField("link_event"): logging.info("link event: %s", event) self.handle_link_event(event.link_event) elif event.HasField("session_event"): logging.info("session event: %s", event) session_event = event.session_event if session_event.event <= core_pb2.SessionState.SHUTDOWN: self.state = event.session_event.event elif session_event.event in {7, 8, 9}: node_id = session_event.node_id dialog = self.mobility_players.get(node_id) if dialog: if session_event.event == 7: dialog.set_play() elif session_event.event == 8: dialog.set_stop() else: dialog.set_pause() else: logging.warning("unknown session event: %s", session_event) elif event.HasField("node_event"): self.handle_node_event(event.node_event) elif event.HasField("config_event"): logging.info("config event: %s", event) elif event.HasField("exception_event"): self.handle_exception_event(event) else: logging.info("unhandled event: %s", event) def handle_link_event(self, event): node_one_id = event.link.node_one_id node_two_id = event.link.node_two_id canvas_node_one = self.canvas_nodes[node_one_id] canvas_node_two = self.canvas_nodes[node_two_id] if event.message_type == core_pb2.MessageType.ADD: self.app.canvas.add_wireless_edge(canvas_node_one, canvas_node_two) elif event.message_type == core_pb2.MessageType.DELETE: self.app.canvas.delete_wireless_edge(canvas_node_one, canvas_node_two) else: logging.warning("unknown link event: %s", event.message_type) def handle_node_event(self, event): if event.source == GUI_SOURCE: return node_id = event.node.id x = event.node.position.x y = event.node.position.y canvas_node = self.canvas_nodes[node_id] canvas_node.move(x, y) def enable_throughputs(self): self.handling_throughputs = self.client.throughputs( self.session_id, self.handle_throughputs) def cancel_throughputs(self): self.handling_throughputs.cancel() self.handling_throughputs = None def handle_throughputs(self, event): if event.session_id != self.session_id: logging.warning( "ignoring throughput event session(%s) current(%s)", event.session_id, self.session_id, ) return logging.info("handling throughputs event: %s", event) self.app.canvas.set_throughputs(event) def handle_exception_event(self, event): logging.info("exception event: %s", event) self.app.statusbar.core_alarms.append(event) def join_session(self, session_id, query_location=True): # update session and title self.session_id = session_id self.master.title(f"CORE Session({self.session_id})") # clear session data self.reset() # get session data try: response = self.client.get_session(self.session_id) session = response.session self.state = session.state self.handling_events = self.client.events(self.session_id, self.handle_events) # get location if query_location: response = self.client.get_session_location(self.session_id) self.location = response.location # get emane models response = self.client.get_emane_models(self.session_id) self.emane_models = response.models # get hooks response = self.client.get_hooks(self.session_id) for hook in response.hooks: self.hooks[hook.file] = hook # get mobility configs response = self.client.get_mobility_configs(self.session_id) for node_id in response.configs: node_config = response.configs[node_id].config self.mobility_configs[node_id] = node_config # get emane config response = self.client.get_emane_config(self.session_id) self.emane_config = response.config # get emane model config response = self.client.get_emane_model_configs(self.session_id) for config in response.configs: interface = None if config.interface != -1: interface = config.interface self.set_emane_model_config(config.node_id, config.model, config.config, interface) # get wlan configurations response = self.client.get_wlan_configs(self.session_id) for _id in response.configs: mapped_config = response.configs[_id] self.wlan_configs[_id] = mapped_config.config # get service configurations response = self.client.get_node_service_configs(self.session_id) for config in response.configs: service_configs = self.service_configs.setdefault( config.node_id, {}) service_configs[config.service] = config.data logging.info("service file configs: %s", config.files) for file_name in config.files: file_configs = self.file_configs.setdefault( config.node_id, {}) files = file_configs.setdefault(config.service, {}) data = config.files[file_name] files[file_name] = data # draw session self.app.canvas.reset_and_redraw(session) # get metadata response = self.client.get_session_metadata(self.session_id) self.parse_metadata(response.config) except grpc.RpcError as e: self.app.after(0, show_grpc_error, e) # update ui to represent current state self.app.after(0, self.app.joined_session_update) def is_runtime(self): return self.state == core_pb2.SessionState.RUNTIME def parse_metadata(self, config): # canvas setting canvas_config = config.get("canvas") logging.info("canvas metadata: %s", canvas_config) if canvas_config: canvas_config = json.loads(canvas_config) gridlines = canvas_config.get("gridlines", True) self.app.canvas.show_grid.set(gridlines) fit_image = canvas_config.get("fit_image", False) self.app.canvas.adjust_to_dim.set(fit_image) wallpaper_style = canvas_config.get("wallpaper-style", 1) self.app.canvas.scale_option.set(wallpaper_style) width = self.app.guiconfig["preferences"]["width"] height = self.app.guiconfig["preferences"]["height"] dimensions = canvas_config.get("dimensions", [width, height]) self.app.canvas.redraw_canvas(dimensions) wallpaper = canvas_config.get("wallpaper") if wallpaper: wallpaper = str(appconfig.BACKGROUNDS_PATH.joinpath(wallpaper)) self.app.canvas.set_wallpaper(wallpaper) else: self.app.canvas.redraw_canvas() self.app.canvas.set_wallpaper(None) # load saved shapes shapes_config = config.get("shapes") if shapes_config: shapes_config = json.loads(shapes_config) for shape_config in shapes_config: logging.info("loading shape: %s", shape_config) shape_type = shape_config["type"] try: shape_type = ShapeType(shape_type) coords = shape_config["iconcoords"] data = AnnotationData( shape_config["label"], shape_config["fontfamily"], shape_config["fontsize"], shape_config["labelcolor"], shape_config["color"], shape_config["border"], shape_config["width"], shape_config["bold"], shape_config["italic"], shape_config["underline"], ) shape = Shape(self.app, self.app.canvas, shape_type, *coords, data=data) self.app.canvas.shapes[shape.id] = shape except ValueError: logging.exception("unknown shape: %s", shape_type) for tag in tags.ABOVE_WALLPAPER_TAGS: self.app.canvas.tag_raise(tag) def create_new_session(self): """ Create a new session :return: nothing """ try: response = self.client.create_session() logging.info("created session: %s", response) location_config = self.app.guiconfig["location"] self.location = core_pb2.SessionLocation( x=location_config["x"], y=location_config["y"], z=location_config["z"], lat=location_config["lat"], lon=location_config["lon"], alt=location_config["alt"], scale=location_config["scale"], ) self.join_session(response.session_id, query_location=False) except grpc.RpcError as e: self.app.after(0, show_grpc_error, e) def delete_session(self, session_id=None): if session_id is None: session_id = self.session_id try: response = self.client.delete_session(session_id) logging.info("deleted session result: %s", response) except grpc.RpcError as e: self.app.after(0, show_grpc_error, e) def set_up(self): """ Query sessions, if there exist any, prompt whether to join one :return: existing sessions """ try: self.client.connect() # get service information response = self.client.get_services() for service in response.services: group_services = self.services.setdefault(service.group, set()) group_services.add(service.name) # if there are no sessions, create a new session, else join a session response = self.client.get_sessions() logging.info("current sessions: %s", response) sessions = response.sessions if len(sessions) == 0: self.create_new_session() else: dialog = SessionsDialog(self.app, self.app) dialog.show() response = self.client.get_service_defaults(self.session_id) self.default_services = { x.node_type: set(x.services) for x in response.defaults } except grpc.RpcError as e: self.app.after(0, show_grpc_error, e) self.app.close() def edit_node(self, core_node): try: self.client.edit_node(self.session_id, core_node.id, core_node.position, source=GUI_SOURCE) except grpc.RpcError as e: self.app.after(0, show_grpc_error, e) def start_session(self): nodes = [x.core_node for x in self.canvas_nodes.values()] links = [x.link for x in 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() hooks = list(self.hooks.values()) service_configs = self.get_service_configs_proto() file_configs = self.get_service_file_configs_proto() asymmetric_links = [ x.asymmetric_link for x in self.links.values() if x.asymmetric_link ] if self.emane_config: emane_config = { x: self.emane_config[x].value for x in self.emane_config } else: emane_config = None response = core_pb2.StartSessionResponse(result=False) try: response = self.client.start_session( self.session_id, nodes, links, self.location, hooks, emane_config, emane_model_configs, wlan_configs, mobility_configs, service_configs, file_configs, asymmetric_links, ) logging.debug("start session(%s), result: %s", self.session_id, response.result) if response.result: self.set_metadata() except grpc.RpcError as e: self.app.after(0, show_grpc_error, e) return response def stop_session(self, session_id=None): if not session_id: session_id = self.session_id response = core_pb2.StopSessionResponse(result=False) try: response = self.client.stop_session(session_id) logging.debug("stopped session(%s), result: %s", session_id, response) except grpc.RpcError as e: self.app.after(0, show_grpc_error, e) return response def show_mobility_players(self): for node_id, config in self.mobility_configs.items(): canvas_node = self.canvas_nodes[node_id] mobility_player = MobilityPlayer(self.app, self.app, canvas_node, config) mobility_player.show() self.mobility_players[node_id] = mobility_player def set_metadata(self): # create canvas data wallpaper = None if self.app.canvas.wallpaper_file: wallpaper = Path(self.app.canvas.wallpaper_file).name canvas_config = { "wallpaper": wallpaper, "wallpaper-style": self.app.canvas.scale_option.get(), "gridlines": self.app.canvas.show_grid.get(), "fit_image": self.app.canvas.adjust_to_dim.get(), "dimensions": self.app.canvas.current_dimensions, } canvas_config = json.dumps(canvas_config) # create shapes data shapes = [] for shape in self.app.canvas.shapes.values(): shapes.append(shape.metadata()) shapes = json.dumps(shapes) metadata = {"canvas": canvas_config, "shapes": shapes} response = self.client.set_session_metadata(self.session_id, metadata) logging.info("set session metadata: %s", response) def launch_terminal(self, node_id): try: terminal = self.app.guiconfig["preferences"]["terminal"] response = self.client.get_node_terminal(self.session_id, node_id) logging.info("get terminal %s", response.terminal) os.system(f"{terminal} {response.terminal} &") except grpc.RpcError as e: self.app.after(0, show_grpc_error, e) def save_xml(self, file_path): """ Save core session as to an xml file :param str file_path: file path that user pick :return: nothing """ try: if self.state != core_pb2.SessionState.RUNTIME: logging.debug( "session state not runtime, send session data to the daemon..." ) self.send_data() response = self.client.save_xml(self.session_id, file_path) logging.info("saved xml(%s): %s", file_path, response) except grpc.RpcError as e: self.app.after(0, show_grpc_error, e) def open_xml(self, file_path): """ Open core xml :param str file_path: file to open :return: session id """ try: response = self.client.open_xml(file_path) logging.debug("open xml: %s", response) self.join_session(response.session_id) except grpc.RpcError as e: self.app.after(0, show_grpc_error, e) def get_node_service(self, node_id, service_name): response = self.client.get_node_service(self.session_id, node_id, service_name) logging.debug("get node service %s", response) return response.service def set_node_service(self, node_id, service_name, startups, validations, shutdowns): response = self.client.set_node_service(self.session_id, node_id, service_name, startups, validations, shutdowns) logging.debug("set node service %s", response) response = self.client.get_node_service(self.session_id, node_id, service_name) logging.debug("get node service : %s", response) return response.service def get_node_service_file(self, node_id, service_name, file_name): response = self.client.get_node_service_file(self.session_id, node_id, service_name, file_name) logging.debug("get service file %s", response) return response.data def set_node_service_file(self, node_id, service_name, file_name, data): response = self.client.set_node_service_file(self.session_id, node_id, service_name, file_name, data) logging.debug("set node service file %s", response) def create_nodes_and_links(self): """ create nodes and links that have not been created yet :return: nothing """ node_protos = [x.core_node for x in self.canvas_nodes.values()] link_protos = [x.link for x in self.links.values()] if self.state != core_pb2.SessionState.DEFINITION: self.client.set_session_state(self.session_id, core_pb2.SessionState.DEFINITION) self.client.set_session_state(self.session_id, core_pb2.SessionState.DEFINITION) for node_proto in node_protos: response = self.client.add_node(self.session_id, node_proto) logging.debug("create node: %s", response) for link_proto in link_protos: response = self.client.add_link( self.session_id, link_proto.node_one_id, link_proto.node_two_id, link_proto.interface_one, link_proto.interface_two, link_proto.options, ) logging.debug("create link: %s", response) def send_data(self): """ send to daemon all session info, but don't start the session :return: nothing """ self.create_nodes_and_links() for config_proto in self.get_wlan_configs_proto(): self.client.set_wlan_config(self.session_id, config_proto.node_id, config_proto.config) for config_proto in self.get_mobility_configs_proto(): self.client.set_mobility_config(self.session_id, config_proto.node_id, config_proto.config) for config_proto in self.get_service_configs_proto(): self.client.set_node_service( self.session_id, config_proto.node_id, config_proto.service, config_proto.startup, config_proto.validate, config_proto.shutdown, ) for config_proto in self.get_service_file_configs_proto(): self.client.set_node_service_file( self.session_id, config_proto.node_id, config_proto.service, config_proto.file, config_proto.data, ) for hook in self.hooks.values(): self.client.add_hook(self.session_id, hook.state, hook.file, hook.data) for config_proto in self.get_emane_model_configs_proto(): self.client.set_emane_model_config( self.session_id, config_proto.node_id, config_proto.model, config_proto.config, config_proto.interface_id, ) if self.emane_config: config = {x: self.emane_config[x].value for x in self.emane_config} self.client.set_emane_config(self.session_id, config) def close(self): """ Clean ups when done using grpc :return: nothing """ logging.debug("close grpc") self.client.close() def next_node_id(self): """ Get the next usable node id. :return: the next id to be used :rtype: int """ i = 1 while True: if i not in self.canvas_nodes: break i += 1 return i def create_node(self, x, y, node_type, model): """ Add node, with information filled in, to grpc manager :param int x: x coord :param int y: y coord :param core_pb2.NodeType node_type: node type :param str model: node model :return: nothing """ node_id = self.next_node_id() position = core_pb2.Position(x=x, y=y) image = None if NodeUtils.is_image_node(node_type): image = "ubuntu:latest" emane = None if node_type == core_pb2.NodeType.EMANE: emane = self.emane_models[0] node = core_pb2.Node( id=node_id, type=node_type, name=f"n{node_id}", model=model, position=position, image=image, emane=emane, ) logging.debug( "adding node to core session: %s, coords: (%s, %s), name: %s", self.session_id, x, y, node.name, ) return node 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 canvas_nodes: list of nodes to delete :return: nothing """ 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] 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] 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) self.links.pop(edge.token, None) def create_interface(self, canvas_node): node = canvas_node.core_node ip4, ip6, prefix = self.interfaces_manager.get_ips(node.id) interface_id = len(canvas_node.interfaces) name = f"eth{interface_id}" interface = core_pb2.Interface(id=interface_id, name=name, ip4=ip4, ip4mask=prefix, ip6=ip6, ip6mask=prefix) canvas_node.interfaces.append(interface) logging.debug( "create node(%s) interface IPv4: %s, name: %s", node.name, interface.ip4, interface.name, ) return interface def create_link(self, edge, canvas_src_node, canvas_dst_node): """ Create core link for a pair of canvas nodes, with token referencing the canvas edge. :param edge: edge for link :param canvas_src_node: canvas node one :param canvas_dst_node: canvas node two :return: nothing """ src_node = canvas_src_node.core_node dst_node = canvas_dst_node.core_node # determine subnet self.interfaces_manager.determine_subnet(canvas_src_node, canvas_dst_node) 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( type=core_pb2.LinkType.WIRED, node_one_id=src_node.id, node_two_id=dst_node.id, interface_one=src_interface, interface_two=dst_interface, ) edge.set_link(link) self.links[edge.token] = edge def get_wlan_configs_proto(self): configs = [] for node_id, config in self.wlan_configs.items(): config = {x: config[x].value for x in config} wlan_config = core_pb2.WlanConfig(node_id=node_id, config=config) configs.append(wlan_config) return configs def get_mobility_configs_proto(self): configs = [] for node_id, config in self.mobility_configs.items(): config = {x: config[x].value for x in config} mobility_config = core_pb2.MobilityConfig(node_id=node_id, config=config) configs.append(mobility_config) return configs def get_emane_model_configs_proto(self): configs = [] for key, config in self.emane_model_configs.items(): node_id, model, interface = key config = {x: config[x].value for x in config} if interface is None: interface = -1 config_proto = core_pb2.EmaneModelConfig(node_id=node_id, interface_id=interface, model=model, config=config) configs.append(config_proto) return configs def get_service_configs_proto(self): configs = [] for node_id, services in self.service_configs.items(): for name, config in services.items(): config_proto = core_pb2.ServiceConfig( node_id=node_id, service=name, startup=config.startup, validate=config.validate, shutdown=config.shutdown, ) configs.append(config_proto) return configs def get_service_file_configs_proto(self): configs = [] for (node_id, file_configs) in self.file_configs.items(): for service, file_config in file_configs.items(): for file, data in file_config.items(): config_proto = core_pb2.ServiceFileConfig(node_id=node_id, service=service, file=file, data=data) configs.append(config_proto) return configs def run(self, node_id): logging.info("running node(%s) cmd: %s", node_id, self.observer) return self.client.node_command(self.session_id, node_id, self.observer).output def get_wlan_config(self, node_id): config = self.wlan_configs.get(node_id) if not config: response = self.client.get_wlan_config(self.session_id, node_id) config = response.config return config def get_mobility_config(self, node_id): config = self.mobility_configs.get(node_id) if not config: response = self.client.get_mobility_config(self.session_id, node_id) config = response.config return config def get_emane_model_config(self, node_id, model, interface=None): logging.info("getting emane model config: %s %s %s", node_id, model, interface) config = self.emane_model_configs.get((node_id, model, interface)) if not config: if interface is None: interface = -1 response = self.client.get_emane_model_config( self.session_id, node_id, model, interface) config = response.config return config def set_emane_model_config(self, node_id, model, config, interface=None): logging.info("setting emane model config: %s %s %s", node_id, model, interface) self.emane_model_configs[(node_id, model, interface)] = config def copy_node_service(self, _from, _to): services = self.canvas_nodes[_from].core_node.services self.canvas_nodes[_to].core_node.services[:] = services def copy_node_config(self, _from, _to): node_type = self.canvas_nodes[_from].core_node.type if node_type == core_pb2.NodeType.DEFAULT: services = self.canvas_nodes[_from].core_node.services self.canvas_nodes[_to].core_node.services[:] = services config = self.service_configs.get(_from) if config: self.service_configs[_to] = config file_configs = self.file_configs.get(_from) if file_configs: for key, value in file_configs.items(): if _to not in self.file_configs: self.file_configs[_to] = {} self.file_configs[_to][key] = value elif node_type == core_pb2.NodeType.WIRELESS_LAN: config = self.wlan_configs.get(_from) if config: self.wlan_configs[_to] = config config = self.mobility_configs.get(_from) if config: self.mobility_configs[_to] = config elif node_type == core_pb2.NodeType.EMANE: config = self.emane_model_configs.get(_from) if config: self.emane_model_configs[_to] = config