diff --git a/README.md b/README.md index c1db0e8..b850d0a 100644 --- a/README.md +++ b/README.md @@ -26,6 +26,7 @@ Librerías Python requeridas: - **paramiko** (se puede instalar con "sudo apt install python3-paramiko") - **psutil** (se puede instalar con "sudo apt install python3-psutil") - **flasgger** (se puede instalar con "sudo apt install python3-flasgger") + - **requests** (se puede instalar con "sudo apt install python3-requests", pero no es necesario en Ubuntu 24) Para que todos los endpoints y scripts funcionen con la configuración actual deben existir los siguientes directorios: - **/opt/opengnsys/ogrepository/images/** diff --git a/api/repo_api.py b/api/repo_api.py index 036d156..b6ce7f5 100644 --- a/api/repo_api.py +++ b/api/repo_api.py @@ -9,8 +9,8 @@ En ciertos casos, transforma los parámetros recibidos desde el portal, para ada (por ejemplo, a partir del ID de una imagen obtiene su nombre y su extensión). Librerías Python requeridas: - flask (se puede instalar con "sudo apt install python3-flask") - - paramiko (se puede instalar con "sudo apt install python3-paramiko") - - requests (se puede instalar con "sudo apt install python3-requests") - No tengo claro que para este paquete sea necesario + - paramiko (se puede instalar con "sudo apt install python3-paramiko") + - requests (se puede instalar con "sudo apt install python3-requests") - No es necesario instalarlo en Ubuntu 24 - flasgger (se puede instalar con "sudo apt install python3-flasgger") """ @@ -28,6 +28,7 @@ import logging import threading import requests import random +from systemd import journal # Imports para Swagger: from flasgger import Swagger import yaml @@ -70,6 +71,8 @@ def get_IPcore(): """ Obtiene el valor asociado a la variable "IPcore", desde el archivo '/opt/opengnsys/ogrepository/etc/ogAdmRepo.cfg'. Retorna la IP encontrada (que corresponde a la IP de ogCore), o un error (si no la encuentra). """ + journal.send("Running function 'get_IPcore'...", PRIORITY=journal.LOG_INFO, SYSLOG_IDENTIFIER="ogrepo-api") + IPcore = None with open(config_file, 'r') as file: for line in file: @@ -77,6 +80,7 @@ def get_IPcore(): IPcore = line.split('=')[1].strip() return IPcore if IPcore is None: + journal.send("Can't obtain ogCore IP", PRIORITY=journal.LOG_ERR, SYSLOG_IDENTIFIER="ogrepo-api") return "IP no encontrada en el archivo de configuración" @@ -93,6 +97,8 @@ def get_image_params(image_id, search='all'): El parámtro "search" tiene el valor predeterminado "all" (que hará que busque tanto en el repo como en la papelera), pero se le puede pasar el valor "repo" (para que busque solo en el repo) o "trash" (para que busque solo en la papelera). """ + journal.send("Running function 'get_image_params'...", PRIORITY=journal.LOG_INFO, SYSLOG_IDENTIFIER="ogrepo-api") + # Creamos un diccionario vacío, para almacenar los resultados: result = {} @@ -129,6 +135,8 @@ def search_process(process, string_to_search): """ Busca procesos que contengan el valor del parámetro "process" y el valor del parámetro "string_to_search" (la ruta de la imagen, normalmente). Si encuentra alguno retorna "True", y si no encuentra ninguno retorna "False". """ + journal.send("Running function 'search_process'...", PRIORITY=journal.LOG_INFO, SYSLOG_IDENTIFIER="ogrepo-api") + try: # Obtenemos todos los procesos que están corriendo, y almacenamos la salida y los errores: result = subprocess.Popen(['ps', '-aux'], stdout=subprocess.PIPE, stderr=subprocess.PIPE, encoding='UTF8') @@ -139,11 +147,14 @@ def search_process(process, string_to_search): # Si hemos encontrado algún proceso que cumpla las condiciones, retornamos "True", y si no retornamos "False": if process_list != []: + journal.send("Process found", PRIORITY=journal.LOG_INFO, SYSLOG_IDENTIFIER="ogrepo-api") return True else: + journal.send("Process not found", PRIORITY=journal.LOG_INFO, SYSLOG_IDENTIFIER="ogrepo-api") return False # Si se ha producido una excepción, imprimimos el error: except Exception as error_description: + journal.send(f"Function result KO (Exception: {str(error_description)})", PRIORITY=journal.LOG_ERR, SYSLOG_IDENTIFIER="ogrepo-api") print(f"Unexpected error: {error_description}") @@ -154,6 +165,8 @@ def check_remote_connection(remote_ip, remote_user): """ Comprueba la conexión SSH/SFTP con el servidor remoto que recibe como primer parámetro. Se utiliza para chequear la conexión antes de importar o exportar una imagen. """ + journal.send("Running function 'check_remote_connection'...", PRIORITY=journal.LOG_INFO, SYSLOG_IDENTIFIER="ogrepo-api") + try: # Iniciamos un cliente SSH: ssh_client = paramiko.SSHClient() @@ -172,10 +185,12 @@ def check_remote_connection(remote_ip, remote_user): sftp_client.close() # Retornamos "True", porque hemos conseguido conectar: + journal.send("Connection OK", PRIORITY=journal.LOG_INFO, SYSLOG_IDENTIFIER="ogrepo-api") return True # Si se produce una excepción, retornamos "False": - except Exception: + except Exception as error_description: + journal.send(f"Function result KO (Exception: {str(error_description)})", PRIORITY=journal.LOG_ERR, SYSLOG_IDENTIFIER="ogrepo-api") return False @@ -187,6 +202,8 @@ def check_remote_image(remote_ip, remote_user, image_file_path): para comprobar si la imagen que recibe como tercer parámetro existe, o si está bloqueada. Se utiliza para chequear la imagen antes de importarla. """ + journal.send("Running function 'check_remote_image'...", PRIORITY=journal.LOG_INFO, SYSLOG_IDENTIFIER="ogrepo-api") + # Iniciamos un cliente SSH: ssh_client = paramiko.SSHClient() # Establecemos la política por defecto para localizar la llave del host localmente: @@ -221,6 +238,8 @@ def check_lock_local(image_file_path, job_id): Cuando no encuentre el archivo ".lock" lo comunicará a ogCore, llamando a un endpoint, y dejará de realizar la comprobación (saliendo del bucle). """ + journal.send("Running function 'check_lock_local'...", PRIORITY=journal.LOG_INFO, SYSLOG_IDENTIFIER="ogrepo-api") + # Esperamos 30 segundos, para dar tiempo a que se cree el archivo ".lock": sleep(30) @@ -230,12 +249,14 @@ def check_lock_local(image_file_path, job_id): if not os.path.exists(f"{image_file_path}.lock"): app.logger.info("Task finalized (no .lock file)") app.logger.info(f"Job_ID: {job_id}") + journal.send("Image unlocked", PRIORITY=journal.LOG_INFO, SYSLOG_IDENTIFIER="ogrepo-api") # Almacenamos en un diccionario los datos a enviar a ogCore: data = { 'job_id': job_id } # Llamamos al endpoint de ogCore, enviando los datos del diccionario: + journal.send(f"Calling function 'recall_ogcore' (JOB_ID: {job_id})", PRIORITY=journal.LOG_INFO, SYSLOG_IDENTIFIER="ogrepo-api") recall_ogcore(data) break # Si aun existe el archivo ".lock", imprimimos un mensaje en la API: @@ -254,6 +275,8 @@ def check_lock_remote(image_file_path, remote_host, remote_user, job_id): Cuando no encuentre el archivo ".lock" lo comunicará a ogCore, llamando a un endpoint, y dejará de realizar la comprobación (saliendo del bucle). """ + journal.send("Running function 'check_lock_remote'...", PRIORITY=journal.LOG_INFO, SYSLOG_IDENTIFIER="ogrepo-api") + # Iniciamos un cliente SSH: ssh_client = paramiko.SSHClient() # Establecemos la política por defecto para localizar la llave del host localmente: @@ -278,12 +301,14 @@ def check_lock_remote(image_file_path, remote_host, remote_user, job_id): # Si ya no existe el archivo ".lock", imprimimos un mensaje en la API, respondemos a ogCore y salimos del bucle: app.logger.info("Task finalized (no .lock file)") app.logger.info(f"Job_ID: {job_id}") + journal.send("Remote image unlocked", PRIORITY=journal.LOG_INFO, SYSLOG_IDENTIFIER="ogrepo-api") # Almacenamos en un diccionario los datos a enviar a ogCore: data = { 'job_id': job_id } # Llamamos al endpoint de ogCore, enviando los datos del diccionario: + journal.send(f"Calling function 'recall_ogcore' (JOB_ID: {job_id})", PRIORITY=journal.LOG_INFO, SYSLOG_IDENTIFIER="ogrepo-api") recall_ogcore(data) break # Esperamos 1 minuto para volver a realizar la comprobación: @@ -302,6 +327,8 @@ def check_aux_files(image_file_path, job_id): en cuyo caso lo comunicará a ogCore, llamando a un endpoint, y dejará de realizar la comprobación. También obtiene el valor del archivo ".full.sum" (que corresonde al ID), y se lo comunica a ogCore. """ + journal.send("Running function 'check_aux_files'...", PRIORITY=journal.LOG_INFO, SYSLOG_IDENTIFIER="ogrepo-api") + # Creamos un bucle infinito: while True: # Si faltan archivos auxiliares por crear, imprimimos un mensaje en la API: @@ -310,6 +337,7 @@ def check_aux_files(image_file_path, job_id): # Si ya se han creado todos los archivos auxiliares, imprimimos un mensaje en la API, respondemos a ogCore y salimos del bucle: else: app.logger.info("Task finalized (all auxilar files created)") + journal.send("Auxiliar files created", PRIORITY=journal.LOG_INFO, SYSLOG_IDENTIFIER="ogrepo-api") # Obtenemos el valor del archivo "full.sum", que corresponde al ID, y lo imprimimos: with open(f"{image_file_path}.full.sum", 'r') as file: image_id = file.read().strip('\n') @@ -322,6 +350,7 @@ def check_aux_files(image_file_path, job_id): 'image_id': image_id } # Llamamos al endpoint de ogCore, enviando los datos del diccionario: + journal.send(f"Calling function 'recall_ogcore' (JOB_ID: {job_id}, IMAGE_ID: {image_id})", PRIORITY=journal.LOG_INFO, SYSLOG_IDENTIFIER="ogrepo-api") recall_ogcore(data) break # Esperamos 10 segundos para volver a realizar la comprobación: @@ -336,6 +365,8 @@ def recall_ogcore(data): Se utiliza para informar a ogCore del resultado de una tarea asíncrona, que estaba corriendo en un proceso independiente (no controlado por los endpoints). """ + journal.send("Running function 'recall_ogcore'...", PRIORITY=journal.LOG_INFO, SYSLOG_IDENTIFIER="ogrepo-api") + # Almacenamos la URL del endpoint de ogCore (prueba): #endpoint_url = f"http://{ogcore_ip}:8006/ogcore/v1/test" endpoint_url = f"https://{ogcore_ip}:8443/og-repository/webhook" @@ -345,11 +376,14 @@ def recall_ogcore(data): data = json.dumps(data) # Hacemos una petición POST al endpoint, enviando lo almacenado en "data": + journal.send("Sending HTTP request...", PRIORITY=journal.LOG_INFO, SYSLOG_IDENTIFIER="ogrepo-api") response = requests.post(endpoint_url, data=data, headers=headers, verify=False) # Imprimimos el código de estado de la petición y la respuesta de ogCore: app.logger.info(f"HTTP Status Code: {response.status_code}") app.logger.info(f"HTTP Response: {response.text}") + journal.send(f"HTTP Status Code: {response.status_code}", PRIORITY=journal.LOG_INFO, SYSLOG_IDENTIFIER="ogrepo-api") + journal.send(f"HTTP Response: {response.text}", PRIORITY=journal.LOG_INFO, SYSLOG_IDENTIFIER="ogrepo-api") @@ -364,22 +398,28 @@ def get_repo_status(): """ Este endpoint devuelve información de CPU, memoria RAM, disco duro y el estado de ciertos servicios y procesos de ogRepository, en formato json. Para ello, ejecuta el script "getRepoStatus.py", que no recibe parámetros. """ + journal.send("Running endpoint 'Obtener Información de Estado de ogRepository'...", PRIORITY=journal.LOG_INFO, SYSLOG_IDENTIFIER="ogrepo-api") + try: + journal.send("Running script 'getRepoStatus.py'...", PRIORITY=journal.LOG_INFO, SYSLOG_IDENTIFIER="ogrepo-api") # Ejecutamos el script "getRepoStatus.py", y almacenamos el resultado: result = subprocess.run(['sudo', 'python3', f"{script_path}/getRepoStatus.py"], check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, encoding='UTF8') # Evaluamos el resultado de la ejecución, y devolvemos la respuesta: if result.returncode == 0: + journal.send("Script result OK (ReturnCode: 0)", PRIORITY=journal.LOG_INFO, SYSLOG_IDENTIFIER="ogrepo-api") return jsonify({ "success": True, "output": json.loads(result.stdout) }), 200 else: + journal.send(f"Script result KO (Error: {result.stderr})", PRIORITY=journal.LOG_ERR, SYSLOG_IDENTIFIER="ogrepo-api") return jsonify({ "success": False, "error": result.stderr }), 500 except Exception as error_description: + journal.send(f"Script result KO (Exception: {str(error_description)})", PRIORITY=journal.LOG_ERR, SYSLOG_IDENTIFIER="ogrepo-api") return jsonify({ "success": False, "exception": str(error_description) @@ -395,22 +435,28 @@ def get_repo_info(): """ Este endpoint devuelve información de todas las imágenes contenidas en el repositorio (incluída la papelera), en formato json. Para ello, ejecuta el script "getRepoInfo.py", con el parámetro "all". """ + journal.send("Running endpoint 'Obtener Información de todas las Imágenes'...", PRIORITY=journal.LOG_INFO, SYSLOG_IDENTIFIER="ogrepo-api") + try: + journal.send("Running script 'getRepoInfo.py'...", PRIORITY=journal.LOG_INFO, SYSLOG_IDENTIFIER="ogrepo-api") # Ejecutamos el script "getRepoInfo.py" (con el parámetro "all"), y almacenamos el resultado: result = subprocess.run(['sudo', 'python3', f"{script_path}/getRepoInfo.py", 'all'], check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, encoding='UTF8') # Evaluamos el resultado de la ejecución, y devolvemos la respuesta: if result.returncode == 0: + journal.send("Script result OK (ReturnCode: 0)", PRIORITY=journal.LOG_INFO, SYSLOG_IDENTIFIER="ogrepo-api") return jsonify({ "success": True, "output": json.loads(result.stdout) }), 200 else: + journal.send(f"Script result KO (Error: {result.stderr})", PRIORITY=journal.LOG_ERR, SYSLOG_IDENTIFIER="ogrepo-api") return jsonify({ "success": False, "error": result.stderr }), 500 except Exception as error_description: + journal.send(f"Script result KO (Exception: {str(error_description)})", PRIORITY=journal.LOG_ERR, SYSLOG_IDENTIFIER="ogrepo-api") return jsonify({ "success": False, "exception": str(error_description) @@ -426,6 +472,8 @@ def get_repo_image_info(imageId): """ Este endpoint devuelve información de la imagen especificada como parámetro, en formato json. Para ello, ejecuta el script "getRepoInfo.py", con el nombre de la imagen como parámetro. """ + journal.send("Running endpoint 'Obtener Información de una Imagen concreta'...", PRIORITY=journal.LOG_INFO, SYSLOG_IDENTIFIER="ogrepo-api") + # Obtenemos el nombre y la extensión de la imagen: param_dict = get_image_params(imageId) @@ -433,27 +481,32 @@ def get_repo_image_info(imageId): if param_dict: cmd = ['sudo', 'python3', f"{script_path}/getRepoInfo.py", f"{param_dict['name']}.{param_dict['extension']}"] else: + journal.send("Image not found", PRIORITY=journal.LOG_ERR, SYSLOG_IDENTIFIER="ogrepo-api") return jsonify({ "success": False, "error": "Image not found" }), 400 try: + journal.send("Running script 'getRepoInfo.py'...", PRIORITY=journal.LOG_INFO, SYSLOG_IDENTIFIER="ogrepo-api") # Ejecutamos el script "getRepoInfo.py" (con los parámetros almacenados), y almacenamos el resultado: result = subprocess.run(cmd, check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, encoding='UTF8') # Evaluamos el resultado de la ejecución, y devolvemos la respuesta: if result.returncode == 0: + journal.send("Script result OK (ReturnCode: 0)", PRIORITY=journal.LOG_INFO, SYSLOG_IDENTIFIER="ogrepo-api") return jsonify({ "success": True, "output": json.loads(result.stdout) }), 200 else: + journal.send(f"Script result KO (Error: {result.stderr})", PRIORITY=journal.LOG_ERR, SYSLOG_IDENTIFIER="ogrepo-api") return jsonify({ "success": False, "error": result.stderr }), 500 except Exception as error_description: + journal.send(f"Script result KO (Exception: {str(error_description)})", PRIORITY=journal.LOG_ERR, SYSLOG_IDENTIFIER="ogrepo-api") return jsonify({ "success": False, "exception": str(error_description) @@ -469,22 +522,28 @@ def update_repo_info(): """ Este endpoint actualiza la información del repositorio y de la papelera, reflejándola en los archivos "repoinfo.json" y "trashinfo.josn". Para ello, ejecuta el script "updateRepoInfo.py", que a su vez ejecuta el script "updateTrashInfo.py". """ + journal.send("Running endpoint 'Actualizar Información del Repositorio'...", PRIORITY=journal.LOG_INFO, SYSLOG_IDENTIFIER="ogrepo-api") + try: + journal.send("Running script 'updateRepoInfo.py'...", PRIORITY=journal.LOG_INFO, SYSLOG_IDENTIFIER="ogrepo-api") # Ejecutamos el script "updateRepoInfo.py" (sin parámetros), y almacenamos el resultado: result = subprocess.run(['sudo', 'python3', f"{script_path}/updateRepoInfo.py"], check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, encoding='UTF8') # Evaluamos el resultado de la ejecución, y devolvemos una respuesta: if result.returncode == 0: + journal.send("Script result OK (ReturnCode: 0)", PRIORITY=journal.LOG_INFO, SYSLOG_IDENTIFIER="ogrepo-api") return jsonify({ "success": True, "output": "Repository info updated successfully" }), 200 else: + journal.send(f"Script result KO (Error: {result.stderr})", PRIORITY=journal.LOG_ERR, SYSLOG_IDENTIFIER="ogrepo-api") return jsonify({ "success": False, "error": result.stderr }), 500 except Exception as error_description: + journal.send(f"Script result KO (Exception: {str(error_description)})", PRIORITY=journal.LOG_ERR, SYSLOG_IDENTIFIER="ogrepo-api") return jsonify({ "success": False, "exception": str(error_description) @@ -501,6 +560,8 @@ def check_image(imageId): comparando el tamaño y el hash MD5 del último MB con los valores almacenados en los archivos "size" y "sum". Para ello, ejecuta el script "checkImage.py", con el nombre de la imagen como único parámetro. """ + journal.send("Running endpoint 'Chequear Integridad de Imagen'...", PRIORITY=journal.LOG_INFO, SYSLOG_IDENTIFIER="ogrepo-api") + # Obtenemos el nombre y la extensión de la imagen: param_dict = get_image_params(imageId, "repo") @@ -508,17 +569,20 @@ def check_image(imageId): if param_dict: cmd = ['sudo', 'python3', f"{script_path}/checkImage.py", f"{param_dict['name']}.{param_dict['extension']}"] else: + journal.send("Image not found (inexistent or deleted)", PRIORITY=journal.LOG_ERR, SYSLOG_IDENTIFIER="ogrepo-api") return jsonify({ "success": False, "error": "Image not found (inexistent or deleted)" }), 400 try: + journal.send("Running script 'checkImage.py'...", PRIORITY=journal.LOG_INFO, SYSLOG_IDENTIFIER="ogrepo-api") # Ejecutamos el script "checkImage.py" (con los parámetros almacenados), y almacenamos el resultado: result = subprocess.run(cmd, check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, encoding='UTF8') # Evaluamos el resultado de la ejecución, y devolvemos la respuesta: if result.returncode == 0: + journal.send("Script result OK (ReturnCode: 0)", PRIORITY=journal.LOG_INFO, SYSLOG_IDENTIFIER="ogrepo-api") if "Error" in result.stdout: return jsonify({ "success": True, @@ -530,11 +594,13 @@ def check_image(imageId): "output": "Image file passed the Integrity Check correctly" }), 200 else: + journal.send(f"Script result KO (Error: {result.stderr})", PRIORITY=journal.LOG_ERR, SYSLOG_IDENTIFIER="ogrepo-api") return jsonify({ "success": False, "error": result.stderr }), 500 except Exception as error_description: + journal.send(f"Script result KO (Exception: {str(error_description)})", PRIORITY=journal.LOG_ERR, SYSLOG_IDENTIFIER="ogrepo-api") return jsonify({ "success": False, "exception": str(error_description) @@ -551,6 +617,8 @@ def delete_image(imageId): moviéndolos a la papelera o eliminándolos permanentemente (dependiendo del parámetro "method"). Para ello, ejecuta el script "deleteImage.py", con el nombre de la imagen como primer parámetro, y el parámetro opcional "-p". """ + journal.send("Running endpoint 'Eliminar una Imagen'...", PRIORITY=journal.LOG_INFO, SYSLOG_IDENTIFIER="ogrepo-api") + # Obtenemos el nombre y la extensión de la imagen: param_dict = get_image_params(imageId, "repo") # Almacenams el método de eliminación ("trash" o "permanent") @@ -563,32 +631,38 @@ def delete_image(imageId): elif method == "trash": cmd = ['sudo', 'python3', f"{script_path}/deleteImage.py", f"{param_dict['name']}.{param_dict['extension']}"] else: + journal.send("Incorret method (must be 'permanent' or 'trash')", PRIORITY=journal.LOG_ERR, SYSLOG_IDENTIFIER="ogrepo-api") return jsonify({ "success": False, "error": "Incorrect method (must be 'permanent' or 'trash')" }), 400 else: + journal.send("Image not found (inexistent or deleted)", PRIORITY=journal.LOG_ERR, SYSLOG_IDENTIFIER="ogrepo-api") return jsonify({ "success": False, "error": "Image not found (inexistent or deleted)" }), 400 try: + journal.send("Running script 'deleteImage.py'...", PRIORITY=journal.LOG_INFO, SYSLOG_IDENTIFIER="ogrepo-api") # Ejecutamos el script "deleteImage.py" (con los parámetros almacenados), y almacenamos el resultado: result = subprocess.run(cmd, check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, encoding='UTF8') # Evaluamos el resultado de la ejecución, y devolvemos una respuesta: if result.returncode == 0: + journal.send("Script result OK (ReturnCode: 0)", PRIORITY=journal.LOG_INFO, SYSLOG_IDENTIFIER="ogrepo-api") return jsonify({ "success": True, "output": "Image deleted successfully" }), 200 else: + journal.send(f"Script result KO (Error: {result.stderr})", PRIORITY=journal.LOG_ERR, SYSLOG_IDENTIFIER="ogrepo-api") return jsonify({ "success": False, "error": result.stderr }), 500 except Exception as error_description: + journal.send(f"Script result KO (Exception: {str(error_description)})", PRIORITY=journal.LOG_ERR, SYSLOG_IDENTIFIER="ogrepo-api") return jsonify({ "success": False, "exception": str(error_description) @@ -605,6 +679,8 @@ def recover_image(): moviéndolos nuevamente al repositorio de imágenes, desde la papelera. Para ello, ejecuta el script "recoverImage.py", con el nombre de la imagen como único parámetro. """ + journal.send("Running endpoint 'Recuperar una Imagen'...", PRIORITY=journal.LOG_INFO, SYSLOG_IDENTIFIER="ogrepo-api") + # Almacenamos el parámetro "ID_img" (enviado por JSON): json_data = json.loads(request.data) image_id = json_data.get("ID_img") @@ -616,27 +692,32 @@ def recover_image(): if param_dict: cmd = ['sudo', 'python3', f"{script_path}/recoverImage.py", f"{param_dict['name']}.{param_dict['extension']}"] else: + journal.send("Image not found (inexistent or recovered previously)", PRIORITY=journal.LOG_ERR, SYSLOG_IDENTIFIER="ogrepo-api") return jsonify({ "success": False, "error": "Image not found (inexistent or recovered previously)" }), 400 try: + journal.send("Running script 'recoverImage.py'...", PRIORITY=journal.LOG_INFO, SYSLOG_IDENTIFIER="ogrepo-api") # Ejecutamos el script "recoverImage.py" (con los parámetros almacenados), y almacenamos el resultado: result = subprocess.run(cmd, check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, encoding='UTF8') # Evaluamos el resultado de la ejecución, y devolvemos una respuesta: if result.returncode == 0: + journal.send("Script result OK (ReturnCode: 0)", PRIORITY=journal.LOG_INFO, SYSLOG_IDENTIFIER="ogrepo-api") return jsonify({ "success": True, "output": "Image recovered successfully" }), 200 else: + journal.send(f"Script result KO (Error: {result.stderr})", PRIORITY=journal.LOG_ERR, SYSLOG_IDENTIFIER="ogrepo-api") return jsonify({ "success": False, "error": result.stderr }), 500 except Exception as error_description: + journal.send(f"Script result KO (Exception: {str(error_description)})", PRIORITY=journal.LOG_ERR, SYSLOG_IDENTIFIER="ogrepo-api") return jsonify({ "success": False, "exception": str(error_description) @@ -652,6 +733,8 @@ def delete_trash_image(imageId): """ Este endpoint elimina permanentemente la imagen especificada como parámetro (y todos sus archivos asociados), desde la papelera. Para ello, ejecuta el script "deleteTrashImage.py", con el nombre de la imagen como único parámetro. """ + journal.send("Running endpoint 'Eliminar una Imagen de la Papelera'...", PRIORITY=journal.LOG_INFO, SYSLOG_IDENTIFIER="ogrepo-api") + # Obtenemos el nombre y la extensión de la imagen: param_dict = get_image_params(imageId, "trash") @@ -659,27 +742,32 @@ def delete_trash_image(imageId): if param_dict: cmd = ['sudo', 'python3', f"{script_path}/deleteTrashImage.py", f"{param_dict['name']}.{param_dict['extension']}"] else: + journal.send("Image not found at trash", PRIORITY=journal.LOG_ERR, SYSLOG_IDENTIFIER="ogrepo-api") return jsonify({ "success": False, "error": "Image not found at trash" }), 400 try: + journal.send("Running script 'deleteTrashImage.py'...", PRIORITY=journal.LOG_INFO, SYSLOG_IDENTIFIER="ogrepo-api") # Ejecutamos el script "deleteTrashImage.py" (con los parámetros almacenados), y almacenamos el resultado: result = subprocess.run(cmd, check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, encoding='UTF8') # Evaluamos el resultado de la ejecución, y devolvemos una respuesta: if result.returncode == 0: + journal.send("Script result OK (ReturnCode: 0)", PRIORITY=journal.LOG_INFO, SYSLOG_IDENTIFIER="ogrepo-api") return jsonify({ "success": True, "output": "Image deleted successfully" }), 200 else: + journal.send(f"Script result KO (Error: {result.stderr})", PRIORITY=journal.LOG_ERR, SYSLOG_IDENTIFIER="ogrepo-api") return jsonify({ "success": False, "error": result.stderr }), 500 except Exception as error_description: + journal.send(f"Script result KO (Exception: {str(error_description)})", PRIORITY=journal.LOG_ERR, SYSLOG_IDENTIFIER="ogrepo-api") return jsonify({ "success": False, "exception": str(error_description) @@ -696,6 +784,8 @@ def import_image(): Para ello, ejecuta el script "importImage.py", con el nombre de la imagen como primer parámetro, la IP o hostname del servidor remoto como segundo parámetro, y el usuario con el que conectar al servidor como tercer parámetro. """ + journal.send("Running endpoint 'Importar una Imagen'...", PRIORITY=journal.LOG_INFO, SYSLOG_IDENTIFIER="ogrepo-api") + # Almacenamos los parámetros enviados en el JSON: json_data = json.loads(request.data) image_name = json_data.get("image") @@ -705,6 +795,7 @@ def import_image(): # Comprobamos la conexión con el equipo remoto, y si falla salimos del endpoint, retornando un error: connection_OK = check_remote_connection(remote_ip, remote_user) if connection_OK == False: + journal.send("Can't connect to remote server", PRIORITY=journal.LOG_ERR, SYSLOG_IDENTIFIER="ogrepo-api") return jsonify({ "success": False, "exception": "Can't connect to remote server" @@ -716,11 +807,13 @@ def import_image(): # Comprobamos si la imagen remota no existe o está bloqueada, en cuyos casos salimos del endpoint y retornamos el error correspondiente: check_image = check_remote_image(remote_ip, remote_user, image_file_path) if check_image == "Remote image not found": + journal.send("Remote image not found", PRIORITY=journal.LOG_ERR, SYSLOG_IDENTIFIER="ogrepo-api") return jsonify({ "success": False, "exception": "Remote image not found" }), 400 elif check_image == "Remote image is locked": + journal.send("Remote image is locked", PRIORITY=journal.LOG_ERR, SYSLOG_IDENTIFIER="ogrepo-api") return jsonify({ "success": False, "exception": "Remote image is locked" @@ -730,16 +823,20 @@ def import_image(): cmd = ['sudo', 'python3', f"{script_path}/importImage.py", image_file_path, remote_ip, remote_user] try: + journal.send("Running script 'importImage.py'...", PRIORITY=journal.LOG_INFO, SYSLOG_IDENTIFIER="ogrepo-api") # Ejecutamos el script "importImage.py" (con los parámetros almacenados), y almacenamos el resultado (pero sin esperar a que termine el proceso): result = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, encoding='UTF8') # Generamos el ID para identificar el trabajo asíncrono: job_id = f"ImportImage_{''.join(random.choice('0123456789abcdef') for char in range(8))}" + journal.send(f"JOB ID generated ({job_id})", PRIORITY=journal.LOG_INFO, SYSLOG_IDENTIFIER="ogrepo-api") # Evaluamos el resultado de la ejecución, y devolvemos una respuesta: if result.returncode is None: + journal.send("Script result OK (ReturnCode: None)", PRIORITY=journal.LOG_INFO, SYSLOG_IDENTIFIER="ogrepo-api") # Si el resultado es correcto, llamamos a la función "check_lock_local" en un hilo paralelo # (para que compruebe si la imagen se ha acabado de importar exitosamente): + journal.send("Calling function 'check_lock_local'...", PRIORITY=journal.LOG_INFO, SYSLOG_IDENTIFIER="ogrepo-api") threading.Thread(target=check_lock_local, args=(image_file_path, job_id,)).start() # Informamos que la imagen se está importando, y salimos del endpoint: @@ -749,16 +846,19 @@ def import_image(): "job_id": job_id }), 200 else: + journal.send("Script result KO (Image import failed)", PRIORITY=journal.LOG_ERR, SYSLOG_IDENTIFIER="ogrepo-api") return jsonify({ "success": False, "error": "Image import failed" }), 500 except subprocess.CalledProcessError as error: + journal.send(f"Script result KO (Process Exception: {str(error)})", PRIORITY=journal.LOG_ERR, SYSLOG_IDENTIFIER="ogrepo-api") return jsonify({ "success": False, "process exception": str(error) }), 500 except Exception as error_description: + journal.send(f"Script result KO (Exception: {str(error_description)})", PRIORITY=journal.LOG_ERR, SYSLOG_IDENTIFIER="ogrepo-api") return jsonify({ "success": False, "exception": str(error_description) @@ -775,6 +875,8 @@ def export_image(): Para ello, ejecuta el script "exportImage.py", con el nombre de la imagen como primer parámetro, la IP o hostname del servidor remoto como segundo parámetro, y el usuario con el que conectar al servidor como tercer parámetro. """ + journal.send("Running endpoint 'Exportar una Imagen'...", PRIORITY=journal.LOG_INFO, SYSLOG_IDENTIFIER="ogrepo-api") + # Almacenamos los parámetros enviados en el JSON: json_data = json.loads(request.data) image_id = json_data.get("ID_img") @@ -789,11 +891,13 @@ def export_image(): image_file_path = f"{param_dict['name']}.{param_dict['extension']}" # Si la imagen existe pero está bloqueada, devolvemos un error: if os.path.exists(f"{repo_path}{image_file_path}.lock"): + journal.send("Image is locked", PRIORITY=journal.LOG_ERR, SYSLOG_IDENTIFIER="ogrepo-api") return jsonify({ "success": False, "exception": "Image is locked" }), 400 else: + journal.send("Image not found", PRIORITY=journal.LOG_ERR, SYSLOG_IDENTIFIER="ogrepo-api") return jsonify({ "success": False, "error": "Image not found" @@ -803,6 +907,7 @@ def export_image(): connection_OK = check_remote_connection(remote_ip, remote_user) if connection_OK == False: + journal.send("Can't connect to remote server", PRIORITY=journal.LOG_ERR, SYSLOG_IDENTIFIER="ogrepo-api") return jsonify({ "success": False, "exception": "Can't connect to remote server" @@ -812,16 +917,20 @@ def export_image(): cmd = ['sudo', 'python3', f"{script_path}/exportImage.py", image_file_path, remote_ip, remote_user] try: + journal.send("Running script 'exportImage.py'...", PRIORITY=journal.LOG_INFO, SYSLOG_IDENTIFIER="ogrepo-api") # Ejecutamos el script "exportImage.py" (con los parámetros almacenados), y almacenamos el resultado (pero sin esperar a que termine el proceso): result = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, encoding='UTF8') # Generamos el ID para identificar el trabajo asíncrono: job_id = f"ExportImage_{''.join(random.choice('0123456789abcdef') for char in range(8))}" + journal.send(f"JOB ID generated ({job_id})", PRIORITY=journal.LOG_INFO, SYSLOG_IDENTIFIER="ogrepo-api") # Evaluamos el resultado de la ejecución, y devolvemos una respuesta: if result.returncode is None: + journal.send("Script result OK (ReturnCode: None)", PRIORITY=journal.LOG_INFO, SYSLOG_IDENTIFIER="ogrepo-api") # Si el resultado es correcto, llamamos a la función "check_lock_remote" en un hilo paralelo # (para que compruebe si la imagen se ha acabado de exportar exitosamente): + journal.send("Calling function 'check_lock_remote'...", PRIORITY=journal.LOG_INFO, SYSLOG_IDENTIFIER="ogrepo-api") threading.Thread(target=check_lock_remote, args=(f"{repo_path}{image_file_path}", remote_ip, remote_user, job_id,)).start() # Informamos que la imagen se está exportando, y salimos del endpoint: @@ -831,22 +940,26 @@ def export_image(): "job_id": job_id }), 200 else: + journal.send("Script result KO (Export image failed)", PRIORITY=journal.LOG_ERR, SYSLOG_IDENTIFIER="ogrepo-api") return jsonify({ "success": False, "error": "Export image failed" }), 500 except subprocess.CalledProcessError as error: + journal.send(f"Script result KO (Process Exception: {str(error)})", PRIORITY=journal.LOG_ERR, SYSLOG_IDENTIFIER="ogrepo-api") return jsonify({ "success": False, "process exception": str(error) }), 500 except Exception as error_description: if "exit status 5" in str(error_description): + journal.send("Image already exists on remote server", PRIORITY=journal.LOG_ERR, SYSLOG_IDENTIFIER="ogrepo-api") return jsonify({ "success": False, "exception": "Image already exists on remote server" }), 400 else: + journal.send(f"Script result KO (Exception: {str(error_description)})", PRIORITY=journal.LOG_ERR, SYSLOG_IDENTIFIER="ogrepo-api") return jsonify({ "success": False, "exception": str(error_description) @@ -862,12 +975,15 @@ def create_torrent_sum(): """ Este endpoint crea los archivos ".size", ".sum", ".full.sum" y ".torrent" para la imagen que recibe como parámetro. Para ello, ejecuta el script "createTorrentSum.py", con el nombre de la imagen como único parámetro. """ + journal.send("Running endpoint 'Crear archivos auxiliares'...", PRIORITY=journal.LOG_INFO, SYSLOG_IDENTIFIER="ogrepo-api") + # Almacenamos los parámetros enviados en el JSON: json_data = json.loads(request.data) image_name = json_data.get("image") # Si la imagen no existe, retornamos un error y salimos del endpoint: if not os.path.exists(f"{repo_path}{image_name}"): + journal.send("Image not found", PRIORITY=journal.LOG_ERR, SYSLOG_IDENTIFIER="ogrepo-api") return jsonify({ "success": False, "exception": "Image not found" @@ -880,16 +996,20 @@ def create_torrent_sum(): cmd = ['sudo', 'python3', f"{script_path}/createTorrentSum.py", image_file_path] try: + journal.send("Running script 'createTorrentSum.py'...", PRIORITY=journal.LOG_INFO, SYSLOG_IDENTIFIER="ogrepo-api") # Ejecutamos el script "createTorrentSum.py" (con los parámetros almacenados), y almacenamos el resultado (pero sin esperar a que termine el proceso): result = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, encoding='UTF8') # Generamos el ID para identificar el trabajo asíncrono: job_id = f"CreateAuxiliarFiles_{''.join(random.choice('0123456789abcdef') for char in range(8))}" + journal.send(f"JOB ID generated ({job_id})", PRIORITY=journal.LOG_INFO, SYSLOG_IDENTIFIER="ogrepo-api") # Evaluamos el resultado de la ejecución, y devolvemos una respuesta: if result.returncode is None: + journal.send("Script result OK (ReturnCode: None)", PRIORITY=journal.LOG_INFO, SYSLOG_IDENTIFIER="ogrepo-api") # Si el resultado es correcto, llamamos a la función "check_aux_files" en un hilo paralelo # (para que compruebe si se han creado todos los archivos auxiliares exitosamente): + journal.send("Calling function 'check_aux_files'...", PRIORITY=journal.LOG_INFO, SYSLOG_IDENTIFIER="ogrepo-api") threading.Thread(target=check_aux_files, args=(f"{repo_path}{image_file_path}", job_id,)).start() # Informamos que los archivos auxiliares se están creando, y salimos del endpoint: @@ -899,22 +1019,26 @@ def create_torrent_sum(): "job_id": job_id }), 200 else: + journal.send(f"Script result KO (Error: {result.stderr})", PRIORITY=journal.LOG_ERR, SYSLOG_IDENTIFIER="ogrepo-api") return jsonify({ "success": False, "error": result.stderr }), 500 except Exception as error_description: if "exit status 2" in str(error_description): + journal.send("Image not found", PRIORITY=journal.LOG_ERR, SYSLOG_IDENTIFIER="ogrepo-api") return jsonify({ "success": False, "exception": "Image not found" }), 400 elif "exit status 3" in str(error_description): + journal.send("Image is locked", PRIORITY=journal.LOG_ERR, SYSLOG_IDENTIFIER="ogrepo-api") return jsonify({ "success": False, "exception": "Image is locked" }), 400 else: + journal.send(f"Script result KO (Exception: {str(error_description)})", PRIORITY=journal.LOG_ERR, SYSLOG_IDENTIFIER="ogrepo-api") return jsonify({ "success": False, "exception": str(error_description) @@ -930,27 +1054,33 @@ def send_wakeonlan(): """ Este endpoint envía un paquete mágico Wake On Lan a la dirección MAC especificada, a través de la IP de broadcast especificadac. Para ello, ejecuta el script "sendWakeOnLan.py", con la IP de broadcast como primer parámetro, y la MAC como segundo parámetro. """ + journal.send("Running endpoint 'Enviar paquete Wake On Lan'...", PRIORITY=journal.LOG_INFO, SYSLOG_IDENTIFIER="ogrepo-api") + # Almacenamos los parámetros enviados en el JSON: json_data = json.loads(request.data) broadcast_ip = json_data.get("broadcast_ip") mac = json_data.get("mac") try: + journal.send("Running script 'sendWakeOnLan.py'...", PRIORITY=journal.LOG_INFO, SYSLOG_IDENTIFIER="ogrepo-api") # Ejecutamos el script "sendWakeOnLan.py" (con los parámetros almacenados), y almacenamos el resultado: result = subprocess.run(['sudo', 'python3', f"{script_path}/sendWakeOnLan.py", broadcast_ip, mac], check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, encoding='UTF8') # Evaluamos el resultado de la ejecución, y devolvemos una respuesta: if result.returncode == 0: + journal.send("Script result OK (ReturnCode: 0)", PRIORITY=journal.LOG_INFO, SYSLOG_IDENTIFIER="ogrepo-api") return jsonify({ "success": True, "output": "Wake On Lan packet sended successfully" }), 200 else: + journal.send(f"Script result KO (Error: {result.stderr})", PRIORITY=journal.LOG_ERR, SYSLOG_IDENTIFIER="ogrepo-api") return jsonify({ "success": False, "error": result.stderr }), 500 except Exception as error_description: + journal.send(f"Script result KO (Exception: {str(error_description)})", PRIORITY=journal.LOG_ERR, SYSLOG_IDENTIFIER="ogrepo-api") return jsonify({ "success": False, "exception": str(error_description) @@ -966,6 +1096,8 @@ def send_udpcast(): """ Este endpoint envía mediante UDPcast la imagen que recibe como primer parámetro, con los datos de transferencia que recibe en los demás parámetros. Para ello, ejecuta el script "sendFileMcast.py", con la imagen como primer parámetro, y los demás en una cadena (como segundo parámetro). """ + journal.send("Running endpoint 'Enviar una Imagen mediante UDPcast'...", PRIORITY=journal.LOG_INFO, SYSLOG_IDENTIFIER="ogrepo-api") + # Almacenamos los parámetros enviados en el JSON: json_data = json.loads(request.data) image_id = json_data.get("ID_img") @@ -983,12 +1115,14 @@ def send_udpcast(): if param_dict: cmd = ['sudo', 'python3', f"{script_path}/sendFileMcast.py", f"{param_dict['name']}.{param_dict['extension']}", f"{port}:{method}:{ip}:{bitrate}:{nclients}:{maxtime}"] else: + journal.send("Image not found", PRIORITY=journal.LOG_ERR, SYSLOG_IDENTIFIER="ogrepo-api") return jsonify({ "success": False, "error": "Image not found" }), 400 try: + journal.send("Running script 'sendFileMcast.py'...", PRIORITY=journal.LOG_INFO, SYSLOG_IDENTIFIER="ogrepo-api") # Ejecutamos el script "sendFileMcast.py" (con los parámetros almacenados), y almacenamos el resultado (pero sin esperar a que termine el proceso): result = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, encoding='UTF8') @@ -998,21 +1132,25 @@ def send_udpcast(): # Evaluamos el resultado de la ejecución, y devolvemos una respuesta: if result.returncode is None and process_running == True: + journal.send("Script result OK (ReturnCode: None), and process running", PRIORITY=journal.LOG_INFO, SYSLOG_IDENTIFIER="ogrepo-api") return jsonify({ "success": True, "output": "Sending image..." }), 200 else: + journal.send("Script result KO (Image send failed)", PRIORITY=journal.LOG_ERR, SYSLOG_IDENTIFIER="ogrepo-api") return jsonify({ "success": False, "error": "Image send failed" }), 500 except subprocess.CalledProcessError as error: + journal.send(f"Script result KO (Process Exception: {str(error)})", PRIORITY=journal.LOG_ERR, SYSLOG_IDENTIFIER="ogrepo-api") return jsonify({ "success": False, "process exeption": str(error) }), 500 except Exception as error_description: + journal.send(f"Script result KO (Exception: {str(error_description)})", PRIORITY=journal.LOG_ERR, SYSLOG_IDENTIFIER="ogrepo-api") return jsonify({ "success": False, "exception": str(error_description) @@ -1029,6 +1167,8 @@ def send_uftp(): Para ello, ejecuta el script "sendFileUFTP.py", con la imagen como primer parámetro, y los demás en una cadena (como segundo parámetro). NOTA: Es necesario que los clientes se hayan puesto en escucha previamente (ejecutando el script "listenUFTPD.py"). """ + journal.send("Running endpoint 'Enviar una Imagen mediante UFTP'...", PRIORITY=journal.LOG_INFO, SYSLOG_IDENTIFIER="ogrepo-api") + # Almacenamos los parámetros enviados en el JSON: json_data = json.loads(request.data) image_id = json_data.get("ID_img") @@ -1043,12 +1183,14 @@ def send_uftp(): if param_dict: cmd = ['sudo', 'python3', f"{script_path}/sendFileUFTP.py", f"{param_dict['name']}.{param_dict['extension']}", f"{port}:{ip}:{bitrate}"] else: + journal.send("Image not found", PRIORITY=journal.LOG_ERR, SYSLOG_IDENTIFIER="ogrepo-api") return jsonify({ "success": False, "error": "Image not found" }), 400 try: + journal.send("Running script 'sendFileUFTP.py'...", PRIORITY=journal.LOG_INFO, SYSLOG_IDENTIFIER="ogrepo-api") # Ejecutamos el script "sendFileUFTP.py" (con los parámetros almacenados), y almacenamos el resultado (pero sin esperar a que termine el proceso): result = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, encoding='UTF8') @@ -1058,21 +1200,25 @@ def send_uftp(): # Evaluamos el resultado de la ejecución, y devolvemos una respuesta: if result.returncode is None and process_running == True: + journal.send("Script result OK (ReturnCode: None), and process running", PRIORITY=journal.LOG_INFO, SYSLOG_IDENTIFIER="ogrepo-api") return jsonify({ "success": True, "output": "Sending image..." }), 200 else: + journal.send("Script result KO (Image send failed)", PRIORITY=journal.LOG_ERR, SYSLOG_IDENTIFIER="ogrepo-api") return jsonify({ "success": False, "error": "Image send failed" }), 500 except subprocess.CalledProcessError as error: + journal.send(f"Script result KO (Process Exception: {str(error)})", PRIORITY=journal.LOG_ERR, SYSLOG_IDENTIFIER="ogrepo-api") return jsonify({ "success": False, "process exeption": str(error) }), 500 except Exception as error_description: + journal.send(f"Script result KO (Exception: {str(error_description)})", PRIORITY=journal.LOG_ERR, SYSLOG_IDENTIFIER="ogrepo-api") return jsonify({ "success": False, "exception": str(error_description) @@ -1088,6 +1234,8 @@ def send_p2p(): """ Este endpoint inicia el tracker "bttrack" y el seeder "bittornado", en el directorio de imágenes (sirviendo todas las imágenes). Para ello, ejecuta los scripts "runTorrentTracker.py" y "runTorrentSeeder.py", que no reciben parámetros. """ + journal.send("Running endpoint 'Enviar una Imagen mediante P2P'...", PRIORITY=journal.LOG_INFO, SYSLOG_IDENTIFIER="ogrepo-api") + # Almacenamos los parámetros enviados en el JSON: json_data = json.loads(request.data) image_id = json_data.get("ID_img") @@ -1101,6 +1249,7 @@ def send_p2p(): cmd_seeder = ['sudo', 'python3', f"{script_path}/runTorrentSeeder.py"] base_path = repo_path.rstrip('/') # Le quito la última barra para poder buscar correctamente en los procesos else: + journal.send("Image not found", PRIORITY=journal.LOG_ERR, SYSLOG_IDENTIFIER="ogrepo-api") return jsonify({ "success": False, "error": "Image not found" @@ -1109,7 +1258,10 @@ def send_p2p(): # Ejecutamos los scripts "runTorrentSeeder.py" y "runTorrentSeeder.py", que no reciben parámetros. # NOTA: No almacenamos la salida ni comprobamos los errores, porque los procesos quedarán corriendo hasta que se finalicen manualmente, # por lo que no podemos comprobar el returncode (luego comprobaremos si los procesos se han iniciado correctamente). + journal.send("Running script 'runTorrentTracker.py'...", PRIORITY=journal.LOG_INFO, SYSLOG_IDENTIFIER="ogrepo-api") subprocess.Popen(cmd_tracker) + + journal.send("Running script 'runTorrentSeeder.py'...", PRIORITY=journal.LOG_INFO, SYSLOG_IDENTIFIER="ogrepo-api") subprocess.Popen(cmd_seeder) # Comprobamos si el tracker y el seeder están corriendo, y si apuntan al directorio que le hemos pasado @@ -1120,11 +1272,13 @@ def send_p2p(): # Evaluamos las comprobaciones anteriores, para devolver la respuesta que corresponda: if tracker_running and seeder_running: + journal.send("Scripts results OK (ReturnCode: None), and processes running", PRIORITY=journal.LOG_INFO, SYSLOG_IDENTIFIER="ogrepo-api") return jsonify({ "success": True, "output": "Tracker and Seeder serving image correctly" }), 200 else: + journal.send("Scripts results KO (Tracker or/and Seeder not runnig)", PRIORITY=journal.LOG_ERR, SYSLOG_IDENTIFIER="ogrepo-api") return jsonify({ "success": False, "error": "Tracker or Seeder (or both) not running" @@ -1141,28 +1295,35 @@ def get_udpcast_info(): lo que en la práctica permite comprobar las transferencias UDPcast activas. Para ello, ejecuta el script "getUDPcastInfo.py", que no recibe parámetros. """ + journal.send("Running endpoint 'Ver Estado de Transmisiones UDPcast'...", PRIORITY=journal.LOG_INFO, SYSLOG_IDENTIFIER="ogrepo-api") + try: + journal.send("Running script 'getUDPcastInfo.py'...", PRIORITY=journal.LOG_INFO, SYSLOG_IDENTIFIER="ogrepo-api") # Ejecutamos el script "getUDPcastInfo.py", y almacenamos el resultado: result = subprocess.run(['sudo', 'python3', f"{script_path}/getUDPcastInfo.py"], check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, encoding='UTF8') # Evaluamos el resultado de la ejecución, y devolvemos la respuesta: if result.returncode == 0: + journal.send("Script result OK (ReturnCode: 0)", PRIORITY=journal.LOG_INFO, SYSLOG_IDENTIFIER="ogrepo-api") return jsonify({ "success": True, "output": json.loads(result.stdout) }), 200 else: + journal.send(f"Script result KO (Error: {result.stderr})", PRIORITY=journal.LOG_ERR, SYSLOG_IDENTIFIER="ogrepo-api") return jsonify({ "success": False, "error": result.stderr }), 500 except Exception as error_description: if "exit status 1" in str(error_description): + journal.send("No UDPcast active transmissions", PRIORITY=journal.LOG_ERR, SYSLOG_IDENTIFIER="ogrepo-api") return jsonify({ "success": False, "exception": "No UDPCast active transmissions" }), 400 else: + journal.send(f"Script result KO (Exception: {str(error_description)})", PRIORITY=journal.LOG_ERR, SYSLOG_IDENTIFIER="ogrepo-api") return jsonify({ "success": False, "exception": str(error_description) @@ -1179,28 +1340,35 @@ def get_uftp_info(): lo que en la práctica permite comprobar las transferencias UFTP activas. Para ello, ejecuta el script "getUFTPInfo.py", que no recibe parámetros. """ + journal.send("Running endpoint 'Ver Estado de Transmisiones UFTP'...", PRIORITY=journal.LOG_INFO, SYSLOG_IDENTIFIER="ogrepo-api") + try: + journal.send("Running script 'getUFTPInfo.py'...", PRIORITY=journal.LOG_INFO, SYSLOG_IDENTIFIER="ogrepo-api") # Ejecutamos el script "getUFTPInfo.py", y almacenamos el resultado: result = subprocess.run(['sudo', 'python3', f"{script_path}/getUFTPInfo.py"], check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, encoding='UTF8') # Evaluamos el resultado de la ejecución, y devolvemos la respuesta: if result.returncode == 0: + journal.send("Script result OK (ReturnCode: 0)", PRIORITY=journal.LOG_INFO, SYSLOG_IDENTIFIER="ogrepo-api") return jsonify({ "success": True, "output": json.loads(result.stdout) }), 200 else: + journal.send(f"Script result KO (Error: {result.stderr})", PRIORITY=journal.LOG_ERR, SYSLOG_IDENTIFIER="ogrepo-api") return jsonify({ "success": False, "error": result.stderr }), 500 except Exception as error_description: if "exit status 1" in str(error_description): + journal.send("No UFTP active transmissions", PRIORITY=journal.LOG_ERR, SYSLOG_IDENTIFIER="ogrepo-api") return jsonify({ "success": False, "exception": "No UFTP active transmissions" }), 400 else: + journal.send(f"Script result KO (Exception: {str(error_description)})", PRIORITY=journal.LOG_ERR, SYSLOG_IDENTIFIER="ogrepo-api") return jsonify({ "success": False, "exception": str(error_description) @@ -1216,6 +1384,8 @@ def stop_udpcast(imageId): """ Este endpoint cancela la transmisión UDPcast de la imagen que recibe como parámetro, finalizando el proceso "udp-sender" asociado. Para ello, ejecuta el script "stopUDPcast.py", pasándole el nombre de la imagen. """ + journal.send("Running endpoint 'Cancelar Transmisión UDPcast'...", PRIORITY=journal.LOG_INFO, SYSLOG_IDENTIFIER="ogrepo-api") + # Obtenemos el nombre y la extensión de la imagen: param_dict = get_image_params(imageId, "repo") @@ -1223,43 +1393,51 @@ def stop_udpcast(imageId): if param_dict: cmd = ['sudo', 'python3', f"{script_path}/stopUDPcast.py", f"{param_dict['name']}.{param_dict['extension']}"] else: + journal.send("Image not found", PRIORITY=journal.LOG_ERR, SYSLOG_IDENTIFIER="ogrepo-api") return jsonify({ "success": False, "error": "Image not found" }), 400 try: + journal.send("Running script 'stopUDPcast.py'...", PRIORITY=journal.LOG_INFO, SYSLOG_IDENTIFIER="ogrepo-api") # Ejecutamos el script "stopUDPcast.py" (con los parámetros almacenados), y almacenamos el resultado: result = subprocess.run(cmd, check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, encoding='UTF8') # Evaluamos el resultado de la ejecución, y devolvemos una respuesta: if result.returncode == 0: + journal.send("Script result OK (ReturnCode: 0)", PRIORITY=journal.LOG_INFO, SYSLOG_IDENTIFIER="ogrepo-api") return jsonify({ "success": True, "output": "Image transmission canceled successfully" }), 200 else: + journal.send(f"Script result KO (Error: {result.stderr})", PRIORITY=journal.LOG_ERR, SYSLOG_IDENTIFIER="ogrepo-api") return jsonify({ "success": False, "error": result.stderr }), 500 except Exception as error_description: if "exit status 3" in str(error_description): + journal.send("No UDPCast active transmissions for specified image", PRIORITY=journal.LOG_ERR, SYSLOG_IDENTIFIER="ogrepo-api") return jsonify({ "success": False, "exception": "No UDPCast active transmissions for specified image" }), 400 elif "exit status 4" in str(error_description): + journal.send("Script result KO (Unexpected error checking UDPcast transmissions)", PRIORITY=journal.LOG_ERR, SYSLOG_IDENTIFIER="ogrepo-api") return jsonify({ "success": False, "exception": "Unexpected error checking UDPcast transmissions" }), 500 elif "exit status 5" in str(error_description): + journal.send("Script result KO (Unexpected error finalizing UDPcast transmission)", PRIORITY=journal.LOG_ERR, SYSLOG_IDENTIFIER="ogrepo-api") return jsonify({ "success": False, "exception": "Unexpected error finalizing UDPcast transmission" }), 500 else: + journal.send(f"Script result KO (Exception: {str(error_description)})", PRIORITY=journal.LOG_ERR, SYSLOG_IDENTIFIER="ogrepo-api") return jsonify({ "success": False, "exception": str(error_description) @@ -1275,6 +1453,8 @@ def stop_uftp(imageId): """ Este endpoint cancela la transmisión UFTP de la imagen que recibe como parámetro, finalizando el proceso "uftp" asociado. Para ello, ejecuta el script "stopUFTP.py", pasándole el nombre de la imagen. """ + journal.send("Running endpoint 'Cancelar Transmisión UFTP'...", PRIORITY=journal.LOG_INFO, SYSLOG_IDENTIFIER="ogrepo-api") + # Obtenemos el nombre y la extensión de la imagen (y el subdirectorio de OU, si fuera el caso): param_dict = get_image_params(imageId, "repo") @@ -1282,43 +1462,51 @@ def stop_uftp(imageId): if param_dict: cmd = ['sudo', 'python3', f"{script_path}/stopUFTP.py", f"{param_dict['name']}.{param_dict['extension']}"] else: + journal.send("Image not found", PRIORITY=journal.LOG_ERR, SYSLOG_IDENTIFIER="ogrepo-api") return jsonify({ "success": False, "error": "Image not found" }), 400 try: + journal.send("Running script 'stopUFTP.py'...", PRIORITY=journal.LOG_INFO, SYSLOG_IDENTIFIER="ogrepo-api") # Ejecutamos el script "stopUFTP.py" (con los parámetros almacenados), y almacenamos el resultado: result = subprocess.run(cmd, check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, encoding='UTF8') # Evaluamos el resultado de la ejecución, y devolvemos una respuesta: if result.returncode == 0: + journal.send("Script result OK (ReturnCode: 0)", PRIORITY=journal.LOG_INFO, SYSLOG_IDENTIFIER="ogrepo-api") return jsonify({ "success": True, "output": "Image transmission canceled successfully" }), 200 else: + journal.send(f"Script result KO (Error: {result.stderr})", PRIORITY=journal.LOG_ERR, SYSLOG_IDENTIFIER="ogrepo-api") return jsonify({ "success": False, "error": result.stderr }), 500 except Exception as error_description: if "exit status 3" in str(error_description): + journal.send("No UFTP active transmissions for specified image", PRIORITY=journal.LOG_ERR, SYSLOG_IDENTIFIER="ogrepo-api") return jsonify({ "success": False, "exception": "No UFTP active transmissions for specified image" }), 400 elif "exit status 4" in str(error_description): + journal.send("Script result KO (Unexpected error checking UFTP transmissions)", PRIORITY=journal.LOG_ERR, SYSLOG_IDENTIFIER="ogrepo-api") return jsonify({ "success": False, "exception": "Unexpected error checking UFTP transmissions" }), 500 elif "exit status 5" in str(error_description): + journal.send("Script result KO (Unexpected error finalizing UFTP transmission)", PRIORITY=journal.LOG_ERR, SYSLOG_IDENTIFIER="ogrepo-api") return jsonify({ "success": False, "exception": "Unexpected error finalizing UFTP transmission" }), 500 else: + journal.send(f"Script result KO (Exception: {str(error_description)})", PRIORITY=journal.LOG_ERR, SYSLOG_IDENTIFIER="ogrepo-api") return jsonify({ "success": False, "exception": str(error_description) @@ -1334,22 +1522,28 @@ def stop_p2p(): """ Este endpoint cancela las transmisiones P2P activas, finalizando los procesos "btlaunchmany.bittornado" (seeder) y "bttrack" (tracker). Para ello, ejecuta el script "stopP2P.py", que no recibe parámetros. """ + journal.send("Running endpoint 'Cancelar Transmisiones P2P'...", PRIORITY=journal.LOG_INFO, SYSLOG_IDENTIFIER="ogrepo-api") + try: + journal.send("Running script 'stopP2P.py'...", PRIORITY=journal.LOG_INFO, SYSLOG_IDENTIFIER="ogrepo-api") # Ejecutamos el script "stopP2P.py", y almacenamos el resultado: result = subprocess.run(['sudo', 'python3', f"{script_path}/stopP2P.py"], check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, encoding='UTF8') # Evaluamos el resultado de la ejecución, y devolvemos la respuesta: if result.returncode == 0: + journal.send("Script result OK (ReturnCode: 0)", PRIORITY=journal.LOG_INFO, SYSLOG_IDENTIFIER="ogrepo-api") return jsonify({ "success": True, "output": "P2P transmissions canceled successfully" }), 200 else: + journal.send(f"Script result KO (Error: {result.stderr})", PRIORITY=journal.LOG_ERR, SYSLOG_IDENTIFIER="ogrepo-api") return jsonify({ "success": False, "error": result.stderr }), 500 except Exception as error_description: + journal.send(f"Script result KO (Exception: {str(error_description)})", PRIORITY=journal.LOG_ERR, SYSLOG_IDENTIFIER="ogrepo-api") return jsonify({ "success": False, "exception": str(error_description)