From 71be7a1365138a7af60c4cd25da3cbe1edd928dd Mon Sep 17 00:00:00 2001 From: Antonio Emmanuel Guerrero Silva Date: Sun, 27 Oct 2024 20:35:50 -0600 Subject: [PATCH] refs #693 Reorganization of files based on ogAdministrator paths. --- admin/Interface/Apagar.py | 9 -- admin/Interface/CambiarAcceso.py | 58 ------------ admin/Interface/Configurar.py | 121 -------------------------- admin/Interface/ConsolaRemota.py | 29 ------ admin/Interface/CrearImagen.py | 83 ------------------ admin/Interface/EjecutarScript.py | 63 -------------- admin/Interface/GetConfiguration.py | 67 -------------- admin/Interface/GetIpAddress.py | 12 --- admin/Interface/IniciarSesion.py | 17 ---- admin/Interface/InventarioHardware.py | 20 ----- admin/Interface/InventarioSoftware.py | 45 ---------- admin/Interface/ProcesaCache.py | 8 -- admin/Interface/Reiniciar.py | 7 -- admin/Interface/RestaurarImagen.py | 28 ------ 14 files changed, 567 deletions(-) delete mode 100644 admin/Interface/Apagar.py delete mode 100644 admin/Interface/CambiarAcceso.py delete mode 100644 admin/Interface/Configurar.py delete mode 100644 admin/Interface/ConsolaRemota.py delete mode 100644 admin/Interface/CrearImagen.py delete mode 100644 admin/Interface/EjecutarScript.py delete mode 100644 admin/Interface/GetConfiguration.py delete mode 100644 admin/Interface/GetIpAddress.py delete mode 100644 admin/Interface/IniciarSesion.py delete mode 100644 admin/Interface/InventarioHardware.py delete mode 100644 admin/Interface/InventarioSoftware.py delete mode 100644 admin/Interface/ProcesaCache.py delete mode 100644 admin/Interface/Reiniciar.py delete mode 100644 admin/Interface/RestaurarImagen.py diff --git a/admin/Interface/Apagar.py b/admin/Interface/Apagar.py deleted file mode 100644 index 4219f56..0000000 --- a/admin/Interface/Apagar.py +++ /dev/null @@ -1,9 +0,0 @@ -import os -import sys - -def main(): - os.system('poweroff') - sys.exit(0) - -if __name__ == "__main__": - main() \ No newline at end of file diff --git a/admin/Interface/CambiarAcceso.py b/admin/Interface/CambiarAcceso.py deleted file mode 100644 index 4d507bd..0000000 --- a/admin/Interface/CambiarAcceso.py +++ /dev/null @@ -1,58 +0,0 @@ -import os -import sys -import subprocess - -#!/usr/bin/env python3 - -def main(mode): - PROG = os.path.basename(__file__) - CALLER = og_get_caller() - if not og_check_string_in_group(CALLER, ["CrearImagen", "ConsolaRemota", "CrearImagenBasica", "CrearSoftIncremental"]): - og_raise_error("OG_ERR_NOTEXEC", f"{CALLER} -> {PROG}") - sys.exit(1) - - REPOIP = og_get_repo_ip() - if not REPOIP: - og_raise_error("OG_ERR_NOTFOUND", "repo no montado") - sys.exit(1) - if og_is_repo_locked(): - og_raise_error("OG_ERR_LOCKED", f"repo {REPOIP}") - sys.exit(1) - - PROTO = os.getenv("ogprotocol", "smb") - if PROTO not in ["nfs", "smb"]: - og_raise_error("OG_ERR_FORMAT", f"protocolo desconocido {PROTO}") - sys.exit(1) - - if mode == "admin": - MODE = "rw" - elif mode == "user": - MODE = "ro" - else: - og_raise_error("OG_ERR_FORMAT", f"modo desconocido {mode}") - sys.exit(1) - - OGIMG = "/path/to/ogimg" # Placeholder for actual OGIMG path - subprocess.run(["umount", OGIMG], check=True) - - ogunit = os.getenv("ogunit", "") - OGUNIT = f"/{ogunit}" if ogunit else "" - og_echo("info", f"{PROG}: Montar repositorio {REPOIP} por {PROTO} en modo {mode}") - - if PROTO == "nfs": - subprocess.run(["mount", "-t", "nfs", f"{REPOIP}:{OGIMG}{OGUNIT}", OGIMG, "-o", MODE], check=True) - elif PROTO == "smb": - with open("/scripts/ogfunctions") as f: - for line in f: - if "OPTIONS=" in line: - PASS = line.split("pass=")[1].split()[0] - break - else: - PASS = "og" - subprocess.run(["mount.cifs", f"//{REPOIP}/ogimages{OGUNIT}", OGIMG, "-o", f"{MODE},serverino,acl,username=opengnsys,password={PASS}"], check=True) - -if __name__ == "__main__": - if len(sys.argv) != 2: - print("Usage: CambiarAcceso.py ", file=sys.stderr) - sys.exit(1) - main(sys.argv[1]) \ No newline at end of file diff --git a/admin/Interface/Configurar.py b/admin/Interface/Configurar.py deleted file mode 100644 index 4950349..0000000 --- a/admin/Interface/Configurar.py +++ /dev/null @@ -1,121 +0,0 @@ -import os -import subprocess -import sys - -def run_command(command): - result = subprocess.run(command, shell=True, capture_output=True, text=True) - if result.returncode != 0: - print(f"Error: {result.stderr}") - sys.exit(result.returncode) - return result.stdout.strip() - -def main(): - # Load engine configurator from engine.cfg file. - og_engine_configurate = os.getenv('OGENGINECONFIGURATE') - if not og_engine_configurate: - run_command('source /opt/opengnsys/etc/engine.cfg') - - # Clear temporary file used as log track by httpdlog - for log_file in [os.getenv('OGLOGSESSION'), os.getenv('OGLOGCOMMAND'), f"{os.getenv('OGLOGCOMMAND')}.tmp"]: - with open(log_file, 'w') as f: - f.write(" ") - - # Registro de inicio de ejecución - run_command(f'ogEcho log session "$MSG_INTERFACE_START {sys.argv[0]} {" ".join(sys.argv[1:])}"') - - # Captura de parámetros (se ignora el 1er parámetro y se eliminan espacios y tabuladores). - param = "".join(sys.argv[2:]).replace(" ", "").replace("\t", "") - - # Activa navegador para ver progreso - coproc = subprocess.Popen(['/opt/opengnsys/bin/browser', '-qws', 'http://localhost/cgi-bin/httpd-log.sh']) - - # Leer los dos bloques de parámetros, separados por '!'. - pparam, sparam = param.split('!') - - # Toma valores de disco y caché, separados por "*". - disk_params = dict(item.split('=') for item in pparam.split('*')) - dis = disk_params.get('dis') - che = disk_params.get('che') - tch = disk_params.get('tch') - - # Error si no se define el parámetro de disco (dis). - if not dis: - sys.exit(os.getenv('OG_ERR_FORMAT')) - - # Toma valores de distribución de particiones, separados por "%". - partition_params = sparam.split('%') - - maxp = 0 - TBP = {} - TBF = {} - - for param in partition_params: - cfg = dict(item.split('=') for item in param.split('*')) - par = int(cfg.get('par', 0)) - cpt = cfg.get('cpt') - sfi = cfg.get('sfi') - tam = cfg.get('tam') - ope = cfg.get('ope') - - if cpt != "CACHE": - TBP[par] = f"{cpt}:{tam}" - - if ope == "1": - if run_command(f'ogCheckStringInGroup {cpt} "EMPTY EXTENDED LINUX-LVM LVM ZPOOL"') != "0": - TBF[par] = sfi - - if par > maxp: - maxp = par - - # Tamaño actual de la cache - CACHESIZE = run_command('ogGetCacheSize') - - # Desmonta todas las particiones y la caché - run_command(f'ogEcho session log "[10] $MSG_HELP_ogUnmountAll"') - run_command(f'ogUnmountAll {dis}') - run_command('ogUnmountCache') - - # Elimina la tabla de particiones - if run_command('ogGetPartitionTableType 1') != 'MSDOS': - run_command(f'ogDeletePartitionTable {dis}') - run_command(f'ogExecAndLog COMMAND ogUpdatePartitionTable {dis}') - run_command(f'ogCreatePartitionTable {dis} MSDOS') - - # Inicia la cache. - if "CACHE" in sparam: - run_command(f'ogEcho session log "[30] $MSG_HELP_ogCreateCache"') - run_command(f'ogEcho session log " initCache {tch}"') - run_command(f'ogExecAndLog COMMAND initCache {tch}') - - # Definir particionado. - run_command(f'ogEcho session log "[50] $MSG_HELP_ogCreatePartitions"') - run_command(f'ogEcho session log " ogCreatePartitions {dis} {" ".join(TBP.values())}"') - if run_command(f'ogExecAndLog COMMAND ogCreatePartitions {dis} {" ".join(TBP.values())}') != "0": - coproc.kill() - sys.exit(run_command(f'ogRaiseError session log $OG_ERR_GENERIC "ogCreatePartitions {dis} {" ".join(TBP.values())}"')) - - run_command(f'ogExecAndLog COMMAND ogUpdatePartitionTable {dis}') - - # Formatear particiones - run_command(f'ogEcho session log "[70] $MSG_HELP_ogFormat"') - - for par in range(1, maxp + 1): - if TBF.get(par) == "CACHE": - if CACHESIZE == tch: - run_command(f'ogEcho session log " ogFormatCache"') - run_command(f'ogExecAndLog COMMAND ogFormatCache') - elif TBF.get(par): - run_command(f'ogEcho session log " ogFormatFs {dis} {par} {TBF[par]}"') - if run_command(f'ogExecAndLog COMMAND ogFormatFs {dis} {par} {TBF[par]}') != "0": - coproc.kill() - sys.exit(run_command(f'ogRaiseError session log $OG_ERR_GENERIC "ogFormatFs {dis} {par} {TBF[par]}"')) - - # Registro de fin de ejecución - run_command(f'ogEcho log session "$MSG_INTERFACE_END {0}"') - - # Retorno - coproc.kill() - sys.exit(0) - -if __name__ == "__main__": - main() \ No newline at end of file diff --git a/admin/Interface/ConsolaRemota.py b/admin/Interface/ConsolaRemota.py deleted file mode 100644 index 6790b6a..0000000 --- a/admin/Interface/ConsolaRemota.py +++ /dev/null @@ -1,29 +0,0 @@ -import os -import sys -import subprocess - -def main(script_path, output_path): - try: - # Make the script executable - os.chmod(script_path, 0o755) - - # Execute the script and redirect output - with open(output_path, 'w') as output_file: - result = subprocess.run([script_path], stdout=output_file, stderr=subprocess.PIPE) - - # Check if the script execution was successful - if result.returncode != 0: - sys.exit(result.returncode) - except Exception as e: - print(f"An error occurred: {e}") - sys.exit(1) - -if __name__ == "__main__": - if len(sys.argv) != 3: - print("Usage: python3 ConsolaRemota.py ") - sys.exit(1) - - script_path = sys.argv[1] - output_path = sys.argv[2] - - main(script_path, output_path) \ No newline at end of file diff --git a/admin/Interface/CrearImagen.py b/admin/Interface/CrearImagen.py deleted file mode 100644 index df66d1e..0000000 --- a/admin/Interface/CrearImagen.py +++ /dev/null @@ -1,83 +0,0 @@ -import os -import sys -import subprocess -import time - -#!/usr/bin/env python3 - - -# Error codes -OG_ERR_NOTEXEC = 1 -OG_ERR_LOCKED = 4 -OG_ERR_FORMAT = 1 -OG_ERR_PARTITION = 3 -OG_ERR_IMAGE = 5 -OG_ERR_NOTWRITE = 14 -OG_ERR_NOTCACHE = 15 -OG_ERR_CACHESIZE = 16 -OG_ERR_REDUCEFS = 17 -OG_ERR_EXTENDFS = 18 - -def main(): - if len(sys.argv) != 5: - og_raise_error(OG_ERR_FORMAT, "Incorrect number of arguments") - - disk_num = sys.argv[1] - partition_num = sys.argv[2] - image_name = sys.argv[3] - repo = sys.argv[4] if sys.argv[4] else "REPO" - - start_time = time.time() - - # Load engine configurator - og_engine_configurate = os.getenv('OGENGINECONFIGURATE') - if not og_engine_configurate: - exec(open("/opt/opengnsys/etc/engine.cfg").read()) - - # Clear temporary log files - with open(os.getenv('OGLOGSESSION'), 'w') as f: - f.write(" ") - with open(os.getenv('OGLOGCOMMAND'), 'w') as f: - f.write(" ") - with open(f"{os.getenv('OGLOGCOMMAND')}.tmp", 'w') as f: - f.write(" ") - - # Log start of execution - og_echo("log session", f"Start {sys.argv[0]} {' '.join(sys.argv)}") - - # Check if called by OpenGnsys Client - caller = og_get_caller() - if caller != "ogAdmClient": - og_raise_error(OG_ERR_NOTEXEC, f"{caller} -> {sys.argv[0]}") - - # Default repository value - if repo == og_get_ip_address(): - repo = "CACHE" - - if og_check_ip_address(repo) or repo == "REPO": - og_unit = os.getenv('ogunit') - if og_unit: - og_unit = og_unit - if not og_change_repo(repo, og_unit): - og_raise_error(OG_ERR_NOTFOUND, f"{repo}") - - if repo == "REPO" and os.getenv('boot') != "admin": - if cambiar_acceso("admin") > 0: - sys.exit(1) - - og_echo("createImage", f"{disk_num} {partition_num} {repo} /{image_name}") - if subprocess.call(["which", "createImageCustom"], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) == 0: - retval = create_image_custom(disk_num, partition_num, repo, image_name) - else: - retval = create_image(disk_num, partition_num, repo, image_name) - - if repo == "REPO" and os.getenv('boot') != "admin": - cambiar_acceso("user") - - # Log end of execution - og_echo("log session", f"End {retval}") - - sys.exit(retval) - -if __name__ == "__main__": - main() \ No newline at end of file diff --git a/admin/Interface/EjecutarScript.py b/admin/Interface/EjecutarScript.py deleted file mode 100644 index 57d9aaa..0000000 --- a/admin/Interface/EjecutarScript.py +++ /dev/null @@ -1,63 +0,0 @@ -import os -import time -import subprocess -import sys - -def main(script_path): - start_time = time.time() - - # Load engine configurator from engine.cfg file. - engine_config_path = '/opt/opengnsys/etc/engine.cfg' - if 'OGENGINECONFIGURATE' not in os.environ: - with open(engine_config_path) as f: - exec(f.read(), globals()) - - # Clear temporary file used as log track by httpdlog - with open(os.environ['OGLOGSESSION'], 'w') as f: - f.write("") - with open(os.environ['OGLOGCOMMAND'], 'w') as f: - f.write("") - - # Registro de inicio de ejecución - ogEcho('log session', f"{os.environ['MSG_INTERFACE_START']} {sys.argv[0]} {' '.join(sys.argv[1:])}") - - with open(os.environ['OGLOGFILE'], 'a') as log_file: - log_file.write("\n Instrucciones a ejecutar: *****************************\n") - with open(script_path) as script_file: - log_file.write(script_file.read()) - - log_file.write("\n Salida de las instrucciones: *****************************\n") - - os.chmod(script_path, 0o755) - result = subprocess.run([script_path], capture_output=True, text=True) - ret_val = result.returncode - - with open(os.environ['OGLOGCOMMAND'], 'a') as log_command_file: - log_command_file.write(result.stdout) - log_command_file.write(result.stderr) - - elapsed_time = time.time() - start_time - if ret_val == 0: - ogEcho('log session', f"[100] Duracion de la operacion {int(elapsed_time // 60)}m {int(elapsed_time % 60)}s") - else: - ogRaiseError('log session', ret_val) - ogEcho('log session', 'error "Operacion no realizada"') - - # Registro de fin de ejecución - ogEcho('log session', f"{os.environ['MSG_INTERFACE_END']} {ret_val}") - - sys.exit(ret_val) - -def ogEcho(log_type, message): - # Placeholder for the ogEcho function - print(f"{log_type}: {message}") - -def ogRaiseError(log_type, error_code): - # Placeholder for the ogRaiseError function - print(f"{log_type}: Error code {error_code}") - -if __name__ == "__main__": - if len(sys.argv) != 2: - print("Usage: python EjecutarScript.py ") - sys.exit(1) - main(sys.argv[1]) \ No newline at end of file diff --git a/admin/Interface/GetConfiguration.py b/admin/Interface/GetConfiguration.py deleted file mode 100644 index a987afb..0000000 --- a/admin/Interface/GetConfiguration.py +++ /dev/null @@ -1,67 +0,0 @@ -import os -import subprocess - -#!/usr/bin/env python3 - -def main(): - os.environ["DEBUG"] = "no" - - ser = ogGetSerialNumber() - cfg = "" - disks = len(ogDiskToDev().split()) - - for dsk in range(1, disks + 1): - particiones = ogGetPartitionsNumber(dsk) or 0 - ptt = ogGetPartitionTableType(dsk) - ptt_map = {"MSDOS": 1, "GPT": 2, "LVM": 3, "ZPOOL": 4} - ptt = ptt_map.get(ptt, 0) - - cfg += f"{dsk}:0:{ptt}:::{ogGetDiskSize(dsk)}:0;" - - for par in range(1, particiones + 1): - cod = ogGetPartitionId(dsk, par) - fsi = getFsType(dsk, par) or "EMPTY" - tam = ogGetPartitionSize(dsk, par) or "0" - soi = "" - uso = 0 - - if fsi not in ["", "EMPTY", "LINUX-SWAP", "LINUX-LVM", "ZVOL"]: - if ogMount(dsk, par): - soi = getOsVersion(dsk, par).split(":")[1] - if not soi: - soi = getOsVersion(dsk, par).split(":")[1] - if not soi and fsi not in ["EMPTY", "CACHE"]: - soi = "DATA" - uso = int(subprocess.getoutput(f"df {ogGetMountPoint(dsk, par)} | awk '{{getline; printf \"%d\",$5}}'") or 0) - - cfg += f"{dsk}:{par}:{cod}:{fsi}:{soi}:{tam}:{uso};" - - if not cfg: - cfg = "1:0:0:::0;" - - cfgfile = "/tmp/getconfig" - with open(cfgfile, "w") as f: - f.write(f"{ser + ';' if ser else ''}{cfg}") - - generateMenuDefault() - - with open(cfgfile, "r") as f: - data = f.read() - - for line in data.split(";"): - if line: - parts = line.split(":") - if len(parts) == 1: - print(f"ser={parts[0]}") - else: - print(f"disk={parts[0]}\tpar={parts[1]}\tcpt={parts[2]}\tfsi={parts[3]}\tsoi={parts[4]}\ttam={parts[5]}\tuso={parts[6]}") - - for root, dirs, files in os.walk("/mnt"): - for file in files: - if file.startswith("ogboot."): - os.remove(os.path.join(root, file)) - - os.environ.pop("DEBUG", None) - -if __name__ == "__main__": - main() \ No newline at end of file diff --git a/admin/Interface/GetIpAddress.py b/admin/Interface/GetIpAddress.py deleted file mode 100644 index 4458282..0000000 --- a/admin/Interface/GetIpAddress.py +++ /dev/null @@ -1,12 +0,0 @@ -import socket - -#!/usr/bin/env python3 - - -def get_ip_address(): - hostname = socket.gethostname() - ip_address = socket.gethostbyname(hostname) - return ip_address - -if __name__ == "__main__": - print("IP Address:", get_ip_address()) \ No newline at end of file diff --git a/admin/Interface/IniciarSesion.py b/admin/Interface/IniciarSesion.py deleted file mode 100644 index 86968d0..0000000 --- a/admin/Interface/IniciarSesion.py +++ /dev/null @@ -1,17 +0,0 @@ -import sys -import subprocess - -def main(): - args = sys.argv[1:] - - if len(args) == 1: - disk = 1 - part = args[0] - else: - disk = args[0] - part = args[1] - - boot_os(disk, part) - -if __name__ == "__main__": - main() \ No newline at end of file diff --git a/admin/Interface/InventarioHardware.py b/admin/Interface/InventarioHardware.py deleted file mode 100644 index 850f14b..0000000 --- a/admin/Interface/InventarioHardware.py +++ /dev/null @@ -1,20 +0,0 @@ -import subprocess -import sys - -def list_hardware_info(): - # Replace this with the actual command to list hardware info - result = subprocess.run(['listHardwareInfo'], capture_output=True, text=True) - return result.stdout - -def save_hardware_info(output_file): - hardware_info = list_hardware_info() - lines = hardware_info.splitlines() - if len(lines) > 1: - with open(output_file, 'w') as f: - f.write('\n'.join(lines[1:])) - -if __name__ == "__main__": - if len(sys.argv) != 2: - print("Usage: python InventarioHardware.py ") - sys.exit(1) - save_hardware_info(sys.argv[1]) \ No newline at end of file diff --git a/admin/Interface/InventarioSoftware.py b/admin/Interface/InventarioSoftware.py deleted file mode 100644 index 6ab4215..0000000 --- a/admin/Interface/InventarioSoftware.py +++ /dev/null @@ -1,45 +0,0 @@ -import os -import time -import shutil -import subprocess -import sys - -def main(arg1, arg2, destination): - start_time = time.time() - - # Load the engine configuration from the engine.cfg file - og_engine_configurate = os.getenv('OGENGINECONFIGURATE') - if not og_engine_configurate: - with open('/opt/opengnsys/etc/engine.cfg') as f: - exec(f.read()) - - # Clear the temporary files used as log tracking for httpdlog - og_log_session = os.getenv('OGLOGSESSION') - og_log_command = os.getenv('OGLOGCOMMAND') - if og_log_session and og_log_command: - with open(og_log_session, 'w') as f: - f.write(" ") - with open(og_log_command, 'w') as f: - f.write(" ") - with open(f"{og_log_command}.tmp", 'w') as f: - f.write(" ") - - # Log the start of execution - msg_interface_start = os.getenv('MSG_INTERFACE_START') - if msg_interface_start: - subprocess.run(['ogEcho', 'log', 'session', f"{msg_interface_start} {__file__} {arg1} {arg2}"]) - - # Get the software info file and copy it to the destination - file = list_software_info(arg1, arg2) - shutil.copy(file, destination) - - elapsed_time = time.time() - start_time - msg_scripts_time_partial = os.getenv('MSG_SCRIPTS_TIME_PARTIAL') - if msg_scripts_time_partial: - subprocess.run(['ogEcho', 'log', 'session', f" [ ] {msg_scripts_time_partial} : {int(elapsed_time // 60)}m {int(elapsed_time % 60)}s"]) - -if __name__ == "__main__": - if len(sys.argv) != 4: - print("Usage: python InventarioSoftware.py ") - sys.exit(1) - main(sys.argv[1], sys.argv[2], sys.argv[3]) \ No newline at end of file diff --git a/admin/Interface/ProcesaCache.py b/admin/Interface/ProcesaCache.py deleted file mode 100644 index c45b959..0000000 --- a/admin/Interface/ProcesaCache.py +++ /dev/null @@ -1,8 +0,0 @@ -import sys - -if __name__ == "__main__": - if len(sys.argv) != 2: - print("Usage: python ProcesaCache.py ") - sys.exit(1) - - init_cache(sys.argv[1]) \ No newline at end of file diff --git a/admin/Interface/Reiniciar.py b/admin/Interface/Reiniciar.py deleted file mode 100644 index d77f9cb..0000000 --- a/admin/Interface/Reiniciar.py +++ /dev/null @@ -1,7 +0,0 @@ -import os - -def reboot_system(): - os.system('reboot') - -if __name__ == "__main__": - reboot_system() \ No newline at end of file diff --git a/admin/Interface/RestaurarImagen.py b/admin/Interface/RestaurarImagen.py deleted file mode 100644 index 60b4af6..0000000 --- a/admin/Interface/RestaurarImagen.py +++ /dev/null @@ -1,28 +0,0 @@ -import sys -import subprocess - -def deploy_image(repo_ip, image_name, disk, partition, protocol, protocol_options, *args): - try: - result = subprocess.run( - ["deployImage", repo_ip, image_name, disk, partition, protocol, protocol_options, *args], - check=True - ) - return result.returncode - except subprocess.CalledProcessError as e: - return e.returncode - -if __name__ == "__main__": - if len(sys.argv) < 7: - print("Usage: python RestaurarImagen.py [additional_args...]") - sys.exit(1) - - disk = sys.argv[1] - partition = sys.argv[2] - image_name = sys.argv[3] - repo_ip = sys.argv[4] - protocol = sys.argv[5] - protocol_options = sys.argv[6] - additional_args = sys.argv[7:] - - exit_code = deploy_image(repo_ip, image_name, disk, partition, protocol, protocol_options, *additional_args) - sys.exit(exit_code) \ No newline at end of file