From b30beadba304728349a186a474f60b612df28165 Mon Sep 17 00:00:00 2001 From: Antonio Emmanuel Guerrero Silva Date: Tue, 22 Oct 2024 22:28:08 -0600 Subject: [PATCH 001/167] refs #839 Review and correction of bugs in migrated code --- 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 insertions(+) create mode 100644 admin/Interface/Apagar.py create mode 100644 admin/Interface/CambiarAcceso.py create mode 100644 admin/Interface/Configurar.py create mode 100644 admin/Interface/ConsolaRemota.py create mode 100644 admin/Interface/CrearImagen.py create mode 100644 admin/Interface/EjecutarScript.py create mode 100644 admin/Interface/GetConfiguration.py create mode 100644 admin/Interface/GetIpAddress.py create mode 100644 admin/Interface/IniciarSesion.py create mode 100644 admin/Interface/InventarioHardware.py create mode 100644 admin/Interface/InventarioSoftware.py create mode 100644 admin/Interface/ProcesaCache.py create mode 100644 admin/Interface/Reiniciar.py create mode 100644 admin/Interface/RestaurarImagen.py diff --git a/admin/Interface/Apagar.py b/admin/Interface/Apagar.py new file mode 100644 index 0000000..4219f56 --- /dev/null +++ b/admin/Interface/Apagar.py @@ -0,0 +1,9 @@ +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 new file mode 100644 index 0000000..4d507bd --- /dev/null +++ b/admin/Interface/CambiarAcceso.py @@ -0,0 +1,58 @@ +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 new file mode 100644 index 0000000..4950349 --- /dev/null +++ b/admin/Interface/Configurar.py @@ -0,0 +1,121 @@ +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 new file mode 100644 index 0000000..6790b6a --- /dev/null +++ b/admin/Interface/ConsolaRemota.py @@ -0,0 +1,29 @@ +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 new file mode 100644 index 0000000..df66d1e --- /dev/null +++ b/admin/Interface/CrearImagen.py @@ -0,0 +1,83 @@ +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 new file mode 100644 index 0000000..57d9aaa --- /dev/null +++ b/admin/Interface/EjecutarScript.py @@ -0,0 +1,63 @@ +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 new file mode 100644 index 0000000..a987afb --- /dev/null +++ b/admin/Interface/GetConfiguration.py @@ -0,0 +1,67 @@ +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 new file mode 100644 index 0000000..4458282 --- /dev/null +++ b/admin/Interface/GetIpAddress.py @@ -0,0 +1,12 @@ +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 new file mode 100644 index 0000000..86968d0 --- /dev/null +++ b/admin/Interface/IniciarSesion.py @@ -0,0 +1,17 @@ +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 new file mode 100644 index 0000000..850f14b --- /dev/null +++ b/admin/Interface/InventarioHardware.py @@ -0,0 +1,20 @@ +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 new file mode 100644 index 0000000..6ab4215 --- /dev/null +++ b/admin/Interface/InventarioSoftware.py @@ -0,0 +1,45 @@ +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 new file mode 100644 index 0000000..c45b959 --- /dev/null +++ b/admin/Interface/ProcesaCache.py @@ -0,0 +1,8 @@ +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 new file mode 100644 index 0000000..d77f9cb --- /dev/null +++ b/admin/Interface/Reiniciar.py @@ -0,0 +1,7 @@ +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 new file mode 100644 index 0000000..60b4af6 --- /dev/null +++ b/admin/Interface/RestaurarImagen.py @@ -0,0 +1,28 @@ +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 From 76f373af779e4306086d7e6818d1811e273f3597 Mon Sep 17 00:00:00 2001 From: Antonio Emmanuel Guerrero Silva Date: Sun, 27 Oct 2024 20:32:42 -0600 Subject: [PATCH 002/167] refs #1051 Revision and correction of errors in the GetConfiguration.py file --- client/interfaceAdm/Apagar.py | 6 +- client/interfaceAdm/EjecutarScript.py | 68 +++--- client/interfaceAdm/GetConfiguration.py | 88 ++++++++ client/interfaceAdm/GetIpAddress.py | 11 + client/interfaceAdm/Reiniciar.py | 2 +- client/shared/scripts/bootOS.py | 58 ++++++ client/shared/scripts/bootOSCustomTemplate.py | 101 +++++++++ client/shared/scripts/buildToOrder.py | 65 ++++++ .../scripts/configureOSCustomTemplate.py | 78 +++++++ .../scripts/createImageCustomTemplate..py | 27 +++ .../shared/scripts/createLogicalPartitions.py | 1 + .../shared/scripts/createPrimaryPartitions.py | 5 + client/shared/scripts/deployImage.py | 139 +++++++++++++ client/shared/scripts/formatFs.py | 30 +++ client/shared/scripts/generateMenuDefault.py | 92 ++++++++ client/shared/scripts/getFsType.py | 5 + client/shared/scripts/getIpAddress.py | 6 + client/shared/scripts/getOsVersion.py | 12 ++ client/shared/scripts/grubSyntax.py | 196 ++++++++++++++++++ client/shared/scripts/initCache.py | 90 ++++++++ client/shared/scripts/installOfflineMode.py | 80 +++++++ .../shared/scripts/launchOgagentInstaller.py | 147 +++++++++++++ client/shared/scripts/listHardwareInfo.py | 36 ++++ client/shared/scripts/listPartitions.py | 11 + .../shared/scripts/listPrimaryPartitions.py | 13 ++ client/shared/scripts/listSoftwareInfo.py | 56 +++++ client/shared/scripts/menuBrowser.py | 16 ++ .../scripts/restoreImageCustomTemplate.py | 34 +++ client/shared/scripts/runApplicationX.py | 18 ++ client/shared/scripts/runhttplog.py | 38 ++++ 30 files changed, 1494 insertions(+), 35 deletions(-) create mode 100644 client/interfaceAdm/GetConfiguration.py create mode 100644 client/interfaceAdm/GetIpAddress.py create mode 100644 client/shared/scripts/bootOS.py create mode 100644 client/shared/scripts/bootOSCustomTemplate.py create mode 100644 client/shared/scripts/buildToOrder.py create mode 100644 client/shared/scripts/configureOSCustomTemplate.py create mode 100644 client/shared/scripts/createImageCustomTemplate..py create mode 100644 client/shared/scripts/createLogicalPartitions.py create mode 100644 client/shared/scripts/createPrimaryPartitions.py create mode 100644 client/shared/scripts/deployImage.py create mode 100644 client/shared/scripts/formatFs.py create mode 100644 client/shared/scripts/generateMenuDefault.py create mode 100644 client/shared/scripts/getFsType.py create mode 100644 client/shared/scripts/getIpAddress.py create mode 100644 client/shared/scripts/getOsVersion.py create mode 100644 client/shared/scripts/grubSyntax.py create mode 100644 client/shared/scripts/initCache.py create mode 100644 client/shared/scripts/installOfflineMode.py create mode 100644 client/shared/scripts/launchOgagentInstaller.py create mode 100644 client/shared/scripts/listHardwareInfo.py create mode 100644 client/shared/scripts/listPartitions.py create mode 100644 client/shared/scripts/listPrimaryPartitions.py create mode 100644 client/shared/scripts/listSoftwareInfo.py create mode 100644 client/shared/scripts/menuBrowser.py create mode 100644 client/shared/scripts/restoreImageCustomTemplate.py create mode 100644 client/shared/scripts/runApplicationX.py create mode 100644 client/shared/scripts/runhttplog.py diff --git a/client/interfaceAdm/Apagar.py b/client/interfaceAdm/Apagar.py index da009dc..2d1598f 100644 --- a/client/interfaceAdm/Apagar.py +++ b/client/interfaceAdm/Apagar.py @@ -1,9 +1,9 @@ import os import sys -def poweroff(): +def main(): os.system('poweroff') + sys.exit(0) if __name__ == "__main__": - poweroff() - sys.exit(0) \ No newline at end of file + main() diff --git a/client/interfaceAdm/EjecutarScript.py b/client/interfaceAdm/EjecutarScript.py index 0bf56ca..ad517fe 100644 --- a/client/interfaceAdm/EjecutarScript.py +++ b/client/interfaceAdm/EjecutarScript.py @@ -3,54 +3,60 @@ import time import subprocess import sys +os.environ.setdefault('MSG_INTERFACE_START', 'Inicio de la interfaz') + +sys.path.append('/opt/opengnsys/lib/engine/bin') +from SystemLib import ogEcho + def main(script_path): start_time = time.time() + print(f"Ejecutando:",script_path) - # Load engine configurator from 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()) + # 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 - og_log_session = os.getenv('OGLOGSESSION') - og_log_command = os.getenv('OGLOGCOMMAND') - if og_log_session: - open(og_log_session, 'w').close() - if og_log_command: - open(og_log_command, 'w').close() + 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 - msg_interface_start = os.getenv('MSG_INTERFACE_START') - og_echo('log session', f"{msg_interface_start} {sys.argv[0]} {' '.join(sys.argv[1:])}") + ogEcho('log session', f"{os.environ['MSG_INTERFACE_START']} {sys.argv[0]} {' '.join(sys.argv[1:])}") - og_log_file = os.getenv('OGLOGFILE') - if og_log_file: - with open(og_log_file, '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") + with open(os.environ['OGLOGFILE'], 'a') as log_file: + log_file.write("\n Instrucciones a ejecutar: *****************************\n" + with open(script_path.split()[1]) as script_file: # Obtener solo el nombre del script + log_file.write(script_file.read()) ) - # Execute the script - os.chmod(script_path, 0o755) - retval = subprocess.call([script_path]) + log_file.write("\n Salida de las instrucciones: *****************************\n") + + # Cambiar permisos y ejecutar el script + os.chmod(script_path.split()[1], 0o755) + result = subprocess.run([sys.executable] + script_path.split(), 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 retval == 0: - og_echo('log session', f"[100] Duracion de la operacion {int(elapsed_time // 60)}m {int(elapsed_time % 60)}s") + if ret_val == 0: + ogEcho('log session', f"[100] Duracion de la operacion {int(elapsed_time // 60)}m {int(elapsed_time % 60)}s") else: - og_raise_error('log session', retval) - og_echo('log session error', "Operacion no realizada") + ogRaiseError('log session', ret_val) + ogEcho('log session', 'error "Operacion no realizada"') # Registro de fin de ejecución - msg_interface_end = os.getenv('MSG_INTERFACE_END') - og_echo('log session', f"{msg_interface_end} {retval}") + ogEcho('log session', f"{os.environ['MSG_INTERFACE_END']} {ret_val}") - sys.exit(retval) + sys.exit(ret_val) 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 + main(sys.argv[1]) diff --git a/client/interfaceAdm/GetConfiguration.py b/client/interfaceAdm/GetConfiguration.py new file mode 100644 index 0000000..7e64850 --- /dev/null +++ b/client/interfaceAdm/GetConfiguration.py @@ -0,0 +1,88 @@ +import os +import subprocess +import sys +#sys.path.append('/opt/opengnsys/lib/engine/bin') +#from DiskLib import ogDiskToDev +#from InventoryLib import ogGetSerialNumber +#!/usr/bin/env python3 + +# No registrar los errores +os.environ["DEBUG"] = "no" + +# Obtener el número de serie y configuración inicial +ser = subprocess.getoutput("ogGetSerialNumber") +cfg = "" + +# Obtener el número de discos +disks = len(subprocess.getoutput("ogDiskToDev").split()) + +# Recorrer discos +for dsk in range(1, disks + 1): + # Número de particiones + particiones = subprocess.getoutput(f"ogGetPartitionsNumber {dsk}") or "0" + particiones = int(particiones) + + # Tipo de tabla de particiones + ptt = subprocess.getoutput(f"ogGetPartitionTableType {dsk}") + ptt_mapping = {"MSDOS": 1, "GPT": 2, "LVM": 3, "ZPOOL": 4} + ptt = ptt_mapping.get(ptt, 0) + + # Información de disco (partición 0) + cfg += f"{dsk}:0:{ptt}:::{subprocess.getoutput(f'ogGetDiskSize {dsk}')}:0;" + + # Recorrer particiones + for par in range(1, particiones + 1): + # Código del identificador de tipo de partición + cod = subprocess.getoutput(f"ogGetPartitionId {dsk} {par} 2>/dev/null") + + # Tipo del sistema de ficheros + fsi = subprocess.getoutput(f"getFsType {dsk} {par} 2>/dev/null") or "EMPTY" + + # Tamaño de la partición + tam = subprocess.getoutput(f"ogGetPartitionSize {dsk} {par} 2>/dev/null") or "0" + + # Sistema operativo instalado + soi = "" + uso = 0 + if fsi not in ["", "EMPTY", "LINUX-SWAP", "LINUX-LVM", "ZVOL"]: + if subprocess.getoutput(f"ogMount {dsk} {par} 2>/dev/null"): + soi = subprocess.getoutput(f"getOsVersion {dsk} {par} 2>/dev/null | cut -f2 -d:") + 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};" + +# Configuración por defecto para cliente sin disco +if not cfg: + cfg = "1:0:0:::0;" + +# Guardar salida en fichero temporal +cfgfile = "/tmp/getconfig" +with open(cfgfile, 'w') as f: + f.write(f"{ser + ';' if ser else ''}{cfg}") + +# Crear el menú por defecto desde el archivo generado +subprocess.run(["generateMenuDefault"], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) + +# Componer salida formateada +formatted_output = [] +with open(cfgfile, 'r') as f: + content = f.read().strip().split(";") + for item in content: + fields = item.split(":") + if len(fields) == 1: + formatted_output.append(f"ser={fields[0]}") + else: + formatted_output.append( + f"disk={fields[0]}\tpar={fields[1]}\tcpt={fields[2]}\tfsi={fields[3]}\tsoi={fields[4]}\ttam={fields[5]}\tuso={fields[6]}" + ) + +# Mostrar la salida formateada +print("\n".join(formatted_output)) + +# Borrar marcas de arranque de Windows +subprocess.run(["rm", "-f", "/mnt/*/ogboot.*", "/mnt/*/*/ogboot.*"]) + +# Volver a registrar los errores +os.environ.pop("DEBUG", None) diff --git a/client/interfaceAdm/GetIpAddress.py b/client/interfaceAdm/GetIpAddress.py new file mode 100644 index 0000000..7549c60 --- /dev/null +++ b/client/interfaceAdm/GetIpAddress.py @@ -0,0 +1,11 @@ +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(get_ip_address()) diff --git a/client/interfaceAdm/Reiniciar.py b/client/interfaceAdm/Reiniciar.py index d77f9cb..53e9ce1 100644 --- a/client/interfaceAdm/Reiniciar.py +++ b/client/interfaceAdm/Reiniciar.py @@ -4,4 +4,4 @@ def reboot_system(): os.system('reboot') if __name__ == "__main__": - reboot_system() \ No newline at end of file + reboot_system() diff --git a/client/shared/scripts/bootOS.py b/client/shared/scripts/bootOS.py new file mode 100644 index 0000000..9950a20 --- /dev/null +++ b/client/shared/scripts/bootOS.py @@ -0,0 +1,58 @@ +import sys +import os +import subprocess + +#!/usr/bin/env python3 +# Script de ejemplo para arrancar un sistema operativo instalado. +# Nota: se usa como base para el programa de arranque de OpenGnsys Admin. + +def main(): + prog = os.path.basename(__file__) + if len(sys.argv) < 3 or len(sys.argv) > 6: + og_raise_error(1, f"Formato: {prog} ndisco nfilesys [str_kernel str_initrd str_kernelparams]") + + disk = sys.argv[1] + filesystem = sys.argv[2] + + try: + part = og_disk_to_dev(disk, filesystem) + except Exception as e: + sys.exit(1) + + try: + mntdir = og_mount(disk, filesystem) + except Exception as e: + sys.exit(1) + + print("[0] Inicio del proceso de arranque.") + + mount_output = subprocess.getoutput(f"mount | grep -q '{mntdir}.*(rw'") + if mount_output: + og_echo("log", "session", "MSG_WARNING: MSG_MOUNTREADONLY") + og_unmount(disk, filesystem) + og_check_fs(disk, filesystem) + + part = og_disk_to_dev(disk, filesystem) + os.makedirs(mntdir, exist_ok=True) + subprocess.run(["ntfs-3g", "-o", "remove_hiberfile", part, mntdir]) + og_echo("log", "session", "Particion desbloqueada") + + og_unmount(disk, filesystem) + og_mount(disk, filesystem) + + if subprocess.call("which bootOsCustom", shell=True, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) == 0: + print("[10] Configuración personalizada del inicio.") + subprocess.run(["bootOsCustom"] + sys.argv[1:]) + + print("[70] Desmontar todos los sistemas de archivos.") + subprocess.run(["sync"]) + for i in range(1, len(og_disk_to_dev(disk, filesystem).split())): + og_unmount_all(i) + + print("[80] Desmontar cache local.") + og_unmount_cache() + print("[90] Arrancar sistema operativo.") + og_boot(sys.argv[1:]) + +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/client/shared/scripts/bootOSCustomTemplate.py b/client/shared/scripts/bootOSCustomTemplate.py new file mode 100644 index 0000000..1f5f0a1 --- /dev/null +++ b/client/shared/scripts/bootOSCustomTemplate.py @@ -0,0 +1,101 @@ +import sys +import os + +#!/usr/bin/env python3 +""" +bootOsCustom +@brief Plantilla para script de configuración personalizada de sistema operativo restaurado. +@param $1 nº de disco +@param $2 nº de partición +@warning Renombrar este fichero como "bootOsCustom" para personalizar el script estándar "bootOs". +@note La partición a inicializar debe estar montada +@version 1.1.1 Soporta varios discos +""" + + +# CONFIGURAR: Partición de datos de Windows que no queremos ocultar (valor por defecto '0' no oculta nada) +DISKDATA = 0 +PARTDATA = 0 + +PROG = os.path.basename(__file__) + +# Control de errores +if len(sys.argv) < 3: + ogRaiseError(OG_ERR_FORMAT, f"Formato: {PROG} ndisco nparticion") + sys.exit(1) + +# Parámetros obligatorios. +DISK = sys.argv[1] # Nº de disco. +PART = sys.argv[2] # Nº de partición. + +# Paso 0: Añadir código para realizar control de errores de los parámetros de entrada (recomendado). +DEVICE = ogDiskToDev(DISK, PART) +if not DEVICE: + sys.exit(1) + +# Paso 1: Adaptar el código de ejemplo para arranque personalizado. +# Nota: el script "bootOs" llama al script "bootOsCustom" después de realizar la operaciones de inicio estándar y antes de desmontar las particiones e iniciar el sistema operativo. + +MNTDIR = ogMount(DISK, PART) +if not MNTDIR: + sys.exit(1) + +NAME = ogGetHostname() +NAME = NAME if NAME else "pc" +OSTYPE = ogGetOsType(DISK, PART) + +if OSTYPE == "Windows": + # Mostrar las particiones NTFS de sistema (dos opciones) + # Opción 1: SIN ocultar las demás. + # ogEcho log session "[40] Mostrar y activar particion de Windows {PART}." + # if ogGetPartitionType(DISK, PART) in ["HNTFS", "WIN-RESERV"]: + # ogUnhidePartition(DISK, PART) + + # Recorremos los distintos discos + # for DEVICE in ogDiskToDev(): + # d = ogDevToDisk(DEVICE) + + # # Mostrar las particiones NTFS de sistema (dos opciones) + # # Opción 2: Ocultamos las demás. + # ogEcho log session "[40] Activar particion de Windows {PART} y ocultar las demás." + # for i in range(1, ogGetPartitionsNumber(d) + 1): + # if (d == DISK and i == PART) or (d == DISKDATA and i == PARTDATA): + # if ogGetPartitionType(d, i) in ["HNTFS", "WIN-RESERV"]: + # ogUnhidePartition(d, i) + # else: + # if ogGetPartitionType(d, i) in ["NTFS", "WINDOWS"]: + # ogHidePartition(d, i) + + # # Borrar marcas de arrranque de todos los Windows instalados en el disco. + # ogEcho log session "[30] Borrar marcas de arrranque de todos los Windows instalados en el disco." + # for i in range(1, ogGetPartitionsNumber(d) + 1): + # if ogGetOsType(d, i) == "Windows": + # ogMount(d, i) + # os.system("rm -f /mnt/*/ogboot.*") + +elif OSTYPE == "Linux": + # Modificar el nombre del equipo + # ogEcho log session "[30] Asignar nombre Linux \"{NAME}\"." + # ETC = ogGetPath(DISK, PART, "/etc") + # if os.path.isdir(ETC): + # with open(os.path.join(ETC, "hostname"), "w") as f: + # f.write(NAME) + + # Sustituir UUID o LABEL por su dispositivo en definición de sistema de archivo raíz. + # if os.path.isfile(os.path.join(ETC, "fstab")): + # ogEcho log session "[40] Actualizar fstab con particion raíz \"{PART}\"." + # with open(os.path.join(ETC, "fstab"), "r") as f: + # lines = f.readlines() + # with open("/tmp/fstab", "w") as f: + # for line in lines: + # if line.split()[1] == "/" and not line.startswith("#"): + # line = line.replace(line.split()[0], PART) + # f.write(line) + # os.replace("/tmp/fstab", os.path.join(ETC, "fstab")) + + # Cambiar claves usuarios, copiando fichero /etc/passwd + # En el servidor el nuevo fichero debe situarse en el directorio del grupo: + # /opt/opengnsys/images/groups/nombre_aula + # if os.path.isfile(os.path.join(ogGetGroupDir(), "passwd")): + # ogEcho log session "[65] Cambiar claves de usuarios." + # os.system(f"cp {os.path.join(ogGetGroupDir(), 'passwd')} {os.path.join(MNTDIR, 'etc')}") \ No newline at end of file diff --git a/client/shared/scripts/buildToOrder.py b/client/shared/scripts/buildToOrder.py new file mode 100644 index 0000000..0dc5721 --- /dev/null +++ b/client/shared/scripts/buildToOrder.py @@ -0,0 +1,65 @@ +import sys + +#!/usr/bin/env python3 + +""" +BuildToOrder +@brief Script de ejemplo para realizar una configuracion del sistema operativo antes de generar imagen o de restaurado. +@brief Activa el uso de los contralodres de disco más usados en windows 7. +@brief (puede usarse como complemento para el programa de creación de imágenes o de restauración). +@param 1 disco +@param 2 particion +@return +@TODO +@exception +@version 1.0.4 - Discos ide + SATA. +@date 2012-10-05 +@version 1.1.1b - Funciona para Windows8 y Windows 10. Si la clave no existe (tiene valor vacío) se crea. +@date 2020-05-04 +""" + +def main(): + PROG = sys.argv[0] + if len(sys.argv) != 3: + ogRaiseError("OG_ERR_FORMAT", f"Formato: {PROG} ndisco nparticion") + + disk = sys.argv[1] + partition = sys.argv[2] + + MNTDIR = ogMount(disk, partition) + OSTYPE = ogGetOsType(disk, partition) + + if OSTYPE == "Windows": + print("Filtro versión de sistema operativo windows.") + TYPE = ogGetOsVersion(disk, partition) + if "Windows XP" in TYPE: + print("Versión de sistema operativo Windows XP no soportado") + sys.exit() + elif "Windows 7" in TYPE: + KEYS = ["intelide", "pciide", "msahci", "iaStorV", "iaStor", "LSI_SAS"] + elif "Windows 8" in TYPE or "Windows 10" in TYPE: + KEYS = ["intelide", "pciide", "storahci", "iaStorV", "iaStorAC", "iaStorAVC", "LSI_SAS"] + else: + KEYS = [] + + print(TYPE) + CONTROLSET = ["ControlSet001", "ControlSet002"] + for C in CONTROLSET: + if ogListRegistryKeys(MNTDIR, "SYSTEM", f'\\{C}') == "": + continue + + for K in KEYS: + FULLK = f'\\{C}\\Services\\{K}\\Start' + VALUE = ogGetRegistryValue(MNTDIR, "SYSTEM", FULLK) + if VALUE == "": + ogDeleteRegistryValue(MNTDIR, "SYSTEM", FULLK) + ogAddRegistryValue(MNTDIR, "SYSTEM", FULLK, "DWORD") + ogSetRegistryValue(MNTDIR, "SYSTEM", FULLK, '0') + print(f" * {C} {K} enabled") + elif OSTYPE == "Linux": + print("Versión de Sistema Operativo GNU/Linux no soportado") + else: + print("Sistema Operativo no soportado") + +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/client/shared/scripts/configureOSCustomTemplate.py b/client/shared/scripts/configureOSCustomTemplate.py new file mode 100644 index 0000000..62c2cde --- /dev/null +++ b/client/shared/scripts/configureOSCustomTemplate.py @@ -0,0 +1,78 @@ +import sys +import subprocess + +#!/usr/bin/env python3 +""" +configureOsCustom +@brief Plantilla para script de configuración personalizada de sistema operativo restaurado. +@param $1 nº de disco +@param $2 nº de partición +@param $3 Repositorio: CACHE, REPO o dirección IP (opcional) +@param $4 Nombre canónico de la imagen sin extensión (opcional) +@warning Renombrar este fichero como "configureOsCustom" para sustituir al script estándar "configureOs". +@note Los parámetros disco y partición son obligatorios y opcionalmente puede recibir también el repositorio y la imagen usada para en el despliegue. +""" + +def main(): + if len(sys.argv) not in [3, 5]: + og_raise_error("OG_ERR_FORMAT", "Usage: configureOsCustom int_ndisc int_npart [str_repo str_imgname]") + + disk = sys.argv[1] + part = sys.argv[2] + repo = sys.argv[3].upper() if len(sys.argv) > 3 else None + imgname = sys.argv[4] if len(sys.argv) > 4 else None + + # Paso 0: Añadir código para realizar control de errores de los parámetros de entrada (recomendado). + + # Paso 1: Adaptar el código de ejemplo para postconfiguración personalizada. + configure_os(disk, part) + + ostype = og_get_os_type(disk, part) + if ostype == "Windows": + # Postconfiguración de Windows. + pass + # Descomentar la siguiente línea para cambiar usuario de inicio. + # subprocess.run(["ogSetWinlogonUser", disk, part, " "], check=True) + # OPCIONAL: desactivar el chkdisk de windows tras la restauracion. Requiere configuracion previa en el engine.cfg + # subprocess.run(["ogLoadHiveWindows", disk, part], check=True) + # subprocess.run(["ogSetWindowsChkdisk", "OGWINCHKDISK"], check=True) + # subprocess.run(["ogUpdateHiveWindows"], check=True) + elif ostype == "Linux": + # Postconfiguración de GNU/Linux. + pass + # OPCIONAL Para UEFI: cambia el UUID de la partición (para tener dos linux en un equipo) + # subprocess.run(["ogUuidChange", disk, part], check=True) + # OPCIONAL Limpiar dispositivos reconocidos previamente + # subprocess.run(["ogCleanLinuxDevices", disk, part], check=True) + # Instala (no configura) el codigo de arranque del Grub en la partición (no lo configura, se mantiene el original de la imagen) + # subprocess.run(["ogGrubInstallPartition", disk, part], check=True) + # OPCIONAL: instala y configura el codigo de arranque del Grub en el MBR (no lo configura, se mantiene el original de la imagen) + # subprocess.run(["ogGrubInstallMbr", disk, part], check=True) + # OPCIONAL: Instala y configura el Grub en el MBR y lo autoconfigura, entradas para los sistemas operativos, además al linux restaurado le añade los parámetros indicados. + # subprocess.run(["ogGrubInstallMbr", disk, part, "TRUE", "irqpoll pci=noacpi noresume quiet splash"], check=True) + elif ostype == "MacOS": + # Postconfiguración de Mac OS X. + with open(f"/mnt/{disk}/{part}/var/root/postconfd.sh", "a") as f: + f.write(""" +### NOTA: descomentar las opciones deseadas. +# Activar Journaling en HFS+ (no usar si el cliente continua en OpenGnsys). +#diskutil enableJournal disk$[$1-1]s$2 +# Pedir usuario y clave en pantalla de conexión. +#defaults write /Library/Preferences/com.apple.loginwindow SHOWFULLNAME -bool yes +# No mostrar botón de cambio rápido de usuario. +#defaults write /Library/Preferences/.GlobalPreferences MultipleSessionEnabled -bool NO +# Bloquear escritorio, fondo, dock, etc del usuario "usuario". +#chflags uchange /Users/usuario/Library/Preferences/com.apple.desktop.plist +#chflags uchange /Users/usuario/Library/Preferences/com.apple.dock.plist +#chflags uchange /Users/usuario/Desktop +# Añadir usuario "usuario" a la lista de desarrolladores de Xcode. +#DevToolsSecurity --enable +#dscl . -append /Groups/_developer GroupMembership usuario +# Bajar volumen (valor entre 0 y 7). +#osascript -e 'set volume 1' +""") + + # Paso 2: Incluir código genérico de postconfiguración. + +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/client/shared/scripts/createImageCustomTemplate..py b/client/shared/scripts/createImageCustomTemplate..py new file mode 100644 index 0000000..f47efbc --- /dev/null +++ b/client/shared/scripts/createImageCustomTemplate..py @@ -0,0 +1,27 @@ +import sys +import os + +#!/usr/bin/env python3 + +def main(): + # Control de parámetros. + if len(sys.argv) != 5: + ogRaiseError(os.getenv('OG_ERR_FORMAT', 1), "createImageCustom int_ndisc int_npart str_repo str_imgname") + + # Toma de parámetros. + DISK = sys.argv[1] # Nº de disco. + PART = sys.argv[2] # Nº de partición. + REPO = sys.argv[3].upper() # Repositorio (en mayúsculas). + IMGNAME = sys.argv[4] # Nombre canónico de imagen (sin extensión). + + # Paso 0: Añadir código para realizar control de errores de los parámetros de entrada (recomendado). + + # Paso 1: Añadir aquí el código para el proceso previo antes de la creación de la imagen en el equipo modelo (opcional). + + # Paso 2: Sustituir, si se desea, la llamada al proceso estándar de creación de imagen por código personalizado. + createImage(DISK, PART, REPO, IMGNAME) + + # Paso 3: Añadir aquí el código para el proceso posterior tras la creación de la imagen (opcional). + +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/client/shared/scripts/createLogicalPartitions.py b/client/shared/scripts/createLogicalPartitions.py new file mode 100644 index 0000000..5f7ce86 --- /dev/null +++ b/client/shared/scripts/createLogicalPartitions.py @@ -0,0 +1 @@ +#!/usr/bin/env python3 \ No newline at end of file diff --git a/client/shared/scripts/createPrimaryPartitions.py b/client/shared/scripts/createPrimaryPartitions.py new file mode 100644 index 0000000..9cd5fe9 --- /dev/null +++ b/client/shared/scripts/createPrimaryPartitions.py @@ -0,0 +1,5 @@ +import sys + +if __name__ == "__main__": + result = og_create_partitions(sys.argv[1:]) + sys.exit(result.returncode) \ No newline at end of file diff --git a/client/shared/scripts/deployImage.py b/client/shared/scripts/deployImage.py new file mode 100644 index 0000000..8891c6e --- /dev/null +++ b/client/shared/scripts/deployImage.py @@ -0,0 +1,139 @@ +import os +import sys +import time + +#!/usr/bin/env python3 + +def main(): + PROG = os.path.basename(__file__) + if len(sys.argv) < 5: + ogRaiseError("session", OG_ERR_FORMAT, f"{MSG_FORMAT}: {PROG} REPO imagen ndisco nparticion [ UNICAST-DIRECT|UNICAST|UNICAST-CACHE|MULTICAST-DIRECT|MULTICAST|MULTICAST-CACHE|TORRENT [opciones protocolo] ]") + sys.exit(1) + + TIME1 = time.time() + REPO = sys.argv[1].upper() or "REPO" + IMGNAME = sys.argv[2] + DISK = sys.argv[3] + PART = sys.argv[4] + PROTO = (sys.argv[5].upper() if len(sys.argv) > 5 else "UNICAST") + PROTOOPT = sys.argv[6] if len(sys.argv) > 6 else "" + OGUNIT = os.getenv("ogunit", "") + + if not OGENGINECONFIGURATE: + exec(open("/opt/opengnsys/etc/engine.cfg").read()) + + with open(OGLOGCOMMAND, 'w') as f: + f.write(" ") + if ogGetCaller() != "EjecutarScript": + with open(OGLOGSESSION, 'w') as f: + f.write("") + + ogEcho("log", "session", f"[1] {MSG_SCRIPTS_START} {PROG} {' '.join(sys.argv)}") + + if ogIsLocked(DISK, PART): + sys.exit(ogRaiseError("session", OG_ERR_LOCKED, f"{MSG_PARTITION}, {DISK} {PART}")) + + ogEcho("log", "session", f"{MSG_HELP_ogUnmount} {DISK} {PART}") + ogUnmount(DISK, PART) + + if REPO == ogGetIpAddress() or REPO == "CACHE": + MODE = "CACHE" + else: + if ogCheckIpAddress(REPO) == 0 or REPO == "REPO": + if not ogChangeRepo(REPO, OGUNIT): + sys.exit(ogRaiseError(OG_ERR_NOTFOUND, f"{REPO} {OGUNIT}")) + MODE = "REPO" + + IMGOS = ogGetImageInfo(ogGetPath(MODE, f"{IMGNAME}.img")) + if IMGOS == 1: + sys.exit(ogRaiseError("session", OG_ERR_NOTFOUND, f"{REPO} {IMGNAME}")) + elif IMGOS == 5: + sys.exit(ogRaiseError("session", OG_ERR_IMAGEFILE, f"{REPO} {IMGNAME}")) + elif IMGOS != 0: + sys.exit(ogRaiseError("session", OG_ERR_GENERIC)) + + IMGSIZE = os.path.getsize(ogGetPath(MODE, f"{IMGNAME}.img")) // 1024 + ogEcho("log", "session", f"[1] REPO={REPO} IMG-FILE={IMGNAME}.img SIZE={IMGSIZE} (KB) METADATA={IMGOS}") + + if MODE == "CACHE": + NEXTOPERATION = "CACHE" + elif MODE == "REPO": + if PROTO in ["MULTICAST-DIRECT", "UNICAST-DIRECT"]: + NEXTOPERATION = PROTO.split('-')[0] + elif PROTO in ["TORRENT", "TORRENT-CACHE", "MULTICAST", "MULTICAST-CACHE", "UNICAST", "UNICAST-CACHE"]: + PROTO = PROTO.split('-')[0] + ogEcho("log", "session", f"[2] updateCache {REPO} /{IMGNAME}.img {PROTO} {PROTOOPT}") + TIME2 = time.time() + RETVAL = updateCache(REPO, f"/{IMGNAME}.img", PROTO, PROTOOPT) + TIME2 = time.time() - TIME2 + ogEcho("log", "session", f" [ ] {MSG_SCRIPTS_TIME_PARTIAL} updateCache {TIME2 // 60}m {TIME2 % 60}s") + if RETVAL == 0: + ogEcho("log", "session", "[50] updateCache (OK)") + NEXTOPERATION = "CACHE" + elif RETVAL in [15, 16]: + ogEcho("log", "session", f"[50] {MSG_ERR_NOTCACHE} ; {MSG_ERR_CACHESIZE}") + ogEcho("log", "session", f"[50] {MSG_SCRIPTS_CHECK_ENGINE}: RESTOREPROTOCOLNOTCACHE={RESTOREPROTOCOLNOTCACHE}") + if RESTOREPROTOCOLNOTCACHE == "MULTICAST": + NEXTOPERATION = "MULTICAST" if PROTO == "MULTICAST" else "UNICAST" + elif RESTOREPROTOCOLNOTCACHE == "UNICAST": + NEXTOPERATION = "UNICAST" + elif RESTOREPROTOCOLNOTCACHE == "NONE": + if RETVAL == 15: + ogEcho("log", "session", f"[100] {MSG_ERR_NOTCACHE}") + sys.exit(ogRaiseError("session", OG_ERR_NOTCACHE, "NOT CACHE")) + elif RETVAL == 16: + ogEcho("log", "session", f"[100] {MSG_ERR_CACHESIZE}") + sys.exit(ogRaiseError("session", OG_ERR_CACHESIZE, "CACHE FULL")) + elif RETVAL in [57, 60]: + sys.exit(RETVAL) + else: + sys.exit(RETVAL) + else: + sys.exit(ogRaiseError("session", OG_ERR_FORMAT, f"{MSG_ERR_FORMAT}, {PROTO}")) + else: + sys.exit(ogRaiseError("session", OG_ERR_FORMAT, f"{MSG_ERR_FORMAT}, {REPO}")) + + TIME3 = time.time() + + if NEXTOPERATION == "CACHE": + PARAMS = f"CACHE {IMGNAME} {DISK} {PART}" + elif NEXTOPERATION == "UNICAST": + PARAMS = f"{REPO} {IMGNAME} {DISK} {PART}" + elif NEXTOPERATION == "MULTICAST": + PARAMS = f"{REPO} {IMGNAME} {DISK} {PART} {PROTO} {PROTOOPT}" + + if os.system("which restoreImageCustom") == 0: + ogEcho("log", "session", f"[55] {MSG_HELP_ogRestoreImage}: restoreImageCustom {PARAMS}") + os.system(f"restoreImageCustom {PARAMS}") + else: + ogEcho("log", "session", f"[55] {MSG_HELP_ogRestoreImage}: restoreImage {PARAMS}") + os.system(f"restoreImage {PARAMS}") + RETVAL = os.system(f"restoreImage {PARAMS}") + + RESUMERESTOREIMAGE = os.popen(f"grep -m 1 'Total Time:' {OGLOGCOMMAND}").read() + ogEcho("log", "session", f" [ ] {RESUMERESTOREIMAGE}") + if RETVAL != 0: + ogRaiseError("session", OG_ERR_IMAGE, f"{REPO} {IMGNAME}") + if ogGetCaller() != "EjecutarScript": + ogEcho("log", "session", f"{MSG_INTERFACE_END} {OG_ERR_IMAGE}") + sys.exit(OG_ERR_IMAGE) + + TIME3 = time.time() - TIME3 + ogEcho("log", "session", f" [ ] {MSG_SCRIPTS_TIME_PARTIAL} : {TIME3 // 60}m {TIME3 % 60}s") + + if os.system("which configureOsCustom") == 0: + ogEcho("log", "session", "[90] configureOsCustom") + os.system(f"configureOsCustom {DISK} {PART} {REPO} {IMGNAME}") + else: + ogEcho("log", "session", f"[90] {MSG_SCRIPTS_OS_CONFIGURE}") + os.system(f"configureOs {DISK} {PART}") + + TIME = time.time() - TIME1 + ogEcho("log", "session", f"[100] {MSG_SCRIPTS_TIME_TOTAL} {TIME // 60}m {TIME % 60}s") + + if ogGetCaller() != "EjecutarScript": + ogEcho("log", "session", f"{MSG_INTERFACE_END} {RETVAL}") + sys.exit(RETVAL) + +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/client/shared/scripts/formatFs.py b/client/shared/scripts/formatFs.py new file mode 100644 index 0000000..ee8fec9 --- /dev/null +++ b/client/shared/scripts/formatFs.py @@ -0,0 +1,30 @@ +import sys +import time +import subprocess + +#!/usr/bin/env python3 +# Script de ejemplo para formatear un sistema de archivos. +# Nota: se usa como base para el programa de formateo de OpenGnsys Admin. + +def main(): + start_time = time.time() + prog = sys.argv[0] + + if len(sys.argv) != 3: + ogRaiseError(1, f"{prog} ndisco nparticion") + + disk = sys.argv[1] + partition = sys.argv[2] + + # Desmontar y formatear el sistema de archivos. + print("[5] Desmontando sistema de archivos") + ogUnmountFs(disk, partition) + print("[20] Formateando sistema de archivos") + ogFormatFs(disk, partition) + + elapsed_time = time.time() - start_time + minutes, seconds = divmod(int(elapsed_time), 60) + print(f"[100] Duración de la operación {minutes}m {seconds}s") + +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/client/shared/scripts/generateMenuDefault.py b/client/shared/scripts/generateMenuDefault.py new file mode 100644 index 0000000..7f30baf --- /dev/null +++ b/client/shared/scripts/generateMenuDefault.py @@ -0,0 +1,92 @@ +import os +import subprocess + +#!/usr/bin/env python3 +# generateMenuDefault - Crea fichero con la página web de inicio del cliente +# con información de red y de los sistemas operativos instalados, +# crea fichero con información del contenido de la caché local. + + +DEVICE = os.getenv('DEVICE', 'eth0') +with open(f'/tmp/net-{DEVICE}.conf') as f: + exec(f.read()) + +FILEINFOHTML = f"{os.getenv('OGLOG')}/{subprocess.getoutput('ogGetIpAddress')}.info.html" +FILEINFOCACHE = f"{os.getenv('OGLOG')}/{subprocess.getoutput('ogGetIpAddress')}.cache.txt" +subprocess.run(['ogMountCache'], stderr=subprocess.DEVNULL) +CACHECONTENIDO = f"ls -m {os.getenv('OGCAC')}/{os.getenv('OGIMG')} 2>/dev/null" + +SPEED = subprocess.getoutput(f"LANG=C ethtool {DEVICE} 2>/dev/null | awk '$1~/Speed/ {{print $2}}'") +SPEED = SPEED.lower() +if SPEED == "1000mb/s": + pass +elif SPEED == "100mb/s": + SPEED = f"{SPEED}" +elif SPEED == "10mb/s": + SPEED = f"{SPEED}" +else: + SPEED = f"{SPEED}" + +DUPLEX = subprocess.getoutput(f"LANG=C ethtool {DEVICE} 2>/dev/null | awk '$1~/Duplex/ {{print $2}}'") +DUPLEX = DUPLEX.lower() +if DUPLEX == "full": + pass +else: + DUPLEX = f"{DUPLEX}" + +CACHESIZEFREE = int(subprocess.getoutput('ogGetFreeSize $(ogFindCache)')) +with open(FILEINFOCACHE, 'w') as f: + if CACHESIZEFREE == 0: + f.write('0.MB,') + else: + f.write(f"{CACHESIZEFREE // 1024}.MB,") + +# Crear menú por defecto. +with open(FILEINFOHTML, 'w') as f: + f.write(f""" +
+

+ + + + + + +

{os.getenv('MSG_HOSTNAME')} {os.getenv('MSG_IPADDR')} {os.getenv('MSG_MACADDR')} {os.getenv('MSG_SPEED')} {os.getenv('MSG_DUPLEX')}
{os.getenv('HOSTNAME')} {subprocess.getoutput('ogGetIpAddress')} {subprocess.getoutput('ogGetMacAddress')} {SPEED} {DUPLEX}
+

+ +

{os.getenv('MSG_MENUTITLE')}

+""") + +# Si existe el fichero de configuración creado por el script getConfiguration, ... +cfgfile = '/tmp/getconfig' +if os.path.isfile(cfgfile): + # Tomar los datos del fichero. + with open(cfgfile) as f_cfg, open(FILEINFOHTML, 'a') as f_html: + for line in f_cfg: + sep = line.split(';') + for item in sep: + dua = item.split(':') + if len(dua) > 4 and dua[4] and dua[4] != "DATA": + f_html.write(f"

{os.getenv('MSG_BOOT')} {dua[4]} ({dua[0]}, {dua[1]})

\n") +else: + # Si no, obtener los datos de los discos. + num_disks = int(subprocess.getoutput('ogDiskToDev | wc -w')) + with open(FILEINFOHTML, 'a') as f_html: + for d in range(1, num_disks + 1): + num_partitions = int(subprocess.getoutput(f'ogGetPartitionsNumber {d}')) + for p in range(1, num_partitions + 1): + version = subprocess.getoutput(f'ogGetOsVersion {d} {p} 2>/dev/null').split(':')[1] + if version: + f_html.write(f"

{os.getenv('MSG_BOOT')} {version} ({d}, {p})

\n") + +# Añadir opción de apagado. +with open(FILEINFOHTML, 'a') as f: + f.write(f""" +

{os.getenv('MSG_POWEROFF')}

+
+""") + +# Crear contenido de la caché. +with open(FILEINFOCACHE, 'a') as f: + f.write(subprocess.getoutput(CACHECONTENIDO)) \ No newline at end of file diff --git a/client/shared/scripts/getFsType.py b/client/shared/scripts/getFsType.py new file mode 100644 index 0000000..d9fcf54 --- /dev/null +++ b/client/shared/scripts/getFsType.py @@ -0,0 +1,5 @@ +import sys + +if __name__ == "__main__": + output = ogGetFsType(sys.argv[1:]) + print(output) \ No newline at end of file diff --git a/client/shared/scripts/getIpAddress.py b/client/shared/scripts/getIpAddress.py new file mode 100644 index 0000000..1694bdd --- /dev/null +++ b/client/shared/scripts/getIpAddress.py @@ -0,0 +1,6 @@ +import sys + +if __name__ == "__main__": + args = sys.argv[1:] + output = ogGetIpAddress(args) + print(output) \ No newline at end of file diff --git a/client/shared/scripts/getOsVersion.py b/client/shared/scripts/getOsVersion.py new file mode 100644 index 0000000..b8637da --- /dev/null +++ b/client/shared/scripts/getOsVersion.py @@ -0,0 +1,12 @@ +import subprocess +import sys + +def main(): + try: + subprocess.run(["ogGetOsVersion"] + sys.argv[1:], check=True) + except subprocess.CalledProcessError as e: + print(f"An error occurred: {e}", file=sys.stderr) + sys.exit(e.returncode) + +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/client/shared/scripts/grubSyntax.py b/client/shared/scripts/grubSyntax.py new file mode 100644 index 0000000..6699b90 --- /dev/null +++ b/client/shared/scripts/grubSyntax.py @@ -0,0 +1,196 @@ +import os +import subprocess +import sys + +#!/usr/bin/env python3 + +def run_command(command): + result = subprocess.run(command, shell=True, capture_output=True, text=True) + return result.stdout.strip() + +def copy_files(src, dest): + if os.path.exists(src): + subprocess.run(f"cp -r {src} {dest}", shell=True) + +def prepare_grub_to_access_device(device): + loop_file = None + if device.startswith("/dev/loop"): + grub_loop_device = device.split('/')[-1] + loop_file = run_command(f"losetup {device} | sed -e 's/^[^(]*(\\([^)]\\+\\)).*/\\1/'") + if not loop_file.startswith("/dev"): + loop_device = device + device = run_command(f"{grub_probe} --target=device {loop_file}") + + if "crypt" in run_command(f"dmsetup status {device}"): + print(f"{device} is a crypto device, which GRUB cannot read directly.") + return + + abstraction = run_command(f"{grub_probe} --device {device} --target=abstraction") + for module in abstraction.split(): + print(f"insmod {module}") + + partmap = run_command(f"{grub_probe} --device {device} --target=partmap") + for module in partmap.split(): + if module in ["netbsd", "openbsd"]: + print("insmod part_bsd") + else: + print(f"insmod part_{module}") + + fs = run_command(f"{grub_probe} --device {device} --target=fs") + for module in fs.split(): + print(f"insmod {module}") + + if "nvme" in device: + d, p = ogDevToDisk(device) + if ogGetPartitionTableType(d) == "GPT": + nvme_device = f"hd{d-1},gpt{p}" + else: + nvme_device = f"hd{d-1},{p-1}" + print(f"set root='{nvme_device}'") + else: + print(f"set root='{run_command(f'{grub_probe} --device {device} --target=drive')}'") + + if loop_file: + loop_mountpoint = run_command(f"awk '{loop_file} ~ \"^\"$2 && $2 != \"/\" {{ print $2 }}' /proc/mounts | tail -n1") + if loop_mountpoint: + print(f"loopback {grub_loop_device} {loop_file[len(loop_mountpoint):]}") + print(f"set root=({grub_loop_device})") + +def main(): + disk = part = kernel_param = None + if len(sys.argv) == 4: + disk, part, kernel_param = sys.argv[1:4] + elif len(sys.argv) == 3: + disk, part = sys.argv[1:3] + elif len(sys.argv) == 2: + kernel_param = sys.argv[1] + + grub_probe = os.getenv("grub_probe", f"{os.getenv('OGBIN')}/grub-probe1.99_{os.uname().machine}") + + if "1.99" in run_command("grub-install --version"): + copy_files("/opt/opengnsys/lib/os-probes/*", "/usr/lib/os-probes/") + else: + osprobe_ms_part = "/opt/opengnsys/lib/os-probes/mounted/efi/31part-x-y" + if os.path.isfile(osprobe_ms_part): + copy_files(osprobe_ms_part, "/usr/lib/os-probes/mounted/efi") + + if os.path.exists(f"/opt/opengnsys/cache/boot/{oglivedir}/ogvmlinuz"): + subprocess.run(f"sed -i 's|/boot/{{oglivedir}}/ogvmlinuz |/vmlinuz |i' /usr/lib/linux-boot-probes/mounted/90fallback", shell=True) + subprocess.run(f"sed -i 's|/vmlinuz |/vmlinuz /boot/{{oglivedir}}/ogvmlinuz |1' /usr/lib/linux-boot-probes/mounted/90fallback", shell=True) + os.makedirs("/opt/opengnsys/cache/etc/", exist_ok=True) + with open("/opt/opengnsys/cache/etc/lsb-release", "w") as f: + f.write("DISTRIB_ID=Ubuntu\n") + f.write("DISTRIB_RELEASE= \n") + f.write(f"DISTRIB_CODENAME={oglivedir.split('-')[1]}\n") + f.write("DISTRIB_DESCRIPTION=OpenGnsys Live\n") + + if disk: + os_search = ogDiskToDev(disk, part) + os_probed = run_command(f"os-prober | grep {os_search} | tr ' ' '^' | paste -s -d ' '") + else: + os_probed = run_command("os-prober | tr ' ' '^' | paste -s -d ' '") + + if not os_probed: + adjust_timeout() + sys.exit(0) + + for os_entry in os_probed.split(): + device, longname, label, boot = os_entry.split(':') + longname = longname.replace('^', ' ') + label = label.replace('^', ' ') + if not longname: + longname = label + + print(f"Found {longname} on {device}", file=sys.stderr) + + if boot == "chain": + if "Windows" in longname: + if not wubi: + if os.path.exists("/usr/share/lupin-support/grub-mkimage") and run_command("/usr/share/lupin-support/grub-mkimage --test"): + wubi = "yes" + else: + wubi = "no" + if wubi == "yes": + print(f"Skipping {longname} on Wubi system", file=sys.stderr) + continue + + label_class = ''.join(longname.lower().split()[:2]) + print(f"menuentry \"{longname} (on {device})\" --class {label_class} --class windows {{") + save_default_entry() + prepare_grub_to_access_device(device) + if "Windows Vista" in longname or "Windows 7" in longname or "Windows Server 2008" in longname: + pass + else: + pass + print("chainloader +1") + print("}") + + elif boot == "efi": + efipath = device.split('@')[1] + device = device.split('@')[0] + onstr = f"(on {device})" + print(f"menuentry '{longname} {onstr}' --class windows --class os {{") + save_default_entry() + prepare_grub_to_access_device(device) + print(f"chainloader {efipath}") + print("}") + + elif boot == "linux": + linux_probed = run_command(f"linux-boot-prober {device} 2> /dev/null | tr ' ' '^' | paste -s -d ' '") + linux_probed = linux_probed.split()[0] + prepare_boot_cache = None + for linux_entry in linux_probed.split(): + lroot, lboot, llabel, lkernel, linitrd, lparams = linux_entry.split(':') + llabel = llabel.replace('^', ' ') + lparams = lparams.replace('^', ' ') + uuid = run_command(f"blkid -s UUID -o value {lroot}") + lparams = lparams.replace(f"UUID={uuid}", lroot) + if not llabel: + llabel = longname + if lroot != lboot: + lkernel = lkernel.replace('/boot', '') + linitrd = linitrd.replace('/boot', '') + label_class = llabel.split()[0].lower() + print(f"menuentry \"{llabel} (on {device})\" --class {label_class} --class linux --class os {{") + save_default_entry() + if not prepare_boot_cache: + prepare_boot_cache = prepare_grub_to_access_device(lboot) + print(prepare_boot_cache) + if label_class == "opengnsys": + kernel_param = run_command("cat /proc/cmdline") + print(f"linux {lkernel} {lparams} {kernel_param}") + if linitrd: + print(f"initrd {linitrd}") + print("}") + + elif boot == "macosx": + osx_uuid = run_command(f"grub-probe --target=fs_uuid --device {device} 2> /dev/null") + osx_entry("xnu_kernel", 32, device, longname, osx_uuid) + osx_entry("xnu_kernel64", 64, device, longname, osx_uuid) + + elif boot == "hurd": + print(f"menuentry \"{longname} (on {device})\" --class hurd --class gnu --class os {{") + save_default_entry() + prepare_grub_to_access_device(device) + grub_device = run_command(f"{grub_probe} --device {device} --target=drive") + mach_device = grub_device.replace("(hd", "").replace(",msdos", "s") + grub_fs = run_command(f"{grub_probe} --device {device} --target=fs") + hurd_fs = grub_fs if grub_fs.endswith("fs") else f"{grub_fs}fs" + print(f"multiboot /boot/gnumach.gz root=device:{mach_device}") + print(f"module /hurd/{hurd_fs}.static {hurd_fs} --readonly \\") + print(f" --multiboot-command-line='{{kernel-command-line}}' \\") + print(f" --host-priv-port='{{host-port}}' \\") + print(f" --device-master-port='{{device-port}}' \\") + print(f" --exec-server-task='{{exec-task}}' -T typed '{{root}}' \\") + print(f" '{{task-create}}' '{{task-resume}}'") + print(f"module /lib/ld.so.1 exec /hurd/exec '{{exec-task=task-create}}'") + print("}") + + else: + print(f" {longname} is not yet supported by grub-mkconfig.", file=sys.stderr) + + adjust_timeout() + os.remove("/opt/opengnsys/cache/etc/lsb-release") + +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/client/shared/scripts/initCache.py b/client/shared/scripts/initCache.py new file mode 100644 index 0000000..886a53e --- /dev/null +++ b/client/shared/scripts/initCache.py @@ -0,0 +1,90 @@ +import sys +import time +import subprocess + +#!/usr/bin/env python3 + +def main(): + TIME1 = time.time() + PROG = sys.argv[0] + EXECFORMAT = f"{PROG} [int_ndisk [int_npart]] {{-1 | 0 | int_size}} [NOMOUNT]" + + args = sys.argv[1:] + if args and args[-1].upper() == "NOMOUNT": + MOUNT = 0 + args = args[:-1] + else: + MOUNT = 1 + + PARAMS = len(args) + if PARAMS == 1: + NDISK = 1 + NPART = 4 + SIZE = int(args[0]) + elif PARAMS == 2: + NDISK = int(args[0]) + NPART = 4 + SIZE = int(args[1]) + elif PARAMS == 3: + NDISK = int(args[0]) + NPART = int(args[1]) + SIZE = int(args[2]) + else: + ogRaiseError("OG_ERR_FORMAT", f"{EXECFORMAT}") + + if NDISK < 1 or NPART < 1: + ogRaiseError("OG_ERR_FORMAT", f"{EXECFORMAT}") + + if SIZE < -1: + ogRaiseError("OG_ERR_FORMAT", f"{EXECFORMAT}") + + if SIZE == 0: + print("No modificar la caché local.") + return + + if SIZE == -1: + print("[10] Trabajar sin caché local.") + ogUnmountCache() + ogDeleteCache() + else: + current_cache = ogFindCache() + if current_cache and f"{NDISK} {NPART}" != current_cache: + print("[10] Detectada otra caché, eliminarla") + ogUnmountCache() + ogDeleteCache() + + try: + OLDSIZE = ogGetCacheSize() + except ValueError: + OLDSIZE = 0 + + if SIZE <= 0: + ogRaiseError("OG_ERR_FORMAT", f"!({SIZE}>0)") + + if SIZE != OLDSIZE: + print("[10] Crear partición de caché local.") + ogUnmountCache() + ogCreateCache(NDISK, NPART, SIZE) + ogUpdatePartitionTable(NDISK) + + cache = ogFindCache() + if not ogIsFormated(cache) or SIZE != OLDSIZE: + print("[50] Formatear caché local.") + ogFormatCache() + + print("[70] Comprobar montaje de caché local.") + if ogMountCache() != 0: + print("[80] Comprobar consistencia y volver a montar caché local.") + ogCheckFs(cache) + if ogMountCache() != 0: + sys.exit(1) + + if MOUNT == 0: + print("[90] Dejar desmontada la caché local.") + ogUnmountCache() + + TIME = time.time() - TIME1 + print(f"[100] Duración de la operación {int(TIME // 60)}m {int(TIME % 60)}s") + +if __name__ == "__main__": + main() diff --git a/client/shared/scripts/installOfflineMode.py b/client/shared/scripts/installOfflineMode.py new file mode 100644 index 0000000..041d1af --- /dev/null +++ b/client/shared/scripts/installOfflineMode.py @@ -0,0 +1,80 @@ +import os +import subprocess +import sys + +#!/usr/bin/env python3 + +""" +installOfflineMode +Prepara el equipo cliente para el modo offline. + +@exception OG_ERR_NOTFOUND Fichero o dispositivo no encontrado. +@exception OG_ERR_NOTCACHE No existe cache. +@author Irina Gomez. ETSII. Universidad de Sevilla +@date 2013/12/5 +""" + + +PROG = os.path.basename(__file__) + +if len(sys.argv) > 1 and sys.argv[1] == "help": + og_help() + +og_echo("log", "session $MSG_HELP_installOfflineMode") + +# Cargamos las variables de entorno. +OGENGINECONFIGURATE = os.getenv('OGENGINECONFIGURATE') +if not OGENGINECONFIGURATE: + exec(open('/opt/opengnsys/etc/engine.cfg').read()) + +DIRTFTP = "/opt/oglive/tftpboot" +DIROGCLIENT = os.path.join(DIRTFTP, "ogclient") + +# Comprobamos que el DIROGCLIENT esta montado desde repo +repo_ip = og_get_repo_ip() +result = subprocess.run(['df'], capture_output=True, text=True) +if f"{repo_ip} {DIRTFTP}" not in result.stdout: + og_raise_error("OG_ERR_NOTFOUND", "REPO OGclient") + +# Copiamos el kernel y el initrd. +og_echo("log", "session [10] updateBootCache") +if not update_boot_cache(): + og_raise_error("OG_ERR_NOTCACHE", "") + +# Creamos los dir necesarios. +OGCAC = "/path/to/ogcac" # Placeholder for OGCAC path +og_echo("log", f"session [40] mkdir -p {OGCAC}/{{ogclient, menus, log}}.") +os.makedirs(os.path.join(OGCAC, "menus/images/iconos"), exist_ok=True) +os.makedirs(os.path.join(OGCAC, "ogclient"), exist_ok=True) +os.makedirs(os.path.join(OGCAC, "log"), exist_ok=True) +os.makedirs(os.path.join(OGCAC, "opt/opengnsys/images"), exist_ok=True) + +# Comparamos el cliente en el server y en cache +og_echo("log", f"session [60] cp {DIROGCLIENT}/ogclient.sqfs {OGCAC}/ogclient/") +try: + with open(os.path.join(DIROGCLIENT, "ogclient.sqfs.sum"), 'r') as f: + SERVEROGCLIENT = f.read().strip() +except FileNotFoundError: + SERVEROGCLIENT = None + +try: + with open(os.path.join(OGCAC, "ogclient/ogclient.sqfs.sum"), 'r') as f: + CACHEOGCLIENT = f.read().strip() +except FileNotFoundError: + CACHEOGCLIENT = None + +if CACHEOGCLIENT != SERVEROGCLIENT: + subprocess.run(['cp', os.path.join(DIROGCLIENT, "ogclient.sqfs"), os.path.join(OGCAC, "ogclient/")]) + subprocess.run(['cp', os.path.join(DIROGCLIENT, "ogclient.sqfs.sum"), os.path.join(OGCAC, "ogclient/")]) + +# Si se ha generado el menu de inicio lo copiamos a cache. +IPCLIENT = og_get_ip_address() +MENU = os.path.join("/path/to/oglog", f"{IPCLIENT}.info.html") # Placeholder for OGLOG path +ICONO = "images/iconos/logoopengnsys.png" +if not os.path.isfile(MENU): + generate_menu_default() + +og_echo("log", f"session [90] cp {MENU} {OGCAC}/menus/{IPCLIENT}.html") +subprocess.run(['cp', MENU, os.path.join(OGCAC, f"menus/{IPCLIENT}.html")]) +subprocess.run(['sed', '-i', 's/"../images"/"images"/g', os.path.join(OGCAC, f"menus/{IPCLIENT}.html")]) +subprocess.run(['wget', '--no-check-certificate', f"https://{og_get_repo_ip()}/opengnsys/{ICONO}", '-O', os.path.join(OGCAC, f"menus/{ICONO}")]) \ No newline at end of file diff --git a/client/shared/scripts/launchOgagentInstaller.py b/client/shared/scripts/launchOgagentInstaller.py new file mode 100644 index 0000000..137db31 --- /dev/null +++ b/client/shared/scripts/launchOgagentInstaller.py @@ -0,0 +1,147 @@ +import os +import sys +import subprocess +import json + +#!/usr/bin/env python3 + +def download_file(url, output): + try: + if subprocess.call(['which', 'curl'], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) == 0: + subprocess.check_call(['curl', '-k', '-f', '--connect-timeout', '1', '-o', output, url]) + else: + subprocess.check_call(['wget', '--no-check-certificate', '-T', '1', '-O', output, url]) + except subprocess.CalledProcessError: + return False + return True + +def main(): + prog = os.path.basename(__file__) + if len(sys.argv) == 2 and sys.argv[1] == "help": + show_help(prog) + + if not callable(globals().get('ogRaiseError')): + raise_error(f"{prog}: it can only be executed by an ogLive client.") + + if len(sys.argv) not in [3, 4]: + raise_error(f"{prog} ndisk npart [adminuser]") + + ndisk, npart = sys.argv[1], sys.argv[2] + windowsadmin = sys.argv[3] if len(sys.argv) == 4 else None + + mntdir = ogMount(ndisk, npart) + if not mntdir: + sys.exit(1) + + ogversion = None + try: + response = subprocess.check_output(['curl', '-k', '-f', '--connect-timeout', '1', '-o', '-', f'https://{ogGetServerIp()}/opengnsys/rest/info']) + ogversion = json.loads(response).get('version') + except subprocess.CalledProcessError: + pass + + if not ogversion: + raise_error(f"GET /rest/info") + + os_type = ogGetOsType(ndisk, npart) + if os_type == "Windows": + hive = ogGetHivePath(mntdir, windowsadmin) + if not hive: + raise_error(f"{ndisk} {npart} {windowsadmin}/NTUSER.DAT") + + ogagentfile = f"OGAgentSetup-{ogversion.replace('pre', '')}.exe" + tmpdir = ogGetPath(f"{mntdir}/Windows/Temp") + if "opengnsys agent" in ogListSoftware(ndisk, npart).lower(): + print("OGAgent for Windows is already installed, you need to uninstall it before re-install.") + else: + if download_file(f"https://{ogGetServerIp()}/opengnsys/descargas/{ogagentfile}", f"{tmpdir}/{ogagentfile}"): + try: + subprocess.check_call(['hivexsh', '-w'], input=f""" +load {hive} +cd \\Software\\Microsoft\\Windows\\CurrentVersion\\RunOnce +setval 1 +Install OGAgent +string:C:\\Windows\\Temp\\{ogagentfile} /S /server {ogGetServerIp()} +commit +close +exit +""".encode()) + print(f'Scheduled OGAgent installation after "{windowsadmin}" logon') + print(" (for connection problems, check configuration file).") + except subprocess.CalledProcessError: + raise_error(f"{ndisk} {npart} .../{windowsadmin}/NTUSER.DAT") + else: + raise_error(f"{ndisk} {npart} /Windows/Temp/{ogagentfile}") + + elif os_type == "Linux": + if "ogagent" in ogListSoftware(ndisk, npart).lower(): + print("OGAgent for Linux is already installed, you need to uninstall it before re-install.") + else: + systemddir = f"{mntdir}/lib/systemd" + if not (os.path.isdir(systemddir) and os.path.isdir(systemddir.replace('/lib', '/etc'))): + raise_error(f"{ndisk} {npart} systemd") + + ogagentfile = None + code = None + if os.path.exists(f"{mntdir}/etc/debian_version"): + ogagentfile = f"ogagent_{ogversion.replace('pre', '')}_all.deb" + code = f"if ! dpkg -l ogagent &>/dev/null && [ -f /var/tmp/{ogagentfile} ]; then apt-get update; apt-get install -y /var/tmp/{ogagentfile}; fi" + elif os.path.exists(f"{mntdir}/etc/redhat-release"): + ogagentfile = f"ogagent-{ogversion.replace('pre', '')}-1.noarch.rpm" + code = f"if ! rpm -q ogagent &>/dev/null && [ -f /var/tmp/{ogagentfile} ]; then yum install -y /var/tmp/{ogagentfile}; fi" + + if not ogagentfile: + raise_error(f"{ndisk} {npart} ogagent") + + tmpdir = f"{mntdir}/var/tmp" + if download_file(f"https://{ogGetServerIp()}/opengnsys/descargas/{ogagentfile}", f"{tmpdir}/{ogagentfile}"): + with open(f"{systemddir}/systemd-launchogagent", 'w') as f: + f.write(f"""#!/bin/bash +[ $EUID = 0 ] || exit 4 +start() {{ + {code} + sed -i "0,/remote=/ s,remote=.*,remote=https://{ogGetServerIp()}/opengnsys/rest/," /usr/share/OGAgent/cfg/ogagent.cfg + service ogagent start +}} +restart() {{ + service ogagent stop + if [ -f /var/tmp/{ogagentfile} ]; then + apt-get update + apt-get install -y --reinstall /var/tmp/{ogagentfile} + fi + sed -i "0,/remote=/ s,remote=.*,remote=https://{ogGetServerIp()}/opengnsys/rest/," /usr/share/OGAgent/cfg/ogagent.cfg + service ogagent start +}} + +case "$1" in + start|restart) "$1" ;; +esac +""") + os.chmod(f"{systemddir}/systemd-launchogagent", 0o755) + + with open(f"{systemddir}/system/launchogagent.service", 'w') as f: + f.write(f"""[Unit] +Description=Installing and configuring OGAgent + +[Service] +Type=oneshot +RemainAfterExit=yes +ExecStart=/lib/systemd/systemd-launchogagent start +TimeoutStartSec=5min + +[Install] +WantedBy=multi-user.target +""") + os.symlink(f"/lib/systemd/system/launchogagent.service", f"{systemddir.replace('/lib', '/etc')}/system/multi-user.target.wants") + print("Scheduled OGAgent installation at next boot") + print(" (process will be executed in the background, do not shutdown until finish).") + else: + raise_error(f"{ndisk} {npart} /var/tmp/{ogagentfile}") + + elif os_type == "MacOS": + print("OGAgent installer for macOS is not implemented yet.") + else: + raise_error(f"{ndisk} {npart}") + +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/client/shared/scripts/listHardwareInfo.py b/client/shared/scripts/listHardwareInfo.py new file mode 100644 index 0000000..8a8b6d3 --- /dev/null +++ b/client/shared/scripts/listHardwareInfo.py @@ -0,0 +1,36 @@ +import os +import subprocess +import sys + +#!/usr/bin/env python3 + +def main(): + PROG = os.path.basename(__file__) + if len(sys.argv) != 1: + og_raise_error(os.getenv('OG_ERR_FORMAT'), f"{os.getenv('MSG_FORMAT')}: {PROG}") + + # Directory of the server where log files are exported + OGLOG = os.getenv('OGLOG') + SERVERLOGDIR = None + mount_output = subprocess.check_output(['mount']).decode('utf-8') + for line in mount_output.splitlines(): + parts = line.split() + if len(parts) > 3 and parts[3] == OGLOG: + SERVERLOGDIR = parts[1] + break + + # List file: hard-IP + HARDFILE = f"hard-{og_get_ip_address()}" + # Redirect output to the list file + try: + with open(f"{OGLOG}/{HARDFILE}", 'w') as f: + f.write(og_list_hardware_info()) + except Exception as e: + sys.exit(1) + + # Output: path of the list file in the repository server + # print(f"{SERVERLOGDIR}/{HARDFILE}") + print(f"{OGLOG}/{HARDFILE}") + +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/client/shared/scripts/listPartitions.py b/client/shared/scripts/listPartitions.py new file mode 100644 index 0000000..e3fe31a --- /dev/null +++ b/client/shared/scripts/listPartitions.py @@ -0,0 +1,11 @@ +import subprocess +import sys + +def list_partitions(*args): + result = subprocess.run(['ogListPartitions'] + list(args), capture_output=True, text=True) + output = result.stdout + cleaned_output = output.rstrip('EMPTY:0 ') + print(cleaned_output) + +if __name__ == "__main__": + list_partitions(*sys.argv[1:]) \ No newline at end of file diff --git a/client/shared/scripts/listPrimaryPartitions.py b/client/shared/scripts/listPrimaryPartitions.py new file mode 100644 index 0000000..a4c894d --- /dev/null +++ b/client/shared/scripts/listPrimaryPartitions.py @@ -0,0 +1,13 @@ +import sys +import subprocess + +def og_list_primary_partitions(args): + try: + result = subprocess.run(['ogListPrimaryPartitions'] + args, check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + print(result.stdout.decode()) + except subprocess.CalledProcessError as e: + print(f"Error: {e.stderr.decode()}", file=sys.stderr) + sys.exit(e.returncode) + +if __name__ == "__main__": + og_list_primary_partitions(sys.argv[1:]) \ No newline at end of file diff --git a/client/shared/scripts/listSoftwareInfo.py b/client/shared/scripts/listSoftwareInfo.py new file mode 100644 index 0000000..eaac54a --- /dev/null +++ b/client/shared/scripts/listSoftwareInfo.py @@ -0,0 +1,56 @@ +import sys +import os +import re +import subprocess + +#!/usr/bin/env python3 + +def main(): + PROG = os.path.basename(__file__) + REDUCED = "no" + + if len(sys.argv) > 1 and sys.argv[1] == "-r": + REDUCED = "yes" + sys.argv.pop(1) + + if len(sys.argv) != 3: + og_raise_error(1, f"Usage: {PROG} [-r] ndisk npart") + + ndisk = sys.argv[1] + npart = sys.argv[2] + + OGLOG = "/path/to/log" # Replace with actual log path + SERVERLOGDIR = None + + # Simulate the mount command and awk processing + mounts = subprocess.check_output(['mount']).decode('utf-8') + for line in mounts.splitlines(): + parts = line.split() + if len(parts) > 3 and parts[2] == OGLOG: + SERVERLOGDIR = parts[1] + break + + if SERVERLOGDIR is None: + og_raise_error(1, "Could not determine server log directory") + + SOFTFILE = f"soft-{og_get_ip_address()}-{ndisk}-{npart}" + softfile_path = os.path.join(OGLOG, SOFTFILE) + + try: + if REDUCED == "no": + software_list = og_list_software(ndisk, npart) + else: + software_list = "\n".join( + line for line in og_list_software(ndisk, npart).splitlines() + if not re.search(r"\(KB[0-9]{6}\)", line) + ) + + with open(softfile_path, 'w') as f: + f.write(software_list) + except Exception as e: + og_raise_error(1, str(e)) + + print(softfile_path) + +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/client/shared/scripts/menuBrowser.py b/client/shared/scripts/menuBrowser.py new file mode 100644 index 0000000..d18acdf --- /dev/null +++ b/client/shared/scripts/menuBrowser.py @@ -0,0 +1,16 @@ +import sys +import os +import subprocess + +#!/usr/bin/env python3 + +def main(): + PROG = os.path.basename(__file__) + if len(sys.argv) != 2: + og_raise_error(os.getenv('OG_ERR_FORMAT', 1), f"{os.getenv('MSG_FORMAT', 'Usage')}: {PROG} urlmenu") + + url = sys.argv[1] + subprocess.run(['browser', '-qws', url]) + +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/client/shared/scripts/restoreImageCustomTemplate.py b/client/shared/scripts/restoreImageCustomTemplate.py new file mode 100644 index 0000000..fc0c1ed --- /dev/null +++ b/client/shared/scripts/restoreImageCustomTemplate.py @@ -0,0 +1,34 @@ +import sys +import os + +#!/usr/bin/env python3 +""" +restoreImageCustom +@brief Plantilla para script de restauración personalizada de imagen. +@param $1 nº de disco +@param $2 nº de partición +@param $3 Repositorio: CACHE, REPO o dirección IP +@param $4 Nombre canónico de la imagen sin extensión +@warning Renombrar este fichero como "restoreImageCustom" para sustituir al script estándar "restoreImage". +""" + +# Control de parámetros. +if not (4 <= len(sys.argv) <= 6): + ogRaiseError(os.getenv('OG_ERR_FORMAT'), "restoreImageCustom str_repo str_imagen int_ndisco int_npart [ str_proto [\"str_opciones\"] ]") + +# Toma de parámetros. +REPO = sys.argv[1].upper() # Repositorio (en mayúsculas). +IMGNAME = sys.argv[2] # Nombre canónico de imagen (sin extensión). +DISK = sys.argv[3] # Nº de disco. +PART = sys.argv[4] # Nº de partición. +PROTO = sys.argv[5].upper() if len(sys.argv) > 5 else "UNICAST" # Protocolo de comunicaciones (por defecto, UNICAST). +PROTOOPT = sys.argv[6] if len(sys.argv) > 6 else "" # Opciones del protocolo separadas por ":" (opcional). + +# Paso 0: Añadir código para realizar control de errores de los parámetros de entrada (recomendado). + +# Paso 1: Añadir aquí el código para el proceso previo antes de la restauración de la imagen en los equipos (opcional). + +# Paso 2: Sustituir, si se desea, la llamada al proceso estándar de restauración de imagen por código personalizado. +restoreImage(*sys.argv[1:]) + +# Aviso: editar la plantilla "configureOsCustom" para añadir el código personalizado para el proceso de postconfiguración de los clientes (no incluir aquí dicho código). \ No newline at end of file diff --git a/client/shared/scripts/runApplicationX.py b/client/shared/scripts/runApplicationX.py new file mode 100644 index 0000000..70b37c4 --- /dev/null +++ b/client/shared/scripts/runApplicationX.py @@ -0,0 +1,18 @@ +import os +import subprocess +import time + +#!/usr/bin/env python3 + + +def start_xvesa(): + subprocess.Popen(['/usr/X11R6/bin/Xvesa', ':0', '-ac', '-shadow', '-screen', '1024x768x24', '-br', '-mouse', '/dev/input/mice']) + time.sleep(0.1) + os.environ['DISPLAY'] = ':0' + +def start_roxterm(): + subprocess.Popen(['/usr/bin/roxterm']) + +if __name__ == "__main__": + start_xvesa() + start_roxterm() \ No newline at end of file diff --git a/client/shared/scripts/runhttplog.py b/client/shared/scripts/runhttplog.py new file mode 100644 index 0000000..b7cb070 --- /dev/null +++ b/client/shared/scripts/runhttplog.py @@ -0,0 +1,38 @@ +import shutil +import os +import subprocess + +def main(): + # Copy lighttpd.conf + shutil.copy('/etc/lighttpd/lighttpd.conf', '/etc/lighttpd/lighttpd.conf.back') + shutil.copy('/opt/opengnsys/lib/httpd/lighttpd.conf', '/etc/lighttpd/') + + # Copy 10-cgi.conf + shutil.copy('/etc/lighttpd/conf-enabled/10-cgi.conf', '/etc/lighttpd/conf-enabled/10-cgi.conf.back') + shutil.copy('/opt/opengnsys/lib/httpd/10-cgi.conf', '/etc/lighttpd/conf-enabled/') + + # Start lighttpd service + subprocess.run(['/etc/init.d/lighttpd', 'start']) + + # Change permissions and create directories + os.chmod('/opt', 0o755) + os.makedirs('/usr/lib/cgi-bin', exist_ok=True) + + # Copy files to /usr/lib/cgi-bin + for filename in os.listdir('/opt/opengnsys/lib/httpd/'): + full_file_name = os.path.join('/opt/opengnsys/lib/httpd/', filename) + if os.path.isfile(full_file_name): + shutil.copy(full_file_name, '/usr/lib/cgi-bin') + + # Run dstat command + with open('/tmp/bandwidth', 'w') as f: + subprocess.Popen(['dstat', '-dn', '10'], stdout=f) + + # Append "WAITING" to OGLOGSESSION + oglogsession = os.getenv('OGLOGSESSION') + if oglogsession: + with open(oglogsession, 'a') as f: + f.write("WAITING\n") + +if __name__ == "__main__": + main() \ No newline at end of file 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 003/167] 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 From 5532fb9eec93815ffb4a091bdebf027aaf0bce87 Mon Sep 17 00:00:00 2001 From: Natalia Serrano Date: Mon, 28 Oct 2024 16:25:04 +0100 Subject: [PATCH 004/167] refs #1059 add ogIsEfiActive() --- client/lib/engine/bin/InventoryLib.lib | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 client/lib/engine/bin/InventoryLib.lib diff --git a/client/lib/engine/bin/InventoryLib.lib b/client/lib/engine/bin/InventoryLib.lib new file mode 100644 index 0000000..c053e8b --- /dev/null +++ b/client/lib/engine/bin/InventoryLib.lib @@ -0,0 +1,19 @@ +#!/usr/bin/python3 + +import os +import stat + +#def ogGetArch(): +#def ogGetOsType(): +#def ogGetOsUuid(): +#def ogGetSerialNumber(): + +def ogIsEfiActive(): + try: + return stat.S_ISDIR (os.stat ('/sys/firmware/efi').st_mode) + except: + return False + +#def ogListHardwareInfo(): +#def ogListSoftware(): +#def ogGetOsVersion(): From eaee15b7d4f744810398d4e0ff8669a09f15cc17 Mon Sep 17 00:00:00 2001 From: Natalia Serrano Date: Mon, 28 Oct 2024 17:50:50 +0100 Subject: [PATCH 005/167] refs #1059 add ogEcho(). Implement ogGlobals --- .gitignore | 2 + client/lib/engine/bin/SystemLib.py | 77 ++++++++++++++++++------------ client/lib/engine/bin/ogGlobals.py | 11 +++++ 3 files changed, 59 insertions(+), 31 deletions(-) create mode 100644 .gitignore create mode 100644 client/lib/engine/bin/ogGlobals.py diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..7243ae5 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +__pycache__/ +*.swp diff --git a/client/lib/engine/bin/SystemLib.py b/client/lib/engine/bin/SystemLib.py index 65476ae..b8449a5 100644 --- a/client/lib/engine/bin/SystemLib.py +++ b/client/lib/engine/bin/SystemLib.py @@ -1,9 +1,11 @@ import subprocess import datetime +from zoneinfo import ZoneInfo import sys import os import shutil +import ogGlobals from DiskLib import * from CacheLib import * from StringLib import * @@ -14,40 +16,53 @@ print (">>>>>>>>>>>>>>>>>>>> Load ", __name__, " <<<<<<<<<<<<<<<<<<<<<<") #OG_ERR_REPO, OG_ERR_NOTOS, OG_ERR_NOGPT, OG_ERR_OUTOFLIMIT, OG_ERR_IMAGE, OG_ERR_CACHE #OGLOGSESSION, OGLOGCOMMAND, OGLOGFILE, OG_ERR_LOCKED, OG_ERR_PARTITION, OG_ERR_FORMAT, OG_ERR_NOTEXEC, OG_ERR_NOTFOUND -def ogEcho(*args): - # Variables locales - CONT = 1 - LOGS = "" - LOGLEVEL = "" - DATETIME = "" +def _logtype2logfile (t): + if 'log' == t: return ogGlobals.OGLOGFILE + elif 'command' == t: return ogGlobals.OGLOGCOMMAND + elif 'session' == t: return ogGlobals.OGLOGSESSION + else: raise Exception (f'unknown log type ({t})') +#/** +# ogEcho [str_logtype ...] [str_loglevel] "str_message" ... +#@brief Muestra mensajes en consola y lo registra en fichero de incidencias. +#@param str_logtype tipo de registro de incidencias ("log", "command", "session") +#@param str_loglevel nivel de registro de incidencias ("info", "warning", "error") +#@param str_message mensaje (puede recibir más de 1 parámetro. +#@return Mensaje mostrado. +#*/ +## zero or more logtypes can be specified +## zero or one loglevel can be specified +## ogEcho ([], None, msg) +## ogEcho ('log', None, msg) +## ogEcho ('session', None, msg) +## ogEcho (['log', 'session'], None, msg) +## ogEcho ([], None, 'info', msg) +## ogEcho ('log', None, 'info', msg) +## ogEcho ('session', None, 'info', msg) +## ogEcho (['log', 'session'], 'info', msg) +def ogEcho (logtypes, loglevel, msg): + logfiles = [] + if type (logtypes) is list: + for l in logtypes: + logfiles.append (_logtype2logfile (l)) + else: ## string + logfiles.append (_logtype2logfile (logtypes)) - # Selección de ficheros de registro de incidencias. - while CONT: - arg = args.pop(0).lower() - if arg == "log": - LOGS += " " + OGLOGFILE - elif arg == "command": - LOGS += " " + OGLOGCOMMAND - elif arg == "session": - LOGS += " " + OGLOGSESSION - else: - CONT = 0 + if loglevel is None or 'help' == loglevel: + for f in logfiles: + with open (f, 'a') as fd: + fd.write (msg + '\n') + return - # Selección del nivel de registro (opcional). - arg = args.pop(0).lower() - if arg == "help": - pass - elif arg == "info" or arg == "warning" or arg == "error": - LOGLEVEL = arg + if 'info' == loglevel or 'warning' == loglevel or 'error' == loglevel: + DATETIME = datetime.datetime.now(ZoneInfo(ogGlobals.TZ)).strftime("%F %T %Z") + if ogGlobals.DEBUG.lower() != "no": + logfiles.append (ogGlobals.OGLOGFILE) - if LOGLEVEL: - DATETIME = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S") - # Registrar mensajes en fichero de log si la depuración no está desactivada. - if DEBUG.lower() != "no": - LOGS += " " + OGLOGFILE - subprocess.call(f"logger -t OpenGnsys {LOGLEVEL} {DATETIME} {' '.join(args)}", shell=True) + for f in logfiles: + with open (f, 'a') as fd: + fd.write (f"OpenGnsys {loglevel} {DATETIME} {msg}\n") else: - print(' '.join(args)) + raise Exception (f'unknown loglevel ({loglevel})') def ogExecAndLog(*args): # Variables locales @@ -298,4 +313,4 @@ def ogIsVirtualMachine(): if "KVM" in output or "VirtualBox" in output: return 1 else: - return 0 \ No newline at end of file + return 0 diff --git a/client/lib/engine/bin/ogGlobals.py b/client/lib/engine/bin/ogGlobals.py new file mode 100644 index 0000000..0f13431 --- /dev/null +++ b/client/lib/engine/bin/ogGlobals.py @@ -0,0 +1,11 @@ +#!/usr/bin/python3 + +#OPENGNSYS='/opt/opengnsys' +OPENGNSYS='/tmp/opengnsys' +OGLOG=f'{OPENGNSYS}/log' +OGLOGFILE=f'{OGLOG}/192.168.42.42' ## TODO +OGLOGCOMMAND='/tmp/command.log' +OGLOGSESSION='/tmp/session.log' +DEBUG='yes' + +TZ='Europe/Madrid' From 9301d9aaaff9dd073a4b57644f561db8e0f9f28e Mon Sep 17 00:00:00 2001 From: Natalia Serrano Date: Mon, 28 Oct 2024 18:02:33 +0100 Subject: [PATCH 006/167] refs #1059 add ogIsVirtualMachine() --- client/lib/engine/bin/SystemLib.py | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/client/lib/engine/bin/SystemLib.py b/client/lib/engine/bin/SystemLib.py index b8449a5..999dd33 100644 --- a/client/lib/engine/bin/SystemLib.py +++ b/client/lib/engine/bin/SystemLib.py @@ -309,8 +309,5 @@ def ogCheckProgram(*args): return 0 def ogIsVirtualMachine(): - output = subprocess.check_output(["dmidecode", "-s", "system-product-name"]).decode("utf-8") - if "KVM" in output or "VirtualBox" in output: - return 1 - else: - return 0 + output = subprocess.run (["dmidecode", "-s", "system-product-name"], capture_output=True, text=True).stdout + return "KVM" in output or "VirtualBox" in output From 94813cea3c747f402a5a46f1b58936c0f232413e Mon Sep 17 00:00:00 2001 From: Natalia Serrano Date: Mon, 28 Oct 2024 18:20:24 +0100 Subject: [PATCH 007/167] refs #1059 add ogGetCaller() --- client/lib/engine/bin/SystemLib.py | 35 ++++++++++++++++++++++-------- 1 file changed, 26 insertions(+), 9 deletions(-) diff --git a/client/lib/engine/bin/SystemLib.py b/client/lib/engine/bin/SystemLib.py index 999dd33..f168dc8 100644 --- a/client/lib/engine/bin/SystemLib.py +++ b/client/lib/engine/bin/SystemLib.py @@ -117,16 +117,33 @@ def ogExecAndLog(*args): # Salida de error del comando ejecutado. return subprocess.PIPESTATUS[0] +#/** +# ogGetCaller +#@brief Devuelve nombre del programa o script ejecutor (padre). +#@return str_name - Nombre del programa ejecutor. +#*/ def ogGetCaller(): - # Obtener el nombre del programa o del script que ha llamado al proceso actual. - output = subprocess.check_output(["ps", "hp", str(os.getppid()), "-o", "args"]).decode("utf-8") - lines = output.split("\n") - caller = "" - for line in lines: - if "bash" in line and line.split()[1] != "": - caller = line.split()[1] - else: - caller = line.split()[0].lstrip("-") + if 'COLUMNS' in os.environ: + cols = os.environ['COLUMNS'] + else: + cols = None + + lines = subprocess.run (["ps", "hp", str(os.getppid()), "-o", "args"], capture_output=True, text=True).stdout.splitlines() + if 0 == len (lines): + return '' + + line = lines[0] + words = line.split() + if "bash" in line and len(words)>1: + caller = words[1] + else: + caller = words[0].lstrip("-") + + if cols is None: + del (os.environ['COLUMNS']) + else: + os.environ['COLUMNS'] = cols + return os.path.basename(caller) def ogHelp(*args): From 83b62179fa7d4c958d412f4441c2e3e4eb3a8efe Mon Sep 17 00:00:00 2001 From: Natalia Serrano Date: Mon, 28 Oct 2024 18:33:30 +0100 Subject: [PATCH 008/167] refs #1059 fix ogEcho("help") --- client/lib/engine/bin/SystemLib.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/client/lib/engine/bin/SystemLib.py b/client/lib/engine/bin/SystemLib.py index f168dc8..2587f5d 100644 --- a/client/lib/engine/bin/SystemLib.py +++ b/client/lib/engine/bin/SystemLib.py @@ -48,6 +48,8 @@ def ogEcho (logtypes, loglevel, msg): logfiles.append (_logtype2logfile (logtypes)) if loglevel is None or 'help' == loglevel: + if ogGlobals.DEBUG.lower() != "no": + logfiles.append (ogGlobals.OGLOGFILE) for f in logfiles: with open (f, 'a') as fd: fd.write (msg + '\n') @@ -55,8 +57,6 @@ def ogEcho (logtypes, loglevel, msg): if 'info' == loglevel or 'warning' == loglevel or 'error' == loglevel: DATETIME = datetime.datetime.now(ZoneInfo(ogGlobals.TZ)).strftime("%F %T %Z") - if ogGlobals.DEBUG.lower() != "no": - logfiles.append (ogGlobals.OGLOGFILE) for f in logfiles: with open (f, 'a') as fd: From b2de290a8d2ff80eb97b731d435d8475f10f705c Mon Sep 17 00:00:00 2001 From: Antonio Emmanuel Guerrero Silva Date: Mon, 28 Oct 2024 22:55:27 -0600 Subject: [PATCH 009/167] refs #1037 References between NetLib, FileLib, SystemLib libraries necessary for the correct operation of InventarioHardware.py are implemented. --- client/interfaceAdm/InventarioHardware.py | 24 +++--- client/lib/engine/bin/FileLib.py | 0 client/lib/engine/bin/SystemLib.py | 91 ++++++++++------------- client/shared/scripts/__init__.py | 0 client/shared/scripts/getIpAddress.py | 17 ++++- client/shared/scripts/listHardwareInfo.py | 62 ++++++++------- 6 files changed, 98 insertions(+), 96 deletions(-) mode change 100644 => 100755 client/lib/engine/bin/FileLib.py mode change 100644 => 100755 client/lib/engine/bin/SystemLib.py create mode 100644 client/shared/scripts/__init__.py diff --git a/client/interfaceAdm/InventarioHardware.py b/client/interfaceAdm/InventarioHardware.py index d0fe079..1c55736 100644 --- a/client/interfaceAdm/InventarioHardware.py +++ b/client/interfaceAdm/InventarioHardware.py @@ -1,20 +1,18 @@ 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 main(output_file): + # Ejecutar el comando `listHardwareInfo.py` y capturar el resultado + result = subprocess.run(["python3", "/opt/opengnsys/scripts/listHardwareInfo.py"], capture_output=True, text=True, check=True) + file_path = result.stdout.strip() # Obtener la ruta del archivo de salida de `listHardwareInfo.py` -def save_hardware_inventory(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:])) + # Leer desde la segunda línea del archivo y escribir en el archivo de salida especificado + with open(file_path, 'r') as input_file, open(output_file, 'w') as output: + lines = input_file.readlines()[1:] # Saltar la primera línea + output.writelines(lines) if __name__ == "__main__": if len(sys.argv) != 2: - print("Usage: python InventarioHardware.py ") - else: - save_hardware_inventory(sys.argv[1]) \ No newline at end of file + print("Uso: python3 InventarioHardware.py ") + sys.exit(1) + main(sys.argv[1]) diff --git a/client/lib/engine/bin/FileLib.py b/client/lib/engine/bin/FileLib.py old mode 100644 new mode 100755 diff --git a/client/lib/engine/bin/SystemLib.py b/client/lib/engine/bin/SystemLib.py old mode 100644 new mode 100755 index 999dd33..7aad1aa --- a/client/lib/engine/bin/SystemLib.py +++ b/client/lib/engine/bin/SystemLib.py @@ -1,68 +1,52 @@ import subprocess import datetime -from zoneinfo import ZoneInfo import sys import os import shutil -import ogGlobals -from DiskLib import * -from CacheLib import * -from StringLib import * - -print (">>>>>>>>>>>>>>>>>>>> Load ", __name__, " <<<<<<<<<<<<<<<<<<<<<<") +#from engine.DiskLib import * +#from engine.CacheLib import * +#from engine.StringLib import * #NODEBUGFUNCTIONS, OGIMG, OG_ERR_CACHESIZE, OG_ERR_NOTCACHE, OG_ERR_NOTWRITE, OG_ERR_FILESYS #OG_ERR_REPO, OG_ERR_NOTOS, OG_ERR_NOGPT, OG_ERR_OUTOFLIMIT, OG_ERR_IMAGE, OG_ERR_CACHE #OGLOGSESSION, OGLOGCOMMAND, OGLOGFILE, OG_ERR_LOCKED, OG_ERR_PARTITION, OG_ERR_FORMAT, OG_ERR_NOTEXEC, OG_ERR_NOTFOUND -def _logtype2logfile (t): - if 'log' == t: return ogGlobals.OGLOGFILE - elif 'command' == t: return ogGlobals.OGLOGCOMMAND - elif 'session' == t: return ogGlobals.OGLOGSESSION - else: raise Exception (f'unknown log type ({t})') -#/** -# ogEcho [str_logtype ...] [str_loglevel] "str_message" ... -#@brief Muestra mensajes en consola y lo registra en fichero de incidencias. -#@param str_logtype tipo de registro de incidencias ("log", "command", "session") -#@param str_loglevel nivel de registro de incidencias ("info", "warning", "error") -#@param str_message mensaje (puede recibir más de 1 parámetro. -#@return Mensaje mostrado. -#*/ -## zero or more logtypes can be specified -## zero or one loglevel can be specified -## ogEcho ([], None, msg) -## ogEcho ('log', None, msg) -## ogEcho ('session', None, msg) -## ogEcho (['log', 'session'], None, msg) -## ogEcho ([], None, 'info', msg) -## ogEcho ('log', None, 'info', msg) -## ogEcho ('session', None, 'info', msg) -## ogEcho (['log', 'session'], 'info', msg) -def ogEcho (logtypes, loglevel, msg): - logfiles = [] - if type (logtypes) is list: - for l in logtypes: - logfiles.append (_logtype2logfile (l)) - else: ## string - logfiles.append (_logtype2logfile (logtypes)) +def ogEcho(*args): + # Variables locales + CONT = 1 + LOGS = "" + LOGLEVEL = "" + DATETIME = "" - if loglevel is None or 'help' == loglevel: - for f in logfiles: - with open (f, 'a') as fd: - fd.write (msg + '\n') - return + # Selección de ficheros de registro de incidencias. + while CONT: + args = list(args) + arg = args.pop(0).lower() + if arg == "log": + LOGS += " " + OGLOGFILE + elif arg == "command": + LOGS += " " + OGLOGCOMMAND + elif arg == "session": + LOGS += " " + OGLOGSESSION + else: + CONT = 0 - if 'info' == loglevel or 'warning' == loglevel or 'error' == loglevel: - DATETIME = datetime.datetime.now(ZoneInfo(ogGlobals.TZ)).strftime("%F %T %Z") - if ogGlobals.DEBUG.lower() != "no": - logfiles.append (ogGlobals.OGLOGFILE) + # Selección del nivel de registro (opcional). + arg = args.pop(0).lower() + if arg == "help": + pass + elif arg == "info" or arg == "warning" or arg == "error": + LOGLEVEL = arg - for f in logfiles: - with open (f, 'a') as fd: - fd.write (f"OpenGnsys {loglevel} {DATETIME} {msg}\n") + if LOGLEVEL: + DATETIME = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S") + # Registrar mensajes en fichero de log si la depuración no está desactivada. + if DEBUG.lower() != "no": + LOGS += " " + OGLOGFILE + subprocess.call(f"logger -t OpenGnsys {LOGLEVEL} {DATETIME} {' '.join(args)}", shell=True) else: - raise Exception (f'unknown loglevel ({loglevel})') + print(' '.join(args)) def ogExecAndLog(*args): # Variables locales @@ -309,5 +293,8 @@ def ogCheckProgram(*args): return 0 def ogIsVirtualMachine(): - output = subprocess.run (["dmidecode", "-s", "system-product-name"], capture_output=True, text=True).stdout - return "KVM" in output or "VirtualBox" in output + output = subprocess.check_output(["dmidecode", "-s", "system-product-name"]).decode("utf-8") + if "KVM" in output or "VirtualBox" in output: + return 1 + else: + return 0 diff --git a/client/shared/scripts/__init__.py b/client/shared/scripts/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/client/shared/scripts/getIpAddress.py b/client/shared/scripts/getIpAddress.py index 1694bdd..7369d4f 100644 --- a/client/shared/scripts/getIpAddress.py +++ b/client/shared/scripts/getIpAddress.py @@ -1,6 +1,17 @@ +#!/usr/bin/env python3 +import subprocess import sys +from NetLib import ogGetIpAddress + +def get_ip_address(*args): + try: + # Ejecuta ogGetIpAddress como un comando en el sistema + result = subprocess.run(["/opt/opengnsys/client/lib/engine/bin/ogGetIpAddress"] + list(args), + capture_output=True, text=True, check=True) + print(result.stdout.strip()) + except subprocess.CalledProcessError as e: + print(f"Error ejecutando ogGetIpAddress: {e}", file=sys.stderr) + sys.exit(1) if __name__ == "__main__": - args = sys.argv[1:] - output = ogGetIpAddress(args) - print(output) \ No newline at end of file + get_ip_address(*sys.argv[1:]) diff --git a/client/shared/scripts/listHardwareInfo.py b/client/shared/scripts/listHardwareInfo.py index 8a8b6d3..d920c73 100644 --- a/client/shared/scripts/listHardwareInfo.py +++ b/client/shared/scripts/listHardwareInfo.py @@ -1,36 +1,42 @@ -import os import subprocess +import os import sys +sys.path.append('/opt/opengnsys/lib/engine/bin') # Agregar ruta de NetLib.py +from InventoryLib import ogListHardwareInfo +from NetLib import ogGetIpAddress -#!/usr/bin/env python3 - -def main(): - PROG = os.path.basename(__file__) - if len(sys.argv) != 1: - og_raise_error(os.getenv('OG_ERR_FORMAT'), f"{os.getenv('MSG_FORMAT')}: {PROG}") - - # Directory of the server where log files are exported - OGLOG = os.getenv('OGLOG') - SERVERLOGDIR = None - mount_output = subprocess.check_output(['mount']).decode('utf-8') - for line in mount_output.splitlines(): +def get_server_log_dir(): + # Obtener el directorio de logs del servidor + oglog = os.getenv("OGLOG") + if not oglog: + return "" + result = subprocess.run(["mount"], capture_output=True, text=True) + for line in result.stdout.splitlines(): parts = line.split() - if len(parts) > 3 and parts[3] == OGLOG: - SERVERLOGDIR = parts[1] - break + if len(parts) >= 4 and parts[3] == oglog: + return parts[1] + return "" - # List file: hard-IP - HARDFILE = f"hard-{og_get_ip_address()}" - # Redirect output to the list file - try: - with open(f"{OGLOG}/{HARDFILE}", 'w') as f: - f.write(og_list_hardware_info()) - except Exception as e: - sys.exit(1) +def list_hardware_info(): + oglog = os.getenv("OGLOG", "/tmp") # Usar /tmp como valor por defecto para OGLOG - # Output: path of the list file in the repository server - # print(f"{SERVERLOGDIR}/{HARDFILE}") - print(f"{OGLOG}/{HARDFILE}") + # Fichero de listado de hardware basado en la IP obtenida + hardfile = f"hard-{ogGetIpAddress()}" + + # Ejecutar ogListHardwareInfo y redirigir al archivo de listado + hardware_info_path = os.path.join(oglog, hardfile) + with open(hardware_info_path, 'w') as output_file: + output_file.write(ogListHardwareInfo()) + + return hardware_info_path if __name__ == "__main__": - main() \ No newline at end of file + # Obtener el directorio del servidor donde se exportan los ficheros de registro + server_log_dir = get_server_log_dir() + + # Generar el archivo de listado de hardware y obtener su ruta + hardware_info_path = list_hardware_info() + + # Imprimir la ruta del archivo generado + print(hardware_info_path) + From c3a0e8db1cbf36e0232754ea77f37ef900fc2129 Mon Sep 17 00:00:00 2001 From: Natalia Serrano Date: Tue, 29 Oct 2024 09:57:25 +0100 Subject: [PATCH 010/167] refs #1059 repeat work --- client/lib/engine/bin/SystemLib.py | 119 ++++++++++++++++++++--------- 1 file changed, 82 insertions(+), 37 deletions(-) diff --git a/client/lib/engine/bin/SystemLib.py b/client/lib/engine/bin/SystemLib.py index 13f59bf..1bd755b 100755 --- a/client/lib/engine/bin/SystemLib.py +++ b/client/lib/engine/bin/SystemLib.py @@ -1,9 +1,11 @@ import subprocess import datetime +from zoneinfo import ZoneInfo import sys import os import shutil +import ogGlobals #from engine.DiskLib import * #from engine.CacheLib import * #from engine.StringLib import * @@ -12,41 +14,53 @@ import shutil #OG_ERR_REPO, OG_ERR_NOTOS, OG_ERR_NOGPT, OG_ERR_OUTOFLIMIT, OG_ERR_IMAGE, OG_ERR_CACHE #OGLOGSESSION, OGLOGCOMMAND, OGLOGFILE, OG_ERR_LOCKED, OG_ERR_PARTITION, OG_ERR_FORMAT, OG_ERR_NOTEXEC, OG_ERR_NOTFOUND -def ogEcho(*args): - # Variables locales - CONT = 1 - LOGS = "" - LOGLEVEL = "" - DATETIME = "" +def _logtype2logfile (t): + if 'log' == t: return ogGlobals.OGLOGFILE + elif 'command' == t: return ogGlobals.OGLOGCOMMAND + elif 'session' == t: return ogGlobals.OGLOGSESSION + else: raise Exception (f'unknown log type ({t})') +#/** +# ogEcho [str_logtype ...] [str_loglevel] "str_message" ... +#@brief Muestra mensajes en consola y lo registra en fichero de incidencias. +#@param str_logtype tipo de registro de incidencias ("log", "command", "session") +#@param str_loglevel nivel de registro de incidencias ("info", "warning", "error") +#@param str_message mensaje (puede recibir más de 1 parámetro. +#@return Mensaje mostrado. +#*/ +## zero or more logtypes can be specified +## zero or one loglevel can be specified +## ogEcho ([], None, msg) +## ogEcho ('log', None, msg) +## ogEcho ('session', None, msg) +## ogEcho (['log', 'session'], None, msg) +## ogEcho ([], None, 'info', msg) +## ogEcho ('log', None, 'info', msg) +## ogEcho ('session', None, 'info', msg) +## ogEcho (['log', 'session'], 'info', msg) +def ogEcho (logtypes, loglevel, msg): + logfiles = [] + if type (logtypes) is list: + for l in logtypes: + logfiles.append (_logtype2logfile (l)) + else: ## string + logfiles.append (_logtype2logfile (logtypes)) - # Selección de ficheros de registro de incidencias. - while CONT: - args = list(args) - arg = args.pop(0).lower() - if arg == "log": - LOGS += " " + OGLOGFILE - elif arg == "command": - LOGS += " " + OGLOGCOMMAND - elif arg == "session": - LOGS += " " + OGLOGSESSION - else: - CONT = 0 + if loglevel is None or 'help' == loglevel: + if ogGlobals.DEBUG.lower() != "no": + logfiles.append (ogGlobals.OGLOGFILE) + for f in logfiles: + with open (f, 'a') as fd: + fd.write (msg + '\n') + return - # Selección del nivel de registro (opcional). - arg = args.pop(0).lower() - if arg == "help": - pass - elif arg == "info" or arg == "warning" or arg == "error": - LOGLEVEL = arg + if 'info' == loglevel or 'warning' == loglevel or 'error' == loglevel: + DATETIME = datetime.datetime.now(ZoneInfo(ogGlobals.TZ)).strftime("%F %T %Z") - if LOGLEVEL: - DATETIME = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S") - # Registrar mensajes en fichero de log si la depuración no está desactivada. - if DEBUG.lower() != "no": - LOGS += " " + OGLOGFILE - subprocess.call(f"logger -t OpenGnsys {LOGLEVEL} {DATETIME} {' '.join(args)}", shell=True) + for f in logfiles: + with open (f, 'a') as fd: + fd.write (f"OpenGnsys {loglevel} {DATETIME} {msg}\n") else: - print(' '.join(args)) + raise Exception (f'unknown loglevel ({loglevel})') def ogExecAndLog(*args): # Variables locales @@ -130,7 +144,24 @@ def ogGetCaller(): return os.path.basename(caller) -def ogHelp(*args): +import inspect +#/** +# ogHelp ["str_function" ["str_format" ["str_example" ... ]]] +#@brief Muestra mensaje de ayuda para una función determinda. +#@param str_function Nombre de la función. +#@param str_format Formato de ejecución de la función. +#@param str_example Ejemplo de ejecución de la función. +#@return str_help - Salida de ayuda. +#@note Si no se indican parámetros, la función se toma de la variable \c $FUNCNAME +#@note La descripción de la función se toma de la variable compuesta por \c MSG_FUNC_$función incluida en el fichero de idiomas. +#@note Pueden especificarse varios mensajes con ejemplos. +#@version 0.9 - Primera versión para OpenGnSys. +#@author Ramon Gomez, ETSII Universidad de Sevilla +#@date 2009-07-27 +#*/ +def ogHelp (fname, fmt, msg): + func = fname or inspect.stack()[1][3] + MSG = f'MSG_HELP_{func}' # Variables locales FUNC = "" MSG = "" @@ -146,6 +177,23 @@ def ogHelp(*args): # Mostrar ejemplos (si existen). for example in args[2:]: ogEcho("help", f" {MSG_EXAMPLE}: {example}") +#function ogHelp () { +# +## Variables locales. +#local FUNC MSG +# +## Mostrar función, descripción y formato. +#FUNC="${1:-${FUNCNAME[${#FUNCNAME[*]}-1]}}" +#MSG="MSG_HELP_$FUNC" +#ogEcho help "$MSG_FUNCTION $FUNC: ${!MSG}" +#[ -n "$2" ] && ogEcho help " $MSG_FORMAT: $2" +## Mostrar ejemplos (si existen). +#shift 2 +#while [ $# -gt 0 ]; do +# ogEcho help " $MSG_EXAMPLE: $1" +# shift +#done +#} def ogRaiseError(*args): # Variables locales @@ -310,8 +358,5 @@ def ogCheckProgram(*args): return 0 def ogIsVirtualMachine(): - output = subprocess.check_output(["dmidecode", "-s", "system-product-name"]).decode("utf-8") - if "KVM" in output or "VirtualBox" in output: - return 1 - else: - return 0 + output = subprocess.run (["dmidecode", "-s", "system-product-name"], capture_output=True, text=True).stdout + return "KVM" in output or "VirtualBox" in output From 2d02f00766b426456b5e3215030c4f9b924d2255 Mon Sep 17 00:00:00 2001 From: Natalia Serrano Date: Tue, 29 Oct 2024 16:19:51 +0100 Subject: [PATCH 011/167] refs #1059 add ogHelp --- client/lib/engine/bin/InventoryLib.lib | 4 +++ client/lib/engine/bin/SystemLib.py | 48 ++++++-------------------- client/lib/engine/bin/ogGlobals.py | 6 ++++ 3 files changed, 21 insertions(+), 37 deletions(-) diff --git a/client/lib/engine/bin/InventoryLib.lib b/client/lib/engine/bin/InventoryLib.lib index c053e8b..3dd0836 100644 --- a/client/lib/engine/bin/InventoryLib.lib +++ b/client/lib/engine/bin/InventoryLib.lib @@ -8,6 +8,10 @@ import stat #def ogGetOsUuid(): #def ogGetSerialNumber(): +#/** +# ogIsEfiActive +#@brief Comprueba si el sistema tiene activo el arranque EFI. +#*/ ## def ogIsEfiActive(): try: return stat.S_ISDIR (os.stat ('/sys/firmware/efi').st_mode) diff --git a/client/lib/engine/bin/SystemLib.py b/client/lib/engine/bin/SystemLib.py index 1bd755b..bb19864 100755 --- a/client/lib/engine/bin/SystemLib.py +++ b/client/lib/engine/bin/SystemLib.py @@ -155,45 +155,19 @@ import inspect #@note Si no se indican parámetros, la función se toma de la variable \c $FUNCNAME #@note La descripción de la función se toma de la variable compuesta por \c MSG_FUNC_$función incluida en el fichero de idiomas. #@note Pueden especificarse varios mensajes con ejemplos. -#@version 0.9 - Primera versión para OpenGnSys. -#@author Ramon Gomez, ETSII Universidad de Sevilla -#@date 2009-07-27 #*/ -def ogHelp (fname, fmt, msg): - func = fname or inspect.stack()[1][3] - MSG = f'MSG_HELP_{func}' - # Variables locales - FUNC = "" - MSG = "" - FUNCNAME = ogHelp.__name__ +def ogHelp (fname, fmt=None, examples=[]): + FUNC = fname or inspect.stack()[1][3] + MSG = f'ogGlobals.MSG_HELP_{FUNC}' + ogEcho ([], "help", f"{ogGlobals.MSG_FUNCTION} {FUNC}: {eval (MSG)}") + if fmt: + ogEcho([], "help", f" {ogGlobals.MSG_FORMAT}: {fmt}") - # Mostrar función, descripción y formato. - FUNC = args[0] if len(args) > 0 else FUNCNAME[-1] - MSG = f"MSG_HELP_{FUNC}" - ogEcho("help", f"{MSG_FUNCTION} {FUNC}: {globals()[MSG]}") - if len(args) > 1: - ogEcho("help", f" {MSG_FORMAT}: {args[1]}") - - # Mostrar ejemplos (si existen). - for example in args[2:]: - ogEcho("help", f" {MSG_EXAMPLE}: {example}") -#function ogHelp () { -# -## Variables locales. -#local FUNC MSG -# -## Mostrar función, descripción y formato. -#FUNC="${1:-${FUNCNAME[${#FUNCNAME[*]}-1]}}" -#MSG="MSG_HELP_$FUNC" -#ogEcho help "$MSG_FUNCTION $FUNC: ${!MSG}" -#[ -n "$2" ] && ogEcho help " $MSG_FORMAT: $2" -## Mostrar ejemplos (si existen). -#shift 2 -#while [ $# -gt 0 ]; do -# ogEcho help " $MSG_EXAMPLE: $1" -# shift -#done -#} + if type (examples) is list: + for example in examples: + ogEcho([], "help", f" {ogGlobals.MSG_EXAMPLE}: {example}") + else: ## string + ogEcho([], "help", f" {ogGlobals.MSG_EXAMPLE}: {examples}") def ogRaiseError(*args): # Variables locales diff --git a/client/lib/engine/bin/ogGlobals.py b/client/lib/engine/bin/ogGlobals.py index 0f13431..e685717 100644 --- a/client/lib/engine/bin/ogGlobals.py +++ b/client/lib/engine/bin/ogGlobals.py @@ -8,4 +8,10 @@ OGLOGCOMMAND='/tmp/command.log' OGLOGSESSION='/tmp/session.log' DEBUG='yes' +## languages +MSG_EXAMPLE='Example' +MSG_FORMAT='Format' +MSG_FUNCTION='Function' +## /languages + TZ='Europe/Madrid' From 7cd6e22b0d1a1664229aa86421e658c59a44db5a Mon Sep 17 00:00:00 2001 From: Natalia Serrano Date: Tue, 29 Oct 2024 17:03:20 +0100 Subject: [PATCH 012/167] refs #1085 add language files --- client/lib/engine/bin/SystemLib.py | 10 +- client/lib/engine/bin/lang_ca_ES.py | 400 ++++++++++++++++++++++++++++ client/lib/engine/bin/lang_en_GB.py | 387 +++++++++++++++++++++++++++ client/lib/engine/bin/lang_es_ES.py | 387 +++++++++++++++++++++++++++ client/lib/engine/bin/ogGlobals.py | 29 +- 5 files changed, 1202 insertions(+), 11 deletions(-) create mode 100644 client/lib/engine/bin/lang_ca_ES.py create mode 100644 client/lib/engine/bin/lang_en_GB.py create mode 100644 client/lib/engine/bin/lang_es_ES.py diff --git a/client/lib/engine/bin/SystemLib.py b/client/lib/engine/bin/SystemLib.py index bb19864..294fa88 100755 --- a/client/lib/engine/bin/SystemLib.py +++ b/client/lib/engine/bin/SystemLib.py @@ -158,16 +158,16 @@ import inspect #*/ def ogHelp (fname, fmt=None, examples=[]): FUNC = fname or inspect.stack()[1][3] - MSG = f'ogGlobals.MSG_HELP_{FUNC}' - ogEcho ([], "help", f"{ogGlobals.MSG_FUNCTION} {FUNC}: {eval (MSG)}") + MSG = f'ogGlobals.lang.MSG_HELP_{FUNC}' + ogEcho ([], "help", f"{ogGlobals.lang.MSG_FUNCTION} {FUNC}: {eval (MSG)}") if fmt: - ogEcho([], "help", f" {ogGlobals.MSG_FORMAT}: {fmt}") + ogEcho([], "help", f" {ogGlobals.lang.MSG_FORMAT}: {fmt}") if type (examples) is list: for example in examples: - ogEcho([], "help", f" {ogGlobals.MSG_EXAMPLE}: {example}") + ogEcho([], "help", f" {ogGlobals.lang.MSG_EXAMPLE}: {example}") else: ## string - ogEcho([], "help", f" {ogGlobals.MSG_EXAMPLE}: {examples}") + ogEcho([], "help", f" {ogGlobals.lang.MSG_EXAMPLE}: {examples}") def ogRaiseError(*args): # Variables locales diff --git a/client/lib/engine/bin/lang_ca_ES.py b/client/lib/engine/bin/lang_ca_ES.py new file mode 100644 index 0000000..81e48ca --- /dev/null +++ b/client/lib/engine/bin/lang_ca_ES.py @@ -0,0 +1,400 @@ +#!/usr/bin/python3 + +# Fichero de idioma: catalá. +#@version 1.1.1 +#@author + + +# Mensajes de error. +MSG_ERR_GENERIC="Error imprevisto no definido" +MSG_ERR_FORMAT="Formato de ejecución incorrecto" +MSG_ERR_OUTOFLIMIT="Valor fuera de rango o no válido" +MSG_ERR_NOTFOUND="Fichero o dispositivo no encontrado" +MSG_ERR_PARTITION="Partición errónea o desconocida" +MSG_ERR_LOCKED="Recurso bloqueado por operación de uso exclusivo" +MSG_ERR_CACHE="Error en partición de caché local" +MSG_ERR_NOGPT="El disco indicado no contiene una particion GPT" +MSG_ERR_REPO="Error al montar el repositorio de imágenes" +MSG_ERR_NOMSDOS="El disco indicado no contiene una partición MSDOS" +MSG_ERR_FILESYS="Sistema de archivos desconocido o no se puede montar" +MSG_ERR_NOTOS="Sistema operativo no detectado o no se puede iniciar" +MSG_ERR_IMAGE="No se puede crear o restaurar una image de sistema" +MSG_ERR_IMAGEFILE="Archivo de imagen corrupto o de otra versión de partclone" +MSG_ERR_NOTEXEC="Programa o función no ejecutable" +MSG_ERR_NOTWRITE="No hay acceso de escritura" +MSG_ERR_NOTCACHE="No existe particion Cache en el cliente" +MSG_ERR_NOTUEFI="La interfaz UEFI no está activa" +MSG_ERR_NOTBIOS="La interfaz BIOS Legacy no está activa" +MSG_ERR_CACHESIZE="El espacio de la cache local o remota no es suficiente" +MSG_ERR_REDUCEFS="Error al reducir el sistema de archivos" +MSG_ERR_EXTENDFS="Error al expandir el sistema de archivos" +MSG_ERR_IMGSIZEPARTITION="Error al restaurar: Particion mas pequeña que la imagen" +MSG_ERR_UPDATECACHE="Error al realizar el comando updateCache" +MSG_ERR_UCASTSYNTAXT="Error en la generación de sintaxis de transferenica unicast" +MSG_ERR_UCASTSENDPARTITION="Error en envio UNICAST de una particion" +MSG_ERR_UCASTSENDFILE="Error en envio UNICAST de un fichero" +MSG_ERR_UCASTRECEIVERPARTITION="Error en la recepcion UNICAST de una particion" +MSG_ERR_UCASTRECEIVERFILE="Error en la recepcion UNICAST de un fichero" +MSG_ERR_MCASTSYNTAXT="Error en la generación de sintaxis de transferenica multicast" +MSG_ERR_MCASTSENDFILE="Error en envio MULTICAST de un fichero" +MSG_ERR_MCASTRECEIVERFILE="Error en la recepcion MULTICAST de un fichero" +MSG_ERR_MCASTSENDPARTITION="Error en envio MULTICAST de una particion" +MSG_ERR_MCASTRECEIVERPARTITION="Error en la recepcion MULTICAST de un fichero" +MSG_ERR_PROTOCOLJOINMASTER="Error en la conexion de una sesion UNICAST|MULTICAST con el MASTER" +MSG_ERR_DONTFORMAT="Error al formatear" +MSG_ERR_DONTMOUNT_IMAGE="Error al montar/reducir la imagen" +MSG_ERR_DONTUNMOUNT_IMAGE="Error al desmontar la imagen" +MSG_ERR_DONTSYNC_IMAGE="Imagen no sincronizable" +MSG_ERR_NOTDIFFERENT="No se detectan diferencias entre la imagen basica y la particion." +MSG_ERR_SYNCHRONIZING="Error al sincronizar, puede afectar la creacion|restauracion de la imagen" + +# Mensajes de avisos. +MSG_DONTUSE="NO USAR" +MSG_DONTMOUNT="Sistema de archivos no montado" +MSG_DONTUNMOUNT="El sistema de archivos no se puede desmontar o no está montado" +MSG_MOUNT="Sistema de archivos montado" +MSG_MOUNTREADONLY="Sistema de archivos montado solo de lectura" +MSG_OBSOLETE="EN DESUSO" + +# Mensajes complementarios para las ayudas. +MSG_64BIT="64 bits" +MSG_DISK="disc" +MSG_ERROR="Error" +MSG_EXAMPLE="Exemple" +MSG_FORMAT="Format" +MSG_FUNCTION="Funció" +MSG_HARDWAREINVENTORY="Inventario de maquinari de la màquina" +MSG_IMAGE="imatge" +MSG_INSTALLED="instal-lat" +MSG_NOCACHE="sense caché local" +MSG_NOEXTENDED="sense partició estensa" +MSG_PARTITION="partició" +MSG_PROTOCOL="protocol" +MSG_RESERVEDVALUE="Valor reservat" +MSG_SEE="Veure" +MSG_UNKNOWN="Desconegut" +MSG_WARNING="Avís" + +# Mensajes del proceso de arranque. +MSG_DETECTLVMRAID="Detectar metadispositivos LVM y RAID." +MSG_ERRBOOTMODE=f"{MSG_ERROR}: Modo de arranque desconocido." +MSG_LAUNCHCLIENT="Ejecutar cliente." +MSG_LOADAPI="Cargar funciones del motor de clonación." +MSG_LOADMODULES="Cargar módulos del kernel." +MSG_MAKELINKS="Crear enlaces simbólicos." +MSG_MOUNTREPO="Montar repositorio por %s en modo %s." +MSG_OFFLINEMODE="Modo de arranque sin conexión." +MSG_OTHERSERVICES="Iniciar servicios complementarios del cliente." +MSG_POWEROFFCONF="Definir parámetros de ahorro de energía." + +# Mensajes del menú por defecto. +MSG_BOOT="Iniciar" +MSG_DUPLEX="Dúplex" +MSG_HOSTNAME="Equipo" +MSG_IPADDR="Dirección IP" +MSG_MACADDR="Dirección MAC" +MSG_MENUTITLE="Menú de opciones" +MSG_POWEROFF="Apagar el equipo" +MSG_SPEED="Velocidad" + +# Mensajes de descripción breve de las funciones de la API. +MSG_HELP_ogAclFilter="Extrae las acl de los ficheros de la diferencial" +MSG_HELP_ogAddCmd="Añade comandos al fichero creado por la función ogInstalMiniSetup." +MSG_HELP_ogAddRegistryKey="Añade una nueva clave al registro de Windows." +MSG_HELP_ogAddRegistryValue="Añade un nuevo valor al registro de Windows." +MSG_HELP_ogAddToLaunchDaemon="" +MSG_HELP_ogBoot="Arranca un sistema operativo instalado." +MSG_HELP_ogBootLoaderDeleteEntry=MSG_DONTUSE +MSG_HELP_ogBootLoaderHidePartitions=MSG_DONTUSE +MSG_HELP_ogBootMbrGeneric="" +MSG_HELP_ogBootMbrXP="" +MSG_HELP_ogBurgDefaultEntry="Configura la entrada por defecto de Burg." +MSG_HELP_ogBurgDeleteEntry="Borra en el Burg del MBR las entradas para el inicio en una particion." +MSG_HELP_ogBurgHidePartitions="Configura el Burg del MBR para que oculte las particiones de windows que no se esten iniciando. Permite definir una partición que no se ocultará (ej: para datos)." +MSG_HELP_ogBurgInstallMbr="Instal·la el carregador d'arrencada BURG al MBR del primer disc dur" +MSG_HELP_ogBurgOgliveDefaultEntry="Configura la entrada de ogLive como la entrada por defecto de Burg." +MSG_HELP_ogCalculateChecksum="Calcula la suma de comprobación (checksum) de un fichero." +MSG_HELP_ogCalculateFullChecksum="" +MSG_HELP_ogChangeRepo="Cambia el repositorio para el recurso remoto images." +MSG_HELP_ogCheckFs="Comprueba la consistencia de un sistema de archivos." +MSG_HELP_ogCheckIpAddress="" +MSG_HELP_ogCheckProgram="" +MSG_HELP_ogCheckStringInGroup="" +MSG_HELP_ogCheckStringInReg="" +MSG_HELP_ogCheckSyncImage="Muestra el contenido de la imagen para comprobarla." +MSG_HELP_ogCleanLinuxDevices="" +MSG_HELP_ogCleanOs="Elimina los archivos que no son necesarios en el sistema operativo." +MSG_HELP_ogCompareChecksumFiles="Compara si coinciden las sumas de comprobación almacenadas de 2 ficheros." +MSG_HELP_ogConfigureFstab="" +MSG_HELP_ogConfigureOgagent="Configura el nuevo agente OGAgent para sistemas ooperativos." +MSG_HELP_ogCopyFile="Copia un fichero a otro almacenamiento." +MSG_HELP_ogCreateBootLoaderImage="" +MSG_HELP_ogCreateCache="Reserva espacio para la partición de caché al final del disco." +MSG_HELP_ogCreateDiskImage="Genera una imagen exacta de un disco completo." +MSG_HELP_ogCreateFileImage="Crea/Redimensiona el archivo de la imagen sincronizada" +MSG_HELP_ogCreateGptPartitions="" +MSG_HELP_ogCreateImage="Genera una imagen exacta de un sistema operativo instalado localmente." +MSG_HELP_ogCreateImageSyntax="" +MSG_HELP_ogCreateInfoImage="Crea informacion del contenido de la imagen" +MSG_HELP_ogCreateMbrImage="Genera una imagen del sector de arranque (MBR)." +MSG_HELP_ogCreatePartitions="Define la estructura de particiones de un disco." +MSG_HELP_ogCreatePartitionTable="Genera una tabla de particiones en caso de que no sea valida." +MSG_HELP_ogCreateTorrent="" +MSG_HELP_ogCopyEfiBootLoader="Copia el cargador de arranque desde la partición EFI a la de sistema." +MSG_HELP_ogDeleteCache="Elimina la partición de caché local." +MSG_HELP_ogDeleteFile="Borra un fichero de un espacio de almacenamiento." +MSG_HELP_ogDeletePartitionTable="Elimina la tabla de particiones del disco" +MSG_HELP_ogDeleteRegistryKey="Borra una clave vacía del registro de Windows." +MSG_HELP_ogDeleteRegistryValue="Borra un valor del registro de Windows." +MSG_HELP_ogDeleteTree="Borra un árbol de directorios de un espacio de almacenamiento." +MSG_HELP_ogDevToDisk="Devuelve el nº de orden de disco o de partición correspondiente al camino del fichero de dispositivo." +MSG_HELP_ogDiskToDev="Devuelve el camino del fichero de dispositivo correspondiente al nº de orden de disco o de partición." +MSG_HELP_ogDomainScript="" +MSG_HELP_ogEcho="" +MSG_HELP_ogExecAndLog="" +MSG_HELP_ogExtendFs="Extiende el tamaño de un sistema de archivo al máximo de su partición." +MSG_HELP_ogFindCache="Indica la partición reservada para caché local." +MSG_HELP_ogFixBootSector="" +MSG_HELP_ogFormatCache="Formatea (inicia) el sistema de caché local." +MSG_HELP_ogFormat="Formatea o reformatea un sistema de archivos." +MSG_HELP_ogFormatFs=MSG_HELP_ogFormat +MSG_HELP_ogGetArch="Devuelve el tipo de arquitectura del cliente." +MSG_HELP_ogGetCacheSize="Devuelve el tamaño de la partición de caché local." +MSG_HELP_ogGetCacheSpace="Devuelve el espacio máximo disponible que puede ser reservado para la partición de caché local." +MSG_HELP_ogGetCaller="" +MSG_HELP_ogGetDiskSize="Devuelve el tamaño del disco." +MSG_HELP_ogGetDiskType="Devuelve el mnemónico de tipo de disco." +MSG_HELP_ogGetFreeSize="" +MSG_HELP_ogGetFsSize="Devuelve el tamaño de un sistema de archivos." +MSG_HELP_ogGetFsType="Devuelve el mnemónico de tipo de sistema de archivos." +MSG_HELP_ogGetGroupDir="Devuelve el camino del directorio por defecto para el grupo del cliente." +MSG_HELP_ogGetGroupName="Devuelve el nombre del grupo al que pertenece el cliente." +MSG_HELP_ogGetHivePath="Devuelve el camino completo del fichero de una sección del registro de Windows." +MSG_HELP_ogGetHostname="Devuelve el nombre de la máquina local." +MSG_HELP_ogGetImageCompressor="Devuelve la herramienta de compresión de la imagen." +MSG_HELP_ogGetImageInfo="Muestra información sobre la imagen monolitica: clonacion:compresor:sistemaarchivos:tamañoKB." +MSG_HELP_ogGetImageProgram="Devuelve el programa usado para crear la imagen." +MSG_HELP_ogGetImageSize="Devuelve el tamaño de una imagen de sistema." +MSG_HELP_ogGetImageType="Devuelve el sistema de ficheros de la imagen." +MSG_HELP_ogGetIpAddress="Devuelve la dirección IP del cliente." +MSG_HELP_ogGetLastSector="Devuelve el último sector usable del disco o de una partición." +MSG_HELP_ogGetMacAddress="Devuelve la dirección Ethernet del cliente." +MSG_HELP_ogGetMountImageDir="Devuelve el directorio de montaje de una imagen." +MSG_HELP_ogGetMountPoint="Devuelve el directorio donde está montado un sistema de archivos local." +MSG_HELP_ogGetNetInterface="" +MSG_HELP_ogGetOsType="Devuelve el tipo de un sistema operativo instalado." +MSG_HELP_ogGetOsUuid="" +MSG_HELP_ogGetOsVersion="Devuelve el tipo y la versión de un sistema operativo instalado." +MSG_HELP_ogGetParentPath="Devuelve el camino completo del directorio padre de un fichero de sistema OpenGnsys." +MSG_HELP_ogGetPartitionActive="Indica cual es la partición marcada como activa en un disco." +MSG_HELP_ogGetPartitionId="Devuelve el identificador de tipo de una partición." +MSG_HELP_ogGetPartitionSize="Devuelve el tamaño de una partición." +MSG_HELP_ogGetPartitionsNumber="" +MSG_HELP_ogGetPartitionTableType="Devuelve el tipo de tabla de particiones del disco" +MSG_HELP_ogGetPartitionType="Devuelve el mnemónico de tipo de una partición." +MSG_HELP_ogGetPath="Devuelve el camino completo de un fichero de sistema OpenGnsys." +MSG_HELP_ogGetRegistryValue="Devuelve el dato de un valor del registro de Windows." +MSG_HELP_ogGetRepoIp="Devuelve la dirección IP del repositorio de datos." +MSG_HELP_ogGetSerialNumber="Devuelve el número de serie del cliente." +MSG_HELP_ogGetServerIp="Devuelve la dirección IP del servidor principal." +MSG_HELP_ogGetSizeParameters="Devuelve el tamaño de los datos de un sistema de ficheros, el espacio necesario para la imagen y si cabe en el repositorio elegido." +MSG_HELP_ogGetWindowsName="Devuelve el nombre del cliente guardado en el registro de Windows." +MSG_HELP_ogGrubAddOgLive="Incluye en el grub del MBR una entrada llamando al cliente de opengnsys." +MSG_HELP_ogGrubDefaultEntry="Configura la entrada por defecto de GRUB." +MSG_HELP_ogGrubDeleteEntry="Borra en el grub del MBR las entradas para el inicio en una particion." +MSG_HELP_ogGrubHidePartitions="Configura el grub del MBR para que oculte las particiones de windows que no se esten iniciando. Permite definir una partición que no se ocultará (ej: para datos)." +MSG_HELP_ogGrubInstallMbr="Instal·la el carregador d'arrencada GRUB al MBR del primer disc dur" +MSG_HELP_ogGrubInstallPartition="Instal·la el carregador d'arrencada BURG al BootSector" +MSG_HELP_ogGrubOgliveDefaultEntry="Configura la entrada de ogLive como la entrada por defecto de GRUB." +MSG_HELP_ogGrubSecurity="Configura usuario y clave para modificar las entradas del menu del Grub." +MSG_HELP_ogGrubUefiConf="Genera el fichero grub.cfg de la partición EFI." +MSG_HELP_ogHelp="Muestra mensajes de ayudas para las funciones." +MSG_HELP_ogHidePartition="Oculta una partición de Windows." +MSG_HELP_ogIdToType="Devuelve el mnemónico asociado al identificador de tipo de partición." +MSG_HELP_ogNvramActiveEntry="Configura a activa entrada del gestor de arranque (NVRAM)." +MSG_HELP_ogNvramAddEntry="Crea nueva entrada del gestor de arranque (NVRAM)." +MSG_HELP_ogNvramDeleteEntry="Borra entrada del gestor de arranque (NVRAM)." +MSG_HELP_ogNvramGetCurrent="Muestra la entrada del gestor de arranque (NVRAM) que ha iniciado el equipo." +MSG_HELP_ogNvramGetNext="Muestra la entrada del gestor de arranque (NVRAM) que se utilizará en el próximo arranque." +MSG_HELP_ogNvramGetOrder="Muestra el orden de las entradas del gestor de arranque (NVRAM)." +MSG_HELP_ogNvramGetTimeout="Muestra el tiempo de espera del gestor de arranque (NVRAM)." +MSG_HELP_ogNvramInactiveEntry="Configura a inactiva entrada del gestor de arranque (NVRAM)." +MSG_HELP_ogNvramList="Lista las entradas del gestor de arranque (NVRAN) marcando con un asterisco las activas" +MSG_HELP_ogNvramSetNext="Configura el próximo arranque con la entrada del gestor de arranque (NVRAM)." +MSG_HELP_ogNvramSetOrder="Configura el orden de las entradas del gestor de arranque (NVRAM)." +MSG_HELP_ogNvramSetTimeout="Configura el tiempo de espera del gestor de arranque (NVRAM)." +MSG_HELP_ogGetOsType="Devuelve el tipo de un sistema operativo instalado." +MSG_HELP_ogInstallFirstBoot="Crea un archivo que se ejecutará en el primer arranque de Windows." +MSG_HELP_ogInstallLaunchDaemon="Instala un archivo que se ejecutará en el arranque de macOS." +MSG_HELP_ogInstallLinuxClient=MSG_OBSOLETE +MSG_HELP_ogInstallMiniSetup="Instala un archivo que se ejecutará en el arranque de Windows." +MSG_HELP_ogInstallRunonce="Crea un archivo que se ejecutará en el inicio de un usuario administrador de Windows." +MSG_HELP_ogInstallWindowsClient=MSG_OBSOLETE +MSG_HELP_ogIsFormated="Comprueba si un sistema de archivos está formateado." +MSG_HELP_ogIsImageLocked="Comprueba si una imagen está bloqueada por una operación de uso exclusivo." +MSG_HELP_ogIsLocked="Comprueba si una partición o su disco están bloqueados por una operación de uso exclusivo." +MSG_HELP_ogIsDiskLocked="Comprueba si un disco está bloqueado por una operación de uso exclusivo." +MSG_HELP_ogIsMounted="Comprueba si un sistema de archivos está montado." +MSG_HELP_ogIsNewerFile="Comprueba si un fichero es más nuevo (se ha modificado después) que otro." +MSG_HELP_ogIsPartitionLocked=MSG_HELP_ogIsLocked +MSG_HELP_ogIsRepoLocked="" +MSG_HELP_ogIsSyncImage="Comprueba si la imagen es sincronizable." +MSG_HELP_ogIsVirtualMachine="" +MSG_HELP_ogIsWritable="Comprueba si un sistema de archivos está montado con permiso de escritura." +MSG_HELP_ogLinuxBootParameters="Devuelve los parámetros de arranque de un sistema operativo Linux instalado." +MSG_HELP_ogListHardwareInfo="Lista el inventario de dispositivos del cliente." +MSG_HELP_ogListLogicalPartitions="" +MSG_HELP_ogListPartitions="Lista la estructura de particiones de un disco." +MSG_HELP_ogListPrimaryPartitions="" +MSG_HELP_ogListRegistryKeys="Lista los nombres de las subclaves incluidas en una clave del registro de Windows." +MSG_HELP_ogListRegistryValues="Lista los nombres de los valores incluidos en una clave del registro de Windows." +MSG_HELP_ogListSoftware="Lista el inventario de programas instalados en un sistema operativo." +MSG_HELP_ogLock="Bloquea una partición para operación de uso exclusivo." +MSG_HELP_ogLockDisk="Bloquea un disco para operación de uso exclusivo." +MSG_HELP_ogLockImage="Bloquea una imagen para operación de uso exclusivo." +MSG_HELP_ogLockPartition=MSG_HELP_ogLock +MSG_HELP_ogMakeChecksumFile="Almacena la suma de comprobación de un fichero." +MSG_HELP_ogMakeDir="Crea un directorio para OpenGnsys." +MSG_HELP_ogMakeGroupDir="Crea el directorio de grupo (aula) en un repositorio." +MSG_HELP_ogMcastReceiverFile="" +MSG_HELP_ogMcastReceiverPartition="" +MSG_HELP_ogMcastRequest="" +MSG_HELP_ogMcastSendFile="" +MSG_HELP_ogMcastSendPartition="" +MSG_HELP_ogMcastSyntax="" +MSG_HELP_ogMountCache="Monta el sistema de archivos dedicado a caché local." +MSG_HELP_ogMountCdrom="Monta dispositivo óptico por defecto." +MSG_HELP_ogMountImage="Monta una imagen sincronizable" +MSG_HELP_ogMount="Monta un sistema de archivos y devuelve el punto de montaje." +MSG_HELP_ogMountFs=MSG_HELP_ogMount +MSG_HELP_ogNvramActiveEntry="Configura a activa entrada del gestor de arranque (NVRAM)." +MSG_HELP_ogNvramAddEntry="Crea nueva entrada del gestor de arranque (NVRAM)." +MSG_HELP_ogNvramDeleteEntry="Borra entrada del gestor de arranque (NVRAM)." +MSG_HELP_ogNvramGetCurrent="Muestra la entrada del gestor de arranque (NVRAM) que ha iniciado el equipo." +MSG_HELP_ogNvramGetNext="Muestra la entrada del gestor de arranque (NVRAM) que se utilizará en el próximo arranque." +MSG_HELP_ogNvramGetOrder="Muestra el orden de las entradas del gestor de arranque (NVRAM)." +MSG_HELP_ogNvramGetTimeout="Muestra el tiempo de espera del gestor de arranque (NVRAM)." +MSG_HELP_ogNvramInactiveEntry="Configura a inactiva entrada del gestor de arranque (NVRAM)." +MSG_HELP_ogNvramList="Lista las entradas del gestor de arranque (NVRAN) marcando con un asterisco las activas" +MSG_HELP_ogNvramPxeFirstEntry="Configura la tarjeta de red como primer arranque en la NVRAM." +MSG_HELP_ogNvramSetNext="Configura el próximo arranque con la entrada del gestor de arranque (NVRAM)." +MSG_HELP_ogNvramSetOrder="Configura el orden de las entradas del gestor de arranque (NVRAM)." +MSG_HELP_ogNvramSetTimeout="Configura el tiempo de espera del gestor de arranque (NVRAM)." +MSG_HELP_ogRaiseError="Muestra y registra mensajes de error y devuelve el código correspondiente." +MSG_HELP_ogReduceFs="Reduce el tamaño del sistema de archivos al mínimo ocupado por sus datos." +MSG_HELP_ogReduceImage="Reduce el tamaño de la imagen" +MSG_HELP_ogRefindDeleteEntry="Borra en rEFInd las entradas para el inicio en una particion." +MSG_HELP_ogRefindDefaultEntry="Configura la entrada por defecto de rEFInd." +MSG_HELP_ogRefindOgliveDefaultEntry="Configura la entrada de ogLive como la entrada por defecto de rEFInd." +MSG_HELP_ogRefindSetTheme="Asigna un tema al rEFInd." +MSG_HELP_ogRefindSetTimeOut="Define el tiempo (segundos) que se muestran las opciones de inicio de rEFInd." +MSG_HELP_ogRefindSetResolution="Define la resolución que usuará el thema del gestor de arranque rEFInd." +MSG_HELP_ogRefindInstall="Instala y configura el gestor rEFInd en la particion EFI" +MSG_HELP_ogRestoreAclImage="" +MSG_HELP_ogRestoreBootLoaderImage="" +MSG_HELP_ogRestoreDiskImage="Restaura una imagen de un disco completo." +MSG_HELP_ogRestoreEfiBootLoader="Copia el cargador de arranque de la partición de sistema a la partición EFI." +MSG_HELP_ogRestoreImage="Restaura una imagen de sistema operativo." +MSG_HELP_ogRestoreInfoImage="Restablece informacion del sistema: acl y enlaces simbolicos" +MSG_HELP_ogRestoreMbrImage="Restaura una imagen del sector de arranque (MBR)." +MSG_HELP_ogRestoreUuidPartitions="Restaura los uuid de las particiones y la tabla de particiones." +MSG_HELP_ogSaveImageInfo="Crea un fichero con la información de la imagen." +MSG_HELP_ogSetLinuxName="" +MSG_HELP_ogSetPartitionActive="Establece el número de partición activa de un disco." +MSG_HELP_ogSetPartitionId="Modifica el tipo de una partición física usando el mnemónico del tipo." +MSG_HELP_ogSetPartitionSize="Establece el tamaño de una partición." +MSG_HELP_ogSetPartitionType="Modifica el identificador de tipo de una partición física." +MSG_HELP_ogSetRegistryValue="Asigna un dato a un valor del registro de Windows." +MSG_HELP_ogSetWindowsName="Asigna el nombre del cliente en el registro de Windows." +MSG_HELP_ogSetWinlogonUser="Asigna el nombre de usuario por defecto para el gestor de entrada de Windows." +MSG_HELP_ogSyncCreate="Sincroniza los datos de la particion a la imagen" +MSG_HELP_ogSyncRestore="Sincroniza los datos de la imagen a la particion" +MSG_HELP_ogTorrentStart="" +MSG_HELP_ogTypeToId="Devuelve el identificador asociado al mnemónico de tipo de partición." +MSG_HELP_ogUcastReceiverPartition="" +MSG_HELP_ogUcastSendFile="" +MSG_HELP_ogUcastSendPartition="" +MSG_HELP_ogUcastSyntax="" +MSG_HELP_ogUnhidePartition="Hace visible una partición de Windows." +MSG_HELP_ogUninstallLinuxClient="Desinstala el cliente OpenGnSys en un sistema operativo Linux." +MSG_HELP_ogUninstallWindowsClient="Desinstala el cliente OpenGnSys en un sistema operativo Windows." +MSG_HELP_ogUnlock="Desbloquea una partición tras finalizar una operación de uso exclusivo." +MSG_HELP_ogUnlockDisk="Desbloquea un disco tras finalizar una operación de uso exclusivo." +MSG_HELP_ogUnlockImage="Desbloquea una imagen tras finalizar una operación de uso exclusivo." +MSG_HELP_ogUnlockPartition=MSG_HELP_ogUnlock +MSG_HELP_ogUnmountAll="Desmonta todos los sistemas de archivos." +MSG_HELP_ogUnmountCache="Desmonta el sistema de archivos de caché local." +MSG_HELP_ogUnmount="Desmonta un sistema de archivos." +MSG_HELP_ogUnmountImage="Desmonta la imagen" +MSG_HELP_ogUnmountFs=MSG_HELP_ogUnmount +MSG_HELP_ogUnsetDirtyBit="" +MSG_HELP_ogUpdateCacheIsNecesary="Comprueba si es necesario actualizar una archivo en la cache local." +MSG_HELP_ogUpdatePartitionTable="Actualiza informacion tabla particiones del disco" +MSG_HELP_ogUuidChange="Reemplaza el UUID de un sistema de ficheros." +MSG_HELP_ogWaitSyncImage="" +MSG_HELP_ogWindowsBootParameters="" +MSG_HELP_ogWindowsRegisterPartition="" + +# Scripts +MSG_HELP_configureOs="Post-configura de arranque del sistema" +MSG_HELP_createBaseImage="Genera imagen basica de la particion" +MSG_HELP_createDiffImage="Genera imagen diferencial de la particion respecto a la imagen basica" +MSG_HELP_installOfflineMode="Prepara el equipo cliente para el modo offline." +MSG_HELP_partclone2sync="Convierte imagen de partclone en imagen sincronizable." +MSG_HELP_restoreBaseImage="Restaura una imagen basica en una particion" +MSG_HELP_restoreDiffImage="Restaura una imagen diferencial en una particion" +MSG_HELP_updateCache="Realiza la actualizacion de la cache" + +# Mensajes de descripción breve de la interfaz. +MSG_INTERFACE_START="[START Interface] Ejecutar comando: " +MSG_INTERFACE_END="[END Interface] Comando terminado con este código: " + +# Mensajes de scripts. +MSG_SCRIPTS_START=" INICIO scripts : " +MSG_SCRIPTS_END=" FIN scripts: " +MSG_SCRIPTS_TASK_END="Fin de la tarea" + +MSG_SCRIPTS_TASK_SLEEP="Esperando para iniciar" +MSG_SCRIPTS_TASK_START="Iniciando" +MSG_SCRIPTS_TASK_ERR="Error" + +# Script createImage. +MSG_SCRIPTS_FILE_RENAME=" Renombrar fichero-imagen previo: " +MSG_SCRIPTS_CREATE_SIZE=" Calcular espacio (KB) requerido para almacenarlo y el disponible: " + +# Script updateCache. +MSG_SCRIPTS_UPDATECACHE_DOUPDATE="comprovar si es necessari actualitzar el fitxer imatge" +MSG_SCRIPTS_UPDATECACHE_CHECKSIZECACHE="Comprobar que el tamaño de la cache es mayor que el fichero a descargar." +# Script updateCache: para las imágenes sincronizadas tipo dir. +MSG_SCRIPTS_UPDATECACHE_CHECKSIZEDIR="Calculamos el tamaño de la imagen." +MSG_SCRIPTS_UPDATECACHE_CHECKSIZEIMG="Comprobamos si hay que la imagen del repositorio es mayor que la de la cache." +MSG_SCRIPTS_UPDATECACHE_IFNOTCACHEDO="Comprobar el espacio libre de la cache y actuar según engine.cfg" + +MSG_SCRIPTS_UPDATECACHE_CHECKMCASTSESSION="Comprobando sesion multicast: ServidorMcast:PuertoDatos" + +# interface sustituye temporalmente al scritp restore +MSG_SCRIPTS_CHECK_ENGINE="Analizar proceso a realizar según engine.cfg" +MSG_SCRIPTS_MULTICAST_PRECHECK_PORT="Determinar puerto principal y auxiliar multicast." +MSG_SCRIPTS_MULTICAST_CHECK_PORT="Comprobar puertos de sesion y datos" +MSG_SCRIPTS_MULTICAST_REQUEST_PORT="Solicitar la apertura: " +MSG_SCRIPTS_OS_CONFIGURE="Iniciar la configuracion del sistema restaurado" + +# TIME MESSAGES +MSG_SCRIPTS_TIME_TOTAL="tiempo total del proceso" +MSG_SCRIPTS_TIME_PARTIAL="tiempo parcial del subproceso" + +# HTTPLOG +MSG_HTTPLOG_NOUSE="No apague este ordenador por favor" + +# Mensajes sincronizadas +MSG_SYNC_RESIZE="Redimensiona la imagen al tamaño necesario" +MSG_SYNC_RESTORE="Trae el listado ficheros y baja la imagen" +MSG_SYNC_DELETE="Diferencial: Borra archivos antiguos" +MSG_SYNC_SLEEP="Espera que se monte/reduzca la imagen" +# Mensajes sincronizadas complementarios a errores +MSG_SYNC_DIFFERENTFS="El sistema de ficheros de destino no coincide con el de la imagen" +MSG_SYNC_EXTENSION="Las extensiones de la imagenes deben ser img o diff" +MSG_SYNC_NOCHECK="La imagen esta montada por otro proceso, no podemos comprobarla" + +MSG_RESTORE="Restaura la imagen en" + diff --git a/client/lib/engine/bin/lang_en_GB.py b/client/lib/engine/bin/lang_en_GB.py new file mode 100644 index 0000000..fbc9eee --- /dev/null +++ b/client/lib/engine/bin/lang_en_GB.py @@ -0,0 +1,387 @@ +#!/usr/bin/python3 + +# English language file. +#@version 1.1.0 +#@author Jose Miguel Hernandez - Universidad de Salamanca +#@date 2018-03-01 + +# Error messages. +MSG_ERR_GENERIC="Undefined unknown error" +MSG_ERR_FORMAT="Wrong execution format" +MSG_ERR_OUTOFLIMIT="Out of range or invalid value" +MSG_ERR_NOTFOUND="File or device not found" +MSG_ERR_PARTITION="Unknown or wrong partition" +MSG_ERR_LOCKED="Resource locked by exclusive use operation" +MSG_ERR_CACHE="Local cache error" +MSG_ERR_NOGPT="Current disk does not include GPT partition" +MSG_ERR_REPO="Failed when mounting images repository" +MSG_ERR_NOMSDOS="Current disk does not include MSDOS partition" +MSG_ERR_FILESYS="Unknown or unmountable file system" +MSG_ERR_NOTOS="Cannot detect or boot OS" +MSG_ERR_IMAGE="Cannot create or restore a system image" +MSG_ERR_IMAGEFILE="Image file corrupt or of other partclone version" +MSG_ERR_NOTEXEC="Non executable program or function" +MSG_ERR_NOTWRITE="Write access denied" +MSG_ERR_NOTCACHE="No client cache partition" +MSG_ERR_NOTUEFI="UEFI isn't active" +MSG_ERR_NOTBIOS="BIOS legacy isn't active" +MSG_ERR_CACHESIZE="Not enough space in local or remote cache" +MSG_ERR_REDUCEFS="Error when reducing file system" +MSG_ERR_EXTENDFS="Error when expanding file system" +MSG_ERR_IMGSIZEPARTITION="Backup error: Partition smaller than image" +MSG_ERR_UPDATECACHE="Error when running `updateCache´ command" +MSG_ERR_UCASTSYNTAXT="Error when generating Unicast transfer syntax" +MSG_ERR_UCASTSENDPARTITION="Error when sending a Unicast partition" +MSG_ERR_UCASTSENDFILE="Error when sending a Unicast file" +MSG_ERR_UCASTRECEIVERPARTITION="Error when receiving an Unicast partition" +MSG_ERR_UCASTRECEIVERFILE="Error when receiving an Unicast file" +MSG_ERR_MCASTSYNTAXT="Error when generating Multicast transfer syntax" +MSG_ERR_MCASTSENDFILE="Error when sending Multicast file" +MSG_ERR_MCASTRECEIVERFILE="Error when receiving Multicast file" +MSG_ERR_MCASTSENDPARTITION="Error when sending Multicast partition" +MSG_ERR_MCASTRECEIVERPARTITION="Error when receiving Multicast partition " +MSG_ERR_PROTOCOLJOINMASTER="Error when connecting Unicast/Multicast session to Master" +MSG_ERR_DONTFORMAT="Formatting Error" +MSG_ERR_DONTMOUNT_IMAGE="Error when mounting/reducing image" +MSG_ERR_DONTUNMOUNT_IMAGE="Error when unmounting image" +MSG_ERR_DONTSYNC_IMAGE="Unsynchronizable image" +MSG_ERR_NOTDIFFERENT="Basic image identical to partition" +MSG_ERR_SYNCHRONIZING="Synchronizing error, it may affect image creation/restoration process" + +# Warning messages. +MSG_DONTUSE="DO NOT USE" +MSG_DONTMOUNT="Unmounted file system" +MSG_DONTUNMOUNT="Cannot unmount file system or it isn't mounted" +MSG_MOUNT="File system already mounted" +MSG_MOUNTREADONLY="Read-only file system mounted" +MSG_OBSOLETE="OBSOLETE" + +# Auxiliary help messages. +MSG_64BIT="64-bit" +MSG_DISK="Disk" +MSG_ERROR="Error" +MSG_EXAMPLE="Example" +MSG_FORMAT="Format" +MSG_FUNCTION="Function" +MSG_HARDWAREINVENTORY="Hardware inventory" +MSG_IMAGE="Image" +MSG_INSTALLED="Installed" +MSG_NOCACHE="No local cache" +MSG_NOEXTENDED="No extended partition" +MSG_PARTITION="Partition" +MSG_PROTOCOL="Protocol" +MSG_RESERVEDVALUE="Reserved value" +MSG_SEE="See" +MSG_UNKNOWN="Unknown" +MSG_WARNING="Warning" + +# Boot process messages. +MSG_DETECTLVMRAID="Detecting LVM and RAID meta-devices." +MSG_ERRBOOTMODE=f"{MSG_ERROR}: Unknown boot mode." +MSG_LAUNCHCLIENT="Launching client browser." +MSG_LOADAPI="Loading cloning-engine functions." +MSG_LOADMODULES="Loading kernel modules." +MSG_MAKELINKS="Creating symbolic links." +MSG_MOUNTREPO="Mounting repository using %s by %s mode." +MSG_OFFLINEMODE="Off-line boot mode." +MSG_OTHERSERVICES="Starting client complementary services." +MSG_POWEROFFCONF="Defining power-saving parameters." + +# Default menu messages. +MSG_BOOT="Boot" +MSG_DUPLEX="Duplex" +MSG_HOSTNAME="Hostname" +MSG_IPADDR="IP Address" +MSG_MACADDR="MAC Address" +MSG_MENUTITLE="Options menu" +MSG_POWEROFF="Shutdown computer" +MSG_SPEED="Speed" + +# API functions messages. +MSG_HELP_ogAclFilter="Draws ACL files from differential image." +MSG_HELP_ogAddCmd="Adds commands to file created by ogInstalMiniSetup." +MSG_HELP_ogAddRegistryKey="Adds new Windows registry key." +MSG_HELP_ogAddRegistryValue="Adds new Windows registry value." +MSG_HELP_ogAddToLaunchDaemon="" +MSG_HELP_ogBoot="Boots installed OS." +MSG_HELP_ogBootLoaderDeleteEntry=MSG_DONTUSE +MSG_HELP_ogBootLoaderHidePartitions=MSG_DONTUSE +MSG_HELP_ogBootMbrGeneric="" +MSG_HELP_ogBootMbrXP="" +MSG_HELP_ogBurgDefaultEntry="Sets default Burg entry." +MSG_HELP_ogBurgDeleteEntry="Deletes partition start-entries from MBR BURG." +MSG_HELP_ogBurgHidePartitions="Sets MBR Burg to hide non starting windows partitions. Allows you to select a partition that will not be hidden (e.g. for data)." +MSG_HELP_ogBurgInstallMbr="Installs BURG boot-loader on 1st HD MBR." +MSG_HELP_ogBurgOgliveDefaultEntry="Sets ogLive input as default Burg input." +MSG_HELP_ogCalculateChecksum="Calculates file checksum." +MSG_HELP_ogCalculateFullChecksum="Calculates file full checksum" +MSG_HELP_ogChangeRepo="Changes repository for remote resource: images." +MSG_HELP_ogCheckFs="Checks file system consistence." +MSG_HELP_ogCheckIpAddress="" +MSG_HELP_ogCheckProgram="" +MSG_HELP_ogCheckStringInGroup="" +MSG_HELP_ogCheckStringInReg="" +MSG_HELP_ogCheckSyncImage="Displays image contents to check it." +MSG_HELP_ogCleanLinuxDevices="" +MSG_HELP_ogCleanOs="Deletes OS unnecessary files." +MSG_HELP_ogCompareChecksumFiles="Compares if the checksums match." +MSG_HELP_ogConfigureFstab="" +MSG_HELP_ogConfigureOgagent="Sets OS new agent: OGAgent." +MSG_HELP_ogCopyFile="Copies file to another storage unit ." +MSG_HELP_ogCreateBootLoaderImage="" +MSG_HELP_ogCreateCache="Saves space for cache partition at the end of disk." +MSG_HELP_ogCreateDiskImage="Creates exact image from local disk." +MSG_HELP_ogCreateFileImage="Creates/Resizes synchronized image file." +MSG_HELP_ogCreateGptPartitions="" +MSG_HELP_ogCreateImage="Creates exact image from local installed OS." +MSG_HELP_ogCreateImageSyntax="" +MSG_HELP_ogCreateInfoImage="Creates image content information." +MSG_HELP_ogCreateMbrImage="Creates MBR image." +MSG_HELP_ogCreatePartitions="Creates disk partition table." +MSG_HELP_ogCreatePartitionTable="Creates partition table, if necessary." +MSG_HELP_ogCreateTorrent="" +MSG_HELP_ogCopyEfiBootLoader="Copy the boot loader from the EFI partition to system partition." +MSG_HELP_ogDeleteCache="Deletes local cache partition." +MSG_HELP_ogDeleteFile="Deletes file from storage." +MSG_HELP_ogDeletePartitionTable="Deletes disk table partition" +MSG_HELP_ogDeleteRegistryKey="Deletes empty Windows registry key." +MSG_HELP_ogDeleteRegistryValue="Deletes Windows registry value." +MSG_HELP_ogDeleteTree="Deletes directory tree." +MSG_HELP_ogDevToDisk="Returns disk or partition ordinal number for device file path." +MSG_HELP_ogDiskToDev="Returns device file path for disk or partition ordinal number." +MSG_HELP_ogDomainScript="" +MSG_HELP_ogEcho="Displays and log messages." +MSG_HELP_ogExecAndLog="Runs and logs command" +MSG_HELP_ogExtendFs="Expands file system size to partition maximum." +MSG_HELP_ogFindCache="Shows local cache reserved partition." +MSG_HELP_ogFixBootSector="" +MSG_HELP_ogFormatCache="Formats (clears) local cache." +MSG_HELP_ogFormat="Formats file system." +MSG_HELP_ogFormatFs=MSG_HELP_ogFormat +MSG_HELP_ogGetArch="Returns client architecture." +MSG_HELP_ogGetCacheSize="Returns local cache partition size." +MSG_HELP_ogGetCacheSpace="Returns maximum available space that can be reserved for local cache partition." +MSG_HELP_ogGetCaller="Returns program or function which is calling to current one" +MSG_HELP_ogGetDiskSize="Returns disk size." +MSG_HELP_ogGetDiskType="Returns disk type." +MSG_HELP_ogGetFreeSize="" +MSG_HELP_ogGetFsSize="Returns file system size." +MSG_HELP_ogGetFsType="Returns file system type." +MSG_HELP_ogGetGroupDir="Returns default directory path for client group." +MSG_HELP_ogGetGroupName="Returns client group name." +MSG_HELP_ogGetHivePath="Returns full path of file from Windows registry section." +MSG_HELP_ogGetHostname="Returns local hostname." +MSG_HELP_ogGetImageCompressor="Returns image compression tool." +MSG_HELP_ogGetImageInfo="Displays monolithic image information: cloning; compressor; file system; size(KB)." +MSG_HELP_ogGetImageProgram="Returns used program to create image." +MSG_HELP_ogGetImageSize="Returns system image size." +MSG_HELP_ogGetImageType="Returns image file system." +MSG_HELP_ogGetIpAddress="Returns client IP." +MSG_HELP_ogGetLastSector="Returns last available sector from disk or partition." +MSG_HELP_ogGetMacAddress="Returns client Ethernet address." +MSG_HELP_ogGetMountImageDir="Returns mounting directory of image." +MSG_HELP_ogGetMountPoint="Returns directory of local file system mount point." +MSG_HELP_ogGetNetInterface="" +MSG_HELP_ogGetOsType="Returns installed OS type." +MSG_HELP_ogGetOsUuid="Returns OS UUID" +MSG_HELP_ogGetOsVersion="Returns OS version." +MSG_HELP_ogGetParentPath="Returns full path of OpenGnsys system file parent directory." +MSG_HELP_ogGetPartitionActive="Returns disk active partition." +MSG_HELP_ogGetPartitionId="Returns partition type ID." +MSG_HELP_ogGetPartitionSize="Returns partition size." +MSG_HELP_ogGetPartitionsNumber="Returns disk partitions number." +MSG_HELP_ogGetPartitionTableType="Returns disk partition table type." +MSG_HELP_ogGetPartitionType="Returns partition type." +MSG_HELP_ogGetPath="Returns full path of OpenGnsys system file." +MSG_HELP_ogGetRegistryValue="Returns data from Windows registry value." +MSG_HELP_ogGetRepoIp="Returns OpenGnsys Repository IP address ." +MSG_HELP_ogGetSerialNumber="Returns host serial number." +MSG_HELP_ogGetServerIp="Returns main OpenGnsys Server IP address." +MSG_HELP_ogGetSizeParameters="Returns file system data size, required space for image and if it fits in the chosen repository." +MSG_HELP_ogGetWindowsName="Returns saved client name on Windows registry." +MSG_HELP_ogGrubAddOgLive="Adds MBR grub an entry calling Opengnsys client." +MSG_HELP_ogGrubDefaultEntry="Sets GRUB default entry." +MSG_HELP_ogGrubDeleteEntry="Deletes partition start entries on MBR grub." +MSG_HELP_ogGrubHidePartitions="Sets MBR grub to hide non starting Windows partitions. Allows you to select a partition that will not be hidden (e.g. for data)." +MSG_HELP_ogGrubInstallMbr="Installs GRUB boot loader on 1st HD MBR" +MSG_HELP_ogGrubInstallPartition="Installs GRUB boot loader on BootSector" +MSG_HELP_ogGrubOgliveDefaultEntry="Sets ogLive entry as default GRUB entry." +MSG_HELP_ogGrubSecurity="Configures user and password for change the menu entries of grub." +MSG_HELP_ogGrubUefiConf="Generates the grub.cfg file of the EFI partition." +MSG_HELP_ogHelp="Shows functions help messages." +MSG_HELP_ogHidePartition="Hides Windows partition." +MSG_HELP_ogIdToType="Returns partition type identifier." +MSG_HELP_ogInstallFirstBoot="Creates file to run on first Windows boot." +MSG_HELP_ogInstallLaunchDaemon="Installs file to run on MACos boot." +MSG_HELP_ogInstallLinuxClient=MSG_OBSOLETE +MSG_HELP_ogInstallMiniSetup="Installs file to run on Windows boot." +MSG_HELP_ogInstallRunonce="Creates file to run on admin-user Windows boot." +MSG_HELP_ogInstallWindowsClient=MSG_OBSOLETE +MSG_HELP_ogIsFormated="Checks file system if formatted." +MSG_HELP_ogIsImageLocked="Checks image if blocked by exclusive use operation." +MSG_HELP_ogIsLocked="Checks partition or disk if blocked by exclusive use operation." +MSG_HELP_ogIsDiskLocked="Checks disk if blocked by exclusive use operation." +MSG_HELP_ogIsMounted="Checks file system if mounted." +MSG_HELP_ogIsNewerFile="Checks if one file is newer (or has been modified later) than another one." +MSG_HELP_ogIsPartitionLocked=MSG_HELP_ogIsLocked +MSG_HELP_ogIsRepoLocked="" +MSG_HELP_ogIsSyncImage="Checks image if synchronizable." +MSG_HELP_ogIsVirtualMachine="Checks if client is a virtual machine" +MSG_HELP_ogIsWritable="Checks if mounted file system has write permissions." +MSG_HELP_ogLinuxBootParameters="Returns installed Linux boot parameters." +MSG_HELP_ogListHardwareInfo="Lists the client hardware inventory." +MSG_HELP_ogListLogicalPartitions="Lists disk logic partitions." +MSG_HELP_ogListPartitions="Lists disk partitions table." +MSG_HELP_ogListPrimaryPartitions="Lists disk primary partitions" +MSG_HELP_ogListRegistryKeys="Lists sub-keys names included on a Windows registry key." +MSG_HELP_ogListRegistryValues="Lists value names included on a Windows registry key." +MSG_HELP_ogListSoftware="Lists OS installed programs inventory." +MSG_HELP_ogLock="Blocks partition for exclusive use operation." +MSG_HELP_ogLockDisk="Blocks disk for exclusive use operation." +MSG_HELP_ogLockImage="Blocks image for exclusive use operation." +MSG_HELP_ogLockPartition=MSG_HELP_ogLock +MSG_HELP_ogMakeChecksumFile="Stores file checksum." +MSG_HELP_ogMakeDir="Makes OpenGnsys directory." +MSG_HELP_ogMakeGroupDir="Makes group (lab) directory on repository." +MSG_HELP_ogMcastReceiverFile="" +MSG_HELP_ogMcastReceiverPartition="" +MSG_HELP_ogMcastRequest="" +MSG_HELP_ogMcastSendFile="" +MSG_HELP_ogMcastSendPartition="" +MSG_HELP_ogMcastSyntax="" +MSG_HELP_ogMountCache="Mounts cache file system." +MSG_HELP_ogMountCdrom="Mounts default optical drive." +MSG_HELP_ogMountImage="Mounts synchronizable image" +MSG_HELP_ogMount="Mounts file system and returns mount point." +MSG_HELP_ogMountFs=MSG_HELP_ogMount +MSG_HELP_ogNvramActiveEntry="Sets active a bootloader (NVRAM) entry." +MSG_HELP_ogNvramAddEntry="Creates new entry in bootloader (NVRAM)." +MSG_HELP_ogNvramDeleteEntry="Deletes a bootloader (NVRAM) entry." +MSG_HELP_ogNvramGetCurrent="Displays the bootloader (NVRAM) entry that was started by the computer." +MSG_HELP_ogNvramGetNext="Displays the bootloader (NVRAM) entry for the boot next." +MSG_HELP_ogNvramGetOrder="Displays the bootloader (NVRAM) entries order." +MSG_HELP_ogNvramGetTimeout="Displays the bootloader (NVRAM) timeout." +MSG_HELP_ogNvramInactiveEntry="Sets inactive bootloader (NVRAM) entry." +MSG_HELP_ogNvramList="Lists bootloader (NVRAM) entries, by staring actives ones." +MSG_HELP_ogNvramPxeFirstEntry="Set the network as the NVRAM first boot." +MSG_HELP_ogNvramSetNext="Set the bootloader (NVRAM) entry for the boot next." +MSG_HELP_ogNvramSetOrder="Sets the bootloader (NVRAM) entries order." +MSG_HELP_ogNvramSetTimeout="Sets the bootloader (NVRAM) timeout." +MSG_HELP_ogRaiseError="Displays and registers error messages and returns code." +MSG_HELP_ogReduceFs="Reduces file system size to minimum." +MSG_HELP_ogReduceImage="Reduces image size." +MSG_HELP_ogRefindDeleteEntry="Deletes the menu entry of a partition in rEFInd." +MSG_HELP_ogRefindDefaultEntry="Configures default menu entry in rEFInd." +MSG_HELP_ogRefindOgliveDefaultEntry="Configures ogLive menu entry as default menu entry in rEFInd." +MSG_HELP_ogRefindSetTheme="Configures rEFInd's theme." +MSG_HELP_ogRefindSetTimeOut="Defines the time that rEFInd shows the menu." +MSG_HELP_ogRefindSetResolution="Defines the resolucion of rEFInd's theme." +MSG_HELP_ogRefindInstall="Installs and configures rEFInd boot loader in ESP." +MSG_HELP_ogRestoreAclImage="Restores Windows ACL (Inf. must be on /tmp)." +MSG_HELP_ogRestoreBootLoaderImage="" +MSG_HELP_ogRestoreDiskImage="Restores disk image." +MSG_HELP_ogRestoreEfiBootLoader="Copy the boot loader from the system partition to the EFI partition." +MSG_HELP_ogRestoreImage="Restore OS image." +MSG_HELP_ogRestoreInfoImage="Restores system information: ACL and symbolic links" +MSG_HELP_ogRestoreMbrImage="Restores boot sector image (MBR)." +MSG_HELP_ogRestoreUuidPartitions="Restores UUID of partitions and partition table." +MSG_HELP_ogSaveImageInfo="Creates the image information file." +MSG_HELP_ogSetLinuxName="" +MSG_HELP_ogSetPartitionActive="Sets active partition number of disk." +MSG_HELP_ogSetPartitionId="Changes partition ID using mnemonic." +MSG_HELP_ogSetPartitionSize="Sets partition size." +MSG_HELP_ogSetPartitionType="Changes partition type ID." +MSG_HELP_ogSetRegistryValue="Assigns data to a Windows registry values." +MSG_HELP_ogSetWindowsName="Assigns client name to Windows registry." +MSG_HELP_ogSetWinlogonUser="Assigns Windows default user name to Windows input manager." +MSG_HELP_ogSyncCreate="Synchronizes partition data to image" +MSG_HELP_ogSyncRestore="Synchronize image data to partition" +MSG_HELP_ogTorrentStart="" +MSG_HELP_ogTypeToId="Returns the ID of partition type mnemonic." +MSG_HELP_ogUcastReceiverPartition="" +MSG_HELP_ogUcastSendFile="" +MSG_HELP_ogUcastSendPartition="" +MSG_HELP_ogUcastSyntax="" +MSG_HELP_ogUnhidePartition="Unhides Windows partition." +MSG_HELP_ogUninstallLinuxClient="Uninstalls old OpenGnSys agent from Linux OS." +MSG_HELP_ogUninstallWindowsClient="Uninstalls oldOpenGnSys agent from Windows OS." +MSG_HELP_ogUnlock="Unlocks partition after exclusive use operation." +MSG_HELP_ogUnlockDisk="Unlocks disk after exclusive use operation." +MSG_HELP_ogUnlockImage="Unlocks image after exclusive use operation." +MSG_HELP_ogUnlockPartition=MSG_HELP_ogUnlock +MSG_HELP_ogUnmountAll="Unmounts all file systems." +MSG_HELP_ogUnmountCache="Unmounts cache file system." +MSG_HELP_ogUnmountImage="Unmounts image" +MSG_HELP_ogUnmount="Unmounts file system." +MSG_HELP_ogUnmountFs=MSG_HELP_ogUnmount +MSG_HELP_ogUnsetDirtyBit="" +MSG_HELP_ogUpdateCacheIsNecesary="Checks if necessary file update in local cache." +MSG_HELP_ogUpdatePartitionTable="Updates disk partition table info " +MSG_HELP_ogUuidChange="Replaces the filesystem UUID" +MSG_HELP_ogWaitSyncImage="" +MSG_HELP_ogWindowsBootParameters="" +MSG_HELP_ogWindowsRegisterPartition="" + +# Scripts +MSG_HELP_configureOs="Post-configure system boot" +MSG_HELP_createBaseImage="Create partition basic image" +MSG_HELP_createDiffImage="Create partition differential image from basic image" +MSG_HELP_installOfflineMode="Prepare client for off-line mode." +MSG_HELP_partclone2sync="Turn part-clone image into synchronizable image." +MSG_HELP_restoreBaseImage="Restore basic image into partition" +MSG_HELP_restoreDiffImage="Restore differential image into partition" +MSG_HELP_updateCache="Update cache" + +# INTERFACE functions messages. +MSG_INTERFACE_START="[START Interface] Run command: " +MSG_INTERFACE_END="[END Interface] Command finished with this code: " + +# SCRIPTS messages. +MSG_SCRIPTS_START=" START scripts: " +MSG_SCRIPTS_END=" END scripts: " +MSG_SCRIPTS_TASK_END="End of task" + +MSG_SCRIPTS_TASK_SLEEP="Waiting to start" +MSG_SCRIPTS_TASK_START="Starting" +MSG_SCRIPTS_TASK_ERR="Error" + +# createImage script +MSG_SCRIPTS_FILE_RENAME="Rename previous image-file: " +MSG_SCRIPTS_CREATE_SIZE="Check required and available storing space(KB): " + +# updateCache script +MSG_SCRIPTS_UPDATECACHE_DOUPDATE="Check if it is necessary to update image file" +MSG_SCRIPTS_UPDATECACHE_CHECKSIZECACHE="Check if Cache size is bigger than image file size." +# Script updateCache: for dir synchronized images . +MSG_SCRIPTS_UPDATECACHE_CHECKSIZEDIR="Calculate image size." +MSG_SCRIPTS_UPDATECACHE_CHECKSIZEIMG="Check if repository image file size is bigger than Cache size." +MSG_SCRIPTS_UPDATECACHE_IFNOTCACHEDO="Check free Cache and apply engine.cfg" + +MSG_SCRIPTS_UPDATECACHE_CHECKMCASTSESSION="Checking Multicast Session McastServer:DataPort" + +# interface temporarily replaces restore script +MSG_SCRIPTS_CHECK_ENGINE="Analyze process to carry out according to engine.cfg" +MSG_SCRIPTS_MULTICAST_PRECHECK_PORT="Check main and auxiliary Multicast port." +MSG_SCRIPTS_MULTICAST_CHECK_PORT="Check session and data ports" +MSG_SCRIPTS_MULTICAST_REQUEST_PORT="Request Multicast port opening: " +MSG_SCRIPTS_OS_CONFIGURE="Start restored system setting" + +# TIME MESSAGES +MSG_SCRIPTS_TIME_TOTAL="Total process time" +MSG_SCRIPTS_TIME_PARTIAL="Partial sub-process time" + +# HTTPLOG +MSG_HTTPLOG_NOUSE="PLEASE DO NOT TURN OFF THIS COMPUTER" + +# Messages for synchronized images (complementary to errors) +MSG_SYNC_RESIZE="Resize image to necessary size" +MSG_SYNC_RESTORE="Get files list and download image" +MSG_SYNC_DELETE="Differential: Delete old files" +MSG_SYNC_SLEEP="Wait for mounting/reducing image" +# Messages for synchronized images (complementary to errors) +MSG_SYNC_DIFFERENTFS="Destination file system does not match image" +MSG_SYNC_EXTENSION="Image extension must be img or diff" +MSG_SYNC_NOCHECK="Image mounted by another process. Cannot verify it" + +MSG_RESTORE="Restore image on " + diff --git a/client/lib/engine/bin/lang_es_ES.py b/client/lib/engine/bin/lang_es_ES.py new file mode 100644 index 0000000..1687e99 --- /dev/null +++ b/client/lib/engine/bin/lang_es_ES.py @@ -0,0 +1,387 @@ +#!/usr/bin/python3 + +# Fichero de idioma: español. +#@version 1.1.1 +#@author + + +# Mensajes de error. +MSG_ERR_GENERIC="Error imprevisto no definido" +MSG_ERR_FORMAT="Formato de ejecución incorrecto" +MSG_ERR_OUTOFLIMIT="Valor fuera de rango o no válido" +MSG_ERR_NOTFOUND="Fichero o dispositivo no encontrado" +MSG_ERR_PARTITION="Partición errónea o desconocida" +MSG_ERR_LOCKED="Recurso bloqueado por operación de uso exclusivo" +MSG_ERR_CACHE="Error en partición de caché local" +MSG_ERR_NOGPT="El disco indicado no contiene una partición GPT" +MSG_ERR_REPO="Error al montar el repositorio de imágenes" +MSG_ERR_NOMSDOS="El disco indicado no contiene una partición MSDOS" +MSG_ERR_FILESYS="Sistema de archivos desconocido o no se puede montar" +MSG_ERR_NOTOS="Sistema operativo no detectado o no se puede iniciar" +MSG_ERR_IMAGE="No se puede crear o restaurar una image de sistema" +MSG_ERR_IMAGEFILE="Archivo de imagen corrupto o de otra versión de partclone" +MSG_ERR_NOTEXEC="Programa o función no ejecutable" +MSG_ERR_NOTWRITE="No hay acceso de escritura" +MSG_ERR_NOTCACHE="No existe partición caché en el cliente" +MSG_ERR_NOTUEFI="La interfaz UEFI no está activa" +MSG_ERR_NOTBIOS="La interfaz BIOS Legacy no está activa" +MSG_ERR_CACHESIZE="El espacio de la caché local o remota no es suficiente" +MSG_ERR_REDUCEFS="Error al reducir el sistema de archivos" +MSG_ERR_EXTENDFS="Error al expandir el sistema de archivos" +MSG_ERR_IMGSIZEPARTITION="Error al restaurar: Partición mas pequeña que la imagen" +MSG_ERR_UPDATECACHE="Error al realizar el comando updateCache" +MSG_ERR_UCASTSYNTAXT="Error en la generación de sintaxis de transferenica Unicast" +MSG_ERR_UCASTSENDPARTITION="Error en envío Unicast de una partición" +MSG_ERR_UCASTSENDFILE="Error en envío Unicast de un fichero" +MSG_ERR_UCASTRECEIVERPARTITION="Error en la recepción Unicast de una partición" +MSG_ERR_UCASTRECEIVERFILE="Error en la recepción Unicast de un fichero" +MSG_ERR_MCASTSYNTAXT="Error en la generación de sintaxis de transferenica Multicast" +MSG_ERR_MCASTSENDFILE="Error en envío Multicast de un fichero" +MSG_ERR_MCASTRECEIVERFILE="Error en la recepción Multicast de un fichero" +MSG_ERR_MCASTSENDPARTITION="Error en envío Multicast de una partición" +MSG_ERR_MCASTRECEIVERPARTITION="Error en la recepción Multicast de un fichero" +MSG_ERR_PROTOCOLJOINMASTER="Error en la conexión de una sesión Unicast|Multicast con el Master" +MSG_ERR_DONTFORMAT="Error al formatear" +MSG_ERR_DONTMOUNT_IMAGE="Error al montar/reducir la imagen" +MSG_ERR_DONTUNMOUNT_IMAGE="Error al desmontar la imagen" +MSG_ERR_DONTSYNC_IMAGE="Imagen no sincronizable" +MSG_ERR_NOTDIFFERENT="No se detectan diferencias entre la imagen básica y la partición" +MSG_ERR_SYNCHRONIZING="Error al sincronizar, puede afectar la creacion|restauracion de la imagen" + +# Mensajes de avisos. +MSG_DONTMOUNT="Sistema de archivos no montado" +MSG_DONTUSE="NO USAR" +MSG_DONTUNMOUNT="El sistema de archivos no se puede desmontar o no está montado" +MSG_MOUNT="Sistema de archivos montado" +MSG_MOUNTREADONLY="Sistema de archivos montado solo de lectura" +MSG_OBSOLETE="EN DESUSO" + +# Mensajes complementarios para las ayudas. +MSG_64BIT="64 bits" +MSG_DISK="disco" +MSG_ERROR="Error" +MSG_EXAMPLE="Ejemplo" +MSG_FORMAT="Formato" +MSG_FUNCTION="Función" +MSG_HARDWAREINVENTORY="Inventario de hardware de la máquina" +MSG_IMAGE="imagen" +MSG_INSTALLED="instalado" +MSG_NOCACHE="sin caché local" +MSG_NOEXTENDED="sin partición extendida" +MSG_PARTITION="partición" +MSG_PROTOCOL="protocolo" +MSG_RESERVEDVALUE="Valor reservado" +MSG_SEE="Ver" +MSG_UNKNOWN="Desconocido" +MSG_WARNING="Aviso" + +# Mensajes del proceso de arranque. +MSG_DETECTLVMRAID="Detectar metadispositivos LVM y RAID." +MSG_ERRBOOTMODE=f"{MSG_ERROR}: Modo de arranque desconocido." +MSG_LAUNCHCLIENT="Ejecutar cliente." +MSG_LOADAPI="Cargar funciones del motor de clonación." +MSG_LOADMODULES="Cargar módulos del kernel." +MSG_MAKELINKS="Crear enlaces simbólicos." +MSG_MOUNTREPO="Montar repositorio por %s en modo %s." +MSG_OFFLINEMODE="Modo de arranque sin conexión." +MSG_OTHERSERVICES="Iniciar servicios complementarios del cliente." +MSG_POWEROFFCONF="Definir parámetros de ahorro de energía." + +# Mensajes del menú por defecto. +MSG_BOOT="Iniciar" +MSG_DUPLEX="Dúplex" +MSG_HOSTNAME="Equipo" +MSG_IPADDR="Dirección IP" +MSG_MACADDR="Dirección MAC" +MSG_MENUTITLE="Menú de opciones" +MSG_POWEROFF="Apagar el equipo" +MSG_SPEED="Velocidad" + +# Mensajes de descripción breve de las funciones de la API. +MSG_HELP_ogAclFilter="Extrae las acl de los ficheros de la diferencial" +MSG_HELP_ogAddCmd="Añade comandos al fichero creado por la función ogInstalMiniSetup." +MSG_HELP_ogAddRegistryKey="Añade una nueva clave al registro de Windows." +MSG_HELP_ogAddRegistryValue="Añade un nuevo valor al registro de Windows." +MSG_HELP_ogAddToLaunchDaemon="" +MSG_HELP_ogBoot="Arranca un sistema operativo instalado." +MSG_HELP_ogBootLoaderDeleteEntry=MSG_DONTUSE +MSG_HELP_ogBootLoaderHidePartitions=MSG_DONTUSE +MSG_HELP_ogBootMbrGeneric="" +MSG_HELP_ogBootMbrXP="" +MSG_HELP_ogBurgDefaultEntry="Configura la entrada por defecto de Burg." +MSG_HELP_ogBurgDeleteEntry="Borra en el Burg del MBR las entradas para el inicio en una particion." +MSG_HELP_ogBurgHidePartitions="Configura el Burg del MBR para que oculte las particiones de windows que no se esten iniciando. Permite definir una partición que no se ocultará (ej: para datos)." +MSG_HELP_ogBurgInstallMbr="Instala el gestor de arranque BURG en el MBR del primer disco duro" +MSG_HELP_ogBurgOgliveDefaultEntry="Configura la entrada de ogLive como la entrada por defecto de Burg." +MSG_HELP_ogCalculateChecksum="Calcula la suma de comprobación (checksum) de un fichero." +MSG_HELP_ogCalculateFullChecksum="Calcula la suma de comprobación completa de un fichero." +MSG_HELP_ogChangeRepo="Cambia el repositorio para el recurso remoto images." +MSG_HELP_ogCheckFs="Comprueba la consistencia de un sistema de archivos." +MSG_HELP_ogCheckIpAddress="" +MSG_HELP_ogCheckProgram="" +MSG_HELP_ogCheckStringInGroup="" +MSG_HELP_ogCheckStringInReg="" +MSG_HELP_ogCheckSyncImage="Muestra el contenido de la imagen para comprobarla." +MSG_HELP_ogCleanLinuxDevices="" +MSG_HELP_ogCleanOs="Elimina los archivos que no son necesarios en el sistema operativo." +MSG_HELP_ogCompareChecksumFiles="Compara si coinciden las sumas de comprobación almacenadas de 2 ficheros." +MSG_HELP_ogConfigureFstab="" +MSG_HELP_ogConfigureOgagent="Configura el nuevo agente OGAgent para sistemas operativos." +MSG_HELP_ogCopyFile="Copia un fichero a otro almacenamiento." +MSG_HELP_ogCreateBootLoaderImage="" +MSG_HELP_ogCreateCache="Reserva espacio para la partición de caché al final del disco." +MSG_HELP_ogCreateDiskImage="Genera una imagen exacta de un disco completo." +MSG_HELP_ogCreateFileImage="Crea/redimensiona el archivo de la imagen sincronizada" +MSG_HELP_ogCreateGptPartitions="" +MSG_HELP_ogCreateImage="Genera una imagen exacta de un sistema operativo instalado localmente." +MSG_HELP_ogCreateImageSyntax="" +MSG_HELP_ogCreateInfoImage="Crea información del contenido de la imagen" +MSG_HELP_ogCreateMbrImage="Genera una imagen del sector de arranque (MBR)." +MSG_HELP_ogCreatePartitions="Define la estructura de particiones de un disco." +MSG_HELP_ogCreatePartitionTable="Genera una tabla de particiones en caso de que no sea valida." +MSG_HELP_ogCreateTorrent="" +MSG_HELP_ogCopyEfiBootLoader="Copia el cargador de arranque desde la partición EFI a la de sistema." +MSG_HELP_ogDeleteCache="Elimina la partición de caché local." +MSG_HELP_ogDeleteFile="Borra un fichero de un espacio de almacenamiento." +MSG_HELP_ogDeletePartitionTable="Elimina la tabla de particiones del disco" +MSG_HELP_ogDeleteRegistryKey="Borra una clave vacía del registro de Windows." +MSG_HELP_ogDeleteRegistryValue="Borra un valor del registro de Windows." +MSG_HELP_ogDeleteTree="Borra un árbol de directorios de un espacio de almacenamiento." +MSG_HELP_ogDevToDisk="Devuelve el nº de orden de disco o de partición correspondiente al camino del fichero de dispositivo." +MSG_HELP_ogDiskToDev="Devuelve el camino del fichero de dispositivo correspondiente al nº de orden de disco o de partición." +MSG_HELP_ogDomainScript="" +MSG_HELP_ogEcho="Muestra un mensaje en pantalla y permite registrarlo en fichero de log" +MSG_HELP_ogExecAndLog="Ejecuta un comando y registra su salida en fichero de log" +MSG_HELP_ogExtendFs="Extiende el tamaño de un sistema de archivo al máximo de su partición." +MSG_HELP_ogFindCache="Indica la partición reservada para caché local." +MSG_HELP_ogFixBootSector="" +MSG_HELP_ogFormatCache="Formatea (inicia) el sistema de caché local." +MSG_HELP_ogFormat="Formatea o reformatea un sistema de archivos." +MSG_HELP_ogFormatFs=MSG_HELP_ogFormat +MSG_HELP_ogGetArch="Devuelve el tipo de arquitectura del cliente." +MSG_HELP_ogGetCacheSize="Devuelve el tamaño de la partición de caché local." +MSG_HELP_ogGetCacheSpace="Devuelve el espacio máximo disponible que puede ser reservado para la partición de caché local." +MSG_HELP_ogGetCaller="Devuelve el programa o función que llama al actual" +MSG_HELP_ogGetDiskSize="Devuelve el tamaño del disco." +MSG_HELP_ogGetDiskType="Devuelve el mnemónico de tipo de disco." +MSG_HELP_ogGetFreeSize="" +MSG_HELP_ogGetFsSize="Devuelve el tamaño de un sistema de archivos." +MSG_HELP_ogGetFsType="Devuelve el mnemónico de tipo de sistema de archivos." +MSG_HELP_ogGetGroupDir="Devuelve el camino del directorio por defecto para el grupo del cliente." +MSG_HELP_ogGetGroupName="Devuelve el nombre del grupo al que pertenece el cliente." +MSG_HELP_ogGetHivePath="Devuelve el camino completo del fichero de una sección del registro de Windows." +MSG_HELP_ogGetHostname="Devuelve el nombre de la máquina local." +MSG_HELP_ogGetImageCompressor="Devuelve la herramienta de compresión de la imagen." +MSG_HELP_ogGetImageInfo="Muestra información sobre la imagen monolitica: clonacion:compresor:sistemaarchivos:tamañoKB." +MSG_HELP_ogGetImageProgram="Devuelve el programa usado para crear la imagen." +MSG_HELP_ogGetImageSize="Devuelve el tamaño de una imagen de sistema." +MSG_HELP_ogGetImageType="Devuelve el sistema de ficheros de la imagen." +MSG_HELP_ogGetIpAddress="Devuelve la dirección IP del cliente." +MSG_HELP_ogGetLastSector="Devuelve el último sector usable del disco o de una partición." +MSG_HELP_ogGetMacAddress="Devuelve la dirección Ethernet del cliente." +MSG_HELP_ogGetMountImageDir="Devuelve el directorio de montaje de una imagen." +MSG_HELP_ogGetMountPoint="Devuelve el directorio donde está montado un sistema de archivos local." +MSG_HELP_ogGetNetInterface="" +MSG_HELP_ogGetOsType="Devuelve el tipo de un sistema operativo instalado." +MSG_HELP_ogGetOsUuid="Devuelve el UUID de un sistema operativo" +MSG_HELP_ogGetOsVersion="Devuelve el tipo y la versión de un sistema operativo instalado." +MSG_HELP_ogGetParentPath="Devuelve el camino completo del directorio padre de un fichero de sistema OpenGnsys." +MSG_HELP_ogGetPartitionActive="Indica cual es la partición marcada como activa en un disco." +MSG_HELP_ogGetPartitionId="Devuelve el identificador de tipo de una partición." +MSG_HELP_ogGetPartitionSize="Devuelve el tamaño de una partición." +MSG_HELP_ogGetPartitionsNumber="Devuelve el número de particiones de un disco" +MSG_HELP_ogGetPartitionTableType="Devuelve el tipo de tabla de particiones del disco" +MSG_HELP_ogGetPartitionType="Devuelve el mnemónico de tipo de una partición." +MSG_HELP_ogGetPath="Devuelve el camino completo de un fichero de sistema OpenGnsys." +MSG_HELP_ogGetRegistryValue="Devuelve el dato de un valor del registro de Windows." +MSG_HELP_ogGetRepoIp="Devuelve la dirección IP del repositorio de datos." +MSG_HELP_ogGetSerialNumber="Devuelve el número de serie del equipo" +MSG_HELP_ogGetServerIp="Devuelve la dirección IP del servidor principal." +MSG_HELP_ogGetSizeParameters="Devuelve el tamaño de los datos de un sistema de ficheros, el espacio necesario para la imagen y si cabe en el repositorio elegido." +MSG_HELP_ogGetWindowsName="Devuelve el nombre del cliente guardado en el registro de Windows." +MSG_HELP_ogGrubAddOgLive="Incluye en el grub del MBR una entrada llamando al cliente de opengnsys." +MSG_HELP_ogGrubDefaultEntry="Configura la entrada por defecto de GRUB." +MSG_HELP_ogGrubDeleteEntry="Borra en el grub del MBR las entradas para el inicio en una particion." +MSG_HELP_ogGrubHidePartitions="Configura el grub del MBR para que oculte las particiones de windows que no se esten iniciando. Permite definir una partición que no se ocultará (ej: para datos)." +MSG_HELP_ogGrubInstallMbr="Instala el gestor de arranque GRUB en el MBR del primer disco duro" +MSG_HELP_ogGrubInstallPartition="Instala el gestor de arranque GRUB en el BootSector" +MSG_HELP_ogGrubOgliveDefaultEntry="Configura la entrada de ogLive como la entrada por defecto de GRUB." +MSG_HELP_ogGrubSecurity="Configura usuario y clave para modificar las entradas del menu del Grub." +MSG_HELP_ogGrubUefiConf="Genera el fichero grub.cfg de la partición EFI." +MSG_HELP_ogHelp="Muestra mensajes de ayudas para las funciones." +MSG_HELP_ogHidePartition="Oculta una partición de Windows." +MSG_HELP_ogIdToType="Devuelve el mnemónico asociado al identificador de tipo de partición." +MSG_HELP_ogInstallFirstBoot="Crea un archivo que se ejecutará en el primer arranque de Windows." +MSG_HELP_ogInstallLaunchDaemon="Instala un archivo que se ejecutará en el arranque de macOS." +MSG_HELP_ogInstallLinuxClient=MSG_OBSOLETE +MSG_HELP_ogInstallMiniSetup="Instala un archivo que se ejecutará en el arranque de Windows." +MSG_HELP_ogInstallRunonce="Crea archivo que se ejecutará en el inicio de un usuario administrador de Windows." +MSG_HELP_ogInstallWindowsClient=MSG_OBSOLETE +MSG_HELP_ogIsFormated="Comprueba si un sistema de archivos está formateado." +MSG_HELP_ogIsImageLocked="Comprueba si una imagen está bloqueada por una operación de uso exclusivo." +MSG_HELP_ogIsLocked="Comprueba si una partición o su disco están bloqueados por una operación de uso exclusivo." +MSG_HELP_ogIsDiskLocked="Comprueba si un disco está bloqueado por una operación de uso exclusivo." +MSG_HELP_ogIsMounted="Comprueba si un sistema de archivos está montado." +MSG_HELP_ogIsNewerFile="Comprueba si un fichero es más nuevo (se ha modificado después) que otro." +MSG_HELP_ogIsPartitionLocked=MSG_HELP_ogIsLocked +MSG_HELP_ogIsRepoLocked="" +MSG_HELP_ogIsSyncImage="Comprueba si la imagen es sincronizable." +MSG_HELP_ogIsVirtualMachine="Comprueba si el cliente es una máquina virtual" +MSG_HELP_ogIsWritable="Comprueba si un sistema de archivos está montado con permiso de escritura." +MSG_HELP_ogLinuxBootParameters="Devuelve los parámetros de arranque de un sistema operativo Linux instalado." +MSG_HELP_ogListHardwareInfo="Lista el inventario de dispositivos del cliente." +MSG_HELP_ogListLogicalPartitions="Lista las particiones lógicas de un disco" +MSG_HELP_ogListPartitions="Lista la estructura de particiones de un disco." +MSG_HELP_ogListPrimaryPartitions="Lista las particiones primarias de un disco" +MSG_HELP_ogListRegistryKeys="Lista los nombres de las subclaves incluidas en una clave del registro de Windows." +MSG_HELP_ogListRegistryValues="Lista los nombres de los valores incluidos en una clave del registro de Windows." +MSG_HELP_ogListSoftware="Lista el inventario de programas instalados en un sistema operativo." +MSG_HELP_ogLock="Bloquea una partición para operación de uso exclusivo." +MSG_HELP_ogLockDisk="Bloquea un disco para operación de uso exclusivo." +MSG_HELP_ogLockImage="Bloquea una imagen para operación de uso exclusivo." +MSG_HELP_ogLockPartition=MSG_HELP_ogLock +MSG_HELP_ogMakeChecksumFile="Almacena la suma de comprobación de un fichero." +MSG_HELP_ogMakeDir="Crea un directorio para OpenGnsys." +MSG_HELP_ogMakeGroupDir="Crea el directorio de grupo (aula) en un repositorio." +MSG_HELP_ogMcastReceiverFile="" +MSG_HELP_ogMcastReceiverPartition="" +MSG_HELP_ogMcastRequest="" +MSG_HELP_ogMcastSendFile="" +MSG_HELP_ogMcastSendPartition="" +MSG_HELP_ogMcastSyntax="" +MSG_HELP_ogMountCache="Monta el sistema de archivos dedicado a caché local." +MSG_HELP_ogMountCdrom="Monta dispositivo óptico por defecto." +MSG_HELP_ogMountImage="Monta una imagen sincronizable" +MSG_HELP_ogMount="Monta un sistema de archivos y devuelve el punto de montaje." +MSG_HELP_ogMountFs=MSG_HELP_ogMount +MSG_HELP_ogNvramActiveEntry="Configura a activa entrada del gestor de arranque (NVRAM)." +MSG_HELP_ogNvramAddEntry="Crea nueva entrada del gestor de arranque (NVRAM)." +MSG_HELP_ogNvramDeleteEntry="Borra entrada del gestor de arranque (NVRAM)." +MSG_HELP_ogNvramGetCurrent="Muestra la entrada del gestor de arranque (NVRAM) que ha iniciado el equipo." +MSG_HELP_ogNvramGetNext="Muestra la entrada del gestor de arranque (NVRAM) que se utilizará en el próximo arranque." +MSG_HELP_ogNvramGetOrder="Muestra el orden de las entradas del gestor de arranque (NVRAM)." +MSG_HELP_ogNvramGetTimeout="Muestra el tiempo de espera del gestor de arranque (NVRAM)." +MSG_HELP_ogNvramInactiveEntry="Configura a inactiva entrada del gestor de arranque (NVRAM)." +MSG_HELP_ogNvramList="Lista las entradas del gestor de arranque (NVRAN) marcando con un asterisco las activas" +MSG_HELP_ogNvramPxeFirstEntry="Configura la tarjeta de red como primer arranque en la NVRAM." +MSG_HELP_ogNvramSetNext="Configura el próximo arranque con la entrada del gestor de arranque (NVRAM)." +MSG_HELP_ogNvramSetOrder="Configura el orden de las entradas del gestor de arranque (NVRAM)." +MSG_HELP_ogNvramSetTimeout="Configura el tiempo de espera del gestor de arranque (NVRAM)." +MSG_HELP_ogRaiseError="Muestra y registra mensajes de error y devuelve el código correspondiente." +MSG_HELP_ogReduceFs="Reduce el tamaño del sistema de archivos al mínimo ocupado por sus datos." +MSG_HELP_ogReduceImage="Reduce el tamaño de la imagen" +MSG_HELP_ogRefindDeleteEntry="Borra en rEFInd las entradas para el inicio en una particion." +MSG_HELP_ogRefindDefaultEntry="Configura la entrada por defecto de rEFInd." +MSG_HELP_ogRefindOgliveDefaultEntry="Configura la entrada de ogLive como la entrada por defecto de rEFInd." +MSG_HELP_ogRefindSetTheme="Asigna un tema al rEFInd." +MSG_HELP_ogRefindSetTimeOut="Define el tiempo (segundos) que se muestran las opciones de inicio de rEFInd." +MSG_HELP_ogRefindSetResolution="Define la resolución que usuará el thema del gestor de arranque rEFInd." +MSG_HELP_ogRefindInstall="Instala y configura el gestor rEFInd en la particion EFI" +MSG_HELP_ogRestoreAclImage="Restaura las ACL de Windows (La informacion debe estar copiada en /tmp)." +MSG_HELP_ogRestoreBootLoaderImage="" +MSG_HELP_ogRestoreDiskImage="Restaura una imagen de un disco completo." +MSG_HELP_ogRestoreEfiBootLoader="Copia el cargador de arranque de la partición de sistema a la partición EFI." +MSG_HELP_ogRestoreImage="Restaura una imagen de sistema operativo." +MSG_HELP_ogRestoreInfoImage="Restablece información del sistema: ACL y enlaces simbolicos" +MSG_HELP_ogRestoreMbrImage="Restaura una imagen del sector de arranque (MBR)." +MSG_HELP_ogRestoreUuidPartitions="Restaura los uuid de las particiones y la tabla de particiones." +MSG_HELP_ogSaveImageInfo="Crea un fichero con la información de la imagen." +MSG_HELP_ogSetLinuxName="" +MSG_HELP_ogSetPartitionActive="Establece el número de partición activa de un disco." +MSG_HELP_ogSetPartitionId="Modifica el tipo de una partición física usando el mnemónico del tipo." +MSG_HELP_ogSetPartitionSize="Establece el tamaño de una partición." +MSG_HELP_ogSetPartitionType="Modifica el identificador de tipo de una partición física." +MSG_HELP_ogSetRegistryValue="Asigna un dato a un valor del registro de Windows." +MSG_HELP_ogSetWindowsName="Asigna el nombre del cliente en el registro de Windows." +MSG_HELP_ogSetWinlogonUser="Asigna el nombre de usuario por defecto para el gestor de entrada de Windows." +MSG_HELP_ogSyncCreate="Sincroniza los datos de la partición a la imagen" +MSG_HELP_ogSyncRestore="Sincroniza los datos de la imagen a la partición" +MSG_HELP_ogTorrentStart="" +MSG_HELP_ogTypeToId="Devuelve el identificador asociado al mnemónico de tipo de partición." +MSG_HELP_ogUcastReceiverPartition="" +MSG_HELP_ogUcastSendFile="" +MSG_HELP_ogUcastSendPartition="" +MSG_HELP_ogUcastSyntax="" +MSG_HELP_ogUnhidePartition="Hace visible una partición de Windows." +MSG_HELP_ogUninstallLinuxClient="Desinstala el antiguo cliente OpenGnSys en un sistema operativo Linux." +MSG_HELP_ogUninstallWindowsClient="Desinstala el antiguo cliente OpenGnSys en un sistema operativo Windows." +MSG_HELP_ogUnlock="Desbloquea una partición tras finalizar una operación de uso exclusivo." +MSG_HELP_ogUnlockDisk="Desbloquea un disco tras finalizar una operación de uso exclusivo." +MSG_HELP_ogUnlockImage="Desbloquea una imagen tras finalizar una operación de uso exclusivo." +MSG_HELP_ogUnlockPartition=MSG_HELP_ogUnlock +MSG_HELP_ogUnmountAll="Desmonta todos los sistemas de archivos." +MSG_HELP_ogUnmountCache="Desmonta el sistema de archivos de caché local." +MSG_HELP_ogUnmount="Desmonta un sistema de archivos." +MSG_HELP_ogUnmountImage="Desmonta la imagen." +MSG_HELP_ogUnmountFs=MSG_HELP_ogUnmount +MSG_HELP_ogUnsetDirtyBit="" +MSG_HELP_ogUpdateCacheIsNecesary="Comprueba si es necesario actualizar una archivo en la cache local." +MSG_HELP_ogUpdatePartitionTable="Actualiza información de la tabla de particiones del disco." +MSG_HELP_ogUuidChange="Reemplaza el UUID de un sistema de ficheros." +MSG_HELP_ogWaitSyncImage="" +MSG_HELP_ogWindowsBootParameters="" +MSG_HELP_ogWindowsRegisterPartition="" + +# Scripts +MSG_HELP_configureOs="Post-configura de arranque del sistema" +MSG_HELP_createBaseImage="Genera imagen básica de la partición" +MSG_HELP_createDiffImage="Genera imagen diferencial de la partición respecto a la imagen básica" +MSG_HELP_installOfflineMode="Prepara el equipo cliente para el modo offline." +MSG_HELP_partclone2sync="Convierte imagen de partclone en imagen sincronizable." +MSG_HELP_restoreBaseImage="Restaura una imagen básica en una partición" +MSG_HELP_restoreDiffImage="Restaura una imagen diferencial en una partición" +MSG_HELP_updateCache="Realiza la actualización de la caché" + +# Mensajes de descripción breve de la interfaz. +MSG_INTERFACE_START="[START Interface] Ejecutar comando: " +MSG_INTERFACE_END="[END Interface] Comando terminado con este código: " + +# Mensajes de scripts. +MSG_SCRIPTS_START=" INICIO scripts: " +MSG_SCRIPTS_END=" FIN scripts: " +MSG_SCRIPTS_TASK_END="Fin de la tarea" + +MSG_SCRIPTS_TASK_SLEEP="Esperando para iniciar" +MSG_SCRIPTS_TASK_START="Iniciando" +MSG_SCRIPTS_TASK_ERR="Error" + +# Script createImage. +MSG_SCRIPTS_FILE_RENAME=" Renombrar fichero-imagen previo: " +MSG_SCRIPTS_CREATE_SIZE=" Calcular espacio (KB) requerido para almacenarlo y el disponible: " + +# Script updateCache. +MSG_SCRIPTS_UPDATECACHE_DOUPDATE="Comprobar si es necesario actualizar el fichero imagen " +MSG_SCRIPTS_UPDATECACHE_CHECKSIZECACHE="Comprobar que el tamaño de la caché es mayor que el fichero a descargar." +# Script updateCache: para las imágenes sincronizadas tipo dir. +MSG_SCRIPTS_UPDATECACHE_CHECKSIZEDIR="Calcular el tamaño de la imagen." +MSG_SCRIPTS_UPDATECACHE_CHECKSIZEIMG="Comprobar si la imagen del repositorio es mayor que la de la caché." +MSG_SCRIPTS_UPDATECACHE_IFNOTCACHEDO="Comprobar el espacio libre de la caché y actuar según engine.cfg" + +MSG_SCRIPTS_UPDATECACHE_CHECKMCASTSESSION="Comprobando sesión Multicast: ServidorMcast:PuertoDatos" + +# interface sustituye temporalmente al scritp restore +MSG_SCRIPTS_CHECK_ENGINE="Analizar proceso a realizar según engine.cfg" +MSG_SCRIPTS_MULTICAST_PRECHECK_PORT="Determinar puerto principal y auxiliar Multicast." +MSG_SCRIPTS_MULTICAST_CHECK_PORT="Comprobar puertos de sesión y datos" +MSG_SCRIPTS_MULTICAST_REQUEST_PORT="Solicitar la apertura: " +MSG_SCRIPTS_OS_CONFIGURE="Iniciar la configuración del sistema restaurado" + +# TIME MESSAGES +MSG_SCRIPTS_TIME_TOTAL="tiempo total del proceso" +MSG_SCRIPTS_TIME_PARTIAL="tiempo parcial del subproceso" + +# HTTPLOG +MSG_HTTPLOG_NOUSE="No apague este ordenador por favor" + +# Mensajes sincronizadas +MSG_SYNC_RESIZE="Redimensiona la imagen al tamaño necesario" +MSG_SYNC_RESTORE="Trae el listado ficheros y baja la imagen" +MSG_SYNC_DELETE="Diferencial: Borra archivos antiguos" +MSG_SYNC_SLEEP="Espera que se monte/reduzca la imagen" +# Mensajes sincronizadas complementarios a errores +MSG_SYNC_DIFFERENTFS="El sistema de ficheros de destino no coincide con el de la imagen" +MSG_SYNC_EXTENSION="Las extensiones de la imagenes deben ser img o diff" +MSG_SYNC_NOCHECK="La imagen esta montada por otro proceso, no podemos comprobarla" + +MSG_RESTORE="Restaura la imagen en" + diff --git a/client/lib/engine/bin/ogGlobals.py b/client/lib/engine/bin/ogGlobals.py index e685717..51bd5eb 100644 --- a/client/lib/engine/bin/ogGlobals.py +++ b/client/lib/engine/bin/ogGlobals.py @@ -1,5 +1,28 @@ #!/usr/bin/python3 +import sys +import locale +import importlib + +def load_lang (name): + global lang + if name in sys.modules: + return True + elif (spec := importlib.util.find_spec (name)) is not None: + lang = importlib.util.module_from_spec (spec) + sys.modules[name] = lang + spec.loader.exec_module (lang) + return True + else: + #print(f"can't find the {name!r} module") + return False + +l = locale.getlocale()[0] +if not l: print (f"couldn't set locale") +if not l or not load_lang (f'lang_{l}'): + if not load_lang ('lang_en_GB'): + raise ModuleNotFoundError (f"can't find the default language module", name=name) + #OPENGNSYS='/opt/opengnsys' OPENGNSYS='/tmp/opengnsys' OGLOG=f'{OPENGNSYS}/log' @@ -8,10 +31,4 @@ OGLOGCOMMAND='/tmp/command.log' OGLOGSESSION='/tmp/session.log' DEBUG='yes' -## languages -MSG_EXAMPLE='Example' -MSG_FORMAT='Format' -MSG_FUNCTION='Function' -## /languages - TZ='Europe/Madrid' From eb43e67b381b0bffb0fe10b7774727a71a022ac2 Mon Sep 17 00:00:00 2001 From: Natalia Serrano Date: Tue, 29 Oct 2024 18:15:00 +0100 Subject: [PATCH 013/167] refs #1059 add ogRaiseError() --- client/lib/engine/bin/SystemLib.py | 182 +++++++++++------------------ client/lib/engine/bin/ogGlobals.py | 57 ++++++++- 2 files changed, 126 insertions(+), 113 deletions(-) diff --git a/client/lib/engine/bin/SystemLib.py b/client/lib/engine/bin/SystemLib.py index 294fa88..7078aeb 100755 --- a/client/lib/engine/bin/SystemLib.py +++ b/client/lib/engine/bin/SystemLib.py @@ -9,6 +9,7 @@ import ogGlobals #from engine.DiskLib import * #from engine.CacheLib import * #from engine.StringLib import * +from StringLib import * #NODEBUGFUNCTIONS, OGIMG, OG_ERR_CACHESIZE, OG_ERR_NOTCACHE, OG_ERR_NOTWRITE, OG_ERR_FILESYS #OG_ERR_REPO, OG_ERR_NOTOS, OG_ERR_NOGPT, OG_ERR_OUTOFLIMIT, OG_ERR_IMAGE, OG_ERR_CACHE @@ -169,123 +170,82 @@ def ogHelp (fname, fmt=None, examples=[]): else: ## string ogEcho([], "help", f" {ogGlobals.lang.MSG_EXAMPLE}: {examples}") -def ogRaiseError(*args): - # Variables locales - CONT = 1 - LOGS = "" - MSG = "" - CODE = "" - FUNCS = "" - FUNCNAME = ogRaiseError.__name__ - - # Si se solicita, mostrar ayuda. - if len(args) > 0 and args[0] == "help": - ogHelp(f"{FUNCNAME}", f"{FUNCNAME} [str_logfile ...] int_errorcode str_errormessage") +#/** +# ogRaiseError [str_logtype ...] int_errcode ["str_errmessage" ...] +#@brief Devuelve el mensaje y el código de error correspondiente. +#@param str_logtype tipo de registro de incidencias. +#@param int_errcode código de error. +#@param str_errmessage mensajes complementarios de error. +#@return str_code - código de error +#*/ +def ogRaiseError (logtypes, code, msg): + if type (logtypes) is str and 'help' == logtypes: + ogHelp ( + 'ogRaiseError', + 'ogRaiseError ([str_logfile, ...], int_errorcode, str_errormessage)', + [ + 'ogRaiseError ("log", 42, "my error message")', + 'ogRaiseError (["log", "session"], 43, "my other error message")', + ] + ) return - # Selección de registros de incidencias. - while CONT: - arg = args.pop(0).lower() - if arg == "log" or arg == "command" or arg == "session": - LOGS += " " + arg - else: - CONT = 0 - - # Obtener código y mensaje de error. - CODE = args.pop(0) - if CODE == OG_ERR_FORMAT: - MSG = f"{MSG_ERR_FORMAT} \"{args.pop(0)}\"" - elif CODE == OG_ERR_NOTFOUND: - MSG = f"{MSG_ERR_NOTFOUND} \"{args.pop(0)}\"" - elif CODE == OG_ERR_OUTOFLIMIT: - MSG = f"{MSG_ERR_OUTOFLIMIT} \"{args.pop(0)}\"" - elif CODE == OG_ERR_PARTITION: - MSG = f"{MSG_ERR_PARTITION} \"{args.pop(0)}\"" - elif CODE == OG_ERR_LOCKED: - MSG = f"{MSG_ERR_LOCKED} \"{args.pop(0)}\"" - elif CODE == OG_ERR_CACHE: - MSG = f"{MSG_ERR_CACHE} \"{args.pop(0)}\"" - elif CODE == OG_ERR_NOGPT: - MSG = f"{MSG_ERR_NOGPT} \"{args.pop(0)}\"" - elif CODE == OG_ERR_REPO: - MSG = f"{MSG_ERR_REPO} \"{args.pop(0)}\"" - elif CODE == OG_ERR_FILESYS: - MSG = f"{MSG_ERR_FILESYS} \"{args.pop(0)}\"" - elif CODE == OG_ERR_IMAGE: - MSG = f"{MSG_ERR_IMAGE} \"{args.pop(0)}\"" - elif CODE == OG_ERR_NOTOS: - MSG = f"{MSG_ERR_NOTOS} \"{args.pop(0)}\"" - elif CODE == OG_ERR_NOTEXEC: - MSG = f"{MSG_ERR_NOTEXEC} \"{args.pop(0)}\"" - elif CODE == OG_ERR_NOTWRITE: - MSG = f"{MSG_ERR_NOTWRITE} \"{args.pop(0)}\"" - elif CODE == OG_ERR_NOTCACHE: - MSG = f"{MSG_ERR_NOTCACHE} \"{args.pop(0)}\"" - elif CODE == OG_ERR_CACHESIZE: - MSG = f"{MSG_ERR_CACHESIZE} \"{args.pop(0)}\"" - elif CODE == OG_ERR_REDUCEFS: - MSG = f"{MSG_ERR_REDUCEFS} \"{args.pop(0)}\"" - elif CODE == OG_ERR_EXTENDFS: - MSG = f"{MSG_ERR_EXTENDFS} \"{args.pop(0)}\"" - elif CODE == OG_ERR_IMGSIZEPARTITION: - MSG = f"{MSG_ERR_IMGSIZEPARTITION} \"{args.pop(0)}\"" - elif CODE == OG_ERR_UPDATECACHE: - MSG = f"{MSG_ERR_UPDATECACHE} \"{args.pop(0)}\"" - elif CODE == OG_ERR_DONTFORMAT: - MSG = f"{MSG_ERR_DONTFORMAT} \"{args.pop(0)}\"" - elif CODE == OG_ERR_IMAGEFILE: - MSG = f"{MSG_ERR_IMAGEFILE} \"{args.pop(0)}\"" - elif CODE == OG_ERR_UCASTSYNTAXT: - MSG = f"{MSG_ERR_UCASTSYNTAXT} \"{args.pop(0)}\"" - elif CODE == OG_ERR_UCASTSENDPARTITION: - MSG = f"{MSG_ERR_UCASTSENDPARTITION} \"{args.pop(0)}\"" - elif CODE == OG_ERR_UCASTSENDFILE: - MSG = f"{MSG_ERR_UCASTSENDFILE} \"{args.pop(0)}\"" - elif CODE == OG_ERR_UCASTRECEIVERPARTITION: - MSG = f"{MSG_ERR_UCASTRECEIVERPARTITION} \"{args.pop(0)}\"" - elif CODE == OG_ERR_UCASTRECEIVERFILE: - MSG = f"{MSG_ERR_UCASTRECEIVERFILE} \"{args.pop(0)}\"" - elif CODE == OG_ERR_MCASTSYNTAXT: - MSG = f"{MSG_ERR_MCASTSYNTAXT} \"{args.pop(0)}\"" - elif CODE == OG_ERR_MCASTSENDFILE: - MSG = f"{MSG_ERR_MCASTSENDFILE} \"{args.pop(0)}\"" - elif CODE == OG_ERR_MCASTRECEIVERFILE: - MSG = f"{MSG_ERR_MCASTRECEIVERFILE} \"{args.pop(0)}\"" - elif CODE == OG_ERR_MCASTSENDPARTITION: - MSG = f"{MSG_ERR_MCASTSENDPARTITION} \"{args.pop(0)}\"" - elif CODE == OG_ERR_MCASTRECEIVERPARTITION: - MSG = f"{MSG_ERR_MCASTRECEIVERPARTITION} \"{args.pop(0)}\"" - elif CODE == OG_ERR_PROTOCOLJOINMASTER: - MSG = f"{MSG_ERR_PROTOCOLJOINMASTER} \"{args.pop(0)}\"" - elif CODE == OG_ERR_DONTMOUNT_IMAGE: - MSG = f"{MSG_ERR_DONTMOUNT_IMAGE} \"{args.pop(0)}\"" - elif CODE == OG_ERR_DONTUNMOUNT_IMAGE: - MSG = f"{MSG_ERR_DONTUNMOUNT_IMAGE} \"{args.pop(0)}\"" - elif CODE == OG_ERR_DONTSYNC_IMAGE: - MSG = f"{MSG_ERR_DONTSYNC_IMAGE} \"{args.pop(0)}\"" - elif CODE == OG_ERR_NOTDIFFERENT: - MSG = f"{MSG_ERR_NOTDIFFERENT} \"{args.pop(0)}\"" - elif CODE == OG_ERR_SYNCHRONIZING: - MSG = f"{MSG_ERR_SYNCHRONIZING} \"{args.pop(0)}\"" - elif CODE == OG_ERR_NOTUEFI: - MSG = f"{MSG_ERR_NOTUEFI} \"{args.pop(0)}\"" - elif CODE == OG_ERR_NOMSDOS: - MSG = f"{MSG_ERR_NOMSDOS} \"{args.pop(0)}\"" - elif CODE == OG_ERR_NOTBIOS: - MSG = f"{MSG_ERR_NOTBIOS} \"{args.pop(0)}\"" + if code == ogGlobals.OG_ERR_FORMAT: MSG = f'{ogGlobals.lang.MSG_ERR_FORMAT} "{msg}"' + elif code == ogGlobals.OG_ERR_NOTFOUND: MSG = f'{ogGlobals.lang.MSG_ERR_NOTFOUND} "{msg}"' + elif code == ogGlobals.OG_ERR_OUTOFLIMIT: MSG = f'{ogGlobals.lang.MSG_ERR_OUTOFLIMIT} "{msg}"' + elif code == ogGlobals.OG_ERR_PARTITION: MSG = f'{ogGlobals.lang.MSG_ERR_PARTITION} "{msg}"' + elif code == ogGlobals.OG_ERR_LOCKED: MSG = f'{ogGlobals.lang.MSG_ERR_LOCKED} "{msg}"' + elif code == ogGlobals.OG_ERR_CACHE: MSG = f'{ogGlobals.lang.MSG_ERR_CACHE} "{msg}"' + elif code == ogGlobals.OG_ERR_NOGPT: MSG = f'{ogGlobals.lang.MSG_ERR_NOGPT} "{msg}"' + elif code == ogGlobals.OG_ERR_REPO: MSG = f'{ogGlobals.lang.MSG_ERR_REPO} "{msg}"' + elif code == ogGlobals.OG_ERR_FILESYS: MSG = f'{ogGlobals.lang.MSG_ERR_FILESYS} "{msg}"' + elif code == ogGlobals.OG_ERR_IMAGE: MSG = f'{ogGlobals.lang.MSG_ERR_IMAGE} "{msg}"' + elif code == ogGlobals.OG_ERR_NOTOS: MSG = f'{ogGlobals.lang.MSG_ERR_NOTOS} "{msg}"' + elif code == ogGlobals.OG_ERR_NOTEXEC: MSG = f'{ogGlobals.lang.MSG_ERR_NOTEXEC} "{msg}"' + elif code == ogGlobals.OG_ERR_NOTWRITE: MSG = f'{ogGlobals.lang.MSG_ERR_NOTWRITE} "{msg}"' + elif code == ogGlobals.OG_ERR_NOTCACHE: MSG = f'{ogGlobals.lang.MSG_ERR_NOTCACHE} "{msg}"' + elif code == ogGlobals.OG_ERR_CACHESIZE: MSG = f'{ogGlobals.lang.MSG_ERR_CACHESIZE} "{msg}"' + elif code == ogGlobals.OG_ERR_REDUCEFS: MSG = f'{ogGlobals.lang.MSG_ERR_REDUCEFS} "{msg}"' + elif code == ogGlobals.OG_ERR_EXTENDFS: MSG = f'{ogGlobals.lang.MSG_ERR_EXTENDFS} "{msg}"' + elif code == ogGlobals.OG_ERR_IMGSIZEPARTITION: MSG = f'{ogGlobals.lang.MSG_ERR_IMGSIZEPARTITION} "{msg}"' + elif code == ogGlobals.OG_ERR_UPDATECACHE: MSG = f'{ogGlobals.lang.MSG_ERR_UPDATECACHE} "{msg}"' + elif code == ogGlobals.OG_ERR_DONTFORMAT: MSG = f'{ogGlobals.lang.MSG_ERR_DONTFORMAT} "{msg}"' + elif code == ogGlobals.OG_ERR_IMAGEFILE: MSG = f'{ogGlobals.lang.MSG_ERR_IMAGEFILE} "{msg}"' + elif code == ogGlobals.OG_ERR_UCASTSYNTAXT: MSG = f'{ogGlobals.lang.MSG_ERR_UCASTSYNTAXT} "{msg}"' + elif code == ogGlobals.OG_ERR_UCASTSENDPARTITION: MSG = f'{ogGlobals.lang.MSG_ERR_UCASTSENDPARTITION} "{msg}"' + elif code == ogGlobals.OG_ERR_UCASTSENDFILE: MSG = f'{ogGlobals.lang.MSG_ERR_UCASTSENDFILE} "{msg}"' + elif code == ogGlobals.OG_ERR_UCASTRECEIVERPARTITION: MSG = f'{ogGlobals.lang.MSG_ERR_UCASTRECEIVERPARTITION} "{msg}"' + elif code == ogGlobals.OG_ERR_UCASTRECEIVERFILE: MSG = f'{ogGlobals.lang.MSG_ERR_UCASTRECEIVERFILE} "{msg}"' + elif code == ogGlobals.OG_ERR_MCASTSYNTAXT: MSG = f'{ogGlobals.lang.MSG_ERR_MCASTSYNTAXT} "{msg}"' + elif code == ogGlobals.OG_ERR_MCASTSENDFILE: MSG = f'{ogGlobals.lang.MSG_ERR_MCASTSENDFILE} "{msg}"' + elif code == ogGlobals.OG_ERR_MCASTRECEIVERFILE: MSG = f'{ogGlobals.lang.MSG_ERR_MCASTRECEIVERFILE} "{msg}"' + elif code == ogGlobals.OG_ERR_MCASTSENDPARTITION: MSG = f'{ogGlobals.lang.MSG_ERR_MCASTSENDPARTITION} "{msg}"' + elif code == ogGlobals.OG_ERR_MCASTRECEIVERPARTITION: MSG = f'{ogGlobals.lang.MSG_ERR_MCASTRECEIVERPARTITION} "{msg}"' + elif code == ogGlobals.OG_ERR_PROTOCOLJOINMASTER: MSG = f'{ogGlobals.lang.MSG_ERR_PROTOCOLJOINMASTER} "{msg}"' + elif code == ogGlobals.OG_ERR_DONTMOUNT_IMAGE: MSG = f'{ogGlobals.lang.MSG_ERR_DONTMOUNT_IMAGE} "{msg}"' + elif code == ogGlobals.OG_ERR_DONTUNMOUNT_IMAGE: MSG = f'{ogGlobals.lang.MSG_ERR_DONTUNMOUNT_IMAGE} "{msg}"' + elif code == ogGlobals.OG_ERR_DONTSYNC_IMAGE: MSG = f'{ogGlobals.lang.MSG_ERR_DONTSYNC_IMAGE} "{msg}"' + elif code == ogGlobals.OG_ERR_NOTDIFFERENT: MSG = f'{ogGlobals.lang.MSG_ERR_NOTDIFFERENT} "{msg}"' + elif code == ogGlobals.OG_ERR_SYNCHRONIZING: MSG = f'{ogGlobals.lang.MSG_ERR_SYNCHRONIZING} "{msg}"' + elif code == ogGlobals.OG_ERR_NOTUEFI: MSG = f'{ogGlobals.lang.MSG_ERR_NOTUEFI} "{msg}"' + elif code == ogGlobals.OG_ERR_NOMSDOS: MSG = f'{ogGlobals.lang.MSG_ERR_NOMSDOS} "{msg}"' + elif code == ogGlobals.OG_ERR_NOTBIOS: MSG = f'{ogGlobals.lang.MSG_ERR_NOTBIOS} "{msg}"' else: - MSG = MSG_ERR_GENERIC - CODE = OG_ERR_GENERIC + MSG = ogGlobals.lang.MSG_ERR_GENERIC + CODE = ogGlobals.OG_ERR_GENERIC - # Obtener lista de funciones afectadas, incluyendo el script que las llama. - FUNCS = " ".join(FUNCNAME[1:]) - FUNCS = FUNCS.replace("main", os.path.basename(sys.argv[0])) + call_stack = [i[3] for i in inspect.stack()] + if len (call_stack) < 3: return ## shouldn't happen + call_stack.pop() ## remove '' + call_stack.pop(0) ## remove 'ogRaiseError' + str_call_stack = ' '.join (call_stack) - # Mostrar mensaje de error si es función depurable y salir con el código indicado. - if CODE == OG_ERR_FORMAT or ogCheckStringInGroup(FUNCS, NODEBUGFUNCTIONS) or not ogCheckStringInGroup(FUNCS.split()[0], NODEBUGFUNCTIONS): - ogEcho(LOGS, "error", f"{FUNCS.replace(' ', '<-')}: {MSG}", file=sys.stderr) + if code == ogGlobals.OG_ERR_FORMAT or \ + ogCheckStringInGroup (str_call_stack, ogGlobals.NODEBUGFUNCTIONS) or \ + not ogCheckStringInGroup (call_stack[0], ogGlobals.NODEBUGFUNCTIONS): + ogEcho (logtypes, "error", f"{str_call_stack.replace(' ', '<-')}: {MSG}") - return CODE + return code def ogIsRepoLocked(): # Variables locales diff --git a/client/lib/engine/bin/ogGlobals.py b/client/lib/engine/bin/ogGlobals.py index 51bd5eb..342eeb2 100644 --- a/client/lib/engine/bin/ogGlobals.py +++ b/client/lib/engine/bin/ogGlobals.py @@ -23,12 +23,65 @@ if not l or not load_lang (f'lang_{l}'): if not load_lang ('lang_en_GB'): raise ModuleNotFoundError (f"can't find the default language module", name=name) +TZ='Europe/Madrid' + + +## engine.cfg +NODEBUGFUNCTIONS='ogCreateImageSyntax ogGetHivePath ogGetOsType ogRestoreImageSyntax ogUnmountAll ogUnmountCache' +## /engine.cfg + + #OPENGNSYS='/opt/opengnsys' -OPENGNSYS='/tmp/opengnsys' +OPENGNSYS='/tmp/opengnsys' ## XXX OGLOG=f'{OPENGNSYS}/log' OGLOGFILE=f'{OGLOG}/192.168.42.42' ## TODO OGLOGCOMMAND='/tmp/command.log' OGLOGSESSION='/tmp/session.log' DEBUG='yes' -TZ='Europe/Madrid' +# Declaración de códigos de error. +OG_ERR_FORMAT=1 # Formato de ejecución incorrecto. +OG_ERR_NOTFOUND=2 # Fichero o dispositivo no encontrado. +OG_ERR_PARTITION=3 # Error en partición de disco. +OG_ERR_LOCKED=4 # Partición o fichero bloqueado. +OG_ERR_IMAGE=5 # Error al crear o restaurar una imagen. +OG_ERR_NOTOS=6 # Sin sistema operativo. +OG_ERR_NOTEXEC=7 # Programa o función no ejecutable. +# Códigos 8-13 reservados por ogAdmClient.h +OG_ERR_NOTWRITE=14 # No hay acceso de escritura +OG_ERR_NOTCACHE=15 # No hay particion cache en cliente +OG_ERR_CACHESIZE=16 # No hay espacio en la cache para almacenar fichero-imagen +OG_ERR_REDUCEFS=17 # Error al reducir sistema archivos +OG_ERR_EXTENDFS=18 # Error al expandir el sistema de archivos +OG_ERR_OUTOFLIMIT=19 # Valor fuera de rango o no válido. +OG_ERR_FILESYS=20 # Sistema de archivos desconocido o no se puede montar +OG_ERR_CACHE=21 # Error en partición de caché local +OG_ERR_NOGPT=22 # El disco indicado no contiene una particion GPT +OG_ERR_REPO=23 # Error al montar el repositorio de imagenes +OG_ERR_NOMSDOS=24 # El disco indicado no contienen una particion MSDOS + +OG_ERR_IMGSIZEPARTITION=30 # Error al restaurar partición más pequeña que la imagen +OG_ERR_UPDATECACHE=31 # Error al realizar el comando updateCache +OG_ERR_DONTFORMAT=32 # Error al formatear +OG_ERR_IMAGEFILE=33 # Archivo de imagen corrupto o de otra versión de $IMGPROG +OG_ERR_GENERIC=40 # Error imprevisto no definido +OG_ERR_UCASTSYNTAXT=50 # Error en la generación de sintaxis de transferenica UNICAST +OG_ERR_UCASTSENDPARTITION=51 # Error en envío UNICAST de partición +OG_ERR_UCASTSENDFILE=52 # Error en envío UNICAST de un fichero +OG_ERR_UCASTRECEIVERPARTITION=53 # Error en la recepcion UNICAST de una particion +OG_ERR_UCASTRECEIVERFILE=54 # Error en la recepcion UNICAST de un fichero +OG_ERR_MCASTSYNTAXT=55 # Error en la generacion de sintaxis de transferenica Multicast. +OG_ERR_MCASTSENDFILE=56 # Error en envio MULTICAST de un fichero +OG_ERR_MCASTRECEIVERFILE=57 # Error en la recepcion MULTICAST de un fichero +OG_ERR_MCASTSENDPARTITION=58 # Error en envio MULTICAST de una particion +OG_ERR_MCASTRECEIVERPARTITION=59 # Error en la recepcion MULTICAST de una particion +OG_ERR_PROTOCOLJOINMASTER=60 # Error en la conexion de una sesion UNICAST|MULTICAST con el MASTER + +OG_ERR_DONTMOUNT_IMAGE=70 # Error al montar una imagen sincronizada. +OG_ERR_DONTSYNC_IMAGE=71 # Imagen no sincronizable (es monolitica) +OG_ERR_DONTUNMOUNT_IMAGE=72 # Error al desmontar la imagen +OG_ERR_NOTDIFFERENT=73 # No se detectan diferencias entre la imagen basica y la particion. +OG_ERR_SYNCHRONIZING=74 # Error al sincronizar, puede afectar la creacion/restauracion de la imagen + +OG_ERR_NOTUEFI=80 # La interfaz UEFI no está activa +OG_ERR_NOTBIOS=81 # La interfaz BIOS legacy no está activa From 79951558248bdeae5bf910dde729e8b282e4473b Mon Sep 17 00:00:00 2001 From: Natalia Serrano Date: Thu, 31 Oct 2024 09:47:08 +0100 Subject: [PATCH 014/167] refs #1059 remove management of "help"--to be done elsewhere --- client/lib/engine/bin/SystemLib.py | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/client/lib/engine/bin/SystemLib.py b/client/lib/engine/bin/SystemLib.py index 7078aeb..c5a8a80 100755 --- a/client/lib/engine/bin/SystemLib.py +++ b/client/lib/engine/bin/SystemLib.py @@ -178,18 +178,21 @@ def ogHelp (fname, fmt=None, examples=[]): #@param str_errmessage mensajes complementarios de error. #@return str_code - código de error #*/ -def ogRaiseError (logtypes, code, msg): - if type (logtypes) is str and 'help' == logtypes: - ogHelp ( - 'ogRaiseError', - 'ogRaiseError ([str_logfile, ...], int_errorcode, str_errormessage)', - [ - 'ogRaiseError ("log", 42, "my error message")', - 'ogRaiseError (["log", "session"], 43, "my other error message")', - ] - ) - return +## si creamos un script ogRaiseError que llame a esta función (lo cual está por ver) +## entonces la gestión de la ayuda va en ese script, por ejemplo: +#from SystemLib import ogHelp +#if 'help' == sys.argv[1]: +# ogHelp ( +# 'ogRaiseError', +# 'ogRaiseError ([str_logfile, ...], int_errorcode, str_errormessage)', +# [ +# 'ogRaiseError ("log", 42, "my error message")', +# 'ogRaiseError (["log", "session"], 43, "my other error message")', +# ] +# ) +# return +def ogRaiseError (logtypes, code, msg): if code == ogGlobals.OG_ERR_FORMAT: MSG = f'{ogGlobals.lang.MSG_ERR_FORMAT} "{msg}"' elif code == ogGlobals.OG_ERR_NOTFOUND: MSG = f'{ogGlobals.lang.MSG_ERR_NOTFOUND} "{msg}"' elif code == ogGlobals.OG_ERR_OUTOFLIMIT: MSG = f'{ogGlobals.lang.MSG_ERR_OUTOFLIMIT} "{msg}"' From 41012ac0bf02b9470d3c99fa2b5df07acc8ebbaf Mon Sep 17 00:00:00 2001 From: Natalia Serrano Date: Thu, 31 Oct 2024 10:10:38 +0100 Subject: [PATCH 015/167] refs #1059 remove some comments--they go to the wiki --- client/lib/engine/bin/SystemLib.py | 24 ------------------------ 1 file changed, 24 deletions(-) diff --git a/client/lib/engine/bin/SystemLib.py b/client/lib/engine/bin/SystemLib.py index c5a8a80..03da470 100755 --- a/client/lib/engine/bin/SystemLib.py +++ b/client/lib/engine/bin/SystemLib.py @@ -28,16 +28,6 @@ def _logtype2logfile (t): #@param str_message mensaje (puede recibir más de 1 parámetro. #@return Mensaje mostrado. #*/ -## zero or more logtypes can be specified -## zero or one loglevel can be specified -## ogEcho ([], None, msg) -## ogEcho ('log', None, msg) -## ogEcho ('session', None, msg) -## ogEcho (['log', 'session'], None, msg) -## ogEcho ([], None, 'info', msg) -## ogEcho ('log', None, 'info', msg) -## ogEcho ('session', None, 'info', msg) -## ogEcho (['log', 'session'], 'info', msg) def ogEcho (logtypes, loglevel, msg): logfiles = [] if type (logtypes) is list: @@ -178,20 +168,6 @@ def ogHelp (fname, fmt=None, examples=[]): #@param str_errmessage mensajes complementarios de error. #@return str_code - código de error #*/ -## si creamos un script ogRaiseError que llame a esta función (lo cual está por ver) -## entonces la gestión de la ayuda va en ese script, por ejemplo: -#from SystemLib import ogHelp -#if 'help' == sys.argv[1]: -# ogHelp ( -# 'ogRaiseError', -# 'ogRaiseError ([str_logfile, ...], int_errorcode, str_errormessage)', -# [ -# 'ogRaiseError ("log", 42, "my error message")', -# 'ogRaiseError (["log", "session"], 43, "my other error message")', -# ] -# ) -# return - def ogRaiseError (logtypes, code, msg): if code == ogGlobals.OG_ERR_FORMAT: MSG = f'{ogGlobals.lang.MSG_ERR_FORMAT} "{msg}"' elif code == ogGlobals.OG_ERR_NOTFOUND: MSG = f'{ogGlobals.lang.MSG_ERR_NOTFOUND} "{msg}"' From 1c53ce8173058b070e9336d2e99f8850c489a5cb Mon Sep 17 00:00:00 2001 From: aguerrero Date: Mon, 4 Nov 2024 04:37:04 +0000 Subject: [PATCH 016/167] refs #1037 full functionality of InventarioHardware.py script is added; InventoryLib.lib library is renamed to InventoryLib.py and hardware inventory functions are updated. --- client/interfaceAdm/InventarioHardware.py | 26 +- client/lib/engine/bin/InventoryLib.lib | 23 -- client/lib/engine/bin/InventoryLib.py | 379 ++++++++++++++++++++++ client/shared/scripts/listHardwareInfo.py | 9 +- 4 files changed, 404 insertions(+), 33 deletions(-) mode change 100644 => 100755 client/interfaceAdm/InventarioHardware.py delete mode 100644 client/lib/engine/bin/InventoryLib.lib create mode 100755 client/lib/engine/bin/InventoryLib.py mode change 100644 => 100755 client/shared/scripts/listHardwareInfo.py diff --git a/client/interfaceAdm/InventarioHardware.py b/client/interfaceAdm/InventarioHardware.py old mode 100644 new mode 100755 index 1c55736..5793bfe --- a/client/interfaceAdm/InventarioHardware.py +++ b/client/interfaceAdm/InventarioHardware.py @@ -3,13 +3,27 @@ import sys def main(output_file): # Ejecutar el comando `listHardwareInfo.py` y capturar el resultado - result = subprocess.run(["python3", "/opt/opengnsys/scripts/listHardwareInfo.py"], capture_output=True, text=True, check=True) - file_path = result.stdout.strip() # Obtener la ruta del archivo de salida de `listHardwareInfo.py` + try: + print(f"------------------------------------------ loading listHardwareInfo.py") + result = subprocess.run( + ["python3", "/opt/opengnsys/scripts/listHardwareInfo.py"], + capture_output=True, text=True, check=True + ) + output_lines = result.stdout.strip().split('\n') + file_path = output_lines[-1] # Obtener la última línea como la ruta del archivo de salida + print(f"------------------------------------------ archivo:{file_path}") + + # Leer desde la segunda línea del archivo y escribir en el archivo de salida especificado + with open(file_path, 'r') as input_file, open(output_file, 'w') as output: + lines = input_file.readlines()[1:] # Saltar la primera línea + output.writelines(lines) - # Leer desde la segunda línea del archivo y escribir en el archivo de salida especificado - with open(file_path, 'r') as input_file, open(output_file, 'w') as output: - lines = input_file.readlines()[1:] # Saltar la primera línea - output.writelines(lines) + except subprocess.CalledProcessError as e: + print("Error ejecutando listHardwareInfo.py:", e.stderr, file=sys.stderr) + sys.exit(e.returncode) + except FileNotFoundError as e: + print(f"Archivo no encontrado: {e.filename}", file=sys.stderr) + sys.exit(1) if __name__ == "__main__": if len(sys.argv) != 2: diff --git a/client/lib/engine/bin/InventoryLib.lib b/client/lib/engine/bin/InventoryLib.lib deleted file mode 100644 index 3dd0836..0000000 --- a/client/lib/engine/bin/InventoryLib.lib +++ /dev/null @@ -1,23 +0,0 @@ -#!/usr/bin/python3 - -import os -import stat - -#def ogGetArch(): -#def ogGetOsType(): -#def ogGetOsUuid(): -#def ogGetSerialNumber(): - -#/** -# ogIsEfiActive -#@brief Comprueba si el sistema tiene activo el arranque EFI. -#*/ ## -def ogIsEfiActive(): - try: - return stat.S_ISDIR (os.stat ('/sys/firmware/efi').st_mode) - except: - return False - -#def ogListHardwareInfo(): -#def ogListSoftware(): -#def ogGetOsVersion(): diff --git a/client/lib/engine/bin/InventoryLib.py b/client/lib/engine/bin/InventoryLib.py new file mode 100755 index 0000000..1f1d7ff --- /dev/null +++ b/client/lib/engine/bin/InventoryLib.py @@ -0,0 +1,379 @@ +import glob +import platform +import sys +import os +import subprocess +import tempfile +import re +import json +import shutil +import sqlite3 +from SystemLib import ogMount, ogGetOsType, ogRaiseError, ogHelp, ogGetOsVersion, ogGetHivePath, ogListRegistryKeys, ogGetRegistryValue, ogGetIpAddress + +sys.path.append('/opt/opengnsys/lib/engine/bin') +from SystemLib import ogEcho +#from Disklib import ogDiskToDev +#from engine.FileLib import * +#from engine.RegistryLib import * +#from engine.FileSystemLib import * + +MSG_HARDWAREINVENTORY = "Inventario de hardware de la máquina" + +def ogGetArch(): + if len(sys.argv) > 1 and sys.argv[1] == "help": + ogHelp(sys.argv[0], sys.argv[0], sys.argv[0] + " => x86_64") + return + + if platform.machine().endswith("64"): + print("x86_64") + else: + print("i386") + +def ogGetOsType(): + # Si se solicita, mostrar ayuda. + if len(sys.argv) > 1 and sys.argv[1] == "help": + ogHelp(sys.argv[0], sys.argv[0] + " int_ndisk int_npartition", sys.argv[0] + " 1 2 => Linux") + return + ogGetOsVersion(sys.argv[1:]).split(':')[0] + +def ogGetOsUuid(): + # Si se solicita, mostrar ayuda. + if len(sys.argv) > 1 and sys.argv[1] == "help": + ogHelp(sys.argv[0], sys.argv[0] + " int_ndisk int_nfilesys", sys.argv[0] + " 1 2 => 540e47c6-8e78-4178-aa46-042e4803fb16") + return + + # Error si no se reciben 2 parametros. + if len(sys.argv) != 3: + ogRaiseError(OG_ERR_FORMAT) + return + + # Montar la particion, si no lo estaba previamente. + MNTDIR = ogMount(sys.argv[1], sys.argv[2]) + if not MNTDIR: + return + + # Obtener UUID según el tipo de sistema operativo. + os_type = ogGetOsType(sys.argv[1], sys.argv[2]) + if os_type == "Linux": + # Leer el UUID del sistema de ficheros raíz o el fichero de identificador. + uuid = subprocess.check_output(["findmnt", "-no", "UUID", MNTDIR], stderr=subprocess.DEVNULL).decode().strip() or open(os.path.join(MNTDIR, "etc", "machine-id")).read().strip() + print(uuid) + elif os_type == "Windows": + # Leer identificador en clave de registro. + uuid = ogGetRegistryValue(MNTDIR, "SOFTWARE", "\\Microsoft\\Cryptography\\MachineGuid") + print(uuid) + +def ogGetSerialNumber(): + # Si se solicita, mostrar ayuda. + if len(sys.argv) > 1 and sys.argv[1] == "help": + ogHelp(sys.argv[0], sys.argv[0], sys.argv[0] + " => 123456") + return + + # Obtener nº de serie (ignorar los no especificados). + SERIALNO = subprocess.check_output(["dmidecode", "-s", "system-serial-number"]).decode().strip() + SERIALNO = re.sub(r"(not specified|to be filled|invalid entry|default string)", "", SERIALNO, flags=re.IGNORECASE) + SERIALNO = SERIALNO.replace(" ", "") + SERIALNO = SERIALNO[:25] if len(SERIALNO) > 25 else SERIALNO + if SERIALNO: + print(SERIALNO) + + return 0 + +def ogIsEfiActive(): + return os.path.isdir("/sys/firmware/efi") + +import subprocess +import os +import sys + +def parse_lshw_output(): + try: + # Ejecutar lshw en formato JSON para un fácil procesamiento + lshw_output = subprocess.check_output(["lshw", "-json"], text=True) + lshw_data = json.loads(lshw_output) # Convertir la salida JSON a un diccionario + + # Extraer información relevante en el formato clave=valor + parsed_output = [] + + # Ejemplo de datos clave que podríamos extraer + if "product" in lshw_data: + parsed_output.append(f"product={lshw_data['product']}") + + if "vendor" in lshw_data: + parsed_output.append(f"vendor={lshw_data['vendor']}") + + if "configuration" in lshw_data and "memory" in lshw_data["configuration"]: + parsed_output.append(f"memory={lshw_data['configuration']['memory']}") + + # Recorrer los dispositivos para obtener información de CPU, almacenamiento, etc. + for item in lshw_data.get("children", []): + if item["class"] == "processor": + parsed_output.append(f"cpu={item.get('product', 'Unknown')}") + elif item["class"] == "memory" and "size" in item: + parsed_output.append(f"total_memory={item['size']}") + elif item["class"] == "disk": + parsed_output.append(f"disk={item.get('product', 'Unknown')}") + + # Devolver los datos combinados + return "\n".join(parsed_output) + + except subprocess.CalledProcessError as e: + print(f"Error al ejecutar lshw: {e}") + return "Error al obtener información de hardware" + +def ogListHardwareInfo(): + # Ejecutar dmidecode y obtener tipo de chasis + try: + output = subprocess.check_output('echo "cha=$(dmidecode -s chassis-type)" | grep -v "Other"', shell=True).decode().strip() + except subprocess.CalledProcessError: + output = "cha=Unknown" + + # Detectar BIOS o UEFI + firmware = "boo=UEFI" if os.path.isdir("/sys/firmware/efi") else "boo=BIOS" + print(firmware) + + # Ejecutar y analizar lshw + lshw_output = parse_lshw_output() + + # Combina y devuelve los resultados + return f"{output}\n{firmware}\n{lshw_output}" + +def ogListSoftware(disk, partition): + # Error si no se reciben 2 parametros + if disk is None or partition is None: + og_raise_error("OG_ERR_FORMAT") + return + + # Obtener tipo de sistema de archivos y montarlo + mnt_dir = og_mount(disk, partition) + os_type = og_get_os_type(disk, partition) + + # Ficheros temporales + apps_file = tempfile.NamedTemporaryFile(delete=False) + tmp_file = tempfile.NamedTemporaryFile(delete=False) + + try: + if os_type == "Linux": + # Procesar paquetes dpkg + pkg_dir = os.path.join(mnt_dir, "var/lib/dpkg") + if os.path.exists(pkg_dir): + with open(os.path.join(pkg_dir, "status"), "r") as status_file: + for line in status_file: + # Process lines to extract software info + pass + # Procesar paquetes RPM + pkg_dir = os.path.join(mnt_dir, "var/lib/rpm") + if os.path.exists(pkg_dir): + # Execute rpm command if available + if shutil.which("rpm"): + subprocess.run(["rpm", "--dbpath", pkg_dir, "-qa", "--qf", "%{NAME} %{VERSION}\n"], stdout=apps_file) + else: + # Compatibility mode for older systems + pass + # Procesar otros tipos de paquetes (pacman, snap, flatpak, etc.) + pass + elif os_type == "Windows": + # Procesar aplicaciones instaladas en Windows + hive_path = og_get_hive_path(mnt_dir, "software") + if hive_path: + subprocess.run(["hivexregedit", "--unsafe-printable-strings", "--export", hive_path, '\Microsoft\Windows\CurrentVersion\Uninstall'], stdout=tmp_file) + elif os_type == "MacOS": + # Procesar aplicaciones instaladas en MacOS + pass + elif os_type == "BSD": + # Procesar aplicaciones instaladas en FreeBSD + pass + else: + og_raise_error("OG_ERR_NOTOS", disk, partition) + finally: + # Eliminar archivos temporales + apps_file.close() + tmp_file.close() + os.remove(apps_file.name) + os.remove(tmp_file.name) + + # Mostrar sistema operativo y aplicaciones + og_get_os_version(disk, partition) + with open(apps_file.name, "r") as apps: + for line in sorted(set(apps.readlines())): + print(line.strip()) + +def ogGetOsVersion(ndisk, nfilesys): + # Variables locales. + MNTDIR = ogMount(ndisk, nfilesys) + TYPE = "" + VERSION = "" + IS64BIT = "" + + # Si se solicita, mostrar ayuda. + if len(sys.argv) > 1 and sys.argv[1] == "help": + ogHelp(sys.argv[0], sys.argv[0] + " int_ndisk int_nfilesys", sys.argv[0] + " 1 2 => Linux:Ubuntu precise (12.04 LTS) 64 bits") + return + + # Error si no se reciben 2 parametros. + if len(sys.argv) != 3: + ogRaiseError(OG_ERR_FORMAT) + return + + # Montar la particion, si no lo estaba previamente. + MNTDIR = ogMount(sys.argv[1], sys.argv[2]) + if not MNTDIR: + return + + # Buscar tipo de sistema operativo. + # Para GNU/Linux: leer descripción. + TYPE = "Linux" + FILE = os.path.join(MNTDIR, "etc", "os-release") + if os.path.exists(FILE): + with open(FILE, "r") as f: + for line in f: + if line.startswith("PRETTY_NAME"): + VERSION = line.split("=")[1].strip().strip('"') + break + + # Si no se puede obtener, buscar en ficheros del sistema. + if not VERSION: + FILE = os.path.join(MNTDIR, "etc", "lsb-release") + if os.path.exists(FILE): + with open(FILE, "r") as f: + for line in f: + if line.startswith("DESCRIPTION"): + VERSION = line.split("=")[1].strip().strip('"') + break + for DISTRIB in ["redhat", "SuSE", "mandrake", "gentoo"]: + FILE = os.path.join(MNTDIR, "etc", f"{DISTRIB}-release") + if os.path.exists(FILE): + with open(FILE, "r") as f: + VERSION = f.readline().strip() + break + FILE = os.path.join(MNTDIR, "etc", "arch-release") + if os.path.exists(FILE): + VERSION = "Arch Linux" + FILE = os.path.join(MNTDIR, "etc", "slackware-version") + if os.path.exists(FILE): + with open(FILE, "r") as f: + VERSION = f.read().strip() + + # Si no se encuentra, intentar ejecutar "lsb_release". + if not VERSION: + try: + output = subprocess.check_output(["chroot", MNTDIR, "lsb_release", "-d"], stderr=subprocess.DEVNULL).decode().strip() + VERSION = output.split(":")[1].strip() + except subprocess.CalledProcessError: + pass + + # Comprobar Linux de 64 bits. + if VERSION and os.path.exists(os.path.join(MNTDIR, "lib64")): + IS64BIT = "64 bits" + + # Para Android, leer fichero de propiedades. + if not VERSION: + TYPE = "Android" + FILE = os.path.join(MNTDIR, "android*", "system", "build.prop") + if glob.glob(FILE): + with open(glob.glob(FILE)[0], "r") as f: + lines = f.readlines() + brand = "" + release = "" + for line in lines: + if line.startswith("product.brand"): + brand = line.split("=")[1].strip() + elif line.startswith("build.version.release"): + release = line.split("=")[1].strip() + VERSION = f"Android {brand} {release}" + if os.path.exists(os.path.join(MNTDIR, "lib64")): + IS64BIT = "64 bits" + + # Para GNU/Hurd, comprobar fichero de inicio (basado en os-prober). + if not VERSION: + TYPE = "Hurd" + FILE = os.path.join(MNTDIR, "hurd", "init") + if os.path.exists(FILE): + VERSION = "GNU/Hurd" + + # Para Windows: leer la version del registro. + if not VERSION: + TYPE = "Windows" + FILE = ogGetHivePath(MNTDIR, "SOFTWARE") + if FILE: + try: + output = subprocess.check_output(["hivexsh", "load", FILE, "cd", "\\Microsoft\\Windows NT\\CurrentVersion", "lsval", "ProductName", "lsval", "DisplayVersion"], stderr=subprocess.DEVNULL).decode().strip() + lines = output.split("\n") + if len(lines) == 2: + VERSION = lines[1].strip() + if ogGetRegistryValue(MNTDIR, "SOFTWARE", "\\Microsoft\\Windows\\CurrentVersion\\ProgramW6432Dir"): + IS64BIT = "64 bits" + except subprocess.CalledProcessError: + pass + + # Para cargador Windows: buscar versión en fichero BCD (basado en os-prober). + if not VERSION: + TYPE = "WinLoader" + FILE = ogGetPath(MNTDIR, "boot", "bcd") + if not FILE: + FILE = ogGetPath(MNTDIR, "EFI", "Microsoft", "boot", "bcd") + if FILE: + for DISTRIB in ["Windows Recovery", "Windows Boot"]: + with open(FILE, "rb") as f: + if re.search(DISTRIB.encode(), f.read()): + VERSION = f"{DISTRIB} loader" + break + + # Para macOS: detectar kernel y completar con fichero plist de información del sistema. + if not VERSION: + TYPE = "MacOS" + FILE = os.path.join(MNTDIR, "mach_kernel") + if os.path.exists(FILE) and not subprocess.check_output(["file", "-b", FILE]).decode().strip().startswith("text"): + if subprocess.check_output(["file", "-b", FILE]).decode().strip().startswith("Mach-O"): + VERSION = "macOS" + if subprocess.check_output(["file", "-b", FILE]).decode().strip().startswith("Mach-O 64-bit"): + IS64BIT = "64 bits" + FILE = os.path.join(MNTDIR, "System", "Library", "CoreServices", "SystemVersion.plist") + if os.path.exists(FILE): + with open(FILE, "r") as f: + plist_data = f.read() + product_name = re.search(r"ProductName\s*(.*?)", plist_data) + product_version = re.search(r"ProductVersion\s*(.*?)", plist_data) + if product_name and product_version: + VERSION = f"{product_name.group(1)} {product_version.group(1)}" + FILE = os.path.join(MNTDIR, "com.apple.recovery.boot") + if os.path.exists(FILE) and VERSION: + VERSION = f"{VERSION} recovery" + + # Para FreeBSD: obtener datos del Kernel. + if not VERSION: + TYPE = "BSD" + FILE = os.path.join(MNTDIR, "boot", "kernel", "kernel") + if os.path.exists(FILE): + output = subprocess.check_output(["strings", FILE]).decode().strip() + match = re.search(r"@.*RELEASE", output) + if match: + VERSION = match.group().split("@")[0].strip() + if subprocess.check_output(["file", "-b", FILE]).decode().strip().endswith("x86-64"): + IS64BIT = "64 bits" + + # Para Solaris: leer el fichero de versión. + if not VERSION: + TYPE = "Solaris" + FILE = os.path.join(MNTDIR, "etc", "release") + if os.path.exists(FILE): + with open(FILE, "r") as f: + VERSION = f.readline().strip() + + # Para cargador GRUB, comprobar fichero de configuración. + if not VERSION: + TYPE = "GrubLoader" + for FILE in [os.path.join(MNTDIR, "grub", "menu.lst"), os.path.join(MNTDIR, "boot", "grub", "menu.lst")]: + if os.path.exists(FILE): + VERSION = "GRUB Loader" + break + for FILE in glob.glob(os.path.join(MNTDIR, "{,boot/}{grub{,2},EFI/*}/grub.cfg")): + if os.path.exists(FILE): + VERSION = "GRUB2 Loader" + break + + # Mostrar resultado y salir sin errores. + if VERSION: + print(f"{TYPE}:{VERSION} {IS64BIT}") + + return 0 diff --git a/client/shared/scripts/listHardwareInfo.py b/client/shared/scripts/listHardwareInfo.py old mode 100644 new mode 100755 index d920c73..9f633b1 --- a/client/shared/scripts/listHardwareInfo.py +++ b/client/shared/scripts/listHardwareInfo.py @@ -1,9 +1,10 @@ import subprocess import os import sys -sys.path.append('/opt/opengnsys/lib/engine/bin') # Agregar ruta de NetLib.py -from InventoryLib import ogListHardwareInfo +sys.path.append('/opt/opengnsys/lib/engine/bin') from NetLib import ogGetIpAddress +sys.path.append('/opt/opengnsys/lib/engine/bin') +from InventoryLib import ogListHardwareInfo def get_server_log_dir(): # Obtener el directorio de logs del servidor @@ -19,10 +20,10 @@ def get_server_log_dir(): def list_hardware_info(): oglog = os.getenv("OGLOG", "/tmp") # Usar /tmp como valor por defecto para OGLOG - + ip_address = ogGetIpAddress() # Fichero de listado de hardware basado en la IP obtenida hardfile = f"hard-{ogGetIpAddress()}" - + print(f"hardfile:{hardfile}") # Ejecutar ogListHardwareInfo y redirigir al archivo de listado hardware_info_path = os.path.join(oglog, hardfile) with open(hardware_info_path, 'w') as output_file: From 063ddb891349e62fbaa3d0cff4cfe6461bd026ee Mon Sep 17 00:00:00 2001 From: Natalia Serrano Date: Mon, 4 Nov 2024 17:33:57 +0100 Subject: [PATCH 017/167] refs #1097 mimic "tee" behaviour --- client/lib/engine/bin/SystemLib.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/lib/engine/bin/SystemLib.py b/client/lib/engine/bin/SystemLib.py index 03da470..0781f1e 100755 --- a/client/lib/engine/bin/SystemLib.py +++ b/client/lib/engine/bin/SystemLib.py @@ -29,7 +29,7 @@ def _logtype2logfile (t): #@return Mensaje mostrado. #*/ def ogEcho (logtypes, loglevel, msg): - logfiles = [] + logfiles = ['/dev/stdout'] if type (logtypes) is list: for l in logtypes: logfiles.append (_logtype2logfile (l)) From c94d2bb38197cb7efb3c793041b4e638a480620e Mon Sep 17 00:00:00 2001 From: Natalia Serrano Date: Mon, 4 Nov 2024 17:36:00 +0100 Subject: [PATCH 018/167] refs #1086 add ogDiskToDev() --- client/lib/engine/bin/DiskLib.py | 285 ++++++++++++++----------- client/lib/engine/bin/FileSystemLib.py | 2 +- 2 files changed, 167 insertions(+), 120 deletions(-) diff --git a/client/lib/engine/bin/DiskLib.py b/client/lib/engine/bin/DiskLib.py index 81ad6a5..52e33fe 100644 --- a/client/lib/engine/bin/DiskLib.py +++ b/client/lib/engine/bin/DiskLib.py @@ -2,6 +2,8 @@ import filecmp import subprocess import shutil import os +import stat +from pathlib import Path from CacheLib import * from FileSystemLib import * @@ -365,142 +367,187 @@ def ogDevToDisk(dev): ogRaiseError(OG_ERR_NOTFOUND, dev) return OG_ERR_NOTFOUND -def ogDiskToDev(*args): - # Variables locales - CACHEFILE = "/var/cache/disks.cfg" - ALLDISKS = [] - MPATH = VOLGROUPS = ZFSVOLS = DISK = PART = ZPOOL = None - i = 1 - - # Si se solicita, mostrar ayuda. - if len(args) == 1 and args[0] == "help": - ogHelp('ogDiskToDev', 'ogDiskToDev int_ndisk [int_npartition]', - 'ogDiskToDev => /dev/sda /dev/sdb', - 'ogDiskToDev 1 => /dev/sda', - 'ogDiskToDev 1 1 => /dev/sda1') - return - - # Borrar fichero de caché de configuración si hay cambios en las particiones. - if not filecmp.cmp('/proc/partitions', '/tmp/.partitions'): - # Guardar copia de las particiones definidas para comprobar cambios. - shutil.copy2('/proc/partitions', '/tmp/.partitions') - os.remove(CACHEFILE) - - # Si existe una correspondencia con disco/dispositivo en el caché; mostrarlo y salir. - with open(CACHEFILE, 'r') as f: - for line in f: - parts = line.strip().split(':') - if len(parts) == 2 and parts[0] == ":".join(args): - print(parts[1]) - return - - # Continuar para detectar nuevos dispositivos. - # Listar dispositivos de discos. - all_disks = subprocess.getoutput("lsblk -n -e 1,2 -x MAJ:MIN 2>/dev/null || lsblk -n -e 1,2").splitlines() +def _getAllDisks(): + ret = [] + all_disks = subprocess.run("lsblk -n -e 1,2 -x MAJ:MIN 2>/dev/null || lsblk -n -e 1,2", shell=True, capture_output=True, text=True).stdout.splitlines() for line in all_disks: parts = line.split() if parts[5] == "disk": - ALLDISKS.append(f"/dev/{parts[0]}") + parts[0].replace ('!', '/') + ret.append(f"/dev/{parts[0]}") + return ret - # Listar volúmenes lógicos. - VOLGROUPS = subprocess.getoutput("vgs -a --noheadings 2>/dev/null").splitlines() - VOLGROUPS = [f"/dev/{line.split()[0]}" for line in VOLGROUPS] +def _getAllVolGroups(): + vgs = subprocess.run(['vgs', '-a', '--noheadings'], capture_output=True, text=True).stdout.splitlines() + ret = [f"/dev/{line.split()[0]}" for line in vgs] + return ret - # Detectar caminos múltiples (ignorar mensaje si no está configurado Multipath). +def _getMPath(): + ret = alldisks2remove = [] try: - MPATH = subprocess.getoutput("multipath -l -v 1 2>/dev/null").splitlines() - MPATH = [f"/dev/mapper/{line.split()[0]}" for line in MPATH] - # Quitar de la lista los discos que forman parte de Multipath. + mpath = subprocess.run(['multipath', '-l', '-v', '1'], capture_output=True, text=True).stdout.splitlines() + ret = [f"/dev/mapper/{line.split()[0]}" for line in mpath] for line in subprocess.getoutput("multipath -ll").splitlines(): if line.split()[5] == "ready": - disk = f"/dev/{line.split()[2]}" - if disk in ALLDISKS: - ALLDISKS.remove(disk) + alldisks2remove.append (f"/dev/{line.split()[2]}") + except FileNotFoundError: + pass except subprocess.CalledProcessError: - MPATH = [] + pass + return ret, alldisks2remove - # Detectar volúmenes ZFS. - ZFSVOLS = subprocess.getoutput("blkid").splitlines() - ZFSVOLS = [line.split(":")[0] for line in ZFSVOLS if "zfs" in line] +def _getAllZFSVols(): + zfsvols = subprocess.run(['blkid'], capture_output=True, text=True).stdout.splitlines() + return [line.split(":")[0] for line in zfsvols if "zfs" in line] - # Mostrar salidas segun el número de parametros. - if len(args) == 0: - print(" ".join(ALLDISKS)) - elif len(args) == 1: - # Error si el parámetro no es un número positivo. - if not args[0].isdigit() or int(args[0]) <= 0: - ogRaiseError(OG_ERR_FORMAT, args[0]) +#/** +# ogDiskToDev [int_ndisk [int_npartition]] +#@brief Devuelve la equivalencia entre el nº de orden del dispositivo (dicso o partición) y el nombre de fichero de dispositivo correspondiente. +#@param int_ndisk nº de orden del disco +#@param int_npartition nº de orden de la partición +#@return Para 0 parametros: Devuelve los nombres de ficheros de los dispositivos sata/ata/usb linux encontrados. +#@return Para 1 parametros: Devuelve la ruta del disco duro indicado. +#@return Para 2 parametros: Devuelve la ruta de la particion indicada. +#@exception OG_ERR_FORMAT Formato incorrecto. +#@exception OG_ERR_NOTFOUND Dispositivo no detectado. +#*/ ## +def ogDiskToDev (arg_disk=None, arg_part=None): + CACHEFILE = "/var/cache/disks.cfg" + + try: + if arg_part != None: + arg_part = int (arg_part) + except: + ogRaiseError([], ogGlobals.OG_ERR_FORMAT, f"{arg_disk} {arg_part}") + return + + try: + if arg_disk != None: + arg_disk = int (arg_disk) + except: + ogRaiseError([], ogGlobals.OG_ERR_FORMAT, arg_disk) + return + + # Si se solicita, mostrar ayuda. + #if len(args) == 1 and args[0] == "help": + # ogHelp('ogDiskToDev', 'ogDiskToDev int_ndisk [int_npartition]', + # 'ogDiskToDev => /dev/sda /dev/sdb', + # 'ogDiskToDev 1 => /dev/sda', + # 'ogDiskToDev 1 1 => /dev/sda1') + # return + + # Borrar fichero de caché de configuración si hay cambios en las particiones. + proc_partitions = Path ('/proc/partitions').read_text() + tmp_partitions = Path ('/tmp/.partitions').read_text() if os.path.exists ('/tmp/.partitions') else '' + if proc_partitions != tmp_partitions: + # Guardar copia de las particiones definidas para comprobar cambios. + shutil.copy2('/proc/partitions', '/tmp/.partitions') + try: + ogEcho ([], 'info', f'removing cachefile') + os.remove(CACHEFILE) + except FileNotFoundError: + pass + + # Si existe una correspondencia con disco/dispositivo en el caché; mostrarlo y salir. + if arg_disk and os.path.exists (CACHEFILE): + with open(CACHEFILE, 'r') as f: + args_joined = ' '.join (map (str, filter (None, [arg_disk,arg_part]))) + ogEcho ([], 'info', f'args_joined ({args_joined})') + for line in f: + parts = line.strip().split(':') + if len(parts) == 2 and parts[0] == args_joined: + return parts[1] + + # Continuar para detectar nuevos dispositivos. + + ALLDISKS = _getAllDisks() + + VOLGROUPS = _getAllVolGroups() + ALLDISKS += VOLGROUPS + + MPATH, ALLDISKS_to_remove =_getMPath() + ALLDISKS = list (set (ALLDISKS) - set (ALLDISKS_to_remove)) + + ZFSVOLS = _getAllZFSVols() + ALLDISKS += ZFSVOLS + print (f'ALLDISKS ({ALLDISKS}) VOLGROUPS ({VOLGROUPS}) MPATH ({MPATH}) ALLDISKS_to_remove ({ALLDISKS_to_remove}) ZFSVOLS ({ZFSVOLS})') + + # No params: return all disks + if arg_disk is None: + return " ".join(ALLDISKS) + + # arg_disk is set: return it + if arg_part is None: + if arg_disk > len (ALLDISKS): + ogRaiseError([], ogGlobals.OG_ERR_NOTFOUND, arg_disk) return - disk = ALLDISKS[int(args[0])-1] - # Error si el fichero no existe. + disk = ALLDISKS[arg_disk-1] if not os.path.exists(disk): - ogRaiseError(OG_ERR_NOTFOUND, args[0]) + ogRaiseError([], ogGlobals.OG_ERR_NOTFOUND, arg_disk) return # Actualizar caché de configuración y mostrar dispositivo. with open(CACHEFILE, 'a') as f: - f.write(f"{args[0]}:{disk}\n") - print(disk) - elif len(args) == 2: - # Error si los 2 parámetros no son números positivos. - if not args[0].isdigit() or int(args[0]) <= 0 or not args[1].isdigit() or int(args[1]) <= 0: - ogRaiseError(OG_ERR_FORMAT, f"{args[0]} {args[1]}") - return - disk = ALLDISKS[int(args[0])-1] - # Error si el fichero no existe. - if not os.path.exists(disk): - ogRaiseError(OG_ERR_NOTFOUND, args[0]) - return - part = f"{disk}{args[1]}" - # Comprobar si es partición. - if os.path.exists(part): - # Actualizar caché de configuración y mostrar dispositivo. - with open(CACHEFILE, 'a') as f: - f.write(f"{args[0]} {args[1]}:{part}\n") - print(part) - else: - # Comprobar si RAID o Multipath (tener en cuenta enlace simbólico). - part = f"{disk}p{args[1]}" - if os.path.exists(part) and os.stat(part, follow_symlinks=True).st_mode[0] == "b": - # Actualizar caché de configuración y mostrar dispositivo. - with open(CACHEFILE, 'a') as f: - f.write(f"{args[0]} {args[1]}:{part}\n") - print(part) - else: - part = "" - # Comprobar si volumen lógico. - if disk in VOLGROUPS: - lvscan = subprocess.getoutput("lvscan -a 2>/dev/null").splitlines() - for line in lvscan: - parts = line.split("'") - if parts[1].startswith(f"{disk}/") and i == int(args[1]): - part = parts[1] - break - i += 1 - # Comprobar si volumen ZFS que puede ser montado. - if disk in ZFSVOLS: - subprocess.run(["zpool", "import", "-f", "-R", "/mnt", "-N", "-a"], stderr=subprocess.DEVNULL) - zpool = subprocess.getoutput(f"blkid -s LABEL -o value {disk}") - zfs_list = subprocess.getoutput(f"zfs list -Hp -o name,canmount,mountpoint -r {zpool}").splitlines() - for line in zfs_list: - parts = line.split() - if parts[1] == "on" and parts[2] != "none": - if i == int(args[1]): - part = parts[0] - break - i += 1 - # Salir si no se encuentra dispositivo. - if not part: - ogRaiseError(OG_ERR_NOTFOUND, f"{args[0]} {args[1]}") - return - # Devolver camino al dispositivo. - # Actualizar caché de configuración y mostrar dispositivo. - with open(CACHEFILE, 'a') as f: - f.write(f"{args[0]} {args[1]}:{part}\n") - print(part) - else: - ogRaiseError(OG_ERR_FORMAT) + f.write(f"{arg_disk}:{disk}\n") + return disk + + # arg_disk and arg_part are set: there are several possibilities + disk = ALLDISKS[arg_disk-1] + if not os.path.exists(disk): + ogRaiseError([], ogGlobals.OG_ERR_NOTFOUND, arg_disk) return + # Plain partition + part = f"{disk}{arg_part}" + if os.path.exists(part): + # Actualizar caché de configuración y mostrar dispositivo. + with open(CACHEFILE, 'a') as f: + f.write(f"{arg_disk} {arg_part}:{part}\n") + return part + + # RAID/Multipath (tener en cuenta enlace simbólico). + part = f"{disk}p{arg_part}" + if os.path.exists(part) and stat.S_ISBLK (os.stat (part, follow_symlinks=True).st_mode): + # Actualizar caché de configuración y mostrar dispositivo. + with open(CACHEFILE, 'a') as f: + f.write(f"{arg_disk} {arg_part}:{part}\n") + return part + + part = "" + # Logical volume + if disk in VOLGROUPS: + lvscan = subprocess.run (['lvscan', '-a'], capture_output=True, text=True).stdout.splitlines() + i = 0 + for line in lvscan: + parts = line.split("'") + if parts[1].startswith(f"{disk}/") and i == arg_part: + part = parts[1] + break + i += 1 + + # ZFS volume + if disk in ZFSVOLS: + subprocess.run(["zpool", "import", "-f", "-R", "/mnt", "-N", "-a"]) + zpool = subprocess.run(['blkid', '-s', 'LABEL', '-o', 'value', disk], capture_output=True, text=True).stdout + zfs_list = subprocess.run(['zfs', 'list', '-Hp', '-o', 'name,canmount,mountpoint', '-r', zpool], capture_output=True, text=True).stdout.splitlines() + i = 0 + for line in zfs_list: + parts = line.split() + if parts[1] == "on" and parts[2] != "none": + if i == int(args[1]): + part = parts[0] + break + i += 1 + + if not part: + ogRaiseError([], ogGlobals.OG_ERR_NOTFOUND, f"{arg_disk} {arg_part}") + return + + # Actualizar caché de configuración y mostrar dispositivo. + with open(CACHEFILE, 'a') as f: + f.write(f"{arg_disk} {arg_part}:{part}\n") + + return part + def ogGetDiskSize(*args): # Variables locales DISK = SIZE = None @@ -1365,4 +1412,4 @@ def ogUnlockDisk(*args): def ogUpdatePartitionTable(): for disk in ogDiskToDev(): - subprocess.run(["partprobe", disk]) \ No newline at end of file + subprocess.run(["partprobe", disk]) diff --git a/client/lib/engine/bin/FileSystemLib.py b/client/lib/engine/bin/FileSystemLib.py index 33d6c8c..7322c67 100644 --- a/client/lib/engine/bin/FileSystemLib.py +++ b/client/lib/engine/bin/FileSystemLib.py @@ -828,4 +828,4 @@ def ogGetFreeSize(int_ndisk, int_npartition, str_SizeOutput): used = float(output[2]) * factor free = float(output[3]) * factor - return free \ No newline at end of file + return free From a5d3d8088d0e3fc0cbe3c29b0acef7fd654db831 Mon Sep 17 00:00:00 2001 From: Natalia Serrano Date: Mon, 4 Nov 2024 18:13:15 +0100 Subject: [PATCH 019/167] refs #1086 don't use set difference--it isn't stable --- client/lib/engine/bin/DiskLib.py | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/client/lib/engine/bin/DiskLib.py b/client/lib/engine/bin/DiskLib.py index 52e33fe..3ad3b05 100644 --- a/client/lib/engine/bin/DiskLib.py +++ b/client/lib/engine/bin/DiskLib.py @@ -428,14 +428,6 @@ def ogDiskToDev (arg_disk=None, arg_part=None): ogRaiseError([], ogGlobals.OG_ERR_FORMAT, arg_disk) return - # Si se solicita, mostrar ayuda. - #if len(args) == 1 and args[0] == "help": - # ogHelp('ogDiskToDev', 'ogDiskToDev int_ndisk [int_npartition]', - # 'ogDiskToDev => /dev/sda /dev/sdb', - # 'ogDiskToDev 1 => /dev/sda', - # 'ogDiskToDev 1 1 => /dev/sda1') - # return - # Borrar fichero de caché de configuración si hay cambios en las particiones. proc_partitions = Path ('/proc/partitions').read_text() tmp_partitions = Path ('/tmp/.partitions').read_text() if os.path.exists ('/tmp/.partitions') else '' @@ -443,7 +435,6 @@ def ogDiskToDev (arg_disk=None, arg_part=None): # Guardar copia de las particiones definidas para comprobar cambios. shutil.copy2('/proc/partitions', '/tmp/.partitions') try: - ogEcho ([], 'info', f'removing cachefile') os.remove(CACHEFILE) except FileNotFoundError: pass @@ -452,7 +443,6 @@ def ogDiskToDev (arg_disk=None, arg_part=None): if arg_disk and os.path.exists (CACHEFILE): with open(CACHEFILE, 'r') as f: args_joined = ' '.join (map (str, filter (None, [arg_disk,arg_part]))) - ogEcho ([], 'info', f'args_joined ({args_joined})') for line in f: parts = line.strip().split(':') if len(parts) == 2 and parts[0] == args_joined: @@ -466,11 +456,11 @@ def ogDiskToDev (arg_disk=None, arg_part=None): ALLDISKS += VOLGROUPS MPATH, ALLDISKS_to_remove =_getMPath() - ALLDISKS = list (set (ALLDISKS) - set (ALLDISKS_to_remove)) + for d in ALLDISKS_to_remove: + if d in ALLDISKS: ALLDISKS.remove (d) ZFSVOLS = _getAllZFSVols() ALLDISKS += ZFSVOLS - print (f'ALLDISKS ({ALLDISKS}) VOLGROUPS ({VOLGROUPS}) MPATH ({MPATH}) ALLDISKS_to_remove ({ALLDISKS_to_remove}) ZFSVOLS ({ZFSVOLS})') # No params: return all disks if arg_disk is None: From 844ae53c052cf4506e626f075f7a3c88fd68f5c7 Mon Sep 17 00:00:00 2001 From: Natalia Serrano Date: Mon, 4 Nov 2024 18:18:02 +0100 Subject: [PATCH 020/167] refs #1098 add ogIsFormated() --- client/lib/engine/bin/FileSystemLib.py | 31 +++++++++++++------------- 1 file changed, 15 insertions(+), 16 deletions(-) diff --git a/client/lib/engine/bin/FileSystemLib.py b/client/lib/engine/bin/FileSystemLib.py index 7322c67..6f7eddf 100644 --- a/client/lib/engine/bin/FileSystemLib.py +++ b/client/lib/engine/bin/FileSystemLib.py @@ -414,29 +414,28 @@ def ogGetMountPoint(int_ndisk, int_nfilesys): result = subprocess.run(["findmnt", "-n", "-o", "TARGET", PART], capture_output=True, text=True) return result.stdout.strip() -def ogIsFormated(int_ndisk, int_nfilesys): - # Si se solicita, mostrar ayuda. - if len(sys.argv) == 3 and sys.argv[2] == "help": - ogHelp("ogIsFormated", "ogIsFormated int_ndisk int_nfilesys", "ogIsFormated 1 1") - return - # Error si no se reciben 2 parámetros. - if len(sys.argv) != 3: - ogRaiseError(OG_ERR_FORMAT) - return - - # Obtener partición. - PART = ogDiskToDev(int_ndisk, int_nfilesys) +#/** +# ogIsFormated int_ndisk int_nfilesys +#@brief Comprueba si un sistema de archivos está formateado. +#@param int_ndisk nº de orden del disco o volumen. +#@param int_nfilesys nº de orden del sistema de archivos +#@return Código de salida: True - formateado, False - sin formato o error. +#*/ ## +def ogIsFormated(disk, part): + PART = ogDiskToDev(disk, part) if not PART: return # Revisar tipo de sistema de archivos. if PART.startswith("/"): - result = subprocess.run(["blkid", "-s", "TYPE", PART], capture_output=True, text=True) - return bool(result.stdout.strip()) + out = subprocess.run(["blkid", "-s", "TYPE", PART], capture_output=True, text=True).stdout.strip() + if 'swap' in out: return False + if '_member' in out: return False + return bool(out) else: - result = subprocess.run(["zfs", "list", "-Hp", "-o", "canmount", PART], capture_output=True, text=True) - return result.stdout.strip() == "on" + out = subprocess.run(["zfs", "list", "-Hp", "-o", "canmount", PART], capture_output=True, text=True).stdout.strip() + return out == "on" def ogIsLocked(int_ndisk, int_nfilesys): return ogIsPartitionLocked(int_ndisk, int_nfilesys) From 269fcd288da825734b0b6724de5f38fff675b8f4 Mon Sep 17 00:00:00 2001 From: aguerrero Date: Tue, 5 Nov 2024 05:45:25 +0000 Subject: [PATCH 021/167] refs #1093 initial version of InventorySoftware, pending to fix log functionality --- client/interfaceAdm/InventarioSoftware.py | 29 ++-- client/lib/engine/bin/RegistryLib.py | 179 ++++++++++++++++++++++ client/shared/scripts/listSoftwareInfo.py | 83 ++++------ 3 files changed, 230 insertions(+), 61 deletions(-) mode change 100644 => 100755 client/interfaceAdm/InventarioSoftware.py create mode 100755 client/lib/engine/bin/RegistryLib.py mode change 100644 => 100755 client/shared/scripts/listSoftwareInfo.py diff --git a/client/interfaceAdm/InventarioSoftware.py b/client/interfaceAdm/InventarioSoftware.py old mode 100644 new mode 100755 index 928681b..7812388 --- a/client/interfaceAdm/InventarioSoftware.py +++ b/client/interfaceAdm/InventarioSoftware.py @@ -7,13 +7,13 @@ import sys def main(arg1, arg2, dest_file): start_time = time.time() - # Load the engine configurator from the engine.cfg file + # Cargar la configuración del motor desde el archivo engine.cfg 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 + # Limpiar los archivos temporales usados como log para httpdlog og_log_session = os.getenv('OGLOGSESSION') og_log_command = os.getenv('OGLOGCOMMAND') if og_log_session and og_log_command: @@ -24,26 +24,35 @@ def main(arg1, arg2, dest_file): with open(f"{og_log_command}.tmp", 'w') as f: f.write(" ") - # Log the start of execution + # Registrar el inicio de ejecución 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 - # Call the actual listSoftwareInfo function - file = listSoftwareInfo(arg1, arg2) + # Ejecutar el script listSoftwareInfo y capturar el archivo de salida + try: + result = subprocess.run( + ["python3", "/opt/opengnsys/scripts/listSoftwareInfo.py", arg1, arg2], + capture_output=True, + text=True, + check=True + ) + file = result.stdout.strip() # Captura la salida del script + except subprocess.CalledProcessError as e: + print(f"Error al ejecutar listSoftwareInfo: {e.stderr}") + sys.exit(e.returncode) + + # Copiar el archivo resultante a dest_file shutil.copy(file, dest_file) - # Log the execution time + # Registrar el tiempo de ejecución 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 + main(sys.argv[1], sys.argv[2], sys.argv[3]) diff --git a/client/lib/engine/bin/RegistryLib.py b/client/lib/engine/bin/RegistryLib.py new file mode 100755 index 0000000..32ef764 --- /dev/null +++ b/client/lib/engine/bin/RegistryLib.py @@ -0,0 +1,179 @@ +import subprocess +import os +import re + +#from engine.FileLib import * +#from engine.SystemLib import * + +def chntpw(*args): + chntpw_path = subprocess.check_output(['which', 'drbl-chntpw']).decode().strip() + if not chntpw_path: + chntpw_path = subprocess.check_output(['which', 'chntpw']).decode().strip() + subprocess.run([chntpw_path, '-e'] + list(args), timeout=5) + +def ogAddRegistryKey(path_mountpoint, str_hive, str_key): + # Variables locales. + FILE = ogGetHivePath(path_mountpoint, str_hive) + if not FILE: + return + + # Añadir nueva clave. + chntpw(FILE, 'cd', str_key.rsplit('\\', 1)[0]) + chntpw(FILE, 'nk', str_key.rsplit('\\', 1)[-1]) + chntpw(FILE, 'q') + chntpw(FILE, 'y') + +def ogAddRegistryValue(path_mountpoint, str_hive, str_key, str_valuename, str_valuetype=''): + # Variables locales. + FILE = ogGetHivePath(path_mountpoint, str_hive) + if not FILE: + return + + # Determine the value type. + if str_valuetype.upper() == 'STRING' or str_valuetype == '': + TYPE = 1 + elif str_valuetype.upper() == 'BINARY': + TYPE = 3 + elif str_valuetype.upper() == 'DWORD': + TYPE = 4 + else: + ogRaiseError(OG_ERR_OUTOFLIMIT, str_valuetype) + return + + # Add the registry value. + chntpw(FILE, 'cd', str_key.rsplit('\\', 1)[0]) + chntpw(FILE, 'nv', str_valuename.rsplit('\\', 1)[-1], TYPE) + chntpw(FILE, 'q') + chntpw(FILE, 'y') + +def ogDeleteRegistryKey(path_mountpoint, str_hive, str_key): + # Variables locales. + FILE = ogGetHivePath(path_mountpoint, str_hive) + if not FILE: + return + + # Delete the registry key. + subprocess.run(['chntpw', FILE], input=f"cd {str_key.rsplit('\\', 1)[0]}\ndk {str_key.rsplit('\\', 1)[-1]}\nq\ny\n".encode(), timeout=5) + +def ogDeleteRegistryValue(path_mountpoint, str_hive, str_valuename): + # Variables locales. + FILE = ogGetHivePath(path_mountpoint, str_hive) + if not FILE: + return + + # Delete the registry value. + chntpw(FILE, 'cd', str_valuename.rsplit('\\', 1)[0]) + chntpw(FILE, 'dv', str_valuename.rsplit('\\', 1)[-1]) + chntpw(FILE, 'q') + chntpw(FILE, 'y') + +def ogGetHivePath(path_mountpoint, str_hive): + # Variables locales. + FILE = None + + # Camino del fichero de registro de usuario o de sistema (de menor a mayor prioridad). + FILE = ogGetPath(f"/{path_mountpoint}/Windows/System32/config/{str_hive}") + if not FILE: + FILE = ogGetPath(f"/{path_mountpoint}/Users/{str_hive}/NTUSER.DAT") + if not FILE: + FILE = ogGetPath(f"/{path_mountpoint}/winnt/system32/config/{str_hive}") + if not FILE: + FILE = ogGetPath(f"/{path_mountpoint}/Documents and Settings/{str_hive}/NTUSER.DAT") + if FILE and os.path.isfile(FILE): + return FILE + else: + ogRaiseError(OG_ERR_NOTFOUND, f"{path_mountpoint} {str_hive}") + return None + +def ogGetRegistryValue(path_mountpoint, str_hive, str_valuename): + # Variables locales. + FILE = ogGetHivePath(path_mountpoint, str_hive) + if not FILE: + return + + # Devolver el dato del valor de registro. + chntpw_cmd = f''' + chntpw "{FILE}" << EOT 2> /dev/null | awk '/> Value/ {{ + if (index($0, "REG_BINARY") > 0) {{ + data="" + }} else {{ + getline + data=$0 + }} + }} + /^:[0-9A-F]+ / {{ + data=data""substr($0, 9, 48) + }} + END {{ + print data + }}' + cd {str_valuename.rsplit('\\', 1)[0]} + cat {str_valuename.rsplit('\\', 1)[-1]} + q + EOT + ''' + subprocess.run(chntpw_cmd, shell=True, timeout=5) + +def ogListRegistryKeys(path_mountpoint, str_hive, str_key): + # Variables locales. + FILE = ogGetHivePath(path_mountpoint, str_hive) + if not FILE: + return + + # Devolver la lista de claves de registro. + chntpw_cmd = f''' + chntpw "{FILE}" << EOT 2> /dev/null | awk 'BEGIN {{FS="[<>]"}} $1~/^ $/ {{print $2}}' + ls {str_key} + q + EOT + ''' + subprocess.run(chntpw_cmd, shell=True, timeout=5) + +def ogListRegistryValues(path_mountpoint, str_hive, str_key): + # Variables locales. + FILE = ogGetHivePath(path_mountpoint, str_hive) + if not FILE: + return + + # Devolver la lista de valores de registro. + chntpw_cmd = f''' + chntpw "{FILE}" << EOT 2> /dev/null | awk 'BEGIN {{FS="[<>]"}} $1~/REG_/ {{print $2}}' + ls {str_key} + q + EOT + ''' + subprocess.run(chntpw_cmd, shell=True, timeout=5) + +def ogSetRegistryValue(path_mountpoint, str_hive, str_valuename, str_data): + # Variables locales. + FILE = ogGetHivePath(path_mountpoint, str_hive) + if not FILE: + return + + # Fichero temporal para componer la entrada al comando "chntpw". + tmpfile = "/tmp/chntpw$$" + try: + # Comprobar tipo de datos del valor del registro. + with open(tmpfile, 'w') as f: + f.write(f"ls {str_valuename.rsplit('\\', 1)[0]}\nq\n") + output = subprocess.check_output(['chntpw', FILE], input=open(tmpfile, 'rb'), stderr=subprocess.DEVNULL).decode() + if f"BINARY.*<{str_valuename.rsplit('\\', 1)[-1]}>" in output: + # Procesar tipo binario (incluir nº de bytes y líneas de 16 parejas hexadecimales). + if not re.match(r'^([0-9A-F]{2} )*$', str_data): + ogRaiseError(OG_ERR_FORMAT, f'"{str_data}"') + return + n = len(str_data) + 1 + with open(tmpfile, 'w') as f: + f.write(f"cd {str_valuename.rsplit('\\', 1)[0]}\ned {str_valuename.rsplit('\\', 1)[-1]}\n{int(n/3)}\n") + for i in range(0, n, 48): + f.write(f":{i//3:05x} {str_data[i:i+48]}\n") + f.write("s\nq\ny\n") + else: + # Cambiar el dato del valor de registro para cadenas y bytes. + with open(tmpfile, 'w') as f: + f.write(f"cd {str_valuename.rsplit('\\', 1)[0]}\ned {str_valuename.rsplit('\\', 1)[-1]}\n{str_data}\nq\ny\n") + + # Aplicar cambios. + subprocess.run(['chntpw', FILE], input=open(tmpfile, 'rb'), stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) + finally: + os.remove(tmpfile) diff --git a/client/shared/scripts/listSoftwareInfo.py b/client/shared/scripts/listSoftwareInfo.py old mode 100644 new mode 100755 index eaac54a..31c2e8d --- a/client/shared/scripts/listSoftwareInfo.py +++ b/client/shared/scripts/listSoftwareInfo.py @@ -1,56 +1,37 @@ import sys import os -import re -import subprocess +sys.path.append('/opt/opengnsys/lib/engine/bin') +from NetLib import ogGetIpAddress +from SystemLib import ogRaiseError +from InventoryLib import ogListSoftware -#!/usr/bin/env python3 +REDUCED = False -def main(): - PROG = os.path.basename(__file__) - REDUCED = "no" - - if len(sys.argv) > 1 and sys.argv[1] == "-r": - REDUCED = "yes" - sys.argv.pop(1) - - if len(sys.argv) != 3: - og_raise_error(1, f"Usage: {PROG} [-r] ndisk npart") - - ndisk = sys.argv[1] - npart = sys.argv[2] - - OGLOG = "/path/to/log" # Replace with actual log path - SERVERLOGDIR = None - - # Simulate the mount command and awk processing - mounts = subprocess.check_output(['mount']).decode('utf-8') - for line in mounts.splitlines(): - parts = line.split() - if len(parts) > 3 and parts[2] == OGLOG: - SERVERLOGDIR = parts[1] - break - - if SERVERLOGDIR is None: - og_raise_error(1, "Could not determine server log directory") - - SOFTFILE = f"soft-{og_get_ip_address()}-{ndisk}-{npart}" - softfile_path = os.path.join(OGLOG, SOFTFILE) - - try: - if REDUCED == "no": - software_list = og_list_software(ndisk, npart) - else: - software_list = "\n".join( - line for line in og_list_software(ndisk, npart).splitlines() - if not re.search(r"\(KB[0-9]{6}\)", line) - ) - - with open(softfile_path, 'w') as f: - f.write(software_list) - except Exception as e: - og_raise_error(1, str(e)) - - print(softfile_path) +if len(sys.argv) > 1 and sys.argv[1] == "-r": + REDUCED = True + sys.argv.pop(1) -if __name__ == "__main__": - main() \ No newline at end of file +if len(sys.argv) != 3: + og_raise_error("OG_ERR_FORMAT", "Usage: listSoftwareInfo [-r] disk partition") + sys.exit(1) + +disk = sys.argv[1] +partition = sys.argv[2] + +# Directorio del servidor donde se exportan los ficheros de registro +server_log_dir = "/mnt/oglog" # Assuming OGLOG is mounted at /mnt/oglog + +# Fichero de listado: soft-IP-disk-partition +soft_file = f"soft-{ogGetIpAddress()}-{disk}-{partition}" +log_path = os.path.join(server_log_dir, soft_file) + +# Redirigir salida al fichero de listado +with open(log_path, "w") as log_file: + if not REDUCED: + ogListSoftware(disk, partition, log_file) + else: + for line in og_list_software(disk, partition): + if "(KB" not in line: + log_file.write(line + "\n") + +print(log_path) From c24b7ca3371de4ea55b501a0f6ba68066e1a1972 Mon Sep 17 00:00:00 2001 From: Natalia Serrano Date: Tue, 5 Nov 2024 10:41:18 +0100 Subject: [PATCH 022/167] refs #1098 add ogDevToDisk() --- client/lib/engine/bin/DiskLib.py | 72 +++++++++++++++++--------------- 1 file changed, 39 insertions(+), 33 deletions(-) diff --git a/client/lib/engine/bin/DiskLib.py b/client/lib/engine/bin/DiskLib.py index 3ad3b05..7daa629 100644 --- a/client/lib/engine/bin/DiskLib.py +++ b/client/lib/engine/bin/DiskLib.py @@ -309,42 +309,48 @@ def ogDeletePartitionTable(*args): subprocess.run(["fdisk", DISK], input="o\nw", text=True) return -def ogDevToDisk(dev): - # Variables locales +#/** +# ogDevToDisk path_device | LABEL="str_label" | UUID="str_uuid" +#@brief Devuelve el nº de orden de dicso (y partición) correspondiente al nombre de fichero de dispositivo o a la etiqueta o UUID del sistema de archivos asociado. +#@param path_device Camino del fichero de dispositivo. +#@param str_label etiqueta de sistema de archivos. +#@param str_uuid UUID de sistema de archivos. +#@return int_ndisk (para dispositivo de disco) +#@return int_ndisk int_npartition (para dispositivo de partición). +#@exception OG_ERR_FORMAT Formato incorrecto. +#@exception OG_ERR_NOTFOUND Dispositivo no detectado. +#@note Solo se acepta en cada llamada 1 de los 3 tipos de parámetros. +#*/ ## +def ogDevToDisk(arg_dev): CACHEFILE = "/var/cache/disks.cfg" - PART = None - n = 1 - # Si se solicita, mostrar ayuda. - if dev == "help": - ogHelp("ogDevToDisk", "ogDevToDisk path_device | LABEL=str_label | UUID=str_uuid", - "ogDevToDisk /dev/sda => 1", - "ogDevToDisk /dev/sda1 => 1 1", - "ogDevToDisk LABEL=CACHE => 1 4") + if '=' in arg_dev: + # arg_dev is "FOO=bar" + cmd = None + if arg_dev.startswith("LABEL="): cmd = ['blkid', '-L', arg_dev[6:]] + elif arg_dev.startswith("PARTLABEL="): cmd = ['realpath', '/dev/disk/by-partlabel/'+arg_dev[11:]] + elif arg_dev.startswith("PARTUUID="): cmd = ['realpath', '/dev/disk/by-partuuid/'+arg_dev[10:]] + elif arg_dev.startswith("UUID="): cmd = ['blkid', '-U', arg_dev[5:]] + if not cmd: + ogRaiseError([], ogGlobals.OG_ERR_FORMAT, arg_dev) + return + DEV = subprocess.run (cmd, capture_output=True, text=True).stdout.strip() + else: + # arg_dev is "/dev/something" + DEV = arg_dev + + if not os.path.exists(DEV): + ogRaiseError([], ogGlobals.OG_ERR_NOTFOUND, arg_dev) return - # Error si no se recibe 1 parámetro. - if len(dev) != 1: - ogRaiseError(OG_ERR_FORMAT) - return - - # Obtener dispositivo a partir de camino, etiqueta o UUID. - DEV = dev[0] - if DEV.startswith("LABEL="): - DEV = subprocess.getoutput(f"blkid -L {DEV[6:]}") - elif DEV.startswith("PARTLABEL="): - DEV = subprocess.getoutput(f"realpath /dev/disk/by-partlabel/{DEV[11:]} 2>/dev/null") - elif DEV.startswith("PARTUUID="): - DEV = subprocess.getoutput(f"realpath /dev/disk/by-partuuid/{DEV[10:]} 2>/dev/null") - elif DEV.startswith("UUID="): - DEV = subprocess.getoutput(f"blkid -U {DEV[5:]}") - # Error si no es fichero de bloques o directorio (para LVM). - if not os.path.exists(DEV): - ogRaiseError(OG_ERR_NOTFOUND, dev) + m = os.stat (DEV, follow_symlinks=True).st_mode + if not stat.S_ISBLK (m) and not stat.S_ISDIR (m): + ogRaiseError([], ogGlobals.OG_ERR_NOTFOUND, arg_dev) return # Buscar en fichero de caché de discos. + PART = None if os.path.exists(CACHEFILE): with open(CACHEFILE, 'r') as f: for line in f: @@ -353,19 +359,19 @@ def ogDevToDisk(dev): PART = parts[0] break - if PART: - return PART + if PART: return PART # Si no se encuentra, procesa todos los discos para devolver su nº de orden y de partición. disks = ogDiskToDev() + n = 1 for d in disks: NVME_PREFIX = "p" if "nvme" in d else "" if DEV.startswith(d): return f"{n} {DEV[len(d) + len(NVME_PREFIX):]}" n += 1 - ogRaiseError(OG_ERR_NOTFOUND, dev) - return OG_ERR_NOTFOUND + ogRaiseError([], ogGlobals.OG_ERR_NOTFOUND, arg_dev) + return def _getAllDisks(): ret = [] @@ -464,7 +470,7 @@ def ogDiskToDev (arg_disk=None, arg_part=None): # No params: return all disks if arg_disk is None: - return " ".join(ALLDISKS) + return ALLDISKS # arg_disk is set: return it if arg_part is None: From 637bdb9295124f8ab089d289c2e11e4627a9b5ea Mon Sep 17 00:00:00 2001 From: Natalia Serrano Date: Tue, 5 Nov 2024 10:43:37 +0100 Subject: [PATCH 023/167] refs #1098 add ogFindCache() --- client/lib/engine/bin/CacheLib.py | 52 ++++++++++++++++++++++--------- 1 file changed, 38 insertions(+), 14 deletions(-) diff --git a/client/lib/engine/bin/CacheLib.py b/client/lib/engine/bin/CacheLib.py index b67d530..fdb5698 100644 --- a/client/lib/engine/bin/CacheLib.py +++ b/client/lib/engine/bin/CacheLib.py @@ -57,22 +57,46 @@ def ogDeleteCache(): except subprocess.CalledProcessError as e: raise RuntimeError(f"Error al borrar la partición de caché: {e}") +#/** +# ogFindCache +#@brief Detecta la partición caché local. +#@param No requiere parametros +#@return int_ndisk int_npart - devuelve el par nº de disco-nº de partición . +#@warning Si no hay cache no devuelve nada +#*/ ## def ogFindCache(): - """ - Encuentra la partición que se usa como caché. + # Obtener el dispositivo del sistema de archivos etiquetado como "CACHE". + PART = subprocess.run (['blkid', '-L', 'CACHE'], capture_output=True, text=True).stdout.strip() - :return: El nombre de la partición de caché si se encuentra, de lo contrario None. - """ - try: - for disk in [f"/dev/sd{chr(97 + i)}" for i in range(26)]: # /dev/sda to /dev/sdz - result = subprocess.run(["sfdisk", "-d", disk], capture_output=True, text=True, check=True) - if "CA00" in result.stdout: - cachepart = [line.split()[0] for line in result.stdout.splitlines() if "CA00" in line][0] - return cachepart - except subprocess.CalledProcessError: - return None + # En discos nvme con particiones GPT la partición se detecta usando el tag PARTLABEL + if not PART: + out = subprocess.run (['blkid', '-t', 'PARTLABEL=CACHE'], capture_output=True, text=True).stdout.strip() + PART = out.split (':')[0] - return None + # Si no se detecta, obtener particiones marcadas de tipo caché en discos MSDOS. + if not PART: + out = subprocess.run (['sfdisk', '-l'], capture_output=True, text=True).stdout.splitlines() + for l in out: + elems = l.split (maxsplit=5) + if 6 > len (elems): continue + if 'ca' in elems[5] or 'a7' in elems[5]: + PART=elems[0] + break + + # Por último revisar todos los discos GPT y obtener las particiones etiquetadas como caché. + if not PART: + PART = '' + for d in ogDiskToDev(): + out = subprocess.run (['sgdisk', '-p', d], capture_output=True, text=True).stdout.splitlines() + for l in out: + elems = l.split (maxsplit=6) + if 7 > len (elems): continue + if 'CACHE' in elems[6]: + p = 'p' if 'nvme' in d else '' + PART += f' {d}{p}{elems[0]}' + + if not PART: return + return ogDevToDisk (PART.split()[0]) # usar la 1ª partición encontrada. def ogFormatCache(): """ @@ -209,4 +233,4 @@ def ogUnmountCache(): raise RuntimeError(f"Error al desmontar la partición de caché: {e}") # Eliminar el enlace simbólico de /mnt/ParticiónCache. - os.remove(f"/mnt/{cachepart}") \ No newline at end of file + os.remove(f"/mnt/{cachepart}") From 9362ea1f0ae10cda8028b214f713626469e5e670 Mon Sep 17 00:00:00 2001 From: Natalia Serrano Date: Tue, 5 Nov 2024 12:54:06 +0100 Subject: [PATCH 024/167] refs #1099 do not import * --- client/lib/engine/bin/CacheLib.py | 8 +++----- client/lib/engine/bin/DiskLib.py | 25 ++++++++++++------------- client/lib/engine/bin/SystemLib.py | 11 ++++------- 3 files changed, 19 insertions(+), 25 deletions(-) diff --git a/client/lib/engine/bin/CacheLib.py b/client/lib/engine/bin/CacheLib.py index fdb5698..13913c5 100644 --- a/client/lib/engine/bin/CacheLib.py +++ b/client/lib/engine/bin/CacheLib.py @@ -5,9 +5,7 @@ import shutil import sys import platform -from FileSystemLib import * -from SystemLib import * -from DiskLib import * +import DiskLib print (">>>>>>>>>>>>>>>>>>>> Load ", __name__, " <<<<<<<<<<<<<<<<<<<<<<") @@ -86,7 +84,7 @@ def ogFindCache(): # Por último revisar todos los discos GPT y obtener las particiones etiquetadas como caché. if not PART: PART = '' - for d in ogDiskToDev(): + for d in DiskLib.ogDiskToDev(): out = subprocess.run (['sgdisk', '-p', d], capture_output=True, text=True).stdout.splitlines() for l in out: elems = l.split (maxsplit=6) @@ -96,7 +94,7 @@ def ogFindCache(): PART += f' {d}{p}{elems[0]}' if not PART: return - return ogDevToDisk (PART.split()[0]) # usar la 1ª partición encontrada. + return DiskLib.ogDevToDisk (PART.split()[0]) # usar la 1ª partición encontrada. def ogFormatCache(): """ diff --git a/client/lib/engine/bin/DiskLib.py b/client/lib/engine/bin/DiskLib.py index 7daa629..9ef5fcb 100644 --- a/client/lib/engine/bin/DiskLib.py +++ b/client/lib/engine/bin/DiskLib.py @@ -5,9 +5,8 @@ import os import stat from pathlib import Path -from CacheLib import * -from FileSystemLib import * -from SystemLib import * +import ogGlobals +import SystemLib print (">>>>>>>>>>>>>>>>>>>> Load ", __name__, " <<<<<<<<<<<<<<<<<<<<<<") @@ -332,7 +331,7 @@ def ogDevToDisk(arg_dev): elif arg_dev.startswith("PARTUUID="): cmd = ['realpath', '/dev/disk/by-partuuid/'+arg_dev[10:]] elif arg_dev.startswith("UUID="): cmd = ['blkid', '-U', arg_dev[5:]] if not cmd: - ogRaiseError([], ogGlobals.OG_ERR_FORMAT, arg_dev) + SystemLib.ogRaiseError([], ogGlobals.OG_ERR_FORMAT, arg_dev) return DEV = subprocess.run (cmd, capture_output=True, text=True).stdout.strip() else: @@ -340,13 +339,13 @@ def ogDevToDisk(arg_dev): DEV = arg_dev if not os.path.exists(DEV): - ogRaiseError([], ogGlobals.OG_ERR_NOTFOUND, arg_dev) + SystemLib.ogRaiseError([], ogGlobals.OG_ERR_NOTFOUND, arg_dev) return # Error si no es fichero de bloques o directorio (para LVM). m = os.stat (DEV, follow_symlinks=True).st_mode if not stat.S_ISBLK (m) and not stat.S_ISDIR (m): - ogRaiseError([], ogGlobals.OG_ERR_NOTFOUND, arg_dev) + SystemLib.ogRaiseError([], ogGlobals.OG_ERR_NOTFOUND, arg_dev) return # Buscar en fichero de caché de discos. @@ -370,7 +369,7 @@ def ogDevToDisk(arg_dev): return f"{n} {DEV[len(d) + len(NVME_PREFIX):]}" n += 1 - ogRaiseError([], ogGlobals.OG_ERR_NOTFOUND, arg_dev) + SystemLib.ogRaiseError([], ogGlobals.OG_ERR_NOTFOUND, arg_dev) return def _getAllDisks(): @@ -424,14 +423,14 @@ def ogDiskToDev (arg_disk=None, arg_part=None): if arg_part != None: arg_part = int (arg_part) except: - ogRaiseError([], ogGlobals.OG_ERR_FORMAT, f"{arg_disk} {arg_part}") + SystemLib.ogRaiseError([], ogGlobals.OG_ERR_FORMAT, f"{arg_disk} {arg_part}") return try: if arg_disk != None: arg_disk = int (arg_disk) except: - ogRaiseError([], ogGlobals.OG_ERR_FORMAT, arg_disk) + SystemLib.ogRaiseError([], ogGlobals.OG_ERR_FORMAT, arg_disk) return # Borrar fichero de caché de configuración si hay cambios en las particiones. @@ -475,11 +474,11 @@ def ogDiskToDev (arg_disk=None, arg_part=None): # arg_disk is set: return it if arg_part is None: if arg_disk > len (ALLDISKS): - ogRaiseError([], ogGlobals.OG_ERR_NOTFOUND, arg_disk) + SystemLib.ogRaiseError([], ogGlobals.OG_ERR_NOTFOUND, arg_disk) return disk = ALLDISKS[arg_disk-1] if not os.path.exists(disk): - ogRaiseError([], ogGlobals.OG_ERR_NOTFOUND, arg_disk) + SystemLib.ogRaiseError([], ogGlobals.OG_ERR_NOTFOUND, arg_disk) return # Actualizar caché de configuración y mostrar dispositivo. with open(CACHEFILE, 'a') as f: @@ -489,7 +488,7 @@ def ogDiskToDev (arg_disk=None, arg_part=None): # arg_disk and arg_part are set: there are several possibilities disk = ALLDISKS[arg_disk-1] if not os.path.exists(disk): - ogRaiseError([], ogGlobals.OG_ERR_NOTFOUND, arg_disk) + SystemLib.ogRaiseError([], ogGlobals.OG_ERR_NOTFOUND, arg_disk) return # Plain partition @@ -535,7 +534,7 @@ def ogDiskToDev (arg_disk=None, arg_part=None): i += 1 if not part: - ogRaiseError([], ogGlobals.OG_ERR_NOTFOUND, f"{arg_disk} {arg_part}") + SystemLib.ogRaiseError([], ogGlobals.OG_ERR_NOTFOUND, f"{arg_disk} {arg_part}") return # Actualizar caché de configuración y mostrar dispositivo. diff --git a/client/lib/engine/bin/SystemLib.py b/client/lib/engine/bin/SystemLib.py index 0781f1e..c26eb42 100755 --- a/client/lib/engine/bin/SystemLib.py +++ b/client/lib/engine/bin/SystemLib.py @@ -4,12 +4,10 @@ from zoneinfo import ZoneInfo import sys import os import shutil +import inspect import ogGlobals -#from engine.DiskLib import * -#from engine.CacheLib import * -#from engine.StringLib import * -from StringLib import * +import StringLib #NODEBUGFUNCTIONS, OGIMG, OG_ERR_CACHESIZE, OG_ERR_NOTCACHE, OG_ERR_NOTWRITE, OG_ERR_FILESYS #OG_ERR_REPO, OG_ERR_NOTOS, OG_ERR_NOGPT, OG_ERR_OUTOFLIMIT, OG_ERR_IMAGE, OG_ERR_CACHE @@ -135,7 +133,6 @@ def ogGetCaller(): return os.path.basename(caller) -import inspect #/** # ogHelp ["str_function" ["str_format" ["str_example" ... ]]] #@brief Muestra mensaje de ayuda para una función determinda. @@ -220,8 +217,8 @@ def ogRaiseError (logtypes, code, msg): str_call_stack = ' '.join (call_stack) if code == ogGlobals.OG_ERR_FORMAT or \ - ogCheckStringInGroup (str_call_stack, ogGlobals.NODEBUGFUNCTIONS) or \ - not ogCheckStringInGroup (call_stack[0], ogGlobals.NODEBUGFUNCTIONS): + StringLib.ogCheckStringInGroup (str_call_stack, ogGlobals.NODEBUGFUNCTIONS) or \ + not StringLib.ogCheckStringInGroup (call_stack[0], ogGlobals.NODEBUGFUNCTIONS): ogEcho (logtypes, "error", f"{str_call_stack.replace(' ', '<-')}: {MSG}") return code From 9953807e79c3a90f80d5394b4b7566f7e834f6da Mon Sep 17 00:00:00 2001 From: Natalia Serrano Date: Tue, 5 Nov 2024 13:58:09 +0100 Subject: [PATCH 025/167] refs #1098 add ogGetFsType() --- client/lib/engine/bin/FileSystemLib.py | 64 ++++++++++++++------------ 1 file changed, 34 insertions(+), 30 deletions(-) diff --git a/client/lib/engine/bin/FileSystemLib.py b/client/lib/engine/bin/FileSystemLib.py index 6f7eddf..72914af 100644 --- a/client/lib/engine/bin/FileSystemLib.py +++ b/client/lib/engine/bin/FileSystemLib.py @@ -1,9 +1,10 @@ import subprocess import sys -from SystemLib import * -from DiskLib import * -from CacheLib import * +import ogGlobals +import SystemLib +import DiskLib +import CacheLib print (">>>>>>>>>>>>>>>>>>>> Load ", __name__, " <<<<<<<<<<<<<<<<<<<<<<") @@ -336,43 +337,47 @@ def ogGetFsSize(int_ndisk, int_npartition, str_unit=None): # Devolver el tamaño (quitar decimales si son 0). return int(SIZE) if SIZE.is_integer() else SIZE -def ogGetFsType(int_ndisk, int_nfilesys): - # Si se solicita, mostrar ayuda. - if len(sys.argv) == 3 and sys.argv[2] == "help": - ogHelp("ogGetFsType", "ogGetFsType int_ndisk int_nfilesys", "ogGetFsType 1 1") - return +#/** +# ogGetFsType int_ndisk int_nfilesys +#@brief Devuelve el mnemonico con el tipo de sistema de archivos. +#@param int_ndisk nº de orden del disco +#@param int_nfilesys nº de orden del sistema de archivos +#@return Mnemonico +#@note Mnemonico: { EXT2, EXT3, EXT4, BTRFS, REISERFS, XFS, JFS, FAT12, FAT16, FAT32, NTFS, LINUX-SWAP, LINUX-LVM, LINUX-RAID, HFS, HFSPLUS, CACHE } +#@exception OG_ERR_FORMAT Formato incorrecto. +#@exception OG_ERR_NOTFOUND Disco o particion no corresponden con un dispositivo. +#*/ ## +def ogGetFsType(disk, part): + PART = DiskLib.ogDiskToDev(disk, part) + if not PART: return - # Error si no se reciben 2 parámetros. - if len(sys.argv) != 3: - ogRaiseError(OG_ERR_FORMAT) - return - - # Obtener partición. - PART = ogDiskToDev(int_ndisk, int_nfilesys) - if not PART: - return - - # Detectar tipo de sistema de archivo (independientemente del tipo de partición). + TYPE = None if PART.startswith("/"): - result = subprocess.run(["blkid", "-o", "export", PART], capture_output=True, text=True) - TYPE = "" - for line in result.stdout.split("\n"): + out = subprocess.run(["blkid", "-o", "export", PART], capture_output=True, text=True).stdout.splitlines() + for line in out: if line.startswith("TYPE="): TYPE = line.split("=")[1].upper() break else: - subprocess.run(["zfs", "mount", PART], stderr=subprocess.DEVNULL) - result = subprocess.run(["mount"], capture_output=True, text=True) - TYPE = "" - for line in result.stdout.split("\n"): + try: + subprocess.run(["zfs", "mount", PART]) + except FileNotFoundError: + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTEXEC, 'zfs') + return + out = subprocess.run(["mount"], capture_output=True, text=True).stdout.splitlines() + for line in out: if line.startswith(PART): TYPE = line.split()[4].upper() break + if not TYPE: + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTFOUND, f'{disk} {part}') + return + # Componer valores correctos. if TYPE == "EXT4": - if f"{int_ndisk} {int_nfilesys}" == ogFindCache(): - if ogIsFormated(int_ndisk, int_nfilesys): + if f"{disk} {part}" == CacheLib.ogFindCache(): + if ogIsFormated(disk, part): TYPE = "CACHE" elif TYPE == "VFAT": result = subprocess.run(["blkid", "-po", "export", PART], capture_output=True, text=True) @@ -391,8 +396,7 @@ def ogGetFsType(int_ndisk, int_nfilesys): elif "_MEMBER" in TYPE: TYPE = TYPE.replace("_MEMBER", "") - if TYPE: - return TYPE + return TYPE def ogGetMountPoint(int_ndisk, int_nfilesys): # Si se solicita, mostrar ayuda. From d46ab35bd6054a98927e0b4419d941c12983bba0 Mon Sep 17 00:00:00 2001 From: aguerrero Date: Wed, 6 Nov 2024 04:30:53 +0000 Subject: [PATCH 026/167] refs #1099 The syntax for calling libraries has been modified --- client/lib/engine/bin/CacheLib.py | 0 client/lib/engine/bin/DiskLib.py | 127 +++++++++++----------- client/lib/engine/bin/FileLib.py | 63 +++++------ client/lib/engine/bin/FileSystemLib.py | 0 client/lib/engine/bin/NetLib.py | 34 +++--- client/lib/engine/bin/RegistryLib.py | 19 ++-- client/lib/engine/bin/__init__.py | 0 client/lib/engine/bin/lang_ca_ES.py | 0 client/lib/engine/bin/lang_en_GB.py | 0 client/lib/engine/bin/lang_es_ES.py | 0 client/lib/engine/bin/ogGlobals.py | 0 client/shared/scripts/listSoftwareInfo.py | 55 +++++----- 12 files changed, 152 insertions(+), 146 deletions(-) mode change 100644 => 100755 client/lib/engine/bin/CacheLib.py mode change 100644 => 100755 client/lib/engine/bin/DiskLib.py mode change 100644 => 100755 client/lib/engine/bin/FileSystemLib.py mode change 100644 => 100755 client/lib/engine/bin/__init__.py mode change 100644 => 100755 client/lib/engine/bin/lang_ca_ES.py mode change 100644 => 100755 client/lib/engine/bin/lang_en_GB.py mode change 100644 => 100755 client/lib/engine/bin/lang_es_ES.py mode change 100644 => 100755 client/lib/engine/bin/ogGlobals.py diff --git a/client/lib/engine/bin/CacheLib.py b/client/lib/engine/bin/CacheLib.py old mode 100644 new mode 100755 diff --git a/client/lib/engine/bin/DiskLib.py b/client/lib/engine/bin/DiskLib.py old mode 100644 new mode 100755 index 9ef5fcb..d26ca4d --- a/client/lib/engine/bin/DiskLib.py +++ b/client/lib/engine/bin/DiskLib.py @@ -7,8 +7,7 @@ from pathlib import Path import ogGlobals import SystemLib - -print (">>>>>>>>>>>>>>>>>>>> Load ", __name__, " <<<<<<<<<<<<<<<<<<<<<<") +import CacheLib def parted(*args): parted_path = shutil.which("parted") @@ -33,13 +32,13 @@ def ogCreatePartitions(*args): # Si se solicita, mostrar ayuda. if len(args) == 1 and args[0] == "help": - ogHelp('ogCreatePartitions', 'ogCreatePartitions int_ndisk str_parttype:int_partsize ...', + SystemLib.ogHelp('ogCreatePartitions', 'ogCreatePartitions int_ndisk str_parttype:int_partsize ...', 'ogCreatePartitions 1 NTFS:10000000 EXT3:5000000 LINUX-SWAP:1000000') return # Error si no se reciben al menos 2 parámetros. if len(args) < 2: - ogRaiseError(OG_ERR_FORMAT) + SystemLib.ogRaiseError(OG_ERR_FORMAT) return # Nº total de sectores, para evitar desbordamiento (evitar redondeo). @@ -54,15 +53,15 @@ def ogCreatePartitions(*args): ogCreateGptPartitions(*args) return elif PTTYPE != "MSDOS": - ogRaiseError(OG_ERR_PARTITION, PTTYPE) + SystemLib.ogRaiseError(OG_ERR_PARTITION, PTTYPE) return SECTORS = ogGetLastSector(ND) # Se recalcula el nº de sectores del disco 1, si existe partición de caché. - CACHEPART = ogFindCache() + CACHEPART = CacheLib.ogFindCache() if CACHEPART and ND == CACHEPART.split()[0]: - CACHESIZE = int(ogGetCacheSize()) * 2 + CACHESIZE = int(CacheLib.ogGetCacheSize()) * 2 # Sector de inicio (la partición 1 empieza en el sector 63). IODISCO = ogDiskToDev(ND) @@ -120,7 +119,7 @@ def ogCreatePartitions(*args): os.remove(tmpsfdisk) if CACHESIZE: - ogMountCache() + CacheLib.ogMountCache() return 0 def ogCreateGptPartitions(*args): @@ -129,13 +128,13 @@ def ogCreateGptPartitions(*args): # Si se solicita, mostrar ayuda. if len(args) == 1 and args[0] == "help": - ogHelp('ogCreateGptPartitions', 'ogCreateGptPartitions int_ndisk str_parttype:int_partsize ...', + SystemLib.ogHelp('ogCreateGptPartitions', 'ogCreateGptPartitions int_ndisk str_parttype:int_partsize ...', 'ogCreateGptPartitions 1 NTFS:10000000 EXT3:5000000 LINUX-SWAP:1000000') return # Error si no se reciben menos de 2 parámetros. if len(args) < 2: - ogRaiseError(OG_ERR_FORMAT) + SystemLib.ogRaiseError(OG_ERR_FORMAT) return # Nº total de sectores, para evitar desbordamiento (evitar redondeo). @@ -148,7 +147,7 @@ def ogCreateGptPartitions(*args): SECTORS = ogGetLastSector(ND) # Se recalcula el nº de sectores del disco si existe partición de caché. - CACHEPART = ogFindCache() + CACHEPART = CacheLib.ogFindCache() if ND == CACHEPART.split()[0]: CACHESIZE = int(ogGetCacheSize()) * 2 if CACHESIZE: @@ -172,7 +171,7 @@ def ogCreateGptPartitions(*args): # Error si la partición es extendida (no válida en discos GPT). if TYPE == "EXTENDED": - ogRaiseError(OG_ERR_PARTITION, "EXTENDED") + SystemLib.ogRaiseError(OG_ERR_PARTITION, "EXTENDED") return # Comprobar si existe la particion actual, capturamos su tamaño para ver si cambio o no @@ -191,7 +190,7 @@ def ogCreateGptPartitions(*args): # Error si se supera el nº total de sectores. if START > SECTORS: - ogRaiseError(OG_ERR_FORMAT, f"{START//2} > {SECTORS//2}") + SystemLib.ogRaiseError(OG_ERR_FORMAT, f"{START//2} > {SECTORS//2}") return PART += 1 @@ -200,7 +199,7 @@ def ogCreateGptPartitions(*args): # Desmontar los sistemas de archivos del disco antes de realizar las operaciones. ogUnmountAll(ND) if CACHESIZE: - ogUnmountCache() + CacheLib.ogUnmountCache() # Si la tabla de particiones no es valida, volver a generarla. ogCreatePartitionTable(ND) @@ -211,7 +210,7 @@ def ogCreateGptPartitions(*args): subprocess.run(["partprobe", DISK], stderr=subprocess.DEVNULL) if CACHESIZE: - ogMountCache() + CacheLib.ogMountCache() return 0 def ogCreatePartitionTable(*args): @@ -220,7 +219,7 @@ def ogCreatePartitionTable(*args): # Si se solicita, mostrar ayuda. if len(args) == 1 and args[0] == "help": - ogHelp('ogCreatePartitionTable', 'ogCreatePartitionTable int_ndisk [str_partype]', + SystemLib.ogHelp('ogCreatePartitionTable', 'ogCreatePartitionTable int_ndisk [str_partype]', 'ogCreatePartitionTable 1 GPT', 'ogCreatePartitionTable 1') return @@ -230,7 +229,7 @@ def ogCreatePartitionTable(*args): elif len(args) == 2: CREATEPTT = args[1] else: - ogRaiseError(OG_ERR_FORMAT) + SystemLib.ogRaiseError(OG_ERR_FORMAT) return # Capturamos el tipo de tabla de particiones actual @@ -287,12 +286,12 @@ def ogDeletePartitionTable(*args): # Si se solicita, mostrar ayuda. if len(args) == 1 and args[0] == "help": - ogHelp('ogDeletePartitionTable', 'ogDeletePartitionTable int_ndisk', 'ogDeletePartitionTable 1') + SystemLib.ogHelp('ogDeletePartitionTable', 'ogDeletePartitionTable int_ndisk', 'ogDeletePartitionTable 1') return # Error si no se reciben 1 parámetros. if len(args) != 1: - ogRaiseError(OG_ERR_FORMAT) + SystemLib.ogRaiseError(OG_ERR_FORMAT) return # Obteniendo Identificador linux del disco. @@ -549,12 +548,12 @@ def ogGetDiskSize(*args): # Si se solicita, mostrar ayuda. if len(args) == 1 and args[0] == "help": - ogHelp('ogGetDiskSize', 'ogGetDiskSize int_ndisk', 'ogGetDiskSize 1 => 244198584') + SystemLib.ogHelp('ogGetDiskSize', 'ogGetDiskSize int_ndisk', 'ogGetDiskSize 1 => 244198584') return # Error si no se recibe 1 parámetro. if len(args) != 1: - ogRaiseError(OG_ERR_FORMAT) + SystemLib.ogRaiseError(OG_ERR_FORMAT) return # Obtener el tamaño del disco. @@ -574,12 +573,12 @@ def ogGetDiskType(*args): # Si se solicita, mostrar ayuda. if len(args) == 1 and args[0] == "help": - ogHelp('ogGetDiskType', 'ogGetDiskType path_device', 'ogGetDiskType /dev/sdb => USB') + SystemLib.ogHelp('ogGetDiskType', 'ogGetDiskType path_device', 'ogGetDiskType /dev/sdb => USB') return # Error si no se recibe 1 parámetro. if len(args) != 1: - ogRaiseError(OG_ERR_FORMAT) + SystemLib.ogRaiseError(OG_ERR_FORMAT) return # Obtener el driver del dispositivo de bloques. @@ -626,7 +625,7 @@ def ogGetLastSector(*args): # Si se solicita, mostrar ayuda. if len(args) == 1 and args[0] == "help": - ogHelp("ogGetLastSector", "ogGetLastSector int_ndisk [int_npart]", + SystemLib.ogHelp("ogGetLastSector", "ogGetLastSector int_ndisk [int_npart]", "ogGetLastSector 1 => 488392064", "ogGetLastSector 1 1 => 102400062") return @@ -646,7 +645,7 @@ def ogGetLastSector(*args): return LASTSECTOR = subprocess.getoutput(f"sgdisk -p {DISK} | awk -v P='{args[1]}' '{{if ($1==P) print $3}}'") else: # Error si se reciben más parámetros. - ogRaiseError(OG_ERR_FORMAT) + SystemLib.ogRaiseError(OG_ERR_FORMAT) return print(LASTSECTOR) @@ -658,12 +657,12 @@ def ogGetPartitionActive(*args): # Si se solicita, mostrar ayuda. if len(args) == 1 and args[0] == "help": - ogHelp('ogGetPartitionActive', 'ogGetPartitionActive int_ndisk', 'ogGetPartitionActive 1 => 1') + SystemLib.ogHelp('ogGetPartitionActive', 'ogGetPartitionActive int_ndisk', 'ogGetPartitionActive 1 => 1') return # Error si no se recibe 1 parámetro. if len(args) != 1: - ogRaiseError(OG_ERR_FORMAT) + SystemLib.ogRaiseError(OG_ERR_FORMAT) return # Comprobar que el disco existe y listar su partición activa. @@ -681,12 +680,12 @@ def ogGetPartitionId(*args): # Si se solicita, mostrar ayuda. if len(args) == 1 and args[0] == "help": - ogHelp('ogGetPartitionId', 'ogGetPartitionId int_ndisk int_npartition', 'ogGetPartitionId 1 1 => 7') + SystemLib.ogHelp('ogGetPartitionId', 'ogGetPartitionId int_ndisk int_npartition', 'ogGetPartitionId 1 1 => 7') return # Error si no se reciben 2 parámetros. if len(args) != 2: - ogRaiseError(OG_ERR_FORMAT) + SystemLib.ogRaiseError(OG_ERR_FORMAT) return # Detectar y mostrar el id. de tipo de partición. @@ -715,12 +714,12 @@ def ogGetPartitionSize(*args): # Si se solicita, mostrar ayuda. if len(args) == 1 and args[0] == "help": - ogHelp('ogGetPartitionSize', 'ogGetPartitionSize int_ndisk int_npartition', 'ogGetPartitionSize 1 1 => 10000000') + SystemLib.ogHelp('ogGetPartitionSize', 'ogGetPartitionSize int_ndisk int_npartition', 'ogGetPartitionSize 1 1 => 10000000') return # Error si no se reciben 2 parámetros. if len(args) != 2: - ogRaiseError(OG_ERR_FORMAT) + SystemLib.ogRaiseError(OG_ERR_FORMAT) return # Devolver tamaño de partición, del volumen lógico o del sistema de archivos (para ZFS). @@ -741,12 +740,12 @@ def ogGetPartitionsNumber(*args): # Si se solicita, mostrar ayuda. if len(args) == 1 and args[0] == "help": - ogHelp('ogGetPartitionsNumber', 'ogGetPartitionsNumber int_ndisk', 'ogGetPartitionsNumber 1 => 3') + SystemLib.ogHelp('ogGetPartitionsNumber', 'ogGetPartitionsNumber int_ndisk', 'ogGetPartitionsNumber 1 => 3') return # Error si no se recibe 1 parámetro. if len(args) != 1: - ogRaiseError(OG_ERR_FORMAT) + SystemLib.ogRaiseError(OG_ERR_FORMAT) return # Contar el número de veces que aparece el disco en su lista de particiones. @@ -776,12 +775,12 @@ def ogGetPartitionTableType(*args): # Si se solicita, mostrar ayuda. if len(args) == 1 and args[0] == "help": - ogHelp('ogGetPartitionTableType', 'ogGetPartitionTableType int_ndisk', 'ogGetPartitionTableType 1 => MSDOS') + SystemLib.ogHelp('ogGetPartitionTableType', 'ogGetPartitionTableType int_ndisk', 'ogGetPartitionTableType 1 => MSDOS') return # Error si no se recibe 1 parámetro. if len(args) != 1: - ogRaiseError(OG_ERR_FORMAT) + SystemLib.ogRaiseError(OG_ERR_FORMAT) return # Sustituye n de disco por su dispositivo. @@ -815,12 +814,12 @@ def ogGetPartitionType(*args): # Si se solicita, mostrar ayuda. if len(args) == 1 and args[0] == "help": - ogHelp('ogGetPartitionType', 'ogGetPartitionType int_ndisk int_npartition', 'ogGetPartitionType 1 1 => NTFS') + SystemLib.ogHelp('ogGetPartitionType', 'ogGetPartitionType int_ndisk int_npartition', 'ogGetPartitionType 1 1 => NTFS') return # Error si no se reciben 2 parámetros. if len(args) != 2: - ogRaiseError(OG_ERR_FORMAT) + SystemLib.ogRaiseError(OG_ERR_FORMAT) return # Detectar id. de tipo de partición y codificar al mnemónico. @@ -839,12 +838,12 @@ def ogHidePartition(*args): # Si se solicita, mostrar ayuda. if len(args) == 1 and args[0] == "help": - ogHelp('ogHidePartition', 'ogHidePartition int_ndisk int_npartition', 'ogHidePartition 1 1') + SystemLib.ogHelp('ogHidePartition', 'ogHidePartition int_ndisk int_npartition', 'ogHidePartition 1 1') return # Error si no se reciben 2 parámetros. if len(args) != 2: - ogRaiseError(OG_ERR_FORMAT) + SystemLib.ogRaiseError(OG_ERR_FORMAT) return # Obtener el dispositivo de la partición. @@ -865,7 +864,7 @@ def ogHidePartition(*args): elif TYPE == "WINDOWS": NEWTYPE = "WIN-RESERV" else: - ogRaiseError(OG_ERR_PARTITION, TYPE) + SystemLib.ogRaiseError(OG_ERR_PARTITION, TYPE) return # Cambiar tipo de partición. @@ -978,7 +977,7 @@ def ogIsDiskLocked(*args): # Si se solicita, mostrar ayuda. if len(args) == 1 and args[0] == "help": - ogHelp('ogIsDiskLocked', 'ogIsDiskLocked int_ndisk', 'if ogIsDiskLocked(1): ...') + SystemLib.ogHelp('ogIsDiskLocked', 'ogIsDiskLocked int_ndisk', 'if ogIsDiskLocked(1): ...') return # Falso, en caso de error. @@ -1002,12 +1001,12 @@ def ogListPartitions(*args): # Si se solicita, mostrar ayuda. if len(args) == 1 and args[0] == "help": - ogHelp('ogListPartitions', 'ogListPartitions int_ndisk', 'ogListPartitions 1 => NTFS:10000000 EXT3:5000000 LINUX-SWAP:1000000') + SystemLib.ogHelp('ogListPartitions', 'ogListPartitions int_ndisk', 'ogListPartitions 1 => NTFS:10000000 EXT3:5000000 LINUX-SWAP:1000000') return # Error si no se recibe 1 parámetro. if len(args) != 1: - ogRaiseError(OG_ERR_FORMAT) + SystemLib.ogRaiseError(OG_ERR_FORMAT) return # Procesar la salida de parted. @@ -1029,7 +1028,7 @@ def ogListPrimaryPartitions(*args): # Si se solicita, mostrar ayuda. if len(args) == 1 and args[0] == "help": - ogHelp('ogListPrimaryPartitions', 'ogListPrimaryPartitions int_ndisk', 'ogListPrimaryPartitions 1 => NTFS:10000000 EXT3:5000000 EXTENDED:1000000') + SystemLib.ogHelp('ogListPrimaryPartitions', 'ogListPrimaryPartitions int_ndisk', 'ogListPrimaryPartitions 1 => NTFS:10000000 EXT3:5000000 EXTENDED:1000000') return PTTYPE = ogGetPartitionTableType(args[0]) @@ -1052,7 +1051,7 @@ def ogListLogicalPartitions(*args): # Si se solicita, mostrar ayuda. if len(args) == 1 and args[0] == "help": - ogHelp('ogListLogicalPartitions', 'ogListLogicalPartitions int_ndisk', 'ogListLogicalPartitions 1 => LINUX-SWAP:999998') + SystemLib.ogHelp('ogListLogicalPartitions', 'ogListLogicalPartitions int_ndisk', 'ogListLogicalPartitions 1 => LINUX-SWAP:999998') return PTTYPE = ogGetPartitionTableType(args[0]) @@ -1071,12 +1070,12 @@ def ogLockDisk(*args): # Si se solicita, mostrar ayuda. if len(args) == 1 and args[0] == "help": - ogHelp('ogLockDisk', 'ogLockDisk int_ndisk', 'ogLockDisk 1') + SystemLib.ogHelp('ogLockDisk', 'ogLockDisk int_ndisk', 'ogLockDisk 1') return # Error si no se recibe 1 parámetro. if len(args) != 1: - ogRaiseError(OG_ERR_FORMAT) + SystemLib.ogRaiseError(OG_ERR_FORMAT) return # Obtener partición. @@ -1095,12 +1094,12 @@ def ogSetPartitionActive(*args): # Si se solicita, mostrar ayuda. if len(args) == 1 and args[0] == "help": - ogHelp('ogSetPartitionActive', 'ogSetPartitionActive int_ndisk int_npartition', 'ogSetPartitionActive 1 1') + SystemLib.ogHelp('ogSetPartitionActive', 'ogSetPartitionActive int_ndisk int_npartition', 'ogSetPartitionActive 1 1') return # Error si no se reciben 2 parámetros. if len(args) != 2: - ogRaiseError(OG_ERR_FORMAT) + SystemLib.ogRaiseError(OG_ERR_FORMAT) return # Comprobar que el disco existe y activar la partición indicada. @@ -1122,12 +1121,12 @@ def ogSetPartitionId(*args): # Si se solicita, mostrar ayuda. if len(args) == 1 and args[0] == "help": - ogHelp('ogSetPartitionId', 'ogSetPartitionId int_ndisk int_npartition hex_partid', 'ogSetPartitionId 1 1 7') + SystemLib.ogHelp('ogSetPartitionId', 'ogSetPartitionId int_ndisk int_npartition hex_partid', 'ogSetPartitionId 1 1 7') return # Error si no se reciben 3 parámetros. if len(args) != 3: - ogRaiseError(OG_ERR_FORMAT) + SystemLib.ogRaiseError(OG_ERR_FORMAT) return # Sustituye nº de disco y nº partición por su dispositivo. @@ -1140,7 +1139,7 @@ def ogSetPartitionId(*args): # Error si el id. de partición no es hexadecimal. ID = args[2].upper() if not re.match("^[0-9A-F]+$", ID): - ogRaiseError(OG_ERR_OUTOFLIMIT, args[2]) + SystemLib.ogRaiseError(OG_ERR_OUTOFLIMIT, args[2]) return # Elección del tipo de partición. @@ -1150,14 +1149,14 @@ def ogSetPartitionId(*args): elif PTTYPE == "MSDOS": subprocess.run(["sfdisk", f"--id", DISK, args[1], ID], stderr=subprocess.DEVNULL) else: - ogRaiseError(OG_ERR_OUTOFLIMIT, f"{args[0]},{PTTYPE}") + SystemLib.ogRaiseError(OG_ERR_OUTOFLIMIT, f"{args[0]},{PTTYPE}") return # MSDOS) Correcto si fdisk sin error o con error pero realiza Syncing if subprocess.run(["partprobe", DISK], stderr=subprocess.DEVNULL).returncode == 0: return else: - ogRaiseError(OG_ERR_PARTITION, f"{args[0]},{args[1]},{args[2]}") + SystemLib.ogRaiseError(OG_ERR_PARTITION, f"{args[0]},{args[1]},{args[2]}") return def ogSetPartitionSize(*args): @@ -1168,12 +1167,12 @@ def ogSetPartitionSize(*args): # Si se solicita, mostrar ayuda. if len(args) == 1 and args[0] == "help": - ogHelp('ogSetPartitionSize', 'ogSetPartitionSize int_ndisk int_npartition int_size', 'ogSetPartitionSize 1 1 10000000') + SystemLib.ogHelp('ogSetPartitionSize', 'ogSetPartitionSize int_ndisk int_npartition int_size', 'ogSetPartitionSize 1 1 10000000') return # Error si no se reciben 3 parámetros. if len(args) != 3: - ogRaiseError(OG_ERR_FORMAT) + SystemLib.ogRaiseError(OG_ERR_FORMAT) return # Obtener el tamaño de la partición. @@ -1199,12 +1198,12 @@ def ogSetPartitionType(*args): # Si se solicita, mostrar ayuda. if len(args) == 1 and args[0] == "help": - ogHelp('ogSetPartitionType', 'ogSetPartitionType int_ndisk int_npartition str_type', 'ogSetPartitionType 1 1 NTFS') + SystemLib.ogHelp('ogSetPartitionType', 'ogSetPartitionType int_ndisk int_npartition str_type', 'ogSetPartitionType 1 1 NTFS') return # Error si no se reciben 3 parámetros. if len(args) != 3: - ogRaiseError(OG_ERR_FORMAT) + SystemLib.ogRaiseError(OG_ERR_FORMAT) return # Sustituye nº de disco por su dispositivo. @@ -1222,7 +1221,7 @@ def ogSetPartitionType(*args): TYPE = args[2] ID = ogTypeToId(TYPE, PTTYPE) if ID is None: - ogRaiseError(OG_ERR_FORMAT, f"{TYPE},{PTTYPE}") + SystemLib.ogRaiseError(OG_ERR_FORMAT, f"{TYPE},{PTTYPE}") return ogSetPartitionId(args[0], args[1], ID) @@ -1348,12 +1347,12 @@ def ogUnhidePartition(*args): # Si se solicita, mostrar ayuda. if len(args) == 1 and args[0] == "help": - ogHelp('ogUnhidePartition', 'ogUnhidePartition int_ndisk int_npartition', 'ogUnhidePartition 1 1') + SystemLib.ogHelp('ogUnhidePartition', 'ogUnhidePartition int_ndisk int_npartition', 'ogUnhidePartition 1 1') return # Error si no se reciben 2 parámetros. if len(args) != 2: - ogRaiseError(OG_ERR_FORMAT) + SystemLib.ogRaiseError(OG_ERR_FORMAT) return PART = ogDiskToDev(args[0], args[1]) @@ -1373,7 +1372,7 @@ def ogUnhidePartition(*args): elif TYPE == "WIN-RESERV": NEWTYPE = "WINDOWS" else: - ogRaiseError(OG_ERR_PARTITION, TYPE) + SystemLib.ogRaiseError(OG_ERR_PARTITION, TYPE) return # Cambiar tipo de partición. @@ -1387,12 +1386,12 @@ def ogUnlockDisk(*args): # Si se solicita, mostrar ayuda. if len(args) == 1 and args[0] == "help": - ogHelp('ogUnlockDisk', 'ogUnlockDisk int_ndisk', 'ogUnlockDisk 1') + SystemLib.ogHelp('ogUnlockDisk', 'ogUnlockDisk int_ndisk', 'ogUnlockDisk 1') return # Error si no se recibe 1 parámetro. if len(args) != 1: - ogRaiseError(OG_ERR_FORMAT) + SystemLib.ogRaiseError(OG_ERR_FORMAT) return # Obtener partición. diff --git a/client/lib/engine/bin/FileLib.py b/client/lib/engine/bin/FileLib.py index 5ff7f36..868e4eb 100755 --- a/client/lib/engine/bin/FileLib.py +++ b/client/lib/engine/bin/FileLib.py @@ -1,8 +1,9 @@ import subprocess import os import shutil - -print (">>>>>>>>>>>>>>>>>>>> Load ", __name__, " <<<<<<<<<<<<<<<<<<<<<<") +import SystemLib +import CacheLib +import FileSystemLib def ogCalculateChecksum(*args): # Check if help is requested @@ -14,7 +15,7 @@ def ogCalculateChecksum(*args): # Get the file path file_path = ogGetPath(*args) if not file_path: - ogRaiseError(OG_ERR_NOTFOUND, *args) + SystemLib.ogRaiseError(OG_ERR_NOTFOUND, *args) return # Calculate the checksum @@ -27,7 +28,7 @@ def ogCompareChecksumFiles(*args): # Variables locales. ARGS = args if "help" in args: - ogHelp("$FUNCNAME", "$FUNCNAME [ str_repo | int_ndisk int_npartition ] path_filepath", "if $FUNCNAME REPO ubuntu.img CACHE ubuntu.img; then ...; fi") + SystemLib.ogHelp("$FUNCNAME", "$FUNCNAME [ str_repo | int_ndisk int_npartition ] path_filepath", "if $FUNCNAME REPO ubuntu.img CACHE ubuntu.img; then ...; fi") return ARGS = args @@ -60,13 +61,13 @@ def ogCalculateFullChecksum(*args): # Variables locales. FILE = None if "help" in args: - ogHelp("$FUNCNAME", "$FUNCNAME [ str_repo | int_ndisk int_npartition ] path_filepath", "$FUNCNAME REPO ubuntu.img ==> ef899299caf8b517ce36f1157a93d8bf") + SystemLib.ogHelp("$FUNCNAME", "$FUNCNAME [ str_repo | int_ndisk int_npartition ] path_filepath", "$FUNCNAME REPO ubuntu.img ==> ef899299caf8b517ce36f1157a93d8bf") return # Comprobar que existe el fichero y devolver sus datos. FILE = ogGetPath(*args) if not FILE: - ogRaiseError(OG_ERR_NOTFOUND, *args) + SystemLib.ogRaiseError(OG_ERR_NOTFOUND, *args) return # Calculate the checksum @@ -79,7 +80,7 @@ def ogCopyFile(*args): # Variables locales. ARGS = args if "help" in args: - ogHelp("$FUNCNAME", "$FUNCNAME [ str_repo | int_ndisk int_npartition ] path_source [ str_repo | int_ndisk int_npartition ] path_target", "$FUNCNAME REPO newfile.txt 1 2 /tmp/newfile.txt") + SystemLib.ogHelp("$FUNCNAME", "$FUNCNAME [ str_repo | int_ndisk int_npartition ] path_source [ str_repo | int_ndisk int_npartition ] path_target", "$FUNCNAME REPO newfile.txt 1 2 /tmp/newfile.txt") return ARGS = args @@ -100,10 +101,10 @@ def ogCopyFile(*args): # Comprobar fichero origen y directorio destino. if not SOURCE: - ogRaiseError(OG_ERR_NOTFOUND, *args[:-1]) + SystemLib.ogRaiseError(OG_ERR_NOTFOUND, *args[:-1]) return if not TARGET: - ogRaiseError(OG_ERR_NOTFOUND, *args) + SystemLib.ogRaiseError(OG_ERR_NOTFOUND, *args) return # Copiar fichero (para evitar problemas de comunicaciones las copias se hacen con rsync en vez de cp). @@ -114,36 +115,36 @@ def ogDeleteFile(*args): # Variables locales. FILE = None if "help" in args: - ogHelp("$FUNCNAME", "$FUNCNAME [ str_repo | int_ndisk int_npartition ] path_file", "$FUNCNAME 1 2 /tmp/newfile.txt") + SystemLib.ogHelp("$FUNCNAME", "$FUNCNAME [ str_repo | int_ndisk int_npartition ] path_file", "$FUNCNAME 1 2 /tmp/newfile.txt") return # Comprobar que existe el fichero y borrarlo. FILE = ogGetPath(*args) if not FILE: - ogRaiseError(OG_ERR_NOTFOUND, *args) + SystemLib.ogRaiseError(OG_ERR_NOTFOUND, *args) return try: os.remove(FILE) except OSError as e: - ogRaiseError(OG_ERR_NOTFOUND, *args) + SystemLib.ogRaiseError(OG_ERR_NOTFOUND, *args) return def ogDeleteTree(*args): # Variables locales. DIR = None if "help" in args: - ogHelp("$FUNCNAME", "$FUNCNAME [ str_repo | int_ndisk int_npartition ] path_dir", "$FUNCNAME 1 2 /tmp/newdir") + SystemLib.ogHelp("$FUNCNAME", "$FUNCNAME [ str_repo | int_ndisk int_npartition ] path_dir", "$FUNCNAME 1 2 /tmp/newdir") return # Comprobar que existe el directorio y borrarlo con su contenido. DIR = ogGetPath(*args) if not DIR: - ogRaiseError(OG_ERR_NOTFOUND, *args) + SystemLib.ogRaiseError(OG_ERR_NOTFOUND, *args) return try: shutil.rmtree(DIR) except OSError as e: - ogRaiseError(OG_ERR_NOTFOUND, *args) + SystemLib.ogRaiseError(OG_ERR_NOTFOUND, *args) return def ogGetPath(*args): @@ -156,7 +157,7 @@ def ogGetPath(*args): # Si se solicita, mostrar ayuda. if "help" in args: - ogHelp("$FUNCNAME", "$FUNCNAME [ str_repo | int_ndisk int_npartition ] path_filepath", "$FUNCNAME \"/mnt/sda1/windows/system32\" ==> /mnt/sda1/WINDOWS/System32", "$FUNCNAME REPO /etc/fstab ==> /opt/opengnsys/images/etc/fstab", "$FUNCNAME 1 1 \"/windows/system32\" ==> /mnt/sda1/WINDOWS/System32") + SystemLib.ogHelp("$FUNCNAME", "$FUNCNAME [ str_repo | int_ndisk int_npartition ] path_filepath", "$FUNCNAME \"/mnt/sda1/windows/system32\" ==> /mnt/sda1/WINDOWS/System32", "$FUNCNAME REPO /etc/fstab ==> /opt/opengnsys/images/etc/fstab", "$FUNCNAME 1 1 \"/windows/system32\" ==> /mnt/sda1/WINDOWS/System32") return # Procesar camino según el número de parámetros. @@ -166,25 +167,25 @@ def ogGetPath(*args): if args[0].upper() == "REPO": FILE = os.path.join(OGIMG, args[1]) elif args[0].upper() == "CACHE": - MNTDIR = ogMountCache() + MNTDIR = CacheLib.ogMountCache() if not MNTDIR: return FILE = os.path.join(MNTDIR, OGIMG, args[1]) elif args[0].upper() == "CDROM": - MNTDIR = ogMountCdrom() + MNTDIR = FileSystemLib.ogMountCdrom() if not MNTDIR: return FILE = os.path.join(MNTDIR, args[1]) else: - ogRaiseError(OG_ERR_FORMAT) + SystemLib.ogRaiseError(OG_ERR_FORMAT) return elif len(args) == 3: - MNTDIR = ogMount(args[0], args[1]) + MNTDIR = FileSystemLib.ogMount(args[0], args[1]) if not MNTDIR: return FILE = os.path.join(MNTDIR, args[2]) else: - ogRaiseError(OG_ERR_FORMAT) + SystemLib.ogRaiseError(OG_ERR_FORMAT) return # Eliminar caracteres \c / duplicados y finales. @@ -210,7 +211,7 @@ def ogGetParentPath(*args): # Variables locales. PARENT = None if "help" in args: - ogHelp("$FUNCNAME", "$FUNCNAME [ str_repo | int_ndisk int_npartition ] path_filepath", "$FUNCNAME \"/mnt/sda1/windows/system32\" ==> /mnt/sda1/WINDOWS", "$FUNCNAME REPO /etc/fstab ==> /opt/opengnsys/images/etc", "$FUNCNAME 1 1 \"/windows/system32\" ==> /mnt/sda1/WINDOWS") + FileSystemLib.ogHelp("$FUNCNAME", "$FUNCNAME [ str_repo | int_ndisk int_npartition ] path_filepath", "$FUNCNAME \"/mnt/sda1/windows/system32\" ==> /mnt/sda1/WINDOWS", "$FUNCNAME REPO /etc/fstab ==> /opt/opengnsys/images/etc", "$FUNCNAME 1 1 \"/windows/system32\" ==> /mnt/sda1/WINDOWS") return # Procesar camino según el número de parámetros. @@ -221,7 +222,7 @@ def ogGetParentPath(*args): elif len(args) == 3: PARENT = f"{args[0]} {args[1]} {os.path.dirname(f'/{args[2]}')}" else: - ogRaiseError(OG_ERR_FORMAT) + SystemLib.ogRaiseError(OG_ERR_FORMAT) return return ogGetPath(PARENT) @@ -230,7 +231,7 @@ def ogIsNewerFile(*args): # Variables locales. ARGS = args if "help" in args: - ogHelp("$FUNCNAME", "$FUNCNAME [ str_repo | int_ndisk int_npartition ] path_source [ str_repo | int_ndisk int_npartition ] path_target", "if $FUNCNAME REPO ubuntu.img CACHE ubuntu.img; then ... fi") + SystemLib.ogHelp("$FUNCNAME", "$FUNCNAME [ str_repo | int_ndisk int_npartition ] path_source [ str_repo | int_ndisk int_npartition ] path_target", "if $FUNCNAME REPO ubuntu.img CACHE ubuntu.img; then ... fi") return ARGS = args @@ -251,10 +252,10 @@ def ogIsNewerFile(*args): # Comprobar que existen los ficheros origen y destino. if not SOURCE: - ogRaiseError(OG_ERR_NOTFOUND, *args[:-1]) + SystemLib.ogRaiseError(OG_ERR_NOTFOUND, *args[:-1]) return if not TARGET: - ogRaiseError(OG_ERR_NOTFOUND, *args) + SystemLib.ogRaiseError(OG_ERR_NOTFOUND, *args) return # Devolver si el primer fichero se ha modificado después que el segundo. @@ -264,13 +265,13 @@ def ogMakeChecksumFile(*args): # Variables locales. FILE = None if "help" in args: - ogHelp("$FUNCNAME", "$FUNCNAME [ str_repo | int_ndisk int_npartition ] path_filepath", "$FUNCNAME REPO ubuntu.img") + SystemLib.ogHelp("$FUNCNAME", "$FUNCNAME [ str_repo | int_ndisk int_npartition ] path_filepath", "$FUNCNAME REPO ubuntu.img") return # Comprobar que existe el fichero y guardar su checksum. FILE = ogGetPath(*args) if not FILE: - ogRaiseError(OG_ERR_NOTFOUND, *args) + SystemLib.ogRaiseError(OG_ERR_NOTFOUND, *args) return checksum = ogCalculateChecksum(FILE) with open(f"{FILE}.sum", "w") as f: @@ -281,13 +282,13 @@ def ogMakeDir(*args): PARENT = None DIR = None if "help" in args: - ogHelp("$FUNCNAME", "$FUNCNAME [ str_repo | int_ndisk int_npartition ] path_dir", "$FUNCNAME 1 2 /tmp/newdir") + SystemLib.ogHelp("$FUNCNAME", "$FUNCNAME [ str_repo | int_ndisk int_npartition ] path_dir", "$FUNCNAME 1 2 /tmp/newdir") return PARENT = ogGetParentPath(*args) if not PARENT: - ogRaiseError(OG_ERR_NOTFOUND, *args) + SystemLib.ogRaiseError(OG_ERR_NOTFOUND, *args) return DIR = os.path.basename(args[-1]) - os.makedirs(os.path.join(PARENT, DIR), exist_ok=True) \ No newline at end of file + os.makedirs(os.path.join(PARENT, DIR), exist_ok=True) diff --git a/client/lib/engine/bin/FileSystemLib.py b/client/lib/engine/bin/FileSystemLib.py old mode 100644 new mode 100755 diff --git a/client/lib/engine/bin/NetLib.py b/client/lib/engine/bin/NetLib.py index 083bb22..49ea950 100755 --- a/client/lib/engine/bin/NetLib.py +++ b/client/lib/engine/bin/NetLib.py @@ -2,8 +2,8 @@ import subprocess import sys import os -from FileLib import * -from SystemLib import * +import NetLib +import SystemLib def ogChangeRepo(): SRCIMG = "" @@ -31,7 +31,7 @@ def ogChangeRepo(): RW = ",rw" if subprocess.returncode == 0 else ",ro" # Si REPO tomamos el repositorio y la unidad organizativa actual - REPO = ogGetRepoIp() + REPO = ogRepoIp() OGUNIT = subprocess.run(["df", "|", "awk", "-F", " ", "'/ogimages/ {sub(\"//.*/ogimages\",\"\",$1); sub(\"/\",\"\",$1); print $1}'"], stdout=subprocess.PIPE, stderr=subprocess.DEVNULL).stdout.decode().strip() # Parametros de entrada. Si $1 = "REPO" dejo el repositorio actual @@ -53,13 +53,13 @@ def ogChangeRepo(): subprocess.run(["eval", "$(grep \"OPTIONS=\" /scripts/ogfunctions)"]) - ogEcho("session", "log", MSG_HELP_ogChangeRepo + " " + NEWREPO + " " + sys.argv[2].rstrip()) + SystemLib.ogEcho("session", "log", MSG_HELP_ogChangeRepo + " " + NEWREPO + " " + sys.argv[2].rstrip()) ogConnect(NEWREPO, ogprotocol, SRCIMG, OGIMG, RW) # Si da error volvemos a montar el inicial if subprocess.returncode != 0: ogConnect(REPO, ogprotocol, SRCIMG, OGIMG, RW) - ogRaiseError("session", OG_ERR_REPO, NEWREPO) + SystemLib.ogRaiseError("session", OG_ERR_REPO, NEWREPO) return subprocess.returncode def ogGetGroupDir(): @@ -68,7 +68,7 @@ def ogGetGroupDir(): GROUP = "" if len(sys.argv) < 2: - ogHelp("ogGetGroupDir", "ogGetGroupDir str_repo", "ogGetGroupDir REPO ==> /opt/opengnsys/images/groups/Grupo1") + SystemLib.ogHelp("ogGetGroupDir", "ogGetGroupDir str_repo", "ogGetGroupDir REPO ==> /opt/opengnsys/images/groups/Grupo1") return if len(sys.argv) == 1: @@ -78,7 +78,7 @@ def ogGetGroupDir(): GROUP = ogGetGroupName() if GROUP: - DIR = ogGetPath(REPO, "/groups/" + GROUP, stderr=subprocess.DEVNULL) + DIR = FileLib.ogGetPath(REPO, "/groups/" + GROUP, stderr=subprocess.DEVNULL) if os.path.isdir(DIR): print(DIR) @@ -86,7 +86,7 @@ def ogGetGroupDir(): def ogGetGroupName(): if len(sys.argv) >= 2 and sys.argv[1] == "help": - ogHelp("ogGetGroupName", "ogGetGroupName", "ogGetGroupName => Grupo1") + SystemLib.ogHelp("ogGetGroupName", "ogGetGroupName", "ogGetGroupName => Grupo1") return if "group" in globals() and group: @@ -98,7 +98,7 @@ def ogGetHostname(): HOST = "" if len(sys.argv) >= 2 and sys.argv[1] == "help": - ogHelp("ogGetHostname", "ogGetHostname", "ogGetHostname => pc1") + SystemLib.ogHelp("ogGetHostname", "ogGetHostname", "ogGetHostname => pc1") return # Tomar nombre de la variable HOSTNAME @@ -130,7 +130,7 @@ def ogGetIpAddress(): IP = "" if len(sys.argv) >= 2 and sys.argv[1] == "help": - ogHelp("ogGetIpAddress", "ogGetIpAddress", "ogGetIpAddress => 192.168.0.10") + SystemLib.ogHelp("ogGetIpAddress", "ogGetIpAddress", "ogGetIpAddress => 192.168.0.10") return if "IPV4ADDR" in os.environ: @@ -154,7 +154,7 @@ def ogGetMacAddress(): MAC = "" if len(sys.argv) >= 2 and sys.argv[1] == "help": - ogHelp("ogGetMacAddress", "ogGetMacAddress", "ogGetMacAddress => 00:11:22:33:44:55") + SystemLib.ogHelp("ogGetMacAddress", "ogGetMacAddress", "ogGetMacAddress => 00:11:22:33:44:55") return # Obtener direcciones Ethernet. @@ -173,7 +173,7 @@ def ogGetMacAddress(): def ogGetNetInterface(): if len(sys.argv) >= 2 and sys.argv[1] == "help": - ogHelp("ogGetNetInterface", "ogGetNetInterface", "ogGetNetInterface => eth0") + SystemLib.ogHelp("ogGetNetInterface", "ogGetNetInterface", "ogGetNetInterface => eth0") return if "DEVICE" in os.environ: @@ -181,14 +181,14 @@ def ogGetNetInterface(): return 0 -def ogGetRepoIp(): +def ogRepoIp(): # Variables locales. SOURCE = "" FSTYPE = "" # Mostrar ayuda. if len(sys.argv) >= 2 and sys.argv[1] == "help": - ogHelp("ogGetRepoIp", "ogGetRepoIp", "ogGetRepoIp => 192.168.0.2") + SystemLib.ogHelp("ogRepoIp", "ogRepoIp", "ogRepoIp => 192.168.0.2") return # Obtener direcciones IP, según el tipo de montaje. @@ -214,7 +214,7 @@ def ogGetServerIp(): # Mostrar ayuda. if len(sys.argv) >= 2 and sys.argv[1] == "help": - ogHelp("ogGetServerIp", "ogGetServerIp", "ogGetServerIp => 192.168.0.2") + SystemLib.ogHelp("ogGetServerIp", "ogGetServerIp", "ogGetServerIp => 192.168.0.2") return # Obtener direcciones IP, según el tipo de montaje. @@ -239,7 +239,7 @@ def ogMakeGroupDir(): GROUP = "" if len(sys.argv) < 2: - ogHelp("ogMakeGroupDir", "ogMakeGroupDir str_repo", "ogMakeGroupDir", "ogMakeGroupDir REPO") + SystemLib.ogHelp("ogMakeGroupDir", "ogMakeGroupDir str_repo", "ogMakeGroupDir", "ogMakeGroupDir REPO") return if len(sys.argv) == 1: @@ -247,7 +247,7 @@ def ogMakeGroupDir(): else: REPO = sys.argv[1] - DIR = ogGetPath(REPO, "/groups/" + ogGetGroupName(), stderr=subprocess.DEVNULL) + DIR = FileLib.ogGetPath(REPO, "/groups/" + ogGetGroupName(), stderr=subprocess.DEVNULL) if DIR: subprocess.run(["mkdir", "-p", DIR], stderr=subprocess.DEVNULL) diff --git a/client/lib/engine/bin/RegistryLib.py b/client/lib/engine/bin/RegistryLib.py index 32ef764..905b0dc 100755 --- a/client/lib/engine/bin/RegistryLib.py +++ b/client/lib/engine/bin/RegistryLib.py @@ -2,8 +2,9 @@ import subprocess import os import re -#from engine.FileLib import * -#from engine.SystemLib import * +import ogGlobals +import SystemLib +import FileLib def chntpw(*args): chntpw_path = subprocess.check_output(['which', 'drbl-chntpw']).decode().strip() @@ -37,7 +38,7 @@ def ogAddRegistryValue(path_mountpoint, str_hive, str_key, str_valuename, str_va elif str_valuetype.upper() == 'DWORD': TYPE = 4 else: - ogRaiseError(OG_ERR_OUTOFLIMIT, str_valuetype) + SystemLib.ogRaiseError(OG_ERR_OUTOFLIMIT, str_valuetype) return # Add the registry value. @@ -72,17 +73,17 @@ def ogGetHivePath(path_mountpoint, str_hive): FILE = None # Camino del fichero de registro de usuario o de sistema (de menor a mayor prioridad). - FILE = ogGetPath(f"/{path_mountpoint}/Windows/System32/config/{str_hive}") + FILE = FileLib.ogGetPath(f"/{path_mountpoint}/Windows/System32/config/{str_hive}") if not FILE: - FILE = ogGetPath(f"/{path_mountpoint}/Users/{str_hive}/NTUSER.DAT") + FILE = FileLib.ogGetPath(f"/{path_mountpoint}/Users/{str_hive}/NTUSER.DAT") if not FILE: - FILE = ogGetPath(f"/{path_mountpoint}/winnt/system32/config/{str_hive}") + FILE = FileLib.ogGetPath(f"/{path_mountpoint}/winnt/system32/config/{str_hive}") if not FILE: - FILE = ogGetPath(f"/{path_mountpoint}/Documents and Settings/{str_hive}/NTUSER.DAT") + FILE = FileLib.ogGetPath(f"/{path_mountpoint}/Documents and Settings/{str_hive}/NTUSER.DAT") if FILE and os.path.isfile(FILE): return FILE else: - ogRaiseError(OG_ERR_NOTFOUND, f"{path_mountpoint} {str_hive}") + SystemLib.ogRaiseError(OG_ERR_NOTFOUND, f"{path_mountpoint} {str_hive}") return None def ogGetRegistryValue(path_mountpoint, str_hive, str_valuename): @@ -160,7 +161,7 @@ def ogSetRegistryValue(path_mountpoint, str_hive, str_valuename, str_data): if f"BINARY.*<{str_valuename.rsplit('\\', 1)[-1]}>" in output: # Procesar tipo binario (incluir nº de bytes y líneas de 16 parejas hexadecimales). if not re.match(r'^([0-9A-F]{2} )*$', str_data): - ogRaiseError(OG_ERR_FORMAT, f'"{str_data}"') + SystemLib.ogRaiseError(OG_ERR_FORMAT, f'"{str_data}"') return n = len(str_data) + 1 with open(tmpfile, 'w') as f: diff --git a/client/lib/engine/bin/__init__.py b/client/lib/engine/bin/__init__.py old mode 100644 new mode 100755 diff --git a/client/lib/engine/bin/lang_ca_ES.py b/client/lib/engine/bin/lang_ca_ES.py old mode 100644 new mode 100755 diff --git a/client/lib/engine/bin/lang_en_GB.py b/client/lib/engine/bin/lang_en_GB.py old mode 100644 new mode 100755 diff --git a/client/lib/engine/bin/lang_es_ES.py b/client/lib/engine/bin/lang_es_ES.py old mode 100644 new mode 100755 diff --git a/client/lib/engine/bin/ogGlobals.py b/client/lib/engine/bin/ogGlobals.py old mode 100644 new mode 100755 diff --git a/client/shared/scripts/listSoftwareInfo.py b/client/shared/scripts/listSoftwareInfo.py index 31c2e8d..7f6ac76 100755 --- a/client/shared/scripts/listSoftwareInfo.py +++ b/client/shared/scripts/listSoftwareInfo.py @@ -1,37 +1,42 @@ -import sys import os +import sys +import subprocess sys.path.append('/opt/opengnsys/lib/engine/bin') -from NetLib import ogGetIpAddress -from SystemLib import ogRaiseError -from InventoryLib import ogListSoftware - -REDUCED = False +import SystemLib +import InventoryLib +import NetLib +import ogGlobals +PROG = os.path.basename(__file__) +REDUCED = "no" if len(sys.argv) > 1 and sys.argv[1] == "-r": - REDUCED = True + REDUCED = "yes" sys.argv.pop(1) if len(sys.argv) != 3: - og_raise_error("OG_ERR_FORMAT", "Usage: listSoftwareInfo [-r] disk partition") + SystemLib.ogRaiseError(ogGlobals.OG_ERR_FORMAT, f"{ogGlobals.MSG_FORMAT}: {PROG} ndisco nparticion") sys.exit(1) -disk = sys.argv[1] -partition = sys.argv[2] +# Directorio del servidor donde se exportan los ficheros de registro. +SERVERLOGDIR = subprocess.run( +["awk", "-v", f"d={ogGlobals.OGLOG}", 'BEGIN {FS="[: ]"} {if ($4==d) dir=$2} END {print dir}'], +capture_output=True, +text=True, +check=True, +).stdout.strip() -# Directorio del servidor donde se exportan los ficheros de registro -server_log_dir = "/mnt/oglog" # Assuming OGLOG is mounted at /mnt/oglog - -# Fichero de listado: soft-IP-disk-partition -soft_file = f"soft-{ogGetIpAddress()}-{disk}-{partition}" -log_path = os.path.join(server_log_dir, soft_file) - -# Redirigir salida al fichero de listado -with open(log_path, "w") as log_file: - if not REDUCED: - ogListSoftware(disk, partition, log_file) +# Fichero de listado: soft-IP-ndisco-npart +SOFTFILE = f"soft-{NetLib.ogGetIpAddress()}-{sys.argv[1]}-{sys.argv[2]}" +# Redirigir salida al fichero de listado. +if REDUCED == "no": + if subprocess.run(["ogListSoftware", sys.argv[1], sys.argv[2]], stdout=open(f"{ogGlobals.OGLOG}/{SOFTFILE}", "w")).returncode != 0: + sys.exit(1) else: - for line in og_list_software(disk, partition): - if "(KB" not in line: - log_file.write(line + "\n") + if subprocess.run(["ogListSoftware", sys.argv[1], sys.argv[2]], stdout=subprocess.PIPE).returncode == 0: + with open(f"{ogGlobals.OGLOG}/{SOFTFILE}", "w") as f: + f.write(subprocess.run(["egrep", "-v", "\(KB[0-9]{6}\)"], input=subprocess.PIPE).stdout.decode()) + else: + sys.exit(1) -print(log_path) +# Salid: camino del fichero de listado en el servidor de repositorio. +print(f"{ogGlobals.OGLOG}/{SOFTFILE}") From 2d94e3742e10a48d07c9385a7828b9d4b33853f5 Mon Sep 17 00:00:00 2001 From: aguerrero Date: Wed, 6 Nov 2024 04:46:28 +0000 Subject: [PATCH 027/167] refs #1099 The syntax for calling libraries into InventoryLib.py has been modified --- client/lib/engine/bin/InventoryLib.py | 56 +++++++++++++-------------- 1 file changed, 27 insertions(+), 29 deletions(-) diff --git a/client/lib/engine/bin/InventoryLib.py b/client/lib/engine/bin/InventoryLib.py index 1f1d7ff..bb8c7bc 100755 --- a/client/lib/engine/bin/InventoryLib.py +++ b/client/lib/engine/bin/InventoryLib.py @@ -8,20 +8,18 @@ import re import json import shutil import sqlite3 -from SystemLib import ogMount, ogGetOsType, ogRaiseError, ogHelp, ogGetOsVersion, ogGetHivePath, ogListRegistryKeys, ogGetRegistryValue, ogGetIpAddress -sys.path.append('/opt/opengnsys/lib/engine/bin') -from SystemLib import ogEcho -#from Disklib import ogDiskToDev -#from engine.FileLib import * -#from engine.RegistryLib import * -#from engine.FileSystemLib import * +import SystemLib +import ogGlobals +import FileLib +import RegistryLib +import FileSystemLib MSG_HARDWAREINVENTORY = "Inventario de hardware de la máquina" def ogGetArch(): if len(sys.argv) > 1 and sys.argv[1] == "help": - ogHelp(sys.argv[0], sys.argv[0], sys.argv[0] + " => x86_64") + SystemLib.ogHelp(sys.argv[0], sys.argv[0], sys.argv[0] + " => x86_64") return if platform.machine().endswith("64"): @@ -32,23 +30,23 @@ def ogGetArch(): def ogGetOsType(): # Si se solicita, mostrar ayuda. if len(sys.argv) > 1 and sys.argv[1] == "help": - ogHelp(sys.argv[0], sys.argv[0] + " int_ndisk int_npartition", sys.argv[0] + " 1 2 => Linux") + SystemLib.ogHelp(sys.argv[0], sys.argv[0] + " int_ndisk int_npartition", sys.argv[0] + " 1 2 => Linux") return ogGetOsVersion(sys.argv[1:]).split(':')[0] def ogGetOsUuid(): # Si se solicita, mostrar ayuda. if len(sys.argv) > 1 and sys.argv[1] == "help": - ogHelp(sys.argv[0], sys.argv[0] + " int_ndisk int_nfilesys", sys.argv[0] + " 1 2 => 540e47c6-8e78-4178-aa46-042e4803fb16") + SystemLib.ogHelp(sys.argv[0], sys.argv[0] + " int_ndisk int_nfilesys", sys.argv[0] + " 1 2 => 540e47c6-8e78-4178-aa46-042e4803fb16") return # Error si no se reciben 2 parametros. if len(sys.argv) != 3: - ogRaiseError(OG_ERR_FORMAT) + SystemLib.ogRaiseError(OG_ERR_FORMAT) return # Montar la particion, si no lo estaba previamente. - MNTDIR = ogMount(sys.argv[1], sys.argv[2]) + MNTDIR = FileSystemLib.ogMount(sys.argv[1], sys.argv[2]) if not MNTDIR: return @@ -60,13 +58,13 @@ def ogGetOsUuid(): print(uuid) elif os_type == "Windows": # Leer identificador en clave de registro. - uuid = ogGetRegistryValue(MNTDIR, "SOFTWARE", "\\Microsoft\\Cryptography\\MachineGuid") + uuid = Registry.ogGetRegistryValue(MNTDIR, "SOFTWARE", "\\Microsoft\\Cryptography\\MachineGuid") print(uuid) def ogGetSerialNumber(): # Si se solicita, mostrar ayuda. if len(sys.argv) > 1 and sys.argv[1] == "help": - ogHelp(sys.argv[0], sys.argv[0], sys.argv[0] + " => 123456") + SystemLib.ogHelp(sys.argv[0], sys.argv[0], sys.argv[0] + " => 123456") return # Obtener nº de serie (ignorar los no especificados). @@ -141,12 +139,12 @@ def ogListHardwareInfo(): def ogListSoftware(disk, partition): # Error si no se reciben 2 parametros if disk is None or partition is None: - og_raise_error("OG_ERR_FORMAT") + SystemLib.ogRaiseError("OG_ERR_FORMAT") return # Obtener tipo de sistema de archivos y montarlo - mnt_dir = og_mount(disk, partition) - os_type = og_get_os_type(disk, partition) + mnt_dir = FileSystemLib.ogMount(disk, partition) + os_type = ogGetOsType(disk, partition) # Ficheros temporales apps_file = tempfile.NamedTemporaryFile(delete=False) @@ -174,17 +172,17 @@ def ogListSoftware(disk, partition): pass elif os_type == "Windows": # Procesar aplicaciones instaladas en Windows - hive_path = og_get_hive_path(mnt_dir, "software") + hive_path = Registry.ogGetHivePath(mnt_dir, "software") if hive_path: subprocess.run(["hivexregedit", "--unsafe-printable-strings", "--export", hive_path, '\Microsoft\Windows\CurrentVersion\Uninstall'], stdout=tmp_file) - elif os_type == "MacOS": + elif osType == "MacOS": # Procesar aplicaciones instaladas en MacOS pass - elif os_type == "BSD": + elif osType == "BSD": # Procesar aplicaciones instaladas en FreeBSD pass else: - og_raise_error("OG_ERR_NOTOS", disk, partition) + SystemLib.ogRaiseError("OG_ERR_NOTOS", disk, partition) finally: # Eliminar archivos temporales apps_file.close() @@ -193,30 +191,30 @@ def ogListSoftware(disk, partition): os.remove(tmp_file.name) # Mostrar sistema operativo y aplicaciones - og_get_os_version(disk, partition) + ogGetOsVersion(disk, partition) with open(apps_file.name, "r") as apps: for line in sorted(set(apps.readlines())): print(line.strip()) def ogGetOsVersion(ndisk, nfilesys): # Variables locales. - MNTDIR = ogMount(ndisk, nfilesys) + MNTDIR = FileSystemLib.ogMount(ndisk, nfilesys) TYPE = "" VERSION = "" IS64BIT = "" # Si se solicita, mostrar ayuda. if len(sys.argv) > 1 and sys.argv[1] == "help": - ogHelp(sys.argv[0], sys.argv[0] + " int_ndisk int_nfilesys", sys.argv[0] + " 1 2 => Linux:Ubuntu precise (12.04 LTS) 64 bits") + SystemLib.ogHelp(sys.argv[0], sys.argv[0] + " int_ndisk int_nfilesys", sys.argv[0] + " 1 2 => Linux:Ubuntu precise (12.04 LTS) 64 bits") return # Error si no se reciben 2 parametros. if len(sys.argv) != 3: - ogRaiseError(OG_ERR_FORMAT) + SystemLib.ogRaiseError(OG_ERR_FORMAT) return # Montar la particion, si no lo estaba previamente. - MNTDIR = ogMount(sys.argv[1], sys.argv[2]) + MNTDIR = FileSystemLib.ogMount(sys.argv[1], sys.argv[2]) if not MNTDIR: return @@ -301,7 +299,7 @@ def ogGetOsVersion(ndisk, nfilesys): lines = output.split("\n") if len(lines) == 2: VERSION = lines[1].strip() - if ogGetRegistryValue(MNTDIR, "SOFTWARE", "\\Microsoft\\Windows\\CurrentVersion\\ProgramW6432Dir"): + if Registry.ogGetRegistryValue(MNTDIR, "SOFTWARE", "\\Microsoft\\Windows\\CurrentVersion\\ProgramW6432Dir"): IS64BIT = "64 bits" except subprocess.CalledProcessError: pass @@ -309,9 +307,9 @@ def ogGetOsVersion(ndisk, nfilesys): # Para cargador Windows: buscar versión en fichero BCD (basado en os-prober). if not VERSION: TYPE = "WinLoader" - FILE = ogGetPath(MNTDIR, "boot", "bcd") + FILE = FileLib.ogGetPath(MNTDIR, "boot", "bcd") if not FILE: - FILE = ogGetPath(MNTDIR, "EFI", "Microsoft", "boot", "bcd") + FILE = FileLib.ogGetPath(MNTDIR, "EFI", "Microsoft", "boot", "bcd") if FILE: for DISTRIB in ["Windows Recovery", "Windows Boot"]: with open(FILE, "rb") as f: From 150685fe75f435a41c7415eb69cd31b53196bd5e Mon Sep 17 00:00:00 2001 From: aguerrero Date: Thu, 7 Nov 2024 06:08:28 +0000 Subject: [PATCH 028/167] refs #1113 InterfaceAdm function call updates --- client/interfaceAdm/Apagar.py | 0 client/interfaceAdm/CambiarAcceso.py | 35 +++++++------- client/interfaceAdm/Configurar.py | 8 ++-- client/interfaceAdm/ConsolaRemota.py | 0 client/interfaceAdm/CrearImagen.py | 48 ++++--------------- client/interfaceAdm/EjecutarScript.py | 17 ++++--- client/interfaceAdm/GetConfiguration.py | 64 ++++++++++++++++++------- client/interfaceAdm/GetIpAddress.py | 11 ----- client/interfaceAdm/IniciarSesion.py | 0 client/interfaceAdm/Reiniciar.py | 0 client/interfaceAdm/RestaurarImagen.py | 2 +- client/interfaceAdm/getConfiguration.py | 0 client/interfaceAdm/getIpAddress.py | 8 +++- client/interfaceAdm/procesaCache.py | 0 14 files changed, 96 insertions(+), 97 deletions(-) mode change 100644 => 100755 client/interfaceAdm/Apagar.py mode change 100644 => 100755 client/interfaceAdm/CambiarAcceso.py mode change 100644 => 100755 client/interfaceAdm/Configurar.py mode change 100644 => 100755 client/interfaceAdm/ConsolaRemota.py mode change 100644 => 100755 client/interfaceAdm/CrearImagen.py mode change 100644 => 100755 client/interfaceAdm/EjecutarScript.py mode change 100644 => 100755 client/interfaceAdm/GetConfiguration.py delete mode 100644 client/interfaceAdm/GetIpAddress.py mode change 100644 => 100755 client/interfaceAdm/IniciarSesion.py mode change 100644 => 100755 client/interfaceAdm/Reiniciar.py mode change 100644 => 100755 client/interfaceAdm/RestaurarImagen.py mode change 100644 => 100755 client/interfaceAdm/getConfiguration.py mode change 100644 => 100755 client/interfaceAdm/getIpAddress.py mode change 100644 => 100755 client/interfaceAdm/procesaCache.py diff --git a/client/interfaceAdm/Apagar.py b/client/interfaceAdm/Apagar.py old mode 100644 new mode 100755 diff --git a/client/interfaceAdm/CambiarAcceso.py b/client/interfaceAdm/CambiarAcceso.py old mode 100644 new mode 100755 index bba158b..61fea66 --- a/client/interfaceAdm/CambiarAcceso.py +++ b/client/interfaceAdm/CambiarAcceso.py @@ -1,8 +1,9 @@ +#!/usr/bin/env python3 import os import sys import subprocess - -#!/usr/bin/env python3 +import NetLib +import SystemLib def main(): if len(sys.argv) != 2: @@ -10,35 +11,35 @@ def main(): sys.exit(1) mode = sys.argv[1] - repo_ip = og_get_repo_ip() + repo_ip = NetLib.ogGetRepoIp() if not repo_ip: - og_raise_error("OG_ERR_NOTFOUND", "repo no montado") + SystemLib.ogRaiseError("OG_ERR_NOTFOUND", "repo no montado") - if og_is_repo_locked(): - og_raise_error("OG_ERR_LOCKED", f"repo {repo_ip}") + if SystemLib.ogIsRepoLocked(): + SystemLib.ogRaiseError("OG_ERR_LOCKED", f"repo {repo_ip}") proto = os.getenv("ogprotocol", "smb") if proto not in ["nfs", "smb"]: - og_raise_error("OG_ERR_FORMAT", f"protocolo desconocido {proto}") + SystemLib.ogRaiseError("OG_ERR_FORMAT", f"protocolo desconocido {proto}") if mode == "admin": mount_mode = "rw" elif mode == "user": mount_mode = "ro" else: - og_raise_error("OG_ERR_FORMAT", f"modo desconocido {mode}") + SystemLib.ogRaiseError("OG_ERR_FORMAT", f"modo desconocido {mode}") - ogimg = os.getenv("OGIMG", "/mnt/ogimg") - ogunit = os.getenv("ogunit", "") - if ogunit: - ogunit = f"/{ogunit}" + OGIMG = os.getenv("OGIMG", "/mnt/OGIMG") + OGUNIT = os.getenv("OGUNIT", "") + if OGUNIT: + OGUNIT = f"/{OGUNIT}" - subprocess.run(["umount", ogimg], check=True) - og_echo("info", f"Montar repositorio {repo_ip} por {proto} en modo {mode}") + subprocess.run(["umount", OGIMG], check=True) + SystemLib.ogEcho("info", f"Montar repositorio {repo_ip} por {proto} en modo {mode}") if proto == "nfs": - subprocess.run(["mount", "-t", "nfs", f"{repo_ip}:{ogimg}{ogunit}", ogimg, "-o", mount_mode], check=True) + subprocess.run(["mount", "-t", "nfs", f"{repo_ip}:{OGIMG}{OGUNIT}", OGIMG, "-o", mount_mode], check=True) elif proto == "smb": with open("/scripts/ogfunctions", "r") as f: for line in f: @@ -47,7 +48,7 @@ def main(): break else: pass_option = "og" - subprocess.run(["mount.cifs", f"//{repo_ip}/ogimages{ogunit}", ogimg, "-o", f"{mount_mode},serverino,acl,username=opengnsys,password={pass_option}"], check=True) + subprocess.run(["mount.cifs", f"//{repo_ip}/ogimages{OGUNIT}", OGIMG, "-o", f"{mount_mode},serverino,acl,username=opengnsys,password={pass_option}"], check=True) if __name__ == "__main__": - main() \ No newline at end of file + main() diff --git a/client/interfaceAdm/Configurar.py b/client/interfaceAdm/Configurar.py old mode 100644 new mode 100755 index 7552289..1ae34d2 --- a/client/interfaceAdm/Configurar.py +++ b/client/interfaceAdm/Configurar.py @@ -1,9 +1,9 @@ import os import sys import subprocess +import SystemLib # Load engine configurator from engine.cfg file. -# Carga el configurador del engine desde el fichero engine.cfg og_engine_configurate = os.getenv('OGENGINECONFIGURATE') if not og_engine_configurate: with open('/opt/opengnsys/client/etc/engine.cfg') as f: @@ -40,14 +40,14 @@ if og_log_command: print("og_log_session", og_log_session) # Registro de inicio de ejecución -def og_echo(log_type, message): +def SystemLib.ogEcho(log_type, message): # Implement the logging function here pass print("os.getenv('MSG_INTERFACE_START')", os.getenv('MSG_INTERFACE_START')) msg_interface_start = os.getenv('MSG_INTERFACE_START') if msg_interface_start: - og_echo('log', f"session {msg_interface_start} {__name__} {' '.join(os.sys.argv[1:])}") + SystemLib.ogEcho('log', f"session {msg_interface_start} {__name__} {' '.join(os.sys.argv[1:])}") # Solo ejecutable por OpenGnsys Client. path = os.getenv('PATH') @@ -143,4 +143,4 @@ subprocess.run(["ogEcho", "log", "session", f"{os.getenv('MSG_INTERFACE_END')} { # Return coproc.kill() -sys.exit(0) \ No newline at end of file +sys.exit(0) diff --git a/client/interfaceAdm/ConsolaRemota.py b/client/interfaceAdm/ConsolaRemota.py old mode 100644 new mode 100755 diff --git a/client/interfaceAdm/CrearImagen.py b/client/interfaceAdm/CrearImagen.py old mode 100644 new mode 100755 index 063d0d7..443df8e --- a/client/interfaceAdm/CrearImagen.py +++ b/client/interfaceAdm/CrearImagen.py @@ -2,18 +2,8 @@ import os import subprocess import sys import time - -# 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 +import NetLib +import ogGlobals def load_engine_config(): engine_config_path = "/opt/opengnsys/etc/engine.cfg" @@ -27,20 +17,10 @@ def clear_temp_logs(): open(f"{os.getenv('OGLOGCOMMAND')}.tmp", 'w').close() def log_session_start(script_name, args): - ogEcho("log session", f"{os.getenv('MSG_INTERFACE_START')} {script_name} {' '.join(args)}") + SystemLib.ogEcho("log session", f"{os.getenv('MSG_INTERFACE_START')} {script_name} {' '.join(args)}") def log_session_end(retval): - ogEcho("log session", f"{os.getenv('MSG_INTERFACE_END')} {retval}") - -def ogEcho(*args): - print(" ".join(args)) - -def ogRaiseError(error_code, message): - print(f"Error {error_code}: {message}", file=sys.stderr) - return error_code - -def ogGetIpAddress(): - return subprocess.check_output(["hostname", "-I"]).decode().strip() + SystemLib.ogEcho("log session", f"{os.getenv('MSG_INTERFACE_END')} {retval}") def ogCheckIpAddress(ip): try: @@ -49,14 +29,6 @@ def ogCheckIpAddress(ip): except subprocess.CalledProcessError: return 1 -def ogChangeRepo(repo, unit): - # Placeholder for actual implementation - return True - -def CambiarAcceso(mode): - # Placeholder for actual implementation - return 0 - def create_image(disk_num, partition_num, repo, image_name): if subprocess.call(["which", "createImageCustom"], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) == 0: return subprocess.call(["createImageCustom", disk_num, partition_num, repo, f"/{image_name}"]) @@ -65,7 +37,7 @@ def create_image(disk_num, partition_num, repo, image_name): def main(): if len(sys.argv) != 5: - sys.exit(ogRaiseError(OG_ERR_FORMAT, "Incorrect number of arguments")) + sys.exit(SystemLib.ogRaiseError(OG_ERR_FORMAT, "Incorrect number of arguments")) disk_num, partition_num, image_name, repo = sys.argv[1:5] @@ -76,13 +48,13 @@ def main(): log_session_start(sys.argv[0], sys.argv[1:]) repo = repo if repo else "REPO" - if repo == ogGetIpAddress(): + if repo == NetLib.ogGetIpAddress(): repo = "CACHE" if ogCheckIpAddress(repo) == 0 or repo == "REPO": - ogunit = os.getenv('ogunit', "") - if not ogChangeRepo(repo, ogunit): - sys.exit(ogRaiseError(OG_ERR_NOTFOUND, f"{repo}")) + OGUNIT = os.getenv('OGUNIT', "") + if not NetLib.ogChangeRepo(repo, OGUNIT): + sys.exit(SystemLib.ogRaiseError(OG_ERR_NOTFOUND, f"{repo}")) if repo == "REPO" and os.getenv('boot') != "admin": retval = CambiarAcceso("admin") @@ -98,4 +70,4 @@ def main(): sys.exit(retval) if __name__ == "__main__": - main() \ No newline at end of file + main() diff --git a/client/interfaceAdm/EjecutarScript.py b/client/interfaceAdm/EjecutarScript.py old mode 100644 new mode 100755 index ad517fe..7e72861 --- a/client/interfaceAdm/EjecutarScript.py +++ b/client/interfaceAdm/EjecutarScript.py @@ -2,11 +2,10 @@ import os import time import subprocess import sys +import SystemLib +import ogGlobals -os.environ.setdefault('MSG_INTERFACE_START', 'Inicio de la interfaz') - -sys.path.append('/opt/opengnsys/lib/engine/bin') -from SystemLib import ogEcho +#sys.path.append('/opt/opengnsys/lib/engine/bin') def main(script_path): start_time = time.time() @@ -25,7 +24,7 @@ def main(script_path): f.write("") # Registro de inicio de ejecución - ogEcho('log session', f"{os.environ['MSG_INTERFACE_START']} {sys.argv[0]} {' '.join(sys.argv[1:])}") + SystemLib.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" @@ -45,13 +44,13 @@ def main(script_path): 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") + SystemLib.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"') + SystemLib.ogRaiseError('log session', ret_val) + SystemLib.ogEcho('log session', 'error "Operacion no realizada"') # Registro de fin de ejecución - ogEcho('log session', f"{os.environ['MSG_INTERFACE_END']} {ret_val}") + SystemLib.ogEcho('log session', f"{os.environ['MSG_INTERFACE_END']} {ret_val}") sys.exit(ret_val) diff --git a/client/interfaceAdm/GetConfiguration.py b/client/interfaceAdm/GetConfiguration.py old mode 100644 new mode 100755 index 7e64850..b5d1b49 --- a/client/interfaceAdm/GetConfiguration.py +++ b/client/interfaceAdm/GetConfiguration.py @@ -1,12 +1,9 @@ import os import subprocess import sys -#sys.path.append('/opt/opengnsys/lib/engine/bin') -#from DiskLib import ogDiskToDev -#from InventoryLib import ogGetSerialNumber -#!/usr/bin/env python3 +import FileSystemLib +import DiskLib -# No registrar los errores os.environ["DEBUG"] = "no" # Obtener el número de serie y configuración inicial @@ -16,40 +13,75 @@ cfg = "" # Obtener el número de discos disks = len(subprocess.getoutput("ogDiskToDev").split()) -# Recorrer discos -for dsk in range(1, disks + 1): + +for dsk in disk_list: # Número de particiones - particiones = subprocess.getoutput(f"ogGetPartitionsNumber {dsk}") or "0" + particiones = FileSystemLib.ogGetPartitionsNumber(dsk) or "0" particiones = int(particiones) # Tipo de tabla de particiones - ptt = subprocess.getoutput(f"ogGetPartitionTableType {dsk}") + ptt = DiskLib.ogGetPartitionTableType(dsk) ptt_mapping = {"MSDOS": 1, "GPT": 2, "LVM": 3, "ZPOOL": 4} ptt = ptt_mapping.get(ptt, 0) # Información de disco (partición 0) - cfg += f"{dsk}:0:{ptt}:::{subprocess.getoutput(f'ogGetDiskSize {dsk}')}:0;" + disk_size = DiskLib.ogGetDiskSize(dsk) + cfg += f"{dsk}:0:{ptt}:::{disk_size}:0;" # Recorrer particiones for par in range(1, particiones + 1): # Código del identificador de tipo de partición - cod = subprocess.getoutput(f"ogGetPartitionId {dsk} {par} 2>/dev/null") + cod = DiskLib.ogGetPartitionId(dsk, par) # Tipo del sistema de ficheros - fsi = subprocess.getoutput(f"getFsType {dsk} {par} 2>/dev/null") or "EMPTY" + fsi = FileSystemLib.getFsType(dsk, par) or "EMPTY" # Tamaño de la partición - tam = subprocess.getoutput(f"ogGetPartitionSize {dsk} {par} 2>/dev/null") or "0" + tam = DiskLib.ogGetPartitionSize(dsk, par) or "0" # Sistema operativo instalado soi = "" uso = 0 if fsi not in ["", "EMPTY", "LINUX-SWAP", "LINUX-LVM", "ZVOL"]: - if subprocess.getoutput(f"ogMount {dsk} {par} 2>/dev/null"): - soi = subprocess.getoutput(f"getOsVersion {dsk} {par} 2>/dev/null | cut -f2 -d:") + mount_point = DiskLib.ogMount(dsk, par) + if mount_point: + # Obtener la versión del sistema operativo instalado + try: + # Asumiendo que getOsVersion es una función disponible + import OsLib # Debes tener OsLib.py disponible con la función getOsVersion + soi_output = OsLib.getOsVersion(dsk, par) + except ImportError: + # Si no está disponible, usar subprocess como alternativa + soi_output = subprocess.getoutput(f"getOsVersion {dsk} {par} 2>/dev/null") + + soi = soi_output.split(':')[1] if ':' in soi_output else '' + # Hacer un segundo intento para algunos casos especiales + if not soi: + soi_output = subprocess.getoutput(f"getOsVersion {dsk} {par} 2>/dev/null") + soi = soi_output.split(':')[1] if ':' in soi_output else '' + + # Sistema de archivos para datos (sistema operativo "DATA") 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") + + # Obtener porcentaje de uso + mount_point = DiskLib.ogGetMountPoint(dsk, par) + df_output = subprocess.getoutput(f"df {mount_point}") + lines = df_output.splitlines() + if len(lines) >= 2: + uso_str = lines[1].split()[4] # Esta debería ser la quinta columna + if uso_str.endswith('%'): + uso = int(uso_str.rstrip('%')) + else: + uso = int(uso_str) + else: + uso = 0 + else: + soi = "" + uso = 0 + else: + soi = "" + uso = 0 cfg += f"{dsk}:{par}:{cod}:{fsi}:{soi}:{tam}:{uso};" diff --git a/client/interfaceAdm/GetIpAddress.py b/client/interfaceAdm/GetIpAddress.py deleted file mode 100644 index 7549c60..0000000 --- a/client/interfaceAdm/GetIpAddress.py +++ /dev/null @@ -1,11 +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(get_ip_address()) diff --git a/client/interfaceAdm/IniciarSesion.py b/client/interfaceAdm/IniciarSesion.py old mode 100644 new mode 100755 diff --git a/client/interfaceAdm/Reiniciar.py b/client/interfaceAdm/Reiniciar.py old mode 100644 new mode 100755 diff --git a/client/interfaceAdm/RestaurarImagen.py b/client/interfaceAdm/RestaurarImagen.py old mode 100644 new mode 100755 index e5f3f37..b3716cc --- a/client/interfaceAdm/RestaurarImagen.py +++ b/client/interfaceAdm/RestaurarImagen.py @@ -15,4 +15,4 @@ if __name__ == "__main__": additional_args = sys.argv[7:] exit_code = deploy_image(ip, image_name, disk, partition, protocol, protocol_options, *additional_args) - sys.exit(exit_code) \ No newline at end of file + sys.exit(exit_code) diff --git a/client/interfaceAdm/getConfiguration.py b/client/interfaceAdm/getConfiguration.py old mode 100644 new mode 100755 diff --git a/client/interfaceAdm/getIpAddress.py b/client/interfaceAdm/getIpAddress.py old mode 100644 new mode 100755 index 8820349..7549c60 --- a/client/interfaceAdm/getIpAddress.py +++ b/client/interfaceAdm/getIpAddress.py @@ -1,5 +1,11 @@ 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 + print(get_ip_address()) diff --git a/client/interfaceAdm/procesaCache.py b/client/interfaceAdm/procesaCache.py old mode 100644 new mode 100755 From e73700a57d635f77ddbe3638070c089902f5ad21 Mon Sep 17 00:00:00 2001 From: aguerrero Date: Thu, 7 Nov 2024 06:10:58 +0000 Subject: [PATCH 029/167] refs #1114 scripts function call updates --- client/shared/scripts/__init__.py | 0 client/shared/scripts/bootOS.py | 34 ++++---- client/shared/scripts/bootOSCustomTemplate.py | 56 +++++++------ client/shared/scripts/buildToOrder.py | 0 .../scripts/configureOSCustomTemplate.py | 0 .../scripts/createImageCustomTemplate..py | 0 .../shared/scripts/createLogicalPartitions.py | 0 .../shared/scripts/createPrimaryPartitions.py | 5 +- client/shared/scripts/deployImage.py | 84 ++++++++++--------- client/shared/scripts/formatFs.py | 10 ++- client/shared/scripts/generateMenuDefault.py | 5 +- client/shared/scripts/getFsType.py | 5 +- client/shared/scripts/getIpAddress.py | 13 ++- client/shared/scripts/getOsVersion.py | 12 +-- client/shared/scripts/grubSyntax.py | 9 +- client/shared/scripts/initCache.py | 44 +++++----- client/shared/scripts/installOfflineMode.py | 24 +++--- .../shared/scripts/launchOgagentInstaller.py | 38 +++++---- client/shared/scripts/listPartitions.py | 17 ++-- .../shared/scripts/listPrimaryPartitions.py | 15 ++-- client/shared/scripts/menuBrowser.py | 5 +- .../scripts/restoreImageCustomTemplate.py | 5 +- client/shared/scripts/runApplicationX.py | 2 +- client/shared/scripts/runhttplog.py | 2 +- 24 files changed, 211 insertions(+), 174 deletions(-) mode change 100644 => 100755 client/shared/scripts/__init__.py mode change 100644 => 100755 client/shared/scripts/bootOS.py mode change 100644 => 100755 client/shared/scripts/bootOSCustomTemplate.py mode change 100644 => 100755 client/shared/scripts/buildToOrder.py mode change 100644 => 100755 client/shared/scripts/configureOSCustomTemplate.py mode change 100644 => 100755 client/shared/scripts/createImageCustomTemplate..py mode change 100644 => 100755 client/shared/scripts/createLogicalPartitions.py mode change 100644 => 100755 client/shared/scripts/createPrimaryPartitions.py mode change 100644 => 100755 client/shared/scripts/deployImage.py mode change 100644 => 100755 client/shared/scripts/formatFs.py mode change 100644 => 100755 client/shared/scripts/generateMenuDefault.py mode change 100644 => 100755 client/shared/scripts/getFsType.py mode change 100644 => 100755 client/shared/scripts/getIpAddress.py mode change 100644 => 100755 client/shared/scripts/getOsVersion.py mode change 100644 => 100755 client/shared/scripts/grubSyntax.py mode change 100644 => 100755 client/shared/scripts/initCache.py mode change 100644 => 100755 client/shared/scripts/installOfflineMode.py mode change 100644 => 100755 client/shared/scripts/launchOgagentInstaller.py mode change 100644 => 100755 client/shared/scripts/listPartitions.py mode change 100644 => 100755 client/shared/scripts/listPrimaryPartitions.py mode change 100644 => 100755 client/shared/scripts/menuBrowser.py mode change 100644 => 100755 client/shared/scripts/restoreImageCustomTemplate.py mode change 100644 => 100755 client/shared/scripts/runApplicationX.py mode change 100644 => 100755 client/shared/scripts/runhttplog.py diff --git a/client/shared/scripts/__init__.py b/client/shared/scripts/__init__.py old mode 100644 new mode 100755 diff --git a/client/shared/scripts/bootOS.py b/client/shared/scripts/bootOS.py old mode 100644 new mode 100755 index 9950a20..678c377 --- a/client/shared/scripts/bootOS.py +++ b/client/shared/scripts/bootOS.py @@ -1,6 +1,10 @@ import sys import os import subprocess +import SystemLib +import FileSystemLib +import DiskLib +import Boot #!/usr/bin/env python3 # Script de ejemplo para arrancar un sistema operativo instalado. @@ -9,18 +13,18 @@ import subprocess def main(): prog = os.path.basename(__file__) if len(sys.argv) < 3 or len(sys.argv) > 6: - og_raise_error(1, f"Formato: {prog} ndisco nfilesys [str_kernel str_initrd str_kernelparams]") + SystemLib.ogRaiseError(1, f"Formato: {prog} ndisco nfilesys [str_kernel str_initrd str_kernelparams]") disk = sys.argv[1] filesystem = sys.argv[2] try: - part = og_disk_to_dev(disk, filesystem) + part = DiskLib.ogDiskToDev(disk, filesystem) except Exception as e: sys.exit(1) try: - mntdir = og_mount(disk, filesystem) + mntdir = FileSystemLib.ogMount(disk, filesystem) except Exception as e: sys.exit(1) @@ -28,17 +32,17 @@ def main(): mount_output = subprocess.getoutput(f"mount | grep -q '{mntdir}.*(rw'") if mount_output: - og_echo("log", "session", "MSG_WARNING: MSG_MOUNTREADONLY") - og_unmount(disk, filesystem) - og_check_fs(disk, filesystem) + SystemLib.ogEcho("log", "session", "MSG_WARNING: MSG_MOUNTREADONLY") + FileSystemLib.ogUnmount(disk, filesystem) + FileSystemLib.ogCheckFs(disk, filesystem) - part = og_disk_to_dev(disk, filesystem) + part = DiskLib.ogDiskToDev(disk, filesystem) os.makedirs(mntdir, exist_ok=True) subprocess.run(["ntfs-3g", "-o", "remove_hiberfile", part, mntdir]) - og_echo("log", "session", "Particion desbloqueada") + SystemLib.ogEcho("log", "session", "Particion desbloqueada") - og_unmount(disk, filesystem) - og_mount(disk, filesystem) + FileSystemLib.ogUnmount(disk, filesystem) + FileSystemLib.ogMount(disk, filesystem) if subprocess.call("which bootOsCustom", shell=True, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) == 0: print("[10] Configuración personalizada del inicio.") @@ -46,13 +50,13 @@ def main(): print("[70] Desmontar todos los sistemas de archivos.") subprocess.run(["sync"]) - for i in range(1, len(og_disk_to_dev(disk, filesystem).split())): - og_unmount_all(i) + for i in range(1, len(DiskLib.ogDiskToDev(disk, filesystem).split())): + FileSystemLib.ogUnmountAll(i) print("[80] Desmontar cache local.") - og_unmount_cache() + FileSystemLib.ogUnmount_cache() print("[90] Arrancar sistema operativo.") - og_boot(sys.argv[1:]) + BootLib.ogBoot(sys.argv[1:]) if __name__ == "__main__": - main() \ No newline at end of file + main() diff --git a/client/shared/scripts/bootOSCustomTemplate.py b/client/shared/scripts/bootOSCustomTemplate.py old mode 100644 new mode 100755 index 1f5f0a1..d6c3bf6 --- a/client/shared/scripts/bootOSCustomTemplate.py +++ b/client/shared/scripts/bootOSCustomTemplate.py @@ -1,5 +1,10 @@ import sys import os +import SystemLib +import DiskLib +import FileSystemLib +import NetLib +import FileLib #!/usr/bin/env python3 """ @@ -12,7 +17,6 @@ bootOsCustom @version 1.1.1 Soporta varios discos """ - # CONFIGURAR: Partición de datos de Windows que no queremos ocultar (valor por defecto '0' no oculta nada) DISKDATA = 0 PARTDATA = 0 @@ -21,7 +25,7 @@ PROG = os.path.basename(__file__) # Control de errores if len(sys.argv) < 3: - ogRaiseError(OG_ERR_FORMAT, f"Formato: {PROG} ndisco nparticion") + SystemLib.ogRaiseError(OG_ERR_FORMAT, f"Formato: {PROG} ndisco nparticion") sys.exit(1) # Parámetros obligatorios. @@ -29,61 +33,61 @@ DISK = sys.argv[1] # Nº de disco. PART = sys.argv[2] # Nº de partición. # Paso 0: Añadir código para realizar control de errores de los parámetros de entrada (recomendado). -DEVICE = ogDiskToDev(DISK, PART) +DEVICE = DiskLib.ogDiskToDev(DISK, PART) if not DEVICE: sys.exit(1) # Paso 1: Adaptar el código de ejemplo para arranque personalizado. # Nota: el script "bootOs" llama al script "bootOsCustom" después de realizar la operaciones de inicio estándar y antes de desmontar las particiones e iniciar el sistema operativo. -MNTDIR = ogMount(DISK, PART) +MNTDIR = FileSystemLib.ogMount(DISK, PART) if not MNTDIR: sys.exit(1) -NAME = ogGetHostname() +NAME = NetLib.ogGetHostname() NAME = NAME if NAME else "pc" -OSTYPE = ogGetOsType(DISK, PART) +OSTYPE = Inventory.ogGetOsType(DISK, PART) if OSTYPE == "Windows": # Mostrar las particiones NTFS de sistema (dos opciones) # Opción 1: SIN ocultar las demás. - # ogEcho log session "[40] Mostrar y activar particion de Windows {PART}." - # if ogGetPartitionType(DISK, PART) in ["HNTFS", "WIN-RESERV"]: - # ogUnhidePartition(DISK, PART) + # SystemLib.ogEcho log session "[40] Mostrar y activar particion de Windows {PART}." + # if DiskLib.ogGetPartitionType(DISK, PART) in ["HNTFS", "WIN-RESERV"]: + # DiskLib.ogUnhidePartition(DISK, PART) # Recorremos los distintos discos - # for DEVICE in ogDiskToDev(): - # d = ogDevToDisk(DEVICE) + # for DEVICE in DiskLib.ogDiskToDev(): + # d = DiskLib.ogDevToDisk(DEVICE) # # Mostrar las particiones NTFS de sistema (dos opciones) # # Opción 2: Ocultamos las demás. - # ogEcho log session "[40] Activar particion de Windows {PART} y ocultar las demás." - # for i in range(1, ogGetPartitionsNumber(d) + 1): + # SystemLib.ogEcho log session "[40] Activar particion de Windows {PART} y ocultar las demás." + # for i in range(1, DiskLib.ogGetPartitionsNumber(d) + 1): # if (d == DISK and i == PART) or (d == DISKDATA and i == PARTDATA): - # if ogGetPartitionType(d, i) in ["HNTFS", "WIN-RESERV"]: - # ogUnhidePartition(d, i) + # if DiskLib.ogGetPartitionType(d, i) in ["HNTFS", "WIN-RESERV"]: + # DiskLib.ogUnhidePartition(d, i) # else: - # if ogGetPartitionType(d, i) in ["NTFS", "WINDOWS"]: - # ogHidePartition(d, i) + # if DiskLib.ogGetPartitionType(d, i) in ["NTFS", "WINDOWS"]: + # DiskLib.ogHidePartition(d, i) # # Borrar marcas de arrranque de todos los Windows instalados en el disco. - # ogEcho log session "[30] Borrar marcas de arrranque de todos los Windows instalados en el disco." - # for i in range(1, ogGetPartitionsNumber(d) + 1): - # if ogGetOsType(d, i) == "Windows": - # ogMount(d, i) + # SystemLib.ogEcho log session "[30] Borrar marcas de arrranque de todos los Windows instalados en el disco." + # for i in range(1, DiskLib.ogGetPartitionsNumber(d) + 1): + # if Inventory.ogGetOsType(d, i) == "Windows": + # FileSystemLib.ogMount(d, i) # os.system("rm -f /mnt/*/ogboot.*") elif OSTYPE == "Linux": # Modificar el nombre del equipo - # ogEcho log session "[30] Asignar nombre Linux \"{NAME}\"." - # ETC = ogGetPath(DISK, PART, "/etc") + # SystemLib.ogEcho log session "[30] Asignar nombre Linux \"{NAME}\"." + # ETC = FileLib.ogGetPath(DISK, PART, "/etc") # if os.path.isdir(ETC): # with open(os.path.join(ETC, "hostname"), "w") as f: # f.write(NAME) # Sustituir UUID o LABEL por su dispositivo en definición de sistema de archivo raíz. # if os.path.isfile(os.path.join(ETC, "fstab")): - # ogEcho log session "[40] Actualizar fstab con particion raíz \"{PART}\"." + # SystemLib.ogEcho log session "[40] Actualizar fstab con particion raíz \"{PART}\"." # with open(os.path.join(ETC, "fstab"), "r") as f: # lines = f.readlines() # with open("/tmp/fstab", "w") as f: @@ -97,5 +101,5 @@ elif OSTYPE == "Linux": # En el servidor el nuevo fichero debe situarse en el directorio del grupo: # /opt/opengnsys/images/groups/nombre_aula # if os.path.isfile(os.path.join(ogGetGroupDir(), "passwd")): - # ogEcho log session "[65] Cambiar claves de usuarios." - # os.system(f"cp {os.path.join(ogGetGroupDir(), 'passwd')} {os.path.join(MNTDIR, 'etc')}") \ No newline at end of file + # SystemLib.ogEcho log session "[65] Cambiar claves de usuarios." + # os.system(f"cp {os.path.join(ogGetGroupDir(), 'passwd')} {os.path.join(MNTDIR, 'etc')}") diff --git a/client/shared/scripts/buildToOrder.py b/client/shared/scripts/buildToOrder.py old mode 100644 new mode 100755 diff --git a/client/shared/scripts/configureOSCustomTemplate.py b/client/shared/scripts/configureOSCustomTemplate.py old mode 100644 new mode 100755 diff --git a/client/shared/scripts/createImageCustomTemplate..py b/client/shared/scripts/createImageCustomTemplate..py old mode 100644 new mode 100755 diff --git a/client/shared/scripts/createLogicalPartitions.py b/client/shared/scripts/createLogicalPartitions.py old mode 100644 new mode 100755 diff --git a/client/shared/scripts/createPrimaryPartitions.py b/client/shared/scripts/createPrimaryPartitions.py old mode 100644 new mode 100755 index 9cd5fe9..18e9c80 --- a/client/shared/scripts/createPrimaryPartitions.py +++ b/client/shared/scripts/createPrimaryPartitions.py @@ -1,5 +1,6 @@ import sys +import DiskLib if __name__ == "__main__": - result = og_create_partitions(sys.argv[1:]) - sys.exit(result.returncode) \ No newline at end of file + result = DiskLib.ogCreatePartitions(sys.argv[1:]) + sys.exit(result.returncode) diff --git a/client/shared/scripts/deployImage.py b/client/shared/scripts/deployImage.py old mode 100644 new mode 100755 index 8891c6e..d282025 --- a/client/shared/scripts/deployImage.py +++ b/client/shared/scripts/deployImage.py @@ -1,13 +1,17 @@ import os import sys import time +import SystemLib +import DiskLib +import NetLib +import ImageLib #!/usr/bin/env python3 def main(): PROG = os.path.basename(__file__) if len(sys.argv) < 5: - ogRaiseError("session", OG_ERR_FORMAT, f"{MSG_FORMAT}: {PROG} REPO imagen ndisco nparticion [ UNICAST-DIRECT|UNICAST|UNICAST-CACHE|MULTICAST-DIRECT|MULTICAST|MULTICAST-CACHE|TORRENT [opciones protocolo] ]") + SystemLib.ogRaiseError("session", OG_ERR_FORMAT, f"{MSG_FORMAT}: {PROG} REPO imagen ndisco nparticion [ UNICAST-DIRECT|UNICAST|UNICAST-CACHE|MULTICAST-DIRECT|MULTICAST|MULTICAST-CACHE|TORRENT [opciones protocolo] ]") sys.exit(1) TIME1 = time.time() @@ -24,36 +28,36 @@ def main(): with open(OGLOGCOMMAND, 'w') as f: f.write(" ") - if ogGetCaller() != "EjecutarScript": + if SystemLib.ogGetCaller() != "EjecutarScript": with open(OGLOGSESSION, 'w') as f: f.write("") - ogEcho("log", "session", f"[1] {MSG_SCRIPTS_START} {PROG} {' '.join(sys.argv)}") + SystemLib.ogEcho("log", "session", f"[1] {MSG_SCRIPTS_START} {PROG} {' '.join(sys.argv)}") - if ogIsLocked(DISK, PART): - sys.exit(ogRaiseError("session", OG_ERR_LOCKED, f"{MSG_PARTITION}, {DISK} {PART}")) + if FileSystemLib.ogIsLocked(DISK, PART): + sys.exit(SystemLib.ogRaiseError("session", OG_ERR_LOCKED, f"{MSG_PARTITION}, {DISK} {PART}")) - ogEcho("log", "session", f"{MSG_HELP_ogUnmount} {DISK} {PART}") - ogUnmount(DISK, PART) + SystemLib.ogEcho("log", "session", f"{MSG_HELP_FileSystemLib.ogUnmount} {DISK} {PART}") + FileSystemLib.ogUnmount(DISK, PART) - if REPO == ogGetIpAddress() or REPO == "CACHE": + if REPO == NetLib.ogGetIpAddress() or REPO == "CACHE": MODE = "CACHE" else: - if ogCheckIpAddress(REPO) == 0 or REPO == "REPO": - if not ogChangeRepo(REPO, OGUNIT): - sys.exit(ogRaiseError(OG_ERR_NOTFOUND, f"{REPO} {OGUNIT}")) + if DiskLib.ogCheckIpAddress(REPO) == 0 or REPO == "REPO": + if not NetLib.ogChangeRepo(REPO, OGUNIT): + sys.exit(SystemLib.ogRaiseError(OG_ERR_NOTFOUND, f"{REPO} {OGUNIT}")) MODE = "REPO" - IMGOS = ogGetImageInfo(ogGetPath(MODE, f"{IMGNAME}.img")) + IMGOS = ImageLib.ogGetImageInfo(ogGetPath(MODE, f"{IMGNAME}.img")) if IMGOS == 1: - sys.exit(ogRaiseError("session", OG_ERR_NOTFOUND, f"{REPO} {IMGNAME}")) + sys.exit(SystemLib.ogRaiseError("session", OG_ERR_NOTFOUND, f"{REPO} {IMGNAME}")) elif IMGOS == 5: - sys.exit(ogRaiseError("session", OG_ERR_IMAGEFILE, f"{REPO} {IMGNAME}")) + sys.exit(SystemLib.ogRaiseError("session", OG_ERR_IMAGEFILE, f"{REPO} {IMGNAME}")) elif IMGOS != 0: - sys.exit(ogRaiseError("session", OG_ERR_GENERIC)) + sys.exit(SystemLib.ogRaiseError("session", OG_ERR_GENERIC)) IMGSIZE = os.path.getsize(ogGetPath(MODE, f"{IMGNAME}.img")) // 1024 - ogEcho("log", "session", f"[1] REPO={REPO} IMG-FILE={IMGNAME}.img SIZE={IMGSIZE} (KB) METADATA={IMGOS}") + SystemLib.ogEcho("log", "session", f"[1] REPO={REPO} IMG-FILE={IMGNAME}.img SIZE={IMGSIZE} (KB) METADATA={IMGOS}") if MODE == "CACHE": NEXTOPERATION = "CACHE" @@ -62,36 +66,36 @@ def main(): NEXTOPERATION = PROTO.split('-')[0] elif PROTO in ["TORRENT", "TORRENT-CACHE", "MULTICAST", "MULTICAST-CACHE", "UNICAST", "UNICAST-CACHE"]: PROTO = PROTO.split('-')[0] - ogEcho("log", "session", f"[2] updateCache {REPO} /{IMGNAME}.img {PROTO} {PROTOOPT}") + SystemLib.ogEcho("log", "session", f"[2] updateCache {REPO} /{IMGNAME}.img {PROTO} {PROTOOPT}") TIME2 = time.time() RETVAL = updateCache(REPO, f"/{IMGNAME}.img", PROTO, PROTOOPT) TIME2 = time.time() - TIME2 - ogEcho("log", "session", f" [ ] {MSG_SCRIPTS_TIME_PARTIAL} updateCache {TIME2 // 60}m {TIME2 % 60}s") + SystemLib.ogEcho("log", "session", f" [ ] {MSG_SCRIPTS_TIME_PARTIAL} updateCache {TIME2 // 60}m {TIME2 % 60}s") if RETVAL == 0: - ogEcho("log", "session", "[50] updateCache (OK)") + SystemLib.ogEcho("log", "session", "[50] updateCache (OK)") NEXTOPERATION = "CACHE" elif RETVAL in [15, 16]: - ogEcho("log", "session", f"[50] {MSG_ERR_NOTCACHE} ; {MSG_ERR_CACHESIZE}") - ogEcho("log", "session", f"[50] {MSG_SCRIPTS_CHECK_ENGINE}: RESTOREPROTOCOLNOTCACHE={RESTOREPROTOCOLNOTCACHE}") + SystemLib.ogEcho("log", "session", f"[50] {MSG_ERR_NOTCACHE} ; {MSG_ERR_CACHESIZE}") + SystemLib.ogEcho("log", "session", f"[50] {MSG_SCRIPTS_CHECK_ENGINE}: RESTOREPROTOCOLNOTCACHE={RESTOREPROTOCOLNOTCACHE}") if RESTOREPROTOCOLNOTCACHE == "MULTICAST": NEXTOPERATION = "MULTICAST" if PROTO == "MULTICAST" else "UNICAST" elif RESTOREPROTOCOLNOTCACHE == "UNICAST": NEXTOPERATION = "UNICAST" elif RESTOREPROTOCOLNOTCACHE == "NONE": if RETVAL == 15: - ogEcho("log", "session", f"[100] {MSG_ERR_NOTCACHE}") - sys.exit(ogRaiseError("session", OG_ERR_NOTCACHE, "NOT CACHE")) + SystemLib.ogEcho("log", "session", f"[100] {MSG_ERR_NOTCACHE}") + sys.exit(SystemLib.ogRaiseError("session", OG_ERR_NOTCACHE, "NOT CACHE")) elif RETVAL == 16: - ogEcho("log", "session", f"[100] {MSG_ERR_CACHESIZE}") - sys.exit(ogRaiseError("session", OG_ERR_CACHESIZE, "CACHE FULL")) + SystemLib.ogEcho("log", "session", f"[100] {MSG_ERR_CACHESIZE}") + sys.exit(SystemLib.ogRaiseError("session", OG_ERR_CACHESIZE, "CACHE FULL")) elif RETVAL in [57, 60]: sys.exit(RETVAL) else: sys.exit(RETVAL) else: - sys.exit(ogRaiseError("session", OG_ERR_FORMAT, f"{MSG_ERR_FORMAT}, {PROTO}")) + sys.exit(SystemLib.ogRaiseError("session", OG_ERR_FORMAT, f"{MSG_ERR_FORMAT}, {PROTO}")) else: - sys.exit(ogRaiseError("session", OG_ERR_FORMAT, f"{MSG_ERR_FORMAT}, {REPO}")) + sys.exit(SystemLib.ogRaiseError("session", OG_ERR_FORMAT, f"{MSG_ERR_FORMAT}, {REPO}")) TIME3 = time.time() @@ -103,37 +107,37 @@ def main(): PARAMS = f"{REPO} {IMGNAME} {DISK} {PART} {PROTO} {PROTOOPT}" if os.system("which restoreImageCustom") == 0: - ogEcho("log", "session", f"[55] {MSG_HELP_ogRestoreImage}: restoreImageCustom {PARAMS}") + SystemLib.ogEcho("log", "session", f"[55] {MSG_HELP_ogRestoreImage}: restoreImageCustom {PARAMS}") os.system(f"restoreImageCustom {PARAMS}") else: - ogEcho("log", "session", f"[55] {MSG_HELP_ogRestoreImage}: restoreImage {PARAMS}") + SystemLib.ogEcho("log", "session", f"[55] {MSG_HELP_ogRestoreImage}: restoreImage {PARAMS}") os.system(f"restoreImage {PARAMS}") RETVAL = os.system(f"restoreImage {PARAMS}") RESUMERESTOREIMAGE = os.popen(f"grep -m 1 'Total Time:' {OGLOGCOMMAND}").read() - ogEcho("log", "session", f" [ ] {RESUMERESTOREIMAGE}") + SystemLib.ogEcho("log", "session", f" [ ] {RESUMERESTOREIMAGE}") if RETVAL != 0: - ogRaiseError("session", OG_ERR_IMAGE, f"{REPO} {IMGNAME}") - if ogGetCaller() != "EjecutarScript": - ogEcho("log", "session", f"{MSG_INTERFACE_END} {OG_ERR_IMAGE}") + SystemLib.ogRaiseError("session", OG_ERR_IMAGE, f"{REPO} {IMGNAME}") + if SystemLib.ogGetCaller() != "EjecutarScript": + SystemLib.ogEcho("log", "session", f"{MSG_INTERFACE_END} {OG_ERR_IMAGE}") sys.exit(OG_ERR_IMAGE) TIME3 = time.time() - TIME3 - ogEcho("log", "session", f" [ ] {MSG_SCRIPTS_TIME_PARTIAL} : {TIME3 // 60}m {TIME3 % 60}s") + SystemLib.ogEcho("log", "session", f" [ ] {MSG_SCRIPTS_TIME_PARTIAL} : {TIME3 // 60}m {TIME3 % 60}s") if os.system("which configureOsCustom") == 0: - ogEcho("log", "session", "[90] configureOsCustom") + SystemLib.ogEcho("log", "session", "[90] configureOsCustom") os.system(f"configureOsCustom {DISK} {PART} {REPO} {IMGNAME}") else: - ogEcho("log", "session", f"[90] {MSG_SCRIPTS_OS_CONFIGURE}") + SystemLib.ogEcho("log", "session", f"[90] {MSG_SCRIPTS_OS_CONFIGURE}") os.system(f"configureOs {DISK} {PART}") TIME = time.time() - TIME1 - ogEcho("log", "session", f"[100] {MSG_SCRIPTS_TIME_TOTAL} {TIME // 60}m {TIME % 60}s") + SystemLib.ogEcho("log", "session", f"[100] {MSG_SCRIPTS_TIME_TOTAL} {TIME // 60}m {TIME % 60}s") - if ogGetCaller() != "EjecutarScript": - ogEcho("log", "session", f"{MSG_INTERFACE_END} {RETVAL}") + if SystemLib.ogGetCaller() != "EjecutarScript": + SystemLib.ogEcho("log", "session", f"{MSG_INTERFACE_END} {RETVAL}") sys.exit(RETVAL) if __name__ == "__main__": - main() \ No newline at end of file + main() diff --git a/client/shared/scripts/formatFs.py b/client/shared/scripts/formatFs.py old mode 100644 new mode 100755 index ee8fec9..78e7e80 --- a/client/shared/scripts/formatFs.py +++ b/client/shared/scripts/formatFs.py @@ -1,6 +1,8 @@ import sys import time import subprocess +import SystemLib +import FileSystemLib #!/usr/bin/env python3 # Script de ejemplo para formatear un sistema de archivos. @@ -11,20 +13,20 @@ def main(): prog = sys.argv[0] if len(sys.argv) != 3: - ogRaiseError(1, f"{prog} ndisco nparticion") + SystemLib.ogRaiseError(1, f"{prog} ndisco nparticion") disk = sys.argv[1] partition = sys.argv[2] # Desmontar y formatear el sistema de archivos. print("[5] Desmontando sistema de archivos") - ogUnmountFs(disk, partition) + FileSystemLib.ogUnmountFs(disk, partition) print("[20] Formateando sistema de archivos") - ogFormatFs(disk, partition) + FileSystemLib.ogFormatFs(disk, partition) elapsed_time = time.time() - start_time minutes, seconds = divmod(int(elapsed_time), 60) print(f"[100] Duración de la operación {minutes}m {seconds}s") if __name__ == "__main__": - main() \ No newline at end of file + main() diff --git a/client/shared/scripts/generateMenuDefault.py b/client/shared/scripts/generateMenuDefault.py old mode 100644 new mode 100755 index 7f30baf..4c06159 --- a/client/shared/scripts/generateMenuDefault.py +++ b/client/shared/scripts/generateMenuDefault.py @@ -1,7 +1,8 @@ +#!/usr/bin/env python3 + import os import subprocess -#!/usr/bin/env python3 # generateMenuDefault - Crea fichero con la página web de inicio del cliente # con información de red y de los sistemas operativos instalados, # crea fichero con información del contenido de la caché local. @@ -89,4 +90,4 @@ with open(FILEINFOHTML, 'a') as f: # Crear contenido de la caché. with open(FILEINFOCACHE, 'a') as f: - f.write(subprocess.getoutput(CACHECONTENIDO)) \ No newline at end of file + f.write(subprocess.getoutput(CACHECONTENIDO)) diff --git a/client/shared/scripts/getFsType.py b/client/shared/scripts/getFsType.py old mode 100644 new mode 100755 index d9fcf54..88fd438 --- a/client/shared/scripts/getFsType.py +++ b/client/shared/scripts/getFsType.py @@ -1,5 +1,6 @@ import sys +import FileSystemLib if __name__ == "__main__": - output = ogGetFsType(sys.argv[1:]) - print(output) \ No newline at end of file + output = FileSystemLib.ogGetFsType(sys.argv[1:]) + print(output) diff --git a/client/shared/scripts/getIpAddress.py b/client/shared/scripts/getIpAddress.py old mode 100644 new mode 100755 index 7369d4f..65f62aa --- a/client/shared/scripts/getIpAddress.py +++ b/client/shared/scripts/getIpAddress.py @@ -1,17 +1,16 @@ #!/usr/bin/env python3 -import subprocess import sys -from NetLib import ogGetIpAddress +import NetLib def get_ip_address(*args): try: - # Ejecuta ogGetIpAddress como un comando en el sistema - result = subprocess.run(["/opt/opengnsys/client/lib/engine/bin/ogGetIpAddress"] + list(args), - capture_output=True, text=True, check=True) - print(result.stdout.strip()) - except subprocess.CalledProcessError as e: + # Llama a ogGetIpAddress desde NetLib y captura el resultado + result = NetLib.ogGetIpAddress(*args) + print(result.strip()) + except Exception as e: print(f"Error ejecutando ogGetIpAddress: {e}", file=sys.stderr) sys.exit(1) if __name__ == "__main__": get_ip_address(*sys.argv[1:]) + diff --git a/client/shared/scripts/getOsVersion.py b/client/shared/scripts/getOsVersion.py old mode 100644 new mode 100755 index b8637da..9b8e82a --- a/client/shared/scripts/getOsVersion.py +++ b/client/shared/scripts/getOsVersion.py @@ -1,12 +1,14 @@ -import subprocess import sys +import InventoryLib def main(): try: - subprocess.run(["ogGetOsVersion"] + sys.argv[1:], check=True) - except subprocess.CalledProcessError as e: + result = InventoryLib.ogGetOsVersion(*sys.argv[1:]) + print(result.strip()) + except Exception as e: print(f"An error occurred: {e}", file=sys.stderr) - sys.exit(e.returncode) + sys.exit(1) if __name__ == "__main__": - main() \ No newline at end of file + main() + diff --git a/client/shared/scripts/grubSyntax.py b/client/shared/scripts/grubSyntax.py old mode 100644 new mode 100755 index 6699b90..f2c9394 --- a/client/shared/scripts/grubSyntax.py +++ b/client/shared/scripts/grubSyntax.py @@ -1,6 +1,7 @@ import os import subprocess import sys +import DiskLib #!/usr/bin/env python3 @@ -41,8 +42,8 @@ def prepare_grub_to_access_device(device): print(f"insmod {module}") if "nvme" in device: - d, p = ogDevToDisk(device) - if ogGetPartitionTableType(d) == "GPT": + d, p = DiskLib.ogDevToDisk(device) + if DiskLib.ogGetPartitionTableType(d) == "GPT": nvme_device = f"hd{d-1},gpt{p}" else: nvme_device = f"hd{d-1},{p-1}" @@ -85,7 +86,7 @@ def main(): f.write("DISTRIB_DESCRIPTION=OpenGnsys Live\n") if disk: - os_search = ogDiskToDev(disk, part) + os_search = DiskLib.ogDiskToDev(disk, part) os_probed = run_command(f"os-prober | grep {os_search} | tr ' ' '^' | paste -s -d ' '") else: os_probed = run_command("os-prober | tr ' ' '^' | paste -s -d ' '") @@ -193,4 +194,4 @@ def main(): os.remove("/opt/opengnsys/cache/etc/lsb-release") if __name__ == "__main__": - main() \ No newline at end of file + main() diff --git a/client/shared/scripts/initCache.py b/client/shared/scripts/initCache.py old mode 100644 new mode 100755 index 886a53e..e60f784 --- a/client/shared/scripts/initCache.py +++ b/client/shared/scripts/initCache.py @@ -1,6 +1,10 @@ import sys import time import subprocess +import SystemLib +import FileSystemLib +import CacheLib +import DiskLib #!/usr/bin/env python3 @@ -30,13 +34,13 @@ def main(): NPART = int(args[1]) SIZE = int(args[2]) else: - ogRaiseError("OG_ERR_FORMAT", f"{EXECFORMAT}") + SystemLib.ogRaiseError("OG_ERR_FORMAT", f"{EXECFORMAT}") if NDISK < 1 or NPART < 1: - ogRaiseError("OG_ERR_FORMAT", f"{EXECFORMAT}") + SystemLib.ogRaiseError("OG_ERR_FORMAT", f"{EXECFORMAT}") if SIZE < -1: - ogRaiseError("OG_ERR_FORMAT", f"{EXECFORMAT}") + SystemLib.ogRaiseError("OG_ERR_FORMAT", f"{EXECFORMAT}") if SIZE == 0: print("No modificar la caché local.") @@ -44,44 +48,44 @@ def main(): if SIZE == -1: print("[10] Trabajar sin caché local.") - ogUnmountCache() - ogDeleteCache() + CacheLib.ogUnmountCache() + CacheLib.ogDeleteCache() else: - current_cache = ogFindCache() + current_cache = CacheLib.ogFindCache() if current_cache and f"{NDISK} {NPART}" != current_cache: print("[10] Detectada otra caché, eliminarla") - ogUnmountCache() - ogDeleteCache() + CacheLib.ogUnmountCache() + CacheLib.ogDeleteCache() try: - OLDSIZE = ogGetCacheSize() + OLDSIZE = CacheLib.ogGetCacheSize() except ValueError: OLDSIZE = 0 if SIZE <= 0: - ogRaiseError("OG_ERR_FORMAT", f"!({SIZE}>0)") + SystemLib.ogRaiseError("OG_ERR_FORMAT", f"!({SIZE}>0)") if SIZE != OLDSIZE: print("[10] Crear partición de caché local.") - ogUnmountCache() - ogCreateCache(NDISK, NPART, SIZE) - ogUpdatePartitionTable(NDISK) + CacheLib.ogUnmountCache() + CacheLib.ogCreateCache(NDISK, NPART, SIZE) + DiskLib.ogUpdatePartitionTable(NDISK) - cache = ogFindCache() - if not ogIsFormated(cache) or SIZE != OLDSIZE: + cache = CacheLib.ogFindCache() + if not FileSystemLib.ogIsFormated(cache) or SIZE != OLDSIZE: print("[50] Formatear caché local.") - ogFormatCache() + CacheLib.ogFormatCache() print("[70] Comprobar montaje de caché local.") - if ogMountCache() != 0: + if CacheLib.ogMountCache() != 0: print("[80] Comprobar consistencia y volver a montar caché local.") - ogCheckFs(cache) - if ogMountCache() != 0: + FileSystem.ogCheckFs(cache) + if CacheLib.ogMountCache() != 0: sys.exit(1) if MOUNT == 0: print("[90] Dejar desmontada la caché local.") - ogUnmountCache() + CacheLib.ogUnmountCache() TIME = time.time() - TIME1 print(f"[100] Duración de la operación {int(TIME // 60)}m {int(TIME % 60)}s") diff --git a/client/shared/scripts/installOfflineMode.py b/client/shared/scripts/installOfflineMode.py old mode 100644 new mode 100755 index 041d1af..89b5447 --- a/client/shared/scripts/installOfflineMode.py +++ b/client/shared/scripts/installOfflineMode.py @@ -1,6 +1,8 @@ import os import subprocess import sys +import SystemLib +import NetLib #!/usr/bin/env python3 @@ -18,9 +20,9 @@ Prepara el equipo cliente para el modo offline. PROG = os.path.basename(__file__) if len(sys.argv) > 1 and sys.argv[1] == "help": - og_help() + SystemLib.ogHelp() -og_echo("log", "session $MSG_HELP_installOfflineMode") +SystemLib.ogEcho("log", "session $MSG_HELP_installOfflineMode") # Cargamos las variables de entorno. OGENGINECONFIGURATE = os.getenv('OGENGINECONFIGURATE') @@ -31,26 +33,26 @@ DIRTFTP = "/opt/oglive/tftpboot" DIROGCLIENT = os.path.join(DIRTFTP, "ogclient") # Comprobamos que el DIROGCLIENT esta montado desde repo -repo_ip = og_get_repo_ip() +repo_ip = NetLib.ogGetRepoIp() result = subprocess.run(['df'], capture_output=True, text=True) if f"{repo_ip} {DIRTFTP}" not in result.stdout: - og_raise_error("OG_ERR_NOTFOUND", "REPO OGclient") + SystemLib.ogRaiseError("OG_ERR_NOTFOUND", "REPO OGclient") # Copiamos el kernel y el initrd. -og_echo("log", "session [10] updateBootCache") +SystemLib.ogEcho("log", "session [10] updateBootCache") if not update_boot_cache(): - og_raise_error("OG_ERR_NOTCACHE", "") + SystemLib.ogRaiseError("OG_ERR_NOTCACHE", "") # Creamos los dir necesarios. OGCAC = "/path/to/ogcac" # Placeholder for OGCAC path -og_echo("log", f"session [40] mkdir -p {OGCAC}/{{ogclient, menus, log}}.") +SystemLib.ogEcho("log", f"session [40] mkdir -p {OGCAC}/{{ogclient, menus, log}}.") os.makedirs(os.path.join(OGCAC, "menus/images/iconos"), exist_ok=True) os.makedirs(os.path.join(OGCAC, "ogclient"), exist_ok=True) os.makedirs(os.path.join(OGCAC, "log"), exist_ok=True) os.makedirs(os.path.join(OGCAC, "opt/opengnsys/images"), exist_ok=True) # Comparamos el cliente en el server y en cache -og_echo("log", f"session [60] cp {DIROGCLIENT}/ogclient.sqfs {OGCAC}/ogclient/") +SystemLib.ogEcho("log", f"session [60] cp {DIROGCLIENT}/ogclient.sqfs {OGCAC}/ogclient/") try: with open(os.path.join(DIROGCLIENT, "ogclient.sqfs.sum"), 'r') as f: SERVEROGCLIENT = f.read().strip() @@ -68,13 +70,13 @@ if CACHEOGCLIENT != SERVEROGCLIENT: subprocess.run(['cp', os.path.join(DIROGCLIENT, "ogclient.sqfs.sum"), os.path.join(OGCAC, "ogclient/")]) # Si se ha generado el menu de inicio lo copiamos a cache. -IPCLIENT = og_get_ip_address() +IPCLIENT = NetLib.ogGetIpAddress() MENU = os.path.join("/path/to/oglog", f"{IPCLIENT}.info.html") # Placeholder for OGLOG path ICONO = "images/iconos/logoopengnsys.png" if not os.path.isfile(MENU): generate_menu_default() -og_echo("log", f"session [90] cp {MENU} {OGCAC}/menus/{IPCLIENT}.html") +SystemLib.ogEcho("log", f"session [90] cp {MENU} {OGCAC}/menus/{IPCLIENT}.html") subprocess.run(['cp', MENU, os.path.join(OGCAC, f"menus/{IPCLIENT}.html")]) subprocess.run(['sed', '-i', 's/"../images"/"images"/g', os.path.join(OGCAC, f"menus/{IPCLIENT}.html")]) -subprocess.run(['wget', '--no-check-certificate', f"https://{og_get_repo_ip()}/opengnsys/{ICONO}", '-O', os.path.join(OGCAC, f"menus/{ICONO}")]) \ No newline at end of file +subprocess.run(['wget', '--no-check-certificate', f"https://{NetLib.ogGetRepoIp()}/opengnsys/{ICONO}", '-O', os.path.join(OGCAC, f"menus/{ICONO}")]) diff --git a/client/shared/scripts/launchOgagentInstaller.py b/client/shared/scripts/launchOgagentInstaller.py old mode 100644 new mode 100755 index 137db31..8006711 --- a/client/shared/scripts/launchOgagentInstaller.py +++ b/client/shared/scripts/launchOgagentInstaller.py @@ -2,6 +2,10 @@ import os import sys import subprocess import json +import FileLib +import FileSystemLib +import InventoryLib +import SystemLib #!/usr/bin/env python3 @@ -21,15 +25,15 @@ def main(): show_help(prog) if not callable(globals().get('ogRaiseError')): - raise_error(f"{prog}: it can only be executed by an ogLive client.") + SystemLib.ogRaiseError(f"{prog}: it can only be executed by an ogLive client.") if len(sys.argv) not in [3, 4]: - raise_error(f"{prog} ndisk npart [adminuser]") + SystemLib.ogRaiseError(f"{prog} ndisk npart [adminuser]") ndisk, npart = sys.argv[1], sys.argv[2] windowsadmin = sys.argv[3] if len(sys.argv) == 4 else None - mntdir = ogMount(ndisk, npart) + mntdir = FileSystemLib.ogMount(ndisk, npart) if not mntdir: sys.exit(1) @@ -41,17 +45,17 @@ def main(): pass if not ogversion: - raise_error(f"GET /rest/info") + SystemLib.ogRaiseError(f"GET /rest/info") - os_type = ogGetOsType(ndisk, npart) + os_type = Inventory.ogGetOsType(ndisk, npart) if os_type == "Windows": - hive = ogGetHivePath(mntdir, windowsadmin) + hive = FileSystemLib.ogGetHivePath(mntdir, windowsadmin) if not hive: - raise_error(f"{ndisk} {npart} {windowsadmin}/NTUSER.DAT") + SystemLib.ogRaiseError(f"{ndisk} {npart} {windowsadmin}/NTUSER.DAT") ogagentfile = f"OGAgentSetup-{ogversion.replace('pre', '')}.exe" - tmpdir = ogGetPath(f"{mntdir}/Windows/Temp") - if "opengnsys agent" in ogListSoftware(ndisk, npart).lower(): + tmpdir = FileLib.ogGetPath(f"{mntdir}/Windows/Temp") + if "opengnsys agent" in InventoryLib.ogListSoftware(ndisk, npart).lower(): print("OGAgent for Windows is already installed, you need to uninstall it before re-install.") else: if download_file(f"https://{ogGetServerIp()}/opengnsys/descargas/{ogagentfile}", f"{tmpdir}/{ogagentfile}"): @@ -69,17 +73,17 @@ exit print(f'Scheduled OGAgent installation after "{windowsadmin}" logon') print(" (for connection problems, check configuration file).") except subprocess.CalledProcessError: - raise_error(f"{ndisk} {npart} .../{windowsadmin}/NTUSER.DAT") + SystemLib.ogRaiseError(f"{ndisk} {npart} .../{windowsadmin}/NTUSER.DAT") else: - raise_error(f"{ndisk} {npart} /Windows/Temp/{ogagentfile}") + SystemLib.ogRaiseError(f"{ndisk} {npart} /Windows/Temp/{ogagentfile}") elif os_type == "Linux": - if "ogagent" in ogListSoftware(ndisk, npart).lower(): + if "ogagent" in InventoryLib.ogListSoftware(ndisk, npart).lower(): print("OGAgent for Linux is already installed, you need to uninstall it before re-install.") else: systemddir = f"{mntdir}/lib/systemd" if not (os.path.isdir(systemddir) and os.path.isdir(systemddir.replace('/lib', '/etc'))): - raise_error(f"{ndisk} {npart} systemd") + SystemLib.ogRaiseError(f"{ndisk} {npart} systemd") ogagentfile = None code = None @@ -91,7 +95,7 @@ exit code = f"if ! rpm -q ogagent &>/dev/null && [ -f /var/tmp/{ogagentfile} ]; then yum install -y /var/tmp/{ogagentfile}; fi" if not ogagentfile: - raise_error(f"{ndisk} {npart} ogagent") + SystemLib.ogRaiseError(f"{ndisk} {npart} ogagent") tmpdir = f"{mntdir}/var/tmp" if download_file(f"https://{ogGetServerIp()}/opengnsys/descargas/{ogagentfile}", f"{tmpdir}/{ogagentfile}"): @@ -136,12 +140,12 @@ WantedBy=multi-user.target print("Scheduled OGAgent installation at next boot") print(" (process will be executed in the background, do not shutdown until finish).") else: - raise_error(f"{ndisk} {npart} /var/tmp/{ogagentfile}") + SystemLib.ogRaiseError(f"{ndisk} {npart} /var/tmp/{ogagentfile}") elif os_type == "MacOS": print("OGAgent installer for macOS is not implemented yet.") else: - raise_error(f"{ndisk} {npart}") + SystemLib.ogRaiseError(f"{ndisk} {npart}") if __name__ == "__main__": - main() \ No newline at end of file + main() diff --git a/client/shared/scripts/listPartitions.py b/client/shared/scripts/listPartitions.py old mode 100644 new mode 100755 index e3fe31a..889bddd --- a/client/shared/scripts/listPartitions.py +++ b/client/shared/scripts/listPartitions.py @@ -1,11 +1,16 @@ -import subprocess import sys +import DiskLib +import SystemLib def list_partitions(*args): - result = subprocess.run(['ogListPartitions'] + list(args), capture_output=True, text=True) - output = result.stdout - cleaned_output = output.rstrip('EMPTY:0 ') - print(cleaned_output) + try: + result = DiskLib.ogListPartitions(*args) + cleaned_output = result.rstrip('EMPTY:0 ').strip() + print(cleaned_output) + + except Exception as e: + SystemLib.ogRaiseError(f"Error al ejecutar ogListPartitions: {e}") if __name__ == "__main__": - list_partitions(*sys.argv[1:]) \ No newline at end of file + list_partitions(*sys.argv[1:]) + diff --git a/client/shared/scripts/listPrimaryPartitions.py b/client/shared/scripts/listPrimaryPartitions.py old mode 100644 new mode 100755 index a4c894d..58cd052 --- a/client/shared/scripts/listPrimaryPartitions.py +++ b/client/shared/scripts/listPrimaryPartitions.py @@ -1,13 +1,14 @@ import sys -import subprocess +import DiskLib +import SystemLib def og_list_primary_partitions(args): try: - result = subprocess.run(['ogListPrimaryPartitions'] + args, check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) - print(result.stdout.decode()) - except subprocess.CalledProcessError as e: - print(f"Error: {e.stderr.decode()}", file=sys.stderr) - sys.exit(e.returncode) + result = DiskLib.ogListPrimaryPartitions(*args) + print(result) + except Exception as e: + SystemLib.ogRaiseError(f"Error al ejecutar ogListPrimaryPartitions: {e}") if __name__ == "__main__": - og_list_primary_partitions(sys.argv[1:]) \ No newline at end of file + og_list_primary_partitions(sys.argv[1:]) + diff --git a/client/shared/scripts/menuBrowser.py b/client/shared/scripts/menuBrowser.py old mode 100644 new mode 100755 index d18acdf..28eecb5 --- a/client/shared/scripts/menuBrowser.py +++ b/client/shared/scripts/menuBrowser.py @@ -1,16 +1,17 @@ import sys import os import subprocess +import SystemLib #!/usr/bin/env python3 def main(): PROG = os.path.basename(__file__) if len(sys.argv) != 2: - og_raise_error(os.getenv('OG_ERR_FORMAT', 1), f"{os.getenv('MSG_FORMAT', 'Usage')}: {PROG} urlmenu") + SystemLib.ogRaiseError(os.getenv('OG_ERR_FORMAT', 1), f"{os.getenv('MSG_FORMAT', 'Usage')}: {PROG} urlmenu") url = sys.argv[1] subprocess.run(['browser', '-qws', url]) if __name__ == "__main__": - main() \ No newline at end of file + main() diff --git a/client/shared/scripts/restoreImageCustomTemplate.py b/client/shared/scripts/restoreImageCustomTemplate.py old mode 100644 new mode 100755 index fc0c1ed..b2b5575 --- a/client/shared/scripts/restoreImageCustomTemplate.py +++ b/client/shared/scripts/restoreImageCustomTemplate.py @@ -1,5 +1,6 @@ import sys import os +import SystemLib #!/usr/bin/env python3 """ @@ -14,7 +15,7 @@ restoreImageCustom # Control de parámetros. if not (4 <= len(sys.argv) <= 6): - ogRaiseError(os.getenv('OG_ERR_FORMAT'), "restoreImageCustom str_repo str_imagen int_ndisco int_npart [ str_proto [\"str_opciones\"] ]") + SystemLib.ogRaiseError(os.getenv('OG_ERR_FORMAT'), "restoreImageCustom str_repo str_imagen int_ndisco int_npart [ str_proto [\"str_opciones\"] ]") # Toma de parámetros. REPO = sys.argv[1].upper() # Repositorio (en mayúsculas). @@ -31,4 +32,4 @@ PROTOOPT = sys.argv[6] if len(sys.argv) > 6 else "" # Opciones del protocolo se # Paso 2: Sustituir, si se desea, la llamada al proceso estándar de restauración de imagen por código personalizado. restoreImage(*sys.argv[1:]) -# Aviso: editar la plantilla "configureOsCustom" para añadir el código personalizado para el proceso de postconfiguración de los clientes (no incluir aquí dicho código). \ No newline at end of file +# Aviso: editar la plantilla "configureOsCustom" para añadir el código personalizado para el proceso de postconfiguración de los clientes (no incluir aquí dicho código). diff --git a/client/shared/scripts/runApplicationX.py b/client/shared/scripts/runApplicationX.py old mode 100644 new mode 100755 index 70b37c4..83475a7 --- a/client/shared/scripts/runApplicationX.py +++ b/client/shared/scripts/runApplicationX.py @@ -15,4 +15,4 @@ def start_roxterm(): if __name__ == "__main__": start_xvesa() - start_roxterm() \ No newline at end of file + start_roxterm() diff --git a/client/shared/scripts/runhttplog.py b/client/shared/scripts/runhttplog.py old mode 100644 new mode 100755 index b7cb070..97c9900 --- a/client/shared/scripts/runhttplog.py +++ b/client/shared/scripts/runhttplog.py @@ -35,4 +35,4 @@ def main(): f.write("WAITING\n") if __name__ == "__main__": - main() \ No newline at end of file + main() From dc56be66c70079c82f86651477ca5982459271f1 Mon Sep 17 00:00:00 2001 From: Natalia Serrano Date: Fri, 8 Nov 2024 13:48:50 +0100 Subject: [PATCH 030/167] refs #1101 add ogUcastSyntax() and its dependencies --- client/lib/engine/bin/ImageLib.py | 275 ++++++++++++++++++++++++++ client/lib/engine/bin/ProtocolLib.py | 276 +++++++++++++++++++++++++++ 2 files changed, 551 insertions(+) create mode 100644 client/lib/engine/bin/ImageLib.py create mode 100644 client/lib/engine/bin/ProtocolLib.py diff --git a/client/lib/engine/bin/ImageLib.py b/client/lib/engine/bin/ImageLib.py new file mode 100644 index 0000000..b9bef13 --- /dev/null +++ b/client/lib/engine/bin/ImageLib.py @@ -0,0 +1,275 @@ +#!/usr/bin/python3 + +import shutil +import subprocess +import os +import os.path +import re +from pathlib import Path + +import DiskLib +import FileSystemLib +import SystemLib +import ogGlobals + +## ProtocolLib.ogUcastSyntax() calls ogCreateImageSyntax() +## in ogCreateImageSyntax(), param2 may contain a pipe or may be empty +## if param2 is empty, then ogUcastSyntax(): +## - does a .split() +## - accesses the third element of the resulting array (ie. does "parts[2]") +## - promptly gets an IndexError exception +## +## param2 in ogCreateImageSyntax() only contains a pipe if 'mbuffer' is installed +## therefore, a hard dependency on mbuffer is created +## +## raise an Exception at import time if mbuffer is not present +if not shutil.which ('mbuffer'): + raise FileNotFoundError ('"mbuffer" utility must be present') + +#/** +#@file ImageLib.py +#@brief Librería o clase Image +#@class Image +#@brief Funciones para creación, restauración y clonación de imágenes de sistemas. +#@warning License: GNU GPLv3+ +#*/ + + +#/** +# ogCreateImageSyntax path_device path_filename [str_tool] [str_compressionlevel] +#@brief Genera una cadena de texto con la instrucción para crear un fichero imagen +#@param path_device dispositivo Linux del sistema de archivos +#@param path_fileneme path absoluto del fichero imagen +#@param [opcional] str_tool herrmaienta de clonacion [partimage, partclone, ntfsclone] +#@param [opcional] str_compressionlevel nivel de compresion. [0 -none-, 1-lzop-, 2-gzip] +#@return str_command - cadena con el comando que se debe ejecutar. +#@warning Salida nula si se producen errores. +#@TODO introducir las herramientas fsarchiver, dd +#*/ ## +#ogCreateImageSyntax /dev/sda1 /opt/opengnsys/images/prueba.img partclone lzop +#ogCreateImageSyntax /dev/sda1 /opt/opengnsys/images/prueba.img +def ogCreateImageSyntax (dev, imgfile, tool='partclone', level='gzip'): + + if 'ntfsclone' == tool: + param1 = f'ntfsclone --force --save-image -O - {dev}' + elif 'partimage' == tool or 'default' == tool: + param1 = f'partimage -M -f3 -o -d -B gui=no -c -z0 --volume=0 save {dev} stdout' + elif 'partclone' == tool: + disk, part = DiskLib.ogDevToDisk (dev).split() + fs = FileSystemLib.ogGetFsType (disk, part) + param1 = { + 'EXT2': 'partclone.extfs', + 'EXT3': 'partclone.extfs', + 'EXT4': 'partclone.extfs', + 'BTRFS': 'partclone.btrfs', + 'REISERFS': 'partclone.reiserfs', + 'REISER4': 'partclone.reiser4', + 'JFS': 'partclone.jfs', + 'XFS': 'partclone.xfs', + 'F2FS': 'partclone.f2fs', + 'NILFS2': 'partclone.nilfs2', + 'NTFS': 'partclone.ntfs', + 'EXFAT': 'partclone.exfat', + 'FAT16': 'partclone.fat', + 'FAT32': 'partclone.fat', + 'HFS': 'partclone.hfsp', + 'HFSPLUS': 'partclone.hfsp', + 'UFS': 'partclone.ufs', + 'VMFS': 'partclone.vmfs', + }.get (fs, 'partclone.imager') + dash_c = '-c' + if not shutil.which (param1): + param1 = 'partclone.dd' + # Algunas versiones de partclone.dd no tienen opción "-c". + out = subprocess.run (['partclone.dd', '--help'], capture_output=True, text=True).stdout + if ' -c' not in out: dash_c = '' + param1=f'{param1} -d0 -F {dash_c} -s {dev}' + else: + raise Exception (f'unknown tool "{tool}"') + + param2 = '| mbuffer -q -m 40M ' if shutil.which ('mbuffer') else ' ' + + param3 = { + 0: ' > ', + 'none': ' > ', + 1: ' | lzop > ', + 'lzop': ' | lzop > ', + 2: ' | gzip -c > ', + 'gzip': ' | gzip -c > ', + 3: ' | bzip -c > ', + 'bzip': ' | bzip -c > ', + }.get (level, ' > ') + + print (f'param1 ({param1}) param2 ({param2}) param3 ({param3}) imgfile ({imgfile})') + if param1: return f'{param1} {param2} {param3} {imgfile}' + + +#/** +# ogRestoreImageSyntax path_filename path_device [str_tools] [str_compressionlevel] +#@brief Genera una cadena de texto con la instrucción para crear un fichero imagen +#@param path_device dispositivo Linux del sistema de archivos +#@param path_fileneme path absoluto del fichero imagen +#@param [opcional] str_tools herrmaienta de clonacion [partimage, partclone, ntfsclone] +#@param [opcional] str_compressionlevel nivel de compresion. [0 -none-, 1-lzop-, 2-gzip] +#@return cadena con el comando que se debe ejecutar. +#@exception OG_ERR_FORMAT formato incorrecto. +#@warning En pruebas iniciales +#@TODO introducir las herramientas fsarchiver, dd +#@TODO introducir el nivel de compresion gzip +#*/ ## +#ogRestoreImageSyntax /opt/opengnsys/images/prueba.img /dev/sda1 [partclone] [lzop] +def ogRestoreImageSyntax (imgfile, part, tool=None, level=None): + if not os.path.exists (imgfile): + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTFOUND, imgfile) + ## original bash code is broken: 'return' is never called + #return + + if tool is None or level is None: + infoimg = ogGetImageInfo (imgfile) + if not infoimg: + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTFOUND, f'no image {imgfile}') + ## original bash code is broken: 'return' is never called + #return + try: + tool, level = infoimg.split (':')[0:2] + except: + tool, level = '', '' + return ogRestoreImageSyntax (imgfile, part, tool, level) + + tool = tool.lower() + level = level.lower() + compressor = { + 0: ' ', + 'none': ' ', + 1: ' lzop -dc ', + 'lzop': ' lzop -dc ', + 2: ' gzip -dc ', + 'gzip': ' gzip -dc ', + 3: ' bzip -dc ', + 'bzip': ' bzip -dc ', + }.get (level, '') + print (f'tool ({tool}) level ({level}) compressor ({compressor})') + if compressor is '': + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTFOUND, f'Compressor no valid {level}') + ## original bash code is broken: 'return' is never called + #return + + mbuffer = '| mbuffer -q -m 40M ' if shutil.which ('mbuffer') else ' ' + print (f'mbuffer ({mbuffer})') + if 'ntfsclone' == tool: + tool = f'| ntfsclone --restore-image --overwrite {part} -' + elif 'partimage' == tool: + tool = f'| partimage -f3 -B gui=no restore {part} stdin' + elif 'partclone' in tool: + # -C para que no compruebe tamaños + tool = f'| partclone.restore -d0 -C -I -o {part}' + elif 'dd' == tool: + tool = f'| pv | dd conv=sync,noerror bs=1M of={part}' + else: + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTFOUND, f'Tools imaging no valid {tool}') + ## original bash code is broken: 'return' is never called + #return + print (f'tool ({tool})') + + return f'{compressor} {imgfile} {mbuffer} {tool}'.strip() + + +#/** +# ogGetImageInfo filename +#@brief muestra información sobre la imagen monolitica. +#@param 1 filename path absoluto del fichero imagen +#@return cadena compuesta por clonacion:compresor:sistemaarchivos:tamañoKB +#@exception OG_ERR_FORMAT formato incorrecto. +#@exception OG_ERR_NOTFOUND fichero no encontrado. +#@exception OG_ERR_IMAGE "Image format is not valid $IMGFILE" +#@warning En pruebas iniciales +#@TODO Definir sintaxis de salida (herramienta y compresor en minuscula) +#@TODO Arreglar loop para ntfsclone +#@TODO insertar parametros entrada tipo OG +#*/ ## +#ogGetImageInfo /opt/opengnsys/images/prueba.img ==> PARTCLONE:LZOP:NTFS:5642158" +def ogGetImageInfo (imgfile): + if not os.path.exists (imgfile): + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTFOUND, imgfile) + return + + imgdetect = False + filehead = f'/tmp/{os.path.basename (imgfile)}.infohead' + compressor = subprocess.run (['file', imgfile], capture_output=True, text=True).stdout.split()[1] + if compressor not in ['gzip', 'lzop']: + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_IMAGE, f'Image format is not valid {imgfile}') + return + + ## original bash idiom is: $($COMPRESSOR -dc $IMGFILE 2>/dev/null | head -n 40 > $FILEHEAD) || ogRaiseError + ## the purpose of which I can't fully comprehend + print (f'shelling out "{compressor} -dc {imgfile} |head -n 40 > {filehead}"') + if subprocess.run (f'{compressor} -dc {imgfile} |head -n 40 > {filehead}', shell=True).returncode: + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_IMAGE, f'Image format is not valid {imgfile}') + return + + tools = fs = size = None + + if False == imgdetect: + lc_all = os.getenv ('LC_ALL') + os.environ['LC_ALL'] = 'C' + partclone_info = subprocess.run (['partclone.info', filehead], stdout=subprocess.PIPE, stderr=subprocess.STDOUT, text=True).stdout + if lc_all is not None: + os.environ["LC_ALL"] = lc_all + else: + del os.environ["LC_ALL"] + if 'size' in partclone_info: + tools = 'PARTCLONE' + sizefactor = 1000000 if 'GB' in partclone_info else 1024 + fs_lines = list (filter (lambda l: 'File system' in l, partclone_info.splitlines())) + fs = fs_lines[0].split (':')[1].strip() + if fs in ['HFS', 'HFSPLUS', 'FAT32']: + ## TODO + #FSPLUS=$(echo $PARTCLONEINFO | awk '{gsub(/\: /,"\n"); print toupper($9);}') + #echo $PARTCLONEINFO | grep GB > /dev/null && SIZEFACTOR=1000000 || SIZEFACTOR=1024 + fsplus = 'PLUS' + if fsplus: + fs += fsplus + size = 42 + else: + size = 42 + ## /TODO + size = int (size * sizefactor) + else: + m = re.search (r'Device size *: *(\S+)', partclone_info) + size = float (m.group(1)) if m else 0 + size = int (size * sizefactor) + imgdetect = True + + if False == imgdetect and not os.path.exists ('/dev/loop2'): + filehead_contents = Path (filehead).read_bytes() + if b'ntfsclone-image' in filehead_contents: + print (f'shelling out "cat {filenead} | ntfsclone --restore --overwrite /dev/loop2 - 2>&1"') + ntfscloneinfo = subprocess.run (f'cat {filenead} | ntfsclone --restore --overwrite /dev/loop2 - 2>&1', shell=True, capture_output=True, text=True).stdout + if 'ntfsclone' in ntfscloneinfo: + tools = 'NTFSCLONE' + size_lines = list (filter (lambda l: '__TODO__' in l, ntfscloneinfo.splitlines())) ## TODO + size = 42 #int (size_lines[0].split (':')[1].strip()) ## TODO + fs = 'NTFS' + imgdetect = True + + if False == imgdetect: + partimageinfo = subprocess.run (['partimage', '-B', 'gui=no', 'imginfo', filehead], stdout=subprocess.PIPE, stderr=subprocess.STDOUT, text=True).stdout + if 'Partition' in partimageinfo: + tools = 'TOOLS=PARTIMAGE' + fs_lines = list (filter (lambda l: '__TODO__' in l, partimageinfo.splitlines())) ## TODO + fs = 'EXTFS' #fs_lines[0].split (':')[1].strip() ## TODO + size_lines = list (filter (lambda l: '__TODO__' in l, partimageinfo.splitlines())) ## TODO + size = 42 #int (size_lines[0].split (':')[1].strip()) ## TODO + imgdetect = True + if 'boot sector' in subprocess.run (['file', filehead], capture_output=True, text=True).stdout: + tools = 'partclone.dd' + fs = '' + size = 0 + imgdetect = True + + if not tools or not compressor or False == imgdetect: + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_IMAGE, f'Image format is not valid {imgfile}') + return + + compressor = compressor.lower() + return ':'.join ([tools, compressor, fs, str (size)]) diff --git a/client/lib/engine/bin/ProtocolLib.py b/client/lib/engine/bin/ProtocolLib.py new file mode 100644 index 0000000..a9b94bf --- /dev/null +++ b/client/lib/engine/bin/ProtocolLib.py @@ -0,0 +1,276 @@ +#!/usr/bin/python3 + +import ogGlobals +import SystemLib +import ImageLib + +#/** +#@file ProtocolLib.py +#@brief Librería o clase Protocol +#@class Protocol +#@brief Funciones para transmisión de datos +#@warning License: GNU GPLv3+ +#*/ + + +##################### FUNCIONES UNICAST ################ + +#/** +# ogUcastSyntax +#@brief Función para generar la instrucción de transferencia de datos unicast +#@param 1 Tipo de operación [ SENDPARTITION RECEIVERPARTITION SENDFILE RECEIVERFILE ] +#@param 2 Sesion Unicast +#@param 3 Dispositivo (opción PARTITION) o fichero(opción FILE) que será enviado. +#@param 4 Tools de clonación (opcion PARTITION) +#@param 5 Tools de compresion (opcion PARTITION) +#@return instrucción para ser ejecutada. +#@exception OG_ERR_FORMAT formato incorrecto. +#@exception OG_ERR_UCASTSYNTAXT formato de la sesion unicast incorrecta. +#@note Requisitos: mbuffer +#@todo: controlar que mbuffer esta disponible para los clientes. +#*/ ## + +#ogUcastSyntax SENDPARTITION 8000:172.17.36.11:172.17.36.12 device tool level +#ogUcastSyntax RECEIVERPARTITION 8000:172.17.36.249 device tool level + +#ogUcastSyntax SENDFILE 8000:172.17.36.11:172.17.36.12 file +#ogUcastSyntax RECEIVERFILE 8000:172.17.36.249 file + +def ogUcastSyntax (op, sess, file=None, device=None, tool=None, level=None): + if 'SENDPARTITION' == op or 'RECEIVERPARTITION' == op: + if device is None: + raise TypeError ('missing required argument: "device"') + if tool is None: + raise TypeError ('missing required argument: "tool"') + if tool not in ['partclone', 'PARTCLONE', 'partimage', 'PARTIMAGE', 'ntfsclone', 'NTFSCLONE']: + raise TypeError (f'argument "tool" has unsupported value "{tool}"') + if level is None: + raise TypeError ('missing required argument: "level"') + if level not in ['lzop', 'gzip', 'LZOP', 'GZIP', '0', '1']: + raise TypeError (f'argument "level" has unsupported value "{level}"') + elif 'SENDFILE' == op or 'RECEIVERFILE' == op: + if file is None: + raise TypeError ('missing required argument: "file"') + else: + raise TypeError ('first parameter should match (SEND|RECEIVER)(PARTITION|FILE), eg. "SENDFILE"') + + if 'SEND' in op: mode = 'server' + else: mode = 'client' + + session = sess.split (':') + + portbase = int (session[0]) + if portbase not in range (8000, 8006): + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_FORMAT, f'McastSession portbase {portbase}') ## || PERROR=3 + return + + if 'SERVER' == mode: + address = '' + for i in range (1, len (session)): + address += f'-O {session[i]}:{portbase}' + else: + address = f'{session[1]}:{portbase}' + print (f'nati mode ({mode}) address ({address})') + + if 'SENDPARTITION' == op: + syn = ImageLib.ogCreateImageSyntax (device, ' ', tool, level) + ## REQUIRES package mbuffer to be installed!! + ## otherwise, param2 in ImageLib.ogCreateImageSyntax() is not '| mbuffer' but empty + ## and then parts[2] is out of range + parts = syn.split ('|') + print (f'syn ({syn}) parts ({parts})') + prog1 = f'{parts[0]}|{parts[2]}'.strip() + prog1 = prog1.replace ('>', '').strip() + return f'{prog1} | mbuffer {address}' + elif 'RECEIVERPARTITION' == op: + syn = ImageLib.ogRestoreImageSyntax (' ', device, tool, level) + parts = syn.split ('|') + compressor = parts[0].strip() + tools = parts[-1].strip() + return f'mbuffer -I {address} | {compressor} | {tools}' + elif 'SENDFILE' == op: + return f'mbuffer {address} -i {file}' + elif 'RECEIVERFILE' == op: + return f'mbuffer -I {address} -i {file}' + else: + pass ## shouldn't happen + + +#/** +# ogUcastSendPartition +#@brief Función para enviar el contenido de una partición a multiples particiones remotas usando UNICAST. +#@param 1 disk +#@param 2 partition +#@param 3 sesionUcast +#@param 4 tool image +#@param 5 tool compresor +#@return +#@exception $OG_ERR_FORMAT +#@exception $OG_ERR_UCASTSENDPARTITION +#@note +#@todo: ogIsLocked siempre devuelve 1 +#*/ ## + + +#/** +# ogUcastReceiverPartition +#@brief Función para recibir directamente en la partición el contenido de un fichero imagen remoto enviado por UNICAST. +#@param 1 disk +#@param 2 partition +#@param 3 session unicast +#@return +#@exception OG_ERR_FORMAT +#@exception OG_ERR_UCASTRECEIVERPARTITION +#@note +#@todo: +#*/ ## + + +#/** +# ogUcastSendFile [ str_repo | int_ndisk int_npart ] /Relative_path_file sessionMulticast +#@brief Envía un fichero por unicast ORIGEN(fichero) DESTINO(sessionmulticast) +#@param (2 parámetros) $1 path_aboluto_fichero $2 sesionMcast +#@param (3 parámetros) $1 Contenedor REPO|CACHE $2 path_absoluto_fichero $3 sesionMulticast +#@param (4 parámetros) $1 disk $2 particion $3 path_absoluto_fichero $4 sesionMulticast +#@return +#@exception OG_ERR_FORMAT formato incorrecto. +#@exception $OG_ERR_NOTFOUND +#@exception OG_ERR_UCASTSENDFILE +#@note Requisitos: +#*/ ## +# + + +#/** +# ogMcastSyntax +#@brief Función para generar la instrucción de ejucción la transferencia de datos multicast +#@param 1 Tipo de operación [ SENDPARTITION RECEIVERPARTITION SENDFILE RECEIVERFILE ] +#@param 2 Sesión Mulicast +#@param 3 Dispositivo (opción PARTITION) o fichero(opción FILE) que será enviado. +#@param 4 Tools de clonación (opcion PARTITION) +#@param 5 Tools de compresion (opcion PARTITION) +#@return instrucción para ser ejecutada. +#@exception OG_ERR_FORMAT formato incorrecto. +#@exception OG_ERR_NOTEXEC +#@exception OG_ERR_MCASTSYNTAXT +#@note Requisitos: upd-cast 2009 o superior +#@todo localvar check versionudp +#*/ ## +# + + + + +#/** +# ogMcastSendFile [ str_repo | int_ndisk int_npart ] /Relative_path_file sessionMulticast +#@brief Envía un fichero por multicast ORIGEN(fichero) DESTINO(sessionmulticast) +#@param (2 parámetros) $1 path_aboluto_fichero $2 sesionMcast +#@param (3 parámetros) $1 Contenedor REPO|CACHE $2 path_absoluto_fichero $3 sesionMulticast +#@param (4 parámetros) $1 disk $2 particion $3 path_absoluto_fichero $4 sesionMulticast +#@return +#@exception OG_ERR_FORMAT formato incorrecto. +#@exception $OG_ERR_NOTFOUND +#@exception OG_ERR_MCASTSENDFILE +#*/ ## +# + + + + +#/** +# ogMcastReceiverFile sesion Multicast [ str_repo | int_ndisk int_npart ] /Relative_path_file +#@brief Recibe un fichero multicast ORIGEN(sesionmulticast) DESTINO(fichero) +#@param (2 parámetros) $1 sesionMcastCLIENT $2 path_aboluto_fichero_destino +#@param (3 parámetros) $1 sesionMcastCLIENT $2 Contenedor REPO|CACHE $3 path_absoluto_fichero_destino +#@param (4 parámetros) $1 sesionMcastCLIENT $2 disk $3 particion $4 path_absoluto_fichero_destino +#@return +#@exception OG_ERR_FORMAT formato incorrecto. +#@exception $OG_ERR_MCASTRECEIVERFILE +#@note Requisitos: +#*/ ## +# + + + +#/** +# ogMcastSendPartition +#@brief Función para enviar el contenido de una partición a multiples particiones remotas. +#@param 1 disk +#@param 2 partition +#@param 3 session multicast +#@param 4 tool clone +#@param 5 tool compressor +#@return +#@exception OG_ERR_FORMAT +#@exception OG_ERR_MCASTSENDPARTITION +#@note +#@todo: ogIsLocked siempre devuelve 1. crear ticket +#*/ ## + + +#/** +# ogMcastReceiverPartition +#@brief Función para recibir directamente en la partición el contenido de un fichero imagen remoto enviado por multicast. +#@param 1 disk +#@param 2 partition +#@param 3 session multicast +#@param 4 tool clone +#@param 5 tool compressor +#@return +#@exception $OG_ERR_FORMAT +#*/ ## + + +#/** +# ogMcastRequest +#@brief Función temporal para solicitar al ogRepoAux el envio de un fichero por multicast +#@param 1 Fichero a enviar ubicado en el REPO. puede ser ruta absoluta o relatica a /opt/opengnsys/images +#@param 2 PROTOOPT opciones protocolo multicast +#@return +#@exception +#*/ ## + + +########################################## +############## funciones torrent +#/** +# ogTorrentStart [ str_repo | int_ndisk int_npart ] Relative_path_file.torrent | SessionProtocol +#@brief Función iniciar P2P - requiere un tracker para todos los modos, y un seeder para los modos peer y leecher y los ficheros .torrent. +#@param str_pathDirectory str_Relative_path_file +#@param int_disk int_partition str_Relative_path_file +#@param str_REPOSITORY(CACHE - LOCAL) str_Relative_path_file +#@param (2 parámetros) $1 path_aboluto_fichero_torrent $2 Parametros_Session_Torrent +#@param (3 parámetros) $1 Contenedor CACHE $2 path_absoluto_fichero_Torrent $3 Parametros_Session_Torrent +#@param (4 parámetros) $1 disk $2 particion $3 path_absoluto_fichero_Torrent 4$ Parametros_Session_Torrent +#@return +#@note protocoloTORRENT=mode:time mode=seeder -> Dejar el equipo seedeando hasta que transcurra el tiempo indicado o un kill desde consola, mode=peer -> seedear mientras descarga mode=leecher -> NO seedear mientras descarga time tiempo que una vez descargada la imagen queremos dejar al cliente como seeder. +#*/ ## + +#/** +# ogCreateTorrent [ str_repo | int_ndisk int_npart ] Relative_path_file +#@brief Función para crear el fichero torrent. +#@param str_pathDirectory str_Relative_path_file +#@param int_disk int_partition str_Relative_path_file +#@param str_REPOSITORY(CACHE - LOCAL) str_Relative_path_file +#@return +#@exception OG_ERR_FORMAT Formato incorrecto. +#@exception OG_ERR_NOTFOUND Disco o particion no corresponden con un dispositivo. +#@exception OG_ERR_PARTITION Tipo de partición desconocido o no se puede montar. +#@exception OG_ERR_NOTOS La partición no tiene instalado un sistema operativo. +#*/ ## + + + +#/** +# ogUpdateCacheIsNecesary [ str_repo ] Relative_path_file_OGIMG_with_/ +#@brief Comprueba que el fichero que se desea almacenar en la cache del cliente, no esta. +#@param 1 str_REPO +#@param 2 str_Relative_path_file_OGIMG_with_/ +#@param 3 md5 to check: use full to check download image torrent +#@return 0 (true) cache sin imagen, SI es necesario actualizar el fichero. +#@return 1 (false) imagen en la cache, NO es necesario actualizar el fichero +#@return >1 (false) error de sintaxis (TODO) +#@note +#@todo: Proceso en el caso de que el fichero tenga el mismo nombre, pero su contenido sea distinto. +#@todo: Se dejan mensajes mientras se confirma su funcionamiento. +#*/ ## From 961ccb8c6613eaead1c8c79833a101e568ce6721 Mon Sep 17 00:00:00 2001 From: Natalia Serrano Date: Fri, 8 Nov 2024 14:07:43 +0100 Subject: [PATCH 031/167] refs #1101 add ogMcastRequest() --- client/lib/engine/bin/ProtocolLib.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/client/lib/engine/bin/ProtocolLib.py b/client/lib/engine/bin/ProtocolLib.py index a9b94bf..f4f21c9 100644 --- a/client/lib/engine/bin/ProtocolLib.py +++ b/client/lib/engine/bin/ProtocolLib.py @@ -226,9 +226,10 @@ def ogUcastSyntax (op, sess, file=None, device=None, tool=None, level=None): #@brief Función temporal para solicitar al ogRepoAux el envio de un fichero por multicast #@param 1 Fichero a enviar ubicado en el REPO. puede ser ruta absoluta o relatica a /opt/opengnsys/images #@param 2 PROTOOPT opciones protocolo multicast -#@return -#@exception #*/ ## +## now ogCore takes this responsibility +def ogMcastRequest (img, proto): + return ########################################## From 4342a5c27e0663b2ddf3afb64d34d65d92767b32 Mon Sep 17 00:00:00 2001 From: Natalia Serrano Date: Mon, 11 Nov 2024 16:28:03 +0100 Subject: [PATCH 032/167] refs #1101 add ogGetPath() and dependencies --- client/lib/engine/bin/CacheLib.py | 34 ++-- client/lib/engine/bin/FileLib.py | 122 +++++++----- client/lib/engine/bin/FileSystemLib.py | 250 ++++++++++++++----------- client/lib/engine/bin/ogGlobals.py | 25 ++- 4 files changed, 244 insertions(+), 187 deletions(-) diff --git a/client/lib/engine/bin/CacheLib.py b/client/lib/engine/bin/CacheLib.py index 13913c5..a813607 100755 --- a/client/lib/engine/bin/CacheLib.py +++ b/client/lib/engine/bin/CacheLib.py @@ -5,9 +5,11 @@ import shutil import sys import platform +import ogGlobals +import SystemLib import DiskLib - -print (">>>>>>>>>>>>>>>>>>>> Load ", __name__, " <<<<<<<<<<<<<<<<<<<<<<") +import FileSystemLib +import CacheLib def ogCreateCache(ndisk=1, npart=4, partsize=None): """ @@ -193,21 +195,21 @@ def ogGetCacheSpace(): return free_space_kb + +#/** +# ogMountCache +#@brief Monta la partición Cache y exporta la variable $OGCAC +#@param sin parametros +#@return path_mountpoint - Punto de montaje del sistema de archivos de cache. +#@warning Salidas de errores no determinada +#*/ ## def ogMountCache(): - """ - Monta la partición de caché en el directorio /mnt/sda4. - - :raises RuntimeError: Si ocurre un error durante el montaje de la partición de caché. - """ - # Si se solicita, mostrar ayuda. - if len(sys.argv) > 1 and sys.argv[1] == "help": - ogHelp("ogMountCache", "help", "ogMountCache") - - # Montar la partición de caché en /mnt/sda4. - try: - subprocess.run(["mount", ogFindCache(), "/mnt/sda4"], check=True) - except subprocess.CalledProcessError as e: - raise RuntimeError(f"Error al montar la partición de caché: {e}") + c = CacheLib.ogFindCache().split() + m = FileSystemLib.ogMountFs (c[0], c[1]) + if not m: + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_PARTITION, ogGlobals.lang.MSG_NOCACHE) + #return + return m def ogUnmountCache(): """ diff --git a/client/lib/engine/bin/FileLib.py b/client/lib/engine/bin/FileLib.py index 868e4eb..89a24d4 100755 --- a/client/lib/engine/bin/FileLib.py +++ b/client/lib/engine/bin/FileLib.py @@ -1,6 +1,8 @@ import subprocess import os import shutil + +import ogGlobals import SystemLib import CacheLib import FileSystemLib @@ -146,66 +148,82 @@ def ogDeleteTree(*args): except OSError as e: SystemLib.ogRaiseError(OG_ERR_NOTFOUND, *args) return - -def ogGetPath(*args): - # Variables locales. - MNTDIR = None - FILE = None - PREVFILE = None - FILEPATH = None - CURRENTDIR = None - # Si se solicita, mostrar ayuda. - if "help" in args: - SystemLib.ogHelp("$FUNCNAME", "$FUNCNAME [ str_repo | int_ndisk int_npartition ] path_filepath", "$FUNCNAME \"/mnt/sda1/windows/system32\" ==> /mnt/sda1/WINDOWS/System32", "$FUNCNAME REPO /etc/fstab ==> /opt/opengnsys/images/etc/fstab", "$FUNCNAME 1 1 \"/windows/system32\" ==> /mnt/sda1/WINDOWS/System32") - return - # Procesar camino según el número de parámetros. - if len(args) == 1: - FILE = args[0] - elif len(args) == 2: - if args[0].upper() == "REPO": - FILE = os.path.join(OGIMG, args[1]) - elif args[0].upper() == "CACHE": - MNTDIR = CacheLib.ogMountCache() - if not MNTDIR: - return - FILE = os.path.join(MNTDIR, OGIMG, args[1]) - elif args[0].upper() == "CDROM": - MNTDIR = FileSystemLib.ogMountCdrom() - if not MNTDIR: - return - FILE = os.path.join(MNTDIR, args[1]) +#/** +# ogGetPath [ str_repo | int_ndisk int_npartition ] path_filepath +#@brief Inicia el proceso de arranque de un sistema de archivos. +#@param path_filepath camino del fichero (independiente de mayúsculas) +#@param str_repo repositorio de ficheros +#@param int_ndisk nº de orden del disco +#@param int_npartition nº de orden de la partición +#@return path_file - camino completo real del fichero. +#@note repo = { REPO, CACHE, CDROM } +#@note Requisitos: \c grep \c sed +#@exception OG_ERR_FORMAT Formato incorrecto. +#@exception OG_ERR_NOTFOUND Fichero o dispositivo no encontrado. +#@exception OG_ERR_PARTITION Tipo de partición desconocido o no se puede montar. +#@warning En caso de error, sólo devuelve el código y no da mensajes. +#@todo Terminar de definir parámetros para acceso a repositorios. +#*/ ## +#ogGetPath (file='/mnt/sda1/windows/system32') ==> '/mnt/sda1/WINDOWS/System32' +#ogGetPath (src='REPO', file='/etc/fstab') ==> '/opt/opengnsys/images/etc/fstab' +#ogGetPath (src='1 1', file='/windows/system32') ==> '/mnt/sda1/WINDOWS/System32' +def ogGetPath (src=None, file=None): + if file is None: + raise TypeError ('missing required argument: "file"') + + f = file + if src is not None: + if 'REPO' == src: + f = os.path.join (ogGlobals.OGIMG, file.strip('/')) + elif 'CACHE' == src: + mntdir = CacheLib.ogMountCache() + if not mntdir: return None + f = os.path.join (mntdir, ogGlobals.OGIMG.strip('/'), file.strip('/')) + elif 'CDROM' == src: + mntdir = FileSystemLib.ogMountCdrom() + if not mntdir: return None + f = os.path.join (mntdir, file.strip('/')) else: - SystemLib.ogRaiseError(OG_ERR_FORMAT) - return - elif len(args) == 3: - MNTDIR = FileSystemLib.ogMount(args[0], args[1]) - if not MNTDIR: - return - FILE = os.path.join(MNTDIR, args[2]) - else: - SystemLib.ogRaiseError(OG_ERR_FORMAT) - return + try: + disk, part = src.split() + except ValueError: + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_FORMAT, '') + return + mntdir = FileSystemLib.ogMount (disk, part) + if not mntdir: return None + f = os.path.join (mntdir, file.strip('/')) - # Eliminar caracteres \c / duplicados y finales. - FILE = os.path.normpath(FILE) + f = os.path.normpath (f) - # Comprobar si existe el fichero para reducir tiempos. - if os.path.exists(FILE): - FILEPATH = FILE + if os.path.exists (f): + filepath = f + #print (f'f ({f}) existe, filepath=f ({filepath})') else: # Buscar el nombre correcto en cada subdirectorio del camino. - FILEPATH = "/" - while FILE != PREVFILE: - FILEPATH = os.path.join(FILEPATH.rstrip("/"), FILE.split("/")[0]) - PREVFILE = FILE - FILE = "/".join(FILE.split("/")[1:]) + prevfile = '' + filepath = '/' + #print (f'f ({f}) prevfile ({prevfile})') + while f != prevfile: + #print ('\nno son iguales, nueva iteracion...') + f_first_component = f.split ('/')[0] ## take 1st component + ls_path = os.path.join (filepath, f_first_component) ## "ls" makes reference to the original bash version + #print (f'f_first_component ({f_first_component}) ls_path ({ls_path})') - if FILEPATH: - return FILEPATH - else: - return None + ## build filepath to return + if os.path.exists (ls_path): + filepath = ls_path + #print (f'ls_path existe, filepath ({filepath})') + else: + filepath = subprocess.run (['find', filepath, '-maxdepth', '1', '-iname', f_first_component, '-print'], capture_output=True, text=True).stdout.strip() + #print (f'ls_path no existe, filepath ({filepath})') + + prevfile = f + f = '/'.join (f.split('/')[1:]) ## remove 1st component + #print (f'f ({f}) prevfile ({prevfile})') + + return filepath def ogGetParentPath(*args): # Variables locales. diff --git a/client/lib/engine/bin/FileSystemLib.py b/client/lib/engine/bin/FileSystemLib.py index 72914af..e99fd31 100755 --- a/client/lib/engine/bin/FileSystemLib.py +++ b/client/lib/engine/bin/FileSystemLib.py @@ -1,13 +1,12 @@ import subprocess import sys +import os.path import ogGlobals import SystemLib import DiskLib import CacheLib -print (">>>>>>>>>>>>>>>>>>>> Load ", __name__, " <<<<<<<<<<<<<<<<<<<<<<") - def ogCheckFs(int_ndisk, int_nfilesys): # Si se solicita, mostrar ayuda. if int_ndisk == "help": @@ -398,25 +397,24 @@ def ogGetFsType(disk, part): return TYPE -def ogGetMountPoint(int_ndisk, int_nfilesys): - # Si se solicita, mostrar ayuda. - if len(sys.argv) == 3 and sys.argv[2] == "help": - ogHelp("ogGetMountPoint", "ogGetMountPoint int_ndisk int_nfilesys", "ogGetMountPoint 1 1") - return - # Error si no se reciben 2 parámetros. - if len(sys.argv) != 3: - ogRaiseError(OG_ERR_FORMAT) - return +#/** +# ogGetMountPoint int_ndisk int_nfilesys +#@brief Devuelve el punto de montaje de un sistema de archivos. +#@param int_ndisk nº de orden del disco +#@param int_nfilesys nº de orden del sistema de archivos +#@return Punto de montaje +#@exception OG_ERR_FORMAT Formato incorrecto. +#@exception OG_ERR_NOTFOUND Disco o particion no corresponden con un dispositivo. +#@note Requisitos: \c mount* \c awk +#*/ ## - # Obtener partición. - PART = ogDiskToDev(int_ndisk, int_nfilesys) - if not PART: - return +def ogGetMountPoint(disk, par): + PART = DiskLib.ogDiskToDev(disk, par) + if not PART: return + + return subprocess.run(["findmnt", "-n", "-o", "TARGET", PART], capture_output=True, text=True).stdout.strip() - # Devolver punto de montaje. - result = subprocess.run(["findmnt", "-n", "-o", "TARGET", PART], capture_output=True, text=True) - return result.stdout.strip() #/** @@ -441,27 +439,31 @@ def ogIsFormated(disk, part): out = subprocess.run(["zfs", "list", "-Hp", "-o", "canmount", PART], capture_output=True, text=True).stdout.strip() return out == "on" -def ogIsLocked(int_ndisk, int_nfilesys): - return ogIsPartitionLocked(int_ndisk, int_nfilesys) -def ogIsPartitionLocked(int_ndisk, int_npartition): - # Si se solicita, mostrar ayuda. - if len(sys.argv) == 3 and sys.argv[2] == "help": - ogHelp("ogIsPartitionLocked", "ogIsPartitionLocked int_ndisk int_npartition", "ogIsPartitionLocked 1 1") - return - # Error si no se reciben 2 parámetros. - if len(sys.argv) != 3: - ogRaiseError(OG_ERR_FORMAT) - return +#/** +# ogIsLocked int_ndisk int_npartition +#@see ogIsPartitionLocked +#*/ - # Obtener partición. - PART = ogDiskToDev(int_ndisk, int_npartition) - if not PART: - return +def ogIsLocked(disk, par): + return ogIsPartitionLocked(disk, par) - # Comprobar existencia de fichero de bloqueo de la partición o de su disco. - LOCKDISK = f"/var/lock/lock{ogDiskToDev(int_ndisk).replace('/', '-')}" + +#/** +# ogIsPartitionLocked int_ndisk int_npartition +#@brief Comprueba si una partición o su disco están bloqueados por una operación de uso exclusivo. +#@param int_ndisk nº de orden del disco +#@param int_npartition nº de orden de la partición +#@return Código de salida: 0 - bloqueado, 1 - sin bloquear o error. +#@note Los ficheros de bloqueo se localizan en \c /var/lock/dev, siendo \c dev el dispositivo de la partición o de su disco, sustituyendo el carácter "/" por "-". +#*/ ## +def ogIsPartitionLocked(disk, par): + DISK = DiskLib.ogDiskToDev(disk) + PART = DiskLib.ogDiskToDev(disk, par) + if not PART: return + + LOCKDISK = f"/var/lock/lock{DISK.replace('/', '-')}" LOCKPART = f"/var/lock/lock{PART.replace('/', '-')}" return os.path.isfile(LOCKDISK) or os.path.isfile(LOCKPART) @@ -480,23 +482,22 @@ def ogIsMounted(int_ndisk, int_nfilesys): MNTDIR = ogGetMountPoint(int_ndisk, int_nfilesys) return bool(MNTDIR) -def ogIsReadonly(int_ndisk, int_nfilesys): - # Si se solicita, mostrar ayuda. - if len(sys.argv) == 3 and sys.argv[2] == "help": - ogHelp("ogIsReadonly", "ogIsReadonly int_ndisk int_nfilesys", "ogIsReadonly 1 1") - return - # Error si no se reciben 2 parámetros. - if len(sys.argv) != 3: - ogRaiseError(OG_ERR_FORMAT) - return +#/** +# ogIsReadonly int_ndisk int_nfilesys +#@brief Comprueba si un sistema de archivos está montado solo de lectura. +#@param int_ndisk nº de orden del disco +#@param int_nfilesys nº de orden del sistema de archivos +#@return Código de salida: 0 - montado solo de lectura, 1 - con escritura o no montado. +#@version 1.1.0 - Primera versión para OpenGnsys. +#@author Ramon Gomez, ETSII Universidad de Sevilla +#@date 2016-01-20 +#*/ ## - # Obtener partición. - PART = ogDiskToDev(int_ndisk, int_nfilesys) - if not PART: - return +def ogIsReadonly(disk, par): + PART = DiskLib.ogDiskToDev(disk, par) + if not PART: return - # Comprobar si la partición está montada en modo de solo lectura. result = subprocess.run(["findmnt", "-n", "-o", "OPTIONS", PART], capture_output=True, text=True) options = result.stdout.strip().split(",") return "ro" in options @@ -545,14 +546,19 @@ def ogLockPartition(int_ndisk, int_npartition): LOCKFILE = f"/var/lock/lock{PART.replace('/', '-')}" open(LOCKFILE, 'a').close() -def ogMount(): - args = sys.argv[2:] - if args == ["CACHE"] or args == ["cache"]: - ogMountCache() - elif args == ["CDROM"] or args == ["cdrom"]: - ogMountCdrom() - else: - ogMountFs(*args) + +#/** +# ogMount int_ndisk int_nfilesys +#@see ogMountFs ogMountCache ogMountCdrom +#*/ ## +def ogMount(*args): + if 1 == len (args): + if 'cache' == args[0].lower(): + return ogMountCache() + elif 'cdrom' == args[0].lower(): + return ogMountCdrom() + elif 2 == len (args): + return ogMountFs(args[0], args[1]) def ogMountFirstFs(int_ndisk): # Obtener número de particiones del disco. @@ -564,65 +570,87 @@ def ogMountFirstFs(int_ndisk): ogRaiseError(OG_ERR_NOTFOUND, int_ndisk) return OG_ERR_NOTFOUND -def ogMountFs(int_ndisk, int_nfilesys): - FUNCNAME = ogExecAndLog.__name__ - # Si se solicita, mostrar ayuda. - if len(sys.argv) == 3 and sys.argv[2] == "help": - ogHelp(f"{FUNCNAME}", "{FUNCNAME} int_ndisk int_nfilesys", "{FUNCNAME} 1 1 => /mnt/sda1") +#/** +# ogMountFs int_ndisk int_nfilesys +#@brief Monta un sistema de archivos. +#@param int_ndisk nº de orden del disco +#@param int_nfilesys nº de orden del sistema de archivos +#@return Punto de montaje +#@exception OG_ERR_FORMAT Formato incorrecto. +#@exception OG_ERR_NOTFOUND Disco o particion no corresponden con un dispositivo. +#@exception OG_ERR_PARTITION Tipo de particion desconocido o no se puede montar. +#*/ ## + +def ogMountFs (disk, par): + dev = DiskLib.ogDiskToDev (disk, par) + if not dev: return + + mntdir = ogGetMountPoint (disk, par) + if mntdir: return mntdir + + if ogIsLocked (disk, par): + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_LOCKED, f"{ogGlobals.lang.MSG_PARTITION}, {disk} {par}") return - # Error si no se reciben 2 parámetros. - if len(sys.argv) != 3: - ogRaiseError(OG_ERR_FORMAT) - return - - # Obtener partición. - PART = ogDiskToDev(int_ndisk, int_nfilesys) - if not PART: - return - - # Comprobar si el sistema de archivos ya está montada. - MNTDIR = ogGetMountPoint(int_ndisk, int_nfilesys) - # Si no, montarlo en un directorio de sistema. - if not MNTDIR: - # Error si la particion esta bloqueada. - if ogIsLocked(int_ndisk, int_nfilesys): - ogRaiseError(OG_ERR_LOCKED, f"{MSG_PARTITION}, {int_ndisk} {int_nfilesys}") - return - - # El camino de un dispositivo normal comienza por el carácter "/". - if PART.startswith("/"): - # Crear punto de montaje o enlace simbólico para caché local. - MNTDIR = PART.replace("/dev", "/mnt") - DEBUG = "no" - if f"{int_ndisk} {int_nfilesys}" == ogFindCache() and OGCAC: - os.makedirs(OGCAC, exist_ok=True) - os.symlink(OGCAC, MNTDIR) - else: - os.makedirs(MNTDIR, exist_ok=True) - del DEBUG - - # Montar sistema de archivos. + # El camino de un dispositivo normal comienza por el carácter "/". + if dev.startswith ('/'): + # Crear punto de montaje o enlace simbólico para caché local. + mntdir = dev.replace ('/dev', '/mnt') + if f"{disk} {par}" == CacheLib.ogFindCache(): + os.makedirs(ogGlobals.OGCAC, exist_ok=True) try: - subprocess.run(["mount", PART, MNTDIR], check=True, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) - except subprocess.CalledProcessError: - try: - subprocess.run(["mount", PART, MNTDIR, "-o", "force,remove_hiberfile"], check=True, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) - except subprocess.CalledProcessError: - ogRaiseError(OG_ERR_PARTITION, f"{int_ndisk}, {int_nfilesys}") - return - # Aviso de montaje de solo lectura. - if ogIsReadonly(int_ndisk, int_nfilesys): - ogEcho("warning", f"{FUNCNAME}: {MSG_MOUNTREADONLY}: \"{int_ndisk}, {int_nfilesys}\"") - else: - # Montar sistema de archivos ZFS (un ZPOOL no comienza por "/"). - try: - subprocess.run(["zfs", "mount", PART], check=True, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) - except subprocess.CalledProcessError: + os.symlink(ogGlobals.OGCAC, mntdir) + except FileExistsError: pass + else: + os.makedirs(mntdir, exist_ok=True) - return MNTDIR + # Montar sistema de archivos. + try: + rc = subprocess.run(['mount', dev, mntdir], check=True).returncode + except subprocess.CalledProcessError: + try: + rc = subprocess.run(['mount', dev, mntdir, '-o', 'force,remove_hiberfile'], check=True).returncode + except subprocess.CalledProcessError: + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_PARTITION, f"{disk}, {par}") + return + if 0 == rc: + pass + elif 14 == rc: + try: + subprocess.run (['ntfsfix', '-d', par], check=True) + except subprocess.CalledProcessError: + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_PARTITION, f"{disk, par}") + #return + else: + try: + subprocess.run (['mount', par, mntdir, '-o', 'ro'], check=True) + except subprocess.CalledProcessError: + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_PARTITION, f"{disk, par}") + #return + + # Aviso de montaje de solo lectura. + if ogIsReadonly(disk, par): + SystemLib.ogEcho("warning", f'ogMountFs: {ogGlobals.lang.MSG_MOUNTREADONLY}: "{disk}, {par}"') + else: + # Montar sistema de archivos ZFS (un ZPOOL no comienza por "/"). + subprocess.run(['zfs', 'mount', dev]) + + return mntdir + + + +#/** +# ogMountCdrom +#@brief Monta dispositivo óptico por defecto +#@return Punto de montaje +#@exception OG_ERR_FORMAT Formato incorrecto. +#@exception OG_ERR_PARTITION Tipo de particion desconocido o no se puede montar. +#@version +#@author +#@date +#*/ ## def ogMountCdrom(): DEV = "/dev/cdrom" # Por defecto MNTDIR = subprocess.run(["mount", "-l", "-t", "iso9660", DEV], capture_output=True, text=True) @@ -633,7 +661,7 @@ def ogMountCdrom(): try: subprocess.run(["mount", "-t", "iso9660", DEV, MNTDIR], check=True, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) except subprocess.CalledProcessError: - ogRaiseError(OG_ERR_PARTITION, "cdrom") + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_PARTITION, "cdrom") return return MNTDIR diff --git a/client/lib/engine/bin/ogGlobals.py b/client/lib/engine/bin/ogGlobals.py index 342eeb2..bf9c1b9 100755 --- a/client/lib/engine/bin/ogGlobals.py +++ b/client/lib/engine/bin/ogGlobals.py @@ -1,8 +1,9 @@ #!/usr/bin/python3 import sys +import os.path import locale -import importlib +import importlib.util def load_lang (name): global lang @@ -27,17 +28,25 @@ TZ='Europe/Madrid' ## engine.cfg +OGLOGSESSION='/tmp/session.log' +OGLOGCOMMAND='/tmp/command.log' NODEBUGFUNCTIONS='ogCreateImageSyntax ogGetHivePath ogGetOsType ogRestoreImageSyntax ogUnmountAll ogUnmountCache' ## /engine.cfg -#OPENGNSYS='/opt/opengnsys' -OPENGNSYS='/tmp/opengnsys' ## XXX -OGLOG=f'{OPENGNSYS}/log' -OGLOGFILE=f'{OGLOG}/192.168.42.42' ## TODO -OGLOGCOMMAND='/tmp/command.log' -OGLOGSESSION='/tmp/session.log' -DEBUG='yes' +## loadenviron.sh +OPENGNSYS = '/opt/opengnsys' +OGBIN = os.path.join (OPENGNSYS, 'bin') +OGETC = os.path.join (OPENGNSYS, 'etc') +OGLIB = os.path.join (OPENGNSYS, 'lib') +OGAPI = os.path.join (OGLIB, 'engine', 'bin') +OGSCRIPTS = os.path.join (OPENGNSYS, 'scripts') +OGIMG = os.path.join (OPENGNSYS, 'images') +OGCAC = os.path.join (OPENGNSYS, 'cache') +OGLOG = os.path.join (OPENGNSYS, 'log') +OGLOGFILE = f'{OGLOG}/192.168.42.42' ## TODO import NetLib; OGLOGFILE = f'$OGLOG/{NetLib.ogGetIpAddress()}.log' +DEBUG = 'yes' +## /loadenviron.sh # Declaración de códigos de error. OG_ERR_FORMAT=1 # Formato de ejecución incorrecto. From d49e01f9e26f06abfb08e249dea1241460f5eca1 Mon Sep 17 00:00:00 2001 From: Natalia Serrano Date: Mon, 11 Nov 2024 16:54:25 +0100 Subject: [PATCH 033/167] refs #1101 add ogGetParentPath() --- client/lib/engine/bin/FileLib.py | 35 ++++++++++++++++---------------- 1 file changed, 18 insertions(+), 17 deletions(-) diff --git a/client/lib/engine/bin/FileLib.py b/client/lib/engine/bin/FileLib.py index 89a24d4..dc649d1 100755 --- a/client/lib/engine/bin/FileLib.py +++ b/client/lib/engine/bin/FileLib.py @@ -224,26 +224,27 @@ def ogGetPath (src=None, file=None): #print (f'f ({f}) prevfile ({prevfile})') return filepath - -def ogGetParentPath(*args): - # Variables locales. - PARENT = None - if "help" in args: - FileSystemLib.ogHelp("$FUNCNAME", "$FUNCNAME [ str_repo | int_ndisk int_npartition ] path_filepath", "$FUNCNAME \"/mnt/sda1/windows/system32\" ==> /mnt/sda1/WINDOWS", "$FUNCNAME REPO /etc/fstab ==> /opt/opengnsys/images/etc", "$FUNCNAME 1 1 \"/windows/system32\" ==> /mnt/sda1/WINDOWS") + + +#/** +# ogGetParentPath [ str_repo | int_ndisk int_npartition ] path_filepath +#@brief Metafunción que devuelve el camino del directorio padre. +#@see ogGetPath +#*/ ## + +#ogGetParentPath ([ str_repo | int_ndisk int_npartition ] path_filepath +#ogGetParentPath ('/mnt/sda1/windows/system32') ==> '/mnt/sda1/WINDOWS' +#ogGetParentPath ('REPO', '/etc/fstab') ==> '/opt/opengnsys/images/etc' +#ogGetParentPath ('1 1', '/windows/system32') ==> '/mnt/sda1/WINDOWS' +def ogGetParentPath (src=None, file=None): + if file is None: + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_FORMAT, '') return - # Procesar camino según el número de parámetros. - if len(args) == 1: - PARENT = os.path.dirname(args[0]) - elif len(args) == 2: - PARENT = f"{args[0]} {os.path.dirname(f'/{args[1]}')}" - elif len(args) == 3: - PARENT = f"{args[0]} {args[1]} {os.path.dirname(f'/{args[2]}')}" + if src is None: + return ogGetPath (file=os.path.dirname (file)) else: - SystemLib.ogRaiseError(OG_ERR_FORMAT) - return - - return ogGetPath(PARENT) + return ogGetPath (src=src, file=os.path.dirname('/'+file)) def ogIsNewerFile(*args): # Variables locales. From 79c1ab34c08ce068823753dc9ad4638ea0b328ec Mon Sep 17 00:00:00 2001 From: Natalia Serrano Date: Mon, 11 Nov 2024 17:15:38 +0100 Subject: [PATCH 034/167] refs #1101 add ogUnmount() and its dependency --- client/lib/engine/bin/FileSystemLib.py | 63 ++++++++++++++++---------- 1 file changed, 40 insertions(+), 23 deletions(-) diff --git a/client/lib/engine/bin/FileSystemLib.py b/client/lib/engine/bin/FileSystemLib.py index e99fd31..d8f5d1a 100755 --- a/client/lib/engine/bin/FileSystemLib.py +++ b/client/lib/engine/bin/FileSystemLib.py @@ -750,45 +750,62 @@ def ogUnlockPartition(int_ndisk, int_npartition): LOCKFILE = f"/var/lock/lock{PART.replace('/', '-')}" os.remove(LOCKFILE) -def ogUnmount(): - ogUnmountFs(*sys.argv[2:]) -def ogUnmountFs(int_ndisk, int_npartition): - FUNCNAME = ogUnmountFs.__name__ - # Si se solicita, mostrar ayuda. - if len(sys.argv) == 3 and sys.argv[2] == "help": - ogHelp("ogUnmountFs", "ogUnmountFs int_ndisk int_npartition", "ogUnmountFs 1 1") - return +#/** +# ogUnmount int_ndisk int_npartition +#@see ogUnmountFs +#*/ ## +def ogUnmount (disk, par): + ogUnmountFs (disk, par) - # Error si no se reciben 2 parámetros. - if len(sys.argv) != 3: - ogRaiseError(OG_ERR_FORMAT) - return +#/** +# ogUnmountFs int_ndisk int_nfilesys +#@brief Desmonta un sistema de archivos. +#@param int_ndisk nº de orden del disco +#@param int_nfilesys nº de orden del sistema de archivos +#@return Nada +#@exception OG_ERR_FORMAT Formato incorrecto. +#@exception OG_ERR_NOTFOUND Disco o particion no corresponden con un dispositivo. +#@warning La partición no está previamente montada o no se puede desmontar. +#*/ ## - # Obtener partición y punto de montaje. - PART = ogDiskToDev(int_ndisk, int_npartition) - MNTDIR = ogGetMountPoint(int_ndisk, int_npartition) +def ogUnmountFs(disk, par): + PART = DiskLib.ogDiskToDev (disk, par) + if not PART: return + MNTDIR = ogGetMountPoint (disk, par) # Si está montada, desmontarla. if MNTDIR: # Error si la particion está bloqueada. - if ogIsPartitionLocked(int_ndisk, int_npartition): - ogRaiseError(OG_ERR_LOCKED, f"{MSG_PARTITION}, {int_ndisk} {int_npartition}") + if ogIsLocked (disk, par): + ogRaiseError ([], ogGlobals.OG_ERR_LOCKED, f"{ogGlobals.lang.MSG_PARTITION}, {disk} {par}") return # Desmontar y borrar punto de montaje. try: - subprocess.run(["umount", PART], check=True, stderr=subprocess.DEVNULL) + subprocess.run(["umount", PART], check=True) except subprocess.CalledProcessError: - ogEcho("warning", f"{FUNCNAME}: {MSG_DONTUNMOUNT}: \"{int_ndisk}, {int_npartition}\"") + SystemLib.ogEcho("warning", f'ogUnmountFs: {ogGlobals.lang.MSG_DONTUNMOUNT}: "{disk}, {par}"') try: os.rmdir(MNTDIR) - except OSError: - os.remove(MNTDIR) + except: + try: + os.remove(MNTDIR) + except: + pass else: - ogEcho("warning", f"{MSG_DONTMOUNT}: \"{int_ndisk},{int_npartition}\"") - ogUnmountFs(int_ndisk, int_npartition) + SystemLib.ogEcho ([], "warning", f'{ogGlobals.lang.MSG_DONTMOUNT}: "{disk},{par}"') + +#/** +# ogUnmountAll int_ndisk +#@brief Desmonta todos los sistema de archivos de un disco, excepto el caché local. +#@param int_ndisk nº de orden del disco +#@return Nada +#@exception OG_ERR_FORMAT Formato incorrecto. +#@exception OG_ERR_NOTFOUND Disco o particion no corresponden con un dispositivo. +#@warning No se desmonta la partición marcada como caché local. +#*/ ## def ogUnmountAll(int_ndisk): # Si se solicita, mostrar ayuda. if len(sys.argv) == 3 and sys.argv[2] == "help": From b668a526b021ebbd1ac30e22f779d7fd33da27d7 Mon Sep 17 00:00:00 2001 From: Natalia Serrano Date: Tue, 12 Nov 2024 10:52:26 +0100 Subject: [PATCH 035/167] refs #1101 improve ogGetImageInfo() a bit --- client/lib/engine/bin/ImageLib.py | 69 +++++++++++++++++++++++++------ 1 file changed, 56 insertions(+), 13 deletions(-) diff --git a/client/lib/engine/bin/ImageLib.py b/client/lib/engine/bin/ImageLib.py index b9bef13..f4ef326 100644 --- a/client/lib/engine/bin/ImageLib.py +++ b/client/lib/engine/bin/ImageLib.py @@ -149,7 +149,7 @@ def ogRestoreImageSyntax (imgfile, part, tool=None, level=None): 'bzip': ' bzip -dc ', }.get (level, '') print (f'tool ({tool}) level ({level}) compressor ({compressor})') - if compressor is '': + if compressor == '': SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTFOUND, f'Compressor no valid {level}') ## original bash code is broken: 'return' is never called #return @@ -213,22 +213,38 @@ def ogGetImageInfo (imgfile): lc_all = os.getenv ('LC_ALL') os.environ['LC_ALL'] = 'C' partclone_info = subprocess.run (['partclone.info', filehead], stdout=subprocess.PIPE, stderr=subprocess.STDOUT, text=True).stdout + #partclone_info = subprocess.run (['cat', '/tmp/foo-partclone'], stdout=subprocess.PIPE, stderr=subprocess.STDOUT, text=True).stdout + #Partclone v0.3.13 http://partclone.org + #Unknown mode + #File system: NTFS + #Device size: 29.2 GB = 7138019 Blocks + #Space in use: 26.6 GB = 6485355 Blocks + #Free Space: 2.7 GB = 652664 Blocks + #Block size: 4096 Byte + # + #image format: 0002 + #created on a: 64 bits platform + #with partclone: v0.3.13 + #bitmap mode: BIT + #checksum algo: CRC32 + #checksum size: 4 + #blocks/checksum: 256 if lc_all is not None: os.environ["LC_ALL"] = lc_all else: del os.environ["LC_ALL"] + if 'size' in partclone_info: tools = 'PARTCLONE' sizefactor = 1000000 if 'GB' in partclone_info else 1024 - fs_lines = list (filter (lambda l: 'File system' in l, partclone_info.splitlines())) - fs = fs_lines[0].split (':')[1].strip() + m = re.search (r'File system *: *(\S+)', partclone_info) + fs = m.group(1) if m else '' if fs in ['HFS', 'HFSPLUS', 'FAT32']: ## TODO #FSPLUS=$(echo $PARTCLONEINFO | awk '{gsub(/\: /,"\n"); print toupper($9);}') - #echo $PARTCLONEINFO | grep GB > /dev/null && SIZEFACTOR=1000000 || SIZEFACTOR=1024 fsplus = 'PLUS' if fsplus: - fs += fsplus + fs += fsplus ## 'HFS' -> 'HFSPLUS' size = 42 else: size = 42 @@ -242,24 +258,51 @@ def ogGetImageInfo (imgfile): if False == imgdetect and not os.path.exists ('/dev/loop2'): filehead_contents = Path (filehead).read_bytes() + ntfscloneinfo = '' if b'ntfsclone-image' in filehead_contents: print (f'shelling out "cat {filenead} | ntfsclone --restore --overwrite /dev/loop2 - 2>&1"') ntfscloneinfo = subprocess.run (f'cat {filenead} | ntfsclone --restore --overwrite /dev/loop2 - 2>&1', shell=True, capture_output=True, text=True).stdout + #ntfscloneinfo = subprocess.run (['cat', '/tmp/foo-ntfsclone'], stdout=subprocess.PIPE, stderr=subprocess.STDOUT, text=True).stdout + if 'ntfsclone' in ntfscloneinfo: tools = 'NTFSCLONE' - size_lines = list (filter (lambda l: '__TODO__' in l, ntfscloneinfo.splitlines())) ## TODO - size = 42 #int (size_lines[0].split (':')[1].strip()) ## TODO + m = re.search (r'__TODO__ *: *(\S+)', ntfscloneinfo) ## TODO + size = 42 #float (m.group(1))/1000 if m else 0 ## TODO fs = 'NTFS' imgdetect = True if False == imgdetect: partimageinfo = subprocess.run (['partimage', '-B', 'gui=no', 'imginfo', filehead], stdout=subprocess.PIPE, stderr=subprocess.STDOUT, text=True).stdout + #partimageinfo = subprocess.run (['cat', '/tmp/foo-partimage'], stdout=subprocess.PIPE, stderr=subprocess.STDOUT, text=True).stdout + #Volume number:.........0 + #Volume size:...........1,27 MiB + #Compression level: ....0 -> ninguno + #Identificator:.........12442509728668372730=ACACACACCB9ECEFA + #Filesystem:............ntfs + #Description:...........Sin descripcion + #Original device:......./dev/nvme0n1p2 + #Original filepath:.... stdout + #Flags:.................0: Bandera sin activar + #Creation date:.........Mon Nov 11 21:00:22 2024 + #Partition size:........476,84 GiB + #Hostname:..............ING-LTR-083 + #Compatible Version:....0.6.1 + #Encryption algorithm:..0 -> ninguno + #MBR saved count:.......0 + print (f'partimageinfo bef ({partimageinfo})') + partimageinfo = re.sub (r':\s*\.+', ' : ', partimageinfo) + print (f'partimageinfo aft ({partimageinfo})') if 'Partition' in partimageinfo: - tools = 'TOOLS=PARTIMAGE' - fs_lines = list (filter (lambda l: '__TODO__' in l, partimageinfo.splitlines())) ## TODO - fs = 'EXTFS' #fs_lines[0].split (':')[1].strip() ## TODO - size_lines = list (filter (lambda l: '__TODO__' in l, partimageinfo.splitlines())) ## TODO - size = 42 #int (size_lines[0].split (':')[1].strip()) ## TODO + tools = 'PARTIMAGE' + m = re.search (r'Filesystem *: *(\S+)', partimageinfo) + fs = m.group(1).upper() if m else '' + + m = re.search (r'Partition size *: *(\S+)', partimageinfo) + size = m.group(1) if m else '' + size = re.sub (r' [MGT]i?B$', '', size) + size = float (size.replace (',', '.')) + size = int (size*1024*1024) + imgdetect = True if 'boot sector' in subprocess.run (['file', filehead], capture_output=True, text=True).stdout: tools = 'partclone.dd' @@ -271,5 +314,5 @@ def ogGetImageInfo (imgfile): SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_IMAGE, f'Image format is not valid {imgfile}') return - compressor = compressor.lower() + compressor = compressor.upper() return ':'.join ([tools, compressor, fs, str (size)]) From 38cb5ab98641975a9080b3e0d53eab5a83b36f1d Mon Sep 17 00:00:00 2001 From: Natalia Serrano Date: Tue, 12 Nov 2024 11:56:56 +0100 Subject: [PATCH 036/167] refs #1101 improve ogGetImageInfo() a bit --- client/lib/engine/bin/ImageLib.py | 28 ++++++++++++---------------- 1 file changed, 12 insertions(+), 16 deletions(-) diff --git a/client/lib/engine/bin/ImageLib.py b/client/lib/engine/bin/ImageLib.py index f4ef326..f9d6357 100644 --- a/client/lib/engine/bin/ImageLib.py +++ b/client/lib/engine/bin/ImageLib.py @@ -236,24 +236,20 @@ def ogGetImageInfo (imgfile): if 'size' in partclone_info: tools = 'PARTCLONE' - sizefactor = 1000000 if 'GB' in partclone_info else 1024 m = re.search (r'File system *: *(\S+)', partclone_info) fs = m.group(1) if m else '' - if fs in ['HFS', 'HFSPLUS', 'FAT32']: - ## TODO - #FSPLUS=$(echo $PARTCLONEINFO | awk '{gsub(/\: /,"\n"); print toupper($9);}') - fsplus = 'PLUS' - if fsplus: - fs += fsplus ## 'HFS' -> 'HFSPLUS' - size = 42 - else: - size = 42 - ## /TODO - size = int (size * sizefactor) - else: - m = re.search (r'Device size *: *(\S+)', partclone_info) - size = float (m.group(1)) if m else 0 - size = int (size * sizefactor) + + sizefactor = 1000000 if 'GB' in partclone_info else 1024 + m = re.search (r'Device size *: *(\S+)', partclone_info) + size = float (m.group(1)) if m else 0 + size = int (size * sizefactor) + + ## why is this? + #if fs in ['HFS', 'HFSPLUS', 'FAT32']: + # #FSPLUS=$(echo $PARTCLONEINFO | awk '{gsub(/\: /,"\n"); print toupper($9);}') + # fsplus = 'PLUS' + # if fsplus: # fs += fsplus ## 'HFS' -> 'HFSPLUS' + imgdetect = True if False == imgdetect and not os.path.exists ('/dev/loop2'): From e8f79964703b9fa9bde16312a0e366f883dd3a1d Mon Sep 17 00:00:00 2001 From: Natalia Serrano Date: Tue, 12 Nov 2024 12:02:25 +0100 Subject: [PATCH 037/167] refs #1101 improve ogGetImageInfo() a bit --- client/lib/engine/bin/ImageLib.py | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/client/lib/engine/bin/ImageLib.py b/client/lib/engine/bin/ImageLib.py index f9d6357..95be66e 100644 --- a/client/lib/engine/bin/ImageLib.py +++ b/client/lib/engine/bin/ImageLib.py @@ -214,6 +214,7 @@ def ogGetImageInfo (imgfile): os.environ['LC_ALL'] = 'C' partclone_info = subprocess.run (['partclone.info', filehead], stdout=subprocess.PIPE, stderr=subprocess.STDOUT, text=True).stdout #partclone_info = subprocess.run (['cat', '/tmp/foo-partclone'], stdout=subprocess.PIPE, stderr=subprocess.STDOUT, text=True).stdout + ## sacado de un email de alberto garcía uma.es #Partclone v0.3.13 http://partclone.org #Unknown mode #File system: NTFS @@ -254,22 +255,34 @@ def ogGetImageInfo (imgfile): if False == imgdetect and not os.path.exists ('/dev/loop2'): filehead_contents = Path (filehead).read_bytes() - ntfscloneinfo = '' if b'ntfsclone-image' in filehead_contents: print (f'shelling out "cat {filenead} | ntfsclone --restore --overwrite /dev/loop2 - 2>&1"') ntfscloneinfo = subprocess.run (f'cat {filenead} | ntfsclone --restore --overwrite /dev/loop2 - 2>&1', shell=True, capture_output=True, text=True).stdout #ntfscloneinfo = subprocess.run (['cat', '/tmp/foo-ntfsclone'], stdout=subprocess.PIPE, stderr=subprocess.STDOUT, text=True).stdout + ## sacado de claude 3 haiku + #ntfsclone v2023.4.0 (libntfs-3g) + #NTFS volume version: 3.1 + #Cluster size: 4096 bytes + #Image volume size: 104857600 bytes (105 MB) + #Space in use: 52428800 bytes (52 MB) + #Reading and restoring NTFS... + #100.00 percent completed + #Syncing ... + #Successfully cloned image to device '/dev/loop2'. + else: + ntfscloneinfo = '' if 'ntfsclone' in ntfscloneinfo: tools = 'NTFSCLONE' - m = re.search (r'__TODO__ *: *(\S+)', ntfscloneinfo) ## TODO - size = 42 #float (m.group(1))/1000 if m else 0 ## TODO + m = re.search (r'Image volume size *: *(\S+)', ntfscloneinfo) + size = float (m.group(1))/1000 if m else 0 fs = 'NTFS' imgdetect = True if False == imgdetect: partimageinfo = subprocess.run (['partimage', '-B', 'gui=no', 'imginfo', filehead], stdout=subprocess.PIPE, stderr=subprocess.STDOUT, text=True).stdout #partimageinfo = subprocess.run (['cat', '/tmp/foo-partimage'], stdout=subprocess.PIPE, stderr=subprocess.STDOUT, text=True).stdout + ## sacado de un email de alberto garcía uma.es #Volume number:.........0 #Volume size:...........1,27 MiB #Compression level: ....0 -> ninguno @@ -285,9 +298,7 @@ def ogGetImageInfo (imgfile): #Compatible Version:....0.6.1 #Encryption algorithm:..0 -> ninguno #MBR saved count:.......0 - print (f'partimageinfo bef ({partimageinfo})') partimageinfo = re.sub (r':\s*\.+', ' : ', partimageinfo) - print (f'partimageinfo aft ({partimageinfo})') if 'Partition' in partimageinfo: tools = 'PARTIMAGE' m = re.search (r'Filesystem *: *(\S+)', partimageinfo) From b245b5b87791b9cb2dd4528c6d6035f626cd8be4 Mon Sep 17 00:00:00 2001 From: Natalia Serrano Date: Tue, 12 Nov 2024 17:48:38 +0100 Subject: [PATCH 038/167] refs #1101 add ogGetRepoIp() --- client/lib/engine/bin/NetLib.py | 107 +++++++++++++++++++++++++------- 1 file changed, 85 insertions(+), 22 deletions(-) diff --git a/client/lib/engine/bin/NetLib.py b/client/lib/engine/bin/NetLib.py index 49ea950..f42961d 100755 --- a/client/lib/engine/bin/NetLib.py +++ b/client/lib/engine/bin/NetLib.py @@ -2,9 +2,19 @@ import subprocess import sys import os +import ogGlobals import NetLib import SystemLib + + +#/** +# ogChangeRepo IPREPO [ OgUnit ] +#@brief Cambia el repositorio para el recurso remoto images. +#@param 1 Ip Repositorio +#@param 2 Abreviatura Unidad Organizativa +#@return Cambio recurso remoto en OGIMG. +#*/ def ogChangeRepo(): SRCIMG = "" NEWREPO = "" @@ -61,7 +71,16 @@ def ogChangeRepo(): ogConnect(REPO, ogprotocol, SRCIMG, OGIMG, RW) SystemLib.ogRaiseError("session", OG_ERR_REPO, NEWREPO) return subprocess.returncode - + + +#/** +# ogGetGroupDir [ str_repo ] +#@brief Devuelve el camino del directorio para el grupo del cliente. +#@param str_repo repositorio de imágenes (opcional) +#@return path_dir - Camino al directorio del grupo. +#@note repo = { REPO, CACHE } REPO por defecto +#@exception OG_ERR_FORMAT formato incorrecto. +#*/ def ogGetGroupDir(): REPO = "" DIR = "" @@ -84,6 +103,12 @@ def ogGetGroupDir(): return 0 + +#/** +# ogGetGroupName +#@brief Devuelve el nombre del grupo al que pertenece el cliente. +#@return str_group - Nombre de grupo. +#*/ def ogGetGroupName(): if len(sys.argv) >= 2 and sys.argv[1] == "help": SystemLib.ogHelp("ogGetGroupName", "ogGetGroupName", "ogGetGroupName => Grupo1") @@ -94,6 +119,12 @@ def ogGetGroupName(): return 0 + +#/** +# ogGetHostname +#@brief Muestra el nombre del cliente. +#@return str_host - nombre de máquina +#*/ ## def ogGetHostname(): HOST = "" @@ -126,6 +157,13 @@ def ogGetHostname(): if HOST: print(HOST) + +#/** +# ogGetIpAddress +#@brief Muestra la dirección IP del sistema +#@return str_ip - Dirección IP +#@note Usa las variables utilizadas por el initrd "/etc/net-ethX.conf +#*/ ## def ogGetIpAddress(): IP = "" @@ -150,6 +188,12 @@ def ogGetIpAddress(): return 0 + +#/** +# ogGetMacAddress +#@brief Muestra la dirección Ethernet del cliente. +#@return str_ether - Dirección Ethernet +#*/ ## def ogGetMacAddress(): MAC = "" @@ -171,6 +215,13 @@ def ogGetMacAddress(): return 0 + +#/** +# ogGetNetInterface +#@brief Muestra la interfaz de red del sistema +#@return str_interface - interfaz de red +#@note Usa las variables utilizadas por el initrd "/etc/net-ethX.conf +#*/ ## def ogGetNetInterface(): if len(sys.argv) >= 2 and sys.argv[1] == "help": SystemLib.ogHelp("ogGetNetInterface", "ogGetNetInterface", "ogGetNetInterface => eth0") @@ -181,32 +232,35 @@ def ogGetNetInterface(): return 0 -def ogRepoIp(): - # Variables locales. - SOURCE = "" - FSTYPE = "" - # Mostrar ayuda. - if len(sys.argv) >= 2 and sys.argv[1] == "help": - SystemLib.ogHelp("ogRepoIp", "ogRepoIp", "ogRepoIp => 192.168.0.2") - return +#/** +# ogGetRepoIp +#@brief Muestra la dirección IP del repositorio de datos. +#@return str_ip - Dirección IP +#*/ ## +def ogGetRepoIp(): + out = subprocess.run (["findmnt", "--json", "--output", "SOURCE,FSTYPE", ogGlobals.OGIMG], capture_output=True, text=True).stdout + try: + j = json.loads (out) + except json.decoder.JSONDecodeError: + return None - # Obtener direcciones IP, según el tipo de montaje. - output = subprocess.run(["findmnt", "-P", "-o", "SOURCE,FSTYPE", OGIMG], stdout=subprocess.PIPE, stderr=subprocess.DEVNULL).stdout.decode().strip() - lines = output.split("\n") - for line in lines: - fields = line.split() - if len(fields) == 2: - if fields[1] == "nfs": - SOURCE = fields[0].split(":")[0] - elif fields[1] == "cifs": - SOURCE = fields[0].split("/")[2] + if 'filesystems' not in j: return None + source = j['filesystems']['source'] + fstype = j['filesystems']['fstype'] - if SOURCE: - print(SOURCE) + if 'nfs' == fstype: return source.split(":")[0] + elif 'cifs' == fstype: return source.split("/")[2] - return 0 + return None + +#/** +# ogGetServerIp +#@brief Muestra la dirección IP del Servidor de OpenGnSys. +#@return str_ip - Dirección IP +#@note Comprobacion segun protocolo de conexion al Repo +#*/ ## def ogGetServerIp(): # Variables locales. SOURCE = "" @@ -233,6 +287,15 @@ def ogGetServerIp(): return 0 + +#/** +# ogMakeGroupDir [ str_repo ] +#@brief Crea el directorio para el grupo del cliente. +#@param str_repo repositorio de imágenes (opcional) +#@return (nada) +#@note repo = { REPO, CACHE } REPO por defecto +#@exception OG_ERR_FORMAT formato incorrecto. +#*/ def ogMakeGroupDir(): REPO = "" DIR = "" From 8e2f35f89e9e509af12cf1e2c1d0caa14511f0da Mon Sep 17 00:00:00 2001 From: Natalia Serrano Date: Tue, 12 Nov 2024 18:20:36 +0100 Subject: [PATCH 039/167] refs #1101 add a missing import --- client/lib/engine/bin/NetLib.py | 1 + 1 file changed, 1 insertion(+) diff --git a/client/lib/engine/bin/NetLib.py b/client/lib/engine/bin/NetLib.py index f42961d..831a3cb 100755 --- a/client/lib/engine/bin/NetLib.py +++ b/client/lib/engine/bin/NetLib.py @@ -1,6 +1,7 @@ import subprocess import sys import os +import json import ogGlobals import NetLib From 6e30bc1bddf57ea3f2bc808b6a94567f78d0499f Mon Sep 17 00:00:00 2001 From: Natalia Serrano Date: Tue, 12 Nov 2024 19:00:27 +0100 Subject: [PATCH 040/167] refs #1101 add ogMcastSyntax() --- client/lib/engine/bin/FileSystemLib.py | 2 +- client/lib/engine/bin/ImageLib.py | 12 +- client/lib/engine/bin/NetLib.py | 4 +- client/lib/engine/bin/ProtocolLib.py | 199 ++++++++++++++++++++++++- client/lib/engine/bin/StringLib.py | 12 ++ client/lib/engine/bin/ogGlobals.py | 18 ++- 6 files changed, 233 insertions(+), 14 deletions(-) diff --git a/client/lib/engine/bin/FileSystemLib.py b/client/lib/engine/bin/FileSystemLib.py index d8f5d1a..384c969 100755 --- a/client/lib/engine/bin/FileSystemLib.py +++ b/client/lib/engine/bin/FileSystemLib.py @@ -425,7 +425,7 @@ def ogGetMountPoint(disk, par): #@return Código de salida: True - formateado, False - sin formato o error. #*/ ## def ogIsFormated(disk, part): - PART = ogDiskToDev(disk, part) + PART = DiskLib.ogDiskToDev (disk, part) if not PART: return diff --git a/client/lib/engine/bin/ImageLib.py b/client/lib/engine/bin/ImageLib.py index 95be66e..aa27350 100644 --- a/client/lib/engine/bin/ImageLib.py +++ b/client/lib/engine/bin/ImageLib.py @@ -100,7 +100,7 @@ def ogCreateImageSyntax (dev, imgfile, tool='partclone', level='gzip'): 'bzip': ' | bzip -c > ', }.get (level, ' > ') - print (f'param1 ({param1}) param2 ({param2}) param3 ({param3}) imgfile ({imgfile})') + #print (f'param1 ({param1}) param2 ({param2}) param3 ({param3}) imgfile ({imgfile})') if param1: return f'{param1} {param2} {param3} {imgfile}' @@ -148,14 +148,14 @@ def ogRestoreImageSyntax (imgfile, part, tool=None, level=None): 3: ' bzip -dc ', 'bzip': ' bzip -dc ', }.get (level, '') - print (f'tool ({tool}) level ({level}) compressor ({compressor})') + #print (f'tool ({tool}) level ({level}) compressor ({compressor})') if compressor == '': SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTFOUND, f'Compressor no valid {level}') ## original bash code is broken: 'return' is never called #return mbuffer = '| mbuffer -q -m 40M ' if shutil.which ('mbuffer') else ' ' - print (f'mbuffer ({mbuffer})') + #print (f'mbuffer ({mbuffer})') if 'ntfsclone' == tool: tool = f'| ntfsclone --restore-image --overwrite {part} -' elif 'partimage' == tool: @@ -169,7 +169,7 @@ def ogRestoreImageSyntax (imgfile, part, tool=None, level=None): SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTFOUND, f'Tools imaging no valid {tool}') ## original bash code is broken: 'return' is never called #return - print (f'tool ({tool})') + #print (f'tool ({tool})') return f'{compressor} {imgfile} {mbuffer} {tool}'.strip() @@ -202,7 +202,7 @@ def ogGetImageInfo (imgfile): ## original bash idiom is: $($COMPRESSOR -dc $IMGFILE 2>/dev/null | head -n 40 > $FILEHEAD) || ogRaiseError ## the purpose of which I can't fully comprehend - print (f'shelling out "{compressor} -dc {imgfile} |head -n 40 > {filehead}"') + #print (f'shelling out "{compressor} -dc {imgfile} |head -n 40 > {filehead}"') if subprocess.run (f'{compressor} -dc {imgfile} |head -n 40 > {filehead}', shell=True).returncode: SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_IMAGE, f'Image format is not valid {imgfile}') return @@ -256,7 +256,7 @@ def ogGetImageInfo (imgfile): if False == imgdetect and not os.path.exists ('/dev/loop2'): filehead_contents = Path (filehead).read_bytes() if b'ntfsclone-image' in filehead_contents: - print (f'shelling out "cat {filenead} | ntfsclone --restore --overwrite /dev/loop2 - 2>&1"') + #print (f'shelling out "cat {filenead} | ntfsclone --restore --overwrite /dev/loop2 - 2>&1"') ntfscloneinfo = subprocess.run (f'cat {filenead} | ntfsclone --restore --overwrite /dev/loop2 - 2>&1', shell=True, capture_output=True, text=True).stdout #ntfscloneinfo = subprocess.run (['cat', '/tmp/foo-ntfsclone'], stdout=subprocess.PIPE, stderr=subprocess.STDOUT, text=True).stdout ## sacado de claude 3 haiku diff --git a/client/lib/engine/bin/NetLib.py b/client/lib/engine/bin/NetLib.py index 831a3cb..197eaaf 100755 --- a/client/lib/engine/bin/NetLib.py +++ b/client/lib/engine/bin/NetLib.py @@ -247,8 +247,8 @@ def ogGetRepoIp(): return None if 'filesystems' not in j: return None - source = j['filesystems']['source'] - fstype = j['filesystems']['fstype'] + source = j['filesystems'][0]['source'] + fstype = j['filesystems'][0]['fstype'] if 'nfs' == fstype: return source.split(":")[0] elif 'cifs' == fstype: return source.split("/")[2] diff --git a/client/lib/engine/bin/ProtocolLib.py b/client/lib/engine/bin/ProtocolLib.py index f4f21c9..4ddc703 100644 --- a/client/lib/engine/bin/ProtocolLib.py +++ b/client/lib/engine/bin/ProtocolLib.py @@ -1,8 +1,15 @@ #!/usr/bin/python3 +import subprocess +import re +import json + import ogGlobals import SystemLib import ImageLib +import FileSystemLib +import StringLib +import NetLib #/** #@file ProtocolLib.py @@ -42,11 +49,11 @@ def ogUcastSyntax (op, sess, file=None, device=None, tool=None, level=None): raise TypeError ('missing required argument: "device"') if tool is None: raise TypeError ('missing required argument: "tool"') - if tool not in ['partclone', 'PARTCLONE', 'partimage', 'PARTIMAGE', 'ntfsclone', 'NTFSCLONE']: + if tool.lower() not in ['partclone', 'partimage', 'ntfsclone']: raise TypeError (f'argument "tool" has unsupported value "{tool}"') if level is None: raise TypeError ('missing required argument: "level"') - if level not in ['lzop', 'gzip', 'LZOP', 'GZIP', '0', '1']: + if level.lower() not in ['lzop', 'gzip', '0', '1']: raise TypeError (f'argument "level" has unsupported value "{level}"') elif 'SENDFILE' == op or 'RECEIVERFILE' == op: if file is None: @@ -70,7 +77,7 @@ def ogUcastSyntax (op, sess, file=None, device=None, tool=None, level=None): address += f'-O {session[i]}:{portbase}' else: address = f'{session[1]}:{portbase}' - print (f'nati mode ({mode}) address ({address})') + #print (f'nati mode ({mode}) address ({address})') if 'SENDPARTITION' == op: syn = ImageLib.ogCreateImageSyntax (device, ' ', tool, level) @@ -78,7 +85,7 @@ def ogUcastSyntax (op, sess, file=None, device=None, tool=None, level=None): ## otherwise, param2 in ImageLib.ogCreateImageSyntax() is not '| mbuffer' but empty ## and then parts[2] is out of range parts = syn.split ('|') - print (f'syn ({syn}) parts ({parts})') + #print (f'syn ({syn}) parts ({parts})') prog1 = f'{parts[0]}|{parts[2]}'.strip() prog1 = prog1.replace ('>', '').strip() return f'{prog1} | mbuffer {address}' @@ -140,6 +147,28 @@ def ogUcastSyntax (op, sess, file=None, device=None, tool=None, level=None): #*/ ## # +def _clientip(): + ipas = subprocess.run (['ip', '-json', 'address', 'show', 'up'], capture_output=True, text=True).stdout + ipasj = json.loads (ipas) + addresses = [] + for e in ipasj: + if 'lo' == e['ifname']: continue + if 'vboxnet' in e['ifname']: continue + if 'br-' in e['ifname']: continue + if 'tun' in e['ifname']: continue + if 'addr_info' not in e: continue + addrs = e['addr_info'] + for a in addrs: + if 'inet' != a['family']: continue + addresses.append ({ 'local': a['local'], 'prefixlen': a['prefixlen'] }) + return addresses + +def _binary_ip (ip): + for l in subprocess.run (['ipcalc', '--nocolor', ip ], capture_output=True, text=True).stdout.splitlines(): + if 'Address' not in l: continue + match = re.search (r'^(Address:)\s+(\S+)\s+(.*$)', l).group(3).replace (' ', '').replace ('.', '') + break + return match #/** # ogMcastSyntax @@ -158,6 +187,168 @@ def ogUcastSyntax (op, sess, file=None, device=None, tool=None, level=None): #*/ ## # +#ogMcastSyntax SENDPARTITION 9000:full-duplex|half-duplex|broadcast:239.194.17.36:80M:50:60 device tools level +#ogMcastSyntax RECEIVERPARTITION 9000 device tools level +#ogMcastSyntax RECEIVERPARTITION 9000:172.17.88.161:40:120 device tools level + +#ogMcastSyntax SENDFILE 9000:full-duplex|half-duplex|broadcast:239.194.17.36:80M:50:60 file +#ogMcastSyntax RECEIVERFILE 9000 file +#ogMcastSyntax RECEIVERFILE 9000:172.17.88.161:40:120 file +def ogMcastSyntax (op, sess, file=None, device=None, tool=None, level=None): + if 'SENDPARTITION' == op or 'RECEIVERPARTITION' == op: + if device is None: + raise TypeError ('missing required argument: "device"') + if tool is None: + raise TypeError ('missing required argument: "tool"') + if tool.lower() not in ['partclone', 'partimage', 'ntfsclone']: + raise TypeError (f'argument "tool" has unsupported value "{tool}"') + if level is None: + raise TypeError ('missing required argument: "level"') + if level.lower() not in ['lzop', 'gzip', '0', '1']: + raise TypeError (f'argument "level" has unsupported value "{level}"') + elif 'SENDFILE' == op or 'RECEIVERFILE' == op: + if file is None: + raise TypeError ('missing required argument: "file"') + else: + raise TypeError ('first parameter should match (SEND|RECEIVER)(PARTITION|FILE), eg. "SENDFILE"') + + if 'SEND' in op: mode = 'server' + else: mode = 'client' + + try: + isudpcast = subprocess.run (['udp-receiver', '--help'], stdout=subprocess.PIPE, stderr=subprocess.STDOUT, text=True).stdout + except subprocess.CalledProcessError: + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTEXEC, 'upd-cast no existe') + return + + session = sess.split (':') + + PERROR = 0 + if 'server' == mode: + if 6 != len (session): + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_FORMAT, 'parametros session de servidor multicast no completa') + PERROR = 2 + elif 'client' == mode: + if 4 < len (session): + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_FORMAT, 'parametros session de cliente multicast no completa') + PERROR = 2 + + mbuffer = " --pipe 'mbuffer -q -m 20M' " + portbase = int (session[0]) + if portbase not in range (9000, 9100, 2): + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_FORMAT, f'McastSession portbase {portbase}') + PERROR = 3 + + if 'server' == mode: + method, address, bitrate, nclients, maxtime = session[1:] + + if method.lower() not in ['full-duplex', 'half-duplex', 'broadcast']: + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_FORMAT, f'McastSession method {method}') + PERROR = 4 + + if not StringLib.ogCheckIpAddress (address): + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_FORMAT, f'McastSession address {address}') + PERROR = 5 + + ## the original regex has a backslash: ^[0-9]{1,3}\M$ + ## not sure why + if not re.search (r'^[0-9]{1,3}M$', bitrate): + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_FORMAT, f'McastSession bitrate {bitrate}') + PERROR = 6 + + if not re.search (r'^[0-9]{1,10}$', nclients): + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_FORMAT, f'McastSession nclients {nclients}') + PERROR = 7 + + if not re.search (r'^[0-9]{1,10}$', maxtime): + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_FORMAT, f'McastSession maxtime {maxtime}') + PERROR = 8 + + cerror = '8x8/128' + syntaxserver = f'udp-sender {mbuffer} --nokbd --portbase {portbase} --{method} --mcast-data-address {address} --fec {cerror} --max-bitrate {bitrate} --ttl 16 --min-clients {nclients} --max-wait {maxtime} --autostart {maxtime} --log /tmp/mcast.log' + + if PERROR: + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_MCASTSYNTAXT, f' {PERROR}') + return + + + if 'client' == mode: + other = session[1:] + #print (f'session ({session}) other ({other})') + serveraddress = other[0] if len (other) > 0 else '' + starttimeout = other[1] if len (other) > 1 else '' + receivertimeout = other[2] if len (other) > 2 else '' + + ## serveraddres + if StringLib.ogCheckIpAddress (serveraddress): + serveraddress = f' --mcast-rdv-address {serveraddress}' + else: + repoip = NetLib.ogGetRepoIp() + clientip = _clientip() + #print (f'repoip ({repoip}) clientip ({clientip})') + if 1 != len (clientip): + raise Exception ('more than one local IP address found') + c = clientip[0] + #print (f'c ({c})') + clientip = c['local'] + mascara = c['prefixlen'] + #print (f'clientip ({clientip}) mascara ({mascara})') + + ripbt = _binary_ip (repoip) + ipbt = _binary_ip (clientip) + reposubred = ripbt[0:mascara] + clientsubred = ipbt[0:mascara] + #print (f'ripbt ({ripbt})') + #print (f'ipbt ({ipbt})') + #print (f'reposubred ({reposubred})') + #print (f'clientsubred ({clientsubred})') + if reposubred == clientsubred: serveraddress = ' ' + else: serveraddress = f' --mcast-rdv-address {repoip}' + + ## starttimeout + if re.search (r'^[0-9]{1,10}$', starttimeout): + if 0 == starttimeout: starttimeout = ' ' + else: starttimeout = f' --start-timeout {starttimeout}' + else: + starttimeout = f' --start-timeout {ogGlobals.MCASTERRORSESSION}' + if 'start-timeout' not in isudpcast: starttimeout = ' ' + + ## receivertimeout + if re.search (r'^[0-9]{1,10}$', receivertimeout): + if 0 == receivertimeout: receivertimeout = ' ' + else: receivertimeout = f' --receive-timeout {receivertimeout}' + else: + receivertimeout = f' --receive-timeout {ogGlobals.MCASTWAIT}' + if 'receive-timeout' not in isudpcast: receivertimeout = ' ' + + syntaxclient = f'udp-receiver {mbuffer} --portbase {portbase} {serveraddress} {starttimeout} {receivertimeout} --log /tmp/mcast.log' + + if 'SENDPARTITION' == op: + syn = ImageLib.ogCreateImageSyntax (device, ' ', tool, level) + ## REQUIRES package mbuffer to be installed!! + ## otherwise, param2 in ImageLib.ogCreateImageSyntax() is not '| mbuffer' but empty + ## and then parts[2] is out of range + parts = syn.split ('|') + #print (f'syn ({syn}) parts ({parts})') + prog1 = f'{parts[0]}|{parts[2]}'.strip() + prog1 = prog1.replace ('>', '').strip() + return f'{prog1} | {syntaxserver}' + + elif 'RECEIVERPARTITION' == op: + syn = ImageLib.ogRestoreImageSyntax (' ', device, tool, level) + parts = syn.split ('|') + compressor = parts[0].strip() + tools = parts[-1].strip() + return f'{syntaxclient} | {compressor} | {tools} ' + + elif 'SENDFILE' == op: + return f'{syntaxserver} --file {file}' + + elif 'RECEIVERFILE' == op: + return f'{syntaxclient} --file {file}' + + else: + raise Exception (f'unknown op ({op})--this should not happen') diff --git a/client/lib/engine/bin/StringLib.py b/client/lib/engine/bin/StringLib.py index 2c9e150..49505d2 100755 --- a/client/lib/engine/bin/StringLib.py +++ b/client/lib/engine/bin/StringLib.py @@ -26,6 +26,18 @@ def ogCheckStringInReg(element, regex): return re.match(regex, element) is not None + + +#/** +# ogCheckIpAddress +#@brief Función para determinar si una cadena es una dirección ipv4 válida +#@param 1 string de la ip a comprobar +#@return 0 si es una dirección válida +#@return 1 si NO es una dirección válida +#@exception OG_ERR_FORMAT formato incorrecto. +#@note +#@todo +#*/ ## def ogCheckIpAddress(ip): """ Función para determinar si una cadena es una dirección ipv4 válida. diff --git a/client/lib/engine/bin/ogGlobals.py b/client/lib/engine/bin/ogGlobals.py index bf9c1b9..63713c9 100755 --- a/client/lib/engine/bin/ogGlobals.py +++ b/client/lib/engine/bin/ogGlobals.py @@ -30,7 +30,23 @@ TZ='Europe/Madrid' ## engine.cfg OGLOGSESSION='/tmp/session.log' OGLOGCOMMAND='/tmp/command.log' -NODEBUGFUNCTIONS='ogCreateImageSyntax ogGetHivePath ogGetOsType ogRestoreImageSyntax ogUnmountAll ogUnmountCache' +#OGWINCHKDISK=True #Hacer chkdisk tras la clonacion +#ACTIONCACHEFULL=None #Que hacer cuando la cache no tenga espacio libre. [ NONE | FORMAT ] ] +#RESTOREPROTOCOLNOTCACHE=None #Que protocolo de restauracion usar en el caso de que no exista cache o no exista espacio sufiente. [NONE | UNICAST | MULTICAST].NONE retorna error +#IMGPROG='partclone' +#IMGCOMP='lzop' +#IMGEXT='img' +#IMGREDUCE=True +#OGWINREDUCE=True #Al enviar particion reducir el sistema de archivos previamente. +MCASTERRORSESSION=120 #timeout (segundos) para abortar la sesion de multicast si no contacta con el servidor de multicast. Valor asignado a 0, utiliza los valores por defecto de udp-cast +MCASTWAIT=30 # timeout (segundos) para abortar la la transferencia si se interrumpe. Valor asignado a 0, utiliza los valores por defecto de udp-cast +#CREATESPEED=100000*4 # Factor para calcular el time-out al crear la imagen. 100000k -> 4s +#FACTORSYNC=120 # Factor de compresion para las imagenes (windos en ext4). +#BACKUP=False # Realizar copia de seguridad antes de crear la imagen. +#IMGFS='EXT4' # Sistema de archivo de la imagenes sincronizadas. EXT4 o BTRFS +#OGSLEEP=20 # Tiempo de sleep antes de realizar el reboot +NODEBUGFUNCTIONS='ogCreateImageSyntax ogGetHivePath ogGetOsType ogRestoreImageSyntax ogUnmountAll ogUnmountCache' # Funciones que no deben mostrar salida de avisos si son llamadas por otras funciones. +#DEFAULTSPEED='' ## /engine.cfg From 3ca8cb6dfed8a869ef724cc248a4e53f417b7cef Mon Sep 17 00:00:00 2001 From: Natalia Serrano Date: Tue, 12 Nov 2024 19:05:14 +0100 Subject: [PATCH 041/167] refs #1101 add ogMcastSendPartition() --- client/lib/engine/bin/ProtocolLib.py | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/client/lib/engine/bin/ProtocolLib.py b/client/lib/engine/bin/ProtocolLib.py index 4ddc703..5bc96b0 100644 --- a/client/lib/engine/bin/ProtocolLib.py +++ b/client/lib/engine/bin/ProtocolLib.py @@ -398,6 +398,21 @@ def ogMcastSyntax (op, sess, file=None, device=None, tool=None, level=None): #@todo: ogIsLocked siempre devuelve 1. crear ticket #*/ ## +#ogMcastSendPartition (disk, par, SessionMulticastSERVER, tools, compresor) +#ogMcastSendPartition (1, 1, '9000:full-duplex:239.194.37.31:50M:20:2', 'partclone', 'lzop') +def ogMcastSendPartition (disk, par, sess, tool, compressor): + PART = DiskLib.ogDiskToDev (disk, par) + if not PART: return + + FileSystemLib.ogUnmount (disk, par) + cmd = ogMcastSyntax ('SENDPARTITION', sess, PART, tool, compressor) + if not cmd: return None + print (f'cmd ({cmd})') + try: + subprocess.run (cmd, shell=True, check=True) + except subprocess.CalledProcessError: + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_MCASTSENDPARTITION, ' ') + return None #/** # ogMcastReceiverPartition From f232fb8bdf9a6f64f79b53e18109a42df1bd545d Mon Sep 17 00:00:00 2001 From: Natalia Serrano Date: Tue, 12 Nov 2024 19:13:52 +0100 Subject: [PATCH 042/167] refs #1101 add ogMcastReceiverPartition() --- client/lib/engine/bin/ProtocolLib.py | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/client/lib/engine/bin/ProtocolLib.py b/client/lib/engine/bin/ProtocolLib.py index 5bc96b0..1d09bab 100644 --- a/client/lib/engine/bin/ProtocolLib.py +++ b/client/lib/engine/bin/ProtocolLib.py @@ -10,6 +10,7 @@ import ImageLib import FileSystemLib import StringLib import NetLib +import DiskLib #/** #@file ProtocolLib.py @@ -405,13 +406,13 @@ def ogMcastSendPartition (disk, par, sess, tool, compressor): if not PART: return FileSystemLib.ogUnmount (disk, par) - cmd = ogMcastSyntax ('SENDPARTITION', sess, PART, tool, compressor) + cmd = ogMcastSyntax ('SENDPARTITION', sess, device=PART, tool=tool, level=compressor) if not cmd: return None print (f'cmd ({cmd})') try: subprocess.run (cmd, shell=True, check=True) except subprocess.CalledProcessError: - SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_MCASTSENDPARTITION, ' ') + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_MCASTSENDPARTITION, ' ') return None #/** @@ -425,6 +426,20 @@ def ogMcastSendPartition (disk, par, sess, tool, compressor): #@return #@exception $OG_ERR_FORMAT #*/ ## +def ogMcastReceiverPartition (disk, par, sess, tool, compressor): + PART = DiskLib.ogDiskToDev (disk, par) + if not PART: return + + FileSystemLib.ogUnmount (disk, par) + cmd = ogMcastSyntax ('RECEIVERPARTITION', sess, device=PART, tool=tool, level=compressor) + if not cmd: return None + print (f'cmd ({cmd})') + try: + subprocess.run (cmd, shell=True, check=True) + except subprocess.CalledProcessError: + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_MCASTRECEIVERPARTITION, ' ') ## original code has OG_ERR_MCASTSENDPARTITION + return None + #/** From bddbf6fa577541bc1982affd30d41b7abb9bd36d Mon Sep 17 00:00:00 2001 From: Natalia Serrano Date: Tue, 12 Nov 2024 19:50:14 +0100 Subject: [PATCH 043/167] refs #1101 add ogMcastSendFile() --- client/lib/engine/bin/ProtocolLib.py | 49 ++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) diff --git a/client/lib/engine/bin/ProtocolLib.py b/client/lib/engine/bin/ProtocolLib.py index 1d09bab..d14fc7c 100644 --- a/client/lib/engine/bin/ProtocolLib.py +++ b/client/lib/engine/bin/ProtocolLib.py @@ -11,6 +11,7 @@ import FileSystemLib import StringLib import NetLib import DiskLib +import FileLib #/** #@file ProtocolLib.py @@ -366,6 +367,54 @@ def ogMcastSyntax (op, sess, file=None, device=None, tool=None, level=None): #*/ ## # +#ogMcastSendFile [str_REPOSITORY] [int_ndisk int_npart] /Relative_path_file sesionMcast" \ +#ogMcastSendFile (disk=1, par=1, file='/aula1/winxp.img', sess='sesionMcast') +#ogMcastSendFile (from='REPO', file='/aula1/ubuntu.iso', sess='sesionMcast') +#ogMcastSendFile (from='CACHE', file='/aula1/winxp.img', sess='sesionMcast') +#ogMcastSendFile ( file='/opt/opengnsys/images/aula1/hd500.vmx', sess='sesionMcast') +def ogMcastSendFile (disk=None, par=None, take_from=None, file=None, sess=None): + if file is None: + raise TypeError ('missing required argument: "file"') + if sess is None: + raise TypeError ('missing required argument: "sess"') + + if take_from is not None: + if disk is None and par is None: + ## we were given take_from= + source = FileLib.ogGetPath (src=take_from, file=file) + dev_err = ' '.join ([take_from, file]) + print (f'ogGetPath (src=({take_from}), file=({file})) = source ({source})') + else: + raise TypeError ('argument "take_from" can be specified along neither "disk" nor "par"') + + else: + if disk is not None and par is not None: + ## we were given disk= par= + source = FileLib.ogGetPath (src=f'{disk} {par}', file=file) + dev_err = ' '.join ([disk, par, file]) + print (f'ogGetPath (src=({disk} {par}), file=({file})) = source ({source})') + elif disk is None and par is None: + ## we were given nothing + source = FileLib.ogGetPath (file=file) + dev_err = file + print (f'ogGetPath (file=({file})) = source ({source})') + else: + raise TypeError ('if one of "disk" and "par" are specified, then both must be') + + path2 = FileLib.ogGetPath (file=source) + print (f'path2 ({path2})') + if not path2: + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTFOUND, f'device or file {dev_err} not found') + return + + cmd = ogMcastSyntax ('SENDFILE', sess, file=source) + if not cmd: return None + print (f'cmd ({cmd})') + try: + subprocess.run (cmd, shell=True, check=True) + except subprocess.CalledProcessError: + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_MCASTSENDFILE, ' ') + return None From cb0c2b259d0bba4465569a8fc07759eb3522c958 Mon Sep 17 00:00:00 2001 From: Natalia Serrano Date: Tue, 12 Nov 2024 20:11:23 +0100 Subject: [PATCH 044/167] refs #1101 add ogMcastReceiverFile() --- client/lib/engine/bin/ProtocolLib.py | 65 +++++++++++++++++++++++++--- 1 file changed, 59 insertions(+), 6 deletions(-) diff --git a/client/lib/engine/bin/ProtocolLib.py b/client/lib/engine/bin/ProtocolLib.py index d14fc7c..b12de50 100644 --- a/client/lib/engine/bin/ProtocolLib.py +++ b/client/lib/engine/bin/ProtocolLib.py @@ -3,6 +3,7 @@ import subprocess import re import json +import os.path import ogGlobals import SystemLib @@ -368,10 +369,10 @@ def ogMcastSyntax (op, sess, file=None, device=None, tool=None, level=None): # #ogMcastSendFile [str_REPOSITORY] [int_ndisk int_npart] /Relative_path_file sesionMcast" \ -#ogMcastSendFile (disk=1, par=1, file='/aula1/winxp.img', sess='sesionMcast') -#ogMcastSendFile (from='REPO', file='/aula1/ubuntu.iso', sess='sesionMcast') -#ogMcastSendFile (from='CACHE', file='/aula1/winxp.img', sess='sesionMcast') -#ogMcastSendFile ( file='/opt/opengnsys/images/aula1/hd500.vmx', sess='sesionMcast') +#ogMcastSendFile (disk=1, par=1, file='/aula1/winxp.img', sess='sesionMcast') +#ogMcastSendFile (take_from='REPO', file='/aula1/ubuntu.iso', sess='sesionMcast') +#ogMcastSendFile (take_from='CACHE', file='/aula1/winxp.img', sess='sesionMcast') +#ogMcastSendFile ( file='/opt/opengnsys/images/aula1/hd500.vmx', sess='sesionMcast') def ogMcastSendFile (disk=None, par=None, take_from=None, file=None, sess=None): if file is None: raise TypeError ('missing required argument: "file"') @@ -382,7 +383,7 @@ def ogMcastSendFile (disk=None, par=None, take_from=None, file=None, sess=None): if disk is None and par is None: ## we were given take_from= source = FileLib.ogGetPath (src=take_from, file=file) - dev_err = ' '.join ([take_from, file]) + dev_err = f'{take_from} {file}' print (f'ogGetPath (src=({take_from}), file=({file})) = source ({source})') else: raise TypeError ('argument "take_from" can be specified along neither "disk" nor "par"') @@ -391,7 +392,7 @@ def ogMcastSendFile (disk=None, par=None, take_from=None, file=None, sess=None): if disk is not None and par is not None: ## we were given disk= par= source = FileLib.ogGetPath (src=f'{disk} {par}', file=file) - dev_err = ' '.join ([disk, par, file]) + dev_err = f'{disk} {par} {file}' print (f'ogGetPath (src=({disk} {par}), file=({file})) = source ({source})') elif disk is None and par is None: ## we were given nothing @@ -401,6 +402,10 @@ def ogMcastSendFile (disk=None, par=None, take_from=None, file=None, sess=None): else: raise TypeError ('if one of "disk" and "par" are specified, then both must be') + if not source: + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTFOUND, f'device or file {dev_err} not found') + return + path2 = FileLib.ogGetPath (file=source) print (f'path2 ({path2})') if not path2: @@ -431,6 +436,54 @@ def ogMcastSendFile (disk=None, par=None, take_from=None, file=None, sess=None): #*/ ## # +#ogMcastReceiverFile ([ str_portMcast] [ [Relative_path_file] | [str_REPOSITORY path_file] | [int_ndisk int_npart path_file ] ]" \ +#ogMcastReceiverFile ( file='/PS1_PH1.img', sess='9000') +#ogMcastReceiverFile (write_to='CACHE', file='/aula1/PS2_PH4.img', sess='9000') +#ogMcastReceiverFile (disk=1, par=1, file='/isos/linux.iso', sess='9000') +def ogMcastReceiverFile (disk=None, par=None, write_to=None, file=None, sess=None): + if file is None: + raise TypeError ('missing required argument: "file"') + if sess is None: + raise TypeError ('missing required argument: "sess"') + + if write_to is not None: + if disk is None and par is None: + ## we were given write_to= + targetdir = FileLib.ogGetParentPath (src=write_to, file=file) + dev_err = f'{write_to} {file}' + print (f'ogGetParentPath (src=({write_to}), file=({file})) = targetdir ({targetdir})') + else: + raise TypeError ('argument "write_to" can be specified along neither "disk" nor "par"') + + else: + if disk is not None and par is not None: + ## we were given disk= par= + targetdir = FileLib.ogGetParentPath (src=f'{disk} {par}', file=file) + dev_err = f'{disk} {par} {file}' + print (f'ogGetParentPath (src=({disk} {par}), file=({file})) = targetdir ({targetdir})') + elif disk is None and par is None: + ## we were given nothing + targetdir = FileLib.ogGetParentPath (file=file) + dev_err = file + print (f'ogGetParentPath (file=({file})) = targetdir ({targetdir})') + else: + raise TypeError ('if one of "disk" and "par" are specified, then both must be') + + if not targetdir: + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTFOUND, f'target directory {targetdir} not found') + return + + targetfile = os.path.basename (file) + print (f'targetfile ({targetfile})') + + cmd = ogMcastSyntax ('RECEIVERFILE', sess, file=os.path.join (targetdir, targetfile)) + if not cmd: return None + print (f'cmd ({cmd})') + try: + subprocess.run (cmd, shell=True, check=True) + except subprocess.CalledProcessError: + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_MCASTRECEIVERFILE, targetfile) + return None #/** From afec1aad2e0fe7554d424d5b66b153d6684063bc Mon Sep 17 00:00:00 2001 From: Antonio Emmanuel Guerrero Silva Date: Tue, 12 Nov 2024 23:21:13 -0600 Subject: [PATCH 045/167] refs #1093 adds interface short description messages and complementary messages --- client/lib/engine/bin/ogGlobals.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/client/lib/engine/bin/ogGlobals.py b/client/lib/engine/bin/ogGlobals.py index 63713c9..cd58566 100755 --- a/client/lib/engine/bin/ogGlobals.py +++ b/client/lib/engine/bin/ogGlobals.py @@ -110,3 +110,13 @@ OG_ERR_SYNCHRONIZING=74 # Error al sincronizar, puede afectar la cr OG_ERR_NOTUEFI=80 # La interfaz UEFI no está activa OG_ERR_NOTBIOS=81 # La interfaz BIOS legacy no está activa + +# Mensajes de descripción breve de la interfaz. +MSG_INTERFACE_START="[START Interface] Ejecutar comando: " +MSG_INTERFACE_END="[END Interface] Comando terminado con este código: " + +# Mensajes complementarios para las ayudas. +MSG_64BIT="64 bits" +MSG_DISK="disc" +MSG_ERROR="Error" +MSG_FORMAT="Format" \ No newline at end of file From 9a1c90234ed8cad1848d5342760db3732e3220db Mon Sep 17 00:00:00 2001 From: Antonio Emmanuel Guerrero Silva Date: Tue, 12 Nov 2024 23:31:27 -0600 Subject: [PATCH 046/167] refs #1093 rebuild ogListSoftware --- client/lib/engine/bin/InventoryLib.py | 74 +++++++++++++-------------- 1 file changed, 37 insertions(+), 37 deletions(-) diff --git a/client/lib/engine/bin/InventoryLib.py b/client/lib/engine/bin/InventoryLib.py index bb8c7bc..c49e46b 100755 --- a/client/lib/engine/bin/InventoryLib.py +++ b/client/lib/engine/bin/InventoryLib.py @@ -137,64 +137,64 @@ def ogListHardwareInfo(): return f"{output}\n{firmware}\n{lshw_output}" def ogListSoftware(disk, partition): - # Error si no se reciben 2 parametros if disk is None or partition is None: - SystemLib.ogRaiseError("OG_ERR_FORMAT") - return + SystemLib.ogRaiseError(ogGlobals.OG_ERR_FORMAT) + return [] - # Obtener tipo de sistema de archivos y montarlo mnt_dir = FileSystemLib.ogMount(disk, partition) os_type = ogGetOsType(disk, partition) - # Ficheros temporales - apps_file = tempfile.NamedTemporaryFile(delete=False) - tmp_file = tempfile.NamedTemporaryFile(delete=False) + apps_file = tempfile.NamedTemporaryFile(delete=False, mode="w+") + tmp_file = tempfile.NamedTemporaryFile(delete=False, mode="w+") + apps = [] try: if os_type == "Linux": - # Procesar paquetes dpkg pkg_dir = os.path.join(mnt_dir, "var/lib/dpkg") - if os.path.exists(pkg_dir): - with open(os.path.join(pkg_dir, "status"), "r") as status_file: - for line in status_file: - # Process lines to extract software info - pass - # Procesar paquetes RPM + status_file = os.path.join(pkg_dir, "status") + if os.path.exists(status_file): + with open(status_file, "r") as f: + pkg, ver = None, None + for line in f: + if line.startswith("Package:"): + pkg = line.split(":", 1)[1].strip() + elif line.startswith("Version:"): + ver = line.split(":", 1)[1].strip() + elif line.startswith("Status:") and "install" not in line: + pkg, ver = None, None + if pkg and ver: + apps.append(f"{pkg} {ver}") + pkg, ver = None, None + pkg_dir = os.path.join(mnt_dir, "var/lib/rpm") if os.path.exists(pkg_dir): - # Execute rpm command if available if shutil.which("rpm"): - subprocess.run(["rpm", "--dbpath", pkg_dir, "-qa", "--qf", "%{NAME} %{VERSION}\n"], stdout=apps_file) + result = subprocess.run( + ["rpm", "--dbpath", pkg_dir, "-qa", "--qf", "%{NAME} %{VERSION}\n"], + capture_output=True, + text=True + ) + if result.returncode == 0: + apps.extend(result.stdout.strip().splitlines()) else: - # Compatibility mode for older systems - pass - # Procesar otros tipos de paquetes (pacman, snap, flatpak, etc.) - pass - elif os_type == "Windows": - # Procesar aplicaciones instaladas en Windows - hive_path = Registry.ogGetHivePath(mnt_dir, "software") - if hive_path: - subprocess.run(["hivexregedit", "--unsafe-printable-strings", "--export", hive_path, '\Microsoft\Windows\CurrentVersion\Uninstall'], stdout=tmp_file) - elif osType == "MacOS": - # Procesar aplicaciones instaladas en MacOS - pass - elif osType == "BSD": - # Procesar aplicaciones instaladas en FreeBSD + SystemLib.ogEcho("session", "error", "The rpm command is not available.") + pass + else: - SystemLib.ogRaiseError("OG_ERR_NOTOS", disk, partition) + SystemLib.ogRaiseError(ogGlobals.OG_ERR_NOTOS, disk, partition) + return [] + finally: - # Eliminar archivos temporales apps_file.close() tmp_file.close() os.remove(apps_file.name) os.remove(tmp_file.name) - # Mostrar sistema operativo y aplicaciones - ogGetOsVersion(disk, partition) - with open(apps_file.name, "r") as apps: - for line in sorted(set(apps.readlines())): - print(line.strip()) + os_version = ogGetOsVersion(disk, partition) + print(f"Operative System: {os_version}") + + return sorted(set(apps)) def ogGetOsVersion(ndisk, nfilesys): # Variables locales. From 77a9eb2439ce0081e2270264c7c559234b838c06 Mon Sep 17 00:00:00 2001 From: Antonio Emmanuel Guerrero Silva Date: Tue, 12 Nov 2024 23:34:52 -0600 Subject: [PATCH 047/167] refs #1093 rebuild ogGetOsVersion --- client/lib/engine/bin/InventoryLib.py | 208 +++++--------------------- 1 file changed, 34 insertions(+), 174 deletions(-) diff --git a/client/lib/engine/bin/InventoryLib.py b/client/lib/engine/bin/InventoryLib.py index c49e46b..6744142 100755 --- a/client/lib/engine/bin/InventoryLib.py +++ b/client/lib/engine/bin/InventoryLib.py @@ -196,182 +196,42 @@ def ogListSoftware(disk, partition): return sorted(set(apps)) -def ogGetOsVersion(ndisk, nfilesys): - # Variables locales. - MNTDIR = FileSystemLib.ogMount(ndisk, nfilesys) - TYPE = "" - VERSION = "" - IS64BIT = "" - # Si se solicita, mostrar ayuda. - if len(sys.argv) > 1 and sys.argv[1] == "help": - SystemLib.ogHelp(sys.argv[0], sys.argv[0] + " int_ndisk int_nfilesys", sys.argv[0] + " 1 2 => Linux:Ubuntu precise (12.04 LTS) 64 bits") - return - - # Error si no se reciben 2 parametros. - if len(sys.argv) != 3: - SystemLib.ogRaiseError(OG_ERR_FORMAT) - return - - # Montar la particion, si no lo estaba previamente. - MNTDIR = FileSystemLib.ogMount(sys.argv[1], sys.argv[2]) - if not MNTDIR: - return - - # Buscar tipo de sistema operativo. - # Para GNU/Linux: leer descripción. - TYPE = "Linux" - FILE = os.path.join(MNTDIR, "etc", "os-release") - if os.path.exists(FILE): - with open(FILE, "r") as f: - for line in f: - if line.startswith("PRETTY_NAME"): - VERSION = line.split("=")[1].strip().strip('"') - break - - # Si no se puede obtener, buscar en ficheros del sistema. - if not VERSION: - FILE = os.path.join(MNTDIR, "etc", "lsb-release") - if os.path.exists(FILE): - with open(FILE, "r") as f: +def ogGetOsVersion(disk, part): + try: + mnt_dir = FileSystemLib.ogMount(disk, part) + + version = None + os_release = os.path.join(mnt_dir, "etc/os-release") + if os.path.isfile(os_release): + with open(os_release, "r") as f: for line in f: - if line.startswith("DESCRIPTION"): - VERSION = line.split("=")[1].strip().strip('"') + if line.startswith("PRETTY_NAME"): + version = line.split("=", 1)[1].strip().strip('"') break - for DISTRIB in ["redhat", "SuSE", "mandrake", "gentoo"]: - FILE = os.path.join(MNTDIR, "etc", f"{DISTRIB}-release") - if os.path.exists(FILE): - with open(FILE, "r") as f: - VERSION = f.readline().strip() - break - FILE = os.path.join(MNTDIR, "etc", "arch-release") - if os.path.exists(FILE): - VERSION = "Arch Linux" - FILE = os.path.join(MNTDIR, "etc", "slackware-version") - if os.path.exists(FILE): - with open(FILE, "r") as f: - VERSION = f.read().strip() - - # Si no se encuentra, intentar ejecutar "lsb_release". - if not VERSION: - try: - output = subprocess.check_output(["chroot", MNTDIR, "lsb_release", "-d"], stderr=subprocess.DEVNULL).decode().strip() - VERSION = output.split(":")[1].strip() - except subprocess.CalledProcessError: - pass - - # Comprobar Linux de 64 bits. - if VERSION and os.path.exists(os.path.join(MNTDIR, "lib64")): - IS64BIT = "64 bits" - - # Para Android, leer fichero de propiedades. - if not VERSION: - TYPE = "Android" - FILE = os.path.join(MNTDIR, "android*", "system", "build.prop") - if glob.glob(FILE): - with open(glob.glob(FILE)[0], "r") as f: - lines = f.readlines() - brand = "" - release = "" - for line in lines: - if line.startswith("product.brand"): - brand = line.split("=")[1].strip() - elif line.startswith("build.version.release"): - release = line.split("=")[1].strip() - VERSION = f"Android {brand} {release}" - if os.path.exists(os.path.join(MNTDIR, "lib64")): - IS64BIT = "64 bits" - - # Para GNU/Hurd, comprobar fichero de inicio (basado en os-prober). - if not VERSION: - TYPE = "Hurd" - FILE = os.path.join(MNTDIR, "hurd", "init") - if os.path.exists(FILE): - VERSION = "GNU/Hurd" - - # Para Windows: leer la version del registro. - if not VERSION: - TYPE = "Windows" - FILE = ogGetHivePath(MNTDIR, "SOFTWARE") - if FILE: - try: - output = subprocess.check_output(["hivexsh", "load", FILE, "cd", "\\Microsoft\\Windows NT\\CurrentVersion", "lsval", "ProductName", "lsval", "DisplayVersion"], stderr=subprocess.DEVNULL).decode().strip() - lines = output.split("\n") - if len(lines) == 2: - VERSION = lines[1].strip() - if Registry.ogGetRegistryValue(MNTDIR, "SOFTWARE", "\\Microsoft\\Windows\\CurrentVersion\\ProgramW6432Dir"): - IS64BIT = "64 bits" - except subprocess.CalledProcessError: - pass - - # Para cargador Windows: buscar versión en fichero BCD (basado en os-prober). - if not VERSION: - TYPE = "WinLoader" - FILE = FileLib.ogGetPath(MNTDIR, "boot", "bcd") - if not FILE: - FILE = FileLib.ogGetPath(MNTDIR, "EFI", "Microsoft", "boot", "bcd") - if FILE: - for DISTRIB in ["Windows Recovery", "Windows Boot"]: - with open(FILE, "rb") as f: - if re.search(DISTRIB.encode(), f.read()): - VERSION = f"{DISTRIB} loader" + + if not version: + lsb_release = os.path.join(mnt_dir, "etc/lsb-release") + if os.path.isfile(lsb_release): + with open(lsb_release, "r") as f: + for line in f: + if line.startswith("DISTRIB_DESCRIPTION"): + version = line.split("=", 1)[1].strip().strip('"') + break + + if not version: + for distrib in ["redhat", "SuSE", "mandrake", "gentoo"]: + distrib_file = os.path.join(mnt_dir, f"etc/{distrib}-release") + if os.path.isfile(distrib_file): + with open(distrib_file, "r") as f: + version = f.readline().strip() break + + is_64bit = os.path.exists(os.path.join(mnt_dir, "lib64")) + if is_64bit: + version = f"{version} 64 bits" - # Para macOS: detectar kernel y completar con fichero plist de información del sistema. - if not VERSION: - TYPE = "MacOS" - FILE = os.path.join(MNTDIR, "mach_kernel") - if os.path.exists(FILE) and not subprocess.check_output(["file", "-b", FILE]).decode().strip().startswith("text"): - if subprocess.check_output(["file", "-b", FILE]).decode().strip().startswith("Mach-O"): - VERSION = "macOS" - if subprocess.check_output(["file", "-b", FILE]).decode().strip().startswith("Mach-O 64-bit"): - IS64BIT = "64 bits" - FILE = os.path.join(MNTDIR, "System", "Library", "CoreServices", "SystemVersion.plist") - if os.path.exists(FILE): - with open(FILE, "r") as f: - plist_data = f.read() - product_name = re.search(r"ProductName\s*(.*?)", plist_data) - product_version = re.search(r"ProductVersion\s*(.*?)", plist_data) - if product_name and product_version: - VERSION = f"{product_name.group(1)} {product_version.group(1)}" - FILE = os.path.join(MNTDIR, "com.apple.recovery.boot") - if os.path.exists(FILE) and VERSION: - VERSION = f"{VERSION} recovery" - - # Para FreeBSD: obtener datos del Kernel. - if not VERSION: - TYPE = "BSD" - FILE = os.path.join(MNTDIR, "boot", "kernel", "kernel") - if os.path.exists(FILE): - output = subprocess.check_output(["strings", FILE]).decode().strip() - match = re.search(r"@.*RELEASE", output) - if match: - VERSION = match.group().split("@")[0].strip() - if subprocess.check_output(["file", "-b", FILE]).decode().strip().endswith("x86-64"): - IS64BIT = "64 bits" - - # Para Solaris: leer el fichero de versión. - if not VERSION: - TYPE = "Solaris" - FILE = os.path.join(MNTDIR, "etc", "release") - if os.path.exists(FILE): - with open(FILE, "r") as f: - VERSION = f.readline().strip() - - # Para cargador GRUB, comprobar fichero de configuración. - if not VERSION: - TYPE = "GrubLoader" - for FILE in [os.path.join(MNTDIR, "grub", "menu.lst"), os.path.join(MNTDIR, "boot", "grub", "menu.lst")]: - if os.path.exists(FILE): - VERSION = "GRUB Loader" - break - for FILE in glob.glob(os.path.join(MNTDIR, "{,boot/}{grub{,2},EFI/*}/grub.cfg")): - if os.path.exists(FILE): - VERSION = "GRUB2 Loader" - break - - # Mostrar resultado y salir sin errores. - if VERSION: - print(f"{TYPE}:{VERSION} {IS64BIT}") - - return 0 + return f"Linux: {version}" if version else "Linux: Unknown" + except Exception as e: + print(f"Fail to get OS: {e}") + return None \ No newline at end of file From 1898521ea873c02f7865a9140db02de6dfe8ba13 Mon Sep 17 00:00:00 2001 From: Antonio Emmanuel Guerrero Silva Date: Tue, 12 Nov 2024 23:36:50 -0600 Subject: [PATCH 048/167] refs #1093 rebuild ogGetOsType --- client/lib/engine/bin/InventoryLib.py | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/client/lib/engine/bin/InventoryLib.py b/client/lib/engine/bin/InventoryLib.py index 6744142..6c975b4 100755 --- a/client/lib/engine/bin/InventoryLib.py +++ b/client/lib/engine/bin/InventoryLib.py @@ -27,12 +27,16 @@ def ogGetArch(): else: print("i386") -def ogGetOsType(): - # Si se solicita, mostrar ayuda. - if len(sys.argv) > 1 and sys.argv[1] == "help": - SystemLib.ogHelp(sys.argv[0], sys.argv[0] + " int_ndisk int_npartition", sys.argv[0] + " 1 2 => Linux") - return - ogGetOsVersion(sys.argv[1:]).split(':')[0] +def ogGetOsType(disk, partition): + try: + os_version = ogGetOsVersion(disk, partition) + if os_version: + return os_version.split(":", 1)[0] + else: + return "Unknown" + except Exception as e: + print(f"Error en ogGetOsType: {e}") + return "Unknown" def ogGetOsUuid(): # Si se solicita, mostrar ayuda. From cd6f15d3b6d67c631d64df4ee0c15eec69b27165 Mon Sep 17 00:00:00 2001 From: Antonio Emmanuel Guerrero Silva Date: Tue, 12 Nov 2024 23:42:07 -0600 Subject: [PATCH 049/167] refs #1093 unneeded imported libraries are removed --- client/lib/engine/bin/InventoryLib.py | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/client/lib/engine/bin/InventoryLib.py b/client/lib/engine/bin/InventoryLib.py index 6c975b4..e18730f 100755 --- a/client/lib/engine/bin/InventoryLib.py +++ b/client/lib/engine/bin/InventoryLib.py @@ -1,4 +1,3 @@ -import glob import platform import sys import os @@ -7,13 +6,10 @@ import tempfile import re import json import shutil -import sqlite3 import SystemLib -import ogGlobals -import FileLib -import RegistryLib import FileSystemLib +import ogGlobals MSG_HARDWAREINVENTORY = "Inventario de hardware de la máquina" @@ -84,10 +80,6 @@ def ogGetSerialNumber(): def ogIsEfiActive(): return os.path.isdir("/sys/firmware/efi") -import subprocess -import os -import sys - def parse_lshw_output(): try: # Ejecutar lshw en formato JSON para un fácil procesamiento @@ -200,7 +192,6 @@ def ogListSoftware(disk, partition): return sorted(set(apps)) - def ogGetOsVersion(disk, part): try: mnt_dir = FileSystemLib.ogMount(disk, part) From 61fb90d0333f6c3ba67effe0407d47196dd29907 Mon Sep 17 00:00:00 2001 From: Antonio Emmanuel Guerrero Silva Date: Tue, 12 Nov 2024 23:59:30 -0600 Subject: [PATCH 050/167] refs #1093 the call to ogListSoftware is optimized --- client/shared/scripts/listSoftwareInfo.py | 51 +++++++++++++---------- 1 file changed, 28 insertions(+), 23 deletions(-) diff --git a/client/shared/scripts/listSoftwareInfo.py b/client/shared/scripts/listSoftwareInfo.py index 7f6ac76..3ad6cef 100755 --- a/client/shared/scripts/listSoftwareInfo.py +++ b/client/shared/scripts/listSoftwareInfo.py @@ -1,7 +1,7 @@ import os import sys -import subprocess sys.path.append('/opt/opengnsys/lib/engine/bin') + import SystemLib import InventoryLib import NetLib @@ -9,34 +9,39 @@ import ogGlobals PROG = os.path.basename(__file__) REDUCED = "no" + if len(sys.argv) > 1 and sys.argv[1] == "-r": REDUCED = "yes" sys.argv.pop(1) +# Validar argumentos if len(sys.argv) != 3: - SystemLib.ogRaiseError(ogGlobals.OG_ERR_FORMAT, f"{ogGlobals.MSG_FORMAT}: {PROG} ndisco nparticion") + SystemLib.ogRaiseError("session", ogGlobals.OG_ERR_FORMAT, f"{ogGlobals.MSG_FORMAT}: {PROG} ndisco nparticion") sys.exit(1) -# Directorio del servidor donde se exportan los ficheros de registro. -SERVERLOGDIR = subprocess.run( -["awk", "-v", f"d={ogGlobals.OGLOG}", 'BEGIN {FS="[: ]"} {if ($4==d) dir=$2} END {print dir}'], -capture_output=True, -text=True, -check=True, -).stdout.strip() - -# Fichero de listado: soft-IP-ndisco-npart +# Nombre del archivo de listado SOFTFILE = f"soft-{NetLib.ogGetIpAddress()}-{sys.argv[1]}-{sys.argv[2]}" -# Redirigir salida al fichero de listado. -if REDUCED == "no": - if subprocess.run(["ogListSoftware", sys.argv[1], sys.argv[2]], stdout=open(f"{ogGlobals.OGLOG}/{SOFTFILE}", "w")).returncode != 0: - sys.exit(1) - else: - if subprocess.run(["ogListSoftware", sys.argv[1], sys.argv[2]], stdout=subprocess.PIPE).returncode == 0: - with open(f"{ogGlobals.OGLOG}/{SOFTFILE}", "w") as f: - f.write(subprocess.run(["egrep", "-v", "\(KB[0-9]{6}\)"], input=subprocess.PIPE).stdout.decode()) - else: - sys.exit(1) +softfile_path = os.path.join(ogGlobals.OGLOG, SOFTFILE) -# Salid: camino del fichero de listado en el servidor de repositorio. -print(f"{ogGlobals.OGLOG}/{SOFTFILE}") +try: + # Generar listado de software con InventoryLib.ogListSoftware + software_list = InventoryLib.ogListSoftware(int(sys.argv[1]), int(sys.argv[2])) + + if REDUCED == "no": + # Escribir el listado completo al archivo + with open(softfile_path, "w") as f: + for line in software_list: + f.write(f"{line}\n") + else: + # Filtrar parches de Windows (KBxxxxxx) y guardar + filtered_list = [line for line in software_list if "(KB" not in line] + with open(softfile_path, "w") as f: + for line in filtered_list: + f.write(f"{line}\n") + + print(softfile_path) + +except Exception as e: + # Manejar errores + SystemLib.ogRaiseError("session", ogGlobals.OG_ERR_FORMAT, f"Error al generar el listado de software: {e}") + sys.exit(1) \ No newline at end of file From 381099dcc40bfeb8af793534f3ea368ebdab1df4 Mon Sep 17 00:00:00 2001 From: Antonio Emmanuel Guerrero Silva Date: Wed, 13 Nov 2024 00:01:32 -0600 Subject: [PATCH 051/167] refs #1093 the call to ogListSoftware is optimized --- client/shared/scripts/listSoftwareInfo.py | 6 ------ 1 file changed, 6 deletions(-) diff --git a/client/shared/scripts/listSoftwareInfo.py b/client/shared/scripts/listSoftwareInfo.py index 3ad6cef..84f94ae 100755 --- a/client/shared/scripts/listSoftwareInfo.py +++ b/client/shared/scripts/listSoftwareInfo.py @@ -14,26 +14,21 @@ if len(sys.argv) > 1 and sys.argv[1] == "-r": REDUCED = "yes" sys.argv.pop(1) -# Validar argumentos if len(sys.argv) != 3: SystemLib.ogRaiseError("session", ogGlobals.OG_ERR_FORMAT, f"{ogGlobals.MSG_FORMAT}: {PROG} ndisco nparticion") sys.exit(1) -# Nombre del archivo de listado SOFTFILE = f"soft-{NetLib.ogGetIpAddress()}-{sys.argv[1]}-{sys.argv[2]}" softfile_path = os.path.join(ogGlobals.OGLOG, SOFTFILE) try: - # Generar listado de software con InventoryLib.ogListSoftware software_list = InventoryLib.ogListSoftware(int(sys.argv[1]), int(sys.argv[2])) if REDUCED == "no": - # Escribir el listado completo al archivo with open(softfile_path, "w") as f: for line in software_list: f.write(f"{line}\n") else: - # Filtrar parches de Windows (KBxxxxxx) y guardar filtered_list = [line for line in software_list if "(KB" not in line] with open(softfile_path, "w") as f: for line in filtered_list: @@ -42,6 +37,5 @@ try: print(softfile_path) except Exception as e: - # Manejar errores SystemLib.ogRaiseError("session", ogGlobals.OG_ERR_FORMAT, f"Error al generar el listado de software: {e}") sys.exit(1) \ No newline at end of file From c066725bce901b5b8eac4e83f7cae5aca39fc38d Mon Sep 17 00:00:00 2001 From: Antonio Emmanuel Guerrero Silva Date: Wed, 13 Nov 2024 00:05:54 -0600 Subject: [PATCH 052/167] refs #1093 Script InventarioSoftware is optimized --- client/interfaceAdm/InventarioSoftware.py | 25 ++++++++--------------- 1 file changed, 9 insertions(+), 16 deletions(-) diff --git a/client/interfaceAdm/InventarioSoftware.py b/client/interfaceAdm/InventarioSoftware.py index 7812388..37d729e 100755 --- a/client/interfaceAdm/InventarioSoftware.py +++ b/client/interfaceAdm/InventarioSoftware.py @@ -4,18 +4,14 @@ import shutil import subprocess import sys +sys.path.append('/opt/opengnsys/lib/engine/bin') +import ogGlobals + def main(arg1, arg2, dest_file): start_time = time.time() - # Cargar la configuración del motor desde el archivo engine.cfg - og_engine_configurate = os.getenv('OGENGINECONFIGURATE') - if not og_engine_configurate: - with open('/opt/opengnsys/etc/engine.cfg') as f: - exec(f.read()) - - # Limpiar los archivos temporales usados como log para httpdlog - og_log_session = os.getenv('OGLOGSESSION') - og_log_command = os.getenv('OGLOGCOMMAND') + og_log_session = os.getenv(ogGlobals.OGLOGSESSION) + og_log_command = os.getenv(ogGlobals.OGLOGCOMMAND) if og_log_session and og_log_command: with open(og_log_session, 'w') as f: f.write(" ") @@ -24,12 +20,10 @@ def main(arg1, arg2, dest_file): with open(f"{og_log_command}.tmp", 'w') as f: f.write(" ") - # Registrar el inicio de ejecución - msg_interface_start = os.getenv('MSG_INTERFACE_START') + msg_interface_start = os.getenv(ogGlobals.MSG_INTERFACE_START) if msg_interface_start: subprocess.run(['ogEcho', 'log', 'session', f"{msg_interface_start} {__file__} {arg1} {arg2}"]) - # Ejecutar el script listSoftwareInfo y capturar el archivo de salida try: result = subprocess.run( ["python3", "/opt/opengnsys/scripts/listSoftwareInfo.py", arg1, arg2], @@ -37,15 +31,14 @@ def main(arg1, arg2, dest_file): text=True, check=True ) - file = result.stdout.strip() # Captura la salida del script + file = result.stdout.strip().splitlines()[-1] except subprocess.CalledProcessError as e: print(f"Error al ejecutar listSoftwareInfo: {e.stderr}") sys.exit(e.returncode) - # Copiar el archivo resultante a dest_file + print(f"Copying:( {file} to {dest_file} )") shutil.copy(file, dest_file) - # Registrar el tiempo de ejecución elapsed_time = time.time() - start_time msg_scripts_time_partial = os.getenv('MSG_SCRIPTS_TIME_PARTIAL') if msg_scripts_time_partial: @@ -55,4 +48,4 @@ 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]) + main(sys.argv[1], sys.argv[2], sys.argv[3]) \ No newline at end of file From 3058a3798fbcbcee91640ad51c1261fb65f6e389 Mon Sep 17 00:00:00 2001 From: Antonio Emmanuel Guerrero Silva Date: Wed, 13 Nov 2024 00:18:17 -0600 Subject: [PATCH 053/167] refs #1093 rebuild ogGetServerIp --- client/lib/engine/bin/NetLib.py | 49 +++++++++++++++++++-------------- 1 file changed, 29 insertions(+), 20 deletions(-) diff --git a/client/lib/engine/bin/NetLib.py b/client/lib/engine/bin/NetLib.py index 197eaaf..2bdbc08 100755 --- a/client/lib/engine/bin/NetLib.py +++ b/client/lib/engine/bin/NetLib.py @@ -263,30 +263,39 @@ def ogGetRepoIp(): #@note Comprobacion segun protocolo de conexion al Repo #*/ ## def ogGetServerIp(): - # Variables locales. - SOURCE = "" - FSTYPE = "" + try: + output = subprocess.run( + ["findmnt", "--json", "--output", "SOURCE,FSTYPE", ogGlobals.OGIMG], + capture_output=True, + text=True, + check=True + ).stdout + except subprocess.CalledProcessError as e: + SystemLib.ogEcho("session", "error", f"Error to run findmnt: {e.stderr}") + return None - # Mostrar ayuda. - if len(sys.argv) >= 2 and sys.argv[1] == "help": - SystemLib.ogHelp("ogGetServerIp", "ogGetServerIp", "ogGetServerIp => 192.168.0.2") - return + try: + mounts = json.loads(output) + except json.decoder.JSONDecodeError: + SystemLib.ogEcho("session", "error", "Error to decode JSON de findmnt.") + return None - # Obtener direcciones IP, según el tipo de montaje. - output = subprocess.run(["findmnt", "-P", "-o", "SOURCE,FSTYPE", OGIMG], stdout=subprocess.PIPE, stderr=subprocess.DEVNULL).stdout.decode().strip() - lines = output.split("\n") - for line in lines: - fields = line.split() - if len(fields) == 2: - if fields[1] == "nfs": - SOURCE = fields[0].split(":")[0] - elif fields[1] == "cifs": - SOURCE = fields[0].split("/")[2] + if 'filesystems' not in mounts or not isinstance(mounts['filesystems'], list): + SystemLib.ogEcho("session", "error", "'filesystems' is not present o not valid in JSON.") + return None - if SOURCE: - print(SOURCE) + for fs in mounts['filesystems']: + if 'source' in fs and 'fstype' in fs: + source = fs['source'] + fstype = fs['fstype'] - return 0 + if fstype == "nfs": + return source.split(":")[0] + elif fstype == "cifs": + return source.split("/")[2] + + SystemLib.ogEcho("session", "info", "No valid file system found") + return None #/** From 646090da3c568156caa84d070a2c71aa3f1c7e62 Mon Sep 17 00:00:00 2001 From: Antonio Emmanuel Guerrero Silva Date: Wed, 13 Nov 2024 00:19:04 -0600 Subject: [PATCH 054/167] refs #1093 rebuild ogGetMacAddress --- client/lib/engine/bin/NetLib.py | 52 ++++++++++++++++++++++----------- 1 file changed, 35 insertions(+), 17 deletions(-) diff --git a/client/lib/engine/bin/NetLib.py b/client/lib/engine/bin/NetLib.py index 2bdbc08..32e9e5e 100755 --- a/client/lib/engine/bin/NetLib.py +++ b/client/lib/engine/bin/NetLib.py @@ -196,26 +196,44 @@ def ogGetIpAddress(): #@return str_ether - Dirección Ethernet #*/ ## def ogGetMacAddress(): - MAC = "" + try: + if "DEVICE" in os.environ: + device = os.environ["DEVICE"] + result = subprocess.run( + ["ip", "-o", "link", "show", "up", "dev", device], + capture_output=True, + text=True, + check=True + ).stdout + else: + result = subprocess.run( + ["ip", "-o", "link", "show", "up"], + capture_output=True, + text=True, + check=True + ).stdout - if len(sys.argv) >= 2 and sys.argv[1] == "help": - SystemLib.ogHelp("ogGetMacAddress", "ogGetMacAddress", "ogGetMacAddress => 00:11:22:33:44:55") - return + mac_addresses = [] + for line in result.splitlines(): + if "link/ether" in line: + parts = line.split() + for i, part in enumerate(parts): + if part == "link/ether": + mac_addresses.append(parts[i + 1].upper()) - # Obtener direcciones Ethernet. - if "DEVICE" in os.environ: - MAC = subprocess.run(["ip", "-o", "link", "show", "up", "dev", os.environ["DEVICE"]], stdout=subprocess.PIPE, stderr=subprocess.DEVNULL).stdout.decode().split() - MAC = [addr.upper() for addr in MAC if "ether" in addr] - else: - MAC = subprocess.run(["ip", "-o", "link", "show", "up"], stdout=subprocess.PIPE, stderr=subprocess.DEVNULL).stdout.decode().split() - MAC = [addr.upper() for addr in MAC if "ether" in addr and "lo" not in addr] - - # Mostrar solo la primera. - if MAC: - print(MAC[0]) - - return 0 + if mac_addresses: + print(mac_addresses[0]) + return mac_addresses[0] + else: + print("No active mac address found") + return None + except subprocess.CalledProcessError as e: + print(f"Error executing ip command: {e.stderr}") + return None + except Exception as e: + print(f"Unexpected error: {str(e)}") + return None #/** # ogGetNetInterface From 1e5a2b79f7b46d77edeccba3fd64229bd0a61366 Mon Sep 17 00:00:00 2001 From: Natalia Serrano Date: Wed, 13 Nov 2024 10:04:41 +0100 Subject: [PATCH 055/167] refs #1101 add ogUcastSendPartition() --- client/lib/engine/bin/ProtocolLib.py | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/client/lib/engine/bin/ProtocolLib.py b/client/lib/engine/bin/ProtocolLib.py index b12de50..85e536c 100644 --- a/client/lib/engine/bin/ProtocolLib.py +++ b/client/lib/engine/bin/ProtocolLib.py @@ -74,10 +74,10 @@ def ogUcastSyntax (op, sess, file=None, device=None, tool=None, level=None): SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_FORMAT, f'McastSession portbase {portbase}') ## || PERROR=3 return - if 'SERVER' == mode: + if 'server' == mode: address = '' for i in range (1, len (session)): - address += f'-O {session[i]}:{portbase}' + address += f' -O {session[i]}:{portbase}' else: address = f'{session[1]}:{portbase}' #print (f'nati mode ({mode}) address ({address})') @@ -121,6 +121,22 @@ def ogUcastSyntax (op, sess, file=None, device=None, tool=None, level=None): #@todo: ogIsLocked siempre devuelve 1 #*/ ## +def ogUcastSendPartition (disk, par, sess, tool, level): + PART = DiskLib.ogDiskToDev (disk, par) + if not PART: return None + + FileSystemLib.ogUnmount (disk, par) + + cmd = ogUcastSyntax ('SENDPARTITION', sess, device=PART, tool=tool, level=level) + if not cmd: return None + print (f'cmd ({cmd})') + try: + subprocess.run (cmd, shell=True, check=True) + except subprocess.CalledProcessError: + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_UCASTSENDPARTITION, ' ') + return None + + #/** # ogUcastReceiverPartition From d75e8a56fa43baf832f2c44b637c378ffa7971bd Mon Sep 17 00:00:00 2001 From: Natalia Serrano Date: Wed, 13 Nov 2024 11:02:29 +0100 Subject: [PATCH 056/167] refs #1101 add ogUcastReceiverPartition() --- client/lib/engine/bin/ProtocolLib.py | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/client/lib/engine/bin/ProtocolLib.py b/client/lib/engine/bin/ProtocolLib.py index 85e536c..352c7b1 100644 --- a/client/lib/engine/bin/ProtocolLib.py +++ b/client/lib/engine/bin/ProtocolLib.py @@ -144,12 +144,29 @@ def ogUcastSendPartition (disk, par, sess, tool, level): #@param 1 disk #@param 2 partition #@param 3 session unicast +#@param 4 tool image +#@param 5 tool compresor #@return #@exception OG_ERR_FORMAT #@exception OG_ERR_UCASTRECEIVERPARTITION #@note #@todo: #*/ ## +def ogUcastReceiverPartition (disk, par, sess, tool, level): + PART = DiskLib.ogDiskToDev (disk, par) + if not PART: return None + + FileSystemLib.ogUnmount (disk, par) + + cmd = ogUcastSyntax ('RECEIVERPARTITION', sess, device=PART, tool=tool, level=level) + if not cmd: return None + print (f'cmd ({cmd})') + try: + subprocess.run (cmd, shell=True, check=True) + except subprocess.CalledProcessError: + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_UCASTRECEIVERPARTITION, ' ') + return None + #/** From 40f31f784ca282629fad01691fe6f294ef582530 Mon Sep 17 00:00:00 2001 From: Natalia Serrano Date: Wed, 13 Nov 2024 11:18:28 +0100 Subject: [PATCH 057/167] refs #1101 add ogUcastSendFile() --- client/lib/engine/bin/ProtocolLib.py | 55 ++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) diff --git a/client/lib/engine/bin/ProtocolLib.py b/client/lib/engine/bin/ProtocolLib.py index 352c7b1..2179956 100644 --- a/client/lib/engine/bin/ProtocolLib.py +++ b/client/lib/engine/bin/ProtocolLib.py @@ -183,6 +183,61 @@ def ogUcastReceiverPartition (disk, par, sess, tool, level): #*/ ## # +## TODO esta función es idéntica a ogMcastSendFile pero con s/Ucast/Mcast/; + +#ogUcastSendFile ([str_REPOSITORY] [int_ndisk int_npart] /Relative_path_file sesionMcast(puerto:ip:ip:ip)" \ +#ogUcastSendFile (disk=1, par=1, file='/aula1/winxp.img', sess='8000:172.17.36.11:172.17.36.12') +#ogUcastSendFile (take_from='REPO', file='/aula1/ubuntu.iso', sess='sesionUcast') +#ogUcastSendFile (take_from='CACHE', file='/aula1/winxp.img', sess='sesionUcast') +#ogUcastSendFile ( file='/opt/opengnsys/images/aula1/hd500.vmx', sess='sesionUcast') +def ogUcastSendFile (disk=None, par=None, take_from=None, file=None, sess=None): + if file is None: + raise TypeError ('missing required argument: "file"') + if sess is None: + raise TypeError ('missing required argument: "sess"') + + if take_from is not None: + if disk is None and par is None: + ## we were given take_from= + source = FileLib.ogGetPath (src=take_from, file=file) + dev_err = f'{take_from} {file}' + print (f'ogGetPath (src=({take_from}), file=({file})) = source ({source})') + else: + raise TypeError ('argument "take_from" can be specified along neither "disk" nor "par"') + + else: + if disk is not None and par is not None: + ## we were given disk= par= + source = FileLib.ogGetPath (src=f'{disk} {par}', file=file) + dev_err = f'{disk} {par} {file}' + print (f'ogGetPath (src=({disk} {par}), file=({file})) = source ({source})') + elif disk is None and par is None: + ## we were given nothing + source = FileLib.ogGetPath (file=file) + dev_err = file + print (f'ogGetPath (file=({file})) = source ({source})') + else: + raise TypeError ('if one of "disk" and "par" are specified, then both must be') + + if not source: + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTFOUND, f'device or file {dev_err} not found') + return + + path2 = FileLib.ogGetPath (file=source) + print (f'path2 ({path2})') + if not path2: + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTFOUND, f'device or file {dev_err} not found') + return + + cmd = ogUcastSyntax ('SENDFILE', sess, file=source) + if not cmd: return None + print (f'cmd ({cmd})') + try: + subprocess.run (cmd, shell=True, check=True) + except subprocess.CalledProcessError: + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_UCASTSENDFILE, ' ') + return None + def _clientip(): ipas = subprocess.run (['ip', '-json', 'address', 'show', 'up'], capture_output=True, text=True).stdout ipasj = json.loads (ipas) From 29f91cc00f166b4606de972db2c0dc1548708371 Mon Sep 17 00:00:00 2001 From: Natalia Serrano Date: Wed, 13 Nov 2024 17:08:36 +0100 Subject: [PATCH 058/167] refs #1101 add ogCreateTorrent() --- client/lib/engine/bin/ImageLib.py | 268 +++++++++++++++++++++++++++ client/lib/engine/bin/ProtocolLib.py | 62 ++++++- 2 files changed, 329 insertions(+), 1 deletion(-) diff --git a/client/lib/engine/bin/ImageLib.py b/client/lib/engine/bin/ImageLib.py index aa27350..348b32c 100644 --- a/client/lib/engine/bin/ImageLib.py +++ b/client/lib/engine/bin/ImageLib.py @@ -11,6 +11,7 @@ import DiskLib import FileSystemLib import SystemLib import ogGlobals +import FileLib ## ProtocolLib.ogUcastSyntax() calls ogCreateImageSyntax() ## in ogCreateImageSyntax(), param2 may contain a pipe or may be empty @@ -174,6 +175,185 @@ def ogRestoreImageSyntax (imgfile, part, tool=None, level=None): return f'{compressor} {imgfile} {mbuffer} {tool}'.strip() + + +#/** +# ogCreateDiskImage int_ndisk str_repo path_image [str_tools] [str_compressionlevel] +#@brief Crea una imagen (copia de seguridad) de un disco completo. +#@param int_ndisk nº de orden del disco +#@param str_repo repositorio de imágenes (remoto o caché local) +#@param path_image camino de la imagen (sin extensión) +#@return (nada, por determinar) +#@note repo = { REPO, CACHE } +#@note Esta primera versión crea imágenes con dd comprimidas con gzip. +#@exception OG_ERR_FORMAT formato incorrecto. +#@exception OG_ERR_NOTFOUND fichero o dispositivo no encontrado. +#@exception OG_ERR_LOCKED particion bloqueada por otra operación. +#@exception OG_ERR_IMAGE error al crear la imagen del sistema. +#@warning En pruebas iniciales +#@todo Gestión de bloqueos de disco +#@todo Comprobar si debe desmontarse la caché local +#@todo Comprobar que no se crea la imagen en el propio disco +#*/ ## + + +#/** +# ogCreateImage int_ndisk int_npartition str_repo path_image [str_tools] [str_compressionlevel] +#@brief Crea una imagen a partir de una partición. +#@param int_ndisk nº de orden del disco +#@param int_npartition nº de orden de la partición +#@param str_repo repositorio de imágenes (remoto o caché local) +#@param path_image camino de la imagen (sin extensión) +#@param [opcional] str_tools herrmaienta de clonacion [partimage, partclone, ntfsclone] +#@param [opcional] str_compressionlevel nivel de compresion. [0 -none-, 1-lzop-, 2-gzip] +#@return (nada, por determinar) +#@note repo = { REPO, CACHE } +#@exception OG_ERR_FORMAT formato incorrecto. +#@exception OG_ERR_NOTFOUND fichero o dispositivo no encontrado. +#@exception OG_ERR_PARTITION partición no accesible o no soportada. +#@exception OG_ERR_LOCKED particion bloqueada por otra operación. +#@exception OG_ERR_IMAGE error al crear la imagen del sistema. +#@todo Comprobaciones, control de errores, definir parámetros, etc. +#*/ ## + + +#/** +# ogCreateMbrImage int_ndisk str_repo path_image +#@brief Crea una imagen a partir del sector de arranque de un disco. +#@param int_ndisk nº de orden del disco +#@param str_repo repositorio de imágenes (remoto o caché local) +#@param path_image camino de la imagen (sin extensión) +#@return (nada, por determinar) +#@note repo = { REPO, CACHE } +#@exception OG_ERR_FORMAT formato incorrecto. +#@exception OG_ERR_NOTFOUND fichero o dispositivo no encontrado. +#@exception OG_ERR_IMAGE error al crear la imagen del sistema. +#*/ ## + + +#/** +# ogCreateBootLoaderImage int_ndisk str_repo path_image +#@brief Crea una imagen del boot loader a partir del sector de arranque de un disco. +#@param int_ndisk nº de orden del disco +#@param str_repo repositorio de imágenes (remoto o caché local) +#@param path_image camino de la imagen (sin extensión) +#@return (nada, por determinar) +#@note repo = { REPO, CACHE } +#@exception OG_ERR_FORMAT formato incorrecto. +#@exception OG_ERR_NOTFOUND fichero o dispositivo no encontrado. +#@exception OG_ERR_IMAGE error al crear la imagen del sistema. +#*/ ## + +#/** +# ogGetSizeParameters int_num_disk int_num_part str_repo [monolit|sync|diff] +#@brief Devuelve el tamaño de los datos de un sistema de ficheros, el espacio necesario para la imagen y si cabe en el repositorio elegido. +#@param int_disk numero de disco +#@param int_part numero de particion +#@param str_repo repositorio de imágenes { REPO, CACHE } +#@param str_imageName Nombre de la imagen +#@param str_imageType Tipo de imagen: monolit (por defecto), sync o diff. (parametro opcional) +#@return SIZEDATA SIZEREQUIRED SIZEFREE ISENOUGHSPACE +#@note si str_imageType= diff necesario /tmp/ogimg.info, que es creado por ogCreateInfoImage. +#@note para el tamaño de la imagen no sigue enlaces simbólicos. +#@exception OG_ERR_FORMAT formato incorrecto. +#*/ ## + +#/** +# ogIsImageLocked [str_repo] path_image +#@brief Comprueba si una imagen está bloqueada para uso exclusivo. +#@param str_repo repositorio de imágenes (opcional) +#@param path_image camino de la imagen (sin extensión) +#@return Código de salida: 0 - bloqueado, 1 - sin bloquear o error. +#@note repo = { REPO, CACHE } +#@exception OG_ERR_FORMAT formato incorrecto. +#*/ ## + + +#/** +# ogLockImage [str_repo] path_image +#@brief Bloquea una imagen para uso exclusivo. +#@param str_repo repositorio de imágenes (opcional) +#@param path_image camino de la imagen (sin extensión) +#@return Nada. +#@note Se genera un fichero con extensión .lock +#@note repo = { REPO, CACHE } +#@exception OG_ERR_FORMAT formato incorrecto. +#*/ ## + + +#/** +# ogRestoreDiskImage str_repo path_image int_npartition +#@brief Restaura (recupera) una imagen de un disco completo. +#@param str_repo repositorio de imágenes o caché local +#@param path_image camino de la imagen +#@param int_ndisk nº de orden del disco +#@return (por determinar) +#@warning Primera versión en pruebas +#@todo Gestionar bloqueos de disco +#@todo Comprobar que no se intenta restaurar de la caché sobre el mismo disco +#@exception OG_ERR_FORMAT formato incorrecto. +#@exception OG_ERR_NOTFOUND fichero de imagen o partición no detectados. +#@exception OG_ERR_LOCKED partición bloqueada por otra operación. +#@exception OG_ERR_IMAGE error al restaurar la imagen del sistema. +#@exception OG_ERR_IMGSIZEPARTITION Tamaño de la particion es menor al tamaño de la imagen. +#*/ ## + + +#/** +# ogRestoreImage str_repo path_image int_ndisk int_npartition +#@brief Restaura una imagen de sistema de archivos en una partición. +#@param str_repo repositorio de imágenes o caché local +#@param path_image camino de la imagen +#@param int_ndisk nº de orden del disco +#@param int_npartition nº de orden de la partición +#@return (por determinar) +#@exception OG_ERR_FORMAT 1 formato incorrecto. +#@exception OG_ERR_NOTFOUND 2 fichero de imagen o partición no detectados. +#@exception OG_ERR_PARTITION 3 # Error en partición de disco. +#@exception OG_ERR_LOCKED 4 partición bloqueada por otra operación. +#@exception OG_ERR_IMAGE 5 error al restaurar la imagen del sistema. +#@exception OG_ERR_IMGSIZEPARTITION 30 Tamaño de la particion es menor al tamaño de la imagen. +#@todo Comprobar incongruencias partición-imagen, control de errores, definir parámetros, caché/repositorio, etc. +#*/ ## + + +#/** +# ogRestoreMbrImage str_repo path_image int_ndisk +#@brief Restaura la imagen del sector de arranque de un disco. +#@param str_repo repositorio de imágenes o caché local +#@param path_image camino de la imagen +#@param int_ndisk nº de orden del disco +#@return (por determinar) +#@exception OG_ERR_FORMAT formato incorrecto. +#@exception OG_ERR_NOTFOUND fichero de imagen o partición no detectados. +#@exception OG_ERR_IMAGE error al restaurar la imagen del sistema. +#*/ ## + + +#/** +# ogRestoreBootLoaderImage str_repo path_image int_ndisk +#@brief Restaura la imagen del boot loader del sector de arranque de un disco. +#@param str_repo repositorio de imágenes o caché local +#@param path_image camino de la imagen +#@param int_ndisk nº de orden del disco +#@return (por determinar) +#@exception OG_ERR_FORMAT formato incorrecto. +#@exception OG_ERR_NOTFOUND fichero de imagen o partición no detectados. +#@exception OG_ERR_IMAGE error al restaurar la imagen del sistema. +#*/ ## + +#/** +# ogUnlockImage [str_repo] path_image +#@brief Desbloquea una imagen con uso exclusivo. +#@param str_repo repositorio de imágenes (opcional) +#@param path_image camino de la imagen (sin extensión) +#@return Nada. +#@note repo = { REPO, CACHE } +#@note Se elimina el fichero de bloqueo con extensión .lock +#@exception OG_ERR_FORMAT formato incorrecto. +#*/ ## + + #/** # ogGetImageInfo filename #@brief muestra información sobre la imagen monolitica. @@ -323,3 +503,91 @@ def ogGetImageInfo (imgfile): compressor = compressor.upper() return ':'.join ([tools, compressor, fs, str (size)]) + +#/** +# ogGetImageProgram str_REPO str_imagen +#@brief muestra información sobre la imagen monolitica. +#@see ogGetImageInfo +#@param 1 REPO o CACHE contenedor de la imagen +#@param 2 filename nombre de la imagen sin extension +#@return nombre del programa usado para generar la imagen +#@exception OG_ERR_FORMAT formato incorrecto. +#@exception OG_ERR_NOTFOUND fichero no encontrado. +#@note ogGetImageProgram REPO imagenA -> partclone +#*/ ## + + +#/** +# ogGetImageCompressor str_REPO str_imagen +#@brief muestra información sobre la imagen monolitica. +#@see ogGetImageInfo +#@param 1 REPO o CACHE contenedor de la imagen +#@param 2 filename nombre de la imagen sin extension +#@return tipo de compresión usada al generar la imagen +#@exception OG_ERR_FORMAT formato incorrecto. +#@exception OG_ERR_NOTFOUND fichero no encontrado. +#@note ogGetImageCompressor REPO imagenA -> lzop +#*/ ## + + +#/** +# ogGetImageType str_REPO str_imagen +#@brief muestra información sobre el sistema de archivos de imagen monolitica. +#@see ogGetImageInfo +#@param 1 REPO o CACHE contenedor de la imagen +#@param 2 filename nombre de la imagen sin extension +#@return tipo de compresión usada al generar la imagen +#@exception OG_ERR_FORMAT formato incorrecto. +#@exception OG_ERR_NOTFOUND fichero no encontrado. +#@note ogGetImageType REPO imagenA -> NTFS +#*/ ## +#ogGetImageType ('REPO', 'imgprueba') ==> 'NTFS' +#ogGetImageType ('CACHE', 'testimg') ==> 'EXTFS' +def ogGetImageType (repo, imgname): + imgfile = FileLib.ogGetPath (src=repo, file=imgname) + if not os.path.exists (imgfile): + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTFOUND, imgfile) + return None + + i = ogGetImageInfo (imgfile) + return i.split (':')[2] + + + +#/** +# ogGetImageSize str_REPO str_imagen +#@brief muestra información sobre el tamaño (KB) del sistema de archivos de imagen monolitica. +#@see ogGetImageInfo +#@param 1 REPO o CACHE contenedor de la imagen +#@param 2 filename nombre de la imagen sin extension +#@return tipo de compresión usada al generar la imagen +#@exception OG_ERR_FORMAT formato incorrecto. +#@exception OG_ERR_NOTFOUND fichero no encontrado. +#@note ogGetImagesize REPO imagenA -> 56432234 > Kb +#*/ ## + + +#/** +# ogCreateGptImage int_ndisk str_repo path_image +#@brief Crea una imagen de la tabla de particiones GPT de un disco. +#@param int_ndisk nº de orden del disco +#@param str_repo repositorio de imágenes (remoto o caché local) +#@param path_image camino de la imagen (sin extensión) +#@return (nada, por determinar) +#@note repo = { REPO, CACHE } +#@exception OG_ERR_FORMAT formato incorrecto. +#@exception OG_ERR_NOTFOUND fichero o dispositivo no encontrado. +#@exception OG_ERR_IMAGE error al crear la imagen del sistema. +#*/ ## + +#/** +# ogRestoreGptImage str_repo path_image int_ndisk +#@brief Restaura la imagen de la tabla de particiones GPT de un disco. +#@param str_repo repositorio de imágenes o caché local +#@param path_image camino de la imagen +#@param int_ndisk nº de orden del disco +#@return (por determinar) +#@exception OG_ERR_FORMAT formato incorrecto. +#@exception OG_ERR_NOTFOUND fichero de imagen o partición no detectados. +#@exception OG_ERR_IMAGE error al restaurar la imagen del sistema. +#*/ ## diff --git a/client/lib/engine/bin/ProtocolLib.py b/client/lib/engine/bin/ProtocolLib.py index 2179956..f51c6d6 100644 --- a/client/lib/engine/bin/ProtocolLib.py +++ b/client/lib/engine/bin/ProtocolLib.py @@ -13,6 +13,7 @@ import StringLib import NetLib import DiskLib import FileLib +import CacheLib #/** #@file ProtocolLib.py @@ -324,7 +325,7 @@ def ogMcastSyntax (op, sess, file=None, device=None, tool=None, level=None): SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_FORMAT, 'parametros session de cliente multicast no completa') PERROR = 2 - mbuffer = " --pipe 'mbuffer -q -m 20M' " + mbuffer = " --pipe 'mbuffer -q -m 20M' " portbase = int (session[0]) if portbase not in range (9000, 9100, 2): SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_FORMAT, f'McastSession portbase {portbase}') @@ -671,6 +672,65 @@ def ogMcastRequest (img, proto): #@exception OG_ERR_NOTOS La partición no tiene instalado un sistema operativo. #*/ ## +#ogCreateTorrent ([str_REPOSITORY] [int_ndisk int_npart] Relative_path_file IpBttrack) +#ogCreateTorrent (disk=1, par=1, file='/aula1/winxp', ip_bttrack='10.1.15.23') +#ogCreateTorrent (take_from='REPO', file='/aula1/winxp', ip_bttrack='10.1.15.45') +#ogCreateTorrent (take_from='CACHE', file='/aula1/winxp', ip_bttrack='10.1.15.45') +def ogCreateTorrent (disk=None, par=None, take_from=None, file=None, ip_bttrack=None): + if file is None: + raise TypeError ('missing required argument: "file"') + if ip_bttrack is None: + raise TypeError ('missing required argument: "ip_bttrack"') + + from_cache = False + + if take_from is not None: + if disk is None and par is None: + ## we were given take_from= + if 'CACHE' == take_from: from_cache = True + ext = ImageLib.ogGetImageType (take_from, file) + if ext is None: + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTFOUND, f'{take_from} {file}') + return + f = f'{file}.{ext}' + source = FileLib.ogGetPath (src=take_from, file=f) + print (f'ogGetPath (src=({take_from}), file=({f})) = source ({source})') + else: + raise TypeError ('argument "take_from" can be specified along neither "disk" nor "par"') + + else: + if disk is not None and par is not None: + ## we were given disk= par= + f = f'{file}.img' + source = FileLib.ogGetPath (src=f'{disk} {par}', file=f) + print (f'ogGetPath (src=({disk} {par}), file=({f})) = source ({source})') + elif disk is None and par is None: + ## we were given nothing + f = f'{file}.img' + source = FileLib.ogGetPath (file=f) + print (f'ogGetPath (file=({f})) = source ({source})') + else: + raise TypeError ('if one of "disk" and "par" are specified, then both must be') + + if not source: + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTFOUND, '') + return + + if from_cache: + if not CacheLib.ogFindCache(): + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTFOUND, "CACHE") + #return None + + if os.path.exists (f'{source}.torrent'): + os.rename (f'{source}.torrent', f'{source}.torrent.ant') + print ('Esperamos que se refresque el servidor') + time.sleep (20) + + cwd = os.getcwd() + os.chdir (os.path.dirname (source)) + print (f'ctorrent -t {os.path.basename (source)} -u http://{ip_bttrack}:6969/announce -s {source}.torrent') + subprocess.run (['ctorrent', '-t', os.path.basename (source), '-u', f'http://{ip_bttrack}:6969/announce', '-s', f'{source}.torrent']) + os.chdir (cwd) #/** From a19e01b078930c6815dea75e101de06499f24567 Mon Sep 17 00:00:00 2001 From: Natalia Serrano Date: Wed, 13 Nov 2024 17:18:53 +0100 Subject: [PATCH 059/167] refs #1101 change "take_from"/"write_to" into "container" --- client/lib/engine/bin/ProtocolLib.py | 78 ++++++++++++++-------------- 1 file changed, 39 insertions(+), 39 deletions(-) diff --git a/client/lib/engine/bin/ProtocolLib.py b/client/lib/engine/bin/ProtocolLib.py index f51c6d6..4fa50b5 100644 --- a/client/lib/engine/bin/ProtocolLib.py +++ b/client/lib/engine/bin/ProtocolLib.py @@ -188,23 +188,23 @@ def ogUcastReceiverPartition (disk, par, sess, tool, level): #ogUcastSendFile ([str_REPOSITORY] [int_ndisk int_npart] /Relative_path_file sesionMcast(puerto:ip:ip:ip)" \ #ogUcastSendFile (disk=1, par=1, file='/aula1/winxp.img', sess='8000:172.17.36.11:172.17.36.12') -#ogUcastSendFile (take_from='REPO', file='/aula1/ubuntu.iso', sess='sesionUcast') -#ogUcastSendFile (take_from='CACHE', file='/aula1/winxp.img', sess='sesionUcast') +#ogUcastSendFile (container='REPO', file='/aula1/ubuntu.iso', sess='sesionUcast') +#ogUcastSendFile (container='CACHE', file='/aula1/winxp.img', sess='sesionUcast') #ogUcastSendFile ( file='/opt/opengnsys/images/aula1/hd500.vmx', sess='sesionUcast') -def ogUcastSendFile (disk=None, par=None, take_from=None, file=None, sess=None): +def ogUcastSendFile (disk=None, par=None, container=None, file=None, sess=None): if file is None: raise TypeError ('missing required argument: "file"') if sess is None: raise TypeError ('missing required argument: "sess"') - if take_from is not None: + if container is not None: if disk is None and par is None: - ## we were given take_from= - source = FileLib.ogGetPath (src=take_from, file=file) - dev_err = f'{take_from} {file}' - print (f'ogGetPath (src=({take_from}), file=({file})) = source ({source})') + ## we were given container= + source = FileLib.ogGetPath (src=container, file=file) + dev_err = f'{container} {file}' + print (f'ogGetPath (src=({container}), file=({file})) = source ({source})') else: - raise TypeError ('argument "take_from" can be specified along neither "disk" nor "par"') + raise TypeError ('argument "container" can be specified along neither "disk" nor "par"') else: if disk is not None and par is not None: @@ -459,23 +459,23 @@ def ogMcastSyntax (op, sess, file=None, device=None, tool=None, level=None): #ogMcastSendFile [str_REPOSITORY] [int_ndisk int_npart] /Relative_path_file sesionMcast" \ #ogMcastSendFile (disk=1, par=1, file='/aula1/winxp.img', sess='sesionMcast') -#ogMcastSendFile (take_from='REPO', file='/aula1/ubuntu.iso', sess='sesionMcast') -#ogMcastSendFile (take_from='CACHE', file='/aula1/winxp.img', sess='sesionMcast') +#ogMcastSendFile (container='REPO', file='/aula1/ubuntu.iso', sess='sesionMcast') +#ogMcastSendFile (container='CACHE', file='/aula1/winxp.img', sess='sesionMcast') #ogMcastSendFile ( file='/opt/opengnsys/images/aula1/hd500.vmx', sess='sesionMcast') -def ogMcastSendFile (disk=None, par=None, take_from=None, file=None, sess=None): +def ogMcastSendFile (disk=None, par=None, container=None, file=None, sess=None): if file is None: raise TypeError ('missing required argument: "file"') if sess is None: raise TypeError ('missing required argument: "sess"') - if take_from is not None: + if container is not None: if disk is None and par is None: - ## we were given take_from= - source = FileLib.ogGetPath (src=take_from, file=file) - dev_err = f'{take_from} {file}' - print (f'ogGetPath (src=({take_from}), file=({file})) = source ({source})') + ## we were given container= + source = FileLib.ogGetPath (src=container, file=file) + dev_err = f'{container} {file}' + print (f'ogGetPath (src=({container}), file=({file})) = source ({source})') else: - raise TypeError ('argument "take_from" can be specified along neither "disk" nor "par"') + raise TypeError ('argument "container" can be specified along neither "disk" nor "par"') else: if disk is not None and par is not None: @@ -526,23 +526,23 @@ def ogMcastSendFile (disk=None, par=None, take_from=None, file=None, sess=None): # #ogMcastReceiverFile ([ str_portMcast] [ [Relative_path_file] | [str_REPOSITORY path_file] | [int_ndisk int_npart path_file ] ]" \ -#ogMcastReceiverFile ( file='/PS1_PH1.img', sess='9000') -#ogMcastReceiverFile (write_to='CACHE', file='/aula1/PS2_PH4.img', sess='9000') -#ogMcastReceiverFile (disk=1, par=1, file='/isos/linux.iso', sess='9000') -def ogMcastReceiverFile (disk=None, par=None, write_to=None, file=None, sess=None): +#ogMcastReceiverFile ( file='/PS1_PH1.img', sess='9000') +#ogMcastReceiverFile (container='CACHE', file='/aula1/PS2_PH4.img', sess='9000') +#ogMcastReceiverFile (disk=1, par=1, file='/isos/linux.iso', sess='9000') +def ogMcastReceiverFile (disk=None, par=None, container=None, file=None, sess=None): if file is None: raise TypeError ('missing required argument: "file"') if sess is None: raise TypeError ('missing required argument: "sess"') - if write_to is not None: + if container is not None: if disk is None and par is None: - ## we were given write_to= - targetdir = FileLib.ogGetParentPath (src=write_to, file=file) - dev_err = f'{write_to} {file}' - print (f'ogGetParentPath (src=({write_to}), file=({file})) = targetdir ({targetdir})') + ## we were given container= + targetdir = FileLib.ogGetParentPath (src=container, file=file) + dev_err = f'{container} {file}' + print (f'ogGetParentPath (src=({container}), file=({file})) = targetdir ({targetdir})') else: - raise TypeError ('argument "write_to" can be specified along neither "disk" nor "par"') + raise TypeError ('argument "container" can be specified along neither "disk" nor "par"') else: if disk is not None and par is not None: @@ -674,9 +674,9 @@ def ogMcastRequest (img, proto): #ogCreateTorrent ([str_REPOSITORY] [int_ndisk int_npart] Relative_path_file IpBttrack) #ogCreateTorrent (disk=1, par=1, file='/aula1/winxp', ip_bttrack='10.1.15.23') -#ogCreateTorrent (take_from='REPO', file='/aula1/winxp', ip_bttrack='10.1.15.45') -#ogCreateTorrent (take_from='CACHE', file='/aula1/winxp', ip_bttrack='10.1.15.45') -def ogCreateTorrent (disk=None, par=None, take_from=None, file=None, ip_bttrack=None): +#ogCreateTorrent (container='REPO', file='/aula1/winxp', ip_bttrack='10.1.15.45') +#ogCreateTorrent (container='CACHE', file='/aula1/winxp', ip_bttrack='10.1.15.45') +def ogCreateTorrent (disk=None, par=None, container=None, file=None, ip_bttrack=None): if file is None: raise TypeError ('missing required argument: "file"') if ip_bttrack is None: @@ -684,19 +684,19 @@ def ogCreateTorrent (disk=None, par=None, take_from=None, file=None, ip_bttrack= from_cache = False - if take_from is not None: + if container is not None: if disk is None and par is None: - ## we were given take_from= - if 'CACHE' == take_from: from_cache = True - ext = ImageLib.ogGetImageType (take_from, file) + ## we were given container= + if 'CACHE' == container: from_cache = True + ext = ImageLib.ogGetImageType (container, file) if ext is None: - SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTFOUND, f'{take_from} {file}') + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTFOUND, f'{container} {file}') return f = f'{file}.{ext}' - source = FileLib.ogGetPath (src=take_from, file=f) - print (f'ogGetPath (src=({take_from}), file=({f})) = source ({source})') + source = FileLib.ogGetPath (src=container, file=f) + print (f'ogGetPath (src=({container}), file=({f})) = source ({source})') else: - raise TypeError ('argument "take_from" can be specified along neither "disk" nor "par"') + raise TypeError ('argument "container" can be specified along neither "disk" nor "par"') else: if disk is not None and par is not None: From 7c1cb0168c1e8ebef4210db64e96e274ec9806ff Mon Sep 17 00:00:00 2001 From: Natalia Serrano Date: Wed, 13 Nov 2024 18:29:22 +0100 Subject: [PATCH 060/167] refs #1101 add ogTorrentStart() --- client/lib/engine/bin/FileLib.py | 6 +- client/lib/engine/bin/ProtocolLib.py | 113 +++++++++++++++++++++++++++ 2 files changed, 116 insertions(+), 3 deletions(-) diff --git a/client/lib/engine/bin/FileLib.py b/client/lib/engine/bin/FileLib.py index dc649d1..e9de16f 100755 --- a/client/lib/engine/bin/FileLib.py +++ b/client/lib/engine/bin/FileLib.py @@ -233,9 +233,9 @@ def ogGetPath (src=None, file=None): #*/ ## #ogGetParentPath ([ str_repo | int_ndisk int_npartition ] path_filepath -#ogGetParentPath ('/mnt/sda1/windows/system32') ==> '/mnt/sda1/WINDOWS' -#ogGetParentPath ('REPO', '/etc/fstab') ==> '/opt/opengnsys/images/etc' -#ogGetParentPath ('1 1', '/windows/system32') ==> '/mnt/sda1/WINDOWS' +#ogGetParentPath ( file='/mnt/sda1/windows/system32') ==> '/mnt/sda1/WINDOWS' +#ogGetParentPath (src='REPO', file='/etc/fstab') ==> '/opt/opengnsys/images/etc' +#ogGetParentPath (src='1 1', file='/windows/system32') ==> '/mnt/sda1/WINDOWS' def ogGetParentPath (src=None, file=None): if file is None: SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_FORMAT, '') diff --git a/client/lib/engine/bin/ProtocolLib.py b/client/lib/engine/bin/ProtocolLib.py index 4fa50b5..b070ac8 100644 --- a/client/lib/engine/bin/ProtocolLib.py +++ b/client/lib/engine/bin/ProtocolLib.py @@ -658,6 +658,119 @@ def ogMcastRequest (img, proto): #@return #@note protocoloTORRENT=mode:time mode=seeder -> Dejar el equipo seedeando hasta que transcurra el tiempo indicado o un kill desde consola, mode=peer -> seedear mientras descarga mode=leecher -> NO seedear mientras descarga time tiempo que una vez descargada la imagen queremos dejar al cliente como seeder. #*/ ## +#ogTorrentStart ( torrentfile='/opt/opengnsys/cache/linux.iso', torrentsess='peer:60') +#ogTorrentStart (container='CACHE', torrentfile='/PS1_PH1.img.torrent', torrentsess='seeder:10000') +#ogTorrentStart (disk=1, par=1, torrentfile='/linux.iso.torrent', torrentsess='leecher:60') +def ogTorrentStart (disk=None, par=None, container=None, torrentfile=None, torrentsess=None): + if torrentfile is None: + raise TypeError ('missing required argument: "torrentfile"') + if torrentsess is None: + raise TypeError ('missing required argument: "torrentsess"') + + if container is not None: + if disk is None and par is None: + ## we were given container= + if 'CACHE' != container.upper(): + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_FORMAT, 'La descarga torrent solo se hace desde local, copia el torrent a la cache y realiza la operación desde esa ubicación') + return None + source = FileLib.ogGetPath (src=container, file=torrentfile) + dev_err = f'{container} {torrentfile}' + print (f'ogGetPath (src=({container}), file=({torrentfile})) = source ({source})') + else: + raise TypeError ('argument "container" can be specified along neither "disk" nor "par"') + + else: + if disk is not None and par is not None: + ## we were given disk= par= + source = FileLib.ogGetPath (src=f'{disk} {par}', file=torrentfile) + dev_err = f'{disk} {par} {torrentfile}' + print (f'ogGetPath (src=({disk} {par}), file=({torrentfile})) = source ({source})') + elif disk is None and par is None: + ## we were given nothing + if torrentfile.startswith ('/opt/opengnsys/images'): + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_FORMAT, 'La descarga torrent solo se hace desde local, copia el torrent a la cache y realiza la operación desde esa ubicación') + return None + source = FileLib.ogGetPath (file=torrentfile) + dev_err = torrentfile + print (f'ogGetPath (file=({torrentfile})) = source ({source})') + else: + raise TypeError ('if one of "disk" and "par" are specified, then both must be') + + if not source: + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTFOUND, f'device or torrentfile {dev_err} not found') + return + + if subprocess.run (['ctorrent', '-x', source]).returncode: + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTFOUND, '') + return None + + target = re.sub (r'\.torrent$', '', source) + dirsource = FileLib.ogGetParentPath (file=source) + + ERROR = None + sess = torrentsess.split (':') + if 2 != len (sess): + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_FORMAT, 'parametros session Torrent no completa: modo:tiempo') + return None + + mode = sess[0].lower() + if mode not in ['seeder', 'peer', 'leecher']: + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_FORMAT, f'valor modo Torrent no valido {sess[0]}') + return None + + time = sess[1] + if not re.search (r'^[0-9]{1,10}$', time): + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_FORMAT, f'valor tiempo no valido {sess[1]}') + return None + time = int (time) + + OPTION = None + cwd = os.getcwd() + # si No fichero .bf, y Si fichero destino imagen ya descargada y su chequeo fue comprobado en su descarga inicial. + if not os.path.exists (f'{source}.bf') and os.path.exists (target): + print ('imagen ya descargada') + if 'seeder' != mode: return 'success' ## return any true value + + print ('MODE seeder ctorrent') + os.chdir (dirsource) + subprocess.run (['timeout', '--signal', 'INT', time, 'ctorrent', '-f', source]) + os.chdir (cwd) + return 'success' + + #Si no existe bf ni fichero destino descarga inicial. + if not os.path.exists (f'{source}.bf') and not os.path.exists (target): + print ('descarga inicial') + OPTION = 'DOWNLOAD' + + # Si fichero bf descarga anterior no completada -. + if os.path.exists (f'{source}.bf') and os.path.exists (target): + print ('Continuar con Descargar inicial no terminada.') + OPTION = 'DOWNLOAD' + + if 'DOWNLOAD' != OPTION: return 'success' + + os.chdir (dirsource) + if 'peer' == mode: + print ('Donwloading Torrent as peer') + # Creamos el fichero de resumen por defecto + with open (f'{source}.bf', 'w') as fd: pass + # ctorrent controla otro fichero -b ${SOURCE}.bfog + subprocess.run (['ctorrent', '-f', '-c', '-X', f'sleep {time}; kill -2 $(pidof ctorrent)', '-C', '100', source, '-s', target, '-b', f'{source}.bfog']) + elif 'leecher' == mode: + print ('Donwloading Torrent as leecher') + subprocess.run (['ctorrent', '${SOURCE}', '-X', 'sleep 30; kill -2 $(pidof ctorrent)', '-C', '100', '-U', '0']) + elif 'seeder' == mode: + print ('MODE seeder ctorrent') + # Creamos el fichero de resumen por defecto + with open (f'{source}.bf', 'w') as fd: pass + # ctorrent controla otro fichero -b ${SOURCE}.bfog + subprocess.run (['ctorrent', '-f', '-c', '-X', f'sleep {time}; kill -2 $(pidof ctorrent)', '-C', '100', source, '-s', target, '-b', f'{source}.bfog']) + else: + print ('this should not happen') + return None + + os.chdir (cwd) + #/** # ogCreateTorrent [ str_repo | int_ndisk int_npart ] Relative_path_file From 6b83fe3f04fdb291bd8a1c2811d8833f34335d59 Mon Sep 17 00:00:00 2001 From: Antonio Emmanuel Guerrero Silva Date: Wed, 13 Nov 2024 12:48:30 -0600 Subject: [PATCH 061/167] refs #1144 global variables that must be in the language files are deleted. --- client/lib/engine/bin/ogGlobals.py | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/client/lib/engine/bin/ogGlobals.py b/client/lib/engine/bin/ogGlobals.py index cd58566..3c02f28 100755 --- a/client/lib/engine/bin/ogGlobals.py +++ b/client/lib/engine/bin/ogGlobals.py @@ -109,14 +109,4 @@ OG_ERR_NOTDIFFERENT=73 # No se detectan diferencias entre la image OG_ERR_SYNCHRONIZING=74 # Error al sincronizar, puede afectar la creacion/restauracion de la imagen OG_ERR_NOTUEFI=80 # La interfaz UEFI no está activa -OG_ERR_NOTBIOS=81 # La interfaz BIOS legacy no está activa - -# Mensajes de descripción breve de la interfaz. -MSG_INTERFACE_START="[START Interface] Ejecutar comando: " -MSG_INTERFACE_END="[END Interface] Comando terminado con este código: " - -# Mensajes complementarios para las ayudas. -MSG_64BIT="64 bits" -MSG_DISK="disc" -MSG_ERROR="Error" -MSG_FORMAT="Format" \ No newline at end of file +OG_ERR_NOTBIOS=81 # La interfaz BIOS legacy no está activa \ No newline at end of file From c03455a32f132a6d965c8c163f3926842d55959f Mon Sep 17 00:00:00 2001 From: Antonio Emmanuel Guerrero Silva Date: Wed, 13 Nov 2024 14:11:36 -0600 Subject: [PATCH 062/167] refs #1144 the call to variables from the language file is modified --- client/interfaceAdm/InventarioSoftware.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/client/interfaceAdm/InventarioSoftware.py b/client/interfaceAdm/InventarioSoftware.py index 37d729e..4c9c316 100755 --- a/client/interfaceAdm/InventarioSoftware.py +++ b/client/interfaceAdm/InventarioSoftware.py @@ -6,6 +6,7 @@ import sys sys.path.append('/opt/opengnsys/lib/engine/bin') import ogGlobals +import SystemLib def main(arg1, arg2, dest_file): start_time = time.time() @@ -20,9 +21,9 @@ def main(arg1, arg2, dest_file): with open(f"{og_log_command}.tmp", 'w') as f: f.write(" ") - msg_interface_start = os.getenv(ogGlobals.MSG_INTERFACE_START) + msg_interface_start = os.getenv(ogGlobals.lang.MSG_INTERFACE_START) if msg_interface_start: - subprocess.run(['ogEcho', 'log', 'session', f"{msg_interface_start} {__file__} {arg1} {arg2}"]) + SystemLib.ogEcho("log", "session", f"{msg_interface_start} {__file__} {arg1} {arg2}") try: result = subprocess.run( @@ -40,9 +41,9 @@ def main(arg1, arg2, dest_file): shutil.copy(file, dest_file) elapsed_time = time.time() - start_time - msg_scripts_time_partial = os.getenv('MSG_SCRIPTS_TIME_PARTIAL') + msg_scripts_time_partial = os.getenv(ogGlobals.lang.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"]) + SystemLib.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: From ea5114a897cc21ede8747885c8db2b580ad41696 Mon Sep 17 00:00:00 2001 From: Antonio Emmanuel Guerrero Silva Date: Wed, 13 Nov 2024 22:03:11 -0600 Subject: [PATCH 063/167] refs #1144 rebuild ogChangeRepo --- client/lib/engine/bin/NetLib.py | 91 ++++++++++++++++----------------- 1 file changed, 43 insertions(+), 48 deletions(-) diff --git a/client/lib/engine/bin/NetLib.py b/client/lib/engine/bin/NetLib.py index 32e9e5e..1f85ee0 100755 --- a/client/lib/engine/bin/NetLib.py +++ b/client/lib/engine/bin/NetLib.py @@ -16,63 +16,58 @@ import SystemLib #@param 2 Abreviatura Unidad Organizativa #@return Cambio recurso remoto en OGIMG. #*/ -def ogChangeRepo(): - SRCIMG = "" - NEWREPO = "" - REPO = "" - OGUNIT = "" +def ogChangeRepo(ip_repo, og_unit=None): + ogprotocol = "cifs" - if len(sys.argv) < 2: - print("Usage: ogChangeRepo IPREPO [ OgUnit ]") - print("Example: ogChangeRepo 10.1.120.3") - print("Example: ogChangeRepo 10.1.120.3 cdc") - return + try: + rw_option = ",rw" if "rw" in subprocess.getoutput("mount | grep 'ogimages'") else ",ro" - if sys.argv[1] == "help": - print("Usage: ogChangeRepo IPREPO [ OgUnit ]") - print("Example: ogChangeRepo 10.1.120.3") - print("Example: ogChangeRepo 10.1.120.3 cdc") - return + current_repo = ogGetRepoIp() + current_og_unit = subprocess.getoutput( + "df | awk -F ' ' '/ogimages/ {sub(\"//.*/ogimages\",\"\",$1); sub(\"/\",\"\",$1); print $1}'" + ).strip() - if len(sys.argv) >= 2: - NEWREPO = sys.argv[1] + new_repo = current_repo if ip_repo.upper() == "REPO" else ip_repo - # Opciones de montaje: lectura o escritura - subprocess.run(["mount", "|", "grep", "ogimages.*rw,"], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) - RW = ",rw" if subprocess.returncode == 0 else ",ro" + if new_repo == current_repo and og_unit == current_og_unit: + return 0 - # Si REPO tomamos el repositorio y la unidad organizativa actual - REPO = ogRepoIp() - OGUNIT = subprocess.run(["df", "|", "awk", "-F", " ", "'/ogimages/ {sub(\"//.*/ogimages\",\"\",$1); sub(\"/\",\"\",$1); print $1}'"], stdout=subprocess.PIPE, stderr=subprocess.DEVNULL).stdout.decode().strip() + subprocess.run(["umount", ogGlobals.OGIMG], check=True) - # Parametros de entrada. Si $1 = "REPO" dejo el repositorio actual - if sys.argv[1].upper() == "REPO": - NEWREPO = REPO + src_img = "ogimages" if not og_unit else f"ogimages/{og_unit}" + + result = subprocess.run( + ["ogConnect", new_repo, ogprotocol, src_img, ogGlobals.OGIMG, rw_option], + text=True, + ) + + if result.returncode != 0: + subprocess.run( + ["ogConnect", current_repo, ogprotocol, src_img, ogGlobals.OGIMG, rw_option], + text=True, + ) + SystemLib.ogRaiseError( + "session", + ogGlobals.OG_ERR_REPO, + f"Error connecting to the new repository: {new_repo}", + ) + return 1 + + SystemLib.ogEcho( + "session", + "log", + f"Repository successfully changed to {new_repo} {og_unit or ''}".strip(), + ) - # Si $1 y $2 son el repositorio y la OU actual me salgo - if NEWREPO == REPO and sys.argv[2] == OGUNIT: return 0 - subprocess.run(["source", "/scripts/functions"], shell=True) - subprocess.run(["source", "/scripts/ogfunctions"], shell=True) - subprocess.run(["umount", OGIMG]) - - if sys.argv[2] == "": - SRCIMG = "ogimages" - else: - SRCIMG = "ogimages/" + sys.argv[2] - - subprocess.run(["eval", "$(grep \"OPTIONS=\" /scripts/ogfunctions)"]) - - SystemLib.ogEcho("session", "log", MSG_HELP_ogChangeRepo + " " + NEWREPO + " " + sys.argv[2].rstrip()) - ogConnect(NEWREPO, ogprotocol, SRCIMG, OGIMG, RW) - - # Si da error volvemos a montar el inicial - if subprocess.returncode != 0: - ogConnect(REPO, ogprotocol, SRCIMG, OGIMG, RW) - SystemLib.ogRaiseError("session", OG_ERR_REPO, NEWREPO) - return subprocess.returncode - + except Exception as e: + SystemLib.ogRaiseError( + "session", + ogGlobals.OG_ERR_FORMAT, + f"Error executing ogChangeRepo: {e}", + ) + return 1 #/** # ogGetGroupDir [ str_repo ] From 976b6367f377cb30c6d87814ece1eeae8db25a2d Mon Sep 17 00:00:00 2001 From: Antonio Emmanuel Guerrero Silva Date: Wed, 13 Nov 2024 22:11:57 -0600 Subject: [PATCH 064/167] refs #1144 rebuild ogGetGroupName --- client/lib/engine/bin/NetLib.py | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/client/lib/engine/bin/NetLib.py b/client/lib/engine/bin/NetLib.py index 1f85ee0..51e76fc 100755 --- a/client/lib/engine/bin/NetLib.py +++ b/client/lib/engine/bin/NetLib.py @@ -106,14 +106,12 @@ def ogGetGroupDir(): #@return str_group - Nombre de grupo. #*/ def ogGetGroupName(): - if len(sys.argv) >= 2 and sys.argv[1] == "help": - SystemLib.ogHelp("ogGetGroupName", "ogGetGroupName", "ogGetGroupName => Grupo1") - return - - if "group" in globals() and group: - print(group) - - return 0 + try: + group = globals().get("group", None) + return group if group else None + except Exception as e: + print(f"Error in ogGetGroupName: {e}") + return None #/** From 8db98b1289b0d326fc34eee5dff206c9bf795b5b Mon Sep 17 00:00:00 2001 From: Antonio Emmanuel Guerrero Silva Date: Wed, 13 Nov 2024 22:15:50 -0600 Subject: [PATCH 065/167] refs #1144 rebuild ogGetGroupDir --- client/lib/engine/bin/NetLib.py | 37 +++++++++++++++------------------ 1 file changed, 17 insertions(+), 20 deletions(-) diff --git a/client/lib/engine/bin/NetLib.py b/client/lib/engine/bin/NetLib.py index 51e76fc..d959585 100755 --- a/client/lib/engine/bin/NetLib.py +++ b/client/lib/engine/bin/NetLib.py @@ -4,8 +4,8 @@ import os import json import ogGlobals -import NetLib import SystemLib +import FileLib @@ -77,28 +77,25 @@ def ogChangeRepo(ip_repo, og_unit=None): #@note repo = { REPO, CACHE } REPO por defecto #@exception OG_ERR_FORMAT formato incorrecto. #*/ -def ogGetGroupDir(): - REPO = "" - DIR = "" - GROUP = "" +def ogGetGroupDir(repo=None): + try: + repo = repo or "REPO" - if len(sys.argv) < 2: - SystemLib.ogHelp("ogGetGroupDir", "ogGetGroupDir str_repo", "ogGetGroupDir REPO ==> /opt/opengnsys/images/groups/Grupo1") - return + group = ogGetGroupName() + if group: + dir_path = FileLib.ogGetPath(repo, f"/groups/{group}") + if dir_path and os.path.isdir(dir_path): + return dir_path - if len(sys.argv) == 1: - REPO = "REPO" - else: - REPO = sys.argv[1] - - GROUP = ogGetGroupName() - if GROUP: - DIR = FileLib.ogGetPath(REPO, "/groups/" + GROUP, stderr=subprocess.DEVNULL) - if os.path.isdir(DIR): - print(DIR) - - return 0 + return None + except Exception as e: + SystemLib.ogRaiseError( + "session", + ogGlobals.OG_ERR_FORMAT, + f"Error in ogGetGroupDir: {e}" + ) + return None #/** # ogGetGroupName From bc3d68e8fbec31a2fd842ca05fbee4fbf40a73c5 Mon Sep 17 00:00:00 2001 From: Antonio Emmanuel Guerrero Silva Date: Thu, 14 Nov 2024 07:50:51 -0600 Subject: [PATCH 066/167] refs #1144 rebuild ogGetHostname --- client/lib/engine/bin/NetLib.py | 62 +++++++++++++++------------------ 1 file changed, 29 insertions(+), 33 deletions(-) diff --git a/client/lib/engine/bin/NetLib.py b/client/lib/engine/bin/NetLib.py index d959585..793bf73 100755 --- a/client/lib/engine/bin/NetLib.py +++ b/client/lib/engine/bin/NetLib.py @@ -7,8 +7,6 @@ import ogGlobals import SystemLib import FileLib - - #/** # ogChangeRepo IPREPO [ OgUnit ] #@brief Cambia el repositorio para el recurso remoto images. @@ -110,44 +108,46 @@ def ogGetGroupName(): print(f"Error in ogGetGroupName: {e}") return None - #/** # ogGetHostname #@brief Muestra el nombre del cliente. #@return str_host - nombre de máquina #*/ ## def ogGetHostname(): - HOST = "" + try: + # 1. Get hostname from the HOSTNAME environment variable + host = os.getenv("HOSTNAME", "").strip() - if len(sys.argv) >= 2 and sys.argv[1] == "help": - SystemLib.ogHelp("ogGetHostname", "ogGetHostname", "ogGetHostname => pc1") - return + # 2. If not set, read from the DHCP leases file + if not host: + dhcp_file = "/var/lib/dhcp3/dhclient.leases" + if os.path.exists(dhcp_file): + with open(dhcp_file, "r") as f: + for line in f: + if 'option host-name' in line: + host = line.split('"')[1].strip(";") + break - # Tomar nombre de la variable HOSTNAME - HOST = os.getenv("HOSTNAME") + # 3. If still not set, read from kernel parameters in /proc/cmdline + if not host: + cmdline_file = "/proc/cmdline" + if os.path.exists(cmdline_file): + with open(cmdline_file, "r") as f: + for entry in f.read().split(): + if entry.startswith("hostname="): + host = entry.split("=")[1].strip() + break - # Si no, tomar del DHCP, opción host-name - if not HOST: - with open("/var/lib/dhcp3/dhclient.leases", "r") as f: - for line in f: - if "option host-name" in line: - HOST = line.split('"')[1] - break + # 4. Update HOSTNAME environment variable if it differs + current_hostname = os.getenv("HOSTNAME", "") + if host and current_hostname != host: + os.environ["HOSTNAME"] = host - # Si no, leer el parámetro del kernel hostname - if not HOST: - with open("/proc/cmdline", "r") as f: - cmdline = f.read() - HOST = re.search(r"hostname=([^ ]+)", cmdline) - if HOST: - HOST = HOST.group(1) - - if HOSTNAME != HOST: - os.environ["HOSTNAME"] = HOST - - if HOST: - print(HOST) + return host if host else None + except Exception as e: + print(f"Error in ogGetHostname: {e}") + return None #/** # ogGetIpAddress @@ -179,7 +179,6 @@ def ogGetIpAddress(): return 0 - #/** # ogGetMacAddress #@brief Muestra la dirección Ethernet del cliente. @@ -241,7 +240,6 @@ def ogGetNetInterface(): return 0 - #/** # ogGetRepoIp #@brief Muestra la dirección IP del repositorio de datos. @@ -263,7 +261,6 @@ def ogGetRepoIp(): return None - #/** # ogGetServerIp #@brief Muestra la dirección IP del Servidor de OpenGnSys. @@ -305,7 +302,6 @@ def ogGetServerIp(): SystemLib.ogEcho("session", "info", "No valid file system found") return None - #/** # ogMakeGroupDir [ str_repo ] #@brief Crea el directorio para el grupo del cliente. From 646d1da734e393bd4fb85cc3bdaee67722867629 Mon Sep 17 00:00:00 2001 From: Natalia Serrano Date: Thu, 14 Nov 2024 15:03:31 +0100 Subject: [PATCH 067/167] refs #1101 add ogUpdateCacheIsNecesary() and dependencies --- client/lib/engine/bin/FileLib.py | 192 +++++++++++++++++++++------ client/lib/engine/bin/ProtocolLib.py | 101 +++++++++++++- 2 files changed, 250 insertions(+), 43 deletions(-) diff --git a/client/lib/engine/bin/FileLib.py b/client/lib/engine/bin/FileLib.py index e9de16f..f25414b 100755 --- a/client/lib/engine/bin/FileLib.py +++ b/client/lib/engine/bin/FileLib.py @@ -1,31 +1,81 @@ +#/** +#@file FileLib.py +#@brief Librería o clase File +#@class File +#@brief Funciones para gestión de archivos y directorios. +#@warning License: GNU GPLv3+ +#*/ + import subprocess import os import shutil +import hashlib import ogGlobals import SystemLib import CacheLib import FileSystemLib -def ogCalculateChecksum(*args): - # Check if help is requested - if "help" in args: - print("ogCalculateChecksum [ str_repo | int_ndisk int_npartition ] path_filepath") - print("ogCalculateChecksum REPO ubuntu.img ==> ef899299caf8b517ce36f1157a93d8bf") +#/** +# ogCalculateChecksum [ str_repo | int_ndisk int_npart ] path_filepath +#@brief Devuelve la suma de comprobación (checksum) de un fichero. +#@param path_filepath camino del fichero (independiente de mayúsculas) +#@param str_repo repositorio de ficheros +#@param int_ndisk nº de orden del disco +#@param int_npartition nº de orden de la partición +#@return hex_checksum Checksum del fichero +#*/ ## +#ogCalculateChecksum ([ str_repo | int_ndisk int_npartition ] path_filepath") +#ogCalculateChecksum (container='REPO', file='ubuntu.img') ==> ef899299caf8b517ce36f1157a93d8bf +#ogCalculateChecksum (disk=1, par=1, file='ubuntu.img') ==> ef899299caf8b517ce36f1157a93d8bf +def ogCalculateChecksum (disk=None, par=None, container=None, file=None): + if file is None: + raise TypeError ('missing required argument: "file"') + + if container is not None: + if disk is None and par is None: + ## we were given container= + f = ogGetPath (src=container, file=file) + dev_err = f'{container} {file}' + print (f'ogGetPath (src=({container}), file=({file})) = f ({f})') + else: + raise TypeError ('argument "container" can be specified along neither "disk" nor "par"') + + else: + if disk is not None and par is not None: + ## we were given disk= par= + f = ogGetPath (src=f'{disk} {par}', file=file) + dev_err = f'{disk} {par} {file}' + print (f'ogGetPath (src=({disk} {par}), file=({file})) = f ({f})') + elif disk is None and par is None: + ## we were given nothing + f = ogGetPath (file=file) + dev_err = file + print (f'ogGetPath (file=({file})) = f ({f})') + else: + raise TypeError ('if one of "disk" and "par" are specified, then both must be') + + if not f: + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTFOUND, dev_err) return - # Get the file path - file_path = ogGetPath(*args) - if not file_path: - SystemLib.ogRaiseError(OG_ERR_NOTFOUND, *args) - return + last_n_bytes = 1024*1024 + if last_n_bytes >= os.stat ('/bin/ls').st_size: + return ogCalculateFullChecksum (disk, par, container, file) + with open (f, 'rb') as fd: + fd.seek (-last_n_bytes, os.SEEK_END) + data = file.read() + md5 = hashlib.md5(data).hexdigest() - # Calculate the checksum - result = subprocess.run(["tail", "-c1M", file_path], capture_output=True) - checksum = result.stdout.decode().split()[0] + return md5 - return checksum +#/** +# ogCompareChecksumFiles [ str_repo | int_ndisk int_npart ] path_source [ str_repo | int_ndisk int_npart ] path_target +#@brief Metafunción que compara las sumas de comprobación almacenadas de 2 ficheros. +#@return bool_compare Valor de comparación. +#@warning No es necesario especificar la extensión ".sum". +#*/ ## def ogCompareChecksumFiles(*args): # Variables locales. ARGS = args @@ -59,24 +109,63 @@ def ogCompareChecksumFiles(*args): except FileNotFoundError: return False -def ogCalculateFullChecksum(*args): - # Variables locales. - FILE = None - if "help" in args: - SystemLib.ogHelp("$FUNCNAME", "$FUNCNAME [ str_repo | int_ndisk int_npartition ] path_filepath", "$FUNCNAME REPO ubuntu.img ==> ef899299caf8b517ce36f1157a93d8bf") + +#/** +# ogCalculateFullChecksum [ str_repo | int_ndisk int_npart ] path_filepath +#@brief Devuelve la suma COMPLETA de comprobación (checksum) de un fichero. +#@param path_filepath camino del fichero (independiente de mayúsculas) +#@param str_repo repositorio de ficheros +#@param int_ndisk nº de orden del disco +#@param int_npartition nº de orden de la partición +#@return hex_checksum Checksum del fichero +#*/ ## +def ogCalculateFullChecksum (disk=None, par=None, container=None, file=None): + if file is None: + raise TypeError ('missing required argument: "file"') + + if container is not None: + if disk is None and par is None: + ## we were given container= + f = ogGetPath (src=container, file=file) + dev_err = f'{container} {file}' + print (f'ogGetPath (src=({container}), file=({file})) = f ({f})') + else: + raise TypeError ('argument "container" can be specified along neither "disk" nor "par"') + + else: + if disk is not None and par is not None: + ## we were given disk= par= + f = ogGetPath (src=f'{disk} {par}', file=file) + dev_err = f'{disk} {par} {file}' + print (f'ogGetPath (src=({disk} {par}), file=({file})) = f ({f})') + elif disk is None and par is None: + ## we were given nothing + f = ogGetPath (file=file) + dev_err = file + print (f'ogGetPath (file=({file})) = f ({f})') + else: + raise TypeError ('if one of "disk" and "par" are specified, then both must be') + + if not f: + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTFOUND, dev_err) return - # Comprobar que existe el fichero y devolver sus datos. - FILE = ogGetPath(*args) - if not FILE: - SystemLib.ogRaiseError(OG_ERR_NOTFOUND, *args) - return + md5 = hashlib.md5() + with open (f, 'rb') as fd: + for chunk in iter (lambda: fd.read (64*1024), b''): + md5.update (chunk) + return md5.hexdigest() - # Calculate the checksum - result = subprocess.run(["md5sum", FILE, "-b"], capture_output=True) - checksum = result.stdout.decode().split()[0] - return checksum + + +#/** +# ogCopyFile [ str_repo | int_ndisk int_npart ] path_source [ str_repo | int_ndisk int_npart ] path_target +#@brief Metafunción para copiar un fichero de sistema OpenGnSys a un directorio. +#@see ogGetPath +#@return Progreso de la copia. +#@warning Deben existir tanto el fichero origen como el directorio destino. +#*/ ## def ogCopyFile(*args): # Variables locales. @@ -113,22 +202,45 @@ def ogCopyFile(*args): result = subprocess.run(["rsync", "--progress", "--inplace", "-avh", SOURCE, TARGET]) return result.returncode -def ogDeleteFile(*args): - # Variables locales. - FILE = None - if "help" in args: - SystemLib.ogHelp("$FUNCNAME", "$FUNCNAME [ str_repo | int_ndisk int_npartition ] path_file", "$FUNCNAME 1 2 /tmp/newfile.txt") + +#/** +# ogDeleteFile [ str_repo | int_ndisk int_npartition ] path_filepath +#@brief Metafunción que borra un fichero de un dispositivo. +#@see ogGetPath +#@version 0.9 - Pruebas con OpenGnSys. +#@author Ramon Gomez, ETSII Universidad de Sevilla +#@date 2009-09-29 +#*/ ## +#ogDeleteFile ([ str_repo | int_ndisk int_npartition ] path_file) +#ogDeleteFile (container='REPO', file='/tmp/newfile.txt') +#ogDeleteFile (disk=1, par=2, file='/tmp/newfile.txt') +def ogDeleteFile (disk=None, par=None, container=None, file=None): + if file is None: + raise TypeError ('missing required argument: "file"') + + if container is not None: + if disk is None and par is None: + ## we were given container= + src = container + else: + raise TypeError ('argument "container" can be specified along neither "disk" nor "par"') + else: + if disk is not None and par is not None: + ## we were given disk= par= + src = f'{disk} {par}' + else: + ## we were given nothing + raise TypeError ('either "container" or both "disk" and "par" must be specified') + + f = ogGetPath (src=src, file=file) + if not f: + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTFOUND, f'{src} {file}') return - # Comprobar que existe el fichero y borrarlo. - FILE = ogGetPath(*args) - if not FILE: - SystemLib.ogRaiseError(OG_ERR_NOTFOUND, *args) - return try: - os.remove(FILE) + os.remove (f) except OSError as e: - SystemLib.ogRaiseError(OG_ERR_NOTFOUND, *args) + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_GENERIC, str (e)) return def ogDeleteTree(*args): diff --git a/client/lib/engine/bin/ProtocolLib.py b/client/lib/engine/bin/ProtocolLib.py index b070ac8..b421307 100644 --- a/client/lib/engine/bin/ProtocolLib.py +++ b/client/lib/engine/bin/ProtocolLib.py @@ -4,6 +4,7 @@ import subprocess import re import json import os.path +import shutil import ogGlobals import SystemLib @@ -852,10 +853,104 @@ def ogCreateTorrent (disk=None, par=None, container=None, file=None, ip_bttrack= #@param 1 str_REPO #@param 2 str_Relative_path_file_OGIMG_with_/ #@param 3 md5 to check: use full to check download image torrent -#@return 0 (true) cache sin imagen, SI es necesario actualizar el fichero. -#@return 1 (false) imagen en la cache, NO es necesario actualizar el fichero -#@return >1 (false) error de sintaxis (TODO) +#@return True cache sin imagen, SI es necesario actualizar el fichero. +#@return False imagen en la cache, NO es necesario actualizar el fichero +#@return None error de sintaxis (TODO) #@note #@todo: Proceso en el caso de que el fichero tenga el mismo nombre, pero su contenido sea distinto. #@todo: Se dejan mensajes mientras se confirma su funcionamiento. #*/ ## +#ogUpdateCacheIsNecesary ('REPO', '/PS1_PH1.img', 'UNICAST') +#ogUpdateCacheIsNecesary ('REPO', '/ogclient.sqfs', 'FULL') +#ogUpdateCacheIsNecesary ('REPO', '/ogclient.sqfs', 'TORRENT') +def ogUpdateCacheIsNecesary (repo, file, proto): + if not CacheLib.ogFindCache(): + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTCACHE, '') + return None + + if repo.lower() != 'repo': + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTFOUND, f' {repo} {file}') + return None + + filesource = FileLib.ogGetPath (src=repo, file=file) + print (f'filesource ({filesource})') + if not filesource: + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTFOUND, f' {repo} {file}') + return None + + # paso 1. si no existe la imagen, confirmar que es necesario actualizar la cache. + filetarget = FileLib.ogGetPath (src='CACHE', file=file) + print (f'filetarget ({filetarget})') + if not filetarget: + # borramos el fichero bf del torrent, en el caso de que se hubiese quedado de algun proceso fallido + if FileLib.ogGetPath (src='CACHE', file=f'/{file}.torrent.bf'): ogDeleteFile ('CACHE', f'{file}.torrent.bf') + if FileLib.ogGetPath (src='CACHE', file=f'/{file}.sum'): ogDeleteFile ('CACHE', f'{file}.sum') + if FileLib.ogGetPath (src='CACHE', file=f'/{file}.full.sum'): ogDeleteFile ('CACHE', f'{file}.full.sum') + print ('TRUE(0), es necesario actualizar. Paso 1, la cache no contiene esa imagen ') + return True + + # Paso 2. Comprobamos que la imagen no estuviese en un proceso previo torrent + if FileLib.ogGetPath (file=f'{filetarget}.torrent.bf'): + #TODO: comprobar los md5 del fichero .torrent para asegurarnos que la imagen a descarga es la misma. + print ('TRUE(0), es necesario actualizar. Paso 2, la imagen esta en un estado de descarga torrent interrumpido') + return True + + ## En este punto la imagen en el repo y en la cache se llaman igual, + # paso 4. Obtener los md5 del fichero imagen en la cacha segun PROTOCOLO $3 + if proto.lower() in ['full', 'torrent']: + #Buscamos MD5 en el REPO SOURCE + if os.path.exists (f'{filesource}.full.sum'): + with open (f'{filesource}.full.sum', 'r') as fd: + md5source = fd.read().strip() + else: + md5source = FileLib.ogCalculateFullChecksum (file=filesource) + + # Generamos el MD5 (full) en la CACHE + if not os.path.exists (f'{filetarget}.full.sum'): + fullck = FileLib.ogCalculateFullChecksum (file=filetarget) + with open (f'{filetarget}.full.sum', 'w') as fd: + fd.write (fullck + '\n') + with open (f'{filetarget}.full.sum', 'r') as fd: + md5target = fd.read().strip() + # Generamos el MD5 (little) en la CACHE para posteriores usos del protocolo MULTICAST + if not os.path.exists (f'{filetarget}.sum'): + ck = FileLib.ogCalculateChecksum (file=filetarget) + with open (f'{filetarget}.sum', 'w') as fd: + fd.write (ck + '\n') + else: + #Buscamos MD5 en el REPO SOURCE + if os.path.exists (f'{filesource}.sum'): + with open (f'{filesource}.sum', 'r') as fd: + md5source = fd.read().strip() + else: + md5source = FileLib.ogCalculateChecksum (file=filesource) + + # Generamos el MD5 (little) en la CACHE + if not os.path.exists (f'{filetarget}.sum'): + ck = FileLib.ogCalculateChecksum (file=filetarget) + with open (f'{filetarget}.sum', 'w') as fd: + fd.write (ck + '\n') + with open (f'{filetarget}.sum', 'r') as fd: + md5target = fd.read().strip() + #Generamos o copiamos MD5 (full) en la CACHE para posteriores usos con Torrent + # Si no existe el full.sum y si existe el .sum es porque el upateCACHE multicast o unicast ha sido correcto. + if not os.path.exists (f'{filetarget}.full.sum') and os.path.exists (f'{filetarget}.sum'): + if os.path.exists (f'{filesource}.full.sum'): + #Existe el .full.sum en REPO realizamos COPIA + shutil.copy2 (f'{filesource}.full.sum', f'{filetarget}.full.sum') + else: + #No existe .full.sum no en REPO LO GENERAMOS en la cache: situacion dificil que ocurra + fullck = FileLib.ogCalculateFullChecksum (file=filetarget) + with open (f'{filetarget}.full.sum', 'w') as fd: + fd.write (fullck + '\n') + + # Paso 5. comparar los md5 + if md5source == md5target: + print ('FALSE (1), No es neceario actualizar. Paso5.A la imagen esta en cache') + return False + else: + print ('imagen en cache distinta, borramos la imagen anterior') + for f in [f'{filetarget}', f'{filetarget}.sum', f'{filetarget}.torrent', f'{filetarget}.full.sum']: + os.unlink (f) + print ('TRUE (0), Si es necesario actualizar.') + return True From b755de21bee28f170823c9c3373db5e053b81354 Mon Sep 17 00:00:00 2001 From: Natalia Serrano Date: Thu, 14 Nov 2024 17:55:09 +0100 Subject: [PATCH 068/167] refs #1150 add a temporal ogConnect() and have ogChangeRepo() use it --- client/lib/engine/bin/NetLib.py | 64 ++++++++++++++++++--------------- 1 file changed, 36 insertions(+), 28 deletions(-) diff --git a/client/lib/engine/bin/NetLib.py b/client/lib/engine/bin/NetLib.py index 793bf73..866196b 100755 --- a/client/lib/engine/bin/NetLib.py +++ b/client/lib/engine/bin/NetLib.py @@ -2,11 +2,28 @@ import subprocess import sys import os import json +import re import ogGlobals import SystemLib import FileLib +def _ogConnect_options(): + ## the original bash code does: eval $(grep "OPTIONS=" /scripts/ogfunctions) + ## this is highly insecure but we need to keep it for now + opt = subprocess.run (['grep', '-o', 'OPTIONS=.*', '/scripts/ogfunctions'], capture_output=True, text=True).stdout.strip() + exec (opt, globals()) + return OPTIONS + +## defined in /scripts/ogfunctions. We can't tackle that yet. +## this is a quick implementation just to unblock development +def _ogConnect (server, protocol, src, dst, options, readonly): + if 'smb' != protocol: return None ## only supported value right now + write_option = ',ro' if readonly else ',rw' + options += write_option + return not subprocess.run (['mount.cifs', f'//{server}/{src}', dst] + options.split()).returncode + + #/** # ogChangeRepo IPREPO [ OgUnit ] #@brief Cambia el repositorio para el recurso remoto images. @@ -15,57 +32,48 @@ import FileLib #@return Cambio recurso remoto en OGIMG. #*/ def ogChangeRepo(ip_repo, og_unit=None): - ogprotocol = "cifs" + ogprotocol = os.environ['ogprotocol'] or 'smb' + + if og_unit: + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_GENERIC, 'the og_unit parameter became unsupported') + return None try: - rw_option = ",rw" if "rw" in subprocess.getoutput("mount | grep 'ogimages'") else ",ro" + mount = subprocess.run (['mount'], capture_output=True, text=True).stdout + ro = not not list (filter (lambda line: re.search (r'ogimages.*\bro,', line), mount.splitlines())) current_repo = ogGetRepoIp() - current_og_unit = subprocess.getoutput( - "df | awk -F ' ' '/ogimages/ {sub(\"//.*/ogimages\",\"\",$1); sub(\"/\",\"\",$1); print $1}'" - ).strip() - new_repo = current_repo if ip_repo.upper() == "REPO" else ip_repo - - if new_repo == current_repo and og_unit == current_og_unit: - return 0 + if new_repo == current_repo: return True subprocess.run(["umount", ogGlobals.OGIMG], check=True) - src_img = "ogimages" if not og_unit else f"ogimages/{og_unit}" - - result = subprocess.run( - ["ogConnect", new_repo, ogprotocol, src_img, ogGlobals.OGIMG, rw_option], - text=True, - ) - - if result.returncode != 0: - subprocess.run( - ["ogConnect", current_repo, ogprotocol, src_img, ogGlobals.OGIMG, rw_option], - text=True, - ) + SystemLib.ogEcho (['session', 'log'], 'info', f'{ogGlobals.lang.MSG_HELP_ogChangeRepo} {new_repo}') + options = _ogConnect_options() + if not _ogConnect (new_repo, ogprotocol, 'ogimages', ogGlobals.OGIMG, options, ro): + _ogConnect (current_repo, ogprotocol, 'ogimages', ogGlobals.OGIMG, options, ro) SystemLib.ogRaiseError( "session", ogGlobals.OG_ERR_REPO, f"Error connecting to the new repository: {new_repo}", ) - return 1 + return False SystemLib.ogEcho( - "session", - "log", - f"Repository successfully changed to {new_repo} {og_unit or ''}".strip(), + ["session", "log"], + 'info', + f"Repository successfully changed to {new_repo}".strip(), ) - return 0 + return True except Exception as e: SystemLib.ogRaiseError( "session", - ogGlobals.OG_ERR_FORMAT, + ogGlobals.OG_ERR_GENERIC, f"Error executing ogChangeRepo: {e}", ) - return 1 + return None #/** # ogGetGroupDir [ str_repo ] From b71e631fb10cfc85a5b21717600eb7c0e142991d Mon Sep 17 00:00:00 2001 From: Natalia Serrano Date: Tue, 19 Nov 2024 12:03:33 +0100 Subject: [PATCH 069/167] refs #1150 add restoreImage.py --- client/lib/engine/bin/DiskLib.py | 43 ++- client/lib/engine/bin/FileSystemLib.py | 376 ++++++++++++------------- client/lib/engine/bin/ImageLib.py | 101 ++++++- client/lib/engine/bin/NetLib.py | 44 +-- client/lib/engine/bin/ProtocolLib.py | 9 +- client/lib/engine/bin/SystemLib.py | 138 +++++---- client/shared/scripts/restoreImage.py | 117 ++++++++ 7 files changed, 527 insertions(+), 301 deletions(-) create mode 100644 client/shared/scripts/restoreImage.py diff --git a/client/lib/engine/bin/DiskLib.py b/client/lib/engine/bin/DiskLib.py index d26ca4d..ddb7168 100755 --- a/client/lib/engine/bin/DiskLib.py +++ b/client/lib/engine/bin/DiskLib.py @@ -8,6 +8,7 @@ from pathlib import Path import ogGlobals import SystemLib import CacheLib +import FileSystemLib def parted(*args): parted_path = shutil.which("parted") @@ -707,32 +708,28 @@ def ogGetPartitionId(*args): print(ID) return -def ogGetPartitionSize(*args): - # Variables locales - PART = None - SIZE = None - # Si se solicita, mostrar ayuda. - if len(args) == 1 and args[0] == "help": - SystemLib.ogHelp('ogGetPartitionSize', 'ogGetPartitionSize int_ndisk int_npartition', 'ogGetPartitionSize 1 1 => 10000000') - return +#/** +# ogGetPartitionSize int_ndisk int_npartition +#@brief Muestra el tamano en KB de una particion determinada. +#@param int_ndisk nº de orden del disco +#@param int_npartition nº de orden de la partición +#@return int_partsize - Tamaño en KB de la partición. +#@exception OG_ERR_FORMAT formato incorrecto. +#@exception OG_ERR_NOTFOUND disco o particion no detectado (no es un dispositivo). +#@note Requisitos: sfdisk, awk +#*/ ## +def ogGetPartitionSize (disk, par): + PART = ogDiskToDev (disk, par) + if PART is None: return - # Error si no se reciben 2 parámetros. - if len(args) != 2: - SystemLib.ogRaiseError(OG_ERR_FORMAT) - return + sz = subprocess.run (['partx', '-gbo', 'SIZE', PART], capture_output=True, text=True).stdout.strip() + if sz: return int (int (sz) / 1024) - # Devolver tamaño de partición, del volumen lógico o del sistema de archivos (para ZFS). - PART = ogDiskToDev(args[0], args[1]) - if PART is None: - return - SIZE = subprocess.getoutput(f"partx -gbo SIZE {PART} 2>/dev/null | awk '{{print int($1/1024)}}'") - if not SIZE: - SIZE = subprocess.getoutput(f"lvs --noheadings -o lv_size --units k {PART} | awk '{{printf \"%d\",$0}}'") - if not SIZE: - SIZE = ogGetFsSize(args[0], args[1]) - print(SIZE or 0) - return + sz = subprocess.run (['lvs', '--noheadings', '-o', 'lv_size', '--units', 'k', PART], capture_output=True, text=True).stdout.strip + if sz: return int (sz) + + return FileSystemLib.ogGetFsSize (disk, par) def ogGetPartitionsNumber(*args): # Variables locales diff --git a/client/lib/engine/bin/FileSystemLib.py b/client/lib/engine/bin/FileSystemLib.py index 384c969..ab7ead1 100755 --- a/client/lib/engine/bin/FileSystemLib.py +++ b/client/lib/engine/bin/FileSystemLib.py @@ -6,6 +6,7 @@ import ogGlobals import SystemLib import DiskLib import CacheLib +import FileSystemLib def ogCheckFs(int_ndisk, int_nfilesys): # Si se solicita, mostrar ayuda. @@ -171,170 +172,144 @@ def ogExtendFs(): ogUnlock(int(sys.argv[1]), int(sys.argv[2])) return ERRCODE -def ogFormat(int_ndisk, int_nfilesys): - if int_nfilesys.lower() == "cache": - ogFormatCache() + +#/** +# ogFormat int_ndisk int_nfilesys | CACHE +#@see ogFormatFs ogFormatCache +#*/ ## + +def ogFormat (disk, par=None, fs=None, label=None): + if disk.lower() == "cache": + return CacheLib.ogFormatCache() else: - ogFormatFs(int_ndisk, int_nfilesys) + return ogFormatFs (disk, par) -def ogFormatFs(int_ndisk, int_nfilesys, str_label=None): - # Si se solicita, mostrar ayuda. - if str_label == "help": - ogHelp("ogFormatFs", "ogFormatFs int_ndisk int_nfilesys [str_label]", "ogFormatFs 1 1", "ogFormatFs 1 1 EXT4", "ogFormatFs 1 1 \"DATA\"", "ogFormatFs 1 1 EXT4 \"DATA\"") + +#/** +# ogFormatFs int_ndisk int_nfilesys [type_fstype] [str_label] +#@brief Formatea un sistema de ficheros según el tipo de su partición. +#@param int_ndisk nº de orden del disco +#@param int_nfilesys nº de orden del sistema de archivos +#@param type_fstype mnemónico de sistema de ficheros a formatear (opcional al reformatear) +#@param str_label etiqueta de volumen (opcional) +#@return (por determinar) +#@exception OG_ERR_FORMAT Formato de ejecución incorrecto. +#@exception OG_ERR_NOTFOUND Disco o particion no corresponden con un dispositivo. +#@exception OG_ERR_PARTITION Partición no accesible o desconocida. +#@note Requisitos: mkfs* +#@warning No formatea particiones montadas ni bloqueadas. +#@todo Definir salidas. +#*/ ## +def ogFormatFs (disk, par, type=None, label=None): + PART = DiskLib.ogDiskToDev (disk, par) + if not PART: return + + if ogIsMounted (disk, par): + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_DONTFORMAT, f'{ogGlobals.lang.MSG_MOUNT}: {disk} {par}') + return None + if ogIsLocked (disk, par): + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_LOCKED, f"{disk} {par}") + return None + + if not type: + type = ogGetFsType (disk, par) + + if not type: + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_FORMAT, f"{disk} {par} ...") + return None + + data = { + 'EXT2': { 'PROG': 'mkfs.ext2', 'PARAMS': '-F' }, + 'EXT3': { 'PROG': 'mkfs.ext3', 'PARAMS': '-F' }, + 'EXT4': { 'PROG': 'mkfs.ext4', 'PARAMS': '-F' }, + 'BTRFS': { 'PROG': 'mkfs.btrfs', 'PARAMS': '-f' }, + 'REISERFS': { 'PROG': 'mkfs.reiserfs', 'PARAMS': '-f', 'LABELPARAM': '-l' }, + 'REISER4': { 'PROG': 'mkfs.reiser4', 'PARAMS': '-f', 'INPUT': 'y\n' }, + 'XFS': { 'PROG': 'mkfs.xfs', 'PARAMS': '-f' }, + 'JFS': { 'PROG': 'mkfs.jfs', 'INPUT': 'y\n' }, + 'F2FS': { 'PROG': 'mkfs.f2fs', 'LABELPARAM': '-l' }, + 'NILFS2': { 'PROG': 'mkfs.nilfs2', 'PARAMS': '-f' }, + 'LINUX-SWAP': { 'PROG': 'mkswap' }, + 'NTFS': { 'PROG': 'mkntfs', 'PARAMS': '-f' }, + 'EXFAT': { 'PROG': 'mkfs.exfat', 'LABELPARAM': '-n' }, + 'FAT32': { 'PROG': 'mkdosfs', 'PARAMS': '-F 32', 'LABELPARAM': '-n' }, + 'FAT16': { 'PROG': 'mkdosfs', 'PARAMS': '-F 16', 'LABELPARAM': '-n' }, + 'FAT12': { 'PROG': 'mkdosfs', 'PARAMS': '-F 12', 'LABELPARAM': '-n' }, + 'HFS': { 'PROG': 'mkfs.hfs' }, + 'HFSPLUS': { 'PROG': 'mkfs.hfsplus', 'LABELPARAM': '-v' }, + 'UFS': { 'PROG': 'mkfs.ufs', 'PARAMS': '-O 2' }, + } + if type not in data: + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_PARTITION, f"{disk} {par} {type}") return - # Error si no se reciben entre 2 y 4 parámetros. - if not (2 <= len(sys.argv) <= 4): - ogRaiseError(OG_ERR_FORMAT) + d = data[type] + prog = d['PROG'] + params = d['PARAMS'] if 'PARAMS' in d else '' + labelparam = d['LABELPARAM'] if 'LABELPARAM' in d else '' + input = d['INPUT'] if 'INPUT' in d else '' + + if label == "CACHE": + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_FORMAT, f"{ogGlobals.lang.MSG_RESERVEDVALUE}: CACHE") return + if label: + params = f"{params} {labelparam or '-L'} {label}" - # Obtener fichero de dispositivo. - PART = ogDiskToDev(int_ndisk, int_nfilesys) - if not PART: - return - - # Error si la partición está montada o bloqueada. - if ogIsMounted(int_ndisk, int_nfilesys): - ogRaiseError(OG_ERR_DONTFORMAT, f"{MSG_MOUNT}: {int_ndisk} {int_nfilesys}") - return - if ogIsLocked(int_ndisk, int_nfilesys): - ogRaiseError(OG_ERR_LOCKED, f"{int_ndisk} {int_nfilesys}") - return - - # Si no se indica el tipo de sistema de archivos, intentar obtenerlo. - TYPE = ogGetFsType(int_ndisk, int_nfilesys) - if not TYPE: - TYPE = sys.argv[3] - - # Error, si no especifica el tipo de sistema de archivos a formatear. - if not TYPE: - ogRaiseError(OG_ERR_FORMAT, f"{int_ndisk} {int_nfilesys} ...") - return - - # Elegir tipo de formato. - if TYPE == "EXT2": - PROG = "mkfs.ext2" - PARAMS = "-F" - elif TYPE == "EXT3": - PROG = "mkfs.ext3" - PARAMS = "-F" - elif TYPE == "EXT4": - PROG = "mkfs.ext4" - PARAMS = "-F" - elif TYPE == "BTRFS": - PROG = "mkfs.btrfs" - PARAMS = "-f" - elif TYPE == "REISERFS": - PROG = "mkfs.reiserfs" - PARAMS = "-f" - LABELPARAM = "-l" - elif TYPE == "REISER4": - PROG = "mkfs.reiser4" - PARAMS = "-f <<<\"y\"" - elif TYPE == "XFS": - PROG = "mkfs.xfs" - PARAMS = "-f" - elif TYPE == "JFS": - PROG = "mkfs.jfs" - PARAMS = "<<<\"y\"" - elif TYPE == "F2FS": - PROG = "mkfs.f2fs" - LABELPARAM = "-l" - elif TYPE == "NILFS2": - PROG = "mkfs.nilfs2" - PARAMS = "-f" - elif TYPE == "LINUX-SWAP": - PROG = "mkswap" - elif TYPE == "NTFS": - PROG = "mkntfs" - PARAMS = "-f" - elif TYPE == "EXFAT": - PROG = "mkfs.exfat" - LABELPARAM = "-n" - elif TYPE == "FAT32": - PROG = "mkdosfs" - PARAMS = "-F 32" - LABELPARAM = "-n" - elif TYPE == "FAT16": - PROG = "mkdosfs" - PARAMS = "-F 16" - LABELPARAM = "-n" - elif TYPE == "FAT12": - PROG = "mkdosfs" - PARAMS = "-F 12" - LABELPARAM = "-n" - elif TYPE == "HFS": - PROG = "mkfs.hfs" - elif TYPE == "HFSPLUS": - PROG = "mkfs.hfsplus" - LABELPARAM = "-v" - elif TYPE == "UFS": - PROG = "mkfs.ufs" - PARAMS = "-O 2" - else: - ogRaiseError(OG_ERR_PARTITION, f"{int_ndisk} {int_nfilesys} {TYPE}") - return - - # Etiquetas de particion. - if not str_label: - if sys.argv[4] == "CACHE": - ogRaiseError(OG_ERR_FORMAT, f"{MSG_RESERVEDVALUE}: CACHE") - return - if len(sys.argv) >= 4: - PARAMS = f"{PARAMS} {LABELPARAM or '-L'} {sys.argv[4]}" - else: - PARAMS = f"{PARAMS} {LABELPARAM or '-L'} {str_label}" - - # Formatear en modo uso exclusivo (desmontar siempre). - ogLock(int_ndisk, int_nfilesys) + ogLock (disk, par) + subprocess.run (['umount', PART]) try: - subprocess.run([PROG, PARAMS, PART], capture_output=True) - ERRCODE = 0 + if input: + errcode = subprocess.run ([prog, params, PART]) + else: + errcode = subprocess.run ([prog, params, PART], input=input, text=True) except FileNotFoundError: - ogRaiseError(OG_ERR_NOTEXEC, PROG) - ERRCODE = OG_ERR_NOTEXEC + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTEXEC, prog) + errcode = ogGlobals.OG_ERR_NOTEXEC except: - ogRaiseError(OG_ERR_PARTITION, f"{int_ndisk} {int_nfilesys}") - ERRCODE = OG_ERR_PARTITION + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_PARTITION, f"{disk} {par}") + errcode = ogGlobals.OG_ERR_PARTITION - ogUnlock(int_ndisk, int_nfilesys) - return ERRCODE + ogUnlock (disk, par) + return errcode -def ogGetFsSize(int_ndisk, int_npartition, str_unit=None): - # Si se solicita, mostrar ayuda. - if str_unit == "help": - ogHelp("ogGetFsSize", "ogGetFsSize int_ndisk int_npartition [str_unit]", "ogGetFsSize 1 1", "ogGetFsSize 1 1 KB") - return - # Error si no se reciben 2 o 3 parámetros. - if not (2 <= len(sys.argv) <= 3): - ogRaiseError(OG_ERR_FORMAT) - return +#/** +# ogGetFsSize int_ndisk int_npartition [str_unit] +#@brief Muestra el tamanio del sistema de archivos indicado, permite definir la unidad de medida, por defecto GB +#@param int_ndisk nº de orden del disco +#@param int_npartition nº de orden de la partición +#@param str_unit unidad (opcional, por defecto: KB) +#@return float_size - Tamaño del sistema de archivos +#@note str_unit = { KB, MB, GB, TB } +#@exception OG_ERR_FORMAT Formato incorrecto. +#@exception OG_ERR_NOTFOUND Disco o partición no corresponden con un dispositivo. +#*/ ## - # Obtener unidad y factor de medida. - UNIT = str_unit or "KB" - FACTOR = 1 - if UNIT.upper() == "MB": - FACTOR = 1024 - elif UNIT.upper() == "GB": - FACTOR = 1024 * 1024 - elif UNIT.upper() == "TB": - FACTOR = 1024 * 1024 * 1024 - elif UNIT.upper() != "KB": - ogRaiseError(OG_ERR_FORMAT, f"{UNIT} != {{ KB, MB, GB, TB }}") +def ogGetFsSize (disk, par, unit=None): + u = unit or "KB" + factor = 1 + if u.upper() == "MB": + factor = 1024 + elif u.upper() == "GB": + factor = 1024 * 1024 + elif u.upper() == "TB": + factor = 1024 * 1024 * 1024 + elif u.upper() != "KB": + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_FORMAT, f"{unit} != {{ KB, MB, GB, TB }}") return # Obtener el tamaño del sistema de archivo (si no está formateado; tamaño = 0). - MNTDIR = ogMount(int_ndisk, int_npartition) - if MNTDIR: - result = subprocess.run(["df", "-BK", MNTDIR], capture_output=True, text=True) - VALUE = result.stdout.split("\n")[1].split()[1] - SIZE = float(VALUE) / FACTOR + mnt = FileSystemLib.ogMount (disk, par) + if mnt: + result = subprocess.run(["df", "-BK", mnt], capture_output=True, text=True) + val = result.stdout.split("\n")[1].split()[1] + val = val.replace ('K', '') + sz = int (val) / factor else: - SIZE = 0 + sz = 0 + + return int (sz) - # Devolver el tamaño (quitar decimales si son 0). - return int(SIZE) if SIZE.is_integer() else SIZE #/** # ogGetFsType int_ndisk int_nfilesys @@ -461,26 +436,24 @@ def ogIsLocked(disk, par): def ogIsPartitionLocked(disk, par): DISK = DiskLib.ogDiskToDev(disk) PART = DiskLib.ogDiskToDev(disk, par) + print (f'nati: ogIsPartitionLocked: DISK ({DISK}) PART ({PART})') if not PART: return LOCKDISK = f"/var/lock/lock{DISK.replace('/', '-')}" LOCKPART = f"/var/lock/lock{PART.replace('/', '-')}" - return os.path.isfile(LOCKDISK) or os.path.isfile(LOCKPART) + rc = os.path.isfile(LOCKDISK) or os.path.isfile(LOCKPART) + print (f'nati: ogIsPartitionLocked: LOCKDISK ({LOCKDISK}) LOCKPART ({LOCKPART}) rc ({rc})') + return rc -def ogIsMounted(int_ndisk, int_nfilesys): - # Si se solicita, mostrar ayuda. - if len(sys.argv) == 3 and sys.argv[2] == "help": - ogHelp("ogIsMounted", "ogIsMounted int_ndisk int_nfilesys", "ogIsMounted 1 1") - return - - # Error si no se reciben 2 parámetros. - if len(sys.argv) != 3: - ogRaiseError(OG_ERR_FORMAT) - return - - # Obtener punto de montaje. - MNTDIR = ogGetMountPoint(int_ndisk, int_nfilesys) - return bool(MNTDIR) +#/** +# ogIsMounted int_ndisk int_nfilesys +#@brief Comprueba si un sistema de archivos está montado. +#@param int_ndisk nº de orden del disco +#@param int_nfilesys nº de orden del sistema de archivos +#@return Código de salida: 0 - montado, 1 - sin montar o error. +#*/ ## +def ogIsMounted (disk, par): + return bool (ogGetMountPoint (disk, par)) #/** @@ -523,28 +496,31 @@ def ogIsWritable(int_ndisk, int_nfilesys): options = result.stdout.strip().split(",") return "rw" in options -def ogLock(int_ndisk, int_nfilesys): - ogLockPartition(int_ndisk, int_nfilesys) -def ogLockPartition(int_ndisk, int_npartition): - # Si se solicita, mostrar ayuda. - if len(sys.argv) == 3 and sys.argv[2] == "help": - ogHelp("ogLockPartition", "ogLockPartition int_ndisk int_npartition", "ogLockPartition 1 1") - return +#/** +# ogLock int_ndisk int_npartition +#@see ogLockPartition +#*/ +def ogLock(disk, par): + return ogLockPartition(disk, par) - # Error si no se reciben 2 parámetros. - if len(sys.argv) != 3: - ogRaiseError(OG_ERR_FORMAT) - return +#/** +# ogLockPartition int_ndisk int_npartition +#@brief Genera un fichero de bloqueo para una partición en uso exlusivo. +#@param int_ndisk nº de orden del disco +#@param int_npartition nº de orden de la partición +#@return (nada) +#@exception OG_ERR_FORMAT Formato incorrecto. +#@exception OG_ERR_NOTFOUND Disco o particion no corresponden con un dispositivo. +#@note El fichero de bloqueo se localiza en \c /var/lock/part, siendo \c part el dispositivo de la partición, sustituyendo el carácter "/" por "-". +#*/ ## +def ogLockPartition (disk, par): + PART = DiskLib.ogDiskToDev (disk, par) + if not PART: return - # Obtener partición. - PART = ogDiskToDev(int_ndisk, int_npartition) - if not PART: - return - - # Crear archivo de bloqueo exclusivo. LOCKFILE = f"/var/lock/lock{PART.replace('/', '-')}" - open(LOCKFILE, 'a').close() + open(LOCKFILE, 'w').close() + return True #/** @@ -580,7 +556,6 @@ def ogMountFirstFs(int_ndisk): #@exception OG_ERR_NOTFOUND Disco o particion no corresponden con un dispositivo. #@exception OG_ERR_PARTITION Tipo de particion desconocido o no se puede montar. #*/ ## - def ogMountFs (disk, par): dev = DiskLib.ogDiskToDev (disk, par) if not dev: return @@ -589,6 +564,7 @@ def ogMountFs (disk, par): if mntdir: return mntdir if ogIsLocked (disk, par): + print (f'nati: ogMountFs: is locked disk ({disk}) par ({par})') SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_LOCKED, f"{ogGlobals.lang.MSG_PARTITION}, {disk} {par}") return @@ -727,26 +703,28 @@ def ogReduceFs(int_ndisk, int_nfilesys): # Devuelve tamaño del sistema de ficheros. return ogGetFsSize(int_ndisk, int_nfilesys) -def ogUnlock(int_ndisk, int_npartition): - ogUnlockPartition(int_ndisk, int_npartition) -def ogUnlockPartition(int_ndisk, int_npartition): - # Si se solicita, mostrar ayuda. - if len(sys.argv) == 3 and sys.argv[2] == "help": - ogHelp("ogUnlockPartition", "ogUnlockPartition int_ndisk int_npartition", "ogUnlockPartition 1 1") - return +#/** +# ogUnlock int_ndisk int_npartition +#@see ogUnlockPartition +#*/ ## +def ogUnlock (disk, par): + return ogUnlockPartition (disk, par) - # Error si no se reciben 2 parámetros. - if len(sys.argv) != 3: - ogRaiseError(OG_ERR_FORMAT) - return +#/** +# ogUnlockPartition int_ndisk int_npartition +#@brief Elimina el fichero de bloqueo para una particion. +#@param int_ndisk nº de orden del disco +#@param int_npartition nº de orden de la partición +#@return (nada) +#@exception OG_ERR_FORMAT Formato incorrecto. +#@exception OG_ERR_NOTFOUND Disco o particion no corresponden con un dispositivo. +#@note El fichero de bloqueo se localiza en \c /var/lock/part, siendo \c part el dispositivo de la partición, sustituyendo el carácter "/" por "-". +#*/ ## +def ogUnlockPartition (disk, par): + PART = DiskLib.ogDiskToDev (disk, par) + if not PART: return - # Obtener partición. - PART = ogDiskToDev(int_ndisk, int_npartition) - if not PART: - return - - # Borrar archivo de bloqueo exclusivo. LOCKFILE = f"/var/lock/lock{PART.replace('/', '-')}" os.remove(LOCKFILE) @@ -756,7 +734,7 @@ def ogUnlockPartition(int_ndisk, int_npartition): #@see ogUnmountFs #*/ ## def ogUnmount (disk, par): - ogUnmountFs (disk, par) + return ogUnmountFs (disk, par) #/** # ogUnmountFs int_ndisk int_nfilesys @@ -793,8 +771,10 @@ def ogUnmountFs(disk, par): os.remove(MNTDIR) except: pass + return True else: SystemLib.ogEcho ([], "warning", f'{ogGlobals.lang.MSG_DONTMOUNT}: "{disk},{par}"') + return True #/** diff --git a/client/lib/engine/bin/ImageLib.py b/client/lib/engine/bin/ImageLib.py index 348b32c..936eaeb 100644 --- a/client/lib/engine/bin/ImageLib.py +++ b/client/lib/engine/bin/ImageLib.py @@ -267,6 +267,17 @@ def ogRestoreImageSyntax (imgfile, part, tool=None, level=None): #@note repo = { REPO, CACHE } #@exception OG_ERR_FORMAT formato incorrecto. #*/ ## +#ogIsImageLocked ('/opt/opengnsys/images/aula1/win7.img') +#ogIsImageLocked ('REPO', '/aula1/win7.img') +def ogIsImageLocked (container=None, imgfile=None): + if container and imgfile: + p = FileLib.ogGetPath (src=container, file=f'{imgfile}.lock') + elif imgfile: + p = FileLib.ogGetPath (file=f'{imgfile}.lock') + else: + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_FORMAT, f'{container} {imgfile}') + return + return os.path.exists (p) #/** @@ -315,6 +326,68 @@ def ogRestoreImageSyntax (imgfile, part, tool=None, level=None): #@exception OG_ERR_IMGSIZEPARTITION 30 Tamaño de la particion es menor al tamaño de la imagen. #@todo Comprobar incongruencias partición-imagen, control de errores, definir parámetros, caché/repositorio, etc. #*/ ## +#ogRestoreImage ('REPO', '/aula1/win7', '1', '1') +def ogRestoreImage (repo, imgpath, disk, par): + PART = DiskLib.ogDiskToDev (disk, par) + if not PART: + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTFOUND, f' {disk} {par}') + return None + + imgtype = 'img' + imgfile = FileLib.ogGetPath (repo, f'{imgpath}.{imgtype}') + if not os.path.exists (imgfile): + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTFOUND, f' {disk} {par}') + return None + + if not ogGetImageInfo (imgfile): + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_IMAGE, f' {repo} {imgpath}') + return None + + # Error si la imagen no cabe en la particion. + imgsize = ogGetImageSize (repo, imgpath) + if not imgsize: + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_IMAGE, f' {repo} {imgpath}') + return None + if not FileSystemLib.ogMount (disk, par): + FileSystemLib.ogFormat (disk, par) + partsize = DiskLib.ogGetPartitionSize (disk, par) + if float (imgsize) > float (partsize): + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_IMGSIZEPARTITION, f' {partsize} < {imgsize}') + return None + + if ogIsImageLocked (container=None, imgfile=imgfile): + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_LOCKED, f'{ogGlobals.lang.MSG_IMAGE} {repo}, {imgpath}.{imgtype}') + return None + + if FileSystemLib.ogIsLocked (disk, par): + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_LOCKED, f'{ogGlobals.lang.MSG_PARTITION} {disk}, {par}') + return None + + program = ogRestoreImageSyntax (imgfile, PART) + + if not FileSystemLib.ogUnmount (disk, par): + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_PARTITION, f' {disk} {par}') + return None + + if not FileSystemLib.ogLock (disk, par): + print (f'not FileSystemLib.ogLock()') + return None + + rc = None + try: + print (f'nati: ogRestoreImage: running ({program})') + p = subprocess.run (program, shell=True, capture_output=True, text=True) + rc = p.returncode + print (f'nati: ogRestoreImage: rc ({rc}) stdout ({p.stdout}) stderr ({p.stderr})') + if not rc: + SystemLib.ogRaiseError ([], ogGlobalsOG_ERR_IMAGE, f'{imgfile}, {disk}, {par}') + except: + pass + finally: + FileSystemLib.ogUnlock (disk, par) + + return rc + #/** @@ -516,6 +589,14 @@ def ogGetImageInfo (imgfile): #@note ogGetImageProgram REPO imagenA -> partclone #*/ ## +#ogGetImageProgram ('REPO', 'prueba') ==> 'PARTCLONE' +def ogGetImageProgram (container, filename): + imgfile = FileLib.ogGetPath (container, f'{filename}.img') + if not os.path.exists (imgfile): + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTFOUND, imgfile) + return None + i = ogGetImageInfo (imgfile) + return i.split (':')[0] #/** # ogGetImageCompressor str_REPO str_imagen @@ -529,6 +610,15 @@ def ogGetImageInfo (imgfile): #@note ogGetImageCompressor REPO imagenA -> lzop #*/ ## +#ogGetImageCompressor ('REPO', 'prueba') ==> 'LZOP' +def ogGetImageCompressor (container, filename): + imgfile = FileLib.ogGetPath (container, f'{filename}.img') + if not os.path.exists (imgfile): + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTFOUND, imgfile) + return None + i = ogGetImageInfo (imgfile) + return i.split (':')[1] + #/** # ogGetImageType str_REPO str_imagen @@ -544,7 +634,7 @@ def ogGetImageInfo (imgfile): #ogGetImageType ('REPO', 'imgprueba') ==> 'NTFS' #ogGetImageType ('CACHE', 'testimg') ==> 'EXTFS' def ogGetImageType (repo, imgname): - imgfile = FileLib.ogGetPath (src=repo, file=imgname) + imgfile = FileLib.ogGetPath (src=repo, file=f'{imgname}.img') if not os.path.exists (imgfile): SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTFOUND, imgfile) return None @@ -565,6 +655,15 @@ def ogGetImageType (repo, imgname): #@exception OG_ERR_NOTFOUND fichero no encontrado. #@note ogGetImagesize REPO imagenA -> 56432234 > Kb #*/ ## +#ogGetImageSize ('REPO', 'prueba') ==> '5642158' +def ogGetImageSize (repo, imgname): + imgfile = FileLib.ogGetPath (src=repo, file=f'{imgname}.img') + if not os.path.exists (imgfile): + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTFOUND, imgfile) + return None + + i = ogGetImageInfo (imgfile) + return i.split (':')[3] #/** diff --git a/client/lib/engine/bin/NetLib.py b/client/lib/engine/bin/NetLib.py index 866196b..e3603fd 100755 --- a/client/lib/engine/bin/NetLib.py +++ b/client/lib/engine/bin/NetLib.py @@ -40,7 +40,7 @@ def ogChangeRepo(ip_repo, og_unit=None): try: mount = subprocess.run (['mount'], capture_output=True, text=True).stdout - ro = not not list (filter (lambda line: re.search (r'ogimages.*\bro,', line), mount.splitlines())) + ro = bool (list (filter (lambda line: re.search (r'ogimages.*\bro,', line), mount.splitlines()))) current_repo = ogGetRepoIp() new_repo = current_repo if ip_repo.upper() == "REPO" else ip_repo @@ -48,7 +48,7 @@ def ogChangeRepo(ip_repo, og_unit=None): subprocess.run(["umount", ogGlobals.OGIMG], check=True) - SystemLib.ogEcho (['session', 'log'], 'info', f'{ogGlobals.lang.MSG_HELP_ogChangeRepo} {new_repo}') + SystemLib.ogEcho (['session', 'log'], None, f'{ogGlobals.lang.MSG_HELP_ogChangeRepo} {new_repo}') options = _ogConnect_options() if not _ogConnect (new_repo, ogprotocol, 'ogimages', ogGlobals.OGIMG, options, ro): _ogConnect (current_repo, ogprotocol, 'ogimages', ogGlobals.OGIMG, options, ro) @@ -61,7 +61,7 @@ def ogChangeRepo(ip_repo, og_unit=None): SystemLib.ogEcho( ["session", "log"], - 'info', + None, f"Repository successfully changed to {new_repo}".strip(), ) @@ -164,28 +164,30 @@ def ogGetHostname(): #@note Usa las variables utilizadas por el initrd "/etc/net-ethX.conf #*/ ## def ogGetIpAddress(): - IP = "" - - if len(sys.argv) >= 2 and sys.argv[1] == "help": - SystemLib.ogHelp("ogGetIpAddress", "ogGetIpAddress", "ogGetIpAddress => 192.168.0.10") - return - if "IPV4ADDR" in os.environ: - IP = os.environ["IPV4ADDR"] - else: - # Obtener direcciones IP. - if "DEVICE" in os.environ: - IP = subprocess.run(["ip", "-o", "address", "show", "up", "dev", os.environ["DEVICE"]], stdout=subprocess.PIPE, stderr=subprocess.DEVNULL).stdout.decode().split() - else: - IP = subprocess.run(["ip", "-o", "address", "show", "up"], stdout=subprocess.PIPE, stderr=subprocess.DEVNULL).stdout.decode().split() + ip = os.environ["IPV4ADDR"] + if '/' in ip: ip = ip.split ('/')[0] + return ip - IP = [addr.split("/")[0] for addr in IP if "inet" in addr] + extra_args = [] + if "DEVICE" in os.environ: + extra_args = [ "dev", os.environ["DEVICE"] ] + ipas = subprocess.run (['ip', '-json', 'address', 'show', 'up'] + extra_args, capture_output=True, text=True).stdout - # Mostrar solo la primera. - if IP: - print(IP[0]) + ipasj = json.loads (ipas) + addresses = [] + for e in ipasj: + if 'lo' == e['ifname']: continue + if 'addr_info' not in e: continue + addrs = e['addr_info'] + for a in addrs: + if 'inet' != a['family']: continue + addresses.append ({ 'local': a['local'], 'prefixlen': a['prefixlen'] }) + + if 1 != len (addresses): + raise Exception ('more than one local IP address found') + return addresses[0] - return 0 #/** # ogGetMacAddress diff --git a/client/lib/engine/bin/ProtocolLib.py b/client/lib/engine/bin/ProtocolLib.py index b421307..9912e4c 100644 --- a/client/lib/engine/bin/ProtocolLib.py +++ b/client/lib/engine/bin/ProtocolLib.py @@ -246,9 +246,6 @@ def _clientip(): addresses = [] for e in ipasj: if 'lo' == e['ifname']: continue - if 'vboxnet' in e['ifname']: continue - if 'br-' in e['ifname']: continue - if 'tun' in e['ifname']: continue if 'addr_info' not in e: continue addrs = e['addr_info'] for a in addrs: @@ -642,7 +639,7 @@ def ogMcastReceiverPartition (disk, par, sess, tool, compressor): #*/ ## ## now ogCore takes this responsibility def ogMcastRequest (img, proto): - return + return True ########################################## @@ -754,7 +751,7 @@ def ogTorrentStart (disk=None, par=None, container=None, torrentfile=None, torre if 'peer' == mode: print ('Donwloading Torrent as peer') # Creamos el fichero de resumen por defecto - with open (f'{source}.bf', 'w') as fd: pass + open (f'{source}.bf', 'w').close() # ctorrent controla otro fichero -b ${SOURCE}.bfog subprocess.run (['ctorrent', '-f', '-c', '-X', f'sleep {time}; kill -2 $(pidof ctorrent)', '-C', '100', source, '-s', target, '-b', f'{source}.bfog']) elif 'leecher' == mode: @@ -763,7 +760,7 @@ def ogTorrentStart (disk=None, par=None, container=None, torrentfile=None, torre elif 'seeder' == mode: print ('MODE seeder ctorrent') # Creamos el fichero de resumen por defecto - with open (f'{source}.bf', 'w') as fd: pass + open (f'{source}.bf', 'w').close() # ctorrent controla otro fichero -b ${SOURCE}.bfog subprocess.run (['ctorrent', '-f', '-c', '-X', f'sleep {time}; kill -2 $(pidof ctorrent)', '-C', '100', source, '-s', target, '-b', f'{source}.bfog']) else: diff --git a/client/lib/engine/bin/SystemLib.py b/client/lib/engine/bin/SystemLib.py index c26eb42..66f0664 100755 --- a/client/lib/engine/bin/SystemLib.py +++ b/client/lib/engine/bin/SystemLib.py @@ -2,10 +2,14 @@ import subprocess import datetime from zoneinfo import ZoneInfo import sys -import os +import os import shutil import inspect +## for ogExecAndLog +from io import StringIO +from contextlib import redirect_stdout, redirect_stderr + import ogGlobals import StringLib @@ -14,9 +18,9 @@ import StringLib #OGLOGSESSION, OGLOGCOMMAND, OGLOGFILE, OG_ERR_LOCKED, OG_ERR_PARTITION, OG_ERR_FORMAT, OG_ERR_NOTEXEC, OG_ERR_NOTFOUND def _logtype2logfile (t): - if 'log' == t: return ogGlobals.OGLOGFILE - elif 'command' == t: return ogGlobals.OGLOGCOMMAND - elif 'session' == t: return ogGlobals.OGLOGSESSION + if 'log' == t.lower(): return ogGlobals.OGLOGFILE + elif 'command' == t.lower(): return ogGlobals.OGLOGCOMMAND + elif 'session' == t.lower(): return ogGlobals.OGLOGSESSION else: raise Exception (f'unknown log type ({t})') #/** # ogEcho [str_logtype ...] [str_loglevel] "str_message" ... @@ -51,58 +55,88 @@ def ogEcho (logtypes, loglevel, msg): else: raise Exception (f'unknown loglevel ({loglevel})') -def ogExecAndLog(*args): - # Variables locales - ISCOMMAND = False - ISLOG = False - ISSESSION = False - COMMAND = "" - CONTINUE = 1 - FILES = "" - REDIREC = "" - FUNCNAME = ogExecAndLog.__name__ - # Si se solicita, mostrar ayuda. - if len(args) > 0 and args[0] == "help": - ogHelp(f"{FUNCNAME} str_logfile ... str_command ...", - f"{FUNCNAME} COMMAND ls -al /") +#/** +# ogExecAndLog str_logfile ... str_command ... +#@brief Ejecuta un comando y guarda su salida en fichero de registro. +#@param str_logfile fichero de registro (pueden ser varios). +#@param str_command comando y comandos a ejecutar. +#@return Salida de ejecución del comando. +#@note str_logfile = { LOG, SESSION, COMMAND } +#*/ +#ogHelp (str_logfile ... str_command ...", +#ogHelp ([], ogMyLib.ogSomeMethod, *args, **kwargs) +#ogHelp ('command', ogMyLib.ogSomeMethod, *args, **kwargs) +#ogHelp (['command'], ogMyLib.ogSomeMethod, *args, **kwargs) +#ogHelp (['log', 'command'], ogMyLib.ogSomeMethod, *args, **kwargs) +def ogExecAndLog (logtypes, fun, *args, **kwargs): + logfiles = ['/dev/stdout'] + if type (logtypes) is list: + for l in logtypes: + logtypes = list (map (lambda x: x.lower(), logtypes)) + logfiles.append (_logtype2logfile (l)) + else: ## string + logtypes = logtypes.lower() + logfiles.append (_logtype2logfile (logtypes)) + + if not fun: + ogRaiseError ([], ogGlobals.OG_ERR_FORMAT, 'no function provided') return - # Procesar parámetros. - while CONTINUE: - arg = args.pop(0).lower() - if arg == "command": - ISCOMMAND = True - continue - elif arg == "log": - ISLOG = True - continue - elif arg == "session": - ISSESSION = True - continue - else: - COMMAND = " ".join(args) - CONTINUE = 0 + ## the original bash code does something like this: + #if [ $ISCOMMAND ]; then + # > $OGLOGCOMMAND + # REDIREC="2>&1" + #fi + #eval $COMMAND $REDIREC | tee -a $FILES - # Error si no se recibe un comando que ejecutar. - if not COMMAND: - ogRaiseError(OG_ERR_FORMAT) - return + ## a hybrid bash/python pseudocode would end up being like the following: + #if 'command' in logtypes: + # rm $OGLOGCOMMAND + # touch $OGLOGCOMMAND + # + #if 'command' in logtypes: + # ## redirect both stdout and stderr + # eval $COMMAND 2>&1 | tee -a $FILES + #else: + # ## redirect stdout only + # eval $COMMAND | tee -a $FILES - # Componer lista de ficheros de registro. - if ISCOMMAND: - FILES = OGLOGCOMMAND - open(FILES, "w").close() - REDIREC = "2>&1" - if ISLOG: - FILES += " " + OGLOGFILE - if ISSESSION: - FILES += " " + OGLOGSESSION + import time + sout = serr = '' + if 'command' in logtypes: + os.unlink (ogGlobals.OGLOGCOMMAND) + open (ogGlobals.OGLOGCOMMAND, 'w').close() + print ('nati: ogExecAndLog: about to redirect stdout and stderr') + time.sleep (1) ## nati + with redirect_stdout (StringIO()) as r_stdout, redirect_stderr (StringIO()) as r_stderr: + rc = fun (*args, **kwargs) + sout = r_stdout.getvalue() + serr = r_stderr.getvalue() + print (f'nati: ogExecAndLog: end of redirections, rc ({rc}) sout ({sout}) serr ({serr})') + time.sleep (1) ## nati + else: + print ('nati: ogExecAndLog: about to redirect stdout only') + time.sleep (1) + with redirect_stdout (StringIO()) as r_stdout: + rc = fun (*args, **kwargs) + sout = r_stdout.getvalue() + print (f'nati: ogExecAndLog: end of redirections, rc ({rc}) sout ({sout})') + time.sleep (1) ## nati - # Ejecutar comando. - subprocess.call(f"{COMMAND} {REDIREC} | tee -a {FILES}", shell=True) - # Salida de error del comando ejecutado. - return subprocess.PIPESTATUS[0] + if sout or serr: + print ('nati: ogExecAndLog: sout or serr are true') + time.sleep (1) ## nati + for f in logfiles: + print (f'nati: ogExecAndLog: logging to logfile ({f})') + with open (f, 'a') as fd: + if sout: fd.write (f"ogExecAndLog: {fun.__name__} stdout:\n{sout}") + else: fd.write (f"ogExecAndLog: {fun.__name__} stdout: (none)\n") + if serr: fd.write (f"ogExecAndLog: {fun.__name__} stderr:\n{serr}") + else: fd.write (f"ogExecAndLog: {fun.__name__} stderr: (none)\n") + + print (f'nati: ogExecAndLog: returning rc ({rc})') + return rc #/** # ogGetCaller @@ -211,14 +245,14 @@ def ogRaiseError (logtypes, code, msg): CODE = ogGlobals.OG_ERR_GENERIC call_stack = [i[3] for i in inspect.stack()] - if len (call_stack) < 3: return ## shouldn't happen + if len (call_stack) < 2: return ## shouldn't happen call_stack.pop() ## remove '' call_stack.pop(0) ## remove 'ogRaiseError' str_call_stack = ' '.join (call_stack) if code == ogGlobals.OG_ERR_FORMAT or \ StringLib.ogCheckStringInGroup (str_call_stack, ogGlobals.NODEBUGFUNCTIONS) or \ - not StringLib.ogCheckStringInGroup (call_stack[0], ogGlobals.NODEBUGFUNCTIONS): + not (len(call_stack)>0 and StringLib.ogCheckStringInGroup (call_stack[0], ogGlobals.NODEBUGFUNCTIONS)): ogEcho (logtypes, "error", f"{str_call_stack.replace(' ', '<-')}: {MSG}") return code diff --git a/client/shared/scripts/restoreImage.py b/client/shared/scripts/restoreImage.py new file mode 100644 index 0000000..f937239 --- /dev/null +++ b/client/shared/scripts/restoreImage.py @@ -0,0 +1,117 @@ +#!/usr/bin/python3 +#/** +#@file restoreImage +#@brief Script de ejemplo para restaurar una imagen. +#@param $1 Repositorio (CACHE, REPO o dirección IP) +#@param $2 Nombre canónico de la imagen (sin extensión) +#@param $3 Número de disco +#@param $4 Número de particion +#@param $5 Protocolo (UNICAST, UNICAST-DIRECT, MULTICAST o MULTICAST-DIRECT) +#@param $6 Opciones del protocolo +#@exception OG_ERR_FORMAT 1 formato incorrecto. +#@exception OG_ERR_NOTFOUND 2 cambio de repositorio: repositorio no encontrado +#@exception OG_ERR_NOTFOUND 2 fichero de imagen o partición no detectados. +#@exception $OG_ERR_MCASTRECEIVERFILE 57 Error en la recepción Multicast de un fichero +#@exception $OG_ERR_PROTOCOLJOINMASTER 60 Error en la conexión de una sesión Unicast|Multicast con el Master +#**/ + +import os +import os.path +import sys +import re +import time + +import ogGlobals +import SystemLib +import NetLib +import StringLib +import FileLib +import ImageLib +import ProtocolLib + +t0 = time.time() +prog = os.path.basename (sys.argv[0]) + +#Load engine configurator from engine.cfg file. +#Carga el configurador del engine desde el fichero engine.cfg +# Valores por defecto: #IMGPROG="partclone" ; #IMGCOMP="lzop" ; #IMGEXT="img" #IMGREDUCE="TRUE" +## (ogGlobals se encarga) + +# Clear temporary file used as log track by httpdlog +# Limpia los ficheros temporales usados como log de seguimiento para httpdlog +open (ogGlobals.OGLOGCOMMAND, 'w').close() +if SystemLib.ogGetCaller() not in ['deployImage', 'restoreImageCustom']: + open (ogGlobals.OGLOGSESSION, 'w').close() + +SystemLib.ogEcho (['log', 'session'], None, f'[1] {ogGlobals.lang.MSG_SCRIPTS_START} {prog} ({sys.argv})') + +# Procesar parámetros de entrada +print (f'argv ({sys.argv}) len ({len (sys.argv)})') +if len (sys.argv) < 6: + SystemLib.ogRaiseError ('session', ogGlobals.OG_ERR_FORMAT, f'{ogGlobals.lang.MSG_FORMAT}: {prog} REPO|CACHE imagen ndisco nparticion [ UNICAST|MULTICAST opciones protocolo]') + sys.exit (1) + +_, repo, imgname, disk, par, *other = sys.argv +proto = other[0].upper() if len (other) > 0 else 'UNICAST' +protoopt = other[1] if len (other) > 1 else '' +repo = repo.upper() +# Si MCASTWAIT menos que tiempo de espera del servidor lo aumento +MCASTWAIT = ogGlobals.MCASTWAIT +if ':' in protoopt: + port, wait = protoopt.split (':') +else: + port, wait = ('', '') +if proto.startswith ('MULTICAST') and re.match (r'^-?\d+$', wait): + if int (MCASTWAIT or 0) < int (wait): + MCASTWAIT = int (wait) + 5 +imgtype = 'img' +print (f'repo ({repo}) imgname ({imgname}) disk ({disk}) par ({par}) proto ({proto}) protoopt ({protoopt}) MCASTWAIT ({MCASTWAIT})') + +# Si es una ip y es igual a la del equipo restaura desde cache +if repo == NetLib.ogGetIpAddress(): repo = 'CACHE' +# Si es una ip y es distinta a la del recurso samba cambiamos de REPO. +if StringLib.ogCheckIpAddress (repo) or 'REPO' == repo: + # Si falla el cambio -> salimos con error repositorio no valido + if not NetLib.ogChangeRepo (repo): + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTFOUND, repo) + sys.exit (1) + REPO = 'REPO' + +# Comprobar que existe la imagen del origen. +imgfile = FileLib.ogGetPath (repo, f'{imgname}.{imgtype}') +imgdir = FileLib.ogGetParentPath (repo, imgname) +print (f'imgfile ({imgfile}) imgdir ({imgdir})') +if not imgfile or not imgdir: + SystemLib.ogRaiseError ('session', ogGlobals.OG_ERR_NOTFOUND, f'{repo}, {imgname}') + sys.exit (1) + +# Procesar protocolos de transferencia. +retval = 0 +if proto in ['UNICAST', 'UNICAST-DIRECT']: + SystemLib.ogEcho (['log', 'session'], None, f'[40] ogRestoreImage {repo} {imgname} {disk} {par} UNICAST') + retval = SystemLib.ogExecAndLog ('command', ImageLib.ogRestoreImage, repo, imgname, disk, par) +elif proto in ['MULTICAST', 'MULTICAST-DIRECT']: + tool = ImageLib.ogGetImageProgram ('REPO', imgname) + if not tool: + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_IMAGE, f'could not get tool used for image {imgname}') + sys.exit (1) + + compress = ImageLib.ogGetImageCompressor ('REPO', imgname) + if not compress: + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_IMAGE, f'could not get compressor used for image {imgname}') + sys.exit (1) + + SystemLib.ogEcho (['log', 'session'], None, f'[40] ogMcastReceiverPartition {disk} {par} {port} {tool} {compress}') + if not ProtocolLib.ogMcastRequest (f'{imgname}.img', protoopt): + sys.exit (1) + retval = SystemLib.ogExecAndLog ('command', ProtocolLib.ogMcastReceiverPartition, disk, par, port, tool, compress) +else: + SystemLib.ogRaiseError ('session', ogGlobals.OG_ERR_FORMAT, f'{ogGlobals.lang.MSG_FORMAT}: {prog} REPO|CACHE imagen ndisco nparticion [ UNICAST|MULTICAST opciones protocolo]') + sys.exit (1) + +t = time.time() - t0 +SystemLib.ogEcho (['log', 'session'], None, f'[100] Duracion de la operacion {int (t/60)}m {int (t%60)}s') + +# Código de salida del comando prinicpal de restauración. +sys.exit (retval) + From d061c6116a660d7be2025cc405a4351f9335e26d Mon Sep 17 00:00:00 2001 From: Antonio Emmanuel Guerrero Silva Date: Tue, 19 Nov 2024 08:53:02 -0600 Subject: [PATCH 070/167] refs #1164 ogRaiseError function call correction --- client/lib/engine/bin/SystemLib.py | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/client/lib/engine/bin/SystemLib.py b/client/lib/engine/bin/SystemLib.py index 66f0664..740eb35 100755 --- a/client/lib/engine/bin/SystemLib.py +++ b/client/lib/engine/bin/SystemLib.py @@ -12,6 +12,7 @@ from contextlib import redirect_stdout, redirect_stderr import ogGlobals import StringLib +import SystemLib #NODEBUGFUNCTIONS, OGIMG, OG_ERR_CACHESIZE, OG_ERR_NOTCACHE, OG_ERR_NOTWRITE, OG_ERR_FILESYS #OG_ERR_REPO, OG_ERR_NOTOS, OG_ERR_NOGPT, OG_ERR_OUTOFLIMIT, OG_ERR_IMAGE, OG_ERR_CACHE @@ -285,7 +286,11 @@ def ogCheckProgram(*args): # Error si no se recibe 1 parámetro. if len(args) != 1: - ogRaiseError(OG_ERR_FORMAT) + SystemLib.ogRaiseError( + "session", + ogGlobals.OG_ERR_FORMAT, + f"Error: {ogGlobals.lang.MSG_ERR_FORMAT} {FUNCNAME} \"str_program ...\"" + ) return PERROR = 0 @@ -296,7 +301,11 @@ def ogCheckProgram(*args): PLOG += f" {i}" if PERROR == 1: - ogRaiseError(OG_ERR_NOTEXEC, PLOG) + SystemLib.ogRaiseError( + "session", + ogGlobals.OG_ERR_NOTEXEC, + f"Error: {PLOG}", + ) return else: return 0 From 6bc47bb1570f988a674ad6940096513324ff00c9 Mon Sep 17 00:00:00 2001 From: Antonio Emmanuel Guerrero Silva Date: Tue, 19 Nov 2024 08:55:33 -0600 Subject: [PATCH 071/167] refs #1164 ogRaiseError function call correction --- client/lib/engine/bin/RegistryLib.py | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/client/lib/engine/bin/RegistryLib.py b/client/lib/engine/bin/RegistryLib.py index 905b0dc..f520520 100755 --- a/client/lib/engine/bin/RegistryLib.py +++ b/client/lib/engine/bin/RegistryLib.py @@ -38,7 +38,11 @@ def ogAddRegistryValue(path_mountpoint, str_hive, str_key, str_valuename, str_va elif str_valuetype.upper() == 'DWORD': TYPE = 4 else: - SystemLib.ogRaiseError(OG_ERR_OUTOFLIMIT, str_valuetype) + SystemLib.ogRaiseError( + "session", + ogGlobals.OG_ERR_OUTOFLIMIT, + f"Error: {str_valuetype}", + ) return # Add the registry value. @@ -83,7 +87,11 @@ def ogGetHivePath(path_mountpoint, str_hive): if FILE and os.path.isfile(FILE): return FILE else: - SystemLib.ogRaiseError(OG_ERR_NOTFOUND, f"{path_mountpoint} {str_hive}") + SystemLib.ogRaiseError( + "session", + ogGlobals.OG_ERR_NOTFOUND, + f"{path_mountpoint} {str_hive}" + ) return None def ogGetRegistryValue(path_mountpoint, str_hive, str_valuename): @@ -161,7 +169,11 @@ def ogSetRegistryValue(path_mountpoint, str_hive, str_valuename, str_data): if f"BINARY.*<{str_valuename.rsplit('\\', 1)[-1]}>" in output: # Procesar tipo binario (incluir nº de bytes y líneas de 16 parejas hexadecimales). if not re.match(r'^([0-9A-F]{2} )*$', str_data): - SystemLib.ogRaiseError(OG_ERR_FORMAT, f'"{str_data}"') + SystemLib.ogRaiseError( + "session", + ogGlobals.OG_ERR_FORMAT, + f'"{str_data}"' + ) return n = len(str_data) + 1 with open(tmpfile, 'w') as f: From 385ddb6ac103fa424e5ba096c51afef1b073c01a Mon Sep 17 00:00:00 2001 From: Antonio Emmanuel Guerrero Silva Date: Tue, 19 Nov 2024 08:57:35 -0600 Subject: [PATCH 072/167] refs #1093 RegistryLib library is added --- client/lib/engine/bin/InventoryLib.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/client/lib/engine/bin/InventoryLib.py b/client/lib/engine/bin/InventoryLib.py index e18730f..48a93ee 100755 --- a/client/lib/engine/bin/InventoryLib.py +++ b/client/lib/engine/bin/InventoryLib.py @@ -10,6 +10,7 @@ import shutil import SystemLib import FileSystemLib import ogGlobals +import RegistryLib MSG_HARDWAREINVENTORY = "Inventario de hardware de la máquina" @@ -42,7 +43,11 @@ def ogGetOsUuid(): # Error si no se reciben 2 parametros. if len(sys.argv) != 3: - SystemLib.ogRaiseError(OG_ERR_FORMAT) + SystemLib.ogRaiseError( + "session", + ogGlobals.OG_ERR_FORMAT, + f"Error: {sys.argv[0]} need 2 arguments.", + ) return # Montar la particion, si no lo estaba previamente. @@ -58,7 +63,7 @@ def ogGetOsUuid(): print(uuid) elif os_type == "Windows": # Leer identificador en clave de registro. - uuid = Registry.ogGetRegistryValue(MNTDIR, "SOFTWARE", "\\Microsoft\\Cryptography\\MachineGuid") + uuid = RegistryLib.ogGetRegistryValue(MNTDIR, "SOFTWARE", "\\Microsoft\\Cryptography\\MachineGuid") print(uuid) def ogGetSerialNumber(): From 88dce42514619d171f9b01072f2b9f45b404ab9d Mon Sep 17 00:00:00 2001 From: Natalia Serrano Date: Wed, 20 Nov 2024 15:34:12 +0100 Subject: [PATCH 073/167] refs #1163 add updateCache.py --- client/lib/engine/bin/CacheLib.py | 93 +++++------ client/lib/engine/bin/FileLib.py | 122 +++++++++----- client/lib/engine/bin/FileSystemLib.py | 68 ++++---- client/lib/engine/bin/NetLib.py | 2 +- client/lib/engine/bin/ogGlobals.py | 4 +- client/shared/scripts/restoreImage.py | 1 + client/shared/scripts/updateCache.py | 218 +++++++++++++++++++++++++ 7 files changed, 386 insertions(+), 122 deletions(-) create mode 100644 client/shared/scripts/updateCache.py diff --git a/client/lib/engine/bin/CacheLib.py b/client/lib/engine/bin/CacheLib.py index a813607..99e543a 100755 --- a/client/lib/engine/bin/CacheLib.py +++ b/client/lib/engine/bin/CacheLib.py @@ -98,60 +98,58 @@ def ogFindCache(): if not PART: return return DiskLib.ogDevToDisk (PART.split()[0]) # usar la 1ª partición encontrada. + +#/** +# ogFormatCache +#@brief Formatea el sistema de ficheros para la caché local. +#@return (por determinar) +#@warning Prueba con formato Reiser. +#@attention +#@note El sistema de archivos de la caché se queda montado. +#*/ ## def ogFormatCache(): - """ - Formatea la partición de caché. - - :raises RuntimeError: Si ocurre un error durante el formateo de la partición. - """ - # Si se solicita, mostrar ayuda. - if len(sys.argv) > 1 and sys.argv[1] == "help": - ogHelp("ogFormatCache", "ogFormatCache") - return - - # Error si no hay definida partición de caché. cachepart = ogFindCache() if cachepart is None: - ogRaiseError(OG_ERR_PARTITION, MSG_NOCACHE) + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_PARTITION, ogGlobals.lang.MSG_NOCACHE) return - disk = ogDiskToDev(cachepart) + disk = DiskLib.ogDiskToDev (cachepart) + if not disk: return - # Formatear sistema de ficheros. ogUnmountCache() options = "extent,large_file" if re.match("^5", platform.release()): options += ",uninit_bg,^metadata_csum,^64bit" + try: subprocess.run(["mkfs.ext4", "-q", "-F", disk, "-L", "CACHE", "-O", options], check=True) except subprocess.CalledProcessError as e: - raise RuntimeError(f"Error al formatear la partición de caché: {e}") + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_PARTITION, "CACHE") + return # Crear estructura básica. mntdir = ogMountCache() - os.makedirs(os.path.join(mntdir, OGIMG), exist_ok=True) + os.makedirs(os.path.join(mntdir, ogGlobals.OGIMG), exist_ok=True) # Incluir kernel e Initrd del ogLive - updateBootCache() + ## como lo llamo sin especificar el path entero? + #subprocess.run (['scripts/updateBootCache.py']) ## TODO + +#/** +# ogGetCacheSize +#@brief Devuelve el tamaño definido para la partición de caché. +#@return int_partsize tamaño de la partición (en KB) +#@exception OG_ERR_PARTITION No existe partición de caché. +#*/ ## def ogGetCacheSize(): - """ - Obtiene el tamaño de la partición de caché. - - :return: Tamaño de la partición de caché en kilobytes. - :raises RuntimeError: Si ocurre un error al obtener el tamaño de la partición de caché. - """ - # Si se solicita, mostrar ayuda. - if len(sys.argv) > 1 and sys.argv[1] == "help": - ogHelp("ogGetCacheSize", "help", "ogGetCacheSize") - - # Error si no se encuentra partición de caché. cachepart = ogFindCache() if cachepart is None: - raise RuntimeError(MSG_NOCACHE) + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_PARTITION, ogGlobals.lang.MSG_NOCACHE) + return - # Devuelve tamaño de la partición de caché. - return ogGetPartitionSize(cachepart) + disk, par = cachepart.split() + return DiskLib.ogGetPartitionSize (disk, par) def ogGetCacheSpace(): """ @@ -204,33 +202,32 @@ def ogGetCacheSpace(): #@warning Salidas de errores no determinada #*/ ## def ogMountCache(): - c = CacheLib.ogFindCache().split() + c = ogFindCache().split() m = FileSystemLib.ogMountFs (c[0], c[1]) if not m: SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_PARTITION, ogGlobals.lang.MSG_NOCACHE) #return return m + +#/** +# ogUnmountCache +#@brief Desmonta la particion Cache y elimina la variable $OGCAC +#@param sin parametros +#@return nada +#@warning Salidas de errores no determinada +#*/ ## def ogUnmountCache(): - """ - Desmonta la partición de caché. - - :raises RuntimeError: Si ocurre un error durante el desmontaje de la partición de caché. - """ - # Si se solicita, mostrar ayuda. - if len(sys.argv) > 1 and sys.argv[1] == "help": - ogHelp("ogUnmountCache", "help", "ogUnmountCache") - - # Obtener la partición de caché. cachepart = ogFindCache() if cachepart is None: - raise RuntimeError("No se encontró la partición de caché.") + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_PARTITION, ogGlobals.lang.MSG_NOCACHE) + return - # Desmontar la partición de caché. - try: - subprocess.run(["umount", cachepart], check=True) - except subprocess.CalledProcessError as e: - raise RuntimeError(f"Error al desmontar la partición de caché: {e}") + if not FileSystemLib.ogIsMounted (cachepart): return True + FileSystemLib.ogUnmountFs (cachepart) # Eliminar el enlace simbólico de /mnt/ParticiónCache. os.remove(f"/mnt/{cachepart}") + dev = ogDiskToDev (cachepart) + dev.replace ('dev', 'mnt') + os.remove (dev) diff --git a/client/lib/engine/bin/FileLib.py b/client/lib/engine/bin/FileLib.py index f25414b..6099dee 100755 --- a/client/lib/engine/bin/FileLib.py +++ b/client/lib/engine/bin/FileLib.py @@ -166,40 +166,58 @@ def ogCalculateFullChecksum (disk=None, par=None, container=None, file=None): #@return Progreso de la copia. #@warning Deben existir tanto el fichero origen como el directorio destino. #*/ ## +#ogCopyFile (src, dst) +#ogCopyFile ({container='REPO', file='newfile.txt'}, {disk=1, par=2, file='/tmp/newfile.txt'}) +#ogCopyFile ({disk=1, par=2, file='/tmp/newfile.txt'}, {container='REPO', file='newfile.txt'}) +def ogCopyFile (src, dst): + for elem in src, dst: + if elem == src: which = 'source' + else: which = 'target' -def ogCopyFile(*args): - # Variables locales. - ARGS = args - if "help" in args: - SystemLib.ogHelp("$FUNCNAME", "$FUNCNAME [ str_repo | int_ndisk int_npartition ] path_source [ str_repo | int_ndisk int_npartition ] path_target", "$FUNCNAME REPO newfile.txt 1 2 /tmp/newfile.txt") - return + if 'file' not in elem: + raise TypeError ('missing required argument in {which} dict:: "file"') - ARGS = args - if args[0].startswith("/"): - # Camino completo. */ (Comentrio Doxygen) - SOURCE = ogGetPath(*args[:1]) - args = args[1:] - elif args[0].isdigit(): - # ndisco npartición. - SOURCE = ogGetPath(*args[:3]) - args = args[3:] - else: - # Otros: repo, cache, cdrom (no se permiten caminos relativos). - SOURCE = ogGetPath(*args[:2]) - args = args[2:] + if 'container' in elem: + if 'disk' not in elem and 'par' not in elem: + ## we were given container= + path = ogGetPath (src=elem['container'], file=elem['file']) + dev_err = f'{elem["container"]} {elem["file"]}' + print (f'ogGetPath {which} (src=({elem["container"]}), file=({elem["file"]})) = path ({path})') + else: + raise TypeError ('argument "container" can be specified along neither "disk" nor "par"') - TARGET = ogGetPath(*args) + else: + if 'disk' in elem and 'par' in elem: + ## we were given disk= par= + path = ogGetPath (src=f'{elem["disk"]} {elem["par"]}', file=elem['file']) + dev_err = f'{elem["disk"]} {elem["par"]} {elem["file"]}' + print (f'ogGetPath {which} (src=({elem["disk"]} {elem["par"]}), file=({elem["file"]})) = path ({path})') + elif 'disk' not in elem and 'par' not in elem: + ## we were given nothing + path = ogGetPath (file=elem['file']) + dev_err = elem['file'] + print (f'ogGetPath {which} (file=({elem["file"]})) = path ({path})') + else: + raise TypeError ('if one of "disk" and "par" are specified, then both must be') + + if elem == src: + SOURCE = path + src_dev_err = dev_err + else: + TARGET = path + dst_dev_err = dev_err - # Comprobar fichero origen y directorio destino. if not SOURCE: - SystemLib.ogRaiseError(OG_ERR_NOTFOUND, *args[:-1]) + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTFOUND, f'device or file {src_dev_err} not found') return if not TARGET: - SystemLib.ogRaiseError(OG_ERR_NOTFOUND, *args) + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTFOUND, f'device or file {dst_dev_err} not found') return + print (f'nati: ogCopyFile: SOURCE ({SOURCE}) TARGET ({TARGET})') # Copiar fichero (para evitar problemas de comunicaciones las copias se hacen con rsync en vez de cp). - result = subprocess.run(["rsync", "--progress", "--inplace", "-avh", SOURCE, TARGET]) + print (f'nati: ogCopyFile: rsync --progress --inplace -avh ({SOURCE}) ({TARGET})') + result = subprocess.run(["rsync", "--progress", "--inplace", "-avh", SOURCE, TARGET], capture_output=True, text=True) return result.returncode @@ -242,7 +260,7 @@ def ogDeleteFile (disk=None, par=None, container=None, file=None): except OSError as e: SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_GENERIC, str (e)) return - + def ogDeleteTree(*args): # Variables locales. DIR = None @@ -408,18 +426,46 @@ def ogMakeChecksumFile(*args): with open(f"{FILE}.sum", "w") as f: f.write(checksum) -def ogMakeDir(*args): - # Variables locales. - PARENT = None - DIR = None - if "help" in args: - SystemLib.ogHelp("$FUNCNAME", "$FUNCNAME [ str_repo | int_ndisk int_npartition ] path_dir", "$FUNCNAME 1 2 /tmp/newdir") + +#/** +# ogMakeDir [ str_repo | int_ndisk int_npartition ] path_dirpath +#@brief Metafunción que crea un subdirectorio vacío en un dispositivo. +#@see ogGetParentPath +#*/ ## +#ogMakeDir (container='REPO', file='/tmp/newdir') +#ogMakeDir (disk='1', par='2', file='/tmp/newdir') +def ogMakeDir (container=None, disk=None, par=None, file=None): + if file is None: + raise TypeError ('missing required argument: "file"') + + if container is not None: + if disk is None and par is None: + ## we were given container= + parent = ogGetParentPath (src=container, file=file) + dev_err = f'{container} {file}' + print (f'ogGetParentPath (src=({container}), file=({file})) = parent ({parent})') + else: + raise TypeError ('argument "container" can be specified along neither "disk" nor "par"') + + else: + if disk is not None and par is not None: + ## we were given disk= par= + parent = ogGetParentPath (src=f'{disk} {par}', file=file) + dev_err = f'{disk} {par} {file}' + print (f'ogGetParentPath (src=({disk} {par}), file=({file})) = parent ({parent})') + elif disk is None and par is None: + ## we were given nothing + parent = ogGetParentPath (file=file) + dev_err = file + print (f'ogGetParentPath (file=({file})) = parent ({parent})') + else: + raise TypeError ('if one of "disk" and "par" are specified, then both must be') + + print (f'nati: ogMakeDir: parent ({parent})') + if not parent: + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTFOUND, f'device or file {dev_err} not found') return - PARENT = ogGetParentPath(*args) - if not PARENT: - SystemLib.ogRaiseError(OG_ERR_NOTFOUND, *args) - return - - DIR = os.path.basename(args[-1]) - os.makedirs(os.path.join(PARENT, DIR), exist_ok=True) + dst = os.path.basename (file) + print (f'nati: ogMakeDir: dst ({dst})') + os.makedirs (os.path.join (parent, dst), exist_ok=True) diff --git a/client/lib/engine/bin/FileSystemLib.py b/client/lib/engine/bin/FileSystemLib.py index ab7ead1..5d9ad14 100755 --- a/client/lib/engine/bin/FileSystemLib.py +++ b/client/lib/engine/bin/FileSystemLib.py @@ -284,17 +284,15 @@ def ogFormatFs (disk, par, type=None, label=None): #@exception OG_ERR_FORMAT Formato incorrecto. #@exception OG_ERR_NOTFOUND Disco o partición no corresponden con un dispositivo. #*/ ## - -def ogGetFsSize (disk, par, unit=None): - u = unit or "KB" +def ogGetFsSize (disk, par, unit='KB'): factor = 1 - if u.upper() == "MB": + if unit.upper() == "MB": factor = 1024 - elif u.upper() == "GB": + elif unit.upper() == "GB": factor = 1024 * 1024 - elif u.upper() == "TB": + elif unit.upper() == "TB": factor = 1024 * 1024 * 1024 - elif u.upper() != "KB": + elif unit.upper() != "KB": SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_FORMAT, f"{unit} != {{ KB, MB, GB, TB }}") return @@ -827,33 +825,37 @@ def ogUnsetDirtyBit(int_ndisk, int_nfilesys): else: pass # Add more specific actions for other file systems if needed. -def ogGetFreeSize(int_ndisk, int_npartition, str_SizeOutput): - if len(sys.argv) == 3 and sys.argv[2] == "help": - ogHelp("ogGetFreeSize", "ogGetFreeSize int_ndisk int_npartition str_SizeOutput", "ogGetFreeSize 1 1 GB") - return - if len(sys.argv) < 3: - ogRaiseError(OG_ERR_FORMAT) - return +#/** +# ogGetFreeSize int_disco int_partition str_SizeOutput +#@brief muestra informacion del tamaño total, datos y libre. +#@param int_ndisk nº de orden del disco +#@param int_npart nº de orden de partición +#@param str_unitSize unidad mostrada +#@return int_size:int_data:int_free +#@TODO Componer corretcamente esta función. +#@exception OG_ERR_FORMAT Formato incorrecto. +#*/ ## - PART = ogDiskToDev(int_ndisk, int_npartition) - if not PART: - return +def ogGetFreeSize(disk, part, unit='KB'): + PART = DiskLib.ogDiskToDev (disk, part) + if not PART: return - unit = str_SizeOutput - if not unit: - unit = "GB" + unit2factor = { + 'kb': 1.024 / 1, + 'mb': 1.024 / 1000, + 'gb': 1.024 / 1000000, + } + if unit.lower() not in unit2factor: + kk + factor = unit2factor[unit.lower()] - factor = 1.024 / 1000000 - if unit == "kB": - factor = 1.024 - elif unit == "MB": - factor = 1.024 / 1000 - - result = subprocess.run(["df", PART], capture_output=True, text=True) - output = result.stdout.strip().split("\n")[1].split() - size = float(output[1]) * factor - used = float(output[2]) * factor - free = float(output[3]) * factor - - return free + particion = FileSystemLib.ogMount (disk, part) + if not particion: + kk + df = subprocess.run (['df'], capture_output=True, text=True).stdout + df_part = list (filter (lambda l: particion in l, df.splitlines())) + if not len (df_part): + kk + _, size, used, free, pct, mntpt = df_part[0].split() + return float (free) * factor diff --git a/client/lib/engine/bin/NetLib.py b/client/lib/engine/bin/NetLib.py index e3603fd..d9e8908 100755 --- a/client/lib/engine/bin/NetLib.py +++ b/client/lib/engine/bin/NetLib.py @@ -221,7 +221,7 @@ def ogGetMacAddress(): mac_addresses.append(parts[i + 1].upper()) if mac_addresses: - print(mac_addresses[0]) + print (f'nati: ogGetMacAddress: {mac_addresses[0]}') return mac_addresses[0] else: print("No active mac address found") diff --git a/client/lib/engine/bin/ogGlobals.py b/client/lib/engine/bin/ogGlobals.py index 3c02f28..946efd8 100755 --- a/client/lib/engine/bin/ogGlobals.py +++ b/client/lib/engine/bin/ogGlobals.py @@ -31,7 +31,7 @@ TZ='Europe/Madrid' OGLOGSESSION='/tmp/session.log' OGLOGCOMMAND='/tmp/command.log' #OGWINCHKDISK=True #Hacer chkdisk tras la clonacion -#ACTIONCACHEFULL=None #Que hacer cuando la cache no tenga espacio libre. [ NONE | FORMAT ] ] +ACTIONCACHEFULL='NONE' #Que hacer cuando la cache no tenga espacio libre. [ NONE | FORMAT ] ] #RESTOREPROTOCOLNOTCACHE=None #Que protocolo de restauracion usar en el caso de que no exista cache o no exista espacio sufiente. [NONE | UNICAST | MULTICAST].NONE retorna error #IMGPROG='partclone' #IMGCOMP='lzop' @@ -109,4 +109,4 @@ OG_ERR_NOTDIFFERENT=73 # No se detectan diferencias entre la image OG_ERR_SYNCHRONIZING=74 # Error al sincronizar, puede afectar la creacion/restauracion de la imagen OG_ERR_NOTUEFI=80 # La interfaz UEFI no está activa -OG_ERR_NOTBIOS=81 # La interfaz BIOS legacy no está activa \ No newline at end of file +OG_ERR_NOTBIOS=81 # La interfaz BIOS legacy no está activa diff --git a/client/shared/scripts/restoreImage.py b/client/shared/scripts/restoreImage.py index f937239..5fce963 100644 --- a/client/shared/scripts/restoreImage.py +++ b/client/shared/scripts/restoreImage.py @@ -8,6 +8,7 @@ #@param $4 Número de particion #@param $5 Protocolo (UNICAST, UNICAST-DIRECT, MULTICAST o MULTICAST-DIRECT) #@param $6 Opciones del protocolo +#@ejemplo restoreImage.py REPO imgname 2 2 unicast #@exception OG_ERR_FORMAT 1 formato incorrecto. #@exception OG_ERR_NOTFOUND 2 cambio de repositorio: repositorio no encontrado #@exception OG_ERR_NOTFOUND 2 fichero de imagen o partición no detectados. diff --git a/client/shared/scripts/updateCache.py b/client/shared/scripts/updateCache.py new file mode 100644 index 0000000..655e861 --- /dev/null +++ b/client/shared/scripts/updateCache.py @@ -0,0 +1,218 @@ +#!/usr/bin/python3 +#/** +# updateCache +#@brief Actualiza la cache del cliente con imagen o fichero iso. +#@param 1 REPO Origen del fichero. -accesible por nfs-samba- +#@param 2 str_fichero nombre del fichero a actualizar. +#@param 3 str_protoco. TORRENT | MULTICAST | UNICAST. +#@param 4 str_opcionesprotocolo +#@param 4 str_opcionesupdatecache +#@ejemplo: updateCache.py REPO imgname.img UNICAST 8042:42 +#@return +#@exception OG_ERR_FORMAT formato incorrecto. +#@exception OG_ERR_NOTCACHE No existe cache -15- +#@exception $OG_ERR_CACHESIZE Tamaño de la paticion menor al archivo a descargar -16- +#@exception $OG_ERR_MCASTRECEIVERFILE Error en la recepción Multicast de un fichero -57- +#@exception $OG_ERR_PROTOCOLJOINMASTER Error en la conexión de una sesión Unicast|Multicast con el Master -60- +#@note +#@todo: +#*/ ## + +import os.path +import sys +import time +import subprocess +import shutil +import glob +import random + +import ogGlobals +import SystemLib +import StringLib +import NetLib +import CacheLib +import FileLib +import ProtocolLib +import FileSystemLib + +prog = os.path.basename (sys.argv[0]) +print (f'argv ({sys.argv}) len ({len (sys.argv)})') +if len (sys.argv) < 3: + SystemLib.ogRaiseError ('session', ogGlobals.OG_ERR_FORMAT, f'{ogGlobals.lang.MSG_FORMAT}: {prog} str_REPO _str_Relative_Path_OGIMG_with_/ PROTOCOLO OPCIONES_PROTOCOLO OPCIONES_UPDATECACHE') + sys.exit (1) +#_, repositorio, path, protocolo, optprotocolo, cacheopts = sys.argv +_, repositorio, path, protocolo, optprotocolo = sys.argv +cacheopts = '' + +if 'RSYNC' == protocolo: + raise Exception ('synchronised images are no longer supported') + +#Carga del configurador del engine +## (ogGlobals se encarga) + +# Clear temporary file used as log track by httpdlog +# Limpia los ficheros temporales usados como log de seguimiento para httpdlog +open (ogGlobals.OGLOGCOMMAND, 'w').close() +if SystemLib.ogGetCaller() not in ['deployImage', 'restoreBaseImage', 'restoreDiffImage']: + open (ogGlobals.OGLOGSESSION, 'w').close() + SystemLib.ogEcho (['log', 'session'], None, f'[1] {ogGlobals.lang.MSG_SCRIPTS_START} {prog} {sys.argv}') + +# Si MCASTWAIT menos que tiempo de espera del servidor lo aumento +MCASTWAIT = ogGlobals.MCASTWAIT +if ':' in optprotocolo: + port, wait = optprotocolo.split (':') +else: + port, wait = ('', '') +if protocolo.startswith ('MULTICAST') and re.match (r'^-?\d+$', wait): + if int (MCASTWAIT or 0) < int (wait): + MCASTWAIT = int (wait) + 5 +# Unidad organizativa. +## (no longer supported) +#print (f'repositorio ({repositorio}) path ({path}) protocolo ({protocolo}) optprotocolo ({optprotocolo}) cacheopts ({cacheopts}) MCASTWAIT ({MCASTWAIT})') + +# Si es una ip y es distinta a la del recurso samba cambiamos de REPO. +if StringLib.ogCheckIpAddress (repositorio) or 'REPO' == repositorio: + if not NetLib.ogChangeRepo (repositorio): + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTFOUND, repositorio) + sys.exit (1) + repositorio = 'REPO' +repoip = NetLib.ogGetRepoIp() +SystemLib.ogEcho (['log', 'session'], None, f'{repositorio} {repoip} {protocolo} {optprotocolo}') + +# Si el repositorio local CACHE no existe error 15. +if not CacheLib.ogFindCache(): + SystemLib.ogRaiseError ('session', ogGlobals.OG_ERR_NOTCACHE, 'CACHE') + sys.exit (1) + +# comprobar si la imagen existe (.img, .img.diff o directorio) +repofile = FileLib.ogGetPath ('REPO', f'/{path}') +if not os.path.exists (repofile): + SystemLib.ogRaiseError ('session', ogGlobals.OG_ERR_NOTFOUND, f'REPO /{path}') + sys.exit (1) + +SystemLib.ogEcho (['log', 'session'], None, ogGlobals.lang.MSG_SCRIPTS_UPDATECACHE_DOUPDATE) +# Distingo si es monolitica o sincronizable +f = subprocess.run (['file', repofile], capture_output=True, text=True).stdout.lower() +if ' btrfs filesystem ' in f or ' ext4 filesystem ' in f or ' directory' in f: + raise Exception ('synchronised images are no longer supported') +rc = ProtocolLib.ogUpdateCacheIsNecesary (repositorio, path, protocolo) +# si rc=True: actualizamos; si rc=False: no actualizamos (exit 0); si rc=None: exit error +if rc == True: pass ## es necesario actualizar +elif rc == False: sys.exit (0) ## no es necesario actualizar +elif rc == None: sys.exit (ogGlobals.OG_ERR_UPDATECACHE) ## hubo errores + +SystemLib.ogEcho (['log', 'session'], None, ogGlobals.lang.MSG_SCRIPTS_UPDATECACHE_CHECKSIZECACHE) +cachesize = CacheLib.ogGetCacheSize() +cache_disk, cache_par = CacheLib.ogFindCache().split() +cachesizefree = FileSystemLib.ogGetFreeSize (cache_disk, cache_par) +path_repo = FileLib.ogGetPath ('REPO', path) +filesize = int (subprocess.run (['ls', '-sk', path_repo], capture_output=True, text=True).stdout.split()[0]) +realfilesize = subprocess.run (['stat', '--format', '%s', repofile], capture_output=True, text=True).stdout +realfilesize = int (int (realfilesize) / 1024) + +# La sincronizada, si existe la imagen en cache el espacio necesario +# es la nueva menos lo que ocupa la que ya hay. +sizerequired = filesize + +#ERROR CACHESIZE 16 (tamanyo de la CACHE insuficiente) +if sizerequired >= cachesize: + SystemLib.ogEcho (['log', 'session'], None, f'{ogGlobals.lang.MSG_WARNING}: {ogGlobals.lang.MSG_ERR_CACHESIZE}: {path} = {sizerequired} > CACHE = {cachesize}') + SystemLib.ogRaiseError ('session', ogGlobals.OG_ERR_CACHESIZE, 'CACHE') + sys.exit (1) + + +#ERROR CACHESIZE 16 (Espacio libre en CACHE insuficiente) +if sizerequired >= cachesizefree: + SystemLib.ogEcho (['log', 'session'], None, f'{ogGlobals.lang.MSG_SCRIPTS_UPDATECACHE_IFNOTCACHEDO}: ACTIONCACHEFULL={ogGlobals.ACTIONCACHEFULL}') + if 'NONE' == ogGlobals.ACTIONCACHEFULL: + SystemLib.ogEcho (['log', 'session'], None, f'{ogGlobals.lang.MSG_WARNING}: {ogGlobals.lang.MSG_ERR_CACHESIZE}: {path} = {sizerequired} > FREE SPACE CACHE = {cachesizefree}') + SystemLib.ogRaiseError ('session', ogGlobals.OG_ERR_CACHESIZE, 'CACHE FULL, NO SPACE FREE') + sys.exit (1) + elif 'FORMAT' == ogGlobals.ACTIONCACHEFULL: + SystemLib.ogEcho (['log', 'session'], None, f'[51] {ogGlobals.lang.MSG_HELP_ogFormatCache}') + CacheLib.ogUnmountCache() + CacheLib.ogFormatCache() + CacheLib.ogMountCache() + elif 'DELETE' == ogGlobals.ACTIONCACHEFULL: + SystemLib.ogEcho (['log', 'session'], None, f'[51] {ogGlobals.lang.MSG_HELP_ogDeleteTree} {ogGlobals.OGCAC}{ogGlobals.OGIMG}/*') + for d in glob.glob (f'{ogGlobals.OGCAC}{ogGlobals.OGIMG}/*'): + shutil.rmtree (d) + else: + SystemLib.ogEcho (['log', 'session'], None, f'{ogGlobals.lang.MSG_WARNING}: {ogGlobals.lang.MSG_ERR_CACHESIZE}: {path} = {filesize} > CACHE = {cachesizefree}') + SystemLib.ogRaiseError ('session', ogGlobals.OG_ERR_CACHESIZE, 'CACHE') + sys.exit (1) + +# Comprobamos que imagen cache igual a la del repo. Si sincronizada no podemos comprobar. +## nati: esto ya lo hicimos mas arriba... +rc = ProtocolLib.ogUpdateCacheIsNecesary (repositorio, path, protocolo) +# si rc=True: actualizamos; si rc=False: no actualizamos (exit 0); si rc=None: exit error +if rc == True: pass ## es necesario actualizar +elif rc == False: sys.exit (0) ## no es necesario actualizar +elif rc == None: sys.exit (ogGlobals.OG_ERR_UPDATECACHE) ## hubo errores + +CacheLib.ogMountCache() + +## Si no existe, crear subdirectorio para el fichero en la cache. +imgdir = FileLib.ogGetParentPath ('CACHE', f'/{path}') +if not imgdir: + SystemLib.ogEcho (['log', 'session'], None, f'[5] {ogGlobals.lang.MSG_HELP_ogMakeDir} "{path} {os.path.dirname (path)}".') + FileLib.ogMakeDir ('CACHE', os.path.dirname (f'/{path}')) + imgdir = ogGetParentPath ('CACHE', f'/{path}') + if not imgdir: + sys.exit (1) + +t0 = time.time() + +if 'TORRENT' == protocolo: + SystemLib.ogEcho (['log', 'session'], None, f'ogCopyFile {repositorio} {path}.torrent absolute {ogGlobals.OGCAC}/{ogGlobals.OGIMG}') + mac_digits = NetLib.ogGetMacAddress().split (':') + timewait = int ('0x' + mac_digits[4] + mac_digits[5], 16) * 120 / 65535 + if not SystemLib.ogExecAndLog ('command', FileLib.ogCopyFile, {'container':repositorio, 'file':f'{path}.torrent'}, {'file':imgdir}): + sys.exit (1) + p2pwait = random.randint (1, 121) + SystemLib.ogEcho (['log', 'session'], None, f' [ ] {ogGlobals.lang.MSG_SCRIPTS_TASK_SLEEP} : {p2pwait} seconds') + time.sleep (p2pwait) + SystemLib.ogEcho (['log', 'session'], None, f' [ ] {ogGlobals.lang.MSG_SCRIPTS_TASK_START}: ogTorrentStart CACHE {path}.torrent {optprotocolo}') + SystemLib.ogExecAndLog ('command', ProtocolLib.ogTorrentStart, 'CACHE', f'{path}.torrent', optprotocolo) + resumeupdatecache = subprocess.run (['grep', '--max-count', '1', '--before-context', '1', 'Download', ogGlobals.OGLOGCOMMAND], capture_output=True, text=True).stdout + resumeupdatecachebf = subprocess.run (['grep', '--max-count', '1', 'Download', ogGlobals.OGLOGCOMMAND], capture_output=True, text=True).stdout + if 'Download complete.' == resumeupdatecachebf: + os.unlink (imgdir + path + '.torrent.bf') +elif 'MULTICAST' == protocolo: + SystemLib.ogEcho (['log', 'session'], None, f'{ogGlobals.lang.MSG_SCRIPTS_UPDATECACHE_CHECKMCASTSESSION}: {repoip}:{port}') + time.sleep (random.randint (1, 31)) + + SystemLib.ogEcho (['log', 'session'], None, f'ogMcastRequest {path} {optprotocolo}') + if not SystemLib.ogExecAndLog ('command', ProtocolLib.ogMcastRequest, path, optprotocolo): + sys.exit (1) + + SystemLib.ogEcho (['log', 'session'], None, f'ogMcastReceiverFile {port} CACHE {path}') + if not SystemLib.ogExecAndLog ('command', ProtocolLib.ogMcastReceiverFile, port, 'CACHE', path): + sys.exit (1) + + resumeupdatecache = subprocess.run (['grep', '--max-count', '1', '--before-context', '1', 'Transfer complete', f'{ogGlobals.OGLOGCOMMAND}.tmp'], capture_output=True, text=True).stdout + +elif 'UNICAST' == protocolo: + print (f'ogExecAndLog ("command", FileLib.ogCopyFile, {{"container":{repositorio}, "file":{path}}}, {{"file":{imgdir}}})') + SystemLib.ogExecAndLog ('command', FileLib.ogCopyFile, {'container':repositorio, 'file':path}, {'file':imgdir}) + time.sleep (5) + resumeupdatecache = subprocess.run (['grep', '--max-count', '1', '100%', f'{ogGlobals.OGLOGCOMMAND}.tmp'], capture_output=True, text=True).stdout + +elif 'RSYNC' == protocolo: + raise Exception ('synchronised images are no longer supported') + +t = time.time() - t0 +SystemLib.ogEcho (['log', 'session'], None, f' [ ] {resumeupdatecache} ') +SystemLib.ogEcho (['log', 'session'], None, f' [ ] {ogGlobals.lang.MSG_SCRIPTS_TIME_PARTIAL} updateCache {int (t/60)}m {int (t%60)}s') +SystemLib.ogEcho (['log', 'session'], None, f' [ ] {ogGlobals.lang.MSG_SCRIPTS_TASK_START} {ogGlobals.lang.MSG_HELP_ogCalculateChecksum} ') +t0 = time.time() +# Si es imagen sincronizada siempre da distinto md5. No podemos comprobar +rc = ProtocolLib.ogUpdateCacheIsNecesary (repositorio, path, protocolo) +if 'deployImage' != SystemLib.ogGetCaller(): + t = time.time() - t0 + SystemLib.ogEcho (['log', 'session'], None, f' [ ] {ogGlobals.lang.MSG_SCRIPTS_TIME_PARTIAL} {ogGlobals.lang.MSG_HELP_ogCalculateChecksum} {int (t/60)}m {int (t%60)}s') + +# si rc todavia es True: exit error; si rc=False: todo bien (exit 0); si rc=None: exit error +if rc == True: sys.exit (ogGlobals.OG_ERR_UPDATECACHE) +elif rc == False: sys.exit (0) +elif rc == None: sys.exit (ogGlobals.OG_ERR_UPDATECACHE) From 18339f947ceef53c308d0f2976fa27ab93020368 Mon Sep 17 00:00:00 2001 From: Antonio Emmanuel Guerrero Silva Date: Wed, 20 Nov 2024 23:06:28 -0600 Subject: [PATCH 074/167] refs #1164 ogCheckProgram function correction --- client/lib/engine/bin/SystemLib.py | 31 +++++++++--------------------- 1 file changed, 9 insertions(+), 22 deletions(-) diff --git a/client/lib/engine/bin/SystemLib.py b/client/lib/engine/bin/SystemLib.py index 740eb35..39d0d23 100755 --- a/client/lib/engine/bin/SystemLib.py +++ b/client/lib/engine/bin/SystemLib.py @@ -268,47 +268,34 @@ def ogIsRepoLocked(): ogHelp(f"{FUNCNAME}", f"{FUNCNAME}", f"if {FUNCNAME}(): ...") # No hacer nada, si no está definido el punto de montaje del repositorio. - if not OGIMG: + if not ogGlobals.OGIMG: return 1 # Comprobar si alguno de los ficheros abiertos por los procesos activos está en el # punto de montaje del repositorio de imágenes. - FILES = subprocess.check_output(["find", "/proc", "-maxdepth", "2", "-type", "f", "-lname", f"{OGIMG}/*"]).decode("utf-8") + FILES = subprocess.check_output(["find", "/proc", "-maxdepth", "2", "-type", "f", "-lname", f"{ogGlobals.OGIMG}/*"]).decode("utf-8") return bool(FILES) -def ogCheckProgram(*args): +def ogCheckProgram(program): FUNCNAME = ogCheckProgram.__name__ - # Si se solicita, mostrar ayuda. - if len(args) > 0 and args[0] == "help": - ogHelp(f"{FUNCNAME} \"str_program ...\"", - f"{FUNCNAME} \"partimage partclone mbuffer\"") - return - # Error si no se recibe 1 parámetro. - if len(args) != 1: + if not program or not isinstance(program, str): SystemLib.ogRaiseError( "session", ogGlobals.OG_ERR_FORMAT, - f"Error: {ogGlobals.lang.MSG_ERR_FORMAT} {FUNCNAME} \"str_program ...\"" + f"Error: {ogGlobals.lang.MSG_ERR_FORMAT} {FUNCNAME} \"program\"" ) return - PERROR = 0 - PLOG = " " - for i in args[0].split(): - if not shutil.which(i): - PERROR = 1 - PLOG += f" {i}" - - if PERROR == 1: + if not shutil.which(program): SystemLib.ogRaiseError( "session", ogGlobals.OG_ERR_NOTEXEC, - f"Error: {PLOG}", + f"Error: The program '{program}' is not available on the system." ) return - else: - return 0 + + return 0 def ogIsVirtualMachine(): output = subprocess.run (["dmidecode", "-s", "system-product-name"], capture_output=True, text=True).stdout From bb0805e2375ad8ca9cffd8481ef7cfa1753171e2 Mon Sep 17 00:00:00 2001 From: Antonio Emmanuel Guerrero Silva Date: Wed, 20 Nov 2024 23:27:46 -0600 Subject: [PATCH 075/167] refs #1164 ogRaiseError function call correction --- client/lib/engine/bin/FileSystemLib.py | 259 ++++++++++++++++++------- 1 file changed, 184 insertions(+), 75 deletions(-) diff --git a/client/lib/engine/bin/FileSystemLib.py b/client/lib/engine/bin/FileSystemLib.py index 5d9ad14..a843cce 100755 --- a/client/lib/engine/bin/FileSystemLib.py +++ b/client/lib/engine/bin/FileSystemLib.py @@ -9,18 +9,17 @@ import CacheLib import FileSystemLib def ogCheckFs(int_ndisk, int_nfilesys): - # Si se solicita, mostrar ayuda. - if int_ndisk == "help": - ogHelp("ogCheckFs", "ogCheckFs int_ndisk int_nfilesys", "ogCheckFs 1 1") - return - # Error si no se reciben 2 parámetros. if len(sys.argv) != 3: - ogRaiseError(OG_ERR_FORMAT) + SystemLib.ogRaiseError( + "session", + ogGlobals.OG_ERR_FORMAT, + "Not enough arguments" + ) return # Obtener partición. - PART = ogDiskToDev(int_ndisk, int_nfilesys) + PART = DiskLib.ogDiskToDev(int_ndisk, int_nfilesys) if not PART: return @@ -73,16 +72,28 @@ def ogCheckFs(int_ndisk, int_nfilesys): elif TYPE == "ZFS": PROG = "fsck.zfs" else: - ogRaiseError(OG_ERR_PARTITION, f"{int_ndisk}, {int_nfilesys}") + SystemLib.ogRaiseError( + "session", + ogGlobals.OG_ERR_PARTITION, + f"{int_ndisk}, {int_nfilesys}" + ) return # Error si el sistema de archivos esta montado o bloqueado. ogUnmount(int_ndisk, int_nfilesys) if ogIsMounted(int_ndisk, int_nfilesys): - ogRaiseError(OG_ERR_PARTITION, f"{int_ndisk} {int_nfilesys}") + SystemLib.ogRaiseError( + "session", + ogGlobals.OG_ERR_PARTITION, + f"{int_ndisk} {int_nfilesys}" + ) return if ogIsLocked(int_ndisk, int_nfilesys): - ogRaiseError(OG_ERR_LOCKED, f"{int_ndisk} {int_nfilesys}") + SystemLib.ogRaiseError( + "session", + ogGlobals.OG_ERR_LOCKED, + f"{int_ndisk} {int_nfilesys}" + ) return # Comprobar en modo uso exclusivo. @@ -91,28 +102,36 @@ def ogCheckFs(int_ndisk, int_nfilesys): result = subprocess.run([PROG, PARAMS, PART], capture_output=True) ERRCODE = result.returncode except FileNotFoundError: - ogRaiseError(OG_ERR_NOTEXEC, PROG) - ERRCODE = OG_ERR_NOTEXEC + SystemLib.ogRaiseError( + "session", + ogGlobals.OG_ERR_NOTEXEC, + PROG + ) + ERRCODE = ogGlobals.OG_ERR_NOTEXEC except: - ogRaiseError(OG_ERR_PARTITION, f"{int_ndisk} {int_nfilesys}") - ERRCODE = OG_ERR_PARTITION + SystemLib.ogRaiseError( + "session", + ogGlobals.OG_ERR_PARTITION, + f"{int_ndisk} {int_nfilesys}" + ) + ERRCODE = ogGlobals.OG_ERR_PARTITION ogUnlock(int_ndisk, int_nfilesys) return ERRCODE def ogExtendFs(): - # Si se solicita, mostrar ayuda. - if len(sys.argv) == 2 and sys.argv[1] == "help": - ogHelp("ogExtendFs", "ogExtendFs int_ndisk int_nfilesys", "ogExtendFs 1 1") - return # Error si no se reciben 2 parámetros. if len(sys.argv) != 3: - ogRaiseError(OG_ERR_FORMAT) + SystemLib.ogRaiseError( + "session", + ogGlobals.OG_ERR_FORMAT, + f"Not enough arguments" + ) return # Obtener partición. - PART = ogDiskToDev(int(sys.argv[1]), int(sys.argv[2])) + PART = DiskLib.ogDiskToDev(int(sys.argv[1]), int(sys.argv[2])) if not PART: return @@ -134,7 +153,11 @@ def ogExtendFs(): PROG = "ntfsresize" PARAMS = "<<<\"y\" -f" else: - ogRaiseError(OG_ERR_PARTITION, f"{int(sys.argv[1])} {int(sys.argv[2])} {TYPE}") + SystemLib.ogRaiseError( + "session", + ogGlobals.OG_ERR_PARTITION, + f"{int(sys.argv[1])} {int(sys.argv[2])} {TYPE}" + ) return # Salida normal si no se va a aplicar la operación. @@ -149,12 +172,20 @@ def ogExtendFs(): else: ogUnmount(int(sys.argv[1]), int(sys.argv[2])) if ogIsMounted(int(sys.argv[1]), int(sys.argv[2])): - ogRaiseError(OG_ERR_PARTITION, f"{int(sys.argv[1])} {int(sys.argv[2])}") + SystemLib.ogRaiseError( + "session", + ogGlobals.OG_ERR_PARTITION, + f"{int(sys.argv[1])} {int(sys.argv[2])}" + ) return # Error si el sistema de archivos está bloqueado. if ogIsLocked(int(sys.argv[1]), int(sys.argv[2])): - ogRaiseError(OG_ERR_LOCKED, f"{int(sys.argv[1])} {int(sys.argv[2])}") + SystemLib.ogRaiseError( + "session", + ogGlobals.OG_ERR_LOCKED, + f"{int(sys.argv[1])} {int(sys.argv[2])}" + ) return # Redimensionar en modo uso exclusivo. @@ -163,11 +194,19 @@ def ogExtendFs(): subprocess.run([PROG, PARAMS, PART], capture_output=True) ERRCODE = 0 except FileNotFoundError: - ogRaiseError(OG_ERR_NOTEXEC, PROG) - ERRCODE = OG_ERR_NOTEXEC + SystemLib.ogRaiseError( + "session", + ogGlobals.OG_ERR_NOTEXEC, + PROG + ) + ERRCODE = ogGlobals.OG_ERR_NOTEXEC except: - ogRaiseError(OG_ERR_PARTITION, f"{int(sys.argv[1])} {int(sys.argv[2])}") - ERRCODE = OG_ERR_PARTITION + SystemLib.ogRaiseError( + "session", + ogGlobals.OG_ERR_PARTITION, + f"{int(sys.argv[1])} {int(sys.argv[2])}" + ) + ERRCODE = ogGlobals.OG_ERR_PARTITION ogUnlock(int(sys.argv[1]), int(sys.argv[2])) return ERRCODE @@ -205,17 +244,29 @@ def ogFormatFs (disk, par, type=None, label=None): if not PART: return if ogIsMounted (disk, par): - SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_DONTFORMAT, f'{ogGlobals.lang.MSG_MOUNT}: {disk} {par}') + SystemLib.ogRaiseError( + [], + ogGlobals.OG_ERR_DONTFORMAT, + f'{ogGlobals.lang.MSG_MOUNT}: {disk} {par}' + ) return None if ogIsLocked (disk, par): - SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_LOCKED, f"{disk} {par}") + SystemLib.ogRaiseError( + [], + ogGlobals.OG_ERR_LOCKED, + f"{disk} {par}" + ) return None if not type: type = ogGetFsType (disk, par) if not type: - SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_FORMAT, f"{disk} {par} ...") + SystemLib.ogRaiseError( + [], + ogGlobals.OG_ERR_FORMAT, + f"{disk} {par} ..." + ) return None data = { @@ -240,7 +291,11 @@ def ogFormatFs (disk, par, type=None, label=None): 'UFS': { 'PROG': 'mkfs.ufs', 'PARAMS': '-O 2' }, } if type not in data: - SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_PARTITION, f"{disk} {par} {type}") + SystemLib.ogRaiseError ( + [], + ogGlobals.OG_ERR_PARTITION, + f"{disk} {par} {type}" + ) return d = data[type] @@ -250,7 +305,11 @@ def ogFormatFs (disk, par, type=None, label=None): input = d['INPUT'] if 'INPUT' in d else '' if label == "CACHE": - SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_FORMAT, f"{ogGlobals.lang.MSG_RESERVEDVALUE}: CACHE") + SystemLib.ogRaiseError ( + [], + ogGlobals.OG_ERR_FORMAT, + f"{ogGlobals.lang.MSG_RESERVEDVALUE}: CACHE" + ) return if label: params = f"{params} {labelparam or '-L'} {label}" @@ -263,10 +322,18 @@ def ogFormatFs (disk, par, type=None, label=None): else: errcode = subprocess.run ([prog, params, PART], input=input, text=True) except FileNotFoundError: - SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTEXEC, prog) + SystemLib.ogRaiseError ( + [], + ogGlobals.OG_ERR_NOTEXEC, + prog + ) errcode = ogGlobals.OG_ERR_NOTEXEC except: - SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_PARTITION, f"{disk} {par}") + SystemLib.ogRaiseError ( + [], + ogGlobals.OG_ERR_PARTITION, + f"{disk} {par}" + ) errcode = ogGlobals.OG_ERR_PARTITION ogUnlock (disk, par) @@ -293,7 +360,11 @@ def ogGetFsSize (disk, par, unit='KB'): elif unit.upper() == "TB": factor = 1024 * 1024 * 1024 elif unit.upper() != "KB": - SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_FORMAT, f"{unit} != {{ KB, MB, GB, TB }}") + SystemLib.ogRaiseError ( + [], + ogGlobals.OG_ERR_FORMAT, + f"{unit} != {{ KB, MB, GB, TB }}" + ) return # Obtener el tamaño del sistema de archivo (si no está formateado; tamaño = 0). @@ -334,7 +405,11 @@ def ogGetFsType(disk, part): try: subprocess.run(["zfs", "mount", PART]) except FileNotFoundError: - SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTEXEC, 'zfs') + SystemLib.ogRaiseError ( + [], + ogGlobals.OG_ERR_NOTEXEC, + 'zfs' + ) return out = subprocess.run(["mount"], capture_output=True, text=True).stdout.splitlines() for line in out: @@ -343,7 +418,11 @@ def ogGetFsType(disk, part): break if not TYPE: - SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTFOUND, f'{disk} {part}') + SystemLib.ogRaiseError ( + [], + ogGlobals.OG_ERR_NOTFOUND, + f'{disk} {part}' + ) return # Componer valores correctos. @@ -474,18 +553,17 @@ def ogIsReadonly(disk, par): return "ro" in options def ogIsWritable(int_ndisk, int_nfilesys): - # Si se solicita, mostrar ayuda. - if len(sys.argv) == 3 and sys.argv[2] == "help": - ogHelp("ogIsWritable", "ogIsWritable int_ndisk int_nfilesys", "ogIsWritable 1 1") - return - # Error si no se reciben 2 parámetros. if len(sys.argv) != 3: - ogRaiseError(OG_ERR_FORMAT) + SystemLib.ogRaiseError( + "session", + ogGlobals.OG_ERR_FORMAT, + f"Not enough arguments" + ) return # Obtener partición. - PART = ogDiskToDev(int_ndisk, int_nfilesys) + PART = DiskLib.ogDiskToDev(int_ndisk, int_nfilesys) if not PART: return @@ -528,7 +606,7 @@ def ogLockPartition (disk, par): def ogMount(*args): if 1 == len (args): if 'cache' == args[0].lower(): - return ogMountCache() + return DiskLib.ogMountCache() elif 'cdrom' == args[0].lower(): return ogMountCdrom() elif 2 == len (args): @@ -536,13 +614,17 @@ def ogMount(*args): def ogMountFirstFs(int_ndisk): # Obtener número de particiones del disco. - NPARTS = ogGetPartitionsNumber(int_ndisk) + NPARTS = DiskLib.ogGetPartitionsNumber(int_ndisk) for PART in range(1, NPARTS + 1): MNTDIR = ogMount(int_ndisk, PART) if MNTDIR: return MNTDIR - ogRaiseError(OG_ERR_NOTFOUND, int_ndisk) - return OG_ERR_NOTFOUND + SystemLib.ogRaiseError( + "session", + ogGlobals.OG_ERR_NOTFOUND, + f"{int_ndisk}" + ) + return ogGlobals.OG_ERR_NOTFOUND #/** # ogMountFs int_ndisk int_nfilesys @@ -563,7 +645,11 @@ def ogMountFs (disk, par): if ogIsLocked (disk, par): print (f'nati: ogMountFs: is locked disk ({disk}) par ({par})') - SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_LOCKED, f"{ogGlobals.lang.MSG_PARTITION}, {disk} {par}") + SystemLib.ogRaiseError ( + [], + ogGlobals.OG_ERR_LOCKED, + f"{ogGlobals.lang.MSG_PARTITION}, {disk} {par}" + ) return # El camino de un dispositivo normal comienza por el carácter "/". @@ -586,7 +672,11 @@ def ogMountFs (disk, par): try: rc = subprocess.run(['mount', dev, mntdir, '-o', 'force,remove_hiberfile'], check=True).returncode except subprocess.CalledProcessError: - SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_PARTITION, f"{disk}, {par}") + SystemLib.ogRaiseError ( + [], + ogGlobals.OG_ERR_PARTITION, + f"{disk}, {par}" + ) return if 0 == rc: @@ -595,13 +685,21 @@ def ogMountFs (disk, par): try: subprocess.run (['ntfsfix', '-d', par], check=True) except subprocess.CalledProcessError: - SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_PARTITION, f"{disk, par}") + SystemLib.ogRaiseError ( + [], + ogGlobals.OG_ERR_PARTITION, + f"{disk, par}" + ) #return else: try: subprocess.run (['mount', par, mntdir, '-o', 'ro'], check=True) except subprocess.CalledProcessError: - SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_PARTITION, f"{disk, par}") + SystemLib.ogRaiseError ( + [], + ogGlobals.OG_ERR_PARTITION, + f"{disk, par}" + ) #return # Aviso de montaje de solo lectura. @@ -635,23 +733,27 @@ def ogMountCdrom(): try: subprocess.run(["mount", "-t", "iso9660", DEV, MNTDIR], check=True, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) except subprocess.CalledProcessError: - SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_PARTITION, "cdrom") + SystemLib.ogRaiseError ( + [], + ogGlobals.OG_ERR_PARTITION, + "cdrom" + ) return return MNTDIR def ogReduceFs(int_ndisk, int_nfilesys): - # Si se solicita, mostrar ayuda. - if len(sys.argv) == 3 and sys.argv[2] == "help": - ogHelp("ogReduceFs", "ogReduceFs int_ndisk int_nfilesys", "ogReduceFs 1 1") - return # Error si no se reciben 2 parámetros. if len(sys.argv) != 3: - ogRaiseError(OG_ERR_FORMAT) + SystemLib.ogRaiseError ( + [], + ogGlobals.OG_ERR_FORMAT, + "Not enough arguments" + ) return # Obtener partición. - PART = ogDiskToDev(int_ndisk, int_nfilesys) + PART = DiskLib.ogDiskToDev(int_ndisk, int_nfilesys) if not PART: return @@ -696,7 +798,11 @@ def ogReduceFs(int_ndisk, int_nfilesys): # No se reduce (por el momento). pass else: - ogRaiseError(OG_ERR_PARTITION, f"{int_ndisk}, {int_nfilesys}") + SystemLib.ogRaiseError ( + [], + ogGlobals.OG_ERR_PARTITION, + f"{int_ndisk}, {int_nfilesys}" + ) # Devuelve tamaño del sistema de ficheros. return ogGetFsSize(int_ndisk, int_nfilesys) @@ -754,7 +860,11 @@ def ogUnmountFs(disk, par): if MNTDIR: # Error si la particion está bloqueada. if ogIsLocked (disk, par): - ogRaiseError ([], ogGlobals.OG_ERR_LOCKED, f"{ogGlobals.lang.MSG_PARTITION}, {disk} {par}") + SystemLib.ogRaiseError ( + [], + ogGlobals.OG_ERR_LOCKED, + f"{ogGlobals.lang.MSG_PARTITION}, {disk} {par}" + ) return # Desmontar y borrar punto de montaje. @@ -785,35 +895,34 @@ def ogUnmountFs(disk, par): #@warning No se desmonta la partición marcada como caché local. #*/ ## def ogUnmountAll(int_ndisk): - # Si se solicita, mostrar ayuda. - if len(sys.argv) == 3 and sys.argv[2] == "help": - ogHelp("ogUnmountAll", "ogUnmountAll int_ndisk", "ogUnmountAll 1") - return - # Error si no se recibe 1 parámetro. if len(sys.argv) != 3: - ogRaiseError(OG_ERR_FORMAT) + SystemLib.ogRaiseError ( + [], + ogGlobals.OG_ERR_FORMAT, + "Not enough arguments" + ) return # Obtener partición y punto de montaje. - DISK = ogDiskToDev(int_ndisk) - for PART in range(1, ogGetPartitionsNumber(int_ndisk) + 1): + DISK = DiskLib.ogDiskToDev(int_ndisk) + for PART in range(1, DiskLib.ogGetPartitionsNumber(int_ndisk) + 1): if ogGetFsType(int_ndisk, PART) != "CACHE": ogUnmount(int_ndisk, PART) def ogUnsetDirtyBit(int_ndisk, int_nfilesys): - # Si se solicita, mostrar ayuda. - if len(sys.argv) == 3 and sys.argv[2] == "help": - ogHelp("ogUnsetDirtyBit", "ogUnsetDirtyBit int_ndisk int_nfilesys", "ogUnsetDirtyBit 1 1") - return # Error si no se reciben 2 parámetros. if len(sys.argv) != 3: - ogRaiseError(OG_ERR_FORMAT) + SystemLib.ogRaiseError ( + [], + ogGlobals.OG_ERR_FORMAT, + "Not enough arguments" + ) return # Obtener partición y punto de montaje. - PART = ogDiskToDev(int_ndisk, int_nfilesys) + PART = DiskLib.ogDiskToDev(int_ndisk, int_nfilesys) if not PART: return From 038d43226471de1d60fd113211216830185b8c81 Mon Sep 17 00:00:00 2001 From: Antonio Emmanuel Guerrero Silva Date: Wed, 20 Nov 2024 23:33:39 -0600 Subject: [PATCH 076/167] refs #1164 ogRaiseError function call correction --- client/lib/engine/bin/FileLib.py | 30 +++++++++++++++++++++++++----- 1 file changed, 25 insertions(+), 5 deletions(-) diff --git a/client/lib/engine/bin/FileLib.py b/client/lib/engine/bin/FileLib.py index 6099dee..424c17a 100755 --- a/client/lib/engine/bin/FileLib.py +++ b/client/lib/engine/bin/FileLib.py @@ -271,12 +271,20 @@ def ogDeleteTree(*args): # Comprobar que existe el directorio y borrarlo con su contenido. DIR = ogGetPath(*args) if not DIR: - SystemLib.ogRaiseError(OG_ERR_NOTFOUND, *args) + SystemLib.ogRaiseError( + "session", + ogGlobals.OG_ERR_NOTFOUND, + f"Not found: {args}" + ) return try: shutil.rmtree(DIR) except OSError as e: - SystemLib.ogRaiseError(OG_ERR_NOTFOUND, *args) + SystemLib.ogRaiseError( + "session", + ogGlobals.OG_ERR_NOTFOUND, + f"{e}" + ) return @@ -401,10 +409,18 @@ def ogIsNewerFile(*args): # Comprobar que existen los ficheros origen y destino. if not SOURCE: - SystemLib.ogRaiseError(OG_ERR_NOTFOUND, *args[:-1]) + SystemLib.ogRaiseError( + "session", + ogGlobals.OG_ERR_NOTFOUND, + f"Not found: {args[:-1]}" + ) return if not TARGET: - SystemLib.ogRaiseError(OG_ERR_NOTFOUND, *args) + SystemLib.ogRaiseError( + "session", + ogGlobals.OG_ERR_NOTFOUND, + f"Not found: {args[-1]}" + ) return # Devolver si el primer fichero se ha modificado después que el segundo. @@ -420,7 +436,11 @@ def ogMakeChecksumFile(*args): # Comprobar que existe el fichero y guardar su checksum. FILE = ogGetPath(*args) if not FILE: - SystemLib.ogRaiseError(OG_ERR_NOTFOUND, *args) + SystemLib.ogRaiseError( + "session", + ogGlobals.OG_ERR_NOTFOUND, + f"Not found: {args}" + ) return checksum = ogCalculateChecksum(FILE) with open(f"{FILE}.sum", "w") as f: From 6e53c31113cab52e987f17e0336af5d9971f8072 Mon Sep 17 00:00:00 2001 From: Natalia Serrano Date: Thu, 21 Nov 2024 15:54:07 +0100 Subject: [PATCH 077/167] refs #1166 add ogRestoreEfiBootLoader() --- client/lib/engine/bin/DiskLib.py | 377 ++++++++++++++------------ client/lib/engine/bin/InventoryLib.py | 315 ++++++++++++++++++--- client/lib/engine/bin/RegistryLib.py | 216 ++++++++++++--- client/lib/engine/bin/UEFILib.py | 232 ++++++++++++++++ 4 files changed, 880 insertions(+), 260 deletions(-) create mode 100644 client/lib/engine/bin/UEFILib.py diff --git a/client/lib/engine/bin/DiskLib.py b/client/lib/engine/bin/DiskLib.py index ddb7168..55f25e2 100755 --- a/client/lib/engine/bin/DiskLib.py +++ b/client/lib/engine/bin/DiskLib.py @@ -486,6 +486,9 @@ def ogDiskToDev (arg_disk=None, arg_part=None): return disk # arg_disk and arg_part are set: there are several possibilities + if arg_disk > len (ALLDISKS): + SystemLib.ogRaiseError([], ogGlobals.OG_ERR_NOTFOUND, arg_disk) + return disk = ALLDISKS[arg_disk-1] if not os.path.exists(disk): SystemLib.ogRaiseError([], ogGlobals.OG_ERR_NOTFOUND, arg_disk) @@ -602,19 +605,27 @@ def ogGetDiskType(*args): print(TYPE) return -def ogGetEsp(): - for d in subprocess.getoutput("blkid -o device").split(): +#/** +# ogGetEsp +#@brief Devuelve números de disco y partición para la partición EFI (ESP). +#*/ ## +def ogGetEsp(): + devices = subprocess.run (['blkid', '-o', 'device'], capture_output=True, text=True).stdout.splitlines() + devices.sort() + for d in devices: # Previene error para /dev/loop0 - PART = ogDevToDisk([d]) + PART = ogDevToDisk (d) + if not PART: continue + # En discos NVMe blkid devuelve una salida del tipo: # >/dev/loop0 # >/dev/nvme0n1 # >/dev/nvme0n1p1 # al analizar la particion nvme0n1, PART solo tiene un argumento y hace que ogGetPartitionId lance un error - LEN = len(PART) - if LEN > 1: - if ogGetPartitionId(PART) == ogTypeToId("EFI", "GPT"): + if len (PART) > 1: + disk, par = PART.split() + if ogGetPartitionId (disk, par) == ogTypeToId ('EFI', 'GPT'): return PART return None @@ -674,39 +685,40 @@ def ogGetPartitionActive(*args): print(output) return -def ogGetPartitionId(*args): - # Variables locales - DISK = None - ID = None - # Si se solicita, mostrar ayuda. - if len(args) == 1 and args[0] == "help": - SystemLib.ogHelp('ogGetPartitionId', 'ogGetPartitionId int_ndisk int_npartition', 'ogGetPartitionId 1 1 => 7') - return +#/** +# ogGetPartitionId int_ndisk int_npartition +#@brief Devuelve el mnemónico con el tipo de partición. +#@param int_ndisk nº de orden del disco +#@param int_npartition nº de orden de la partición +#@return Identificador de tipo de partición. +#@exception OG_ERR_FORMAT Formato incorrecto. +#@exception OG_ERR_NOTFOUND Disco o partición no corresponde con un dispositivo. +#@note Requisitos: sfdisk +#*/ ## +def ogGetPartitionId (disk, par): + DISK = ogDiskToDev (disk) + if DISK is None: return - # Error si no se reciben 2 parámetros. - if len(args) != 2: - SystemLib.ogRaiseError(OG_ERR_FORMAT) - return + pttype = ogGetPartitionTableType (disk) + if 'GPT' == pttype: + lines = subprocess.run (['sgdisk', '-p', DISK], capture_output=True, text=True).stdout.splitlines() + start_index = next (i for i, line in enumerate(lines) if 'Number' in line) + for l in lines[start_index:]: + idx, start, end, sz, sz_units, code, *rest = l.split() + if idx == par: + fsid = code + break + if fsid == '8300' and f'{disk} {par}' == ogFindCache(): + fsid = 'CA00' + elif 'MSDOS' == pttype: + fsid = subprocess.run (['sfdisk', '--part-type', DISK, par], capture_output=True, text=True).stdout.strip() + elif 'LVM' == pttype: + fsid = '10000' + elif 'ZPOOL' == pttype: + fsid = '10010' - # Detectar y mostrar el id. de tipo de partición. - DISK = ogDiskToDev(args[0]) - if DISK is None: - return - PTTYPE = ogGetPartitionTableType(args[0]) - if PTTYPE == "GPT": - ID = subprocess.getoutput(f"sgdisk -p {DISK} 2>/dev/null | awk -v p={args[1]} '{{if ($1==p) print $6;}}'") - if ID == "8300" and f"{args[0]} {args[1]}" == ogFindCache(): - ID = "CA00" - elif PTTYPE == "MSDOS": - ID = subprocess.getoutput(f"sfdisk --id {DISK} {args[1]} 2>/dev/null") - elif PTTYPE == "LVM": - ID = "10000" - elif PTTYPE == "ZPOOL": - ID = "10010" - - print(ID) - return + return fsid #/** @@ -765,45 +777,51 @@ def ogGetPartitionsNumber(*args): print(output) return -def ogGetPartitionTableType(*args): - # Variables locales - DISK = None - TYPE = None - # Si se solicita, mostrar ayuda. - if len(args) == 1 and args[0] == "help": - SystemLib.ogHelp('ogGetPartitionTableType', 'ogGetPartitionTableType int_ndisk', 'ogGetPartitionTableType 1 => MSDOS') - return +#/** +# ogGetPartitionTableType int_ndisk +#@brief Devuelve el tipo de tabla de particiones del disco (GPT o MSDOS) +#@param int_ndisk nº de orden del disco +#@return str_tabletype - Tipo de tabla de paritiones +#@warning Salidas de errores no determinada +#@note tabletype = { MSDOS, GPT } +#@note Requisitos: blkid, parted, vgs +#*/ ## +def ogGetPartitionTableType (disk): + DISK = ogDiskToDev (disk) + if DISK is None: return - # Error si no se recibe 1 parámetro. - if len(args) != 1: - SystemLib.ogRaiseError(OG_ERR_FORMAT) - return + m = os.stat (DISK, follow_symlinks=True).st_mode + if stat.S_ISBLK (m): + lines = subprocess.run (['parted', '--script', '--machine', DISK, 'print'], capture_output=True, text=True).stdout.splitlines() + for l in lines: + elems = l.split (':') + if DISK == elems[0]: + type = elems[5].upper() + break - # Sustituye n de disco por su dispositivo. - DISK = ogDiskToDev(args[0]) - if DISK is None: - return - - # Comprobar tabla de particiones. - if os.path.exists(DISK): - output = subprocess.getoutput(f"parted -sm {DISK} print 2>/dev/null | awk -F: -v D={DISK} '{{ if($1 == D) print toupper($6)}}'") - if not output: - output = subprocess.getoutput(f"parted -sm {DISK} print 2>/dev/null | awk -F: -v D={DISK} '{{ if($1 == D) print toupper($6)}}'") # Comprobar si es volumen lógico. - if os.path.isdir(DISK) and subprocess.run(["vgs", DISK], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL).returncode == 0: - output = "LVM" + if os.path.isdir (DISK) and 0 == subprocess.run (['vgs', DISK]).returncode: + type = 'LVM' + # Comprobar si es pool de ZFS. - if not output or output == "UNKNOWN": - blkid_output = subprocess.getoutput(f"blkid -s TYPE {DISK} | grep zfs") - if blkid_output: - output = "ZPOOL" + if not type or 'UNKNOWN' == type: + if 'zfs' in subprocess.run (['blkid', '-s', 'TYPE', DISK], capture_output=True, text=True).stdout: + type = 'ZPOOL' - # Mostrar salida. - if output: - print(output) - return + return type + +#/** +# ogGetPartitionType int_ndisk int_npartition +#@brief Devuelve el mnemonico con el tipo de partición. +#@param int_ndisk nº de orden del disco +#@param int_npartition nº de orden de la partición +#@return Mnemonico +#@note Mnemonico: valor devuelto por ogIdToType. +#@exception OG_ERR_FORMAT Formato incorrecto. +#@exception OG_ERR_NOTFOUND Disco o particion no corresponden con un dispositivo. +#*/ ## def ogGetPartitionType(*args): # Variables locales ID = None @@ -1224,118 +1242,123 @@ def ogSetPartitionType(*args): ogSetPartitionId(args[0], args[1], ID) return -def ogTypeToId(TYPE, PTTYPE="MSDOS"): - # Asociar id. de partición para su mnemónico. - ID = "" - # Elección del tipo de partición. - if PTTYPE == "GPT": - if TYPE == "EMPTY": - ID = "0" - elif TYPE in ["WINDOWS", "NTFS", "EXFAT", "FAT32", "FAT16", "FAT12", "HNTFS", "HFAT32", "HFAT16", "HFAT12"]: - ID = "0700" - elif TYPE == "WIN-RESERV": - ID = "0C01" - elif TYPE == "CHROMEOS-KRN": - ID = "7F00" - elif TYPE == "CHROMEOS": - ID = "7F01" - elif TYPE == "CHROMEOS-RESERV": - ID = "7F02" - elif TYPE == "LINUX-SWAP": - ID = "8200" - elif TYPE in ["LINUX", "EXT2", "EXT3", "EXT4", "REISERFS", "REISER4", "XFS", "JFS"]: - ID = "8300" - elif TYPE == "LINUX-RESERV": - ID = "8301" - elif TYPE == "LINUX-LVM": - ID = "8E00" - elif TYPE == "FREEBSD-DISK": - ID = "A500" - elif TYPE == "FREEBSD-BOOT": - ID = "A501" - elif TYPE == "FREEBSD-SWAP": - ID = "A502" - elif TYPE == "FREEBSD": - ID = "A503" - elif TYPE == "HFS-BOOT": - ID = "AB00" - elif TYPE in ["HFS", "HFS+"]: - ID = "AF00" - elif TYPE == "HFS-RAID": - ID = "AF01" - elif TYPE == "SOLARIS-BOOT": - ID = "BE00" - elif TYPE == "SOLARIS": - ID = "BF00" - elif TYPE == "SOLARIS-SWAP": - ID = "BF02" - elif TYPE == "SOLARIS-DISK": - ID = "BF03" - elif TYPE == "CACHE": - ID = "CA00" - elif TYPE == "EFI": - ID = "EF00" - elif TYPE == "LINUX-RAID": - ID = "FD00" - elif PTTYPE == "MSDOS": - if TYPE == "EMPTY": - ID = "0" - elif TYPE == "FAT12": - ID = "1" - elif TYPE == "EXTENDED": - ID = "5" - elif TYPE == "FAT16": - ID = "6" - elif TYPE in ["WINDOWS", "NTFS", "EXFAT"]: - ID = "7" - elif TYPE == "FAT32": - ID = "b" - elif TYPE == "HFAT12": - ID = "11" - elif TYPE == "HFAT16": - ID = "16" - elif TYPE == "HNTFS": - ID = "17" - elif TYPE == "HFAT32": - ID = "1b" - elif TYPE == "LINUX-SWAP": - ID = "82" - elif TYPE in ["LINUX", "EXT2", "EXT3", "EXT4", "REISERFS", "REISER4", "XFS", "JFS"]: - ID = "83" - elif TYPE == "LINUX-LVM": - ID = "8e" - elif TYPE == "FREEBSD": - ID = "a5" - elif TYPE == "OPENBSD": - ID = "a6" - elif TYPE in ["HFS", "HFS+"]: - ID = "af" - elif TYPE == "SOLARIS-BOOT": - ID = "be" - elif TYPE == "SOLARIS": - ID = "bf" - elif TYPE == "CACHE": - ID = "ca" - elif TYPE == "DATA": - ID = "da" - elif TYPE == "GPT": - ID = "ee" - elif TYPE == "EFI": - ID = "ef" - elif TYPE == "VMFS": - ID = "fb" - elif TYPE == "LINUX-RAID": - ID = "fd" - elif PTTYPE == "LVM": - if TYPE == "LVM-LV": - ID = "10000" - elif PTTYPE == "ZVOL": - if TYPE == "ZFS-VOL": - ID = "10010" +#/** +# ogTypeToId str_parttype [str_tabletype] +#@brief Devuelve el identificador correspondiente a un tipo de partición. +#@param str_parttype mnemónico de tipo de partición. +#@param str_tabletype mnemónico de tipo de tabla de particiones (MSDOS por defecto). +#@return int_idpart identificador de tipo de partición. +#@exception OG_ERR_FORMAT Formato incorrecto. +#@note tabletype = { MSDOS, GPT }, (MSDOS, por defecto) +#*/ ## +#ogTypeToId ('LINUX') => "83" +#ogTypeToId ('LINUX', 'MSDOS') => "83" +def ogTypeToId (type, pttype='MSDOS'): + data = { + 'GPT': { + 'EMPTY': '0', + 'WINDOWS': '0700', + 'NTFS': '0700', + 'EXFAT': '0700', + 'FAT32': '0700', + 'FAT16': '0700', + 'FAT12': '0700', + 'HNTFS': '0700', + 'HFAT32': '0700', + 'HFAT16': '0700', + 'HFAT12': '0700', + 'WIN-RESERV': '0C01', + 'CHROMEOS-KRN': '7F00', + 'CHROMEOS': '7F01', + 'CHROMEOS-RESERV': '7F02', + 'LINUX-SWAP': '8200', + 'LINUX': '8300', + 'EXT2': '8300', + 'EXT3': '8300', + 'EXT4': '8300', + 'REISERFS': '8300', + 'REISER4': '8300', + 'XFS': '8300', + 'JFS': '8300', + 'LINUX-RESERV': '8301', + 'LINUX-LVM': '8E00', + 'FREEBSD-DISK': 'A500', + 'FREEBSD-BOOT': 'A501', + 'FREEBSD-SWAP': 'A502', + 'FREEBSD': 'A503', + 'HFS-BOOT': 'AB00', + 'HFS': 'AF00', + 'HFS+': 'AF00', + 'HFSPLUS': 'AF00', + 'HFS-RAID': 'AF01', + 'SOLARIS-BOOT': 'BE00', + 'SOLARIS': 'BF00', + 'SOLARIS-SWAP': 'BF02', + 'SOLARIS-DISK': 'BF03', + 'CACHE': 'CA00', + 'EFI': 'EF00', + 'LINUX-RAID': 'FD00', + }, + 'MSDOS': { + 'EMPTY': '0', + 'FAT12': '1', + 'EXTENDED': '5', + 'FAT16': '6', + 'WINDOWS': '7', + 'NTFS': '7', + 'EXFAT': '7', + 'FAT32': 'b', + 'HFAT12': '11', + 'HFAT16': '16', + 'HNTFS': '17', + 'HFAT32': '1b', + 'LINUX-SWAP': '82', + 'LINUX': '83', + 'EXT2': '83', + 'EXT3': '83', + 'EXT4': '83', + 'REISERFS': '83', + 'REISER4': '83', + 'XFS': '83', + 'JFS': '83', + 'LINUX-LVM': '8e', + 'FREEBSD': 'a5', + 'OPENBSD': 'a6', + 'HFS': 'af', + 'HFS+': 'af', + 'SOLARIS-BOOT': 'be', + 'SOLARIS': 'bf', + 'CACHE': 'ca', + 'DATA': 'da', + 'GPT': 'ee', + 'EFI': 'ef', + 'VMFS': 'fb', + 'LINUX-RAID': 'fd', + }, + 'LVM': { + 'LVM-LV': '10000', + }, + 'ZVOL': { + 'ZFS-VOL': '10010', + }, + } - return ID + if pttype.upper() not in data: return None + if type.upper() not in data[pttype.upper()]: return None + return data[pttype.upper()][type.upper()] + +#/** +# ogUnhidePartition int_ndisk int_npartition +#@brief Hace visible una partición oculta. +#@param int_ndisk nº de orden del disco +#@param int_npartition nº de orden de la partición +#@return (nada) +#@exception OG_ERR_FORMAT formato incorrecto. +#@exception OG_ERR_NOTFOUND disco o particion no detectado (no es un dispositivo). +#@exception OG_ERR_PARTITION tipo de partición no reconocido. +#*/ ## def ogUnhidePartition(*args): # Variables locales PART = None diff --git a/client/lib/engine/bin/InventoryLib.py b/client/lib/engine/bin/InventoryLib.py index 48a93ee..0a6aa5f 100755 --- a/client/lib/engine/bin/InventoryLib.py +++ b/client/lib/engine/bin/InventoryLib.py @@ -1,3 +1,12 @@ +#/** +#@file Inventory.lib +#@brief Librería o clase Inventory +#@class Inventory +#@brief Funciones para recogida de datos de inventario de hardware y software de los clientes. +#@version 1.1.0 +#@warning License: GNU GPLv3+ +#*/ + import platform import sys import os @@ -6,14 +15,21 @@ import tempfile import re import json import shutil +import glob +import plistlib +import ogGlobals import SystemLib import FileSystemLib -import ogGlobals import RegistryLib +import FileLib -MSG_HARDWAREINVENTORY = "Inventario de hardware de la máquina" +#/** +# ogGetArch +#@brief Devuelve el tipo de arquitectura del cliente. +#@return str_arch - Arquitectura (i386 para 32 bits, x86_64 para 64 bits). +#*/ def ogGetArch(): if len(sys.argv) > 1 and sys.argv[1] == "help": SystemLib.ogHelp(sys.argv[0], sys.argv[0], sys.argv[0] + " => x86_64") @@ -24,6 +40,15 @@ def ogGetArch(): else: print("i386") + +#/** +# ogGetOsType int_ndisk int_npartition +#@brief Devuelve el tipo del sistema operativo instalado. +#@param int_ndisk nº de orden del disco +#@param int_npartition nº de orden de la partición +#@return OSType - Tipo de sistema operativo. +#@see ogGetOsVersion +#*/ ## def ogGetOsType(disk, partition): try: os_version = ogGetOsVersion(disk, partition) @@ -35,6 +60,16 @@ def ogGetOsType(disk, partition): print(f"Error en ogGetOsType: {e}") return "Unknown" + +#/** +# ogGetOsUuid int_ndisk int_nfilesys +#@brief Devuelve el UUID del sistema operativo instalado en un sistema de archivos. +#@param int_ndisk nº de orden del disco +#@param int_nfilesys nº de orden de la partición +#@return str_uuid - UUID del sistema operativo. +#@exception OG_ERR_FORMAT Formato incorrecto. +#@exception OG_ERR_NOTFOUND Disco o partición no corresponden con un dispositiv +#*/ ## def ogGetOsUuid(): # Si se solicita, mostrar ayuda. if len(sys.argv) > 1 and sys.argv[1] == "help": @@ -65,7 +100,12 @@ def ogGetOsUuid(): # Leer identificador en clave de registro. uuid = RegistryLib.ogGetRegistryValue(MNTDIR, "SOFTWARE", "\\Microsoft\\Cryptography\\MachineGuid") print(uuid) - + + +#/** +# ogGetSerialNumber +#@brief Obtiene el nº de serie del cliente. +#*/ ## def ogGetSerialNumber(): # Si se solicita, mostrar ayuda. if len(sys.argv) > 1 and sys.argv[1] == "help": @@ -82,6 +122,11 @@ def ogGetSerialNumber(): return 0 + +#/** +# ogIsEfiActive +#@brief Comprueba si el sistema tiene activo el arranque EFI. +#*/ ## def ogIsEfiActive(): return os.path.isdir("/sys/firmware/efi") @@ -97,7 +142,7 @@ def parse_lshw_output(): # Ejemplo de datos clave que podríamos extraer if "product" in lshw_data: parsed_output.append(f"product={lshw_data['product']}") - + if "vendor" in lshw_data: parsed_output.append(f"vendor={lshw_data['vendor']}") @@ -115,11 +160,20 @@ def parse_lshw_output(): # Devolver los datos combinados return "\n".join(parsed_output) - + except subprocess.CalledProcessError as e: print(f"Error al ejecutar lshw: {e}") return "Error al obtener información de hardware" + +#/** +# ogListHardwareInfo +#@brief Lista el inventario de hardware de la máquina cliente. +#@return TipoDispositivo:Modelo (por determinar) +#@warning Se ignoran los parámetros de entrada. +#@note TipoDispositivo = { bio, boa, bus, cha, cdr, cpu, dis, fir, mem, mod, mul, net, sto, usb, vga } +#@note Requisitos: dmidecode, lshw, awk +#*/ ## def ogListHardwareInfo(): # Ejecutar dmidecode y obtener tipo de chasis try: @@ -137,6 +191,17 @@ def ogListHardwareInfo(): # Combina y devuelve los resultados return f"{output}\n{firmware}\n{lshw_output}" + +#/** +# ogListSoftware int_ndisk int_npartition +#@brief Lista el inventario de software instalado en un sistema operativo. +#@param int_ndisk nº de orden del disco +#@param int_npartition nº de orden de la partición +#@return programa versión ... +#@warning Se ignoran los parámetros de entrada. +#@note Requisitos: ... +#@todo Detectar software en Linux +#*/ ## def ogListSoftware(disk, partition): if disk is None or partition is None: SystemLib.ogRaiseError(ogGlobals.OG_ERR_FORMAT) @@ -197,41 +262,215 @@ def ogListSoftware(disk, partition): return sorted(set(apps)) +## https://stackoverflow.com/questions/2522651/find-a-key-inside-a-deeply-nested-dictionary/2522706#2522706 +def _find_key_recursive(plist_dict, key_substr): + for k in plist_dict.keys(): + if key_substr in k: return plist_dict[k] + for k, v in plist_dict.items(): + if type(v) is dict: # Only recurse if we hit a dict value + value = _find_key_recursive(v, key_substr) + if value: + return value + return '' + +#/** +# ogGetOsVersion int_ndisk int_nfilesys +#@brief Devuelve la versión del sistema operativo instalado en un sistema de archivos. +#@param int_ndisk nº de orden del disco +#@param int_nfilesys nº de orden de la partición +#@return OSType:OSVersion - tipo y versión del sistema operativo. +#@note OSType = { Android, BSD, GrubLoader, Hurd, Linux, MacOS, Solaris, Windows, WinLoader } +#@note Requisitos: awk, head, chroot +#@exception OG_ERR_FORMAT Formato incorrecto. +#@exception OG_ERR_NOTFOUND Disco o partición no corresponden con un dispositiv +#@exception OG_ERR_PARTITION Fallo al montar el sistema de archivos. +#*/ ## +#ogGetOsVersion ("1", "2") => "Linux:Ubuntu precise (12.04 LTS) 64 bits" def ogGetOsVersion(disk, part): - try: - mnt_dir = FileSystemLib.ogMount(disk, part) - - version = None - os_release = os.path.join(mnt_dir, "etc/os-release") - if os.path.isfile(os_release): - with open(os_release, "r") as f: + mntdir = FileSystemLib.ogMount (disk, part) + if not mntdir: + return None + + type = version = None + is64bit = '' + +# Buscar tipo de sistema operativo. +# Para GNU/Linux: leer descripción. + os_release = os.path.join(mntdir, "etc/os-release") + if os.path.isfile(os_release): + type = 'Linux' + with open(os_release, "r") as f: + for line in f: + if line.startswith("PRETTY_NAME"): + version = line.split("=", 1)[1].strip().strip('"') + break + + if not version: + lsb_release = os.path.join(mntdir, "etc/lsb-release") + if os.path.isfile(lsb_release): + type = 'Linux' + with open(lsb_release, "r") as f: for line in f: - if line.startswith("PRETTY_NAME"): + if line.startswith("DISTRIB_DESCRIPTION"): version = line.split("=", 1)[1].strip().strip('"') break - - if not version: - lsb_release = os.path.join(mnt_dir, "etc/lsb-release") - if os.path.isfile(lsb_release): - with open(lsb_release, "r") as f: - for line in f: - if line.startswith("DISTRIB_DESCRIPTION"): - version = line.split("=", 1)[1].strip().strip('"') - break - - if not version: - for distrib in ["redhat", "SuSE", "mandrake", "gentoo"]: - distrib_file = os.path.join(mnt_dir, f"etc/{distrib}-release") - if os.path.isfile(distrib_file): - with open(distrib_file, "r") as f: - version = f.readline().strip() - break - - is_64bit = os.path.exists(os.path.join(mnt_dir, "lib64")) - if is_64bit: - version = f"{version} 64 bits" - return f"Linux: {version}" if version else "Linux: Unknown" - except Exception as e: - print(f"Fail to get OS: {e}") - return None \ No newline at end of file + if not version: + for distrib in ["redhat", "SuSE", "mandrake", "gentoo"]: + distrib_file = os.path.join(mntdir, f"etc/{distrib}-release") + if os.path.isfile(distrib_file): + type = 'Linux' + with open(distrib_file, "r") as f: + version = f.readline().strip() + break + + if not version: + arch_release_file = os.path.join(mntdir, "etc/arch-release") + if os.path.isfile(arch_release_file): + type = 'Linux' + version = "Arch Linux" + + if not version: + slack_release_file = os.path.join(mntdir, "slackware-version") + if os.path.isfile(slack_release_file): + type = 'Linux' + with open (slack_release_file, 'r') as fd: + c = fd.read() + version = "Slackware {c}" + +# Si no se encuentra, intentar ejecutar "lsb_release". + if not version: + out = subprocess.run (['chroot', mntdir, 'lsb_release', '-d'], capture_output=True, text=True).stdout + m = re.search (':\t(.*)', out) + if m: + type = 'Linux' + version = m.group(1) +# Comprobar Linux de 64 bits. + if version and os.path.exists(os.path.join(mntdir, "lib64")): + is64bit = ogGlobals.lang.MSG_64BIT +# Para Android, leer fichero de propiedades. + if not version: + type = 'Android' + files = glob.glob (os.path.join (mntdir, 'android*/system/build.prop')) + if files and os.path.isfile (files[0]): + v = [] + with open (files[0], 'r') as f: + for line in f: + if 'product.brand' in line or 'build.version.release' in line: + v.append (line.split('=')[1].strip()) + version = ' '.join (v) + if os.path.exists(os.path.join(mntdir, "lib64")): + is64bit = ogGlobals.lang.MSG_64BIT +# Para GNU/Hurd, comprobar fichero de inicio (basado en os-prober). + if not version: + type = 'Hurd' + if os.path.exists(os.path.join(mntdir, "hurd/init")): + version = 'GNU/Hurd' +# Para Windows: leer la version del registro. + if not version: + type = 'Windows' + build = 0 + file = RegistryLib.ogGetHivePath (mntdir, 'SOFTWARE') + if file: + # Nuevo método más rápido para acceder al registro de Windows.. + i = '\n'.join ([ + f'load {file}', + r'cd \Microsoft\Windows NT\CurrentVersion', + 'lsval ProductName', + 'lsval DisplayVersion', + ]) + version = subprocess.run (['hivexsh'], input=i, capture_output=True, text=True).stdout +# Recoge el valor del número de compilación para ver si es Windows 10/11 + i = '\n'.join ([ + f'load {file}', + r'cd \Microsoft\Windows NT\CurrentVersion', + 'lsval CurrentBuildNumber', + ]) + build = subprocess.run (['hivexsh'], input=i, capture_output=True, text=True).stdout + + if subprocess.run (['reglookup', '-H', '-p', 'Microsoft/Windows/CurrentVersion/ProgramW6432Dir', file], capture_output=True, text=True).stdout: + is64bit = ogGlobals.lang.MSG_64BIT + + if not version: + # Compatibilidad con métrodo antiguo y más lento de acceder al registro. + version = RegistryLib.ogGetRegistryValue (mntdir, 'software', r'\Microsoft\Windows NT\CurrentVersion\ProductName') + if RegistryLib.ogGetRegistryValue (mntdir, 'software', r'\Microsoft\Windows\CurrentVersion\ProgramW6432Dir'): + is64bit = ogGlobals.lang.MSG_64BIT + # Si la compilación es mayor o igual a 22000 es Windows 11 + if int (build) >= 22000: + version = version.replace ('10', '11') +# Para cargador Windows: buscar versión en fichero BCD (basado en os-prober). + if not version: + type = 'WinLoader' + file = FileLib.ogGetPath (file=f'{mntdir}/boot/bcd') + if file: + for distrib in 'Windows Recovery', 'Windows Boot': + with open (file, 'rb') as fd: + contents = fd.read() + distrib_utf16_regex = re.sub (r'(.)', '\\1.', distrib) + distrib_utf16_regex = bytes (distrib_utf16_regex, 'ascii') + if re.search (distrib_utf16, contents): + version = f'{distrib} loader' +# Para macOS: detectar kernel y completar con fichero plist de información del sistema. + if not version: + type = 'MacOS' + # Kernel de Mac OS (no debe ser fichero de texto). + file = f'{mntdir}/mach_kernel' + out = subprocess.run (['file', '--brief', file], capture_output=True, text=True).stdout + if not 'text' in out: + # Obtener tipo de kernel. + if 'Mach-O' in out: version = 'macOS' + if 'Mach-O 64-bit' in out: is64bit = ogGlobals.lang.MSG_64BIT + # Datos de configuración de versión de Mac OS. + file = f'{mntdir}/System/Library/CoreServices/SystemVersion.plist' + if os.path.exists (file): + with open (file, 'rb') as fd: + contents = fd.read() + plist_dict = plistlib.loads (contents) + n = _find_key_recursive (plist_dict, 'ProductName') + v = _find_key_recursive (plist_dict, 'ProductVersion') + version = f'{n} {v}'.strip() + # Datos de recuperación de macOS. + if version and os.path.exists (f'{mntdir}/com.apple.recovery.boot'): + version += ' recovery' + +# Para FreeBSD: obtener datos del Kernel. +### TODO Revisar solución. + if not version: + type = 'BSD' + file = f'{mntdir}/boot/kernel/kernel' + if os.path.exists (file): + lines = subprocess.run (['strings', file], capture_output=True, text=True).stdout.splitlines() + release_search = list (filter (lambda x: re.search ('@.*RELEASE', x), lines)) + if release_search: + first, second, *rest = release_search[0].split() + first = first.replace ('@(#)', '') + version = f'{first} {second}' + out = subprocess.run (['file', '--brief', file], capture_output=True, text=True).stdout + if 'x86-64' in out: is64bit = ogGlobals.lang.MSG_64BIT +# Para Solaris: leer el fichero de versión. +### TODO Revisar solución. + if not version: + type = 'Solaris' + file = f'{mntdir}/etc/release' + if os.path.exists (file): + with open (file, 'r') as fd: + version = fd.readline().strip +# Para cargador GRUB, comprobar fichero de configuración. + if not version: + type = 'GrubLoader' + for file in f'{mntdir}/grub/menu.lst', f'{mntdir}/boot/grub/menu.lst': + if os.path.exists (file): + VERSION = 'GRUB Loader' + for entry in f'{mntdir}/grub/grub.cfg', f'{mntdir}/grub2/grub.cfg', f'{mntdir}/EFI/*/grub.cfg', f'{mntdir}/boot/grub/grub.cfg', f'{mntdir}/boot/grub2/grub.cfg', f'{mntdir}/boot/EFI/*/grub.cfg': + for file in glob.glob (entry): + if os.path.exists (file): + version = 'GRUB2 Loader' + + + + + +# Mostrar resultado y salir sin errores. + if version: return f"{type}: {version} {is64bit}" + return None diff --git a/client/lib/engine/bin/RegistryLib.py b/client/lib/engine/bin/RegistryLib.py index f520520..c4c7eab 100755 --- a/client/lib/engine/bin/RegistryLib.py +++ b/client/lib/engine/bin/RegistryLib.py @@ -1,17 +1,41 @@ +#/** +#@file Registry.lib +#@brief Librería o clase Registry +#@class Boot +#@brief Funciones para gestión del registro de Windows. +#@version 1.1.0 +#@warning License: GNU GPLv3+ +#*/ + import subprocess import os import re +import shutil import ogGlobals import SystemLib import FileLib -def chntpw(*args): - chntpw_path = subprocess.check_output(['which', 'drbl-chntpw']).decode().strip() - if not chntpw_path: - chntpw_path = subprocess.check_output(['which', 'chntpw']).decode().strip() - subprocess.run([chntpw_path, '-e'] + list(args), timeout=5) +# Función ficticia para lanzar chntpw con timeout de 5 s., evitando cuelgues del programa. +def chntpw (file, input): + exe = shutil.which ('drbl-chntpw') or shutil.which ('chntpw') + return subprocess.run ([exe, '-e', file], timeout=5, input=input, capture_output=True, text=True).stdout + + +#/** +# ogAddRegistryKey path_mountpoint str_hive str_keyname +#@brief Añade una nueva clave al registro de Windows. +#@param path_mountpoint directorio donde está montado el sistema Windows +#@param str_hive sección del registro +#@param str_keyname nombre de la clave +#@return (nada) +#@exception OG_ERR_FORMAT Formato incorrecto. +#@exception OG_ERR_NOTFOUND Fichero de registro no encontrado. +#@note hive = { default, sam, security, software, system, components } +#@warning Requisitos: chntpw +#@warning El sistema de archivos de Windows debe estar montada previamente. +#*/ ## def ogAddRegistryKey(path_mountpoint, str_hive, str_key): # Variables locales. FILE = ogGetHivePath(path_mountpoint, str_hive) @@ -24,6 +48,22 @@ def ogAddRegistryKey(path_mountpoint, str_hive, str_key): chntpw(FILE, 'q') chntpw(FILE, 'y') + +#/** +# ogAddRegistryValue path_mountpoint str_hive str_valuename [str_valuetype] +#@brief Añade un nuevo valor al registro de Windows, indicando su tipo de datos. +#@param path_mountpoint directorio donde está montado el sistema Windows +#@param str_hive sección del registro +#@param str_valuename nombre del valor +#@param str_valuetype tipo de datos del valor (opcional) +#@return (nada) +#@exception OG_ERR_FORMAT Formato incorrecto. +#@exception OG_ERR_NOTFOUND Fichero de registro no encontrado. +#@note hive = { DEFAULT, SAM, SECURITY, SOFTWARE, SYSTEM, COMPONENTS } +#@note valuetype = { STRING, BINARY, DWORD }, por defecto: STRING +#@warning Requisitos: chntpw +#@warning El sistema de archivos de Windows debe estar montada previamente. +#*/ ## def ogAddRegistryValue(path_mountpoint, str_hive, str_key, str_valuename, str_valuetype=''): # Variables locales. FILE = ogGetHivePath(path_mountpoint, str_hive) @@ -51,6 +91,21 @@ def ogAddRegistryValue(path_mountpoint, str_hive, str_key, str_valuename, str_va chntpw(FILE, 'q') chntpw(FILE, 'y') + +#/** +# ogDeleteRegistryKey path_mountpoint str_hive str_keyname +#@brief Elimina una clave del registro de Windows con todo su contenido. +#@param path_mountpoint directorio donde está montado el sistema Windows +#@param str_hive sección del registro +#@param str_keyname nombre de la clave +#@return (nada) +#@exception OG_ERR_FORMAT Formato incorrecto. +#@exception OG_ERR_NOTFOUND Fichero de registro no encontrado. +#@note hive = { default, sam, security, software, system, components } +#@warning Requisitos: chntpw +#@warning El sistema de archivos de Windows debe estar montada previamente. +#@warning La clave debe estar vacía para poder ser borrada. +#*/ ## def ogDeleteRegistryKey(path_mountpoint, str_hive, str_key): # Variables locales. FILE = ogGetHivePath(path_mountpoint, str_hive) @@ -60,6 +115,20 @@ def ogDeleteRegistryKey(path_mountpoint, str_hive, str_key): # Delete the registry key. subprocess.run(['chntpw', FILE], input=f"cd {str_key.rsplit('\\', 1)[0]}\ndk {str_key.rsplit('\\', 1)[-1]}\nq\ny\n".encode(), timeout=5) + +#/** +# ogDeleteRegistryValue path_mountpoint str_hive str_valuename +#@brief Elimina un valor del registro de Windows. +#@param path_mountpoint directorio donde está montado el sistema Windows +#@param str_hive sección del registro +#@param str_valuename nombre del valor +#@return (nada) +#@exception OG_ERR_FORMAT Formato incorrecto. +#@exception OG_ERR_NOTFOUND Fichero de registro no encontrado. +#@note hive = { default, sam, security, software, system, components } +#@warning Requisitos: chntpw +#@warning El sistema de archivos de Windows debe estar montada previamente. +#*/ ## def ogDeleteRegistryValue(path_mountpoint, str_hive, str_valuename): # Variables locales. FILE = ogGetHivePath(path_mountpoint, str_hive) @@ -72,57 +141,85 @@ def ogDeleteRegistryValue(path_mountpoint, str_hive, str_valuename): chntpw(FILE, 'q') chntpw(FILE, 'y') -def ogGetHivePath(path_mountpoint, str_hive): - # Variables locales. - FILE = None +#/** +# ogGetHivePath path_mountpoint [str_hive|str_user] +#@brief Función básica que devuelve el camino del fichero con una sección del registro. +#@param path_mountpoint directorio donde está montado el sistema Windows +#@param str_hive sección del registro +#@return str_path - camino del fichero de registro +#@exception OG_ERR_FORMAT Formato incorrecto. +#@exception OG_ERR_NOTFOUND Fichero de registro no encontrado. +#@note hive = { DEFAULT, SAM, SECURITY, SOFTWARE, SYSTEM, COMPONENTS, NombreDeUsuario } +#@warning El sistema de archivos de Windows debe estar montada previamente. +#*/ ## +#ogGetHivePath ('/mnt/sda1', 'SOFTWARE') => /mnt/sda1/WINDOWS/System32/config/SOFTWARE +#ogGetHivePath ('/mnt/sda1', 'user1') => /mnt/sda1/Users/user1/NTUSER.DAT +def ogGetHivePath(path_mountpoint, str_hive): # Camino del fichero de registro de usuario o de sistema (de menor a mayor prioridad). - FILE = FileLib.ogGetPath(f"/{path_mountpoint}/Windows/System32/config/{str_hive}") - if not FILE: - FILE = FileLib.ogGetPath(f"/{path_mountpoint}/Users/{str_hive}/NTUSER.DAT") - if not FILE: - FILE = FileLib.ogGetPath(f"/{path_mountpoint}/winnt/system32/config/{str_hive}") - if not FILE: - FILE = FileLib.ogGetPath(f"/{path_mountpoint}/Documents and Settings/{str_hive}/NTUSER.DAT") + FILE = FileLib.ogGetPath(file=f"/{path_mountpoint}/Windows/System32/config/{str_hive}") + if not FILE: FILE = FileLib.ogGetPath(file=f"/{path_mountpoint}/Users/{str_hive}/NTUSER.DAT") + if not FILE: FILE = FileLib.ogGetPath(file=f"/{path_mountpoint}/winnt/system32/config/{str_hive}") + if not FILE: FILE = FileLib.ogGetPath(file=f"/{path_mountpoint}/Documents and Settings/{str_hive}/NTUSER.DAT") if FILE and os.path.isfile(FILE): return FILE else: SystemLib.ogRaiseError( - "session", + [], ogGlobals.OG_ERR_NOTFOUND, f"{path_mountpoint} {str_hive}" ) return None - -def ogGetRegistryValue(path_mountpoint, str_hive, str_valuename): - # Variables locales. - FILE = ogGetHivePath(path_mountpoint, str_hive) - if not FILE: - return - # Devolver el dato del valor de registro. - chntpw_cmd = f''' - chntpw "{FILE}" << EOT 2> /dev/null | awk '/> Value/ {{ - if (index($0, "REG_BINARY") > 0) {{ - data="" - }} else {{ - getline - data=$0 - }} - }} - /^:[0-9A-F]+ / {{ - data=data""substr($0, 9, 48) - }} - END {{ - print data - }}' - cd {str_valuename.rsplit('\\', 1)[0]} - cat {str_valuename.rsplit('\\', 1)[-1]} - q - EOT - ''' - subprocess.run(chntpw_cmd, shell=True, timeout=5) - + +#/** +# ogGetRegistryValue path_mountpoint str_hive str_valuename +#@brief Devuelve el dato de un valor del registro de Windows. +#@param path_mountpoint directorio donde está montado el sistema Windows +#@param str_hive sección del registro +#@param str_valuename nombre del valor +#@return str_valuedata - datos del valor. +#@exception OG_ERR_FORMAT Formato incorrecto. +#@exception OG_ERR_NOTFOUND Fichero de registro no encontrado. +#@note hive = { default, sam, security, software, system, components } +#@warning Requisitos: chntpw, awk +#@warning El sistema de archivos de Windows debe estar montado previamente. +#*/ ## +def ogGetRegistryValue(path_mountpoint, str_hive, str_valuename): + FILE = ogGetHivePath(path_mountpoint, str_hive) + if not FILE: return + + elems = str_valuename.split ('\\') + dirname = '\\'.join (elems[0:-1]) + basename = elems[-1] + + input = '\n'.join ([ + f'cd {dirname}', + f'cat {basename}', + 'q', + ]) + chntpw_out = chntpw (file, input) + lines = chntpw_out.splitlines() + if 2 != len (lines): + return None + if 'REG_BINARY' in lines[0]: + offset, content = lines[1].split (maxsplit=1) + return content + + +#/** +# ogListRegistryKeys path_mountpoint str_hive str_key +#@brief Lista los nombres de subclaves de una determinada clave del registro de Windows. +#@param path_mountpoint directorio donde está montado el sistema Windows +#@param str_hive sección del registro +#@param str_key clave de registro +#@return str_subkey ... - lista de subclaves +#@exception OG_ERR_FORMAT Formato incorrecto. +#@exception OG_ERR_NOTFOUND Fichero de registro no encontrado. +#@note hive = { default, sam, security, software, system, components } +#@warning Requisitos: chntpw, awk +#@warning El sistema de archivos de Windows debe estar montado previamente. +#*/ ## def ogListRegistryKeys(path_mountpoint, str_hive, str_key): # Variables locales. FILE = ogGetHivePath(path_mountpoint, str_hive) @@ -138,6 +235,20 @@ def ogListRegistryKeys(path_mountpoint, str_hive, str_key): ''' subprocess.run(chntpw_cmd, shell=True, timeout=5) + +#/** +# ogListRegistryValues path_mountpoint str_hive str_key +#@brief Lista los nombres de valores de una determinada clave del registro de Windows. +#@param path_mountpoint directorio donde está montado el sistema Windows +#@param str_hive sección del registro +#@param str_key clave de registro +#@return str_value ... - lista de valores +#@exception OG_ERR_FORMAT Formato incorrecto. +#@exception OG_ERR_NOTFOUND Fichero de registro no encontrado. +#@note hive = { default, sam, security, software, system, components } +#@warning Requisitos: chntpw, awk +#@warning El sistema de archivos de Windows debe estar montado previamente. +#*/ ## def ogListRegistryValues(path_mountpoint, str_hive, str_key): # Variables locales. FILE = ogGetHivePath(path_mountpoint, str_hive) @@ -153,6 +264,21 @@ def ogListRegistryValues(path_mountpoint, str_hive, str_key): ''' subprocess.run(chntpw_cmd, shell=True, timeout=5) + +#/** +# ogSetRegistryValue path_mountpoint str_hive str_valuename str_valuedata +#@brief Establece el dato asociado a un valor del registro de Windows. +#@param path_mountpoint directorio donde está montado el sistema Windows +#@param str_hive sección del registro +#@param str_valuename nombre del valor de registro +#@param str_valuedata dato del valor de registro +#@return (nada) +#@exception OG_ERR_FORMAT Formato incorrecto. +#@exception OG_ERR_NOTFOUND Fichero de registro no encontrado. +#@note hive = { default, sam, security, software, system, components } +#@warning Requisitos: chntpw +#@warning El sistema de archivos de Windows debe estar montado previamente. +#*/ ## def ogSetRegistryValue(path_mountpoint, str_hive, str_valuename, str_data): # Variables locales. FILE = ogGetHivePath(path_mountpoint, str_hive) diff --git a/client/lib/engine/bin/UEFILib.py b/client/lib/engine/bin/UEFILib.py new file mode 100644 index 0000000..831a7a1 --- /dev/null +++ b/client/lib/engine/bin/UEFILib.py @@ -0,0 +1,232 @@ +import os.path +import shutil + +import ogGlobals +import SystemLib +import FileSystemLib +import DiskLib +import FileLib +import InventoryLib + +#!/bin/bash +# Libreria provisional para uso de UEFI +# Las funciones se incluirán las librerías ya existentes + +#/** +# ogNvramActiveEntry +#@brief Activa entrada de la NVRAM identificada por la etiqueta o el orden +#@param Num_order_entry | Label_entry Número de orden o la etiqueta de la entrada a borrar. +#@return (nada) +#@exception OG_ERR_FORMAT formato incorrecto. +#@exception OG_ERR_NOTUEFI UEFI no activa. +#@exception OG_ERR_NOTFOUND fichero o dispositivo no encontrado. +#*/ ## + +#/** +# ogNvramAddEntry +#@brief Crea nueva entrada en el gestor de arranque (NVRAM), opcionalmente la incluye al final del orden de arranque. +#@param Str_Label_entry Número de disco o etiqueta de la entrada a crear. +#@param Str_BootLoader Número de partición o cargador de arranque. +#@param Bool_Incluir_Arranque Incluir en el orden de arranque (por defecto FALSE) (opcional) +#@return (nada) +#@exception OG_ERR_FORMAT formato incorrecto. +#@exception OG_ERR_NOTUEFI UEFI no activa. +#@exception OG_ERR_NOTFOUND fichero o dispositivo no encontrado. +#*/ ## + + +#/** +# ogCopyEfiBootLoader int_ndisk str_repo path_image +#@brief Copia el cargador de arranque desde la partición EFI a la de sistema. +#@param int_ndisk nº de orden del disco +#@param int_part nº de partición +#@return (nada, por determinar) +#@exception OG_ERR_FORMAT formato incorrecto. +#@exception OG_ERR_NOTFOUND fichero o dispositivo no encontrado. +#@note Si existe el cargador en la partición de sistema no es válido +#*/ ## + + +#/** +# ogNvramDeleteEntry +#@brief Borra entrada de la NVRAM identificada por la etiqueta o el orden +#@param Num_order_entry | Label_entry Número de orden o la etiqueta de la entrada a borrar. +#@return (nada) +#@exception OG_ERR_FORMAT formato incorrecto. +#@exception OG_ERR_NOTUEFI UEFI no activa. +#@exception OG_ERR_NOTFOUND fichero o dispositivo no encontrado (entrada en NVRAM). +#*/ ## + + +#/** +# ogNvramGetCurrent +#@brief Muestra la entrada del gestor de arranque (NVRAM) que ha iniciado el equipo. +#@return Entrada con la que se ha iniciado el equipo +#@exception OG_ERR_NOTUEFI UEFI no activa. +#*/ ## + + +# ogNvramGetNext +#@brief Muestra la entrada del gestor de arranque (NVRAM) que se utilizará en el próximo arranque. +#@return Entrada que se utilizará en el próximo arranque +#@exception OG_ERR_NOTUEFI UEFI no activa. +#*/ ## + + +# ogNvramGetOrder +#@brief Muestra el orden de las entradas del gestor de arranque (NVRAM) +#@return Orden de las entradas +#@exception OG_ERR_NOTUEFI UEFI no activa. +#*/ ## + + +#/** +# ogNvramGetTimeout +#@brief Muestra el tiempo de espera del gestor de arranque (NVRAM) +#@return Timeout de la NVRAM +#@exception OG_ERR_NOTUEFI UEFI no activa. +#*/ ## + + +#/** +# ogGrubUefiConf int_ndisk int_part str_dir_grub +#@brief Genera el fichero grub.cfg de la ESP +#@param int_ndisk nº de orden del disco +#@param int_part nº de partición +#@param str_dir_grub prefijo del directorio de grub en la partición de sistema. ej: /boot/grubPARTITION +#@return (nada, por determinar) +#@exception OG_ERR_FORMAT formato incorrecto. +#@exception OG_ERR_NOTFOUND fichero o dispositivo no encontrado. +#@TODO Confirmar si el fichero "$EFIDIR/EFI/$BOOTLABEL/grub.cfg" es necesario. +#*/ ## + + +#/** +# ogNvramInactiveEntry +#@brief Inactiva entrada de la NVRAM identificada por la etiqueta o el orden +#@param Num_order_entry | Label_entry Número de orden o la etiqueta de la entrada a borrar. +#@return (nada) +#@exception OG_ERR_FORMAT formato incorrecto. +#@exception OG_ERR_NOTFOUND fichero o dispositivo no encontrado. +#@exception OG_ERR_NOTUEFI UEFI no activa. +#*/ ## + + +#/** +# ogNvramList +#@brief Lista las entradas de la NVRAN (sólo equipos UEFI) +#@return Entradas de la NVRAM con el formato: orden etiqueta [* (si está activa) ] +#@exception OG_ERR_NOTUEFI UEFI no activa. +#*/ ## + + +#/** +# ogNvramPxeFirstEntry +#@brief Sitúa la entrada de la tarjeta de red en el primer lugar en la NVRAM. +#@return (nada) +#@exception OG_ERR_NOTUEFI UEFI no activa. +#*/ ## + + +#/** +# ogRestoreEfiBootLoader int_ndisk str_repo +#@brief Copia el cargador de arranque de la partición de sistema a la partición EFI. +#@param int_ndisk nº de orden del disco +#@param int_part nº de partición +#@return (nada, por determinar) +#@exception OG_ERR_FORMAT formato incorrecto. +#@exception OG_ERR_NOTFOUND fichero o dispositivo no encontrado (partición de sistema o EFI). +#@exception OG_ERR_NOTOS sin sistema operativo. +#*/ ## +def ogRestoreEfiBootLoader (disk, par): + mntdir = FileSystemLib.ogMount (disk, par) + if not mntdir: + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_PARTITION, f'{disk} {par}') + return + + esp = DiskLib.ogGetEsp() + if not esp: + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTFOUND, 'EFI partition') + return + esp_disk, esp_par = esp.split() + efidir = FileSystemLib.ogMount (esp_disk, esp_par) + if not efidir: + FileSystemLib.ogFormat (esp_disk, esp_par, 'FAT32') + efidir = FileSystemLib.ogMount (esp_disk, esp_par) + if not efidir: + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_PARTITION, 'ESP') + return + + osversion = InventoryLib.ogGetOsVersion (disk, par) + if 'Windows 1' in osversion: + bootlabel = f'Part-{disk:02d}-{par:02d}' + loader = FileLib.ogGetPath (f'{mntdir}/ogBoot/bootmgfw.efi') + if not loader: + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTOS, f'{disk} {par} ({osversion}, EFI)') + return + efi_bl = f'{efidir}/EFI/{bootlabel}' + if os.path.exists (efi_bl): + shutil.rmtree (efi_bl) + os.makedirs (efi_bl, exist_ok=True) + shutil.copytree (os.path.dirname (loader), f'{efi_bl}/Boot', symlinks=True) + shutil.copy (loader, f'{efi_bl}/Boot/ogloader.efi') + if '' != FileLib.ogGetPath (f'{efidir}/EFI/Microsoft'): + os.rename (f'{efidir}/EFI/Microsoft', f'{efidir}/EFI/Microsoft.backup.og') + + return + + +#/** +# ogRestoreUuidPartitions +#@brief Restaura los uuid de las particiones y la tabla de particiones +#@param int_ndisk nº de orden del disco +#@param int_nfilesys nº de orden del sistema de archivos +#@param REPO|CACHE repositorio +#@param str_imgname nombre de la imagen +#@return (nada) +#@exception OG_ERR_FORMAT Formato incorrecto. +#@exception OG_ERR_NOTFOUND No encontrado fichero de información de la imagen (con uuid) +#*/ ## + + +#/** +# ogNvramSetNext +#@brief Configura el próximo arranque con la entrada del gestor de arranque (NVRAM) identificada por la etiqueta o el orden. +#@param Num_order_entry | Label_entry Número de orden o la etiqueta de la entrada a borrar. +#@return (nada) +#@exception OG_ERR_FORMAT formato incorrecto. +#@exception OG_ERR_NOTUEFI UEFI no activa. +#@exception OG_ERR_NOTFOUND fichero o dispositivo no encontrado. +#*/ ## + +#/** +# ogNvramSetOrder +#@brief Configura el orden de las entradas de la NVRAM +#@param Orden de las entradas separadas por espacios +#@return (nada) +#@exception OG_ERR_FORMAT formato incorrecto. +#@exception OG_ERR_NOTUEFI UEFI no activa. +#@exception OG_ERR_NOTFOUND fichero o dispositivo no encontrado (entrada NVRAM). +#*/ ## + + +#/** +# ogNvramSetTimeout +#@brief Configura el tiempo de espera de la NVRAM +#@param Orden de las entradas separadas por espacios +#@return (nada) + +#@exception OG_ERR_FORMAT formato incorrecto. +#@exception OG_ERR_NOTFOUND fichero o dispositivo no encontrado. +#*/ ## + + +#/** +# ogUuidChange int_ndisk str_repo +#@brief Reemplaza el UUID de un sistema de ficheros. +#@param int_ndisk nº de orden del disco +#@param int_part nº de partición +#@return (nada, por determinar) +#@exception OG_ERR_FORMAT formato incorrecto. +#@exception OG_ERR_NOTFOUND fichero o dispositivo no encontrado. +#*/ ## From b4b2ab09cb40a94c919bfc29de461b25b307ed9c Mon Sep 17 00:00:00 2001 From: Natalia Serrano Date: Thu, 21 Nov 2024 16:07:30 +0100 Subject: [PATCH 078/167] refs #1166 add ogGetHostname() --- client/lib/engine/bin/NetLib.py | 57 +++++++++++++++------------------ 1 file changed, 26 insertions(+), 31 deletions(-) diff --git a/client/lib/engine/bin/NetLib.py b/client/lib/engine/bin/NetLib.py index d9e8908..4020c2e 100755 --- a/client/lib/engine/bin/NetLib.py +++ b/client/lib/engine/bin/NetLib.py @@ -1,3 +1,12 @@ +#/** +#@file Net.lib +#@brief Librería o clase Net +#@class Net +#@brief Funciones básicas de red. +#@version 1.0.6 +#@warning License: GNU GPLv3+ +#*/ + import subprocess import sys import os @@ -122,40 +131,26 @@ def ogGetGroupName(): #@return str_host - nombre de máquina #*/ ## def ogGetHostname(): - try: - # 1. Get hostname from the HOSTNAME environment variable - host = os.getenv("HOSTNAME", "").strip() +# Tomar nombre de la variable HOSTNAME + host = os.getenv("HOSTNAME", "").strip() + if host: return host - # 2. If not set, read from the DHCP leases file - if not host: - dhcp_file = "/var/lib/dhcp3/dhclient.leases" - if os.path.exists(dhcp_file): - with open(dhcp_file, "r") as f: - for line in f: - if 'option host-name' in line: - host = line.split('"')[1].strip(";") - break +# Si no, tomar del DHCP, opción host-name /* (comentario para Doxygen) + dhcp_file = "/var/lib/dhcp3/dhclient.leases" + if os.path.exists(dhcp_file): + with open(dhcp_file, "r") as f: + for line in f: + if 'option host-name' in line: + return line.split('"')[1].strip(";") - # 3. If still not set, read from kernel parameters in /proc/cmdline - if not host: - cmdline_file = "/proc/cmdline" - if os.path.exists(cmdline_file): - with open(cmdline_file, "r") as f: - for entry in f.read().split(): - if entry.startswith("hostname="): - host = entry.split("=")[1].strip() - break +# Si no, leer el parámetro del kernel hostname (comentario para Doxygen) */ + cmdline_file = "/proc/cmdline" + if os.path.exists(cmdline_file): + with open(cmdline_file, "r") as f: + for entry in f.read().split(): + if entry.startswith("hostname="): + return entry.split("=")[1].strip() - # 4. Update HOSTNAME environment variable if it differs - current_hostname = os.getenv("HOSTNAME", "") - if host and current_hostname != host: - os.environ["HOSTNAME"] = host - - return host if host else None - - except Exception as e: - print(f"Error in ogGetHostname: {e}") - return None #/** # ogGetIpAddress From 8ba0913684cbc967db95fef050ae93cdae98670a Mon Sep 17 00:00:00 2001 From: Natalia Serrano Date: Thu, 21 Nov 2024 16:11:21 +0100 Subject: [PATCH 079/167] refs #1166 add ogIsWritable() --- client/lib/engine/bin/FileSystemLib.py | 24 ++++++++++-------------- 1 file changed, 10 insertions(+), 14 deletions(-) diff --git a/client/lib/engine/bin/FileSystemLib.py b/client/lib/engine/bin/FileSystemLib.py index a843cce..80859e0 100755 --- a/client/lib/engine/bin/FileSystemLib.py +++ b/client/lib/engine/bin/FileSystemLib.py @@ -552,22 +552,18 @@ def ogIsReadonly(disk, par): options = result.stdout.strip().split(",") return "ro" in options -def ogIsWritable(int_ndisk, int_nfilesys): - if len(sys.argv) != 3: - SystemLib.ogRaiseError( - "session", - ogGlobals.OG_ERR_FORMAT, - f"Not enough arguments" - ) - return +#/** +# ogIsWritable int_ndisk int_nfilesys +#@brief Comprueba si un sistema de archivos está montado de lectura y escritura. +#@param int_ndisk nº de orden del disco +#@param int_nfilesys nº de orden del sistema de archivos +#@return Código de salida: 0 - lectura y escritura, 1 - solo lectura o no montado. +#*/ ## +def ogIsWritable (disk, par): + PART = DiskLib.ogDiskToDev (disk, par) + if not PART: return - # Obtener partición. - PART = DiskLib.ogDiskToDev(int_ndisk, int_nfilesys) - if not PART: - return - - # Comprobar si la partición está montada en modo de escritura. result = subprocess.run(["findmnt", "-n", "-o", "OPTIONS", PART], capture_output=True, text=True) options = result.stdout.strip().split(",") return "rw" in options From 4be9f566a64e6eb787f5668762a316a34364b1c9 Mon Sep 17 00:00:00 2001 From: Natalia Serrano Date: Thu, 21 Nov 2024 16:31:19 +0100 Subject: [PATCH 080/167] refs #1166 add ogGetPartitionActive() --- client/lib/engine/bin/DiskLib.py | 280 +++++++++++++++++++++++++++++-- 1 file changed, 262 insertions(+), 18 deletions(-) diff --git a/client/lib/engine/bin/DiskLib.py b/client/lib/engine/bin/DiskLib.py index 55f25e2..dd0c04c 100755 --- a/client/lib/engine/bin/DiskLib.py +++ b/client/lib/engine/bin/DiskLib.py @@ -1,3 +1,12 @@ +#/** +#@file Disk.lib +#@brief Librería o clase Disk +#@class Disk +#@brief Funciones para gestión de discos y particiones. +#@version 1.1.1 +#@warning License: GNU GPLv3+ +#*/ + import filecmp import subprocess import shutil @@ -10,6 +19,7 @@ import SystemLib import CacheLib import FileSystemLib +# Función ficticia para lanzar parted con timeout, evitando cuelgues del programa. def parted(*args): parted_path = shutil.which("parted") if parted_path: @@ -26,6 +36,23 @@ def parted(*args): else: return "Error: 'parted' command not found" + +#/** +# ogCreatePartitions int_ndisk str_parttype:int_partsize ... +#@brief Define el conjunto de particiones de un disco. +#@param int_ndisk nº de orden del disco +#@param str_parttype mnemónico del tipo de partición +#@param int_partsize tamaño de la partición (en KB) +#@return (nada, por determinar) +#@exception OG_ERR_FORMAT formato incorrecto. +#@exception OG_ERR_NOTFOUND disco o partición no detectado (no es un dispositivo). +#@exception OG_ERR_PARTITION error en partición o en tabla de particiones. +#@attention El nº de partición se indica por el orden de los párametros \c parttype:partsize +#@attention Pueden definirse particiones vacías de tipo \c EMPTY +#@attention No puede definirse partición de cache y no se modifica si existe. +#@note Requisitos: sfdisk, parted, partprobe, awk +#@todo Definir atributos (arranque, oculta) y tamaños en MB, GB, etc. +#*/ ## def ogCreatePartitions(*args): # Variables locales ND = DISK = PTTYPE = PART = SECTORS = START = SIZE = TYPE = CACHEPART = None @@ -123,6 +150,23 @@ def ogCreatePartitions(*args): CacheLib.ogMountCache() return 0 + +#/** +# ogCreateGptPartitions int_ndisk str_parttype:int_partsize ... +#@brief Define el conjunto de particiones de un disco GPT +#@param int_ndisk nº de orden del disco +#@param str_parttype mnemónico del tipo de partición +#@param int_partsize tamaño de la partición (en KB) +#@return (nada, por determinar) +#@exception OG_ERR_FORMAT formato incorrecto. +#@exception OG_ERR_NOTFOUND disco o partición no detectado (no es un dispositivo). +#@exception OG_ERR_PARTITION error en partición o en tabla de particiones. +#@attention El nº de partición se indica por el orden de los párametros \c parttype:partsize +#@attention Pueden definirse particiones vacías de tipo \c EMPTY +#@attention No puede definirse partición de caché y no se modifica si existe. +#@note Requisitos: sfdisk, parted, partprobe, awk +#@todo Definir atributos (arranque, oculta) y tamaños en MB, GB, etc. +#*/ ## def ogCreateGptPartitions(*args): # Variables locales ND = DISK = PART = SECTORS = ALIGN = START = SIZE = TYPE = CACHEPART = CACHESIZE = DELOPTIONS = OPTIONS = None @@ -214,6 +258,18 @@ def ogCreateGptPartitions(*args): CacheLib.ogMountCache() return 0 + +#/** +# ogCreatePartitionTable int_ndisk [str_tabletype] +#@brief Genera una tabla de particiones en caso de que no sea valida, si es valida no hace nada. +#@param int_ndisk nº de orden del disco +#@param str_tabletype tipo de tabla de particiones (opcional) +#@return (por determinar) +#@exception OG_ERR_FORMAT Formato incorrecto. +#@exception OG_ERR_NOTFOUND Disco o particion no corresponden con un dispositivo. +#@note tabletype: { MSDOS, GPT }, MSDOS por defecto +#@note Requisitos: fdisk, gdisk, parted +#*/ ## def ogCreatePartitionTable(*args): # Variables locales DISK = PTTYPE = CREATE = CREATEPTT = None @@ -281,6 +337,13 @@ def ogCreatePartitionTable(*args): subprocess.run(["partprobe", DISK], stderr=subprocess.DEVNULL) return + +#/** +# ogDeletePartitionTable ndisk +#@brief Borra la tabla de particiones del disco. +#@param int_ndisk nº de orden del disco +#@return la informacion propia del fdisk +#*/ ## def ogDeletePartitionTable(*args): # Variables locales DISK = None @@ -546,6 +609,16 @@ def ogDiskToDev (arg_disk=None, arg_part=None): return part + +#/** +# ogGetDiskSize int_ndisk +#@brief Muestra el tamaño en KB de un disco. +#@param int_ndisk nº de orden del disco +#@return int_size - Tamaño en KB del disco. +#@exception OG_ERR_FORMAT formato incorrecto. +#@exception OG_ERR_NOTFOUND disco o particion no detectado (no es un dispositivo). +#@note Requisitos: sfdisk, awk +#*/ ## def ogGetDiskSize(*args): # Variables locales DISK = SIZE = None @@ -571,6 +644,15 @@ def ogGetDiskSize(*args): print(SIZE) return + +#/** +# ogGetDiskType path_device +#@brief Muestra el tipo de disco (real, RAID, meta-disco, USB, etc.). +#@param path_device Dispositivo +#@exception OG_ERR_FORMAT formato incorrecto. +#@exception OG_ERR_NOTFOUND disco no detectado o no es un dispositivo de bloques. +#@note Requisitos: udevadm +#*/ ## def ogGetDiskType(*args): # Variables locales DEV = MAJOR = TYPE = None @@ -629,6 +711,17 @@ def ogGetEsp(): return PART return None + +#/** +# ogGetLastSector int_ndisk [int_npart] +#@brief Devuelve el último sector usable del disco o de una partición. +#@param int_ndisk nº de orden del disco +#@param int_npart nº de orden de la partición (opcional) +#@return Último sector usable. +#@exception OG_ERR_FORMAT Formato incorrecto. +#@exception OG_ERR_NOTFOUND Disco o partición no corresponde con un dispositivo. +#@note Requisitos: sfdisk, sgdisk +#*/ ## def ogGetLastSector(*args): # Variables locales DISK = None @@ -663,27 +756,39 @@ def ogGetLastSector(*args): print(LASTSECTOR) return -def ogGetPartitionActive(*args): - # Variables locales - DISK = None - # Si se solicita, mostrar ayuda. - if len(args) == 1 and args[0] == "help": - SystemLib.ogHelp('ogGetPartitionActive', 'ogGetPartitionActive int_ndisk', 'ogGetPartitionActive 1 => 1') - return +#/** +# ogGetPartitionActive int_ndisk +#@brief Muestra que particion de un disco esta marcada como de activa. +#@param int_ndisk nº de orden del disco +#@exception OG_ERR_FORMAT Formato incorrecto. +#@exception OG_ERR_NOTFOUND Disco o particion no corresponden con un dispositivo. +#@note Requisitos: parted +#@todo Queda definir formato para atributos (arranque, oculta, ...). +#*/ ## +def ogGetPartitionActive (disk): + DISK = ogDiskToDev (disk) + if DISK is None: return - # Error si no se recibe 1 parámetro. - if len(args) != 1: - SystemLib.ogRaiseError(OG_ERR_FORMAT) - return + if 'LANG' in os.environ: + lang = os.environ['LANG'] - # Comprobar que el disco existe y listar su partición activa. - DISK = ogDiskToDev(args[0]) - if DISK is None: - return - output = subprocess.getoutput(f"parted -sm {DISK} print 2>/dev/null | awk -F: '$7~/boot/ {{print $1}}'") - print(output) - return + ret = None + os.environ['LANG'] = 'C' + lines = subprocess.run (['parted', '--script', '--machine', DISK, 'print'], capture_output=True, text=True).stdout.splitlines() + for line in lines: + parts = line.split (':') + if len (parts) < 6: continue + if 'boot' in parts[6]: + ret = parts[0] + break + + if lang is None: + del os.environ['LANG'] + else: + os.environ['LAMG'] = lang + + return ret #/** @@ -743,6 +848,16 @@ def ogGetPartitionSize (disk, par): return FileSystemLib.ogGetFsSize (disk, par) + +#/** +# ogGetPartitionsNumber int_ndisk +#@brief Detecta el numero de particiones del disco duro indicado. +#@param int_ndisk nº de orden del disco +#@return Devuelve el numero paritiones del disco duro indicado +#@warning Salidas de errores no determinada +#@attention Requisitos: parted +#@note Notas sin especificar +#*/ ## def ogGetPartitionsNumber(*args): # Variables locales DISK = None @@ -845,6 +960,17 @@ def ogGetPartitionType(*args): print(TYPE) return + +#/** +# ogHidePartition int_ndisk int_npartition +#@brief Oculta un apartición visible. +#@param int_ndisk nº de orden del disco +#@param int_npartition nº de orden de la partición +#@return (nada) +#@exception OG_ERR_FORMAT formato incorrecto. +#@exception OG_ERR_NOTFOUND disco o particion no detectado (no es un dispositivo). +#@exception OG_ERR_PARTITION tipo de partición no reconocido. +#*/ ## def ogHidePartition(*args): # Variables locales PART = None @@ -886,6 +1012,14 @@ def ogHidePartition(*args): ogSetPartitionType(args[0], args[1], NEWTYPE) return + +#/** +# ogIdToType int_idpart +#@brief Devuelve el identificador correspondiente a un tipo de partición. +#@param int_idpart identificador de tipo de partición. +#@return str_parttype mnemónico de tipo de partición. +#@exception OG_ERR_FORMAT Formato incorrecto. +#*/ ## def ogIdToType(ID): # Obtener valor hexadecimal de 4 caracteres rellenado con 0 por delante. ID = ID.zfill(4) @@ -985,6 +1119,13 @@ def ogIdToType(ID): return TYPE + +# ogIsDiskLocked int_ndisk +#@brief Comprueba si un disco está bloqueado por una operación de uso exclusivo. +#@param int_ndisk nº de orden del disco +#@return Código de salida: 0 - bloqueado, 1 - sin bloquear o error. +#@note Los ficheros de bloqueo se localizan en \c /var/lock/dev, siendo \c dev el dispositivo de la partición o de su disco, sustituyendo el carácter "/" por "-". +#*/ ## def ogIsDiskLocked(*args): # Variables locales DISK = None @@ -1006,6 +1147,18 @@ def ogIsDiskLocked(*args): LOCKFILE = f"/var/lock/lock{DISK.replace('/', '-')}" return os.path.isfile(LOCKFILE) + +#/** +# ogListPartitions int_ndisk +#@brief Lista las particiones definidas en un disco. +#@param int_ndisk nº de orden del disco +#@return str_parttype:int_partsize ... +#@exception OG_ERR_FORMAT formato incorrecto. +#@exception OG_ERR_NOTFOUND disco o particion no detectado (no es un dispositivo). +#@note Requisitos: \c parted \c awk +#@attention El nº de partición se indica por el orden de los párametros \c parttype:partsize +#@attention Las tuplas de valores están separadas por espacios. +#*/ ## def ogListPartitions(*args): # Variables locales DISK = None @@ -1036,6 +1189,13 @@ def ogListPartitions(*args): print() return + +#/** +# ogListPrimaryPartitions int_ndisk +#@brief Metafunción que lista las particiones primarias no vacías de un disco. +#@param int_ndisk nº de orden del disco +#@see ogListPartitions +#*/ ## def ogListPrimaryPartitions(*args): # Variables locales PTTYPE = None @@ -1059,6 +1219,13 @@ def ogListPrimaryPartitions(*args): print(PARTS.split(" ")[0:4]) return + +#/** +# ogListLogicalPartitions int_ndisk +#@brief Metafunción que lista las particiones lógicas de una tabla tipo MSDOS. +#@param int_ndisk nº de orden del disco +#@see ogListPartitions +#*/ ## def ogListLogicalPartitions(*args): # Variables locales PTTYPE = None @@ -1078,6 +1245,16 @@ def ogListLogicalPartitions(*args): return PARTS.split(" ")[4:] + +#/** +# ogLockDisk int_ndisk +#@brief Genera un fichero de bloqueo para un disco en uso exlusivo. +#@param int_ndisk nº de orden del disco +#@return (nada) +#@exception OG_ERR_FORMAT Formato incorrecto. +#@exception OG_ERR_NOTFOUND Disco o particion no corresponden con un dispositivo. +#@note El fichero de bloqueo se localiza en \c /var/lock/disk, siendo \c disk el dispositivo del disco, sustituyendo el carácter "/" por "-". +#*/ ## def ogLockDisk(*args): # Variables locales DISK = None @@ -1102,6 +1279,17 @@ def ogLockDisk(*args): LOCKFILE = f"/var/lock/lock{DISK.replace('/', '-')}" open(LOCKFILE, 'a').close() + +#/** +# ogSetPartitionActive int_ndisk int_npartition +#@brief Establece cual es la partición activa de un disco. +#@param int_ndisk nº de orden del disco +#@param int_npartition nº de orden de la partición +#@return (nada). +#@exception OG_ERR_FORMAT Formato incorrecto. +#@exception OG_ERR_NOTFOUND Disco o partición no corresponden con un dispositivo. +#@note Requisitos: parted +#*/ ## def ogSetPartitionActive(*args): # Variables locales DISK = None @@ -1127,6 +1315,20 @@ def ogSetPartitionActive(*args): subprocess.run(["parted", "-s", DISK, "set", args[1], "boot", "on"], stderr=subprocess.DEVNULL) return + +#/** +# ogSetPartitionId int_ndisk int_npartition hex_partid +#@brief Cambia el identificador de la partición. +#@param int_ndisk nº de orden del disco +#@param int_npartition nº de orden de la partición +#@param hex_partid identificador de tipo de partición +#@return (nada) +#@exception OG_ERR_FORMAT Formato incorrecto. +#@exception OG_ERR_NOTFOUND Disco o partición no corresponden con un dispositivo. +#@exception OG_ERR_OUTOFLIMIT Valor no válido. +#@exception OG_ERR_PARTITION Error al cambiar el id. de partición. +#@attention Requisitos: fdisk, sgdisk +#*/ ## def ogSetPartitionId(*args): # Variables locales DISK = None @@ -1174,6 +1376,19 @@ def ogSetPartitionId(*args): SystemLib.ogRaiseError(OG_ERR_PARTITION, f"{args[0]},{args[1]},{args[2]}") return + +#/** +# ogSetPartitionSize int_ndisk int_npartition int_size +#@brief Muestra el tamano en KB de una particion determinada. +#@param int_ndisk nº de orden del disco +#@param int_npartition nº de orden de la partición +#@param int_size tamaño de la partición (en KB) +#@return (nada) +#@exception OG_ERR_FORMAT formato incorrecto. +#@exception OG_ERR_NOTFOUND disco o particion no detectado (no es un dispositivo). +#@note Requisitos: sfdisk, awk +#@todo Compruebar que el tamaño sea numérico positivo y evitar que pueda solaparse con la siguiente partición. +#*/ ## def ogSetPartitionSize(*args): # Variables locales DISK = None @@ -1204,6 +1419,16 @@ def ogSetPartitionSize(*args): subprocess.run(["partprobe", DISK], stderr=subprocess.DEVNULL) return + +#/** +# ogSetPartitionType int_ndisk int_npartition str_type +#@brief Cambia el identificador de la partición. +#@param int_ndisk nº de orden del disco +#@param int_npartition nº de orden de la partición +#@param str_type mnemónico de tipo de partición +#@return (nada) +#@attention Requisitos: fdisk, sgdisk +#*/ ## def ogSetPartitionType(*args): # Variables locales DISK = None @@ -1399,6 +1624,16 @@ def ogUnhidePartition(*args): ogSetPartitionType(args[0], args[1], NEWTYPE) return + +#/** +# ogUnlockDisk int_ndisk +#@brief Elimina el fichero de bloqueo para un disco. +#@param int_ndisk nº de orden del disco +#@return (nada) +#@exception OG_ERR_FORMAT Formato incorrecto. +#@exception OG_ERR_NOTFOUND Disco o particion no corresponden con un dispositivo. +#@note El fichero de bloqueo se localiza en \c /var/lock/disk, siendo \c disk el dispositivo del disco, sustituyendo el carácter "/" por "-". +#*/ ## def ogUnlockDisk(*args): # Variables locales DISK = None @@ -1424,6 +1659,15 @@ def ogUnlockDisk(*args): os.remove(LOCKFILE) return + +#/** +# ogUpdatePartitionTable +#@brief Fuerza al kernel releer la tabla de particiones de los discos duros +#@param no requiere +#@return informacion propia de la herramienta +#@note Requisitos: \c partprobe +#@warning pendiente estructurar la funcion a opengnsys +#*/ ## def ogUpdatePartitionTable(): for disk in ogDiskToDev(): subprocess.run(["partprobe", disk]) From 410f47fba20c4d1e0f2279bc7e342831be97a7c0 Mon Sep 17 00:00:00 2001 From: Natalia Serrano Date: Thu, 21 Nov 2024 16:36:04 +0100 Subject: [PATCH 081/167] refs #1166 add ogSetPartitionActive() --- client/lib/engine/bin/DiskLib.py | 30 ++++++++++-------------------- 1 file changed, 10 insertions(+), 20 deletions(-) diff --git a/client/lib/engine/bin/DiskLib.py b/client/lib/engine/bin/DiskLib.py index dd0c04c..3ad9e46 100755 --- a/client/lib/engine/bin/DiskLib.py +++ b/client/lib/engine/bin/DiskLib.py @@ -18,6 +18,7 @@ import ogGlobals import SystemLib import CacheLib import FileSystemLib +import InventoryLib # Función ficticia para lanzar parted con timeout, evitando cuelgues del programa. def parted(*args): @@ -1290,29 +1291,18 @@ def ogLockDisk(*args): #@exception OG_ERR_NOTFOUND Disco o partición no corresponden con un dispositivo. #@note Requisitos: parted #*/ ## -def ogSetPartitionActive(*args): - # Variables locales - DISK = None - PART = None - - # Si se solicita, mostrar ayuda. - if len(args) == 1 and args[0] == "help": - SystemLib.ogHelp('ogSetPartitionActive', 'ogSetPartitionActive int_ndisk int_npartition', 'ogSetPartitionActive 1 1') +def ogSetPartitionActive (disk, par): + if InventoryLib.ogIsEfiActive(): + SystemLib.ogEcho (['session', 'log'], 'warning', f'EFI: {ogGlobals.lang.MSG_DONTUSE} {ogSetPartitionActive}') return - # Error si no se reciben 2 parámetros. - if len(args) != 2: - SystemLib.ogRaiseError(OG_ERR_FORMAT) - return + DISK = ogDiskToDev (disk) + if DISK is None: return - # Comprobar que el disco existe y activar la partición indicada. - DISK = ogDiskToDev(args[0]) - if DISK is None: - return - PART = ogDiskToDev(args[0], args[1]) - if PART is None: - return - subprocess.run(["parted", "-s", DISK, "set", args[1], "boot", "on"], stderr=subprocess.DEVNULL) + PART = ogDiskToDev (disk, par) + if PART is None: return + + subprocess.run (["parted", "-s", DISK, "set", par, "boot", "on"]) return From 9a78f9f2c78358b09821bb91f85f3b85e644c4f0 Mon Sep 17 00:00:00 2001 From: Natalia Serrano Date: Thu, 21 Nov 2024 17:49:21 +0100 Subject: [PATCH 082/167] refs #1166 add ogExtendFs() --- client/lib/engine/bin/FileSystemLib.py | 190 +++++++++++++++---------- client/lib/engine/bin/InventoryLib.py | 2 +- 2 files changed, 116 insertions(+), 76 deletions(-) diff --git a/client/lib/engine/bin/FileSystemLib.py b/client/lib/engine/bin/FileSystemLib.py index 80859e0..8d80135 100755 --- a/client/lib/engine/bin/FileSystemLib.py +++ b/client/lib/engine/bin/FileSystemLib.py @@ -1,3 +1,12 @@ +#/** +#@file FileSystem.lib +#@brief Librería o clase FileSystem +#@class FileSystem +#@brief Funciones para gestión de sistemas de archivos. +#@version 1.1.0 +#@warning License: GNU GPLv3+ +#*/ + import subprocess import sys import os.path @@ -8,6 +17,20 @@ import DiskLib import CacheLib import FileSystemLib + +#/** +# ogCheckFs int_ndisk int_nfilesys +#@brief Comprueba el estado de un sistema de archivos. +#@param int_ndisk nº de orden del disco +#@param int_nfilesys nº de orden del sistema de archivos +#@return (nada) +#@exception OG_ERR_FORMAT Formato incorrecto. +#@exception OG_ERR_NOTFOUND Disco o particion no corresponden con un dispositivo. +#@exception OG_ERR_PARTITION Partición desconocida o no accesible. +#@note Requisitos: *fsck* +#@warning No se comprueban sistemas de archivos montados o bloqueados. +#@todo Definir salidas. +#*/ ## def ogCheckFs(int_ndisk, int_nfilesys): if len(sys.argv) != 3: @@ -119,97 +142,84 @@ def ogCheckFs(int_ndisk, int_nfilesys): ogUnlock(int_ndisk, int_nfilesys) return ERRCODE -def ogExtendFs(): - # Error si no se reciben 2 parámetros. - if len(sys.argv) != 3: - SystemLib.ogRaiseError( - "session", - ogGlobals.OG_ERR_FORMAT, - f"Not enough arguments" - ) - return +#/** +# ogExtendFs int_ndisk int_nfilesys +#@brief Extiende un sistema de archivos al tamaño de su partición. +#@param int_ndisk nº de orden del disco +#@param int_nfilesys nº de orden del sistema de archivos +#@return (nada) +#@exception OG_ERR_FORMAT Formato incorrecto. +#@exception OG_ERR_NOTFOUND Disco o particion no corresponden con un dispositivo. +#@exception OG_ERR_PARTITION Partición desconocida o no accesible. +#@note Requisitos: *resize* +#*/ ## +def ogExtendFs (disk, par): + PART = DiskLib.ogDiskToDev (disk, par) + if not PART: return - # Obtener partición. - PART = DiskLib.ogDiskToDev(int(sys.argv[1]), int(sys.argv[2])) - if not PART: - return + data = { + 'EXT2': { 'prog': 'resize2fs', 'params': '-f', }, + 'EXT3': { 'prog': 'resize2fs', 'params': '-f', }, + 'EXT4': { 'prog': 'resize2fs', 'params': '-f', }, + 'BTRFS': { 'prog': 'btrfs', 'params': 'filesystem resize max', 'domount': True }, + 'REISERFS': { 'prog': 'resize_reiserfs', 'params': '-f', }, + 'REISER4': { 'prog': 'resize_reiserfs', 'params': '-f', }, + 'NTFS': { 'prog': 'ntfsresize', 'params': '-f', 'input': 'y' }, + 'F2FS': { 'unsupported': True }, + 'JFS': { 'unsupported': True }, + 'NILFS2': { 'unsupported': True }, # try "nilfs-resize" + 'XFS': { 'unsupported': True }, + 'EXFAT': { 'unsupported': True }, + 'FAT32': { 'unsupported': True }, # try "fatresize" + 'FAT16': { 'unsupported': True }, # try "fatresize" + 'HFS': { 'unsupported': True }, + 'HFSPLUS': { 'unsupported': True }, + 'UFS': { 'unsupported': True }, + } - # Redimensionar al tamaño máximo según el tipo de partición. - TYPE = ogGetFsType(int(sys.argv[1]), int(sys.argv[2])) - if TYPE == "EXT[234]": - PROG = "resize2fs" - PARAMS = "-f" - elif TYPE == "BTRFS": - PROG = "btrfs" - PARAMS = "filesystem resize max" - DOMOUNT = True # Debe estar montado. - elif TYPE == "REISERFS" or TYPE == "REISER4": - PROG = "resize_reiserfs" - PARAMS = "-f" - elif TYPE == "F2FS" or TYPE == "JFS" or TYPE == "NILFS2" or TYPE == "XFS" or TYPE == "EXFAT" or TYPE == "FAT32" or TYPE == "FAT16" or TYPE == "HFS" or TYPE == "HFSPLUS" or TYPE == "UFS": - return # No se reduce (por el momento). - elif TYPE == "NTFS": - PROG = "ntfsresize" - PARAMS = "<<<\"y\" -f" + type = ogGetFsType (disk, par) + if type in data: + prog = data[type]['prog'] if 'prog' in data[type] else None + params = data[type]['params'] if 'params' in data[type] else None + domount = data[type]['domount'] if 'domount' in data[type] else False + input = data[type]['input'] if 'input' in data[type] else None else: - SystemLib.ogRaiseError( - "session", - ogGlobals.OG_ERR_PARTITION, - f"{int(sys.argv[1])} {int(sys.argv[2])} {TYPE}" - ) + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_PARTITION, f'{disk} {par} {type}') return - # Salida normal si no se va a aplicar la operación. - if not PROG: - return + if not prog: return - # Error si el sistema de archivos no se queda en el estado de montaje adecuado. - if DOMOUNT: - PART = ogMount(int(sys.argv[1]), int(sys.argv[2])) - if not PART: - return + if domount: + PART = ogMount (disk, par) + if not PART: return else: - ogUnmount(int(sys.argv[1]), int(sys.argv[2])) - if ogIsMounted(int(sys.argv[1]), int(sys.argv[2])): - SystemLib.ogRaiseError( - "session", - ogGlobals.OG_ERR_PARTITION, - f"{int(sys.argv[1])} {int(sys.argv[2])}" - ) + ogUnmount (disk, par) + if ogIsMounted (disk, par): + SystemLib.ogRaiseError([], ogGlobals.OG_ERR_PARTITION, f'{disk} {par}') return - # Error si el sistema de archivos está bloqueado. - if ogIsLocked(int(sys.argv[1]), int(sys.argv[2])): - SystemLib.ogRaiseError( - "session", - ogGlobals.OG_ERR_LOCKED, - f"{int(sys.argv[1])} {int(sys.argv[2])}" - ) +# Error si el sistema de archivos está bloqueado. + if ogIsLocked (disk, par): + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_LOCKED, f'{disk} {par}') return - # Redimensionar en modo uso exclusivo. - ogLock(int(sys.argv[1]), int(sys.argv[2])) +# Redimensionar en modo uso exclusivo. + ogLock (disk, par) try: - subprocess.run([PROG, PARAMS, PART], capture_output=True) - ERRCODE = 0 + if input: + rc = subprocess.run ([prog] + params.split() + [PART], input=input, text=True).returncode + else: + rc = subprocess.run ([prog] + params.split() + [PART]).returncode except FileNotFoundError: - SystemLib.ogRaiseError( - "session", - ogGlobals.OG_ERR_NOTEXEC, - PROG - ) - ERRCODE = ogGlobals.OG_ERR_NOTEXEC + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTEXEC, prog) + rc = ogGlobals.OG_ERR_NOTEXEC except: - SystemLib.ogRaiseError( - "session", - ogGlobals.OG_ERR_PARTITION, - f"{int(sys.argv[1])} {int(sys.argv[2])}" - ) - ERRCODE = ogGlobals.OG_ERR_PARTITION + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_PARTITION, f'{disk} {par}') + rc = ogGlobals.OG_ERR_PARTITION - ogUnlock(int(sys.argv[1]), int(sys.argv[2])) - return ERRCODE + ogUnlock (disk, par) + return not rc ## reverse to indicate success #/** @@ -608,6 +618,13 @@ def ogMount(*args): elif 2 == len (args): return ogMountFs(args[0], args[1]) + +#/** +# ogMountFirstFs int_ndisk +#@brief Monta el primer sistema de archivos disponible en el disco. +#@param int_ndisk nº de orden del disco +#@return Punto de montaje del primer sistema de archivos detectado +#*/ ## def ogMountFirstFs(int_ndisk): # Obtener número de particiones del disco. NPARTS = DiskLib.ogGetPartitionsNumber(int_ndisk) @@ -737,6 +754,20 @@ def ogMountCdrom(): return return MNTDIR + +#/** +# ogReduceFs int_ndisk int_nfilesys +#@brief Reduce el tamaño del sistema de archivos, sin tener en cuenta el espacio libre. +#@param int_ndisk nº de orden del disco +#@param int_nfilesys nº de orden del sistema de archivos +#@return int_tamañoKB - tamaño en KB +#@exception OG_ERR_FORMAT Formato incorrecto. +#@exception OG_ERR_NOTFOUND Disco o particion no corresponden con un dispositivo. +#@exception OG_ERR_PARTITION Partición desconocida o no accesible. +#@warning En Windows, se borran los ficheros de hiberanción y de paginación. +#@warning El sistema de archivos se amplía al mínimo + 10%. +#@note Requisitos: *resize* +#*/ ## def ogReduceFs(int_ndisk, int_nfilesys): # Error si no se reciben 2 parámetros. @@ -906,6 +937,15 @@ def ogUnmountAll(int_ndisk): if ogGetFsType(int_ndisk, PART) != "CACHE": ogUnmount(int_ndisk, PART) + +#/** +# ogUnsetDirtyBit int_ndisk int_npart +#@brief Inhabilita el Dirty Bit del sistema de ficheros NTFS para evitar un CHKDSK en el primer arranque +#@param int_ndisk nº de orden del disco +#@param int_npart nº de orden de partición +#@return Nada +#@exception OG_ERR_FORMAT Formato incorrecto. +#*/ ## def ogUnsetDirtyBit(int_ndisk, int_nfilesys): # Error si no se reciben 2 parámetros. diff --git a/client/lib/engine/bin/InventoryLib.py b/client/lib/engine/bin/InventoryLib.py index 0a6aa5f..021fbbc 100755 --- a/client/lib/engine/bin/InventoryLib.py +++ b/client/lib/engine/bin/InventoryLib.py @@ -55,7 +55,7 @@ def ogGetOsType(disk, partition): if os_version: return os_version.split(":", 1)[0] else: - return "Unknown" + return None except Exception as e: print(f"Error en ogGetOsType: {e}") return "Unknown" From 39ad37e324379eaa5556bfe6acb65362a2c9535c Mon Sep 17 00:00:00 2001 From: Natalia Serrano Date: Fri, 22 Nov 2024 09:59:48 +0100 Subject: [PATCH 083/167] refs #1166 add ogSetWindowsName() --- client/lib/engine/bin/BootLib.py | 548 +++++++++++++++++++++++++ client/lib/engine/bin/DiskLib.py | 3 +- client/lib/engine/bin/FileSystemLib.py | 3 +- client/lib/engine/bin/InventoryLib.py | 3 +- client/lib/engine/bin/NetLib.py | 3 +- client/lib/engine/bin/RegistryLib.py | 100 +++-- client/shared/scripts/restoreImage.py | 2 +- 7 files changed, 615 insertions(+), 47 deletions(-) create mode 100644 client/lib/engine/bin/BootLib.py diff --git a/client/lib/engine/bin/BootLib.py b/client/lib/engine/bin/BootLib.py new file mode 100644 index 0000000..d04e5a1 --- /dev/null +++ b/client/lib/engine/bin/BootLib.py @@ -0,0 +1,548 @@ +#/** +#@file BootLib.py +#@brief Librería o clase Boot +#@class Boot +#@brief Funciones para arranque y post-configuración de sistemas de archivos. +#@warning License: GNU GPLv3+ +#*/ + +import ogGlobals +import SystemLib +import FileSystemLib +import RegistryLib + +#/** +# ogBoot int_ndisk int_nfilesys [ NVRAMPERM ] [str_kernel str_initrd str_krnlparams] +#@brief Inicia el proceso de arranque de un sistema de archivos. +#@param int_ndisk nº de orden del disco +#@param int_nfilesys nº de orden del sistema de archivos +#@param str_nvramperm UEFI: La entrada en la NVRAM se incluye en el orden de arranque (opcional) +#@param str_krnlparams parámetros de arranque del kernel (opcional) +#@return (activar el sistema de archivos). +#@exception OG_ERR_FORMAT Formato incorrecto. +#@exception OG_ERR_NOTFOUND Disco o particion no corresponden con un dispositivo. +#@exception OG_ERR_PARTITION Tipo de partición desconocido o no se puede montar. +#@exception OG_ERR_NOTOS La partición no tiene instalado un sistema operativo. +#@note En Linux, si no se indican los parámetros de arranque se detectan de la opción por defecto del cargador GRUB. +#@note En Linux, debe arrancarse la partición del directorio \c /boot +#*/ ## + + +#/** +# ogGetWindowsName int_ndisk int_nfilesys +#@brief Muestra el nombre del equipo en el registro de Windows. +#@param int_ndisk nº de orden del disco +#@param int_nfilesys nº de orden del sistema de archivos +#@return str_name - nombre del equipo +#@exception OG_ERR_FORMAT Formato incorrecto. +#@exception OG_ERR_NOTFOUND Disco o particion no corresponden con un dispositivo. +#@exception OG_ERR_PARTITION Tipo de partición desconocido o no se puede montar. +#*/ ## + + +#/** +# ogLinuxBootParameters int_ndisk int_nfilesys +#@brief Muestra los parámetros de arranque de un sistema de archivos Linux. +#@param int_ndisk nº de orden del disco +#@param int_nfilesys nº de orden del sistema de archivos +#@return str_kernel str_initrd str_parameters ... +#@exception OG_ERR_FORMAT Formato incorrecto. +#@exception OG_ERR_NOTFOUND Disco o particion no corresponden con un dispositivo. +#@exception OG_ERR_PARTITION Tipo de partición desconocido o no se puede montar. +#@warning Función básica usada por \c ogBoot +#*/ ## + + +#/** +# ogSetWindowsName int_ndisk int_nfilesys str_name +#@brief Establece el nombre del equipo en el registro de Windows. +#@param int_ndisk nº de orden del disco +#@param int_nfilesys nº de orden del sistema de archivos +#@param str_name nombre asignado +#@return (nada) +#@exception OG_ERR_FORMAT Formato incorrecto. +#@exception OG_ERR_NOTFOUND Disco o particion no corresponden con un dispositivo. +#@exception OG_ERR_PARTITION Tipo de partición desconocido o no se puede montar. +#@exception OG_ERR_OUTOFLIMIT Nombre Netbios con más de 15 caracteres. +#*/ ## +def ogSetWindowsName (disk, par, name): + if len (name) > 15: + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_OUTOFLIMIT, f'"{name[0:15]}..."') + return + + mntdir = FileSystemLib.ogMount (disk, par) + if not mntdir: return None + + RegistryLib.ogSetRegistryValue (mntdir, 'system', r'\ControlSet001\Control\ComputerName\ComputerName\ComputerName', name) + RegistryLib.ogSetRegistryValue (mntdir, 'system', r'\ControlSet001\Services\Tcpip\Parameters\Hostname', name) + RegistryLib.ogSetRegistryValue (mntdir, 'system', r'\ControlSet001\Services\Tcpip\Parameters\HostName', name) + RegistryLib.ogSetRegistryValue (mntdir, 'system', r'\ControlSet001\services\Tcpip\Parameters\Hostname', name) + RegistryLib.ogSetRegistryValue (mntdir, 'system', r'\ControlSet001\Services\Tcpip\Parameters\NV Hostname', name) + RegistryLib.ogSetRegistryValue (mntdir, 'system', r'\ControlSet001\Services\Tcpip\Parameters\NV HostName', name) + RegistryLib.ogSetRegistryValue (mntdir, 'system', r'\ControlSet001\services\Tcpip\Parameters\NV Hostname', name) + + + +#/** +# ogSetWinlogonUser int_ndisk int_npartition str_username +#@brief Establece el nombre de usuario por defecto en la entrada de Windows. +#@param int_ndisk nº de orden del disco +#@param int_npartition nº de orden de la partición +#@param str_username nombre de usuario por defecto +#@return (nada) +#@exception OG_ERR_FORMAT Formato incorrecto. +#@exception OG_ERR_NOTFOUND Disco o particion no corresponden con un dispositivo. +#@exception OG_ERR_PARTITION Tipo de partición desconocido o no se puede montar. +#*/ ## + + +#/** +# ogBootMbrXP int_ndisk +#@brief Genera un nuevo Master Boot Record en el disco duro indicado, compatible con los SO tipo Windows +#@param int_ndisk nº de orden del disco +#@return salida del programa my-sys +#@exception OG_ERR_FORMAT Formato incorrecto. +#@exception OG_ERR_PARTITION Tipo de partición desconocido o no se puede montar. +#*/ ## + + +#/** +# ogBootMbrGeneric int_ndisk +#@brief Genera un nuevo Codigo de arranque en el MBR del disco indicado, compatible con los SO tipo Windows, Linux. +#@param int_ndisk nº de orden del disco +#@return salida del programa my-sys +#@exception OG_ERR_FORMAT Formato incorrecto. +#@exception OG_ERR_NOTFOUND Tipo de partición desconocido o no se puede montar. +#*/ ## + + + + +#/** +# ogFixBootSector int_ndisk int_parition +#@brief Corrige el boot sector de una particion activa para MS windows/dos -fat-ntfs +#@param int_ndisk nº de orden del disco +#@param int_partition nº de particion +#@return +#@exception OG_ERR_FORMAT Formato incorrecto. +#@exception OG_ERR_PARTITION Tipo de partición desconocido o no se puede montar. +#*/ ## + + +#/** +# ogGetBootMbr int_ndisk +#@brief Obtiene el contenido del sector de arranque de un disco. +#@param int_ndisk nº de orden del disco +#@return str_MBR Descripción del contenido del MBR. +#@exception OG_ERR_FORMAT Formato incorrecto. +#@exception OG_ERR_NOTFOUND Dispositivo de disco no encontrado. +#*/ ## + +#/** +# ogWindowsBootParameters int_ndisk int_parition +#@brief Configura el gestor de arranque de windows 7 / vista / XP / 2000 +#@param int_ndisk nº de orden del disco +#@param int_partition nº de particion +#@return +#@exception OG_ERR_FORMAT Formato incorrecto. +#@exception OG_ERR_PARTITION Tipo de partición desconocido o no se puede montar. +#*/ ## + + + +#/** +# ogWindowsRegisterPartition int_ndisk int_partiton str_volume int_disk int_partition +#@brief Registra una partición en windows con un determinado volumen. +#@param int_ndisk nº de orden del disco a registrar +#@param int_partition nº de particion a registrar +#@param str_volumen volumen a resgistar +#@param int_ndisk_windows nº de orden del disco donde esta windows +#@param int_partition_windows nº de particion donde esta windows +#@return +#@exception OG_ERR_FORMAT Formato incorrecto. +#@exception OG_ERR_PARTITION Tipo de partición desconocido o no se puede montar. +#*/ ## + +#/** +# ogGrubInstallMbr int_disk_GRUBCFG int_partition_GRUBCFG +#@brief Instala el grub el el MBR del primer disco duro (FIRSTSTAGE). El fichero de configuración grub.cfg ubicado según parametros disk y part(SECONDSTAGE). Admite sistemas Windows. +#@param int_disk_SecondStage +#@param int_part_SecondStage +#@param bolean_Check_Os_installed_and_Configure_2ndStage true | false[default] +#@return +#@exception OG_ERR_FORMAT Formato incorrecto. +#*/ ## + + +#/** +# ogGrubInstallPartition int_disk_SECONDSTAGE int_partition_SECONDSTAGE bolean_Check_Os_installed_and_Configure_2ndStage +#@brief Instala y actualiza el gestor grub en el bootsector de la particion indicada +#@param int_disk_SecondStage +#@param int_part_SecondStage +#@param bolean_Check_Os_installed_and_Configure_2ndStage true | false[default] +#@param str "kernel param " +#@return +#@exception OG_ERR_FORMAT Formato incorrecto. +#*/ ## + + +#/** +# ogConfigureFstab int_ndisk int_nfilesys +#@brief Configura el fstab según particiones existentes +#@param int_ndisk nº de orden del disco +#@param int_nfilesys nº de orden del sistema de archivos +#@return (nada) +#@exception OG_ERR_FORMAT Formato incorrecto. +#@exception OG_ERR_NOTFOUND No se encuentra el fichero fstab a procesar. +#@warning Puede haber un error si hay más de 1 partición swap. +#*/ ## + +#/** +# ogSetLinuxName int_ndisk int_nfilesys [str_name] +#@brief Establece el nombre del equipo en los ficheros hostname y hosts. +#@param int_ndisk nº de orden del disco +#@param int_nfilesys nº de orden del sistema de archivos +#@param str_name nombre asignado (opcional) +#@return (nada) +#@exception OG_ERR_FORMAT Formato incorrecto. +#@exception OG_ERR_NOTFOUND Disco o particion no corresponden con un dispositivo. +#@exception OG_ERR_PARTITION Tipo de partición desconocido o no se puede montar. +#@note Si no se indica nombre, se asigna un valor por defecto. +#*/ ## + + + +#/** +# ogCleanLinuxDevices int_ndisk int_nfilesys +#@brief Limpia los dispositivos del equipo de referencia. Interfaz de red ... +#@param int_ndisk nº de orden del disco +#@param int_nfilesys nº de orden del sistema de archivos +#@return (nada) +#@exception OG_ERR_FORMAT Formato incorrecto. +#@exception OG_ERR_NOTFOUND Disco o particion no corresponden con un dispositivo. +#@exception OG_ERR_PARTITION Tipo de partición desconocido o no se puede montar. +#*/ ## + +#/** +# ogGrubAddOgLive num_disk num_part [ timeout ] [ offline ] +#@brief Crea entrada de menu grub para ogclient, tomando como paramentros del kernel los actuales del cliente. +#@param 1 Numero de disco +#@param 2 Numero de particion +#@param 3 timeout Segundos de espera para iniciar el sistema operativo por defecto (opcional) +#@param 4 offline configura el modo offline [offline|online] (opcional) +#@return (nada) +#@exception OG_ERR_FORMAT Formato incorrecto. +#@exception OG_ERR_NOTFOUND No existe kernel o initrd en cache. +#@exception OG_ERR_NOTFOUND No existe archivo de configuracion del grub. +# /// FIXME: Solo para el grub instalado en MBR por Opengnsys, ampliar para más casos. +#*/ ## + +#/** +# ogGrubHidePartitions num_disk num_part +#@brief ver ogBootLoaderHidePartitions +#@see ogBootLoaderHidePartitions +#*/ ## + +#/** +# ogBurgHidePartitions num_disk num_part +#@brief ver ogBootLoaderHidePartitions +#@see ogBootLoaderHidePartitions +#*/ ## + +#/** +# ogBootLoaderHidePartitions num_disk num_part +#@brief Configura el grub/burg para que oculte las particiones de windows que no se esten iniciando. +#@param 1 Numero de disco +#@param 2 Numero de particion +#@param 3 Numero de disco de la partición de datos (no ocultar) +#@param 4 Numero de particion de datos (no ocultar) +#@return (nada) +#@exception OG_ERR_FORMAT Formato incorrecto. +#@exception No existe archivo de configuracion del grub/burg. +#*/ + +#/** +# ogGrubDeleteEntry num_disk num_part num_disk_delete num_part_delete +#@brief ver ogBootLoaderDeleteEntry +#@see ogBootLoaderDeleteEntry +#*/ + +#/** +# ogBurgDeleteEntry num_disk num_part num_disk_delete num_part_delete +#@brief ver ogBootLoaderDeleteEntry +#@see ogBootLoaderDeleteEntry +#*/ + +#/** +# ogRefindDeleteEntry num_disk_delete num_part_delete +#@brief ver ogBootLoaderDeleteEntry +#@see ogBootLoaderDeleteEntry +#*/ + +#/** +# ogBootLoaderDeleteEntry num_disk num_part num_part_delete +#@brief Borra en el grub las entradas para el inicio en una particion. +#@param 1 Numero de disco donde esta el grub +#@param 2 Numero de particion donde esta el grub +#@param 3 Numero del disco del que borramos las entradas +#@param 4 Numero de la particion de la que borramos las entradas +#@note Tiene que ser llamada desde ogGrubDeleteEntry, ogBurgDeleteEntry o ogRefindDeleteEntry +#@return (nada) +#@exception OG_ERR_FORMAT Use ogGrubDeleteEntry or ogBurgDeleteEntry. +#@exception OG_ERR_FORMAT Formato incorrecto. +#@exception OG_ERR_NOTFOUND No existe archivo de configuracion del grub. +#*/ ## + +#/** +# ogBurgInstallMbr int_disk_GRUBCFG int_partition_GRUBCFG +#@param bolean_Check_Os_installed_and_Configure_2ndStage true | false[default] +#@brief Instala y actualiza el gestor grub en el MBR del disco duro donde se encuentra el fichero grub.cfg. Admite sistemas Windows. +#@param int_disk_SecondStage +#@param int_part_SecondStage +#@param bolean_Check_Os_installed_and_Configure_2ndStage true | false[default] +#@return +#@exception OG_ERR_FORMAT Formato incorrecto. +#@exception OG_ERR_PARTITION Partición no soportada +#*/ ## + +#/** +# ogGrubDefaultEntry int_disk_GRUGCFG int_partition_GRUBCFG int_disk_default_entry int_npartition_default_entry +#@brief ver ogBootLoaderDefaultEntry +#@see ogBootLoaderDefaultEntry +#*/ ## + +#/** +# ogBurgDefaultEntry int_disk_BURGCFG int_partition_BURGCFG int_disk_default_entry int_npartition_default_entry +#@brief ver ogBootLoaderDefaultEntry +#@see ogBootLoaderDefaultEntry +#*/ ## + + +#/** +# ogRefindDefaultEntry int_disk_default_entry int_npartition_default_entry +#@brief ver ogBootLoaderDefaultEntry +#@see ogBootLoaderDefaultEntry +#*/ ## + +#/** +# ogBootLoaderDefaultEntry int_disk_CFG int_partition_CFG int_disk_default_entry int_npartition_default_entry +#@brief Configura la entrada por defecto de Burg +#@param int_disk_SecondStage +#@param int_part_SecondStage +#@param int_disk_default_entry +#@param int_part_default_entry +#@return +#@exception OG_ERR_FORMAT Formato incorrecto. +#@exception OG_ERR_PARTITION Partición errónea o desconocida (ogMount). +#@exception OG_ERR_OUTOFLIMIT Param $3 no es entero. +#@exception OG_ERR_NOTFOUND Fichero de configuración no encontrado: burg.cfg. +#*/ ## + +#/** +# ogGrubOgliveDefaultEntry num_disk num_part +#@brief ver ogBootLoaderOgliveDefaultEntry +#@see ogBootLoaderOgliveDefaultEntry +#*/ ## + +#/** +# ogBurgOgliveDefaultEntry num_disk num_part +#@brief ver ogBootLoaderOgliveDefaultEntry +#@see ogBootLoaderOgliveDefaultEntry +#*/ ## + + +#/** +# ogRefindOgliveDefaultEntry +#@brief ver ogBootLoaderOgliveDefaultEntry +#@see ogBootLoaderOgliveDefaultEntry +#*/ ## + + +#/** +# ogBootLoaderOgliveDefaultEntry +#@brief Configura la entrada de ogLive como la entrada por defecto de Burg. +#@param int_disk_SecondStage +#@param int_part_SecondStage +#@return +#@exception OG_ERR_FORMAT Formato incorrecto. +#@exception OG_ERR_PARTITION Partición errónea o desconocida (ogMount). +#@exception OG_ERR_NOTFOUND Fichero de configuración no encontrado: burg.cfg. +#@exception OG_ERR_NOTFOUND Entrada de OgLive no encontrada en burg.cfg. +#*/ ## + + +#/** +# ogGrubSecurity int_disk_GRUBCFG int_partition_GRUBCFG [user] [password] +#@brief Configura grub.cfg para que sólo permita editar entrada o acceder a línea de comandos al usuario especificado +#@param int_disk_SecondStage +#@param int_part_SecondStage +#@param user (default root) +#@param password (default "", no puede entrar) +#@return (nada) +#@exception OG_ERR_FORMAT Formato incorrecto. +#@exception OG_ERR_PARTITION Tipo de partición desconocido o no se puede montar (ogMount). +#@exception OG_ERR_NOTFOUND No encuentra archivo de configuración del grub. +#*/ ## + + +#/** +# ogGrubSetTheme num_disk num_part str_theme +#@brief ver ogBootLoaderSetTheme +#@see ogBootLoaderSetTheme +#*/ ## + +#/** +# ogBurgSetTheme num_disk num_part str_theme +#@brief ver ogBootLoaderSetTheme +#@see ogBootLoaderSetTheme +#*/ ## + + +#/** +# ogRefindSetTheme str_theme +#@brief ver ogBootLoaderSetTheme +#@see ogBootLoaderSetTheme +#*/ ## + + +#/** +# ogBootLoaderSetTheme +#@brief asigna un tema al BURG +#@param int_disk_SecondStage +#@param int_part_SecondStage +#@param str_theme_name +#@return +#@exception OG_ERR_FORMAT Formato incorrecto. +#@exception OG_ERR_PARTITION Partición errónea o desconocida (ogMount). +#@exception OG_ERR_NOTFOUND Fichero de configuración no encontrado: grub.cfg burg.cfg refind.conf. +#@exception OG_ERR_NOTFOUND Entrada deltema no encontrada en burg.cfg. +#@exception OG_ERR_NOTFOUND Fichero de configuración del tema no encontrado: theme.conf (sólo refind). +#@note El tema debe situarse en OGLIB/BOOTLOADER/themes +#*/ ## + +#/** +# ogGrubSetAdminKeys num_disk num_part str_theme +#@brief ver ogBootLoaderSetTheme +#@see ogBootLoaderSetTheme +#*/ ## + +#/** +# ogBurgSetAdminKeys num_disk num_part str_bolean +#@brief ver ogBootLoaderSetAdminKeys +#@see ogBootLoaderSetAdminKeys +#*/ ## + + + +#/** +# ogBootLoaderSetAdminKeys +#@brief Activa/Desactica las teclas de administracion +#@param int_disk_SecondStage +#@param int_part_SecondStage +#@param Boolean TRUE/FALSE +#@return +#@exception OG_ERR_FORMAT Formato incorrecto. +#@exception OG_ERR_PARTITION Partición errónea o desconocida (ogMount). +#@exception OG_ERR_NOTFOUND Fichero de configuración no encontrado: grub.cfg burg.cfg. +#@exception OG_ERR_NOTFOUND Entrada deltema no encontrada en burg.cfg. +#*/ ## + + + +#/** +# ogGrubSetTimeOut num_disk num_part int_timeout_seconds +#@brief ver ogBootLoaderSetTimeOut +#@see ogBootLoaderSetTimeOut +#*/ ## + +#/** +# ogBurgSetTimeOut num_disk num_part str_bolean +#@brief ver ogBootLoaderSetTimeOut +#@see ogBootLoaderSetTimeOut +#*/ ## + + +#/** +# ogRefindSetTimeOut int_timeout_second +#@brief ver ogBootLoaderSetTimeOut +#@see ogBootLoaderSetTimeOut +#*/ ## + +#/** +# ogBootLoaderSetTimeOut +#@brief Define el tiempo (segundos) que se muestran las opciones de inicio +#@param int_disk_SecondStage +#@param int_part_SecondStage +#@param int_timeout_seconds +#@return +#@exception OG_ERR_FORMAT Formato incorrecto. +#@exception OG_ERR_PARTITION Partición errónea o desconocida (ogMount). +#@exception OG_ERR_NOTFOUND Fichero de configuración no encontrado: grub.cfg burg.cfg. +#@exception OG_ERR_NOTFOUND Entrada deltema no encontrada en burg.cfg. +#*/ ## + + +#/** +# ogGrubSetResolution num_disk num_part int_resolution +#@brief ver ogBootLoaderSetResolution +#@see ogBootLoaderSetResolution +#*/ ## + +#/** +# ogBurgSetResolution num_disk num_part str_bolean +#@brief ver ogBootLoaderSetResolution +#@see ogBootLoaderSetResolution +#*/ ## + + + +#/** +# ogBootLoaderSetResolution +#@brief Define la resolucion que usuara el thema del gestor de arranque +#@param int_disk_SecondStage +#@param int_part_SecondStage +#@param str_resolution (Opcional) +#@return +#@exception OG_ERR_FORMAT Formato incorrecto. +#@exception OG_ERR_PARTITION Partición errónea o desconocida (ogMount). +#@exception OG_ERR_NOTFOUND Fichero de configuración no encontrado: grub.cfg burg.cfg. +#*/ ## + + + + +#/** +# ogBootLoaderSetResolution +#@brief Define la resolucion que usuara el thema del gestor de arranque +#@param int_resolution1 +#@param int_resolution2 (Opcional) +#@return +#@exception OG_ERR_FORMAT Formato incorrecto. +#@exception OG_ERR_PARTITION Partición errónea o desconocida (ogMount). +#@exception OG_ERR_NOTFOUND Fichero de configuración no encontrado: grub.cfg burg.cfg. +#*/ ## + +# ogRefindInstall bool_autoconfig +#@brief Instala y actualiza el gestor rEFInd en la particion EFI +#@param bolean_Check__auto_config true | false[default] +#@return +#@exception OG_ERR_FORMAT Formato incorrecto. +#@exception OG_ERR_NOTFOUND No se encuentra la partición ESP. +#@exception OG_ERR_NOTFOUND No se encuentra shimx64.efi.signed. +#@exception OG_ERR_NOTFOUND No se encuentra refind-install o refind en OGLIB +#@exception OG_ERR_PARTITION No se puede montar la partición ESP. +#@note Refind debe estar instalado en el ogLive o compartido en OGLIB +#*/ ## + +#/** +# ogGrub4dosInstallMbr int_ndisk +#@brief Genera un nuevo Codigo de arranque en el MBR del disco indicado, compatible con los SO tipo Windows, Linux. +#@param int_ndisk nº de orden del disco +#@param int_ndisk nº de orden del particion +#@return +#@exception OG_ERR_FORMAT Formato incorrecto. +#@exception OG_ERR_NOTFOUND Tipo de partición desconocido o no se puede montar. +#@exception OG_ERR_NOTBIOS Equipo no firmware BIOS legacy +#@exception OG_ERR_NOMSDOS Disco duro no particioniado en modo msdos +#@exception OG_ERR_NOTWRITE Particion no modificable. +#*/ ## diff --git a/client/lib/engine/bin/DiskLib.py b/client/lib/engine/bin/DiskLib.py index 3ad9e46..61f97f3 100755 --- a/client/lib/engine/bin/DiskLib.py +++ b/client/lib/engine/bin/DiskLib.py @@ -1,9 +1,8 @@ #/** -#@file Disk.lib +#@file DiskLib.py #@brief Librería o clase Disk #@class Disk #@brief Funciones para gestión de discos y particiones. -#@version 1.1.1 #@warning License: GNU GPLv3+ #*/ diff --git a/client/lib/engine/bin/FileSystemLib.py b/client/lib/engine/bin/FileSystemLib.py index 8d80135..ef43e6b 100755 --- a/client/lib/engine/bin/FileSystemLib.py +++ b/client/lib/engine/bin/FileSystemLib.py @@ -1,9 +1,8 @@ #/** -#@file FileSystem.lib +#@file FileSystemLib.py #@brief Librería o clase FileSystem #@class FileSystem #@brief Funciones para gestión de sistemas de archivos. -#@version 1.1.0 #@warning License: GNU GPLv3+ #*/ diff --git a/client/lib/engine/bin/InventoryLib.py b/client/lib/engine/bin/InventoryLib.py index 021fbbc..a0ec0fd 100755 --- a/client/lib/engine/bin/InventoryLib.py +++ b/client/lib/engine/bin/InventoryLib.py @@ -1,9 +1,8 @@ #/** -#@file Inventory.lib +#@file InventoryLib.py #@brief Librería o clase Inventory #@class Inventory #@brief Funciones para recogida de datos de inventario de hardware y software de los clientes. -#@version 1.1.0 #@warning License: GNU GPLv3+ #*/ diff --git a/client/lib/engine/bin/NetLib.py b/client/lib/engine/bin/NetLib.py index 4020c2e..7bfe7d1 100755 --- a/client/lib/engine/bin/NetLib.py +++ b/client/lib/engine/bin/NetLib.py @@ -1,9 +1,8 @@ #/** -#@file Net.lib +#@file NetLib.py #@brief Librería o clase Net #@class Net #@brief Funciones básicas de red. -#@version 1.0.6 #@warning License: GNU GPLv3+ #*/ diff --git a/client/lib/engine/bin/RegistryLib.py b/client/lib/engine/bin/RegistryLib.py index c4c7eab..f35f61d 100755 --- a/client/lib/engine/bin/RegistryLib.py +++ b/client/lib/engine/bin/RegistryLib.py @@ -1,9 +1,8 @@ #/** -#@file Registry.lib +#@file RegistryLib.py #@brief Librería o clase Registry #@class Boot #@brief Funciones para gestión del registro de Windows. -#@version 1.1.0 #@warning License: GNU GPLv3+ #*/ @@ -11,6 +10,7 @@ import subprocess import os import re import shutil +import tempfile import ogGlobals import SystemLib @@ -185,17 +185,17 @@ def ogGetHivePath(path_mountpoint, str_hive): #@warning Requisitos: chntpw, awk #@warning El sistema de archivos de Windows debe estar montado previamente. #*/ ## -def ogGetRegistryValue(path_mountpoint, str_hive, str_valuename): - FILE = ogGetHivePath(path_mountpoint, str_hive) +def ogGetRegistryValue(path_mountpoint, hive, k): + FILE = ogGetHivePath(path_mountpoint, hive) if not FILE: return - elems = str_valuename.split ('\\') - dirname = '\\'.join (elems[0:-1]) - basename = elems[-1] + k_elems = k.split ('\\') + k_dirname = '\\'.join (k_elems[0:-1]) + k_basename = k_elems[-1] input = '\n'.join ([ - f'cd {dirname}', - f'cat {basename}', + f'cd {k_dirname}', + f'cat {k_basename}', 'q', ]) chntpw_out = chntpw (file, input) @@ -264,6 +264,24 @@ def ogListRegistryValues(path_mountpoint, str_hive, str_key): ''' subprocess.run(chntpw_cmd, shell=True, timeout=5) +def _format_hex (hex_string): + result = [] + offset = 0 + + hex_values = hex_string.strip().split() + result.append (str (len (hex_values))) + + while hex_values: + chunk = hex_values[:16] + hex_values = hex_values[16:] + + offset_str = f':{offset:05x} ' + hex_line = ' '.join (chunk) + result.append (offset_str + hex_line) + + offset += 16 + + return '\n'.join (result) #/** # ogSetRegistryValue path_mountpoint str_hive str_valuename str_valuedata @@ -279,40 +297,46 @@ def ogListRegistryValues(path_mountpoint, str_hive, str_key): #@warning Requisitos: chntpw #@warning El sistema de archivos de Windows debe estar montado previamente. #*/ ## -def ogSetRegistryValue(path_mountpoint, str_hive, str_valuename, str_data): - # Variables locales. - FILE = ogGetHivePath(path_mountpoint, str_hive) - if not FILE: - return +#ogSetRegistryValue ('/mnt/sda1', 'SOFTWARE', '\Key\SubKey\StringValue', 'Abcde Fghij') +#ogSetRegistryValue ('/mnt/sda1', 'SOFTWARE', '\Key\SubKey\DwordValue', 1) +#ogSetRegistryValue ('/mnt/sda1', 'SOFTWARE', '\Key\SubKey\BinaryValue', '04 08 0C 10') +def ogSetRegistryValue (mntpt, hive, k, v): + hivefile = ogGetHivePath (mntpt, hive) + if not hivefile: return - # Fichero temporal para componer la entrada al comando "chntpw". - tmpfile = "/tmp/chntpw$$" +# ${3%\\*} es dirname +# ${3##*\\} es basename + k_elems = k.split ('\\') + k_dirname = '\\'.join (k_elems[0:-1]) + k_basename = k_elems[-1] + + tmpfile = tempfile.TemporaryFile (prefix='chntpw-', mode='w') try: - # Comprobar tipo de datos del valor del registro. with open(tmpfile, 'w') as f: - f.write(f"ls {str_valuename.rsplit('\\', 1)[0]}\nq\n") - output = subprocess.check_output(['chntpw', FILE], input=open(tmpfile, 'rb'), stderr=subprocess.DEVNULL).decode() - if f"BINARY.*<{str_valuename.rsplit('\\', 1)[-1]}>" in output: - # Procesar tipo binario (incluir nº de bytes y líneas de 16 parejas hexadecimales). - if not re.match(r'^([0-9A-F]{2} )*$', str_data): - SystemLib.ogRaiseError( - "session", - ogGlobals.OG_ERR_FORMAT, - f'"{str_data}"' - ) + f.write (f"ls {k_dirname}\n") + f.write ('q\n') + + output = subprocess.run (['chntpw', hivefile], input=open(tmpfile, 'r'), capture_output=True, text=True).stdout + if re.search (f"BINARY.*<{k_basename}>", output): + ## the entry in the registry is binary. Our input should be a sequence of bytes + + if ' ' != v[-1]: v += ' ' ## the regex below requires a trailing space + if not re.match (r'^([0-9A-F]{2} )*$', v.upper()): + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_FORMAT, f'"{v}"') return - n = len(str_data) + 1 - with open(tmpfile, 'w') as f: - f.write(f"cd {str_valuename.rsplit('\\', 1)[0]}\ned {str_valuename.rsplit('\\', 1)[-1]}\n{int(n/3)}\n") - for i in range(0, n, 48): - f.write(f":{i//3:05x} {str_data[i:i+48]}\n") - f.write("s\nq\ny\n") + + formatted = _format_hex (v.upper()) + formatted += '\ns' else: - # Cambiar el dato del valor de registro para cadenas y bytes. - with open(tmpfile, 'w') as f: - f.write(f"cd {str_valuename.rsplit('\\', 1)[0]}\ned {str_valuename.rsplit('\\', 1)[-1]}\n{str_data}\nq\ny\n") - + formatted = v + + with open(tmpfile, 'w') as f: + f.write (f'cd {k_dirname}\n') + f.write (f'ed {k_basename}\n') + f.write (f'{formatted}\n') + f.write ('q\ny\n') + # Aplicar cambios. - subprocess.run(['chntpw', FILE], input=open(tmpfile, 'rb'), stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) + subprocess.run (['chntpw', hivefile], input=open(tmpfile, 'r')) finally: os.remove(tmpfile) diff --git a/client/shared/scripts/restoreImage.py b/client/shared/scripts/restoreImage.py index 5fce963..39fc017 100644 --- a/client/shared/scripts/restoreImage.py +++ b/client/shared/scripts/restoreImage.py @@ -1,6 +1,6 @@ #!/usr/bin/python3 #/** -#@file restoreImage +#@file restoreImage.py #@brief Script de ejemplo para restaurar una imagen. #@param $1 Repositorio (CACHE, REPO o dirección IP) #@param $2 Nombre canónico de la imagen (sin extensión) From ceb82ef24e027d05a60cab339bc62a17a4294f89 Mon Sep 17 00:00:00 2001 From: Natalia Serrano Date: Mon, 25 Nov 2024 17:24:26 +0100 Subject: [PATCH 084/167] refs #1166 add ogWindowsBootParameters() --- client/lib/engine/bin/BootLib.py | 150 +++++++++++++++++++++++++++++++ client/lib/engine/bin/UEFILib.py | 2 +- 2 files changed, 151 insertions(+), 1 deletion(-) diff --git a/client/lib/engine/bin/BootLib.py b/client/lib/engine/bin/BootLib.py index d04e5a1..dddc291 100644 --- a/client/lib/engine/bin/BootLib.py +++ b/client/lib/engine/bin/BootLib.py @@ -6,10 +6,16 @@ #@warning License: GNU GPLv3+ #*/ +import re +import tempfile +import subprocess + import ogGlobals import SystemLib import FileSystemLib import RegistryLib +import DiskLib +import InventoryLib #/** # ogBoot int_ndisk int_nfilesys [ NVRAMPERM ] [str_kernel str_initrd str_krnlparams] @@ -148,6 +154,150 @@ def ogSetWindowsName (disk, par, name): #@exception OG_ERR_PARTITION Tipo de partición desconocido o no se puede montar. #*/ ## +def ogWindowsBootParameters (disk, par): + if not DiskLib.ogDiskToDev (disk, par): + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_PARTITION, '') + return + + disk0 = int (disk) - 1 + + tmpfile = tempfile.NamedTemporaryFile (prefix='ogWBP-', mode='w').name + if InventoryLib.ogIsEfiActive(): + bootdisk, bootpar = DiskLib.ogGetEsp().split() + if not FileSystemLib.ogUnmount (bootdisk, bootpar): + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_PARTITION, f'ESP: {bootdisk} {bootpar}') + return + bootdisk = str (int (bootdisk) - 1) + bootlabel = f'Part-{int(bootdisk):02d}-{int(bootpar):02d}' + bcdfile = f'boot_BCD_file=/EFI/{bootlabel}/Boot/BCD' + else: + bootdisk = disk0 + bootpar = par + bcdfile = '' + + +# Obtener versión de Windows. + winver = InventoryLib.ogGetOsVersion (disk, par) + parts = re.split (':| ', winver) + if 'Windows' == parts[0] and 'Server' == parts[2]: + winver = parts[1] + parts[2] + parts[3] + else: + winver = parts[1] + parts[2] + if not winver: + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTOS, 'Windows') + return + +# Acciones para Windows XP. + if 'XP' in winver: + m = FileSystemLib.ogMount (disk, par) + if not m or not os.path.exists (f'{m}/boot.ini'): + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTFOUND, 'boot.ini') + return + with open (f'{m}/boot.ini', 'r') as fd: + boot_ini = fd.read() + boot_ini = re.sub (r'partition\([0-9]\)', f'partition({par})', boot_ini) + boot_ini = re.sub (r'rdisk\([0-9]\)', f'rdisk({disk0})', boot_ini) + with open (f'{m}/tmp.boot.ini', 'w') as fd: + fd.write (boot_ini) + os.rename (f'{m}/tmp.boot.ini', f'{m}/boot.ini') + return True + + if not FileSystemLib.ogUnmount (disk, par): + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_PARTITION, '') + return + + +#Preparando instruccion Windows Resume Application + with open (tmpfile, 'w') as fd: + fd.write (f"""boot_disk={bootdisk} +boot_main_part={bootpar} +{bcdfile} +disk={disk0} +main_part={par} +boot_entry=Windows Resume Application +""") + subprocess.run (['timeout', '--foreground', '--signal=SIGKILL', '5s', 'spartlnx.run', '-cui', '-nm', '-w', '-f', tmpfile], stdin=subprocess.DEVNULL) + + +#Preparando instruccion tipo windows + with open (tmpfile, 'w') as fd: + fd.write (f"""boot_disk={bootdisk} +boot_main_part={bootpar} +{bcdfile} +disk={disk0} +main_part={par} +boot_entry={winver} +""") + subprocess.run (['timeout', '--foreground', '--signal=SIGKILL', '5s', 'spartlnx.run', '-cui', '-nm', '-w', '-f', tmpfile], stdin=subprocess.DEVNULL) + +##Preparando instruccion Ramdisk Options + with open (tmpfile, 'w') as fd: + fd.write (f"""boot_disk={bootdisk} +boot_main_part={bootpar} +{bcdfile} +disk={disk0} +main_part={par} +boot_entry=Ramdisk Options +""") + subprocess.run (['timeout', '--foreground', '--signal=SIGKILL', '5s', 'spartlnx.run', '-cui', '-nm', '-w', '-f', tmpfile], stdin=subprocess.DEVNULL) + +##Preparando instruccion Recovery Environment + with open (tmpfile, 'w') as fd: + fd.write (f"""boot_disk={bootdisk} +boot_main_part={bootpar} +{bcdfile} +disk={disk0} +main_part={par} +boot_entry=Windows Recovery Environment +""") + subprocess.run (['timeout', '--foreground', '--signal=SIGKILL', '5s', 'spartlnx.run', '-cui', '-nm', '-w', '-f', tmpfile], stdin=subprocess.DEVNULL) + +##Preparando instruccion Recovery + with open (tmpfile, 'w') as fd: + fd.write (f"""boot_disk={bootdisk} +boot_main_part={bootpar} +{bcdfile} +disk={disk0} +main_part={par} +boot_entry=Windows Recovery +""") + subprocess.run (['timeout', '--foreground', '--signal=SIGKILL', '5s', 'spartlnx.run', '-cui', '-nm', '-w', '-f', tmpfile], stdin=subprocess.DEVNULL) + +#Preparando instruccion Windows Boot Manager + with open (tmpfile, 'w') as fd: + fd.write (f"""boot_disk={bootdisk} +boot_main_part={bootpar} +{bcdfile} +disk={bootdisk} +main_part={bootpar} +boot_entry=Windows Boot Manager +""") + subprocess.run (['timeout', '--foreground', '--signal=SIGKILL', '5s', 'spartlnx.run', '-cui', '-nm', '-w', '-f', tmpfile], stdin=subprocess.DEVNULL) + +#Preparando instruccion Herramienta de diagnóstico de memoria de Windows + with open (tmpfile, 'w') as fd: + fd.write (f"""boot_disk={bootdisk} +boot_main_part={bootpar} +{bcdfile} +disk={bootdisk} +main_part={bootpar} +boot_entry=Herramienta de diagnóstico de memoria de Windows +""") + subprocess.run (['timeout', '--foreground', '--signal=SIGKILL', '5s', 'spartlnx.run', '-cui', '-nm', '-w', '-f', tmpfile], stdin=subprocess.DEVNULL) + +#Preparando instruccion Herramienta de diagnóstico de memoria de Windows + with open (tmpfile, 'w') as fd: + fd.write (f"""boot_disk={bootdisk} +boot_main_part={bootpar} +{bcdfile} +disk={bootdisk} +main_part={bootpar} +boot_entry=Herramienta de diagnstico de memoria de Windows +""") + subprocess.run (['timeout', '--foreground', '--signal=SIGKILL', '5s', 'spartlnx.run', '-cui', '-nm', '-w', '-f', tmpfile], stdin=subprocess.DEVNULL) + + os.remove (tmpfile) + #/** diff --git a/client/lib/engine/bin/UEFILib.py b/client/lib/engine/bin/UEFILib.py index 831a7a1..ecfd411 100644 --- a/client/lib/engine/bin/UEFILib.py +++ b/client/lib/engine/bin/UEFILib.py @@ -159,7 +159,7 @@ def ogRestoreEfiBootLoader (disk, par): osversion = InventoryLib.ogGetOsVersion (disk, par) if 'Windows 1' in osversion: - bootlabel = f'Part-{disk:02d}-{par:02d}' + bootlabel = f'Part-{int(disk):02d}-{int(par):02d}' loader = FileLib.ogGetPath (f'{mntdir}/ogBoot/bootmgfw.efi') if not loader: SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTOS, f'{disk} {par} ({osversion}, EFI)') From 29752be51c3b11fe7cfdd215e65d10c009c5ce56 Mon Sep 17 00:00:00 2001 From: Natalia Serrano Date: Mon, 25 Nov 2024 17:38:41 +0100 Subject: [PATCH 085/167] refs #1166 add ogWindowsRegisterPartition() --- client/lib/engine/bin/BootLib.py | 47 ++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/client/lib/engine/bin/BootLib.py b/client/lib/engine/bin/BootLib.py index dddc291..a8ce397 100644 --- a/client/lib/engine/bin/BootLib.py +++ b/client/lib/engine/bin/BootLib.py @@ -6,6 +6,7 @@ #@warning License: GNU GPLv3+ #*/ +import os import re import tempfile import subprocess @@ -16,6 +17,7 @@ import FileSystemLib import RegistryLib import DiskLib import InventoryLib +import FileLib #/** # ogBoot int_ndisk int_nfilesys [ NVRAMPERM ] [str_kernel str_initrd str_krnlparams] @@ -312,6 +314,51 @@ boot_entry=Herramienta de diagnstico de memoria de Windows #@exception OG_ERR_FORMAT Formato incorrecto. #@exception OG_ERR_PARTITION Tipo de partición desconocido o no se puede montar. #*/ ## +#ogWindowsRegisterPartition ("1", "1", "c:", "1", "1") +def ogWindowsRegisterPartition (registered_disk, registered_par, registered_vol, disk, par): + registered_vol = registered_vol[0].upper() + tmpfile = tempfile.NamedTemporaryFile (prefix='ogWBP-', mode='w').name + + if not DiskLib.ogDiskToDev (registered_disk, registered_par): + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_PARTITION, 'particion a registrar') + return + + if not DiskLib.ogDiskToDev (disk, par): + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_PARTITION, 'particion de windows') + return + + t = InventoryLib.ogGetOsType (disk, par) + if 'Windows' not in t: + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTOS, 'no es windows') + return + + v = InventoryLib.ogGetOsVersion (disk, par) + + if FileLib.ogGetPath (src=f'{disk} {par}', file='WINDOWS'): + systemroot = 'Windows' + elif FileLib.ogGetPath (src=f'{disk} {par}', file='WINNT'): + systemroot = 'winnt' + else: + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTOS, '') + return + + FileSystemLib.ogUnmount (disk, par) + disk0 = str (int (disk) - 1) + registered_disk0 = str (int (registered_disk) - 1) + + with open (tmpfile, 'w') as fd: + fd.write (f"""windows_disk={disk0} +windows_main_part={par} +windows_dir={systemroot} +disk={registered_disk0} +main_part={registered_par} +;ext_part +part_letter={registered_vol} +""") + subprocess.run (['timeout', '--foreground', '--signal=SIGKILL', '5s', 'spartlnx.run', '-cui', '-nm', '-w', '-f', tmpfile], stdin=subprocess.DEVNULL) + + os.remove (tmpfile) + #/** # ogGrubInstallMbr int_disk_GRUBCFG int_partition_GRUBCFG From 57ab927976f32c6953d57a2db8cc76435fd9e397 Mon Sep 17 00:00:00 2001 From: Natalia Serrano Date: Mon, 25 Nov 2024 18:03:13 +0100 Subject: [PATCH 086/167] refs #1166 add ogFixBootSector() --- client/lib/engine/bin/BootLib.py | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/client/lib/engine/bin/BootLib.py b/client/lib/engine/bin/BootLib.py index a8ce397..c9e5e7d 100644 --- a/client/lib/engine/bin/BootLib.py +++ b/client/lib/engine/bin/BootLib.py @@ -135,6 +135,27 @@ def ogSetWindowsName (disk, par, name): #@exception OG_ERR_FORMAT Formato incorrecto. #@exception OG_ERR_PARTITION Tipo de partición desconocido o no se puede montar. #*/ ## +def ogFixBootSector (disk, par): + partype = DiskLib.ogGetPartitionId (disk, par) + if partype not in [ '1', '4', '6', '7', 'b', 'c', 'e', 'f', '17', '700', 'EF00' ]: + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_PARTITION, '') + return + + if not FileSystemLib.ogUnmount (disk, par): + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_PARTITION, '') + return + + disk0 = str (int (disk) - 1) + + tmpfile = tempfile.NamedTemporaryFile (prefix='ogFBS-', mode='w').name + with open (tmpfile, 'w') as fd: + fd.write (f"""disk={disk0} +main_part={par} +fix_first_sector=yes +""") + subprocess.run (['timeout', '--foreground', '--signal=SIGKILL', '5s', 'spartlnx.run', '-cui', '-nm', '-w', '-f', tmpfile], stdin=subprocess.DEVNULL) + + os.remove (tmpfile) #/** @@ -317,7 +338,7 @@ boot_entry=Herramienta de diagnstico de memoria de Windows #ogWindowsRegisterPartition ("1", "1", "c:", "1", "1") def ogWindowsRegisterPartition (registered_disk, registered_par, registered_vol, disk, par): registered_vol = registered_vol[0].upper() - tmpfile = tempfile.NamedTemporaryFile (prefix='ogWBP-', mode='w').name + tmpfile = tempfile.NamedTemporaryFile (prefix='ogWRP-', mode='w').name if not DiskLib.ogDiskToDev (registered_disk, registered_par): SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_PARTITION, 'particion a registrar') From 66e3150b1a62735ffd65864171b2f033b7f71180 Mon Sep 17 00:00:00 2001 From: Natalia Serrano Date: Wed, 4 Dec 2024 10:49:02 +0100 Subject: [PATCH 087/167] refs #1224 add ogConfigureFstab() --- client/lib/engine/bin/BootLib.py | 55 ++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) diff --git a/client/lib/engine/bin/BootLib.py b/client/lib/engine/bin/BootLib.py index c9e5e7d..261f988 100644 --- a/client/lib/engine/bin/BootLib.py +++ b/client/lib/engine/bin/BootLib.py @@ -10,6 +10,7 @@ import os import re import tempfile import subprocess +import shutil import ogGlobals import SystemLib @@ -414,6 +415,60 @@ part_letter={registered_vol} #@exception OG_ERR_NOTFOUND No se encuentra el fichero fstab a procesar. #@warning Puede haber un error si hay más de 1 partición swap. #*/ ## +def ogConfigureFstab (disk, par): + fstab = FileLib.ogGetPath (src=f'{disk} {par}', file='/etc/fstab') + if not fstab: + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTFOUND, f'{disk},{par},/etc/fstab') + return + + shutil.copy2 (fstab, fstab+'.backup') + + with open ('/etc/fstab', 'r') as fd: + while True: + l = fd.readline() + if not l: break + cosas = l.split() + if 6 != len (cosas): continue + fstab_dev, fstab_mntpt, fstab_fstype, fstab_opts, fstab_dump, fstab_pass = cosas + if '#' in fstab_dev: continue + if '/' == fstab_mntpt: + defroot = fstab_dev + elif 'swap' == fstab_fstype: + defswap = fstab_dev + elif '/boot/efi' == fstab_mntpt: + efiopt = '\t'.join ([fstab_fstype, fstab_opts, fstab_dump, fstab_pass]) + + partroot = DiskLib.ogDiskToDev (disk, par) + partswap = subprocess.run (['blkid', '-', ' TYPE=swap'], capture_output=True, text=True).stdout + if partswap: + partswap = partswap.splitlines()[0] + partswap = partswap.split (':')[0] + if defswap: + print ("Hay definicion de SWAP en el FSTAB $DEFSWAP -> modificamos fichero con nuevo valor $DEFSWAP->$PARTSWAP") # Mensaje temporal. + subprocess.run (f'sed "s|{defswap}|{partswap}|g; s|{defroot}|{partroot}|g" {fstab}.backup > {fstab}', shell=True) + else: + print ("No hay definicion de SWAP y si hay partición SWAP -> moficamos fichero") # Mensaje temporal. + subprocess.run (f'sed "s|{defroot}|{partroot}|g" {fstab}.backup > {fstab}', shell=True) + with open ('/etc/fstab', 'a') as fd: + fd.write (f'{partswap} none swap sw 0 0\n') + else: + print ("No hay partición SWAP -> configuramos FSTAB") # Mensaje temporal. + subprocess.run (f'sed "/swap/d" {fstab}.backup > {fstab}', shell=True) +# Si es un sistema EFI incluimos partición ESP (Si existe la modificamos) + if InventoryLib.ogIsEfiActive(): + esp = DiskLib.ogGetEsp() + efidisk, efipart = esp.split() + efidev = DiskLib.ogDiskToDev (efidisk, efipart) + + ## Opciones de la partición ESP: si no existe ponemos un valor por defecto + if not efiopt: + efiopt = '\t'.join (['vfat', 'umask=0077', '0', '1']) + + subprocess.run (f'sed -i /"boot\\/efi"/d {fstab}', shell=True) + with open ('/etc/fstab', 'a') as fd: + fd.write ('{efidev}\t/boot/efi\t{efiopt}\n') + + #/** # ogSetLinuxName int_ndisk int_nfilesys [str_name] From b54877528c299461d00b4539e00050fb3b754940 Mon Sep 17 00:00:00 2001 From: Natalia Serrano Date: Wed, 4 Dec 2024 10:50:59 +0100 Subject: [PATCH 088/167] refs #1217 do not translate grubSyntax to python --- client/shared/scripts/grubSyntax | 486 ++++++++++++++++++++++++++++ client/shared/scripts/grubSyntax.py | 197 ----------- 2 files changed, 486 insertions(+), 197 deletions(-) create mode 100755 client/shared/scripts/grubSyntax delete mode 100755 client/shared/scripts/grubSyntax.py diff --git a/client/shared/scripts/grubSyntax b/client/shared/scripts/grubSyntax new file mode 100755 index 0000000..2ff21fb --- /dev/null +++ b/client/shared/scripts/grubSyntax @@ -0,0 +1,486 @@ +#!/bin/bash +set -e + +#grubSyntax +#version 1.1.0 +#autoconfigurador de items de menu para grub/brg +#basado en scripts del paquete de grub +#Antonio Doblas Viso +#Universidad de Málaga +#@version 1.1.1 - En los parámetros del kernel se sustituye el UUID por el dispositivo. +#@version 1.1.1 - Detecta cargador de Windows en directorio Part-xx-yy dentro de ESP (#802 #888) + +export PYTHONPATH=/opt/opengnsys/lib/engine/bin/ + +DISK= +PART= + + + +if [ $# == 3 ]; then + DISK=$1;PART=$2;KERNELPARAM=$3 +fi + +if [ $# == 2 ]; then + DISK=$1;PART=$2 +fi + +if [ $# == 1 ]; then + KERNELPARAM=$1 +fi + + +#Versión de scripts compatible con la versión 1.99 de grub-probe +#Uso del grub-probe 1.99 según arquitectura +grub_probe=${grub_probe:-$OGBIN/grub-probe1.99_$(arch)} + +#librerias del osProber para kernel antiguos: detecta e identifica sistema operativos. +if grub-install --version | grep 1.99 ; then + cp -r /opt/opengnsys/lib/os-probes/* /usr/lib/os-probes/ +else + # Librería os-probe para cargador de microsoft en dir part-x-y (uefi) + OSPROBE_MS_PART="/opt/opengnsys/lib/os-probes/mounted/efi/31part-x-y" + [ -f $OSPROBE_MS_PART ] && cp $OSPROBE_MS_PART /usr/lib/os-probes/mounted/efi +fi + + +#Autoreconocimiento del ogLive en cache +#fichero de reconocimeinto de grub +#fichero de lsb-release en la cache (al final de este scripts se elimina esta entrada para que el browser no lo muestre + +if [ $(ls /opt/opengnsys/cache/boot/$oglivedir/ogvmlinuz 2>/dev/null) ]; then + sed -i 's|/boot/\${oglivedir}/ogvmlinuz |/vmlinuz |i' /usr/lib/linux-boot-probes/mounted/90fallback + sed -i 's|/vmlinuz |/vmlinuz /boot/\${oglivedir}/ogvmlinuz |1' /usr/lib/linux-boot-probes/mounted/90fallback + mkdir -p /opt/opengnsys/cache/etc/ + echo "DISTRIB_ID=Ubuntu" > /opt/opengnsys/cache/etc/lsb-release + echo "DISTRIB_RELEASE= " >> /opt/opengnsys/cache/etc/lsb-release + echo $oglivedir | awk -F- ' {print "DISTRIB_CODENAME="$2 }' >> /opt/opengnsys/cache/etc/lsb-release + echo "DISTRIB_DESCRIPTION=OpenGnsys Live" >> /opt/opengnsys/cache/etc/lsb-release +fi + +#ver linea 195 detección de los os en variable OSPROBED + +OG_prepare_grub_to_access_device () +{ + device="$1" + loop_file= + case ${device} in + /dev/loop/*|/dev/loop[0-9]) + grub_loop_device="${device#/dev/}" + loop_file=`losetup "${device}" | sed -e "s/^[^(]*(\([^)]\+\)).*/\1/"` + case $loop_file in + /dev/*) ;; + *) + loop_device="${device}" + device=`"${grub_probe}" --target=device "${loop_file}"` || return 0 + ;; + esac + ;; + esac + if dmsetup status $device 2>/dev/null | grep -q 'crypt[[:space:]]$'; then + grub_warn \ + "$device is a crypto device, which GRUB cannot read directly. Some" \ + "necessary modules may be missing from /boot/grub/grub.cfg. You may" \ + "need to list them in GRUB_PRELOAD_MODULES in /etc/default/grub. See" \ + "http://bugs.debian.org/542165 for details." + return 0 + fi + # Abstraction modules aren't auto-loaded. + abstraction="`"${grub_probe}" --device "${device}" --target=abstraction`" + for module in ${abstraction} ; do + echo "insmod ${module}" + done + partmap="`"${grub_probe}" --device "${device}" --target=partmap`" + for module in ${partmap} ; do + case "${module}" in + netbsd | openbsd) + echo "insmod part_bsd";; + *) + echo "insmod part_${module}";; + esac + done + fs="`"${grub_probe}" --device "${device}" --target=fs`" + for module in ${fs} ; do + echo "insmod ${module}" + done + # If there's a filesystem UUID that GRUB is capable of identifying, use it; + # otherwise set root as per value in device.map. + #OG modificacion + # PARCHE UHU ...SI el disco es nvme se cambia su nomenclatura, ya que grub_probe no funciona bien + if [[ $DEVICE == *"nvme"* ]]; then + #DEVICE=`echo $DEVICE | sed -e "s/\/dev\/nvme/hd/g" | sed -e "s/n.*p/,gpt/g"` + #TODO Detectar si es GPT o no... + read -r D P <<< $(python3 -c 'import DiskLib; d = DiskLib.ogDevToDisk ("'$DEVICE'"); print (d)') + PTT = $(python3 -c 'import DiskLib; t = DiskLib.ogGetPartitionTableType ("'$D'"); print (t)') + if [ "$PTT" == "GPT" ]; then + # Si es gpt se sustituye por "hd(X-1),gptY" + #device=`echo $device | sed -e "s/\/dev\/nvme/hd/g" | sed -e "s/n.*p/,gpt/g"` + nvmeDevice=`echo "hd"$(expr $D - 1)",gpt$P"` + + else + # Sino se sustituye por hd(X-1),(Y-1) + nvmeDevice=`echo "hd"$(expr $D - 1)","$(expr $P - 1)` + fi + echo "set root='$nvmeDevice'" + else + echo "set root='`"${grub_probe}" --device "${device}" --target=drive`'" + fi + + #if fs_uuid="`"${grub_probe}" --device "${device}" --target=fs_uuid 2> /dev/null`" ; then + # echo "search --no-floppy --fs-uuid --set=root ${fs_uuid}" + #fi + + if [ "x${loop_file}" != x ]; then + loop_mountpoint="$(awk '"'${loop_file}'" ~ "^"$2 && $2 != "/" { print $2 }' /proc/mounts | tail -n1)" + if [ "x${loop_mountpoint}" != x ]; then + echo "loopback ${grub_loop_device} ${loop_file#$loop_mountpoint}" + echo "set root=(${grub_loop_device})" + fi + fi +} + + + + + +# grub-mkconfig helper script. +# Copyright (C) 2006,2007,2008,2009 Free Software Foundation, Inc. +# +# GRUB is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# GRUB is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GRUB. If not, see . + + +prefix=/usr +exec_prefix=${prefix} +libdir=${exec_prefix}/lib + +. ${libdir}/grub/grub-mkconfig_lib + +found_other_os= + +make_timeout () { + if [ "x${found_other_os}" = "x" ] ; then + if [ "x${1}" != "x" ] ; then + if [ "x${GRUB_HIDDEN_TIMEOUT_QUIET}" = "xtrue" ] ; then + verbose= + else + verbose=" --verbose" + fi + + if [ "x${1}" = "x0" ] ; then + cat < /dev/null`" -o -z "`which linux-boot-prober 2> /dev/null`" ] ; then + # missing os-prober and/or linux-boot-prober + adjust_timeout + exit 0 +fi + +case "$1" in + + +esac + + + +# ADV OSPROBED +if [ -n "${DISK}" ]; then + #Si $DISK esta definido buscar en el disco y la particion parametro 1 y 2 + OSSEARCH=$(python3 -c 'import DiskLib; d = DiskLib.ogDiskToDev ("'$DISK'", "'$PART'"); print (d)') + OSPROBED="`os-prober | grep $OSSEARCH | tr ' ' '^' | paste -s -d ' '`" +else + #si no esta definido + OSPROBED="`os-prober | tr ' ' '^' | paste -s -d ' '`" +fi + +#DISK=${DISK:-"1"} +#echo $OSSEARCH +#echo "$OSPROBED" + + +if [ -z "${OSPROBED}" ] ; then + # empty os-prober output, nothing doing + adjust_timeout + exit 0 +fi + +osx_entry() { + found_other_os=1 + cat << EOF +menuentry "${LONGNAME} (${2}-bit) (on ${DEVICE})" --class osx --class darwin --class os { +EOF +save_default_entry | sed -e "s/^/\t/" +prepare_grub_to_access_device ${DEVICE} | sed -e "s/^/\t/" +cat << EOF + load_video + set do_resume=0 + if [ /var/vm/sleepimage -nt10 / ]; then + if xnu_resume /var/vm/sleepimage; then + set do_resume=1 + fi + fi + if [ \$do_resume = 0 ]; then + xnu_uuid ${OSXUUID} uuid + if [ -f /Extra/DSDT.aml ]; then + acpi -e /Extra/DSDT.aml + fi + $1 /mach_kernel boot-uuid=\${uuid} rd=*uuid + if [ /System/Library/Extensions.mkext -nt /System/Library/Extensions ]; then + xnu_mkext /System/Library/Extensions.mkext + else + xnu_kextdir /System/Library/Extensions + fi + if [ -f /Extra/Extensions.mkext ]; then + xnu_mkext /Extra/Extensions.mkext + fi + if [ -d /Extra/Extensions ]; then + xnu_kextdir /Extra/Extensions + fi + if [ -f /Extra/devprop.bin ]; then + xnu_devprop_load /Extra/devprop.bin + fi + if [ -f /Extra/splash.jpg ]; then + insmod jpeg + xnu_splash /Extra/splash.jpg + fi + if [ -f /Extra/splash.png ]; then + insmod png + xnu_splash /Extra/splash.png + fi + if [ -f /Extra/splash.tga ]; then + insmod tga + xnu_splash /Extra/splash.tga + fi + fi +} +EOF +} + +wubi= + +for OS in ${OSPROBED} ; do + DEVICE="`echo ${OS} | cut -d ':' -f 1`" + LONGNAME="`echo ${OS} | cut -d ':' -f 2 | tr '^' ' '`" + LABEL="`echo ${OS} | cut -d ':' -f 3 | tr '^' ' '`" + BOOT="`echo ${OS} | cut -d ':' -f 4`" + + if [ -z "${LONGNAME}" ] ; then + LONGNAME="${LABEL}" + fi + + echo "Found ${LONGNAME} on ${DEVICE}" >&2 + + case ${BOOT} in + chain) + + case ${LONGNAME} in + Windows*) + if [ -z "$wubi" ]; then + if [ -x /usr/share/lupin-support/grub-mkimage ] && \ + /usr/share/lupin-support/grub-mkimage --test; then + wubi=yes + else + wubi=no + fi + fi + if [ "$wubi" = yes ]; then + echo "Skipping ${LONGNAME} on Wubi system" >&2 + continue + fi + ;; + esac + #adv + LABELCLASS=$(echo "${LONGNAME}" | awk '{print tolower($1$2);}') + + found_other_os=1 + cat << EOF +menuentry "${LONGNAME} (on ${DEVICE})" --class $LABELCLASS --class windows { +EOF +save_default_entry | sed -e "s/^/\t/" +#ADV prepare_grub_to_access_device ${DEVICE} | sed -e "s/^/\t/" +OG_prepare_grub_to_access_device ${DEVICE} | sed -e "s/^/\t/" + +case ${LONGNAME} in + Windows\ Vista*|Windows\ 7*|Windows\ Server\ 2008*) + ;; + *) + #ADV cat << EOF + #ADV drivemap -s (hd0) \${root} + #ADV EOF + ;; +esac + +cat <&2 + ;; + esac +done + +adjust_timeout + +rm /opt/opengnsys/cache/etc/lsb-release &>/dev/null diff --git a/client/shared/scripts/grubSyntax.py b/client/shared/scripts/grubSyntax.py deleted file mode 100755 index f2c9394..0000000 --- a/client/shared/scripts/grubSyntax.py +++ /dev/null @@ -1,197 +0,0 @@ -import os -import subprocess -import sys -import DiskLib - -#!/usr/bin/env python3 - -def run_command(command): - result = subprocess.run(command, shell=True, capture_output=True, text=True) - return result.stdout.strip() - -def copy_files(src, dest): - if os.path.exists(src): - subprocess.run(f"cp -r {src} {dest}", shell=True) - -def prepare_grub_to_access_device(device): - loop_file = None - if device.startswith("/dev/loop"): - grub_loop_device = device.split('/')[-1] - loop_file = run_command(f"losetup {device} | sed -e 's/^[^(]*(\\([^)]\\+\\)).*/\\1/'") - if not loop_file.startswith("/dev"): - loop_device = device - device = run_command(f"{grub_probe} --target=device {loop_file}") - - if "crypt" in run_command(f"dmsetup status {device}"): - print(f"{device} is a crypto device, which GRUB cannot read directly.") - return - - abstraction = run_command(f"{grub_probe} --device {device} --target=abstraction") - for module in abstraction.split(): - print(f"insmod {module}") - - partmap = run_command(f"{grub_probe} --device {device} --target=partmap") - for module in partmap.split(): - if module in ["netbsd", "openbsd"]: - print("insmod part_bsd") - else: - print(f"insmod part_{module}") - - fs = run_command(f"{grub_probe} --device {device} --target=fs") - for module in fs.split(): - print(f"insmod {module}") - - if "nvme" in device: - d, p = DiskLib.ogDevToDisk(device) - if DiskLib.ogGetPartitionTableType(d) == "GPT": - nvme_device = f"hd{d-1},gpt{p}" - else: - nvme_device = f"hd{d-1},{p-1}" - print(f"set root='{nvme_device}'") - else: - print(f"set root='{run_command(f'{grub_probe} --device {device} --target=drive')}'") - - if loop_file: - loop_mountpoint = run_command(f"awk '{loop_file} ~ \"^\"$2 && $2 != \"/\" {{ print $2 }}' /proc/mounts | tail -n1") - if loop_mountpoint: - print(f"loopback {grub_loop_device} {loop_file[len(loop_mountpoint):]}") - print(f"set root=({grub_loop_device})") - -def main(): - disk = part = kernel_param = None - if len(sys.argv) == 4: - disk, part, kernel_param = sys.argv[1:4] - elif len(sys.argv) == 3: - disk, part = sys.argv[1:3] - elif len(sys.argv) == 2: - kernel_param = sys.argv[1] - - grub_probe = os.getenv("grub_probe", f"{os.getenv('OGBIN')}/grub-probe1.99_{os.uname().machine}") - - if "1.99" in run_command("grub-install --version"): - copy_files("/opt/opengnsys/lib/os-probes/*", "/usr/lib/os-probes/") - else: - osprobe_ms_part = "/opt/opengnsys/lib/os-probes/mounted/efi/31part-x-y" - if os.path.isfile(osprobe_ms_part): - copy_files(osprobe_ms_part, "/usr/lib/os-probes/mounted/efi") - - if os.path.exists(f"/opt/opengnsys/cache/boot/{oglivedir}/ogvmlinuz"): - subprocess.run(f"sed -i 's|/boot/{{oglivedir}}/ogvmlinuz |/vmlinuz |i' /usr/lib/linux-boot-probes/mounted/90fallback", shell=True) - subprocess.run(f"sed -i 's|/vmlinuz |/vmlinuz /boot/{{oglivedir}}/ogvmlinuz |1' /usr/lib/linux-boot-probes/mounted/90fallback", shell=True) - os.makedirs("/opt/opengnsys/cache/etc/", exist_ok=True) - with open("/opt/opengnsys/cache/etc/lsb-release", "w") as f: - f.write("DISTRIB_ID=Ubuntu\n") - f.write("DISTRIB_RELEASE= \n") - f.write(f"DISTRIB_CODENAME={oglivedir.split('-')[1]}\n") - f.write("DISTRIB_DESCRIPTION=OpenGnsys Live\n") - - if disk: - os_search = DiskLib.ogDiskToDev(disk, part) - os_probed = run_command(f"os-prober | grep {os_search} | tr ' ' '^' | paste -s -d ' '") - else: - os_probed = run_command("os-prober | tr ' ' '^' | paste -s -d ' '") - - if not os_probed: - adjust_timeout() - sys.exit(0) - - for os_entry in os_probed.split(): - device, longname, label, boot = os_entry.split(':') - longname = longname.replace('^', ' ') - label = label.replace('^', ' ') - if not longname: - longname = label - - print(f"Found {longname} on {device}", file=sys.stderr) - - if boot == "chain": - if "Windows" in longname: - if not wubi: - if os.path.exists("/usr/share/lupin-support/grub-mkimage") and run_command("/usr/share/lupin-support/grub-mkimage --test"): - wubi = "yes" - else: - wubi = "no" - if wubi == "yes": - print(f"Skipping {longname} on Wubi system", file=sys.stderr) - continue - - label_class = ''.join(longname.lower().split()[:2]) - print(f"menuentry \"{longname} (on {device})\" --class {label_class} --class windows {{") - save_default_entry() - prepare_grub_to_access_device(device) - if "Windows Vista" in longname or "Windows 7" in longname or "Windows Server 2008" in longname: - pass - else: - pass - print("chainloader +1") - print("}") - - elif boot == "efi": - efipath = device.split('@')[1] - device = device.split('@')[0] - onstr = f"(on {device})" - print(f"menuentry '{longname} {onstr}' --class windows --class os {{") - save_default_entry() - prepare_grub_to_access_device(device) - print(f"chainloader {efipath}") - print("}") - - elif boot == "linux": - linux_probed = run_command(f"linux-boot-prober {device} 2> /dev/null | tr ' ' '^' | paste -s -d ' '") - linux_probed = linux_probed.split()[0] - prepare_boot_cache = None - for linux_entry in linux_probed.split(): - lroot, lboot, llabel, lkernel, linitrd, lparams = linux_entry.split(':') - llabel = llabel.replace('^', ' ') - lparams = lparams.replace('^', ' ') - uuid = run_command(f"blkid -s UUID -o value {lroot}") - lparams = lparams.replace(f"UUID={uuid}", lroot) - if not llabel: - llabel = longname - if lroot != lboot: - lkernel = lkernel.replace('/boot', '') - linitrd = linitrd.replace('/boot', '') - label_class = llabel.split()[0].lower() - print(f"menuentry \"{llabel} (on {device})\" --class {label_class} --class linux --class os {{") - save_default_entry() - if not prepare_boot_cache: - prepare_boot_cache = prepare_grub_to_access_device(lboot) - print(prepare_boot_cache) - if label_class == "opengnsys": - kernel_param = run_command("cat /proc/cmdline") - print(f"linux {lkernel} {lparams} {kernel_param}") - if linitrd: - print(f"initrd {linitrd}") - print("}") - - elif boot == "macosx": - osx_uuid = run_command(f"grub-probe --target=fs_uuid --device {device} 2> /dev/null") - osx_entry("xnu_kernel", 32, device, longname, osx_uuid) - osx_entry("xnu_kernel64", 64, device, longname, osx_uuid) - - elif boot == "hurd": - print(f"menuentry \"{longname} (on {device})\" --class hurd --class gnu --class os {{") - save_default_entry() - prepare_grub_to_access_device(device) - grub_device = run_command(f"{grub_probe} --device {device} --target=drive") - mach_device = grub_device.replace("(hd", "").replace(",msdos", "s") - grub_fs = run_command(f"{grub_probe} --device {device} --target=fs") - hurd_fs = grub_fs if grub_fs.endswith("fs") else f"{grub_fs}fs" - print(f"multiboot /boot/gnumach.gz root=device:{mach_device}") - print(f"module /hurd/{hurd_fs}.static {hurd_fs} --readonly \\") - print(f" --multiboot-command-line='{{kernel-command-line}}' \\") - print(f" --host-priv-port='{{host-port}}' \\") - print(f" --device-master-port='{{device-port}}' \\") - print(f" --exec-server-task='{{exec-task}}' -T typed '{{root}}' \\") - print(f" '{{task-create}}' '{{task-resume}}'") - print(f"module /lib/ld.so.1 exec /hurd/exec '{{exec-task=task-create}}'") - print("}") - - else: - print(f" {longname} is not yet supported by grub-mkconfig.", file=sys.stderr) - - adjust_timeout() - os.remove("/opt/opengnsys/cache/etc/lsb-release") - -if __name__ == "__main__": - main() From 9c059ce407b56711ca2b9b47807e0e88b653d202 Mon Sep 17 00:00:00 2001 From: Natalia Serrano Date: Wed, 4 Dec 2024 14:20:18 +0100 Subject: [PATCH 089/167] refs #1222 add ogGrubInstallPartition() --- client/lib/engine/bin/BootLib.py | 85 ++++++++++++++++++++++++++- client/lib/engine/bin/InventoryLib.py | 10 +--- 2 files changed, 85 insertions(+), 10 deletions(-) diff --git a/client/lib/engine/bin/BootLib.py b/client/lib/engine/bin/BootLib.py index 261f988..3331aec 100644 --- a/client/lib/engine/bin/BootLib.py +++ b/client/lib/engine/bin/BootLib.py @@ -11,6 +11,7 @@ import re import tempfile import subprocess import shutil +import glob import ogGlobals import SystemLib @@ -404,6 +405,84 @@ part_letter={registered_vol} #@exception OG_ERR_FORMAT Formato incorrecto. #*/ ## +def ogGrubInstallPartition (disk, par, checkos='FALSE', kernelparam=''): + backupname = '.backup.og' + + version = InventoryLib.ogGetOsVersion (disk, par) + if not version or 'Linux' not in version: + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTOS, 'no es linux') + return + + firststage = DiskLib.ogDiskToDev (disk, par) #Localizar primera etapa del grub + secondstage = FileSystemLib.ogMount (disk, par) #localizar disco segunda etapa del grub + prefixsecondstage = '/boot/grubPARTITION' #Localizar directorio segunda etapa del grub + efioptgrub = [] # Si es EFI instalamos el grub en la ESP + #efibootdir = '' # Desde el bootdir uefi y bios buscan el grub.cfg en subdirectorios distintos. + + if InventoryLib.ogIsEfiActive(): + esp = DiskLib.ogGetEsp() + efidisk, efipart = esp.split() + efisecondstage = FileSystemLib.ogMount (efidisk, efipart) + if not efisecondstage: + FileSystemLib.ogFormat (efidisk, efipart, 'FAT32') + efisecondstage = FileSystemLib.ogMount (efidisk, efipart) + if not efisecondstage: + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_PARTITION, 'ESP') + return + efisubdir = f'Part-{int(disk):02d}-{int(par):02d}' + if os.path.isdir (f'{efisecondstage}/EFI/{efisubdir}'): # Borramos la configuración anterior + shutil.rmtree (f'{efisecondstage}/EFI/{efisubdir}') + os.makedirs (f'{efisecondstage}/EFI/{efisubdir}/Boot') + arch = InventoryLib.ogGetArch() + efioptgrub = ['--removable', '--no-nvram', '--uefi-secure-boot', '--target', f'{arch}-efi', f'--efi-directory={efisecondstage}/EFI/{efisubdir}'] + #efibootdir = '/boot' + + # Si Reconfigurar segunda etapa (grub.cfg) == FALSE + if 'FALSE' == checkos.upper() and (os.path.exists (f'{secondstage}/boot/grub/grub.cfg') or os.path.exists (f'{secondstage}/boot/grub/grub.cfg{backupname}')): + if os.path.exists (f'{secondstage}/boot/grub/grub.cfg{backupname}'): + os.rename (f'{secondstage}/boot/grub/grub.cfg{backupname}', f'{secondstage}/boot/grub/grub.cfg') + if os.path.isdir (f'{secondstage}{prefixsecondstage}'): + shutil.rmtree (f'{secondstage}{prefixsecondstage}') + prefixsecondstage = '' # Reactivamos el grub con el grub.cfg original. + else: # SI Reconfigurar segunda etapa (grub.cfg) == TRUE + if InventoryLib.ogIsEfiActive(): + # UEFI: grubSintax necesita grub.cfg para detectar los kernels: si no existe recupero backup. + if not os.path.exists (f'{secondstage}/boot/grub/grub.cfg'): + if os.path.exists (f'{secondstage}/boot/grub/grub.cfg{backupname}'): + os.rename (f'{secondstage}/boot/grub/grub.cfg{backupname}', f'{secondstage}/boot/grub/grub.cfg') + else: + os.rename (f'{secondstage}/boot/grub/grub.cfg', f'{secondstage}/boot/grub/grub.cfg{backupname}') + + with open ('/etc/default/grub', 'a') as fd: #Configur la sintaxis grub para evitar menus de "recovery" en el OGLive + fd.write ('GRUB_DISABLE_RECOVERY="true"\n') + fd.write ('GRUB_DISABLE_LINUX_UUID="true"\n') + + os.makedirs (f'{secondstage}{prefixsecondstage}/boot/grub/') #Preparar configuración segunda etapa: crear ubicacion + subprocess.run (['sed', '-i', 's/^set -e/#set -e/', '/etc/grub.d/00_header']) #Preparar configuración segunda etapa: crear cabecera del fichero (ingnorar errores) + # (ogLive 5.0) Si 'pkgdatadir' está vacía ponemos valor de otros ogLive + subprocess.run (['sed', '-i', '/grub-mkconfig_lib/i\pkgdatadir=${pkgdatadir:-"${datarootdir}/grub"}', '/etc/grub.d/00_header']) + out = subprocess.run (['/etc/grub.d/00_header'], capture_output=True, text=True).stdout + with open (f'{secondstage}{prefixsecondstage}/boot/grub/grub.cfg', 'w') as fd: + fd.write (out + '\n') + + #Preparar configuración segunda etapa: crear entrada del sistema operativo + out = subprocess.run (['grubSyntax', disk, par, kernelparam], capture_output=True, text=True).stdout + with open (f'{secondstage}{prefixsecondstage}/boot/grub/grub.cfg', 'a') as fd: + fd.write (out + '\n') + + eval = subprocess.run (['grub-install', '--force'] + efioptgrub + [f'--root-directory={secondstage}{prefixsecondstage}', firststage]).returncode + + if InventoryLib.ogIsEfiActive(): # Movemos el grubx64.efi + for b in (glob.glob (f'{efisecondstage}/EFI/{efisubdir}/EFI/BOOT/*')): + os.rename (f'{efisecondstage}/EFI/{efisubdir}/EFI/BOOT/{b}', f'{efisecondstage}/EFI/{efisubdir}/Boot/{b}') + shutil.rmtree (f'{efisecondstage}/EFI/{efisubdir}/EFI') + shutil.copy2 ('/usr/lib/shim/shimx64.efi.signed', f'{efisecondstage}/EFI/{efisubdir}/Boot/shimx64.efi') + # Nombre OpenGnsys para cargador + shutil.copy2 (f'{efisecondstage}/EFI/{efisubdir}/Boot/grubx64.efi', f'{efisecondstage}/EFI/{efisubdir}/Boot/ogloader.efi') + + return eval + + #/** # ogConfigureFstab int_ndisk int_nfilesys @@ -444,15 +523,15 @@ def ogConfigureFstab (disk, par): partswap = partswap.splitlines()[0] partswap = partswap.split (':')[0] if defswap: - print ("Hay definicion de SWAP en el FSTAB $DEFSWAP -> modificamos fichero con nuevo valor $DEFSWAP->$PARTSWAP") # Mensaje temporal. + print ("Hay definicion de SWAP en el FSTAB $DEFSWAP -> modificamos fichero con nuevo valor $DEFSWAP->$PARTSWAP") # Mensaje temporal. subprocess.run (f'sed "s|{defswap}|{partswap}|g; s|{defroot}|{partroot}|g" {fstab}.backup > {fstab}', shell=True) else: - print ("No hay definicion de SWAP y si hay partición SWAP -> moficamos fichero") # Mensaje temporal. + print ("No hay definicion de SWAP y si hay partición SWAP -> moficamos fichero") # Mensaje temporal. subprocess.run (f'sed "s|{defroot}|{partroot}|g" {fstab}.backup > {fstab}', shell=True) with open ('/etc/fstab', 'a') as fd: fd.write (f'{partswap} none swap sw 0 0\n') else: - print ("No hay partición SWAP -> configuramos FSTAB") # Mensaje temporal. + print ("No hay partición SWAP -> configuramos FSTAB") # Mensaje temporal. subprocess.run (f'sed "/swap/d" {fstab}.backup > {fstab}', shell=True) # Si es un sistema EFI incluimos partición ESP (Si existe la modificamos) if InventoryLib.ogIsEfiActive(): diff --git a/client/lib/engine/bin/InventoryLib.py b/client/lib/engine/bin/InventoryLib.py index a0ec0fd..0788032 100755 --- a/client/lib/engine/bin/InventoryLib.py +++ b/client/lib/engine/bin/InventoryLib.py @@ -30,14 +30,10 @@ import FileLib #@return str_arch - Arquitectura (i386 para 32 bits, x86_64 para 64 bits). #*/ def ogGetArch(): - if len(sys.argv) > 1 and sys.argv[1] == "help": - SystemLib.ogHelp(sys.argv[0], sys.argv[0], sys.argv[0] + " => x86_64") - return - - if platform.machine().endswith("64"): - print("x86_64") + if os.path.isdir ('/lib64'): + return 'x86_64' else: - print("i386") + return 'i386' #/** From bcc1e7bbe1d3ba2f5ecd38158876b7a701eec4b2 Mon Sep 17 00:00:00 2001 From: Natalia Serrano Date: Wed, 4 Dec 2024 14:40:21 +0100 Subject: [PATCH 090/167] refs #1223 add ogUninstallLinuxClient() --- client/lib/engine/bin/PostConfLib.py | 175 +++++++++++++++++++++++++++ 1 file changed, 175 insertions(+) create mode 100644 client/lib/engine/bin/PostConfLib.py diff --git a/client/lib/engine/bin/PostConfLib.py b/client/lib/engine/bin/PostConfLib.py new file mode 100644 index 0000000..d840f2a --- /dev/null +++ b/client/lib/engine/bin/PostConfLib.py @@ -0,0 +1,175 @@ +#/** +#@file PostConfLib.py +#@brief Librería o clase PostConf +#@class PostConf +#@brief Funciones para la postconfiguración de sistemas operativos. +#@warning License: GNU GPLv3+ +#*/ + +import os +import subprocess + +import FileSystemLib + +#/** +# ogCleanOs int_ndisk int_nfilesys +#@brief Elimina los archivos que no son necesarios en el sistema operativo. +#@param int_ndisk nº de orden del disco +#@param int_nfilesys nº de orden del sistema de archivos +#@exception OG_ERR_FORMAT Formato incorrecto. +#@exception OG_ERR_NOTFOUND Disco o particion no corresponden con un dispositivo. +#@exception OG_ERR_PARTITION Partición desconocida o no accesible. +#@note Antes incluido en la funcion ogReduceFs +#@return (nada) +#*/ ## + + + +#/** +# ogInstallMiniSetup int_ndisk int_npartition str_filename [str_admuser str_admpassword bool_autologin [str_autouser str_autopassword] ] +#@brief Metafunción para instalar archivo que se ejecutará en el arranque de Windows. +#@see ogInstallFirstBoot ogInstallRunonce +#*/ ## + + +#/** +# ogInstallFirstBoot int_ndisk int_npartition str_filename +#@brief Crea unas claves del registro y el archivo cmd que se ejecutara en el primer arranque estando la maquina en un estado bloqueado +#@param int_ndisk nº de orden del disco +#@param int_npartition nº de orden de la partición +#@param str_filename nombre del archivo .cmd a ejecutar en el arranque +#@return (nada) +#@exception OG_ERR_FORMAT Formato incorrecto. +#@note El archivo estará en system32 y será visible por el sistema. +#*/ ## + + +#/** +# ogInstallRunonce int_ndisk int_npartition str_filename str_adm_user str_adm_password bool_autologin [str_auto_user str_auto_password] +#@brief Crea el archivo cmd que se ejecutara en el runonce de un usuario administrador +#@param int_ndisk nº de orden del disco +#@param int_npartition nº de orden de la partición +#@param str_filename nombre del archivo .cmd a ejecutar en el arranque (estara en system32 y sera visible por el sistema) +#@param str_adm_user usuario administrador para hacer autologin y ejecutar el runonce +#@param str_adm_password password del usuario administrador +#@param bool_autologin si despues de la postconfiguracion queremos que la maquina haga autologin (0 o 1) +#@param str_auto_user Usuario con el que queremos que haga autologin despues de la postconfiguracion +#@param str_auto_password Password del usuario que hara autologin +#@return (nada) +#@exception OG_ERR_FORMAT Formato incorrecto. +#*/ ## + +#/** +# ogAddCmd int_ndisk int_npartition str_filename str_commands +#@brief Añade comandos al cmd creado por ogInstalMiniSetup +#@param int_ndisk nº de orden del disco +#@param int_npartition nº de orden de la partición +#@param str_filename nombre del fichero cmd (siempre se guardara en windows\system32\para que sea visible por el sistema +#@param str_commands comando o comandos que se añadiran al fichero +#@return +#@exception OG_ERR_FORMAT Formato incorrecto. +#@exception OG_ERR_PARTITION Tipo de partición desconocido o no se puede montar. +#*/ ## + + +#/** +# ogDomainScript int_ndisk int_npartition str_domain str_user str_password +#@brief Crea un script .vbs para unir al dominio una maquina windows y el comando adequado en el archivo cmd creado por ogInstallMiniSetup +#@param int_ndisk nº de orden del disco +#@param int_npartition nº de orden de la partición +#@param str_filename nombre del fichero cmd donde deberemos introducir el comando de ejecutar el script vbs +#@param str_domain dominio donde se quiere conectar +#@param str_user usuario con privilegios para unir al dominio +#@param str_password password del usuario con privilegios +#@return +#@exception OG_ERR_FORMAT Formato incorrecto. +#*/ ## + + +### PRUEBAS. + +#/** +# ogConfigureOgagent int_ndisk int_filesys +#@brief Modifica el fichero de configuración del nuevo agente OGAent para sistemas operativos. +#@param int_ndisk nº de orden del disco +#@param int_filesys nº de orden del sistema de archivos +#@return (nada) +#@exception OG_ERR_FORMAT Formato incorrecto. +#@exception OG_ERR_NOTFOUND Fichero o dispositivo no encontrado. +#@exception OG_ERR_LOCKED Sistema de archivos bloqueado. +#*/ ## + + +#/** +# ogInstallLaunchDaemon int_ndisk int_nfilesys str_filename +#@brief Instala archivo que se ejecutará en el arranque de macOS. +#@param int_ndisk nº de orden del disco +#@param int_nfilesys nº de orden del sistema de archivos +#@param str_filename nombre del script +#return (nada) +#@exception OG_ERR_FORMAT Formato incorrecto. +#@exception OG_ERR_NOTFOUND Fichero o directorio no encontrado. +#@npte Crea ficheros de configuración /Library/LaunchDaemon/es.opengnsys.Script.plist. +#*/ ## + + +### PRUEBAS. + +#/** +# ogAddToLaunchDaemon int_ndisk int_nfilesys str_filename str_commands +#@brief Añade comandos al script creado por ogInstalLaunchDaemon. +#@param int_ndisk nº de orden del disco +#@param int_nfilesys nº de orden del sistema de archivos +#@param str_filename nombre del script (siempre se guardará en /usr/share para que sea visible por el sistema +#@param str_commands comando o comandos que se añadiran al fichero +#return (nada) +#@exception OG_ERR_FORMAT Formato incorrecto. +#@exception OG_ERR_NOTFOUND Fichero o directorio no encontrado. +#*/ ## + + +#/** +# ogUninstallLinuxClient int_ndisk int_filesys +#@brief Desinstala el cliente OpenGnSys para sistemas operativos GNU/Linux. +#@param int_ndisk nº de orden del disco +#@param int_filesys nº de orden del sistema de archivos +#@return (nada) +#@exception OG_ERR_FORMAT Formato incorrecto. +#@exception OG_ERR_PARTITION Paritición o sistema de archivos incorrectos. +#@exception OG_ERR_LOCKED Sistema de archivos bloqueado. +#*/ ## +def ogUninstallLinuxClient (disk, par): + mntdir = FileSystemLib.ogMount (disk, par) + if not mntdir: + return + + for f in [ + f'{mntdir}/usr/sbin/ogAdmLnxClient', + f'{mntdir}/sbin/ogAdmLnxClient', + f'{mntdir}/usr/local/sbin/ogAdmLnxClient', + f'{mntdir}/etc/ogAdmLnxClient.cfg', + f'{mntdir}/usr/local/etc/ogAdmLnxClient.cfg', + ]: + try: os.remove (f) + except: pass + + for f in [ + f'{mntdir}/etc/rc.local', + f'{mntdir}/etc/rc.d/rc.local', + f'{mntdir}/usr/local/etc/rc.local', + f'{mntdir}/usr/local/etc/rc.d/rc.local', + ]: + subprocess.run (['sed', '-i', '-e', '/ogAdmLnxClient/ d', f], stderr=subprocess.DEVNULL) + + +#/** +# ogUninstallWindowsClient int_ndisk int_filesys str_filename +#@brief Desinstala el cliente OpenGnSys para sistemas operativos Windows. +#@param int_ndisk nº de orden del disco +#@param int_npartition nº de orden de la partición +#@param str_filename nombre del fichero cmd donde deberemos introducir el comando de ejecutar el script vbs +#@return (nada) +#@exception OG_ERR_FORMAT Formato incorrecto. +#@exception OG_ERR_PARTITION Paritición o sistema de archivos incorrectos. +#@exception OG_ERR_LOCKED Sistema de archivos bloqueado. +#*/ ## From 1332b0b8bcdb86e2c510681b5f2366e9784ee155 Mon Sep 17 00:00:00 2001 From: Natalia Serrano Date: Wed, 4 Dec 2024 16:13:38 +0100 Subject: [PATCH 091/167] refs #1219 add ogConfigureOgagent() --- client/lib/engine/bin/NetLib.py | 42 ++++++++-------------------- client/lib/engine/bin/PostConfLib.py | 36 ++++++++++++++++++++++++ 2 files changed, 47 insertions(+), 31 deletions(-) diff --git a/client/lib/engine/bin/NetLib.py b/client/lib/engine/bin/NetLib.py index 7bfe7d1..e36f863 100755 --- a/client/lib/engine/bin/NetLib.py +++ b/client/lib/engine/bin/NetLib.py @@ -272,39 +272,19 @@ def ogGetRepoIp(): #@note Comprobacion segun protocolo de conexion al Repo #*/ ## def ogGetServerIp(): - try: - output = subprocess.run( - ["findmnt", "--json", "--output", "SOURCE,FSTYPE", ogGlobals.OGIMG], - capture_output=True, - text=True, - check=True - ).stdout - except subprocess.CalledProcessError as e: - SystemLib.ogEcho("session", "error", f"Error to run findmnt: {e.stderr}") - return None + return os.environ['ogcore'] - try: - mounts = json.loads(output) - except json.decoder.JSONDecodeError: - SystemLib.ogEcho("session", "error", "Error to decode JSON de findmnt.") - return None +#/** +# ogGetServerPort +#@brief Muestra el puerto del Servidor de OpenGnSys. +#@return str_port - Puerto +#*/ ## +def ogGetServerPort(): + if 'ogcore_port' in os.environ: + return os.environ['ogcore_port'] + else: + return '8443' - if 'filesystems' not in mounts or not isinstance(mounts['filesystems'], list): - SystemLib.ogEcho("session", "error", "'filesystems' is not present o not valid in JSON.") - return None - - for fs in mounts['filesystems']: - if 'source' in fs and 'fstype' in fs: - source = fs['source'] - fstype = fs['fstype'] - - if fstype == "nfs": - return source.split(":")[0] - elif fstype == "cifs": - return source.split("/")[2] - - SystemLib.ogEcho("session", "info", "No valid file system found") - return None #/** # ogMakeGroupDir [ str_repo ] diff --git a/client/lib/engine/bin/PostConfLib.py b/client/lib/engine/bin/PostConfLib.py index d840f2a..3033d11 100644 --- a/client/lib/engine/bin/PostConfLib.py +++ b/client/lib/engine/bin/PostConfLib.py @@ -9,7 +9,11 @@ import os import subprocess +import ogGlobals +import SystemLib import FileSystemLib +import FileLib +import NetLib #/** # ogCleanOs int_ndisk int_nfilesys @@ -98,6 +102,38 @@ import FileSystemLib #@exception OG_ERR_NOTFOUND Fichero o dispositivo no encontrado. #@exception OG_ERR_LOCKED Sistema de archivos bloqueado. #*/ ## +def ogConfigureOgagent (disk, par): + mntdir = FileSystemLib.ogMount (disk, par) + if not mntdir: + return + + for agentdir in ['usr/share/OGAgent', 'Program Files/OGAgent', 'Program Files (x86)/OGAgent', 'Applications/OGAgent.app']: + cfgfile = FileLib.ogGetPath (file=f'{mntdir}/{agentdir}/cfg/ogagent.cfg') + if cfgfile: break + + if not cfgfile: + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTFOUND, 'ogagent.cfg') + return + + ogcore_scheme = 'https' + ogcore_ip = NetLib.ogGetServerIp() + ogcore_port = NetLib.ogGetServerPort() + cfgfile_patched = cfgfile + '.patched' + in_opengnsys_section = False + with open (cfgfile, 'r') as fdin: + with open (cfgfile_patched, 'w') as fdout: + while True: + lineout = linein = fdin.readline() + if not linein: break + if in_opengnsys_section: + if 'remote' == linein[0:6]: + lineout = f'remote={ogcore_scheme}://{ogcore_ip}:{ogcore_port}/opengnsys/rest/\n' + if '[' == linein[0:1]: + in_opengnsys_section = False + if '[opengnsys]' == linein[0:11]: + in_opengnsys_section = True + fdout.write (lineout) + os.rename (cfgfile_patched, cfgfile) #/** From 7dccc621cbd9de6fe6d6e302107b3d2242bcbddc Mon Sep 17 00:00:00 2001 From: Natalia Serrano Date: Thu, 5 Dec 2024 14:55:28 +0100 Subject: [PATCH 092/167] refs #1226 finish and refactor RegistryLib --- client/lib/engine/bin/RegistryLib.py | 229 +++++++++++++++------------ 1 file changed, 125 insertions(+), 104 deletions(-) diff --git a/client/lib/engine/bin/RegistryLib.py b/client/lib/engine/bin/RegistryLib.py index f35f61d..c924bbd 100755 --- a/client/lib/engine/bin/RegistryLib.py +++ b/client/lib/engine/bin/RegistryLib.py @@ -17,11 +17,18 @@ import SystemLib import FileLib # Función ficticia para lanzar chntpw con timeout de 5 s., evitando cuelgues del programa. -def chntpw (file, input): - exe = shutil.which ('drbl-chntpw') or shutil.which ('chntpw') - - return subprocess.run ([exe, '-e', file], timeout=5, input=input, capture_output=True, text=True).stdout +chntpw_exe = shutil.which ('drbl-chntpw') or shutil.which ('chntpw') +def chntpw (hivefile, input_file): + return subprocess.run ([chntpw_exe, '-e', hivefile], timeout=5, input=open(input_file, 'r'), capture_output=True, text=True).stdout +## en el codigo bash aparecen "${3%\\*}" y "${3##*\\}" varias veces +## ${3%\\*} es el "dirname" de una key del registro +## ${3##*\\} es el "basename" +def _split_k (k): + k_elems = k.split ('\\') + k_dirname = '\\'.join (k_elems[0:-1]) + k_basename = k_elems[-1] + return k_dirname, k_basename #/** # ogAddRegistryKey path_mountpoint str_hive str_keyname @@ -36,18 +43,19 @@ def chntpw (file, input): #@warning Requisitos: chntpw #@warning El sistema de archivos de Windows debe estar montada previamente. #*/ ## -def ogAddRegistryKey(path_mountpoint, str_hive, str_key): - # Variables locales. - FILE = ogGetHivePath(path_mountpoint, str_hive) - if not FILE: - return +def ogAddRegistryKey (mntpt, hive, k): + hivefile = ogGetHivePath (mntpt, hive) + if not hivefile: return - # Añadir nueva clave. - chntpw(FILE, 'cd', str_key.rsplit('\\', 1)[0]) - chntpw(FILE, 'nk', str_key.rsplit('\\', 1)[-1]) - chntpw(FILE, 'q') - chntpw(FILE, 'y') + k_dirname, k_basename = _split_k (k) + tmpfile = tempfile.TemporaryFile (prefix='chntpw-', mode='w') + with open (tmpfile, 'w') as f: + f.write (f'cd {k_dirname}\n') + f.write (f'nk {k_basename}\n') + f.write ('q\ny\n') + chntpw (hivefile, tmpfile) + os.remove (tmpfile) #/** # ogAddRegistryValue path_mountpoint str_hive str_valuename [str_valuetype] @@ -64,32 +72,29 @@ def ogAddRegistryKey(path_mountpoint, str_hive, str_key): #@warning Requisitos: chntpw #@warning El sistema de archivos de Windows debe estar montada previamente. #*/ ## -def ogAddRegistryValue(path_mountpoint, str_hive, str_key, str_valuename, str_valuetype=''): - # Variables locales. - FILE = ogGetHivePath(path_mountpoint, str_hive) - if not FILE: - return +#ogAddRegistryValue ('/mnt/sda1', 'SOFTWARE', '\Microsoft\NewKey\Value1') +#ogAddRegistryValue ('/mnt/sda1', 'SOFTWARE', '\Microsoft\NewKey\Value1', 'DWORD') +def ogAddRegistryValue (mntpt, hive, k, vtype='STRING'): + hivefile = ogGetHivePath (mntpt, hive) + if not hivefile: return + + k_dirname, k_basename = _split_k (k) # Determine the value type. - if str_valuetype.upper() == 'STRING' or str_valuetype == '': - TYPE = 1 - elif str_valuetype.upper() == 'BINARY': - TYPE = 3 - elif str_valuetype.upper() == 'DWORD': - TYPE = 4 + if 'STRING' == vtype.upper(): TYPE = 1 + elif 'BINARY' == vtype.upper(): TYPE = 3 + elif 'DWORD' == vtype.upper(): TYPE = 4 else: - SystemLib.ogRaiseError( - "session", - ogGlobals.OG_ERR_OUTOFLIMIT, - f"Error: {str_valuetype}", - ) + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_OUTOFLIMIT, vtype) return - # Add the registry value. - chntpw(FILE, 'cd', str_key.rsplit('\\', 1)[0]) - chntpw(FILE, 'nv', str_valuename.rsplit('\\', 1)[-1], TYPE) - chntpw(FILE, 'q') - chntpw(FILE, 'y') + tmpfile = tempfile.TemporaryFile (prefix='chntpw-', mode='w') + with open (tmpfile, 'w') as f: + f.write (f'cd {k_dirname}\n') + f.write (f'nv {TYPE} {k_basename}\n') + f.write ('q\ny\n') + chntpw (hivefile, tmpfile) + os.remove (tmpfile) #/** @@ -106,14 +111,19 @@ def ogAddRegistryValue(path_mountpoint, str_hive, str_key, str_valuename, str_va #@warning El sistema de archivos de Windows debe estar montada previamente. #@warning La clave debe estar vacía para poder ser borrada. #*/ ## -def ogDeleteRegistryKey(path_mountpoint, str_hive, str_key): - # Variables locales. - FILE = ogGetHivePath(path_mountpoint, str_hive) - if not FILE: - return +def ogDeleteRegistryKey (mntpt, hive, k): + hivefile = ogGetHivePath (mntpt, hive) + if not hivefile: return - # Delete the registry key. - subprocess.run(['chntpw', FILE], input=f"cd {str_key.rsplit('\\', 1)[0]}\ndk {str_key.rsplit('\\', 1)[-1]}\nq\ny\n".encode(), timeout=5) + k_dirname, k_basename = _split_k (k) + + tmpfile = tempfile.TemporaryFile (prefix='chntpw-', mode='w') + with open (tmpfile, 'w') as f: + f.write (f'cd {k_dirname}\n') + f.write (f'dk {k_basename}\n') + f.write ('q\ny\n') + chntpw (hivefile, tmpfile) + os.remove (tmpfile) #/** @@ -129,17 +139,20 @@ def ogDeleteRegistryKey(path_mountpoint, str_hive, str_key): #@warning Requisitos: chntpw #@warning El sistema de archivos de Windows debe estar montada previamente. #*/ ## -def ogDeleteRegistryValue(path_mountpoint, str_hive, str_valuename): - # Variables locales. - FILE = ogGetHivePath(path_mountpoint, str_hive) - if not FILE: - return +#ogDeleteRegistryValue ('/mnt/sda1', 'SOFTWARE', '\Microsoft\NewKey\Value1') +def ogDeleteRegistryValue (mntpt, hive, k): + hivefile = ogGetHivePath (mntpt, hive) + if not hivefile: return - # Delete the registry value. - chntpw(FILE, 'cd', str_valuename.rsplit('\\', 1)[0]) - chntpw(FILE, 'dv', str_valuename.rsplit('\\', 1)[-1]) - chntpw(FILE, 'q') - chntpw(FILE, 'y') + k_dirname, k_basename = _split_k (k) + + tmpfile = tempfile.TemporaryFile (prefix='chntpw-', mode='w') + with open(tmpfile, 'w') as f: + f.write (f'cd {k_dirname}\n') + f.write (f'dv {k_basename}\n') + f.write ('q\ny\n') + chntpw (hivefile, tmpfile) + os.remove(tmpfile) #/** @@ -153,21 +166,20 @@ def ogDeleteRegistryValue(path_mountpoint, str_hive, str_valuename): #@note hive = { DEFAULT, SAM, SECURITY, SOFTWARE, SYSTEM, COMPONENTS, NombreDeUsuario } #@warning El sistema de archivos de Windows debe estar montada previamente. #*/ ## -#ogGetHivePath ('/mnt/sda1', 'SOFTWARE') => /mnt/sda1/WINDOWS/System32/config/SOFTWARE #ogGetHivePath ('/mnt/sda1', 'user1') => /mnt/sda1/Users/user1/NTUSER.DAT -def ogGetHivePath(path_mountpoint, str_hive): +def ogGetHivePath(mntpt, hive): # Camino del fichero de registro de usuario o de sistema (de menor a mayor prioridad). - FILE = FileLib.ogGetPath(file=f"/{path_mountpoint}/Windows/System32/config/{str_hive}") - if not FILE: FILE = FileLib.ogGetPath(file=f"/{path_mountpoint}/Users/{str_hive}/NTUSER.DAT") - if not FILE: FILE = FileLib.ogGetPath(file=f"/{path_mountpoint}/winnt/system32/config/{str_hive}") - if not FILE: FILE = FileLib.ogGetPath(file=f"/{path_mountpoint}/Documents and Settings/{str_hive}/NTUSER.DAT") + FILE = FileLib.ogGetPath(file=f"/{mntpt}/Windows/System32/config/{hive}") + if not FILE: FILE = FileLib.ogGetPath(file=f"/{mntpt}/Users/{hive}/NTUSER.DAT") + if not FILE: FILE = FileLib.ogGetPath(file=f"/{mntpt}/winnt/system32/config/{hive}") + if not FILE: FILE = FileLib.ogGetPath(file=f"/{mntpt}/Documents and Settings/{hive}/NTUSER.DAT") if FILE and os.path.isfile(FILE): return FILE else: SystemLib.ogRaiseError( [], ogGlobals.OG_ERR_NOTFOUND, - f"{path_mountpoint} {str_hive}" + f"{mntpt} {hive}" ) return None @@ -185,20 +197,20 @@ def ogGetHivePath(path_mountpoint, str_hive): #@warning Requisitos: chntpw, awk #@warning El sistema de archivos de Windows debe estar montado previamente. #*/ ## -def ogGetRegistryValue(path_mountpoint, hive, k): - FILE = ogGetHivePath(path_mountpoint, hive) +def ogGetRegistryValue (mntpt, hive, k): + FILE = ogGetHivePath(mntpt, hive) if not FILE: return - k_elems = k.split ('\\') - k_dirname = '\\'.join (k_elems[0:-1]) - k_basename = k_elems[-1] + k_dirname, k_basename = _split_k (k) - input = '\n'.join ([ - f'cd {k_dirname}', - f'cat {k_basename}', - 'q', - ]) - chntpw_out = chntpw (file, input) + tmpfile = tempfile.TemporaryFile (prefix='chntpw-', mode='w') + with open(tmpfile, 'w') as f: + f.write (f'cd {k_dirname}\n') + f.write (f'cat {k_basename}\n') + f.write ('q\n') + + chntpw_out = chntpw (hivefile, tmpfile) + os.remove (tmpfile) lines = chntpw_out.splitlines() if 2 != len (lines): return None @@ -220,20 +232,26 @@ def ogGetRegistryValue(path_mountpoint, hive, k): #@warning Requisitos: chntpw, awk #@warning El sistema de archivos de Windows debe estar montado previamente. #*/ ## -def ogListRegistryKeys(path_mountpoint, str_hive, str_key): - # Variables locales. - FILE = ogGetHivePath(path_mountpoint, str_hive) - if not FILE: - return +#ogListRegistryKeys ('/mnt/sda1', 'SOFTWARE', '\Microsoft\Windows\CurrentVersion') +def ogListRegistryKeys (mntpt, hive, k): + FILE = ogGetHivePath(mntpt, hive) + if not FILE: return - # Devolver la lista de claves de registro. - chntpw_cmd = f''' - chntpw "{FILE}" << EOT 2> /dev/null | awk 'BEGIN {{FS="[<>]"}} $1~/^ $/ {{print $2}}' - ls {str_key} - q - EOT - ''' - subprocess.run(chntpw_cmd, shell=True, timeout=5) + tmpfile = tempfile.TemporaryFile (prefix='chntpw-', mode='w') + with open(tmpfile, 'w') as f: + f.write (f'ls {k}\n') + f.write ('q\n') + chntpw_out = chntpw (hivefile, tmpfile) + os.remove (tmpfile) + lines = chntpw_out.splitlines() + + ret = [] + for l in lines: + elems = re.split ('[<>]', l) + if len(elems) < 2: continue + if ' ' == elems[0]: + ret.append (elems[1]) + return ret #/** @@ -249,20 +267,27 @@ def ogListRegistryKeys(path_mountpoint, str_hive, str_key): #@warning Requisitos: chntpw, awk #@warning El sistema de archivos de Windows debe estar montado previamente. #*/ ## -def ogListRegistryValues(path_mountpoint, str_hive, str_key): - # Variables locales. - FILE = ogGetHivePath(path_mountpoint, str_hive) - if not FILE: - return +#ogListRegistryValues ('/mnt/sda1', 'SOFTWARE', '\Microsoft\Windows\CurrentVersion') +def ogListRegistryValues (mntpt, hive, k): + FILE = ogGetHivePath(mntpt, hive) + if not FILE: return + + tmpfile = tempfile.TemporaryFile (prefix='chntpw-', mode='w') + with open(tmpfile, 'w') as f: + f.write (f'ls {k}\n') + f.write ('q\n') + chntpw_out = chntpw (hivefile, tmpfile) + os.remove (tmpfile) + lines = chntpw_out.splitlines() + + ret = [] + for l in lines: + elems = re.split ('[<>]', l) + if len(elems) < 2: continue + if 'REG_' in elems[0]: + ret.append (elems[1]) + return ret - # Devolver la lista de valores de registro. - chntpw_cmd = f''' - chntpw "{FILE}" << EOT 2> /dev/null | awk 'BEGIN {{FS="[<>]"}} $1~/REG_/ {{print $2}}' - ls {str_key} - q - EOT - ''' - subprocess.run(chntpw_cmd, shell=True, timeout=5) def _format_hex (hex_string): result = [] @@ -304,11 +329,7 @@ def ogSetRegistryValue (mntpt, hive, k, v): hivefile = ogGetHivePath (mntpt, hive) if not hivefile: return -# ${3%\\*} es dirname -# ${3##*\\} es basename - k_elems = k.split ('\\') - k_dirname = '\\'.join (k_elems[0:-1]) - k_basename = k_elems[-1] + k_dirname, k_basename = _split_k (k) tmpfile = tempfile.TemporaryFile (prefix='chntpw-', mode='w') try: @@ -316,8 +337,8 @@ def ogSetRegistryValue (mntpt, hive, k, v): f.write (f"ls {k_dirname}\n") f.write ('q\n') - output = subprocess.run (['chntpw', hivefile], input=open(tmpfile, 'r'), capture_output=True, text=True).stdout - if re.search (f"BINARY.*<{k_basename}>", output): + chntpw_out = chntpw (hivefile, tmpfile) + if re.search (f"BINARY.*<{k_basename}>", chntpw_out): ## the entry in the registry is binary. Our input should be a sequence of bytes if ' ' != v[-1]: v += ' ' ## the regex below requires a trailing space @@ -337,6 +358,6 @@ def ogSetRegistryValue (mntpt, hive, k, v): f.write ('q\ny\n') # Aplicar cambios. - subprocess.run (['chntpw', hivefile], input=open(tmpfile, 'r')) + chntpw (hivefile, tmpfile) finally: os.remove(tmpfile) From 9f94951f3f9fb5a9f8d3020f346355bad2168991 Mon Sep 17 00:00:00 2001 From: Natalia Serrano Date: Thu, 5 Dec 2024 15:02:47 +0100 Subject: [PATCH 093/167] refs #1221 add ogUninstallWindowsClient() --- client/lib/engine/bin/PostConfLib.py | 93 ++++++++++++++++++++++++++++ 1 file changed, 93 insertions(+) diff --git a/client/lib/engine/bin/PostConfLib.py b/client/lib/engine/bin/PostConfLib.py index 3033d11..a6e7f58 100644 --- a/client/lib/engine/bin/PostConfLib.py +++ b/client/lib/engine/bin/PostConfLib.py @@ -14,6 +14,7 @@ import SystemLib import FileSystemLib import FileLib import NetLib +import RegistryLib #/** # ogCleanOs int_ndisk int_nfilesys @@ -34,6 +35,11 @@ import NetLib #@brief Metafunción para instalar archivo que se ejecutará en el arranque de Windows. #@see ogInstallFirstBoot ogInstallRunonce #*/ ## +def ogInstallMiniSetup (disk, par, cmdfile, user=None, pwd=None, autologin=False, userauto=None, pwdauto=None): + if user: + ogInstallRunonce (disk, par, cmdfile, user, pwd, autologin, userauto, pwdauto) + else: + ogInstallFirstBoot (disk, par, cmdfile) #/** @@ -46,6 +52,30 @@ import NetLib #@exception OG_ERR_FORMAT Formato incorrecto. #@note El archivo estará en system32 y será visible por el sistema. #*/ ## +#ogInstallFirstBoot ('1', '1', 'filename.cmd') +def ogInstallFirstBoot (disk, par, cmdfile): + mntdir = FileSystemLib.ogMount (disk, par) + if not mntdir: return + for i in ['winnt', 'windows']: + dir = FileLib.ogGetPath (file=f'{mntdir}/{i}/system32') + if dir: cmddir = dir + if not cmddir: + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTFOUND, f'{mntdir}/windows/system32') + return + full_cmdfile = f'{cmddir}/{cmdfile}' + + # Creamos el archivo cmd y creamos un par de comandos para que una vez acabe la + # postconfiguracion resetee el mini setup, sino lo haria en cada arranque. + with open (full_cmdfile, 'w') as fd: + fd.write ('REG ADD HKLM\System\Setup /v SystemSetupInProgress /t REG_DWORD /d 0 /f\n') + fd.write ('REG ADD HKLM\System\Setup /v CmdLine /t REG_SZ /d "" /f\n') + + # Crear los valores de registro necesarios para que se haga la ejecución del .cmd al aranque. + RegistryLib.ogSetRegistryValue (mntdir, 'SYSTEM', r'\Setup\SystemSetupInProgress', 1) + RegistryLib.ogSetRegistryValue (mntdir, 'SYSTEM', r'\Setup\SetupType', 4) + #RegistryLib.ogDeleteRegistryValue (mntdir, 'SYSTEM', r'\Setup\CmdLine') + RegistryLib.ogAddRegistryValue (mntdir, 'SYSTEM', r'\Setup\CmdLine') + RegistryLib.ogSetRegistryValue (mntdir, 'SYSTEM', r'\Setup\CmdLine', f'cmd.exe /c $(basename {full_cmdfile})') #/** @@ -62,6 +92,44 @@ import NetLib #@return (nada) #@exception OG_ERR_FORMAT Formato incorrecto. #*/ ## +#ogInstallRunonce ('1', '1', 'filename.cmd', 'administrator', 'passadmin', '1', 'userauto', 'pwdauto') +#ogInstallRunonce ('1', '1', 'filename.cmd', 'administrator', 'passadmin', '0') +def ogInstallRunonce (disk, par, cmdfile, user, pwd, autologin, userauto=None, pwdauto=None): + mountpoint = FileLib.ogGetPath (src=f'{disk} {par}', file='/') + for i in ['winnt', 'windows']: + dir = FileLib.ogGetPath (file=f'{mountpoint}/{i}/system32') + if dir: cmddir = dir + if not cmddir: + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTFOUND, f'{mountpoint}/Windows/System32') + return + full_cmdfile = f'{cmddir}/{cmdfile}' + if not autologin: + # Si no queremos hacer autologin despues de la postconfiguracion lo indicamos en las claves de registro + with open (full_cmdfile, 'w') as fd: + fd.write (r'DEL C:\ogboot.*\n') + fd.write (r'REG ADD "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon" /v AutoAdminLogon /t REG_SZ /d 0 /f\n') + fd.write (r'REG ADD "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon" /v DefaultUserName /t REG_SZ /d "" /f\n') + fd.write (r'REG DELETE "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon" /v DefaultPassword /f\n') + else: + # Si queremos hacer autologin despues de la postconfiguracion introducimos la informacion en las claves de registro + with open (full_cmdfile, 'w') as fd: + fd.write (r'DEL C:\ogboot.*' + '\n') + fd.write (r'REG ADD "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon" /v AutoAdminLogon /t REG_SZ /d 1 /f' + '\n') + fd.write (fr'REG ADD "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon" /v DefaultUserName /t REG_SZ /d "{userauto}" /f' + '\n') + fd.write (fr'REG ADD "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon" /v DefaultPassword /t REG_SZ /d "{pwdauto}" /f' + '\n') + #Creamos las claves de registro necesarias para que meter el cmd en el runonce del usuario y este haga autologin + RegistryLib.ogAddRegistryValue (mountpoint, 'software', r'\Microsoft\Windows\CurrentVersion\RunOnce\PostConfiguracion') + RegistryLib.ogSetRegistryValue (mountpoint, 'software', r'\Microsoft\Windows\CurrentVersion\RunOnce\PostConfiguracion', rf'C:\windows\system32\{full_cmdfile}') + RegistryLib.ogAddRegistryValue (mountpoint, 'software', r'\Microsoft\Windows NT\CurrentVersion\Winlogon\AutoAdminLogon') + RegistryLib.ogSetRegistryValue (mountpoint, 'software', r'\Microsoft\Windows NT\CurrentVersion\Winlogon\AutoAdminLogon', 1) + RegistryLib.ogAddRegistryValue (mountpoint, 'software', r'\Microsoft\Windows NT\CurrentVersion\Winlogon\DefaultUserName') + RegistryLib.ogSetRegistryValue (mountpoint, 'software', r'\Microsoft\Windows NT\CurrentVersion\Winlogon\DefaultUserName', user) + RegistryLib.ogAddRegistryValue (mountpoint, 'software', r'\Microsoft\Windows NT\CurrentVersion\Winlogon\DefaultDomainName') + RegistryLib.ogSetRegistryValue (mountpoint, 'software', r'\Microsoft\Windows NT\CurrentVersion\Winlogon\DefaultDomainName', '.\\') + RegistryLib.ogAddRegistryValue (mountpoint, 'software', r'\Microsoft\Windows NT\CurrentVersion\Winlogon\DefaultPassword') + RegistryLib.ogSetRegistryValue (mountpoint, 'software', r'\Microsoft\Windows NT\CurrentVersion\Winlogon\DefaultPassword', pwd) + RegistryLib.ogDeleteRegistryValue (mountpoint, 'software', r'\Microsoft\Windows NT\CurrentVersion\Winlogon\ForceAutoLockOnLogon') + RegistryLib.ogDeleteRegistryValue (mountpoint, 'software', r'\Microsoft\Windows NT\CurrentVersion\Winlogon\AutoLogonCount') #/** # ogAddCmd int_ndisk int_npartition str_filename str_commands @@ -74,6 +142,20 @@ import NetLib #@exception OG_ERR_FORMAT Formato incorrecto. #@exception OG_ERR_PARTITION Tipo de partición desconocido o no se puede montar. #*/ ## +#ogAddCmd ('1', '1', 'filename.cmd', 'command') +def ogAddCmd (disk, par, cmdfile, cmd): + mountpoint = FileSystemLib.ogMount (disk, par) + if not mountpoint: return + + full_cmdfile = FileLib.ogGetPath (file=f'{mountpoint}/windows/system32') + '/' + cmdfile + if not full_cmdfile: + ogInstallMiniSetup (disk, par, cmdfile) + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTFOUND, f'{mountpoint}/windows/system32/{cmdfile}') + return + + # Concatenamos el comando en el fichero de comandos + with open (full_cmdfile, 'a') as fd: + fd.write (cmd + '\n') #/** @@ -209,3 +291,14 @@ def ogUninstallLinuxClient (disk, par): #@exception OG_ERR_PARTITION Paritición o sistema de archivos incorrectos. #@exception OG_ERR_LOCKED Sistema de archivos bloqueado. #*/ ## +#ogUninstallWindowsClient ('1', '1', 'filename.cmd') +def ogUninstallWindowsClient (disk, par, cmdfile): + mntdir = FileSystemLib.ogMount (disk, par) + if not mntdir: return + + exe1 = FileLib.ogGetPath (file=f'{mntdir}/windows/ogAdmWinClient.exe') + exe2 = FileLib.ogGetPath (file=f'{mntdir}/winnt/ogAdmWinClient.exe') + if exe1 or exe2: + ogAddCmd (disk, par, cmdfile, 'ogAdmWinClient -remove') + ogAddCmd (disk, par, cmdfile, r'DEL C:\Windows\ogAdmWinClient.exe') + ogAddCmd (disk, par, cmdfile, r'DEL C:\Winnt\ogAdmWinClient.exe') From 3e64d7377c1dcaf9e2372639a51e70a88870091b Mon Sep 17 00:00:00 2001 From: Natalia Serrano Date: Wed, 11 Dec 2024 10:43:41 +0100 Subject: [PATCH 094/167] refs #1218 add all ogNvram...() functions --- client/lib/engine/bin/UEFILib.py | 313 +++++++++++++++++++++++++++++++ 1 file changed, 313 insertions(+) diff --git a/client/lib/engine/bin/UEFILib.py b/client/lib/engine/bin/UEFILib.py index ecfd411..1a979f6 100644 --- a/client/lib/engine/bin/UEFILib.py +++ b/client/lib/engine/bin/UEFILib.py @@ -21,6 +21,39 @@ import InventoryLib #@exception OG_ERR_NOTUEFI UEFI no activa. #@exception OG_ERR_NOTFOUND fichero o dispositivo no encontrado. #*/ ## +#ogNvramActiveEntry ('2') +#ogNvramActiveEntry ('Windows Boot Manager') +def ogNvramActiveEntry (entry): + if not InventoryLib.ogIsEfiActive(): + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTUEFI, '') + return + + numentries = [] + efibootmgr_out = subprocess.run (['efibootmgr'], capture_output=True, text=True).stdout + try: + foo = int (entry, 16) ## raises ValueError if entry doesn't look like hexadecimal + num = f'{foo:04x}'.upper() + for l in efibootmgr_out.splitlines(): + words = l.split() + if len(words) < 2: continue + if num in words[0]: + numentries.append (words[0][4:8]) + except ValueError: + for l in efibootmgr_out.splitlines(): + words = l.split (maxsplit=1) + if len(words) < 2: continue + if words[1] == entry: + numentries.append (words[0][4:8]) + + if not numentries: + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTFOUND, f'NVRAM entry "{entry}"') + return + + if 1 != len(numentries): + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_GENERIC, f'more than one entry found') + return + + subprocess.run (['efibootmgr', '-a', '-b', numentries[0]], capture_output=True, text=True) #/** # ogNvramAddEntry @@ -33,6 +66,43 @@ import InventoryLib #@exception OG_ERR_NOTUEFI UEFI no activa. #@exception OG_ERR_NOTFOUND fichero o dispositivo no encontrado. #*/ ## +#ogNvramAddEntry ('1', '2', True) +#ogNvramAddEntry ('grub', '/EFI/grub/grubx64.efi', True) +#ogNvramAddEntry ('Windows', '/EFI/Microsoft/Boot/bootmgfw.efi') +def ogNvramAddEntry (bootlbl, bootldr, nvram_set=False): + if not InventoryLib.ogIsEfiActive(): + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTUEFI, '') + return + + esp = DiskLib.ogGetEsp() + if not esp: + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTFOUND, 'ESP') + return + efidisk, efipar = esp.split() + + try: + foo = int(bootlbl) + int(bootldr) ## raises ValueError if bootlbl/bootldr don't look like numbers + bootlabel = f'Part-{int(bootlbl):02d}-{int(bootldr):02d}' + bootloader = f'/EFI/{bootlabel}/Boot/ogloader.efi' + except ValueError: + bootlabel = bootlbl + bootloader = bootldr + + ogNvramDeleteEntry (bootlabel) + + dev = DiskLib.ogDiskToDev (efidisk) + subprocess.run (['efibootmgr', '-C', '-d', dev, '-p', efipar, '-L', bootlabel, '-l', bootloader]) + + if nvram_set: + efibootmgr_out = subprocess.run (['efibootmgr'], capture_output=True, text=True).stdout + for l in efibootmgr_out.splitlines(): + words = l.split (maxsplit=1) + if len(words) < 2: continue + if words[1] == bootlabel: + numentry = words[0][4:8] + order = ogNvramGetOrder() + ogNvramSetOrder (order + [numentry]) + #/** @@ -56,6 +126,40 @@ import InventoryLib #@exception OG_ERR_NOTUEFI UEFI no activa. #@exception OG_ERR_NOTFOUND fichero o dispositivo no encontrado (entrada en NVRAM). #*/ ## +#ogNvramDeleteEntry ('2') +#ogNvramDeleteEntry ('Windows Boot Manager') +def ogNvramDeleteEntry (entry): + if not InventoryLib.ogIsEfiActive(): + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTUEFI, '') + return + + numentries = [] + efibootmgr_out = subprocess.run (['efibootmgr'], capture_output=True, text=True).stdout + try: + foo = int (entry, 16) ## raises ValueError if entry doesn't look like hexadecimal + num = f'{foo:04x}'.upper() + for l in efibootmgr_out.splitlines(): + words = l.split() + if len(words) < 2: continue + if num in words[0]: + numentries.append (words[0][4:8]) + except ValueError: + for l in efibootmgr_out.splitlines(): + words = l.split (maxsplit=1) + if len(words) < 2: continue + if words[1] == entry: + numentries.append (words[0][4:8]) + + if not numentries: + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTFOUND, f'NVRAM entry "{entry}"') + return + + if 1 != len(numentries): + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_GENERIC, f'more than one entry found') + return + + subprocess.run (['efibootmgr', '-B', '-b', numentries[0]], capture_output=True, text=True) + #/** @@ -64,6 +168,24 @@ import InventoryLib #@return Entrada con la que se ha iniciado el equipo #@exception OG_ERR_NOTUEFI UEFI no activa. #*/ ## +def ogNvramGetCurrent(): + if not InventoryLib.ogIsEfiActive(): + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTUEFI, '') + return + + bootentry = '9999' + ret = None + efibootmgr_out = subprocess.run (['efibootmgr'], capture_output=True, text=True).stdout + for l in efibootmgr_out.splitlines(): + words = l.split (maxsplit=1) + if len(words) < 2: continue + if 'BootCurrent' in words[0]: + bootentry = words[1] + continue + if bootentry in words[0]: + num = words[0][4:8].strip ('0') or '0' + ret = f'{num} {words[1]}' + return ret # ogNvramGetNext @@ -71,6 +193,19 @@ import InventoryLib #@return Entrada que se utilizará en el próximo arranque #@exception OG_ERR_NOTUEFI UEFI no activa. #*/ ## +def ogNvramGetNext(): + if not InventoryLib.ogIsEfiActive(): + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTUEFI, '') + return + + ret = None + efibootmgr_out = subprocess.run (['efibootmgr'], capture_output=True, text=True).stdout + for l in efibootmgr_out.splitlines(): + words = l.split (maxsplit=1) + if len(words) < 2: continue + if 'BootNext' in words[0]: + ret = words[1] + return ret # ogNvramGetOrder @@ -78,6 +213,19 @@ import InventoryLib #@return Orden de las entradas #@exception OG_ERR_NOTUEFI UEFI no activa. #*/ ## +def ogNvramGetOrder(): + if not InventoryLib.ogIsEfiActive(): + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTUEFI, '') + return + + ret = [] + efibootmgr_out = subprocess.run (['efibootmgr'], capture_output=True, text=True).stdout + for l in efibootmgr_out.splitlines(): + words = l.split() + if len(words) < 2: continue + if 'BootOrder:' == words[0]: + ret = words[1].split (',') + return ret #/** @@ -86,6 +234,19 @@ import InventoryLib #@return Timeout de la NVRAM #@exception OG_ERR_NOTUEFI UEFI no activa. #*/ ## +def ogNvramGetTimeout(): + if not InventoryLib.ogIsEfiActive(): + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTUEFI, '') + return + + ret = None + efibootmgr_out = subprocess.run (['efibootmgr'], capture_output=True, text=True).stdout + for l in efibootmgr_out.splitlines(): + words = l.split (maxsplit=1) + if len(words) < 2: continue + if 'Timeout:' == words[0]: + ret = words[1] + return ret #/** @@ -110,6 +271,39 @@ import InventoryLib #@exception OG_ERR_NOTFOUND fichero o dispositivo no encontrado. #@exception OG_ERR_NOTUEFI UEFI no activa. #*/ ## +#ogNvramInactiveEntry ('2') +#ogNvramInactiveEntry ('Windows Boot Manager') +def ogNvramInactiveEntry (entry): + if not InventoryLib.ogIsEfiActive(): + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTUEFI, '') + return + + numentries = [] + efibootmgr_out = subprocess.run (['efibootmgr'], capture_output=True, text=True).stdout + try: + foo = int (entry, 16) ## raises ValueError if entry doesn't look like hexadecimal + num = f'{foo:04x}'.upper() + for l in efibootmgr_out.splitlines(): + words = l.split() + if len(words) < 2: continue + if num in words[0]: + numentries.append (words[0][4:8]) + except ValueError: + for l in efibootmgr_out.splitlines(): + words = l.split (maxsplit=1) + if len(words) < 2: continue + if words[1] == entry: + numentries.append (words[0][4:8]) + + if not numentries: + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTFOUND, f'NVRAM entry "{entry}"') + return + + if 1 != len(numentries): + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_GENERIC, f'more than one entry found') + return + + subprocess.run (['efibootmgr', '-A', '-b', numentries[0]], capture_output=True, text=True) #/** @@ -118,6 +312,21 @@ import InventoryLib #@return Entradas de la NVRAM con el formato: orden etiqueta [* (si está activa) ] #@exception OG_ERR_NOTUEFI UEFI no activa. #*/ ## +def ogNvramList (): + if not InventoryLib.ogIsEfiActive(): + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTUEFI, '') + return + + ret = '' + efibootmgr_out = subprocess.run (['efibootmgr'], capture_output=True, text=True).stdout + for l in efibootmgr_out.splitlines(): + words = l.split (maxsplit=1) + if len(words) < 2: continue + if re.search ('Boot[0-9]', words[0]): + active = '*' if '*' in words[0] else '' + num = words[0][4:8].strip ('0') or '0' + ret += '{:>4s} {} {}'.format (num, words[1], active) + return ret #/** @@ -126,6 +335,32 @@ import InventoryLib #@return (nada) #@exception OG_ERR_NOTUEFI UEFI no activa. #*/ ## +def ogNvramPxeFirstEntry(): + if not InventoryLib.ogIsEfiActive(): + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTUEFI, '') + return + + num = '' + efibootmgr_out = subprocess.run (['efibootmgr'], capture_output=True, text=True).stdout + for l in efibootmgr_out.splitlines(): + if re.search ('IP[vV]{0,1}4', l): + num = l[4:8].strip ('0') or '0' + numentry = f'{int(num):04x}'.upper() + + o = ogNvramGetOrder() + if not o: + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_GENERIC, f'ogNvramGetOrder returned an empty list') + return + + # Si la entrada es la primera nos salimos. + if numentry == o[0]: + return True + + # Si la entrada ya existe la borramos. + order = [numentry] + list (filter (lambda x: x if x!=numentry else [], order)) + ogNvramSetOrder (order) + + return True #/** @@ -198,6 +433,39 @@ def ogRestoreEfiBootLoader (disk, par): #@exception OG_ERR_NOTUEFI UEFI no activa. #@exception OG_ERR_NOTFOUND fichero o dispositivo no encontrado. #*/ ## +#ogNvramSetNext ('2') +#ogNvramSetNext ('Windows Boot Manager') +def ogNvramSetNext (entry): + if not InventoryLib.ogIsEfiActive(): + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTUEFI, '') + return + + numentries = [] + efibootmgr_out = subprocess.run (['efibootmgr'], capture_output=True, text=True).stdout + try: + foo = int (entry, 16) ## raises ValueError if entry doesn't look like hexadecimal + num = f'{foo:04x}'.upper() + for l in efibootmgr_out.splitlines(): + words = l.split() + if len(words) < 2: continue + if num in words[0]: + numentries.append (words[0][4:8]) + except ValueError: + for l in efibootmgr_out.splitlines(): + words = l.split (maxsplit=1) + if len(words) < 2: continue + if words[1] == entry: + numentries.append (words[0][4:8]) + + if not numentries: + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTFOUND, f'NVRAM entry "{entry}"') + return + + if 1 != len(numentries): + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_GENERIC, f'more than one entry found') + return + + subprocess.run (['efibootmgr', '-n', numentries[0]], capture_output=True, text=True) #/** # ogNvramSetOrder @@ -208,6 +476,38 @@ def ogRestoreEfiBootLoader (disk, par): #@exception OG_ERR_NOTUEFI UEFI no activa. #@exception OG_ERR_NOTFOUND fichero o dispositivo no encontrado (entrada NVRAM). #*/ ## +#ogNvramSetOrder (['1', '3']) +def ogNvramSetOrder (order): + mntdir = FileSystemLib.ogMount (disk, par) + if not mntdir: + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_PARTITION, f'{disk} {par}') + return + + try: + for i in order: + foo = int (i, 16) + except ValueError: + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_FORMAT, 'ogNvramSetOrder ([array or hex values])') + return + + # Entradas de la NVRAM actuales + numentries = [] + efibootmgr_out = subprocess.run (['efibootmgr'], capture_output=True, text=True).stdout + for l in efibootmgr_out.splitlines(): + words = l.split() + if len(words) < 2: continue + if re.search ('Boot[0-9a-fA-F]{4}', words[0]): + numentries.append ('0' + words[0][4:8]) + + new_order = [] + for o in order: + h = f'{int(o):04x}'.upper() + if h not in numentries: + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTFOUND, f'NVRAM entry order "{h}"') + return + new_order.append (h) + + subprocess.run (['efibootmgr', '-o', ','.join (new_order)]) #/** @@ -219,6 +519,19 @@ def ogRestoreEfiBootLoader (disk, par): #@exception OG_ERR_FORMAT formato incorrecto. #@exception OG_ERR_NOTFOUND fichero o dispositivo no encontrado. #*/ ## +#ogNvramSetTimeout ('2') +def ogNvramSetTimeout (t) { + if not InventoryLib.ogIsEfiActive(): + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTUEFI, '') + return + + try: + num = int (t) ## raises ValueError if t doesn't look like a number + except ValueError: + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_FORMAT, 'ogNvramSetTimeout (timeout)' + return + + subprocess.run (['efibootmgr', '-t', t]) #/** From d082bcf9160fac4fe332031475846518b9552b95 Mon Sep 17 00:00:00 2001 From: Natalia Serrano Date: Thu, 12 Dec 2024 10:54:45 +0100 Subject: [PATCH 095/167] refs #1218 add ogGrubInstallMbr() --- client/lib/engine/bin/BootLib.py | 109 ++++++++++++++++++++++- client/lib/engine/bin/UEFILib.py | 12 +-- client/shared/scripts/updateBootCache.py | 62 +++++++++++++ 3 files changed, 174 insertions(+), 9 deletions(-) create mode 100755 client/shared/scripts/updateBootCache.py diff --git a/client/lib/engine/bin/BootLib.py b/client/lib/engine/bin/BootLib.py index 3331aec..3b4e045 100644 --- a/client/lib/engine/bin/BootLib.py +++ b/client/lib/engine/bin/BootLib.py @@ -20,6 +20,7 @@ import RegistryLib import DiskLib import InventoryLib import FileLib +import UEFILib #/** # ogBoot int_ndisk int_nfilesys [ NVRAMPERM ] [str_kernel str_initrd str_krnlparams] @@ -393,6 +394,106 @@ part_letter={registered_vol} #@exception OG_ERR_FORMAT Formato incorrecto. #*/ ## +#ogGrubInstallMbr ('1', '1', 'FALSE') +#ogGrubInstallMbr ('1', '1', 'TRUE', 'nomodeset irqpoll pci=noacpi quiet splash') +def ogGrubInstallMbr (disk, par, checkos='FALSE', kernelparam=''): + backupname = '.backup.og' + + #error si no es linux. + #version = InventoryLib.ogGetOsVersion (disk, par) + #if not version or 'Linux' not in version: + # SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTOS, 'no es linux') + # return + + firststage = DiskLib.ogDiskToDev ('1') #La primera etapa del grub se fija en el primer disco duro + secondstage = FileSystemLib.ogMount (disk, par) #localizar disco segunda etapa del grub + if not secondstage: return + os.makedirs (f'{secondstage}/boot/grub/', exist_ok=True) + prefixsecondstage = '/boot/grubMBR' #Localizar directorio segunda etapa del grub + efioptgrub = [] + + if InventoryLib.ogIsEfiActive(): + esp = DiskLib.ogGetEsp() + efidisk, efipart = esp.split() + # Comprobamos que exista ESP y el directorio para ubuntu + efisecondstage = FileSystemLib.ogMount (efidisk, efipart) + if not efisecondstage: + FileSystemLib.ogFormat (efidisk, efipart, 'FAT32') + efisecondstage = FileSystemLib.ogMount (efidisk, efipart) + if not efisecondstage: + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_PARTITION, 'ESP') + return + efisubdir = 'grub' + if os.path.isdir (f'{efisecondstage}/EFI/{efisubdir}'): # Borramos la configuración anterior + shutil.rmtree (f'{efisecondstage}/EFI/{efisubdir}') + os.makedirs (f'{efisecondstage}/EFI/{efisubdir}/Boot') + arch = InventoryLib.ogGetArch() + efioptgrub = ['--removable', '--no-nvram', '--uefi-secure-boot', '--target', f'{arch}-efi', f'--efi-directory={efisecondstage}/EFI/{efisubdir}'] + + # Si Reconfigurar segunda etapa (grub.cfg) == FALSE + if 'FALSE' == checkos.upper() and (os.path.exists (f'{secondstage}/boot/grub/grub.cfg') or os.path.exists (f'{secondstage}/boot/grub/grub.cfg{backupname}')): + if os.path.exists (f'{secondstage}/boot/grub/grub.cfg{backupname}'): + os.rename (f'{secondstage}/boot/grub/grub.cfg{backupname}', f'{secondstage}/boot/grub/grub.cfg') + if os.path.isdir (f'{secondstage}{prefixsecondstage}'): + shutil.rmtree (f'{secondstage}{prefixsecondstage}') + prefixsecondstage = '' # Reactivamos el grub con el grub.cfg original. + else: # SI Reconfigurar segunda etapa (grub.cfg) == TRUE + #llamada a updateBootCache para que aloje la primera fase del ogLive + subprocess.run (['scripts/updateBootCache.py'], check=True) ## nati: TODO: ver el path + + if InventoryLib.ogIsEfiActive(): + # UEFI: grubSintax necesita grub.cfg para detectar los kernels: si no existe recupero backup. + if not os.path.exists (f'{secondstage}/boot/grub/grub.cfg'): + if os.path.exists (f'{secondstage}/boot/grub/grub.cfg{backupname}'): + os.rename (f'{secondstage}/boot/grub/grub.cfg{backupname}', f'{secondstage}/boot/grub/grub.cfg') + else: + os.rename (f'{secondstage}/boot/grub/grub.cfg', f'{secondstage}/boot/grub/grub.cfg{backupname}') + + with open ('/etc/default/grub', 'a') as fd: #Configur la sintaxis grub para evitar menus de "recovery" en el OGLive + fd.write ('GRUB_DISABLE_RECOVERY="true"\n') + fd.write ('GRUB_DISABLE_LINUX_UUID="true"\n') + + os.makedirs (f'{secondstage}{prefixsecondstage}/boot/grub/') #Preparar configuración segunda etapa: crear ubicacion + subprocess.run (['sed', '-i', 's/^set -e/#set -e/', '/etc/grub.d/00_header']) #Preparar configuración segunda etapa: crear cabecera del fichero (ingnorar errores) + # (ogLive 5.0) Si 'pkgdatadir' está vacía ponemos valor de otros ogLive + subprocess.run (['sed', '-i', '/grub-mkconfig_lib/i\pkgdatadir=${pkgdatadir:-"${datarootdir}/grub"}', '/etc/grub.d/00_header']) + out = subprocess.run (['/etc/grub.d/00_header'], capture_output=True, text=True).stdout + with open (f'{secondstage}{prefixsecondstage}/boot/grub/grub.cfg', 'w') as fd: + fd.write (out + '\n') + + #Preparar configuración segunda etapa: crear entrada del sistema operativo + out = subprocess.run (['grubSyntax', kernelparam], capture_output=True, text=True).stdout + with open (f'{secondstage}{prefixsecondstage}/boot/grub/grub.cfg', 'a') as fd: + fd.write (out + '\n') + + # Renombramos la configuración de grub antigua + if os.path.exists (f'{secondstage}/boot/grub/grub.cfg'): + os.rename (f'{secondstage}/boot/grub/grub.cfg', f'{secondstage}/boot/grub/grub.cfg{backupname}') + + eval = subprocess.run (['grub-install', '--force'] + efioptgrub + [f'--root-directory={secondstage}{prefixsecondstage}', firststage]).returncode + + if InventoryLib.ogIsEfiActive(): # Movemos el grubx64.efi + for b in (glob.glob (f'{efisecondstage}/EFI/{efisubdir}/EFI/BOOT/*')): + os.rename (f'{efisecondstage}/EFI/{efisubdir}/EFI/BOOT/{b}', f'{efisecondstage}/EFI/{efisubdir}/Boot/{b}') + shutil.rmtree (f'{efisecondstage}/EFI/{efisubdir}/EFI') + shutil.copy2 ('/usr/lib/shim/shimx64.efi.signed', f'{efisecondstage}/EFI/{efisubdir}/Boot/shimx64.efi') + # Nombre OpenGnsys para cargador + shutil.copy2 (f'{efisecondstage}/EFI/{efisubdir}/Boot/grubx64.efi', f'{efisecondstage}/EFI/{efisubdir}/Boot/ogloader.efi') + + # Creamos entrada NVRAM y la ponemos en segundo lugar + UEFILib.ogNvramAddEntry ('grub', '/EFI/grub/Boot/shimx64.efi') + grubentry = UEFILib.ogNvramList() + for l in grubentry.splitlines(): + words = l.split (maxsplit=1) + if len(words) < 2: continue + if 'grub' == words[1]: + grubentry = words[0] + neworder = UEFILib.ogNvramGetOrder() + neworder = neworder[0:1] + [grubentry] + neworder[1:] ## la ponemos en segundo lugar + UEFILib.ogNvramSetOrder (neworder) + + return eval + #/** # ogGrubInstallPartition int_disk_SECONDSTAGE int_partition_SECONDSTAGE bolean_Check_Os_installed_and_Configure_2ndStage @@ -405,9 +506,12 @@ part_letter={registered_vol} #@exception OG_ERR_FORMAT Formato incorrecto. #*/ ## +#ogGrubInstallPartition ('1', '1', 'FALSE') +#ogGrubInstallPartition ('1', '1', 'TRUE', 'nomodeset irqpoll pci=noacpi quiet splash') def ogGrubInstallPartition (disk, par, checkos='FALSE', kernelparam=''): backupname = '.backup.og' + #error si no es linux. version = InventoryLib.ogGetOsVersion (disk, par) if not version or 'Linux' not in version: SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTOS, 'no es linux') @@ -416,12 +520,12 @@ def ogGrubInstallPartition (disk, par, checkos='FALSE', kernelparam=''): firststage = DiskLib.ogDiskToDev (disk, par) #Localizar primera etapa del grub secondstage = FileSystemLib.ogMount (disk, par) #localizar disco segunda etapa del grub prefixsecondstage = '/boot/grubPARTITION' #Localizar directorio segunda etapa del grub - efioptgrub = [] # Si es EFI instalamos el grub en la ESP - #efibootdir = '' # Desde el bootdir uefi y bios buscan el grub.cfg en subdirectorios distintos. + efioptgrub = [] if InventoryLib.ogIsEfiActive(): esp = DiskLib.ogGetEsp() efidisk, efipart = esp.split() + # Comprobamos que exista ESP y el directorio para ubuntu efisecondstage = FileSystemLib.ogMount (efidisk, efipart) if not efisecondstage: FileSystemLib.ogFormat (efidisk, efipart, 'FAT32') @@ -435,7 +539,6 @@ def ogGrubInstallPartition (disk, par, checkos='FALSE', kernelparam=''): os.makedirs (f'{efisecondstage}/EFI/{efisubdir}/Boot') arch = InventoryLib.ogGetArch() efioptgrub = ['--removable', '--no-nvram', '--uefi-secure-boot', '--target', f'{arch}-efi', f'--efi-directory={efisecondstage}/EFI/{efisubdir}'] - #efibootdir = '/boot' # Si Reconfigurar segunda etapa (grub.cfg) == FALSE if 'FALSE' == checkos.upper() and (os.path.exists (f'{secondstage}/boot/grub/grub.cfg') or os.path.exists (f'{secondstage}/boot/grub/grub.cfg{backupname}')): diff --git a/client/lib/engine/bin/UEFILib.py b/client/lib/engine/bin/UEFILib.py index 1a979f6..ecab87a 100644 --- a/client/lib/engine/bin/UEFILib.py +++ b/client/lib/engine/bin/UEFILib.py @@ -210,7 +210,7 @@ def ogNvramGetNext(): # ogNvramGetOrder #@brief Muestra el orden de las entradas del gestor de arranque (NVRAM) -#@return Orden de las entradas +#@return Array, orden de las entradas #@exception OG_ERR_NOTUEFI UEFI no activa. #*/ ## def ogNvramGetOrder(): @@ -309,10 +309,10 @@ def ogNvramInactiveEntry (entry): #/** # ogNvramList #@brief Lista las entradas de la NVRAN (sólo equipos UEFI) -#@return Entradas de la NVRAM con el formato: orden etiqueta [* (si está activa) ] +#@return Multiline string: entradas de la NVRAM con el formato: orden etiqueta [* (si está activa) ] #@exception OG_ERR_NOTUEFI UEFI no activa. #*/ ## -def ogNvramList (): +def ogNvramList(): if not InventoryLib.ogIsEfiActive(): SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTUEFI, '') return @@ -325,7 +325,7 @@ def ogNvramList (): if re.search ('Boot[0-9]', words[0]): active = '*' if '*' in words[0] else '' num = words[0][4:8].strip ('0') or '0' - ret += '{:>4s} {} {}'.format (num, words[1], active) + ret += '{:>4s} {} {}\n'.format (num, words[1], active) return ret @@ -520,7 +520,7 @@ def ogNvramSetOrder (order): #@exception OG_ERR_NOTFOUND fichero o dispositivo no encontrado. #*/ ## #ogNvramSetTimeout ('2') -def ogNvramSetTimeout (t) { +def ogNvramSetTimeout (t): if not InventoryLib.ogIsEfiActive(): SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTUEFI, '') return @@ -528,7 +528,7 @@ def ogNvramSetTimeout (t) { try: num = int (t) ## raises ValueError if t doesn't look like a number except ValueError: - SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_FORMAT, 'ogNvramSetTimeout (timeout)' + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_FORMAT, 'ogNvramSetTimeout (timeout)') return subprocess.run (['efibootmgr', '-t', t]) diff --git a/client/shared/scripts/updateBootCache.py b/client/shared/scripts/updateBootCache.py new file mode 100755 index 0000000..854b9c9 --- /dev/null +++ b/client/shared/scripts/updateBootCache.py @@ -0,0 +1,62 @@ +#!/usr/bin/python3 + +import os +import shutil + +import ogGlobals +import SystemLib +import CacheLib + +#/** +# updateBootCache +#@brief acelerador arranque pxe. incorpora a la cache el initrd y el kernel. +#@param 1 +#@param ejemplo: +#@return +#@exception OG_ERR_NOTCACHE # 15 si cache no existe 15 +#@exception OG_ERR_NOTFOUND=2 # Fichero o dispositivo no encontrado. +#@note +#@todo: +#*/ ## + +oglivedir = os.environ.get ('oglivedir', 'ogLive') +ogbtftp = f'/opt/oglive/tftpboot/{oglivedir}' +ogbcache = f'{ogGlobals.OGCAC}/boot/{oglivedir}' + +#control de errores +if not os.path.isdir (ogbtftp): + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTFOUND, ogbtftp) + os.exit (1) + +if not CacheLib.ogMountCache(): + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTCACHE, 'CACHE') + os.exit (1) + +os.makedirs (ogbcache, exist_ok=True) + + # comparamos los del server +with open (f'{ogbtftp}/ogvmlinuz.sum', 'rb') as fd: servervmlinuz = fd.read() +with open (f'{ogbtftp}/oginitrd.img.sum', 'rb') as fd: serverinitrd = fd.read() + + #comparamos los de la cache +with open (f'{ogbcache}/ogvmlinuz.sum', 'rb') as fd: cachevmlinuz = fd.read() +with open (f'{ogbcache}/oginitrd.img.sum', 'rb') as fd: cacheinitrd = fd.read() + +print (f'MD5 on SERVER: {servervmlinuz} {serverinitrd}') +print (f'MD5 on CACHE: {cachevmlinuz} {cacheinitrd}') + +do_reboot = '0' +if cachevmlinuz != servervmlinuz: + print ('ogvmlinuz updating') + shutil.copy2 (f'{ogbtftp}/ogvmlinuz', f'{ogbcache}/ogvmlinuz') + shutil.copy2 (f'{ogbtftp}/ogvmlinuz.sum', f'{ogbcache}/ogvmlinuz.sum') + do_reboot = '1' + +if cacheinitrd != serverinitrd: + print ('oginitrd updating') + shutil.copy2 (f'{ogbtftp}/oginitrd.img', f'{ogbcache}/oginitrd.img') + shutil.copy2 (f'{ogbtftp}/oginitrd.img.sum', f'{ogbcache}/oginitrd.img.sum') + do_reboot = '1' + +print (do_reboot) +os.exit (0) From 1de8e854adf8381bb0180538c86f3b821e0fa742 Mon Sep 17 00:00:00 2001 From: Natalia Serrano Date: Thu, 12 Dec 2024 13:10:34 +0100 Subject: [PATCH 096/167] refs #1242 add scripts/configureOs.py --- client/lib/engine/bin/BootLib.py | 2 +- client/shared/scripts/configureOs.py | 154 +++++++++++++++++++++++++++ 2 files changed, 155 insertions(+), 1 deletion(-) create mode 100755 client/shared/scripts/configureOs.py diff --git a/client/lib/engine/bin/BootLib.py b/client/lib/engine/bin/BootLib.py index 3b4e045..c298994 100644 --- a/client/lib/engine/bin/BootLib.py +++ b/client/lib/engine/bin/BootLib.py @@ -439,7 +439,7 @@ def ogGrubInstallMbr (disk, par, checkos='FALSE', kernelparam=''): prefixsecondstage = '' # Reactivamos el grub con el grub.cfg original. else: # SI Reconfigurar segunda etapa (grub.cfg) == TRUE #llamada a updateBootCache para que aloje la primera fase del ogLive - subprocess.run (['scripts/updateBootCache.py'], check=True) ## nati: TODO: ver el path + subprocess.run ([f'{ogGlobals.OGSCRIPTS}/updateBootCache.py'], check=True) ## TODO: check that this works if InventoryLib.ogIsEfiActive(): # UEFI: grubSintax necesita grub.cfg para detectar los kernels: si no existe recupero backup. diff --git a/client/shared/scripts/configureOs.py b/client/shared/scripts/configureOs.py new file mode 100755 index 0000000..051c6c6 --- /dev/null +++ b/client/shared/scripts/configureOs.py @@ -0,0 +1,154 @@ +#!/usr/bin/python3 + +#/** +# configureOs +#@brief Script para realizar la configuracion del sistema operativo restaurado. +#@param 1 disco +#@param 2 particion +#@return +#@TODO comprobar que el tipo de particion corresponde con el sistema de archivos. +#@exception OG_ERR_FORMAT # 1 formato incorrecto. +#*/ ## + +import sys +import os +import os.path +import subprocess + +import ogGlobals +import DiskLib +import FileSystemLib +import InventoryLib +import BootLib +import UEFILib +import PostConfLib +import FileLib + +## el código bash original hace: +## [ -f $DEVICECFG ] && source $DEVICECFG +## pero luego no utiliza ninguna de las variables definidas en el archivo... + +disk = sys.argv[0] +par = sys.argv[1] + +# Si el sistema de archivos no esta extendido, ampliarlo al tamaño de su partición. +partsize = DiskLib.ogGetPartitionSize (disk, par) +if not partsize: sys.exit (1) +fssize = FileSystemLib.ogGetFsSize (disk, par) +if fssize < partsize: + print ('Extender sistema de archivos.') + FileSystemLib.ogExtendFs (disk, par) + +# Si no existe partición activa, activar este sistema. +flagactive = DiskLib.ogGetPartitionActive (disk) +if not flagactive: DiskLib.ogSetPartitionActive (disk, par) + +# Si el sistema de archivos es de solo lectura, no hacer la post-configuración. +mntdir = FileSystemLib.ogMount (disk, par) +if not FileSystemLib.ogIsWritable (disk, par): + print ('AVISO: sistema de archivos de solo lectura, no se ejecuta postconfiguración.') + sys.exit (0) + +# Nombre del cliente. +host = NetLib.ogGetHostname() + +# Post-configuración personalizada para cada tipo de sistema operativo. +ostype = InventoryLib.ogGetOsType (disk, par) +if 'Windows' == ostype: + if not host: host = 'pc' + BootLib.ogSetWindowsName (disk, par, host) # Cambiar nombre en sistemas Windows. + if InventoryLib.ogIsEfiActive(): # Si es UEFI copio el cargador de arranque a la partición EFI e instalo Grub. + UEFILib.ogRestoreEfiBootLoader (disk, par) + esp = DiskLib.ogGetEsp() + efidisk, efipart = esp.split() + BootLib.ogGrubInstallMbr (efidisk, efipart, 'TRUE') + else: + BootLib.ogFixBootSector (disk, par) # Configurar el boot sector de la partición Windows. + BootLib.ogWindowsBootParameters (disk, par) # Configurar el gestor de arranque de Windows XP/Vista/7. + BootLib.ogWindowsRegisterPartition (disk, par, 'C', disk, par) # Registrar en Windows que la partición indicada es su nueva unidad C:\ + PostConfLib.ogConfigureOgagent (disk, par) # Configurar nuevo agente OGAgent. + path1 = FileLib.ogGetPath (file=f'{mntdir}/windows/ogAdmWinClient.exe') + path2 = FileLib.ogGetPath (file=f'{mntdir}/winnt/ogAdmWinClient.exe') + if path1 or path2: # Eliminar el antiguo cliente de Windows. + PostConfLib.ogInstallMiniSetup (disk, par, 'postconf.cmd') + PostConfLib.ogUninstallWindowsClient (disk, par, 'postconf.cmd') + +elif 'Linux' == ostype: + BootLib.ogConfigureFstab (disk, par) # Configuro fstab: particion de Swap y si es UEFI además la partición EFI. + if InventoryLib.ogIsEfiActive(): # Si es UEFI instalo Grub en la partición EFI + esp = DiskLib.ogGetEsp() + efidisk, efipart = esp.split() + BootLib.ogGrubInstallMbr (efidisk, efipart, 'TRUE') + BootLib.ogGrubInstallPartition (disk, par) ## Instala (no configura) el codigo de arranque del Grub en la partición (no lo configura, se mantiene el original de la imagen) + find_out = subprocess.run (['find', f'{mntdir}/usr/sbin', f'{mntdir}/sbin', f'{mntdir}/usr/local/sbin', '-name', 'ogAdmLnxClient', '-print'], capture_output=True, text=True).stdout + if find_out: + PostConfLib.ogUninstallLinuxClient (disk, par) # Eliminar el antiguo cliente de Linux. + PostConfLib.ogConfigureOgagent (disk, par) # Configurar nuevo agente OGAgent. + ## Modificar el nombre del equipo + print (f'Asignar nombre Linux "{host}".') + etc = FileLib.ogGetPath (src=f'{disk} {par}', file='/etc') + if os.path.isdir (etc): + with open (f'{etc}/hostname', 'w') as fd: + fd.write (f'{host}\n') + +elif 'MacOS' == ostype: + open (f'{mntdir}/osxpostconf', 'a').close() ## touch, Fichero indicador de activación de postconfiguración. + + # Crear fichero de configuración del servicio de arranque. + with open (f'{mntdir}/Library/LaunchDaemons/es.opengnsys.postconfd.plist', 'w') as fd: + fd.write ('\n') + fd.write ('\n') + fd.write ('\t\n') + fd.write ('\t\tLabel\n') + fd.write ('\t\tes.opengnsys.postconfd.sh\n') + fd.write ('\t\tProgramArguments\n') + fd.write ('\t\t\n') + fd.write ('\t\t\t/var/root/postconfd.sh\n') + fd.write ('\t\t\n') + fd.write ('\t\tRunAtLoad\n') + fd.write ('\t\t\n') + fd.write ('\t\tStandardOutPath\n') + fd.write ('\t\t/var/log/postconfd.log\n') + fd.write ('\t\tStandardErrorPath\n') + fd.write ('\t\t/var/log/postconfd.err\n') + fd.write ('\t\tDebug\n') + fd.write ('\t\t\n') + fd.write ('\t\n') + fd.write ('\n') + + # Programa de inicio que será ejecutado en el arranque de Mac OS X. + with open (f'{mntdir}/var/root/postconfd.sh', 'w') as fd: + fd.write ('#!/bin/bash\n') + fd.write ('# postconfd - ejecución de scripts de inicio.\n') + fd.write ('\n') + fd.write ('# Ejecutar postconfiguración si existe el fichero indicador.\n') + fd.write ('if [ -e /osxpostconf ]; then\n') + fd.write ('\t# Tomar nombre del equipo.\n') + fd.write (f'\tHOST="{host}"\n') + fd.write ('\tif [ -z "$HOST" ]; then\n') + fd.write ('\t\t# Si no hay nombre asociado, activar la red para obtener datos del DHCP.\n') + fd.write ('\t\tsource /etc/rc.common\n') + fd.write ('\t\tCheckForNetwork\n') + fd.write ('\t\twhile [ "$NETWORKUP" != "-YES-" ]; do\n') + fd.write ('\t\t\tsleep 5\n') + fd.write ('\t\t\tNETWORKUP=\n') + fd.write ('\t\t\tCheckForNetwork\n') + fd.write ('\t\tdone\n') + fd.write ('\t\t# Componer nombre del equipo a partir de datos del DHCP.\n') + fd.write ('\t\tIP=$(ifconfig en0 inet | awk \'{if ($1=="inet") print $2}\')\n') + fd.write ('\t\tHOST="mac-$(echo ${IP//./-} | cut -f3-4 -d-)"\n') + fd.write ('\tfi\n') + fd.write ('\t# Asignar nombre del equipo.\n') + fd.write ('\tscutil --set ComputerName "$HOST"\n') + fd.write ('\tscutil --set LocalHostName "$HOST"\n') + fd.write ('\tscutil --set HostName "$HOST"\n') + fd.write ('\thostname "$HOST"\n') + fd.write ('\t# Descromprimir ficheros de versión para obtener inventario de aplicaciones.\n') + fd.write ('\tfind /Applications -type d -name "*.app" -prune -exec \\n') + fd.write ('\t ditto --nopreserveHFSCompression "{}/Contents/version.plist" "{}/Contents/version.plist.uncompress"\n') + fd.write ('\trm -f /osxpostconf # Borrar fichero indicador de psotconfiguración\n') + fd.write ('fi\n') + os.chmod (f'{mntdir}/var/root/postconfd.sh', 0o700) # Dar permiso de ejecución. + PostConfLib.ogConfigureOgagent (disk, par) # Configurar nuevo agente OGAgent de sistema operativo. + +sys.exit (0) From f0c4f7e07aca86ada33dc96628f205bfe4f5ca8b Mon Sep 17 00:00:00 2001 From: Natalia Serrano Date: Thu, 12 Dec 2024 18:29:39 +0100 Subject: [PATCH 097/167] refs #1245 add scripts/deployImage.py --- client/lib/engine/bin/ogGlobals.py | 2 +- client/shared/scripts/deployImage.py | 251 +++++++++++++++------------ 2 files changed, 141 insertions(+), 112 deletions(-) diff --git a/client/lib/engine/bin/ogGlobals.py b/client/lib/engine/bin/ogGlobals.py index 946efd8..3bdedb5 100755 --- a/client/lib/engine/bin/ogGlobals.py +++ b/client/lib/engine/bin/ogGlobals.py @@ -32,7 +32,7 @@ OGLOGSESSION='/tmp/session.log' OGLOGCOMMAND='/tmp/command.log' #OGWINCHKDISK=True #Hacer chkdisk tras la clonacion ACTIONCACHEFULL='NONE' #Que hacer cuando la cache no tenga espacio libre. [ NONE | FORMAT ] ] -#RESTOREPROTOCOLNOTCACHE=None #Que protocolo de restauracion usar en el caso de que no exista cache o no exista espacio sufiente. [NONE | UNICAST | MULTICAST].NONE retorna error +RESTOREPROTOCOLNOTCACHE=None #Que protocolo de restauracion usar en el caso de que no exista cache o no exista espacio sufiente. [NONE | UNICAST | MULTICAST].NONE retorna error #IMGPROG='partclone' #IMGCOMP='lzop' #IMGEXT='img' diff --git a/client/shared/scripts/deployImage.py b/client/shared/scripts/deployImage.py index d282025..f18be81 100755 --- a/client/shared/scripts/deployImage.py +++ b/client/shared/scripts/deployImage.py @@ -1,143 +1,172 @@ +#!/usr/bin/python3 + import os import sys import time +import subprocess +import shutil + +import ogGlobals import SystemLib import DiskLib import NetLib +import StringLib +import FileLib import ImageLib -#!/usr/bin/env python3 +#Descripcion: +# Si Repositorio es el global (REPO) realiza un deploy. +# Si Repositorio es local (CACHE) realiza un restoreImage CACHE +# El deploy, si detecta que el cliente no tiene una CACHE o no tiene espacio suficiente consulta el engine.cfg RESTOREPROTOCOLNOCACHE -def main(): - PROG = os.path.basename(__file__) - if len(sys.argv) < 5: - SystemLib.ogRaiseError("session", OG_ERR_FORMAT, f"{MSG_FORMAT}: {PROG} REPO imagen ndisco nparticion [ UNICAST-DIRECT|UNICAST|UNICAST-CACHE|MULTICAST-DIRECT|MULTICAST|MULTICAST-CACHE|TORRENT [opciones protocolo] ]") - sys.exit(1) +def main (repo, imgname, disk, par, proto='UNICAST', protoopt=''): + time1 = time.time() - TIME1 = time.time() - REPO = sys.argv[1].upper() or "REPO" - IMGNAME = sys.argv[2] - DISK = sys.argv[3] - PART = sys.argv[4] - PROTO = (sys.argv[5].upper() if len(sys.argv) > 5 else "UNICAST") - PROTOOPT = sys.argv[6] if len(sys.argv) > 6 else "" - OGUNIT = os.getenv("ogunit", "") +# Clear temporary file used as log track by httpdlog +# Limpia los ficheros temporales usados como log de seguimiento para httpdlog + with open (ogGlobals.OGLOGCOMMAND, 'w') as fd: + fd.write (' ') + if 'EjecutarScript' != SystemLib.ogGetCaller(): + with open (ogGlobals.OGLOGSESSION, 'w') as fd: + fd.write ('') - if not OGENGINECONFIGURATE: - exec(open("/opt/opengnsys/etc/engine.cfg").read()) +# Registro de inicio de ejecución + SystemLib.ogEcho (['log', 'session'], None, f'[1] {ogGlobals.lang.MSG_SCRIPTS_START} {__file__} {" ".join(sys.argv)}') - with open(OGLOGCOMMAND, 'w') as f: - f.write(" ") - if SystemLib.ogGetCaller() != "EjecutarScript": - with open(OGLOGSESSION, 'w') as f: - f.write("") +# Si el origen(pariticion) esta bloqueada salir. + if FileSystemLib.ogIsLocked (disk, par): + SystemLib.ogRaiseError ('session', ogGlobals.OG_ERR_LOCKED, f'{ogGlobals.lang.MSG_PARTITION}, {disk} {par}') + sys.exit (1) - SystemLib.ogEcho("log", "session", f"[1] {MSG_SCRIPTS_START} {PROG} {' '.join(sys.argv)}") + SystemLib.ogEcho (['log', 'session'], None, f'{ogGlobals.lang.MSG_HELP_ogUnmount} {disk} {par}') + FileSystemLib.ogUnmount (disk, par) - if FileSystemLib.ogIsLocked(DISK, PART): - sys.exit(SystemLib.ogRaiseError("session", OG_ERR_LOCKED, f"{MSG_PARTITION}, {DISK} {PART}")) - - SystemLib.ogEcho("log", "session", f"{MSG_HELP_FileSystemLib.ogUnmount} {DISK} {PART}") - FileSystemLib.ogUnmount(DISK, PART) - - if REPO == NetLib.ogGetIpAddress() or REPO == "CACHE": - MODE = "CACHE" +# Valor por defecto para el repositorio. + if repo == NetLib.ogGetIpAddress() or 'CACHE' == repo: + MODE = 'CACHE' else: - if DiskLib.ogCheckIpAddress(REPO) == 0 or REPO == "REPO": - if not NetLib.ogChangeRepo(REPO, OGUNIT): - sys.exit(SystemLib.ogRaiseError(OG_ERR_NOTFOUND, f"{REPO} {OGUNIT}")) - MODE = "REPO" + if StringLib.ogCheckIpAddress (repo) or 'REPO' == repo: + if not NetLib.ogChangeRepo (repo): + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTFOUND, repo) + sys.exit (1) + MODE = 'REPO' - IMGOS = ImageLib.ogGetImageInfo(ogGetPath(MODE, f"{IMGNAME}.img")) - if IMGOS == 1: - sys.exit(SystemLib.ogRaiseError("session", OG_ERR_NOTFOUND, f"{REPO} {IMGNAME}")) - elif IMGOS == 5: - sys.exit(SystemLib.ogRaiseError("session", OG_ERR_IMAGEFILE, f"{REPO} {IMGNAME}")) - elif IMGOS != 0: - sys.exit(SystemLib.ogRaiseError("session", OG_ERR_GENERIC)) +#Informacioin previa de la imagen + imgpath = FileLib.ogGetPath (MODE, f'{imgname}.img') + imgos = ImageLib.ogGetImageInfo (imgpath) + #if imgos == 1: sys.exit(SystemLib.ogRaiseError("session", OG_ERR_NOTFOUND, f"{repo} {imgname}")) + #elif imgos == 5: sys.exit(SystemLib.ogRaiseError("session", OG_ERR_IMAGEFILE, f"{repo} {imgname}")) + #elif imgos != 0: sys.exit(SystemLib.ogRaiseError("session", OG_ERR_GENERIC)) + if not imgos: + SystemLib.ogRaiseError ('session', ogGlobals.OG_ERR_GENERIC, '') + sys.exit (1) - IMGSIZE = os.path.getsize(ogGetPath(MODE, f"{IMGNAME}.img")) // 1024 - SystemLib.ogEcho("log", "session", f"[1] REPO={REPO} IMG-FILE={IMGNAME}.img SIZE={IMGSIZE} (KB) METADATA={IMGOS}") + imgsize = os.path.getsize (imgpath) // 1024 + SystemLib.ogEcho (['log', 'session'], None, f'[1] REPO={repo} IMG-FILE={imgname}.img SIZE={imgsize} (KB) METADATA={imgos}') - if MODE == "CACHE": - NEXTOPERATION = "CACHE" - elif MODE == "REPO": - if PROTO in ["MULTICAST-DIRECT", "UNICAST-DIRECT"]: - NEXTOPERATION = PROTO.split('-')[0] - elif PROTO in ["TORRENT", "TORRENT-CACHE", "MULTICAST", "MULTICAST-CACHE", "UNICAST", "UNICAST-CACHE"]: - PROTO = PROTO.split('-')[0] - SystemLib.ogEcho("log", "session", f"[2] updateCache {REPO} /{IMGNAME}.img {PROTO} {PROTOOPT}") - TIME2 = time.time() - RETVAL = updateCache(REPO, f"/{IMGNAME}.img", PROTO, PROTOOPT) - TIME2 = time.time() - TIME2 - SystemLib.ogEcho("log", "session", f" [ ] {MSG_SCRIPTS_TIME_PARTIAL} updateCache {TIME2 // 60}m {TIME2 % 60}s") - if RETVAL == 0: - SystemLib.ogEcho("log", "session", "[50] updateCache (OK)") - NEXTOPERATION = "CACHE" - elif RETVAL in [15, 16]: - SystemLib.ogEcho("log", "session", f"[50] {MSG_ERR_NOTCACHE} ; {MSG_ERR_CACHESIZE}") - SystemLib.ogEcho("log", "session", f"[50] {MSG_SCRIPTS_CHECK_ENGINE}: RESTOREPROTOCOLNOTCACHE={RESTOREPROTOCOLNOTCACHE}") - if RESTOREPROTOCOLNOTCACHE == "MULTICAST": - NEXTOPERATION = "MULTICAST" if PROTO == "MULTICAST" else "UNICAST" - elif RESTOREPROTOCOLNOTCACHE == "UNICAST": - NEXTOPERATION = "UNICAST" - elif RESTOREPROTOCOLNOTCACHE == "NONE": - if RETVAL == 15: - SystemLib.ogEcho("log", "session", f"[100] {MSG_ERR_NOTCACHE}") - sys.exit(SystemLib.ogRaiseError("session", OG_ERR_NOTCACHE, "NOT CACHE")) - elif RETVAL == 16: - SystemLib.ogEcho("log", "session", f"[100] {MSG_ERR_CACHESIZE}") - sys.exit(SystemLib.ogRaiseError("session", OG_ERR_CACHESIZE, "CACHE FULL")) - elif RETVAL in [57, 60]: - sys.exit(RETVAL) +# Procesar repositorio. + if 'CACHE' == MODE: + nextoperation = 'CACHE' + elif 'REPO' == MODE: + if 'MULTICAST-DIRECT' == proto: + nextoperation = 'MULTICAST' + elif 'UNICAST-DIRECT' == proto: + nextoperation = 'UNICAST' + # Si protocolo es torrent|torrent-cache o multicast|multicast-cache + elif proto in ['TORRENT', 'TORRENT-CACHE', 'MULTICAST', 'MULTICAST-CACHE', 'UNICAST', 'UNICAST-CACHE']: + # Eliminamos CACHE o DIRECT + proto = proto.split ('-')[0] + SystemLib.ogEcho (['log', 'session'], None, f'[2] updateCache {repo} "/{imgname}.img" {proto} {protoopt}') + time2 = time.time() + retval = subprocess.run (['updateCache', repo, f'/{imgname}.img', proto, protoopt]).returncode + time2 = time.time() - time2 + SystemLib.ogEcho (['log', 'session'], None, f' [ ] {ogGlobals.lang.MSG_SCRIPTS_TIME_PARTIAL} updateCache {int (time2/60)}m {int (time2%60)}s') + if 0 == retval: + SystemLib.ogEcho (['log', 'session'], None, '[50] updateCache (OK)') + nextoperation = 'CACHE' + elif retval in [15, 16]: + # no se permite usar la cache (no existe(15) o no espacio sufiente (16). Se consulta engine.cfg para RESTOREPROTOCOLNOCACHE [ multicast unicast none ] + SystemLib.ogEcho (['log', 'session'], None, f'[50] {ogGlobals.lang.MSG_ERR_NOTCACHE} ; {ogGlobals.lang.MSG_ERR_CACHESIZE}') + SystemLib.ogEcho (['log', 'session'], None, f'[50] {ogGlobals.lang.MSG_SCRIPTS_CHECK_ENGINE}: RESTOREPROTOCOLNOTCACHE={ogGlobals.RESTOREPROTOCOLNOTCACHE}') + if 'MULTICAST' == RESTOREPROTOCOLNOTCACHE: + if 'MULTICAST' == proto: nextoperation = 'MULTICAST' + elif 'TORRENT' == proto: nextoperation = 'UNICAST' + elif 'UNICAST' == proto: nextoperation = 'UNICAST' + elif 'UNICAST' == RESTOREPROTOCOLNOTCACHE: + nextoperation = 'UNICAST' + elif RESTOREPROTOCOLNOTCACHE is None: + if 15 == retval: + SystemLib.ogEcho (['log', 'session'], None, f'[100] {ogGlobals.lang.MSG_ERR_NOTCACHE}') + SystemLib.ogRaiseError ('session', ogGlobals.OG_ERR_NOTCACHE, 'NOT CACHE') + sys.exit (1) + elif 16 == retval: + SystemLib.ogEcho (['log', 'session'], None, f'[100] {ogGlobals.lang.MSG_ERR_CACHESIZE}') + SystemLib.ogRaiseError ('session', ogGlobals.OG_ERR_CACHESIZE, 'CACHE FULL') + sys.exit (1) + elif retval in [57, 60]: + # Time-out en la transferencia multicast (El mensaje de error está enviado) + sys.exit (retval) else: - sys.exit(RETVAL) + # Error desconocido + sys.exit (retval) else: - sys.exit(SystemLib.ogRaiseError("session", OG_ERR_FORMAT, f"{MSG_ERR_FORMAT}, {PROTO}")) + SystemLib.ogRaiseError ('session', ogGlobals.OG_ERR_FORMAT, f'{ogGlobals.lang.MSG_ERR_FORMAT}, {proto}') + sys.exit (1) else: - sys.exit(SystemLib.ogRaiseError("session", OG_ERR_FORMAT, f"{MSG_ERR_FORMAT}, {REPO}")) + SystemLib.ogRaiseError ('session', ogGlobals.OG_ERR_FORMAT, f'{ogGlobals.lang.MSG_ERR_FORMAT}, {repo}') + sys.exit (1) - TIME3 = time.time() + time3 = time.time() - if NEXTOPERATION == "CACHE": - PARAMS = f"CACHE {IMGNAME} {DISK} {PART}" - elif NEXTOPERATION == "UNICAST": - PARAMS = f"{REPO} {IMGNAME} {DISK} {PART}" - elif NEXTOPERATION == "MULTICAST": - PARAMS = f"{REPO} {IMGNAME} {DISK} {PART} {PROTO} {PROTOOPT}" +# Obtener parámetros de restauración. + if 'CACHE' == nextoperation: + params = ['CACHE', imgname, disk, par] + elif 'UNICAST' == nextoperation: + params = [repo, imgname, disk, par] + elif 'MULTICAST' == nextoperation: + params = [repo, imgname, disk, par, proto, protoopt] - if os.system("which restoreImageCustom") == 0: - SystemLib.ogEcho("log", "session", f"[55] {MSG_HELP_ogRestoreImage}: restoreImageCustom {PARAMS}") - os.system(f"restoreImageCustom {PARAMS}") +# Si existe, ejecuta script personalizado "restoreImageCustom"; si no, llama al genérico "restoreImage". + if shutil.which ('restoreImageCustom'): + SystemLib.ogEcho (['log', 'session'], None, f'[55] {ogGlobals.lang.MSG_HELP_ogRestoreImage}: restoreImageCustom {params}') + retval = subprocess.run (['restoreImageCustom'] + params).returncode else: - SystemLib.ogEcho("log", "session", f"[55] {MSG_HELP_ogRestoreImage}: restoreImage {PARAMS}") - os.system(f"restoreImage {PARAMS}") - RETVAL = os.system(f"restoreImage {PARAMS}") + SystemLib.ogEcho (['log', 'session'], None, f'[55] {ogGlobals.lang.MSG_HELP_ogRestoreImage}: restoreImage {params}') + retval = subprocess.run (['restoreImage'] + params).returncode - RESUMERESTOREIMAGE = os.popen(f"grep -m 1 'Total Time:' {OGLOGCOMMAND}").read() - SystemLib.ogEcho("log", "session", f" [ ] {RESUMERESTOREIMAGE}") - if RETVAL != 0: - SystemLib.ogRaiseError("session", OG_ERR_IMAGE, f"{REPO} {IMGNAME}") - if SystemLib.ogGetCaller() != "EjecutarScript": - SystemLib.ogEcho("log", "session", f"{MSG_INTERFACE_END} {OG_ERR_IMAGE}") - sys.exit(OG_ERR_IMAGE) +# Mostrar resultados. + resumerestoreimage = subprocess.run (['grep', '--max-count', '1', 'Total Time:', ogGlobals.OGLOGCOMMAND], capture_output=True, text=True).stdout + SystemLib.ogEcho (['log', 'session'], None, f' [ ] {resumerestoreimage} ') +# Si la transferencia ha dado error me salgo. + if retval: + SystemLib.ogRaiseError ('session', ogGlobals.OG_ERR_IMAGE, f'{repo} {imgname}') + if SystemLib.ogGetCaller() != 'EjecutarScript': + SystemLib.ogEcho (['log', 'session'], None, f'{ogGlobals.lang.MSG_INTERFACE_END} {ogGlobals.OG_ERR_IMAGE}') + sys.exit (ogGlobals.OG_ERR_IMAGE) - TIME3 = time.time() - TIME3 - SystemLib.ogEcho("log", "session", f" [ ] {MSG_SCRIPTS_TIME_PARTIAL} : {TIME3 // 60}m {TIME3 % 60}s") + time3 = time.time() - time3 + SystemLib.ogEcho (['log', 'session'], None, f' [ ] {ogGlobals.lang.MSG_SCRIPTS_TIME_PARTIAL} : {int (time3/60)}m {int (time3%60)}s') - if os.system("which configureOsCustom") == 0: - SystemLib.ogEcho("log", "session", "[90] configureOsCustom") - os.system(f"configureOsCustom {DISK} {PART} {REPO} {IMGNAME}") +# Si existe, ejecuta script personalizado de postconfiguración "configureOsCustom"; si no, llama al genérico "configureOs". + if shutil.which ('configureOsCustom'): + SystemLib.ogEcho (['log', 'session'], None, '[90] configureOsCustom') + subprocess.run (['configureOsCustom', disk, par, repo, imgname]) else: - SystemLib.ogEcho("log", "session", f"[90] {MSG_SCRIPTS_OS_CONFIGURE}") - os.system(f"configureOs {DISK} {PART}") + SystemLib.ogEcho (['log', 'session'], None, f'[90] {ogGlobals.lang.MSG_SCRIPTS_OS_CONFIGURE}') + subprocess.run (['configureOs', disk, par]) - TIME = time.time() - TIME1 - SystemLib.ogEcho("log", "session", f"[100] {MSG_SCRIPTS_TIME_TOTAL} {TIME // 60}m {TIME % 60}s") + time_total = time.time() - time1 + SystemLib.ogEcho (['log', 'session'], None, f'[100] {ogGlobals.lang.MSG_SCRIPTS_TIME_TOTAL} {int (time_total/60)}m {int (time_total%60)}s') - if SystemLib.ogGetCaller() != "EjecutarScript": - SystemLib.ogEcho("log", "session", f"{MSG_INTERFACE_END} {RETVAL}") - sys.exit(RETVAL) +# Registro de fin de ejecución +# Si se ha llamado desde ejecutar script no lo muestro para no repetir. + if SystemLib.ogGetCaller() != 'EjecutarScript': + SystemLib.ogEcho (['log', 'session'], None, f'{ogGlobals.lang.MSG_INTERFACE_END} {retval}') + sys.exit (retval) -if __name__ == "__main__": - main() +if __name__ == '__main__': + if len (sys.argv) < 4: + SystemLib.ogRaiseError ('session', ogGlobals.OG_ERR_FORMAT, f'{ogGlobals.lang.MSG_FORMAT}: {__file__} REPO imagen ndisco nparticion [ UNICAST-DIRECT|UNICAST|UNICAST-CACHE|MULTICAST-DIRECT|MULTICAST|MULTICAST-CACHE|TORRENT [opciones protocolo] ]') + sys.exit (1) + sys.argv[0] = sys.argv[0].upper() if sys.argv[0] else 'REPO' + main (*sys.argv) From f66bf4f5071f9c9e847acafd7911c76e89a77eaf Mon Sep 17 00:00:00 2001 From: Natalia Serrano Date: Tue, 17 Dec 2024 14:24:47 +0100 Subject: [PATCH 098/167] refs #1245 add several fixes --- client/lib/engine/bin/BootLib.py | 4 +-- client/lib/engine/bin/PostConfLib.py | 4 +-- client/shared/scripts/configureOs.py | 5 ++-- client/shared/scripts/deployImage.py | 38 +++++++++++++++++---------- client/shared/scripts/restoreImage.py | 2 +- client/shared/scripts/updateCache.py | 6 ++--- 6 files changed, 35 insertions(+), 24 deletions(-) diff --git a/client/lib/engine/bin/BootLib.py b/client/lib/engine/bin/BootLib.py index c298994..b963842 100644 --- a/client/lib/engine/bin/BootLib.py +++ b/client/lib/engine/bin/BootLib.py @@ -456,7 +456,7 @@ def ogGrubInstallMbr (disk, par, checkos='FALSE', kernelparam=''): os.makedirs (f'{secondstage}{prefixsecondstage}/boot/grub/') #Preparar configuración segunda etapa: crear ubicacion subprocess.run (['sed', '-i', 's/^set -e/#set -e/', '/etc/grub.d/00_header']) #Preparar configuración segunda etapa: crear cabecera del fichero (ingnorar errores) # (ogLive 5.0) Si 'pkgdatadir' está vacía ponemos valor de otros ogLive - subprocess.run (['sed', '-i', '/grub-mkconfig_lib/i\pkgdatadir=${pkgdatadir:-"${datarootdir}/grub"}', '/etc/grub.d/00_header']) + subprocess.run (['sed', '-i', r'/grub-mkconfig_lib/i\pkgdatadir=${pkgdatadir:-"${datarootdir}/grub"}', '/etc/grub.d/00_header']) out = subprocess.run (['/etc/grub.d/00_header'], capture_output=True, text=True).stdout with open (f'{secondstage}{prefixsecondstage}/boot/grub/grub.cfg', 'w') as fd: fd.write (out + '\n') @@ -563,7 +563,7 @@ def ogGrubInstallPartition (disk, par, checkos='FALSE', kernelparam=''): os.makedirs (f'{secondstage}{prefixsecondstage}/boot/grub/') #Preparar configuración segunda etapa: crear ubicacion subprocess.run (['sed', '-i', 's/^set -e/#set -e/', '/etc/grub.d/00_header']) #Preparar configuración segunda etapa: crear cabecera del fichero (ingnorar errores) # (ogLive 5.0) Si 'pkgdatadir' está vacía ponemos valor de otros ogLive - subprocess.run (['sed', '-i', '/grub-mkconfig_lib/i\pkgdatadir=${pkgdatadir:-"${datarootdir}/grub"}', '/etc/grub.d/00_header']) + subprocess.run (['sed', '-i', r'/grub-mkconfig_lib/i\pkgdatadir=${pkgdatadir:-"${datarootdir}/grub"}', '/etc/grub.d/00_header']) out = subprocess.run (['/etc/grub.d/00_header'], capture_output=True, text=True).stdout with open (f'{secondstage}{prefixsecondstage}/boot/grub/grub.cfg', 'w') as fd: fd.write (out + '\n') diff --git a/client/lib/engine/bin/PostConfLib.py b/client/lib/engine/bin/PostConfLib.py index a6e7f58..4871c6d 100644 --- a/client/lib/engine/bin/PostConfLib.py +++ b/client/lib/engine/bin/PostConfLib.py @@ -67,8 +67,8 @@ def ogInstallFirstBoot (disk, par, cmdfile): # Creamos el archivo cmd y creamos un par de comandos para que una vez acabe la # postconfiguracion resetee el mini setup, sino lo haria en cada arranque. with open (full_cmdfile, 'w') as fd: - fd.write ('REG ADD HKLM\System\Setup /v SystemSetupInProgress /t REG_DWORD /d 0 /f\n') - fd.write ('REG ADD HKLM\System\Setup /v CmdLine /t REG_SZ /d "" /f\n') + fd.write (r'REG ADD HKLM\System\Setup /v SystemSetupInProgress /t REG_DWORD /d 0 /f\n') + fd.write (r'REG ADD HKLM\System\Setup /v CmdLine /t REG_SZ /d "" /f\n') # Crear los valores de registro necesarios para que se haga la ejecución del .cmd al aranque. RegistryLib.ogSetRegistryValue (mntdir, 'SYSTEM', r'\Setup\SystemSetupInProgress', 1) diff --git a/client/shared/scripts/configureOs.py b/client/shared/scripts/configureOs.py index 051c6c6..13248df 100755 --- a/client/shared/scripts/configureOs.py +++ b/client/shared/scripts/configureOs.py @@ -18,6 +18,7 @@ import subprocess import ogGlobals import DiskLib import FileSystemLib +import NetLib import InventoryLib import BootLib import UEFILib @@ -28,8 +29,8 @@ import FileLib ## [ -f $DEVICECFG ] && source $DEVICECFG ## pero luego no utiliza ninguna de las variables definidas en el archivo... -disk = sys.argv[0] -par = sys.argv[1] +disk = sys.argv[1] +par = sys.argv[2] # Si el sistema de archivos no esta extendido, ampliarlo al tamaño de su partición. partsize = DiskLib.ogGetPartitionSize (disk, par) diff --git a/client/shared/scripts/deployImage.py b/client/shared/scripts/deployImage.py index f18be81..e5a2ec2 100755 --- a/client/shared/scripts/deployImage.py +++ b/client/shared/scripts/deployImage.py @@ -8,6 +8,7 @@ import shutil import ogGlobals import SystemLib +import FileSystemLib import DiskLib import NetLib import StringLib @@ -19,7 +20,13 @@ import ImageLib # Si Repositorio es local (CACHE) realiza un restoreImage CACHE # El deploy, si detecta que el cliente no tiene una CACHE o no tiene espacio suficiente consulta el engine.cfg RESTOREPROTOCOLNOCACHE +prog = os.path.basename (sys.argv[0]) + def main (repo, imgname, disk, par, proto='UNICAST', protoopt=''): + if repo: repo = repo.upper() + else: repo = 'REPO' + proto = proto.upper() + protoopt = protoopt.upper() time1 = time.time() # Clear temporary file used as log track by httpdlog @@ -31,7 +38,7 @@ def main (repo, imgname, disk, par, proto='UNICAST', protoopt=''): fd.write ('') # Registro de inicio de ejecución - SystemLib.ogEcho (['log', 'session'], None, f'[1] {ogGlobals.lang.MSG_SCRIPTS_START} {__file__} {" ".join(sys.argv)}') + SystemLib.ogEcho (['log', 'session'], None, f'[1] {ogGlobals.lang.MSG_SCRIPTS_START} {prog} {" ".join(sys.argv)}') # Si el origen(pariticion) esta bloqueada salir. if FileSystemLib.ogIsLocked (disk, par): @@ -42,17 +49,21 @@ def main (repo, imgname, disk, par, proto='UNICAST', protoopt=''): FileSystemLib.ogUnmount (disk, par) # Valor por defecto para el repositorio. - if repo == NetLib.ogGetIpAddress() or 'CACHE' == repo: - MODE = 'CACHE' + mode = None + if NetLib.ogGetIpAddress() == repo or 'CACHE' == repo: + mode = 'CACHE' else: if StringLib.ogCheckIpAddress (repo) or 'REPO' == repo: if not NetLib.ogChangeRepo (repo): SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTFOUND, repo) sys.exit (1) - MODE = 'REPO' + mode = 'REPO' #Informacioin previa de la imagen - imgpath = FileLib.ogGetPath (MODE, f'{imgname}.img') + if mode: + imgpath = FileLib.ogGetPath (src=mode, file=f'{imgname}.img') + else: + imgpath = FileLib.ogGetPath (file=f'{imgname}.img') imgos = ImageLib.ogGetImageInfo (imgpath) #if imgos == 1: sys.exit(SystemLib.ogRaiseError("session", OG_ERR_NOTFOUND, f"{repo} {imgname}")) #elif imgos == 5: sys.exit(SystemLib.ogRaiseError("session", OG_ERR_IMAGEFILE, f"{repo} {imgname}")) @@ -65,9 +76,9 @@ def main (repo, imgname, disk, par, proto='UNICAST', protoopt=''): SystemLib.ogEcho (['log', 'session'], None, f'[1] REPO={repo} IMG-FILE={imgname}.img SIZE={imgsize} (KB) METADATA={imgos}') # Procesar repositorio. - if 'CACHE' == MODE: + if 'CACHE' == mode: nextoperation = 'CACHE' - elif 'REPO' == MODE: + elif 'REPO' == mode: if 'MULTICAST-DIRECT' == proto: nextoperation = 'MULTICAST' elif 'UNICAST-DIRECT' == proto: @@ -78,7 +89,7 @@ def main (repo, imgname, disk, par, proto='UNICAST', protoopt=''): proto = proto.split ('-')[0] SystemLib.ogEcho (['log', 'session'], None, f'[2] updateCache {repo} "/{imgname}.img" {proto} {protoopt}') time2 = time.time() - retval = subprocess.run (['updateCache', repo, f'/{imgname}.img', proto, protoopt]).returncode + retval = subprocess.run (['updateCache.py', repo, f'/{imgname}.img', proto, protoopt]).returncode time2 = time.time() - time2 SystemLib.ogEcho (['log', 'session'], None, f' [ ] {ogGlobals.lang.MSG_SCRIPTS_TIME_PARTIAL} updateCache {int (time2/60)}m {int (time2%60)}s') if 0 == retval: @@ -132,7 +143,7 @@ def main (repo, imgname, disk, par, proto='UNICAST', protoopt=''): retval = subprocess.run (['restoreImageCustom'] + params).returncode else: SystemLib.ogEcho (['log', 'session'], None, f'[55] {ogGlobals.lang.MSG_HELP_ogRestoreImage}: restoreImage {params}') - retval = subprocess.run (['restoreImage'] + params).returncode + retval = subprocess.run (['restoreImage.py'] + params).returncode # Mostrar resultados. resumerestoreimage = subprocess.run (['grep', '--max-count', '1', 'Total Time:', ogGlobals.OGLOGCOMMAND], capture_output=True, text=True).stdout @@ -153,7 +164,7 @@ def main (repo, imgname, disk, par, proto='UNICAST', protoopt=''): subprocess.run (['configureOsCustom', disk, par, repo, imgname]) else: SystemLib.ogEcho (['log', 'session'], None, f'[90] {ogGlobals.lang.MSG_SCRIPTS_OS_CONFIGURE}') - subprocess.run (['configureOs', disk, par]) + subprocess.run (['configureOs.py', disk, par]) time_total = time.time() - time1 SystemLib.ogEcho (['log', 'session'], None, f'[100] {ogGlobals.lang.MSG_SCRIPTS_TIME_TOTAL} {int (time_total/60)}m {int (time_total%60)}s') @@ -165,8 +176,7 @@ def main (repo, imgname, disk, par, proto='UNICAST', protoopt=''): sys.exit (retval) if __name__ == '__main__': - if len (sys.argv) < 4: - SystemLib.ogRaiseError ('session', ogGlobals.OG_ERR_FORMAT, f'{ogGlobals.lang.MSG_FORMAT}: {__file__} REPO imagen ndisco nparticion [ UNICAST-DIRECT|UNICAST|UNICAST-CACHE|MULTICAST-DIRECT|MULTICAST|MULTICAST-CACHE|TORRENT [opciones protocolo] ]') + if len (sys.argv) < 6: + SystemLib.ogRaiseError ('session', ogGlobals.OG_ERR_FORMAT, f'{ogGlobals.lang.MSG_FORMAT}: {prog} REPO imagen ndisco nparticion [ UNICAST-DIRECT|UNICAST|UNICAST-CACHE|MULTICAST-DIRECT|MULTICAST|MULTICAST-CACHE|TORRENT [opciones protocolo] ]') sys.exit (1) - sys.argv[0] = sys.argv[0].upper() if sys.argv[0] else 'REPO' - main (*sys.argv) + main (*sys.argv[1:]) diff --git a/client/shared/scripts/restoreImage.py b/client/shared/scripts/restoreImage.py index 39fc017..a5f0ff6 100644 --- a/client/shared/scripts/restoreImage.py +++ b/client/shared/scripts/restoreImage.py @@ -48,7 +48,7 @@ SystemLib.ogEcho (['log', 'session'], None, f'[1] {ogGlobals.lang.MSG_SCRIPTS_ST # Procesar parámetros de entrada print (f'argv ({sys.argv}) len ({len (sys.argv)})') -if len (sys.argv) < 6: +if len (sys.argv) < 5: SystemLib.ogRaiseError ('session', ogGlobals.OG_ERR_FORMAT, f'{ogGlobals.lang.MSG_FORMAT}: {prog} REPO|CACHE imagen ndisco nparticion [ UNICAST|MULTICAST opciones protocolo]') sys.exit (1) diff --git a/client/shared/scripts/updateCache.py b/client/shared/scripts/updateCache.py index 655e861..773bef3 100644 --- a/client/shared/scripts/updateCache.py +++ b/client/shared/scripts/updateCache.py @@ -40,9 +40,9 @@ print (f'argv ({sys.argv}) len ({len (sys.argv)})') if len (sys.argv) < 3: SystemLib.ogRaiseError ('session', ogGlobals.OG_ERR_FORMAT, f'{ogGlobals.lang.MSG_FORMAT}: {prog} str_REPO _str_Relative_Path_OGIMG_with_/ PROTOCOLO OPCIONES_PROTOCOLO OPCIONES_UPDATECACHE') sys.exit (1) -#_, repositorio, path, protocolo, optprotocolo, cacheopts = sys.argv -_, repositorio, path, protocolo, optprotocolo = sys.argv -cacheopts = '' +_, repositorio, path, protocolo, *other = sys.argv +optprotocolo = other[0] if len (other) > 0 else '' +cacheopts = other[1] if len (other) > 1 else '' if 'RSYNC' == protocolo: raise Exception ('synchronised images are no longer supported') From f6ae95020143346520aa91328c229e0b1e3a364d Mon Sep 17 00:00:00 2001 From: Natalia Serrano Date: Tue, 17 Dec 2024 14:25:34 +0100 Subject: [PATCH 099/167] refs #1302 fix ogCalculateChecksum --- client/lib/engine/bin/FileLib.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/client/lib/engine/bin/FileLib.py b/client/lib/engine/bin/FileLib.py index 424c17a..62ce2f4 100755 --- a/client/lib/engine/bin/FileLib.py +++ b/client/lib/engine/bin/FileLib.py @@ -60,11 +60,11 @@ def ogCalculateChecksum (disk=None, par=None, container=None, file=None): return last_n_bytes = 1024*1024 - if last_n_bytes >= os.stat ('/bin/ls').st_size: + if last_n_bytes >= os.stat (f).st_size: return ogCalculateFullChecksum (disk, par, container, file) with open (f, 'rb') as fd: fd.seek (-last_n_bytes, os.SEEK_END) - data = file.read() + data = fd.read() md5 = hashlib.md5(data).hexdigest() return md5 From 93177def1f93d4dbf27289e4827d46d6e8b3c394 Mon Sep 17 00:00:00 2001 From: Natalia Serrano Date: Wed, 18 Dec 2024 12:12:25 +0100 Subject: [PATCH 100/167] refs #1307 fix calls to chntpw --- client/lib/engine/bin/RegistryLib.py | 134 +++++++++++++-------------- 1 file changed, 66 insertions(+), 68 deletions(-) diff --git a/client/lib/engine/bin/RegistryLib.py b/client/lib/engine/bin/RegistryLib.py index c924bbd..8b32511 100755 --- a/client/lib/engine/bin/RegistryLib.py +++ b/client/lib/engine/bin/RegistryLib.py @@ -19,7 +19,9 @@ import FileLib # Función ficticia para lanzar chntpw con timeout de 5 s., evitando cuelgues del programa. chntpw_exe = shutil.which ('drbl-chntpw') or shutil.which ('chntpw') def chntpw (hivefile, input_file): - return subprocess.run ([chntpw_exe, '-e', hivefile], timeout=5, input=open(input_file, 'r'), capture_output=True, text=True).stdout + with open (input_file, 'r') as fd: + input_contents = fd.read() + return subprocess.run ([chntpw_exe, '-e', hivefile], timeout=5, input=input_contents, capture_output=True, text=True).stdout ## en el codigo bash aparecen "${3%\\*}" y "${3##*\\}" varias veces ## ${3%\\*} es el "dirname" de una key del registro @@ -49,13 +51,13 @@ def ogAddRegistryKey (mntpt, hive, k): k_dirname, k_basename = _split_k (k) - tmpfile = tempfile.TemporaryFile (prefix='chntpw-', mode='w') - with open (tmpfile, 'w') as f: + with tempfile.NamedTemporaryFile (delete_on_close=False, prefix='chntpw-', mode='w') as f: f.write (f'cd {k_dirname}\n') f.write (f'nk {k_basename}\n') f.write ('q\ny\n') - chntpw (hivefile, tmpfile) - os.remove (tmpfile) + f.close() + chntpw (hivefile, f.name) + os.remove (f.name) #/** # ogAddRegistryValue path_mountpoint str_hive str_valuename [str_valuetype] @@ -88,13 +90,13 @@ def ogAddRegistryValue (mntpt, hive, k, vtype='STRING'): SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_OUTOFLIMIT, vtype) return - tmpfile = tempfile.TemporaryFile (prefix='chntpw-', mode='w') - with open (tmpfile, 'w') as f: + with tempfile.NamedTemporaryFile (delete_on_close=False, prefix='chntpw-', mode='w') as f: f.write (f'cd {k_dirname}\n') f.write (f'nv {TYPE} {k_basename}\n') f.write ('q\ny\n') - chntpw (hivefile, tmpfile) - os.remove (tmpfile) + f.close() + chntpw (hivefile, f.name) + os.remove (f.name) #/** @@ -117,13 +119,13 @@ def ogDeleteRegistryKey (mntpt, hive, k): k_dirname, k_basename = _split_k (k) - tmpfile = tempfile.TemporaryFile (prefix='chntpw-', mode='w') - with open (tmpfile, 'w') as f: + with tempfile.NamedTemporaryFile (delete_on_close=False, prefix='chntpw-', mode='w') as f: f.write (f'cd {k_dirname}\n') f.write (f'dk {k_basename}\n') f.write ('q\ny\n') - chntpw (hivefile, tmpfile) - os.remove (tmpfile) + f.close() + chntpw (hivefile, f.name) + os.remove (f.name) #/** @@ -146,13 +148,13 @@ def ogDeleteRegistryValue (mntpt, hive, k): k_dirname, k_basename = _split_k (k) - tmpfile = tempfile.TemporaryFile (prefix='chntpw-', mode='w') - with open(tmpfile, 'w') as f: + with tempfile.NamedTemporaryFile (delete_on_close=False, prefix='chntpw-', mode='w') as f: f.write (f'cd {k_dirname}\n') f.write (f'dv {k_basename}\n') f.write ('q\ny\n') - chntpw (hivefile, tmpfile) - os.remove(tmpfile) + f.close() + chntpw (hivefile, f.name) + os.remove(f.name) #/** @@ -167,6 +169,8 @@ def ogDeleteRegistryValue (mntpt, hive, k): #@warning El sistema de archivos de Windows debe estar montada previamente. #*/ ## #ogGetHivePath ('/mnt/sda1', 'user1') => /mnt/sda1/Users/user1/NTUSER.DAT +#ogGetHivePath ('/mnt/sda1', 'SYSTEM') => //mnt/sda1/Windows/System32/config/SYSTEM +#ogGetHivePath ('/mnt/sda1', 'IEUser') => //mnt/sda1/Users/IEUser/NTUSER.DAT def ogGetHivePath(mntpt, hive): # Camino del fichero de registro de usuario o de sistema (de menor a mayor prioridad). FILE = FileLib.ogGetPath(file=f"/{mntpt}/Windows/System32/config/{hive}") @@ -176,11 +180,7 @@ def ogGetHivePath(mntpt, hive): if FILE and os.path.isfile(FILE): return FILE else: - SystemLib.ogRaiseError( - [], - ogGlobals.OG_ERR_NOTFOUND, - f"{mntpt} {hive}" - ) + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTFOUND, f'{mntpt} {hive}') return None @@ -198,19 +198,19 @@ def ogGetHivePath(mntpt, hive): #@warning El sistema de archivos de Windows debe estar montado previamente. #*/ ## def ogGetRegistryValue (mntpt, hive, k): - FILE = ogGetHivePath(mntpt, hive) - if not FILE: return + hivefile = ogGetHivePath(mntpt, hive) + if not hivefile: return k_dirname, k_basename = _split_k (k) - tmpfile = tempfile.TemporaryFile (prefix='chntpw-', mode='w') - with open(tmpfile, 'w') as f: + with tempfile.NamedTemporaryFile (delete_on_close=False, prefix='chntpw-', mode='w') as f: f.write (f'cd {k_dirname}\n') f.write (f'cat {k_basename}\n') f.write ('q\n') + f.close() + chntpw_out = chntpw (hivefile, f.name) + os.remove (f.name) - chntpw_out = chntpw (hivefile, tmpfile) - os.remove (tmpfile) lines = chntpw_out.splitlines() if 2 != len (lines): return None @@ -234,17 +234,17 @@ def ogGetRegistryValue (mntpt, hive, k): #*/ ## #ogListRegistryKeys ('/mnt/sda1', 'SOFTWARE', '\Microsoft\Windows\CurrentVersion') def ogListRegistryKeys (mntpt, hive, k): - FILE = ogGetHivePath(mntpt, hive) - if not FILE: return + hivefile = ogGetHivePath(mntpt, hive) + if not hivefile: return - tmpfile = tempfile.TemporaryFile (prefix='chntpw-', mode='w') - with open(tmpfile, 'w') as f: + with tempfile.NamedTemporaryFile (delete_on_close=False, prefix='chntpw-', mode='w') as f: f.write (f'ls {k}\n') f.write ('q\n') - chntpw_out = chntpw (hivefile, tmpfile) - os.remove (tmpfile) - lines = chntpw_out.splitlines() + f.close() + chntpw_out = chntpw (hivefile, f.name) + os.remove (f.name) + lines = chntpw_out.splitlines() ret = [] for l in lines: elems = re.split ('[<>]', l) @@ -269,17 +269,17 @@ def ogListRegistryKeys (mntpt, hive, k): #*/ ## #ogListRegistryValues ('/mnt/sda1', 'SOFTWARE', '\Microsoft\Windows\CurrentVersion') def ogListRegistryValues (mntpt, hive, k): - FILE = ogGetHivePath(mntpt, hive) - if not FILE: return + hivefile = ogGetHivePath(mntpt, hive) + if not hivefile: return - tmpfile = tempfile.TemporaryFile (prefix='chntpw-', mode='w') - with open(tmpfile, 'w') as f: + with tempfile.NamedTemporaryFile (delete_on_close=False, prefix='chntpw-', mode='w') as f: f.write (f'ls {k}\n') f.write ('q\n') - chntpw_out = chntpw (hivefile, tmpfile) - os.remove (tmpfile) - lines = chntpw_out.splitlines() + f.close() + chntpw_out = chntpw (hivefile, f.name) + os.remove (f.name) + lines = chntpw_out.splitlines() ret = [] for l in lines: elems = re.split ('[<>]', l) @@ -331,33 +331,31 @@ def ogSetRegistryValue (mntpt, hive, k, v): k_dirname, k_basename = _split_k (k) - tmpfile = tempfile.TemporaryFile (prefix='chntpw-', mode='w') - try: - with open(tmpfile, 'w') as f: - f.write (f"ls {k_dirname}\n") - f.write ('q\n') + with tempfile.NamedTemporaryFile (delete_on_close=False, prefix='chntpw-', mode='w') as f: + ## TODO: indentation here. This 'try' should be indented + f.write (f"ls {k_dirname}\n") + f.write ('q\n') + f.close() + chntpw_out = chntpw (hivefile, f.name) + os.remove(f.name) - chntpw_out = chntpw (hivefile, tmpfile) - if re.search (f"BINARY.*<{k_basename}>", chntpw_out): - ## the entry in the registry is binary. Our input should be a sequence of bytes + if re.search (f"BINARY.*<{k_basename}>", chntpw_out): + ## the entry in the registry is binary. Our input should be a sequence of bytes - if ' ' != v[-1]: v += ' ' ## the regex below requires a trailing space - if not re.match (r'^([0-9A-F]{2} )*$', v.upper()): - SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_FORMAT, f'"{v}"') - return + if ' ' != v[-1]: v += ' ' ## the regex below requires a trailing space + if not re.match (r'^([0-9A-F]{2} )*$', v.upper()): + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_FORMAT, f'"{v}"') + return - formatted = _format_hex (v.upper()) - formatted += '\ns' - else: - formatted = v + formatted = _format_hex (v.upper()) + formatted += '\ns' + else: + formatted = v - with open(tmpfile, 'w') as f: - f.write (f'cd {k_dirname}\n') - f.write (f'ed {k_basename}\n') - f.write (f'{formatted}\n') - f.write ('q\ny\n') - - # Aplicar cambios. - chntpw (hivefile, tmpfile) - finally: - os.remove(tmpfile) + with tempfile.NamedTemporaryFile (delete_on_close=False, prefix='chntpw-', mode='w') as f: + f.write (f'cd {k_dirname}\n') + f.write (f'ed {k_basename}\n') + f.write (f'{formatted}\n') + f.write ('q\ny\n') + chntpw (hivefile, f.name) + os.remove(f.name) From 32d5305dc264baa26a75a236e34ec1d307df5046 Mon Sep 17 00:00:00 2001 From: Natalia Serrano Date: Wed, 18 Dec 2024 13:38:46 +0100 Subject: [PATCH 101/167] refs #1308 fix loop in ogGetPath --- client/lib/engine/bin/FileLib.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/client/lib/engine/bin/FileLib.py b/client/lib/engine/bin/FileLib.py index 62ce2f4..433b6ed 100755 --- a/client/lib/engine/bin/FileLib.py +++ b/client/lib/engine/bin/FileLib.py @@ -358,7 +358,8 @@ def ogGetPath (src=None, file=None): #print (f'ls_path no existe, filepath ({filepath})') prevfile = f - f = '/'.join (f.split('/')[1:]) ## remove 1st component + if '/' in f: + f = '/'.join (f.split('/')[1:]) ## remove 1st component #print (f'f ({f}) prevfile ({prevfile})') return filepath From d1b49362a4ef34990fc431f0ae0adece62f2bab2 Mon Sep 17 00:00:00 2001 From: Natalia Serrano Date: Wed, 18 Dec 2024 14:42:29 +0100 Subject: [PATCH 102/167] refs #1309 fix ogGetRegistryValue --- client/lib/engine/bin/RegistryLib.py | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/client/lib/engine/bin/RegistryLib.py b/client/lib/engine/bin/RegistryLib.py index 8b32511..f8dd5d1 100755 --- a/client/lib/engine/bin/RegistryLib.py +++ b/client/lib/engine/bin/RegistryLib.py @@ -184,6 +184,17 @@ def ogGetHivePath(mntpt, hive): return None +## simulate 'grep --after-context 1' +def _grep_A1 (strings, search_term): + results = [] + for i in range (len (strings)): + if search_term in strings[i]: + results.append (strings[i]) + if i + 1 < len(strings): + results.append (strings[i + 1]) + + return results + #/** # ogGetRegistryValue path_mountpoint str_hive str_valuename #@brief Devuelve el dato de un valor del registro de Windows. @@ -212,11 +223,18 @@ def ogGetRegistryValue (mntpt, hive, k): os.remove (f.name) lines = chntpw_out.splitlines() + lines = _grep_A1 (lines, '> Value') if 2 != len (lines): return None + + ret = None if 'REG_BINARY' in lines[0]: - offset, content = lines[1].split (maxsplit=1) - return content + if re.search ('^:[0-9A-F]+ ', lines[1]): + print ('re.match') + ret = lines[1][8:56] + else: + ret = lines[1] + return ret #/** From e43a1265579683a99bb8beb709b4aadd00a6b346 Mon Sep 17 00:00:00 2001 From: Natalia Serrano Date: Wed, 18 Dec 2024 16:55:26 +0100 Subject: [PATCH 103/167] refs #1310 close a file before reading from it again --- client/lib/engine/bin/RegistryLib.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/client/lib/engine/bin/RegistryLib.py b/client/lib/engine/bin/RegistryLib.py index f8dd5d1..e8277be 100755 --- a/client/lib/engine/bin/RegistryLib.py +++ b/client/lib/engine/bin/RegistryLib.py @@ -74,7 +74,9 @@ def ogAddRegistryKey (mntpt, hive, k): #@warning Requisitos: chntpw #@warning El sistema de archivos de Windows debe estar montada previamente. #*/ ## -#ogAddRegistryValue ('/mnt/sda1', 'SOFTWARE', '\Microsoft\NewKey\Value1') +#ogAddRegistryValue ('/mnt/sda1', 'SOFTWARE', '\Microsoft\NewKey\Value1') ## type STRING by default +#ogAddRegistryValue ('/mnt/sda1', 'SOFTWARE', '\Microsoft\NewKey\Value1', 'STRING') +#ogAddRegistryValue ('/mnt/sda1', 'SOFTWARE', '\Microsoft\NewKey\Value1', 'BINARY') #ogAddRegistryValue ('/mnt/sda1', 'SOFTWARE', '\Microsoft\NewKey\Value1', 'DWORD') def ogAddRegistryValue (mntpt, hive, k, vtype='STRING'): hivefile = ogGetHivePath (mntpt, hive) @@ -350,7 +352,6 @@ def ogSetRegistryValue (mntpt, hive, k, v): k_dirname, k_basename = _split_k (k) with tempfile.NamedTemporaryFile (delete_on_close=False, prefix='chntpw-', mode='w') as f: - ## TODO: indentation here. This 'try' should be indented f.write (f"ls {k_dirname}\n") f.write ('q\n') f.close() @@ -375,5 +376,6 @@ def ogSetRegistryValue (mntpt, hive, k, v): f.write (f'ed {k_basename}\n') f.write (f'{formatted}\n') f.write ('q\ny\n') + f.close() chntpw (hivefile, f.name) os.remove(f.name) From a68556e8c91728ad003609af4b30e4b60c76bcb6 Mon Sep 17 00:00:00 2001 From: Natalia Serrano Date: Thu, 19 Dec 2024 17:27:51 +0100 Subject: [PATCH 104/167] refs #1312 fix contents of postconf.cmd --- client/lib/engine/bin/FileSystemLib.py | 2 -- client/lib/engine/bin/PostConfLib.py | 17 +++++++++-------- 2 files changed, 9 insertions(+), 10 deletions(-) diff --git a/client/lib/engine/bin/FileSystemLib.py b/client/lib/engine/bin/FileSystemLib.py index ef43e6b..bcb7d79 100755 --- a/client/lib/engine/bin/FileSystemLib.py +++ b/client/lib/engine/bin/FileSystemLib.py @@ -522,13 +522,11 @@ def ogIsLocked(disk, par): def ogIsPartitionLocked(disk, par): DISK = DiskLib.ogDiskToDev(disk) PART = DiskLib.ogDiskToDev(disk, par) - print (f'nati: ogIsPartitionLocked: DISK ({DISK}) PART ({PART})') if not PART: return LOCKDISK = f"/var/lock/lock{DISK.replace('/', '-')}" LOCKPART = f"/var/lock/lock{PART.replace('/', '-')}" rc = os.path.isfile(LOCKDISK) or os.path.isfile(LOCKPART) - print (f'nati: ogIsPartitionLocked: LOCKDISK ({LOCKDISK}) LOCKPART ({LOCKPART}) rc ({rc})') return rc #/** diff --git a/client/lib/engine/bin/PostConfLib.py b/client/lib/engine/bin/PostConfLib.py index 4871c6d..2a1e0c4 100644 --- a/client/lib/engine/bin/PostConfLib.py +++ b/client/lib/engine/bin/PostConfLib.py @@ -63,19 +63,20 @@ def ogInstallFirstBoot (disk, par, cmdfile): SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTFOUND, f'{mntdir}/windows/system32') return full_cmdfile = f'{cmddir}/{cmdfile}' + bn = os.path.basename (full_cmdfile) # Creamos el archivo cmd y creamos un par de comandos para que una vez acabe la # postconfiguracion resetee el mini setup, sino lo haria en cada arranque. with open (full_cmdfile, 'w') as fd: - fd.write (r'REG ADD HKLM\System\Setup /v SystemSetupInProgress /t REG_DWORD /d 0 /f\n') - fd.write (r'REG ADD HKLM\System\Setup /v CmdLine /t REG_SZ /d "" /f\n') + fd.write (r'REG ADD HKLM\System\Setup /v SystemSetupInProgress /t REG_DWORD /d 0 /f' + '\n') + fd.write (r'REG ADD HKLM\System\Setup /v CmdLine /t REG_SZ /d "" /f' + '\n') # Crear los valores de registro necesarios para que se haga la ejecución del .cmd al aranque. RegistryLib.ogSetRegistryValue (mntdir, 'SYSTEM', r'\Setup\SystemSetupInProgress', 1) RegistryLib.ogSetRegistryValue (mntdir, 'SYSTEM', r'\Setup\SetupType', 4) #RegistryLib.ogDeleteRegistryValue (mntdir, 'SYSTEM', r'\Setup\CmdLine') RegistryLib.ogAddRegistryValue (mntdir, 'SYSTEM', r'\Setup\CmdLine') - RegistryLib.ogSetRegistryValue (mntdir, 'SYSTEM', r'\Setup\CmdLine', f'cmd.exe /c $(basename {full_cmdfile})') + RegistryLib.ogSetRegistryValue (mntdir, 'SYSTEM', r'\Setup\CmdLine', f'cmd.exe /c {bn}') #/** @@ -106,10 +107,10 @@ def ogInstallRunonce (disk, par, cmdfile, user, pwd, autologin, userauto=None, p if not autologin: # Si no queremos hacer autologin despues de la postconfiguracion lo indicamos en las claves de registro with open (full_cmdfile, 'w') as fd: - fd.write (r'DEL C:\ogboot.*\n') - fd.write (r'REG ADD "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon" /v AutoAdminLogon /t REG_SZ /d 0 /f\n') - fd.write (r'REG ADD "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon" /v DefaultUserName /t REG_SZ /d "" /f\n') - fd.write (r'REG DELETE "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon" /v DefaultPassword /f\n') + fd.write (r'DEL C:\ogboot.*' + '\n') + fd.write (r'REG ADD "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon" /v AutoAdminLogon /t REG_SZ /d 0 /f' + '\n') + fd.write (r'REG ADD "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon" /v DefaultUserName /t REG_SZ /d "" /f' + '\n') + fd.write (r'REG DELETE "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon" /v DefaultPassword /f' + '\n') else: # Si queremos hacer autologin despues de la postconfiguracion introducimos la informacion en las claves de registro with open (full_cmdfile, 'w') as fd: @@ -119,7 +120,7 @@ def ogInstallRunonce (disk, par, cmdfile, user, pwd, autologin, userauto=None, p fd.write (fr'REG ADD "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon" /v DefaultPassword /t REG_SZ /d "{pwdauto}" /f' + '\n') #Creamos las claves de registro necesarias para que meter el cmd en el runonce del usuario y este haga autologin RegistryLib.ogAddRegistryValue (mountpoint, 'software', r'\Microsoft\Windows\CurrentVersion\RunOnce\PostConfiguracion') - RegistryLib.ogSetRegistryValue (mountpoint, 'software', r'\Microsoft\Windows\CurrentVersion\RunOnce\PostConfiguracion', rf'C:\windows\system32\{full_cmdfile}') + RegistryLib.ogSetRegistryValue (mountpoint, 'software', r'\Microsoft\Windows\CurrentVersion\RunOnce\PostConfiguracion', rf'C:\windows\system32\{cmdfile}') RegistryLib.ogAddRegistryValue (mountpoint, 'software', r'\Microsoft\Windows NT\CurrentVersion\Winlogon\AutoAdminLogon') RegistryLib.ogSetRegistryValue (mountpoint, 'software', r'\Microsoft\Windows NT\CurrentVersion\Winlogon\AutoAdminLogon', 1) RegistryLib.ogAddRegistryValue (mountpoint, 'software', r'\Microsoft\Windows NT\CurrentVersion\Winlogon\DefaultUserName') From c4c53d66794b67e70be3e486336784f5b7cd3fa6 Mon Sep 17 00:00:00 2001 From: Natalia Serrano Date: Fri, 10 Jan 2025 13:35:32 +0100 Subject: [PATCH 105/167] refs #1326 add ogDeleteTree() --- client/lib/engine/bin/FileLib.py | 51 ++++++++++++++++---------- client/lib/engine/bin/FileSystemLib.py | 7 +--- 2 files changed, 32 insertions(+), 26 deletions(-) diff --git a/client/lib/engine/bin/FileLib.py b/client/lib/engine/bin/FileLib.py index 433b6ed..bc8de5e 100755 --- a/client/lib/engine/bin/FileLib.py +++ b/client/lib/engine/bin/FileLib.py @@ -261,30 +261,41 @@ def ogDeleteFile (disk=None, par=None, container=None, file=None): SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_GENERIC, str (e)) return -def ogDeleteTree(*args): - # Variables locales. - DIR = None - if "help" in args: - SystemLib.ogHelp("$FUNCNAME", "$FUNCNAME [ str_repo | int_ndisk int_npartition ] path_dir", "$FUNCNAME 1 2 /tmp/newdir") + +#/** +# ogDeleteTree [ str_repo | int_ndisk int_npartition ] path_dirpath +#@brief Metafunción que borra todo un subárbol de directorios de un dispositivo. +#@see ogGetPath +#*/ ## +#ogDeleteTree (container='REPO', file='/tmp/newdir') +#ogDeleteTree (disk=1, par=2, file='/tmp/newdir') +def ogDeleteTree (disk=None, par=None, container=None, file=None): + if file is None: + raise TypeError ('missing required argument: "file"') + + if container is not None: + if disk is None and par is None: + ## we were given container= + src = container + else: + raise TypeError ('argument "container" can be specified along neither "disk" nor "par"') + else: + if disk is not None and par is not None: + ## we were given disk= par= + src = f'{disk} {par}' + else: + ## we were given nothing + raise TypeError ('either "container" or both "disk" and "par" must be specified') + + f = ogGetPath (src=src, file=file) + if not f: + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTFOUND, f'{src} {file}') return - # Comprobar que existe el directorio y borrarlo con su contenido. - DIR = ogGetPath(*args) - if not DIR: - SystemLib.ogRaiseError( - "session", - ogGlobals.OG_ERR_NOTFOUND, - f"Not found: {args}" - ) - return try: - shutil.rmtree(DIR) + shutil.rmtree (f) except OSError as e: - SystemLib.ogRaiseError( - "session", - ogGlobals.OG_ERR_NOTFOUND, - f"{e}" - ) + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTFOUND, e) return diff --git a/client/lib/engine/bin/FileSystemLib.py b/client/lib/engine/bin/FileSystemLib.py index bcb7d79..f1953ec 100755 --- a/client/lib/engine/bin/FileSystemLib.py +++ b/client/lib/engine/bin/FileSystemLib.py @@ -654,12 +654,7 @@ def ogMountFs (disk, par): if mntdir: return mntdir if ogIsLocked (disk, par): - print (f'nati: ogMountFs: is locked disk ({disk}) par ({par})') - SystemLib.ogRaiseError ( - [], - ogGlobals.OG_ERR_LOCKED, - f"{ogGlobals.lang.MSG_PARTITION}, {disk} {par}" - ) + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_LOCKED, f'{ogGlobals.lang.MSG_PARTITION}, {disk} {par}') return # El camino de un dispositivo normal comienza por el carácter "/". From cb3c8b2bf5cc65ef17a0b6b35ec6153232c7a813 Mon Sep 17 00:00:00 2001 From: Natalia Serrano Date: Fri, 10 Jan 2025 13:41:02 +0100 Subject: [PATCH 106/167] refs #1328 add ogCleanLinuxDevices() --- client/lib/engine/bin/BootLib.py | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/client/lib/engine/bin/BootLib.py b/client/lib/engine/bin/BootLib.py index b963842..8966b8f 100644 --- a/client/lib/engine/bin/BootLib.py +++ b/client/lib/engine/bin/BootLib.py @@ -677,6 +677,17 @@ def ogConfigureFstab (disk, par): #@exception OG_ERR_NOTFOUND Disco o particion no corresponden con un dispositivo. #@exception OG_ERR_PARTITION Tipo de partición desconocido o no se puede montar. #*/ ## +#ogCleanLinuxDevices (1, 1) +def ogCleanLinuxDevices (disk, par): + mntdir = FileSystemLib.ogMount (disk, par) + if not mntdir: return None + + # Eliminar fichero de configuración de udev para dispositivos fijos de red. + if os.path.exists (f'{mntdir}/etc/udev/rules.d/70-persistent-net.rules'): + os.unlink (f'{mntdir}/etc/udev/rules.d/70-persistent-net.rules') + # Eliminar fichero resume (estado previo de hibernación) utilizado por el initrd scripts-premount + if os.path.exists (f'{mntdir}/etc/initramfs-tools/conf.d/resume'): + os.unlink ( f'{mntdir}/etc/initramfs-tools/conf.d/resume') #/** # ogGrubAddOgLive num_disk num_part [ timeout ] [ offline ] From 43437d549146c18c44f93b67fbd374ce995eb967 Mon Sep 17 00:00:00 2001 From: Natalia Serrano Date: Fri, 10 Jan 2025 14:23:54 +0100 Subject: [PATCH 107/167] refs #1327 add ogCleanOs() --- client/lib/engine/bin/PostConfLib.py | 15 +++++++++++++++ client/lib/engine/bin/ProtocolLib.py | 6 +++--- 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/client/lib/engine/bin/PostConfLib.py b/client/lib/engine/bin/PostConfLib.py index 2a1e0c4..e97b266 100644 --- a/client/lib/engine/bin/PostConfLib.py +++ b/client/lib/engine/bin/PostConfLib.py @@ -7,6 +7,7 @@ #*/ import os +import glob import subprocess import ogGlobals @@ -15,6 +16,8 @@ import FileSystemLib import FileLib import NetLib import RegistryLib +import InventoryLib +import BootLib #/** # ogCleanOs int_ndisk int_nfilesys @@ -27,6 +30,18 @@ import RegistryLib #@note Antes incluido en la funcion ogReduceFs #@return (nada) #*/ ## +#ogCleanOs (1, 1) +def ogCleanOs (disk, par): + t = InventoryLib.ogGetOsType (disk, par) + if 'Linux' == t: + BootLib.ogCleanLinuxDevices (disk, par) + mntdir = FileSystemLib.ogMount (disk, par) + for t in glob.glob ('{mntdir}/tmp/*'): + shutil.rmtree (t) + elif 'Windows' == t: + for f in 'pagefile.sys', 'hiberfil.sys', 'swapfile.sys': + p = FileLib.ogGetPath (src=f'{disk} {par}', file=f) + if p: FileLib.ogDeleteFile (disk=disk, par=par, file=f) diff --git a/client/lib/engine/bin/ProtocolLib.py b/client/lib/engine/bin/ProtocolLib.py index 9912e4c..d06a696 100644 --- a/client/lib/engine/bin/ProtocolLib.py +++ b/client/lib/engine/bin/ProtocolLib.py @@ -880,9 +880,9 @@ def ogUpdateCacheIsNecesary (repo, file, proto): print (f'filetarget ({filetarget})') if not filetarget: # borramos el fichero bf del torrent, en el caso de que se hubiese quedado de algun proceso fallido - if FileLib.ogGetPath (src='CACHE', file=f'/{file}.torrent.bf'): ogDeleteFile ('CACHE', f'{file}.torrent.bf') - if FileLib.ogGetPath (src='CACHE', file=f'/{file}.sum'): ogDeleteFile ('CACHE', f'{file}.sum') - if FileLib.ogGetPath (src='CACHE', file=f'/{file}.full.sum'): ogDeleteFile ('CACHE', f'{file}.full.sum') + if FileLib.ogGetPath (src='CACHE', file=f'/{file}.torrent.bf'): ogDeleteFile (container='CACHE', file=f'{file}.torrent.bf') + if FileLib.ogGetPath (src='CACHE', file=f'/{file}.sum'): ogDeleteFile (container='CACHE', file=f'{file}.sum') + if FileLib.ogGetPath (src='CACHE', file=f'/{file}.full.sum'): ogDeleteFile (container='CACHE', file=f'{file}.full.sum') print ('TRUE(0), es necesario actualizar. Paso 1, la cache no contiene esa imagen ') return True From f64f20a88fe98274f0a28722cf5e0f35993ed21a Mon Sep 17 00:00:00 2001 From: Natalia Serrano Date: Tue, 21 Jan 2025 15:02:46 +0100 Subject: [PATCH 108/167] refs #1337 add some commands --- client/lib/engine/bin/BootLib.py | 5 +- client/lib/engine/bin/CacheLib.py | 52 ++++++++++++--- client/lib/engine/bin/FileLib.py | 13 ++++ client/lib/engine/bin/SystemLib.py | 35 +++++------ client/shared/functions/ogCalculateChecksum | 32 ++++++++++ .../shared/functions/ogCalculateFullChecksum | 32 ++++++++++ client/shared/functions/ogChangeRepo | 23 +++++++ client/shared/functions/ogCheckIpAddress | 22 +++++++ client/shared/functions/ogCleanLinuxDevices | 23 +++++++ client/shared/functions/ogCleanOs | 23 +++++++ client/shared/functions/ogConfigureFstab | 23 +++++++ client/shared/functions/ogConfigureOgagent | 23 +++++++ client/shared/functions/ogCopyFile | 63 +++++++++++++++++++ client/shared/functions/ogCreateImageSyntax | 25 ++++++++ client/shared/functions/ogDeleteFile | 32 ++++++++++ client/shared/functions/ogDeleteTree | 32 ++++++++++ client/shared/functions/ogDevToDisk | 22 +++++++ client/shared/functions/ogDiskToDev | 23 +++++++ client/shared/functions/ogEcho | 24 +++++++ client/shared/functions/ogExecAndLog | 53 ++++++++++++++++ client/shared/functions/ogFindCache | 22 +++++++ client/shared/functions/ogGetArch | 22 +++++++ client/shared/functions/ogGetCacheSize | 22 +++++++ client/shared/functions/ogGetCaller | 22 +++++++ client/shared/functions/ogGetFreeSize | 24 +++++++ client/shared/functions/ogGetFsSize | 24 +++++++ client/shared/functions/ogGetFsType | 23 +++++++ client/shared/functions/ogGetHostname | 22 +++++++ client/shared/functions/ogGetImageCompressor | 23 +++++++ client/shared/functions/ogGetImageInfo | 22 +++++++ client/shared/functions/ogGetImageProgram | 23 +++++++ client/shared/functions/ogGetImageSize | 23 +++++++ client/shared/functions/ogGetImageType | 23 +++++++ client/shared/functions/ogGetIpAddress | 22 +++++++ client/shared/functions/ogGetMacAddress | 22 +++++++ client/shared/functions/ogGetMountPoint | 23 +++++++ client/shared/functions/ogGetOsType | 23 +++++++ client/shared/functions/ogGetOsVersion | 23 +++++++ client/shared/functions/ogGetParentPath | 32 ++++++++++ client/shared/functions/ogGetPartitionActive | 22 +++++++ client/shared/functions/ogGetPartitionId | 23 +++++++ client/shared/functions/ogGetPartitionSize | 23 +++++++ .../shared/functions/ogGetPartitionTableType | 22 +++++++ client/shared/functions/ogGetPath | 32 ++++++++++ client/shared/functions/ogGetRepoIp | 22 +++++++ client/shared/functions/ogGetServerIp | 22 +++++++ .../shared/functions/ogGrubInstallPartition | 25 ++++++++ client/shared/functions/ogHelp | 24 +++++++ client/shared/functions/ogIsEfiActive | 22 +++++++ client/shared/functions/ogIsFormated | 23 +++++++ client/shared/functions/ogIsImageLocked | 23 +++++++ client/shared/functions/ogIsLocked | 23 +++++++ client/shared/functions/ogIsMounted | 23 +++++++ client/shared/functions/ogIsPartitionLocked | 23 +++++++ client/shared/functions/ogIsReadonly | 23 +++++++ client/shared/functions/ogIsVirtualMachine | 22 +++++++ client/shared/functions/ogIsWritable | 23 +++++++ client/shared/functions/ogLock | 23 +++++++ client/shared/functions/ogLockPartition | 23 +++++++ client/shared/functions/ogMakeDir | 32 ++++++++++ client/shared/functions/ogMount | 35 +++++++++++ client/shared/functions/ogMountCache | 22 +++++++ client/shared/functions/ogMountFs | 23 +++++++ client/shared/functions/ogRaiseError | 34 ++++++++++ client/shared/functions/ogRestoreImageSyntax | 25 ++++++++ client/shared/functions/ogSetPartitionActive | 23 +++++++ client/shared/functions/ogTypeToId | 23 +++++++ .../shared/functions/ogUninstallLinuxClient | 23 +++++++ client/shared/functions/ogUnlock | 23 +++++++ client/shared/functions/ogUnlockPartition | 23 +++++++ client/shared/functions/ogUnmount | 23 +++++++ client/shared/functions/ogUnmountCache | 22 +++++++ client/shared/functions/ogUnmountFs | 23 +++++++ 73 files changed, 1812 insertions(+), 28 deletions(-) create mode 100755 client/shared/functions/ogCalculateChecksum create mode 100755 client/shared/functions/ogCalculateFullChecksum create mode 100755 client/shared/functions/ogChangeRepo create mode 100755 client/shared/functions/ogCheckIpAddress create mode 100755 client/shared/functions/ogCleanLinuxDevices create mode 100755 client/shared/functions/ogCleanOs create mode 100755 client/shared/functions/ogConfigureFstab create mode 100755 client/shared/functions/ogConfigureOgagent create mode 100755 client/shared/functions/ogCopyFile create mode 100755 client/shared/functions/ogCreateImageSyntax create mode 100755 client/shared/functions/ogDeleteFile create mode 100755 client/shared/functions/ogDeleteTree create mode 100755 client/shared/functions/ogDevToDisk create mode 100755 client/shared/functions/ogDiskToDev create mode 100755 client/shared/functions/ogEcho create mode 100755 client/shared/functions/ogExecAndLog create mode 100755 client/shared/functions/ogFindCache create mode 100755 client/shared/functions/ogGetArch create mode 100755 client/shared/functions/ogGetCacheSize create mode 100755 client/shared/functions/ogGetCaller create mode 100755 client/shared/functions/ogGetFreeSize create mode 100755 client/shared/functions/ogGetFsSize create mode 100755 client/shared/functions/ogGetFsType create mode 100755 client/shared/functions/ogGetHostname create mode 100755 client/shared/functions/ogGetImageCompressor create mode 100755 client/shared/functions/ogGetImageInfo create mode 100755 client/shared/functions/ogGetImageProgram create mode 100755 client/shared/functions/ogGetImageSize create mode 100755 client/shared/functions/ogGetImageType create mode 100755 client/shared/functions/ogGetIpAddress create mode 100755 client/shared/functions/ogGetMacAddress create mode 100755 client/shared/functions/ogGetMountPoint create mode 100755 client/shared/functions/ogGetOsType create mode 100755 client/shared/functions/ogGetOsVersion create mode 100755 client/shared/functions/ogGetParentPath create mode 100755 client/shared/functions/ogGetPartitionActive create mode 100755 client/shared/functions/ogGetPartitionId create mode 100755 client/shared/functions/ogGetPartitionSize create mode 100755 client/shared/functions/ogGetPartitionTableType create mode 100755 client/shared/functions/ogGetPath create mode 100755 client/shared/functions/ogGetRepoIp create mode 100755 client/shared/functions/ogGetServerIp create mode 100755 client/shared/functions/ogGrubInstallPartition create mode 100755 client/shared/functions/ogHelp create mode 100755 client/shared/functions/ogIsEfiActive create mode 100755 client/shared/functions/ogIsFormated create mode 100755 client/shared/functions/ogIsImageLocked create mode 100755 client/shared/functions/ogIsLocked create mode 100755 client/shared/functions/ogIsMounted create mode 100755 client/shared/functions/ogIsPartitionLocked create mode 100755 client/shared/functions/ogIsReadonly create mode 100755 client/shared/functions/ogIsVirtualMachine create mode 100755 client/shared/functions/ogIsWritable create mode 100755 client/shared/functions/ogLock create mode 100755 client/shared/functions/ogLockPartition create mode 100755 client/shared/functions/ogMakeDir create mode 100755 client/shared/functions/ogMount create mode 100755 client/shared/functions/ogMountCache create mode 100755 client/shared/functions/ogMountFs create mode 100755 client/shared/functions/ogRaiseError create mode 100755 client/shared/functions/ogRestoreImageSyntax create mode 100755 client/shared/functions/ogSetPartitionActive create mode 100755 client/shared/functions/ogTypeToId create mode 100755 client/shared/functions/ogUninstallLinuxClient create mode 100755 client/shared/functions/ogUnlock create mode 100755 client/shared/functions/ogUnlockPartition create mode 100755 client/shared/functions/ogUnmount create mode 100755 client/shared/functions/ogUnmountCache create mode 100755 client/shared/functions/ogUnmountFs diff --git a/client/lib/engine/bin/BootLib.py b/client/lib/engine/bin/BootLib.py index 8966b8f..aab937e 100644 --- a/client/lib/engine/bin/BootLib.py +++ b/client/lib/engine/bin/BootLib.py @@ -554,13 +554,14 @@ def ogGrubInstallPartition (disk, par, checkos='FALSE', kernelparam=''): if os.path.exists (f'{secondstage}/boot/grub/grub.cfg{backupname}'): os.rename (f'{secondstage}/boot/grub/grub.cfg{backupname}', f'{secondstage}/boot/grub/grub.cfg') else: - os.rename (f'{secondstage}/boot/grub/grub.cfg', f'{secondstage}/boot/grub/grub.cfg{backupname}') + if (os.path.exists (f'{secondstage}/boot/grub/grub.cfg')): + os.rename (f'{secondstage}/boot/grub/grub.cfg', f'{secondstage}/boot/grub/grub.cfg{backupname}') with open ('/etc/default/grub', 'a') as fd: #Configur la sintaxis grub para evitar menus de "recovery" en el OGLive fd.write ('GRUB_DISABLE_RECOVERY="true"\n') fd.write ('GRUB_DISABLE_LINUX_UUID="true"\n') - os.makedirs (f'{secondstage}{prefixsecondstage}/boot/grub/') #Preparar configuración segunda etapa: crear ubicacion + os.makedirs (f'{secondstage}{prefixsecondstage}/boot/grub/', exist_ok=True) #Preparar configuración segunda etapa: crear ubicacion subprocess.run (['sed', '-i', 's/^set -e/#set -e/', '/etc/grub.d/00_header']) #Preparar configuración segunda etapa: crear cabecera del fichero (ingnorar errores) # (ogLive 5.0) Si 'pkgdatadir' está vacía ponemos valor de otros ogLive subprocess.run (['sed', '-i', r'/grub-mkconfig_lib/i\pkgdatadir=${pkgdatadir:-"${datarootdir}/grub"}', '/etc/grub.d/00_header']) diff --git a/client/lib/engine/bin/CacheLib.py b/client/lib/engine/bin/CacheLib.py index 99e543a..37246c9 100755 --- a/client/lib/engine/bin/CacheLib.py +++ b/client/lib/engine/bin/CacheLib.py @@ -11,6 +11,18 @@ import DiskLib import FileSystemLib import CacheLib +#/** +# ogCreateCache [int_ndisk] int_partsize +#@brief Define la caché local, por defecto en partición 4 del disco 1. +#@param int_ndisk numero de disco donde crear la cache, si no se indica es el 1 por defecto +#@param int_npart número de partición (opcional, 4 por defecto) +#@param int_partsize tamaño de la partición (en KB) +#@return (nada, por determinar) +#@exception OG_ERR_FORMAT formato incorrecto. +#@note Requisitos: sfdisk, parted, awk, sed +#@warning El tamaño de caché debe estar entre 50 MB y la mitad del disco. +#@warning La caché no puede solaparse con las particiones de datos. +#*/ ## def ogCreateCache(ndisk=1, npart=4, partsize=None): """ Define la caché local, por defecto en partición 4 del disco 1. @@ -41,6 +53,26 @@ def ogCreateCache(ndisk=1, npart=4, partsize=None): except subprocess.CalledProcessError as e: raise RuntimeError(f"Error al crear la caché: {e}") + +#/** +# ogDeleteCache +#@brief Elimina la partición de caché local. +#@return (nada, por determinar) +#@exception OG_ERR_FORMAT formato incorrecto. +#@note Requisitos: fdisk, sgdisk, partprobe +#@version 0.91 - Definición de caché local. +#@author Ramon Gomez, ETSII Universidad de Sevilla +#@date 2010/03/11 +#@version 1.0.4 - Soporte para discos GPT. +#@author Universidad de Huelva +#@date 2012/03/13 +#@version 1.0.6b - llamada correcta a ogUpdatePartitionTable +#@author Antonio Doblas Universidad de Málaga +#@date 2016/11/16 +#@version 1.1.0 - Sustituir "sfdisk" por "fdisk" para discos MSDOS. +#@author Ramon Gomez, ETSII Universidad de Sevilla +#@date 2016/05/25 +#*/ ## def ogDeleteCache(): """ Borra la partición utilizada para caché. @@ -113,7 +145,8 @@ def ogFormatCache(): SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_PARTITION, ogGlobals.lang.MSG_NOCACHE) return - disk = DiskLib.ogDiskToDev (cachepart) + cachepart = cachepart.split() + disk = DiskLib.ogDiskToDev (cachepart[0], cachepart[1]) if not disk: return ogUnmountCache() @@ -151,6 +184,12 @@ def ogGetCacheSize(): disk, par = cachepart.split() return DiskLib.ogGetPartitionSize (disk, par) +#/** +# ogGetCacheSpace +#@brief Devuelve el espacio de disco disponible para la partición de caché. +#@return int_size tamaño disponible (en KB) +#@note El espacio disponible es el que hay entre el límite superior de la partición 3 del disco 1 y el final de dicho disco, y no puede ser superior a la mitad de dicho disco. +#*/ ## def ogGetCacheSpace(): """ Obtiene el espacio libre en la partición de caché en kilobytes. @@ -218,16 +257,15 @@ def ogMountCache(): #@warning Salidas de errores no determinada #*/ ## def ogUnmountCache(): - cachepart = ogFindCache() + cachepart = ogFindCache().split() if cachepart is None: SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_PARTITION, ogGlobals.lang.MSG_NOCACHE) return - if not FileSystemLib.ogIsMounted (cachepart): return True - FileSystemLib.ogUnmountFs (cachepart) + if not FileSystemLib.ogIsMounted (cachepart[0], cachepart[1]): return True + FileSystemLib.ogUnmountFs (cachepart[0], cachepart[1]) # Eliminar el enlace simbólico de /mnt/ParticiónCache. - os.remove(f"/mnt/{cachepart}") - dev = ogDiskToDev (cachepart) - dev.replace ('dev', 'mnt') + dev = DiskLib.ogDiskToDev (cachepart[0], cachepart[1]) + dev = dev.replace ('dev', 'mnt') os.remove (dev) diff --git a/client/lib/engine/bin/FileLib.py b/client/lib/engine/bin/FileLib.py index bc8de5e..204bdce 100755 --- a/client/lib/engine/bin/FileLib.py +++ b/client/lib/engine/bin/FileLib.py @@ -396,6 +396,13 @@ def ogGetParentPath (src=None, file=None): else: return ogGetPath (src=src, file=os.path.dirname('/'+file)) +#/** +# ogIsNewerFile [ str_repo | int_ndisk int_npart ] path_source [ str_repo | int_ndisk int_npart ] path_target +#@brief Metafunción que indica se un fichero es más nuevo que otro. +#@see ogGetPath +#@return Código de salida: 0 - nuevo, 1 - antiguo o error +#@warning Deben existir tanto el fichero origen como el destino. +#*/ ## def ogIsNewerFile(*args): # Variables locales. ARGS = args @@ -438,6 +445,12 @@ def ogIsNewerFile(*args): # Devolver si el primer fichero se ha modificado después que el segundo. return os.path.getmtime(SOURCE) > os.path.getmtime(TARGET) +#/** +# ogMakeChecksumFile [ str_repo | int_ndisk int_npart ] path_filepath +#@brief Metafunción que guarda el valor de comprobación de un fichero. +#@see ogCalculateChecksum +#@warning Genera un fichero con extensión ".sum". +#*/ ## def ogMakeChecksumFile(*args): # Variables locales. FILE = None diff --git a/client/lib/engine/bin/SystemLib.py b/client/lib/engine/bin/SystemLib.py index 39d0d23..811ddcd 100755 --- a/client/lib/engine/bin/SystemLib.py +++ b/client/lib/engine/bin/SystemLib.py @@ -103,40 +103,27 @@ def ogExecAndLog (logtypes, fun, *args, **kwargs): # ## redirect stdout only # eval $COMMAND | tee -a $FILES - import time sout = serr = '' if 'command' in logtypes: os.unlink (ogGlobals.OGLOGCOMMAND) open (ogGlobals.OGLOGCOMMAND, 'w').close() - print ('nati: ogExecAndLog: about to redirect stdout and stderr') - time.sleep (1) ## nati with redirect_stdout (StringIO()) as r_stdout, redirect_stderr (StringIO()) as r_stderr: rc = fun (*args, **kwargs) sout = r_stdout.getvalue() serr = r_stderr.getvalue() - print (f'nati: ogExecAndLog: end of redirections, rc ({rc}) sout ({sout}) serr ({serr})') - time.sleep (1) ## nati else: - print ('nati: ogExecAndLog: about to redirect stdout only') - time.sleep (1) with redirect_stdout (StringIO()) as r_stdout: rc = fun (*args, **kwargs) sout = r_stdout.getvalue() - print (f'nati: ogExecAndLog: end of redirections, rc ({rc}) sout ({sout})') - time.sleep (1) ## nati - if sout or serr: - print ('nati: ogExecAndLog: sout or serr are true') - time.sleep (1) ## nati + rc_str = str (rc) + if sout or serr or ('True' != rc_str and 'False' != rc_str and 'None' != rc_str): for f in logfiles: - print (f'nati: ogExecAndLog: logging to logfile ({f})') with open (f, 'a') as fd: - if sout: fd.write (f"ogExecAndLog: {fun.__name__} stdout:\n{sout}") - else: fd.write (f"ogExecAndLog: {fun.__name__} stdout: (none)\n") - if serr: fd.write (f"ogExecAndLog: {fun.__name__} stderr:\n{serr}") - else: fd.write (f"ogExecAndLog: {fun.__name__} stderr: (none)\n") + if sout: fd.write (f'{sout}\n') + if serr: fd.write (f'{serr}\n') + if rc_str: fd.write (f'{rc_str}\n') - print (f'nati: ogExecAndLog: returning rc ({rc})') return rc #/** @@ -182,7 +169,11 @@ def ogGetCaller(): def ogHelp (fname, fmt=None, examples=[]): FUNC = fname or inspect.stack()[1][3] MSG = f'ogGlobals.lang.MSG_HELP_{FUNC}' - ogEcho ([], "help", f"{ogGlobals.lang.MSG_FUNCTION} {FUNC}: {eval (MSG)}") + try: + MSG = eval (MSG) + except: + MSG = '' + ogEcho ([], "help", f"{ogGlobals.lang.MSG_FUNCTION} {FUNC}: {MSG}") if fmt: ogEcho([], "help", f" {ogGlobals.lang.MSG_FORMAT}: {fmt}") @@ -258,6 +249,12 @@ def ogRaiseError (logtypes, code, msg): return code +#/** +# ogIsRepoLocked +#@brief Comprueba si el repositorio está siendo usado (tiene ficheros abiertos). +#@param No. +#@return Código de salida: 0 - bloqueado, 1 - sin bloquear o error. +#*/ def ogIsRepoLocked(): # Variables locales FILES = "" diff --git a/client/shared/functions/ogCalculateChecksum b/client/shared/functions/ogCalculateChecksum new file mode 100755 index 0000000..d55da2e --- /dev/null +++ b/client/shared/functions/ogCalculateChecksum @@ -0,0 +1,32 @@ +#!/usr/bin/python3 + +import sys +import argparse +from SystemLib import ogHelp +from FileLib import ogCalculateChecksum + +if 2 == len (sys.argv) and 'help' == sys.argv[1]: + #parser.print_help() sale en inglés aunque la locale indique otra cosa + ogHelp ('ogCalculateChecksum', 'ogCalculateChecksum [ str_repo | int_ndisk int_npartition ] path_filepath', ['ogCalculateChecksum REPO ubuntu.img']) + sys.exit (0) + +parser = argparse.ArgumentParser (add_help=False) +if 3 == len (sys.argv): + parser.add_argument ('container', nargs='?', default=None) + parser.add_argument ('file', nargs='?', default=None) +elif 4 == len (sys.argv): + parser.add_argument ('disk', nargs='?', default=None) + parser.add_argument ('par', nargs='?', default=None) + parser.add_argument ('file', nargs='?', default=None) + +args = parser.parse_args() + +if 3 == len (sys.argv): + ret = ogCalculateChecksum (container=args.container, file=args.file) +elif 4 == len (sys.argv): + ret = ogCalculateChecksum (container=f'{args.disk} {args.par}', file=args.file) + +if ret is not None: + if ret == True: sys.exit (0) + elif ret == False: sys.exit (1) + else: print (ret) diff --git a/client/shared/functions/ogCalculateFullChecksum b/client/shared/functions/ogCalculateFullChecksum new file mode 100755 index 0000000..f871f03 --- /dev/null +++ b/client/shared/functions/ogCalculateFullChecksum @@ -0,0 +1,32 @@ +#!/usr/bin/python3 + +import sys +import argparse +from SystemLib import ogHelp +from FileLib import ogCalculateFullChecksum + +if 2 == len (sys.argv) and 'help' == sys.argv[1]: + #parser.print_help() sale en inglés aunque la locale indique otra cosa + ogHelp ('ogCalculateFullChecksum', 'ogCalculateFullChecksum [ str_repo | int_ndisk int_npartition ] path_filepath', ['ogCalculateFullChecksum REPO ubuntu.img']) + sys.exit (0) + +parser = argparse.ArgumentParser (add_help=False) +if 3 == len (sys.argv): + parser.add_argument ('container', nargs='?', default=None) + parser.add_argument ('file', nargs='?', default=None) +elif 4 == len (sys.argv): + parser.add_argument ('disk', nargs='?', default=None) + parser.add_argument ('par', nargs='?', default=None) + parser.add_argument ('file', nargs='?', default=None) + +args = parser.parse_args() + +if 3 == len (sys.argv): + ret = ogCalculateFullChecksum (container=args.container, file=args.file) +elif 4 == len (sys.argv): + ret = ogCalculateFullChecksum (container=f'{args.disk} {args.par}', file=args.file) + +if ret is not None: + if ret == True: sys.exit (0) + elif ret == False: sys.exit (1) + else: print (ret) diff --git a/client/shared/functions/ogChangeRepo b/client/shared/functions/ogChangeRepo new file mode 100755 index 0000000..0a65304 --- /dev/null +++ b/client/shared/functions/ogChangeRepo @@ -0,0 +1,23 @@ +#!/usr/bin/python3 + +import sys +import argparse +from SystemLib import ogHelp +from NetLib import ogChangeRepo + +parser = argparse.ArgumentParser (add_help=False) +parser.add_argument ('ip_repo') +parser.add_argument ('og_unit', nargs='?', default=None) + +if 2 == len (sys.argv) and 'help' == sys.argv[1]: + #parser.print_help() sale en inglés aunque la locale indique otra cosa + ogHelp ('ogChangeRepo', 'ogChangeRepo IPREPO', ['ogChangeRepo 10.1.120.3']) + sys.exit (0) + +args = parser.parse_args() + +ret = ogChangeRepo (args.ip_repo, args.og_unit) +if ret is not None: + if ret == True: sys.exit (0) + elif ret == False: sys.exit (1) + else: print (ret) diff --git a/client/shared/functions/ogCheckIpAddress b/client/shared/functions/ogCheckIpAddress new file mode 100755 index 0000000..0e25310 --- /dev/null +++ b/client/shared/functions/ogCheckIpAddress @@ -0,0 +1,22 @@ +#!/usr/bin/python3 + +import sys +import argparse +from SystemLib import ogHelp +from StringLib import ogCheckIpAddress + +parser = argparse.ArgumentParser (add_help=False) +parser.add_argument ('ip') + +if 2 == len (sys.argv) and 'help' == sys.argv[1]: + #parser.print_help() sale en inglés aunque la locale indique otra cosa + ogHelp ('ogCheckIpAddress') + sys.exit (0) + +args = parser.parse_args() + +ret = ogCheckIpAddress (args.ip) +if ret is not None: + if ret == True: sys.exit (0) + elif ret == False: sys.exit (1) + else: print (ret) diff --git a/client/shared/functions/ogCleanLinuxDevices b/client/shared/functions/ogCleanLinuxDevices new file mode 100755 index 0000000..7603084 --- /dev/null +++ b/client/shared/functions/ogCleanLinuxDevices @@ -0,0 +1,23 @@ +#!/usr/bin/python3 + +import sys +import argparse +from SystemLib import ogHelp +from BootLib import ogCleanLinuxDevices + +parser = argparse.ArgumentParser (add_help=False) +parser.add_argument ('disk') +parser.add_argument ('par') + +if 2 == len (sys.argv) and 'help' == sys.argv[1]: + #parser.print_help() sale en inglés aunque la locale indique otra cosa + ogHelp ('ogCleanLinuxDevices', 'ogCleanLinuxDevices int_ndisk int_nfilesys', ['ogCleanLinuxDevices 1 1']) + sys.exit (0) + +args = parser.parse_args() + +ret = ogCleanLinuxDevices (args.disk, args.par) +if ret is not None: + if ret == True: sys.exit (0) + elif ret == False: sys.exit (1) + else: print (ret) diff --git a/client/shared/functions/ogCleanOs b/client/shared/functions/ogCleanOs new file mode 100755 index 0000000..e2309c6 --- /dev/null +++ b/client/shared/functions/ogCleanOs @@ -0,0 +1,23 @@ +#!/usr/bin/python3 + +import sys +import argparse +from SystemLib import ogHelp +from PostConfLib import ogCleanOs + +parser = argparse.ArgumentParser (add_help=False) +parser.add_argument ('disk') +parser.add_argument ('par') + +if 2 == len (sys.argv) and 'help' == sys.argv[1]: + #parser.print_help() sale en inglés aunque la locale indique otra cosa + ogHelp ('ogCleanOs', 'ogCleanOs int_ndisk int_nfilesys', ['ogCleanOs 1 1']) + sys.exit (0) + +args = parser.parse_args() + +ret = ogCleanOs (args.disk, args.par) +if ret is not None: + if ret == True: sys.exit (0) + elif ret == False: sys.exit (1) + else: print (ret) diff --git a/client/shared/functions/ogConfigureFstab b/client/shared/functions/ogConfigureFstab new file mode 100755 index 0000000..03d351d --- /dev/null +++ b/client/shared/functions/ogConfigureFstab @@ -0,0 +1,23 @@ +#!/usr/bin/python3 + +import sys +import argparse +from SystemLib import ogHelp +from BootLib import ogConfigureFstab + +parser = argparse.ArgumentParser (add_help=False) +parser.add_argument ('disk') +parser.add_argument ('par') + +if 2 == len (sys.argv) and 'help' == sys.argv[1]: + #parser.print_help() sale en inglés aunque la locale indique otra cosa + ogHelp ('ogConfigureFstab', 'ogConfigureFstab int_ndisk int_nfilesys', ['ogConfigureFstab 1 1']) + sys.exit (0) + +args = parser.parse_args() + +ret = ogConfigureFstab (args.disk, args.par) +if ret is not None: + if ret == True: sys.exit (0) + elif ret == False: sys.exit (1) + else: print (ret) diff --git a/client/shared/functions/ogConfigureOgagent b/client/shared/functions/ogConfigureOgagent new file mode 100755 index 0000000..7ed9fcd --- /dev/null +++ b/client/shared/functions/ogConfigureOgagent @@ -0,0 +1,23 @@ +#!/usr/bin/python3 + +import sys +import argparse +from SystemLib import ogHelp +from PostConfLib import ogConfigureOgagent + +parser = argparse.ArgumentParser (add_help=False) +parser.add_argument ('disk') +parser.add_argument ('par') + +if 2 == len (sys.argv) and 'help' == sys.argv[1]: + #parser.print_help() sale en inglés aunque la locale indique otra cosa + ogHelp ('ogConfigureOgagent', 'ogConfigureOgagent int_ndisk int_filesys', ['ogConfigureOgagent 1 1']) + sys.exit (0) + +args = parser.parse_args() + +ret = ogConfigureOgagent (args.disk, args.par) +if ret is not None: + if ret == True: sys.exit (0) + elif ret == False: sys.exit (1) + else: print (ret) diff --git a/client/shared/functions/ogCopyFile b/client/shared/functions/ogCopyFile new file mode 100755 index 0000000..04f1784 --- /dev/null +++ b/client/shared/functions/ogCopyFile @@ -0,0 +1,63 @@ +#!/usr/bin/python3 + +import sys +import argparse +from SystemLib import ogHelp +from FileLib import ogCopyFile + +if 2 == len (sys.argv) and 'help' == sys.argv[1]: + #parser.print_help() sale en inglés aunque la locale indique otra cosa + ogHelp ('ogCopyFile', 'ogCopyFile [ str_repo | int_ndisk int_npartition ] path_source [ str_repo | int_ndisk int_npartition ] path_target', ['ogCopyFile REPO newfile.txt 1 2 /tmp/newfile.txt']) + sys.exit (0) + +parser = argparse.ArgumentParser (add_help=False) +if 5 == len (sys.argv): + parser.add_argument ('src_container') + parser.add_argument ('src_file') + parser.add_argument ('dst_container') + parser.add_argument ('dst_file') + args = parser.parse_args() + src = { 'container': args.src_container, 'file': args.src_file } + dst = { 'container': args.dst_container, 'file': args.dst_file } +elif 7 == len (sys.argv): + parser.add_argument ('src_disk') + parser.add_argument ('src_par') + parser.add_argument ('src_file') + parser.add_argument ('dst_disk') + parser.add_argument ('dst_par') + parser.add_argument ('dst_file') + args = parser.parse_args() + src = { 'disk': args.src_disk, 'par': args.src_par, 'file': args.src_file } + dst = { 'disk': args.dst_disk, 'par': args.dst_par, 'file': args.dst_file } +elif 6 == len (sys.argv): + ## can be either: + ## - src_disk src_par src_file dst_container dst_file + ## - src_container src_file dst_disk dst_par dst_file + + try: + num = int (sys.argv[1]) ## raises ValueError if sys.argv[1] doesn't look like a number + ## "src_disk src_par src_file dst_container dst_file" + parser.add_argument ('src_disk') + parser.add_argument ('src_par') + parser.add_argument ('src_file') + parser.add_argument ('dst_container') + parser.add_argument ('dst_file') + args = parser.parse_args() + src = { 'disk': args.src_disk, 'par': args.src_par, 'file': args.src_file } + dst = { 'container': args.dst_container, 'file': args.dst_file } + except: + ## "src_container src_file dst_disk dst_par dst_file" + parser.add_argument ('src_container') + parser.add_argument ('src_file') + parser.add_argument ('dst_disk') + parser.add_argument ('dst_par') + parser.add_argument ('dst_file') + args = parser.parse_args() + src = { 'container': args.src_container, 'file': args.src_file } + dst = { 'disk': args.dst_disk, 'par': args.dst_par, 'file': args.dst_file } + +ret = ogCopyFile (src, dst) +if ret is not None: + if ret == True: sys.exit (0) + elif ret == False: sys.exit (1) + else: print (ret) diff --git a/client/shared/functions/ogCreateImageSyntax b/client/shared/functions/ogCreateImageSyntax new file mode 100755 index 0000000..bc3651b --- /dev/null +++ b/client/shared/functions/ogCreateImageSyntax @@ -0,0 +1,25 @@ +#!/usr/bin/python3 + +import sys +import argparse +from SystemLib import ogHelp +from ImageLib import ogCreateImageSyntax + +parser = argparse.ArgumentParser (add_help=False) +parser.add_argument ('dev') +parser.add_argument ('imgfile') +parser.add_argument ('tool', nargs='?', default='partclone') +parser.add_argument ('level', nargs='?', default='gzip') + +if 2 == len (sys.argv) and 'help' == sys.argv[1]: + #parser.print_help() sale en inglés aunque la locale indique otra cosa + ogHelp ('ogCreateImageSyntax', 'ogCreateImageSyntax path_device path_imagefile [str_tool] [str_compressionlevel]', ['ogCreateImageSyntax /dev/sda1 /opt/opengnsys/images/prueba.img partclone lzop', 'ogCreateImageSyntax /dev/sda1 /opt/opengnsys/images/prueba.img']) + sys.exit (0) + +args = parser.parse_args() + +ret = ogCreateImageSyntax (args.dev, args.imgfile, args.tool, args.level) +if ret is not None: + if ret == True: sys.exit (0) + elif ret == False: sys.exit (1) + else: print (ret) diff --git a/client/shared/functions/ogDeleteFile b/client/shared/functions/ogDeleteFile new file mode 100755 index 0000000..32d4763 --- /dev/null +++ b/client/shared/functions/ogDeleteFile @@ -0,0 +1,32 @@ +#!/usr/bin/python3 + +import sys +import argparse +from SystemLib import ogHelp +from FileLib import ogDeleteFile + +if 2 == len (sys.argv) and 'help' == sys.argv[1]: + #parser.print_help() sale en inglés aunque la locale indique otra cosa + ogHelp ('ogDeleteFile', 'ogDeleteFile [ str_repo | int_ndisk int_npartition ] path_file', ['ogDeleteFile 1 2 /tmp/newfile.txt']) + sys.exit (0) + +parser = argparse.ArgumentParser (add_help=False) +if 3 == len (sys.argv): + parser.add_argument ('container', nargs='?', default=None) + parser.add_argument ('file', nargs='?', default=None) +elif 4 == len (sys.argv): + parser.add_argument ('disk', nargs='?', default=None) + parser.add_argument ('par', nargs='?', default=None) + parser.add_argument ('file', nargs='?', default=None) + +args = parser.parse_args() + +if 3 == len (sys.argv): + ret = ogDeleteFile (container=args.container, file=args.file) +elif 4 == len (sys.argv): + ret = ogDeleteFile (container=f'{args.disk} {args.par}', file=args.file) + +if ret is not None: + if ret == True: sys.exit (0) + elif ret == False: sys.exit (1) + else: print (ret) diff --git a/client/shared/functions/ogDeleteTree b/client/shared/functions/ogDeleteTree new file mode 100755 index 0000000..527b1a5 --- /dev/null +++ b/client/shared/functions/ogDeleteTree @@ -0,0 +1,32 @@ +#!/usr/bin/python3 + +import sys +import argparse +from SystemLib import ogHelp +from FileLib import ogDeleteTree + +if 2 == len (sys.argv) and 'help' == sys.argv[1]: + #parser.print_help() sale en inglés aunque la locale indique otra cosa + ogHelp ('ogDeleteTree', 'ogDeleteTree [ str_repo | int_ndisk int_npartition ] path_dir', ['ogDeleteTree 1 2 /tmp/newdir']) + sys.exit (0) + +parser = argparse.ArgumentParser (add_help=False) +if 3 == len (sys.argv): + parser.add_argument ('container', nargs='?', default=None) + parser.add_argument ('file', nargs='?', default=None) +elif 4 == len (sys.argv): + parser.add_argument ('disk', nargs='?', default=None) + parser.add_argument ('par', nargs='?', default=None) + parser.add_argument ('file', nargs='?', default=None) + +args = parser.parse_args() + +if 3 == len (sys.argv): + ret = ogDeleteTree (container=args.container, file=args.file) +elif 4 == len (sys.argv): + ret = ogDeleteTree (container=f'{args.disk} {args.par}', file=args.file) + +if ret is not None: + if ret == True: sys.exit (0) + elif ret == False: sys.exit (1) + else: print (ret) diff --git a/client/shared/functions/ogDevToDisk b/client/shared/functions/ogDevToDisk new file mode 100755 index 0000000..b3d6fea --- /dev/null +++ b/client/shared/functions/ogDevToDisk @@ -0,0 +1,22 @@ +#!/usr/bin/python3 + +import sys +import argparse +from SystemLib import ogHelp +from DiskLib import ogDevToDisk + +parser = argparse.ArgumentParser (add_help=False) +parser.add_argument ('arg_dev') + +if 2 == len (sys.argv) and 'help' == sys.argv[1]: + #parser.print_help() sale en inglés aunque la locale indique otra cosa + ogHelp ('ogDevToDisk', 'ogDevToDisk path_device | LABEL=str_label | UUID=str_uuid', ['ogDevToDisk /dev/sda', 'ogDevToDisk /dev/sda1', 'ogDevToDisk LABEL=CACHE']) + sys.exit (0) + +args = parser.parse_args() + +ret = ogDevToDisk (args.arg_dev) +if ret is not None: + if ret == True: sys.exit (0) + elif ret == False: sys.exit (1) + else: print (ret) diff --git a/client/shared/functions/ogDiskToDev b/client/shared/functions/ogDiskToDev new file mode 100755 index 0000000..d12736d --- /dev/null +++ b/client/shared/functions/ogDiskToDev @@ -0,0 +1,23 @@ +#!/usr/bin/python3 + +import sys +import argparse +from SystemLib import ogHelp +from DiskLib import ogDiskToDev + +parser = argparse.ArgumentParser (add_help=False) +parser.add_argument ('arg_disk', nargs='?', default=None) +parser.add_argument ('arg_part', nargs='?', default=None) + +if 2 == len (sys.argv) and 'help' == sys.argv[1]: + #parser.print_help() sale en inglés aunque la locale indique otra cosa + ogHelp ('ogDiskToDev', 'ogDiskToDev int_ndisk [int_npartition]', ['ogDiskToDev', 'ogDiskToDev 1', 'ogDiskToDev 1 1']) + sys.exit (0) + +args = parser.parse_args() + +ret = ogDiskToDev (args.arg_disk, args.arg_part) +if ret is not None: + if ret == True: sys.exit (0) + elif ret == False: sys.exit (1) + else: print (ret) diff --git a/client/shared/functions/ogEcho b/client/shared/functions/ogEcho new file mode 100755 index 0000000..14d8bf5 --- /dev/null +++ b/client/shared/functions/ogEcho @@ -0,0 +1,24 @@ +#!/usr/bin/python3 + +import sys +import argparse +from SystemLib import ogHelp +from SystemLib import ogEcho + +parser = argparse.ArgumentParser (add_help=False) +parser.add_argument ('logtypes') +parser.add_argument ('loglevel') +parser.add_argument ('msg') + +if 2 == len (sys.argv) and 'help' == sys.argv[1]: + #parser.print_help() sale en inglés aunque la locale indique otra cosa + ogHelp ('ogEcho') + sys.exit (0) + +args = parser.parse_args() + +ret = ogEcho (args.logtypes, args.loglevel, args.msg) +if ret is not None: + if ret == True: sys.exit (0) + elif ret == False: sys.exit (1) + else: print (ret) diff --git a/client/shared/functions/ogExecAndLog b/client/shared/functions/ogExecAndLog new file mode 100755 index 0000000..977f6b4 --- /dev/null +++ b/client/shared/functions/ogExecAndLog @@ -0,0 +1,53 @@ +#!/usr/bin/python3 + +import sys +## lo siento, pero tiene que ser así +from BootLib import * +from CacheLib import * +from DiskLib import * +from FileLib import * +from FileSystemLib import * +from ImageLib import * +from InventoryLib import * +from NetLib import * +from PostConfLib import * +from ProtocolLib import * +from RegistryLib import * +from StringLib import * +from SystemLib import * +from UEFILib import * + +if 2 == len (sys.argv) and 'help' == sys.argv[1]: + #parser.print_help() sale en inglés aunque la locale indique otra cosa + ogHelp ('ogExecAndLog', 'ogExecAndLog str_logfile ... str_command ...', ['ogExecAndLog COMMAND ls -al /']) + sys.exit (0) + +logtypes = [] +while True: + if sys.argv[1] in ['command', 'log', 'session']: + logtypes.append (sys.argv.pop (1)) + else: break + +fun_name = sys.argv.pop (1) +try: + fun = locals()[fun_name] +except KeyError: + print (f'not implemented: {fun_name}') + sys.exit (1) + +args = [] +kwargs = {} +for arg in sys.argv[1:]: + if '=' in arg: + k, v = arg.split ('=') + kwargs[k] = v + else: + args.append (arg) + +## args has to be a tuple +args = tuple (args) + +ret = ogExecAndLog (logtypes, fun, *args, **kwargs) +if ret is not None: + if ret == True: sys.exit (0) + elif ret == False: sys.exit (1) diff --git a/client/shared/functions/ogFindCache b/client/shared/functions/ogFindCache new file mode 100755 index 0000000..181872d --- /dev/null +++ b/client/shared/functions/ogFindCache @@ -0,0 +1,22 @@ +#!/usr/bin/python3 + +import sys +import argparse +from SystemLib import ogHelp +from CacheLib import ogFindCache + +parser = argparse.ArgumentParser (add_help=False) + + +if 2 == len (sys.argv) and 'help' == sys.argv[1]: + #parser.print_help() sale en inglés aunque la locale indique otra cosa + ogHelp ('ogFindCache', 'ogFindCache') + sys.exit (0) + +args = parser.parse_args() + +ret = ogFindCache () +if ret is not None: + if ret == True: sys.exit (0) + elif ret == False: sys.exit (1) + else: print (ret) diff --git a/client/shared/functions/ogGetArch b/client/shared/functions/ogGetArch new file mode 100755 index 0000000..bf24319 --- /dev/null +++ b/client/shared/functions/ogGetArch @@ -0,0 +1,22 @@ +#!/usr/bin/python3 + +import sys +import argparse +from SystemLib import ogHelp +from InventoryLib import ogGetArch + +parser = argparse.ArgumentParser (add_help=False) + + +if 2 == len (sys.argv) and 'help' == sys.argv[1]: + #parser.print_help() sale en inglés aunque la locale indique otra cosa + ogHelp ('ogGetArch') + sys.exit (0) + +args = parser.parse_args() + +ret = ogGetArch () +if ret is not None: + if ret == True: sys.exit (0) + elif ret == False: sys.exit (1) + else: print (ret) diff --git a/client/shared/functions/ogGetCacheSize b/client/shared/functions/ogGetCacheSize new file mode 100755 index 0000000..51a73dc --- /dev/null +++ b/client/shared/functions/ogGetCacheSize @@ -0,0 +1,22 @@ +#!/usr/bin/python3 + +import sys +import argparse +from SystemLib import ogHelp +from CacheLib import ogGetCacheSize + +parser = argparse.ArgumentParser (add_help=False) + + +if 2 == len (sys.argv) and 'help' == sys.argv[1]: + #parser.print_help() sale en inglés aunque la locale indique otra cosa + ogHelp ('ogGetCacheSize', 'ogGetCacheSize') + sys.exit (0) + +args = parser.parse_args() + +ret = ogGetCacheSize () +if ret is not None: + if ret == True: sys.exit (0) + elif ret == False: sys.exit (1) + else: print (ret) diff --git a/client/shared/functions/ogGetCaller b/client/shared/functions/ogGetCaller new file mode 100755 index 0000000..2147fb2 --- /dev/null +++ b/client/shared/functions/ogGetCaller @@ -0,0 +1,22 @@ +#!/usr/bin/python3 + +import sys +import argparse +from SystemLib import ogHelp +from SystemLib import ogGetCaller + +parser = argparse.ArgumentParser (add_help=False) + + +if 2 == len (sys.argv) and 'help' == sys.argv[1]: + #parser.print_help() sale en inglés aunque la locale indique otra cosa + ogHelp ('ogGetCaller') + sys.exit (0) + +args = parser.parse_args() + +ret = ogGetCaller () +if ret is not None: + if ret == True: sys.exit (0) + elif ret == False: sys.exit (1) + else: print (ret) diff --git a/client/shared/functions/ogGetFreeSize b/client/shared/functions/ogGetFreeSize new file mode 100755 index 0000000..5f1899e --- /dev/null +++ b/client/shared/functions/ogGetFreeSize @@ -0,0 +1,24 @@ +#!/usr/bin/python3 + +import sys +import argparse +from SystemLib import ogHelp +from FileSystemLib import ogGetFreeSize + +parser = argparse.ArgumentParser (add_help=False) +parser.add_argument ('disk') +parser.add_argument ('part') +parser.add_argument ('unit', nargs='?', default='KB') + +if 2 == len (sys.argv) and 'help' == sys.argv[1]: + #parser.print_help() sale en inglés aunque la locale indique otra cosa + ogHelp ('ogGetFreeSize', 'ogGetFreeSize int_disco int_partition str_SizeOutput [ kB MB GB ]', ['ogGetFreeSize 1 1 MB']) + sys.exit (0) + +args = parser.parse_args() + +ret = ogGetFreeSize (args.disk, args.part, args.unit) +if ret is not None: + if ret == True: sys.exit (0) + elif ret == False: sys.exit (1) + else: print (ret) diff --git a/client/shared/functions/ogGetFsSize b/client/shared/functions/ogGetFsSize new file mode 100755 index 0000000..9227810 --- /dev/null +++ b/client/shared/functions/ogGetFsSize @@ -0,0 +1,24 @@ +#!/usr/bin/python3 + +import sys +import argparse +from SystemLib import ogHelp +from FileSystemLib import ogGetFsSize + +parser = argparse.ArgumentParser (add_help=False) +parser.add_argument ('disk') +parser.add_argument ('par') +parser.add_argument ('unit', nargs='?', default='KB') + +if 2 == len (sys.argv) and 'help' == sys.argv[1]: + #parser.print_help() sale en inglés aunque la locale indique otra cosa + ogHelp ('ogGetFsSize', 'ogGetFsSize int_ndisk int_npartition [str_unit]', ['ogGetFsSize 1 1', 'ogGetFsSize 1 1 KB']) + sys.exit (0) + +args = parser.parse_args() + +ret = ogGetFsSize (args.disk, args.par, args.unit) +if ret is not None: + if ret == True: sys.exit (0) + elif ret == False: sys.exit (1) + else: print (ret) diff --git a/client/shared/functions/ogGetFsType b/client/shared/functions/ogGetFsType new file mode 100755 index 0000000..d89b09f --- /dev/null +++ b/client/shared/functions/ogGetFsType @@ -0,0 +1,23 @@ +#!/usr/bin/python3 + +import sys +import argparse +from SystemLib import ogHelp +from FileSystemLib import ogGetFsType + +parser = argparse.ArgumentParser (add_help=False) +parser.add_argument ('disk') +parser.add_argument ('part') + +if 2 == len (sys.argv) and 'help' == sys.argv[1]: + #parser.print_help() sale en inglés aunque la locale indique otra cosa + ogHelp ('ogGetFsType', 'ogGetFsType int_ndisk int_nfilesys', ['ogGetFsType 1 1']) + sys.exit (0) + +args = parser.parse_args() + +ret = ogGetFsType (args.disk, args.part) +if ret is not None: + if ret == True: sys.exit (0) + elif ret == False: sys.exit (1) + else: print (ret) diff --git a/client/shared/functions/ogGetHostname b/client/shared/functions/ogGetHostname new file mode 100755 index 0000000..d042a3c --- /dev/null +++ b/client/shared/functions/ogGetHostname @@ -0,0 +1,22 @@ +#!/usr/bin/python3 + +import sys +import argparse +from SystemLib import ogHelp +from NetLib import ogGetHostname + +parser = argparse.ArgumentParser (add_help=False) + + +if 2 == len (sys.argv) and 'help' == sys.argv[1]: + #parser.print_help() sale en inglés aunque la locale indique otra cosa + ogHelp ('ogGetHostname') + sys.exit (0) + +args = parser.parse_args() + +ret = ogGetHostname () +if ret is not None: + if ret == True: sys.exit (0) + elif ret == False: sys.exit (1) + else: print (ret) diff --git a/client/shared/functions/ogGetImageCompressor b/client/shared/functions/ogGetImageCompressor new file mode 100755 index 0000000..7b21fb3 --- /dev/null +++ b/client/shared/functions/ogGetImageCompressor @@ -0,0 +1,23 @@ +#!/usr/bin/python3 + +import sys +import argparse +from SystemLib import ogHelp +from ImageLib import ogGetImageCompressor + +parser = argparse.ArgumentParser (add_help=False) +parser.add_argument ('container') +parser.add_argument ('filename') + +if 2 == len (sys.argv) and 'help' == sys.argv[1]: + #parser.print_help() sale en inglés aunque la locale indique otra cosa + ogHelp ('ogGetImageCompressor', 'ogGetImageCompressor str_repo path_image', ['ogGetImageCompressor REPO prueba']) + sys.exit (0) + +args = parser.parse_args() + +ret = ogGetImageCompressor (args.container, args.filename) +if ret is not None: + if ret == True: sys.exit (0) + elif ret == False: sys.exit (1) + else: print (ret) diff --git a/client/shared/functions/ogGetImageInfo b/client/shared/functions/ogGetImageInfo new file mode 100755 index 0000000..f227f2c --- /dev/null +++ b/client/shared/functions/ogGetImageInfo @@ -0,0 +1,22 @@ +#!/usr/bin/python3 + +import sys +import argparse +from SystemLib import ogHelp +from ImageLib import ogGetImageInfo + +parser = argparse.ArgumentParser (add_help=False) +parser.add_argument ('imgfile') + +if 2 == len (sys.argv) and 'help' == sys.argv[1]: + #parser.print_help() sale en inglés aunque la locale indique otra cosa + ogHelp ('ogGetImageInfo', 'ogGetImageInfo path_filename', ['ogGetImageInfo /opt/opengnsys/images/prueba.img']) + sys.exit (0) + +args = parser.parse_args() + +ret = ogGetImageInfo (args.imgfile) +if ret is not None: + if ret == True: sys.exit (0) + elif ret == False: sys.exit (1) + else: print (ret) diff --git a/client/shared/functions/ogGetImageProgram b/client/shared/functions/ogGetImageProgram new file mode 100755 index 0000000..80b2a15 --- /dev/null +++ b/client/shared/functions/ogGetImageProgram @@ -0,0 +1,23 @@ +#!/usr/bin/python3 + +import sys +import argparse +from SystemLib import ogHelp +from ImageLib import ogGetImageProgram + +parser = argparse.ArgumentParser (add_help=False) +parser.add_argument ('container') +parser.add_argument ('filename') + +if 2 == len (sys.argv) and 'help' == sys.argv[1]: + #parser.print_help() sale en inglés aunque la locale indique otra cosa + ogHelp ('ogGetImageProgram', 'ogGetImageProgram str_repo path_image', ['ogGetImageProgram REPO prueba']) + sys.exit (0) + +args = parser.parse_args() + +ret = ogGetImageProgram (args.container, args.filename) +if ret is not None: + if ret == True: sys.exit (0) + elif ret == False: sys.exit (1) + else: print (ret) diff --git a/client/shared/functions/ogGetImageSize b/client/shared/functions/ogGetImageSize new file mode 100755 index 0000000..da45ec8 --- /dev/null +++ b/client/shared/functions/ogGetImageSize @@ -0,0 +1,23 @@ +#!/usr/bin/python3 + +import sys +import argparse +from SystemLib import ogHelp +from ImageLib import ogGetImageSize + +parser = argparse.ArgumentParser (add_help=False) +parser.add_argument ('repo') +parser.add_argument ('imgname') + +if 2 == len (sys.argv) and 'help' == sys.argv[1]: + #parser.print_help() sale en inglés aunque la locale indique otra cosa + ogHelp ('ogGetImageSize', 'ogGetImageSize str_repo path_image', ['ogGetImageSize REPO prueba']) + sys.exit (0) + +args = parser.parse_args() + +ret = ogGetImageSize (args.repo, args.imgname) +if ret is not None: + if ret == True: sys.exit (0) + elif ret == False: sys.exit (1) + else: print (ret) diff --git a/client/shared/functions/ogGetImageType b/client/shared/functions/ogGetImageType new file mode 100755 index 0000000..304f030 --- /dev/null +++ b/client/shared/functions/ogGetImageType @@ -0,0 +1,23 @@ +#!/usr/bin/python3 + +import sys +import argparse +from SystemLib import ogHelp +from ImageLib import ogGetImageType + +parser = argparse.ArgumentParser (add_help=False) +parser.add_argument ('repo') +parser.add_argument ('imgname') + +if 2 == len (sys.argv) and 'help' == sys.argv[1]: + #parser.print_help() sale en inglés aunque la locale indique otra cosa + ogHelp ('ogGetImageType', 'ogGetImageType str_repo path_image', ['ogGetImageType REPO prueba']) + sys.exit (0) + +args = parser.parse_args() + +ret = ogGetImageType (args.repo, args.imgname) +if ret is not None: + if ret == True: sys.exit (0) + elif ret == False: sys.exit (1) + else: print (ret) diff --git a/client/shared/functions/ogGetIpAddress b/client/shared/functions/ogGetIpAddress new file mode 100755 index 0000000..4a3e976 --- /dev/null +++ b/client/shared/functions/ogGetIpAddress @@ -0,0 +1,22 @@ +#!/usr/bin/python3 + +import sys +import argparse +from SystemLib import ogHelp +from NetLib import ogGetIpAddress + +parser = argparse.ArgumentParser (add_help=False) + + +if 2 == len (sys.argv) and 'help' == sys.argv[1]: + #parser.print_help() sale en inglés aunque la locale indique otra cosa + ogHelp ('ogGetIpAddress') + sys.exit (0) + +args = parser.parse_args() + +ret = ogGetIpAddress () +if ret is not None: + if ret == True: sys.exit (0) + elif ret == False: sys.exit (1) + else: print (ret) diff --git a/client/shared/functions/ogGetMacAddress b/client/shared/functions/ogGetMacAddress new file mode 100755 index 0000000..b3585f4 --- /dev/null +++ b/client/shared/functions/ogGetMacAddress @@ -0,0 +1,22 @@ +#!/usr/bin/python3 + +import sys +import argparse +from SystemLib import ogHelp +from NetLib import ogGetMacAddress + +parser = argparse.ArgumentParser (add_help=False) + + +if 2 == len (sys.argv) and 'help' == sys.argv[1]: + #parser.print_help() sale en inglés aunque la locale indique otra cosa + ogHelp ('ogGetMacAddress') + sys.exit (0) + +args = parser.parse_args() + +ret = ogGetMacAddress () +if ret is not None: + if ret == True: sys.exit (0) + elif ret == False: sys.exit (1) + else: print (ret) diff --git a/client/shared/functions/ogGetMountPoint b/client/shared/functions/ogGetMountPoint new file mode 100755 index 0000000..9cb0625 --- /dev/null +++ b/client/shared/functions/ogGetMountPoint @@ -0,0 +1,23 @@ +#!/usr/bin/python3 + +import sys +import argparse +from SystemLib import ogHelp +from FileSystemLib import ogGetMountPoint + +parser = argparse.ArgumentParser (add_help=False) +parser.add_argument ('disk') +parser.add_argument ('par') + +if 2 == len (sys.argv) and 'help' == sys.argv[1]: + #parser.print_help() sale en inglés aunque la locale indique otra cosa + ogHelp ('ogGetMountPoint', 'ogGetMountPoint int_ndisk int_nfilesys', ['ogGetMountPoint 1 1']) + sys.exit (0) + +args = parser.parse_args() + +ret = ogGetMountPoint (args.disk, args.par) +if ret is not None: + if ret == True: sys.exit (0) + elif ret == False: sys.exit (1) + else: print (ret) diff --git a/client/shared/functions/ogGetOsType b/client/shared/functions/ogGetOsType new file mode 100755 index 0000000..77a6f29 --- /dev/null +++ b/client/shared/functions/ogGetOsType @@ -0,0 +1,23 @@ +#!/usr/bin/python3 + +import sys +import argparse +from SystemLib import ogHelp +from InventoryLib import ogGetOsType + +parser = argparse.ArgumentParser (add_help=False) +parser.add_argument ('disk') +parser.add_argument ('partition') + +if 2 == len (sys.argv) and 'help' == sys.argv[1]: + #parser.print_help() sale en inglés aunque la locale indique otra cosa + ogHelp ('ogGetOsType', 'ogGetOsType int_ndisk int_npartition', ['ogGetOsType 1 2']) + sys.exit (0) + +args = parser.parse_args() + +ret = ogGetOsType (args.disk, args.partition) +if ret is not None: + if ret == True: sys.exit (0) + elif ret == False: sys.exit (1) + else: print (ret) diff --git a/client/shared/functions/ogGetOsVersion b/client/shared/functions/ogGetOsVersion new file mode 100755 index 0000000..a91fec6 --- /dev/null +++ b/client/shared/functions/ogGetOsVersion @@ -0,0 +1,23 @@ +#!/usr/bin/python3 + +import sys +import argparse +from SystemLib import ogHelp +from InventoryLib import ogGetOsVersion + +parser = argparse.ArgumentParser (add_help=False) +parser.add_argument ('disk') +parser.add_argument ('part') + +if 2 == len (sys.argv) and 'help' == sys.argv[1]: + #parser.print_help() sale en inglés aunque la locale indique otra cosa + ogHelp ('ogGetOsVersion', 'ogGetOsVersion int_ndisk int_nfilesys', ['ogGetOsVersion 1 2']) + sys.exit (0) + +args = parser.parse_args() + +ret = ogGetOsVersion (args.disk, args.part) +if ret is not None: + if ret == True: sys.exit (0) + elif ret == False: sys.exit (1) + else: print (ret) diff --git a/client/shared/functions/ogGetParentPath b/client/shared/functions/ogGetParentPath new file mode 100755 index 0000000..3051970 --- /dev/null +++ b/client/shared/functions/ogGetParentPath @@ -0,0 +1,32 @@ +#!/usr/bin/python3 + +import sys +import argparse +from SystemLib import ogHelp +from FileLib import ogGetParentPath + +if 2 == len (sys.argv) and 'help' == sys.argv[1]: + #parser.print_help() sale en inglés aunque la locale indique otra cosa + ogHelp ('ogGetParentPath', 'ogGetParentPath [ str_repo | int_ndisk int_npartition ] path_filepath', ['ogGetParentPath /mnt/sda1/windows/system32', 'ogGetPath REPO /etc/fstab', 'ogGetPath 1 1 /windows/system32']) + sys.exit (0) + +parser = argparse.ArgumentParser (add_help=False) +if 3 == len (sys.argv): + parser.add_argument ('src', nargs='?', default=None) + parser.add_argument ('file', nargs='?', default=None) +elif 4 == len (sys.argv): + parser.add_argument ('disk', nargs='?', default=None) + parser.add_argument ('par', nargs='?', default=None) + parser.add_argument ('file', nargs='?', default=None) + +args = parser.parse_args() + +if 3 == len (sys.argv): + ret = ogGetParentPath (src=args.src, file=args.file) +elif 4 == len (sys.argv): + ret = ogGetParentPath (src=f'{args.disk} {args.par}', file=args.file) + +if ret is not None: + if ret == True: sys.exit (0) + elif ret == False: sys.exit (1) + else: print (ret) diff --git a/client/shared/functions/ogGetPartitionActive b/client/shared/functions/ogGetPartitionActive new file mode 100755 index 0000000..ce516bc --- /dev/null +++ b/client/shared/functions/ogGetPartitionActive @@ -0,0 +1,22 @@ +#!/usr/bin/python3 + +import sys +import argparse +from SystemLib import ogHelp +from DiskLib import ogGetPartitionActive + +parser = argparse.ArgumentParser (add_help=False) +parser.add_argument ('disk') + +if 2 == len (sys.argv) and 'help' == sys.argv[1]: + #parser.print_help() sale en inglés aunque la locale indique otra cosa + ogHelp ('ogGetPartitionActive', 'ogGetPartitionActive int_ndisk', ['ogGetPartitionActive 1']) + sys.exit (0) + +args = parser.parse_args() + +ret = ogGetPartitionActive (args.disk) +if ret is not None: + if ret == True: sys.exit (0) + elif ret == False: sys.exit (1) + else: print (ret) diff --git a/client/shared/functions/ogGetPartitionId b/client/shared/functions/ogGetPartitionId new file mode 100755 index 0000000..dfcae9b --- /dev/null +++ b/client/shared/functions/ogGetPartitionId @@ -0,0 +1,23 @@ +#!/usr/bin/python3 + +import sys +import argparse +from SystemLib import ogHelp +from DiskLib import ogGetPartitionId + +parser = argparse.ArgumentParser (add_help=False) +parser.add_argument ('disk') +parser.add_argument ('par') + +if 2 == len (sys.argv) and 'help' == sys.argv[1]: + #parser.print_help() sale en inglés aunque la locale indique otra cosa + ogHelp ('ogGetPartitionId', 'ogGetPartitionId int_ndisk int_npartition', ['ogGetPartitionId 1 1']) + sys.exit (0) + +args = parser.parse_args() + +ret = ogGetPartitionId (args.disk, args.par) +if ret is not None: + if ret == True: sys.exit (0) + elif ret == False: sys.exit (1) + else: print (ret) diff --git a/client/shared/functions/ogGetPartitionSize b/client/shared/functions/ogGetPartitionSize new file mode 100755 index 0000000..0ea7767 --- /dev/null +++ b/client/shared/functions/ogGetPartitionSize @@ -0,0 +1,23 @@ +#!/usr/bin/python3 + +import sys +import argparse +from SystemLib import ogHelp +from DiskLib import ogGetPartitionSize + +parser = argparse.ArgumentParser (add_help=False) +parser.add_argument ('disk') +parser.add_argument ('par') + +if 2 == len (sys.argv) and 'help' == sys.argv[1]: + #parser.print_help() sale en inglés aunque la locale indique otra cosa + ogHelp ('ogGetPartitionSize', 'ogGetPartitionSize int_ndisk int_npartition', ['ogGetPartitionSize 1 1']) + sys.exit (0) + +args = parser.parse_args() + +ret = ogGetPartitionSize (args.disk, args.par) +if ret is not None: + if ret == True: sys.exit (0) + elif ret == False: sys.exit (1) + else: print (ret) diff --git a/client/shared/functions/ogGetPartitionTableType b/client/shared/functions/ogGetPartitionTableType new file mode 100755 index 0000000..262ad62 --- /dev/null +++ b/client/shared/functions/ogGetPartitionTableType @@ -0,0 +1,22 @@ +#!/usr/bin/python3 + +import sys +import argparse +from SystemLib import ogHelp +from DiskLib import ogGetPartitionTableType + +parser = argparse.ArgumentParser (add_help=False) +parser.add_argument ('disk') + +if 2 == len (sys.argv) and 'help' == sys.argv[1]: + #parser.print_help() sale en inglés aunque la locale indique otra cosa + ogHelp ('ogGetPartitionTableType', 'ogGetPartitionTableType int_ndisk', ['ogGetPartitionTableType 1']) + sys.exit (0) + +args = parser.parse_args() + +ret = ogGetPartitionTableType (args.disk) +if ret is not None: + if ret == True: sys.exit (0) + elif ret == False: sys.exit (1) + else: print (ret) diff --git a/client/shared/functions/ogGetPath b/client/shared/functions/ogGetPath new file mode 100755 index 0000000..457b448 --- /dev/null +++ b/client/shared/functions/ogGetPath @@ -0,0 +1,32 @@ +#!/usr/bin/python3 + +import sys +import argparse +from SystemLib import ogHelp +from FileLib import ogGetPath + +if 2 == len (sys.argv) and 'help' == sys.argv[1]: + #parser.print_help() sale en inglés aunque la locale indique otra cosa + ogHelp ('ogGetPath', 'ogGetPath [ str_repo | int_ndisk int_npartition ] path_filepath', ['ogGetPath /mnt/sda1/windows/system32', 'ogGetPath REPO /etc/fstab', 'ogGetPath 1 1 /windows/system32']) + sys.exit (0) + +parser = argparse.ArgumentParser (add_help=False) +if 3 == len (sys.argv): + parser.add_argument ('src', nargs='?', default=None) + parser.add_argument ('file', nargs='?', default=None) +elif 4 == len (sys.argv): + parser.add_argument ('disk', nargs='?', default=None) + parser.add_argument ('par', nargs='?', default=None) + parser.add_argument ('file', nargs='?', default=None) + +args = parser.parse_args() + +if 3 == len (sys.argv): + ret = ogGetPath (src=args.src, file=args.file) +elif 4 == len (sys.argv): + ret = ogGetPath (src=f'{args.disk} {args.par}', file=args.file) + +if ret is not None: + if ret == True: sys.exit (0) + elif ret == False: sys.exit (1) + else: print (ret) diff --git a/client/shared/functions/ogGetRepoIp b/client/shared/functions/ogGetRepoIp new file mode 100755 index 0000000..6d89ff6 --- /dev/null +++ b/client/shared/functions/ogGetRepoIp @@ -0,0 +1,22 @@ +#!/usr/bin/python3 + +import sys +import argparse +from SystemLib import ogHelp +from NetLib import ogGetRepoIp + +parser = argparse.ArgumentParser (add_help=False) + + +if 2 == len (sys.argv) and 'help' == sys.argv[1]: + #parser.print_help() sale en inglés aunque la locale indique otra cosa + ogHelp ('ogGetRepoIp') + sys.exit (0) + +args = parser.parse_args() + +ret = ogGetRepoIp () +if ret is not None: + if ret == True: sys.exit (0) + elif ret == False: sys.exit (1) + else: print (ret) diff --git a/client/shared/functions/ogGetServerIp b/client/shared/functions/ogGetServerIp new file mode 100755 index 0000000..7f23a8f --- /dev/null +++ b/client/shared/functions/ogGetServerIp @@ -0,0 +1,22 @@ +#!/usr/bin/python3 + +import sys +import argparse +from SystemLib import ogHelp +from NetLib import ogGetServerIp + +parser = argparse.ArgumentParser (add_help=False) + + +if 2 == len (sys.argv) and 'help' == sys.argv[1]: + #parser.print_help() sale en inglés aunque la locale indique otra cosa + ogHelp ('ogGetServerIp') + sys.exit (0) + +args = parser.parse_args() + +ret = ogGetServerIp () +if ret is not None: + if ret == True: sys.exit (0) + elif ret == False: sys.exit (1) + else: print (ret) diff --git a/client/shared/functions/ogGrubInstallPartition b/client/shared/functions/ogGrubInstallPartition new file mode 100755 index 0000000..eca057a --- /dev/null +++ b/client/shared/functions/ogGrubInstallPartition @@ -0,0 +1,25 @@ +#!/usr/bin/python3 + +import sys +import argparse +from SystemLib import ogHelp +from BootLib import ogGrubInstallPartition + +parser = argparse.ArgumentParser (add_help=False) +parser.add_argument ('disk') +parser.add_argument ('par') +parser.add_argument ('checkos', nargs='?', default='FALSE') +parser.add_argument ('kernelparam', nargs='?', default='') + +if 2 == len (sys.argv) and 'help' == sys.argv[1]: + #parser.print_help() sale en inglés aunque la locale indique otra cosa + ogHelp ('ogGrubInstallPartition', 'ogGrubInstallPartition int_ndiskSecondStage int_partitionSecondStage bolean_Configure_2ndStage "param param"', ['ogGrubInstallPartition 1 1 FALSE', 'ogGrubInstallPartition 1 1 TRUE "nomodeset irqpoll pci=noacpi quiet splash"']) + sys.exit (0) + +args = parser.parse_args() + +ret = ogGrubInstallPartition (args.disk, args.par, args.checkos, args.kernelparam) +if ret is not None: + if ret == True: sys.exit (0) + elif ret == False: sys.exit (1) + else: print (ret) diff --git a/client/shared/functions/ogHelp b/client/shared/functions/ogHelp new file mode 100755 index 0000000..e26329f --- /dev/null +++ b/client/shared/functions/ogHelp @@ -0,0 +1,24 @@ +#!/usr/bin/python3 + +import sys +import argparse +from SystemLib import ogHelp +from SystemLib import ogHelp + +parser = argparse.ArgumentParser (add_help=False) +parser.add_argument ('fname') +parser.add_argument ('fmt', nargs='?', default=None) +parser.add_argument ('examples', nargs='?', default=[]) + +if 2 == len (sys.argv) and 'help' == sys.argv[1]: + #parser.print_help() sale en inglés aunque la locale indique otra cosa + ogHelp ('ogHelp') + sys.exit (0) + +args = parser.parse_args() + +ret = ogHelp (args.fname, args.fmt, args.examples) +if ret is not None: + if ret == True: sys.exit (0) + elif ret == False: sys.exit (1) + else: print (ret) diff --git a/client/shared/functions/ogIsEfiActive b/client/shared/functions/ogIsEfiActive new file mode 100755 index 0000000..099ef7b --- /dev/null +++ b/client/shared/functions/ogIsEfiActive @@ -0,0 +1,22 @@ +#!/usr/bin/python3 + +import sys +import argparse +from SystemLib import ogHelp +from InventoryLib import ogIsEfiActive + +parser = argparse.ArgumentParser (add_help=False) + + +if 2 == len (sys.argv) and 'help' == sys.argv[1]: + #parser.print_help() sale en inglés aunque la locale indique otra cosa + ogHelp ('ogIsEfiActive') + sys.exit (0) + +args = parser.parse_args() + +ret = ogIsEfiActive () +if ret is not None: + if ret == True: sys.exit (0) + elif ret == False: sys.exit (1) + else: print (ret) diff --git a/client/shared/functions/ogIsFormated b/client/shared/functions/ogIsFormated new file mode 100755 index 0000000..3ab17f0 --- /dev/null +++ b/client/shared/functions/ogIsFormated @@ -0,0 +1,23 @@ +#!/usr/bin/python3 + +import sys +import argparse +from SystemLib import ogHelp +from FileSystemLib import ogIsFormated + +parser = argparse.ArgumentParser (add_help=False) +parser.add_argument ('disk') +parser.add_argument ('part') + +if 2 == len (sys.argv) and 'help' == sys.argv[1]: + #parser.print_help() sale en inglés aunque la locale indique otra cosa + ogHelp ('ogIsFormated', 'ogIsFormated int_ndisk int_nfilesys', ['ogIsFormated 1 1']) + sys.exit (0) + +args = parser.parse_args() + +ret = ogIsFormated (args.disk, args.part) +if ret is not None: + if ret == True: sys.exit (0) + elif ret == False: sys.exit (1) + else: print (ret) diff --git a/client/shared/functions/ogIsImageLocked b/client/shared/functions/ogIsImageLocked new file mode 100755 index 0000000..5d9bdb6 --- /dev/null +++ b/client/shared/functions/ogIsImageLocked @@ -0,0 +1,23 @@ +#!/usr/bin/python3 + +import sys +import argparse +from SystemLib import ogHelp +from ImageLib import ogIsImageLocked + +parser = argparse.ArgumentParser (add_help=False) +parser.add_argument ('container', nargs='?', default=None) +parser.add_argument ('imgfile', nargs='?', default=None) + +if 2 == len (sys.argv) and 'help' == sys.argv[1]: + #parser.print_help() sale en inglés aunque la locale indique otra cosa + ogHelp ('ogIsImageLocked', 'ogIsImageLocked [str_repo] path_image', ['ogIsImageLocked /opt/opengnsys/images/aula1/win7.img', 'ogIsImageLocked REPO /aula1/win7.img']) + sys.exit (0) + +args = parser.parse_args() + +ret = ogIsImageLocked (args.container, args.imgfile) +if ret is not None: + if ret == True: sys.exit (0) + elif ret == False: sys.exit (1) + else: print (ret) diff --git a/client/shared/functions/ogIsLocked b/client/shared/functions/ogIsLocked new file mode 100755 index 0000000..6523cf8 --- /dev/null +++ b/client/shared/functions/ogIsLocked @@ -0,0 +1,23 @@ +#!/usr/bin/python3 + +import sys +import argparse +from SystemLib import ogHelp +from FileSystemLib import ogIsLocked + +parser = argparse.ArgumentParser (add_help=False) +parser.add_argument ('disk') +parser.add_argument ('par') + +if 2 == len (sys.argv) and 'help' == sys.argv[1]: + #parser.print_help() sale en inglés aunque la locale indique otra cosa + ogHelp ('ogIsLocked', 'ogIsLocked int_ndisk int_nfilesys', ['ogIsLocked 1 1']) + sys.exit (0) + +args = parser.parse_args() + +ret = ogIsLocked (args.disk, args.par) +if ret is not None: + if ret == True: sys.exit (0) + elif ret == False: sys.exit (1) + else: print (ret) diff --git a/client/shared/functions/ogIsMounted b/client/shared/functions/ogIsMounted new file mode 100755 index 0000000..1158a65 --- /dev/null +++ b/client/shared/functions/ogIsMounted @@ -0,0 +1,23 @@ +#!/usr/bin/python3 + +import sys +import argparse +from SystemLib import ogHelp +from FileSystemLib import ogIsMounted + +parser = argparse.ArgumentParser (add_help=False) +parser.add_argument ('disk') +parser.add_argument ('par') + +if 2 == len (sys.argv) and 'help' == sys.argv[1]: + #parser.print_help() sale en inglés aunque la locale indique otra cosa + ogHelp ('ogIsMounted', 'ogIsMounted int_ndisk int_nfilesys', ['ogIsMounted 1 1']) + sys.exit (0) + +args = parser.parse_args() + +ret = ogIsMounted (args.disk, args.par) +if ret is not None: + if ret == True: sys.exit (0) + elif ret == False: sys.exit (1) + else: print (ret) diff --git a/client/shared/functions/ogIsPartitionLocked b/client/shared/functions/ogIsPartitionLocked new file mode 100755 index 0000000..f340264 --- /dev/null +++ b/client/shared/functions/ogIsPartitionLocked @@ -0,0 +1,23 @@ +#!/usr/bin/python3 + +import sys +import argparse +from SystemLib import ogHelp +from FileSystemLib import ogIsPartitionLocked + +parser = argparse.ArgumentParser (add_help=False) +parser.add_argument ('disk') +parser.add_argument ('par') + +if 2 == len (sys.argv) and 'help' == sys.argv[1]: + #parser.print_help() sale en inglés aunque la locale indique otra cosa + ogHelp ('ogIsPartitionLocked', 'ogIsPartitionLocked int_ndisk int_nfilesys', ['ogIsPartitionLocked 1 1']) + sys.exit (0) + +args = parser.parse_args() + +ret = ogIsPartitionLocked (args.disk, args.par) +if ret is not None: + if ret == True: sys.exit (0) + elif ret == False: sys.exit (1) + else: print (ret) diff --git a/client/shared/functions/ogIsReadonly b/client/shared/functions/ogIsReadonly new file mode 100755 index 0000000..6a20026 --- /dev/null +++ b/client/shared/functions/ogIsReadonly @@ -0,0 +1,23 @@ +#!/usr/bin/python3 + +import sys +import argparse +from SystemLib import ogHelp +from FileSystemLib import ogIsReadonly + +parser = argparse.ArgumentParser (add_help=False) +parser.add_argument ('disk') +parser.add_argument ('par') + +if 2 == len (sys.argv) and 'help' == sys.argv[1]: + #parser.print_help() sale en inglés aunque la locale indique otra cosa + ogHelp ('ogIsReadonly', 'ogIsReadonly int_ndisk int_nfilesys', ['ogIsReadonly 1 1']) + sys.exit (0) + +args = parser.parse_args() + +ret = ogIsReadonly (args.disk, args.par) +if ret is not None: + if ret == True: sys.exit (0) + elif ret == False: sys.exit (1) + else: print (ret) diff --git a/client/shared/functions/ogIsVirtualMachine b/client/shared/functions/ogIsVirtualMachine new file mode 100755 index 0000000..9592da3 --- /dev/null +++ b/client/shared/functions/ogIsVirtualMachine @@ -0,0 +1,22 @@ +#!/usr/bin/python3 + +import sys +import argparse +from SystemLib import ogHelp +from SystemLib import ogIsVirtualMachine + +parser = argparse.ArgumentParser (add_help=False) + + +if 2 == len (sys.argv) and 'help' == sys.argv[1]: + #parser.print_help() sale en inglés aunque la locale indique otra cosa + ogHelp ('ogIsVirtualMachine') + sys.exit (0) + +args = parser.parse_args() + +ret = ogIsVirtualMachine () +if ret is not None: + if ret == True: sys.exit (0) + elif ret == False: sys.exit (1) + else: print (ret) diff --git a/client/shared/functions/ogIsWritable b/client/shared/functions/ogIsWritable new file mode 100755 index 0000000..53e1314 --- /dev/null +++ b/client/shared/functions/ogIsWritable @@ -0,0 +1,23 @@ +#!/usr/bin/python3 + +import sys +import argparse +from SystemLib import ogHelp +from FileSystemLib import ogIsWritable + +parser = argparse.ArgumentParser (add_help=False) +parser.add_argument ('disk') +parser.add_argument ('par') + +if 2 == len (sys.argv) and 'help' == sys.argv[1]: + #parser.print_help() sale en inglés aunque la locale indique otra cosa + ogHelp ('ogIsWritable', 'ogIsWritable int_ndisk int_nfilesys', ['ogIsWritable 1 1']) + sys.exit (0) + +args = parser.parse_args() + +ret = ogIsWritable (args.disk, args.par) +if ret is not None: + if ret == True: sys.exit (0) + elif ret == False: sys.exit (1) + else: print (ret) diff --git a/client/shared/functions/ogLock b/client/shared/functions/ogLock new file mode 100755 index 0000000..8bb795f --- /dev/null +++ b/client/shared/functions/ogLock @@ -0,0 +1,23 @@ +#!/usr/bin/python3 + +import sys +import argparse +from SystemLib import ogHelp +from FileSystemLib import ogLock + +parser = argparse.ArgumentParser (add_help=False) +parser.add_argument ('disk') +parser.add_argument ('par') + +if 2 == len (sys.argv) and 'help' == sys.argv[1]: + #parser.print_help() sale en inglés aunque la locale indique otra cosa + ogHelp ('ogLock', 'ogLock int_ndisk int_nfilesys', ['ogLock 1 1']) + sys.exit (0) + +args = parser.parse_args() + +ret = ogLock (args.disk, args.par) +if ret is not None: + if ret == True: sys.exit (0) + elif ret == False: sys.exit (1) + else: print (ret) diff --git a/client/shared/functions/ogLockPartition b/client/shared/functions/ogLockPartition new file mode 100755 index 0000000..e83da43 --- /dev/null +++ b/client/shared/functions/ogLockPartition @@ -0,0 +1,23 @@ +#!/usr/bin/python3 + +import sys +import argparse +from SystemLib import ogHelp +from FileSystemLib import ogLockPartition + +parser = argparse.ArgumentParser (add_help=False) +parser.add_argument ('disk') +parser.add_argument ('par') + +if 2 == len (sys.argv) and 'help' == sys.argv[1]: + #parser.print_help() sale en inglés aunque la locale indique otra cosa + ogHelp ('ogLockPartition', 'ogLockPartition int_ndisk int_nfilesys', ['ogLockPartition 1 1']) + sys.exit (0) + +args = parser.parse_args() + +ret = ogLockPartition (args.disk, args.par) +if ret is not None: + if ret == True: sys.exit (0) + elif ret == False: sys.exit (1) + else: print (ret) diff --git a/client/shared/functions/ogMakeDir b/client/shared/functions/ogMakeDir new file mode 100755 index 0000000..b12f1c1 --- /dev/null +++ b/client/shared/functions/ogMakeDir @@ -0,0 +1,32 @@ +#!/usr/bin/python3 + +import sys +import argparse +from SystemLib import ogHelp +from FileLib import ogMakeDir + +if 2 == len (sys.argv) and 'help' == sys.argv[1]: + #parser.print_help() sale en inglés aunque la locale indique otra cosa + ogHelp ('ogMakeDir', 'ogMakeDir [ str_repo | int_ndisk int_npartition ] path_dir', ['ogMakeDir 1 2 /tmp/newdir']) + sys.exit (0) + +parser = argparse.ArgumentParser (add_help=False) +if 3 == len (sys.argv): + parser.add_argument ('container', nargs='?', default=None) + parser.add_argument ('file', nargs='?', default=None) +elif 4 == len (sys.argv): + parser.add_argument ('disk', nargs='?', default=None) + parser.add_argument ('par', nargs='?', default=None) + parser.add_argument ('file', nargs='?', default=None) + +args = parser.parse_args() + +if 3 == len (sys.argv): + ret = ogMakeDir (container=args.container, file=args.file) +elif 4 == len (sys.argv): + ret = ogMakeDir (container=f'{args.disk} {args.par}', file=args.file) + +if ret is not None: + if ret == True: sys.exit (0) + elif ret == False: sys.exit (1) + else: print (ret) diff --git a/client/shared/functions/ogMount b/client/shared/functions/ogMount new file mode 100755 index 0000000..2a92f44 --- /dev/null +++ b/client/shared/functions/ogMount @@ -0,0 +1,35 @@ +#!/usr/bin/python3 + +## this script doesn't call ogMount. It replicates the functionality instead. + +import sys +import argparse +from SystemLib import ogHelp +from CacheLib import ogMountCache +from FileSystemLib import ogMountCdrom, ogMountFs + +if 2 == len (sys.argv) and 'help' == sys.argv[1]: + #parser.print_help() sale en inglés aunque la locale indique otra cosa + ogHelp ('ogMount') + sys.exit (0) + +parser = argparse.ArgumentParser (add_help=False) +done = False +if 2 == len (sys.argv): + if 'cache' == sys.argv[1].lower(): + done = True + ret = ogMountCache() + elif 'cdrom' == sys.argv[1].lower(): + done = True + ret = ogMountCdrom() + +if not done: + parser.add_argument ('disk') + parser.add_argument ('par') + args = parser.parse_args() + ret = ogMountFs (args.disk, args.par) + +if ret is not None: + if ret == True: sys.exit (0) + elif ret == False: sys.exit (1) + else: print (ret) diff --git a/client/shared/functions/ogMountCache b/client/shared/functions/ogMountCache new file mode 100755 index 0000000..8dd7578 --- /dev/null +++ b/client/shared/functions/ogMountCache @@ -0,0 +1,22 @@ +#!/usr/bin/python3 + +import sys +import argparse +from SystemLib import ogHelp +from CacheLib import ogMountCache + +parser = argparse.ArgumentParser (add_help=False) + + +if 2 == len (sys.argv) and 'help' == sys.argv[1]: + #parser.print_help() sale en inglés aunque la locale indique otra cosa + ogHelp ('ogMountCache', 'ogMountCache') + sys.exit (0) + +args = parser.parse_args() + +ret = ogMountCache () +if ret is not None: + if ret == True: sys.exit (0) + elif ret == False: sys.exit (1) + else: print (ret) diff --git a/client/shared/functions/ogMountFs b/client/shared/functions/ogMountFs new file mode 100755 index 0000000..2e2bdcf --- /dev/null +++ b/client/shared/functions/ogMountFs @@ -0,0 +1,23 @@ +#!/usr/bin/python3 + +import sys +import argparse +from SystemLib import ogHelp +from FileSystemLib import ogMountFs + +parser = argparse.ArgumentParser (add_help=False) +parser.add_argument ('disk') +parser.add_argument ('par') + +if 2 == len (sys.argv) and 'help' == sys.argv[1]: + #parser.print_help() sale en inglés aunque la locale indique otra cosa + ogHelp ('ogMountFs', 'ogMountFs int_ndisk int_nfilesys', ['ogMountFs 1 1']) + sys.exit (0) + +args = parser.parse_args() + +ret = ogMountFs (args.disk, args.par) +if ret is not None: + if ret == True: sys.exit (0) + elif ret == False: sys.exit (1) + else: print (ret) diff --git a/client/shared/functions/ogRaiseError b/client/shared/functions/ogRaiseError new file mode 100755 index 0000000..15c94a6 --- /dev/null +++ b/client/shared/functions/ogRaiseError @@ -0,0 +1,34 @@ +#!/usr/bin/python3 + +import sys +import argparse +import ogGlobals +from SystemLib import ogHelp +from SystemLib import ogRaiseError + +if 2 == len (sys.argv) and 'help' == sys.argv[1]: + #parser.print_help() sale en inglés aunque la locale indique otra cosa + ogHelp ('ogRaiseError', 'ogRaiseError [str_logfile ...] int_errorcode str_errormessage') + sys.exit (0) + +logtypes = [] +while True: + if sys.argv[1] in ['command', 'log', 'session']: + logtypes.append (sys.argv.pop (1)) + else: break + +parser = argparse.ArgumentParser (add_help=False) +parser.add_argument ('code') +parser.add_argument ('msg') +args = parser.parse_args() + +try: + code = getattr (ogGlobals, args.code) +except AttributeError: + print (f'unknown code {args.code}') + sys.exit (1) + +ret = ogRaiseError (logtypes, code, args.msg) +if ret is not None: + if ret == True: sys.exit (0) + elif ret == False: sys.exit (1) diff --git a/client/shared/functions/ogRestoreImageSyntax b/client/shared/functions/ogRestoreImageSyntax new file mode 100755 index 0000000..40d80ee --- /dev/null +++ b/client/shared/functions/ogRestoreImageSyntax @@ -0,0 +1,25 @@ +#!/usr/bin/python3 + +import sys +import argparse +from SystemLib import ogHelp +from ImageLib import ogRestoreImageSyntax + +parser = argparse.ArgumentParser (add_help=False) +parser.add_argument ('imgfile') +parser.add_argument ('part') +parser.add_argument ('tool', nargs='?', default=None) +parser.add_argument ('level', nargs='?', default=None) + +if 2 == len (sys.argv) and 'help' == sys.argv[1]: + #parser.print_help() sale en inglés aunque la locale indique otra cosa + ogHelp ('ogRestoreImageSyntax', 'ogRestoreImageSyntax filename partition [tool] [levelcompresor]', ['ogRestoreImageSyntax /opt/opengnsys/images/prueba.img /dev/sda1 [partclone] [lzop]']) + sys.exit (0) + +args = parser.parse_args() + +ret = ogRestoreImageSyntax (args.imgfile, args.part, args.tool, args.level) +if ret is not None: + if ret == True: sys.exit (0) + elif ret == False: sys.exit (1) + else: print (ret) diff --git a/client/shared/functions/ogSetPartitionActive b/client/shared/functions/ogSetPartitionActive new file mode 100755 index 0000000..c8a97b8 --- /dev/null +++ b/client/shared/functions/ogSetPartitionActive @@ -0,0 +1,23 @@ +#!/usr/bin/python3 + +import sys +import argparse +from SystemLib import ogHelp +from DiskLib import ogSetPartitionActive + +parser = argparse.ArgumentParser (add_help=False) +parser.add_argument ('disk') +parser.add_argument ('par') + +if 2 == len (sys.argv) and 'help' == sys.argv[1]: + #parser.print_help() sale en inglés aunque la locale indique otra cosa + ogHelp ('ogSetPartitionActive', 'ogSetPartitionActive int_ndisk int_npartition', ['ogSetPartitionActive 1 1']) + sys.exit (0) + +args = parser.parse_args() + +ret = ogSetPartitionActive (args.disk, args.par) +if ret is not None: + if ret == True: sys.exit (0) + elif ret == False: sys.exit (1) + else: print (ret) diff --git a/client/shared/functions/ogTypeToId b/client/shared/functions/ogTypeToId new file mode 100755 index 0000000..cce6665 --- /dev/null +++ b/client/shared/functions/ogTypeToId @@ -0,0 +1,23 @@ +#!/usr/bin/python3 + +import sys +import argparse +from SystemLib import ogHelp +from DiskLib import ogTypeToId + +parser = argparse.ArgumentParser (add_help=False) +parser.add_argument ('type') +parser.add_argument ('pttype', nargs='?', default='MSDOS') + +if 2 == len (sys.argv) and 'help' == sys.argv[1]: + #parser.print_help() sale en inglés aunque la locale indique otra cosa + ogHelp ('ogTypeToId', 'ogTypeToId str_parttype [str_tabletype]', ['ogTypeToId LINUX', 'ogTypeToId LINUX MSDOS']) + sys.exit (0) + +args = parser.parse_args() + +ret = ogTypeToId (args.type, args.pttype) +if ret is not None: + if ret == True: sys.exit (0) + elif ret == False: sys.exit (1) + else: print (ret) diff --git a/client/shared/functions/ogUninstallLinuxClient b/client/shared/functions/ogUninstallLinuxClient new file mode 100755 index 0000000..0dfbe27 --- /dev/null +++ b/client/shared/functions/ogUninstallLinuxClient @@ -0,0 +1,23 @@ +#!/usr/bin/python3 + +import sys +import argparse +from SystemLib import ogHelp +from PostConfLib import ogUninstallLinuxClient + +parser = argparse.ArgumentParser (add_help=False) +parser.add_argument ('disk') +parser.add_argument ('par') + +if 2 == len (sys.argv) and 'help' == sys.argv[1]: + #parser.print_help() sale en inglés aunque la locale indique otra cosa + ogHelp ('ogUninstallLinuxClient', 'ogUninstallLinuxClient int_ndisk int_filesys', ['ogUninstallLinuxClient 1 1']) + sys.exit (0) + +args = parser.parse_args() + +ret = ogUninstallLinuxClient (args.disk, args.par) +if ret is not None: + if ret == True: sys.exit (0) + elif ret == False: sys.exit (1) + else: print (ret) diff --git a/client/shared/functions/ogUnlock b/client/shared/functions/ogUnlock new file mode 100755 index 0000000..ac321a2 --- /dev/null +++ b/client/shared/functions/ogUnlock @@ -0,0 +1,23 @@ +#!/usr/bin/python3 + +import sys +import argparse +from SystemLib import ogHelp +from FileSystemLib import ogUnlock + +parser = argparse.ArgumentParser (add_help=False) +parser.add_argument ('disk') +parser.add_argument ('par') + +if 2 == len (sys.argv) and 'help' == sys.argv[1]: + #parser.print_help() sale en inglés aunque la locale indique otra cosa + ogHelp ('ogUnlock', 'ogUnlock int_ndisk int_npartition', ['ogUnlock 1 1']) + sys.exit (0) + +args = parser.parse_args() + +ret = ogUnlock (args.disk, args.par) +if ret is not None: + if ret == True: sys.exit (0) + elif ret == False: sys.exit (1) + else: print (ret) diff --git a/client/shared/functions/ogUnlockPartition b/client/shared/functions/ogUnlockPartition new file mode 100755 index 0000000..134c072 --- /dev/null +++ b/client/shared/functions/ogUnlockPartition @@ -0,0 +1,23 @@ +#!/usr/bin/python3 + +import sys +import argparse +from SystemLib import ogHelp +from FileSystemLib import ogUnlockPartition + +parser = argparse.ArgumentParser (add_help=False) +parser.add_argument ('disk') +parser.add_argument ('par') + +if 2 == len (sys.argv) and 'help' == sys.argv[1]: + #parser.print_help() sale en inglés aunque la locale indique otra cosa + ogHelp ('ogUnlockPartition') + sys.exit (0) + +args = parser.parse_args() + +ret = ogUnlockPartition (args.disk, args.par) +if ret is not None: + if ret == True: sys.exit (0) + elif ret == False: sys.exit (1) + else: print (ret) diff --git a/client/shared/functions/ogUnmount b/client/shared/functions/ogUnmount new file mode 100755 index 0000000..024294b --- /dev/null +++ b/client/shared/functions/ogUnmount @@ -0,0 +1,23 @@ +#!/usr/bin/python3 + +import sys +import argparse +from SystemLib import ogHelp +from FileSystemLib import ogUnmount + +parser = argparse.ArgumentParser (add_help=False) +parser.add_argument ('disk') +parser.add_argument ('par') + +if 2 == len (sys.argv) and 'help' == sys.argv[1]: + #parser.print_help() sale en inglés aunque la locale indique otra cosa + ogHelp ('ogUnmount', 'ogUnmount int_ndisk int_npartition', ['ogUnmount 1 1']) + sys.exit (0) + +args = parser.parse_args() + +ret = ogUnmount (args.disk, args.par) +if ret is not None: + if ret == True: sys.exit (0) + elif ret == False: sys.exit (1) + else: print (ret) diff --git a/client/shared/functions/ogUnmountCache b/client/shared/functions/ogUnmountCache new file mode 100755 index 0000000..89a35fc --- /dev/null +++ b/client/shared/functions/ogUnmountCache @@ -0,0 +1,22 @@ +#!/usr/bin/python3 + +import sys +import argparse +from SystemLib import ogHelp +from CacheLib import ogUnmountCache + +parser = argparse.ArgumentParser (add_help=False) + + +if 2 == len (sys.argv) and 'help' == sys.argv[1]: + #parser.print_help() sale en inglés aunque la locale indique otra cosa + ogHelp ('ogUnmountCache', 'ogUnmountCache') + sys.exit (0) + +args = parser.parse_args() + +ret = ogUnmountCache () +if ret is not None: + if ret == True: sys.exit (0) + elif ret == False: sys.exit (1) + else: print (ret) diff --git a/client/shared/functions/ogUnmountFs b/client/shared/functions/ogUnmountFs new file mode 100755 index 0000000..8c83bc0 --- /dev/null +++ b/client/shared/functions/ogUnmountFs @@ -0,0 +1,23 @@ +#!/usr/bin/python3 + +import sys +import argparse +from SystemLib import ogHelp +from FileSystemLib import ogUnmountFs + +parser = argparse.ArgumentParser (add_help=False) +parser.add_argument ('disk') +parser.add_argument ('par') + +if 2 == len (sys.argv) and 'help' == sys.argv[1]: + #parser.print_help() sale en inglés aunque la locale indique otra cosa + ogHelp ('ogUnmountFs', 'ogUnmountFs int_ndisk int_npartition', ['ogUnmountFs 1 1']) + sys.exit (0) + +args = parser.parse_args() + +ret = ogUnmountFs (args.disk, args.par) +if ret is not None: + if ret == True: sys.exit (0) + elif ret == False: sys.exit (1) + else: print (ret) From a346ba386e87333f6756e6d2754d9b1754b43442 Mon Sep 17 00:00:00 2001 From: Natalia Serrano Date: Wed, 22 Jan 2025 10:28:12 +0100 Subject: [PATCH 109/167] refs #1337 add more commands --- client/lib/engine/bin/FileSystemLib.py | 56 +++++-------------- client/lib/engine/bin/ImageLib.py | 2 - client/lib/engine/bin/ProtocolLib.py | 2 - client/lib/engine/bin/RegistryLib.py | 1 - client/shared/functions/ogAddCmd | 25 +++++++++ client/shared/functions/ogAddRegistryKey | 24 ++++++++ client/shared/functions/ogAddRegistryValue | 25 +++++++++ client/shared/functions/ogDeleteRegistryKey | 24 ++++++++ client/shared/functions/ogDeleteRegistryValue | 24 ++++++++ client/shared/functions/ogExtendFs | 23 ++++++++ client/shared/functions/ogFixBootSector | 23 ++++++++ client/shared/functions/ogFormat | 28 ++++++++++ client/shared/functions/ogFormatCache | 22 ++++++++ client/shared/functions/ogFormatFs | 25 +++++++++ client/shared/functions/ogGetHivePath | 23 ++++++++ client/shared/functions/ogGetRegistryValue | 24 ++++++++ client/shared/functions/ogInstallFirstBoot | 24 ++++++++ client/shared/functions/ogInstallMiniSetup | 35 ++++++++++++ client/shared/functions/ogInstallRunonce | 29 ++++++++++ client/shared/functions/ogListRegistryKeys | 25 +++++++++ client/shared/functions/ogListRegistryValues | 25 +++++++++ client/shared/functions/ogMcastSyntax | 34 +++++++++++ client/shared/functions/ogRestoreImage | 25 +++++++++ client/shared/functions/ogSetRegistryValue | 25 +++++++++ client/shared/functions/ogSetWindowsName | 24 ++++++++ client/shared/functions/ogUcastSyntax | 34 +++++++++++ .../shared/functions/ogUninstallWindowsClient | 24 ++++++++ .../shared/functions/ogUpdateCacheIsNecesary | 24 ++++++++ .../shared/functions/ogWindowsBootParameters | 23 ++++++++ .../functions/ogWindowsRegisterPartition | 26 +++++++++ 30 files changed, 681 insertions(+), 47 deletions(-) create mode 100755 client/shared/functions/ogAddCmd create mode 100755 client/shared/functions/ogAddRegistryKey create mode 100755 client/shared/functions/ogAddRegistryValue create mode 100755 client/shared/functions/ogDeleteRegistryKey create mode 100755 client/shared/functions/ogDeleteRegistryValue create mode 100755 client/shared/functions/ogExtendFs create mode 100755 client/shared/functions/ogFixBootSector create mode 100755 client/shared/functions/ogFormat create mode 100755 client/shared/functions/ogFormatCache create mode 100755 client/shared/functions/ogFormatFs create mode 100755 client/shared/functions/ogGetHivePath create mode 100755 client/shared/functions/ogGetRegistryValue create mode 100755 client/shared/functions/ogInstallFirstBoot create mode 100755 client/shared/functions/ogInstallMiniSetup create mode 100755 client/shared/functions/ogInstallRunonce create mode 100755 client/shared/functions/ogListRegistryKeys create mode 100755 client/shared/functions/ogListRegistryValues create mode 100755 client/shared/functions/ogMcastSyntax create mode 100755 client/shared/functions/ogRestoreImage create mode 100755 client/shared/functions/ogSetRegistryValue create mode 100755 client/shared/functions/ogSetWindowsName create mode 100755 client/shared/functions/ogUcastSyntax create mode 100755 client/shared/functions/ogUninstallWindowsClient create mode 100755 client/shared/functions/ogUpdateCacheIsNecesary create mode 100755 client/shared/functions/ogWindowsBootParameters create mode 100755 client/shared/functions/ogWindowsRegisterPartition diff --git a/client/lib/engine/bin/FileSystemLib.py b/client/lib/engine/bin/FileSystemLib.py index f1953ec..46cba8e 100755 --- a/client/lib/engine/bin/FileSystemLib.py +++ b/client/lib/engine/bin/FileSystemLib.py @@ -230,7 +230,7 @@ def ogFormat (disk, par=None, fs=None, label=None): if disk.lower() == "cache": return CacheLib.ogFormatCache() else: - return ogFormatFs (disk, par) + return ogFormatFs (disk, par, fs=fs, label=label) #/** @@ -248,34 +248,22 @@ def ogFormat (disk, par=None, fs=None, label=None): #@warning No formatea particiones montadas ni bloqueadas. #@todo Definir salidas. #*/ ## -def ogFormatFs (disk, par, type=None, label=None): +def ogFormatFs (disk, par, fs=None, label=None): PART = DiskLib.ogDiskToDev (disk, par) if not PART: return if ogIsMounted (disk, par): - SystemLib.ogRaiseError( - [], - ogGlobals.OG_ERR_DONTFORMAT, - f'{ogGlobals.lang.MSG_MOUNT}: {disk} {par}' - ) + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_DONTFORMAT, f'{ogGlobals.lang.MSG_MOUNT}: {disk} {par}') return None if ogIsLocked (disk, par): - SystemLib.ogRaiseError( - [], - ogGlobals.OG_ERR_LOCKED, - f"{disk} {par}" - ) + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_LOCKED, f"{disk} {par}") return None - if not type: - type = ogGetFsType (disk, par) + if not fs: + fs = ogGetFsType (disk, par) - if not type: - SystemLib.ogRaiseError( - [], - ogGlobals.OG_ERR_FORMAT, - f"{disk} {par} ..." - ) + if not fs: + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_FORMAT, f"{disk} {par} ...") return None data = { @@ -299,26 +287,18 @@ def ogFormatFs (disk, par, type=None, label=None): 'HFSPLUS': { 'PROG': 'mkfs.hfsplus', 'LABELPARAM': '-v' }, 'UFS': { 'PROG': 'mkfs.ufs', 'PARAMS': '-O 2' }, } - if type not in data: - SystemLib.ogRaiseError ( - [], - ogGlobals.OG_ERR_PARTITION, - f"{disk} {par} {type}" - ) + if fs not in data: + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_PARTITION, f"{disk} {par} {fs}") return - d = data[type] + d = data[fs] prog = d['PROG'] params = d['PARAMS'] if 'PARAMS' in d else '' labelparam = d['LABELPARAM'] if 'LABELPARAM' in d else '' input = d['INPUT'] if 'INPUT' in d else '' if label == "CACHE": - SystemLib.ogRaiseError ( - [], - ogGlobals.OG_ERR_FORMAT, - f"{ogGlobals.lang.MSG_RESERVEDVALUE}: CACHE" - ) + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_FORMAT, f"{ogGlobals.lang.MSG_RESERVEDVALUE}: CACHE") return if label: params = f"{params} {labelparam or '-L'} {label}" @@ -331,18 +311,10 @@ def ogFormatFs (disk, par, type=None, label=None): else: errcode = subprocess.run ([prog, params, PART], input=input, text=True) except FileNotFoundError: - SystemLib.ogRaiseError ( - [], - ogGlobals.OG_ERR_NOTEXEC, - prog - ) + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTEXEC, prog) errcode = ogGlobals.OG_ERR_NOTEXEC except: - SystemLib.ogRaiseError ( - [], - ogGlobals.OG_ERR_PARTITION, - f"{disk} {par}" - ) + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_PARTITION, f"{disk} {par}") errcode = ogGlobals.OG_ERR_PARTITION ogUnlock (disk, par) diff --git a/client/lib/engine/bin/ImageLib.py b/client/lib/engine/bin/ImageLib.py index 936eaeb..69e872f 100644 --- a/client/lib/engine/bin/ImageLib.py +++ b/client/lib/engine/bin/ImageLib.py @@ -375,10 +375,8 @@ def ogRestoreImage (repo, imgpath, disk, par): rc = None try: - print (f'nati: ogRestoreImage: running ({program})') p = subprocess.run (program, shell=True, capture_output=True, text=True) rc = p.returncode - print (f'nati: ogRestoreImage: rc ({rc}) stdout ({p.stdout}) stderr ({p.stderr})') if not rc: SystemLib.ogRaiseError ([], ogGlobalsOG_ERR_IMAGE, f'{imgfile}, {disk}, {par}') except: diff --git a/client/lib/engine/bin/ProtocolLib.py b/client/lib/engine/bin/ProtocolLib.py index d06a696..425ccbd 100644 --- a/client/lib/engine/bin/ProtocolLib.py +++ b/client/lib/engine/bin/ProtocolLib.py @@ -870,14 +870,12 @@ def ogUpdateCacheIsNecesary (repo, file, proto): return None filesource = FileLib.ogGetPath (src=repo, file=file) - print (f'filesource ({filesource})') if not filesource: SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTFOUND, f' {repo} {file}') return None # paso 1. si no existe la imagen, confirmar que es necesario actualizar la cache. filetarget = FileLib.ogGetPath (src='CACHE', file=file) - print (f'filetarget ({filetarget})') if not filetarget: # borramos el fichero bf del torrent, en el caso de que se hubiese quedado de algun proceso fallido if FileLib.ogGetPath (src='CACHE', file=f'/{file}.torrent.bf'): ogDeleteFile (container='CACHE', file=f'{file}.torrent.bf') diff --git a/client/lib/engine/bin/RegistryLib.py b/client/lib/engine/bin/RegistryLib.py index e8277be..11a2c08 100755 --- a/client/lib/engine/bin/RegistryLib.py +++ b/client/lib/engine/bin/RegistryLib.py @@ -232,7 +232,6 @@ def ogGetRegistryValue (mntpt, hive, k): ret = None if 'REG_BINARY' in lines[0]: if re.search ('^:[0-9A-F]+ ', lines[1]): - print ('re.match') ret = lines[1][8:56] else: ret = lines[1] diff --git a/client/shared/functions/ogAddCmd b/client/shared/functions/ogAddCmd new file mode 100755 index 0000000..8c0b913 --- /dev/null +++ b/client/shared/functions/ogAddCmd @@ -0,0 +1,25 @@ +#!/usr/bin/python3 + +import sys +import argparse +from SystemLib import ogHelp +from PostConfLib import ogAddCmd + +parser = argparse.ArgumentParser (add_help=False) +parser.add_argument ('disk') +parser.add_argument ('par') +parser.add_argument ('cmdfile') +parser.add_argument ('cmd') + +if 2 == len (sys.argv) and 'help' == sys.argv[1]: + #parser.print_help() sale en inglés aunque la locale indique otra cosa + ogHelp ('ogAddCmd', 'ogAddCmd int_ndisk int_npartition str_filename str_commands', ['ogAddCmd 1 1 filename.cmd command']) + sys.exit (0) + +args = parser.parse_args() + +ret = ogAddCmd (args.disk, args.par, args.cmdfile, args.cmd) +if ret is not None: + if ret == True: sys.exit (0) + elif ret == False: sys.exit (1) + else: print (ret) diff --git a/client/shared/functions/ogAddRegistryKey b/client/shared/functions/ogAddRegistryKey new file mode 100755 index 0000000..8b0c59b --- /dev/null +++ b/client/shared/functions/ogAddRegistryKey @@ -0,0 +1,24 @@ +#!/usr/bin/python3 + +import sys +import argparse +from SystemLib import ogHelp +from RegistryLib import ogAddRegistryKey + +parser = argparse.ArgumentParser (add_help=False) +parser.add_argument ('mntpt') +parser.add_argument ('hive') +parser.add_argument ('k') + +if 2 == len (sys.argv) and 'help' == sys.argv[1]: + #parser.print_help() sale en inglés aunque la locale indique otra cosa + ogHelp ('ogAddRegistryKey', 'ogAddRegistryKey path_mountpoint str_hive str_key', [r'ogAddRegistryKey /mnt/sda1 SOFTWARE "\Microsoft\NewKey"']) + sys.exit (0) + +args = parser.parse_args() + +ret = ogAddRegistryKey (args.mntpt, args.hive, args.k) +if ret is not None: + if ret == True: sys.exit (0) + elif ret == False: sys.exit (1) + else: print (ret) diff --git a/client/shared/functions/ogAddRegistryValue b/client/shared/functions/ogAddRegistryValue new file mode 100755 index 0000000..d4dd054 --- /dev/null +++ b/client/shared/functions/ogAddRegistryValue @@ -0,0 +1,25 @@ +#!/usr/bin/python3 + +import sys +import argparse +from SystemLib import ogHelp +from RegistryLib import ogAddRegistryValue + +parser = argparse.ArgumentParser (add_help=False) +parser.add_argument ('mntpt') +parser.add_argument ('hive') +parser.add_argument ('k') +parser.add_argument ('vtype', nargs='?', default='STRING') + +if 2 == len (sys.argv) and 'help' == sys.argv[1]: + #parser.print_help() sale en inglés aunque la locale indique otra cosa + ogHelp ('ogAddRegistryValue', 'ogAddRegistryValue path_mountpoint str_hive str_valuename [str_valuetype]', [r'ogAddRegistryValue /mnt/sda1 SOFTWARE "\Microsoft\NewKey\Value1"', r'ogAddRegistryValue /mnt/sda1 SOFTWARE "\Microsoft\NewKey\Value1" DWORD']) + sys.exit (0) + +args = parser.parse_args() + +ret = ogAddRegistryValue (args.mntpt, args.hive, args.k, args.vtype) +if ret is not None: + if ret == True: sys.exit (0) + elif ret == False: sys.exit (1) + else: print (ret) diff --git a/client/shared/functions/ogDeleteRegistryKey b/client/shared/functions/ogDeleteRegistryKey new file mode 100755 index 0000000..3eba2e1 --- /dev/null +++ b/client/shared/functions/ogDeleteRegistryKey @@ -0,0 +1,24 @@ +#!/usr/bin/python3 + +import sys +import argparse +from SystemLib import ogHelp +from RegistryLib import ogDeleteRegistryKey + +parser = argparse.ArgumentParser (add_help=False) +parser.add_argument ('mntpt') +parser.add_argument ('hive') +parser.add_argument ('k') + +if 2 == len (sys.argv) and 'help' == sys.argv[1]: + #parser.print_help() sale en inglés aunque la locale indique otra cosa + ogHelp ('ogDeleteRegistryKey', 'ogDeleteRegistryKey path_mountpoint str_hive str_key', [r'ogDeleteRegistryKey /mnt/sda1 SOFTWARE "\Microsoft\NewKey"']) + sys.exit (0) + +args = parser.parse_args() + +ret = ogDeleteRegistryKey (args.mntpt, args.hive, args.k) +if ret is not None: + if ret == True: sys.exit (0) + elif ret == False: sys.exit (1) + else: print (ret) diff --git a/client/shared/functions/ogDeleteRegistryValue b/client/shared/functions/ogDeleteRegistryValue new file mode 100755 index 0000000..7721bfa --- /dev/null +++ b/client/shared/functions/ogDeleteRegistryValue @@ -0,0 +1,24 @@ +#!/usr/bin/python3 + +import sys +import argparse +from SystemLib import ogHelp +from RegistryLib import ogDeleteRegistryValue + +parser = argparse.ArgumentParser (add_help=False) +parser.add_argument ('mntpt') +parser.add_argument ('hive') +parser.add_argument ('k') + +if 2 == len (sys.argv) and 'help' == sys.argv[1]: + #parser.print_help() sale en inglés aunque la locale indique otra cosa + ogHelp ('ogDeleteRegistryValue', 'ogDeleteRegistryValue path_mountpoint str_hive str_valuename', [r'ogDeleteRegistryValue /mnt/sda1 SOFTWARE "\Microsoft\NewKey\Value1"']) + sys.exit (0) + +args = parser.parse_args() + +ret = ogDeleteRegistryValue (args.mntpt, args.hive, args.k) +if ret is not None: + if ret == True: sys.exit (0) + elif ret == False: sys.exit (1) + else: print (ret) diff --git a/client/shared/functions/ogExtendFs b/client/shared/functions/ogExtendFs new file mode 100755 index 0000000..b706e87 --- /dev/null +++ b/client/shared/functions/ogExtendFs @@ -0,0 +1,23 @@ +#!/usr/bin/python3 + +import sys +import argparse +from SystemLib import ogHelp +from FileSystemLib import ogExtendFs + +parser = argparse.ArgumentParser (add_help=False) +parser.add_argument ('disk') +parser.add_argument ('par') + +if 2 == len (sys.argv) and 'help' == sys.argv[1]: + #parser.print_help() sale en inglés aunque la locale indique otra cosa + ogHelp ('ogExtendFs', 'ogExtendFs int_ndisk int_nfilesys', ['ogExtendFs 1 1']) + sys.exit (0) + +args = parser.parse_args() + +ret = ogExtendFs (args.disk, args.par) +if ret is not None: + if ret == True: sys.exit (0) + elif ret == False: sys.exit (1) + else: print (ret) diff --git a/client/shared/functions/ogFixBootSector b/client/shared/functions/ogFixBootSector new file mode 100755 index 0000000..3e9ecb5 --- /dev/null +++ b/client/shared/functions/ogFixBootSector @@ -0,0 +1,23 @@ +#!/usr/bin/python3 + +import sys +import argparse +from SystemLib import ogHelp +from BootLib import ogFixBootSector + +parser = argparse.ArgumentParser (add_help=False) +parser.add_argument ('disk') +parser.add_argument ('par') + +if 2 == len (sys.argv) and 'help' == sys.argv[1]: + #parser.print_help() sale en inglés aunque la locale indique otra cosa + ogHelp ('ogFixBootSector', 'ogFixBootSector int_ndisk int_partition', ['ogFixBootSector 1 1']) + sys.exit (0) + +args = parser.parse_args() + +ret = ogFixBootSector (args.disk, args.par) +if ret is not None: + if ret == True: sys.exit (0) + elif ret == False: sys.exit (1) + else: print (ret) diff --git a/client/shared/functions/ogFormat b/client/shared/functions/ogFormat new file mode 100755 index 0000000..cc955a2 --- /dev/null +++ b/client/shared/functions/ogFormat @@ -0,0 +1,28 @@ +#!/usr/bin/python3 + +import sys +import argparse +from SystemLib import ogHelp +from FileSystemLib import ogFormat +from CacheLib import ogFormatCache + +if 2 == len (sys.argv) and 'help' == sys.argv[1]: + #parser.print_help() sale en inglés aunque la locale indique otra cosa + ogHelp ('ogFormat', 'ogFormat int_ndisk int_nfilesys [str_label]', ['ogFormat 1 1', 'ogFormat 1 1 EXT4', 'ogFormat 1 1 DATA', 'ogFormat 1 1 EXT4 DATA']) + sys.exit (0) + +if 2 == len (sys.argv) and 'cache' == sys.argv[1]: + ret = ogFormatCache() +else: + parser = argparse.ArgumentParser (add_help=False) + parser.add_argument ('disk') + parser.add_argument ('par') + parser.add_argument ('fs', nargs='?', default=None) + parser.add_argument ('label', nargs='?', default=None) + args = parser.parse_args() + ret = ogFormat (args.disk, args.par, args.fs, args.label) + +if ret is not None: + if ret == True: sys.exit (0) + elif ret == False: sys.exit (1) + else: print (ret) diff --git a/client/shared/functions/ogFormatCache b/client/shared/functions/ogFormatCache new file mode 100755 index 0000000..375d8b2 --- /dev/null +++ b/client/shared/functions/ogFormatCache @@ -0,0 +1,22 @@ +#!/usr/bin/python3 + +import sys +import argparse +from SystemLib import ogHelp +from CacheLib import ogFormatCache + +parser = argparse.ArgumentParser (add_help=False) + + +if 2 == len (sys.argv) and 'help' == sys.argv[1]: + #parser.print_help() sale en inglés aunque la locale indique otra cosa + ogHelp ('ogFormatCache', 'ogFormatCache') + sys.exit (0) + +args = parser.parse_args() + +ret = ogFormatCache () +if ret is not None: + if ret == True: sys.exit (0) + elif ret == False: sys.exit (1) + else: print (ret) diff --git a/client/shared/functions/ogFormatFs b/client/shared/functions/ogFormatFs new file mode 100755 index 0000000..babe6ef --- /dev/null +++ b/client/shared/functions/ogFormatFs @@ -0,0 +1,25 @@ +#!/usr/bin/python3 + +import sys +import argparse +from SystemLib import ogHelp +from FileSystemLib import ogFormatFs + +parser = argparse.ArgumentParser (add_help=False) +parser.add_argument ('disk') +parser.add_argument ('par') +parser.add_argument ('type', nargs='?', default=None) +parser.add_argument ('label', nargs='?', default=None) + +if 2 == len (sys.argv) and 'help' == sys.argv[1]: + #parser.print_help() sale en inglés aunque la locale indique otra cosa + ogHelp ('ogFormatFs', 'ogFormatFs int_ndisk int_nfilesys [str_label]', ['ogFormatFs 1 1', 'ogFormatFs 1 1 EXT4', 'ogFormatFs 1 1 DATA', 'ogFormatFs 1 1 EXT4 DATA']) + sys.exit (0) + +args = parser.parse_args() + +ret = ogFormatFs (args.disk, args.par, args.type, args.label) +if ret is not None: + if ret == True: sys.exit (0) + elif ret == False: sys.exit (1) + else: print (ret) diff --git a/client/shared/functions/ogGetHivePath b/client/shared/functions/ogGetHivePath new file mode 100755 index 0000000..ebac741 --- /dev/null +++ b/client/shared/functions/ogGetHivePath @@ -0,0 +1,23 @@ +#!/usr/bin/python3 + +import sys +import argparse +from SystemLib import ogHelp +from RegistryLib import ogGetHivePath + +parser = argparse.ArgumentParser (add_help=False) +parser.add_argument ('mntpt') +parser.add_argument ('hive') + +if 2 == len (sys.argv) and 'help' == sys.argv[1]: + #parser.print_help() sale en inglés aunque la locale indique otra cosa + ogHelp ('ogGetHivePath', 'ogGetHivePath path_mountpoint [str_hive|str_user]', ['ogGetHivePath /mnt/sda1 SOFTWARE', 'ogGetHivePath /mnt/sda1 user1']) + sys.exit (0) + +args = parser.parse_args() + +ret = ogGetHivePath (args.mntpt, args.hive) +if ret is not None: + if ret == True: sys.exit (0) + elif ret == False: sys.exit (1) + else: print (ret) diff --git a/client/shared/functions/ogGetRegistryValue b/client/shared/functions/ogGetRegistryValue new file mode 100755 index 0000000..c3645a5 --- /dev/null +++ b/client/shared/functions/ogGetRegistryValue @@ -0,0 +1,24 @@ +#!/usr/bin/python3 + +import sys +import argparse +from SystemLib import ogHelp +from RegistryLib import ogGetRegistryValue + +parser = argparse.ArgumentParser (add_help=False) +parser.add_argument ('mntpt') +parser.add_argument ('hive') +parser.add_argument ('k') + +if 2 == len (sys.argv) and 'help' == sys.argv[1]: + #parser.print_help() sale en inglés aunque la locale indique otra cosa + ogHelp ('ogGetRegistryValue', 'ogGetRegistryValue path_mountpoint str_hive str_valuename', [r'ogGetRegistryValue /mnt/sda1 SOFTWARE "\Microsoft\NewKey\Value1"']) + sys.exit (0) + +args = parser.parse_args() + +ret = ogGetRegistryValue (args.mntpt, args.hive, args.k) +if ret is not None: + if ret == True: sys.exit (0) + elif ret == False: sys.exit (1) + else: print (ret) diff --git a/client/shared/functions/ogInstallFirstBoot b/client/shared/functions/ogInstallFirstBoot new file mode 100755 index 0000000..ea54b00 --- /dev/null +++ b/client/shared/functions/ogInstallFirstBoot @@ -0,0 +1,24 @@ +#!/usr/bin/python3 + +import sys +import argparse +from SystemLib import ogHelp +from PostConfLib import ogInstallFirstBoot + +parser = argparse.ArgumentParser (add_help=False) +parser.add_argument ('disk') +parser.add_argument ('par') +parser.add_argument ('cmdfile') + +if 2 == len (sys.argv) and 'help' == sys.argv[1]: + #parser.print_help() sale en inglés aunque la locale indique otra cosa + ogHelp ('ogInstallFirstBoot', 'ogInstallFirstBoot int_ndisk int_npartition str_filename', ['ogInstallFirstBoot 1 1 filename.cmd']) + sys.exit (0) + +args = parser.parse_args() + +ret = ogInstallFirstBoot (args.disk, args.par, args.cmdfile) +if ret is not None: + if ret == True: sys.exit (0) + elif ret == False: sys.exit (1) + else: print (ret) diff --git a/client/shared/functions/ogInstallMiniSetup b/client/shared/functions/ogInstallMiniSetup new file mode 100755 index 0000000..4ffcec0 --- /dev/null +++ b/client/shared/functions/ogInstallMiniSetup @@ -0,0 +1,35 @@ +#!/usr/bin/python3 + +import sys +import argparse +from SystemLib import ogHelp +from PostConfLib import ogInstallMiniSetup + +if 2 == len (sys.argv) and 'help' == sys.argv[1]: + #parser.print_help() sale en inglés aunque la locale indique otra cosa + ogHelp ('ogInstallMiniSetup', 'MSG_SEE ogInstallFirstBoot ogInstallRunonce') + sys.exit (0) + +parser = argparse.ArgumentParser (add_help=False) +if 4 == len (sys.argv): + parser.add_argument ('disk') + parser.add_argument ('par') + parser.add_argument ('cmdfile') + args = parser.parse_args() + ret = ogInstallMiniSetup (args.disk, args.par, args.cmdfile) +else: + parser.add_argument ('disk') + parser.add_argument ('par') + parser.add_argument ('cmdfile') + parser.add_argument ('user', nargs='?', default=None) + parser.add_argument ('pwd', nargs='?', default=None) + parser.add_argument ('autologin', nargs='?', default=False) + parser.add_argument ('userauto', nargs='?', default=None) + parser.add_argument ('pwdauto', nargs='?', default=None) + args = parser.parse_args() + ret = ogInstallMiniSetup (args.disk, args.par, args.cmdfile, args.user, args.pwd, args.autologin, args.userauto, args.pwdauto) + +if ret is not None: + if ret == True: sys.exit (0) + elif ret == False: sys.exit (1) + else: print (ret) diff --git a/client/shared/functions/ogInstallRunonce b/client/shared/functions/ogInstallRunonce new file mode 100755 index 0000000..5d52354 --- /dev/null +++ b/client/shared/functions/ogInstallRunonce @@ -0,0 +1,29 @@ +#!/usr/bin/python3 + +import sys +import argparse +from SystemLib import ogHelp +from PostConfLib import ogInstallRunonce + +parser = argparse.ArgumentParser (add_help=False) +parser.add_argument ('disk') +parser.add_argument ('par') +parser.add_argument ('cmdfile') +parser.add_argument ('user') +parser.add_argument ('pwd') +parser.add_argument ('autologin') +parser.add_argument ('userauto', nargs='?', default=None) +parser.add_argument ('pwdauto', nargs='?', default=None) + +if 2 == len (sys.argv) and 'help' == sys.argv[1]: + #parser.print_help() sale en inglés aunque la locale indique otra cosa + ogHelp ('ogInstallRunonce', 'ogInstallRunonce int_ndisk int_npartition str_filename str_adm_user str_adm_password bool_autologin [str_auto_user str_auto_password]', ['ogInstallRunonce 1 1 filename.cmd administrator passadmin 1 userauto passuserauto', 'ogInstallRunonce 1 1 filename.cmd administrator passadmin 0']) + sys.exit (0) + +args = parser.parse_args() + +ret = ogInstallRunonce (args.disk, args.par, args.cmdfile, args.user, args.pwd, args.autologin, args.userauto, args.pwdauto) +if ret is not None: + if ret == True: sys.exit (0) + elif ret == False: sys.exit (1) + else: print (ret) diff --git a/client/shared/functions/ogListRegistryKeys b/client/shared/functions/ogListRegistryKeys new file mode 100755 index 0000000..c56d829 --- /dev/null +++ b/client/shared/functions/ogListRegistryKeys @@ -0,0 +1,25 @@ +#!/usr/bin/python3 + +import sys +import argparse +from SystemLib import ogHelp +from RegistryLib import ogListRegistryKeys + +parser = argparse.ArgumentParser (add_help=False) +parser.add_argument ('mntpt') +parser.add_argument ('hive') +parser.add_argument ('k') + +if 2 == len (sys.argv) and 'help' == sys.argv[1]: + #parser.print_help() sale en inglés aunque la locale indique otra cosa + ogHelp ('ogListRegistryKeys', 'ogListRegistryKeys path_mountpoint str_hive str_key', [r'ogListRegistryKeys /mnt/sda1 SOFTWARE "\Microsoft\Windows\CurrentVersion"']) + sys.exit (0) + +args = parser.parse_args() + +ret = ogListRegistryKeys (args.mntpt, args.hive, args.k) +if ret is not None: + if ret == True: sys.exit (0) + elif ret == False: sys.exit (1) + else: + for k in ret: print (k) diff --git a/client/shared/functions/ogListRegistryValues b/client/shared/functions/ogListRegistryValues new file mode 100755 index 0000000..b6dcc78 --- /dev/null +++ b/client/shared/functions/ogListRegistryValues @@ -0,0 +1,25 @@ +#!/usr/bin/python3 + +import sys +import argparse +from SystemLib import ogHelp +from RegistryLib import ogListRegistryValues + +parser = argparse.ArgumentParser (add_help=False) +parser.add_argument ('mntpt') +parser.add_argument ('hive') +parser.add_argument ('k') + +if 2 == len (sys.argv) and 'help' == sys.argv[1]: + #parser.print_help() sale en inglés aunque la locale indique otra cosa + ogHelp ('ogListRegistryValues', 'ogListRegistryValues path_mountpoint str_hive str_key', [r'ogListRegistryValues /mnt/sda1 SOFTWARE "\Microsoft\Windows\CurrentVersion"']) + sys.exit (0) + +args = parser.parse_args() + +ret = ogListRegistryValues (args.mntpt, args.hive, args.k) +if ret is not None: + if ret == True: sys.exit (0) + elif ret == False: sys.exit (1) + else: + for k in ret: print (k) diff --git a/client/shared/functions/ogMcastSyntax b/client/shared/functions/ogMcastSyntax new file mode 100755 index 0000000..a595498 --- /dev/null +++ b/client/shared/functions/ogMcastSyntax @@ -0,0 +1,34 @@ +#!/usr/bin/python3 + +import sys +import argparse +from SystemLib import ogHelp +from ProtocolLib import ogMcastSyntax + +if 2 == len (sys.argv) and 'help' == sys.argv[1]: + #parser.print_help() sale en inglés aunque la locale indique otra cosa + ogHelp ('ogMcastSyntax', 'ogMcastSyntax params', ['ogMcastSyntax SENDPARTITION str_sessionSERVER str_device str_tools str_level', 'ogMcastSyntax RECEIVERPARTITION str_sessionCLIENT str_device str_tools str_level', 'ogMcastSyntax SENDFILE str_sessionSERVER str_file', 'ogMcastSyntax RECEIVERFILE str_sessionCLIENT str_file', 'sessionServer syntax: portbase:method:mcastaddress:speed:nclients:ntimeWaitingUntilNclients', 'sessionServer example: 9000:full-duplex|half-duplex|broadcast:239.194.17.36:80M:50:60', 'sessionClient syntax: portbase', 'sessionClient example: 9000', 'sessionClient syntax: portbase:serverIP:TimeOut_session:TimeOut_transmision', 'sessionClient example: 9000:172.17.88.161:40:120']) + sys.exit (0) + +kwargs = {} +parser = argparse.ArgumentParser (add_help=False) +if 'SENDPARTITION' == sys.argv[1] or 'RECEIVERPARTITION' == sys.argv[1]: + parser.add_argument ('op') + parser.add_argument ('sess') + parser.add_argument ('device') + parser.add_argument ('tool') + parser.add_argument ('level') + args = parser.parse_args() + kwargs = { 'device': args.device, 'tool': args.tool, 'level': args.level } +elif 'SENDFILE' == sys.argv[1] or 'RECEIVERFILE' == sys.argv[1]: + parser.add_argument ('op') + parser.add_argument ('sess') + parser.add_argument ('file') + args = parser.parse_args() + kwargs = { 'file': args.file } + +ret = ogMcastSyntax (args.op, args.sess, **kwargs) +if ret is not None: + if ret == True: sys.exit (0) + elif ret == False: sys.exit (1) + else: print (ret) diff --git a/client/shared/functions/ogRestoreImage b/client/shared/functions/ogRestoreImage new file mode 100755 index 0000000..57a461c --- /dev/null +++ b/client/shared/functions/ogRestoreImage @@ -0,0 +1,25 @@ +#!/usr/bin/python3 + +import sys +import argparse +from SystemLib import ogHelp +from ImageLib import ogRestoreImage + +parser = argparse.ArgumentParser (add_help=False) +parser.add_argument ('repo') +parser.add_argument ('imgpath') +parser.add_argument ('disk') +parser.add_argument ('par') + +if 2 == len (sys.argv) and 'help' == sys.argv[1]: + #parser.print_help() sale en inglés aunque la locale indique otra cosa + ogHelp ('ogRestoreImage', 'ogRestoreImage str_repo path_image int_ndisk int_npart', ['ogRestoreImage REPO /aula1/win7 1 1']) + sys.exit (0) + +args = parser.parse_args() + +ret = ogRestoreImage (args.repo, args.imgpath, args.disk, args.par) +if ret is not None: + if ret == True: sys.exit (0) + elif ret == False: sys.exit (1) + else: print (ret) diff --git a/client/shared/functions/ogSetRegistryValue b/client/shared/functions/ogSetRegistryValue new file mode 100755 index 0000000..d13d47f --- /dev/null +++ b/client/shared/functions/ogSetRegistryValue @@ -0,0 +1,25 @@ +#!/usr/bin/python3 + +import sys +import argparse +from SystemLib import ogHelp +from RegistryLib import ogSetRegistryValue + +parser = argparse.ArgumentParser (add_help=False) +parser.add_argument ('mntpt') +parser.add_argument ('hive') +parser.add_argument ('k') +parser.add_argument ('v') + +if 2 == len (sys.argv) and 'help' == sys.argv[1]: + #parser.print_help() sale en inglés aunque la locale indique otra cosa + ogHelp ('ogSetRegistryValue', 'ogSetRegistryValue path_mountpoint str_hive str_valuename str_data', [r'ogSetRegistryValue /mnt/sda1 SOFTWARE "\Key\SubKey\StringValue" "Abcde Fghij"', r'ogSetRegistryValue /mnt/sda1 SOFTWARE "\Key\SubKey\DwordValue" 1', r'ogSetRegistryValue /mnt/sda1 SOFTWARE "\Key\SubKey\BinaryValue" "04 08 0C 10"']) + sys.exit (0) + +args = parser.parse_args() + +ret = ogSetRegistryValue (args.mntpt, args.hive, args.k, args.v) +if ret is not None: + if ret == True: sys.exit (0) + elif ret == False: sys.exit (1) + else: print (ret) diff --git a/client/shared/functions/ogSetWindowsName b/client/shared/functions/ogSetWindowsName new file mode 100755 index 0000000..d199c9d --- /dev/null +++ b/client/shared/functions/ogSetWindowsName @@ -0,0 +1,24 @@ +#!/usr/bin/python3 + +import sys +import argparse +from SystemLib import ogHelp +from BootLib import ogSetWindowsName + +parser = argparse.ArgumentParser (add_help=False) +parser.add_argument ('disk') +parser.add_argument ('par') +parser.add_argument ('name') + +if 2 == len (sys.argv) and 'help' == sys.argv[1]: + #parser.print_help() sale en inglés aunque la locale indique otra cosa + ogHelp ('ogSetWindowsName', 'ogSetWindowsName int_ndisk int_filesys str_name', ['ogSetWindowsName 1 1 PRACTICA-PC']) + sys.exit (0) + +args = parser.parse_args() + +ret = ogSetWindowsName (args.disk, args.par, args.name) +if ret is not None: + if ret == True: sys.exit (0) + elif ret == False: sys.exit (1) + else: print (ret) diff --git a/client/shared/functions/ogUcastSyntax b/client/shared/functions/ogUcastSyntax new file mode 100755 index 0000000..f360bc5 --- /dev/null +++ b/client/shared/functions/ogUcastSyntax @@ -0,0 +1,34 @@ +#!/usr/bin/python3 + +import sys +import argparse +from SystemLib import ogHelp +from ProtocolLib import ogUcastSyntax + +if 2 == len (sys.argv) and 'help' == sys.argv[1]: + #parser.print_help() sale en inglés aunque la locale indique otra cosa + ogHelp ('ogUcastSyntax', 'ogUcastSyntax params', ['ogUcastSyntax SENDPARTITION str_sessionSERVER str_device str_tools str_level', 'ogUcastSyntax RECEIVERPARTITION str_sessionCLIENT str_device str_tools str_level', 'ogUcastSyntax SENDFILE str_sessionSERVER str_file', 'ogUcastSyntax RECEIVERFILE str_sessionCLIENT str_file', 'sessionServer syntax: portbase:ipCLIENT-1:ipCLIENT-2:ipCLIENT-N', 'sessionServer example: 8000:172.17.36.11:172.17.36.12', 'sessionClient syntax: portbase:ipMASTER', 'sessionClient example: 8000:172.17.36.249']) + sys.exit (0) + +kwargs = {} +parser = argparse.ArgumentParser (add_help=False) +if 'SENDPARTITION' == sys.argv[1] or 'RECEIVERPARTITION' == sys.argv[1]: + parser.add_argument ('op') + parser.add_argument ('sess') + parser.add_argument ('device') + parser.add_argument ('tool') + parser.add_argument ('level') + args = parser.parse_args() + kwargs = { 'device': args.device, 'tool': args.tool, 'level': args.level } +elif 'SENDFILE' == sys.argv[1] or 'RECEIVERFILE' == sys.argv[1]: + parser.add_argument ('op') + parser.add_argument ('sess') + parser.add_argument ('file') + args = parser.parse_args() + kwargs = { 'file': args.file } + +ret = ogUcastSyntax (args.op, args.sess, **kwargs) +if ret is not None: + if ret == True: sys.exit (0) + elif ret == False: sys.exit (1) + else: print (ret) diff --git a/client/shared/functions/ogUninstallWindowsClient b/client/shared/functions/ogUninstallWindowsClient new file mode 100755 index 0000000..20ad443 --- /dev/null +++ b/client/shared/functions/ogUninstallWindowsClient @@ -0,0 +1,24 @@ +#!/usr/bin/python3 + +import sys +import argparse +from SystemLib import ogHelp +from PostConfLib import ogUninstallWindowsClient + +parser = argparse.ArgumentParser (add_help=False) +parser.add_argument ('disk') +parser.add_argument ('par') +parser.add_argument ('cmdfile') + +if 2 == len (sys.argv) and 'help' == sys.argv[1]: + #parser.print_help() sale en inglés aunque la locale indique otra cosa + ogHelp ('ogUninstallWindowsClient', 'ogUninstallWindowsClient int_ndisk int_filesys str_filename', ['ogUninstallWindowsClient 1 1 filename.cmd']) + sys.exit (0) + +args = parser.parse_args() + +ret = ogUninstallWindowsClient (args.disk, args.par, args.cmdfile) +if ret is not None: + if ret == True: sys.exit (0) + elif ret == False: sys.exit (1) + else: print (ret) diff --git a/client/shared/functions/ogUpdateCacheIsNecesary b/client/shared/functions/ogUpdateCacheIsNecesary new file mode 100755 index 0000000..db05cec --- /dev/null +++ b/client/shared/functions/ogUpdateCacheIsNecesary @@ -0,0 +1,24 @@ +#!/usr/bin/python3 + +import sys +import argparse +from SystemLib import ogHelp +from ProtocolLib import ogUpdateCacheIsNecesary + +parser = argparse.ArgumentParser (add_help=False) +parser.add_argument ('repo') +parser.add_argument ('file') +parser.add_argument ('proto') + +if 2 == len (sys.argv) and 'help' == sys.argv[1]: + #parser.print_help() sale en inglés aunque la locale indique otra cosa + ogHelp ('ogUpdateCacheIsNecesary', 'ogUpdateCacheIsNecesary str_repo relative_path_image [protocol|FULL]', ['ogUpdateCacheIsNecesary REPO /PS1_PH1.img UNICAST', 'ogUpdateCacheIsNecesary REPO /ogclient.sqfs FULL']) + sys.exit (0) + +args = parser.parse_args() + +ret = ogUpdateCacheIsNecesary (args.repo, args.file, args.proto) +if ret is not None: + if ret == True: sys.exit (0) + elif ret == False: sys.exit (1) + else: print (ret) diff --git a/client/shared/functions/ogWindowsBootParameters b/client/shared/functions/ogWindowsBootParameters new file mode 100755 index 0000000..3a410d9 --- /dev/null +++ b/client/shared/functions/ogWindowsBootParameters @@ -0,0 +1,23 @@ +#!/usr/bin/python3 + +import sys +import argparse +from SystemLib import ogHelp +from BootLib import ogWindowsBootParameters + +parser = argparse.ArgumentParser (add_help=False) +parser.add_argument ('disk') +parser.add_argument ('par') + +if 2 == len (sys.argv) and 'help' == sys.argv[1]: + #parser.print_help() sale en inglés aunque la locale indique otra cosa + ogHelp ('ogWindowsBootParameters', 'ogWindowsBootParameters int_ndisk int_partition', ['ogWindowsBootParameters 1 1']) + sys.exit (0) + +args = parser.parse_args() + +ret = ogWindowsBootParameters (args.disk, args.par) +if ret is not None: + if ret == True: sys.exit (0) + elif ret == False: sys.exit (1) + else: print (ret) diff --git a/client/shared/functions/ogWindowsRegisterPartition b/client/shared/functions/ogWindowsRegisterPartition new file mode 100755 index 0000000..34036bc --- /dev/null +++ b/client/shared/functions/ogWindowsRegisterPartition @@ -0,0 +1,26 @@ +#!/usr/bin/python3 + +import sys +import argparse +from SystemLib import ogHelp +from BootLib import ogWindowsRegisterPartition + +parser = argparse.ArgumentParser (add_help=False) +parser.add_argument ('registered_disk') +parser.add_argument ('registered_par') +parser.add_argument ('registered_vol') +parser.add_argument ('disk') +parser.add_argument ('par') + +if 2 == len (sys.argv) and 'help' == sys.argv[1]: + #parser.print_help() sale en inglés aunque la locale indique otra cosa + ogHelp ('ogWindowsRegisterPartition', 'ogWindowsRegisterPartition int_ndisk_TO_register int_partition_TO_register str_NewVolume int_disk int_partition', ['ogWindowsRegisterPartition 1 1 c: 1 1']) + sys.exit (0) + +args = parser.parse_args() + +ret = ogWindowsRegisterPartition (args.registered_disk, args.registered_par, args.registered_vol, args.disk, args.par) +if ret is not None: + if ret == True: sys.exit (0) + elif ret == False: sys.exit (1) + else: print (ret) From d54925252fdda28a8958c36258e44d41b5193e66 Mon Sep 17 00:00:00 2001 From: Natalia Serrano Date: Fri, 24 Jan 2025 15:41:23 +0100 Subject: [PATCH 110/167] refs #1337 add UEFI commands and a couple of fixes elsewhere --- client/lib/engine/bin/InventoryLib.py | 7 ++++-- client/lib/engine/bin/UEFILib.py | 15 ++++++------ client/shared/functions/ogGetEsp | 22 +++++++++++++++++ client/shared/functions/ogGetPath | 8 +++++-- client/shared/functions/ogNvramActiveEntry | 22 +++++++++++++++++ client/shared/functions/ogNvramAddEntry | 24 +++++++++++++++++++ client/shared/functions/ogNvramDeleteEntry | 22 +++++++++++++++++ client/shared/functions/ogNvramGetCurrent | 22 +++++++++++++++++ client/shared/functions/ogNvramGetNext | 22 +++++++++++++++++ client/shared/functions/ogNvramGetOrder | 22 +++++++++++++++++ client/shared/functions/ogNvramGetTimeout | 22 +++++++++++++++++ client/shared/functions/ogNvramInactiveEntry | 22 +++++++++++++++++ client/shared/functions/ogNvramList | 22 +++++++++++++++++ client/shared/functions/ogNvramPxeFirstEntry | 22 +++++++++++++++++ client/shared/functions/ogNvramSetNext | 22 +++++++++++++++++ client/shared/functions/ogNvramSetOrder | 16 +++++++++++++ client/shared/functions/ogNvramSetTimeout | 22 +++++++++++++++++ .../shared/functions/ogRestoreEfiBootLoader | 23 ++++++++++++++++++ 18 files changed, 346 insertions(+), 11 deletions(-) create mode 100755 client/shared/functions/ogGetEsp create mode 100755 client/shared/functions/ogNvramActiveEntry create mode 100755 client/shared/functions/ogNvramAddEntry create mode 100755 client/shared/functions/ogNvramDeleteEntry create mode 100755 client/shared/functions/ogNvramGetCurrent create mode 100755 client/shared/functions/ogNvramGetNext create mode 100755 client/shared/functions/ogNvramGetOrder create mode 100755 client/shared/functions/ogNvramGetTimeout create mode 100755 client/shared/functions/ogNvramInactiveEntry create mode 100755 client/shared/functions/ogNvramList create mode 100755 client/shared/functions/ogNvramPxeFirstEntry create mode 100755 client/shared/functions/ogNvramSetNext create mode 100755 client/shared/functions/ogNvramSetOrder create mode 100755 client/shared/functions/ogNvramSetTimeout create mode 100755 client/shared/functions/ogRestoreEfiBootLoader diff --git a/client/lib/engine/bin/InventoryLib.py b/client/lib/engine/bin/InventoryLib.py index 0788032..ac58d9e 100755 --- a/client/lib/engine/bin/InventoryLib.py +++ b/client/lib/engine/bin/InventoryLib.py @@ -375,6 +375,7 @@ def ogGetOsVersion(disk, part): 'lsval DisplayVersion', ]) version = subprocess.run (['hivexsh'], input=i, capture_output=True, text=True).stdout + version = version.replace ('\n', ' ') # Recoge el valor del número de compilación para ver si es Windows 10/11 i = '\n'.join ([ f'load {file}', @@ -398,13 +399,15 @@ def ogGetOsVersion(disk, part): if not version: type = 'WinLoader' file = FileLib.ogGetPath (file=f'{mntdir}/boot/bcd') + if not file: + file = FileLib.ogGetPath (file=f'{mntdir}/EFI/Microsoft/boot/bcd') if file: for distrib in 'Windows Recovery', 'Windows Boot': with open (file, 'rb') as fd: contents = fd.read() distrib_utf16_regex = re.sub (r'(.)', '\\1.', distrib) distrib_utf16_regex = bytes (distrib_utf16_regex, 'ascii') - if re.search (distrib_utf16, contents): + if re.search (distrib_utf16_regex, contents): version = f'{distrib} loader' # Para macOS: detectar kernel y completar con fichero plist de información del sistema. if not version: @@ -467,5 +470,5 @@ def ogGetOsVersion(disk, part): # Mostrar resultado y salir sin errores. - if version: return f"{type}: {version} {is64bit}" + if version: return f"{type}:{version} {is64bit}" return None diff --git a/client/lib/engine/bin/UEFILib.py b/client/lib/engine/bin/UEFILib.py index ecab87a..4c54401 100644 --- a/client/lib/engine/bin/UEFILib.py +++ b/client/lib/engine/bin/UEFILib.py @@ -1,4 +1,6 @@ import os.path +import re +import subprocess import shutil import ogGlobals @@ -357,7 +359,7 @@ def ogNvramPxeFirstEntry(): return True # Si la entrada ya existe la borramos. - order = [numentry] + list (filter (lambda x: x if x!=numentry else [], order)) + order = [numentry] + list (filter (lambda x: x if x!=numentry else [], o)) ogNvramSetOrder (order) return True @@ -395,7 +397,7 @@ def ogRestoreEfiBootLoader (disk, par): osversion = InventoryLib.ogGetOsVersion (disk, par) if 'Windows 1' in osversion: bootlabel = f'Part-{int(disk):02d}-{int(par):02d}' - loader = FileLib.ogGetPath (f'{mntdir}/ogBoot/bootmgfw.efi') + loader = FileLib.ogGetPath (file=f'{mntdir}/ogBoot/bootmgfw.efi') if not loader: SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTOS, f'{disk} {par} ({osversion}, EFI)') return @@ -405,7 +407,7 @@ def ogRestoreEfiBootLoader (disk, par): os.makedirs (efi_bl, exist_ok=True) shutil.copytree (os.path.dirname (loader), f'{efi_bl}/Boot', symlinks=True) shutil.copy (loader, f'{efi_bl}/Boot/ogloader.efi') - if '' != FileLib.ogGetPath (f'{efidir}/EFI/Microsoft'): + if '' != FileLib.ogGetPath (file=f'{efidir}/EFI/Microsoft'): os.rename (f'{efidir}/EFI/Microsoft', f'{efidir}/EFI/Microsoft.backup.og') return @@ -478,9 +480,8 @@ def ogNvramSetNext (entry): #*/ ## #ogNvramSetOrder (['1', '3']) def ogNvramSetOrder (order): - mntdir = FileSystemLib.ogMount (disk, par) - if not mntdir: - SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_PARTITION, f'{disk} {par}') + if not InventoryLib.ogIsEfiActive(): + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTUEFI, '') return try: @@ -501,7 +502,7 @@ def ogNvramSetOrder (order): new_order = [] for o in order: - h = f'{int(o):04x}'.upper() + h = f'{int(o,16):05x}'.upper() if h not in numentries: SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTFOUND, f'NVRAM entry order "{h}"') return diff --git a/client/shared/functions/ogGetEsp b/client/shared/functions/ogGetEsp new file mode 100755 index 0000000..3431956 --- /dev/null +++ b/client/shared/functions/ogGetEsp @@ -0,0 +1,22 @@ +#!/usr/bin/python3 + +import sys +import argparse +from SystemLib import ogHelp +from DiskLib import ogGetEsp + +parser = argparse.ArgumentParser (add_help=False) + + +if 2 == len (sys.argv) and 'help' == sys.argv[1]: + #parser.print_help() sale en inglés aunque la locale indique otra cosa + ogHelp ('ogGetEsp') + sys.exit (0) + +args = parser.parse_args() + +ret = ogGetEsp () +if ret is not None: + if ret == True: sys.exit (0) + elif ret == False: sys.exit (1) + else: print (ret) diff --git a/client/shared/functions/ogGetPath b/client/shared/functions/ogGetPath index 457b448..d40cc5e 100755 --- a/client/shared/functions/ogGetPath +++ b/client/shared/functions/ogGetPath @@ -11,7 +11,9 @@ if 2 == len (sys.argv) and 'help' == sys.argv[1]: sys.exit (0) parser = argparse.ArgumentParser (add_help=False) -if 3 == len (sys.argv): +if 2 == len (sys.argv): + parser.add_argument ('file', nargs='?', default=None) +elif 3 == len (sys.argv): parser.add_argument ('src', nargs='?', default=None) parser.add_argument ('file', nargs='?', default=None) elif 4 == len (sys.argv): @@ -21,7 +23,9 @@ elif 4 == len (sys.argv): args = parser.parse_args() -if 3 == len (sys.argv): +if 2 == len (sys.argv): + ret = ogGetPath (file=args.file) +elif 3 == len (sys.argv): ret = ogGetPath (src=args.src, file=args.file) elif 4 == len (sys.argv): ret = ogGetPath (src=f'{args.disk} {args.par}', file=args.file) diff --git a/client/shared/functions/ogNvramActiveEntry b/client/shared/functions/ogNvramActiveEntry new file mode 100755 index 0000000..9eee20a --- /dev/null +++ b/client/shared/functions/ogNvramActiveEntry @@ -0,0 +1,22 @@ +#!/usr/bin/python3 + +import sys +import argparse +from SystemLib import ogHelp +from UEFILib import ogNvramActiveEntry + +parser = argparse.ArgumentParser (add_help=False) +parser.add_argument ('entry') + +if 2 == len (sys.argv) and 'help' == sys.argv[1]: + #parser.print_help() sale en inglés aunque la locale indique otra cosa + ogHelp ('ogNvramActiveEntry', 'ogNvramActiveEntry [ Num_order_entry | Label_entry ]', ['ogNvramActiveEntry 2', 'ogNvramActiveEntry "Windows Boot Manager"']) + sys.exit (0) + +args = parser.parse_args() + +ret = ogNvramActiveEntry (args.entry) +if ret is not None: + if ret == True: sys.exit (0) + elif ret == False: sys.exit (1) + else: print (ret) diff --git a/client/shared/functions/ogNvramAddEntry b/client/shared/functions/ogNvramAddEntry new file mode 100755 index 0000000..1cffa53 --- /dev/null +++ b/client/shared/functions/ogNvramAddEntry @@ -0,0 +1,24 @@ +#!/usr/bin/python3 + +import sys +import argparse +from SystemLib import ogHelp +from UEFILib import ogNvramAddEntry + +parser = argparse.ArgumentParser (add_help=False) +parser.add_argument ('bootlbl') +parser.add_argument ('bootldr') +parser.add_argument ('nvram_set', nargs='?', default=False) + +if 2 == len (sys.argv) and 'help' == sys.argv[1]: + #parser.print_help() sale en inglés aunque la locale indique otra cosa + ogHelp ('ogNvramAddEntry', 'ogNvramAddEntry Str_label_entry Str_boot_loader [ Bool_add_bootorder ]', ['ogNvramAddEntry 1 2 TRUE', 'ogNvramAddEntry grub /EFI/grub/grubx64.efi TRUE', 'ogNvramAddEntry Windows /EFI/Microsoft/Boot/bootmgfw.efi']) + sys.exit (0) + +args = parser.parse_args() + +ret = ogNvramAddEntry (args.bootlbl, args.bootldr, args.nvram_set) +if ret is not None: + if ret == True: sys.exit (0) + elif ret == False: sys.exit (1) + else: print (ret) diff --git a/client/shared/functions/ogNvramDeleteEntry b/client/shared/functions/ogNvramDeleteEntry new file mode 100755 index 0000000..d8f7912 --- /dev/null +++ b/client/shared/functions/ogNvramDeleteEntry @@ -0,0 +1,22 @@ +#!/usr/bin/python3 + +import sys +import argparse +from SystemLib import ogHelp +from UEFILib import ogNvramDeleteEntry + +parser = argparse.ArgumentParser (add_help=False) +parser.add_argument ('entry') + +if 2 == len (sys.argv) and 'help' == sys.argv[1]: + #parser.print_help() sale en inglés aunque la locale indique otra cosa + ogHelp ('ogNvramDeleteEntry', 'ogNvramDeleteEntry [ Num_order_entry | Label_entry ]', ['ogNvramDeleteEntry 2', 'ogNvramAddEntry "Windows Boot Manager"']) + sys.exit (0) + +args = parser.parse_args() + +ret = ogNvramDeleteEntry (args.entry) +if ret is not None: + if ret == True: sys.exit (0) + elif ret == False: sys.exit (1) + else: print (ret) diff --git a/client/shared/functions/ogNvramGetCurrent b/client/shared/functions/ogNvramGetCurrent new file mode 100755 index 0000000..c2a393d --- /dev/null +++ b/client/shared/functions/ogNvramGetCurrent @@ -0,0 +1,22 @@ +#!/usr/bin/python3 + +import sys +import argparse +from SystemLib import ogHelp +from UEFILib import ogNvramGetCurrent + +parser = argparse.ArgumentParser (add_help=False) + + +if 2 == len (sys.argv) and 'help' == sys.argv[1]: + #parser.print_help() sale en inglés aunque la locale indique otra cosa + ogHelp ('ogNvramGetCurrent') + sys.exit (0) + +args = parser.parse_args() + +ret = ogNvramGetCurrent () +if ret is not None: + if ret == True: sys.exit (0) + elif ret == False: sys.exit (1) + else: print (ret) diff --git a/client/shared/functions/ogNvramGetNext b/client/shared/functions/ogNvramGetNext new file mode 100755 index 0000000..4cacb1d --- /dev/null +++ b/client/shared/functions/ogNvramGetNext @@ -0,0 +1,22 @@ +#!/usr/bin/python3 + +import sys +import argparse +from SystemLib import ogHelp +from UEFILib import ogNvramGetNext + +parser = argparse.ArgumentParser (add_help=False) + + +if 2 == len (sys.argv) and 'help' == sys.argv[1]: + #parser.print_help() sale en inglés aunque la locale indique otra cosa + ogHelp ('ogNvramGetNext') + sys.exit (0) + +args = parser.parse_args() + +ret = ogNvramGetNext () +if ret is not None: + if ret == True: sys.exit (0) + elif ret == False: sys.exit (1) + else: print (ret) diff --git a/client/shared/functions/ogNvramGetOrder b/client/shared/functions/ogNvramGetOrder new file mode 100755 index 0000000..ef80387 --- /dev/null +++ b/client/shared/functions/ogNvramGetOrder @@ -0,0 +1,22 @@ +#!/usr/bin/python3 + +import sys +import argparse +from SystemLib import ogHelp +from UEFILib import ogNvramGetOrder + +parser = argparse.ArgumentParser (add_help=False) + + +if 2 == len (sys.argv) and 'help' == sys.argv[1]: + #parser.print_help() sale en inglés aunque la locale indique otra cosa + ogHelp ('ogNvramGetOrder') + sys.exit (0) + +args = parser.parse_args() + +ret = ogNvramGetOrder () +if ret is not None: + if ret == True: sys.exit (0) + elif ret == False: sys.exit (1) + else: print (','.join (ret)) diff --git a/client/shared/functions/ogNvramGetTimeout b/client/shared/functions/ogNvramGetTimeout new file mode 100755 index 0000000..15d1e8d --- /dev/null +++ b/client/shared/functions/ogNvramGetTimeout @@ -0,0 +1,22 @@ +#!/usr/bin/python3 + +import sys +import argparse +from SystemLib import ogHelp +from UEFILib import ogNvramGetTimeout + +parser = argparse.ArgumentParser (add_help=False) + + +if 2 == len (sys.argv) and 'help' == sys.argv[1]: + #parser.print_help() sale en inglés aunque la locale indique otra cosa + ogHelp ('ogNvramGetTimeout') + sys.exit (0) + +args = parser.parse_args() + +ret = ogNvramGetTimeout () +if ret is not None: + if ret == True: sys.exit (0) + elif ret == False: sys.exit (1) + else: print (ret) diff --git a/client/shared/functions/ogNvramInactiveEntry b/client/shared/functions/ogNvramInactiveEntry new file mode 100755 index 0000000..780213c --- /dev/null +++ b/client/shared/functions/ogNvramInactiveEntry @@ -0,0 +1,22 @@ +#!/usr/bin/python3 + +import sys +import argparse +from SystemLib import ogHelp +from UEFILib import ogNvramInactiveEntry + +parser = argparse.ArgumentParser (add_help=False) +parser.add_argument ('entry') + +if 2 == len (sys.argv) and 'help' == sys.argv[1]: + #parser.print_help() sale en inglés aunque la locale indique otra cosa + ogHelp ('ogNvramInactiveEntry', 'ogNvramInactiveEntry [ Num_order_entry | Label_entry ]', ['ogNvramInactiveEntry 2', 'ogNvramInactiveEntry "Windows Boot Manager"']) + sys.exit (0) + +args = parser.parse_args() + +ret = ogNvramInactiveEntry (args.entry) +if ret is not None: + if ret == True: sys.exit (0) + elif ret == False: sys.exit (1) + else: print (ret) diff --git a/client/shared/functions/ogNvramList b/client/shared/functions/ogNvramList new file mode 100755 index 0000000..d44c974 --- /dev/null +++ b/client/shared/functions/ogNvramList @@ -0,0 +1,22 @@ +#!/usr/bin/python3 + +import sys +import argparse +from SystemLib import ogHelp +from UEFILib import ogNvramList + +parser = argparse.ArgumentParser (add_help=False) + + +if 2 == len (sys.argv) and 'help' == sys.argv[1]: + #parser.print_help() sale en inglés aunque la locale indique otra cosa + ogHelp ('ogNvramList') + sys.exit (0) + +args = parser.parse_args() + +ret = ogNvramList () +if ret is not None: + if ret == True: sys.exit (0) + elif ret == False: sys.exit (1) + else: print (ret) diff --git a/client/shared/functions/ogNvramPxeFirstEntry b/client/shared/functions/ogNvramPxeFirstEntry new file mode 100755 index 0000000..208328e --- /dev/null +++ b/client/shared/functions/ogNvramPxeFirstEntry @@ -0,0 +1,22 @@ +#!/usr/bin/python3 + +import sys +import argparse +from SystemLib import ogHelp +from UEFILib import ogNvramPxeFirstEntry + +parser = argparse.ArgumentParser (add_help=False) + + +if 2 == len (sys.argv) and 'help' == sys.argv[1]: + #parser.print_help() sale en inglés aunque la locale indique otra cosa + ogHelp ('ogNvramPxeFirstEntry') + sys.exit (0) + +args = parser.parse_args() + +ret = ogNvramPxeFirstEntry () +if ret is not None: + if ret == True: sys.exit (0) + elif ret == False: sys.exit (1) + else: print (ret) diff --git a/client/shared/functions/ogNvramSetNext b/client/shared/functions/ogNvramSetNext new file mode 100755 index 0000000..7c8ee3d --- /dev/null +++ b/client/shared/functions/ogNvramSetNext @@ -0,0 +1,22 @@ +#!/usr/bin/python3 + +import sys +import argparse +from SystemLib import ogHelp +from UEFILib import ogNvramSetNext + +parser = argparse.ArgumentParser (add_help=False) +parser.add_argument ('entry') + +if 2 == len (sys.argv) and 'help' == sys.argv[1]: + #parser.print_help() sale en inglés aunque la locale indique otra cosa + ogHelp ('ogNvramSetNext', 'ogNvramSetNext [ Num_order_entry | Label_entry ]', ['ogNvramSetNext 2', 'ogNvramSetNext "Windows Boot Manager"']) + sys.exit (0) + +args = parser.parse_args() + +ret = ogNvramSetNext (args.entry) +if ret is not None: + if ret == True: sys.exit (0) + elif ret == False: sys.exit (1) + else: print (ret) diff --git a/client/shared/functions/ogNvramSetOrder b/client/shared/functions/ogNvramSetOrder new file mode 100755 index 0000000..13c22b4 --- /dev/null +++ b/client/shared/functions/ogNvramSetOrder @@ -0,0 +1,16 @@ +#!/usr/bin/python3 + +import sys +from SystemLib import ogHelp +from UEFILib import ogNvramSetOrder + +if 2 == len (sys.argv) and 'help' == sys.argv[1]: + #parser.print_help() sale en inglés aunque la locale indique otra cosa + ogHelp ('ogNvramSetOrder', 'ogNvramSetOrder Num_order1 [ Num_order2 ] ...', ['ogNvramSetOrder 1 3']) + sys.exit (0) + +ret = ogNvramSetOrder (sys.argv[1:]) +if ret is not None: + if ret == True: sys.exit (0) + elif ret == False: sys.exit (1) + else: print (ret) diff --git a/client/shared/functions/ogNvramSetTimeout b/client/shared/functions/ogNvramSetTimeout new file mode 100755 index 0000000..d54f89a --- /dev/null +++ b/client/shared/functions/ogNvramSetTimeout @@ -0,0 +1,22 @@ +#!/usr/bin/python3 + +import sys +import argparse +from SystemLib import ogHelp +from UEFILib import ogNvramSetTimeout + +parser = argparse.ArgumentParser (add_help=False) +parser.add_argument ('t') + +if 2 == len (sys.argv) and 'help' == sys.argv[1]: + #parser.print_help() sale en inglés aunque la locale indique otra cosa + ogHelp ('ogNvramSetTimeout', 'ogNvramSetTimeout int_Timeout (seg)', ['ogNvramSetTimeout 2']) + sys.exit (0) + +args = parser.parse_args() + +ret = ogNvramSetTimeout (args.t) +if ret is not None: + if ret == True: sys.exit (0) + elif ret == False: sys.exit (1) + else: print (ret) diff --git a/client/shared/functions/ogRestoreEfiBootLoader b/client/shared/functions/ogRestoreEfiBootLoader new file mode 100755 index 0000000..7e72e37 --- /dev/null +++ b/client/shared/functions/ogRestoreEfiBootLoader @@ -0,0 +1,23 @@ +#!/usr/bin/python3 + +import sys +import argparse +from SystemLib import ogHelp +from UEFILib import ogRestoreEfiBootLoader + +parser = argparse.ArgumentParser (add_help=False) +parser.add_argument ('disk') +parser.add_argument ('par') + +if 2 == len (sys.argv) and 'help' == sys.argv[1]: + #parser.print_help() sale en inglés aunque la locale indique otra cosa + ogHelp ('ogRestoreEfiBootLoader', 'ogRestoreEfiBootLoader int_ndisk int_part', ['ogRestoreEfiBootLoader 1 2']) + sys.exit (0) + +args = parser.parse_args() + +ret = ogRestoreEfiBootLoader (args.disk, args.par) +if ret is not None: + if ret == True: sys.exit (0) + elif ret == False: sys.exit (1) + else: print (ret) From 87357f4f8edfdc13279be4e6d7276a35cbb61c74 Mon Sep 17 00:00:00 2001 From: Natalia Serrano Date: Mon, 27 Jan 2025 14:52:28 +0100 Subject: [PATCH 111/167] refs #1337 add ucast/mcast functions --- client/interfaceAdm/Apagar.py | 1 + client/interfaceAdm/Configurar.py | 1 + client/interfaceAdm/ConsolaRemota.py | 3 +- client/interfaceAdm/CrearImagen.py | 1 + client/interfaceAdm/EjecutarScript.py | 1 + client/interfaceAdm/GetConfiguration.py | 1 + client/interfaceAdm/IniciarSesion.py | 3 +- client/interfaceAdm/InventarioHardware.py | 1 + client/interfaceAdm/InventarioSoftware.py | 3 +- client/interfaceAdm/Reiniciar.py | 1 + client/interfaceAdm/RestaurarImagen.py | 1 + client/interfaceAdm/getConfiguration.py | 3 +- client/interfaceAdm/getIpAddress.py | 3 +- client/interfaceAdm/procesaCache.py | 3 +- client/lib/engine/bin/FileSystemLib.py | 31 +++++++------ client/lib/engine/bin/ProtocolLib.py | 36 --------------- client/shared/functions/ogCreateTorrent | 31 +++++++++++++ client/shared/functions/ogMcastReceiverFile | 39 ++++++++++++++++ .../shared/functions/ogMcastReceiverPartition | 26 +++++++++++ client/shared/functions/ogMcastSendFile | 46 +++++++++++++++++++ client/shared/functions/ogMcastSendPartition | 26 +++++++++++ client/shared/functions/ogMountCdrom | 22 +++++++++ .../shared/functions/ogUcastReceiverPartition | 26 +++++++++++ client/shared/functions/ogUcastSendPartition | 26 +++++++++++ 24 files changed, 278 insertions(+), 57 deletions(-) create mode 100755 client/shared/functions/ogCreateTorrent create mode 100755 client/shared/functions/ogMcastReceiverFile create mode 100755 client/shared/functions/ogMcastReceiverPartition create mode 100755 client/shared/functions/ogMcastSendFile create mode 100755 client/shared/functions/ogMcastSendPartition create mode 100755 client/shared/functions/ogMountCdrom create mode 100755 client/shared/functions/ogUcastReceiverPartition create mode 100755 client/shared/functions/ogUcastSendPartition diff --git a/client/interfaceAdm/Apagar.py b/client/interfaceAdm/Apagar.py index 2d1598f..eafc875 100755 --- a/client/interfaceAdm/Apagar.py +++ b/client/interfaceAdm/Apagar.py @@ -1,3 +1,4 @@ +#!/usr/bin/env python3 import os import sys diff --git a/client/interfaceAdm/Configurar.py b/client/interfaceAdm/Configurar.py index 1ae34d2..fbe8aaa 100755 --- a/client/interfaceAdm/Configurar.py +++ b/client/interfaceAdm/Configurar.py @@ -1,3 +1,4 @@ +#!/usr/bin/env python3 import os import sys import subprocess diff --git a/client/interfaceAdm/ConsolaRemota.py b/client/interfaceAdm/ConsolaRemota.py index 99b4c6e..f0bf848 100755 --- a/client/interfaceAdm/ConsolaRemota.py +++ b/client/interfaceAdm/ConsolaRemota.py @@ -1,3 +1,4 @@ +#!/usr/bin/env python3 import os import sys import subprocess @@ -25,4 +26,4 @@ if __name__ == "__main__": script_path = sys.argv[1] output_path = sys.argv[2] - main(script_path, output_path) \ No newline at end of file + main(script_path, output_path) diff --git a/client/interfaceAdm/CrearImagen.py b/client/interfaceAdm/CrearImagen.py index 443df8e..29628e0 100755 --- a/client/interfaceAdm/CrearImagen.py +++ b/client/interfaceAdm/CrearImagen.py @@ -1,3 +1,4 @@ +#!/usr/bin/env python3 import os import subprocess import sys diff --git a/client/interfaceAdm/EjecutarScript.py b/client/interfaceAdm/EjecutarScript.py index 7e72861..35dde8d 100755 --- a/client/interfaceAdm/EjecutarScript.py +++ b/client/interfaceAdm/EjecutarScript.py @@ -1,3 +1,4 @@ +#!/usr/bin/env python3 import os import time import subprocess diff --git a/client/interfaceAdm/GetConfiguration.py b/client/interfaceAdm/GetConfiguration.py index b5d1b49..eabf97c 100755 --- a/client/interfaceAdm/GetConfiguration.py +++ b/client/interfaceAdm/GetConfiguration.py @@ -1,3 +1,4 @@ +#!/usr/bin/env python3 import os import subprocess import sys diff --git a/client/interfaceAdm/IniciarSesion.py b/client/interfaceAdm/IniciarSesion.py index 86968d0..48aa5d5 100755 --- a/client/interfaceAdm/IniciarSesion.py +++ b/client/interfaceAdm/IniciarSesion.py @@ -1,3 +1,4 @@ +#!/usr/bin/env python3 import sys import subprocess @@ -14,4 +15,4 @@ def main(): boot_os(disk, part) if __name__ == "__main__": - main() \ No newline at end of file + main() diff --git a/client/interfaceAdm/InventarioHardware.py b/client/interfaceAdm/InventarioHardware.py index 5793bfe..bb1188d 100755 --- a/client/interfaceAdm/InventarioHardware.py +++ b/client/interfaceAdm/InventarioHardware.py @@ -1,3 +1,4 @@ +#!/usr/bin/env python3 import subprocess import sys diff --git a/client/interfaceAdm/InventarioSoftware.py b/client/interfaceAdm/InventarioSoftware.py index 4c9c316..29f3420 100755 --- a/client/interfaceAdm/InventarioSoftware.py +++ b/client/interfaceAdm/InventarioSoftware.py @@ -1,3 +1,4 @@ +#!/usr/bin/env python3 import os import time import shutil @@ -49,4 +50,4 @@ 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 + main(sys.argv[1], sys.argv[2], sys.argv[3]) diff --git a/client/interfaceAdm/Reiniciar.py b/client/interfaceAdm/Reiniciar.py index 53e9ce1..f1b0e25 100755 --- a/client/interfaceAdm/Reiniciar.py +++ b/client/interfaceAdm/Reiniciar.py @@ -1,3 +1,4 @@ +#!/usr/bin/env python3 import os def reboot_system(): diff --git a/client/interfaceAdm/RestaurarImagen.py b/client/interfaceAdm/RestaurarImagen.py index b3716cc..a5fda6c 100755 --- a/client/interfaceAdm/RestaurarImagen.py +++ b/client/interfaceAdm/RestaurarImagen.py @@ -1,3 +1,4 @@ +#!/usr/bin/env python3 import sys import subprocess diff --git a/client/interfaceAdm/getConfiguration.py b/client/interfaceAdm/getConfiguration.py index 74efdbe..89a1b0a 100755 --- a/client/interfaceAdm/getConfiguration.py +++ b/client/interfaceAdm/getConfiguration.py @@ -1,3 +1,4 @@ +#!/usr/bin/env python3 import os import subprocess @@ -76,4 +77,4 @@ def main(): os.environ.pop("DEBUG", None) if __name__ == "__main__": - main() \ No newline at end of file + main() diff --git a/client/interfaceAdm/getIpAddress.py b/client/interfaceAdm/getIpAddress.py index 7549c60..0ba1389 100755 --- a/client/interfaceAdm/getIpAddress.py +++ b/client/interfaceAdm/getIpAddress.py @@ -1,6 +1,5 @@ -import socket - #!/usr/bin/env python3 +import socket def get_ip_address(): hostname = socket.gethostname() diff --git a/client/interfaceAdm/procesaCache.py b/client/interfaceAdm/procesaCache.py index 7280394..a5eb168 100755 --- a/client/interfaceAdm/procesaCache.py +++ b/client/interfaceAdm/procesaCache.py @@ -1,3 +1,4 @@ +#!/usr/bin/env python3 import sys if __name__ == "__main__": @@ -5,4 +6,4 @@ if __name__ == "__main__": print("Usage: python procesaCache.py ") sys.exit(1) - init_cache(sys.argv[1]) \ No newline at end of file + init_cache(sys.argv[1]) diff --git a/client/lib/engine/bin/FileSystemLib.py b/client/lib/engine/bin/FileSystemLib.py index 46cba8e..570bbd8 100755 --- a/client/lib/engine/bin/FileSystemLib.py +++ b/client/lib/engine/bin/FileSystemLib.py @@ -701,22 +701,25 @@ def ogMountFs (disk, par): #@date #*/ ## def ogMountCdrom(): - DEV = "/dev/cdrom" # Por defecto - MNTDIR = subprocess.run(["mount", "-l", "-t", "iso9660", DEV], capture_output=True, text=True) - MNTDIR = MNTDIR.stdout.strip().split(" ")[2] - if not MNTDIR: - MNTDIR = DEV.replace("/dev", "/mnt") - os.makedirs(MNTDIR, exist_ok=True) + DEV = '/dev/cdrom' # Por defecto + outlines = subprocess.run (['mount'], capture_output=True, text=True).stdout.split ('\n') + mntdir = '' + for l in outlines: + items = l.split (' ') + if DEV == items[0]: + mntdir = items[2] + break + + if not mntdir: + mntdir = DEV.replace ('/dev', '/mnt') + os.makedirs (mntdir, exist_ok=True) try: - subprocess.run(["mount", "-t", "iso9660", DEV, MNTDIR], check=True, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) + subprocess.run (['mount', '-t', 'iso9660', DEV, mntdir], check=True) except subprocess.CalledProcessError: - SystemLib.ogRaiseError ( - [], - ogGlobals.OG_ERR_PARTITION, - "cdrom" - ) - return - return MNTDIR + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_PARTITION, 'cdrom') + return None + + return mntdir #/** diff --git a/client/lib/engine/bin/ProtocolLib.py b/client/lib/engine/bin/ProtocolLib.py index 425ccbd..35b8a1e 100644 --- a/client/lib/engine/bin/ProtocolLib.py +++ b/client/lib/engine/bin/ProtocolLib.py @@ -82,7 +82,6 @@ def ogUcastSyntax (op, sess, file=None, device=None, tool=None, level=None): address += f' -O {session[i]}:{portbase}' else: address = f'{session[1]}:{portbase}' - #print (f'nati mode ({mode}) address ({address})') if 'SENDPARTITION' == op: syn = ImageLib.ogCreateImageSyntax (device, ' ', tool, level) @@ -90,7 +89,6 @@ def ogUcastSyntax (op, sess, file=None, device=None, tool=None, level=None): ## otherwise, param2 in ImageLib.ogCreateImageSyntax() is not '| mbuffer' but empty ## and then parts[2] is out of range parts = syn.split ('|') - #print (f'syn ({syn}) parts ({parts})') prog1 = f'{parts[0]}|{parts[2]}'.strip() prog1 = prog1.replace ('>', '').strip() return f'{prog1} | mbuffer {address}' @@ -131,7 +129,6 @@ def ogUcastSendPartition (disk, par, sess, tool, level): cmd = ogUcastSyntax ('SENDPARTITION', sess, device=PART, tool=tool, level=level) if not cmd: return None - print (f'cmd ({cmd})') try: subprocess.run (cmd, shell=True, check=True) except subprocess.CalledProcessError: @@ -162,7 +159,6 @@ def ogUcastReceiverPartition (disk, par, sess, tool, level): cmd = ogUcastSyntax ('RECEIVERPARTITION', sess, device=PART, tool=tool, level=level) if not cmd: return None - print (f'cmd ({cmd})') try: subprocess.run (cmd, shell=True, check=True) except subprocess.CalledProcessError: @@ -203,7 +199,6 @@ def ogUcastSendFile (disk=None, par=None, container=None, file=None, sess=None): ## we were given container= source = FileLib.ogGetPath (src=container, file=file) dev_err = f'{container} {file}' - print (f'ogGetPath (src=({container}), file=({file})) = source ({source})') else: raise TypeError ('argument "container" can be specified along neither "disk" nor "par"') @@ -212,12 +207,10 @@ def ogUcastSendFile (disk=None, par=None, container=None, file=None, sess=None): ## we were given disk= par= source = FileLib.ogGetPath (src=f'{disk} {par}', file=file) dev_err = f'{disk} {par} {file}' - print (f'ogGetPath (src=({disk} {par}), file=({file})) = source ({source})') elif disk is None and par is None: ## we were given nothing source = FileLib.ogGetPath (file=file) dev_err = file - print (f'ogGetPath (file=({file})) = source ({source})') else: raise TypeError ('if one of "disk" and "par" are specified, then both must be') @@ -226,14 +219,12 @@ def ogUcastSendFile (disk=None, par=None, container=None, file=None, sess=None): return path2 = FileLib.ogGetPath (file=source) - print (f'path2 ({path2})') if not path2: SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTFOUND, f'device or file {dev_err} not found') return cmd = ogUcastSyntax ('SENDFILE', sess, file=source) if not cmd: return None - print (f'cmd ({cmd})') try: subprocess.run (cmd, shell=True, check=True) except subprocess.CalledProcessError: @@ -364,7 +355,6 @@ def ogMcastSyntax (op, sess, file=None, device=None, tool=None, level=None): if 'client' == mode: other = session[1:] - #print (f'session ({session}) other ({other})') serveraddress = other[0] if len (other) > 0 else '' starttimeout = other[1] if len (other) > 1 else '' receivertimeout = other[2] if len (other) > 2 else '' @@ -375,23 +365,16 @@ def ogMcastSyntax (op, sess, file=None, device=None, tool=None, level=None): else: repoip = NetLib.ogGetRepoIp() clientip = _clientip() - #print (f'repoip ({repoip}) clientip ({clientip})') if 1 != len (clientip): raise Exception ('more than one local IP address found') c = clientip[0] - #print (f'c ({c})') clientip = c['local'] mascara = c['prefixlen'] - #print (f'clientip ({clientip}) mascara ({mascara})') ripbt = _binary_ip (repoip) ipbt = _binary_ip (clientip) reposubred = ripbt[0:mascara] clientsubred = ipbt[0:mascara] - #print (f'ripbt ({ripbt})') - #print (f'ipbt ({ipbt})') - #print (f'reposubred ({reposubred})') - #print (f'clientsubred ({clientsubred})') if reposubred == clientsubred: serveraddress = ' ' else: serveraddress = f' --mcast-rdv-address {repoip}' @@ -419,7 +402,6 @@ def ogMcastSyntax (op, sess, file=None, device=None, tool=None, level=None): ## otherwise, param2 in ImageLib.ogCreateImageSyntax() is not '| mbuffer' but empty ## and then parts[2] is out of range parts = syn.split ('|') - #print (f'syn ({syn}) parts ({parts})') prog1 = f'{parts[0]}|{parts[2]}'.strip() prog1 = prog1.replace ('>', '').strip() return f'{prog1} | {syntaxserver}' @@ -471,7 +453,6 @@ def ogMcastSendFile (disk=None, par=None, container=None, file=None, sess=None): ## we were given container= source = FileLib.ogGetPath (src=container, file=file) dev_err = f'{container} {file}' - print (f'ogGetPath (src=({container}), file=({file})) = source ({source})') else: raise TypeError ('argument "container" can be specified along neither "disk" nor "par"') @@ -480,12 +461,10 @@ def ogMcastSendFile (disk=None, par=None, container=None, file=None, sess=None): ## we were given disk= par= source = FileLib.ogGetPath (src=f'{disk} {par}', file=file) dev_err = f'{disk} {par} {file}' - print (f'ogGetPath (src=({disk} {par}), file=({file})) = source ({source})') elif disk is None and par is None: ## we were given nothing source = FileLib.ogGetPath (file=file) dev_err = file - print (f'ogGetPath (file=({file})) = source ({source})') else: raise TypeError ('if one of "disk" and "par" are specified, then both must be') @@ -494,14 +473,12 @@ def ogMcastSendFile (disk=None, par=None, container=None, file=None, sess=None): return path2 = FileLib.ogGetPath (file=source) - print (f'path2 ({path2})') if not path2: SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTFOUND, f'device or file {dev_err} not found') return cmd = ogMcastSyntax ('SENDFILE', sess, file=source) if not cmd: return None - print (f'cmd ({cmd})') try: subprocess.run (cmd, shell=True, check=True) except subprocess.CalledProcessError: @@ -538,7 +515,6 @@ def ogMcastReceiverFile (disk=None, par=None, container=None, file=None, sess=No ## we were given container= targetdir = FileLib.ogGetParentPath (src=container, file=file) dev_err = f'{container} {file}' - print (f'ogGetParentPath (src=({container}), file=({file})) = targetdir ({targetdir})') else: raise TypeError ('argument "container" can be specified along neither "disk" nor "par"') @@ -547,12 +523,10 @@ def ogMcastReceiverFile (disk=None, par=None, container=None, file=None, sess=No ## we were given disk= par= targetdir = FileLib.ogGetParentPath (src=f'{disk} {par}', file=file) dev_err = f'{disk} {par} {file}' - print (f'ogGetParentPath (src=({disk} {par}), file=({file})) = targetdir ({targetdir})') elif disk is None and par is None: ## we were given nothing targetdir = FileLib.ogGetParentPath (file=file) dev_err = file - print (f'ogGetParentPath (file=({file})) = targetdir ({targetdir})') else: raise TypeError ('if one of "disk" and "par" are specified, then both must be') @@ -561,11 +535,9 @@ def ogMcastReceiverFile (disk=None, par=None, container=None, file=None, sess=No return targetfile = os.path.basename (file) - print (f'targetfile ({targetfile})') cmd = ogMcastSyntax ('RECEIVERFILE', sess, file=os.path.join (targetdir, targetfile)) if not cmd: return None - print (f'cmd ({cmd})') try: subprocess.run (cmd, shell=True, check=True) except subprocess.CalledProcessError: @@ -597,7 +569,6 @@ def ogMcastSendPartition (disk, par, sess, tool, compressor): FileSystemLib.ogUnmount (disk, par) cmd = ogMcastSyntax ('SENDPARTITION', sess, device=PART, tool=tool, level=compressor) if not cmd: return None - print (f'cmd ({cmd})') try: subprocess.run (cmd, shell=True, check=True) except subprocess.CalledProcessError: @@ -622,7 +593,6 @@ def ogMcastReceiverPartition (disk, par, sess, tool, compressor): FileSystemLib.ogUnmount (disk, par) cmd = ogMcastSyntax ('RECEIVERPARTITION', sess, device=PART, tool=tool, level=compressor) if not cmd: return None - print (f'cmd ({cmd})') try: subprocess.run (cmd, shell=True, check=True) except subprocess.CalledProcessError: @@ -673,7 +643,6 @@ def ogTorrentStart (disk=None, par=None, container=None, torrentfile=None, torre return None source = FileLib.ogGetPath (src=container, file=torrentfile) dev_err = f'{container} {torrentfile}' - print (f'ogGetPath (src=({container}), file=({torrentfile})) = source ({source})') else: raise TypeError ('argument "container" can be specified along neither "disk" nor "par"') @@ -682,7 +651,6 @@ def ogTorrentStart (disk=None, par=None, container=None, torrentfile=None, torre ## we were given disk= par= source = FileLib.ogGetPath (src=f'{disk} {par}', file=torrentfile) dev_err = f'{disk} {par} {torrentfile}' - print (f'ogGetPath (src=({disk} {par}), file=({torrentfile})) = source ({source})') elif disk is None and par is None: ## we were given nothing if torrentfile.startswith ('/opt/opengnsys/images'): @@ -690,7 +658,6 @@ def ogTorrentStart (disk=None, par=None, container=None, torrentfile=None, torre return None source = FileLib.ogGetPath (file=torrentfile) dev_err = torrentfile - print (f'ogGetPath (file=({torrentfile})) = source ({source})') else: raise TypeError ('if one of "disk" and "par" are specified, then both must be') @@ -805,7 +772,6 @@ def ogCreateTorrent (disk=None, par=None, container=None, file=None, ip_bttrack= return f = f'{file}.{ext}' source = FileLib.ogGetPath (src=container, file=f) - print (f'ogGetPath (src=({container}), file=({f})) = source ({source})') else: raise TypeError ('argument "container" can be specified along neither "disk" nor "par"') @@ -814,12 +780,10 @@ def ogCreateTorrent (disk=None, par=None, container=None, file=None, ip_bttrack= ## we were given disk= par= f = f'{file}.img' source = FileLib.ogGetPath (src=f'{disk} {par}', file=f) - print (f'ogGetPath (src=({disk} {par}), file=({f})) = source ({source})') elif disk is None and par is None: ## we were given nothing f = f'{file}.img' source = FileLib.ogGetPath (file=f) - print (f'ogGetPath (file=({f})) = source ({source})') else: raise TypeError ('if one of "disk" and "par" are specified, then both must be') diff --git a/client/shared/functions/ogCreateTorrent b/client/shared/functions/ogCreateTorrent new file mode 100755 index 0000000..409bd31 --- /dev/null +++ b/client/shared/functions/ogCreateTorrent @@ -0,0 +1,31 @@ +#!/usr/bin/python3 + +import sys +import argparse +from SystemLib import ogHelp +from ProtocolLib import ogCreateTorrent + +if 2 == len (sys.argv) and 'help' == sys.argv[1]: + #parser.print_help() sale en inglés aunque la locale indique otra cosa + ogHelp ('ogCreateTorrent', 'ogCreateTorrent [str_REPOSITORY] [int_ndisk int_npart] Relative_path_file IpBttrack', ['ogCreateTorrent 1 1 /aula1/winxp 10.1.15.23', 'ogCreateTorrent REPO /aula1/winxp 10.1.15.45']) + sys.exit (0) + +parser = argparse.ArgumentParser (add_help=False) +if 4 == len (sys.argv): + parser.add_argument ('container') +elif 5 == len (sys.argv): + parser.add_argument ('disk') + parser.add_argument ('par') + +parser.add_argument ('file') +parser.add_argument ('ip_bttrack') +args = parser.parse_args() + +if 4 == len (sys.argv): + ret = ogCreateTorrent (container=args.container, file=args.file, ip_bttrack=args.ip_bttrack) +elif 5 == len (sys.argv): + ret = ogCreateTorrent (disk=args.disk, par=args.par, file=args.file, ip_bttrack=args.ip_bttrack) +if ret is not None: + if ret == True: sys.exit (0) + elif ret == False: sys.exit (1) + else: print (ret) diff --git a/client/shared/functions/ogMcastReceiverFile b/client/shared/functions/ogMcastReceiverFile new file mode 100755 index 0000000..2b33ac2 --- /dev/null +++ b/client/shared/functions/ogMcastReceiverFile @@ -0,0 +1,39 @@ +#!/usr/bin/python3 + +import sys +import argparse +from SystemLib import ogHelp +from ProtocolLib import ogMcastReceiverFile + +if 2 == len (sys.argv) and 'help' == sys.argv[1]: + #parser.print_help() sale en inglés aunque la locale indique otra cosa + ogHelp ('ogMcastReceiverFile', 'ogMcastReceiverFile [ str_portMcast] [ [Relative_path_file] | [str_REPOSITORY path_file] | [int_ndisk int_npart path_file ] ]', ['ogMcastReceiverFile 9000 /PS1_PH1.img', 'ogMcastReceiverFile 9000 CACHE /aula1/PS2_PH4.img', 'ogMcastReceiverFile 9000 1 1 /isos/linux.iso']) + sys.exit (0) + +parser = argparse.ArgumentParser (add_help=False) +if 3 == len (sys.argv): + parser.add_argument ('sess', nargs='?', default=None) + parser.add_argument ('file', nargs='?', default=None) +elif 4 == len (sys.argv): + parser.add_argument ('sess', nargs='?', default=None) + parser.add_argument ('container', nargs='?', default=None) + parser.add_argument ('file', nargs='?', default=None) +elif 5 == len (sys.argv): + parser.add_argument ('sess', nargs='?', default=None) + parser.add_argument ('disk', nargs='?', default=None) + parser.add_argument ('par', nargs='?', default=None) + parser.add_argument ('file', nargs='?', default=None) + +args = parser.parse_args() + +if 3 == len (sys.argv): + ret = ogMcastReceiverFile (file=args.file, sess=args.sess) +elif 4 == len (sys.argv): + ret = ogMcastReceiverFile (container=args.container, file=args.file, sess=args.sess) +elif 5 == len (sys.argv): + ret = ogMcastReceiverFile (disk=args.disk, par=args.par, file=args.file, sess=args.sess) + +if ret is not None: + if ret == True: sys.exit (0) + elif ret == False: sys.exit (1) + else: print (ret) diff --git a/client/shared/functions/ogMcastReceiverPartition b/client/shared/functions/ogMcastReceiverPartition new file mode 100755 index 0000000..45a8763 --- /dev/null +++ b/client/shared/functions/ogMcastReceiverPartition @@ -0,0 +1,26 @@ +#!/usr/bin/python3 + +import sys +import argparse +from SystemLib import ogHelp +from ProtocolLib import ogMcastReceiverPartition + +parser = argparse.ArgumentParser (add_help=False) +parser.add_argument ('disk') +parser.add_argument ('par') +parser.add_argument ('sess') +parser.add_argument ('tool') +parser.add_argument ('compressor') + +if 2 == len (sys.argv) and 'help' == sys.argv[1]: + #parser.print_help() sale en inglés aunque la locale indique otra cosa + ogHelp ('ogMcastReceiverPartition', 'ogMcastReceiverPartition int_ndisk int_npart SessionMulticastCLIENT tools compresor', ['ogMcastReceiverPartition 1 1 9000 partclone lzop']) + sys.exit (0) + +args = parser.parse_args() + +ret = ogMcastReceiverPartition (args.disk, args.par, args.sess, args.tool, args.compressor) +if ret is not None: + if ret == True: sys.exit (0) + elif ret == False: sys.exit (1) + else: print (ret) diff --git a/client/shared/functions/ogMcastSendFile b/client/shared/functions/ogMcastSendFile new file mode 100755 index 0000000..7ed75ed --- /dev/null +++ b/client/shared/functions/ogMcastSendFile @@ -0,0 +1,46 @@ +#!/usr/bin/python3 + +import sys +import argparse +from SystemLib import ogHelp +from ProtocolLib import ogMcastSendFile + +parser = argparse.ArgumentParser (add_help=False) +parser.add_argument ('disk', nargs='?', default=None) +parser.add_argument ('par', nargs='?', default=None) +parser.add_argument ('container', nargs='?', default=None) +parser.add_argument ('file', nargs='?', default=None) +parser.add_argument ('sess', nargs='?', default=None) + +if 2 == len (sys.argv) and 'help' == sys.argv[1]: + #parser.print_help() sale en inglés aunque la locale indique otra cosa + ogHelp ('ogMcastSendFile', 'ogMcastSendFile [str_REPOSITORY] [int_ndisk int_npart] /Relative_path_file sesionMcast', ['ogMcastSendFile 1 1 /aula1/winxp.img sesionMcast', 'ogMcastSendFile REPO /aula1/ubuntu.iso sesionMcast', 'ogMcastSendFile CACHE /aula1/winxp.img sesionMcast', 'ogMcastSendFile /opt/opengnsys/images/aula1/hd500.vmx sesionMcast']) + sys.exit (0) + +parser = argparse.ArgumentParser (add_help=False) +if 3 == len (sys.argv): + parser.add_argument ('file', nargs='?', default=None) + parser.add_argument ('sess', nargs='?', default=None) +elif 4 == len (sys.argv): + parser.add_argument ('container', nargs='?', default=None) + parser.add_argument ('file', nargs='?', default=None) + parser.add_argument ('sess', nargs='?', default=None) +elif 5 == len (sys.argv): + parser.add_argument ('disk', nargs='?', default=None) + parser.add_argument ('par', nargs='?', default=None) + parser.add_argument ('file', nargs='?', default=None) + parser.add_argument ('sess', nargs='?', default=None) + +args = parser.parse_args() + +if 3 == len (sys.argv): + ret = ogMcastSendFile (file=args.file, sess=args.sess) +elif 4 == len (sys.argv): + ret = ogMcastSendFile (container=args.container, file=args.file, sess=args.sess) +elif 5 == len (sys.argv): + ret = ogMcastSendFile (disk=args.disk, par=args.par, file=args.file, sess=args.sess) + +if ret is not None: + if ret == True: sys.exit (0) + elif ret == False: sys.exit (1) + else: print (ret) diff --git a/client/shared/functions/ogMcastSendPartition b/client/shared/functions/ogMcastSendPartition new file mode 100755 index 0000000..7c8ea6e --- /dev/null +++ b/client/shared/functions/ogMcastSendPartition @@ -0,0 +1,26 @@ +#!/usr/bin/python3 + +import sys +import argparse +from SystemLib import ogHelp +from ProtocolLib import ogMcastSendPartition + +parser = argparse.ArgumentParser (add_help=False) +parser.add_argument ('disk') +parser.add_argument ('par') +parser.add_argument ('sess') +parser.add_argument ('tool') +parser.add_argument ('compressor') + +if 2 == len (sys.argv) and 'help' == sys.argv[1]: + #parser.print_help() sale en inglés aunque la locale indique otra cosa + ogHelp ('ogMcastSendPartition', 'ogMcastSendPartition int_ndisk int_npart SessionMulticastSERVER tools compresor', ['ogMcastSendPartition 1 1 9000:full-duplex:239.194.37.31:50M:20:2 partclone lzop']) + sys.exit (0) + +args = parser.parse_args() + +ret = ogMcastSendPartition (args.disk, args.par, args.sess, args.tool, args.compressor) +if ret is not None: + if ret == True: sys.exit (0) + elif ret == False: sys.exit (1) + else: print (ret) diff --git a/client/shared/functions/ogMountCdrom b/client/shared/functions/ogMountCdrom new file mode 100755 index 0000000..24db5f1 --- /dev/null +++ b/client/shared/functions/ogMountCdrom @@ -0,0 +1,22 @@ +#!/usr/bin/python3 + +import sys +import argparse +from SystemLib import ogHelp +from FileSystemLib import ogMountCdrom + +parser = argparse.ArgumentParser (add_help=False) + + +if 2 == len (sys.argv) and 'help' == sys.argv[1]: + #parser.print_help() sale en inglés aunque la locale indique otra cosa + ogHelp ('ogMountCdrom', 'ogMountCdrom', ['ogMountCdrom']) + sys.exit (0) + +args = parser.parse_args() + +ret = ogMountCdrom () +if ret is not None: + if ret == True: sys.exit (0) + elif ret == False: sys.exit (1) + else: print (ret) diff --git a/client/shared/functions/ogUcastReceiverPartition b/client/shared/functions/ogUcastReceiverPartition new file mode 100755 index 0000000..31fb177 --- /dev/null +++ b/client/shared/functions/ogUcastReceiverPartition @@ -0,0 +1,26 @@ +#!/usr/bin/python3 + +import sys +import argparse +from SystemLib import ogHelp +from ProtocolLib import ogUcastReceiverPartition + +parser = argparse.ArgumentParser (add_help=False) +parser.add_argument ('disk') +parser.add_argument ('par') +parser.add_argument ('sess') +parser.add_argument ('tool') +parser.add_argument ('level') + +if 2 == len (sys.argv) and 'help' == sys.argv[1]: + #parser.print_help() sale en inglés aunque la locale indique otra cosa + ogHelp ('ogUcastReceiverPartition', 'ogUcastReceiverPartition int_ndisk int_npart SessionMulticastCLIENT tools compresor', ['ogUcastReceiverPartition 1 1 8000:ipMASTER partclone lzop']) + sys.exit (0) + +args = parser.parse_args() + +ret = ogUcastReceiverPartition (args.disk, args.par, args.sess, args.tool, args.level) +if ret is not None: + if ret == True: sys.exit (0) + elif ret == False: sys.exit (1) + else: print (ret) diff --git a/client/shared/functions/ogUcastSendPartition b/client/shared/functions/ogUcastSendPartition new file mode 100755 index 0000000..8fba6dd --- /dev/null +++ b/client/shared/functions/ogUcastSendPartition @@ -0,0 +1,26 @@ +#!/usr/bin/python3 + +import sys +import argparse +from SystemLib import ogHelp +from ProtocolLib import ogUcastSendPartition + +parser = argparse.ArgumentParser (add_help=False) +parser.add_argument ('disk') +parser.add_argument ('par') +parser.add_argument ('sess') +parser.add_argument ('tool') +parser.add_argument ('level') + +if 2 == len (sys.argv) and 'help' == sys.argv[1]: + #parser.print_help() sale en inglés aunque la locale indique otra cosa + ogHelp ('ogUcastSendPartition', 'ogUcastSendPartition int_ndisk int_npart SessionUNICAST-SERVER tools compresor', ['ogUcastSendPartition 1 1 8000:172.17.36.11:172.17.36.12 partclone lzop']) + sys.exit (0) + +args = parser.parse_args() + +ret = ogUcastSendPartition (args.disk, args.par, args.sess, args.tool, args.level) +if ret is not None: + if ret == True: sys.exit (0) + elif ret == False: sys.exit (1) + else: print (ret) From 6a02b6f4f1b492c4c6de2ff26750a9aac544b6bf Mon Sep 17 00:00:00 2001 From: Natalia Serrano Date: Mon, 27 Jan 2025 17:41:38 +0100 Subject: [PATCH 112/167] refs #1337 add ogGrubInstallMbr, fix bugs --- client/lib/engine/bin/BootLib.py | 5 +++-- client/lib/engine/bin/DiskLib.py | 3 ++- client/lib/engine/bin/FileSystemLib.py | 4 ++-- client/shared/functions/ogGrubInstallMbr | 25 ++++++++++++++++++++++++ 4 files changed, 32 insertions(+), 5 deletions(-) create mode 100755 client/shared/functions/ogGrubInstallMbr diff --git a/client/lib/engine/bin/BootLib.py b/client/lib/engine/bin/BootLib.py index aab937e..87823a2 100644 --- a/client/lib/engine/bin/BootLib.py +++ b/client/lib/engine/bin/BootLib.py @@ -474,7 +474,8 @@ def ogGrubInstallMbr (disk, par, checkos='FALSE', kernelparam=''): if InventoryLib.ogIsEfiActive(): # Movemos el grubx64.efi for b in (glob.glob (f'{efisecondstage}/EFI/{efisubdir}/EFI/BOOT/*')): - os.rename (f'{efisecondstage}/EFI/{efisubdir}/EFI/BOOT/{b}', f'{efisecondstage}/EFI/{efisubdir}/Boot/{b}') + bn = os.path.basename (b) + os.rename (f'{efisecondstage}/EFI/{efisubdir}/EFI/BOOT/{bn}', f'{efisecondstage}/EFI/{efisubdir}/Boot/{bn}') shutil.rmtree (f'{efisecondstage}/EFI/{efisubdir}/EFI') shutil.copy2 ('/usr/lib/shim/shimx64.efi.signed', f'{efisecondstage}/EFI/{efisubdir}/Boot/shimx64.efi') # Nombre OpenGnsys para cargador @@ -484,7 +485,7 @@ def ogGrubInstallMbr (disk, par, checkos='FALSE', kernelparam=''): UEFILib.ogNvramAddEntry ('grub', '/EFI/grub/Boot/shimx64.efi') grubentry = UEFILib.ogNvramList() for l in grubentry.splitlines(): - words = l.split (maxsplit=1) + words = l.split() if len(words) < 2: continue if 'grub' == words[1]: grubentry = words[0] diff --git a/client/lib/engine/bin/DiskLib.py b/client/lib/engine/bin/DiskLib.py index 61f97f3..dcde73f 100755 --- a/client/lib/engine/bin/DiskLib.py +++ b/client/lib/engine/bin/DiskLib.py @@ -804,6 +804,7 @@ def ogGetPartitionActive (disk): def ogGetPartitionId (disk, par): DISK = ogDiskToDev (disk) if DISK is None: return + fsid = None pttype = ogGetPartitionTableType (disk) if 'GPT' == pttype: @@ -814,7 +815,7 @@ def ogGetPartitionId (disk, par): if idx == par: fsid = code break - if fsid == '8300' and f'{disk} {par}' == ogFindCache(): + if fsid == '8300' and f'{disk} {par}' == CacheLib.ogFindCache(): fsid = 'CA00' elif 'MSDOS' == pttype: fsid = subprocess.run (['sfdisk', '--part-type', DISK, par], capture_output=True, text=True).stdout.strip() diff --git a/client/lib/engine/bin/FileSystemLib.py b/client/lib/engine/bin/FileSystemLib.py index 570bbd8..9120a5e 100755 --- a/client/lib/engine/bin/FileSystemLib.py +++ b/client/lib/engine/bin/FileSystemLib.py @@ -307,9 +307,9 @@ def ogFormatFs (disk, par, fs=None, label=None): subprocess.run (['umount', PART]) try: if input: - errcode = subprocess.run ([prog, params, PART]) + errcode = subprocess.run ([prog] + params.split (' ') + [PART]) else: - errcode = subprocess.run ([prog, params, PART], input=input, text=True) + errcode = subprocess.run ([prog] + params.split (' ') + [PART], input=input, text=True) except FileNotFoundError: SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTEXEC, prog) errcode = ogGlobals.OG_ERR_NOTEXEC diff --git a/client/shared/functions/ogGrubInstallMbr b/client/shared/functions/ogGrubInstallMbr new file mode 100755 index 0000000..97a7497 --- /dev/null +++ b/client/shared/functions/ogGrubInstallMbr @@ -0,0 +1,25 @@ +#!/usr/bin/python3 + +import sys +import argparse +from SystemLib import ogHelp +from BootLib import ogGrubInstallMbr + +parser = argparse.ArgumentParser (add_help=False) +parser.add_argument ('disk') +parser.add_argument ('par') +parser.add_argument ('checkos', nargs='?', default='FALSE') +parser.add_argument ('kernelparam', nargs='?', default='') + +if 2 == len (sys.argv) and 'help' == sys.argv[1]: + #parser.print_help() sale en inglés aunque la locale indique otra cosa + ogHelp ('ogGrubInstallMbr', 'ogGrubInstallMbr int_ndiskSecondStage int_partitionSecondStage bolean_Configure_2ndStage "param param"', ['ogGrubInstallMbr 1 1 FALSE', 'ogGrubInstallMbr 1 1 TRUE "nomodeset irqpoll pci=noacpi quiet splash"']) + sys.exit (0) + +args = parser.parse_args() + +ret = ogGrubInstallMbr (args.disk, args.par, args.checkos, args.kernelparam) +if ret is not None: + if ret == True: sys.exit (0) + elif ret == False: sys.exit (1) + else: print (ret) From 6748652d88b3a47f69eeb6ed24813dd83372ac64 Mon Sep 17 00:00:00 2001 From: Natalia Serrano Date: Mon, 27 Jan 2025 18:26:14 +0100 Subject: [PATCH 113/167] refs #1337 add ogTorrentStart, fix bugs --- client/lib/engine/bin/CacheLib.py | 4 ++- client/shared/functions/ogTorrentStart | 39 ++++++++++++++++++++++++++ 2 files changed, 42 insertions(+), 1 deletion(-) create mode 100755 client/shared/functions/ogTorrentStart diff --git a/client/lib/engine/bin/CacheLib.py b/client/lib/engine/bin/CacheLib.py index 37246c9..575457b 100755 --- a/client/lib/engine/bin/CacheLib.py +++ b/client/lib/engine/bin/CacheLib.py @@ -162,7 +162,9 @@ def ogFormatCache(): # Crear estructura básica. mntdir = ogMountCache() - os.makedirs(os.path.join(mntdir, ogGlobals.OGIMG), exist_ok=True) + j = '/'.join ([mntdir, ogGlobals.OGIMG]) ## os.path.join doesn't work: "If a segment […] is an absolute path, all previous segments are ignored" + print (f'cucu mntdir ({mntdir}) OGIMG ({ogGlobals.OGIMG}) j ({j})') + os.makedirs (j, exist_ok=True) # Incluir kernel e Initrd del ogLive ## como lo llamo sin especificar el path entero? diff --git a/client/shared/functions/ogTorrentStart b/client/shared/functions/ogTorrentStart new file mode 100755 index 0000000..778d512 --- /dev/null +++ b/client/shared/functions/ogTorrentStart @@ -0,0 +1,39 @@ +#!/usr/bin/python3 + +import sys +import argparse +from SystemLib import ogHelp +from ProtocolLib import ogTorrentStart + +if 2 == len (sys.argv) and 'help' == sys.argv[1]: + #parser.print_help() sale en inglés aunque la locale indique otra cosa + ogHelp ('ogTorrentStart', 'ogTorrentStart [ str_repo] [ [Relative_path_fileTORRENT] | [str_REPOSITORY path_fileTORRENT] | [int_ndisk int_npart path_fileTORRENT ] ] SessionTorrent', ['ogTorrentStart CACHE /PS1_PH1.img.torrent seeder:10000', 'ogTorrentStart /opt/opengnsys/cache/linux.iso peer:60', 'ogTorrentStart 1 1 /linux.iso.torrent leecher:60']) + sys.exit (0) + +parser = argparse.ArgumentParser (add_help=False) +if 3 == len (sys.argv): + parser.add_argument ('torrentfile', nargs='?', default=None) + parser.add_argument ('torrentsess', nargs='?', default=None) +elif 4 == len (sys.argv): + parser.add_argument ('container', nargs='?', default=None) + parser.add_argument ('torrentfile', nargs='?', default=None) + parser.add_argument ('torrentsess', nargs='?', default=None) +elif 5 == len (sys.argv): + parser.add_argument ('disk', nargs='?', default=None) + parser.add_argument ('par', nargs='?', default=None) + parser.add_argument ('torrentfile', nargs='?', default=None) + parser.add_argument ('torrentsess', nargs='?', default=None) + +args = parser.parse_args() + +if 3 == len (sys.argv): + ret = ogTorrentStart (torrentfile=args.torrentfile, torrentsess=args.torrentsess) +elif 4 == len (sys.argv): + ret = ogTorrentStart (container=args.container, torrentfile=args.torrentfile, torrentsess=args.torrentsess) +elif 5 == len (sys.argv): + ret = ogTorrentStart (disk=args.disk, par=args.par, torrentfile=args.torrentfile, torrentsess=args.torrentsess) + +if ret is not None: + if ret == True: sys.exit (0) + elif ret == False: sys.exit (1) + else: print (ret) From 40627771836cd93e3095b2ac0388fb127d9b7f84 Mon Sep 17 00:00:00 2001 From: Natalia Serrano Date: Tue, 28 Jan 2025 10:08:16 +0100 Subject: [PATCH 114/167] refs #1337 add ogUcastSendFile, fix bugs --- client/shared/functions/ogUcastSendFile | 39 +++++++++++++++++++++++++ client/shared/scripts/updateCache.py | 5 ++-- 2 files changed, 42 insertions(+), 2 deletions(-) create mode 100755 client/shared/functions/ogUcastSendFile diff --git a/client/shared/functions/ogUcastSendFile b/client/shared/functions/ogUcastSendFile new file mode 100755 index 0000000..498965a --- /dev/null +++ b/client/shared/functions/ogUcastSendFile @@ -0,0 +1,39 @@ +#!/usr/bin/python3 + +import sys +import argparse +from SystemLib import ogHelp +from ProtocolLib import ogUcastSendFile + +if 2 == len (sys.argv) and 'help' == sys.argv[1]: + #parser.print_help() sale en inglés aunque la locale indique otra cosa + ogHelp ('ogUcastSendFile', 'ogUcastSendFile [str_REPOSITORY] [int_ndisk int_npart] /Relative_path_file sesionMcast(puerto:ip:ip:ip)', ['ogUcastSendFile 1 1 /aula1/winxp.img 8000:172.17.36.11:172.17.36.12', 'ogUcastSendFile REPO /aula1/ubuntu.iso sesionUcast', 'ogUcastSendFile CACHE /aula1/winxp.img sesionUcast', 'ogUcastSendFile /opt/opengnsys/images/aula1/hd500.vmx sesionUcast']) + sys.exit (0) + +parser = argparse.ArgumentParser (add_help=False) +if 3 == len (sys.argv): + parser.add_argument ('file', nargs='?', default=None) + parser.add_argument ('sess', nargs='?', default=None) +elif 4 == len (sys.argv): + parser.add_argument ('container', nargs='?', default=None) + parser.add_argument ('file', nargs='?', default=None) + parser.add_argument ('sess', nargs='?', default=None) +elif 5 == len (sys.argv): + parser.add_argument ('disk', nargs='?', default=None) + parser.add_argument ('par', nargs='?', default=None) + parser.add_argument ('file', nargs='?', default=None) + parser.add_argument ('sess', nargs='?', default=None) + +args = parser.parse_args() + +if 3 == len (sys.argv): + ret = ogUcastSendFile (file=args.file, sess=args.sess) +elif 4 == len (sys.argv): + ret = ogUcastSendFile (container=args.container, file=args.file, sess=args.sess) +elif 5 == len (sys.argv): + ret = ogUcastSendFile (disk=args.disk, par=args.par, file=args.file, sess=args.sess) + +if ret is not None: + if ret == True: sys.exit (0) + elif ret == False: sys.exit (1) + else: print (ret) diff --git a/client/shared/scripts/updateCache.py b/client/shared/scripts/updateCache.py index 773bef3..179781c 100644 --- a/client/shared/scripts/updateCache.py +++ b/client/shared/scripts/updateCache.py @@ -20,6 +20,7 @@ import os.path import sys +import re import time import subprocess import shutil @@ -60,7 +61,7 @@ if SystemLib.ogGetCaller() not in ['deployImage', 'restoreBaseImage', 'restoreDi # Si MCASTWAIT menos que tiempo de espera del servidor lo aumento MCASTWAIT = ogGlobals.MCASTWAIT if ':' in optprotocolo: - port, wait = optprotocolo.split (':') + port, wait, *other = optprotocolo.split (':') else: port, wait = ('', '') if protocolo.startswith ('MULTICAST') and re.match (r'^-?\d+$', wait): @@ -187,7 +188,7 @@ elif 'MULTICAST' == protocolo: sys.exit (1) SystemLib.ogEcho (['log', 'session'], None, f'ogMcastReceiverFile {port} CACHE {path}') - if not SystemLib.ogExecAndLog ('command', ProtocolLib.ogMcastReceiverFile, port, 'CACHE', path): + if not SystemLib.ogExecAndLog ('command', ProtocolLib.ogMcastReceiverFile, sess=port, container='CACHE', file=path): sys.exit (1) resumeupdatecache = subprocess.run (['grep', '--max-count', '1', '--before-context', '1', 'Transfer complete', f'{ogGlobals.OGLOGCOMMAND}.tmp'], capture_output=True, text=True).stdout From e266bf07c99a9c6e36848aac7ba56a560af93bb7 Mon Sep 17 00:00:00 2001 From: Natalia Serrano Date: Tue, 28 Jan 2025 12:46:29 +0100 Subject: [PATCH 115/167] refs #1329 add ogGetSizeParameters --- client/lib/engine/bin/ImageLib.py | 68 +++++++++++++++++++++ client/shared/functions/ogGetSizeParameters | 21 +++++++ 2 files changed, 89 insertions(+) create mode 100755 client/shared/functions/ogGetSizeParameters diff --git a/client/lib/engine/bin/ImageLib.py b/client/lib/engine/bin/ImageLib.py index 69e872f..1a789e7 100644 --- a/client/lib/engine/bin/ImageLib.py +++ b/client/lib/engine/bin/ImageLib.py @@ -12,6 +12,7 @@ import FileSystemLib import SystemLib import ogGlobals import FileLib +import CacheLib ## ProtocolLib.ogUcastSyntax() calls ogCreateImageSyntax() ## in ogCreateImageSyntax(), param2 may contain a pipe or may be empty @@ -257,6 +258,73 @@ def ogRestoreImageSyntax (imgfile, part, tool=None, level=None): #@note para el tamaño de la imagen no sigue enlaces simbólicos. #@exception OG_ERR_FORMAT formato incorrecto. #*/ ## +#SIZEDATA, SIZEREQUIRED, SIZEFREE, ISENOUGHSPACE = ogGetSizeParameters (1, 1, 'REPO', 'myimg') +def ogGetSizeParameters (disk, par, repo, imgname, imgtype=None): + repo = repo.upper() + ## imgtype se soporta como parametro pero se ignora + + mntdir = FileSystemLib.ogMount (disk, par) + if not mntdir: + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_PARTITION, f'{disk} {par}') + return None + + #if [ "$IMGTYPE" == "_DIFF_" ]; then cosas + #else: + sizedata = None + df_out = subprocess.run (['df', '-k'], capture_output=True, text=True).stdout + for l in df_out.splitlines(): + if (re.search (f'{mntdir}$', l)): + sizedata = int (l.split()[2]) + break + if sizedata is None: + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_GENERIC, 'sizedata is None') + return None + + #if [ "$IMGTYPE" == "_SYNC_" -o "$IMGTYPE" == "_DIFF_" ]; then cosas + #else: + factorgzip=55/100 + factorlzop=65/100 + sizerequired = sizedata * factorlzop + + #Comprobar espacio libre en el contenedor. + sizefree = None + if 'CACHE' == repo: + cache_disk, cache_par = CacheLib.ogFindCache().split() + sizefree = FileSystemLib.ogGetFreeSize (cache_disk, cache_par) + if 'REPO' == repo: + df_out = subprocess.run (['df', '-k'], capture_output=True, text=True).stdout + for l in df_out.splitlines(): + if (re.search (f'{ogGlobals.OGIMG}', l)): + sizefree = int (l.split()[3]) + break + if sizefree is None: + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_GENERIC, 'sizefree is None') + return None + +# Comprobamos si existe una imagen con el mismo nombre en $REPO +# En sincronizadas restamos tamaño de la imagen y en monoloticas de la .ant + #case "${IMGTYPE}" in blah blah + #*) + imgext = 'img.ant' + + imgdir = FileLib.ogGetParentPath (src=repo, file=f'/{imgname}') + bn = os.path.basename (f'/{imgname}') + imgfile = FileLib.ogGetPath (file=f'{imgdir}/{bn}.{imgext}') + + if not imgfile: + imgsize = 0 + else: + ls_out = subprocess.run (['ls', '-s', imgfile], capture_output=True, text=True).stdout + imgsize = int (ls_out.split()[0]) + + sizefree = sizefree + imgsize + + if sizerequired < sizefree: + isenoughspace = True + else: + isenoughspace = False + + return sizedata, sizerequired, sizefree, isenoughspace #/** # ogIsImageLocked [str_repo] path_image diff --git a/client/shared/functions/ogGetSizeParameters b/client/shared/functions/ogGetSizeParameters new file mode 100755 index 0000000..951f7a8 --- /dev/null +++ b/client/shared/functions/ogGetSizeParameters @@ -0,0 +1,21 @@ +#!/usr/bin/python3 + +import sys +import argparse +from SystemLib import ogHelp +from ImageLib import ogGetSizeParameters + +parser = argparse.ArgumentParser (add_help=False) +parser.add_argument ('disk') +parser.add_argument ('par') +parser.add_argument ('container') +parser.add_argument ('imgname') + +if 2 == len (sys.argv) and 'help' == sys.argv[1]: + #parser.print_help() sale en inglés aunque la locale indique otra cosa + ogHelp ('ogGetSizeParameters', 'ogGetSizeParameters num_disk num_part str_repo path_imgname', ['read SIZEDATA SIZEREQUIRED SIZEFREE ISENOUGHSPACE <<< $(ogGetSizeParameters 1 2 REPO Windows10)', 'read SIZEDATA SIZEREQUIRED SIZEFREE ISENOUGHSPACE <<< $(ogGetSizeParameters 1 6 CACHE Ubuntu16']) + sys.exit (0) + +args = parser.parse_args() +sizedata, sizerequired, sizefree, isenoughspace = ogGetSizeParameters (args.disk, args.par, args.container, args.imgname) +print (' '.join ([str(sizedata), str(sizerequired), str(sizefree), str(isenoughspace)])) From 6f59aaaca7fbf64921e407bba2a29215a95ed6fa Mon Sep 17 00:00:00 2001 From: Natalia Serrano Date: Tue, 28 Jan 2025 13:17:12 +0100 Subject: [PATCH 116/167] refs #1330 add ogCheckFs --- client/lib/engine/bin/FileSystemLib.py | 156 ++++++++----------------- client/shared/functions/ogCheckFs | 23 ++++ 2 files changed, 74 insertions(+), 105 deletions(-) create mode 100755 client/shared/functions/ogCheckFs diff --git a/client/lib/engine/bin/FileSystemLib.py b/client/lib/engine/bin/FileSystemLib.py index 9120a5e..8eb19e1 100755 --- a/client/lib/engine/bin/FileSystemLib.py +++ b/client/lib/engine/bin/FileSystemLib.py @@ -30,116 +30,62 @@ import FileSystemLib #@warning No se comprueban sistemas de archivos montados o bloqueados. #@todo Definir salidas. #*/ ## -def ogCheckFs(int_ndisk, int_nfilesys): +def ogCheckFs (disk, par): + PART = DiskLib.ogDiskToDev (disk, par) + if not PART: return - if len(sys.argv) != 3: - SystemLib.ogRaiseError( - "session", - ogGlobals.OG_ERR_FORMAT, - "Not enough arguments" - ) - return - - # Obtener partición. - PART = DiskLib.ogDiskToDev(int_ndisk, int_nfilesys) - if not PART: - return - - TYPE = ogGetFsType(int_ndisk, int_nfilesys) - if TYPE == "EXT[234]" or TYPE == "CACHE": - PROG = "e2fsck" - PARAMS = "-y" - CODES = [1, 2] - elif TYPE == "BTRFS": - PROG = "btrfsck" - CODES = [1] - elif TYPE == "REISERFS": - PROG = "fsck.reiserfs" - PARAMS = "<<<\"Yes\"" - CODES = [1, 2] - elif TYPE == "REISER4": - PROG = "fsck.reiser4" - PARAMS = "-ay" - elif TYPE == "JFS": - PROG = "fsck.jfs" - CODES = [1, 2] - elif TYPE == "XFS": - PROG = "xfs_repair" - elif TYPE == "F2FS": - PROG = "fsck.f2fs" - elif TYPE == "NTFS": - PROG = "ntfsfix" - elif TYPE == "EXFAT": - PROG = "fsck.exfat" - elif TYPE == "FAT32": - PROG = "dosfsck" - PARAMS = "-a" - CODES = [1] - elif TYPE == "FAT16": - PROG = "dosfsck" - PARAMS = "-a" - CODES = [1] - elif TYPE == "FAT12": - PROG = "dosfsck" - PARAMS = "-a" - CODES = [1] - elif TYPE == "HFS": - PROG = "fsck.hfs" - PARAMS = "-f" - elif TYPE == "HFSPLUS": - PROG = "fsck.hfs" - PARAMS = "-f" - elif TYPE == "UFS": - PROG = "fsck.ufs" - elif TYPE == "ZFS": - PROG = "fsck.zfs" + data = { + 'EXT2': { 'prog': 'e2fsck', 'params': '-y', 'codes': (1, 2), }, + 'EXT3': { 'prog': 'e2fsck', 'params': '-y', 'codes': (1, 2), }, + 'EXT4': { 'prog': 'e2fsck', 'params': '-y', 'codes': (1, 2), }, + 'CACHE': { 'prog': 'e2fsck', 'params': '-y', 'codes': (1, 2), }, + 'BTRFS': { 'prog': 'btrfsck', 'codes': (1), }, + 'REISERFS': { 'prog': 'fsck.reiserfs', 'codes': (1, 2), 'input': 'Yes' }, + 'REISER4': { 'prog': 'fsck.reiser4', 'params': '-ay', }, + 'JFS': { 'prog': 'fsck.jfs', 'codes': (1, 2), }, + 'XFS': { 'prog': 'xfs_repair', }, + 'F2FS': { 'prog': 'fsck.f2fs', }, + 'NTFS': { 'prog': 'ntfsfix', }, + 'EXFAT': { 'prog': 'fsck.exfat', }, + 'FAT32': { 'prog': 'dosfsck', 'params': '-a', 'codes': (1), }, + 'FAT16': { 'prog': 'dosfsck', 'params': '-a', 'codes': (1), }, + 'FAT12': { 'prog': 'dosfsck', 'params': '-a', 'codes': (1), }, + 'HFS': { 'prog': 'fsck.hfs', 'params': '-f', }, + 'HFSPLUS': { 'prog': 'fsck.hfs', 'params': '-f', }, + 'UFS': { 'prog': 'fsck.ufs', }, + 'ZFS': { 'prog': 'fsck.zfs', }, + } + type = ogGetFsType (disk, par) + if type in data: + prog = data[type]['prog'] + params = data[type]['params'] if 'params' in data[type] else '' + codes = data[type]['codes'] if 'codes' in data[type] else [] + input = data[type]['input'] if 'input' in data[type] else None else: - SystemLib.ogRaiseError( - "session", - ogGlobals.OG_ERR_PARTITION, - f"{int_ndisk}, {int_nfilesys}" - ) - return + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_PARTITION, f'{disk}, {par}, {type}') + return None - # Error si el sistema de archivos esta montado o bloqueado. - ogUnmount(int_ndisk, int_nfilesys) - if ogIsMounted(int_ndisk, int_nfilesys): - SystemLib.ogRaiseError( - "session", - ogGlobals.OG_ERR_PARTITION, - f"{int_ndisk} {int_nfilesys}" - ) - return - if ogIsLocked(int_ndisk, int_nfilesys): - SystemLib.ogRaiseError( - "session", - ogGlobals.OG_ERR_LOCKED, - f"{int_ndisk} {int_nfilesys}" - ) - return + ogUnmount (disk, par) + if ogIsMounted (disk, par): + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_PARTITION, f'{disk} {par}') + return None + if ogIsLocked (disk, par): + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_LOCKED, f'{disk} {par}') + return None - # Comprobar en modo uso exclusivo. - ogLock(int_ndisk, int_nfilesys) - try: - result = subprocess.run([PROG, PARAMS, PART], capture_output=True) - ERRCODE = result.returncode - except FileNotFoundError: - SystemLib.ogRaiseError( - "session", - ogGlobals.OG_ERR_NOTEXEC, - PROG - ) - ERRCODE = ogGlobals.OG_ERR_NOTEXEC - except: - SystemLib.ogRaiseError( - "session", - ogGlobals.OG_ERR_PARTITION, - f"{int_ndisk} {int_nfilesys}" - ) - ERRCODE = ogGlobals.OG_ERR_PARTITION + ogLock (disk, par) + rc = subprocess.run ([prog] + params.split() + [PART], input=input, text=True).returncode + if 0 == rc or rc in codes: + errcode = 0 + elif 127 == rc: + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTEXEC, prog) + errcode = ogGlobals.OG_ERR_NOTEXEC + else: + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_PARTITION, f'{disk} {par}') + errcode = ogGlobals.OG_ERR_PARTITION - ogUnlock(int_ndisk, int_nfilesys) - return ERRCODE + ogUnlock (disk, par) + return errcode #/** diff --git a/client/shared/functions/ogCheckFs b/client/shared/functions/ogCheckFs new file mode 100755 index 0000000..7eade6a --- /dev/null +++ b/client/shared/functions/ogCheckFs @@ -0,0 +1,23 @@ +#!/usr/bin/python3 + +import sys +import argparse +from SystemLib import ogHelp +from FileSystemLib import ogCheckFs + +parser = argparse.ArgumentParser (add_help=False) +parser.add_argument ('disk') +parser.add_argument ('par') + +if 2 == len (sys.argv) and 'help' == sys.argv[1]: + #parser.print_help() sale en inglés aunque la locale indique otra cosa + ogHelp ('ogCheckFs', 'ogCheckFs int_ndisk int_nfilesys', ['ogCheckFs 1 1']) + sys.exit (0) + +args = parser.parse_args() +ret = ogCheckFs (args.disk, args.par) + +if ret is not None: + if ret == True: sys.exit (0) + elif ret == False: sys.exit (1) + else: print (ret) From 6538fe90b31a483746381424d528f50e23b01d03 Mon Sep 17 00:00:00 2001 From: Natalia Serrano Date: Tue, 28 Jan 2025 13:35:46 +0100 Subject: [PATCH 117/167] refs #1331 add ogCopyEfiBootLoader --- client/lib/engine/bin/UEFILib.py | 33 +++++++++++++++++++++ client/shared/functions/ogCopyEfiBootLoader | 23 ++++++++++++++ 2 files changed, 56 insertions(+) create mode 100755 client/shared/functions/ogCopyEfiBootLoader diff --git a/client/lib/engine/bin/UEFILib.py b/client/lib/engine/bin/UEFILib.py index 4c54401..a70b5a7 100644 --- a/client/lib/engine/bin/UEFILib.py +++ b/client/lib/engine/bin/UEFILib.py @@ -117,6 +117,39 @@ def ogNvramAddEntry (bootlbl, bootldr, nvram_set=False): #@exception OG_ERR_NOTFOUND fichero o dispositivo no encontrado. #@note Si existe el cargador en la partición de sistema no es válido #*/ ## +def ogCopyEfiBootLoader (disk, par): + mntdir = FileSystemLib.ogMount (disk, par) + if not mntdir: + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_PARTITION, f'{disk} {par}') + return None + + esp = DiskLib.ogGetEsp() + if not esp: + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTFOUND, 'EFI partition') + return + esp_disk, esp_par = esp.split() + efidir = FileSystemLib.ogMount (esp_disk, esp_par) + if not efidir: + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_PARTITION, 'ESP') + return + + bootlabel = f'Part-{int(disk):02d}-{int(par):02d}' + osversion = InventoryLib.ogGetOsVersion (disk, par) + print (f'bootlabel ({bootlabel})') + print (f'osversion ({osversion})') + if 'Windows 1' in osversion: + loader = None + for i in f'{efidir}/EFI/Microsoft/Boot/bootmgfw.efi', f'{efidir}/EFI/{bootlabel}/Boot/bootmgfw.efi': + if os.path.exists (i): + loader = i + if not loader: + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTOS, f'{disk} {par} ({osversion}, EFI)') + return None + + if (os.path.isdir (f'{mntdir}/ogBoot')): + shutil.rmtree (f'{mntdir}/ogBoot') + dirloader = os.path.realpath (os.path.dirname (loader) + '/..') + shutil.copytree (f'{dirloader}/Boot', f'{mntdir}/ogBoot') #/** diff --git a/client/shared/functions/ogCopyEfiBootLoader b/client/shared/functions/ogCopyEfiBootLoader new file mode 100755 index 0000000..41d5d9b --- /dev/null +++ b/client/shared/functions/ogCopyEfiBootLoader @@ -0,0 +1,23 @@ +#!/usr/bin/python3 + +import sys +import argparse +from SystemLib import ogHelp +from UEFILib import ogCopyEfiBootLoader + +parser = argparse.ArgumentParser (add_help=False) +parser.add_argument ('disk') +parser.add_argument ('par') + +if 2 == len (sys.argv) and 'help' == sys.argv[1]: + #parser.print_help() sale en inglés aunque la locale indique otra cosa + ogHelp ('ogCopyEfiBootLoader', 'ogCopyEfiBootLoader int_ndisk int_part', ['ogCopyEfiBootLoader 1 2']) + sys.exit (0) + +args = parser.parse_args() +ret = ogCopyEfiBootLoader (args.disk, args.par) + +if ret is not None: + if ret == True: sys.exit (0) + elif ret == False: sys.exit (1) + else: print (ret) From ad9c498e3890f1dab976a6138f0952a1bac7ff39 Mon Sep 17 00:00:00 2001 From: Natalia Serrano Date: Tue, 28 Jan 2025 15:42:45 +0100 Subject: [PATCH 118/167] refs #1332 add ogReduceFs, fix bugs --- client/lib/engine/bin/FileSystemLib.py | 135 +++++++++++++------------ client/shared/functions/ogReduceFs | 23 +++++ 2 files changed, 96 insertions(+), 62 deletions(-) create mode 100755 client/shared/functions/ogReduceFs diff --git a/client/lib/engine/bin/FileSystemLib.py b/client/lib/engine/bin/FileSystemLib.py index 8eb19e1..250efcb 100755 --- a/client/lib/engine/bin/FileSystemLib.py +++ b/client/lib/engine/bin/FileSystemLib.py @@ -253,9 +253,9 @@ def ogFormatFs (disk, par, fs=None, label=None): subprocess.run (['umount', PART]) try: if input: - errcode = subprocess.run ([prog] + params.split (' ') + [PART]) + errcode = subprocess.run ([prog] + params.split (' ') + [PART]).returncode else: - errcode = subprocess.run ([prog] + params.split (' ') + [PART], input=input, text=True) + errcode = subprocess.run ([prog] + params.split (' ') + [PART], input=input, text=True).returncode except FileNotFoundError: SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTEXEC, prog) errcode = ogGlobals.OG_ERR_NOTEXEC @@ -681,71 +681,82 @@ def ogMountCdrom(): #@warning El sistema de archivos se amplía al mínimo + 10%. #@note Requisitos: *resize* #*/ ## -def ogReduceFs(int_ndisk, int_nfilesys): - - # Error si no se reciben 2 parámetros. - if len(sys.argv) != 3: - SystemLib.ogRaiseError ( - [], - ogGlobals.OG_ERR_FORMAT, - "Not enough arguments" - ) - return - - # Obtener partición. - PART = DiskLib.ogDiskToDev(int_ndisk, int_nfilesys) - if not PART: - return +def ogReduceFs (disk, par): + PART = DiskLib.ogDiskToDev (disk, par) + if not PART: return # Redimensionar según el tipo de partición. - TYPE = ogGetFsType(int_ndisk, int_nfilesys) - if TYPE == "EXT4": - ogUnmount(int_ndisk, int_nfilesys) - subprocess.run(["resize2fs", "-fpM", PART], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) - elif TYPE == "BTRFS": - MNTDIR = ogMount(int_ndisk, int_nfilesys) - SIZE = subprocess.run(["btrfs", "filesystem", "show", MNTDIR], capture_output=True, text=True) - SIZE = SIZE.stdout.strip().split(" ")[6] - SIZE = int(float(SIZE) * 1.1 + 1) - subprocess.run(["btrfs", "filesystem", "resize", str(SIZE), MNTDIR], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) - elif TYPE in ["REISERFS", "REISER4"]: - MNTDIR = ogMount(int_ndisk, int_nfilesys) - SIZE = int(subprocess.run(["df", "-k", MNTDIR], capture_output=True, text=True).stdout.strip().split("\n")[1].split()[2]) - SIZE = SIZE * 110 // 100 - ogUnmount(int_ndisk, int_nfilesys) - subprocess.run(["resize_reiserfs", "-s" + str(SIZE) + "K", PART], input="y\n", stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) - elif TYPE == "NTFS": - ogUnmount(int_ndisk, int_nfilesys) - MAXSIZE, SIZE = subprocess.run(["ntfsresize", "-fi", PART], capture_output=True, text=True) - MAXSIZE = MAXSIZE.strip().split(" ")[3] - SIZE = SIZE.strip().split(" ")[4] - SIZE = int(float(SIZE) * 1.1 / 1024 + 1) * 1024 - RETVAL = 1 - while RETVAL != 0 and SIZE + EXTRASIZE < MAXSIZE: - EXTRASIZE = subprocess.run(["ntfsresize", "-fns", str(SIZE), PART], capture_output=True, text=True) - EXTRASIZE = int(EXTRASIZE.stdout.strip()) if EXTRASIZE.stdout.strip() else 0 - RETVAL = EXTRASIZE != 0 - SIZE += EXTRASIZE - if SIZE < MAXSIZE: - subprocess.run(["ntfsresize", "-fs", str(SIZE), PART], input="y\n", stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) - elif TYPE in ["FAT32", "FAT16"]: - # No se reduce (por el momento). - pass - elif TYPE == "HFS" or TYPE == "HFSPLUS": - # No se reduce (por el momento). - pass - elif TYPE == "UFS": - # No se reduce (por el momento). + type = ogGetFsType (disk, par) + if type in ['EXT2', 'EXT3', 'EXT4']: + ogUnmount (disk, par) + rc = subprocess.run (['resize2fs', '-fpM', PART], capture_output=True, text=True).returncode + if rc: + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_PARTITION, f"{disk},{par}") + return None + elif 'BTRFS' == type: + mntdir = ogMount (disk, par) + # Calcular tamaño ocupado + 10%, redondeado + 1 (incluyendo letra de unidad). + btrfs_lines = subprocess.run (['btrfs', 'filesystem', 'show', mntdir], capture_output=True, text=True).stdout.splitlines() + for l in btrfs_lines: + if 'devid' not in l: continue + ## 'devid 2 size 8.89GiB used 1.00GiB path /dev/sda4' + devid_str, devid, size_str, size, used_str, used, path_str, path = l.split() + if PART != os.path.realpath (path): continue + (sz, unit) = re.search ('^([^A-Z]+)([A-Z])', used).groups() + sz = float (sz) * 1.1 + 1 + size = f'{str(sz)}{unit}' + subprocess.run (['btrfs', 'filesystem', 'resize', size, mntdir], capture_output=True, text=True) + break + elif type in ['REISERFS', 'REISER4']: + mntdir = ogMount (disk, par) + df_lines = subprocess.run (['df', '-k', mntdir], capture_output=True, text=True).stdout.splitlines() + for l in df_lines: + if 'Filesystem' in l: continue + fs, blocks, used, avail, use_pct, mntpt = l.split() + size = str (int (used) * 1.1) + ogUnmount (disk, par) + subprocess.run (['resize_reiserfs', f'-s{size}K', PART], input='y\n', capture_output=True, text=True) + break + elif type == 'NTFS': + ogUnmount (disk, par) + nr_lines = subprocess.run (['ntfsresize', '-fi', PART], capture_output=True, text=True).stdout.splitlines() + maxsize = None + size = None + for l in nr_lines: + if 'device size' in l: + maxsize = float (l.split()[3]) + if 'resize at' in l: + size = l.split()[4] + size = int ((int (size) * 1.1 / 1024 + 1) * 1024) + + if not maxsize and not size: + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_PARTITION, f'{disk},{par}') + return None + + import time + + extrasize = 0 + retval = 1 + while retval != 0 and size+extrasize < maxsize: + nr = subprocess.run (['ntfsresize', '-fns', str(size), PART], capture_output=True, text=True) + for l in nr.stdout.splitlines(): + if 'Needed relocations' not in l: continue + extrasize = int ((int (l.split()[3])*1.1/1024+1)*1024) + break + retval = nr.returncode + size += extrasize + if size < maxsize: + rc = subprocess.run (['ntfsresize', '-fs', str(size), PART], input='y\n', capture_output=True, text=True).returncode + if rc: + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_PARTITION, f"{disk},{par}") + return None + elif type in ['FAT32', 'FAT16', 'F2FS', 'JFS', 'NILFS2', 'XFS', 'EXFAT', 'HFS', 'HFSPLUS', 'UFS']: pass else: - SystemLib.ogRaiseError ( - [], - ogGlobals.OG_ERR_PARTITION, - f"{int_ndisk}, {int_nfilesys}" - ) + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_PARTITION, f"{disk},{par}") + return None - # Devuelve tamaño del sistema de ficheros. - return ogGetFsSize(int_ndisk, int_nfilesys) + return ogGetFsSize (disk, par) #/** diff --git a/client/shared/functions/ogReduceFs b/client/shared/functions/ogReduceFs new file mode 100755 index 0000000..999aa90 --- /dev/null +++ b/client/shared/functions/ogReduceFs @@ -0,0 +1,23 @@ +#!/usr/bin/python3 + +import sys +import argparse +from SystemLib import ogHelp +from FileSystemLib import ogReduceFs + +parser = argparse.ArgumentParser (add_help=False) +parser.add_argument ('disk') +parser.add_argument ('par') + +if 2 == len (sys.argv) and 'help' == sys.argv[1]: + #parser.print_help() sale en inglés aunque la locale indique otra cosa + ogHelp ('ogReduceFs', 'ogReduceFs int_ndisk int_nfilesys', ['ogReduceFs 1 1']) + sys.exit (0) + +args = parser.parse_args() +ret = ogReduceFs (args.disk, args.par) + +if ret is not None: + if ret == True: sys.exit (0) + elif ret == False: sys.exit (1) + else: print (ret) From 4cc8b1be1d0e7d338d93db1df441bf06009e484b Mon Sep 17 00:00:00 2001 From: Natalia Serrano Date: Tue, 28 Jan 2025 15:58:12 +0100 Subject: [PATCH 119/167] refs #1334 add ogLockImage --- client/lib/engine/bin/ImageLib.py | 16 +++++++++++++++ client/shared/functions/ogLockImage | 30 +++++++++++++++++++++++++++++ 2 files changed, 46 insertions(+) create mode 100755 client/shared/functions/ogLockImage diff --git a/client/lib/engine/bin/ImageLib.py b/client/lib/engine/bin/ImageLib.py index 1a789e7..fbdeb74 100644 --- a/client/lib/engine/bin/ImageLib.py +++ b/client/lib/engine/bin/ImageLib.py @@ -358,6 +358,22 @@ def ogIsImageLocked (container=None, imgfile=None): #@note repo = { REPO, CACHE } #@exception OG_ERR_FORMAT formato incorrecto. #*/ ## +def ogLockImage (container=None, imgfile=None): + if not imgfile: + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_FORMAT, '') + return None + + if container: + imgdir = FileLib.ogGetParentPath (src=container, file=imgfile) + else: + imgdir = FileLib.ogGetParentPath (file=imgfile) + + try: + bn = os.path.basename (imgfile) + open (f'{imgdir}/{bn}.lock', 'w').close() + except: + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTWRITE, f'{container} {imgfile}') + return None #/** diff --git a/client/shared/functions/ogLockImage b/client/shared/functions/ogLockImage new file mode 100755 index 0000000..0c8f505 --- /dev/null +++ b/client/shared/functions/ogLockImage @@ -0,0 +1,30 @@ +#!/usr/bin/python3 + +import sys +import argparse +from SystemLib import ogHelp +from ImageLib import ogLockImage + +if 2 == len (sys.argv) and 'help' == sys.argv[1]: + #parser.print_help() sale en inglés aunque la locale indique otra cosa + ogHelp ('ogLockImage', 'ogLockImage [str_repo] path_image', ['ogLockImage /opt/opengnsys/images/aula1/win7.img', 'ogLockImage REPO /aula1/win7.img']) + sys.exit (0) + +parser = argparse.ArgumentParser (add_help=False) +if 2 == len (sys.argv): + parser.add_argument ('file') +elif 3 == len (sys.argv): + parser.add_argument ('container') + parser.add_argument ('file') + +args = parser.parse_args() + +if 2 == len (sys.argv): + ret = ogLockImage (imgfile=args.file) +elif 3 == len (sys.argv): + ret = ogLockImage (container=args.container, imgfile=args.file) + +if ret is not None: + if ret == True: sys.exit (0) + elif ret == False: sys.exit (1) + else: print (ret) From 424248b35394af20da95f0fb7ef0514f267321db Mon Sep 17 00:00:00 2001 From: Natalia Serrano Date: Tue, 28 Jan 2025 18:05:37 +0100 Subject: [PATCH 120/167] refs #1333 add ogCreateImage --- client/lib/engine/bin/FileSystemLib.py | 8 +++- client/lib/engine/bin/ImageLib.py | 58 ++++++++++++++++++++++++++ client/shared/functions/ogCreateImage | 37 ++++++++++++++++ client/shared/functions/ogUnlockImage | 30 +++++++++++++ 4 files changed, 131 insertions(+), 2 deletions(-) create mode 100755 client/shared/functions/ogCreateImage create mode 100755 client/shared/functions/ogUnlockImage diff --git a/client/lib/engine/bin/FileSystemLib.py b/client/lib/engine/bin/FileSystemLib.py index 250efcb..aed53e7 100755 --- a/client/lib/engine/bin/FileSystemLib.py +++ b/client/lib/engine/bin/FileSystemLib.py @@ -516,7 +516,10 @@ def ogLockPartition (disk, par): if not PART: return LOCKFILE = f"/var/lock/lock{PART.replace('/', '-')}" - open(LOCKFILE, 'w').close() + try: + open (LOCKFILE, 'w').close() + except: + return False return True @@ -781,7 +784,8 @@ def ogUnlockPartition (disk, par): if not PART: return LOCKFILE = f"/var/lock/lock{PART.replace('/', '-')}" - os.remove(LOCKFILE) + if os.path.exists (LOCKFILE): + os.remove (LOCKFILE) #/** diff --git a/client/lib/engine/bin/ImageLib.py b/client/lib/engine/bin/ImageLib.py index fbdeb74..c8af204 100644 --- a/client/lib/engine/bin/ImageLib.py +++ b/client/lib/engine/bin/ImageLib.py @@ -13,6 +13,7 @@ import SystemLib import ogGlobals import FileLib import CacheLib +import NetLib ## ProtocolLib.ogUcastSyntax() calls ogCreateImageSyntax() ## in ogCreateImageSyntax(), param2 may contain a pipe or may be empty @@ -216,6 +217,52 @@ def ogRestoreImageSyntax (imgfile, part, tool=None, level=None): #@exception OG_ERR_IMAGE error al crear la imagen del sistema. #@todo Comprobaciones, control de errores, definir parámetros, etc. #*/ ## +def ogCreateImage (disk, par, container, imgfile, tool='partclone', level='gzip'): + PART = DiskLib.ogDiskToDev (disk, par) + if not PART: return None + + if FileSystemLib.ogIsLocked (disk, par): + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_LOCKED, f'{ogGlobals.lang.MSG_ERR_LOCKED} {disk}, {par}') + return None + + imgtype = 'img' # Extensión genérica de imágenes. + imgdir = FileLib.ogGetParentPath (src=container, file=imgfile) + if not imgdir: + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTFOUND, f'{container} {imgfile}') + return None + + bn = os.path.basename (imgfile) + IMGFILE = f'{imgdir}/{bn}.{imgtype}' + if ogIsImageLocked (IMGFILE): + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_LOCKED, f'{ogGlobals.lang.MSG_IMAGE} {container}, {imgfile}') + return None + +# Generar la instruccion a ejecutar antes de aplicar los bloqueos. + program = ogCreateImageSyntax (PART, IMGFILE, tool=tool, level=level) +# Desmontar partición, bloquear partición e imagen. + FileSystemLib.ogUnmount (disk, par) + if not FileSystemLib.ogLock (disk, par): + return None + if not ogLockImage (container, f'{imgfile}.{imgtype}'): + return None + +# Crear Imagen. + #trap + p = subprocess.run (program, shell=True, check=True) + errcode = p.returncode + if 0 == errcode: + i = ogGetImageInfo (IMGFILE) + h = NetLib.ogGetHostname() + with open (f'{IMGFILE}.info', 'w') as fd: + fd.write (f'{i}:{h}\n') + else: + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_IMAGE, f'{disk} {par} {IMGFILE}') + if os.path.exists (IMGFILE): + os.unlink (IMGFILE) + + FileSystemLib.ogUnlock (disk, par) + ogUnlockImage (container, f'{imgfile}.{imgtype}') + return errcode #/** @@ -371,6 +418,7 @@ def ogLockImage (container=None, imgfile=None): try: bn = os.path.basename (imgfile) open (f'{imgdir}/{bn}.lock', 'w').close() + return True except: SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTWRITE, f'{container} {imgfile}') return None @@ -507,6 +555,16 @@ def ogRestoreImage (repo, imgpath, disk, par): #@note Se elimina el fichero de bloqueo con extensión .lock #@exception OG_ERR_FORMAT formato incorrecto. #*/ ## +#ogUnlockImage REPO /cucu.img +def ogUnlockImage (container=None, imgfile=None): + f = f'{imgfile}.lock' + if container: + p = FileLib.ogGetPath (src=container, file=f) + else: + p = FileLib.ogGetPath (file=f) + + if os.path.exists (p): + os.unlink (p) #/** diff --git a/client/shared/functions/ogCreateImage b/client/shared/functions/ogCreateImage new file mode 100755 index 0000000..14c9709 --- /dev/null +++ b/client/shared/functions/ogCreateImage @@ -0,0 +1,37 @@ +#!/usr/bin/python3 + +import sys +import argparse +from SystemLib import ogHelp +from ImageLib import ogCreateImage + +if 2 == len (sys.argv) and 'help' == sys.argv[1]: + #parser.print_help() sale en inglés aunque la locale indique otra cosa + ogHelp ('ogCreateImage', 'ogCreateImage int_ndisk int_npart str_repo path_image', ['ogCreateImage 1 1 REPO /aula1/win7']) + sys.exit (0) + +parser = argparse.ArgumentParser (add_help=False) +if 5 == len (sys.argv): + parser.add_argument ('disk') + parser.add_argument ('par') + parser.add_argument ('container') + parser.add_argument ('imgfile') +elif 7 == len (sys.argv): + parser.add_argument ('disk') + parser.add_argument ('par') + parser.add_argument ('container') + parser.add_argument ('imgfile') + parser.add_argument ('tool') + parser.add_argument ('level') + +args = parser.parse_args() + +if 5 == len (sys.argv): + ret = ogCreateImage (args.disk, args.par, args.container, args.imgfile) +elif 7 == len (sys.argv): + ret = ogCreateImage (args.disk, args.par, args.container, args.imgfile, args.tool, args.level) + +if ret is not None: + if ret == True: sys.exit (0) + elif ret == False: sys.exit (1) + else: print (ret) diff --git a/client/shared/functions/ogUnlockImage b/client/shared/functions/ogUnlockImage new file mode 100755 index 0000000..c0f5196 --- /dev/null +++ b/client/shared/functions/ogUnlockImage @@ -0,0 +1,30 @@ +#!/usr/bin/python3 + +import sys +import argparse +from SystemLib import ogHelp +from ImageLib import ogUnlockImage + +if 2 == len (sys.argv) and 'help' == sys.argv[1]: + #parser.print_help() sale en inglés aunque la locale indique otra cosa + ogHelp ('ogUnlockImage', 'ogUnlockImage [str_repo] path_image', ['ogUnlockImage /opt/opengnsys/images/aula1/win7.img', 'ogUnlockImage REPO /aula1/win7.img']) + sys.exit (0) + +parser = argparse.ArgumentParser (add_help=False) +if 2 == len (sys.argv): + parser.add_argument ('file') +elif 3 == len (sys.argv): + parser.add_argument ('container') + parser.add_argument ('file') + +args = parser.parse_args() + +if 2 == len (sys.argv): + ret = ogUnlockImage (imgfile=args.file) +elif 3 == len (sys.argv): + ret = ogUnlockImage (container=args.container, imgfile=args.file) + +if ret is not None: + if ret == True: sys.exit (0) + elif ret == False: sys.exit (1) + else: print (ret) From 9997e78b31be28fdecae6a9bb275bcb59f7b7fdd Mon Sep 17 00:00:00 2001 From: Natalia Serrano Date: Wed, 29 Jan 2025 12:13:30 +0100 Subject: [PATCH 121/167] refs #1397 add createImage.py, fix bugs --- client/lib/engine/bin/FileLib.py | 3 +- client/lib/engine/bin/FileSystemLib.py | 10 +- client/lib/engine/bin/ImageLib.py | 2 +- client/lib/engine/bin/ogGlobals.py | 8 +- client/shared/scripts/createImage.py | 197 ++++++++++++++++++ ...plate..py => createImageCustomTemplate.py} | 0 6 files changed, 209 insertions(+), 11 deletions(-) create mode 100755 client/shared/scripts/createImage.py rename client/shared/scripts/{createImageCustomTemplate..py => createImageCustomTemplate.py} (100%) diff --git a/client/lib/engine/bin/FileLib.py b/client/lib/engine/bin/FileLib.py index 204bdce..2a4adf4 100755 --- a/client/lib/engine/bin/FileLib.py +++ b/client/lib/engine/bin/FileLib.py @@ -509,8 +509,9 @@ def ogMakeDir (container=None, disk=None, par=None, file=None): print (f'nati: ogMakeDir: parent ({parent})') if not parent: SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTFOUND, f'device or file {dev_err} not found') - return + return None dst = os.path.basename (file) print (f'nati: ogMakeDir: dst ({dst})') os.makedirs (os.path.join (parent, dst), exist_ok=True) + return True diff --git a/client/lib/engine/bin/FileSystemLib.py b/client/lib/engine/bin/FileSystemLib.py index aed53e7..83e5c26 100755 --- a/client/lib/engine/bin/FileSystemLib.py +++ b/client/lib/engine/bin/FileSystemLib.py @@ -85,7 +85,7 @@ def ogCheckFs (disk, par): errcode = ogGlobals.OG_ERR_PARTITION ogUnlock (disk, par) - return errcode + return not errcode ## reverse to indicate success #/** @@ -133,21 +133,21 @@ def ogExtendFs (disk, par): SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_PARTITION, f'{disk} {par} {type}') return - if not prog: return + if not prog: return None if domount: PART = ogMount (disk, par) - if not PART: return + if not PART: return None else: ogUnmount (disk, par) if ogIsMounted (disk, par): SystemLib.ogRaiseError([], ogGlobals.OG_ERR_PARTITION, f'{disk} {par}') - return + return None # Error si el sistema de archivos está bloqueado. if ogIsLocked (disk, par): SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_LOCKED, f'{disk} {par}') - return + return None # Redimensionar en modo uso exclusivo. ogLock (disk, par) diff --git a/client/lib/engine/bin/ImageLib.py b/client/lib/engine/bin/ImageLib.py index c8af204..5c5b200 100644 --- a/client/lib/engine/bin/ImageLib.py +++ b/client/lib/engine/bin/ImageLib.py @@ -262,7 +262,7 @@ def ogCreateImage (disk, par, container, imgfile, tool='partclone', level='gzip' FileSystemLib.ogUnlock (disk, par) ogUnlockImage (container, f'{imgfile}.{imgtype}') - return errcode + return not errcode ## reverse to indicate success #/** diff --git a/client/lib/engine/bin/ogGlobals.py b/client/lib/engine/bin/ogGlobals.py index 3bdedb5..41b0d4b 100755 --- a/client/lib/engine/bin/ogGlobals.py +++ b/client/lib/engine/bin/ogGlobals.py @@ -33,10 +33,10 @@ OGLOGCOMMAND='/tmp/command.log' #OGWINCHKDISK=True #Hacer chkdisk tras la clonacion ACTIONCACHEFULL='NONE' #Que hacer cuando la cache no tenga espacio libre. [ NONE | FORMAT ] ] RESTOREPROTOCOLNOTCACHE=None #Que protocolo de restauracion usar en el caso de que no exista cache o no exista espacio sufiente. [NONE | UNICAST | MULTICAST].NONE retorna error -#IMGPROG='partclone' -#IMGCOMP='lzop' -#IMGEXT='img' -#IMGREDUCE=True +IMGPROG='partclone' +IMGCOMP='lzop' +IMGEXT='img' +IMGREDUCE=True #OGWINREDUCE=True #Al enviar particion reducir el sistema de archivos previamente. MCASTERRORSESSION=120 #timeout (segundos) para abortar la sesion de multicast si no contacta con el servidor de multicast. Valor asignado a 0, utiliza los valores por defecto de udp-cast MCASTWAIT=30 # timeout (segundos) para abortar la la transferencia si se interrumpe. Valor asignado a 0, utiliza los valores por defecto de udp-cast diff --git a/client/shared/scripts/createImage.py b/client/shared/scripts/createImage.py new file mode 100755 index 0000000..fb625d9 --- /dev/null +++ b/client/shared/scripts/createImage.py @@ -0,0 +1,197 @@ +#!/usr/bin/python3 + +import os +import sys +import time +import tempfile +import subprocess + +import ogGlobals +import SystemLib +import NetLib +import StringLib +import DiskLib +import CacheLib +import FileLib +import PostConfLib +import ImageLib +import FileSystemLib +import InventoryLib +import UEFILib + +#/** +#@file createImage +#@brief Scirpt de ejemplo para crear una imagen de un sistema de archivos. +#@brief Se usa como base para el programa de creación de imágenes de OpenGnsys Admin). +#@param 1 disco +#@param 2 particion +#@param 3 REPO|CACHE +#@param 4 imagen +#@return +#@exception OG_ERR_FORMAT # 1 formato incorrecto. +#@exception OG_ERR_PARTITION # 3 Error en partición de disco o en su sistema de archivos +#@exception OG_ERR_IMAGE # 5 Error en funcion ogCreateImage o ogRestoreImage. +#@exception OG_ERR_NOTWRITE # 14 error de escritura +#@exception OG_ERR_NOTCACHE # 15 si cache no existe 15 +#@exception OG_ERR_CACHESIZE # 16 si espacio de la cache local o remota no tiene espacio 16 +#@exception OG_ERR_REDUCEFS # 17 error al reducir sistema de archivos. +#@exception OG_ERR_EXTENDFS # 18 Errror al expandir el sistema de archivos. +#@note +#@todo: que hacer, si el tamaño de la cache es sufciente, pero no tiene espacio libre +#@todo: que hacer, si hay una imagen con igual nombre en la cache +#*/ ## + +# Test 1. crear una imagen en un REPO sin espacio libre. +# test 2. crear una imagen en un REPO en modo solo lectura. +# test 3. intentar crear una imagen en la cache de un equipo que no la disponga. +# test 4. crear una imagen en la Cache sin espacio sufiente. +# test 5. intentar crear una imagen, en la que no se puede reducir el FS. + +prog = os.path.basename (sys.argv[0]) + +def main (disk, par, repo, imgname): + time1 = time.time() + + imgext = getattr (ogGlobals, 'IMGEXT') + if not imgext: imgext = 'img' + repo = repo.upper() + +#Load engine configurator from engine.cfg file. +#Carga el configurador del engine desde el fichero engine.cfg + +# Valores por defecto en etc/engine.cfg + +# Clear temporary file used as log track by httpdlog +# Limpia los ficheros temporales usados como log de seguimiento para httpdlog +# salvo si es llamado desde createImageCustom + if 'createImageCustom' != SystemLib.ogGetCaller(): + with open (ogGlobals.OGLOGSESSION, 'w') as fd: fd.write ('') + with open (ogGlobals.OGLOGCOMMAND, 'w') as fd: fd.write ('') + with open (f'{ogGlobals.OGLOGCOMMAND}.tmp', 'w') as fd: fd.write ('') + + SystemLib.ogEcho (['log', 'session'], None, f'[1] {ogGlobals.lang.MSG_SCRIPTS_START} {" ".join(sys.argv)}') + +# Si es una ip y es igual a la del equipo restaura desde cache + if NetLib.ogGetIpAddress() == repo: + repo = 'CACHE' + if StringLib.ogCheckIpAddress (repo) or 'REPO' == repo: + if not NetLib.ogChangeRepo (repo): + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTFOUND, repo) + sys.exit (1) + repo = 'REPO' + +# Si el repositorio es CACHE comprobamos que exista + if 'CACHE' == repo: + if not CacheLib.ogFindCache(): + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTCACHE, 'CACHE') + sys.exit (1) + +# Obtener información de los parámetros de entrada. + PART = DiskLib.ogDiskToDev (disk, par) + if not PART: + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_PARTITION, f'{disk} {par}') + sys.exit (1) + +#Comprobamos acceso de escritura. + dirtemp = time.strftime ('%Y%m%d-%H%M%S', time.gmtime()) + if not FileLib.ogMakeDir (container=repo, file=f'/{imgname}{dirtemp}'): + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTWRITE, repo) + FileLib.ogDeleteTree (repo, f'/{imgname}{dirtemp}') + sys.exit (1) + + imgdir = FileLib.ogGetParentPath (src=repo, file=f'/{imgname}') + if not imgdir: + dn = os.path.dirname (f'/{imgname}') + SystemLib.ogEcho (['log', 'session'], None, f'[5] {ogGlobals.lang.MSG_HELP_ogMakeDir} "{repo} {dn}"') + if not FileLib.ogMakeDir (container=repo, file=dn): + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTWRITE, f'{repo} /{imgname}') + sys.exit (1) + imgdir = FileLib.ogGetParentPath (src=repo, file=f'/{imgmame}') + if not imgdir: + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTWRITE, f'{repo} /{imgname}') + sys.exit (1) + bn = os.path.basename (f'/{imgname}') + imgfile = f'{imgdir}/{bn}.{imgext}' + + with open (ogGlobals.OGLOGCOMMAND, 'w') as fd: fd.write ('') + PostConfLib.ogCleanOs (disk, par) + +#Comprobar espacio que requerira la imagen para ser almacenada + sizedata, sizerequired, sizefree, isenoughspace = ImageLib.ogGetSizeParameters (disk, par, repo, imgname) + SystemLib.ogEcho (['log', 'session'], None, f'[16] {prog} {ogGlobals.lang.MSG_SCRIPTS_CREATE_SIZE} {sizerequired} {sizefree}') + if not isenoughspace: + SystemLib.ogRaiseError ('session', ogGlobals.OG_ERR_CACHESIZE, repo) + sys.exit (1) + +# Comprobar consistencia del sistema de archivos. + with open (ogGlobals.OGLOGCOMMAND, 'w') as fd: fd.write ('') + sizefs = FileSystemLib.ogGetFsSize (disk, par) + SystemLib.ogEcho (['log', 'session'], None, f'[20] {ogGlobals.lang.MSG_HELP_ogCheckFs} {par} {sizefs} (KB)') + FileSystemLib.ogUnmount (disk, par) + if not FileSystemLib.ogCheckFs (disk, par): + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_PARTITION, f'ogCheckFs {disk} {par}') + sys.exit (1) + +# Si es UEFI copio el cargador de arranque a la partición + ostype = InventoryLib.ogGetOsType (disk, par) + if InventoryLib.ogIsEfiActive() and 'Windows' == ostype: + SystemLib.ogEcho (['log', 'session'], None, f'[25] {ogGlobals.lang.MSG_HELP_ogCopyEfiBootLoader}') + UEFILib.ogCopyEfiBootLoader (disk, par) + +# Evaluar variable de engine.cfg para reducir el sistema de archivos en la creacion + if ogGlobals.IMGREDUCE: + SystemLib.ogEcho (['log', 'session'], None, f'[30] {ogGlobals.lang.MSG_HELP_ogReduceFs}') + FileSystemLib.ogReduceFs (disk, par) + newsizefs = FileSystemLib.ogGetFsSize (disk, par) + timeaux = time.time() - time1 + SystemLib.ogEcho (['log', 'session'], None, f' {ogGlobals.lang.MSG_SCRIPTS_TIME_PARTIAL} ( {newsizefs} KB ) : {int (timeaux/60)}m {int (timeaux%60)}s') + +# Renombrar el fichero de imagen si ya existe. + if os.path.exists (imgfile): + SystemLib.ogEcho (['log', 'session'], None, f'[35] {ogGlobals.lang.MSG_SCRIPTS_FILE_RENAME} "{imgfile}" -> "{imgfile}.ant".') + os.rename (imgfile, f'{imgfile}.ant') + if os.path.exists (f'{imgfile}.torrent'): os.rename (f'{imgfile}.torrent', f'{imgfile}.torrent.ant') + if os.path.exists (f'{imgfile}.sum'): os.rename (f'{imgfile}.sum', f'{imgfile}.sum.ant') + if os.path.exists (f'{imgfile}.full.sum'): os.rename (f'{imgfile}.full.sum', f'{imgfile}.full.sum.ant') + +# Crear la imagen. + with open (ogGlobals.OGLOGCOMMAND, 'w') as fd: fd.write ('') + time2 = time.time() + SystemLib.ogEcho (['log', 'session'], None, f'[40] {ogGlobals.lang.MSG_HELP_ogCreateImage} : ogCreateImage {disk} {par} {repo} {imgname} {ogGlobals.IMGPROG} {ogGlobals.IMGCOMP}') + if not ImageLib.ogCreateImage (disk, par, repo, f'/{imgname}', ogGlobals.IMGPROG, ogGlobals.IMGCOMP): + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_IMAGE, 'ogCreateImage') + sys.exit (1) + resumecreateimage = subprocess.run (['grep', 'Total Time:', ogGlobals.OGLOGCOMMAND], capture_output=True, text=True).stdout + timeaux2 = time.time() - time2 + SystemLib.ogEcho (['log', 'session'], None, f' {resumecreateimage} ') + SystemLib.ogEcho (['log', 'session'], None, f' {ogGlobals.lang.MSG_SCRIPTS_TIME_PARTIAL} : {int (timeaux2/60)}m {int (timeaux2%60)}s') + +# Extender sistema de archivos + time3 = time.time() + SystemLib.ogEcho (['log', 'session'], None, f'[90] Extender sistema de archivos.') + if not FileSystemLib.ogExtendFs (disk, par): + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_EXTENDFS, f'{disk} {par}') + sys.exit (1) + sizefs2 = FileSystemLib.ogGetFsSize (disk, par) + timeaux3 = time.time() - time3 + SystemLib.ogEcho (['log', 'session'], None, f' {ogGlobals.lang.MSG_HELP_ogExtendFs} {newsizefs} -> {sizefs} = {sizefs2}: {int (timeaux3/60)}m {int (timeaux3%60)}s') + +#TODO que hacer si error al extender sistemade archivos + +#resumen de la operacion + p = FileLib.ogGetPath (src=repo, file=f'/{imgname}.{imgext}') + ls_out = subprocess.run (['ls', '-s', p], capture_output=True, text=True).stdout + imgsize = ls_out.split()[0] + imgos = ImageLib.ogGetImageInfo (p) + + t = time.time() - time1 + SystemLib.ogEcho (['log', 'session'], None, f'[100] {ogGlobals.lang.MSG_SCRIPTS_TIME_TOTAL} {int (t/60)}m {int (t%60)}s') + SystemLib.ogEcho (['log', 'session'], None, f' FileSystem {PART} with {newsizefs} KB data created onto file-image as {imgname} and used {imgsize} KB') + SystemLib.ogEcho (['log', 'session'], None, f' Image-file {imgname} metadata: {imgos}') + +if __name__ == '__main__': + if 5 != len (sys.argv): + SystemLib.ogRaiseError ('session', ogGlobals.OG_ERR_FORMAT, f'{ogGlobals.lang.MSG_FORMAT}: {prog} ndisco nparticion REPO|CACHE imagen') + sys.exit (1) + main (*sys.argv[1:]) + diff --git a/client/shared/scripts/createImageCustomTemplate..py b/client/shared/scripts/createImageCustomTemplate.py similarity index 100% rename from client/shared/scripts/createImageCustomTemplate..py rename to client/shared/scripts/createImageCustomTemplate.py From 30c90442b7fd2a467431ff7cacb735c1ed473729 Mon Sep 17 00:00:00 2001 From: Natalia Serrano Date: Wed, 29 Jan 2025 12:28:25 +0100 Subject: [PATCH 122/167] refs #1399 remove ogCheckStringInGroup, ogCheckStringInReg --- client/lib/engine/bin/StringLib.py | 26 -------------------------- client/lib/engine/bin/SystemLib.py | 6 ++++-- client/lib/engine/bin/ogGlobals.py | 2 +- 3 files changed, 5 insertions(+), 29 deletions(-) diff --git a/client/lib/engine/bin/StringLib.py b/client/lib/engine/bin/StringLib.py index 49505d2..eda1c93 100755 --- a/client/lib/engine/bin/StringLib.py +++ b/client/lib/engine/bin/StringLib.py @@ -1,31 +1,5 @@ import re -def ogCheckStringInGroup(element, group): - """ - Función para determinar si el elemento pertenece a un conjunto. - - :param element: elemento a comprobar - :param group: grupo de elementos para comprobar tipo "valor1 valor2 valor3" - :return: True si pertenece al grupo, False si NO pertenece al grupo - """ - if not isinstance(element, str) or not isinstance(group, str): - raise ValueError("Formato incorrecto, ambos parámetros deben ser cadenas.") - - return element in group.split() - -def ogCheckStringInReg(element, regex): - """ - Función para determinar si el elemento contiene una "expresión regular". - - :param element: elemento a comprobar - :param regex: expresión regular - :return: True si coincide con la expresión, False si NO coincide con la expresión - """ - if not isinstance(element, str) or not isinstance(regex, str): - raise ValueError("Formato incorrecto, ambos parámetros deben ser cadenas.") - - return re.match(regex, element) is not None - #/** diff --git a/client/lib/engine/bin/SystemLib.py b/client/lib/engine/bin/SystemLib.py index 811ddcd..9524949 100755 --- a/client/lib/engine/bin/SystemLib.py +++ b/client/lib/engine/bin/SystemLib.py @@ -236,15 +236,17 @@ def ogRaiseError (logtypes, code, msg): MSG = ogGlobals.lang.MSG_ERR_GENERIC CODE = ogGlobals.OG_ERR_GENERIC + # Obtener lista de funciones afectadas, incluyendo el script que las llama. call_stack = [i[3] for i in inspect.stack()] if len (call_stack) < 2: return ## shouldn't happen call_stack.pop() ## remove '' call_stack.pop(0) ## remove 'ogRaiseError' str_call_stack = ' '.join (call_stack) + # Mostrar mensaje de error si es función depurable y salir con el código indicado. if code == ogGlobals.OG_ERR_FORMAT or \ - StringLib.ogCheckStringInGroup (str_call_stack, ogGlobals.NODEBUGFUNCTIONS) or \ - not (len(call_stack)>0 and StringLib.ogCheckStringInGroup (call_stack[0], ogGlobals.NODEBUGFUNCTIONS)): + (str_call_stack in ogGlobals.NODEBUGFUNCTIONS) or \ + not (len(call_stack)>0 and (call_stack[0] in ogGlobals.NODEBUGFUNCTIONS)): ogEcho (logtypes, "error", f"{str_call_stack.replace(' ', '<-')}: {MSG}") return code diff --git a/client/lib/engine/bin/ogGlobals.py b/client/lib/engine/bin/ogGlobals.py index 41b0d4b..cbce1ff 100755 --- a/client/lib/engine/bin/ogGlobals.py +++ b/client/lib/engine/bin/ogGlobals.py @@ -45,7 +45,7 @@ MCASTWAIT=30 # timeout (segundos) para abortar la la tran #BACKUP=False # Realizar copia de seguridad antes de crear la imagen. #IMGFS='EXT4' # Sistema de archivo de la imagenes sincronizadas. EXT4 o BTRFS #OGSLEEP=20 # Tiempo de sleep antes de realizar el reboot -NODEBUGFUNCTIONS='ogCreateImageSyntax ogGetHivePath ogGetOsType ogRestoreImageSyntax ogUnmountAll ogUnmountCache' # Funciones que no deben mostrar salida de avisos si son llamadas por otras funciones. +NODEBUGFUNCTIONS=['ogCreateImageSyntax', 'ogGetHivePath', 'ogGetOsType', 'ogRestoreImageSyntax', 'ogUnmountAll', 'ogUnmountCache'] # Funciones que no deben mostrar salida de avisos si son llamadas por otras funciones. #DEFAULTSPEED='' ## /engine.cfg From fab9fe7ddba416f43430c4737a7ebd5677cd9623 Mon Sep 17 00:00:00 2001 From: Natalia Serrano Date: Wed, 29 Jan 2025 18:13:20 +0100 Subject: [PATCH 123/167] refs #1401 add ogListSoftware, fix a bug --- client/lib/engine/bin/BootLib.py | 2 + client/lib/engine/bin/InventoryLib.py | 167 +++++++++++++++++-------- client/shared/functions/ogListSoftware | 24 ++++ 3 files changed, 143 insertions(+), 50 deletions(-) create mode 100755 client/shared/functions/ogListSoftware diff --git a/client/lib/engine/bin/BootLib.py b/client/lib/engine/bin/BootLib.py index 87823a2..bf6f0b9 100644 --- a/client/lib/engine/bin/BootLib.py +++ b/client/lib/engine/bin/BootLib.py @@ -605,6 +605,8 @@ def ogConfigureFstab (disk, par): SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTFOUND, f'{disk},{par},/etc/fstab') return + efiopt = '' + shutil.copy2 (fstab, fstab+'.backup') with open ('/etc/fstab', 'r') as fd: diff --git a/client/lib/engine/bin/InventoryLib.py b/client/lib/engine/bin/InventoryLib.py index ac58d9e..4ff5d40 100755 --- a/client/lib/engine/bin/InventoryLib.py +++ b/client/lib/engine/bin/InventoryLib.py @@ -10,12 +10,12 @@ import platform import sys import os import subprocess -import tempfile import re import json import shutil import glob import plistlib +#import bsddb import ogGlobals import SystemLib @@ -197,65 +197,132 @@ def ogListHardwareInfo(): #@note Requisitos: ... #@todo Detectar software en Linux #*/ ## -def ogListSoftware(disk, partition): - if disk is None or partition is None: - SystemLib.ogRaiseError(ogGlobals.OG_ERR_FORMAT) - return [] +def ogListSoftware (disk, par): + mntdir = FileSystemLib.ogMount (disk, par) + if not mntdir: return None + ostype = ogGetOsType (disk, par) + if not ostype: return None - mnt_dir = FileSystemLib.ogMount(disk, partition) - os_type = ogGetOsType(disk, partition) - - apps_file = tempfile.NamedTemporaryFile(delete=False, mode="w+") - tmp_file = tempfile.NamedTemporaryFile(delete=False, mode="w+") apps = [] - try: - if os_type == "Linux": - pkg_dir = os.path.join(mnt_dir, "var/lib/dpkg") - status_file = os.path.join(pkg_dir, "status") - if os.path.exists(status_file): - with open(status_file, "r") as f: - pkg, ver = None, None - for line in f: - if line.startswith("Package:"): - pkg = line.split(":", 1)[1].strip() - elif line.startswith("Version:"): - ver = line.split(":", 1)[1].strip() - elif line.startswith("Status:") and "install" not in line: - pkg, ver = None, None - if pkg and ver: - apps.append(f"{pkg} {ver}") - pkg, ver = None, None + if 'Linux' == ostype: + # Procesar paquetes dpkg. + pkgdir = f'{mntdir}/var/lib/dpkg' + if os.path.exists (pkgdir): + status_file = os.path.join(pkgdir, "status") + awk_script = ''' + /Package:/ {if (pack!="") print pack,vers; + sub(/-dev$/,"",$2); + pack=$2} + /Version:/ {sub(/^.*:/,"",$2); sub(/-.*$/,"",$2); + vers=$2} + /Status:/ {if ($2!="install") pack=vers=""} + END {if (pack!="") print pack,vers} + ''' + awk_out = subprocess.run (['awk', awk_script, status_file], capture_output=True, text=True).stdout + apps = awk_out.splitlines() - pkg_dir = os.path.join(mnt_dir, "var/lib/rpm") - if os.path.exists(pkg_dir): - if shutil.which("rpm"): - result = subprocess.run( - ["rpm", "--dbpath", pkg_dir, "-qa", "--qf", "%{NAME} %{VERSION}\n"], - capture_output=True, - text=True - ) - if result.returncode == 0: - apps.extend(result.stdout.strip().splitlines()) - else: - SystemLib.ogEcho("session", "error", "The rpm command is not available.") + # Procesar paquetes RPM. + pkgdir = f'{mntdir}/var/lib/rpm' + if os.path.exists (pkgdir): + if shutil.which ('rpm'): + for f in glob.glob (f'{pkgdir}/__db.*'): + os.unlink (f) + rpm_out = subprocess.run (['rpm', '--dbpath', pkgdir, '-qa', '--qf', '%{NAME} %{VERSION}\n'], capture_output=True, text=True).stdout + for l in rpm_out.splitlines(): + words = l.split() + if (not re.search ('-devel$', words[0])): + words[1] = re.sub ('-.*', '', words[1]) + apps.append (' '.join (words)) + for f in glob.glob (f'{pkgdir}/__db.*'): + os.unlink (f) + else: + pass + #db = bsddb.hashopen (f'{pkgdir}/Name', 'r'); + #for k in db.keys(): + # apps.append (re.sub ('-devel$', '', k)) - pass + # Procesar paquetes pacman. + pkgdir = f'{mntdir}/var/lib/pacman/local' + if os.path.exists (pkgdir): + for f in glob.glob (f'{pkgdir}/*'): + if '-' not in f: continue + idx = f[0:f.rfind ('-')].rfind ('-') ## index of 2nd-to-last dash + apps.append (f[0:idx] + ' ' + f[idx+1:]) + # Procesar aplicaciones Snappy. + pkgdir = f'{mntdir}/snap' + out = '' + awk_script = ''' + /name:/ {pack=$2} + /version:/ {vers=$2} + END {if (pack!="") print pack,"(snap)",vers} + ''' + files = subprocess.run (['find', f'{pkgdir}/*/current/meta', '-name', 'snap.yaml'], capture_output=True, text=True).stdout.splitlines() + for f in files: + awk_out = subprocess.run (['awk', awk_script, f], capture_output=True, text=True).stdout + out += awk_out + apps += out.splitlines() + # Procesar aplicaciones Flatpak. + pkgdir = f'{mntdir}/var/lib/flatpak' + files = glob.glob (f'{pkgdir}/app/*/current/active/deploy/*') + for f in files: + p = open (f.strip()).read().split ('\0') + try: + if (p[0] != 'flathub'): raise ValueError + apps.append ('{} (flatpak) {}'.format (p[p.index('appdata-name') + 4], p[p.index('appdata-version') + 1])) + except ValueError: + pass + elif 'Windows' == ostype: + if shutil.which ('hivexregedit'): + hive = RegistryLib.ogGetHivePath (mntdir, 'software') + if hive: + cmd1_out = subprocess.run (['hivexregedit', '--unsafe-printable-strings', '--export', hive, r'\Microsoft\Windows\CurrentVersion\Uninstall'], capture_output=True, text=True).stdout + cmd1_out += subprocess.run (['hivexregedit', '--unsafe-printable-strings', '--export', hive, r'\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall'], capture_output=True, text=True).stdout + out = name = '' + for l in cmd1_out.splitlines(): + words = l.split ('"') + if len(words) < 4: continue + if (re.match (r'\[', words[0])): name='' + if (re.search ('DisplayName', words[1])): name=words[3] + if (re.search ('DisplayVersion', words[1])): apps.append (f'{name} {words[3]}') else: - SystemLib.ogRaiseError(ogGlobals.OG_ERR_NOTOS, disk, partition) - return [] + keys = RegistryLib.ogListRegistryKeys (mntdir, 'software', r'\Microsoft\Windows\CurrentVersion\Uninstall') + keys32 = RegistryLib.ogListRegistryKeys (mntdir, 'software', r'\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall') + for k in keys: + prog = RegistryLib.ogGetRegistryValue (mntdir, 'software', rf'\Microsoft\Windows\CurrentVersion\Uninstall\{k}\DisplayName') + if prog: + vers = RegistryLib.ogGetRegistryValue (mntdir, 'software', rf'\Microsoft\Windows\CurrentVersion\Uninstall\{k}\DisplayVersion') + apps.append (f'{prog} {vers}') + for k in keys32: + prog = RegistryLib.gGetRegistryValue (mntdir, 'software', rf'\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\{k}\DisplayName') + if prog: + vers = RegistryLib.ogGetRegistryValue (mntdir, 'software', rf'\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\{k}\DisplayVersion') + apps.append (f'{prog} {vers}') - finally: - apps_file.close() - tmp_file.close() - os.remove(apps_file.name) - os.remove(tmp_file.name) + elif 'MacOS' == ostype: + files = subprocess.run (['find', f'{mntdir}/Applications', '-type', 'd', '-name', '*.app', '-prune', '-print'], capture_output=True, text=True).stdout.splitlines() + for k in files: + FILE = f'{k}/Contents/version.plist' + if not os.stat (FILE).st_size: + FILE = f'{k}/Contents/version.plist.uncompress' + if os.stat (FILE).st_size: + VERSION = subprocess.run (['awk', '-F[<>]', '/ShortVersionString/ {getline;v=$3} END {print v}', FILE], capture_output=True, text=True).stdout.strip() + bn = os.path.basename (k) + bn = re.sub ('.app$', '', bn) + apps.append (f'{bn} {VERSION}') - os_version = ogGetOsVersion(disk, partition) - print(f"Operative System: {os_version}") + elif 'BSD' == ostype: + sqlite_out = subprocess.run (['sqlite3', f'{mntdir}/var/db/pkg/local.sqlite'], input='SELECT name FROM pkg_search;\n', capture_output=True, text=True).stdout + for l in sqlite_out.splitlines(): + apps.append (' '.join (re.search ('(.*)-(.*)', l).groups())) - return sorted(set(apps)) + else: + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTOS, f'{disk}, {par} ({ostype})') + return None + + os_version = ogGetOsVersion (disk, par).split (':')[1] + return [os_version] + sorted (set (apps)) ## https://stackoverflow.com/questions/2522651/find-a-key-inside-a-deeply-nested-dictionary/2522706#2522706 def _find_key_recursive(plist_dict, key_substr): diff --git a/client/shared/functions/ogListSoftware b/client/shared/functions/ogListSoftware new file mode 100755 index 0000000..75abb9f --- /dev/null +++ b/client/shared/functions/ogListSoftware @@ -0,0 +1,24 @@ +#!/usr/bin/python3 + +import sys +import argparse +from SystemLib import ogHelp +from InventoryLib import ogListSoftware + +parser = argparse.ArgumentParser (add_help=False) +parser.add_argument ('disk') +parser.add_argument ('par') + +if 2 == len (sys.argv) and 'help' == sys.argv[1]: + #parser.print_help() sale en inglés aunque la locale indique otra cosa + ogHelp ('ogListSoftware', 'ogListSoftware int_disk int_partition', ['ogListSoftware 1 1']) + sys.exit (0) + +args = parser.parse_args() + +ret = ogListSoftware (args.disk, args.par) +if ret is not None: + if ret == True: sys.exit (0) + elif ret == False: sys.exit (1) + else: + for k in ret: print (k) From 451fa584b588126749425d68aac58a6499819290 Mon Sep 17 00:00:00 2001 From: Natalia Serrano Date: Wed, 29 Jan 2025 18:33:36 +0100 Subject: [PATCH 124/167] refs #1402 add listSoftwareInfo.py --- client/shared/scripts/listSoftwareInfo.py | 56 +++++++++++------------ 1 file changed, 27 insertions(+), 29 deletions(-) diff --git a/client/shared/scripts/listSoftwareInfo.py b/client/shared/scripts/listSoftwareInfo.py index 84f94ae..1c2756e 100755 --- a/client/shared/scripts/listSoftwareInfo.py +++ b/client/shared/scripts/listSoftwareInfo.py @@ -1,41 +1,39 @@ +#!/usr/bin/python3 +# Scirpt de ejemplo para almacenear en fichero temporal el listado de software. +# Nota: se usa como base para el programa de recogida de listado de software de OpenGnsys Admin. +# Formato: listSoftwareInfo [-r] ndisk npart +# -r listado reducido (sin parches de Windows) + import os import sys -sys.path.append('/opt/opengnsys/lib/engine/bin') +import re +import argparse +import ogGlobals import SystemLib import InventoryLib import NetLib -import ogGlobals -PROG = os.path.basename(__file__) -REDUCED = "no" +prog = os.path.basename (sys.argv[0]) -if len(sys.argv) > 1 and sys.argv[1] == "-r": - REDUCED = "yes" - sys.argv.pop(1) +def main (disk, par, reduced): + ip = NetLib.ogGetIpAddress() + softfile = f'{ogGlobals.OGLOG}/soft-{ip}-{disk}-{par}' + software_list = InventoryLib.ogListSoftware (disk, par) -if len(sys.argv) != 3: - SystemLib.ogRaiseError("session", ogGlobals.OG_ERR_FORMAT, f"{ogGlobals.MSG_FORMAT}: {PROG} ndisco nparticion") - sys.exit(1) + if reduced: + software_list = [line for line in software_list if not re.search (r'(KB[0-9]{6})', line)] -SOFTFILE = f"soft-{NetLib.ogGetIpAddress()}-{sys.argv[1]}-{sys.argv[2]}" -softfile_path = os.path.join(ogGlobals.OGLOG, SOFTFILE) + with open (softfile, 'w') as f: + for line in software_list: + f.write (f'{line}\n') -try: - software_list = InventoryLib.ogListSoftware(int(sys.argv[1]), int(sys.argv[2])) + print (softfile) - if REDUCED == "no": - with open(softfile_path, "w") as f: - for line in software_list: - f.write(f"{line}\n") - else: - filtered_list = [line for line in software_list if "(KB" not in line] - with open(softfile_path, "w") as f: - for line in filtered_list: - f.write(f"{line}\n") - - print(softfile_path) - -except Exception as e: - SystemLib.ogRaiseError("session", ogGlobals.OG_ERR_FORMAT, f"Error al generar el listado de software: {e}") - sys.exit(1) \ No newline at end of file +if __name__ == '__main__': + parser = argparse.ArgumentParser (add_help=False) + parser.add_argument ('-r', '--reduced', action='store_true', default=False) + parser.add_argument ('disk') + parser.add_argument ('par') + args = parser.parse_args() + main (args.disk, args.par, args.reduced) From e73e91dbc3a599758e82a6679bfbef7fa584587c Mon Sep 17 00:00:00 2001 From: Natalia Serrano Date: Thu, 30 Jan 2025 11:26:00 +0100 Subject: [PATCH 125/167] refs #1410 add ogGetLastSector --- client/lib/engine/bin/DiskLib.py | 54 +++++++++++-------------- client/shared/functions/ogGetLastSector | 30 ++++++++++++++ 2 files changed, 53 insertions(+), 31 deletions(-) create mode 100755 client/shared/functions/ogGetLastSector diff --git a/client/lib/engine/bin/DiskLib.py b/client/lib/engine/bin/DiskLib.py index dcde73f..e700cc4 100755 --- a/client/lib/engine/bin/DiskLib.py +++ b/client/lib/engine/bin/DiskLib.py @@ -722,39 +722,31 @@ def ogGetEsp(): #@exception OG_ERR_NOTFOUND Disco o partición no corresponde con un dispositivo. #@note Requisitos: sfdisk, sgdisk #*/ ## -def ogGetLastSector(*args): - # Variables locales - DISK = None - PART = None - LASTSECTOR = None +def ogGetLastSector (disk, par=None): + DISK = ogDiskToDev (disk) + if not DISK: return None + env = os.environ + env['LANG'] = 'C' + last = None + if par: + PART = ogDiskToDev (disk, par) + if not PART: return None + sgdisk_out = subprocess.run (['sgdisk', '-p', DISK], env=env, capture_output=True, text=True).stdout + for l in sgdisk_out.splitlines(): + items = l.split() + if len(items) < 3: continue + if par != items[0]: continue + last = items[2] + break - # Si se solicita, mostrar ayuda. - if len(args) == 1 and args[0] == "help": - SystemLib.ogHelp("ogGetLastSector", "ogGetLastSector int_ndisk [int_npart]", - "ogGetLastSector 1 => 488392064", - "ogGetLastSector 1 1 => 102400062") - return + else: + sgdisk_out = subprocess.run (['sgdisk', '-p', DISK], env=env, capture_output=True, text=True).stdout + for l in sgdisk_out.splitlines(): + if 'last usable sector' not in l: continue + items = l.split() + last = items[-1] - # Obtener último sector. - if len(args) == 1: # Para un disco. - DISK = ogDiskToDev(args[0]) - if DISK is None: - return - LASTSECTOR = subprocess.getoutput(f"sgdisk -p {DISK} | awk '/last usable sector/ {{print($(NF))}}'") - elif len(args) == 2: # Para una partición. - DISK = ogDiskToDev(args[0]) - if DISK is None: - return - PART = ogDiskToDev(args[0], args[1]) - if PART is None: - return - LASTSECTOR = subprocess.getoutput(f"sgdisk -p {DISK} | awk -v P='{args[1]}' '{{if ($1==P) print $3}}'") - else: # Error si se reciben más parámetros. - SystemLib.ogRaiseError(OG_ERR_FORMAT) - return - - print(LASTSECTOR) - return + return last #/** diff --git a/client/shared/functions/ogGetLastSector b/client/shared/functions/ogGetLastSector new file mode 100755 index 0000000..4723660 --- /dev/null +++ b/client/shared/functions/ogGetLastSector @@ -0,0 +1,30 @@ +#!/usr/bin/python3 + +import sys +import argparse +from SystemLib import ogHelp +from DiskLib import ogGetLastSector + +if 2 == len (sys.argv) and 'help' == sys.argv[1]: + #parser.print_help() sale en inglés aunque la locale indique otra cosa + ogHelp ('ogGetLastSector', 'ogGetLastSector int_ndisk [int_npart]', ['ogGetLastSector 1'], ['ogGetLastSector 1 1']) + sys.exit (0) + +parser = argparse.ArgumentParser (add_help=False) +if 2 == len (sys.argv): + parser.add_argument ('disk') +elif 3 == len (sys.argv): + parser.add_argument ('disk') + parser.add_argument ('par') + +args = parser.parse_args() + +if 2 == len (sys.argv): + ret = ogGetLastSector (args.disk) +elif 3 == len (sys.argv): + ret = ogGetLastSector (args.disk, args.par) + +if ret is not None: + if ret == True: sys.exit (0) + elif ret == False: sys.exit (1) + else: print (ret) From 34bc9c3c89e90d7bc2dcd52135aa8792e07504c0 Mon Sep 17 00:00:00 2001 From: Natalia Serrano Date: Thu, 30 Jan 2025 11:48:44 +0100 Subject: [PATCH 126/167] refs #1411 add ogUnmountAll --- client/lib/engine/bin/DiskLib.py | 56 +++++++++---------- client/lib/engine/bin/FileSystemLib.py | 20 ++----- client/shared/functions/ogGetPartitionsNumber | 22 ++++++++ client/shared/functions/ogUnmountAll | 22 ++++++++ 4 files changed, 74 insertions(+), 46 deletions(-) create mode 100755 client/shared/functions/ogGetPartitionsNumber create mode 100755 client/shared/functions/ogUnmountAll diff --git a/client/lib/engine/bin/DiskLib.py b/client/lib/engine/bin/DiskLib.py index e700cc4..2332052 100755 --- a/client/lib/engine/bin/DiskLib.py +++ b/client/lib/engine/bin/DiskLib.py @@ -851,39 +851,33 @@ def ogGetPartitionSize (disk, par): #@attention Requisitos: parted #@note Notas sin especificar #*/ ## -def ogGetPartitionsNumber(*args): - # Variables locales - DISK = None +def ogGetPartitionsNumber (disk): + DISK = ogDiskToDev (disk) + if not DISK: return None + out = 0 - # Si se solicita, mostrar ayuda. - if len(args) == 1 and args[0] == "help": - SystemLib.ogHelp('ogGetPartitionsNumber', 'ogGetPartitionsNumber int_ndisk', 'ogGetPartitionsNumber 1 => 3') - return + pttype = ogGetPartitionTableType (disk) + if pttype in ['GPT', 'MSDOS']: + partx_out = subprocess.run (['partx', '-gso', 'NR', DISK], capture_output=True, text=True).stdout + lines = partx_out.splitlines() + out = lines[-1].strip() + elif 'LVM' == pttype: + lvs_out = subprocess.run (['lvs', '--noheadings', DISK], capture_output=True, text=True).stdout + lines = lvs_out.splitlines() + out = len (lines) + elif 'ZPOOL' == pttype: + if subprocess.run (['zpool', 'list']).returncode: + subprocess.run (['modprobe', 'zfs']) + subprocess.run (['zpool', 'import', '-f', '-R', '/mnt', '-N', '-a']) + blkid = subprocess.run (['blkid', '-s', 'LABEL', '-o', 'value', DISK], capture_output=True, text=True).stdout + zfs_out = subprocess.run (['zfs', 'list', '-Hp', '-o', 'name,canmount,mountpoint', '-r', blkid], capture_output=True, text=True).stdout + out = 0 + for l in zfs_out.splitlines(): + items = l.split() + if len(items) < 3: continue + if 'on' == items[1] and 'none' != items[2]: out += 1 - # Error si no se recibe 1 parámetro. - if len(args) != 1: - SystemLib.ogRaiseError(OG_ERR_FORMAT) - return - - # Contar el número de veces que aparece el disco en su lista de particiones. - DISK = ogDiskToDev(args[0]) - if DISK is None: - return - PTTYPE = ogGetPartitionTableType(args[0]) - if PTTYPE in ["GPT", "MSDOS"]: - output = subprocess.getoutput(f"partx -gso NR {DISK} 2>/dev/null | awk -v p=0 '{{p=$1}} END {{print p}}'") - elif PTTYPE == "LVM": - output = subprocess.getoutput(f"lvs --noheadings {DISK} 2>/dev/null | wc -l") - elif PTTYPE == "ZPOOL": - subprocess.run(["zpool", "list"], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) # Check if zpool command exists - subprocess.run(["modprobe", "zfs"]) # Load zfs module if not already loaded - subprocess.run(["zpool", "import", "-f", "-R", "/mnt", "-N", "-a"], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) # Import all zpools - output = subprocess.getoutput(f"zfs list -Hp -o name,canmount,mountpoint -r $(blkid -s LABEL -o value {DISK}) | awk '$2==\"on\" && $3!=\"none\" {{c++}} END {{print c}}'") - else: - output = None - - print(output) - return + return int (out) #/** diff --git a/client/lib/engine/bin/FileSystemLib.py b/client/lib/engine/bin/FileSystemLib.py index 83e5c26..9b01d35 100755 --- a/client/lib/engine/bin/FileSystemLib.py +++ b/client/lib/engine/bin/FileSystemLib.py @@ -849,21 +849,11 @@ def ogUnmountFs(disk, par): #@exception OG_ERR_NOTFOUND Disco o particion no corresponden con un dispositivo. #@warning No se desmonta la partición marcada como caché local. #*/ ## -def ogUnmountAll(int_ndisk): - - if len(sys.argv) != 3: - SystemLib.ogRaiseError ( - [], - ogGlobals.OG_ERR_FORMAT, - "Not enough arguments" - ) - return - - # Obtener partición y punto de montaje. - DISK = DiskLib.ogDiskToDev(int_ndisk) - for PART in range(1, DiskLib.ogGetPartitionsNumber(int_ndisk) + 1): - if ogGetFsType(int_ndisk, PART) != "CACHE": - ogUnmount(int_ndisk, PART) +def ogUnmountAll (disk): + DISK = DiskLib.ogDiskToDev (disk) + for PART in range (1, DiskLib.ogGetPartitionsNumber (disk) + 1): + if 'CACHE' != ogGetFsType (disk, PART): + ogUnmount (disk, PART) #/** diff --git a/client/shared/functions/ogGetPartitionsNumber b/client/shared/functions/ogGetPartitionsNumber new file mode 100755 index 0000000..de6bbe7 --- /dev/null +++ b/client/shared/functions/ogGetPartitionsNumber @@ -0,0 +1,22 @@ +#!/usr/bin/python3 + +import sys +import argparse +from SystemLib import ogHelp +from DiskLib import ogGetPartitionsNumber + +parser = argparse.ArgumentParser (add_help=False) +parser.add_argument ('disk') + +if 2 == len (sys.argv) and 'help' == sys.argv[1]: + #parser.print_help() sale en inglés aunque la locale indique otra cosa + ogHelp ('ogGetPartitionsNumber', 'ogGetPartitionsNumber int_ndisk', ['ogGetPartitionsNumber 1']) + sys.exit (0) + +args = parser.parse_args() +ret = ogGetPartitionsNumber (args.disk) + +if ret is not None: + if ret == True: sys.exit (0) + elif ret == False: sys.exit (1) + else: print (ret) diff --git a/client/shared/functions/ogUnmountAll b/client/shared/functions/ogUnmountAll new file mode 100755 index 0000000..5b69eb7 --- /dev/null +++ b/client/shared/functions/ogUnmountAll @@ -0,0 +1,22 @@ +#!/usr/bin/python3 + +import sys +import argparse +from SystemLib import ogHelp +from FileSystemLib import ogUnmountAll + +parser = argparse.ArgumentParser (add_help=False) +parser.add_argument ('disk') + +if 2 == len (sys.argv) and 'help' == sys.argv[1]: + #parser.print_help() sale en inglés aunque la locale indique otra cosa + ogHelp ('ogUnmountAll', 'ogUnmountAll int_ndisk', ['ogUnmountAll 1']) + sys.exit (0) + +args = parser.parse_args() +ret = ogUnmountAll (args.disk) + +if ret is not None: + if ret == True: sys.exit (0) + elif ret == False: sys.exit (1) + else: print (ret) From 9e02db9136911740d3b6e19400cacbc6c148b668 Mon Sep 17 00:00:00 2001 From: Natalia Serrano Date: Thu, 30 Jan 2025 13:17:41 +0100 Subject: [PATCH 127/167] refs #1412 add ogCreatePartitionTable --- client/lib/engine/bin/DiskLib.py | 90 +++++++------------ .../shared/functions/ogCreatePartitionTable | 30 +++++++ 2 files changed, 63 insertions(+), 57 deletions(-) create mode 100755 client/shared/functions/ogCreatePartitionTable diff --git a/client/lib/engine/bin/DiskLib.py b/client/lib/engine/bin/DiskLib.py index 2332052..e1c3f6b 100755 --- a/client/lib/engine/bin/DiskLib.py +++ b/client/lib/engine/bin/DiskLib.py @@ -270,72 +270,48 @@ def ogCreateGptPartitions(*args): #@note tabletype: { MSDOS, GPT }, MSDOS por defecto #@note Requisitos: fdisk, gdisk, parted #*/ ## -def ogCreatePartitionTable(*args): - # Variables locales - DISK = PTTYPE = CREATE = CREATEPTT = None +def ogCreatePartitionTable (disk, createptt=None): + DISK = ogDiskToDev (disk) + if not DISK: return None - # Si se solicita, mostrar ayuda. - if len(args) == 1 and args[0] == "help": - SystemLib.ogHelp('ogCreatePartitionTable', 'ogCreatePartitionTable int_ndisk [str_partype]', - 'ogCreatePartitionTable 1 GPT', 'ogCreatePartitionTable 1') - return + pttype = ogGetPartitionTableType (disk) or 'MSDOS' # Por defecto para discos vacíos. + createptt = createptt or pttype + CREATE = None - # Error si no se reciben 1 o 2 parámetros. - if len(args) == 1: - CREATEPTT = "" - elif len(args) == 2: - CREATEPTT = args[1] - else: - SystemLib.ogRaiseError(OG_ERR_FORMAT) - return - - # Capturamos el tipo de tabla de particiones actual - DISK = ogDiskToDev(args[0]) - if DISK is None: - return - PTTYPE = ogGetPartitionTableType(args[0]) or "MSDOS" # Por defecto para discos vacíos. - CREATEPTT = CREATEPTT or PTTYPE - - # Si la tabla actual y la que se indica son iguales, se comprueba si hay que regenerarla. - if CREATEPTT == PTTYPE: - if PTTYPE == "GPT": +# Si la tabla actual y la que se indica son iguales, se comprueba si hay que regenerarla. + if createptt == pttype: + if 'GPT' == pttype: try: - result = subprocess.run( - ["sgdisk", "-p", DISK], - stderr=subprocess.PIPE, - stdout=subprocess.DEVNULL - ) - if result.returncode != 0: - CREATE = "GPT" + result = subprocess.run (['sgdisk', '-p', DISK]) + if result.returncode: + CREATE = 'GPT' except subprocess.CalledProcessError: - CREATE = "GPT" - elif PTTYPE == "MSDOS": + CREATE = 'GPT' + elif 'MSDOS' == pttype: try: - result = subprocess.run( - ["parted", "-s", DISK, "print"], - stderr=subprocess.PIPE, - stdout=subprocess.DEVNULL - ) - if result.returncode != 0: - CREATE = "MSDOS" + result = subprocess.run (['parted', '-s', DISK, 'print']) + if result.returncode: + CREATE = 'MSDOS' except subprocess.CalledProcessError: - CREATE = "MSDOS" + CREATE = 'MSDOS' else: - CREATE = CREATEPTT + CREATE = createptt.upper() - # Dependiendo del valor de CREATE, creamos la tabla de particiones en cada caso. - if CREATE == "GPT": - if PTTYPE == "MSDOS": - subprocess.run(["sgdisk", "-go", DISK]) +# Dependiendo del valor de CREATE, creamos la tabla de particiones en cada caso. + if 'GPT' == CREATE: + if 'MSDOS' == pttype: + subprocess.run (['sgdisk', '-go', DISK]) else: - subprocess.run(["gdisk", DISK], input="2\nw\nY\n", text=True) - subprocess.run(["partprobe", DISK], stderr=subprocess.DEVNULL) - elif CREATE == "MSDOS": - if PTTYPE == "GPT": - subprocess.run(["sgdisk", "-Z", DISK]) - subprocess.run(["fdisk", DISK], input="o\nn\np\n\n\n\nd\n\nw", text=True) - subprocess.run(["partprobe", DISK], stderr=subprocess.DEVNULL) - return + subprocess.run (['gdisk', DISK], input='2\nw\nY\n', text=True) + subprocess.run (['partprobe', DISK]) + elif 'MSDOS' == CREATE: + if 'GPT' == pttype: + subprocess.run (['sgdisk', '-Z', DISK]) + # Crear y borrar una partición para que la tabla se genere bien. + subprocess.run (['fdisk', DISK], input='o\nn\np\n\n\n\nd\n\nw', text=True) + subprocess.run (['partprobe', DISK]) + + return None #/** diff --git a/client/shared/functions/ogCreatePartitionTable b/client/shared/functions/ogCreatePartitionTable new file mode 100755 index 0000000..415c10c --- /dev/null +++ b/client/shared/functions/ogCreatePartitionTable @@ -0,0 +1,30 @@ +#!/usr/bin/python3 + +import sys +import argparse +from SystemLib import ogHelp +from DiskLib import ogCreatePartitionTable + +if 2 == len (sys.argv) and 'help' == sys.argv[1]: + #parser.print_help() sale en inglés aunque la locale indique otra cosa + ogHelp ('ogCreatePartitionTable', 'ogCreatePartitionTable int_ndisk [str_partype]', ['ogCreatePartitionTable 1 GPT', 'ogCreatePartitionTable 1']) + sys.exit (0) + +parser = argparse.ArgumentParser (add_help=False) +if 2 == len (sys.argv): + parser.add_argument ('disk') +elif 3 == len (sys.argv): + parser.add_argument ('disk') + parser.add_argument ('createptt') + +args = parser.parse_args() + +if 2 == len (sys.argv): + ret = ogCreatePartitionTable (args.disk) +elif 3 == len (sys.argv): + ret = ogCreatePartitionTable (args.disk, args.createptt) + +if ret is not None: + if ret == True: sys.exit (0) + elif ret == False: sys.exit (1) + else: print (ret) From 25901173b999a9d357298f70b3f65dcd4b2b4814 Mon Sep 17 00:00:00 2001 From: Natalia Serrano Date: Thu, 30 Jan 2025 13:20:27 +0100 Subject: [PATCH 128/167] refs #1413 add ogUpdatePartitionTable --- client/shared/functions/ogUpdatePartitionTable | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100755 client/shared/functions/ogUpdatePartitionTable diff --git a/client/shared/functions/ogUpdatePartitionTable b/client/shared/functions/ogUpdatePartitionTable new file mode 100755 index 0000000..8200b2a --- /dev/null +++ b/client/shared/functions/ogUpdatePartitionTable @@ -0,0 +1,13 @@ +#!/usr/bin/python3 + +import sys +import argparse +from SystemLib import ogHelp +from DiskLib import ogUpdatePartitionTable + +ret = ogUpdatePartitionTable() + +if ret is not None: + if ret == True: sys.exit (0) + elif ret == False: sys.exit (1) + else: print (ret) From 1c6b5ace1642b6abb511cdf620e181476132067a Mon Sep 17 00:00:00 2001 From: Natalia Serrano Date: Thu, 30 Jan 2025 17:05:21 +0100 Subject: [PATCH 129/167] refs #1415 add ogGetCacheSpace, fix a bug --- client/lib/engine/bin/CacheLib.py | 82 ++++++++++++++----------- client/shared/functions/ogGetCacheSpace | 13 ++++ 2 files changed, 59 insertions(+), 36 deletions(-) create mode 100755 client/shared/functions/ogGetCacheSpace diff --git a/client/lib/engine/bin/CacheLib.py b/client/lib/engine/bin/CacheLib.py index 575457b..d2303b1 100755 --- a/client/lib/engine/bin/CacheLib.py +++ b/client/lib/engine/bin/CacheLib.py @@ -193,46 +193,51 @@ def ogGetCacheSize(): #@note El espacio disponible es el que hay entre el límite superior de la partición 3 del disco 1 y el final de dicho disco, y no puede ser superior a la mitad de dicho disco. #*/ ## def ogGetCacheSpace(): - """ - Obtiene el espacio libre en la partición de caché en kilobytes. - - :return: Espacio libre en kilobytes. - :raises RuntimeError: Si ocurre un error al obtener el espacio libre. - """ - # Si se solicita, mostrar ayuda. - if len(sys.argv) > 1 and sys.argv[1] == "help": - ogHelp("ogGetCacheSpace", "help", "ogGetCacheSpace") - - # Error si no se encuentra partición de caché. cachepart = ogFindCache() - if cachepart is None: - raise RuntimeError(MSG_NOCACHE) + if not cachepart: + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_PARTITION, ogGlobals.lang.MSG_NOCACHE) + return None + cachepart = cachepart.split() - # Obtener el tamaño del disco y el número de sectores. - disk = ogDiskToDev(cachepart) - try: - result = subprocess.run(["sfdisk", "-g", disk], capture_output=True, text=True, check=True) - output = result.stdout - sectors_per_cylinder = int(output.splitlines()[1].split()[1]) - total_sectors = int(output.splitlines()[1].split()[0]) * sectors_per_cylinder - 1 - except subprocess.CalledProcessError as e: - raise RuntimeError(f"Error al obtener el espacio libre: {e}") + disk = DiskLib.ogDiskToDev (cachepart[0]) + if not disk: + return None - # Obtener el último sector de la partición 3. - try: - result = subprocess.run(["sfdisk", "-uS", "-l", disk], capture_output=True, text=True, check=True) - output = result.stdout - end_sector_part3 = int([line.split()[2] for line in output.splitlines() if cachepart + "3" in line][0]) - except subprocess.CalledProcessError as e: - raise RuntimeError(f"Error al obtener el espacio libre: {e}") + sectors = 0 + disk_bn = os.path.basename (disk) + with open ('/proc/partitions', 'r') as fd: + proc_parts = fd.read() + for l in proc_parts.splitlines(): + items = l.split() + if len(items) < 4: continue + if items[3] == disk_bn: + sectors = 2 * int (items[2]) + if not sectors: return None - # Calcular el espacio libre en kilobytes. - if end_sector_part3 > total_sectors // 2: - free_space_kb = (total_sectors - end_sector_part3) // 2 + sfdisk_out = subprocess.run (['sfdisk', '-g', disk], capture_output=True, text=True).stdout + cyls = int (sfdisk_out.split()[1]) + sectors = sectors/cyls * cyls - 1 + + ## the original code has a hard dependency on the existence of a third partition + ## if the disk has sda1, sda2 and sda4, the code fails. + ## this is an improved version + endpart3 = 0 + for trypart in [3, 2, 1]: + sfdisk_out = subprocess.run (['sfdisk', '-uS', '-l', disk], capture_output=True, text=True).stdout + for l in sfdisk_out.splitlines(): + items = l.split() + if len(items) < 6: continue + if f'{disk}{trypart}' == items[0]: + endpart3 = int (items[2]) + break + if endpart3: break + if not endpart3: return None + +# Mostrar espacio libre en KB (1 KB = 2 sectores) + if endpart3 > sectors // 2: + return (sectors - endpart3) // 2 else: - free_space_kb = total_sectors // 4 - - return free_space_kb + return sectors // 4 #/** @@ -243,7 +248,12 @@ def ogGetCacheSpace(): #@warning Salidas de errores no determinada #*/ ## def ogMountCache(): - c = ogFindCache().split() + c = ogFindCache() + if not c: + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_PARTITION, ogGlobals.lang.MSG_NOCACHE) + return None + + c = c.split() m = FileSystemLib.ogMountFs (c[0], c[1]) if not m: SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_PARTITION, ogGlobals.lang.MSG_NOCACHE) diff --git a/client/shared/functions/ogGetCacheSpace b/client/shared/functions/ogGetCacheSpace new file mode 100755 index 0000000..2e5dce3 --- /dev/null +++ b/client/shared/functions/ogGetCacheSpace @@ -0,0 +1,13 @@ +#!/usr/bin/python3 + +import sys +import argparse +from SystemLib import ogHelp +from CacheLib import ogGetCacheSpace + +ret = ogGetCacheSpace() + +if ret is not None: + if ret == True: sys.exit (0) + elif ret == False: sys.exit (1) + else: print (ret) From 0b95027e5edcd7179c955d79f86c75c50f3cdb47 Mon Sep 17 00:00:00 2001 From: Natalia Serrano Date: Thu, 30 Jan 2025 17:32:28 +0100 Subject: [PATCH 130/167] refs #1414 add ogDeleteCache, fix a bug --- client/lib/engine/bin/CacheLib.py | 50 +++++++++++++------------- client/lib/engine/bin/FileSystemLib.py | 4 ++- client/shared/functions/ogDeleteCache | 13 +++++++ 3 files changed, 42 insertions(+), 25 deletions(-) create mode 100755 client/shared/functions/ogDeleteCache diff --git a/client/lib/engine/bin/CacheLib.py b/client/lib/engine/bin/CacheLib.py index d2303b1..19f7943 100755 --- a/client/lib/engine/bin/CacheLib.py +++ b/client/lib/engine/bin/CacheLib.py @@ -60,34 +60,36 @@ def ogCreateCache(ndisk=1, npart=4, partsize=None): #@return (nada, por determinar) #@exception OG_ERR_FORMAT formato incorrecto. #@note Requisitos: fdisk, sgdisk, partprobe -#@version 0.91 - Definición de caché local. -#@author Ramon Gomez, ETSII Universidad de Sevilla -#@date 2010/03/11 -#@version 1.0.4 - Soporte para discos GPT. -#@author Universidad de Huelva -#@date 2012/03/13 -#@version 1.0.6b - llamada correcta a ogUpdatePartitionTable -#@author Antonio Doblas Universidad de Málaga -#@date 2016/11/16 -#@version 1.1.0 - Sustituir "sfdisk" por "fdisk" para discos MSDOS. -#@author Ramon Gomez, ETSII Universidad de Sevilla -#@date 2016/05/25 #*/ ## def ogDeleteCache(): - """ - Borra la partición utilizada para caché. - - :raises RuntimeError: Si ocurre un error durante la eliminación de la partición de caché. - """ cachepart = ogFindCache() - if cachepart is None: - raise RuntimeError("No se encontró la partición de caché.") + if not cachepart: + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_PARTITION, ogGlobals.lang.MSG_NOCACHE) + return None - disk = f"/dev/sd{chr(96 + int(cachepart))}" - try: - subprocess.run(["parted", disk, "rm", cachepart], check=True) - except subprocess.CalledProcessError as e: - raise RuntimeError(f"Error al borrar la partición de caché: {e}") + ndisk, npart = cachepart.split() + disk = DiskLib.ogDiskToDev (ndisk) + +# Desmontar todos los sistemas de archivos del disco. + FileSystemLib.ogUnmountAll (ndisk) + + ptt = DiskLib.ogGetPartitionTableType (ndisk) + if 'GPT' == ptt: + # Si la tabla de particiones no es valida, volver a generarla. + if subprocess.run (['sgdisk', '-p', disk]).returncode: + subprocess.run (['gdisk', disk], input='2\nw\nY\n', text=True) + subprocess.run (['sgdisk', disk, f'-d{npart}']) + elif 'MSDOS' == ptt: + # Si la tabla de particiones no es valida, volver a generarla. + if subprocess.run (['parted', '-s', disk, 'print']).returncode: + subprocess.run (['fdisk', disk], input='w', text=True) + # Eliminar la partición de caché. + subprocess.run (['fdisk', disk], input=f'd\n{npart}\nw', text=True) +# Borrar etiqueta de la caché. + if os.path.exists ('/dev/disk/by-label/CACHE'): + os.unlink ('/dev/disk/by-label/CACHE') +#Actualiza la tabla de particiones en el kernel. + DiskLib.ogUpdatePartitionTable() #/** # ogFindCache diff --git a/client/lib/engine/bin/FileSystemLib.py b/client/lib/engine/bin/FileSystemLib.py index 9b01d35..bb4fc61 100755 --- a/client/lib/engine/bin/FileSystemLib.py +++ b/client/lib/engine/bin/FileSystemLib.py @@ -851,7 +851,9 @@ def ogUnmountFs(disk, par): #*/ ## def ogUnmountAll (disk): DISK = DiskLib.ogDiskToDev (disk) - for PART in range (1, DiskLib.ogGetPartitionsNumber (disk) + 1): + n = DiskLib.ogGetPartitionsNumber (disk) + if not n: return None + for PART in range (1, n+1): if 'CACHE' != ogGetFsType (disk, PART): ogUnmount (disk, PART) diff --git a/client/shared/functions/ogDeleteCache b/client/shared/functions/ogDeleteCache new file mode 100755 index 0000000..80914b8 --- /dev/null +++ b/client/shared/functions/ogDeleteCache @@ -0,0 +1,13 @@ +#!/usr/bin/python3 + +import sys +import argparse +from SystemLib import ogHelp +from CacheLib import ogDeleteCache + +ret = ogDeleteCache() + +if ret is not None: + if ret == True: sys.exit (0) + elif ret == False: sys.exit (1) + else: print (ret) From 56ba4194610333430e7b6187c070f79705d12623 Mon Sep 17 00:00:00 2001 From: Natalia Serrano Date: Fri, 31 Jan 2025 15:54:26 +0100 Subject: [PATCH 131/167] refs #1409 add ogCreateCache, fix bugs --- client/lib/engine/bin/CacheLib.py | 112 ++++++++++++++++++++------ client/lib/engine/bin/DiskLib.py | 6 +- client/shared/functions/ogCreateCache | 36 +++++++++ client/shared/scripts/createImage.py | 1 - 4 files changed, 126 insertions(+), 29 deletions(-) create mode 100755 client/shared/functions/ogCreateCache diff --git a/client/lib/engine/bin/CacheLib.py b/client/lib/engine/bin/CacheLib.py index 19f7943..0d1a43b 100755 --- a/client/lib/engine/bin/CacheLib.py +++ b/client/lib/engine/bin/CacheLib.py @@ -23,35 +23,97 @@ import CacheLib #@warning El tamaño de caché debe estar entre 50 MB y la mitad del disco. #@warning La caché no puede solaparse con las particiones de datos. #*/ ## -def ogCreateCache(ndisk=1, npart=4, partsize=None): - """ - Define la caché local, por defecto en partición 4 del disco 1. - - :param ndisk: número de disco donde crear la caché, por defecto es 1. - :param npart: número de partición (opcional, 4 por defecto). - :param partsize: tamaño de la partición en KB. - :raises ValueError: Si el formato de los parámetros es incorrecto. - :raises RuntimeError: Si ocurre un error durante la creación de la caché. - """ +def ogCreateCache (ndsk=1, part=4, sizecache=0): + if not sizecache: + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_FORMAT, '') + return None + sizecache = int (sizecache) - if partsize is None: - raise ValueError("El tamaño de la partición debe especificarse.") + DISK = DiskLib.ogDiskToDev (ndsk) + if not DISK: return None - # Verifica si las herramientas necesarias están instaladas - required_tools = ["sfdisk", "parted", "awk", "sed"] - for tool in required_tools: - if not shutil.which(tool): - raise RuntimeError(f"La herramienta {tool} no está instalada.") + # PATCH Para discos nvme la particion debe ser p1, p2, etc...en lugar de 1,2, sino falla sfdisk + NVME_PREFIX = '' + if 'nvme' in DISK: + NVME_PREFIX = 'p' - # Preparar los comandos para crear la caché - disk = f"/dev/sd{chr(96 + ndisk)}" - size_in_sectors = partsize * 2 # Asumiendo 512B por sector + END = DiskLib.ogGetLastSector (ndsk) + SIZE = 2 * sizecache +# Inicio partición cache según el disco tenga sectores de 4k o menores + IOSIZE = 0 + fdisk_out = subprocess.run (['fdisk', '-l', DISK], capture_output=True, text=True).stdout + for l in fdisk_out.splitlines(): + items = l.split() + if len(items) < 4: continue + if 'I/O' == items[0]: + IOSIZE = int (items[3]) + break + START = 0 + if 4096 == IOSIZE: + END -= 8192 + START = END - SIZE + 2048 - (END-SIZE)%2048 + else: + START = END - SIZE + 1 + + ENDPREVPART = None + i = 1 + while True: + prev_part = part - i + if prev_part <= 0: break + ENDPREVPART = DiskLib.ogGetLastSector (ndsk, prev_part) + if ENDPREVPART: break + i += 1 + if not ENDPREVPART: + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_FORMAT, ndsk) + return None +# Error si tamaño no está entre límites permitidos o si se solapa con la partición anterior. + MINSIZE = 25000 + MAXSIZE = END + if SIZE < MINSIZE or SIZE > MAXSIZE or START < ENDPREVPART: + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_FORMAT, ndsk) + return None + +# Desmontar todos los sistemas de archivos del disco. + FileSystemLib.ogUnmountAll (ndsk) +# Definir particiones y notificar al kernel. +# En el caso de ser disco GPT, de momento se borra la particion y se vuelve a crear, +# por lo que se pierden los datos. + pttype = DiskLib.ogGetPartitionTableType (ndsk) + if not pttype: + pttype = 'MSDOS' + DiskLib.ogCreatePartitionTable (ndsk, pttype) + + get_ptt = DiskLib.ogGetPartitionTableType (ndsk) + if 'GPT' == get_ptt: + # Si la tabla de particiones no es valida, volver a generarla. + if subprocess.run (['sgdisk', '-p', DISK]).returncode: + subprocess.run (['gdisk', DISK], input='2\nw\nY\n', text=True) + # Si existe la cache se borra previamente + if ogFindCache(): ogDeleteCache() + # Capturamos el codigo de particion GPT para cache + # PATCH - Cuando es GPT, la particion con codigo CACHE (CA00) no existe y no puede crearse, se cambia por LINUX (8300) + ID = DiskLib.ogTypeToId ('LINUX', 'GPT') + subprocess.run (['sgdisk', DISK, f'-n{part}:{START}:{END}', f'-c{part}:CACHE', f'-t{part}:{ID}']) + elif 'MSDOS' == get_ptt: + # Si la tabla de particiones no es valida, volver a generarla. + if subprocess.run (['parted', '-s', DISK, 'print']).returncode: + subprocess.run (['fdisk', DISK], input='w\n', text=True) + # Definir particiones y notificar al kernel. + ID = DiskLib.ogTypeToId ('CACHE', 'MSDOS') + # Salvamos la configuración de las particiones e incluimos la cache. + tmp = subprocess.run (['sfdisk', '--dump', DISK], capture_output=True, text=True).stdout.splitlines() + tmp = [ x for x in tmp if f'{DISK}{part}' not in x ] + tmp.append (f'{DISK}{NVME_PREFIX}{part} : start= {START}, size= {SIZE}, Id={ID}') + # Ordenamos las líneas de los dispositivos + UNIT = [ x for x in tmp if 'unit' in x ][0] + tmp = sorted ([ x for x in tmp if re.match ('^/dev', x) ]) + tmp = [UNIT, ''] + tmp + # Guardamos nueva configuración en el disco. + i = '\n'.join(tmp) + subprocess.run (['sfdisk', '--no-reread', DISK], input=i, text=True) +# Actualiza la tabla de particiones en el kernel. + DiskLib.ogUpdatePartitionTable() - try: - # Lógica simplificada para crear la caché en la partición - subprocess.run(["parted", disk, "mkpart", "primary", str(npart), str(partsize)], check=True) - except subprocess.CalledProcessError as e: - raise RuntimeError(f"Error al crear la caché: {e}") #/** diff --git a/client/lib/engine/bin/DiskLib.py b/client/lib/engine/bin/DiskLib.py index e1c3f6b..51f54b9 100755 --- a/client/lib/engine/bin/DiskLib.py +++ b/client/lib/engine/bin/DiskLib.py @@ -711,8 +711,8 @@ def ogGetLastSector (disk, par=None): for l in sgdisk_out.splitlines(): items = l.split() if len(items) < 3: continue - if par != items[0]: continue - last = items[2] + if str (par) != items[0]: continue + last = int (items[2]) break else: @@ -720,7 +720,7 @@ def ogGetLastSector (disk, par=None): for l in sgdisk_out.splitlines(): if 'last usable sector' not in l: continue items = l.split() - last = items[-1] + last = int (items[-1]) return last diff --git a/client/shared/functions/ogCreateCache b/client/shared/functions/ogCreateCache new file mode 100755 index 0000000..62a97e5 --- /dev/null +++ b/client/shared/functions/ogCreateCache @@ -0,0 +1,36 @@ +#!/usr/bin/python3 + +import sys +import argparse +from SystemLib import ogHelp +from CacheLib import ogCreateCache + +if 2 == len (sys.argv) and 'help' == sys.argv[1]: + #parser.print_help() sale en inglés aunque la locale indique otra cosa + ogHelp ('ogCreateCache', 'ogCreateCache [int_ndisk [int_npart]] int_partsize', ['ogCreateCache 10000000', 'ogCreateCache 1 10000000', 'ogCreateCache 1 4 10000000']) + sys.exit (0) + +parser = argparse.ArgumentParser (add_help=False) +if 2 == len (sys.argv): + parser.add_argument ('sizecache') +elif 3 == len (sys.argv): + parser.add_argument ('disk') + parser.add_argument ('sizecache') +elif 4 == len (sys.argv): + parser.add_argument ('disk') + parser.add_argument ('part') + parser.add_argument ('sizecache') + +args = parser.parse_args() + +if 2 == len (sys.argv): + ret = ogCreateCache (sizecache=args.sizecache) +elif 3 == len (sys.argv): + ret = ogCreateCache (ndsk=args.disk, sizecache=args.sizecache) +elif 4 == len (sys.argv): + ret = ogCreateCache (ndsk=int(args.disk), part=int(args.part), sizecache=int(args.sizecache)) + +if ret is not None: + if ret == True: sys.exit (0) + elif ret == False: sys.exit (1) + else: print (ret) diff --git a/client/shared/scripts/createImage.py b/client/shared/scripts/createImage.py index fb625d9..716c2b3 100755 --- a/client/shared/scripts/createImage.py +++ b/client/shared/scripts/createImage.py @@ -3,7 +3,6 @@ import os import sys import time -import tempfile import subprocess import ogGlobals From c8e76614ae140a0cde301cb01516bdd22eac1689 Mon Sep 17 00:00:00 2001 From: Natalia Serrano Date: Fri, 31 Jan 2025 17:36:14 +0100 Subject: [PATCH 132/167] refs #1429 add ogGetSerialNumber --- client/lib/engine/bin/InventoryLib.py | 12 ++---------- client/shared/functions/ogGetSerialNumber | 17 +++++++++++++++++ 2 files changed, 19 insertions(+), 10 deletions(-) create mode 100755 client/shared/functions/ogGetSerialNumber diff --git a/client/lib/engine/bin/InventoryLib.py b/client/lib/engine/bin/InventoryLib.py index 4ff5d40..a708b3d 100755 --- a/client/lib/engine/bin/InventoryLib.py +++ b/client/lib/engine/bin/InventoryLib.py @@ -102,20 +102,12 @@ def ogGetOsUuid(): #@brief Obtiene el nº de serie del cliente. #*/ ## def ogGetSerialNumber(): - # Si se solicita, mostrar ayuda. - if len(sys.argv) > 1 and sys.argv[1] == "help": - SystemLib.ogHelp(sys.argv[0], sys.argv[0], sys.argv[0] + " => 123456") - return - - # Obtener nº de serie (ignorar los no especificados). SERIALNO = subprocess.check_output(["dmidecode", "-s", "system-serial-number"]).decode().strip() SERIALNO = re.sub(r"(not specified|to be filled|invalid entry|default string)", "", SERIALNO, flags=re.IGNORECASE) SERIALNO = SERIALNO.replace(" ", "") SERIALNO = SERIALNO[:25] if len(SERIALNO) > 25 else SERIALNO - if SERIALNO: - print(SERIALNO) - - return 0 + if SERIALNO: return SERIALNO + return None #/** diff --git a/client/shared/functions/ogGetSerialNumber b/client/shared/functions/ogGetSerialNumber new file mode 100755 index 0000000..dc02c8e --- /dev/null +++ b/client/shared/functions/ogGetSerialNumber @@ -0,0 +1,17 @@ +#!/usr/bin/python3 + +import sys +from SystemLib import ogHelp +from InventoryLib import ogGetSerialNumber + +if 2 == len (sys.argv) and 'help' == sys.argv[1]: + #parser.print_help() sale en inglés aunque la locale indique otra cosa + ogHelp ('ogGetSerialNumber', 'ogGetSerialNumber', ['ogGetSerialNumber']) + sys.exit (0) + +ret = ogGetSerialNumber() + +if ret is not None: + if ret == True: sys.exit (0) + elif ret == False: sys.exit (1) + else: print (ret) From 2744273b82f4389b84058ea52f4d974522079a06 Mon Sep 17 00:00:00 2001 From: Natalia Serrano Date: Mon, 3 Feb 2025 12:48:30 +0100 Subject: [PATCH 133/167] refs #1427 add ogGetOsUuid, fix bugs --- client/lib/engine/bin/DiskLib.py | 5 ++-- client/lib/engine/bin/InventoryLib.py | 40 +++++++++------------------ client/shared/functions/ogGetOsUuid | 23 +++++++++++++++ client/shared/scripts/configureOs.py | 4 +++ 4 files changed, 43 insertions(+), 29 deletions(-) create mode 100755 client/shared/functions/ogGetOsUuid diff --git a/client/lib/engine/bin/DiskLib.py b/client/lib/engine/bin/DiskLib.py index 51f54b9..114afd6 100755 --- a/client/lib/engine/bin/DiskLib.py +++ b/client/lib/engine/bin/DiskLib.py @@ -836,7 +836,8 @@ def ogGetPartitionsNumber (disk): if pttype in ['GPT', 'MSDOS']: partx_out = subprocess.run (['partx', '-gso', 'NR', DISK], capture_output=True, text=True).stdout lines = partx_out.splitlines() - out = lines[-1].strip() + if len(lines): + out = lines[-1].strip() elif 'LVM' == pttype: lvs_out = subprocess.run (['lvs', '--noheadings', DISK], capture_output=True, text=True).stdout lines = lvs_out.splitlines() @@ -1255,7 +1256,7 @@ def ogLockDisk(*args): #*/ ## def ogSetPartitionActive (disk, par): if InventoryLib.ogIsEfiActive(): - SystemLib.ogEcho (['session', 'log'], 'warning', f'EFI: {ogGlobals.lang.MSG_DONTUSE} {ogSetPartitionActive}') + SystemLib.ogEcho (['session', 'log'], 'warning', f'EFI: {ogGlobals.lang.MSG_DONTUSE} ogSetPartitionActive') return DISK = ogDiskToDev (disk) diff --git a/client/lib/engine/bin/InventoryLib.py b/client/lib/engine/bin/InventoryLib.py index a708b3d..7101b5f 100755 --- a/client/lib/engine/bin/InventoryLib.py +++ b/client/lib/engine/bin/InventoryLib.py @@ -65,36 +65,22 @@ def ogGetOsType(disk, partition): #@exception OG_ERR_FORMAT Formato incorrecto. #@exception OG_ERR_NOTFOUND Disco o partición no corresponden con un dispositiv #*/ ## -def ogGetOsUuid(): - # Si se solicita, mostrar ayuda. - if len(sys.argv) > 1 and sys.argv[1] == "help": - SystemLib.ogHelp(sys.argv[0], sys.argv[0] + " int_ndisk int_nfilesys", sys.argv[0] + " 1 2 => 540e47c6-8e78-4178-aa46-042e4803fb16") - return +def ogGetOsUuid (disk, par): + mntdir = FileSystemLib.ogMount (disk, par) + if not mntdir: return None - # Error si no se reciben 2 parametros. - if len(sys.argv) != 3: - SystemLib.ogRaiseError( - "session", - ogGlobals.OG_ERR_FORMAT, - f"Error: {sys.argv[0]} need 2 arguments.", - ) - return - - # Montar la particion, si no lo estaba previamente. - MNTDIR = FileSystemLib.ogMount(sys.argv[1], sys.argv[2]) - if not MNTDIR: - return - - # Obtener UUID según el tipo de sistema operativo. - os_type = ogGetOsType(sys.argv[1], sys.argv[2]) - if os_type == "Linux": +# Obtener UUID según el tipo de sistema operativo. + os_type = ogGetOsType (disk, par) + if 'Linux' == os_type: # Leer el UUID del sistema de ficheros raíz o el fichero de identificador. - uuid = subprocess.check_output(["findmnt", "-no", "UUID", MNTDIR], stderr=subprocess.DEVNULL).decode().strip() or open(os.path.join(MNTDIR, "etc", "machine-id")).read().strip() - print(uuid) - elif os_type == "Windows": + uuid = subprocess.run (['findmnt', '-no', 'UUID', mntdir], capture_output=True, text=True).stdout.strip() + if not uuid: + uuid = open (os.path.join (mntdir, 'etc', 'machine-id')).read().strip() + return uuid + elif 'Windows' == os_type: # Leer identificador en clave de registro. - uuid = RegistryLib.ogGetRegistryValue(MNTDIR, "SOFTWARE", "\\Microsoft\\Cryptography\\MachineGuid") - print(uuid) + uuid = RegistryLib.ogGetRegistryValue (mntdir, 'SOFTWARE', r'\Microsoft\Cryptography\MachineGuid') + return uuid #/** diff --git a/client/shared/functions/ogGetOsUuid b/client/shared/functions/ogGetOsUuid new file mode 100755 index 0000000..306d96c --- /dev/null +++ b/client/shared/functions/ogGetOsUuid @@ -0,0 +1,23 @@ +#!/usr/bin/python3 + +import sys +import argparse +from SystemLib import ogHelp +from InventoryLib import ogGetOsUuid + +parser = argparse.ArgumentParser (add_help=False) +parser.add_argument ('disk') +parser.add_argument ('par') + +if 2 == len (sys.argv) and 'help' == sys.argv[1]: + #parser.print_help() sale en inglés aunque la locale indique otra cosa + ogHelp ('ogGetOsUuid', 'ogGetOsUuid int_ndisk int_nfilesys', ['ogGetOsUuid 1 2']) + sys.exit (0) + +args = parser.parse_args() +ret = ogGetOsUuid (args.disk, args.par) + +if ret is not None: + if ret == True: sys.exit (0) + elif ret == False: sys.exit (1) + else: print (ret) diff --git a/client/shared/scripts/configureOs.py b/client/shared/scripts/configureOs.py index 13248df..bd61865 100755 --- a/client/shared/scripts/configureOs.py +++ b/client/shared/scripts/configureOs.py @@ -16,6 +16,7 @@ import os.path import subprocess import ogGlobals +import SystemLib import DiskLib import FileSystemLib import NetLib @@ -61,6 +62,9 @@ if 'Windows' == ostype: if InventoryLib.ogIsEfiActive(): # Si es UEFI copio el cargador de arranque a la partición EFI e instalo Grub. UEFILib.ogRestoreEfiBootLoader (disk, par) esp = DiskLib.ogGetEsp() + if not esp: + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTFOUND, 'ESP') + sys.exit (1) efidisk, efipart = esp.split() BootLib.ogGrubInstallMbr (efidisk, efipart, 'TRUE') else: From c6735b15ee5182e1bf44bd0e19f29723cf0de00a Mon Sep 17 00:00:00 2001 From: Natalia Serrano Date: Mon, 3 Feb 2025 13:14:37 +0100 Subject: [PATCH 134/167] refs #1428 add ogListHardwareInfo --- client/lib/engine/bin/InventoryLib.py | 104 ++++++++++++--------- client/shared/functions/ogListHardwareInfo | 17 ++++ 2 files changed, 75 insertions(+), 46 deletions(-) create mode 100755 client/shared/functions/ogListHardwareInfo diff --git a/client/lib/engine/bin/InventoryLib.py b/client/lib/engine/bin/InventoryLib.py index 7101b5f..2269af3 100755 --- a/client/lib/engine/bin/InventoryLib.py +++ b/client/lib/engine/bin/InventoryLib.py @@ -103,41 +103,6 @@ def ogGetSerialNumber(): def ogIsEfiActive(): return os.path.isdir("/sys/firmware/efi") -def parse_lshw_output(): - try: - # Ejecutar lshw en formato JSON para un fácil procesamiento - lshw_output = subprocess.check_output(["lshw", "-json"], text=True) - lshw_data = json.loads(lshw_output) # Convertir la salida JSON a un diccionario - - # Extraer información relevante en el formato clave=valor - parsed_output = [] - - # Ejemplo de datos clave que podríamos extraer - if "product" in lshw_data: - parsed_output.append(f"product={lshw_data['product']}") - - if "vendor" in lshw_data: - parsed_output.append(f"vendor={lshw_data['vendor']}") - - if "configuration" in lshw_data and "memory" in lshw_data["configuration"]: - parsed_output.append(f"memory={lshw_data['configuration']['memory']}") - - # Recorrer los dispositivos para obtener información de CPU, almacenamiento, etc. - for item in lshw_data.get("children", []): - if item["class"] == "processor": - parsed_output.append(f"cpu={item.get('product', 'Unknown')}") - elif item["class"] == "memory" and "size" in item: - parsed_output.append(f"total_memory={item['size']}") - elif item["class"] == "disk": - parsed_output.append(f"disk={item.get('product', 'Unknown')}") - - # Devolver los datos combinados - return "\n".join(parsed_output) - - except subprocess.CalledProcessError as e: - print(f"Error al ejecutar lshw: {e}") - return "Error al obtener información de hardware" - #/** # ogListHardwareInfo @@ -148,21 +113,68 @@ def parse_lshw_output(): #@note Requisitos: dmidecode, lshw, awk #*/ ## def ogListHardwareInfo(): + ret = '' + + SystemLib.ogEcho ([], 'info', ogGlobals.lang.MSG_HARDWAREINVENTORY) # Ejecutar dmidecode y obtener tipo de chasis - try: - output = subprocess.check_output('echo "cha=$(dmidecode -s chassis-type)" | grep -v "Other"', shell=True).decode().strip() - except subprocess.CalledProcessError: - output = "cha=Unknown" + dmi_out = subprocess.run (['dmidecode', '-s', 'chassis-type'], capture_output=True, text=True).stdout + dmi_out = '\n'.join ([ x for x in dmi_out.splitlines() if 'Other' not in x ]) + ret += f'cha={dmi_out}\n' - # Detectar BIOS o UEFI - firmware = "boo=UEFI" if os.path.isdir("/sys/firmware/efi") else "boo=BIOS" - print(firmware) + if os.path.exists ('/sys/firmware/efi'): + ret += f'boo=UEFI\n' + else: + ret += f'boo=BIOS\n' - # Ejecutar y analizar lshw - lshw_output = parse_lshw_output() + awk_script = r''' + BEGIN {type="mod";} + /product:/ {sub(/ *product: */,""); prod=$0;} + /vendor:/ {sub(/ *vendor: */,""); vend=$0;} + /version:/ {sub(/ *version: */,"v.");vers=$0;} + /size:/ {size=$2;} + /clock:/ {clock=$2;} + /slot:/ {sub(/ *slot: */,""); slot=$0;} + /\*-/ {if (type=="mem"){ + if (size!=""){ + numbank++; + print type"="vend,prod,size,clock" ("slot")";} + }else{ + if (type=="totalmem"){ + if (size!=""){ + totalmemory="mem="size;} + }else{ + if (type!="" && prod!=""){ + if (prod=="v."vers) + vers=""; + print type"="vend,prod,size,vers;} } + } + type=prod=vend=vers=size=clock=slot="";} + $1~/-core/ {type="boa";} + $1~/-firmware/ {type="bio";} + $1~/-cpu/ {type="cpu";} + $1~/-bank/ {type="mem";} + $1~/-memory/ {type="totalmem";} + $1~/-ide/ {type="ide";} + $1~/-storage/ {type="sto";} + $1~/-disk/ {type="dis";} + $1~/-cdrom/ {type="cdr";} + $1~/-display/ {type="vga";} + $1~/-network/ {type="net";} + $1~/-multimedia/ {type="mul";} + $1~/-usb/ {type="usb";} + $1~/-firewire/ {type="fir";} + $1~/-serial/ {type="bus";} + END {if (type!="" && prod!="") + print type"="vend,prod,size,vers; + if (length(numbank)==0 && length(totalmemory)>=4) + print totalmemory; } + ''' + lshw_out = subprocess.run (['lshw'], capture_output=True, text=True).stdout + awk_out = subprocess.run (['awk', awk_script], input=lshw_out, capture_output=True, text=True).stdout - # Combina y devuelve los resultados - return f"{output}\n{firmware}\n{lshw_output}" + ret += awk_out + + return ret #/** diff --git a/client/shared/functions/ogListHardwareInfo b/client/shared/functions/ogListHardwareInfo new file mode 100755 index 0000000..2eaa493 --- /dev/null +++ b/client/shared/functions/ogListHardwareInfo @@ -0,0 +1,17 @@ +#!/usr/bin/python3 + +import sys +from SystemLib import ogHelp +from InventoryLib import ogListHardwareInfo + +if 2 == len (sys.argv) and 'help' == sys.argv[1]: + #parser.print_help() sale en inglés aunque la locale indique otra cosa + ogHelp ('ogListHardwareInfo', 'ogListHardwareInfo', ['ogListHardwareInfo']) + sys.exit (0) + +ret = ogListHardwareInfo() + +if ret is not None: + if ret == True: sys.exit (0) + elif ret == False: sys.exit (1) + else: print (ret) From 04d0b2208bd6a232694b8af3df4466f4b294b40f Mon Sep 17 00:00:00 2001 From: Natalia Serrano Date: Mon, 3 Feb 2025 13:53:30 +0100 Subject: [PATCH 135/167] refs #1431 #1430 add ogIsRepoLocked, remove the unused ogCheckProgram --- client/lib/engine/bin/SystemLib.py | 58 +++++++++++--------------- client/shared/functions/ogIsRepoLocked | 17 ++++++++ 2 files changed, 41 insertions(+), 34 deletions(-) create mode 100755 client/shared/functions/ogIsRepoLocked diff --git a/client/lib/engine/bin/SystemLib.py b/client/lib/engine/bin/SystemLib.py index 9524949..338a5e3 100755 --- a/client/lib/engine/bin/SystemLib.py +++ b/client/lib/engine/bin/SystemLib.py @@ -5,6 +5,7 @@ import sys import os import shutil import inspect +import glob ## for ogExecAndLog from io import StringIO @@ -258,43 +259,32 @@ def ogRaiseError (logtypes, code, msg): #@return Código de salida: 0 - bloqueado, 1 - sin bloquear o error. #*/ def ogIsRepoLocked(): - # Variables locales - FILES = "" - FUNCNAME = ogIsRepoLocked.__name__ - - # Si se solicita, mostrar ayuda. - if len(sys.argv) > 1 and sys.argv[1] == "help": - ogHelp(f"{FUNCNAME}", f"{FUNCNAME}", f"if {FUNCNAME}(): ...") - - # No hacer nada, si no está definido el punto de montaje del repositorio. +# No hacer nada, si no está definido el punto de montaje del repositorio. if not ogGlobals.OGIMG: - return 1 + return False - # Comprobar si alguno de los ficheros abiertos por los procesos activos está en el - # punto de montaje del repositorio de imágenes. - FILES = subprocess.check_output(["find", "/proc", "-maxdepth", "2", "-type", "f", "-lname", f"{ogGlobals.OGIMG}/*"]).decode("utf-8") - return bool(FILES) +# Comprobar si alguno de los ficheros abiertos por los procesos activos está en el +# punto de montaje del repositorio de imágenes. + proc_entries = glob.glob ('/proc/[0-9]*/fd/*') + for e in proc_entries: + p = os.path.realpath (e) + if ogGlobals.OGIMG in p: + return True + return False -def ogCheckProgram(program): - FUNCNAME = ogCheckProgram.__name__ - - if not program or not isinstance(program, str): - SystemLib.ogRaiseError( - "session", - ogGlobals.OG_ERR_FORMAT, - f"Error: {ogGlobals.lang.MSG_ERR_FORMAT} {FUNCNAME} \"program\"" - ) - return - - if not shutil.which(program): - SystemLib.ogRaiseError( - "session", - ogGlobals.OG_ERR_NOTEXEC, - f"Error: The program '{program}' is not available on the system." - ) - return - - return 0 +## has no users +#def ogCheckProgram(program): +# FUNCNAME = ogCheckProgram.__name__ +# +# if not program or not isinstance(program, str): +# SystemLib.ogRaiseError ("session", ogGlobals.OG_ERR_FORMAT, f"Error: {ogGlobals.lang.MSG_ERR_FORMAT} {FUNCNAME} \"program\"") +# return +# +# if not shutil.which(program): +# SystemLib.ogRaiseError ( "session", ogGlobals.OG_ERR_NOTEXEC, f"Error: The program '{program}' is not available on the system.") +# return +# +# return 0 def ogIsVirtualMachine(): output = subprocess.run (["dmidecode", "-s", "system-product-name"], capture_output=True, text=True).stdout diff --git a/client/shared/functions/ogIsRepoLocked b/client/shared/functions/ogIsRepoLocked new file mode 100755 index 0000000..aad48d2 --- /dev/null +++ b/client/shared/functions/ogIsRepoLocked @@ -0,0 +1,17 @@ +#!/usr/bin/python3 + +import sys +from SystemLib import ogHelp +from SystemLib import ogIsRepoLocked + +if 2 == len (sys.argv) and 'help' == sys.argv[1]: + #parser.print_help() sale en inglés aunque la locale indique otra cosa + ogHelp ('ogIsRepoLocked', 'ogIsRepoLocked', ['ogIsRepoLocked']) + sys.exit (0) + +ret = ogIsRepoLocked() + +if ret is not None: + if ret == True: sys.exit (0) + elif ret == False: sys.exit (1) + else: print (ret) From 3a886c857909117964590b97493d0b36010eeefd Mon Sep 17 00:00:00 2001 From: Natalia Serrano Date: Tue, 11 Feb 2025 13:50:53 +0100 Subject: [PATCH 136/167] refs #1487 add ogUnsetDirtyBit --- client/lib/engine/bin/FileSystemLib.py | 29 ++++++------------------- client/shared/functions/ogUnsetDirtyBit | 23 ++++++++++++++++++++ 2 files changed, 30 insertions(+), 22 deletions(-) create mode 100755 client/shared/functions/ogUnsetDirtyBit diff --git a/client/lib/engine/bin/FileSystemLib.py b/client/lib/engine/bin/FileSystemLib.py index bb4fc61..42c422e 100755 --- a/client/lib/engine/bin/FileSystemLib.py +++ b/client/lib/engine/bin/FileSystemLib.py @@ -866,29 +866,14 @@ def ogUnmountAll (disk): #@return Nada #@exception OG_ERR_FORMAT Formato incorrecto. #*/ ## -def ogUnsetDirtyBit(int_ndisk, int_nfilesys): +def ogUnsetDirtyBit (disk, par): + PART = DiskLib.ogDiskToDev (disk, par) + if not PART: return None - # Error si no se reciben 2 parámetros. - if len(sys.argv) != 3: - SystemLib.ogRaiseError ( - [], - ogGlobals.OG_ERR_FORMAT, - "Not enough arguments" - ) - return - - # Obtener partición y punto de montaje. - PART = DiskLib.ogDiskToDev(int_ndisk, int_nfilesys) - if not PART: - return - - # Realizar acciones específicas según el tipo de sistema de archivos. - TYPE = ogGetFsType(int_ndisk, int_nfilesys) - if TYPE == "NTFS": - ogUnmount(int_ndisk, int_nfilesys) - subprocess.run(["ntfsfix", "-d", PART], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) - else: - pass # Add more specific actions for other file systems if needed. + TYPE = ogGetFsType (disk, par) + if 'NTFS' == TYPE: + ogUnmount (disk, par) + subprocess.run (['ntfsfix', '--clear-dirty', PART]) #/** diff --git a/client/shared/functions/ogUnsetDirtyBit b/client/shared/functions/ogUnsetDirtyBit new file mode 100755 index 0000000..c7314f2 --- /dev/null +++ b/client/shared/functions/ogUnsetDirtyBit @@ -0,0 +1,23 @@ +#!/usr/bin/python3 + +import sys +import argparse +from SystemLib import ogHelp +from FileSystemLib import ogUnsetDirtyBit + +parser = argparse.ArgumentParser (add_help=False) +parser.add_argument ('disk') +parser.add_argument ('par') + +if 2 == len (sys.argv) and 'help' == sys.argv[1]: + #parser.print_help() sale en inglés aunque la locale indique otra cosa + ogHelp ('ogUnsetDirtyBit', 'ogUnsetDirtyBit int_ndisk int_nfilesys', ['ogUnsetDirtyBit 1 1']) + sys.exit (0) + +args = parser.parse_args() +ret = ogUnsetDirtyBit (args.disk, args.par) + +if ret is not None: + if ret == True: sys.exit (0) + elif ret == False: sys.exit (1) + else: print (ret) From cdb0128cd801bd7e902d347aa6356f894caec4b0 Mon Sep 17 00:00:00 2001 From: Natalia Serrano Date: Tue, 11 Feb 2025 13:55:09 +0100 Subject: [PATCH 137/167] refs #1488 add ogMountFirstFs --- client/lib/engine/bin/FileSystemLib.py | 15 +++++---------- client/shared/functions/ogMountFirstFs | 22 ++++++++++++++++++++++ 2 files changed, 27 insertions(+), 10 deletions(-) create mode 100755 client/shared/functions/ogMountFirstFs diff --git a/client/lib/engine/bin/FileSystemLib.py b/client/lib/engine/bin/FileSystemLib.py index 42c422e..15139f3 100755 --- a/client/lib/engine/bin/FileSystemLib.py +++ b/client/lib/engine/bin/FileSystemLib.py @@ -543,18 +543,13 @@ def ogMount(*args): #@param int_ndisk nº de orden del disco #@return Punto de montaje del primer sistema de archivos detectado #*/ ## -def ogMountFirstFs(int_ndisk): - # Obtener número de particiones del disco. - NPARTS = DiskLib.ogGetPartitionsNumber(int_ndisk) - for PART in range(1, NPARTS + 1): - MNTDIR = ogMount(int_ndisk, PART) +def ogMountFirstFs (disk): + NPARTS = DiskLib.ogGetPartitionsNumber (disk) + for PART in range (1, NPARTS + 1): + MNTDIR = ogMount (disk, PART) if MNTDIR: return MNTDIR - SystemLib.ogRaiseError( - "session", - ogGlobals.OG_ERR_NOTFOUND, - f"{int_ndisk}" - ) + SystemLib.ogRaiseError ('session', ogGlobals.OG_ERR_NOTFOUND, f'{disk}') return ogGlobals.OG_ERR_NOTFOUND #/** diff --git a/client/shared/functions/ogMountFirstFs b/client/shared/functions/ogMountFirstFs new file mode 100755 index 0000000..61f324d --- /dev/null +++ b/client/shared/functions/ogMountFirstFs @@ -0,0 +1,22 @@ +#!/usr/bin/python3 + +import sys +import argparse +from SystemLib import ogHelp +from FileSystemLib import ogMountFirstFs + +parser = argparse.ArgumentParser (add_help=False) +parser.add_argument ('disk') + +if 2 == len (sys.argv) and 'help' == sys.argv[1]: + #parser.print_help() sale en inglés aunque la locale indique otra cosa + ogHelp ('ogMountFirstFs', 'ogMountFirstFs int_ndisk', ['ogMountFirstFs 1']) + sys.exit (0) + +args = parser.parse_args() +ret = ogMountFirstFs (args.disk) + +if ret is not None: + if ret == True: sys.exit (0) + elif ret == False: sys.exit (1) + else: print (ret) From 375a3a8ad0f699761af3f72ab984fe33e5561355 Mon Sep 17 00:00:00 2001 From: Natalia Serrano Date: Wed, 12 Feb 2025 11:20:03 +0100 Subject: [PATCH 138/167] refs #1495 add ogIsDiskLocked --- client/lib/engine/bin/DiskLib.py | 24 ++++-------------------- client/shared/functions/ogIsDiskLocked | 22 ++++++++++++++++++++++ 2 files changed, 26 insertions(+), 20 deletions(-) create mode 100755 client/shared/functions/ogIsDiskLocked diff --git a/client/lib/engine/bin/DiskLib.py b/client/lib/engine/bin/DiskLib.py index 114afd6..cb2657a 100755 --- a/client/lib/engine/bin/DiskLib.py +++ b/client/lib/engine/bin/DiskLib.py @@ -1090,26 +1090,10 @@ def ogIdToType(ID): #@return Código de salida: 0 - bloqueado, 1 - sin bloquear o error. #@note Los ficheros de bloqueo se localizan en \c /var/lock/dev, siendo \c dev el dispositivo de la partición o de su disco, sustituyendo el carácter "/" por "-". #*/ ## -def ogIsDiskLocked(*args): - # Variables locales - DISK = None - LOCKFILE = None - - # Si se solicita, mostrar ayuda. - if len(args) == 1 and args[0] == "help": - SystemLib.ogHelp('ogIsDiskLocked', 'ogIsDiskLocked int_ndisk', 'if ogIsDiskLocked(1): ...') - return - - # Falso, en caso de error. - if len(args) != 1: - return False - DISK = ogDiskToDev(args[0], 2) - if DISK is None: - return False - - # Comprobar existencia de fichero de bloqueo para el disco. - LOCKFILE = f"/var/lock/lock{DISK.replace('/', '-')}" - return os.path.isfile(LOCKFILE) +def ogIsDiskLocked (disk): + DISK = ogDiskToDev (disk) + if not DISK: return False + return os.path.isfile (f'/var/lock/lock{DISK.replace('/', '-')}') #/** diff --git a/client/shared/functions/ogIsDiskLocked b/client/shared/functions/ogIsDiskLocked new file mode 100755 index 0000000..25ebde8 --- /dev/null +++ b/client/shared/functions/ogIsDiskLocked @@ -0,0 +1,22 @@ +#!/usr/bin/python3 + +import sys +import argparse +from SystemLib import ogHelp +from DiskLib import ogIsDiskLocked + +parser = argparse.ArgumentParser (add_help=False) +parser.add_argument ('disk') + +if 2 == len (sys.argv) and 'help' == sys.argv[1]: + #parser.print_help() sale en inglés aunque la locale indique otra cosa + ogHelp ('ogIsDiskLocked', 'ogIsDiskLocked int_ndisk', ['ogIsDiskLocked 1']) + sys.exit (0) + +args = parser.parse_args() +ret = ogIsDiskLocked (args.disk) + +if ret is not None: + if ret == True: sys.exit (0) + elif ret == False: sys.exit (1) + else: print (ret) From 8b11b4e08d09a3986b594c65e19c2ff577a553d5 Mon Sep 17 00:00:00 2001 From: Natalia Serrano Date: Wed, 12 Feb 2025 11:24:23 +0100 Subject: [PATCH 139/167] refs #1499 add ogLockDisk --- client/lib/engine/bin/DiskLib.py | 29 +++++------------------------ client/shared/functions/ogLockDisk | 22 ++++++++++++++++++++++ 2 files changed, 27 insertions(+), 24 deletions(-) create mode 100755 client/shared/functions/ogLockDisk diff --git a/client/lib/engine/bin/DiskLib.py b/client/lib/engine/bin/DiskLib.py index cb2657a..fea7c8d 100755 --- a/client/lib/engine/bin/DiskLib.py +++ b/client/lib/engine/bin/DiskLib.py @@ -1093,7 +1093,7 @@ def ogIdToType(ID): def ogIsDiskLocked (disk): DISK = ogDiskToDev (disk) if not DISK: return False - return os.path.isfile (f'/var/lock/lock{DISK.replace('/', '-')}') + return os.path.isfile (f'/var/lock/lock{DISK.replace("/", "-")}') #/** @@ -1203,29 +1203,10 @@ def ogListLogicalPartitions(*args): #@exception OG_ERR_NOTFOUND Disco o particion no corresponden con un dispositivo. #@note El fichero de bloqueo se localiza en \c /var/lock/disk, siendo \c disk el dispositivo del disco, sustituyendo el carácter "/" por "-". #*/ ## -def ogLockDisk(*args): - # Variables locales - DISK = None - LOCKFILE = None - - # Si se solicita, mostrar ayuda. - if len(args) == 1 and args[0] == "help": - SystemLib.ogHelp('ogLockDisk', 'ogLockDisk int_ndisk', 'ogLockDisk 1') - return - - # Error si no se recibe 1 parámetro. - if len(args) != 1: - SystemLib.ogRaiseError(OG_ERR_FORMAT) - return - - # Obtener partición. - DISK = ogDiskToDev(args[0]) - if DISK is None: - return - - # Crear archivo de bloqueo exclusivo. - LOCKFILE = f"/var/lock/lock{DISK.replace('/', '-')}" - open(LOCKFILE, 'a').close() +def ogLockDisk (disk): + DISK = ogDiskToDev (disk) + if not DISK: return None + open (f'/var/lock/lock{DISK.replace("/", "-")}', 'a').close() #/** diff --git a/client/shared/functions/ogLockDisk b/client/shared/functions/ogLockDisk new file mode 100755 index 0000000..1b1e640 --- /dev/null +++ b/client/shared/functions/ogLockDisk @@ -0,0 +1,22 @@ +#!/usr/bin/python3 + +import sys +import argparse +from SystemLib import ogHelp +from DiskLib import ogLockDisk + +parser = argparse.ArgumentParser (add_help=False) +parser.add_argument ('disk') + +if 2 == len (sys.argv) and 'help' == sys.argv[1]: + #parser.print_help() sale en inglés aunque la locale indique otra cosa + ogHelp ('ogLockDisk', 'ogLockDisk int_ndisk', ['ogLockDisk 1']) + sys.exit (0) + +args = parser.parse_args() +ret = ogLockDisk (args.disk) + +if ret is not None: + if ret == True: sys.exit (0) + elif ret == False: sys.exit (1) + else: print (ret) From e12cc1150ffc200ee096bc8ee655e58216774d25 Mon Sep 17 00:00:00 2001 From: Natalia Serrano Date: Wed, 12 Feb 2025 11:27:01 +0100 Subject: [PATCH 140/167] refs #1500 add ogUnlockDisk --- client/lib/engine/bin/DiskLib.py | 28 ++++------------------------ client/shared/functions/ogUnlockDisk | 22 ++++++++++++++++++++++ 2 files changed, 26 insertions(+), 24 deletions(-) create mode 100755 client/shared/functions/ogUnlockDisk diff --git a/client/lib/engine/bin/DiskLib.py b/client/lib/engine/bin/DiskLib.py index fea7c8d..73f3bc0 100755 --- a/client/lib/engine/bin/DiskLib.py +++ b/client/lib/engine/bin/DiskLib.py @@ -1552,30 +1552,10 @@ def ogUnhidePartition(*args): #@exception OG_ERR_NOTFOUND Disco o particion no corresponden con un dispositivo. #@note El fichero de bloqueo se localiza en \c /var/lock/disk, siendo \c disk el dispositivo del disco, sustituyendo el carácter "/" por "-". #*/ ## -def ogUnlockDisk(*args): - # Variables locales - DISK = None - LOCKFILE = None - - # Si se solicita, mostrar ayuda. - if len(args) == 1 and args[0] == "help": - SystemLib.ogHelp('ogUnlockDisk', 'ogUnlockDisk int_ndisk', 'ogUnlockDisk 1') - return - - # Error si no se recibe 1 parámetro. - if len(args) != 1: - SystemLib.ogRaiseError(OG_ERR_FORMAT) - return - - # Obtener partición. - DISK = ogDiskToDev(args[0]) - if DISK is None: - return - - # Borrar archivo de bloqueo exclusivo. - LOCKFILE = f"/var/lock/lock{DISK.replace('/', '-')}" - os.remove(LOCKFILE) - return +def ogUnlockDisk (disk): + DISK = ogDiskToDev (disk) + if not DISK: return None + os.remove (f'/var/lock/lock{DISK.replace("/", "-")}') #/** diff --git a/client/shared/functions/ogUnlockDisk b/client/shared/functions/ogUnlockDisk new file mode 100755 index 0000000..04ee6ed --- /dev/null +++ b/client/shared/functions/ogUnlockDisk @@ -0,0 +1,22 @@ +#!/usr/bin/python3 + +import sys +import argparse +from SystemLib import ogHelp +from DiskLib import ogUnlockDisk + +parser = argparse.ArgumentParser (add_help=False) +parser.add_argument ('disk') + +if 2 == len (sys.argv) and 'help' == sys.argv[1]: + #parser.print_help() sale en inglés aunque la locale indique otra cosa + ogHelp ('ogUnlockDisk', 'ogUnlockDisk int_ndisk', ['ogUnlockDisk 1']) + sys.exit (0) + +args = parser.parse_args() +ret = ogUnlockDisk (args.disk) + +if ret is not None: + if ret == True: sys.exit (0) + elif ret == False: sys.exit (1) + else: print (ret) From b4fe9232baf342c65e54bcc39eb9fc5f6bdbb27f Mon Sep 17 00:00:00 2001 From: Natalia Serrano Date: Wed, 12 Feb 2025 13:56:11 +0100 Subject: [PATCH 141/167] refs #1496 add ogGetDiskSize --- client/lib/engine/bin/DiskLib.py | 41 +++++++++++++-------------- client/shared/functions/ogGetDiskSize | 22 ++++++++++++++ 2 files changed, 41 insertions(+), 22 deletions(-) create mode 100755 client/shared/functions/ogGetDiskSize diff --git a/client/lib/engine/bin/DiskLib.py b/client/lib/engine/bin/DiskLib.py index 73f3bc0..7480c53 100755 --- a/client/lib/engine/bin/DiskLib.py +++ b/client/lib/engine/bin/DiskLib.py @@ -595,30 +595,27 @@ def ogDiskToDev (arg_disk=None, arg_part=None): #@exception OG_ERR_NOTFOUND disco o particion no detectado (no es un dispositivo). #@note Requisitos: sfdisk, awk #*/ ## -def ogGetDiskSize(*args): - # Variables locales - DISK = SIZE = None +def ogGetDiskSize (disk): + DISK = ogDiskToDev (disk) + if not DISK: return None - # Si se solicita, mostrar ayuda. - if len(args) == 1 and args[0] == "help": - SystemLib.ogHelp('ogGetDiskSize', 'ogGetDiskSize int_ndisk', 'ogGetDiskSize 1 => 244198584') - return + bn = os.path.basename (DISK) + SIZE = None + with open ('/proc/partitions', 'r') as fd: + while True: + l = fd.readline() + if not l: break + items = l.split() + if len(items) < 4: continue + if items[3] == bn: + SIZE = int (items[2]) + break + if not SIZE: + vgs_out = subprocess.run (['vgs', '--noheadings', '--units=B', '-o', 'dev_size', DISK], capture_output=True, text=True).stdout + items = vgs_out.split() + SIZE = int (items[0]) // 1024 - # Error si no se recibe 1 parámetro. - if len(args) != 1: - SystemLib.ogRaiseError(OG_ERR_FORMAT) - return - - # Obtener el tamaño del disco. - DISK = ogDiskToDev(args[0]) - if DISK is None: - return - SIZE = subprocess.getoutput(f"lsblk -n -b -o SIZE {DISK}") - - # Mostrar salida. - if SIZE: - print(SIZE) - return + return SIZE #/** diff --git a/client/shared/functions/ogGetDiskSize b/client/shared/functions/ogGetDiskSize new file mode 100755 index 0000000..ea7c42e --- /dev/null +++ b/client/shared/functions/ogGetDiskSize @@ -0,0 +1,22 @@ +#!/usr/bin/python3 + +import sys +import argparse +from SystemLib import ogHelp +from DiskLib import ogGetDiskSize + +parser = argparse.ArgumentParser (add_help=False) +parser.add_argument ('disk') + +if 2 == len (sys.argv) and 'help' == sys.argv[1]: + #parser.print_help() sale en inglés aunque la locale indique otra cosa + ogHelp ('ogGetDiskSize', 'ogGetDiskSize int_ndisk', ['ogGetDiskSize 1']) + sys.exit (0) + +args = parser.parse_args() +ret = ogGetDiskSize (args.disk) + +if ret is not None: + if ret == True: sys.exit (0) + elif ret == False: sys.exit (1) + else: print (ret) From 4142459c8879da43d824263f54f0f75a4ebc2ca3 Mon Sep 17 00:00:00 2001 From: Natalia Serrano Date: Thu, 13 Feb 2025 11:21:53 +0100 Subject: [PATCH 142/167] refs #1497 add ogGetDiskType --- client/lib/engine/bin/DiskLib.py | 76 +++++++++++++++++---------- client/shared/functions/ogGetDiskType | 22 ++++++++ 2 files changed, 69 insertions(+), 29 deletions(-) create mode 100755 client/shared/functions/ogGetDiskType diff --git a/client/lib/engine/bin/DiskLib.py b/client/lib/engine/bin/DiskLib.py index 7480c53..7315d56 100755 --- a/client/lib/engine/bin/DiskLib.py +++ b/client/lib/engine/bin/DiskLib.py @@ -626,39 +626,57 @@ def ogGetDiskSize (disk): #@exception OG_ERR_NOTFOUND disco no detectado o no es un dispositivo de bloques. #@note Requisitos: udevadm #*/ ## -def ogGetDiskType(*args): - # Variables locales - DEV = MAJOR = TYPE = None +def ogGetDiskType (dev): + DEV = os.path.basename (dev) - # Si se solicita, mostrar ayuda. - if len(args) == 1 and args[0] == "help": - SystemLib.ogHelp('ogGetDiskType', 'ogGetDiskType path_device', 'ogGetDiskType /dev/sdb => USB') - return + bn = os.path.basename (DEV) + MAJOR = None + with open ('/proc/partitions', 'r') as fd: + while True: + l = fd.readline() + if not l: break + items = l.split() + if len(items) < 4: continue + if items[3] == bn: + MAJOR = items[0] + break - # Error si no se recibe 1 parámetro. - if len(args) != 1: - SystemLib.ogRaiseError(OG_ERR_FORMAT) - return + TYPE = None + with open ('/proc/devices', 'r') as fd: + within_block_section = False + while True: + l = fd.readline() + if not l: break + + if 'Block' in l: + within_block_section = True + continue + if not within_block_section: + continue + + items = l.split() + if len(items) < 2: continue + if items[0] == MAJOR: + TYPE = items[1].upper() + break - # Obtener el driver del dispositivo de bloques. - DEV = args[0].split("/dev/")[1] - MAJOR = subprocess.getoutput(f"awk -v D='{DEV}' '{{if ($4==D) print $1;}}' /proc/partitions") - TYPE = subprocess.getoutput(f"awk -v D={MAJOR} '/Block/ {{bl=1}} {{if ($1==D&&bl) print toupper($2)}}' /proc/devices") # Devolver mnemónico del driver de dispositivo. - if TYPE == "SD": - TYPE = "DISK" - if subprocess.getoutput(f"udevadm info -q property {args[0]} 2>/dev/null | grep -q '^ID_BUS=usb'"): - TYPE = "USB" - elif TYPE == "BLKEXT": - TYPE = "NVM" - elif TYPE == "SR" or TYPE.startswith("IDE"): - TYPE = "CDROM" # FIXME Comprobar discos IDE. - elif TYPE == "MD" or TYPE.startswith("CCISS"): - TYPE = "RAID" - elif TYPE == "DEVICE-MAPPER": - TYPE = "MAPPER" # FIXME Comprobar LVM y RAID. - print(TYPE) - return + if 'SD' == TYPE: + TYPE = 'DISK' + udevadm_out = subprocess.run (['udevadm', 'info', '-q', 'property', dev], capture_output=True, text=True).stdout + for l in udevadm_out.splitlines(): + if 'ID_BUS=usb' == l[0:10]: + TYPE = 'USB' + elif 'BLKEXT' == TYPE: + TYPE = 'NVM' + elif 'SR' == TYPE or TYPE.startswith ('IDE'): + TYPE = 'CDROM' # FIXME Comprobar discos IDE. + elif 'MD' == TYPE or TYPE.startswith ('CCISS'): + TYPE = 'RAID' + elif 'DEVICE-MAPPER' == TYPE: + TYPE = 'MAPPER' # FIXME Comprobar LVM y RAID. + + return TYPE #/** diff --git a/client/shared/functions/ogGetDiskType b/client/shared/functions/ogGetDiskType new file mode 100755 index 0000000..022482f --- /dev/null +++ b/client/shared/functions/ogGetDiskType @@ -0,0 +1,22 @@ +#!/usr/bin/python3 + +import sys +import argparse +from SystemLib import ogHelp +from DiskLib import ogGetDiskType + +parser = argparse.ArgumentParser (add_help=False) +parser.add_argument ('dev') + +if 2 == len (sys.argv) and 'help' == sys.argv[1]: + #parser.print_help() sale en inglés aunque la locale indique otra cosa + ogHelp ('ogGetDiskType', 'ogGetDiskType path_device', ['ogGetDiskType /dev/sdb']) + sys.exit (0) + +args = parser.parse_args() +ret = ogGetDiskType (args.dev) + +if ret is not None: + if ret == True: sys.exit (0) + elif ret == False: sys.exit (1) + else: print (ret) From 1fdbdd637cafb0e73331cf8f86b87f46dcb6ba4f Mon Sep 17 00:00:00 2001 From: Natalia Serrano Date: Thu, 13 Feb 2025 11:32:49 +0100 Subject: [PATCH 143/167] refs #1498 add ogIdToType --- client/lib/engine/bin/DiskLib.py | 160 ++++++++++++----------------- client/shared/functions/ogIdToType | 22 ++++ 2 files changed, 87 insertions(+), 95 deletions(-) create mode 100755 client/shared/functions/ogIdToType diff --git a/client/lib/engine/bin/DiskLib.py b/client/lib/engine/bin/DiskLib.py index 7315d56..7a89fcf 100755 --- a/client/lib/engine/bin/DiskLib.py +++ b/client/lib/engine/bin/DiskLib.py @@ -999,104 +999,74 @@ def ogHidePartition(*args): #@return str_parttype mnemónico de tipo de partición. #@exception OG_ERR_FORMAT Formato incorrecto. #*/ ## -def ogIdToType(ID): +def ogIdToType (ID): # Obtener valor hexadecimal de 4 caracteres rellenado con 0 por delante. ID = ID.zfill(4) - TYPE = None - # Asignar el tipo de partición según el ID. - if ID == "0000": - TYPE = "EMPTY" - elif ID == "0001": - TYPE = "FAT12" - elif ID in ["0005", "000f"]: - TYPE = "EXTENDED" - elif ID in ["0006", "000e"]: - TYPE = "FAT16" - elif ID == "0007": - TYPE = "NTFS" - elif ID in ["000b", "000c"]: - TYPE = "FAT32" - elif ID == "0011": - TYPE = "HFAT12" - elif ID == "0012": - TYPE = "COMPAQDIAG" - elif ID in ["0016", "001e"]: - TYPE = "HFAT16" - elif ID == "0017": - TYPE = "HNTFS" - elif ID in ["001b", "001c"]: - TYPE = "HFAT32" - elif ID == "0042": - TYPE = "WIN-DYNAMIC" - elif ID in ["0082", "8200"]: - TYPE = "LINUX-SWAP" - elif ID in ["0083", "8300"]: - TYPE = "LINUX" - elif ID in ["008e", "8E00"]: - TYPE = "LINUX-LVM" - elif ID in ["00a5", "a503"]: - TYPE = "FREEBSD" - elif ID == "00a6": - TYPE = "OPENBSD" - elif ID == "00a7": - TYPE = "CACHE" # (compatibilidad con Brutalix) - elif ID in ["00af", "af00"]: - TYPE = "HFS" - elif ID in ["00be", "be00"]: - TYPE = "SOLARIS-BOOT" - elif ID in ["00bf", "bf00145"]: - TYPE = "SOLARIS" - elif ID in ["00ca", "ca00"]: - TYPE = "CACHE" - elif ID == "00da": - TYPE = "DATA" - elif ID == "00ee": - TYPE = "GPT" - elif ID in ["00ef", "ef00"]: - TYPE = "EFI" - elif ID == "00fb": - TYPE = "VMFS" - elif ID in ["00fd", "fd00"]: - TYPE = "LINUX-RAID" - elif ID == "0700": - TYPE = "WINDOWS" - elif ID == "0c01": - TYPE = "WIN-RESERV" - elif ID == "7f00": - TYPE = "CHROMEOS-KRN" - elif ID == "7f01": - TYPE = "CHROMEOS" - elif ID == "7f02": - TYPE = "CHROMEOS-RESERV" - elif ID == "8301": - TYPE = "LINUX-RESERV" - elif ID == "a500": - TYPE = "FREEBSD-DISK" - elif ID == "a501": - TYPE = "FREEBSD-BOOT" - elif ID == "a502": - TYPE = "FREEBSD-SWAP" - elif ID == "ab00": - TYPE = "HFS-BOOT" - elif ID == "af01": - TYPE = "HFS-RAID" - elif ID == "bf02": - TYPE = "SOLARIS-SWAP" - elif ID == "bf03": - TYPE = "SOLARIS-DISK" - elif ID == "ef01": - TYPE = "MBR" - elif ID == "ef02": - TYPE = "BIOS-BOOT" - elif ID == "10000": - TYPE = "LVM-LV" - elif ID == "10010": - TYPE = "ZFS-VOL" - else: - TYPE = "UNKNOWN" - - return TYPE + id2type = { + '0000': 'EMPTY', + '0001': 'FAT12', + '0005': 'EXTENDED', + '000f': 'EXTENDED', + '0006': 'FAT16', + '000e': 'FAT16', + '0007': 'NTFS', + '000b': 'FAT32', + '000c': 'FAT32', + '0011': 'HFAT12', + '0012': 'COMPAQDIAG', + '0016': 'HFAT16', + '001e': 'HFAT16', + '0017': 'HNTFS', + '001b': 'HFAT32', + '001c': 'HFAT32', + '0042': 'WIN-DYNAMIC', + '0082': 'LINUX-SWAP', + '8200': 'LINUX-SWAP', + '0083': 'LINUX', + '8300': 'LINUX', + '008e': 'LINUX-LVM', + '8E00': 'LINUX-LVM', + '00a5': 'FREEBSD', + 'a503': 'FREEBSD', + '00a6': 'OPENBSD', + '00a7': 'CACHE', # (compatibilidad con Brutalix) + '00af': 'HFS', + 'af00': 'HFS', + '00be': 'SOLARIS-BOOT', + 'be00': 'SOLARIS-BOOT', + '00bf': 'SOLARIS', + 'bf00145': 'SOLARIS', + '00ca': 'CACHE', + 'ca00': 'CACHE', + '00da': 'DATA', + '00ee': 'GPT', + '00ef': 'EFI', + 'ef00': 'EFI', + '00fb': 'VMFS', + '00fd': 'LINUX-RAID', + 'fd00': 'LINUX-RAID', + '0700': 'WINDOWS', + '0c01': 'WIN-RESERV', + '7f00': 'CHROMEOS-KRN', + '7f01': 'CHROMEOS', + '7f02': 'CHROMEOS-RESERV', + '8301': 'LINUX-RESERV', + 'a500': 'FREEBSD-DISK', + 'a501': 'FREEBSD-BOOT', + 'a502': 'FREEBSD-SWAP', + 'ab00': 'HFS-BOOT', + 'af01': 'HFS-RAID', + 'bf02': 'SOLARIS-SWAP', + 'bf03': 'SOLARIS-DISK', + 'ef01': 'MBR', + 'ef02': 'BIOS-BOOT', + '10000': 'LVM-LV', + '10010': 'ZFS-VOL', + } + if ID in id2type: + return id2type[ID] + return 'UNKNOWN' # ogIsDiskLocked int_ndisk diff --git a/client/shared/functions/ogIdToType b/client/shared/functions/ogIdToType new file mode 100755 index 0000000..50bec6e --- /dev/null +++ b/client/shared/functions/ogIdToType @@ -0,0 +1,22 @@ +#!/usr/bin/python3 + +import sys +import argparse +from SystemLib import ogHelp +from DiskLib import ogIdToType + +parser = argparse.ArgumentParser (add_help=False) +parser.add_argument ('id') + +if 2 == len (sys.argv) and 'help' == sys.argv[1]: + #parser.print_help() sale en inglés aunque la locale indique otra cosa + ogHelp ('ogIdToType', 'ogIdToType int_idpart', ['ogIdToType 83']) + sys.exit (0) + +args = parser.parse_args() +ret = ogIdToType (args.id) + +if ret is not None: + if ret == True: sys.exit (0) + elif ret == False: sys.exit (1) + else: print (ret) From 5cc3176d745cefed82bdc586d335e5f806333aa5 Mon Sep 17 00:00:00 2001 From: Natalia Serrano Date: Thu, 13 Feb 2025 12:20:09 +0100 Subject: [PATCH 144/167] refs #1503 add ogGetPartitionType --- client/lib/engine/bin/DiskLib.py | 28 +++++----------------- client/shared/functions/ogGetPartitionType | 23 ++++++++++++++++++ 2 files changed, 29 insertions(+), 22 deletions(-) create mode 100755 client/shared/functions/ogGetPartitionType diff --git a/client/lib/engine/bin/DiskLib.py b/client/lib/engine/bin/DiskLib.py index 7a89fcf..8b8978c 100755 --- a/client/lib/engine/bin/DiskLib.py +++ b/client/lib/engine/bin/DiskLib.py @@ -916,28 +916,12 @@ def ogGetPartitionTableType (disk): #@exception OG_ERR_FORMAT Formato incorrecto. #@exception OG_ERR_NOTFOUND Disco o particion no corresponden con un dispositivo. #*/ ## -def ogGetPartitionType(*args): - # Variables locales - ID = None - TYPE = None +def ogGetPartitionType (disk, par): + ID = ogGetPartitionId (disk, par) + if ID is None: return None + print (f'got ID ({ID})') - # Si se solicita, mostrar ayuda. - if len(args) == 1 and args[0] == "help": - SystemLib.ogHelp('ogGetPartitionType', 'ogGetPartitionType int_ndisk int_npartition', 'ogGetPartitionType 1 1 => NTFS') - return - - # Error si no se reciben 2 parámetros. - if len(args) != 2: - SystemLib.ogRaiseError(OG_ERR_FORMAT) - return - - # Detectar id. de tipo de partición y codificar al mnemónico. - ID = ogGetPartitionId(args[0], args[1]) - if ID is None: - return - TYPE = ogIdToType(ID) - print(TYPE) - return + return ogIdToType (ID) #/** @@ -1001,7 +985,7 @@ def ogHidePartition(*args): #*/ ## def ogIdToType (ID): # Obtener valor hexadecimal de 4 caracteres rellenado con 0 por delante. - ID = ID.zfill(4) + ID = ID.zfill(4).lower() id2type = { '0000': 'EMPTY', diff --git a/client/shared/functions/ogGetPartitionType b/client/shared/functions/ogGetPartitionType new file mode 100755 index 0000000..51e6644 --- /dev/null +++ b/client/shared/functions/ogGetPartitionType @@ -0,0 +1,23 @@ +#!/usr/bin/python3 + +import sys +import argparse +from SystemLib import ogHelp +from DiskLib import ogGetPartitionType + +parser = argparse.ArgumentParser (add_help=False) +parser.add_argument ('disk') +parser.add_argument ('par') + +if 2 == len (sys.argv) and 'help' == sys.argv[1]: + #parser.print_help() sale en inglés aunque la locale indique otra cosa + ogHelp ('ogGetPartitionType', 'ogGetPartitionType int_ndisk int_nfilesys', ['ogGetPartitionType 1 1']) + sys.exit (0) + +args = parser.parse_args() +ret = ogGetPartitionType (args.disk, args.par) + +if ret is not None: + if ret == True: sys.exit (0) + elif ret == False: sys.exit (1) + else: print (ret) From 00da7454ec33f7f59af554afbe9895bf965d986e Mon Sep 17 00:00:00 2001 From: Natalia Serrano Date: Thu, 13 Feb 2025 12:44:00 +0100 Subject: [PATCH 145/167] refs #1504 add ogListPartitions --- client/lib/engine/bin/DiskLib.py | 41 +++++++----------------- client/shared/functions/ogListPartitions | 22 +++++++++++++ 2 files changed, 34 insertions(+), 29 deletions(-) create mode 100755 client/shared/functions/ogListPartitions diff --git a/client/lib/engine/bin/DiskLib.py b/client/lib/engine/bin/DiskLib.py index 8b8978c..3afd71c 100755 --- a/client/lib/engine/bin/DiskLib.py +++ b/client/lib/engine/bin/DiskLib.py @@ -795,7 +795,7 @@ def ogGetPartitionId (disk, par): start_index = next (i for i, line in enumerate(lines) if 'Number' in line) for l in lines[start_index:]: idx, start, end, sz, sz_units, code, *rest = l.split() - if idx == par: + if idx == str(par): fsid = code break if fsid == '8300' and f'{disk} {par}' == CacheLib.ogFindCache(): @@ -919,7 +919,6 @@ def ogGetPartitionTableType (disk): def ogGetPartitionType (disk, par): ID = ogGetPartitionId (disk, par) if ID is None: return None - print (f'got ID ({ID})') return ogIdToType (ID) @@ -1076,35 +1075,19 @@ def ogIsDiskLocked (disk): #@attention El nº de partición se indica por el orden de los párametros \c parttype:partsize #@attention Las tuplas de valores están separadas por espacios. #*/ ## -def ogListPartitions(*args): - # Variables locales - DISK = None - PART = None - NPARTS = None - TYPE = None - SIZE = None +def ogListPartitions (disk): + DISK = ogDiskToDev (disk) + if not DISK: return None - # Si se solicita, mostrar ayuda. - if len(args) == 1 and args[0] == "help": - SystemLib.ogHelp('ogListPartitions', 'ogListPartitions int_ndisk', 'ogListPartitions 1 => NTFS:10000000 EXT3:5000000 LINUX-SWAP:1000000') - return + p = [] + NPARTS = ogGetPartitionsNumber (disk) + for PART in range (1, NPARTS + 1): + t = ogGetPartitionType (disk, PART) + TYPE = ogGetPartitionType (disk, PART) or 'EMPTY' + SIZE = ogGetPartitionSize (disk, PART) or 0 + p.append (f'{TYPE}:{SIZE}') - # Error si no se recibe 1 parámetro. - if len(args) != 1: - SystemLib.ogRaiseError(OG_ERR_FORMAT) - return - - # Procesar la salida de parted. - DISK = ogDiskToDev(args[0]) - if DISK is None: - return - NPARTS = ogGetPartitionsNumber(args[0]) - for PART in range(1, NPARTS + 1): - TYPE = ogGetPartitionType(args[0], PART) or "EMPTY" - SIZE = ogGetPartitionSize(args[0], PART) or 0 - print(f"{TYPE}:{SIZE} ", end="") - print() - return + return ' '.join (p) #/** diff --git a/client/shared/functions/ogListPartitions b/client/shared/functions/ogListPartitions new file mode 100755 index 0000000..e507d73 --- /dev/null +++ b/client/shared/functions/ogListPartitions @@ -0,0 +1,22 @@ +#!/usr/bin/python3 + +import sys +import argparse +from SystemLib import ogHelp +from DiskLib import ogListPartitions + +parser = argparse.ArgumentParser (add_help=False) +parser.add_argument ('disk') + +if 2 == len (sys.argv) and 'help' == sys.argv[1]: + #parser.print_help() sale en inglés aunque la locale indique otra cosa + ogHelp ('ogListPartitions', 'ogListPartitions int_ndisk', ['ogListPartitions 1']) + sys.exit (0) + +args = parser.parse_args() +ret = ogListPartitions (args.disk) + +if ret is not None: + if ret == True: sys.exit (0) + elif ret == False: sys.exit (1) + else: print (ret) From 941ace29bb4c7015d1faf8eaf8bad0ebce420004 Mon Sep 17 00:00:00 2001 From: Natalia Serrano Date: Thu, 13 Feb 2025 13:04:06 +0100 Subject: [PATCH 146/167] refs #1501 add ogListLogicalPartitions --- client/lib/engine/bin/DiskLib.py | 24 ++++++------------- .../shared/functions/ogListLogicalPartitions | 22 +++++++++++++++++ client/shared/functions/ogListPartitions | 2 +- 3 files changed, 30 insertions(+), 18 deletions(-) create mode 100755 client/shared/functions/ogListLogicalPartitions diff --git a/client/lib/engine/bin/DiskLib.py b/client/lib/engine/bin/DiskLib.py index 3afd71c..617efc4 100755 --- a/client/lib/engine/bin/DiskLib.py +++ b/client/lib/engine/bin/DiskLib.py @@ -1087,7 +1087,7 @@ def ogListPartitions (disk): SIZE = ogGetPartitionSize (disk, PART) or 0 p.append (f'{TYPE}:{SIZE}') - return ' '.join (p) + return p #/** @@ -1126,24 +1126,14 @@ def ogListPrimaryPartitions(*args): #@param int_ndisk nº de orden del disco #@see ogListPartitions #*/ ## -def ogListLogicalPartitions(*args): - # Variables locales - PTTYPE = None - PARTS = None +def ogListLogicalPartitions (disk): + PTTYPE = ogGetPartitionTableType (disk) + if not PTTYPE: return None - # Si se solicita, mostrar ayuda. - if len(args) == 1 and args[0] == "help": - SystemLib.ogHelp('ogListLogicalPartitions', 'ogListLogicalPartitions int_ndisk', 'ogListLogicalPartitions 1 => LINUX-SWAP:999998') - return + PARTS = ogListPartitions (disk) + if not PARTS: return None - PTTYPE = ogGetPartitionTableType(args[0]) - if PTTYPE is None: - return - PARTS = ogListPartitions(*args) - if PARTS is None: - return - - return PARTS.split(" ")[4:] + return PARTS[4:] #/** diff --git a/client/shared/functions/ogListLogicalPartitions b/client/shared/functions/ogListLogicalPartitions new file mode 100755 index 0000000..c79a006 --- /dev/null +++ b/client/shared/functions/ogListLogicalPartitions @@ -0,0 +1,22 @@ +#!/usr/bin/python3 + +import sys +import argparse +from SystemLib import ogHelp +from DiskLib import ogListLogicalPartitions + +parser = argparse.ArgumentParser (add_help=False) +parser.add_argument ('disk') + +if 2 == len (sys.argv) and 'help' == sys.argv[1]: + #parser.print_help() sale en inglés aunque la locale indique otra cosa + ogHelp ('ogListLogicalPartitions', 'ogListLogicalPartitions int_ndisk', ['ogListLogicalPartitions 1']) + sys.exit (0) + +args = parser.parse_args() +ret = ogListLogicalPartitions (args.disk) + +if ret is not None: + if ret == True: sys.exit (0) + elif ret == False: sys.exit (1) + else: print (' '.join (ret)) diff --git a/client/shared/functions/ogListPartitions b/client/shared/functions/ogListPartitions index e507d73..ca0479b 100755 --- a/client/shared/functions/ogListPartitions +++ b/client/shared/functions/ogListPartitions @@ -19,4 +19,4 @@ ret = ogListPartitions (args.disk) if ret is not None: if ret == True: sys.exit (0) elif ret == False: sys.exit (1) - else: print (ret) + else: print (' '.join (ret)) From 79718100f6808e2a5d528f53acc3ea760780a473 Mon Sep 17 00:00:00 2001 From: Natalia Serrano Date: Thu, 13 Feb 2025 13:24:47 +0100 Subject: [PATCH 147/167] refs #1502 add ogListPrimaryPartitions --- client/lib/engine/bin/DiskLib.py | 34 ++++++++----------- .../shared/functions/ogListPrimaryPartitions | 22 ++++++++++++ 2 files changed, 36 insertions(+), 20 deletions(-) create mode 100755 client/shared/functions/ogListPrimaryPartitions diff --git a/client/lib/engine/bin/DiskLib.py b/client/lib/engine/bin/DiskLib.py index 617efc4..0faee2a 100755 --- a/client/lib/engine/bin/DiskLib.py +++ b/client/lib/engine/bin/DiskLib.py @@ -1096,28 +1096,22 @@ def ogListPartitions (disk): #@param int_ndisk nº de orden del disco #@see ogListPartitions #*/ ## -def ogListPrimaryPartitions(*args): - # Variables locales - PTTYPE = None - PARTS = None +def ogListPrimaryPartitions (disk): + PTTYPE = ogGetPartitionTableType (disk) + if not PTTYPE: return None - # Si se solicita, mostrar ayuda. - if len(args) == 1 and args[0] == "help": - SystemLib.ogHelp('ogListPrimaryPartitions', 'ogListPrimaryPartitions int_ndisk', 'ogListPrimaryPartitions 1 => NTFS:10000000 EXT3:5000000 EXTENDED:1000000') - return + PARTS = ogListPartitions (disk) + if not PARTS: return None - PTTYPE = ogGetPartitionTableType(args[0]) - if PTTYPE is None: - return - PARTS = ogListPartitions(*args) - if PARTS is None: - return - - if PTTYPE == "GPT": - print(PARTS.rstrip(" EMPTY:0")) - elif PTTYPE == "MSDOS": - print(PARTS.split(" ")[0:4]) - return + if 'GPT' == PTTYPE: + res = [] + for idx in range (len(PARTS),0,-1): + item = PARTS[idx-1] + if 0==len(res) and 'EMPTY:0' == item: continue + res.insert (0, item) + return res + elif 'MSDOS' == PTTYPE: + return PARTS[0:4] #/** diff --git a/client/shared/functions/ogListPrimaryPartitions b/client/shared/functions/ogListPrimaryPartitions new file mode 100755 index 0000000..045289f --- /dev/null +++ b/client/shared/functions/ogListPrimaryPartitions @@ -0,0 +1,22 @@ +#!/usr/bin/python3 + +import sys +import argparse +from SystemLib import ogHelp +from DiskLib import ogListPrimaryPartitions + +parser = argparse.ArgumentParser (add_help=False) +parser.add_argument ('disk') + +if 2 == len (sys.argv) and 'help' == sys.argv[1]: + #parser.print_help() sale en inglés aunque la locale indique otra cosa + ogHelp ('ogListPrimaryPartitions', 'ogListPrimaryPartitions int_ndisk', ['ogListPrimaryPartitions 1']) + sys.exit (0) + +args = parser.parse_args() +ret = ogListPrimaryPartitions (args.disk) + +if ret is not None: + if ret == True: sys.exit (0) + elif ret == False: sys.exit (1) + else: print (' '.join (ret)) From 788ae31b0fae95ba0424e224029959e8bcab972c Mon Sep 17 00:00:00 2001 From: Natalia Serrano Date: Thu, 13 Feb 2025 14:03:28 +0100 Subject: [PATCH 148/167] refs #1509 add ogDeletePartitionTable --- client/lib/engine/bin/DiskLib.py | 32 +++++-------------- .../shared/functions/ogDeletePartitionTable | 22 +++++++++++++ 2 files changed, 30 insertions(+), 24 deletions(-) create mode 100755 client/shared/functions/ogDeletePartitionTable diff --git a/client/lib/engine/bin/DiskLib.py b/client/lib/engine/bin/DiskLib.py index 0faee2a..1279f70 100755 --- a/client/lib/engine/bin/DiskLib.py +++ b/client/lib/engine/bin/DiskLib.py @@ -320,31 +320,15 @@ def ogCreatePartitionTable (disk, createptt=None): #@param int_ndisk nº de orden del disco #@return la informacion propia del fdisk #*/ ## -def ogDeletePartitionTable(*args): - # Variables locales - DISK = None +def ogDeletePartitionTable (disk): + DISK = ogDiskToDev (disk) + if not DISK: return None - # Si se solicita, mostrar ayuda. - if len(args) == 1 and args[0] == "help": - SystemLib.ogHelp('ogDeletePartitionTable', 'ogDeletePartitionTable int_ndisk', 'ogDeletePartitionTable 1') - return - - # Error si no se reciben 1 parámetros. - if len(args) != 1: - SystemLib.ogRaiseError(OG_ERR_FORMAT) - return - - # Obteniendo Identificador linux del disco. - DISK = ogDiskToDev(args[0]) - if DISK is None: - return - - # Crear una tabla de particiones vacía. - PTTYPE = ogGetPartitionTableType(args[0]) - if PTTYPE == "GPT": - subprocess.run(["sgdisk", "-o", DISK]) - elif PTTYPE == "MSDOS": - subprocess.run(["fdisk", DISK], input="o\nw", text=True) + PTTYPE = ogGetPartitionTableType (disk) + if 'GPT' == PTTYPE: + subprocess.run (['sgdisk', '--clear', DISK]) + elif 'MSDOS' == PTTYPE: + subprocess.run (['fdisk', DISK], input='o\nw', text=True) return #/** diff --git a/client/shared/functions/ogDeletePartitionTable b/client/shared/functions/ogDeletePartitionTable new file mode 100755 index 0000000..5d35b5d --- /dev/null +++ b/client/shared/functions/ogDeletePartitionTable @@ -0,0 +1,22 @@ +#!/usr/bin/python3 + +import sys +import argparse +from SystemLib import ogHelp +from DiskLib import ogDeletePartitionTable + +parser = argparse.ArgumentParser (add_help=False) +parser.add_argument ('disk') + +if 2 == len (sys.argv) and 'help' == sys.argv[1]: + #parser.print_help() sale en inglés aunque la locale indique otra cosa + ogHelp ('ogDeletePartitionTable', 'ogDeletePartitionTable int_ndisk', ['ogDeletePartitionTable 1']) + sys.exit (0) + +args = parser.parse_args() +ret = ogDeletePartitionTable (args.disk) + +if ret is not None: + if ret == True: sys.exit (0) + elif ret == False: sys.exit (1) + else: print (ret) From 0d8d543526979de95e752720020ccffdc7cb33d5 Mon Sep 17 00:00:00 2001 From: Natalia Serrano Date: Fri, 14 Feb 2025 13:54:20 +0100 Subject: [PATCH 149/167] refs #1513 add ogSetPartitionId --- client/lib/engine/bin/DiskLib.py | 64 ++++++++++++-------------------- 1 file changed, 24 insertions(+), 40 deletions(-) diff --git a/client/lib/engine/bin/DiskLib.py b/client/lib/engine/bin/DiskLib.py index 1279f70..eefbfac 100755 --- a/client/lib/engine/bin/DiskLib.py +++ b/client/lib/engine/bin/DiskLib.py @@ -10,6 +10,7 @@ import filecmp import subprocess import shutil import os +import re import stat from pathlib import Path @@ -1167,52 +1168,35 @@ def ogSetPartitionActive (disk, par): #@exception OG_ERR_PARTITION Error al cambiar el id. de partición. #@attention Requisitos: fdisk, sgdisk #*/ ## -def ogSetPartitionId(*args): - # Variables locales - DISK = None - PART = None - PTTYPE = None - ID = None +def ogSetPartitionId (disk, par, id): + DISK = ogDiskToDev (disk) + if not DISK: return None - # Si se solicita, mostrar ayuda. - if len(args) == 1 and args[0] == "help": - SystemLib.ogHelp('ogSetPartitionId', 'ogSetPartitionId int_ndisk int_npartition hex_partid', 'ogSetPartitionId 1 1 7') - return + PART = ogDiskToDev (disk, par) + if not PART: return None - # Error si no se reciben 3 parámetros. - if len(args) != 3: - SystemLib.ogRaiseError(OG_ERR_FORMAT) - return +# Error si el id. de partición no es hexadecimal. + if not re.match ('^[0-9A-Fa-f]+$', id): + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_OUTOFLIMIT, id) + return None - # Sustituye nº de disco y nº partición por su dispositivo. - DISK = ogDiskToDev(args[0]) - if DISK is None: - return - PART = ogDiskToDev(args[0], args[1]) - if PART is None: - return - # Error si el id. de partición no es hexadecimal. - ID = args[2].upper() - if not re.match("^[0-9A-F]+$", ID): - SystemLib.ogRaiseError(OG_ERR_OUTOFLIMIT, args[2]) - return - - # Elección del tipo de partición. - PTTYPE = ogGetPartitionTableType(args[0]) - if PTTYPE == "GPT": - subprocess.run(["sgdisk", f"-t{args[1]}:{ID}", DISK], stderr=subprocess.DEVNULL) - elif PTTYPE == "MSDOS": - subprocess.run(["sfdisk", f"--id", DISK, args[1], ID], stderr=subprocess.DEVNULL) +# Elección del tipo de partición. + PTTYPE = ogGetPartitionTableType (disk) + if 'GPT' == PTTYPE: + p = subprocess.run (['sgdisk', f'-t{par}:{id.upper()}', DISK]) + elif 'MSDOS' == PTTYPE: + p = subprocess.run (['sfdisk', '--id', DISK, par, id.upper()]) else: - SystemLib.ogRaiseError(OG_ERR_OUTOFLIMIT, f"{args[0]},{PTTYPE}") - return + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_OUTOFLIMIT, f'{disk},{PTTYPE}') + return None - # MSDOS) Correcto si fdisk sin error o con error pero realiza Syncing - if subprocess.run(["partprobe", DISK], stderr=subprocess.DEVNULL).returncode == 0: - return +# MSDOS) Correcto si fdisk sin error o con error pero realiza Syncing + if 0 == p.returncode: + subprocess.run (['partprobe', DISK]) + return True else: - SystemLib.ogRaiseError(OG_ERR_PARTITION, f"{args[0]},{args[1]},{args[2]}") - return + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_PARTITION, f'{disk},{part},{id}') + return None #/** From f7263381b968f5dbfeecebe63f5ab23e3f79b8c8 Mon Sep 17 00:00:00 2001 From: Natalia Serrano Date: Fri, 14 Feb 2025 13:55:53 +0100 Subject: [PATCH 150/167] refs #1513 add ogSetPartitionId --- client/shared/functions/ogSetPartitionId | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100755 client/shared/functions/ogSetPartitionId diff --git a/client/shared/functions/ogSetPartitionId b/client/shared/functions/ogSetPartitionId new file mode 100755 index 0000000..865051f --- /dev/null +++ b/client/shared/functions/ogSetPartitionId @@ -0,0 +1,24 @@ +#!/usr/bin/python3 + +import sys +import argparse +from SystemLib import ogHelp +from DiskLib import ogSetPartitionId + +parser = argparse.ArgumentParser (add_help=False) +parser.add_argument ('disk') +parser.add_argument ('par') +parser.add_argument ('id') + +if 2 == len (sys.argv) and 'help' == sys.argv[1]: + #parser.print_help() sale en inglés aunque la locale indique otra cosa + ogHelp ('ogSetPartitionId', 'ogSetPartitionId int_ndisk int_npartition hex_partid', ['ogSetPartitionId 1 1 7']) + sys.exit (0) + +args = parser.parse_args() +ret = ogSetPartitionId (args.disk, args.par, args.id) + +if ret is not None: + if ret == True: sys.exit (0) + elif ret == False: sys.exit (1) + else: print (ret) From 158c25f43ef3475d183900fbad2cb3c6a246be02 Mon Sep 17 00:00:00 2001 From: Natalia Serrano Date: Fri, 14 Feb 2025 13:56:16 +0100 Subject: [PATCH 151/167] refs #1511 add ogHidePartition --- client/lib/engine/bin/DiskLib.py | 49 ++++++------------------- client/shared/functions/ogHidePartition | 23 ++++++++++++ 2 files changed, 35 insertions(+), 37 deletions(-) create mode 100755 client/shared/functions/ogHidePartition diff --git a/client/lib/engine/bin/DiskLib.py b/client/lib/engine/bin/DiskLib.py index eefbfac..9493ac4 100755 --- a/client/lib/engine/bin/DiskLib.py +++ b/client/lib/engine/bin/DiskLib.py @@ -918,46 +918,21 @@ def ogGetPartitionType (disk, par): #@exception OG_ERR_NOTFOUND disco o particion no detectado (no es un dispositivo). #@exception OG_ERR_PARTITION tipo de partición no reconocido. #*/ ## -def ogHidePartition(*args): - # Variables locales - PART = None - TYPE = None - NEWTYPE = None +def ogHidePartition (disk, par): + PART = ogDiskToDev (disk, par) + if not PART: return None - # Si se solicita, mostrar ayuda. - if len(args) == 1 and args[0] == "help": - SystemLib.ogHelp('ogHidePartition', 'ogHidePartition int_ndisk int_npartition', 'ogHidePartition 1 1') - return - - # Error si no se reciben 2 parámetros. - if len(args) != 2: - SystemLib.ogRaiseError(OG_ERR_FORMAT) - return - - # Obtener el dispositivo de la partición. - PART = ogDiskToDev(args[0], args[1]) - if PART is None: - return - - # Obtener tipo de partición. - TYPE = ogGetPartitionType(args[0], args[1]) - if TYPE == "NTFS": - NEWTYPE = "HNTFS" - elif TYPE == "FAT32": - NEWTYPE = "HFAT32" - elif TYPE == "FAT16": - NEWTYPE = "HFAT16" - elif TYPE == "FAT12": - NEWTYPE = "HFAT12" - elif TYPE == "WINDOWS": - NEWTYPE = "WIN-RESERV" + TYPE = ogGetPartitionType (disk, par) + if 'NTFS' == TYPE: NEWTYPE = 'HNTFS' + elif 'FAT32' == TYPE: NEWTYPE = 'HFAT32' + elif 'FAT16' == TYPE: NEWTYPE = 'HFAT16' + elif 'FAT12' == TYPE: NEWTYPE = 'HFAT12' + elif 'WINDOWS' == TYPE: NEWTYPE = 'WIN-RESERV' else: - SystemLib.ogRaiseError(OG_ERR_PARTITION, TYPE) - return + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_PARTITION, TYPE) + return None - # Cambiar tipo de partición. - ogSetPartitionType(args[0], args[1], NEWTYPE) - return + ogSetPartitionType (disk, par, NEWTYPE) #/** diff --git a/client/shared/functions/ogHidePartition b/client/shared/functions/ogHidePartition new file mode 100755 index 0000000..2a97ce1 --- /dev/null +++ b/client/shared/functions/ogHidePartition @@ -0,0 +1,23 @@ +#!/usr/bin/python3 + +import sys +import argparse +from SystemLib import ogHelp +from DiskLib import ogHidePartition + +parser = argparse.ArgumentParser (add_help=False) +parser.add_argument ('disk') +parser.add_argument ('par') + +if 2 == len (sys.argv) and 'help' == sys.argv[1]: + #parser.print_help() sale en inglés aunque la locale indique otra cosa + ogHelp ('ogHidePartition', 'ogHidePartition int_ndisk int_npartition', ['ogHidePartition 1 1']) + sys.exit (0) + +args = parser.parse_args() +ret = ogHidePartition (args.disk, args.par) + +if ret is not None: + if ret == True: sys.exit (0) + elif ret == False: sys.exit (1) + else: print (ret) From d71e261829c650e0c6921a7fb4912dde4a01f987 Mon Sep 17 00:00:00 2001 From: Natalia Serrano Date: Fri, 14 Feb 2025 14:02:24 +0100 Subject: [PATCH 152/167] refs #1512 add ogUnhidePartition --- client/lib/engine/bin/DiskLib.py | 48 ++++++----------------- client/shared/functions/ogUnhidePartition | 23 +++++++++++ 2 files changed, 35 insertions(+), 36 deletions(-) create mode 100755 client/shared/functions/ogUnhidePartition diff --git a/client/lib/engine/bin/DiskLib.py b/client/lib/engine/bin/DiskLib.py index 9493ac4..8fe5b9e 100755 --- a/client/lib/engine/bin/DiskLib.py +++ b/client/lib/engine/bin/DiskLib.py @@ -1381,45 +1381,21 @@ def ogTypeToId (type, pttype='MSDOS'): #@exception OG_ERR_NOTFOUND disco o particion no detectado (no es un dispositivo). #@exception OG_ERR_PARTITION tipo de partición no reconocido. #*/ ## -def ogUnhidePartition(*args): - # Variables locales - PART = None - TYPE = None - NEWTYPE = None +def ogUnhidePartition (disk, par): + PART = ogDiskToDev (disk, par) + if not PART: return None - # Si se solicita, mostrar ayuda. - if len(args) == 1 and args[0] == "help": - SystemLib.ogHelp('ogUnhidePartition', 'ogUnhidePartition int_ndisk int_npartition', 'ogUnhidePartition 1 1') - return - - # Error si no se reciben 2 parámetros. - if len(args) != 2: - SystemLib.ogRaiseError(OG_ERR_FORMAT) - return - - PART = ogDiskToDev(args[0], args[1]) - if PART is None: - return - - # Obtener tipo de partición. - TYPE = ogGetPartitionType(args[0], args[1]) - if TYPE == "HNTFS": - NEWTYPE = "NTFS" - elif TYPE == "HFAT32": - NEWTYPE = "FAT32" - elif TYPE == "HFAT16": - NEWTYPE = "FAT16" - elif TYPE == "HFAT12": - NEWTYPE = "FAT12" - elif TYPE == "WIN-RESERV": - NEWTYPE = "WINDOWS" + TYPE = ogGetPartitionType (disk, par) + if 'HNTFS' == TYPE: NEWTYPE = 'NTFS' + elif 'HFAT32' == TYPE: NEWTYPE = 'FAT32' + elif 'HFAT16' == TYPE: NEWTYPE = 'FAT16' + elif 'HFAT12' == TYPE: NEWTYPE = 'FAT12' + elif 'WIN-RESERV' == TYPE: NEWTYPE = 'WINDOWS' else: - SystemLib.ogRaiseError(OG_ERR_PARTITION, TYPE) - return + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_PARTITION, TYPE) + return None - # Cambiar tipo de partición. - ogSetPartitionType(args[0], args[1], NEWTYPE) - return + ogSetPartitionType (disk, par, NEWTYPE) #/** diff --git a/client/shared/functions/ogUnhidePartition b/client/shared/functions/ogUnhidePartition new file mode 100755 index 0000000..539303e --- /dev/null +++ b/client/shared/functions/ogUnhidePartition @@ -0,0 +1,23 @@ +#!/usr/bin/python3 + +import sys +import argparse +from SystemLib import ogHelp +from DiskLib import ogUnhidePartition + +parser = argparse.ArgumentParser (add_help=False) +parser.add_argument ('disk') +parser.add_argument ('par') + +if 2 == len (sys.argv) and 'help' == sys.argv[1]: + #parser.print_help() sale en inglés aunque la locale indique otra cosa + ogHelp ('ogUnhidePartition', 'ogUnhidePartition int_ndisk int_npartition', ['ogUnhidePartition 1 1']) + sys.exit (0) + +args = parser.parse_args() +ret = ogUnhidePartition (args.disk, args.par) + +if ret is not None: + if ret == True: sys.exit (0) + elif ret == False: sys.exit (1) + else: print (ret) From b193dadf31b1cfb87c5e13d74b991d74ded0b058 Mon Sep 17 00:00:00 2001 From: Natalia Serrano Date: Fri, 14 Feb 2025 14:17:44 +0100 Subject: [PATCH 153/167] refs #1514 add ogSetPartitionType --- client/lib/engine/bin/DiskLib.py | 45 ++++++---------------- client/shared/functions/ogSetPartitionType | 24 ++++++++++++ 2 files changed, 36 insertions(+), 33 deletions(-) create mode 100755 client/shared/functions/ogSetPartitionType diff --git a/client/lib/engine/bin/DiskLib.py b/client/lib/engine/bin/DiskLib.py index 8fe5b9e..26c0424 100755 --- a/client/lib/engine/bin/DiskLib.py +++ b/client/lib/engine/bin/DiskLib.py @@ -1226,43 +1226,22 @@ def ogSetPartitionSize(*args): #@return (nada) #@attention Requisitos: fdisk, sgdisk #*/ ## -def ogSetPartitionType(*args): - # Variables locales - DISK = None - PART = None - PTTYPE = None - TYPE = None +def ogSetPartitionType (disk, par, t): + DISK = ogDiskToDev (disk) + if not DISK: return None - # Si se solicita, mostrar ayuda. - if len(args) == 1 and args[0] == "help": - SystemLib.ogHelp('ogSetPartitionType', 'ogSetPartitionType int_ndisk int_npartition str_type', 'ogSetPartitionType 1 1 NTFS') - return + PART = ogDiskToDev (disk, par) + if not PART: return None - # Error si no se reciben 3 parámetros. - if len(args) != 3: - SystemLib.ogRaiseError(OG_ERR_FORMAT) - return + PTTYPE = ogGetPartitionTableType (disk) + if not PTTYPE: return None - # Sustituye nº de disco por su dispositivo. - DISK = ogDiskToDev(args[0]) - if DISK is None: - return - PART = ogDiskToDev(args[0], args[1]) - if PART is None: - return + ID = ogTypeToId (t, PTTYPE) + if not ID: + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_FORMAT, f'{t},{PTTYPE}') + return None - # Elección del tipo de partición. - PTTYPE = ogGetPartitionTableType(args[0]) - if PTTYPE is None: - return - TYPE = args[2] - ID = ogTypeToId(TYPE, PTTYPE) - if ID is None: - SystemLib.ogRaiseError(OG_ERR_FORMAT, f"{TYPE},{PTTYPE}") - return - - ogSetPartitionId(args[0], args[1], ID) - return + ogSetPartitionId (disk, par, ID) #/** diff --git a/client/shared/functions/ogSetPartitionType b/client/shared/functions/ogSetPartitionType new file mode 100755 index 0000000..875d0c4 --- /dev/null +++ b/client/shared/functions/ogSetPartitionType @@ -0,0 +1,24 @@ +#!/usr/bin/python3 + +import sys +import argparse +from SystemLib import ogHelp +from DiskLib import ogSetPartitionType + +parser = argparse.ArgumentParser (add_help=False) +parser.add_argument ('disk') +parser.add_argument ('par') +parser.add_argument ('type') + +if 2 == len (sys.argv) and 'help' == sys.argv[1]: + #parser.print_help() sale en inglés aunque la locale indique otra cosa + ogHelp ('ogSetPartitionType', 'ogSetPartitionType int_ndisk int_npartition str_type', ['ogSetPartitionType 1 1 NTFS']) + sys.exit (0) + +args = parser.parse_args() +ret = ogSetPartitionType (args.disk, args.par, args.type) + +if ret is not None: + if ret == True: sys.exit (0) + elif ret == False: sys.exit (1) + else: print (ret) From bc16613939ef76e706102264caa779749e170aba Mon Sep 17 00:00:00 2001 From: Natalia Serrano Date: Fri, 14 Feb 2025 14:22:50 +0100 Subject: [PATCH 154/167] refs #1515 add ogSetPartitionSize --- client/lib/engine/bin/DiskLib.py | 40 +++++++--------------- client/shared/functions/ogSetPartitionSize | 24 +++++++++++++ 2 files changed, 37 insertions(+), 27 deletions(-) create mode 100755 client/shared/functions/ogSetPartitionSize diff --git a/client/lib/engine/bin/DiskLib.py b/client/lib/engine/bin/DiskLib.py index 26c0424..d3bd286 100755 --- a/client/lib/engine/bin/DiskLib.py +++ b/client/lib/engine/bin/DiskLib.py @@ -1186,35 +1186,21 @@ def ogSetPartitionId (disk, par, id): #@note Requisitos: sfdisk, awk #@todo Compruebar que el tamaño sea numérico positivo y evitar que pueda solaparse con la siguiente partición. #*/ ## -def ogSetPartitionSize(*args): - # Variables locales - DISK = None - PART = None - SIZE = None +def ogSetPartitionSize (disk, par, size): + DISK = ogDiskToDev (disk) + if not DISK: return None - # Si se solicita, mostrar ayuda. - if len(args) == 1 and args[0] == "help": - SystemLib.ogHelp('ogSetPartitionSize', 'ogSetPartitionSize int_ndisk int_npartition int_size', 'ogSetPartitionSize 1 1 10000000') - return + PART = ogDiskToDev (disk, par) + if not PART: return None - # Error si no se reciben 3 parámetros. - if len(args) != 3: - SystemLib.ogRaiseError(OG_ERR_FORMAT) - return - - # Obtener el tamaño de la partición. - DISK = ogDiskToDev(args[0]) - if DISK is None: - return - PART = ogDiskToDev(args[0], args[1]) - if PART is None: - return - # Convertir tamaño en KB a sectores de 512 B. - SIZE = int(args[2]) * 2 - # Redefinir el tamaño de la partición. - subprocess.run(["sfdisk", "-f", "-uS", f"-N{args[1]}", DISK], input=f",{SIZE}", text=True, stderr=subprocess.DEVNULL) - subprocess.run(["partprobe", DISK], stderr=subprocess.DEVNULL) - return +# Convertir tamaño en KB a sectores de 512 B. + SIZE = 2 * int (size) +# Redefinir el tamaño de la partición. + p = subprocess.run (['sfdisk', '-f', '-uS', f'-N{par}', DISK], input=f',{SIZE}', text=True) + if p.returncode: + ogRaiseError ([], ogGlobals.OG_ERR_PARTITION, f'{disk},{par}') + return None + subprocess.run (['partprobe', DISK]) #/** diff --git a/client/shared/functions/ogSetPartitionSize b/client/shared/functions/ogSetPartitionSize new file mode 100755 index 0000000..84d17b9 --- /dev/null +++ b/client/shared/functions/ogSetPartitionSize @@ -0,0 +1,24 @@ +#!/usr/bin/python3 + +import sys +import argparse +from SystemLib import ogHelp +from DiskLib import ogSetPartitionSize + +parser = argparse.ArgumentParser (add_help=False) +parser.add_argument ('disk') +parser.add_argument ('par') +parser.add_argument ('size') + +if 2 == len (sys.argv) and 'help' == sys.argv[1]: + #parser.print_help() sale en inglés aunque la locale indique otra cosa + ogHelp ('ogSetPartitionSize', 'ogSetPartitionSize int_ndisk int_npartition int_size', ['ogSetPartitionSize 1 1 10000000']) + sys.exit (0) + +args = parser.parse_args() +ret = ogSetPartitionSize (args.disk, args.par, args.size) + +if ret is not None: + if ret == True: sys.exit (0) + elif ret == False: sys.exit (1) + else: print (ret) From 5e40504effa7ee4cf9bcab249744ce44a3d8541b Mon Sep 17 00:00:00 2001 From: Natalia Serrano Date: Mon, 17 Feb 2025 13:48:03 +0100 Subject: [PATCH 155/167] refs #1527 add ogCreateGptPartitions --- client/lib/engine/bin/CacheLib.py | 2 +- client/lib/engine/bin/DiskLib.py | 101 +++++++++--------- client/shared/functions/ogCreateGptPartitions | 23 ++++ 3 files changed, 75 insertions(+), 51 deletions(-) create mode 100755 client/shared/functions/ogCreateGptPartitions diff --git a/client/lib/engine/bin/CacheLib.py b/client/lib/engine/bin/CacheLib.py index 0d1a43b..e6f0659 100755 --- a/client/lib/engine/bin/CacheLib.py +++ b/client/lib/engine/bin/CacheLib.py @@ -227,7 +227,7 @@ def ogFormatCache(): # Crear estructura básica. mntdir = ogMountCache() j = '/'.join ([mntdir, ogGlobals.OGIMG]) ## os.path.join doesn't work: "If a segment […] is an absolute path, all previous segments are ignored" - print (f'cucu mntdir ({mntdir}) OGIMG ({ogGlobals.OGIMG}) j ({j})') + #print (f'cucu mntdir ({mntdir}) OGIMG ({ogGlobals.OGIMG}) j ({j})') os.makedirs (j, exist_ok=True) # Incluir kernel e Initrd del ogLive diff --git a/client/lib/engine/bin/DiskLib.py b/client/lib/engine/bin/DiskLib.py index d3bd286..21db54a 100755 --- a/client/lib/engine/bin/DiskLib.py +++ b/client/lib/engine/bin/DiskLib.py @@ -168,96 +168,97 @@ def ogCreatePartitions(*args): #@note Requisitos: sfdisk, parted, partprobe, awk #@todo Definir atributos (arranque, oculta) y tamaños en MB, GB, etc. #*/ ## -def ogCreateGptPartitions(*args): - # Variables locales - ND = DISK = PART = SECTORS = ALIGN = START = SIZE = TYPE = CACHEPART = CACHESIZE = DELOPTIONS = OPTIONS = None - - # Si se solicita, mostrar ayuda. - if len(args) == 1 and args[0] == "help": - SystemLib.ogHelp('ogCreateGptPartitions', 'ogCreateGptPartitions int_ndisk str_parttype:int_partsize ...', - 'ogCreateGptPartitions 1 NTFS:10000000 EXT3:5000000 LINUX-SWAP:1000000') - return - - # Error si no se reciben menos de 2 parámetros. - if len(args) < 2: - SystemLib.ogRaiseError(OG_ERR_FORMAT) - return - +def ogCreateGptPartitions (disk, parts): # Nº total de sectores, para evitar desbordamiento (evitar redondeo). - ND = args[0] - DISK = ogDiskToDev(ND) - if DISK is None: - return + ND = disk + DISK = ogDiskToDev (ND) + if not DISK: return None # Se calcula el ultimo sector del disco (total de sectores usables) - SECTORS = ogGetLastSector(ND) + SECTORS = ogGetLastSector (disk) # Se recalcula el nº de sectores del disco si existe partición de caché. + CACHESIZE = 0 CACHEPART = CacheLib.ogFindCache() - if ND == CACHEPART.split()[0]: - CACHESIZE = int(ogGetCacheSize()) * 2 - if CACHESIZE: - SECTORS -= CACHESIZE + if CACHEPART: + cache_disk, cache_part = CACHEPART.split() + if ND == cache_disk: + CACHESIZE = int (CacheLib.ogGetCacheSize()) * 2 + if CACHESIZE: + SECTORS -= CACHESIZE # Si el disco es GPT empieza en el sector 2048 por defecto, pero podria cambiarse - ALIGN = subprocess.getoutput(f"sgdisk -D {DISK} 2>/dev/null") + ALIGN = int (subprocess.run (['sgdisk', '-D', DISK], capture_output=True, text=True).stdout) START = ALIGN PART = 1 # Leer parámetros con definición de particionado. - args = args[1:] # Shift - while args: + DELOPTIONS = [] + OPTIONS = [] + for p in parts: # Si PART es la cache, nos la saltamos y seguimos con el siguiente numero para conservar los datos de la partición de caché. - if f"{ND} {PART}" == CACHEPART and CACHESIZE: + if f'{ND} {PART}' == CACHEPART and CACHESIZE: PART += 1 # Leer formato de cada parámetro - Tipo:Tamaño - TYPE = args[0].split(":")[0] - SIZE = int(args[0].split(":")[1]) + TYPE, SIZE = p.split (':') + try: + SIZE = int (SIZE) + except ValueError: + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_FORMAT, SIZE) + return None # Error si la partición es extendida (no válida en discos GPT). - if TYPE == "EXTENDED": - SystemLib.ogRaiseError(OG_ERR_PARTITION, "EXTENDED") - return + if 'EXTENDED' == TYPE: + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_PARTITION, 'EXTENDED') + return None # Comprobar si existe la particion actual, capturamos su tamaño para ver si cambio o no - PARTSIZE = ogGetPartitionSize(ND, PART) + PARTSIZE = ogGetPartitionSize (ND, PART) # En sgdisk no se pueden redimensionar las particiones, es necesario borrarlas y volver a crealas if PARTSIZE: - DELOPTIONS += f" -d{PART}" + DELOPTIONS.append (f'-d{PART}') # Creamos la particion # Obtener identificador de tipo de partición válido. - ID = ogTypeToId(TYPE, "GPT") - if TYPE != "CACHE" and ID: - OPTIONS += f" -n{PART}:{START}:+{SIZE} -t{PART}:{ID} " + ID = ogTypeToId (TYPE, 'GPT') + if 'CACHE' == TYPE or not ID: + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_PARTITION, TYPE) + return None + # Comprobar tamaño numérico y convertir en sectores de 512 B. + SIZE = 2 * SIZE + # SIZE debe ser múltiplo de ALIGN, si no gdisk lo mueve automáticamente. + DIV = SIZE // ALIGN + SIZE = DIV * ALIGN + # En el caso de que la partición sea EMPTY no se crea nada + if 'EMPTY' != TYPE: + OPTIONS += [f'-n{PART}:{START}:+{SIZE}', f'-t{PART}:{ID}'] START += SIZE # Error si se supera el nº total de sectores. if START > SECTORS: - SystemLib.ogRaiseError(OG_ERR_FORMAT, f"{START//2} > {SECTORS//2}") - return + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_FORMAT, f'{START//2} > {SECTORS//2}') + return None PART += 1 - args = args[1:] # Desmontar los sistemas de archivos del disco antes de realizar las operaciones. - ogUnmountAll(ND) + FileSystemLib.ogUnmountAll (ND) if CACHESIZE: CacheLib.ogUnmountCache() # Si la tabla de particiones no es valida, volver a generarla. - ogCreatePartitionTable(ND) + ogCreatePartitionTable (ND) # Definir particiones y notificar al kernel. # Borramos primero las particiones y luego creamos las nuevas - subprocess.run(["sgdisk"] + DELOPTIONS.split() + OPTIONS.split() + [DISK], stderr=subprocess.DEVNULL) - subprocess.run(["partprobe", DISK], stderr=subprocess.DEVNULL) + subprocess.run (['sgdisk'] + DELOPTIONS + OPTIONS + [DISK]) + subprocess.run (['partprobe', DISK]) - if CACHESIZE: - CacheLib.ogMountCache() - return 0 + if CACHESIZE: CacheLib.ogMountCache() + + return True #/** @@ -283,14 +284,14 @@ def ogCreatePartitionTable (disk, createptt=None): if createptt == pttype: if 'GPT' == pttype: try: - result = subprocess.run (['sgdisk', '-p', DISK]) + result = subprocess.run (['sgdisk', '-p', DISK], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) if result.returncode: CREATE = 'GPT' except subprocess.CalledProcessError: CREATE = 'GPT' elif 'MSDOS' == pttype: try: - result = subprocess.run (['parted', '-s', DISK, 'print']) + result = subprocess.run (['parted', '-s', DISK, 'print'], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) if result.returncode: CREATE = 'MSDOS' except subprocess.CalledProcessError: diff --git a/client/shared/functions/ogCreateGptPartitions b/client/shared/functions/ogCreateGptPartitions new file mode 100755 index 0000000..0259325 --- /dev/null +++ b/client/shared/functions/ogCreateGptPartitions @@ -0,0 +1,23 @@ +#!/usr/bin/python3 + +import sys +import argparse +from SystemLib import ogHelp +from DiskLib import ogCreateGptPartitions + +if 2 == len (sys.argv) and 'help' == sys.argv[1]: + #parser.print_help() sale en inglés aunque la locale indique otra cosa + ogHelp ('ogCreateGptPartitions', 'ogCreateGptPartitions int_ndisk str_parttype:int_partsize ...', ['ogCreateGptPartitions 1 NTFS:10000000 EXT3:5000000 LINUX-SWAP:1000000']) + sys.exit (0) + +parser = argparse.ArgumentParser (add_help=False) +parser.add_argument ('disk') +parser.add_argument ('parts', nargs='+') +args = parser.parse_args() + +ret = ogCreateGptPartitions (args.disk, args.parts) + +if ret is not None: + if ret == True: sys.exit (0) + elif ret == False: sys.exit (1) + else: print (ret) From caf1f4416159a46c4abff6f6f657c504fbc7b8f8 Mon Sep 17 00:00:00 2001 From: Natalia Serrano Date: Tue, 18 Feb 2025 14:17:39 +0100 Subject: [PATCH 156/167] refs #1528 add ogCreatePartitions --- client/lib/engine/bin/DiskLib.py | 173 ++++++++++++--------- client/shared/functions/ogCreatePartitions | 23 +++ 2 files changed, 124 insertions(+), 72 deletions(-) create mode 100755 client/shared/functions/ogCreatePartitions diff --git a/client/lib/engine/bin/DiskLib.py b/client/lib/engine/bin/DiskLib.py index 21db54a..e6bd26d 100755 --- a/client/lib/engine/bin/DiskLib.py +++ b/client/lib/engine/bin/DiskLib.py @@ -54,49 +54,42 @@ def parted(*args): #@note Requisitos: sfdisk, parted, partprobe, awk #@todo Definir atributos (arranque, oculta) y tamaños en MB, GB, etc. #*/ ## -def ogCreatePartitions(*args): - # Variables locales - ND = DISK = PTTYPE = PART = SECTORS = START = SIZE = TYPE = CACHEPART = None - IODISCO = IOSIZE = CACHESIZE = EXTSTART = EXTSIZE = NVME_PREFIX = tmpsfdisk = None +def ogCreatePartitions (disk, parts): + ND = disk + DISK = ogDiskToDev (ND) + if not DISK: return None - # Si se solicita, mostrar ayuda. - if len(args) == 1 and args[0] == "help": - SystemLib.ogHelp('ogCreatePartitions', 'ogCreatePartitions int_ndisk str_parttype:int_partsize ...', - 'ogCreatePartitions 1 NTFS:10000000 EXT3:5000000 LINUX-SWAP:1000000') - return + PTTYPE = ogGetPartitionTableType (disk) + if not PTTYPE: PTTYPE = 'MSDOS' # Por defecto para discos vacíos. - # Error si no se reciben al menos 2 parámetros. - if len(args) < 2: - SystemLib.ogRaiseError(OG_ERR_FORMAT) - return + if 'GPT' == PTTYPE: + return ogCreateGptPartitions (disk, parts) + elif 'MSDOS' != PTTYPE: + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_PARTITION, PTTYPE) + return None - # Nº total de sectores, para evitar desbordamiento (evitar redondeo). - ND = args[0] - DISK = ogDiskToDev(ND) - if DISK is None: - return + SECTORS = ogGetLastSector (disk) - PTTYPE = ogGetPartitionTableType(ND) or "MSDOS" # Por defecto para discos vacíos. - - if PTTYPE == "GPT": - ogCreateGptPartitions(*args) - return - elif PTTYPE != "MSDOS": - SystemLib.ogRaiseError(OG_ERR_PARTITION, PTTYPE) - return - - SECTORS = ogGetLastSector(ND) - - # Se recalcula el nº de sectores del disco 1, si existe partición de caché. +# Se recalcula el nº de sectores del disco 1, si existe partición de caché. + CACHESIZE = 0 CACHEPART = CacheLib.ogFindCache() - if CACHEPART and ND == CACHEPART.split()[0]: - CACHESIZE = int(CacheLib.ogGetCacheSize()) * 2 + if CACHEPART: + cache_disk, cache_part = CACHEPART.split() + if ND == cache_disk: + CACHESIZE = int (CacheLib.ogGetCacheSize()) * 2 - # Sector de inicio (la partición 1 empieza en el sector 63). - IODISCO = ogDiskToDev(ND) - IOSIZE = subprocess.getoutput(f"fdisk -l {IODISCO} | awk '/I\\/O/ {{print $4}}'") +# Sector de inicio (la partición 1 empieza en el sector 63). + IODISCO = ogDiskToDev (disk) + IOSIZE = 0 + fdisk_out = subprocess.run (['fdisk', '-l', IODISCO], capture_output=True, text=True).stdout + for l in fdisk_out.splitlines(): + if 'I/O' not in l: continue + items = l.split() + if len(items) < 4: continue + IOSIZE = items[3] + break - if IOSIZE == "4096": + if '4096' == IOSIZE: START = 4096 SECTORS -= 8192 if CACHESIZE: @@ -108,48 +101,84 @@ def ogCreatePartitions(*args): PART = 1 - # Fichero temporal de entrada para "sfdisk" - tmpsfdisk = f"/tmp/sfdisk{os.getpid()}" - try: - with open(tmpsfdisk, 'w') as f: - f.write("unit: sectors\n\n") +# Fichero temporal de entrada para "sfdisk" + sfdisk_input = 'unit: sectors\n\n' - NVME_PREFIX = "p" if "nvme" in DISK else "" + NVME_PREFIX = 'p' if 'nvme' in DISK else '' - # Generar fichero de entrada para "sfdisk" con las particiones. - args = args[1:] # Shift - while args: - # Conservar los datos de la partición de caché. - if f"{ND} {PART}" == CACHEPART and CACHESIZE: - with open(tmpsfdisk, 'a') as f: - f.write(f"{DISK}{NVME_PREFIX}{PART} : start={SECTORS + 1}, size={CACHESIZE}, Id=ca\n") - PART += 1 - - # Leer formato de cada parámetro - Tipo:Tamaño - TYPE = args[0].split(":")[0] - SIZE = int(args[0].split(":")[1]) - - # Obtener identificador de tipo de partición válido. - ID = ogTypeToId(TYPE, "MSDOS") - with open(tmpsfdisk, 'a') as f: - f.write(f"{DISK}{NVME_PREFIX}{PART} : start={START}, size={SIZE}, Id={ID}\n") - START += SIZE - SECTORS -= SIZE +# Generar fichero de entrada para "sfdisk" con las particiones. + for p in parts: + # Conservar los datos de la partición de caché. + if f'{ND} {PART}' == CACHEPART and CACHESIZE: + sfdisk_input += f'{DISK}{NVME_PREFIX}{PART} : start={SECTORS+1}, size={CACHESIZE}, Id=ca\n' PART += 1 - args = args[1:] - # Ejecutar "sfdisk" con el fichero temporal. - subprocess.run(["sfdisk", DISK], input=open(tmpsfdisk, 'r').read(), text=True) - subprocess.run(["partprobe", DISK]) + # Leer formato de cada parámetro - Tipo:Tamaño + TYPE, SIZE = p.split (':') + try: + SIZE = int (SIZE) + except ValueError: + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_FORMAT, SIZE) + return None - finally: - # Eliminar fichero temporal. - if os.path.exists(tmpsfdisk): - os.remove(tmpsfdisk) + # Obtener identificador de tipo de partición válido. + ID = ogTypeToId (TYPE, 'MSDOS') + if 'CACHE' == TYPE or not ID: + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_PARTITION, TYPE) + return None + # Comprobar tamaño numérico y convertir en sectores de 512 B. + SIZE *= 2 + # Comprobar si la partición es extendida. + EXTSTART = EXTSIZE = 0 + if 5 == ID: + if PART > 4: + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_FORMAT, '') + return None + # El inicio de la primera partición logica es el de la extendida más 4x512 + EXTSTART = START+2048 + EXTSIZE = SIZE-2048 + # Incluir particiones lógicas dentro de la partición extendida. + if 5 == PART: + if not EXTSTART: + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_FORMAT, '') + return None + START = EXTSTART + SECTORS = EXTSTART+EXTSIZE + # Generar datos para la partición. + sfdisk_input += f'{DISK}{NVME_PREFIX}{PART} : start={START}, size={SIZE}, Id={ID}\n' + # Error si se supera el nº total de sectores. + START += SIZE + if '4096' == IOSIZE and PART > 4: + START += 2048 + if START > SECTORS: + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_FORMAT, f'{START//2} > {SECTORS//2}') + return None + PART += 1 - if CACHESIZE: - CacheLib.ogMountCache() - return 0 +# Si no se indican las 4 particiones primarias, definirlas como vacías, conservando la partición de caché. + while PART <= 4: + if f'{ND} {PART}' == CACHEPART and CACHESIZE: + sfdisk_input += f'{DISK}{NVME_PREFIX}{PART} : start={SECTORS+1}, size={CACHESIZE}, Id=ca\n' + else: + sfdisk_input += f'{DISK}{NVME_PREFIX}{PART} : start=0, size=0, Id=0\n' + PART += 1 +# Si se define partición extendida sin lógicas, crear particion 5 vacía. + if 5 == PART and EXTSTART: + sfdisk_input += f'{DISK}5 : start={EXTSTART}, SIZE={EXTSIZE}, Id=0\n' + +# Desmontar los sistemas de archivos del disco antes de realizar las operaciones. + FileSystemLib.ogUnmountAll (ND) + if CACHESIZE: CacheLib.ogUnmountCache() + +# Si la tabla de particiones no es valida, volver a generarla. + ogCreatePartitionTable (ND) +# Definir particiones y notificar al kernel. + print (f'about to run sfdisk: ({sfdisk_input})') + p = subprocess.run (['sfdisk', DISK], input=sfdisk_input, capture_output=True, text=True) + print (f'rc ({p.returncode}) stdout ({p.stdout}) stderr ({p.stderr})') + subprocess.run (['partprobe', DISK]) + if CACHESIZE: CacheLib.ogMountCache() + return True #/** diff --git a/client/shared/functions/ogCreatePartitions b/client/shared/functions/ogCreatePartitions new file mode 100755 index 0000000..8269a53 --- /dev/null +++ b/client/shared/functions/ogCreatePartitions @@ -0,0 +1,23 @@ +#!/usr/bin/python3 + +import sys +import argparse +from SystemLib import ogHelp +from DiskLib import ogCreatePartitions + +if 2 == len (sys.argv) and 'help' == sys.argv[1]: + #parser.print_help() sale en inglés aunque la locale indique otra cosa + ogHelp ('ogCreatePartitions', 'ogCreatePartitions int_ndisk str_parttype:int_partsize ...', ['ogCreatePartitions 1 NTFS:10000000 EXT3:5000000 LINUX-SWAP:1000000']) + sys.exit (0) + +parser = argparse.ArgumentParser (add_help=False) +parser.add_argument ('disk') +parser.add_argument ('parts', nargs='+') +args = parser.parse_args() + +ret = ogCreatePartitions (args.disk, args.parts) + +if ret is not None: + if ret == True: sys.exit (0) + elif ret == False: sys.exit (1) + else: print (ret) From c1dc47f1604589888c47837c3bf7b7bb173dab80 Mon Sep 17 00:00:00 2001 From: Natalia Serrano Date: Thu, 20 Feb 2025 11:36:09 +0100 Subject: [PATCH 157/167] refs #1588 fix usage of ogFindCache() --- client/lib/engine/bin/ImageLib.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/client/lib/engine/bin/ImageLib.py b/client/lib/engine/bin/ImageLib.py index 5c5b200..0d3b5d1 100644 --- a/client/lib/engine/bin/ImageLib.py +++ b/client/lib/engine/bin/ImageLib.py @@ -336,7 +336,11 @@ def ogGetSizeParameters (disk, par, repo, imgname, imgtype=None): #Comprobar espacio libre en el contenedor. sizefree = None if 'CACHE' == repo: - cache_disk, cache_par = CacheLib.ogFindCache().split() + CACHEPART = CacheLib.ogFindCache() + if not CACHEPART: + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTCACHE, '') + return None + cache_disk, cache_par = CACHEPART.split() sizefree = FileSystemLib.ogGetFreeSize (cache_disk, cache_par) if 'REPO' == repo: df_out = subprocess.run (['df', '-k'], capture_output=True, text=True).stdout From acf2c1dc4901581007d8f6773830eec543c6da37 Mon Sep 17 00:00:00 2001 From: Natalia Serrano Date: Thu, 20 Feb 2025 13:57:57 +0100 Subject: [PATCH 158/167] refs #1594 indent some comments --- client/lib/engine/bin/DiskLib.py | 40 ++++++++++++++++---------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/client/lib/engine/bin/DiskLib.py b/client/lib/engine/bin/DiskLib.py index e6bd26d..88e12da 100755 --- a/client/lib/engine/bin/DiskLib.py +++ b/client/lib/engine/bin/DiskLib.py @@ -70,7 +70,7 @@ def ogCreatePartitions (disk, parts): SECTORS = ogGetLastSector (disk) -# Se recalcula el nº de sectores del disco 1, si existe partición de caché. + # Se recalcula el nº de sectores del disco si existe partición de caché. CACHESIZE = 0 CACHEPART = CacheLib.ogFindCache() if CACHEPART: @@ -78,7 +78,7 @@ def ogCreatePartitions (disk, parts): if ND == cache_disk: CACHESIZE = int (CacheLib.ogGetCacheSize()) * 2 -# Sector de inicio (la partición 1 empieza en el sector 63). + # Sector de inicio (la partición 1 empieza en el sector 63). IODISCO = ogDiskToDev (disk) IOSIZE = 0 fdisk_out = subprocess.run (['fdisk', '-l', IODISCO], capture_output=True, text=True).stdout @@ -101,19 +101,19 @@ def ogCreatePartitions (disk, parts): PART = 1 -# Fichero temporal de entrada para "sfdisk" + # Fichero temporal de entrada para "sfdisk" sfdisk_input = 'unit: sectors\n\n' NVME_PREFIX = 'p' if 'nvme' in DISK else '' -# Generar fichero de entrada para "sfdisk" con las particiones. + # Generar fichero de entrada para "sfdisk" con las particiones. for p in parts: - # Conservar los datos de la partición de caché. + # Conservar los datos de la partición de caché. if f'{ND} {PART}' == CACHEPART and CACHESIZE: sfdisk_input += f'{DISK}{NVME_PREFIX}{PART} : start={SECTORS+1}, size={CACHESIZE}, Id=ca\n' PART += 1 - # Leer formato de cada parámetro - Tipo:Tamaño + # Leer formato de cada parámetro - Tipo:Tamaño TYPE, SIZE = p.split (':') try: SIZE = int (SIZE) @@ -121,23 +121,23 @@ def ogCreatePartitions (disk, parts): SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_FORMAT, SIZE) return None - # Obtener identificador de tipo de partición válido. + # Obtener identificador de tipo de partición válido. ID = ogTypeToId (TYPE, 'MSDOS') if 'CACHE' == TYPE or not ID: SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_PARTITION, TYPE) return None - # Comprobar tamaño numérico y convertir en sectores de 512 B. + # Comprobar tamaño numérico y convertir en sectores de 512 B. SIZE *= 2 - # Comprobar si la partición es extendida. + # Comprobar si la partición es extendida. EXTSTART = EXTSIZE = 0 if 5 == ID: if PART > 4: SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_FORMAT, '') return None - # El inicio de la primera partición logica es el de la extendida más 4x512 + # El inicio de la primera partición logica es el de la extendida más 4x512 EXTSTART = START+2048 EXTSIZE = SIZE-2048 - # Incluir particiones lógicas dentro de la partición extendida. + # Incluir particiones lógicas dentro de la partición extendida. if 5 == PART: if not EXTSTART: SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_FORMAT, '') @@ -148,6 +148,8 @@ def ogCreatePartitions (disk, parts): sfdisk_input += f'{DISK}{NVME_PREFIX}{PART} : start={START}, size={SIZE}, Id={ID}\n' # Error si se supera el nº total de sectores. START += SIZE + + # Error si se supera el nº total de sectores. if '4096' == IOSIZE and PART > 4: START += 2048 if START > SECTORS: @@ -155,24 +157,25 @@ def ogCreatePartitions (disk, parts): return None PART += 1 -# Si no se indican las 4 particiones primarias, definirlas como vacías, conservando la partición de caché. + # Si no se indican las 4 particiones primarias, definirlas como vacías, conservando la partición de caché. while PART <= 4: if f'{ND} {PART}' == CACHEPART and CACHESIZE: sfdisk_input += f'{DISK}{NVME_PREFIX}{PART} : start={SECTORS+1}, size={CACHESIZE}, Id=ca\n' else: sfdisk_input += f'{DISK}{NVME_PREFIX}{PART} : start=0, size=0, Id=0\n' PART += 1 -# Si se define partición extendida sin lógicas, crear particion 5 vacía. + # Si se define partición extendida sin lógicas, crear particion 5 vacía. if 5 == PART and EXTSTART: sfdisk_input += f'{DISK}5 : start={EXTSTART}, SIZE={EXTSIZE}, Id=0\n' -# Desmontar los sistemas de archivos del disco antes de realizar las operaciones. + # Desmontar los sistemas de archivos del disco antes de realizar las operaciones. FileSystemLib.ogUnmountAll (ND) if CACHESIZE: CacheLib.ogUnmountCache() -# Si la tabla de particiones no es valida, volver a generarla. + # Si la tabla de particiones no es valida, volver a generarla. ogCreatePartitionTable (ND) -# Definir particiones y notificar al kernel. + + # Definir particiones y notificar al kernel. print (f'about to run sfdisk: ({sfdisk_input})') p = subprocess.run (['sfdisk', DISK], input=sfdisk_input, capture_output=True, text=True) print (f'rc ({p.returncode}) stdout ({p.stdout}) stderr ({p.stderr})') @@ -198,7 +201,6 @@ def ogCreatePartitions (disk, parts): #@todo Definir atributos (arranque, oculta) y tamaños en MB, GB, etc. #*/ ## def ogCreateGptPartitions (disk, parts): - # Nº total de sectores, para evitar desbordamiento (evitar redondeo). ND = disk DISK = ogDiskToDev (ND) if not DISK: return None @@ -225,7 +227,7 @@ def ogCreateGptPartitions (disk, parts): DELOPTIONS = [] OPTIONS = [] for p in parts: - # Si PART es la cache, nos la saltamos y seguimos con el siguiente numero para conservar los datos de la partición de caché. + # Conservar los datos de la partición de caché. if f'{ND} {PART}' == CACHEPART and CACHESIZE: PART += 1 @@ -284,9 +286,7 @@ def ogCreateGptPartitions (disk, parts): # Borramos primero las particiones y luego creamos las nuevas subprocess.run (['sgdisk'] + DELOPTIONS + OPTIONS + [DISK]) subprocess.run (['partprobe', DISK]) - if CACHESIZE: CacheLib.ogMountCache() - return True From e6937a211a993fd1612e6505fa4de89c4f95f937 Mon Sep 17 00:00:00 2001 From: Natalia Serrano Date: Thu, 20 Feb 2025 14:00:41 +0100 Subject: [PATCH 159/167] refs #1594 simplify a couple of lines --- client/lib/engine/bin/DiskLib.py | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/client/lib/engine/bin/DiskLib.py b/client/lib/engine/bin/DiskLib.py index 88e12da..a87fbc3 100755 --- a/client/lib/engine/bin/DiskLib.py +++ b/client/lib/engine/bin/DiskLib.py @@ -176,9 +176,7 @@ def ogCreatePartitions (disk, parts): ogCreatePartitionTable (ND) # Definir particiones y notificar al kernel. - print (f'about to run sfdisk: ({sfdisk_input})') p = subprocess.run (['sfdisk', DISK], input=sfdisk_input, capture_output=True, text=True) - print (f'rc ({p.returncode}) stdout ({p.stdout}) stderr ({p.stderr})') subprocess.run (['partprobe', DISK]) if CACHESIZE: CacheLib.ogMountCache() return True @@ -257,10 +255,11 @@ def ogCreateGptPartitions (disk, parts): SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_PARTITION, TYPE) return None # Comprobar tamaño numérico y convertir en sectores de 512 B. - SIZE = 2 * SIZE + SIZE *= 2 # SIZE debe ser múltiplo de ALIGN, si no gdisk lo mueve automáticamente. - DIV = SIZE // ALIGN - SIZE = DIV * ALIGN + SIZE = (SIZE // ALIGN) * ALIGN + + # Generar datos para la partición. # En el caso de que la partición sea EMPTY no se crea nada if 'EMPTY' != TYPE: OPTIONS += [f'-n{PART}:{START}:+{SIZE}', f'-t{PART}:{ID}'] @@ -276,14 +275,12 @@ def ogCreateGptPartitions (disk, parts): # Desmontar los sistemas de archivos del disco antes de realizar las operaciones. FileSystemLib.ogUnmountAll (ND) - if CACHESIZE: - CacheLib.ogUnmountCache() + if CACHESIZE: CacheLib.ogUnmountCache() # Si la tabla de particiones no es valida, volver a generarla. ogCreatePartitionTable (ND) # Definir particiones y notificar al kernel. - # Borramos primero las particiones y luego creamos las nuevas subprocess.run (['sgdisk'] + DELOPTIONS + OPTIONS + [DISK]) subprocess.run (['partprobe', DISK]) if CACHESIZE: CacheLib.ogMountCache() From ad404f9982e1655b63c3b18e124b3e68a6f12c77 Mon Sep 17 00:00:00 2001 From: Natalia Serrano Date: Thu, 20 Feb 2025 14:02:10 +0100 Subject: [PATCH 160/167] refs #1594 ignore empty slots --- client/lib/engine/bin/DiskLib.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/client/lib/engine/bin/DiskLib.py b/client/lib/engine/bin/DiskLib.py index a87fbc3..6969d47 100755 --- a/client/lib/engine/bin/DiskLib.py +++ b/client/lib/engine/bin/DiskLib.py @@ -144,9 +144,12 @@ def ogCreatePartitions (disk, parts): return None START = EXTSTART SECTORS = EXTSTART+EXTSIZE - # Generar datos para la partición. - sfdisk_input += f'{DISK}{NVME_PREFIX}{PART} : start={START}, size={SIZE}, Id={ID}\n' - # Error si se supera el nº total de sectores. + + # Generar datos para la partición. + # En el caso de que la partición sea EMPTY no se crea nada + if 'EMPTY' != TYPE: + sfdisk_input += f'{DISK}{NVME_PREFIX}{PART} : start={START}, size={SIZE}, Id={ID}\n' + START += SIZE # Error si se supera el nº total de sectores. From 45cfe252222e8f750516af91fdd5c0d496954023 Mon Sep 17 00:00:00 2001 From: Natalia Serrano Date: Thu, 20 Feb 2025 14:02:37 +0100 Subject: [PATCH 161/167] refs #1594 fix a bug --- client/lib/engine/bin/DiskLib.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/lib/engine/bin/DiskLib.py b/client/lib/engine/bin/DiskLib.py index 6969d47..350a482 100755 --- a/client/lib/engine/bin/DiskLib.py +++ b/client/lib/engine/bin/DiskLib.py @@ -842,7 +842,7 @@ def ogGetPartitionSize (disk, par): sz = subprocess.run (['partx', '-gbo', 'SIZE', PART], capture_output=True, text=True).stdout.strip() if sz: return int (int (sz) / 1024) - sz = subprocess.run (['lvs', '--noheadings', '-o', 'lv_size', '--units', 'k', PART], capture_output=True, text=True).stdout.strip + sz = subprocess.run (['lvs', '--noheadings', '-o', 'lv_size', '--units', 'k', PART], capture_output=True, text=True).stdout.strip() if sz: return int (sz) return FileSystemLib.ogGetFsSize (disk, par) From 000ea29e7072828908b46e6b1ec2966ca3cab459 Mon Sep 17 00:00:00 2001 From: Natalia Serrano Date: Thu, 20 Feb 2025 14:03:12 +0100 Subject: [PATCH 162/167] refs #1594 fix two bugs --- client/lib/engine/bin/CacheLib.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/client/lib/engine/bin/CacheLib.py b/client/lib/engine/bin/CacheLib.py index e6f0659..0a9f8c7 100755 --- a/client/lib/engine/bin/CacheLib.py +++ b/client/lib/engine/bin/CacheLib.py @@ -333,15 +333,16 @@ def ogMountCache(): #@warning Salidas de errores no determinada #*/ ## def ogUnmountCache(): - cachepart = ogFindCache().split() + cachepart = ogFindCache() if cachepart is None: SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_PARTITION, ogGlobals.lang.MSG_NOCACHE) return + cachepart = cachepart.split() if not FileSystemLib.ogIsMounted (cachepart[0], cachepart[1]): return True FileSystemLib.ogUnmountFs (cachepart[0], cachepart[1]) # Eliminar el enlace simbólico de /mnt/ParticiónCache. dev = DiskLib.ogDiskToDev (cachepart[0], cachepart[1]) dev = dev.replace ('dev', 'mnt') - os.remove (dev) + if os.path.exists (dev): os.remove (dev) From 2a0737f2c5c82495689b8c1700ba220ff582cf87 Mon Sep 17 00:00:00 2001 From: Natalia Serrano Date: Thu, 20 Feb 2025 14:17:12 +0100 Subject: [PATCH 163/167] refs #1594 more comments and whitespace shuffling --- client/lib/engine/bin/DiskLib.py | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/client/lib/engine/bin/DiskLib.py b/client/lib/engine/bin/DiskLib.py index 350a482..a953159 100755 --- a/client/lib/engine/bin/DiskLib.py +++ b/client/lib/engine/bin/DiskLib.py @@ -68,6 +68,7 @@ def ogCreatePartitions (disk, parts): SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_PARTITION, PTTYPE) return None + # Se calcula el ultimo sector del disco (total de sectores usables) SECTORS = ogGetLastSector (disk) # Se recalcula el nº de sectores del disco si existe partición de caché. @@ -77,7 +78,6 @@ def ogCreatePartitions (disk, parts): cache_disk, cache_part = CACHEPART.split() if ND == cache_disk: CACHESIZE = int (CacheLib.ogGetCacheSize()) * 2 - # Sector de inicio (la partición 1 empieza en el sector 63). IODISCO = ogDiskToDev (disk) IOSIZE = 0 @@ -101,12 +101,8 @@ def ogCreatePartitions (disk, parts): PART = 1 - # Fichero temporal de entrada para "sfdisk" sfdisk_input = 'unit: sectors\n\n' - NVME_PREFIX = 'p' if 'nvme' in DISK else '' - - # Generar fichero de entrada para "sfdisk" con las particiones. for p in parts: # Conservar los datos de la partición de caché. if f'{ND} {PART}' == CACHEPART and CACHESIZE: @@ -134,7 +130,7 @@ def ogCreatePartitions (disk, parts): if PART > 4: SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_FORMAT, '') return None - # El inicio de la primera partición logica es el de la extendida más 4x512 + # El inicio de la primera partición logica es el de la extendida más 4x512 EXTSTART = START+2048 EXTSIZE = SIZE-2048 # Incluir particiones lógicas dentro de la partición extendida. From 3a1435b587f603408496f7754c94cca847f39c9a Mon Sep 17 00:00:00 2001 From: Natalia Serrano Date: Thu, 20 Feb 2025 14:18:17 +0100 Subject: [PATCH 164/167] refs #1594 create GPT parttable in ogCreateGptPartitions --- client/lib/engine/bin/DiskLib.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/lib/engine/bin/DiskLib.py b/client/lib/engine/bin/DiskLib.py index a953159..f39c8f4 100755 --- a/client/lib/engine/bin/DiskLib.py +++ b/client/lib/engine/bin/DiskLib.py @@ -277,7 +277,7 @@ def ogCreateGptPartitions (disk, parts): if CACHESIZE: CacheLib.ogUnmountCache() # Si la tabla de particiones no es valida, volver a generarla. - ogCreatePartitionTable (ND) + ogCreatePartitionTable (ND, 'GPT') # Definir particiones y notificar al kernel. subprocess.run (['sgdisk'] + DELOPTIONS + OPTIONS + [DISK]) From 4b4d004743049335dd7dec3349935a4bd4bc3987 Mon Sep 17 00:00:00 2001 From: Natalia Serrano Date: Thu, 20 Feb 2025 14:19:20 +0100 Subject: [PATCH 165/167] refs #1594 remove unused variable --- client/lib/engine/bin/DiskLib.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/lib/engine/bin/DiskLib.py b/client/lib/engine/bin/DiskLib.py index f39c8f4..ece1339 100755 --- a/client/lib/engine/bin/DiskLib.py +++ b/client/lib/engine/bin/DiskLib.py @@ -175,7 +175,7 @@ def ogCreatePartitions (disk, parts): ogCreatePartitionTable (ND) # Definir particiones y notificar al kernel. - p = subprocess.run (['sfdisk', DISK], input=sfdisk_input, capture_output=True, text=True) + subprocess.run (['sfdisk', DISK], input=sfdisk_input, capture_output=True, text=True) subprocess.run (['partprobe', DISK]) if CACHESIZE: CacheLib.ogMountCache() return True From 7c9fbc014f7896a3abf058535fcb565b3fd91ede Mon Sep 17 00:00:00 2001 From: Natalia Serrano Date: Fri, 21 Feb 2025 09:55:31 +0100 Subject: [PATCH 166/167] refs #1596 add initCache.py --- client/lib/engine/bin/CacheLib.py | 9 +- client/shared/scripts/initCache.py | 151 +++++++++++++++++------------ 2 files changed, 95 insertions(+), 65 deletions(-) diff --git a/client/lib/engine/bin/CacheLib.py b/client/lib/engine/bin/CacheLib.py index 0a9f8c7..180684f 100755 --- a/client/lib/engine/bin/CacheLib.py +++ b/client/lib/engine/bin/CacheLib.py @@ -64,8 +64,9 @@ def ogCreateCache (ndsk=1, part=4, sizecache=0): if ENDPREVPART: break i += 1 if not ENDPREVPART: - SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_FORMAT, ndsk) - return None + ENDPREVPART=0 + #SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_FORMAT, ndsk) + #return None # Error si tamaño no está entre límites permitidos o si se solapa con la partición anterior. MINSIZE = 25000 MAXSIZE = END @@ -245,7 +246,7 @@ def ogGetCacheSize(): cachepart = ogFindCache() if cachepart is None: SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_PARTITION, ogGlobals.lang.MSG_NOCACHE) - return + return None disk, par = cachepart.split() return DiskLib.ogGetPartitionSize (disk, par) @@ -321,7 +322,7 @@ def ogMountCache(): m = FileSystemLib.ogMountFs (c[0], c[1]) if not m: SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_PARTITION, ogGlobals.lang.MSG_NOCACHE) - #return + return None return m diff --git a/client/shared/scripts/initCache.py b/client/shared/scripts/initCache.py index e60f784..9fb4ed8 100755 --- a/client/shared/scripts/initCache.py +++ b/client/shared/scripts/initCache.py @@ -1,94 +1,123 @@ +#!/usr/bin/python3 +# Scirpt de iniciación de la caché local de disco. +# Nota: se usa como base para el programa de configuración de equipos de OpenGnsys Admin). +# Formato: initCache [int_ndisk [int_npart]] {-1 | 0 | int_size} [NOMOUNT] + import sys import time import subprocess + +import ogGlobals import SystemLib import FileSystemLib import CacheLib import DiskLib -#!/usr/bin/env python3 - -def main(): +def main (NDISK, NPART, SIZE, MOUNT): TIME1 = time.time() - PROG = sys.argv[0] - EXECFORMAT = f"{PROG} [int_ndisk [int_npart]] {{-1 | 0 | int_size}} [NOMOUNT]" - args = sys.argv[1:] - if args and args[-1].upper() == "NOMOUNT": - MOUNT = 0 - args = args[:-1] - else: - MOUNT = 1 - - PARAMS = len(args) - if PARAMS == 1: - NDISK = 1 - NPART = 4 - SIZE = int(args[0]) - elif PARAMS == 2: - NDISK = int(args[0]) - NPART = 4 - SIZE = int(args[1]) - elif PARAMS == 3: - NDISK = int(args[0]) - NPART = int(args[1]) - SIZE = int(args[2]) - else: - SystemLib.ogRaiseError("OG_ERR_FORMAT", f"{EXECFORMAT}") - - if NDISK < 1 or NPART < 1: - SystemLib.ogRaiseError("OG_ERR_FORMAT", f"{EXECFORMAT}") - - if SIZE < -1: - SystemLib.ogRaiseError("OG_ERR_FORMAT", f"{EXECFORMAT}") - - if SIZE == 0: +# Si tamaño=0, no hacer nada. + if 0 == SIZE: print("No modificar la caché local.") - return - - if SIZE == -1: + return True + +# Si tamaño=-1, borrar caché. + if -1 == SIZE: print("[10] Trabajar sin caché local.") CacheLib.ogUnmountCache() CacheLib.ogDeleteCache() else: + # Si la caché actual está definida en otro disco y partición, se elimina. current_cache = CacheLib.ogFindCache() if current_cache and f"{NDISK} {NPART}" != current_cache: print("[10] Detectada otra caché, eliminarla") CacheLib.ogUnmountCache() CacheLib.ogDeleteCache() - - try: - OLDSIZE = CacheLib.ogGetCacheSize() - except ValueError: - OLDSIZE = 0 - + + # Tomamos el tamaño actual. Si no existe cache será 0. + CACHESIZE = CacheLib.ogGetCacheSize() + if not CACHESIZE: CACHESIZE = 0 ## may be None + + # Error si tamaño definido no es >0. if SIZE <= 0: - SystemLib.ogRaiseError("OG_ERR_FORMAT", f"!({SIZE}>0)") - - if SIZE != OLDSIZE: + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_FORMAT, f"!({SIZE}>0)") + return False + + # Si no existe caché o si cambia su tamaño, crearla. + if SIZE != CACHESIZE: print("[10] Crear partición de caché local.") CacheLib.ogUnmountCache() - CacheLib.ogCreateCache(NDISK, NPART, SIZE) - DiskLib.ogUpdatePartitionTable(NDISK) - + CacheLib.ogCreateCache (NDISK, NPART, SIZE) + DiskLib.ogUpdatePartitionTable() + + # Si caché no montada y no formateada o cambia el tamaño: formatear. cache = CacheLib.ogFindCache() - if not FileSystemLib.ogIsFormated(cache) or SIZE != OLDSIZE: + if not cache: + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTCACHE, '') + return False + cache = cache.split() + if not FileSystemLib.ogIsFormated (cache[0], cache[1]) or SIZE != CACHESIZE: print("[50] Formatear caché local.") CacheLib.ogFormatCache() - print("[70] Comprobar montaje de caché local.") - if CacheLib.ogMountCache() != 0: + # Si error al montar, chequear sistema de archivos y volver a montar. + if not CacheLib.ogMountCache(): print("[80] Comprobar consistencia y volver a montar caché local.") - FileSystem.ogCheckFs(cache) - if CacheLib.ogMountCache() != 0: - sys.exit(1) - - if MOUNT == 0: + FileSystem.ogCheckFs (cache[0], cache[1]) + if not CacheLib.ogMountCache(): + return False + + # Dejar desmontada la caché si se ha solicitado. + if not MOUNT: print("[90] Dejar desmontada la caché local.") CacheLib.ogUnmountCache() - + +# Duración del proceso. TIME = time.time() - TIME1 - print(f"[100] Duración de la operación {int(TIME // 60)}m {int(TIME % 60)}s") + print (f"[100] Duración de la operación {int(TIME // 60)}m {int(TIME % 60)}s") + return True if __name__ == "__main__": - main() + PROG = sys.argv[0] + EXECFORMAT = f"{PROG} [int_ndisk [int_npart]] {{-1 | 0 | int_size}} [NOMOUNT]" + + args = sys.argv[1:] + if args and 'NOMOUNT' == args[-1].upper(): + MOUNT = False + args = args[:-1] + else: + MOUNT = True + + PARAMS = len (args) + try: + if 1 == PARAMS: + NDISK = 1 + NPART = 4 + SIZE = int (args[0]) + elif 2 == PARAMS: + NDISK = int (args[0]) + NPART = 4 + SIZE = int (args[1]) + elif 3 == PARAMS: + NDISK = int (args[0]) + NPART = int (args[1]) + SIZE = int (args[2]) + else: + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_FORMAT, EXECFORMAT) + sys.exit (1) + except ValueError: + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_FORMAT, EXECFORMAT) + sys.exit (1) + + # Si disco o partición no son mayores o iguales que 1, error. + if NDISK < 1 or NPART < 1: + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_FORMAT, EXECFORMAT) + sys.exit (1) + + # Si tamaño no es numérico o tamaño<-1, error. + if SIZE < -1: + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_FORMAT, EXECFORMAT) + sys.exit (1) + + rc = main (NDISK, NPART, SIZE, MOUNT) + sys.exit (not rc) From cc17975a438c8065f0c08d4dd88bb98f52b2a06b Mon Sep 17 00:00:00 2001 From: Natalia Serrano Date: Tue, 25 Feb 2025 09:25:01 +0100 Subject: [PATCH 167/167] refs #1597 #1605 add Configurar.py --- client/interfaceAdm/Configurar.py | 260 +++++++++++++++++------------- client/lib/engine/bin/CacheLib.py | 12 ++ 2 files changed, 163 insertions(+), 109 deletions(-) diff --git a/client/interfaceAdm/Configurar.py b/client/interfaceAdm/Configurar.py index fbe8aaa..d355c49 100755 --- a/client/interfaceAdm/Configurar.py +++ b/client/interfaceAdm/Configurar.py @@ -1,147 +1,189 @@ -#!/usr/bin/env python3 +#!/usr/bin/python3 + import os import sys import subprocess + +import ogGlobals import SystemLib +import CacheLib +import FileSystemLib +import DiskLib -# Load engine configurator from engine.cfg file. -og_engine_configurate = os.getenv('OGENGINECONFIGURATE') -if not og_engine_configurate: - with open('/opt/opengnsys/client/etc/engine.cfg') as f: - for line in f: - if '=' in line: - key, value = line.strip().split('=', 1) - os.environ[key] = value - print(f"{key}={value}") - - +#Load engine configurator from engine.cfg file. +#Carga el configurador del engine desde el fichero engine.cfg +## (ogGlobals se encarga) # Clear temporary file used as log track by httpdlog # Limpia los ficheros temporales usados como log de seguimiento para httpdlog -og_log_session = os.getenv('OGLOGSESSION') -og_log_command = os.getenv('OGLOGCOMMAND') +open (ogGlobals.OGLOGSESSION, 'w').close() +open (ogGlobals.OGLOGCOMMAND, 'w').close() +open (ogGlobals.OGLOGCOMMAND+'.tmp', 'w').close() -if og_log_session: - # Check if the file exists, if not create it - if not os.path.exists(og_log_session): - os.makedirs(os.path.dirname(og_log_session), exist_ok=True) - with open(og_log_session, 'w') as f: - f.write(" ") - else: - with open(og_log_session, 'w') as f: - f.write(" ") - -print("og_log_command", og_log_command) - -if og_log_command: - with open(og_log_command, 'w') as f: - f.write(" ") - with open(f"{og_log_command}.tmp", 'w') as f: - f.write(" ") - -print("og_log_session", og_log_session) # Registro de inicio de ejecución -def SystemLib.ogEcho(log_type, message): - # Implement the logging function here - pass - -print("os.getenv('MSG_INTERFACE_START')", os.getenv('MSG_INTERFACE_START')) -msg_interface_start = os.getenv('MSG_INTERFACE_START') -if msg_interface_start: - SystemLib.ogEcho('log', f"session {msg_interface_start} {__name__} {' '.join(os.sys.argv[1:])}") +SystemLib.ogEcho (['log', 'session'], None, f'{ogGlobals.lang.MSG_INTERFACE_START} {sys.argv}') # Solo ejecutable por OpenGnsys Client. -path = os.getenv('PATH') -if path: - os.environ['PATH'] = f"{path}:{os.path.dirname(__name__)}" - +#path = os.getenv('PATH') +#if path: +# os.environ['PATH'] = f"{path}:{os.path.dirname(__name__)}" prog = os.path.basename(__name__) -print("prog", prog) +#____________________________________________________________________ +# +# El parámetro $2 es el que aporta toda la información y el $1 se queda obsoleto +# Formato de entrada: +# dis=Número de disco +# *=caracter de separación +# che=Vale 0 o 1 +# *=caracter de separación +# $tch=tamaño cache +# != caracter de separación +# +# Y un numero indeterminado de cadenas del tipo siguuenteseparadas por el caracter '$': +# par=Número de particion*cod=Código de partición*sfi=Sistema de ficheros*tam=Tamaño de la partición*ope=Operación +# @= caracter de separación +#____________________________________________________________________ # Captura de parámetros (se ignora el 1er parámetro y se eliminan espacios y tabuladores). -param = ''.join(sys.argv[2:]).replace(' ', '').replace('\t', '') +#param='dis=1*che=0*tch=70000000!par=1*cpt=NTFS*sfi=NTFS*tam=11000000*ope=0%' +#param = ''.join(sys.argv[2:]).replace(' ', '').replace('\t', '') +param = sys.argv[2] -print("param", param) +# Activa navegador para ver progreso +coproc = subprocess.Popen (['/opt/opengnsys/bin/browser', '-qws', 'http://localhost/cgi-bin/httpd-log.sh']) -# Activate browser to see progress -browser_command = ["/opt/opengnsys/bin/browser", "-qws", "http://localhost/cgi-bin/httpd-log.sh"] -coproc = subprocess.Popen(browser_command) - -# Read the two blocks of parameters, separated by '!' -tbprm = param.split('!') +# Leer los dos bloques de parámetros, separados por '!'. +tbprm = param.split ('!') pparam = tbprm[0] # General disk parameters sparam = tbprm[1] # Partitioning and formatting parameters -# Take disk and cache values, separated by '*' -tbprm = pparam.split('*') +# Toma valores de disco y caché, separados por "*". +# Los valores están en las variables $dis: disco, $che: existe cache (1, 0), $tch: Tamaño de la cache. +tbprm = pparam.split ('*') +dis = ptt = tch = None for item in tbprm: - if '=' in item: - key, value = item.split('=', 1) - os.environ[key] = value + if '=' not in item: continue -# Error if disk parameter (dis) is not defined -if 'dis' not in os.environ: - sys.exit(int(os.getenv('OG_ERR_FORMAT', 1))) + k, v = item.split ('=', 1) + if k not in ['dis', 'tch', 'ptt']: ## 'ptt' added, unused 'che' removed + print (f'ignoring unknown disk parameter ({k})') + continue -# Take partition distribution values, separated by '%' -cfg = [] # Configuration values -tbp = [] # Partition table -tbf = [] # Formatting table + if 'dis' == k: dis = int (v) + elif 'ptt' == k: ptt = v + elif 'tch' == k: tch = v + +# Error si no se define el parámetro de disco (dis). +if dis is None: sys.exit (ogGlobals.OG_ERR_FORMAT) +if ptt is None: ptt = 'MSDOS' +if tch is None: tch = '0' + +# Toma valores de distribución de particiones, separados por "%". +tbp = [] # Valores de configuración (parámetros para ogCreatePartitions) +tbf = {} # Tabla de formateo tbprm = sparam.split('%') -maxp = 0 +maxp=0 for item in tbprm: - cfg = item.split('*') - for c in cfg: - if '=' in c: - key, value = c.split('=', 1) - os.environ[key] = value - if os.getenv('cpt') != "CACHE": - tbp.append(f"{os.getenv('cpt')}:{os.getenv('tam')}") - if os.getenv('ope') == '1': - if os.getenv('cpt') not in ["EMPTY", "EXTENDED", "LINUX-LVM", "LVM", "ZPOOL"]: - tbf.append(os.getenv('sfi')) - maxp = max(maxp, int(os.getenv('par', 0))) + if not item: continue ## por si nos pasan un '%' al final de todo + # Leer datos de la partición, separados por "*". + par = cpt = sfi = tam = None + ope = 0 + for c in item.split ('*'): + if '=' not in c: continue -# Process -# Current cache size -cache_size = subprocess.check_output(["ogGetCacheSize"]).strip() + k, v = c.split ('=', 1) + if k not in ['par', 'cpt', 'sfi', 'tam', 'ope']: + print (f'ignoring unknown partition parameter ({k})') + continue -# Unmount all partitions and cache -subprocess.run(["ogUnmountAll", os.getenv('dis')], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) -subprocess.run(["ogUnmountCache"]) + if 'par' == k: par = int (v) + elif 'cpt' == k: cpt = v + elif 'sfi' == k: sfi = v + elif 'tam' == k: tam = v + elif 'ope' == k: ope = int (v) -# Delete partition table if not MSDOS -if subprocess.check_output(["ogGetPartitionTableType", "1"]).strip() != b'MSDOS': - subprocess.run(["ogDeletePartitionTable", os.getenv('dis')]) - subprocess.run(["ogExecAndLog", "COMMAND", "ogUpdatePartitionTable", os.getenv('dis')]) - subprocess.run(["ogCreatePartitionTable", os.getenv('dis'), "MSDOS"]) + missing_params = [] + if par is None: missing_params.append ('par') + if cpt is None: missing_params.append ('cpt') + if sfi is None: missing_params.append ('sfi') + if tam is None: missing_params.append ('tam') + if missing_params: + print (f'partition data ({item}) missing required parameters ({' '.join (missing_params)})') + sys.exit (1) -# Initialize cache -if "CACHE" in sparam: - subprocess.run(["ogExecAndLog", "COMMAND", "initCache", os.getenv('tch')]) + # Componer datos de particionado. + if 'CACHE' != cpt: tbp.append (f'{cpt}:{tam}') + if ope: + # Si se activa operación de formatear, componer datos de formateo. + if cpt not in ['EMPTY', 'EXTENDED', 'LINUX-LVM', 'LVM', 'ZPOOL']: + tbf[par] = sfi + # Obtener la partición mayor. + if par > maxp: maxp = par -# Define partitioning -subprocess.run(["ogExecAndLog", "COMMAND", "ogCreatePartitions", os.getenv('dis')] + tbp) -if subprocess.run(["ogExecAndLog", "COMMAND", "ogUpdatePartitionTable", os.getenv('dis')]).returncode != 0: +#____________________________________________________ +# +# Proceso +#____________________________________________________ +# Tamaño actual de la cache +CACHESIZE=CacheLib.ogGetCacheSize() + +# Desmonta todas las particiones y la caché + +SystemLib.ogEcho (['session', 'log'], None, f'[10] {ogGlobals.lang.MSG_HELP_ogUnmountAll}') +FileSystemLib.ogUnmountAll (dis) +CacheLib.ogUnmountCache() + +# Elimina la tabla de particiones +cur_ptt = DiskLib.ogGetPartitionTableType (dis) +if not cur_ptt or ptt != cur_ptt: + DiskLib.ogDeletePartitionTable (dis) + SystemLib.ogExecAndLog ('command', DiskLib.ogUpdatePartitionTable) + + # Crea tabla de particiones MSDOS (NOTA: adaptar para tablas GPT). + DiskLib.ogCreatePartitionTable (dis, ptt) + +# Inicia la cache. +if 'CACHE' in sparam: + SystemLib.ogEcho (['session', 'log'], None, f'[30] {ogGlobals.lang.MSG_HELP_ogCreateCache}') + SystemLib.ogEcho (['session', 'log'], None, f' initCache {tch}') + SystemLib.ogExecAndLog ('command', CacheLib.initCache, tch) + +# Definir particionado. +SystemLib.ogEcho (['session', 'log'], None, f'[50] {ogGlobals.lang.MSG_HELP_ogCreatePartitions}') +SystemLib.ogEcho (['session', 'log'], None, f' ogCreatePartitions {dis} {' '.join (tbp)}') +res = SystemLib.ogExecAndLog ('command', DiskLib.ogCreatePartitions, dis, tbp) +if not res: coproc.kill() - sys.exit(int(subprocess.check_output(["ogRaiseError", "session", "log", os.getenv('OG_ERR_GENERIC', '1'), f"ogCreatePartitions {os.getenv('dis')} {' '.join(tbp)}"]))) - -# Format partitions -for par in range(1, maxp + 1): - if tbf[par] == "CACHE": - if cache_size == os.getenv('tch'): - subprocess.run(["ogExecAndLog", "COMMAND", "ogFormatCache"]) - elif tbf[par]: - if subprocess.run(["ogExecAndLog", "COMMAND", "ogFormatFs", os.getenv('dis'), str(par), tbf[par]]).returncode != 0: - coproc.kill() - sys.exit(int(subprocess.check_output(["ogRaiseError", "session", "log", os.getenv('OG_ERR_GENERIC', '1'), f"ogFormatFs {os.getenv('dis')} {par} {tbf[par]}"]))) + SystemLib.ogRaiseError (['log', 'session'], ogGlobals.OG_ERR_GENERIC, f'ogCreatePartitions {dis} {' '.join (tbp)}') + sys.exit (1) +SystemLib.ogExecAndLog ('command', DiskLib.ogUpdatePartitionTable) +# Formatear particiones +SystemLib.ogEcho (['session', 'log'], None, f'[70] {ogGlobals.lang.MSG_HELP_ogFormat}') retval = 0 -subprocess.run(["ogEcho", "log", "session", f"{os.getenv('MSG_INTERFACE_END')} {retval}"]) +for p in range (1, maxp+1): + if p not in tbf: continue + if 'CACHE' == tbf[p]: + if CACHESIZE == tch: # Si el tamaño es distinto ya se ha formateado. + SystemLib.ogEcho (['session', 'log'], None, ' ogFormatCache') + retval = SystemLib.ogExecAndLog ('command', CacheLib.ogFormatCache) + else: + SystemLib.ogEcho (['session', 'log'], None, f' ogFormatFs {dis} {p} {tbf[p]}') + retval = SystemLib.ogExecAndLog ('command', FileSystemLib.ogFormatFs, dis, str(p), tbf[p]) + if retval: + coproc.kill() + SystemLib.ogRaiseError (['session', 'log'], ogGlobals.OG_ERR_GENERIC, f'ogFormatFs {dis} {p} {tbf[p]}') + sys.exit (1) +# Registro de fin de ejecución +SystemLib.ogEcho (['session', 'log'], None, f'{ogGlobals.lang.MSG_INTERFACE_END} {retval}') + +#___________________________________________________________________ +# +# Retorno +#___________________________________________________________________ -# Return coproc.kill() -sys.exit(0) +sys.exit (0) diff --git a/client/lib/engine/bin/CacheLib.py b/client/lib/engine/bin/CacheLib.py index 180684f..5e8d9d5 100755 --- a/client/lib/engine/bin/CacheLib.py +++ b/client/lib/engine/bin/CacheLib.py @@ -347,3 +347,15 @@ def ogUnmountCache(): dev = DiskLib.ogDiskToDev (cachepart[0], cachepart[1]) dev = dev.replace ('dev', 'mnt') if os.path.exists (dev): os.remove (dev) + + +#/** +# initCache +#@brief Simplemente llama al script initCache +#@brief Es necesario tener una función para poder pasársela a ogExecAndLog +#@param los mismos parametros que initCache +#@return lo mismo que devuelve initCache +#*/ ## +def initCache (*args): + p = subprocess.run (['/opt/opengnsys/images/nati/client/shared/scripts/initCache.py'] + list(args)) + return p.returncode