def stopdaemons(self) -> None: """ Kill the appropriate EMANE daemons. """ # TODO: we may want to improve this if we had the PIDs from the specific EMANE # daemons that we"ve started kill_emaned = "killall -q emane" kill_transortd = "killall -q emanetransportd" stop_emane_on_host = False for node in self.getnodes(): if hasattr(node, "transport_type") and node.transport_type == "raw": stop_emane_on_host = True continue if node.up: node.cmd(kill_emaned, wait=False) # TODO: RJ45 node if stop_emane_on_host: try: utils.cmd(kill_emaned) utils.cmd(kill_transortd) self.session.distributed.execute(lambda x: x.remote_cmd(kill_emaned)) self.session.distributed.execute(lambda x: x.remote_cmd(kill_transortd)) except CoreCommandError: logging.exception("error shutting down emane daemons")
def emane_check(self) -> None: """ Check if emane is installed and load models. :return: nothing """ # check for emane path = utils.which("emane", required=False) if not path: logging.info("emane is not installed") return # get version emane_version = utils.cmd("emane --version") logging.info("using emane: %s", emane_version) # load default emane models self.load_models(EMANE_MODELS) # load custom models custom_models_path = self.session.options.get_config( "emane_models_dir") if custom_models_path: emane_models = utils.load_classes(custom_models_path, EmaneModel) self.load_models(emane_models)
def emane_check(self) -> None: """ Check if emane is installed and load models. :return: nothing """ try: # check for emane args = "emane --version" emane_version = utils.cmd(args) logging.info("using EMANE: %s", emane_version) self.session.distributed.execute(lambda x: x.remote_cmd(args)) # load default emane models self.load_models(EMANE_MODELS) # load custom models custom_models_path = self.session.options.get_config( "emane_models_dir") if custom_models_path: emane_models = utils.load_classes(custom_models_path, EmaneModel) self.load_models(emane_models) except CoreCommandError: logging.info("emane is not installed")
def nsenter_cmd(self, args: str, wait: bool = True, shell: bool = False) -> str: if self.server is None: args = self.client.create_ns_cmd(args) return utils.cmd(args, wait=wait, shell=shell) else: args = self.client.create_ns_cmd(args) return self.server.remote_cmd(args, wait=wait)
def host_cmd( self, args: str, env: Dict[str, str] = None, cwd: str = None, wait: bool = True, shell: bool = False, ) -> str: """ Runs a command that is used to configure and setup the network on the host system and all configured distributed servers. :param args: command to run :param env: environment to run command with :param cwd: directory to run command in :param wait: True to wait for status, False otherwise :param shell: True to use shell, False otherwise :return: combined stdout and stderr :raises CoreCommandError: when a non-zero exit status occurs """ logging.debug("network node(%s) cmd", self.name) output = utils.cmd(args, env, cwd, wait, shell) self.session.distributed.execute( lambda x: x.remote_cmd(args, env, cwd, wait)) return output
def check_cmd(self, cmd: str, wait: bool = True, shell: bool = False) -> str: logging.info("docker cmd output: %s", cmd) return utils.cmd(f"docker exec {self.name} {cmd}", wait=wait, shell=shell)
def post_startup(self, iface: CoreInterface) -> None: # get configured schedule emane_net = self.session.get_node(self.id, EmaneNet) config = self.session.emane.get_iface_config(emane_net, iface) schedule = Path(config[self.schedule_name]) if not schedule.is_file(): logger.error("ignoring invalid tdma schedule: %s", schedule) return # initiate tdma schedule nem_id = self.session.emane.get_nem_id(iface) if not nem_id: logger.error("could not find nem for interface") return service = self.session.emane.nem_service.get(nem_id) if service: device = service.device logger.info( "setting up tdma schedule: schedule(%s) device(%s)", schedule, device ) utils.cmd(f"emaneevent-tdmaschedule -i {device} {schedule}")
def statescript(self, typestr: str) -> None: """ State of the mobility script. :param typestr: state type string :return: nothing """ filename = None if typestr == "run" or typestr == "unpause": filename = self.script_start elif typestr == "pause": filename = self.script_pause elif typestr == "stop": filename = self.script_stop if filename is None or filename == "": return filename = self.findfile(filename) args = f"/bin/sh {filename} {typestr}" utils.cmd( args, cwd=self.session.session_dir, env=self.session.get_environment() )
def post_startup(self): """ Logic to execute after the emane manager is finished with startup. :return: nothing """ # get configured schedule config = self.session.emane.get_configs(node_id=self.id, config_type=self.name) if not config: return schedule = config[self.schedule_name] # get the set event device event_device = self.session.emane.event_device # initiate tdma schedule logging.info("setting up tdma schedule: schedule(%s) device(%s)", schedule, event_device) args = f"emaneevent-tdmaschedule -i {event_device} {schedule}" utils.cmd(args)
def cmd(self, args, wait=True): """ Runs shell command on node, with option to not wait for a result. :param list[str]|str args: command to run :param bool wait: wait for command to exit, defaults to True :return: exit status for command :rtype: int """ os.chdir(self.nodedir) status = utils.cmd(args, wait) return status
def detectversionfromcmd(cls) -> int: """ Detect the apache2 version using the 'a2query' command. """ try: result = utils.cmd("a2query -v") status = 0 except CoreCommandError as e: status = e.returncode result = e.stderr if status == 0 and result[:3] == "2.4": return cls.APACHEVER24 return cls.APACHEVER22
def check_cmd(self, args: str, wait: bool = True, shell: bool = False) -> str: """ Run command and return exit status and combined stdout and stderr. :param args: command to run :param wait: True to wait for command status, False otherwise :param shell: True to use shell, False otherwise :return: combined stdout and stderr :raises core.CoreCommandError: when there is a non-zero exit status """ self._verify_connection() args = self.create_cmd(args) return utils.cmd(args, wait=wait, shell=shell)
def cmd(self, args: str, wait: bool = True, shell: bool = False) -> str: """ Runs a command that is used to configure and setup the network within a node. :param args: command to run :param wait: True to wait for status, False otherwise :param shell: True to use shell, False otherwise :return: combined stdout and stderr :raises CoreCommandError: when a non-zero exit status occurs """ args = self._create_cmd(args, shell) if self.server is None: return utils.cmd(args, wait=wait, shell=shell) else: return self.server.remote_cmd(args, wait=wait)
def host_cmd(self, args, env=None, cwd=None, wait=True, shell=False): """ Runs a command on the host system or distributed server. :param str args: command to run :param dict env: environment to run command with :param str cwd: directory to run command in :param bool wait: True to wait for status, False otherwise :param bool shell: True to use shell, False otherwise :return: combined stdout and stderr :rtype: str :raises CoreCommandError: when a non-zero exit status occurs """ if self.server is None: return utils.cmd(args, env, cwd, wait, shell) else: return self.server.remote_cmd(args, env, cwd, wait)
def get_ipv4_addresses(hostname): if hostname == "localhost": addresses = [] args = f"{IP_BIN} -o -f inet address show" output = utils.cmd(args) for line in output.split(os.linesep): split = line.split() if not split: continue interface_name = split[1] address = split[3] if not address.startswith("127."): addresses.append((interface_name, address)) return addresses else: # TODO: handle other hosts raise NotImplementedError
def _load_emane(self) -> None: """ Check if emane is installed and load models. :return: nothing """ # check for emane path = utils.which("emane", required=False) self.has_emane = path is not None if not self.has_emane: logger.info("emane is not installed, emane functionality disabled") return # get version emane_version = utils.cmd("emane --version") logger.info("using emane: %s", emane_version) emane_prefix = self.config.get("emane_prefix", DEFAULT_EMANE_PREFIX) emane_prefix = Path(emane_prefix) EmaneModelManager.load_locals(emane_prefix) # load custom models custom_path = self.config.get("emane_models_dir") if custom_path is not None: logger.info("loading custom emane models: %s", custom_path) custom_path = Path(custom_path) EmaneModelManager.load(custom_path, emane_prefix)
def check_cmd(self, cmd, wait=True, shell=False): args = self.create_cmd(cmd) return utils.cmd(args, wait=wait, shell=shell)
def localdevexists(): args = [constants.IP_BIN, "link", "show", self.localname] return utils.cmd(args)
def ns_cmd(self, cmd: str, wait: bool) -> str: args = f"nsenter -t {self.pid} -u -i -p -n {cmd}" return utils.cmd(args, wait=wait)
def check_cmd(self, cmd: str, wait: bool = True, shell: bool = False) -> str: args = self.create_cmd(cmd) return utils.cmd(args, wait=wait, shell=shell)
def cmd(self, cmd, wait=True): if isinstance(cmd, list): cmd = " ".join(cmd) logging.info("docker cmd wait(%s): %s", wait, cmd) return utils.cmd( "docker exec {name} {cmd}".format(name=self.name, cmd=cmd), wait)
def ns_cmd(self, cmd, wait=True): if isinstance(cmd, list): cmd = " ".join(cmd) args = self._ns_args(cmd) logging.info("ns cmd: %s", args) return utils.cmd(args, wait)
def startdaemons(self) -> None: """ Start one EMANE daemon per node having a radio. Add a control network even if the user has not configured one. """ logging.info("starting emane daemons...") loglevel = str(EmaneManager.DEFAULT_LOG_LEVEL) cfgloglevel = self.session.options.get_config_int("emane_log_level") realtime = self.session.options.get_config_bool("emane_realtime", default=True) if cfgloglevel: logging.info("setting user-defined EMANE log level: %d", cfgloglevel) loglevel = str(cfgloglevel) emanecmd = f"emane -d -l {loglevel}" if realtime: emanecmd += " -r" otagroup, _otaport = self.get_config("otamanagergroup").split(":") otadev = self.get_config("otamanagerdevice") otanetidx = self.session.get_control_net_index(otadev) eventgroup, _eventport = self.get_config("eventservicegroup").split(":") eventdev = self.get_config("eventservicedevice") eventservicenetidx = self.session.get_control_net_index(eventdev) run_emane_on_host = False for node in self.getnodes(): if hasattr(node, "transport_type") and node.transport_type == "raw": run_emane_on_host = True continue path = self.session.session_dir n = node.id # control network not yet started here self.session.add_remove_control_interface( node, 0, remove=False, conf_required=False ) if otanetidx > 0: logging.info("adding ota device ctrl%d", otanetidx) self.session.add_remove_control_interface( node, otanetidx, remove=False, conf_required=False ) if eventservicenetidx >= 0: logging.info("adding event service device ctrl%d", eventservicenetidx) self.session.add_remove_control_interface( node, eventservicenetidx, remove=False, conf_required=False ) # multicast route is needed for OTA data node.node_net_client.create_route(otagroup, otadev) # multicast route is also needed for event data if on control network if eventservicenetidx >= 0 and eventgroup != otagroup: node.node_net_client.create_route(eventgroup, eventdev) # start emane log_file = os.path.join(path, f"emane{n}.log") platform_xml = os.path.join(path, f"platform{n}.xml") args = f"{emanecmd} -f {log_file} {platform_xml}" output = node.cmd(args) logging.info("node(%s) emane daemon running: %s", node.name, args) logging.debug("node(%s) emane daemon output: %s", node.name, output) if not run_emane_on_host: return path = self.session.session_dir log_file = os.path.join(path, "emane.log") platform_xml = os.path.join(path, "platform.xml") emanecmd += f" -f {log_file} {platform_xml}" utils.cmd(emanecmd, cwd=path) self.session.distributed.execute(lambda x: x.remote_cmd(emanecmd, cwd=path)) logging.info("host emane daemon running: %s", emanecmd)