def _parse_simulation_runs(self, simulation_run_patterns: typing.Sequence[str], reference_run: str, exclude_runs: typing.Sequence[str]): # search all denoted runs simulation_runs = [] for pattern in simulation_run_patterns: simulation_runs += glob.glob(pattern) simulation_runs = [ filepath for filepath in simulation_runs if os.path.isfile(filepath)] # search all excluded runs runs_to_exclude = [] for pattern in exclude_runs: runs_to_exclude += glob.glob(pattern) runs_to_exclude = [ filepath for filepath in runs_to_exclude if os.path.isfile(filepath)] n_runs_before_filtering = len(simulation_runs) simulation_runs = [filepath for filepath in simulation_runs if filepath not in runs_to_exclude] n_runs_after_filtering = len(simulation_runs) # remove the reference run if reference_run in simulation_runs: simulation_runs.remove(reference_run) # sort it because we can! def atoi(text): return int(text) if text.isdigit() else text def natural_keys(text): return [atoi(c) for c in re.split(r'(\d+)', text)] simulation_runs = sorted(simulation_runs, key=natural_keys) # check simulation_runs_ok = len(simulation_runs) != 0 msg = self._msg_option.format( "# simul.-files", len(simulation_runs)) print(str_info(msg)) self.logger.info(msg) msg = self._msg_option.format( "# excluded files", (n_runs_before_filtering-n_runs_after_filtering)) print(str_info(msg)) self.logger.info(msg) if not simulation_runs_ok: err_msg = "No simulation files could be found with the specified patterns. Check the argument 'simulation_runs'." self.logger.error(err_msg) raise RuntimeError(str_error(err_msg)) return simulation_runs
def _parse_parameter_file(self, parameter_file) -> Union[None, str]: _msg_parameter_file = "" if len(parameter_file) > 0: if not os.path.isfile(parameter_file): parameter_file = None _msg_parameter_file = "Can not find parameter file '{}'".format( parameter_file) else: parameter_file = parameter_file # missing parameter file else: parameter_file = None _msg_parameter_file = "Parameter file missing. Consider specifying the path with the option '--parameter-file'." msg = self._msg_option.format("parameter-file", parameter_file) print(str_info(msg)) self.logger.info(msg) if _msg_parameter_file: print(str_warn(_msg_parameter_file)) self.logger.warn(_msg_parameter_file) return parameter_file
def _parse_config_file(self, config_file) -> Union[str, None]: _msg_config_file = "" if len(config_file) > 0: if not os.path.isfile(config_file): config_file = None _msg_config_file = "Can not find config file '{}'".format( config_file) else: config_file = config_file # missing config file else: config_file = None _msg_config_file = "Config file missing. Consider specifying the path with the option '--config-file'." msg = self._msg_option.format("config-file", config_file) print(str_info(msg)) self.logger.info(msg) if _msg_config_file: print(str_warn(_msg_config_file)) self.logger.warn(_msg_config_file) return config_file
def _parse_use_id_mapping(self, use_id_mapping) -> bool: msg = self._msg_option.format("use-id-mapping", use_id_mapping) print(str_info(msg)) self.logger.info(msg) return use_id_mapping
def _parse_project_dir(self, project_dir): project_dir = os.path.abspath(project_dir) msg = self._msg_option.format("project-dir", project_dir) print(str_info(msg)) self.logger.info(msg) return project_dir
def _parse_n_processes(self, n_processes) -> int: print(str_info(self._msg_option.format("n-processes", n_processes))) if n_processes <= 0: err_msg = "n-processes is '{0}' but must be at least 1.".format( n_processes) self.logger.error(err_msg) raise ValueError(str_error(err_msg)) return n_processes
def _parse_reference_run(self, reference_run) -> str: reference_run_ok = os.path.isfile(reference_run) msg = self._msg_option.format("reference-run", reference_run) print(str_info(msg)) self.logger.info(msg) if not reference_run_ok: err_msg = "Filepath '{0}' is not a file.".format(reference_run) self.logger.error(err_msg) raise RuntimeError(str_error(err_msg)) return reference_run
def _parse_diffcrash_home(self, diffcrash_home) -> str: diffcrash_home_ok = len(diffcrash_home) != 0 msg = self._msg_option.format("diffcrash-home", diffcrash_home) print(str_info(msg)) self.logger.info(msg) if not diffcrash_home_ok: err_msg = "Specify the path to the Diffcrash installation either with the environment variable 'DIFFCRASHHOME' or the option --diffcrash-home." self.logger.error(err_msg) raise RuntimeError(str_error(err_msg)) return diffcrash_home
def _parse_crash_code(self, crash_code) -> str: # these guys are allowed valid_crash_codes = ["dyna", "radioss", "pam"] # do the thing crash_code_ok = crash_code in valid_crash_codes print(str_info(self._msg_option.format("crash-code", crash_code))) self.logger.info(self._msg_option.format("crash-code", crash_code)) if not crash_code_ok: err_msg = "Invalid crash code '{0}'. Please use one of: {1}".format( crash_code, str(valid_crash_codes)) self.logger.error(err_msg) raise RuntimeError(str_error(err_msg)) return crash_code
def main(): # parse arguments parser = parse_args() # check stuff check_args(parser) # assemble command cmd = get_ansa_server_command( ansa_filepath=parser.ansa_filepath, python33_path=parser.python33_path, port=parser.port, ) # run server print( str_info("Running: {0}".format(' '.join(str(entry) for entry in cmd)))) os.system(' '.join(str(entry) for entry in cmd))
def connect_interactive(address: str): ''' Run a client connection on a specific port Parameters ---------- address . `str` ip address to connect to ''' # logging print(str_info(_msg_using_address.format(address))) print() # get options for rpc bridge options = get_grpc_connection_options() # open channel and do the thign with grpc.insecure_channel(address, options) as channel: stub = AnsaGRPC_pb2_grpc.LassoAnsaDriverStub(channel) client = AnsaClient(stub) import code code.interact(local=locals())
def get_ansa_server_command(ansa_filepath: str, python33_path: str, port: int, interactive: bool, show_gui: bool, enable_logging: bool) -> str: ''' Assemble the ansa command for running the server Parameters ---------- ansa_filepath : `str` path to ansa executable python33_path : `str` path to python 3.3 whose site-packages shall be used port : `int` port to run remote scripting on interactive : `bool` run ansa server in interactive mode show_gui : `bool` show a GUI of the server enable_logging : `bool` whether to log actions run in ANSA Returns ------- cmd : `list` of `str` ansa command for running the server ''' # path to the script, which ansa has to run current_dir = os.path.dirname(__file__) server_script_filepath = os.path.join(current_dir, "server_ansa.py") # ansa filepath if not ansa_filepath: if os.name == 'nt': ansa_filepath = 'ansa64.bat' elif os.name == 'posix': ansa_filepath = 'ansa64.sh' print(str_info(_msg_ansa_filepath_unspecified.format(ansa_filepath))) # basic commands cmd = [ansa_filepath, '-nolauncher'] # show a gui? if not show_gui: cmd.append("-nogui") # find the site-packages dir if python33_path: site_packages_dirs = glob.glob(os.path.join(python33_path, '**', 'site-packages'), recursive=True) if len(site_packages_dirs) == 0: raise RuntimeError( str_error(_msg_no_site_packages.format(python33_path))) if len(site_packages_dirs) > 1: raise RuntimeError( str_error(_msg_multiple_site_packages.format(python33_path))) site_packages_path = site_packages_dirs[0] os.environ["ANSA_GRPC_SITE_PACKAGES_PATH"] = site_packages_path # check if required libs are installed # required_libs = ["grpc*", "enum*", "protobuf3*", "google*"] # for required_lib_name in required_libs: # if not glob.glob(os.path.join(site_packages_path, required_lib_name)): # raise RuntimeError(str_error(_msg_import_error.format( # _msg_missing_library.format(required_lib_name, site_packages_path) # ))) # python33 path not specified (print an info) elif not python33_path: print(str_info(_msg_site_packages_unspecified)) site_packages_path = "" # this function in the script will be run with the following arguments cmd.append("-execscript") cmd.append(server_script_filepath) script_command = "\"serve({port},{interactive},{enable_logging})\"" cmd.append("-execpy") cmd.append( script_command.format(site_packages_path=site_packages_path, port=port, interactive=interactive, enable_logging=enable_logging)) return cmd
def get_ansa_server_command(ansa_filepath: str, python33_path: str, port: int) -> str: ''' Assemble the ansa command for running the server Parameters ---------- ansa_filepath : `str` path to ansa executable python33_path : `str` path to python 3.3 whose site-packages shall be used port : `int` port to run remote scripting on Returns ------- cmd : `list` of `str` ansa command for running the server ''' # path to the script, which ansa has to run current_dir = os.path.dirname(__file__) server_script_filepath = os.path.join(current_dir, "server_ansa.py") # ansa filepath if not ansa_filepath: if os.name == 'nt': ansa_filepath = 'ansa64.bat' elif os.name == 'posix': ansa_filepath = 'ansa64.sh' print(str_info(_msg_ansa_filepath_unspecified.format(ansa_filepath))) # basic commands cmd = [ansa_filepath, '-nolauncher'] # show a gui? cmd.append("-nogui") # find the site-packages dir if python33_path: site_packages_dirs = glob.glob(os.path.join(python33_path, '**', 'site-packages'), recursive=True) if len(site_packages_dirs) == 0: raise RuntimeError( str_error(_msg_no_site_packages.format(python33_path))) if len(site_packages_dirs) > 1: raise RuntimeError( str_error(_msg_multiple_site_packages.format(python33_path))) site_packages_path = site_packages_dirs[0] os.environ["ANSA_REST_SITE_PACKAGES_PATH"] = site_packages_path # check if required libs are installed required_libs = ["flask*"] for required_lib_name in required_libs: if not glob.glob( os.path.join(site_packages_path, required_lib_name)): raise RuntimeError( str_error( _msg_missing_library.format(required_lib_name, site_packages_path))) # python33 path not specified (print an info) elif not python33_path: print(str_info(_msg_site_packages_unspecified)) site_packages_path = "" # this function in the script will be run with the following arguments cmd.append("-execscript") cmd.append(server_script_filepath) script_command = "\"serve({port})\"" cmd.append("-execpy") cmd.append( script_command.format( site_packages_path=site_packages_path, port=port, )) return cmd
def serve(port, interactive, enable_logging): ''' Run the grpc server ''' print_header() # set logging if enable_logging: logging.basicConfig(level=logging.INFO) fmt_settings = "{0:14}: {1}" logging.info(str_info(fmt_settings.format("port", port))) logging.info(str_info(fmt_settings.format("interactive", interactive))) logging.info(str_info(fmt_settings.format( "enable_logging", enable_logging))) # grpc server options # We increase the transfer limit from 4MB to 1GB here # This is seriously bad since big stuff should be streamed # but I'm not getting paid for this. gigabyte = 1024 ** 3 options = [ ('grpc.max_send_message_length', gigabyte), ('grpc.max_receive_message_length', gigabyte) ] # run server # Note: Since ANSA is not threadsafe we allow only 1 worker. server = grpc.server( futures.ThreadPoolExecutor(max_workers=1), options=options ) # register our driver driver_servicer = LassoAnsaDriverServicer() AnsaGRPC_pb2_grpc.add_LassoAnsaDriverServicer_to_server( driver_servicer, server) port = server.add_insecure_port('[::]:{}'.format(port)) # check if port was fine if port == 0: logging.error(_msg_port_taken.format(port)) raise RuntimeError(str_error(_msg_port_taken.format(port))) # finally start server server.start() # let main process wait or make ANSA interactively accessible # while the threadpool process handles incoming commands try: if interactive: if enable_logging: print() import code code.interact(local=locals()) else: while True: # time.sleep(60 * 60 * 24) time.sleep(1) if driver_servicer.please_shutdown: raise KeyboardInterrupt() except KeyboardInterrupt: logging.info(_msg_stopping_server) server.stop(0) except Exception as err: logging.error(str_error(_msg_some_weird_error.format(str(err)))) server.stop(0)
def __init__(self): ''' Create a server executing tasks ''' logging.info(str_info("LassoAnsaDriverServicer.__init__")) self.please_shutdown = False