ogrepository/api/repo_api.py

1563 lines
78 KiB
Python

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
API de ogRepository, programada en Flask.
Responde a peticiones HTTP (en principio, enviadas desde ogCore) mediante endpoints, que a su vez ejecutan los scripts Python almacenados en ogRepository.
En ciertos casos, transforma los parámetros recibidos desde el portal, para adaptarlos a los que es necesario enviar a los scripts
(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 es necesario instalarlo en Ubuntu 24
- flasgger (se puede instalar con "sudo apt install python3-flasgger")
"""
# --------------------------------------------------------------------------------------------
# IMPORTS
# --------------------------------------------------------------------------------------------
from flask import Flask, jsonify, request
import os
import subprocess
import json
from time import sleep
import paramiko
import logging
import threading
import requests
import random
from systemd import journal
# Imports para Swagger:
from flasgger import Swagger
import yaml
# --------------------------------------------------------------------------------------------
# VARIABLES
# --------------------------------------------------------------------------------------------
repo_path = '/opt/opengnsys/ogrepository/images/' # No borrar la barra final
script_path = '/opt/opengnsys/ogrepository/bin'
repo_file = '/opt/opengnsys/ogrepository/etc/repoinfo.json'
trash_file = '/opt/opengnsys/ogrepository/etc/trashinfo.json'
config_file = '/opt/opengnsys/ogrepository/etc/ogAdmRepo.cfg'
# --------------------------------------------------------------------------------------------
# FUNCTIONS
# --------------------------------------------------------------------------------------------
# Creamos una instancia de la aplicación Flask:
app = Flask(__name__)
# Cargamos el contenido del archivo "swagger.yaml":
with open("swagger.yaml", "r") as file:
swagger_template = yaml.safe_load(file)
# Así cambiamos el nombre de la página (por defecto, es 'Flasgger'):
swagger_config = Swagger.DEFAULT_CONFIG
swagger_config['title'] = 'ogRepository API'
swagger = Swagger(app, template=swagger_template)
# ---------------------------------------------------------
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:
if line.startswith('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"
# Almacenamos la IP de ogCore:
ogcore_ip = get_IPcore()
# ---------------------------------------------------------
def get_image_params(image_id, search='all'):
""" A partir de un ID de imagen (que corresponde al "fullsum"), busca la imagen en el repositorio y/o en la papelera (dependiendo del parámetro "search").
Si encuentra la imagen devuelve su nombre y su extensión en un diccionario, y si no encuentra la imagen especificada retorna "None".
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 = {}
# Abrimos y almacenamos el archivo "repoinfo.json" (solo si se ha de buscar en el repo, y si el archivo tiene contenido):
if (search == 'all' or search == 'repo') and os.path.getsize(repo_file) > 0:
with open(repo_file, 'r') as file:
repo_data = json.load(file)
# Iteramos la clave "images" y buscamos la imagen (y si la encontramos almacenamos el nombre y la extension):
for image in repo_data.get('images', []):
if image.get('fullsum') == image_id:
result['name'] = image.get('name')
result['extension'] = image.get('type')
return result
# Abrimos y almacenamos el archivo "trashinfo.json" (solo si se ha de buscar en la papelera, y si el archivo tiene contenido):
if (search == 'all' or search == 'trash') and os.path.getsize(trash_file) > 0:
with open(trash_file, 'r') as file:
trash_data = json.load(file)
# Iteramos la clave "images" y buscamos la imagen (y si la encontramos almacenamos el nombre y la extension):
for image in trash_data.get('images', []):
if image.get('fullsum') == image_id:
result['name'] = image.get('name')
result['extension'] = image.get('type')
return result
# Si no encontramos la imagen, retornamos "None":
return None
# ---------------------------------------------------------
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')
out, error = result.communicate()
# Almacenamos en una lista los procesos que contengan el proceso del parámetro y la cadena a buscar:
process_list = [line for line in out.split('\n') if process in line and string_to_search in line]
# 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}")
# ---------------------------------------------------------
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()
# Establecemos la política por defecto para localizar la llave del host localmente:
ssh_client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
# Conectamos con el equipo remoto por SSH:
ssh_client.connect(remote_ip, 22, remote_user) # Así se hace con claves
#ssh_client.connect(remote_ip, 22, remote_user, 'opengnsys') # Así se haría con password
# Iniciamos un cliente SFTP:
sftp_client = ssh_client.open_sftp()
# Cerramos el cliente SSH y el cliente SFTP:
ssh_client.close()
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 as error_description:
journal.send(f"Function result KO (Exception: {str(error_description)})", PRIORITY=journal.LOG_ERR, SYSLOG_IDENTIFIER="ogrepo-api")
return False
# ---------------------------------------------------------
def check_remote_image(remote_ip, remote_user, image_file_path):
""" Conecta con el servidor remoto que recibe como primer parámetro,
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:
ssh_client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
# Conectamos con el equipo remoto por SSH:
ssh_client.connect(remote_ip, 22, remote_user) # Así se hace con claves
#ssh_client.connect(remote_ip, 22, remote_user, 'opengnsys') # Así se haría con password
# Iniciamos un cliente SFTP:
sftp_client = ssh_client.open_sftp()
# Si la imagen no existe, retornamos el mensaje correspondiente:
if not os.path.exists(image_file_path):
return "Remote image not found"
# Si la imagen existe pero está bloqueada, retornamos el mensaje correspondiente:
if os.path.exists(f"{image_file_path}.lock"):
return "Remote image is locked"
# Cerramos el cliente SSH y el cliente SFTP:
ssh_client.close()
sftp_client.close()
# ---------------------------------------------------------
def check_lock_local(image_file_path, job_id):
""" Cada minuto comprueba si existe un archivo ".lock" asociado a la imagen que recibe como parámetro
(lo que significará que hay una tarea en curso), en el repositorio local.
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)
# Creamos un bucle infinito:
while True:
# Si ya no existe el archivo ".lock", imprimimos un mensaje en la API, respondemos a ogCore y salimos del bucle:
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:
else:
app.logger.info("Task in process (.lock file exists)")
# Esperamos 1 minuto para volver a realizar la comprobación:
sleep(60)
# ---------------------------------------------------------
def check_lock_remote(image_file_path, remote_host, remote_user, job_id):
""" Cada minuto comprueba si existe un archivo ".lock" asociado a la imagen que recibe como parámetro
(lo que significará que hay una tarea en curso), en un repositorio remoto (al que conecta por SSH/SFTP).
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:
ssh_client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
# Conectamos con el equipo remoto por SSH:
ssh_client.connect(remote_host, 22, remote_user) # Así se hace con claves
#ssh_client.connect(remote_host, 22, remote_user, 'opengnsys') # Así se haría con password
# Iniciamos un cliente SFTP:
sftp_client = ssh_client.open_sftp()
# Esperamos 30 segundos, para dar tiempo a que se cree el archivo ".lock":
sleep(30)
# Creamos un bucle infinito:
while True:
try:
# Si aun existe el archivo ".lock", imprimimos un mensaje en la API:
sftp_client.stat(f"{image_file_path}.lock")
app.logger.info("Task in process (.lock file exists)")
except IOError:
# 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:
sleep(60)
# Ya fuera del bucle, cerramos el cliente SSH y el cliente SFTP:
ssh_client.close()
sftp_client.close()
# ---------------------------------------------------------
def check_aux_files(image_file_path, job_id):
""" Cada 10 segundos comprueba si se han creado todos los archivos auxiliares de la imagen que recibe como parámetro,
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:
if not os.path.exists(f"{image_file_path}.size") or not os.path.exists(f"{image_file_path}.sum") or not os.path.exists(f"{image_file_path}.full.sum") or not os.path.exists(f"{image_file_path}.torrent") or not os.path.exists(f"{image_file_path}.info.checked"):
app.logger.info("Task in process (auxiliar files remaining)")
# 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')
app.logger.info(f"Job_ID: {job_id}")
app.logger.info(f"Image_ID: {image_id}")
# Almacenamos en un diccionario los datos a enviar a ogCore:
data = {
'job_id': 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:
sleep(10)
# ---------------------------------------------------------
def recall_ogcore(data):
""" Hace una petición HTTP de tipo POST a un endpoint de ogCore, enviando datos que dependen del caso.
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"
# Almacenamos los headers, y convertiomos "data" a JSON:
headers = {'content-type': 'application/json'}
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")
# --------------------------------------------------------------------------------------------
# ENDPOINTS
# --------------------------------------------------------------------------------------------
# 1 - Endpoint "Obtener Información de Estado de ogRepository" (SINCRONO):
@app.route("/ogrepository/v1/status", methods=['GET'])
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)
}), 500
# ---------------------------------------------------------
# 2 - Endpoint "Obtener Información de todas las Imágenes" (SINCRONO):
@app.route("/ogrepository/v1/images", methods=['GET'])
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)
}), 500
# ---------------------------------------------------------
# 3 - Endpoint "Obtener Información de una Imagen concreta" (SINCRONO):
@app.route("/ogrepository/v1/images/<string:imageId>", methods=['GET'])
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)
# Evaluamos los parámetros obtenidos, para construir la llamada al script, o para devover un error si no se ha encontrado la imagen:
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)
}), 500
# ---------------------------------------------------------
# 4 - Endpoint "Actualizar Información del Repositorio" (SINCRONO):
@app.route("/ogrepository/v1/images", methods=['PUT'])
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)
}), 500
# ---------------------------------------------------------
# 5 - Endpoint "Chequear Integridad de Imagen" (SINCRONO):
@app.route("/ogrepository/v1/status/images/<string:imageId>", methods=['GET'])
def check_image(imageId):
""" Este endpoint comprueba la integridad de la imagen especificada como parámetro,
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")
# Evaluamos los parámetros obtenidos, para construir la llamada al script, o para devover un error si no se ha encontrado la imagen:
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,
"output": "Image file didn't pass the Integrity Check"
}), 200
else:
return jsonify({
"success": True,
"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)
}), 500
# ---------------------------------------------------------
# 6 - Endpoint "Eliminar una Imagen" (SINCRONO):
@app.route("/ogrepository/v1/images/<string:imageId>", methods=['DELETE'])
def delete_image(imageId):
""" Este endpoint elimina la imagen especificada como parámetro (y todos sus archivos asociados),
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")
method = request.values.get('method')
# Evaluamos los parámetros obtenidos, para construir la llamada al script, o para devover un error si no se ha encontrado la imagen:
if param_dict:
if method == "permanent":
cmd = ['sudo', 'python3', f"{script_path}/deleteImage.py", f"{param_dict['name']}.{param_dict['extension']}", '-p']
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)
}), 500
# ---------------------------------------------------------
# 7 - Endpoint "Recuperar una Imagen" (SINCRONO):
@app.route("/ogrepository/v1/trash/images", methods=['POST'])
def recover_image():
""" Este endpoint recupera la imagen especificada como parámetro (y todos sus archivos asociados),
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")
# Obtenemos el nombre y la extensión de la imagen:
param_dict = get_image_params(image_id, "trash")
# Evaluamos los parámetros obtenidos, para construir la llamada al script, o para devover un error si no se ha encontrado la imagen:
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)
}), 500
# ---------------------------------------------------------
# 8 - Endpoint "Eliminar una Imagen de la Papelera" (SINCRONO):
@app.route("/ogrepository/v1/trash/images/<string:imageId>", methods=['DELETE'])
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")
# Evaluamos los parámetros obtenidos, para construir la llamada al script, o para devover un error si no se ha encontrado la imagen:
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)
}), 500
# ---------------------------------------------------------
# 9 - Endpoint "Importar una Imagen" (ASINCRONO):
@app.route("/ogrepository/v1/repo/images", methods=['POST'])
def import_image():
""" Este endpoint importa la imagen especificada como primer parámetro (y todos sus archivos asociados), desde un servidor remoto al servidor local.
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")
remote_ip = json_data.get("repo_ip")
remote_user = json_data.get("user")
# 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"
}), 400
# Construimos la ruta de la imagen:
image_file_path = f"{repo_path}{image_name}"
# 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"
}), 400
# Construimos la llamada al script:
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:
return jsonify({
"success": True,
"output": "Importing 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)
}), 500
# ---------------------------------------------------------
# 10 - Endpoint "Exportar una Imagen" (ASINCRONO):
@app.route("/ogrepository/v1/repo/images", methods=['PUT'])
def export_image():
""" Este endpoint exporta la imagen especificada como primer parámetro (y todos sus archivos asociados), desde el servidor local a un servidor remoto.
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")
remote_ip = json_data.get("repo_ip")
remote_user = json_data.get("user")
# Obtenemos el nombre y la extensión de la imagen (y el subdirectorio de OU, si fuera el caso):
param_dict = get_image_params(image_id, "repo")
# Evaluamos los parámetros obtenidos, para construir la ruta de la imagen, o para devover un error si no se ha encontrado la imagen (o si está bloqueada):
if param_dict:
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"
}), 400
# 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"
}), 400
# Construimos la llamada al script:
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:
return jsonify({
"success": True,
"output": "Exporting 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)
}), 500
# ---------------------------------------------------------
# 11 - Endpoint "Crear archivos auxiliares" (ASINCRONO):
@app.route("/ogrepository/v1/images/torrentsum", methods=['POST'])
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"
}), 400
# Construimos la ruta de la imagen (relativa a "repo_path"):
image_file_path = image_name
# Construimos la llamada al script:
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:
return jsonify({
"success": True,
"output": "Creating auxiliar files...",
"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)
}), 500
# ---------------------------------------------------------
# 12 - Endpoint "Enviar paquete Wake On Lan" (SINCRONO):
@app.route("/ogrepository/v1/wol", methods=['POST'])
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)
}), 500
# ---------------------------------------------------------
# 13 - Endpoint "Enviar una Imagen mediante UDPcast" (ASINCRONO):
@app.route("/ogrepository/v1/udpcast", methods=['POST'])
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")
port = json_data.get("port")
method = json_data.get("method")
ip = json_data.get("ip")
bitrate = json_data.get("bitrate")
nclients = json_data.get("nclients")
maxtime = json_data.get("maxtime")
# Obtenemos el nombre y la extensión de la imagen (y el subdirectorio de OU, si fuera el caso):
param_dict = get_image_params(image_id, "repo")
# Evaluamos los parámetros obtenidos, para construir la llamada al script, o para devover un error si no se ha encontrado la imagen:
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')
# Comprobamos si está corriendo el proceso correspondiente de "udp-sender" (esperando 5 segundos para darle tiempo a iniciarse):
sleep(5)
process_running = search_process('udp-sender', f"{param_dict['name']}.{param_dict['extension']}")
# 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)
}), 500
# ---------------------------------------------------------
# 14 - Endpoint "Enviar una Imagen mediante UFTP" (ASINCRONO):
@app.route("/ogrepository/v1/uftp", methods=['POST'])
def send_uftp():
""" Este endpoint envía mediante UFTP 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 "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")
port = json_data.get("port")
ip = json_data.get("ip")
bitrate = json_data.get("bitrate")
# Obtenemos el nombre y la extensión de la imagen (y el subdirectorio de OU, si fuera el caso):
param_dict = get_image_params(image_id, "repo")
# Evaluamos los parámetros obtenidos, para construir la llamada al script, o para devover un error si no se ha encontrado la imagen:
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')
# Comprobamos si está corriendo el proceso correspondiente de "uftp" (esperando 5 segundos para darle tiempo a iniciarse):
sleep(5)
process_running = search_process('uftp', f"{param_dict['name']}.{param_dict['extension']}")
# 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)
}), 500
# ---------------------------------------------------------
# 15 - Endpoint "Enviar una Imagen mediante P2P" (ASINCRONO):
@app.route("/ogrepository/v1/p2p", methods=['POST'])
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")
# Obtenemos el nombre y la extensión de la imagen (y el subdirectorio de OU, si fuera el caso):
param_dict = get_image_params(image_id, "repo")
# Evaluamos los parámetros obtenidos, para construir las llamadas a los scripts, o para devover un error si no se ha encontrado la imagen:
if param_dict:
cmd_tracker = ['sudo', 'python3', f"{script_path}/runTorrentTracker.py"]
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"
}), 400
# 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
# (esperamos 10 segundos antes de hacerlo, porque los procesos no se inician inmediatamente):
sleep(10)
tracker_running = search_process('bttrack', base_path)
seeder_running = search_process('btlaunchmany', base_path)
# 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"
}), 500
# ---------------------------------------------------------
# 16 - Endpoint "Ver Estado de Transmisiones UDPcast" (SINCRONO):
@app.route("/ogrepository/v1/udpcast", methods=['GET'])
def get_udpcast_info():
""" Este endpoint devuelve información sobre los procesos de "udp-sender" activos, en formato json,
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)
}), 500
# ---------------------------------------------------------
# 17 - Endpoint "Ver Estado de Transmisiones UFTP" (SINCRONO):
@app.route("/ogrepository/v1/uftp", methods=['GET'])
def get_uftp_info():
""" Este endpoint devuelve información sobre los procesos de "uftp" activos, en formato json,
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)
}), 500
# ---------------------------------------------------------
# 18 - Endpoint "Cancelar Transmisión UDPcast" (SINCRONO):
@app.route("/ogrepository/v1/udpcast/images/<string:imageId>", methods=['DELETE'])
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")
# Evaluamos los parámetros obtenidos, para construir la llamada al script, o para devover un error si no se ha encontrado la imagen:
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)
}), 500
# ---------------------------------------------------------
# 19 - Endpoint "Cancelar Transmisión UFTP" (SINCRONO):
@app.route("/ogrepository/v1/uftp/images/<string:imageId>", methods=['DELETE'])
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")
# Evaluamos los parámetros obtenidos, para construir la llamada al script, o para devover un error si no se ha encontrado la imagen:
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)
}), 500
# ---------------------------------------------------------
# 20 - Endpoint "Cancelar Transmisiones P2P" (SINCRONO):
@app.route("/ogrepository/v1/p2p", methods=['DELETE'])
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)
}), 500
# --------------------------------------------------------------------------------------------
# Ejecutamos la aplicación, en el puerto "8006":
if __name__ == '__main__':
app.run(debug=True, host='0.0.0.0', port=8006)
# --------------------------------------------------------------------------------------------